Merge "Chinese Conversion Table Update 2016-7"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 8 Dec 2016 07:26:08 +0000 (07:26 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 8 Dec 2016 07:26:08 +0000 (07:26 +0000)
914 files changed:
.eslintrc.json [new file with mode: 0644]
.jscsrc [deleted file]
.jshintignore [deleted file]
.jshintrc [deleted file]
.mailmap
CREDITS
Gruntfile.js
HISTORY
RELEASE-NOTES-1.28 [deleted file]
RELEASE-NOTES-1.29
autoload.php
composer.json
docs/extension.schema.json
docs/extension.schema.v1.json
docs/hooks.txt
includes/AjaxResponse.php
includes/AuthPlugin.php
includes/Block.php
includes/CategoryViewer.php
includes/DefaultSettings.php
includes/EditPage.php
includes/FileDeleteForm.php
includes/Message.php
includes/MimeMagic.php
includes/MovePage.php
includes/OutputPage.php
includes/Preferences.php
includes/PrefixSearch.php
includes/RevisionList.php
includes/ServiceWiring.php
includes/Setup.php
includes/TemplateParser.php
includes/WatchedItemQueryService.php
includes/Xml.php
includes/actions/CreditsAction.php
includes/actions/HistoryAction.php
includes/actions/InfoAction.php
includes/actions/MarkpatrolledAction.php
includes/actions/RevisiondeleteAction.php [deleted file]
includes/actions/ViewAction.php
includes/api/ApiAMCreateAccount.php
includes/api/ApiAuthManagerHelper.php
includes/api/ApiBase.php
includes/api/ApiBlock.php
includes/api/ApiCSPReport.php
includes/api/ApiChangeAuthenticationData.php
includes/api/ApiCheckToken.php
includes/api/ApiClearHasMsg.php
includes/api/ApiClientLogin.php
includes/api/ApiComparePages.php
includes/api/ApiContinuationManager.php
includes/api/ApiDelete.php
includes/api/ApiDisabled.php
includes/api/ApiEditPage.php
includes/api/ApiEmailUser.php
includes/api/ApiErrorFormatter.php
includes/api/ApiExpandTemplates.php
includes/api/ApiFeedContributions.php
includes/api/ApiFeedRecentChanges.php
includes/api/ApiFeedWatchlist.php
includes/api/ApiFileRevert.php
includes/api/ApiFormatJson.php
includes/api/ApiFormatPhp.php
includes/api/ApiFormatRaw.php
includes/api/ApiFormatXml.php
includes/api/ApiHelp.php
includes/api/ApiImageRotate.php
includes/api/ApiImport.php
includes/api/ApiLinkAccount.php
includes/api/ApiLogin.php
includes/api/ApiLogout.php
includes/api/ApiMain.php
includes/api/ApiManageTags.php
includes/api/ApiMergeHistory.php
includes/api/ApiMessage.php
includes/api/ApiMove.php
includes/api/ApiOpenSearch.php
includes/api/ApiOptions.php
includes/api/ApiPageSet.php
includes/api/ApiParamInfo.php
includes/api/ApiParse.php
includes/api/ApiPatrol.php
includes/api/ApiProtect.php
includes/api/ApiPurge.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllDeletedRevisions.php
includes/api/ApiQueryAllImages.php
includes/api/ApiQueryAllLinks.php
includes/api/ApiQueryAllMessages.php
includes/api/ApiQueryAllPages.php
includes/api/ApiQueryAllUsers.php
includes/api/ApiQueryBacklinks.php
includes/api/ApiQueryBacklinksprop.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryBlocks.php
includes/api/ApiQueryCategories.php
includes/api/ApiQueryCategoryMembers.php
includes/api/ApiQueryDeletedRevisions.php
includes/api/ApiQueryDeletedrevs.php
includes/api/ApiQueryDisabled.php
includes/api/ApiQueryFilearchive.php
includes/api/ApiQueryIWBacklinks.php
includes/api/ApiQueryIWLinks.php
includes/api/ApiQueryImageInfo.php
includes/api/ApiQueryImages.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryLangBacklinks.php
includes/api/ApiQueryLangLinks.php
includes/api/ApiQueryLinks.php
includes/api/ApiQueryLogEvents.php
includes/api/ApiQueryMyStashedFiles.php
includes/api/ApiQueryQueryPage.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQueryRevisionsBase.php
includes/api/ApiQuerySearch.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiQueryStashImageInfo.php
includes/api/ApiQueryTokens.php
includes/api/ApiQueryUserContributions.php
includes/api/ApiQueryUserInfo.php
includes/api/ApiQueryUsers.php
includes/api/ApiQueryWatchlist.php
includes/api/ApiQueryWatchlistRaw.php
includes/api/ApiRemoveAuthenticationData.php
includes/api/ApiResetPassword.php
includes/api/ApiResult.php
includes/api/ApiRevisionDelete.php
includes/api/ApiRollback.php
includes/api/ApiSetNotificationTimestamp.php
includes/api/ApiStashEdit.php
includes/api/ApiTag.php
includes/api/ApiTokens.php
includes/api/ApiUnblock.php
includes/api/ApiUndelete.php
includes/api/ApiUpload.php
includes/api/ApiUsageException.php [new file with mode: 0644]
includes/api/ApiWatch.php
includes/api/i18n/ar.json
includes/api/i18n/ast.json
includes/api/i18n/bgn.json
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/es.json
includes/api/i18n/fr.json
includes/api/i18n/gl.json
includes/api/i18n/he.json
includes/api/i18n/hu.json
includes/api/i18n/id.json
includes/api/i18n/it.json
includes/api/i18n/ja.json
includes/api/i18n/ko.json
includes/api/i18n/lb.json
includes/api/i18n/lij.json
includes/api/i18n/mk.json
includes/api/i18n/nb.json
includes/api/i18n/nl.json
includes/api/i18n/pl.json
includes/api/i18n/pt.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/th.json [new file with mode: 0644]
includes/api/i18n/uk.json
includes/api/i18n/zh-hans.json
includes/auth/AuthManager.php
includes/auth/AuthenticationRequest.php
includes/auth/LocalPasswordPrimaryAuthenticationProvider.php
includes/auth/RememberMeAuthenticationRequest.php
includes/auth/TemporaryPasswordAuthenticationRequest.php
includes/auth/TemporaryPasswordPrimaryAuthenticationProvider.php
includes/auth/Throttler.php
includes/auth/UserDataAuthenticationRequest.php
includes/cache/CacheHelper.php
includes/cache/MessageCache.php
includes/changes/RecentChange.php
includes/changetags/ChangeTags.php
includes/changetags/ChangeTagsLogItem.php
includes/collation/Collation.php
includes/collation/IcuCollation.php
includes/collation/NumericUppercaseCollation.php
includes/content/CodeContentHandler.php
includes/context/RequestContext.php
includes/db/DatabaseMssql.php
includes/db/DatabaseOracle.php
includes/db/MWLBFactory.php
includes/debug/logger/LegacyLogger.php
includes/debug/logger/monolog/LogstashFormatter.php [new file with mode: 0644]
includes/diff/DifferenceEngine.php
includes/exception/MWExceptionRenderer.php
includes/filerepo/ForeignDBRepo.php
includes/filerepo/ForeignDBViaLBRepo.php
includes/filerepo/LocalRepo.php
includes/filerepo/file/File.php
includes/filerepo/file/ForeignDBFile.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLFormField.php
includes/htmlform/fields/HTMLAutoCompleteSelectField.php
includes/htmlform/fields/HTMLButtonField.php
includes/htmlform/fields/HTMLCheckMatrix.php
includes/htmlform/fields/HTMLDateTimeField.php
includes/htmlform/fields/HTMLFloatField.php
includes/htmlform/fields/HTMLFormFieldCloner.php
includes/htmlform/fields/HTMLIntField.php
includes/htmlform/fields/HTMLMultiSelectField.php
includes/htmlform/fields/HTMLRadioField.php
includes/htmlform/fields/HTMLRestrictionsField.php
includes/htmlform/fields/HTMLSelectAndOtherField.php
includes/htmlform/fields/HTMLSelectField.php
includes/htmlform/fields/HTMLTextField.php
includes/htmlform/fields/HTMLTitleTextField.php
includes/htmlform/fields/HTMLUserTextField.php
includes/http/CurlHttpRequest.php
includes/http/Http.php
includes/http/MWHttpRequest.php
includes/http/PhpHttpRequest.php
includes/import/WikiImporter.php
includes/installer/DatabaseUpdater.php
includes/installer/i18n/ar.json
includes/installer/i18n/ast.json
includes/installer/i18n/be.json
includes/installer/i18n/bn.json
includes/installer/i18n/cs.json
includes/installer/i18n/en.json
includes/installer/i18n/et.json
includes/installer/i18n/fa.json
includes/installer/i18n/fr.json
includes/installer/i18n/ia.json
includes/installer/i18n/ja.json
includes/installer/i18n/ko.json
includes/installer/i18n/ku-latn.json
includes/installer/i18n/nb.json
includes/installer/i18n/nl.json
includes/installer/i18n/pt.json
includes/installer/i18n/qqq.json
includes/installer/i18n/sd.json
includes/installer/i18n/th.json
includes/installer/i18n/udm.json
includes/installer/i18n/uk.json
includes/installer/i18n/zh-hans.json
includes/installer/i18n/zh-hant.json
includes/libs/CookieJar.php
includes/libs/MapCacheLRU.php
includes/libs/Xhprof.php
includes/libs/objectcache/APCUBagOStuff.php
includes/libs/objectcache/WinCacheBagOStuff.php
includes/libs/rdbms/connectionmanager/ConnectionManager.php [new file with mode: 0644]
includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManager.php [new file with mode: 0644]
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/database/IDatabase.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/libs/rdbms/loadmonitor/LoadMonitorMySQL.php
includes/logging/BlockLogFormatter.php
includes/logging/ContentModelLogFormatter.php
includes/logging/DeleteLogFormatter.php
includes/logging/LogEventsList.php
includes/media/Bitmap.php
includes/media/DjVu.php
includes/media/Jpeg.php
includes/media/MediaTransformOutput.php
includes/media/SVG.php
includes/media/TransformationalImageHandler.php
includes/objectcache/SqlBagOStuff.php
includes/page/Article.php
includes/page/ImageHistoryPseudoPager.php
includes/page/WikiFilePage.php
includes/page/WikiPage.php
includes/parser/CoreParserFunctions.php
includes/parser/Parser.php
includes/password/EncryptedPassword.php
includes/password/MWOldPassword.php
includes/password/ParameterizedPassword.php
includes/password/Password.php
includes/password/UserPasswordPolicy.php
includes/profiler/ProfilerXhprof.php
includes/registration/ExtensionJsonValidationError.php [new file with mode: 0644]
includes/registration/ExtensionJsonValidator.php [new file with mode: 0644]
includes/registration/ExtensionProcessor.php
includes/registration/ExtensionRegistry.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderClientHtml.php
includes/resourceloader/ResourceLoaderContext.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderImageModule.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php [deleted file]
includes/resourceloader/ResourceLoaderUserOptionsModule.php
includes/resourceloader/ResourceLoaderUserTokensModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/revisiondelete/RevDelArchiveItem.php
includes/revisiondelete/RevDelArchivedFileItem.php
includes/revisiondelete/RevDelFileItem.php
includes/revisiondelete/RevDelLogItem.php
includes/revisiondelete/RevDelRevisionItem.php
includes/session/SessionManager.php
includes/skins/QuickTemplate.php
includes/skins/Skin.php
includes/skins/SkinTemplate.php
includes/specialpage/ChangesListSpecialPage.php
includes/specialpage/LoginSignupSpecialPage.php
includes/specialpage/WantedQueryPage.php
includes/specials/SpecialActiveusers.php
includes/specials/SpecialAllPages.php
includes/specials/SpecialAncientpages.php
includes/specials/SpecialApiHelp.php
includes/specials/SpecialBlock.php
includes/specials/SpecialBrokenRedirects.php
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialDoubleRedirects.php
includes/specials/SpecialEditTags.php
includes/specials/SpecialEmailuser.php
includes/specials/SpecialFewestrevisions.php
includes/specials/SpecialFileDuplicateSearch.php
includes/specials/SpecialImport.php
includes/specials/SpecialListgrants.php
includes/specials/SpecialListgrouprights.php
includes/specials/SpecialMIMEsearch.php
includes/specials/SpecialMediaStatistics.php
includes/specials/SpecialMergeHistory.php
includes/specials/SpecialMostcategories.php
includes/specials/SpecialMostinterwikis.php
includes/specials/SpecialMostlinked.php
includes/specials/SpecialMostlinkedtemplates.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialPasswordReset.php
includes/specials/SpecialPrefixindex.php
includes/specials/SpecialProtectedtitles.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialRevisiondelete.php
includes/specials/SpecialSearch.php
includes/specials/SpecialSpecialpages.php
includes/specials/SpecialStatistics.php
includes/specials/SpecialTrackingCategories.php
includes/specials/SpecialUnblock.php
includes/specials/SpecialUndelete.php
includes/specials/SpecialUnusedcategories.php
includes/specials/SpecialUpload.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialVersion.php
includes/specials/SpecialWantedcategories.php
includes/specials/SpecialWatchlist.php
includes/specials/pagers/ActiveUsersPager.php
includes/specials/pagers/AllMessagesTablePager.php
includes/specials/pagers/BlockListPager.php
includes/specials/pagers/CategoryPager.php
includes/specials/pagers/ContribsPager.php
includes/specials/pagers/DeletedContribsPager.php
includes/specials/pagers/ImageListPager.php
includes/specials/pagers/NewFilesPager.php
includes/upload/UploadStash.php
includes/user/PasswordReset.php
includes/user/User.php
jsduck.json
languages/data/Names.php
languages/i18n/ace.json
languages/i18n/ady-cyrl.json
languages/i18n/aeb-arab.json
languages/i18n/af.json
languages/i18n/aln.json
languages/i18n/am.json
languages/i18n/an.json
languages/i18n/anp.json
languages/i18n/ar.json
languages/i18n/arc.json
languages/i18n/arq.json
languages/i18n/ary.json
languages/i18n/arz.json
languages/i18n/as.json
languages/i18n/ase.json
languages/i18n/ast.json
languages/i18n/av.json
languages/i18n/avk.json
languages/i18n/awa.json
languages/i18n/az.json
languages/i18n/azb.json
languages/i18n/ba.json
languages/i18n/ban.json
languages/i18n/bar.json
languages/i18n/bcc.json
languages/i18n/bcl.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bgn.json
languages/i18n/bho.json
languages/i18n/bjn.json
languages/i18n/bn.json
languages/i18n/bo.json
languages/i18n/bpy.json
languages/i18n/bqi.json
languages/i18n/br.json
languages/i18n/bs.json
languages/i18n/bto.json
languages/i18n/ca.json
languages/i18n/ce.json
languages/i18n/ceb.json
languages/i18n/ch.json
languages/i18n/ckb.json
languages/i18n/co.json
languages/i18n/cps.json
languages/i18n/crh-latn.json
languages/i18n/cs.json
languages/i18n/csb.json
languages/i18n/cv.json
languages/i18n/cy.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/dsb.json
languages/i18n/dtp.json
languages/i18n/dty.json
languages/i18n/dv.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/eu.json
languages/i18n/ext.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/frc.json
languages/i18n/frp.json
languages/i18n/frr.json
languages/i18n/fur.json
languages/i18n/fy.json
languages/i18n/ga.json
languages/i18n/gag.json
languages/i18n/gan-hans.json
languages/i18n/gan-hant.json
languages/i18n/gd.json
languages/i18n/gl.json
languages/i18n/glk.json
languages/i18n/gom-deva.json
languages/i18n/gom-latn.json
languages/i18n/gor.json
languages/i18n/grc.json
languages/i18n/gsw.json
languages/i18n/gv.json
languages/i18n/haw.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hif-latn.json
languages/i18n/hil.json
languages/i18n/hr.json
languages/i18n/hrx.json
languages/i18n/hsb.json
languages/i18n/ht.json
languages/i18n/hu.json
languages/i18n/hy.json
languages/i18n/ia.json
languages/i18n/id.json
languages/i18n/ie.json
languages/i18n/ig.json
languages/i18n/ilo.json
languages/i18n/inh.json
languages/i18n/is.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jam.json
languages/i18n/jut.json
languages/i18n/jv.json
languages/i18n/ka.json
languages/i18n/kaa.json
languages/i18n/kab.json
languages/i18n/kbd-cyrl.json
languages/i18n/khw.json
languages/i18n/kk-arab.json
languages/i18n/kk-cyrl.json
languages/i18n/kk-latn.json
languages/i18n/km.json
languages/i18n/ko.json
languages/i18n/krc.json
languages/i18n/kri.json
languages/i18n/ksh.json
languages/i18n/ku-latn.json
languages/i18n/kw.json
languages/i18n/la.json
languages/i18n/lad.json
languages/i18n/lb.json
languages/i18n/lfn.json
languages/i18n/lg.json
languages/i18n/li.json
languages/i18n/lij.json
languages/i18n/liv.json
languages/i18n/lki.json
languages/i18n/lmo.json
languages/i18n/lo.json
languages/i18n/loz.json
languages/i18n/lrc.json
languages/i18n/lt.json
languages/i18n/ltg.json
languages/i18n/lus.json
languages/i18n/lv.json
languages/i18n/lzh.json
languages/i18n/mai.json
languages/i18n/map-bms.json
languages/i18n/mdf.json
languages/i18n/mg.json
languages/i18n/min.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/mr.json
languages/i18n/ms.json
languages/i18n/mwl.json
languages/i18n/my.json
languages/i18n/myv.json
languages/i18n/mzn.json
languages/i18n/nah.json
languages/i18n/nan.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nds.json
languages/i18n/ne.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/oc.json
languages/i18n/os.json
languages/i18n/pa.json
languages/i18n/pam.json
languages/i18n/pcd.json
languages/i18n/pdc.json
languages/i18n/pfl.json
languages/i18n/pl.json
languages/i18n/pms.json
languages/i18n/pnb.json
languages/i18n/pnt.json
languages/i18n/prg.json
languages/i18n/ps.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/qug.json
languages/i18n/rm.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/rue.json
languages/i18n/sa.json
languages/i18n/sah.json
languages/i18n/sat.json
languages/i18n/sc.json
languages/i18n/sco.json
languages/i18n/sd.json
languages/i18n/sdc.json
languages/i18n/sdh.json
languages/i18n/se.json
languages/i18n/sei.json
languages/i18n/ses.json
languages/i18n/sgs.json
languages/i18n/sh.json
languages/i18n/shi.json
languages/i18n/shn.json
languages/i18n/si.json
languages/i18n/sk.json
languages/i18n/sl.json
languages/i18n/sli.json
languages/i18n/sq.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/srn.json
languages/i18n/stq.json
languages/i18n/su.json
languages/i18n/sv.json
languages/i18n/sw.json
languages/i18n/ta.json
languages/i18n/tcy.json
languages/i18n/te.json
languages/i18n/tet.json
languages/i18n/tg-cyrl.json
languages/i18n/tg-latn.json
languages/i18n/th.json
languages/i18n/tk.json
languages/i18n/tl.json
languages/i18n/tly.json
languages/i18n/to.json
languages/i18n/tpi.json
languages/i18n/tr.json
languages/i18n/tru.json
languages/i18n/ts.json
languages/i18n/tt-cyrl.json
languages/i18n/tt-latn.json
languages/i18n/tyv.json
languages/i18n/udm.json
languages/i18n/ug-arab.json
languages/i18n/uk.json
languages/i18n/ur.json
languages/i18n/uz.json
languages/i18n/vep.json
languages/i18n/vi.json
languages/i18n/vmf.json
languages/i18n/vo.json
languages/i18n/vot.json
languages/i18n/wa.json
languages/i18n/war.json
languages/i18n/wuu.json
languages/i18n/xal.json
languages/i18n/xmf.json
languages/i18n/yi.json
languages/i18n/yo.json
languages/i18n/zea.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesBn.php
languages/messages/MessagesKrl.php [new file with mode: 0644]
languages/messages/MessagesMdf.php
languages/messages/MessagesOlo.php
languages/messages/MessagesRoa_tara.php
languages/messages/MessagesUk.php
maintenance/Maintenance.php
maintenance/backup.inc
maintenance/cleanupRemovedModules.php
maintenance/cleanupUploadStash.php
maintenance/dictionary/mediawiki.dic
maintenance/doMaintenance.php
maintenance/findMissingFiles.php
maintenance/findOrphanedFiles.php
maintenance/importTextFiles.php
maintenance/jsduck/categories.json
maintenance/mergeMessageFileList.php
maintenance/populateContentModel.php
maintenance/protect.php
maintenance/purgeChangedFiles.php
maintenance/purgeParserCache.php
maintenance/runBatchedQuery.php
maintenance/storage/checkStorage.php
maintenance/updateCredits.php
maintenance/validateRegistrationFile.php
maintenance/wrapOldPasswords.php
package.json
phpcs.xml
resources/Resources.php
resources/lib/json2/json2.js [deleted file]
resources/lib/oojs-ui/i18n/el.json
resources/lib/oojs-ui/oojs-ui-apex.js
resources/lib/oojs-ui/oojs-ui-core-apex.css
resources/lib/oojs-ui/oojs-ui-core-mediawiki.css
resources/lib/oojs-ui/oojs-ui-core.js
resources/lib/oojs-ui/oojs-ui-mediawiki.js
resources/lib/oojs-ui/oojs-ui-toolbars-apex.css
resources/lib/oojs-ui/oojs-ui-toolbars-mediawiki.css
resources/lib/oojs-ui/oojs-ui-toolbars.js
resources/lib/oojs-ui/oojs-ui-widgets-apex.css
resources/lib/oojs-ui/oojs-ui-widgets-mediawiki.css
resources/lib/oojs-ui/oojs-ui-widgets.js
resources/lib/oojs-ui/oojs-ui-windows-apex.css
resources/lib/oojs-ui/oojs-ui-windows-mediawiki.css
resources/lib/oojs-ui/oojs-ui-windows.js
resources/lib/oojs-ui/themes/mediawiki/icons-alerts.json
resources/lib/oojs-ui/themes/mediawiki/icons-content.json
resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json
resources/lib/oojs-ui/themes/mediawiki/icons-editing-core.json
resources/lib/oojs-ui/themes/mediawiki/icons-editing-list.json
resources/lib/oojs-ui/themes/mediawiki/icons-editing-styling.json
resources/lib/oojs-ui/themes/mediawiki/icons-interactions.json
resources/lib/oojs-ui/themes/mediawiki/icons-layout.json
resources/lib/oojs-ui/themes/mediawiki/icons-location.json
resources/lib/oojs-ui/themes/mediawiki/icons-media.json
resources/lib/oojs-ui/themes/mediawiki/icons-moderation.json
resources/lib/oojs-ui/themes/mediawiki/icons-movement.json
resources/lib/oojs-ui/themes/mediawiki/icons-user.json
resources/lib/oojs-ui/themes/mediawiki/icons-wikimedia.json
resources/lib/oojs-ui/themes/mediawiki/icons.json
resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-progressive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-progressive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-progressive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-progressive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-progressive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-progressive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.svg
resources/lib/oojs-ui/themes/mediawiki/indicators.json
resources/lib/qunitjs/qunit.css
resources/lib/qunitjs/qunit.js
resources/src/jquery/jquery.accessKeyLabel.js
resources/src/jquery/jquery.autoEllipsis.js
resources/src/jquery/jquery.byteLimit.js
resources/src/jquery/jquery.color.js
resources/src/jquery/jquery.colorUtil.js
resources/src/jquery/jquery.confirmable.js
resources/src/jquery/jquery.expandableField.js
resources/src/jquery/jquery.hidpi.js
resources/src/jquery/jquery.highlightText.js
resources/src/jquery/jquery.localize.js
resources/src/jquery/jquery.mwExtension.js
resources/src/jquery/jquery.placeholder.js
resources/src/jquery/jquery.qunit.completenessTest.js
resources/src/jquery/jquery.spinner.js
resources/src/jquery/jquery.suggestions.js
resources/src/jquery/jquery.tablesorter.js
resources/src/jquery/jquery.textSelection.js
resources/src/json-skip.js [deleted file]
resources/src/mediawiki.action/mediawiki.action.edit.stash.js
resources/src/mediawiki.action/mediawiki.action.history.js
resources/src/mediawiki.action/mediawiki.action.history.styles.css
resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js
resources/src/mediawiki.action/mediawiki.action.view.filepage.css
resources/src/mediawiki.action/mediawiki.action.view.redirect.js
resources/src/mediawiki.language/languages/ga.js
resources/src/mediawiki.language/languages/he.js
resources/src/mediawiki.language/languages/hy.js
resources/src/mediawiki.language/mediawiki.language.js
resources/src/mediawiki.language/mediawiki.language.numbers.js
resources/src/mediawiki.legacy/protect.js
resources/src/mediawiki.legacy/shared.css
resources/src/mediawiki.legacy/wikibits.js
resources/src/mediawiki.less/mediawiki.ui/variables.less
resources/src/mediawiki.messagePoster/mediawiki.messagePoster.MessagePoster.js
resources/src/mediawiki.messagePoster/mediawiki.messagePoster.WikitextMessagePoster.js
resources/src/mediawiki.messagePoster/mediawiki.messagePoster.factory.js
resources/src/mediawiki.skinning/content.css
resources/src/mediawiki.skinning/elements.css
resources/src/mediawiki.skinning/interface.css
resources/src/mediawiki.special/mediawiki.special.apisandbox.js
resources/src/mediawiki.special/mediawiki.special.edittags.js
resources/src/mediawiki.special/mediawiki.special.search.styles.css
resources/src/mediawiki.special/mediawiki.special.upload.js
resources/src/mediawiki.toolbar/toolbar.js
resources/src/mediawiki.widgets.datetime/CalendarWidget.js
resources/src/mediawiki.widgets.datetime/DateTimeFormatter.js
resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js
resources/src/mediawiki.widgets.datetime/DiscordianDateTimeFormatter.js
resources/src/mediawiki.widgets.datetime/ProlepticGregorianDateTimeFormatter.js
resources/src/mediawiki.widgets/MediaSearch/broken-image.png [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css [new file with mode: 0644]
resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js [new file with mode: 0644]
resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.js
resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js
resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.js
resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js
resources/src/mediawiki.widgets/mw.widgets.NamespaceInputWidget.js
resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js
resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js
resources/src/mediawiki.widgets/mw.widgets.TitleSearchWidget.js
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
resources/src/mediawiki.widgets/mw.widgets.UserInputWidget.js
resources/src/mediawiki/ForeignApi.js
resources/src/mediawiki/api.js
resources/src/mediawiki/api/edit.js
resources/src/mediawiki/api/parse.js
resources/src/mediawiki/api/upload.js
resources/src/mediawiki/api/watch.js
resources/src/mediawiki/htmlform/hide-if.js
resources/src/mediawiki/htmlform/htmlform.Element.js
resources/src/mediawiki/htmlform/multiselect.js
resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js
resources/src/mediawiki/mediawiki.ForeignUpload.js
resources/src/mediawiki/mediawiki.Title.js
resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
resources/src/mediawiki/mediawiki.Upload.Dialog.js
resources/src/mediawiki/mediawiki.Upload.js
resources/src/mediawiki/mediawiki.Uri.js
resources/src/mediawiki/mediawiki.checkboxtoggle.js
resources/src/mediawiki/mediawiki.confirmCloseWindow.js
resources/src/mediawiki/mediawiki.debug.js
resources/src/mediawiki/mediawiki.errorLogger.js
resources/src/mediawiki/mediawiki.experiments.js
resources/src/mediawiki/mediawiki.feedback.js
resources/src/mediawiki/mediawiki.filewarning.js
resources/src/mediawiki/mediawiki.inspect.js
resources/src/mediawiki/mediawiki.jqueryMsg.js
resources/src/mediawiki/mediawiki.js
resources/src/mediawiki/mediawiki.log.js
resources/src/mediawiki/mediawiki.notification.js
resources/src/mediawiki/mediawiki.searchSuggest.js
resources/src/mediawiki/mediawiki.storage.js
resources/src/mediawiki/mediawiki.template.mustache.js
resources/src/mediawiki/mediawiki.user.blockcookie.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.user.js
resources/src/mediawiki/mediawiki.util.js
resources/src/mediawiki/mediawiki.viewport.js
resources/src/mediawiki/page/gallery-slideshow.js
resources/src/mediawiki/page/gallery.css
resources/src/mediawiki/page/image-pagination.js
resources/src/mediawiki/page/patrol.ajax.js
resources/src/mediawiki/page/rollback.js
resources/src/mediawiki/page/startup.js
resources/src/moment-dmy.js
resources/src/moment-locale-overrides.js
resources/src/polyfill-nodeTypes.js
resources/src/startup.js
tests/common/TestsAutoLoader.php
tests/integration/includes/http/CurlHttpRequestTest.php [new file with mode: 0644]
tests/integration/includes/http/MWHttpRequestTestCase.php [new file with mode: 0644]
tests/integration/includes/http/PhpHttpRequestTest.php [new file with mode: 0644]
tests/parser/ParserTestMockParser.php [new file with mode: 0644]
tests/parser/ParserTestRunner.php
tests/parser/parserTests.txt
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/ResourceLoaderTestCase.php
tests/phpunit/data/localisationcache/ba.json [new file with mode: 0644]
tests/phpunit/data/localisationcache/en.json
tests/phpunit/data/localisationcache/ru.json
tests/phpunit/data/localisationcache/uk.json [deleted file]
tests/phpunit/includes/HttpTest.php [deleted file]
tests/phpunit/includes/MessageTest.php
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/PrefixSearchTest.php
tests/phpunit/includes/WatchedItemQueryServiceUnitTest.php
tests/phpunit/includes/XmlTest.php
tests/phpunit/includes/api/ApiBaseTest.php
tests/phpunit/includes/api/ApiBlockTest.php
tests/phpunit/includes/api/ApiContinuationManagerTest.php
tests/phpunit/includes/api/ApiEditPageTest.php
tests/phpunit/includes/api/ApiErrorFormatterTest.php
tests/phpunit/includes/api/ApiMainTest.php
tests/phpunit/includes/api/ApiMessageTest.php
tests/phpunit/includes/api/ApiOptionsTest.php
tests/phpunit/includes/api/ApiParseTest.php
tests/phpunit/includes/api/ApiQueryWatchlistIntegrationTest.php
tests/phpunit/includes/api/ApiQueryWatchlistRawIntegrationTest.php
tests/phpunit/includes/api/ApiTestCase.php
tests/phpunit/includes/api/ApiUnblockTest.php
tests/phpunit/includes/api/ApiUploadTest.php
tests/phpunit/includes/api/ApiWatchTest.php
tests/phpunit/includes/api/MockApi.php
tests/phpunit/includes/api/MockApiQueryBase.php
tests/phpunit/includes/api/format/ApiFormatPhpTest.php
tests/phpunit/includes/api/format/ApiFormatXmlTest.php
tests/phpunit/includes/api/query/ApiQueryTest.php
tests/phpunit/includes/auth/AbstractPasswordPrimaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/LegacyHookPreAuthenticationProviderTest.php
tests/phpunit/includes/auth/LocalPasswordPrimaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/TemporaryPasswordPrimaryAuthenticationProviderTest.php
tests/phpunit/includes/auth/ThrottlerTest.php
tests/phpunit/includes/cache/GenderCacheTest.php
tests/phpunit/includes/cache/LocalisationCacheTest.php
tests/phpunit/includes/config/ConfigFactoryTest.php
tests/phpunit/includes/debug/logger/monolog/LogstashFormatterTest.php [new file with mode: 0644]
tests/phpunit/includes/htmlform/HTMLAutoCompleteSelectFieldTest.php
tests/phpunit/includes/htmlform/HTMLCheckMatrixTest.php
tests/phpunit/includes/http/HttpTest.php [new file with mode: 0644]
tests/phpunit/includes/import/ImportLinkCacheIntegrationTest.php
tests/phpunit/includes/import/ImportTest.php
tests/phpunit/includes/installer/DatabaseUpdaterTest.php [deleted file]
tests/phpunit/includes/libs/rdbms/connectionmanager/ConnectionManagerTest.php [new file with mode: 0644]
tests/phpunit/includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManagerTest.php [new file with mode: 0644]
tests/phpunit/includes/page/ArticleTest.php
tests/phpunit/includes/page/WikiPageTest.php
tests/phpunit/includes/registration/ExtensionRegistryTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderClientHtmlTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderContextTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderImageTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
tests/phpunit/includes/search/SearchEnginePrefixTest.php
tests/phpunit/includes/specials/SpecialRecentchangesTest.php
tests/phpunit/includes/upload/UploadFromUrlTest.php
tests/phpunit/includes/user/PasswordResetTest.php
tests/phpunit/includes/user/UserTest.php
tests/phpunit/maintenance/MaintenanceTest.php
tests/phpunit/structure/ExtensionJsonValidationTest.php
tests/phpunit/suite.xml
tests/phpunit/tests/MediaWikiTestCaseTest.php
tests/qunit/data/testrunner.js
tests/qunit/suites/resources/jquery/jquery.color.test.js
tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.ForeignApi.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.messages.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.options.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.upload.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.storage.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.test.js
thumb.php

diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644 (file)
index 0000000..044dd72
--- /dev/null
@@ -0,0 +1,18 @@
+{
+       "extends": "wikimedia",
+       "env": {
+               "browser": true,
+               "jquery": true,
+               "qunit": true
+       },
+       "globals": {
+               "require": false,
+               "module": false,
+               "mediaWiki": false,
+               "mwPerformance": false,
+               "OO": false
+       },
+       "rules": {
+               "dot-notation": 0
+       }
+}
diff --git a/.jscsrc b/.jscsrc
deleted file mode 100644 (file)
index 3f7e90d..0000000
--- a/.jscsrc
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-       "preset": "wikimedia",
-       "es3": true,
-
-       "requireVarDeclFirst": null,
-
-       "requireDotNotation": { "allExcept": [ "keywords" ] },
-       "jsDoc": {
-               "checkAnnotations": {
-                       "preset": "jsduck5",
-                       "extra": {
-                               "context": "some",
-                               "see": "some"
-                       }
-               },
-               "checkParamNames": true,
-               "checkRedundantAccess": true,
-               "checkRedundantReturns": true,
-               "checkTypes": "strictNativeCase",
-               "requireNewlineAfterDescription": true,
-               "requireParamTypes": true,
-               "requireReturnTypes": true
-       },
-
-       "excludeFiles": [
-               "docs/**",
-               "extensions/**",
-               "node_modules/**",
-               "resources/lib/**",
-               "resources/src/jquery.tipsy/**",
-               "resources/src/jquery/jquery.farbtastic.js",
-               "resources/src/mediawiki.libs/**",
-               "skins/**",
-               "vendor/**"
-       ]
-}
diff --git a/.jshintignore b/.jshintignore
deleted file mode 100644 (file)
index fdde7d0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# Generated documentation
-docs/**
-
-# third-party libs
-extensions/**
-node_modules/**
-resources/lib/**
-resources/src/jquery.tipsy/**
-resources/src/jquery/jquery.farbtastic.js
-resources/src/mediawiki.libs/**
-skins/**
-vendor/**
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100644 (file)
index 441c4e3..0000000
--- a/.jshintrc
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-       // Enforcing
-       "bitwise": true,
-       "eqeqeq": true,
-       "esversion": 3,
-       "freeze": true,
-       "futurehostile": true,
-       "latedef": "nofunc",
-       "noarg": true,
-       "nonew": true,
-       "strict": false,
-       "undef": true,
-       "unused": true,
-
-       // Relaxing
-       "laxbreak": true,
-       "multistr": true,
-
-       // Environment
-       "browser": true,
-
-       "globals": {
-               "require": false,
-               "module": false,
-               "mediaWiki": true,
-               "JSON": true,
-               "OO": true,
-               "mwPerformance": true,
-               "jQuery": false,
-               "QUnit": false,
-               "sinon": false
-       }
-}
index 6d9f8e8..dd968e8 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -3,18 +3,18 @@
 #
 # To update the CREDITS file, run maintenance/updateCredits.php
 #
-# Two types of entries are useful here. The first sets a cannonical author
+# Two types of entries are useful here. The first sets a canonical author
 # name for a given email address:
 #
-#   Cannonical Author Name <author email>
+#   Canonical Author Name <author email>
 #
 # The second allows collecting alternate email addresses into a single
-# cannonical author name and email address:
+# canonical author name and email address:
 #
-#   Cannonical Author Name <author email> <alternate email>
+#   Canonical Author Name <author email> <alternate email>
 #
 # Mappings are only needed for authors who have used multiple author names
-# and/or author emails for revisions over time. Author names begenning with
+# and/or author emails for revisions over time. Author names beginning with
 # "[BOT]" will be omitted from the CREDITS file.
 #
 # See also: https://git-scm.com/docs/git-shortlog#_mapping_authors
@@ -32,9 +32,9 @@ addshore <addshorewiki@gmail.com>
 Aditya Sastry <ganeshaditya1@gmail.com>
 Adrian Heine <adrian.heine@wikimedia.de>
 Alex Z. <mrzmanwiki@gmail.com> <mrzman@users.mediawiki.org>
-Alexander Emsenhuber <ialex.wiki@gmail.com>
-Alexander Emsenhuber <ialex.wiki@gmail.com> <ialex@users.mediawiki.org>
-Alexander Emsenhuber <ialex.wiki@gmail.com> <mediawiki@emsenhuber.ch>
+Alexandre Emsenhuber <ialex.wiki@gmail.com>
+Alexandre Emsenhuber <ialex.wiki@gmail.com> <ialex@users.mediawiki.org>
+Alexandre Emsenhuber <ialex.wiki@gmail.com> <mediawiki@emsenhuber.ch>
 Alexander Monk <krenair@gmail.com>
 Alexander Monk <krenair@gmail.com> <alex@wikimedia.org>
 Alexander Monk <krenair@gmail.com> <krenair@wikimedia.org>
diff --git a/CREDITS b/CREDITS
index 1c1cf87..d9ff970 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -34,7 +34,6 @@ following names for their contribution to the product.
 * Alex Ivanov
 * Alex Shih-Han Lin
 * Alex Z.
-* Alexander Emsenhuber
 * Alexander I. Mashin
 * Alexander Lehmann
 * Alexander Monk
index a08db5c..55b7932 100644 (file)
@@ -1,33 +1,44 @@
-/*jshint node:true */
+/* eslint-env node */
+
 module.exports = function ( grunt ) {
-       grunt.loadNpmTasks( 'grunt-contrib-copy' );
-       grunt.loadNpmTasks( 'grunt-contrib-jshint' );
-       grunt.loadNpmTasks( 'grunt-stylelint' );
-       grunt.loadNpmTasks( 'grunt-contrib-watch' );
-       grunt.loadNpmTasks( 'grunt-banana-checker' );
-       grunt.loadNpmTasks( 'grunt-jscs' );
-       grunt.loadNpmTasks( 'grunt-jsonlint' );
-       grunt.loadNpmTasks( 'grunt-karma' );
 
        var wgServer = process.env.MW_SERVER,
                wgScriptPath = process.env.MW_SCRIPT_PATH,
                karmaProxy = {};
 
+       grunt.loadNpmTasks( 'grunt-banana-checker' );
+       grunt.loadNpmTasks( 'grunt-contrib-copy' );
+       grunt.loadNpmTasks( 'grunt-contrib-watch' );
+       grunt.loadNpmTasks( 'grunt-eslint' );
+       grunt.loadNpmTasks( 'grunt-jsonlint' );
+       grunt.loadNpmTasks( 'grunt-karma' );
+       grunt.loadNpmTasks( 'grunt-stylelint' );
+
        karmaProxy[ wgScriptPath ] = wgServer + wgScriptPath;
 
        grunt.initConfig( {
-               jshint: {
-                       options: {
-                               jshintrc: true
-                       },
-                       all: '.'
-               },
-               jscs: {
-                       all: '.'
+               eslint: {
+                       all: [
+                               '**/*.js',
+                               '!docs/**',
+                               '!tests/**',
+                               '!node_modules/**',
+                               '!resources/lib/**',
+                               '!resources/src/jquery.tipsy/**',
+                               '!resources/src/jquery/jquery.farbtastic.js',
+                               '!resources/src/mediawiki.libs/**',
+                               '!vendor/**',
+                               // Explicitly say "**/*.js" here in case of symlinks
+                               '!extensions/**/*.js',
+                               '!skins/**/*.js',
+                               // Skip functions aren't even parseable
+                               '!resources/src/dom-level2-skip.js',
+                               '!resources/src/es5-skip.js',
+                               '!resources/src/mediawiki.hidpi-skip.js'
+                       ]
                },
                jsonlint: {
                        all: [
-                               '.jscsrc',
                                '**/*.json',
                                '!{docs/js,extensions,node_modules,skins,vendor}/**'
                        ]
@@ -48,7 +59,7 @@ module.exports = function ( grunt ) {
                },
                watch: {
                        files: [
-                               '.{stylelintrc,jscsrc,jshintignore,jshintrc}',
+                               '.{stylelintrc,eslintrc.json}',
                                '**/*',
                                '!{docs,extensions,node_modules,skins,vendor}/**'
                        ],
@@ -103,7 +114,7 @@ module.exports = function ( grunt ) {
                return !!( process.env.MW_SERVER && process.env.MW_SCRIPT_PATH );
        } );
 
-       grunt.registerTask( 'lint', [ 'jshint', 'jscs', 'jsonlint', 'banana', 'stylelint' ] );
+       grunt.registerTask( 'lint', [ 'eslint', 'banana', 'stylelint' ] );
        grunt.registerTask( 'qunit', [ 'assert-mw-env', 'karma:main' ] );
 
        grunt.registerTask( 'test', [ 'lint' ] );
diff --git a/HISTORY b/HISTORY
index 6de7de4..28a9b86 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -1,4 +1,328 @@
-Change notes from older releases. For current info see RELEASE-NOTES-1.28.
+Change notes from older releases. For current info see RELEASE-NOTES-1.29.
+
+== MediaWiki 1.28 ==
+
+=== Changes since 1.28.0-rc1 ===
+* (T148957) Replace wgShowExceptionDetails with wgShowDBErrorBacktrace on db
+  errors.
+* (T148956) Only apply wgDBschema to postgres/mssql.
+* (T145991) Introduce separate log action for deleting pages on move.
+* (T141474) (T110464) Bypass login page if no user input is required.
+
+=== Changes since 1.28.0-rc0 ===
+* (T142210) The changes to move the parser "NewPP limit report" from a HTML
+  comment to a machine-readable JavaScript config option 'wgPageParseReport'
+  have been undone. They caused the human-readable limit report to be shown
+  incompletely or not at all. ParserOutput::setLimitReportData() and
+  getLimitReportData() behave as they did in MediaWiki 1.27 again.
+* (T149510) Value of {{DISPLAYTITLE:}} parser function will not be used for
+  the text of subheadings on a category page when creating it. This wasn't
+  working correctly.
+* (T106793) MediaWiki will no longer try to perform a HTTP redirect to the
+  canonical pretty URL when a non-pretty URL is used. It resulted in redirect
+  loops in some clients and in some server configurations. This undoes a change
+  made in MediaWiki 1.26.
+* (T149759) manifest_version: 2 was removed.
+
+=== Configuration changes in 1.28 ===
+* $wgSend404Code now affects status code of action=history if the page is not there.
+* BREAKING CHANGE: $wgHTTPProxy is now *required* for all external requests
+  made by MediaWiki via a proxy. Relying on the http_proxy environment
+  variable is no longer supported.
+* The load.php entry point now enforces the existing policy of not allowing
+  access to session data, which includes the session user and the session
+  user's language. If such access is attempted, an exception will be thrown.
+* The number of internal PBKDF2 iterations used to derive the session secret
+  is configurable via $wgSessionPbkdf2Iterations.
+* Upload dialog's file upload log comment can now be configured separately for
+  local and foreign uploads.
+* $wgForeignUploadTargets now defaults to `[ 'local' ]`, where `'local'`
+  signifies local uploads. A value of `[]` (empty array) now means that
+  no upload targets are allowed, effectively disabling the upload dialog.
+* The deprecated $wgEditEncoding variable has been removed; it was only used
+  for Esperanto language character conversion. You are now recommended to use
+  input methods provided by the UniversalLanguageSelector extension.
+* When $wgPingback is true, MediaWiki will periodically ping
+  https://www.mediawiki.org/beacon with basic information about the local
+  MediaWiki installation. This data includes, for example, the type of system,
+  PHP version, and chosen database backend. This behavior is off by default.
+* When $wgEditSubmitButtonLabelPublish is true, MediaWiki will label the button
+  to store-to-database-and-show-to-others as "Publish page"/"Publish changes";
+  if false, the default, they will be "Save page"/"Save changes".
+* The 'editcontentmodel' permission is now granted to all logged-in users ('user').
+  instead of just administrators ('sysop'). Documentation for this feature is
+  available at <https://www.mediawiki.org/wiki/Help:ChangeContentModel>.
+* $wgRevisionCacheExpiry is now set to one week by default instead of being disabled.
+* Magic links are now disabled by default, and can be re-enabled by modifying the value
+  of $wgEnableMagicLinks. Their usage is discouraged, but if they are manually enabled,
+  a tracking category will be added to help identify usage and make it easier to migrate
+  away from. If you depend upon magic link functionality, it is requested that you comment
+  on <https://www.mediawiki.org/wiki/Requests_for_comment/Future_of_magic_links> and
+  explain your use case(s).
+* New config variable $wgCSPFalsePositiveUrls to control what URLs to ignore
+  in upcoming Content-Security-Policy feature's reporting.
+
+=== New features in 1.28 ===
+* User::isBot() method for checking if an account is a bot role account.
+* Added a new 'slideshow' mode for galleries.
+* Added a new hook, 'UserIsBot', to aid in determining if a user is a bot.
+* Added a new hook, 'ApiMakeParserOptions', to allow extensions to better
+  interact with API parsing.
+* Added a new hook, 'UploadVerifyUpload', which can be used to reject a file
+  upload. Unlike 'UploadVerifyFile' it provides information about upload comment
+  and the file description page, but does not run for uploads to stash.
+* (T141604) Extensions can now provide a better error message when their
+  maintenance scripts are run without the extension being installed.
+* (T8948) Numeric sorting in categories is now supported by setting $wgCategoryCollation
+  to 'uca-default-u-kn' or 'uca-<langcode>-u-kn'. If you can't use UCA collations,
+  a 'numeric' collation is also available. If migrating from another
+  collation, you will need to run the updateCollation.php maintenance script.
+* Two new codes have been added to #time parser function: "xit" for days in current
+  month, and "xiz" for days passed in the year, both in Iranian calendar.
+* mw.Api has a new option, useUS, to use U+001F (Unit Separator) when
+  appropriate for sending multi-valued parameters. This defaults to true when
+  the mw.Api instance seems to be for the local wiki.
+* After a client performs an action which alters a database that has replica databases,
+  MediaWiki will wait for the replica databases to synchronize with the master database
+  while it renders the HTML output. However, if the output is a redirect to another wiki
+  on the wiki farm with a different domain, MediaWiki will instead alter the redirect
+  URL to include a ?cpPosTime parameter that triggers the database synchronization when
+  the URL is followed by the client. The same-domain case uses a new cpPosTime cookie.
+* Added new hooks, 'ApiQueryBaseBeforeQuery', 'ApiQueryBaseAfterQuery', and
+  'ApiQueryBaseProcessRow', to make it easier for extensions to add 'prop' and
+  'show' parameters to existing API query modules.
+
+=== External library changes in 1.28 ===
+
+==== Upgraded external libraries ====
+* Updated es5-shim from v4.1.5 to v4.5.8
+* Updated composer/semver from v1.4.1 to v1.4.2
+* Updated wikimedia/php-session-serializer from v1.0.3 to v1.0.4
+
+==== New external libraries ====
+* Added wikimedia/scoped-callback v1.0.0
+* Added wikimedia/wait-condition-loop v1.0.1
+
+=== Bug fixes in 1.28 ===
+* (T146496) action=history pages should return 404 HTTP error code if the page does not exist
+* (T137264) SECURITY: XSS in unclosed internal links
+* (T133147) SECURITY: Escape '<' and ']]>' in inline <style> blocks
+* (T133147) SECURITY: Require login to preview user CSS pages
+* (T132926) SECURITY: Do not allow undeleting a revision deleted file if it is
+  the top file
+* (T129738) SECURITY: Make $wgBlockDisablesLogin also restrict logged in
+  permissions
+* (T129738) SECURITY: Make blocks log users out if $wgBlockDisablesLogin is true
+* (T139670) Move 'UserGetRights' call before application of
+  Session::getAllowedUserRights()
+
+=== Action API changes in 1.28 ===
+* Added 'maxarticlesize' property to action=query&meta=siteinfo which contains
+  the value of $wgMaxArticleSize.
+* Property 'modulemessages' from action=parse&prop=modules was removed
+  (deprecated since 1.26).
+* The following response properties from action=login, deprecated in 1.27, are
+  now removed: lgtoken, cookieprefix, sessionid. Clients should handle cookies
+  to properly manage session state.
+* Submitting the lgtoken and lgpassword parameters in the query string to
+  action=login is now deprecated and outputs a warning. They should be submitted
+  in the POST body instead.
+* Submitting sensitive authentication request parameters to action=clientlogin,
+  action=createaccount, action=linkaccount, and action=changeauthenticationdata
+  in the query string is now deprecated and outputs a warning. They should be
+  submitted in the POST body instead.
+* (T141960) Multi-valued parameters may now be separated using U+001F (Unit Separator)
+  instead of the pipe character. This will be useful if some of the multiple
+  values need to contain pipes, e.g. for action=options.
+* The API will now warn if input is not NFC-normalized Unicode or if it
+  contains invalid characters.
+* The 'normalized' list output by action=query and other modules that use
+  ApiPageSet may contain entries where the 'from' value is percent-encoded as
+  the raw value cannot be represented in a valid API response. These are
+  indicated by a 'fromencoded' boolean alongside the existing 'from' parameter.
+* (T28680) action=paraminfo can now return info about all submodules of a
+  module without listing them all explicitly.
+* (T146770) It is now possible to assert that the current user is a specific
+  named user, using the 'assertuser' parameter.
+* (T141963) Added a 'known' property when missing-but-known titles (e.g. from
+  the 'TitleIsAlwaysKnown' hook) are output in various modules.
+
+=== Action API internal changes in 1.28 ===
+* Added a new hook, 'ApiMakeParserOptions', to allow extensions to better
+  interact with ApiParse and ApiExpandTemplates.
+* (T139565) SECURITY: API: Generate head items in the context of the given title
+* (T115333) SECURITY: Check read permission when loading page content in ApiParse
+* ApiBase::getResultData() was removed (deprecated since 1.25)
+* ApiBase::makeHelpArrayToString() was removed (deprecated since 1.25)
+* ApiBase::makeHelpMsgParameters() was removed (deprecated since 1.25)
+* ApiBase::makeHelpMsg() was removed (deprecated since 1.25)
+* ApiFormatBase::formatHTML() was removed (deprecated since 1.25)
+* ApiFormatBase::getNeedsRawData() was removed (deprecated since 1.25)
+* ApiFormatBase::getWantsHelp() was removed (deprecated since 1.25)
+* ApiFormatBase::setBufferResult() was removed (deprecated since 1.25)
+* ApiFormatBase::setHelp() was removed (deprecated since 1.25)
+* ApiFormatBase::setUnescapeAmps() was removed (deprecated since 1.25)
+* ApiMain::makeHelpMsgHeader() was removed (deprecated since 1.25)
+* ApiMain::reallyMakeHelpMsg() was removed (deprecated since 1.25)
+* ApiMain::setHelp() was removed (deprecated since 1.25)
+* ApiResult::beginContinuation() was removed (deprecated since 1.25)
+* ApiResult::cleanUpUTF8() was removed (deprecated since 1.25)
+* ApiResult::convertStatusToArray() was removed (deprecated since 1.25)
+* ApiResult::disableSizeCheck() was removed (deprecated since 1.24)
+* ApiResult::enableSizeCheck() was removed (deprecated since 1.24)
+* ApiResult::endContinuation() was removed (deprecated since 1.25)
+* ApiResult::getData() was removed (deprecated since 1.25)
+* ApiResult::getIsRawMode() was removed (deprecated since 1.25)
+* ApiResult::setContent() was removed (deprecated since 1.25)
+* ApiResult::setContinueParam() was removed (deprecated since 1.25)
+* ApiResult::setElement() was removed (deprecated since 1.25)
+* ApiResult::setGeneratorContinueParam() was removed (deprecated since 1.25)
+* ApiResult::setIndexedTagName_internal() was removed (deprecated since 1.25)
+* ApiResult::setIndexedTagName_recursive() was removed (deprecated since 1.25)
+* ApiResult::setMainForContinuation() was removed (deprecated since 1.25)
+* ApiResult::setParsedLimit() was removed (deprecated since 1.25)
+* ApiResult::setRawMode() was removed (deprecated since 1.25)
+* ApiResult::size() was removed (deprecated since 1.25)
+* Added new hooks, 'ApiQueryBaseBeforeQuery', 'ApiQueryBaseAfterQuery', and
+  'ApiQueryBaseProcessRow', to make it easier for extensions to add 'prop' and
+  'show' parameters to existing API query modules. A query module can enable
+  these hooks by passing an array for $hookData to ApiQueryBase::select() and
+  by calling ApiQueryBase->processRow() before adding a row's data to the
+  result.
+
+=== Languages updated in 1.28 ===
+
+MediaWiki supports over 375 languages. Many localisations are updated
+regularly. Below only new and removed languages are listed, as well as
+changes to languages because of Phabricator reports.
+
+* (T137411) ban (Balinese), thanks to translators Adi Mayndra, Andru,
+  BASAbali, M. Adiputra, Naval Scene, Nemo bis, NoiX180, and 아라.
+* (T135867) shn (Shan), thanks to translators Khun Sar, Piangpha,
+  Saiddzone Saimawnkham, Saosukham, and Sengwan.
+* Czech (cs) and Slovak (sk) set as reciprocal fallbacks.
+* (T146744) Livvi-Karelian (olo) namespace messages created thanks to translator Ilja.mos.
+
+=== Other changes in 1.28 ===
+* (T128697) Improved handling of large diffs.
+* [BREAKING CHANGE] $wgExtendedLoginCookies has been removed. You can
+  use or update a custom session provider if needed.
+* Deprecated APIEditBeforeSave hook in favor of EditFilterMergedContent.
+* The 'UploadVerification' hook is deprecated. Use 'UploadVerifyFile' instead.
+* SiteConfiguration::isLocalVHost() was removed (deprecated since 1.25).
+* The 'UserLoginComplete' hook has a new parameter to differentiate between actual
+  login and visiting the login page while already logged in.
+* ResourceLoader::makeLoaderURL() was removed (deprecated since 1.24).
+* $.fn.liveAndTestAtStart was removed (deprecated since 1.24).
+* mw.util.tooltipAccessKeyPrefix was removed (deprecated since 1.24).
+* mw.util.tooltipAccessKeyRegexp was removed (deprecated since 1.24).
+* Linker::link() and Linker::linkKnown() were deprecated; please instead use
+  MediaWiki\Linker\LinkRenderer. In addition, the LinkBegin and LinkEnd hooks
+  were replaced by HtmlPageLinkRendererBegin and HtmlPageLinkRendererEnd
+  respectively. See docs/hooks.txt for the specific changes needed for those hooks.
+* Linker::formatSize() was deprecated. Use Language::formatSize() directly.
+* Aliases for Linker methods, deprecated since 1.21, were removed from Skin:
+  * Skin::commentBlock() (use Linker::commentBlock() instead)
+  * Skin::generateRollback() (use Linker::generateRollback() instead)
+  * Skin::link() (use MediaWiki\Linker\LinkRenderer instead)
+  * Skin::linkKnown() (use MediaWiki\Linker\LinkRenderer instead)
+  * Skin::userLink() (use Linker::userLink() instead)
+  * Skin::userToolLinks() (use Linker::userToolLinks() instead)
+* Disabled "bug 2702" HTML tidying of parsed UI messages on wikis where Tidy is
+  disabled.
+* DifferenceEngine::generateDiffBody() was removed (deprecated since 1.21).
+* UploadBase::stashFileGetKey() and UploadBase::stashSession() were deprecated.
+  Use ...->stashFile()->getFileKey() instead.
+* "Public domain" was removed as a wiki license option from the installer, in
+  favour of CC-0.
+* AuthenticationRequest::$required is now changed from REQUIRED to PRIMARY_REQUIRED
+  on requests needed by primary providers even if all primaries need them.
+  Primary providers are discouraged from returning multiple REQUIRED requests.
+* OOjs UI PHP widgets constructed with the `'infusable' => true` config option
+  will no longer be automatically infused. You should call `OO.ui.infuse()`
+  on them yourself from your JavaScript code.
+* parserTests.php has moved to tests/parser/parserTests.php
+* The command line options specific to parser tests have been removed from
+  phpunit.php: --regex and --keep-uploads. Instead of --regex, use --filter.
+  Instead of --keep-uploads, use the same option to parserTests.php, but you
+  must specify a directory with --upload-dir.
+* The 'jquery.arrowSteps' ResourceLoader module is now deprecated.
+* IP::isConfiguredProxy() and IP::isTrustedProxy() were removed. Callers should
+  migrate to using the same functions on a ProxyLookup instance, obtainable from
+  MediaWikiServices.
+* The ArticleAfterFetchContent, ArticleInsertComplete, ArticleSave, ArticleSaveComplete,
+  ArticleViewCustom, EditFilterMerged, EditPageGetDiffText, EditPageGetPreviewText and
+  ShowRawCssJs hooks will now emit deprecation warnings if used.
+* (T68404) CSS3 attr() function with url type is no longer allowed
+  in inline styles.
+* Database::getSearchEngine() is deprecated, use SearchEngineFactory::getSearchEngineClass
+  instead.
+
+== Compatibility ==
+
+MediaWiki 1.28 requires PHP 5.5.9 or later. There is experimental support for
+HHVM 3.6.5 or later.
+
+MySQL is the recommended DBMS. PostgreSQL or SQLite can also be used, but
+support for them is somewhat less mature. There is experimental support for
+Oracle and Microsoft SQL Server.
+
+The supported versions are:
+
+* MySQL 5.0.3 or later
+* PostgreSQL 8.3 or later
+* SQLite 3.3.7 or later
+* Oracle 9.0.1 or later
+* Microsoft SQL Server 2005 (9.00.1399)
+
+== Upgrading ==
+
+1.28 has several database changes since 1.27, and will not work without schema
+updates. Note that due to changes to some very large tables like the revision
+table, the schema update may take quite long (minutes on a medium sized site,
+many hours on a large site).
+
+If upgrading from before 1.11, and you are using a wiki as a commons
+repository, make sure that it is updated as well. Otherwise, errors may arise
+due to database schema changes.
+
+If upgrading from before 1.7, you may want to run refreshLinks.php to ensure
+new database fields are filled with data.
+
+If you are upgrading from MediaWiki 1.4.x or earlier, you should upgrade to
+1.5 first. The upgrade script maintenance/upgrade1_5.php has been removed
+with MediaWiki 1.21.
+
+Don't forget to always back up your database before upgrading!
+
+See the file UPGRADE for more detailed upgrade instructions.
+
+For notes on 1.27.x and older releases, see HISTORY.
+
+== Online documentation ==
+
+Documentation for both end-users and site administrators is available on
+MediaWiki.org, and is covered under the GNU Free Documentation License (except
+for pages that explicitly state that their contents are in the public domain):
+
+       https://www.mediawiki.org/wiki/Special:MyLanguage/Documentation
+
+== Mailing list ==
+
+A mailing list is available for MediaWiki user support and discussion:
+
+       https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
+
+A low-traffic announcements-only list is also available:
+
+       https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce
+
+It's highly recommended that you sign up for one of these lists if you're
+going to run a public MediaWiki, so you can be notified of security fixes.
+
+== IRC help ==
+
+There's usually someone online in #mediawiki on irc.freenode.net.
 
 = MediaWiki 1.27 =
 
diff --git a/RELEASE-NOTES-1.28 b/RELEASE-NOTES-1.28
deleted file mode 100644 (file)
index 557162e..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-== MediaWiki 1.28 ==
-
-THIS IS NOT A RELEASE YET
-
-MediaWiki 1.28 is an alpha-quality branch and is not recommended for use in
-production.
-
-=== Changes since 1.28.0rc0 ===
-* (T142210) The changes to move the parser "NewPP limit report" from a HTML
-  comment to a machine-readable JavaScript config option 'wgPageParseReport'
-  have been undone. They caused the human-readable limit report to be shown
-  incompletely or not at all. ParserOutput::setLimitReportData() and
-  getLimitReportData() behave as they did in MediaWiki 1.27 again.
-* (T149510) Value of {{DISPLAYTITLE:}} parser function will not be used for
-  the text of subheadings on a category page when creating it. This wasn't
-  working correctly.
-* (T106793) MediaWiki will no longer try to perform a HTTP redirect to the
-  canonical pretty URL when a non-pretty URL is used. It resulted in redirect
-  loops in some clients and in some server configurations. This undoes a change
-  made in MediaWiki 1.26.
-
-=== Configuration changes in 1.28 ===
-* $wgSend404Code now affects status code of action=history if the page is not there.
-* BREAKING CHANGE: $wgHTTPProxy is now *required* for all external requests
-  made by MediaWiki via a proxy. Relying on the http_proxy environment
-  variable is no longer supported.
-* The load.php entry point now enforces the existing policy of not allowing
-  access to session data, which includes the session user and the session
-  user's language. If such access is attempted, an exception will be thrown.
-* The number of internal PBKDF2 iterations used to derive the session secret
-  is configurable via $wgSessionPbkdf2Iterations.
-* Upload dialog's file upload log comment can now be configured separately for
-  local and foreign uploads.
-* $wgForeignUploadTargets now defaults to `[ 'local' ]`, where `'local'`
-  signifies local uploads. A value of `[]` (empty array) now means that
-  no upload targets are allowed, effectively disabling the upload dialog.
-* The deprecated $wgEditEncoding variable has been removed; it was only used
-  for Esperanto language character conversion. You are now recommended to use
-  input methods provided by the UniversalLanguageSelector extension.
-* When $wgPingback is true, MediaWiki will periodically ping
-  https://www.mediawiki.org/beacon with basic information about the local
-  MediaWiki installation. This data includes, for example, the type of system,
-  PHP version, and chosen database backend. This behavior is off by default.
-* When $wgEditSubmitButtonLabelPublish is true, MediaWiki will label the button
-  to store-to-database-and-show-to-others as "Publish page"/"Publish changes";
-  if false, the default, they will be "Save page"/"Save changes".
-* The 'editcontentmodel' permission is now granted to all logged-in users ('user').
-  instead of just administrators ('sysop'). Documentation for this feature is
-  available at <https://www.mediawiki.org/wiki/Help:ChangeContentModel>.
-* $wgRevisionCacheExpiry is now set to one week by default instead of being disabled.
-* Magic links are now disabled by default, and can be re-enabled by modifying the value
-  of $wgEnableMagicLinks. Their usage is discouraged, but if they are manually enabled,
-  a tracking category will be added to help identify usage and make it easier to migrate
-  away from. If you depend upon magic link functionality, it is requested that you comment
-  on <https://www.mediawiki.org/wiki/Requests_for_comment/Future_of_magic_links> and
-  explain your use case(s).
-* New config variable $wgCSPFalsePositiveUrls to control what URLs to ignore
-  in upcoming Content-Security-Policy feature's reporting.
-
-=== New features in 1.28 ===
-* User::isBot() method for checking if an account is a bot role account.
-* Added a new 'slideshow' mode for galleries.
-* Added a new hook, 'UserIsBot', to aid in determining if a user is a bot.
-* Added a new hook, 'ApiMakeParserOptions', to allow extensions to better
-  interact with API parsing.
-* Added a new hook, 'UploadVerifyUpload', which can be used to reject a file
-  upload. Unlike 'UploadVerifyFile' it provides information about upload comment
-  and the file description page, but does not run for uploads to stash.
-* (T141604) Extensions can now provide a better error message when their
-  maintenance scripts are run without the extension being installed.
-* (T8948) Numeric sorting in categories is now supported by setting $wgCategoryCollation
-  to 'uca-default-u-kn' or 'uca-<langcode>-u-kn'. If you can't use UCA collations,
-  a 'numeric' collation is also available. If migrating from another
-  collation, you will need to run the updateCollation.php maintenance script.
-* Two new codes have been added to #time parser function: "xit" for days in current
-  month, and "xiz" for days passed in the year, both in Iranian calendar.
-* mw.Api has a new option, useUS, to use U+001F (Unit Separator) when
-  appropriate for sending multi-valued parameters. This defaults to true when
-  the mw.Api instance seems to be for the local wiki.
-* After a client performs an action which alters a database that has replica databases,
-  MediaWiki will wait for the replica databases to synchronize with the master database
-  while it renders the HTML output. However, if the output is a redirect to another wiki
-  on the wiki farm with a different domain, MediaWiki will instead alter the redirect
-  URL to include a ?cpPosTime parameter that triggers the database synchronization when
-  the URL is followed by the client. The same-domain case uses a new cpPosTime cookie.
-* Added new hooks, 'ApiQueryBaseBeforeQuery', 'ApiQueryBaseAfterQuery', and
-  'ApiQueryBaseProcessRow', to make it easier for extensions to add 'prop' and
-  'show' parameters to existing API query modules.
-
-=== External library changes in 1.28 ===
-
-==== Upgraded external libraries ====
-* Updated es5-shim from v4.1.5 to v4.5.8
-* Updated composer/semver from v1.4.1 to v1.4.2
-* Updated wikimedia/php-session-serializer from v1.0.3 to v1.0.4
-
-==== New external libraries ====
-* Added wikimedia/scoped-callback v1.0.0
-* Added wikimedia/wait-condition-loop v1.0.1
-
-==== Removed and replaced external libraries ====
-
-=== Bug fixes in 1.28 ===
-* (T146496) action=history pages should return 404 HTTP error code if the page does not exist
-* (T137264) SECURITY: XSS in unclosed internal links
-* (T133147) SECURITY: Escape '<' and ']]>' in inline <style> blocks
-* (T133147) SECURITY: Require login to preview user CSS pages
-* (T132926) SECURITY: Do not allow undeleting a revision deleted file if it is
-  the top file
-* (T129738) SECURITY: Make $wgBlockDisablesLogin also restrict logged in
-  permissions
-* (T129738) SECURITY: Make blocks log users out if $wgBlockDisablesLogin is true
-* (T139670) Move 'UserGetRights' call before application of
-  Session::getAllowedUserRights()
-
-=== Action API changes in 1.28 ===
-* Added 'maxarticlesize' property to action=query&meta=siteinfo which contains
-  the value of $wgMaxArticleSize.
-* Property 'modulemessages' from action=parse&prop=modules was removed
-  (deprecated since 1.26).
-* The following response properties from action=login, deprecated in 1.27, are
-  now removed: lgtoken, cookieprefix, sessionid. Clients should handle cookies
-  to properly manage session state.
-* Submitting the lgtoken and lgpassword parameters in the query string to
-  action=login is now deprecated and outputs a warning. They should be submitted
-  in the POST body instead.
-* Submitting sensitive authentication request parameters to action=clientlogin,
-  action=createaccount, action=linkaccount, and action=changeauthenticationdata
-  in the query string is now deprecated and outputs a warning. They should be
-  submitted in the POST body instead.
-* (T141960) Multi-valued parameters may now be separated using U+001F (Unit Separator)
-  instead of the pipe character. This will be useful if some of the multiple
-  values need to contain pipes, e.g. for action=options.
-* The API will now warn if input is not NFC-normalized Unicode or if it
-  contains invalid characters.
-* The 'normalized' list output by action=query and other modules that use
-  ApiPageSet may contain entries where the 'from' value is percent-encoded as
-  the raw value cannot be represented in a valid API response. These are
-  indicated by a 'fromencoded' boolean alongside the existing 'from' parameter.
-* (T28680) action=paraminfo can now return info about all submodules of a
-  module without listing them all explicitly.
-* (T146770) It is now possible to assert that the current user is a specific
-  named user, using the 'assertuser' parameter.
-* (T141963) Added a 'known' property when missing-but-known titles (e.g. from
-  the 'TitleIsAlwaysKnown' hook) are output in various modules.
-
-=== Action API internal changes in 1.28 ===
-* Added a new hook, 'ApiMakeParserOptions', to allow extensions to better
-  interact with ApiParse and ApiExpandTemplates.
-* (T139565) SECURITY: API: Generate head items in the context of the given title
-* (T115333) SECURITY: Check read permission when loading page content in ApiParse
-* ApiBase::getResultData() was removed (deprecated since 1.25)
-* ApiBase::makeHelpArrayToString() was removed (deprecated since 1.25)
-* ApiBase::makeHelpMsgParameters() was removed (deprecated since 1.25)
-* ApiBase::makeHelpMsg() was removed (deprecated since 1.25)
-* ApiFormatBase::formatHTML() was removed (deprecated since 1.25)
-* ApiFormatBase::getNeedsRawData() was removed (deprecated since 1.25)
-* ApiFormatBase::getWantsHelp() was removed (deprecated since 1.25)
-* ApiFormatBase::setBufferResult() was removed (deprecated since 1.25)
-* ApiFormatBase::setHelp() was removed (deprecated since 1.25)
-* ApiFormatBase::setUnescapeAmps() was removed (deprecated since 1.25)
-* ApiMain::makeHelpMsgHeader() was removed (deprecated since 1.25)
-* ApiMain::reallyMakeHelpMsg() was removed (deprecated since 1.25)
-* ApiMain::setHelp() was removed (deprecated since 1.25)
-* ApiResult::beginContinuation() was removed (deprecated since 1.25)
-* ApiResult::cleanUpUTF8() was removed (deprecated since 1.25)
-* ApiResult::convertStatusToArray() was removed (deprecated since 1.25)
-* ApiResult::disableSizeCheck() was removed (deprecated since 1.24)
-* ApiResult::enableSizeCheck() was removed (deprecated since 1.24)
-* ApiResult::endContinuation() was removed (deprecated since 1.25)
-* ApiResult::getData() was removed (deprecated since 1.25)
-* ApiResult::getIsRawMode() was removed (deprecated since 1.25)
-* ApiResult::setContent() was removed (deprecated since 1.25)
-* ApiResult::setContinueParam() was removed (deprecated since 1.25)
-* ApiResult::setElement() was removed (deprecated since 1.25)
-* ApiResult::setGeneratorContinueParam() was removed (deprecated since 1.25)
-* ApiResult::setIndexedTagName_internal() was removed (deprecated since 1.25)
-* ApiResult::setIndexedTagName_recursive() was removed (deprecated since 1.25)
-* ApiResult::setMainForContinuation() was removed (deprecated since 1.25)
-* ApiResult::setParsedLimit() was removed (deprecated since 1.25)
-* ApiResult::setRawMode() was removed (deprecated since 1.25)
-* ApiResult::size() was removed (deprecated since 1.25)
-* Added new hooks, 'ApiQueryBaseBeforeQuery', 'ApiQueryBaseAfterQuery', and
-  'ApiQueryBaseProcessRow', to make it easier for extensions to add 'prop' and
-  'show' parameters to existing API query modules. A query module can enable
-  these hooks by passing an array for $hookData to ApiQueryBase::select() and
-  by calling ApiQueryBase->processRow() before adding a row's data to the
-  result.
-
-=== Languages updated in 1.28 ===
-
-MediaWiki supports over 350 languages. Many localisations are updated
-regularly. Below only new and removed languages are listed, as well as
-changes to languages because of Phabricator reports.
-
-* (T137411) ban (Balinese), thanks to translators Adi Mayndra, Andru,
-  BASAbali, M. Adiputra, Naval Scene, Nemo bis, NoiX180, and 아라.
-* (T135867) shn (Shan), thanks to translators Khun Sar, Piangpha,
-  Saiddzone Saimawnkham, Saosukham, and Sengwan.
-* Czech (cs) and Slovak (sk) set as reciprocal fallbacks.
-* (T146744) Livvi-Karelian (olo) namespace messages created thanks to translator Ilja.mos.
-
-=== Other changes in 1.28 ===
-* (T128697) Improved handling of large diffs.
-* [BREAKING CHANGE] $wgExtendedLoginCookies has been removed. You can
-  use or update a custom session provider if needed.
-* Deprecated APIEditBeforeSave hook in favor of EditFilterMergedContent.
-* The 'UploadVerification' hook is deprecated. Use 'UploadVerifyFile' instead.
-* SiteConfiguration::isLocalVHost() was removed (deprecated since 1.25).
-* The 'UserLoginComplete' hook has a new parameter to differentiate between actual
-  login and visiting the login page while already logged in.
-* ResourceLoader::makeLoaderURL() was removed (deprecated since 1.24).
-* $.fn.liveAndTestAtStart was removed (deprecated since 1.24).
-* mw.util.tooltipAccessKeyPrefix was removed (deprecated since 1.24).
-* mw.util.tooltipAccessKeyRegexp was removed (deprecated since 1.24).
-* Linker::link() and Linker::linkKnown() were deprecated; please instead use
-  MediaWiki\Linker\LinkRenderer. In addition, the LinkBegin and LinkEnd hooks
-  were replaced by HtmlPageLinkRendererBegin and HtmlPageLinkRendererEnd
-  respectively. See docs/hooks.txt for the specific changes needed for those hooks.
-* Linker::formatSize() was deprecated. Use Language::formatSize() directly.
-* Aliases for Linker methods, deprecated since 1.21, were removed from Skin:
-  * Skin::commentBlock() (use Linker::commentBlock() instead)
-  * Skin::generateRollback() (use Linker::generateRollback() instead)
-  * Skin::link() (use MediaWiki\Linker\LinkRenderer instead)
-  * Skin::linkKnown() (use MediaWiki\Linker\LinkRenderer instead)
-  * Skin::userLink() (use Linker::userLink() instead)
-  * Skin::userToolLinks() (use Linker::userToolLinks() instead)
-* Disabled "bug 2702" HTML tidying of parsed UI messages on wikis where Tidy is
-  disabled.
-* DifferenceEngine::generateDiffBody() was removed (deprecated since 1.21).
-* UploadBase::stashFileGetKey() and UploadBase::stashSession() were deprecated.
-  Use ...->stashFile()->getFileKey() instead.
-* "Public domain" was removed as a wiki license option from the installer, in
-  favour of CC-0.
-* AuthenticationRequest::$required is now changed from REQUIRED to PRIMARY_REQUIRED
-  on requests needed by primary providers even if all primaries need them.
-  Primary providers are discouraged from returning multiple REQUIRED requests.
-* OOjs UI PHP widgets constructed with the `'infusable' => true` config option
-  will no longer be automatically infused. You should call `OO.ui.infuse()`
-  on them yourself from your JavaScript code.
-* parserTests.php has moved to tests/parser/parserTests.php
-* The command line options specific to parser tests have been removed from
-  phpunit.php: --regex and --keep-uploads. Instead of --regex, use --filter.
-  Instead of --keep-uploads, use the same option to parserTests.php, but you
-  must specify a directory with --upload-dir.
-* The 'jquery.arrowSteps' ResourceLoader module is now deprecated.
-* IP::isConfiguredProxy() and IP::isTrustedProxy() were removed. Callers should
-  migrate to using the same functions on a ProxyLookup instance, obtainable from
-  MediaWikiServices.
-* The ArticleAfterFetchContent, ArticleInsertComplete, ArticleSave, ArticleSaveComplete,
-  ArticleViewCustom, EditFilterMerged, EditPageGetDiffText, EditPageGetPreviewText and
-  ShowRawCssJs hooks will now emit deprecation warnings if used.
-* (T68404) CSS3 attr() function with url type is no longer allowed
-  in inline styles.
-
-== Compatibility ==
-
-MediaWiki 1.28 requires PHP 5.5.9 or later. There is experimental support for
-HHVM 3.6.5 or later.
-
-MySQL is the recommended DBMS. PostgreSQL or SQLite can also be used, but
-support for them is somewhat less mature. There is experimental support for
-Oracle and Microsoft SQL Server.
-
-The supported versions are:
-
-* MySQL 5.0.3 or later
-* PostgreSQL 8.3 or later
-* SQLite 3.3.7 or later
-* Oracle 9.0.1 or later
-* Microsoft SQL Server 2005 (9.00.1399)
-
-== Upgrading ==
-
-1.28 has several database changes since 1.27, and will not work without schema
-updates. Note that due to changes to some very large tables like the revision
-table, the schema update may take quite long (minutes on a medium sized site,
-many hours on a large site).
-
-If upgrading from before 1.11, and you are using a wiki as a commons
-repository, make sure that it is updated as well. Otherwise, errors may arise
-due to database schema changes.
-
-If upgrading from before 1.7, you may want to run refreshLinks.php to ensure
-new database fields are filled with data.
-
-If you are upgrading from MediaWiki 1.4.x or earlier, you should upgrade to
-1.5 first. The upgrade script maintenance/upgrade1_5.php has been removed
-with MediaWiki 1.21.
-
-Don't forget to always back up your database before upgrading!
-
-See the file UPGRADE for more detailed upgrade instructions.
-
-For notes on 1.27.x and older releases, see HISTORY.
-
-== Online documentation ==
-
-Documentation for both end-users and site administrators is available on
-MediaWiki.org, and is covered under the GNU Free Documentation License (except
-for pages that explicitly state that their contents are in the public domain):
-
-       https://www.mediawiki.org/wiki/Special:MyLanguage/Documentation
-
-== Mailing list ==
-
-A mailing list is available for MediaWiki user support and discussion:
-
-       https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
-
-A low-traffic announcements-only list is also available:
-
-       https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce
-
-It's highly recommended that you sign up for one of these lists if you're
-going to run a public MediaWiki, so you can be notified of security fixes.
-
-== IRC help ==
-
-There's usually someone online in #mediawiki on irc.freenode.net.
index fa1e1c4..986ecd8 100644 (file)
@@ -6,12 +6,31 @@ MediaWiki 1.29 is an alpha-quality branch and is not recommended for use in
 production.
 
 === Configuration changes in 1.29 ===
+* Default cookie expiration time has been reduced to 30 days. Login cookie expiration time is
+  kept at 180 days.
+* A new configuration variable has been added: $wgCookieSetOnAutoblock. This
+  determines whether to set a cookie when a user is autoblocked. Doing so means
+  that a blocked user, even after logging out and moving to a new IP address,
+  will still be blocked.
+* The resetpassword right and associated password reset capture feature has
+  been removed.
+* The $error parameter to the EmailUser hook should be set to a Status object
+  or boolean false. This should be compatible with at least MediaWiki 1.23 if
+  not earlier. Returning a raw HTML string is now deprecated.
+* The $message parameter to the ApiCheckCanExecute hook should be set to an
+  ApiMessage. This is compatible with MediaWiki 1.27 and later. Returning a
+  code for ApiBase::parseMsg() will no longer work.
+* ApiBase::$messageMap is no longer public. Code attempting to access it will
+  result in a PHP fatal error.
 
 === New features in 1.29 ===
+* (T5233) A cookie can now be set when a user is autoblocked, to track that user if
+  they move to a new IP address. This is disabled by default.
 
 === External library changes in 1.29 ===
 
 ==== Upgraded external libraries ====
+* Updated QUnit from v1.22.0 to v1.23.1.
 
 ==== New external libraries ====
 
@@ -24,8 +43,49 @@ production.
   action=createaccount, action=linkaccount, and action=changeauthenticationdata
   in the query string is now an error. They should be submitted in the POST
   body instead.
+* The capture option for action=resetpassword has been removed
+* action=clearhasmsg now requires a POST.
+* (T47843) API errors and warnings may be requested in non-English languages
+  using the new 'errorformat', 'errorlang', and 'errorsuselocal' parameters.
+* API error codes may have changed. Most notably, errors from modules using
+  parameter prefixes (e.g. all query submodules) will no longer be prefixed.
+* action=emailuser may return a "Warnings" status, and now returns 'warnings' and
+  'errors' subelements (as applicable) instead of 'message'.
+* action=imagerotate returns an 'errors' subelement rather than 'errormessage'.
+* action=move now reports errors when moving the talk page as an array under
+  key 'talkmove-errors', rather than using 'talkmove-error-code' and
+  'talkmove-error-info'. The format for subpage move errors has also changed.
+* action=revisiondelete no longer includes a "rendered" property on warnings
+  and errors for each item. Use errorformat=wikitext if you're wanting parsed
+  output.
+* action=rollback no longer returns a "messageHtml" property on errors. Use
+  errorformat=html if you're wanting HTML formatting of messages.
+* action=upload now reports optional stash failures as an array under key
+  'stasherrors' rather than a 'stashfailed' text string.
+* action=watch reports 'errors' and 'warnings' instead of a single 'error'.
 
 === Action API internal changes in 1.29 ===
+* New methods were added to ApiBase to handle errors and warnings using i18n
+  keys. Methods for using hard-coded English messages were deprecated:
+  * ApiBase::dieUsage() was deprecated
+  * ApiBase::dieUsageMsg() was deprecated
+  * ApiBase::dieUsageMsgOrDebug() was deprecated
+  * ApiBase::getErrorFromStatus() was deprecated
+  * ApiBase::parseMsg() was deprecated
+  * ApiBase::setWarning() was deprecated
+* ApiBase::$messageMap is no longer public. Code attempting to access it will
+  result in a PHP fatal error.
+* The $message parameter to the ApiCheckCanExecute hook should be set to an
+  ApiMessage. This is compatible with MediaWiki 1.27 and later. Returning a
+  code for ApiBase::parseMsg() will no longer work.
+* UsageException is deprecated in favor of ApiUsageException. For the time
+  being ApiUsageException is a subclass of UsageException to allow things that
+  catch only UsageException to still function properly.
+* If, for some strange reason, code was using an ApiErrorFormatter instead of
+  ApiErrorFormatter_BackCompat, note that the result format has changed and
+  various methods now take a module path rather than a module name.
+* ApiMessageTrait::getApiCode() now strips 'apierror-' and 'apiwarn-' prefixes
+  from the message key, and maps some message keys for backwards compatibility.
 
 === Languages updated in 1.29 ===
 
@@ -33,9 +93,27 @@ MediaWiki supports over 350 languages. Many localisations are updated
 regularly. Below only new and removed languages are listed, as well as
 changes to languages because of Phabricator reports.
 
+==== No fallback for Ukrainian ====
+* (T39314) The fallback from Ukrainian to Russian was removed. The Ukrainian
+  language will now use the default fallback language: English. When a translation
+  to Ukrainian is not available, an English string will be shown.
+
 === Other changes in 1.29 ===
 * Database::getSearchEngine() (deprecated in 1.28) was removed. Use
   SearchEngineFactory::getSearchEngineClass() instead.
+* $wgSessionsInMemcached (deprecated in 1.20) was removed. No replacement is
+  required as all sessions are stored in Object Cache now.
+* MWHttpRequest::execute() should be considered to return a StatusValue; the
+  Status return type is deprecated.
+* User::edits() (deprecated in 1.21) was removed.
+* Xml::escapeJsString() (deprecated in 1.21) was removed.
+* Article::getText() and Article::prepareTextForEdit() (deprecated in 1.21)
+  were removed.
+* Article::getAutosummary() and WikiPage::getAutosummary (deprecated in 1.21)
+  were removed.
+* Hooks ArticleViewCustom, EditPageGetDiffText and ShowRawCssJs (deprecated in 1.21)
+  were removed.
+* Class RevisiondeleteAction (deprecated in 1.25) was removed.
 
 == Compatibility ==
 
index 30ef985..e079686 100644 (file)
@@ -145,6 +145,7 @@ $wgAutoloadLocalClasses = [
        'ApiUnblock' => __DIR__ . '/includes/api/ApiUnblock.php',
        'ApiUndelete' => __DIR__ . '/includes/api/ApiUndelete.php',
        'ApiUpload' => __DIR__ . '/includes/api/ApiUpload.php',
+       'ApiUsageException' => __DIR__ . '/includes/api/ApiUsageException.php',
        'ApiUserrights' => __DIR__ . '/includes/api/ApiUserrights.php',
        'ApiWatch' => __DIR__ . '/includes/api/ApiWatch.php',
        'ArchivedFile' => __DIR__ . '/includes/filerepo/file/ArchivedFile.php',
@@ -428,6 +429,8 @@ $wgAutoloadLocalClasses = [
        'ExplodeIterator' => __DIR__ . '/includes/libs/ExplodeIterator.php',
        'ExportProgressFilter' => __DIR__ . '/maintenance/backup.inc',
        'ExportSites' => __DIR__ . '/maintenance/exportSites.php',
+       'ExtensionJsonValidationError' => __DIR__ . '/includes/registration/ExtensionJsonValidationError.php',
+       'ExtensionJsonValidator' => __DIR__ . '/includes/registration/ExtensionJsonValidator.php',
        'ExtensionLanguages' => __DIR__ . '/maintenance/language/languages.inc',
        'ExtensionProcessor' => __DIR__ . '/includes/registration/ExtensionProcessor.php',
        'ExtensionRegistry' => __DIR__ . '/includes/registration/ExtensionRegistry.php',
@@ -875,6 +878,7 @@ $wgAutoloadLocalClasses = [
        'MediaWiki\\Logger\\Monolog\\LegacyFormatter' => __DIR__ . '/includes/debug/logger/monolog/LegacyFormatter.php',
        'MediaWiki\\Logger\\Monolog\\LegacyHandler' => __DIR__ . '/includes/debug/logger/monolog/LegacyHandler.php',
        'MediaWiki\\Logger\\Monolog\\LineFormatter' => __DIR__ . '/includes/debug/logger/monolog/LineFormatter.php',
+       'MediaWiki\\Logger\\Monolog\\LogstashFormatter' => __DIR__ . '/includes/debug/logger/monolog/LogstashFormatter.php',
        'MediaWiki\\Logger\\Monolog\\SyslogHandler' => __DIR__ . '/includes/debug/logger/monolog/SyslogHandler.php',
        'MediaWiki\\Logger\\Monolog\\WikiProcessor' => __DIR__ . '/includes/debug/logger/monolog/WikiProcessor.php',
        'MediaWiki\\Logger\\NullSpi' => __DIR__ . '/includes/debug/logger/NullSpi.php',
@@ -1196,7 +1200,6 @@ $wgAutoloadLocalClasses = [
        'ResourceLoaderSpecialCharacterDataModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderSpecialCharacterDataModule.php',
        'ResourceLoaderStartUpModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderStartUpModule.php',
        'ResourceLoaderUploadDialogModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUploadDialogModule.php',
-       'ResourceLoaderUserCSSPrefsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php',
        'ResourceLoaderUserDefaultsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserDefaultsModule.php',
        'ResourceLoaderUserModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserModule.php',
        'ResourceLoaderUserOptionsModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderUserOptionsModule.php',
@@ -1230,7 +1233,6 @@ $wgAutoloadLocalClasses = [
        'RevisionItemBase' => __DIR__ . '/includes/RevisionList.php',
        'RevisionList' => __DIR__ . '/includes/RevisionList.php',
        'RevisionListBase' => __DIR__ . '/includes/RevisionList.php',
-       'RevisiondeleteAction' => __DIR__ . '/includes/actions/RevisiondeleteAction.php',
        'RiffExtractor' => __DIR__ . '/includes/libs/RiffExtractor.php',
        'RightsLogFormatter' => __DIR__ . '/includes/logging/RightsLogFormatter.php',
        'RollbackAction' => __DIR__ . '/includes/actions/RollbackAction.php',
@@ -1502,7 +1504,7 @@ $wgAutoloadLocalClasses = [
        'UploadStashWrongOwnerException' => __DIR__ . '/includes/upload/UploadStash.php',
        'UploadStashZeroLengthFileException' => __DIR__ . '/includes/upload/UploadStash.php',
        'UppercaseCollation' => __DIR__ . '/includes/collation/UppercaseCollation.php',
-       'UsageException' => __DIR__ . '/includes/api/ApiMain.php',
+       'UsageException' => __DIR__ . '/includes/api/ApiUsageException.php',
        'User' => __DIR__ . '/includes/user/User.php',
        'UserArray' => __DIR__ . '/includes/user/UserArray.php',
        'UserArrayFromResult' => __DIR__ . '/includes/user/UserArrayFromResult.php',
@@ -1569,6 +1571,8 @@ $wgAutoloadLocalClasses = [
        'WikiRevision' => __DIR__ . '/includes/import/WikiRevision.php',
        'WikiStatsOutput' => __DIR__ . '/maintenance/language/StatOutputs.php',
        'WikiTextStructure' => __DIR__ . '/includes/content/WikiTextStructure.php',
+       'Wikimedia\\Rdbms\\ConnectionManager' => __DIR__ . '/includes/libs/rdbms/connectionmanager/ConnectionManager.php',
+       'Wikimedia\\Rdbms\\SessionConsistentConnectionManager' => __DIR__ . '/includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManager.php',
        'WikitextContent' => __DIR__ . '/includes/content/WikitextContent.php',
        'WikitextContentHandler' => __DIR__ . '/includes/content/WikitextContentHandler.php',
        'WinCacheBagOStuff' => __DIR__ . '/includes/libs/objectcache/WinCacheBagOStuff.php',
index e1d9f47..f57b9ce 100644 (file)
@@ -25,7 +25,7 @@
                "ext-xml": "*",
                "liuggio/statsd-php-client": "1.0.18",
                "mediawiki/at-ease": "1.1.0",
-               "oojs/oojs-ui": "0.18.0",
+               "oojs/oojs-ui": "0.18.2",
                "oyejorge/less.php": "1.7.0.10",
                "php": ">=5.5.9",
                "psr/log": "1.0.0",
index 2cf5fe1..30feaef 100644 (file)
                "SkinOOUIThemes": {
                        "type": "object"
                },
+               "PasswordPolicy": {
+                       "type": "object",
+                       "description": "Password policies"
+               },
+               "FileExtensions": {
+                       "type": "array",
+                       "description": "Preferred file extensions for uploading",
+                       "items": {
+                               "type": "string"
+                       }
+               },
                "callback": {
                        "type": [
                                "array",
index 8659dff..421ea5c 100644 (file)
                "SkinOOUIThemes": {
                        "type": "object"
                },
+               "PasswordPolicy": {
+                       "type": "object",
+                       "description": "Password policies"
+               },
+               "FileExtensions": {
+                       "type": "array",
+                       "description": "Preferred file extensions for uploading",
+                       "items": {
+                               "type": "string"
+                       }
+               },
                "callback": {
                        "type": [
                                "array",
index 5b707c1..7efd5d2 100644 (file)
@@ -358,8 +358,12 @@ authenticate and authorize API clients before executing the module. Return
 false and set a message to cancel the request.
 $module: Module object
 $user: Current user
-&$message: API usage message to die with, as a message key or array
-  as accepted by ApiBase::dieUsageMsg.
+&$message: API message to die with. Specific values accepted depend on the
+ MediaWiki version:
+ * 1.29+: IApiMessage, Message, string message key, or key+parameters array to
+   pass to ApiBase::dieWithError().
+ * 1.27+: IApiMessage, or a key or key+parameters in ApiBase::$messageMap.
+ * Earlier: A key or key+parameters in ApiBase::$messageMap.
 
 'APIEditBeforeSave': DEPRECATED! Use EditFilterMergedContent instead.
 Before saving a page with api.php?action=edit, after
@@ -774,14 +778,6 @@ $article: the article
 &$sectionanchor: The section anchor link (e.g. "#overview" )
 &$extraq: Extra query parameters which can be added via hooked functions
 
-'ArticleViewCustom': DEPRECATED! Use ArticleContentViewCustom instead.
-Allows to output the text of the article in a different format than wikitext.
-Note that it is preferable to implement proper handing for a custom data type
-using the ContentHandler facility.
-$text: text of the page
-$title: title of the page
-$output: reference to $wgOut
-
 'ArticleViewFooter': After showing the footer section of an ordinary page view
 $article: Article object
 $patrolFooterShown: boolean whether patrol footer is shown
@@ -1417,13 +1413,6 @@ different data types using the ContentHandler facility.
 $editPage: EditPage object
 &$newtext: wikitext that will be used as "your version"
 
-'EditPageGetDiffText': DEPRECATED! Use EditPageGetDiffContent instead.
-Allow modifying the wikitext that will be used in "Show changes". Note that it
-is preferable to implement diff handling for different data types using the
-ContentHandler facility.
-$editPage: EditPage object
-&$newtext: wikitext that will be used as "your version"
-
 'EditPageGetPreviewContent': Allow modifying the wikitext that will be
 previewed. Note that it is preferable to implement previews for different data
 types using the ContentHandler facility.
@@ -1459,7 +1448,7 @@ true to allow those checks to occur, and false if checking is done.
 &$from: MailAddress object of sending user
 &$subject: subject of the mail
 &$text: text of the mail
-&$error: Out-param for an error
+&$error: Out-param for an error. Should be set to a Status object or boolean false.
 
 'EmailUserCC': Before sending the copy of the email to the author.
 &$to: MailAddress object of receiving user
@@ -2464,6 +2453,13 @@ $revId: ID of the revision that was parsed to create $parserOutput
 'ParserCloned': Called when the parser is cloned.
 $parser: Newly-cloned Parser object
 
+'ParserFetchTemplate': Called when the parser fetches a template
+$parser: Parser Parser object or false
+$title: Title object of the template to be fetched
+$rev: Revision object of the template
+&$text: Transclusion text of the template or false or null
+&$deps: Array of template dependencies with 'title', 'page_id', 'rev_id' keys
+
 'ParserFirstCallInit': Called when the parser initialises for the first time.
 &$parser: Parser object being cleared
 
@@ -2547,8 +2543,6 @@ $user: the User considering the edit
 'PasswordPoliciesForUser': Alter the effective password policy for a user.
 $user: User object whose policy you are modifying
 &$effectivePolicy: Array of policy statements that apply to this user
-$purpose: string indicating purpose of the check, one of 'login', 'create',
-  or 'reset'
 
 'PerformRetroactiveAutoblock': Called before a retroactive autoblock is applied
 to a user.
@@ -2836,12 +2830,6 @@ Special:ShortPages.
 'ShowMissingArticle': Called when generating the output for a non-existent page.
 $article: The article object corresponding to the page
 
-'ShowRawCssJs': DEPRECATED! Use the ContentGetParserOutput hook instead.
-Customise the output of raw CSS and JavaScript in page views.
-$text: Text being shown
-$title: Title of the custom script/stylesheet page
-$output: Current OutputPage object
-
 'ShowSearchHit': Customize display of search hit.
 $searchPage: The SpecialSearch instance.
 $result: The SearchResult to show
@@ -3217,6 +3205,15 @@ $engine: the search engine
   message key to use in the name column,
 $context: IContextSource object
 
+'SpecialTrackingCategories::preprocess': Called after LinkBatch on Special:TrackingCategories
+$specialPage: The SpecialTrackingCategories object
+$trackingCategories: Array of data from Special:TrackingCategories with msg and cats
+
+'SpecialTrackingCategories::generateCatLink': Called for each cat link on Special:TrackingCategories
+$specialPage: The SpecialTrackingCategories object
+$catTitle: The Title object of the linked category
+&$html: The Result html
+
 'SpecialUploadComplete': Called after successfully uploading a file from
 Special:Upload.
 &$form: The SpecialUpload object
index 0686578..3e42c08 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  * @ingroup Ajax
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * Handle responses for Ajax requests (send headers, print
@@ -82,7 +83,7 @@ class AjaxResponse {
        function __construct( $text = null, Config $config = null ) {
                $this->mCacheDuration = null;
                $this->mVary = null;
-               $this->mConfig = $config ?: ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               $this->mConfig = $config ?: MediaWikiServices::getInstance()->getMainConfig();
 
                $this->mDisabled = false;
                $this->mText = '';
index 0b65593..b85e1d6 100644 (file)
@@ -73,7 +73,7 @@ class AuthPlugin {
        /**
         * Modify options in the login template.
         *
-        * @param UserLoginTemplate $template
+        * @param BaseTemplate $template
         * @param string $type 'signup' or 'login'. Added in 1.16.
         */
        public function modifyUITemplate( &$template, &$type ) {
index a11ba26..8663d03 100644 (file)
@@ -1417,6 +1417,33 @@ class Block {
                $this->blocker = $user;
        }
 
+       /**
+        * Set the 'BlockID' cookie to this block's ID and expiry time. The cookie's expiry will be
+        * the same as the block's, unless it's greater than $wgCookieExpiration in which case
+        * $wgCookieExpiration will be used instead (defaults to 30 days).
+        *
+        * An empty value can also be set, in order to retain the cookie but remove the block ID
+        * (e.g. as used in User::getBlockedStatus).
+        *
+        * @param WebResponse $response The response on which to set the cookie.
+        * @param boolean $setEmpty Whether to set the cookie's value to the empty string.
+        */
+       public function setCookie( WebResponse $response, $setEmpty = false ) {
+               // Calculate the default expiry time.
+               $config = RequestContext::getMain()->getConfig();
+               $defaultExpiry = wfTimestamp() + $config->get( 'CookieExpiration' );
+
+               // Use the Block's expiry time only if it's less than the default.
+               $expiry = wfTimestamp( TS_UNIX, $this->getExpiry() );
+               if ( $expiry > $defaultExpiry ) {
+                       // The *default* default expiry is 30 days.
+                       $expiry = $defaultExpiry;
+               }
+
+               $cookieValue = $setEmpty ? '' : $this->getId();
+               $response->setCookie( 'BlockID', $cookieValue, $expiry );
+       }
+
        /**
         * Get the key and parameters for the corresponding error message.
         *
index b95f274..4c4b8bb 100644 (file)
@@ -197,7 +197,11 @@ class CategoryViewer extends ContextSource {
                $link = null;
                Hooks::run( 'CategoryViewer::generateLink', [ $type, $title, $html, &$link ] );
                if ( $link === null ) {
-                       $link = Linker::link( $title, $html );
+                       $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+                       if ( $html !== null ) {
+                               $html = new HtmlArmor( $html );
+                       }
+                       $link = $linkRenderer->makeLink( $title, $html );
                }
                if ( $isRedirect ) {
                        $link = '<span class="redirect-in-category">' . $link . '</span>';
index 9d8ccf8..5557dca 100644 (file)
@@ -1586,7 +1586,7 @@ $wgEnableUserEmail = true;
 
 /**
  * Set to true to put the sending user's email in a Reply-To header
- * instead of From. ($wgEmergencyContact will be used as From.)
+ * instead of From. ($wgPasswordSender will be used as From.)
  *
  * Some mailers (eg SMTP) set the SMTP envelope sender to the From value,
  * which can cause problems with SPF validation and leak recipient addresses
@@ -2365,13 +2365,6 @@ $wgMainStash = 'db-replicated';
  */
 $wgParserCacheExpireTime = 86400;
 
-/**
- * Deprecated alias for $wgSessionsInObjectCache.
- *
- * @deprecated since 1.20; Use $wgSessionsInObjectCache
- */
-$wgSessionsInMemcached = true;
-
 /**
  * @deprecated since 1.27, session data is always stored in object cache.
  */
@@ -5864,7 +5857,7 @@ $wgProxyList = [];
 /**
  * Default cookie lifetime, in seconds. Setting to 0 makes all cookies session-only.
  */
-$wgCookieExpiration = 180 * 86400;
+$wgCookieExpiration = 30 * 86400;
 
 /**
  * Default login cookie lifetime, in seconds. Setting
@@ -5872,7 +5865,7 @@ $wgCookieExpiration = 180 * 86400;
  * calculate the cookie lifetime. As with $wgCookieExpiration, 0 will make
  * login cookies session-only.
  */
-$wgExtendedLoginCookieExpiration = null;
+$wgExtendedLoginCookieExpiration = 180 * 86400;
 
 /**
  * Set to set an explicit domain on the login cookies eg, "justthis.domain.org"
@@ -5926,6 +5919,12 @@ $wgCacheVaryCookies = [];
  */
 $wgSessionName = false;
 
+/**
+ * Whether to set a cookie when a user is autoblocked. Doing so means that a blocked user, even
+ * after logging out and moving to a new IP address, will still be blocked.
+ */
+$wgCookieSetOnAutoblock = false;
+
 /** @} */ # end of cookie settings }
 
 /************************************************************************//**
@@ -7510,6 +7509,7 @@ $wgLogActionsHandlers = [
        'contentmodel/change' => 'ContentModelLogFormatter',
        'contentmodel/new' => 'ContentModelLogFormatter',
        'delete/delete' => 'DeleteLogFormatter',
+       'delete/delete_redir' => 'DeleteLogFormatter',
        'delete/event' => 'DeleteLogFormatter',
        'delete/restore' => 'DeleteLogFormatter',
        'delete/revision' => 'DeleteLogFormatter',
@@ -7561,6 +7561,7 @@ $wgActionFilteredLogs = [
        ],
        'delete' => [
                'delete' => [ 'delete' ],
+               'delete_redir' => [ 'delete_redir' ],
                'restore' => [ 'restore' ],
                'event' => [ 'event' ],
                'revision' => [ 'revision' ],
@@ -8380,9 +8381,9 @@ $wgSearchRunSuggestedQuery = true;
 /**
  * Where popular password file is located.
  *
- * Default in core contains 50,000 most popular. This config
+ * Default in core contains 10,000 most popular. This config
  * allows you to change which file, in case you want to generate
- * a password file with > 50000 entries in it.
+ * a password file with > 10000 entries in it.
  *
  * @see maintenance/createCommonPasswordCdb.php
  * @since 1.27
index 5b0bc8a..f37ce34 100644 (file)
@@ -2326,9 +2326,12 @@ class EditPage {
        }
 
        function setHeaders() {
-               global $wgOut, $wgUser, $wgAjaxEditStash;
+               global $wgOut, $wgUser, $wgAjaxEditStash, $wgCookieSetOnAutoblock;
 
                $wgOut->addModules( 'mediawiki.action.edit' );
+               if ( $wgCookieSetOnAutoblock === true ) {
+                       $wgOut->addModules( 'mediawiki.user.blockcookie' );
+               }
                $wgOut->addModuleStyles( 'mediawiki.action.edit.styles' );
 
                if ( $wgUser->getOption( 'showtoolbar' ) ) {
@@ -3323,7 +3326,6 @@ HTML
                }
 
                if ( $newContent ) {
-                       ContentHandler::runLegacyHooks( 'EditPageGetDiffText', [ $this, &$newContent ], '1.21' );
                        Hooks::run( 'EditPageGetDiffContent', [ $this, &$newContent ] );
 
                        $popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
@@ -3407,6 +3409,7 @@ HTML
         *
         * @param Title $title
         * @param string $format Output format, valid values are any function of a Message object
+        * @param Language|string|null $langcode Language code or Language object.
         * @return string
         */
        public static function getCopyrightWarning( $title, $format = 'plain', $langcode = null ) {
@@ -4067,7 +4070,7 @@ HTML
 
        /**
         * Returns an array of html code of the following buttons:
-        * save, diff, preview and live
+        * save, diff and preview
         *
         * @param int $tabindex Current tabindex
         *
@@ -4101,7 +4104,6 @@ HTML
                ] + Linker::tooltipAndAccesskeyAttribs( 'preview' );
                $buttons['preview'] = Html::submitButton( $this->context->msg( 'showpreview' )->text(),
                        $attribs );
-               $buttons['live'] = '';
 
                $attribs = [
                        'id' => 'wpDiff',
index e6223e8..f850152 100644 (file)
@@ -152,7 +152,7 @@ class FileDeleteForm {
         * @param User $user User object performing the request
         * @param array $tags Tags to apply to the deletion action
         * @throws MWException
-        * @return bool|Status
+        * @return Status
         */
        public static function doDelete( &$title, &$file, &$oldimage, $reason,
                $suppress, User $user = null, $tags = []
index 27aab8a..7e5cc7d 100644 (file)
@@ -168,6 +168,17 @@ class Message implements MessageSpecifier, Serializable {
        /** Transform {{..}} constructs, HTML-escape the result */
        const FORMAT_ESCAPED = 'escaped';
 
+       /**
+        * Mapping from Message::listParam() types to Language methods.
+        * @var array
+        */
+       protected static $listTypeMap = [
+               'comma' => 'commaList',
+               'semicolon' => 'semicolonList',
+               'pipe' => 'pipeList',
+               'text' => 'listToText',
+       ];
+
        /**
         * In which language to get this message. True, which is the default,
         * means the current user language, false content language.
@@ -766,6 +777,7 @@ class Message implements MessageSpecifier, Serializable {
         */
        public function useDatabase( $useDatabase ) {
                $this->useDatabase = (bool)$useDatabase;
+               $this->message = null;
                return $this;
        }
 
@@ -822,6 +834,7 @@ class Message implements MessageSpecifier, Serializable {
                        // message key is user-controlled.
                        // '⧼' is used instead of '<' to side-step any
                        // double-escaping issues.
+                       // (Keep synchronised with mw.Message#toString in JS.)
                        return '⧼' . htmlspecialchars( $this->key ) . '⧽';
                }
 
@@ -1068,6 +1081,22 @@ class Message implements MessageSpecifier, Serializable {
                return [ 'plaintext' => $plaintext ];
        }
 
+       /**
+        * @since 1.29
+        *
+        * @param array $list
+        * @param string $type 'comma', 'semicolon', 'pipe', 'text'
+        * @return array Array with "list" and "type" keys.
+        */
+       public static function listParam( array $list, $type = 'text' ) {
+               if ( !isset( self::$listTypeMap[$type] ) ) {
+                       throw new InvalidArgumentException(
+                               "Invalid type '$type'. Known types are: " . join( ', ', array_keys( self::$listTypeMap ) )
+                       );
+               }
+               return [ 'list' => $list, 'type' => $type ];
+       }
+
        /**
         * Substitutes any parameters into the message text.
         *
@@ -1121,6 +1150,8 @@ class Message implements MessageSpecifier, Serializable {
                                return [ 'before', $this->getLanguage()->formatBitrate( $param['bitrate'] ) ];
                        } elseif ( isset( $param['plaintext'] ) ) {
                                return [ 'after', $this->formatPlaintext( $param['plaintext'], $format ) ];
+                       } elseif ( isset( $param['list'] ) ) {
+                               return $this->formatListParam( $param['list'], $param['type'], $format );
                        } else {
                                $warning = 'Invalid parameter for message "' . $this->getKey() . '": ' .
                                        htmlspecialchars( serialize( $param ) );
@@ -1131,10 +1162,27 @@ class Message implements MessageSpecifier, Serializable {
                                return [ 'before', '[INVALID]' ];
                        }
                } elseif ( $param instanceof Message ) {
+                       // Match language, flags, etc. to the current message.
+                       $msg = clone $param;
+                       if ( $msg->language !== $this->language || $msg->useDatabase !== $this->useDatabase ) {
+                               // Cache depends on these parameters
+                               $msg->message = null;
+                       }
+                       $msg->interface = $this->interface;
+                       $msg->language = $this->language;
+                       $msg->useDatabase = $this->useDatabase;
+                       $msg->title = $this->title;
+
+                       // DWIM
+                       if ( $format === 'block-parse' ) {
+                               $format = 'parse';
+                       }
+                       $msg->format = $format;
+
                        // Message objects should not be before parameters because
                        // then they'll get double escaped. If the message needs to be
                        // escaped, it'll happen right here when we call toString().
-                       return [ 'after', $param->toString( $format ) ];
+                       return [ 'after', $msg->toString( $format ) ];
                } else {
                        return [ 'before', $param ];
                }
@@ -1232,6 +1280,54 @@ class Message implements MessageSpecifier, Serializable {
 
                }
        }
+
+       /**
+        * Formats a list of parameters as a concatenated string.
+        * @since 1.29
+        * @param array $params
+        * @param string $listType
+        * @param string $format One of the FORMAT_* constants.
+        * @return array Array with the parameter type (either "before" or "after") and the value.
+        */
+       protected function formatListParam( array $params, $listType, $format ) {
+               if ( !isset( self::$listTypeMap[$listType] ) ) {
+                       $warning = 'Invalid list type for message "' . $this->getKey() . '": ' .
+                               htmlspecialchars( serialize( $param ) );
+                       trigger_error( $warning, E_USER_WARNING );
+                       $e = new Exception;
+                       wfDebugLog( 'Bug58676', $warning . "\n" . $e->getTraceAsString() );
+                       return [ 'before', '[INVALID]' ];
+               }
+               $func = self::$listTypeMap[$listType];
+
+               // Handle an empty list sensibly
+               if ( !$params ) {
+                       return [ 'before', $this->getLanguage()->$func( [] ) ];
+               }
+
+               // First, determine what kinds of list items we have
+               $types = [];
+               $vars = [];
+               $list = [];
+               foreach ( $params as $n => $p ) {
+                       list( $type, $value ) = $this->extractParam( $p, $format );
+                       $types[$type] = true;
+                       $list[] = $value;
+                       $vars[] = '$' . ( $n + 1 );
+               }
+
+               // Easy case: all are 'before' or 'after', so just join the
+               // values and use the same type.
+               if ( count( $types ) === 1 ) {
+                       return [ key( $types ), $this->getLanguage()->$func( $list ) ];
+               }
+
+               // Hard case: We need to process each value per its type, then
+               // return the concatenated values as 'after'. We handle this by turning
+               // the list into a RawMessage and processing that as a parameter.
+               $vars = $this->getLanguage()->$func( $vars );
+               return $this->extractParam( new RawMessage( $vars, $params ), $format );
+       }
 }
 
 /**
index c03bce7..f062d13 100644 (file)
  * @file
  */
 use MediaWiki\MediaWikiServices;
-use MediaWiki\Logger\LoggerFactory;
+use Wikimedia\Assert\Assert;
 
+/**
+ * @deprecated since 1.29
+ * MimeAnalyzer should be used instead of MimeMagic
+ */
 class MimeMagic extends MimeAnalyzer {
        /**
         * Get an instance of this class
         * @return MimeMagic
-        * @deprecated since 1.28
+        * @deprecated since 1.28 get a MimeAnalyzer instance form MediaWikiServices
         */
        public static function singleton() {
-               return MediaWikiServices::getInstance()->getMIMEAnalyzer();
-       }
-
-       /**
-        * @param array $params
-        * @param Config $mainConfig
-        * @return array
-        */
-       public static function applyDefaultParameters( array $params, Config $mainConfig ) {
-               $logger = LoggerFactory::getInstance( 'Mime' );
-               $params += [
-                       'typeFile' => $mainConfig->get( 'MimeTypeFile' ),
-                       'infoFile' => $mainConfig->get( 'MimeInfoFile' ),
-                       'xmlTypes' => $mainConfig->get( 'XMLMimeTypes' ),
-                       'guessCallback' =>
-                               function ( $mimeAnalyzer, &$head, &$tail, $file, &$mime ) use ( $logger ) {
-                                       // Also test DjVu
-                                       $deja = new DjVuImage( $file );
-                                       if ( $deja->isValid() ) {
-                                               $logger->info( __METHOD__ . ": detected $file as image/vnd.djvu\n" );
-                                               $mime = 'image/vnd.djvu';
-
-                                               return;
-                                       }
-                                       // Some strings by reference for performance - assuming well-behaved hooks
-                                       Hooks::run(
-                                               'MimeMagicGuessFromContent',
-                                               [ $mimeAnalyzer, &$head, &$tail, $file, &$mime ]
-                                       );
-                               },
-                       'extCallback' => function ( $mimeAnalyzer, $ext, &$mime ) {
-                               // Media handling extensions can improve the MIME detected
-                               Hooks::run( 'MimeMagicImproveFromExtension', [ $mimeAnalyzer, $ext, &$mime ] );
-                       },
-                       'initCallback' => function ( $mimeAnalyzer ) {
-                               // Allow media handling extensions adding MIME-types and MIME-info
-                               Hooks::run( 'MimeMagicInit', [ $mimeAnalyzer ] );
-                       },
-                       'logger' => $logger
-               ];
-
-               if ( $params['infoFile'] === 'includes/mime.info' ) {
-                       $params['infoFile'] = __DIR__ . "/libs/mime/mime.info";
-               }
-
-               if ( $params['typeFile'] === 'includes/mime.types' ) {
-                       $params['typeFile'] = __DIR__ . "/libs/mime/mime.types";
-               }
-
-               $detectorCmd = $mainConfig->get( 'MimeDetectorCommand' );
-               if ( $detectorCmd ) {
-                       $params['detectCallback'] = function ( $file ) use ( $detectorCmd ) {
-                               return wfShellExec( "$detectorCmd " . wfEscapeShellArg( $file ) );
-                       };
-               }
-
-               return $params;
+               // XXX: We know that the MimeAnalyzer is currently an instance of MimeMagic
+               $instance = MediaWikiServices::getInstance()->getMimeAnalyzer();
+               Assert::postcondition(
+                       $instance instanceof MimeMagic,
+                       __METHOD__ . ' should return an instance of ' . MimeMagic::class
+               );
+               return $instance;
        }
 }
index a8f6f8e..cbb4651 100644 (file)
@@ -457,7 +457,9 @@ class MovePage {
                                $nt->getArticleID(),
                                /* $commit */ false,
                                $errs,
-                               $user
+                               $user,
+                               [],
+                               'delete_redir'
                        );
 
                        if ( !$status->isGood() ) {
index 50629ba..bae871e 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Session\SessionManager;
 use WrappedString\WrappedString;
 use WrappedString\WrappedStringList;
@@ -107,7 +108,10 @@ class OutputPage extends ContextSource {
        protected $mCategoryLinks = [];
 
        /** @var array */
-       protected $mCategories = [];
+       protected $mCategories = [
+               'hidden' => [],
+               'normal' => [],
+       ];
 
        /** @var array */
        protected $mIndicators = [];
@@ -1007,8 +1011,9 @@ class OutputPage extends ContextSource {
                if ( $title->isRedirect() ) {
                        $query['redirect'] = 'no';
                }
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                return wfMessage( 'backlinksubtitle' )
-                       ->rawParams( Linker::link( $title, null, [], $query ) );
+                       ->rawParams( $linkRenderer->makeLink( $title, null, [], $query ) );
        }
 
        /**
@@ -1249,31 +1254,7 @@ class OutputPage extends ContextSource {
                        return;
                }
 
-               # Add the links to a LinkBatch
-               $arr = [ NS_CATEGORY => $categories ];
-               $lb = new LinkBatch;
-               $lb->setArray( $arr );
-
-               # Fetch existence plus the hiddencat property
-               $dbr = wfGetDB( DB_REPLICA );
-               $fields = array_merge(
-                       LinkCache::getSelectFields(),
-                       [ 'page_namespace', 'page_title', 'pp_value' ]
-               );
-
-               $res = $dbr->select( [ 'page', 'page_props' ],
-                       $fields,
-                       $lb->constructSet( 'page', $dbr ),
-                       __METHOD__,
-                       [],
-                       [ 'page_props' => [ 'LEFT JOIN', [
-                               'pp_propname' => 'hiddencat',
-                               'pp_page = page_id'
-                       ] ] ]
-               );
-
-               # Add the results to the link cache
-               $lb->addResultToCache( LinkCache::singleton(), $res );
+               $res = $this->addCategoryLinksToLBAndGetResult( $categories );
 
                # Set all the values to 'normal'.
                $categories = array_fill_keys( array_keys( $categories ), 'normal' );
@@ -1290,6 +1271,7 @@ class OutputPage extends ContextSource {
                        'OutputPageMakeCategoryLinks',
                        [ &$this, $categories, &$this->mCategoryLinks ] )
                ) {
+                       $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                        foreach ( $categories as $category => $type ) {
                                // array keys will cast numeric category names to ints, so cast back to string
                                $category = (string)$category;
@@ -1303,12 +1285,46 @@ class OutputPage extends ContextSource {
                                        continue;
                                }
                                $text = $wgContLang->convertHtml( $title->getText() );
-                               $this->mCategories[] = $title->getText();
-                               $this->mCategoryLinks[$type][] = Linker::link( $title, $text );
+                               $this->mCategories[$type][] = $title->getText();
+                               $this->mCategoryLinks[$type][] = $linkRenderer->makeLink( $title, new HtmlArmor( $text ) );
                        }
                }
        }
 
+       /**
+        * @param array $categories
+        * @return bool|ResultWrapper
+        */
+       protected function addCategoryLinksToLBAndGetResult( array $categories ) {
+               # Add the links to a LinkBatch
+               $arr = [ NS_CATEGORY => $categories ];
+               $lb = new LinkBatch;
+               $lb->setArray( $arr );
+
+               # Fetch existence plus the hiddencat property
+               $dbr = wfGetDB( DB_REPLICA );
+               $fields = array_merge(
+                       LinkCache::getSelectFields(),
+                       [ 'page_namespace', 'page_title', 'pp_value' ]
+               );
+
+               $res = $dbr->select( [ 'page', 'page_props' ],
+                       $fields,
+                       $lb->constructSet( 'page', $dbr ),
+                       __METHOD__,
+                       [],
+                       [ 'page_props' => [ 'LEFT JOIN', [
+                               'pp_propname' => 'hiddencat',
+                               'pp_page = page_id'
+                       ] ] ]
+               );
+
+               # Add the results to the link cache
+               $lb->addResultToCache( LinkCache::singleton(), $res );
+
+               return $res;
+       }
+
        /**
         * Reset the category links (but not the category list) and add $categories
         *
@@ -1332,12 +1348,26 @@ class OutputPage extends ContextSource {
        }
 
        /**
-        * Get the list of category names this page belongs to
+        * Get the list of category names this page belongs to.
         *
+        * @param string $type The type of categories which should be returned. Possible values:
+        *  * all: all categories of all types
+        *  * hidden: only the hidden categories
+        *  * normal: all categories, except hidden categories
         * @return array Array of strings
         */
-       public function getCategories() {
-               return $this->mCategories;
+       public function getCategories( $type = 'all' ) {
+               if ( $type === 'all' ) {
+                       $allCategories = [];
+                       foreach ( $this->mCategories as $categories ) {
+                               $allCategories = array_merge( $allCategories, $categories );
+                       }
+                       return $allCategories;
+               }
+               if ( !isset( $this->mCategories[$type] ) ) {
+                       throw new InvalidArgumentException( 'Invalid category type given: ' . $type );
+               }
+               return $this->mCategories[$type];
        }
 
        /**
@@ -2626,8 +2656,10 @@ class OutputPage extends ContextSource {
         * @param array $options Options array to pass to Linker
         */
        public function addReturnTo( $title, array $query = [], $text = null, $options = [] ) {
+               $linkRenderer = MediaWikiServices::getInstance()
+                       ->getLinkRendererFactory()->createFromLegacyOptions( $options );
                $link = $this->msg( 'returnto' )->rawParams(
-                       Linker::link( $title, $text, [], $query, $options ) )->escaped();
+                       $linkRenderer->makeLink( $title, $text, [], $query ) )->escaped();
                $this->addHTML( "<p id=\"mw-returnto\">{$link}</p>\n" );
        }
 
@@ -2708,7 +2740,6 @@ class OutputPage extends ContextSource {
                                'site.styles',
                                'noscript',
                                'user.styles',
-                               'user.cssprefs',
                        ] );
                        $this->getSkin()->setupSkinUserCss( $this );
 
@@ -2821,6 +2852,14 @@ class OutputPage extends ContextSource {
                $bodyClasses[] = $userdir;
                $bodyClasses[] = "sitedir-$sitedir";
 
+               $underline = $this->getUser()->getOption( 'underline' );
+               if ( $underline < 2 ) {
+                       // The following classes can be used here:
+                       // * mw-underline-always
+                       // * mw-underline-never
+                       $bodyClasses[] = 'mw-underline-' . ( $underline ? 'always' : 'never' );
+               }
+
                if ( $this->getLanguage()->capitalizeAllNouns() ) {
                        # A <body> class is probably not the best way to do this . . .
                        $bodyClasses[] = 'capitalize-all-nouns';
index d86b19a..d40e0c1 100644 (file)
@@ -21,6 +21,7 @@
  */
 use MediaWiki\Auth\AuthManager;
 use MediaWiki\Auth\PasswordAuthenticationRequest;
+use MediaWiki\MediaWikiServices;
 
 /**
  * We're now using the HTMLForm object with some customisation to generate the
@@ -253,7 +254,9 @@ class Preferences {
                        'section' => 'personal/info',
                ];
 
-               $editCount = Linker::link( SpecialPage::getTitleFor( "Contributions", $userName ),
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+
+               $editCount = $linkRenderer->makeLink( SpecialPage::getTitleFor( "Contributions", $userName ),
                        $lang->formatNum( $user->getEditCount() ) );
 
                $defaultPreferences['editcount'] = [
@@ -297,8 +300,8 @@ class Preferences {
                if ( $canEditPrivateInfo && $authManager->allowsAuthenticationDataChange(
                        new PasswordAuthenticationRequest(), false )->isGood()
                ) {
-                       $link = Linker::link( SpecialPage::getTitleFor( 'ChangePassword' ),
-                               $context->msg( 'prefs-resetpass' )->escaped(), [],
+                       $link = $linkRenderer->makeLink( SpecialPage::getTitleFor( 'ChangePassword' ),
+                               $context->msg( 'prefs-resetpass' )->text(), [],
                                [ 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ] );
 
                        $defaultPreferences['password'] = [
@@ -448,9 +451,9 @@ class Preferences {
 
                                $emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : '';
                                if ( $canEditPrivateInfo && $authManager->allowsPropertyChange( 'emailaddress' ) ) {
-                                       $link = Linker::link(
+                                       $link = $linkRenderer->makeLink(
                                                SpecialPage::getTitleFor( 'ChangeEmail' ),
-                                               $context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->escaped(),
+                                               $context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->text(),
                                                [],
                                                [ 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ] );
 
@@ -601,14 +604,15 @@ class Preferences {
                        $linkTools = [];
                        $userName = $user->getName();
 
+                       $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                        if ( $allowUserCss ) {
                                $cssPage = Title::makeTitleSafe( NS_USER, $userName . '/common.css' );
-                               $linkTools[] = Linker::link( $cssPage, $context->msg( 'prefs-custom-css' )->escaped() );
+                               $linkTools[] = $linkRenderer->makeLink( $cssPage, $context->msg( 'prefs-custom-css' )->text() );
                        }
 
                        if ( $allowUserJs ) {
                                $jsPage = Title::makeTitleSafe( NS_USER, $userName . '/common.js' );
-                               $linkTools[] = Linker::link( $jsPage, $context->msg( 'prefs-custom-js' )->escaped() );
+                               $linkTools[] = $linkRenderer->makeLink( $jsPage, $context->msg( 'prefs-custom-js' )->text() );
                        }
 
                        $defaultPreferences['commoncssjs'] = [
@@ -1110,6 +1114,8 @@ class Preferences {
                $mptitle = Title::newMainPage();
                $previewtext = $context->msg( 'skin-preview' )->escaped();
 
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+
                # Only show skins that aren't disabled in $wgSkipSkins
                $validSkinNames = Skin::getAllowedSkins();
 
@@ -1145,12 +1151,12 @@ class Preferences {
                        # Create links to user CSS/JS pages
                        if ( $allowUserCss ) {
                                $cssPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/' . $skinkey . '.css' );
-                               $linkTools[] = Linker::link( $cssPage, $context->msg( 'prefs-custom-css' )->escaped() );
+                               $linkTools[] = $linkRenderer->makeLink( $cssPage, $context->msg( 'prefs-custom-css' )->text() );
                        }
 
                        if ( $allowUserJs ) {
                                $jsPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/' . $skinkey . '.js' );
-                               $linkTools[] = Linker::link( $jsPage, $context->msg( 'prefs-custom-js' )->escaped() );
+                               $linkTools[] = $linkRenderer->makeLink( $jsPage, $context->msg( 'prefs-custom-js' )->text() );
                        }
 
                        $display = $sn . ' ' . $context->msg( 'parentheses' )
@@ -1624,7 +1630,8 @@ class PreferencesForm extends HTMLForm {
                if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) {
                        $t = SpecialPage::getTitleFor( 'Preferences', 'reset' );
 
-                       $html .= "\n" . Linker::link( $t, $this->msg( 'restoreprefs' )->escaped(),
+                       $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+                       $html .= "\n" . $linkRenderer->makeLink( $t, $this->msg( 'restoreprefs' )->text(),
                                Html::buttonAttributes( $attrs, [ 'mw-ui-quiet' ] ) );
 
                        $html = Xml::tags( 'div', [ 'class' => 'mw-prefs-buttons' ], $html );
index f6c4147..04c17e4 100644 (file)
@@ -239,7 +239,7 @@ abstract class PrefixSearch {
                // canonical and alias title forms...
                $keys = [];
                foreach ( SpecialPageFactory::getNames() as $page ) {
-                       $keys[$wgContLang->caseFold( $page )] = $page;
+                       $keys[$wgContLang->caseFold( $page )] = [ 'page' => $page, 'rank' => 0 ];
                }
 
                foreach ( $wgContLang->getSpecialPageAliases() as $page => $aliases ) {
@@ -247,33 +247,35 @@ abstract class PrefixSearch {
                                continue;
                        }
 
-                       foreach ( $aliases as $alias ) {
-                               $keys[$wgContLang->caseFold( $alias )] = $alias;
+                       foreach ( $aliases as $key => $alias ) {
+                               $keys[$wgContLang->caseFold( $alias )] = [ 'page' => $alias, 'rank' => $key ];
                        }
                }
                ksort( $keys );
 
-               $srchres = [];
-               $skipped = 0;
+               $matches = [];
                foreach ( $keys as $pageKey => $page ) {
                        if ( $searchKey === '' || strpos( $pageKey, $searchKey ) === 0 ) {
                                // bug 27671: Don't use SpecialPage::getTitleFor() here because it
                                // localizes its input leading to searches for e.g. Special:All
                                // returning Spezial:MediaWiki-Systemnachrichten and returning
                                // Spezial:Alle_Seiten twice when $wgLanguageCode == 'de'
-                               if ( $offset > 0 && $skipped < $offset ) {
-                                       $skipped++;
-                                       continue;
+                               $matches[$page['rank']][] = Title::makeTitleSafe( NS_SPECIAL, $page['page'] );
+
+                               if ( isset( $matches[0] ) && count( $matches[0] ) >= $limit + $offset ) {
+                                       // We have enough items in primary rank, no use to continue
+                                       break;
                                }
-                               $srchres[] = Title::makeTitleSafe( NS_SPECIAL, $page );
                        }
 
-                       if ( count( $srchres ) >= $limit ) {
-                               break;
-                       }
                }
 
-               return $srchres;
+               // Ensure keys are in order
+               ksort( $matches );
+               // Flatten the array
+               $matches = array_reduce( $matches, 'array_merge', [] );
+
+               return array_slice( $matches, $offset, $limit );
        }
 
        /**
index fb444bd..052fd16 100644 (file)
@@ -20,6 +20,8 @@
  * @file
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * List for revision table items for a single page
  */
@@ -268,6 +270,14 @@ abstract class RevisionItemBase {
         * This is used to show the list in HTML form, by the special page.
         */
        abstract public function getHTML();
+
+       /**
+        * Returns an instance of LinkRenderer
+        * @return \MediaWiki\Linker\LinkRenderer
+        */
+       protected function getLinkRenderer() {
+               return MediaWikiServices::getInstance()->getLinkRenderer();
+       }
 }
 
 class RevisionList extends RevisionListBase {
index c2197a6..4fec472 100644 (file)
@@ -96,7 +96,7 @@ return [
                $config = $services->getMainConfig();
                return new ClassicInterwikiLookup(
                        $wgContLang,
-                       ObjectCache::getMainWANInstance(),
+                       $services->getMainWANObjectCache(),
                        $config->get( 'InterwikiExpiry' ),
                        $config->get( 'InterwikiCache' ),
                        $config->get( 'InterwikiScopes' ),
@@ -214,12 +214,56 @@ return [
        },
 
        'MimeAnalyzer' => function( MediaWikiServices $services ) {
-               return new MimeMagic(
-                       MimeMagic::applyDefaultParameters(
-                               [],
-                               $services->getMainConfig()
-                       )
-               );
+               $logger = LoggerFactory::getInstance( 'Mime' );
+               $mainConfig = $services->getMainConfig();
+               $params = [
+                       'typeFile' => $mainConfig->get( 'MimeTypeFile' ),
+                       'infoFile' => $mainConfig->get( 'MimeInfoFile' ),
+                       'xmlTypes' => $mainConfig->get( 'XMLMimeTypes' ),
+                       'guessCallback' =>
+                               function ( $mimeAnalyzer, &$head, &$tail, $file, &$mime ) use ( $logger ) {
+                                       // Also test DjVu
+                                       $deja = new DjVuImage( $file );
+                                       if ( $deja->isValid() ) {
+                                               $logger->info( __METHOD__ . ": detected $file as image/vnd.djvu\n" );
+                                               $mime = 'image/vnd.djvu';
+
+                                               return;
+                                       }
+                                       // Some strings by reference for performance - assuming well-behaved hooks
+                                       Hooks::run(
+                                               'MimeMagicGuessFromContent',
+                                               [ $mimeAnalyzer, &$head, &$tail, $file, &$mime ]
+                                       );
+                               },
+                       'extCallback' => function ( $mimeAnalyzer, $ext, &$mime ) {
+                               // Media handling extensions can improve the MIME detected
+                               Hooks::run( 'MimeMagicImproveFromExtension', [ $mimeAnalyzer, $ext, &$mime ] );
+                       },
+                       'initCallback' => function ( $mimeAnalyzer ) {
+                               // Allow media handling extensions adding MIME-types and MIME-info
+                               Hooks::run( 'MimeMagicInit', [ $mimeAnalyzer ] );
+                       },
+                       'logger' => $logger
+               ];
+
+               if ( $params['infoFile'] === 'includes/mime.info' ) {
+                       $params['infoFile'] = __DIR__ . "/libs/mime/mime.info";
+               }
+
+               if ( $params['typeFile'] === 'includes/mime.types' ) {
+                       $params['typeFile'] = __DIR__ . "/libs/mime/mime.types";
+               }
+
+               $detectorCmd = $mainConfig->get( 'MimeDetectorCommand' );
+               if ( $detectorCmd ) {
+                       $params['detectCallback'] = function ( $file ) use ( $detectorCmd ) {
+                               return wfShellExec( "$detectorCmd " . wfEscapeShellArg( $file ) );
+                       };
+               }
+
+               // XXX: MimeMagic::singleton currently requires this service to return an instance of MimeMagic
+               return new MimeMagic( $params );
        },
 
        'ProxyLookup' => function( MediaWikiServices $services ) {
@@ -238,7 +282,7 @@ return [
        'LinkCache' => function( MediaWikiServices $services ) {
                return new LinkCache(
                        $services->getTitleFormatter(),
-                       ObjectCache::getMainWANInstance()
+                       $services->getMainWANObjectCache()
                );
        },
 
index 357c76d..f6631ea 100644 (file)
@@ -36,8 +36,10 @@ if ( !defined( 'MEDIAWIKI' ) ) {
 $fname = 'Setup.php';
 $ps_setup = Profiler::instance()->scopedProfileIn( $fname );
 
-// If any extensions are still queued, force load them
+// Load queued extensions
 ExtensionRegistry::getInstance()->loadFromQueue();
+// Don't let any other extensions load
+ExtensionRegistry::getInstance()->finish();
 
 // Check to see if we are at the file scope
 if ( !isset( $wgVersion ) ) {
@@ -462,7 +464,7 @@ if ( $wgMaximalPasswordLength !== false ) {
 }
 
 // Backwards compatibility warning
-if ( !$wgSessionsInObjectCache && !$wgSessionsInMemcached ) {
+if ( !$wgSessionsInObjectCache ) {
        wfDeprecated( '$wgSessionsInObjectCache = false', '1.27' );
        if ( $wgSessionHandler ) {
                wfDeprecated( '$wgSessionsHandler', '1.27' );
index a1e6d5b..470a75c 100644 (file)
@@ -1,4 +1,6 @@
 <?php
+use MediaWiki\MediaWikiServices;
+
 /**
  * Handles compiling Mustache templates into PHP rendering functions
  *
@@ -98,7 +100,7 @@ class TemplateParser {
                $fastHash = md5( $fileContents );
 
                // Fetch a secret key for building a keyed hash of the PHP code
-               $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               $config = MediaWikiServices::getInstance()->getMainConfig();
                $secretKey = $config->get( 'SecretKey' );
 
                if ( $secretKey ) {
index 0c3d52a..cd78b49 100644 (file)
@@ -422,10 +422,7 @@ class WatchedItemQueryService {
                        $ownersToken = $watchlistOwner->getOption( 'watchlisttoken' );
                        $token = $options['watchlistOwnerToken'];
                        if ( $ownersToken == '' || !hash_equals( $ownersToken, $token ) ) {
-                               throw new UsageException(
-                                       'Incorrect watchlist token provided -- please set a correct token in Special:Preferences',
-                                       'bad_wltoken'
-                               );
+                               throw ApiUsageException::newWithMessage( null, 'apierror-bad-watchlist-token', 'bad_wltoken' );
                        }
                        return $watchlistOwner->getId();
                }
index 4c6b071..e124c38 100644 (file)
@@ -613,42 +613,6 @@ class Xml {
                                        $content, false );
        }
 
-       /**
-        * Returns an escaped string suitable for inclusion in a string literal
-        * for JavaScript source code.
-        * Illegal control characters are assumed not to be present.
-        *
-        * @deprecated since 1.21; use Xml::encodeJsVar() or Xml::encodeJsCall() instead
-        * @param string $string String to escape
-        * @return string
-        */
-       public static function escapeJsString( $string ) {
-               // See ECMA 262 section 7.8.4 for string literal format
-               $pairs = [
-                       "\\" => "\\\\",
-                       "\"" => "\\\"",
-                       '\'' => '\\\'',
-                       "\n" => "\\n",
-                       "\r" => "\\r",
-
-                       # To avoid closing the element or CDATA section
-                       "<" => "\\x3c",
-                       ">" => "\\x3e",
-
-                       # To avoid any complaints about bad entity refs
-                       "&" => "\\x26",
-
-                       # Work around https://bugzilla.mozilla.org/show_bug.cgi?id=274152
-                       # Encode certain Unicode formatting chars so affected
-                       # versions of Gecko don't misinterpret our strings;
-                       # this is a common problem with Farsi text.
-                       "\xe2\x80\x8c" => "\\u200c", // ZERO WIDTH NON-JOINER
-                       "\xe2\x80\x8d" => "\\u200d", // ZERO WIDTH JOINER
-               ];
-
-               return strtr( $string, $pairs );
-       }
-
        /**
         * Encode a variable of arbitrary type to JavaScript.
         * If the value is an XmlJsCode object, pass through the object's value verbatim.
index 1332ab4..803695a 100644 (file)
@@ -23,6 +23,8 @@
  * @author <evan@wikitravel.org>
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * @ingroup Actions
  */
@@ -198,14 +200,15 @@ class CreditsAction extends FormlessAction {
                if ( $this->canShowRealUserName() && !$user->isAnon() ) {
                        $real = $user->getRealName();
                } else {
-                       $real = false;
+                       $real = $user->getName();
                }
 
                $page = $user->isAnon()
                        ? SpecialPage::getTitleFor( 'Contributions', $user->getName() )
                        : $user->getUserPage();
 
-               return Linker::link( $page, htmlspecialchars( $real ? $real : $user->getName() ) );
+               return MediaWikiServices::getInstance()
+                       ->getLinkRenderer()->makeLink( $page, $real );
        }
 
        /**
@@ -231,9 +234,9 @@ class CreditsAction extends FormlessAction {
         * @return string HTML link
         */
        protected function othersLink() {
-               return Linker::linkKnown(
+               return MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
                        $this->getTitle(),
-                       $this->msg( 'others' )->escaped(),
+                       $this->msg( 'others' )->text(),
                        [],
                        [ 'action' => 'credits' ]
                );
index c1763fa..9573cac 100644 (file)
@@ -23,6 +23,8 @@
  * @ingroup Actions
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This class handles printing the history page for an article. In order to
  * be efficient, it uses timestamps rather than offsets for paging, to avoid
@@ -58,9 +60,9 @@ class HistoryAction extends FormlessAction {
 
        protected function getDescription() {
                // Creation of a subtitle link pointing to [[Special:Log]]
-               return Linker::linkKnown(
+               return MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
                        SpecialPage::getTitleFor( 'Log' ),
-                       $this->msg( 'viewpagelogs' )->escaped(),
+                       $this->msg( 'viewpagelogs' )->text(),
                        [],
                        [ 'page' => $this->getTitle()->getPrefixedText() ]
                );
@@ -734,9 +736,9 @@ class HistoryPager extends ReverseChronologicalPager {
                                $undoTooltip = $latest
                                        ? [ 'title' => $this->msg( 'tooltip-undo' )->text() ]
                                        : [];
-                               $undolink = Linker::linkKnown(
+                               $undolink = MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
                                        $this->getTitle(),
-                                       $this->msg( 'editundo' )->escaped(),
+                                       $this->msg( 'editundo' )->text(),
                                        $undoTooltip,
                                        [
                                                'action' => 'edit',
@@ -788,16 +790,15 @@ class HistoryPager extends ReverseChronologicalPager {
         */
        function revLink( $rev ) {
                $date = $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $this->getUser() );
-               $date = htmlspecialchars( $date );
                if ( $rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
-                       $link = Linker::linkKnown(
+                       $link = MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
                                $this->getTitle(),
                                $date,
                                [ 'class' => 'mw-changeslist-date' ],
                                [ 'oldid' => $rev->getId() ]
                        );
                } else {
-                       $link = $date;
+                       $link = htmlspecialchars( $date );
                }
                if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
                        $link = "<span class=\"history-deleted\">$link</span>";
@@ -818,7 +819,7 @@ class HistoryPager extends ReverseChronologicalPager {
                if ( $latest || !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
                        return $cur;
                } else {
-                       return Linker::linkKnown(
+                       return MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
                                $this->getTitle(),
                                $cur,
                                [],
@@ -847,9 +848,10 @@ class HistoryPager extends ReverseChronologicalPager {
                        return $last;
                }
 
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( $next === 'unknown' ) {
                        # Next row probably exists but is unknown, use an oldid=prev link
-                       return Linker::linkKnown(
+                       return $linkRenderer->makeKnownLink(
                                $this->getTitle(),
                                $last,
                                [],
@@ -868,7 +870,7 @@ class HistoryPager extends ReverseChronologicalPager {
                        return $last;
                }
 
-               return Linker::linkKnown(
+               return $linkRenderer->makeKnownLink(
                        $this->getTitle(),
                        $last,
                        [],
index be3be85..49b9ab7 100644 (file)
@@ -230,11 +230,11 @@ class InfoAction extends FormlessAction {
                if ( $title->isRedirect() ) {
                        $pageInfo['header-basic'][] = [
                                $this->msg( 'pageinfo-redirectsto' ),
-                               Linker::link( $this->page->getRedirectTarget() ) .
+                               $linkRenderer->makeLink( $this->page->getRedirectTarget() ) .
                                $this->msg( 'word-separator' )->escaped() .
-                               $this->msg( 'parentheses' )->rawParams( Linker::link(
+                               $this->msg( 'parentheses' )->rawParams( $linkRenderer->makeLink(
                                        $this->page->getRedirectTarget(),
-                                       $this->msg( 'pageinfo-redirectsto-info' )->escaped(),
+                                       $this->msg( 'pageinfo-redirectsto-info' )->text(),
                                        [],
                                        [ 'action' => 'info' ]
                                ) )->escaped()
@@ -266,9 +266,9 @@ class InfoAction extends FormlessAction {
                ) {
                        // Link to Special:PageLanguage with pre-filled page title if user has permissions
                        $titleObj = SpecialPage::getTitleFor( 'PageLanguage', $title->getPrefixedText() );
-                       $langDisp = Linker::link(
+                       $langDisp = $linkRenderer->makeLink(
                                $titleObj,
-                               $this->msg( 'pageinfo-language' )->escaped()
+                               $this->msg( 'pageinfo-language' )->text()
                        );
                } else {
                        // Display just the message
@@ -360,9 +360,9 @@ class InfoAction extends FormlessAction {
                // Redirects to this page
                $whatLinksHere = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() );
                $pageInfo['header-basic'][] = [
-                       Linker::link(
+                       $linkRenderer->makeLink(
                                $whatLinksHere,
-                               $this->msg( 'pageinfo-redirects-name' )->escaped(),
+                               $this->msg( 'pageinfo-redirects-name' )->text(),
                                [],
                                [
                                        'hidelinks' => 1,
@@ -436,7 +436,7 @@ class InfoAction extends FormlessAction {
 
                        foreach ( $sources as $sourceTitle ) {
                                $cascadingFrom .= Html::rawElement(
-                                       'li', [], Linker::linkKnown( $sourceTitle ) );
+                                       'li', [], $linkRenderer->makeKnownLink( $sourceTitle ) );
                        }
 
                        $cascadingFrom = Html::rawElement( 'ul', [], $cascadingFrom );
@@ -525,9 +525,9 @@ class InfoAction extends FormlessAction {
                        // Date of page creation
                        $pageInfo['header-edits'][] = [
                                $this->msg( 'pageinfo-firsttime' ),
-                               Linker::linkKnown(
+                               $linkRenderer->makeKnownLink(
                                        $title,
-                                       htmlspecialchars( $lang->userTimeAndDate( $firstRev->getTimestamp(), $user ) ),
+                                       $lang->userTimeAndDate( $firstRev->getTimestamp(), $user ),
                                        [],
                                        [ 'oldid' => $firstRev->getId() ]
                                )
@@ -544,11 +544,9 @@ class InfoAction extends FormlessAction {
                        // Date of latest edit
                        $pageInfo['header-edits'][] = [
                                $this->msg( 'pageinfo-lasttime' ),
-                               Linker::linkKnown(
+                               $linkRenderer->makeKnownLink(
                                        $title,
-                                       htmlspecialchars(
-                                               $lang->userTimeAndDate( $this->page->getTimestamp(), $user )
-                                       ),
+                                       $lang->userTimeAndDate( $this->page->getTimestamp(), $user ),
                                        [],
                                        [ 'oldid' => $this->page->getLatest() ]
                                )
@@ -655,9 +653,9 @@ class InfoAction extends FormlessAction {
 
                        if ( !$config->get( 'MiserMode' ) && $pageCounts['transclusion']['to'] > 0 ) {
                                if ( $pageCounts['transclusion']['to'] > count( $transcludedTargets ) ) {
-                                       $more = Linker::link(
+                                       $more = $linkRenderer->makeLink(
                                                $whatLinksHere,
-                                               $this->msg( 'moredotdotdot' )->escaped(),
+                                               $this->msg( 'moredotdotdot' )->text(),
                                                [],
                                                [ 'hidelinks' => 1, 'hideredirs' => 1 ]
                                        );
@@ -836,6 +834,7 @@ class InfoAction extends FormlessAction {
                $real_names = [];
                $user_names = [];
                $anon_ips = [];
+               $linkRenderer = MediaWikiServices::getLinkRenderer();
 
                # Sift for real versus user names
                /** @var $user User */
@@ -846,11 +845,11 @@ class InfoAction extends FormlessAction {
 
                        $hiddenPrefs = $this->context->getConfig()->get( 'HiddenPrefs' );
                        if ( $user->getId() == 0 ) {
-                               $anon_ips[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
+                               $anon_ips[] = $linkRenderer->makeLink( $page, $user->getName() );
                        } elseif ( !in_array( 'realname', $hiddenPrefs ) && $user->getRealName() ) {
-                               $real_names[] = Linker::link( $page, htmlspecialchars( $user->getRealName() ) );
+                               $real_names[] = $linkRenderer->makeLink( $page, $user->getRealName() );
                        } else {
-                               $user_names[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
+                               $user_names[] = $linkRenderer->makeLink( $page, $user->getName() );
                        }
                }
 
index 8df6044..611e683 100644 (file)
@@ -20,6 +20,8 @@
  * @ingroup Actions
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * Mark a revision as patrolled on a page
  *
@@ -56,6 +58,7 @@ class MarkpatrolledAction extends FormAction {
        protected function preText() {
                $rc = $this->getRecentChange();
                $title = $rc->getTitle();
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
 
                // Based on logentry-patrol-patrol (see PatrolLogFormatter)
                $revId = $rc->getAttribute( 'rc_this_oldid' );
@@ -64,8 +67,8 @@ class MarkpatrolledAction extends FormAction {
                        'diff' => $revId,
                        'oldid' => $rc->getAttribute( 'rc_last_oldid' )
                ];
-               $revlink = Linker::link( $title, htmlspecialchars( $revId ), [], $query );
-               $pagelink = Linker::link( $title, htmlspecialchars( $title->getPrefixedText() ) );
+               $revlink = $linkRenderer->makeLink( $title, $revId, [], $query );
+               $pagelink = $linkRenderer->makeLink( $title, $title->getPrefixedText() );
 
                return $this->msg( 'confirm-markpatrolled-top' )->params(
                        $title->getPrefixedText(),
diff --git a/includes/actions/RevisiondeleteAction.php b/includes/actions/RevisiondeleteAction.php
deleted file mode 100644 (file)
index 7df42b3..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-/**
- * An action that just pass the request to Special:RevisionDelete
- *
- * Copyright © 2011 Alexandre Emsenhuber
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- *
- * @file
- * @ingroup Actions
- * @author Alexandre Emsenhuber
- */
-
-/**
- * An action that just pass the request to Special:RevisionDelete
- *
- * @ingroup Actions
- * @deprecated since 1.25 This class has been replaced by SpecialPageAction, but
- * you really shouldn't have been using it outside core in the first place
- */
-class RevisiondeleteAction extends FormlessAction {
-       public function __construct( Page $page, IContextSource $context = null ) {
-               wfDeprecated( 'RevisiondeleteAction class', '1.25' );
-               parent::__construct( $page, $context );
-       }
-
-       public function getName() {
-               return 'revisiondelete';
-       }
-
-       public function requiresUnblock() {
-               return false;
-       }
-
-       public function getDescription() {
-               return '';
-       }
-
-       public function onView() {
-               return '';
-       }
-
-       public function show() {
-               $special = SpecialPageFactory::getPage( 'Revisiondelete' );
-               $special->setContext( $this->getContext() );
-               $special->getContext()->setTitle( $special->getPageTitle() );
-               $special->run( '' );
-       }
-
-       public function doesWrites() {
-               return true;
-       }
-}
index 4a7f623..0ba964f 100644 (file)
@@ -26,7 +26,7 @@
 /**
  * An action that views article content
  *
- * This is a wrapper that will call Article::render().
+ * This is a wrapper that will call Article::view().
  *
  * @ingroup Actions
  */
index 2511e3b..5d12590 100644 (file)
@@ -56,8 +56,8 @@ class ApiAMCreateAccount extends ApiBase {
                        $bits = wfParseUrl( $params['returnurl'] );
                        if ( !$bits || $bits['scheme'] === '' ) {
                                $encParamName = $this->encodeParamName( 'returnurl' );
-                               $this->dieUsage(
-                                       "Invalid value '{$params['returnurl']}' for url parameter $encParamName",
+                               $this->dieWithError(
+                                       [ 'apierror-badurl', $encParamName, wfEscapeWikiText( $params['returnurl'] ) ],
                                        "badurl_{$encParamName}"
                                );
                        }
index 6fafebf..5327d7a 100644 (file)
@@ -93,7 +93,7 @@ class ApiAuthManagerHelper {
        /**
         * Call $manager->securitySensitiveOperationStatus()
         * @param string $operation Operation being checked.
-        * @throws UsageException
+        * @throws ApiUsageException
         */
        public function securitySensitiveOperation( $operation ) {
                $status = AuthManager::singleton()->securitySensitiveOperationStatus( $operation );
@@ -102,14 +102,10 @@ class ApiAuthManagerHelper {
                                return;
 
                        case AuthManager::SEC_REAUTH:
-                               $this->module->dieUsage(
-                                       'You have not authenticated recently in this session, please reauthenticate.', 'reauthenticate'
-                               );
+                               $this->module->dieWithError( 'apierror-reauthenticate' );
 
                        case AuthManager::SEC_FAIL:
-                               $this->module->dieUsage(
-                                       'This action is not available as your identify cannot be verified.', 'cannotreauthenticate'
-                               );
+                               $this->module->dieWithError( 'apierror-cannotreauthenticate' );
 
                        default:
                                throw new UnexpectedValueException( "Unknown status \"$status\"" );
index 506ff73..a40593f 100644 (file)
@@ -67,7 +67,8 @@ abstract class ApiBase extends ContextSource {
         * - limit: An integer or the string 'max'. Default lower limit is 0 (but
         *   see PARAM_MIN), and requires that PARAM_MAX and PARAM_MAX2 be
         *   specified. Cannot be used with PARAM_ISMULTI.
-        * - namespace: An integer representing a MediaWiki namespace.
+        * - namespace: An integer representing a MediaWiki namespace. Forces PARAM_ALL = true to
+        *   support easily specifying all namespaces.
         * - NULL: Any string.
         * - password: Any non-empty string. Input value is private or sensitive.
         *   <input type="password"> would be an appropriate HTML form field.
@@ -171,8 +172,18 @@ abstract class ApiBase extends ContextSource {
         */
        const PARAM_SUBMODULE_PARAM_PREFIX = 16;
 
+       /**
+        * (boolean|string) When PARAM_TYPE has a defined set of values and PARAM_ISMULTI is true,
+        * this allows for an asterisk ('*') to be passed in place of a pipe-separated list of
+        * every possible value. If a string is set, it will be used in place of the asterisk.
+        * @since 1.29
+        */
+       const PARAM_ALL = 17;
+
        /**@}*/
 
+       const ALL_DEFAULT_STRING = '*';
+
        /** Fast query, standard limit. */
        const LIMIT_BIG1 = 500;
        /** Fast query, apihighlimits limit. */
@@ -534,7 +545,7 @@ abstract class ApiBase extends ContextSource {
         * @since 1.25
         * @param string $path
         * @return ApiBase|null
-        * @throws UsageException
+        * @throws ApiUsageException
         */
        public function getModuleFromPath( $path ) {
                $module = $this->getMain();
@@ -554,14 +565,14 @@ abstract class ApiBase extends ContextSource {
                        $manager = $parent->getModuleManager();
                        if ( $manager === null ) {
                                $errorPath = implode( '+', array_slice( $parts, 0, $i ) );
-                               $this->dieUsage( "The module \"$errorPath\" has no submodules", 'badmodule' );
+                               $this->dieWithError( [ 'apierror-badmodule-nosubmodules', $errorPath ], 'badmodule' );
                        }
                        $module = $manager->getModule( $parts[$i] );
 
                        if ( $module === null ) {
                                $errorPath = $i ? implode( '+', array_slice( $parts, 0, $i ) ) : $parent->getModuleName();
-                               $this->dieUsage(
-                                       "The module \"$errorPath\" does not have a submodule \"{$parts[$i]}\"",
+                               $this->dieWithError(
+                                       [ 'apierror-badmodule-badsubmodule', $errorPath, wfEscapeWikiText( $parts[$i] ) ],
                                        'badmodule'
                                );
                        }
@@ -659,11 +670,18 @@ abstract class ApiBase extends ContextSource {
        /**
         * This method mangles parameter name based on the prefix supplied to the constructor.
         * Override this method to change parameter name during runtime
-        * @param string $paramName Parameter name
-        * @return string Prefixed parameter name
+        * @param string|string[] $paramName Parameter name
+        * @return string|string[] Prefixed parameter name
+        * @since 1.29 accepts an array of strings
         */
        public function encodeParamName( $paramName ) {
-               return $this->mModulePrefix . $paramName;
+               if ( is_array( $paramName ) ) {
+                       return array_map( function ( $name ) {
+                               return $this->mModulePrefix . $name;
+                       }, $paramName );
+               } else {
+                       return $this->mModulePrefix . $paramName;
+               }
        }
 
        /**
@@ -714,20 +732,32 @@ abstract class ApiBase extends ContextSource {
        public function requireOnlyOneParameter( $params, $required /*...*/ ) {
                $required = func_get_args();
                array_shift( $required );
-               $p = $this->getModulePrefix();
 
                $intersection = array_intersect( array_keys( array_filter( $params,
                        [ $this, 'parameterNotEmpty' ] ) ), $required );
 
                if ( count( $intersection ) > 1 ) {
-                       $this->dieUsage(
-                               "The parameters {$p}" . implode( ", {$p}", $intersection ) . ' can not be used together',
-                               'invalidparammix' );
+                       $this->dieWithError( [
+                               'apierror-invalidparammix',
+                               Message::listParam( array_map(
+                                       function ( $p ) {
+                                               return '<var>' . $this->encodeParamName( $p ) . '</var>';
+                                       },
+                                       array_values( $intersection )
+                               ) ),
+                               count( $intersection ),
+                       ] );
                } elseif ( count( $intersection ) == 0 ) {
-                       $this->dieUsage(
-                               "One of the parameters {$p}" . implode( ", {$p}", $required ) . ' is required',
-                               'missingparam'
-                       );
+                       $this->dieWithError( [
+                               'apierror-missingparam-one-of',
+                               Message::listParam( array_map(
+                                       function ( $p ) {
+                                               return '<var>' . $this->encodeParamName( $p ) . '</var>';
+                                       },
+                                       array_values( $required )
+                               ) ),
+                               count( $required ),
+                       ], 'missingparam' );
                }
        }
 
@@ -740,16 +770,21 @@ abstract class ApiBase extends ContextSource {
        public function requireMaxOneParameter( $params, $required /*...*/ ) {
                $required = func_get_args();
                array_shift( $required );
-               $p = $this->getModulePrefix();
 
                $intersection = array_intersect( array_keys( array_filter( $params,
                        [ $this, 'parameterNotEmpty' ] ) ), $required );
 
                if ( count( $intersection ) > 1 ) {
-                       $this->dieUsage(
-                               "The parameters {$p}" . implode( ", {$p}", $intersection ) . ' can not be used together',
-                               'invalidparammix'
-                       );
+                       $this->dieWithError( [
+                               'apierror-invalidparammix',
+                               Message::listParam( array_map(
+                                       function ( $p ) {
+                                               return '<var>' . $this->encodeParamName( $p ) . '</var>';
+                                       },
+                                       array_values( $intersection )
+                               ) ),
+                               count( $intersection ),
+                       ] );
                }
        }
 
@@ -763,7 +798,6 @@ abstract class ApiBase extends ContextSource {
        public function requireAtLeastOneParameter( $params, $required /*...*/ ) {
                $required = func_get_args();
                array_shift( $required );
-               $p = $this->getModulePrefix();
 
                $intersection = array_intersect(
                        array_keys( array_filter( $params, [ $this, 'parameterNotEmpty' ] ) ),
@@ -771,8 +805,16 @@ abstract class ApiBase extends ContextSource {
                );
 
                if ( count( $intersection ) == 0 ) {
-                       $this->dieUsage( "At least one of the parameters {$p}" .
-                               implode( ", {$p}", $required ) . ' is required', "{$p}missingparam" );
+                       $this->dieWithError( [
+                               'apierror-missingparam-at-least-one-of',
+                               Message::listParam( array_map(
+                                       function ( $p ) {
+                                               return '<var>' . $this->encodeParamName( $p ) . '</var>';
+                                       },
+                                       array_values( $required )
+                               ) ),
+                               count( $required ),
+                       ], 'missingparam' );
                }
        }
 
@@ -801,10 +843,8 @@ abstract class ApiBase extends ContextSource {
                }
 
                if ( $badParams ) {
-                       $this->dieUsage(
-                               'The following parameters were found in the query string, but must be in the POST body: '
-                                       . join( ', ', $badParams ),
-                               'mustpostparams'
+                       $this->dieWithError(
+                               [ 'apierror-mustpostparams', join( ', ', $badParams ), count( $badParams ) ]
                        );
                }
        }
@@ -837,10 +877,10 @@ abstract class ApiBase extends ContextSource {
                if ( isset( $params['title'] ) ) {
                        $titleObj = Title::newFromText( $params['title'] );
                        if ( !$titleObj || $titleObj->isExternal() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $params['title'] ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
                        }
                        if ( !$titleObj->canExist() ) {
-                               $this->dieUsage( "Namespace doesn't allow actual pages", 'pagecannotexist' );
+                               $this->dieWithError( 'apierror-pagecannotexist' );
                        }
                        $pageObj = WikiPage::factory( $titleObj );
                        if ( $load !== false ) {
@@ -852,7 +892,7 @@ abstract class ApiBase extends ContextSource {
                        }
                        $pageObj = WikiPage::newFromID( $params['pageid'], $load );
                        if ( !$pageObj ) {
-                               $this->dieUsageMsg( [ 'nosuchpageid', $params['pageid'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchpageid', $params['pageid'] ] );
                        }
                }
 
@@ -920,6 +960,7 @@ abstract class ApiBase extends ContextSource {
                        $dupes = false;
                        $deprecated = false;
                        $required = false;
+                       $allowAll = false;
                } else {
                        $default = isset( $paramSettings[self::PARAM_DFLT] )
                                ? $paramSettings[self::PARAM_DFLT]
@@ -939,6 +980,9 @@ abstract class ApiBase extends ContextSource {
                        $required = isset( $paramSettings[self::PARAM_REQUIRED] )
                                ? $paramSettings[self::PARAM_REQUIRED]
                                : false;
+                       $allowAll = isset( $paramSettings[self::PARAM_ALL] )
+                               ? $paramSettings[self::PARAM_ALL]
+                               : false;
 
                        // When type is not given, and no choices, the type is the same as $default
                        if ( !isset( $type ) ) {
@@ -979,10 +1023,8 @@ abstract class ApiBase extends ContextSource {
                                // accidentally uploaded as a field fails spectacularly)
                                $value = $this->getMain()->getRequest()->unsetVal( $encParamName );
                                if ( $value !== null ) {
-                                       $this->dieUsage(
-                                               "File upload param $encParamName is not a file upload; " .
-                                                       'be sure to use multipart/form-data for your POST and include ' .
-                                                       'a filename in the Content-Disposition header.',
+                                       $this->dieWithError(
+                                               [ 'apierror-badupload', $encParamName ],
                                                "badupload_{$encParamName}"
                                        );
                                }
@@ -992,6 +1034,9 @@ abstract class ApiBase extends ContextSource {
 
                        if ( isset( $value ) && $type == 'namespace' ) {
                                $type = MWNamespace::getValidNamespaces();
+                               // By default, namespace parameters allow ALL_DEFAULT_STRING to be used to specify
+                               // all namespaces.
+                               $allowAll = true;
                        }
                        if ( isset( $value ) && $type == 'submodule' ) {
                                if ( isset( $paramSettings[self::PARAM_SUBMODULE_MAP] ) ) {
@@ -1014,10 +1059,7 @@ abstract class ApiBase extends ContextSource {
                                        // done by WebRequest for $_GET. Let's call that a feature.
                                        $value = join( "\x1f", $request->normalizeUnicode( explode( "\x1f", $rawValue ) ) );
                                } else {
-                                       $this->dieUsage(
-                                               "U+001F multi-value separation may only be used for multi-valued parameters.",
-                                               'badvalue_notmultivalue'
-                                       );
+                                       $this->dieWithError( 'apierror-badvalue-notmultivalue', 'badvalue_notmultivalue' );
                                }
                        }
 
@@ -1027,12 +1069,19 @@ abstract class ApiBase extends ContextSource {
                        }
                }
 
+               $allSpecifier = ( is_string( $allowAll ) ? $allowAll : self::ALL_DEFAULT_STRING );
+               if ( $allowAll && $multi && is_array( $type ) && in_array( $allSpecifier, $type, true ) ) {
+                       ApiBase::dieDebug(
+                               __METHOD__,
+                               "For param $encParamName, PARAM_ALL collides with a possible value" );
+               }
                if ( isset( $value ) && ( $multi || is_array( $type ) ) ) {
                        $value = $this->parseMultiValue(
                                $encParamName,
                                $value,
                                $multi,
-                               is_array( $type ) ? $type : null
+                               is_array( $type ) ? $type : null,
+                               $allowAll ? $allSpecifier : null
                        );
                }
 
@@ -1047,7 +1096,7 @@ abstract class ApiBase extends ContextSource {
                                        case 'text':
                                        case 'password':
                                                if ( $required && $value === '' ) {
-                                                       $this->dieUsageMsg( [ 'missingparam', $paramName ] );
+                                                       $this->dieWithError( [ 'apierror-missingparam', $paramName ] );
                                                }
                                                break;
                                        case 'integer': // Force everything using intval() and optionally validate limits
@@ -1150,8 +1199,6 @@ abstract class ApiBase extends ContextSource {
 
                        // Set a warning if a deprecated parameter has been passed
                        if ( $deprecated && $value !== false ) {
-                               $this->setWarning( "The $encParamName parameter has been deprecated." );
-
                                $feature = $encParamName;
                                $m = $this;
                                while ( !$m->isMain() ) {
@@ -1161,10 +1208,10 @@ abstract class ApiBase extends ContextSource {
                                        $feature = "{$param}={$name}&{$feature}";
                                        $m = $p;
                                }
-                               $this->logFeatureUsage( $feature );
+                               $this->addDeprecation( [ 'apiwarn-deprecation-parameter', $encParamName ], $feature );
                        }
                } elseif ( $required ) {
-                       $this->dieUsageMsg( [ 'missingparam', $paramName ] );
+                       $this->dieWithError( [ 'apierror-missingparam', $paramName ] );
                }
 
                return $value;
@@ -1179,11 +1226,7 @@ abstract class ApiBase extends ContextSource {
         */
        protected function handleParamNormalization( $paramName, $value, $rawValue ) {
                $encParamName = $this->encodeParamName( $paramName );
-               $this->setWarning(
-                       "The value passed for '$encParamName' contains invalid or non-normalized data. "
-                       . 'Textual data should be valid, NFC-normalized Unicode without '
-                       . 'C0 control characters other than HT (\\t), LF (\\n), and CR (\\r).'
-               );
+               $this->addWarning( [ 'apiwarn-badutf8', $encParamName ] );
        }
 
        /**
@@ -1215,9 +1258,13 @@ abstract class ApiBase extends ContextSource {
         *  separated by '|'?
         * @param string[]|null $allowedValues An array of values to check against. If
         *  null, all values are accepted.
+        * @param string|null $allSpecifier String to use to specify all allowed values, or null
+        *  if this behavior should not be allowed
         * @return string|string[] (allowMultiple ? an_array_of_values : a_single_value)
         */
-       protected function parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues ) {
+       protected function parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues,
+               $allSpecifier = null
+       ) {
                if ( ( trim( $value ) === '' || trim( $value ) === "\x1f" ) && $allowMultiple ) {
                        return [];
                }
@@ -1229,10 +1276,17 @@ abstract class ApiBase extends ContextSource {
                        ? self::LIMIT_SML2
                        : self::LIMIT_SML1;
 
+               if ( $allowMultiple && is_array( $allowedValues ) && $allSpecifier &&
+                       count( $valuesList ) === 1 && $valuesList[0] === $allSpecifier
+               ) {
+                       return $allowedValues;
+               }
+
                if ( self::truncateArray( $valuesList, $sizeLimit ) ) {
-                       $this->logFeatureUsage( "too-many-$valueName-for-{$this->getModulePath()}" );
-                       $this->setWarning( "Too many values supplied for parameter '$valueName': " .
-                               "the limit is $sizeLimit" );
+                       $this->addDeprecation(
+                               [ 'apiwarn-toomanyvalues', $valueName, $sizeLimit ],
+                               "too-many-$valueName-for-{$this->getModulePath()}"
+                       );
                }
 
                if ( !$allowMultiple && count( $valuesList ) != 1 ) {
@@ -1241,26 +1295,38 @@ abstract class ApiBase extends ContextSource {
                                return $value;
                        }
 
-                       $possibleValues = is_array( $allowedValues )
-                               ? "of '" . implode( "', '", $allowedValues ) . "'"
-                               : '';
-                       $this->dieUsage(
-                               "Only one $possibleValues is allowed for parameter '$valueName'",
-                               "multival_$valueName"
-                       );
+                       if ( is_array( $allowedValues ) ) {
+                               $values = array_map( function ( $v ) {
+                                       return '<kbd>' . wfEscapeWikiText( $v ) . '</kbd>';
+                               }, $allowedValues );
+                               $this->dieWithError( [
+                                       'apierror-multival-only-one-of',
+                                       $valueName,
+                                       Message::listParam( $values ),
+                                       count( $values ),
+                               ], "multival_$valueName" );
+                       } else {
+                               $this->dieWithError( [
+                                       'apierror-multival-only-one',
+                                       $valueName,
+                               ], "multival_$valueName" );
+                       }
                }
 
                if ( is_array( $allowedValues ) ) {
                        // Check for unknown values
-                       $unknown = array_diff( $valuesList, $allowedValues );
+                       $unknown = array_map( 'wfEscapeWikiText', array_diff( $valuesList, $allowedValues ) );
                        if ( count( $unknown ) ) {
                                if ( $allowMultiple ) {
-                                       $s = count( $unknown ) > 1 ? 's' : '';
-                                       $vals = implode( ', ', $unknown );
-                                       $this->setWarning( "Unrecognized value$s for parameter '$valueName': $vals" );
+                                       $this->addWarning( [
+                                               'apiwarn-unrecognizedvalues',
+                                               $valueName,
+                                               Message::listParam( $unknown, 'comma' ),
+                                               count( $unknown ),
+                                       ] );
                                } else {
-                                       $this->dieUsage(
-                                               "Unrecognized value for parameter '$valueName': {$valuesList[0]}",
+                                       $this->dieWithError(
+                                               [ 'apierror-unrecognizedvalue', $valueName, wfEscapeWikiText( $valuesList[0] ) ],
                                                "unknown_$valueName"
                                        );
                                }
@@ -1286,7 +1352,12 @@ abstract class ApiBase extends ContextSource {
                $enforceLimits = false
        ) {
                if ( !is_null( $min ) && $value < $min ) {
-                       $msg = $this->encodeParamName( $paramName ) . " may not be less than $min (set to $value)";
+                       $msg = ApiMessage::create(
+                               [ 'apierror-integeroutofrange-belowminimum',
+                                       $this->encodeParamName( $paramName ), $min, $value ],
+                               'integeroutofrange',
+                               [ 'min' => $min, 'max' => $max, 'botMax' => $botMax ?: $max ]
+                       );
                        $this->warnOrDie( $msg, $enforceLimits );
                        $value = $min;
                }
@@ -1302,13 +1373,22 @@ abstract class ApiBase extends ContextSource {
                if ( !is_null( $max ) && $value > $max ) {
                        if ( !is_null( $botMax ) && $this->getMain()->canApiHighLimits() ) {
                                if ( $value > $botMax ) {
-                                       $msg = $this->encodeParamName( $paramName ) .
-                                               " may not be over $botMax (set to $value) for bots or sysops";
+                                       $msg = ApiMessage::create(
+                                               [ 'apierror-integeroutofrange-abovebotmax',
+                                                       $this->encodeParamName( $paramName ), $botMax, $value ],
+                                               'integeroutofrange',
+                                               [ 'min' => $min, 'max' => $max, 'botMax' => $botMax ?: $max ]
+                                       );
                                        $this->warnOrDie( $msg, $enforceLimits );
                                        $value = $botMax;
                                }
                        } else {
-                               $msg = $this->encodeParamName( $paramName ) . " may not be over $max (set to $value) for users";
+                               $msg = ApiMessage::create(
+                                       [ 'apierror-integeroutofrange-abovemax',
+                                               $this->encodeParamName( $paramName ), $max, $value ],
+                                       'integeroutofrange',
+                                       [ 'min' => $min, 'max' => $max, 'botMax' => $botMax ?: $max ]
+                               );
                                $this->warnOrDie( $msg, $enforceLimits );
                                $value = $max;
                        }
@@ -1326,11 +1406,9 @@ abstract class ApiBase extends ContextSource {
                // (wfTimestamp() also accepts various non-strings and the string of 14
                // ASCII NUL bytes, but those can't get here)
                if ( !$value ) {
-                       $this->logFeatureUsage( 'unclear-"now"-timestamp' );
-                       $this->setWarning(
-                               "Passing '$value' for timestamp parameter $encParamName has been deprecated." .
-                                       ' If for some reason you need to explicitly specify the current time without' .
-                                       ' calculating it client-side, use "now".'
+                       $this->addDeprecation(
+                               [ 'apiwarn-unclearnowtimestamp', $encParamName, wfEscapeWikiText( $value ) ],
+                               'unclear-"now"-timestamp'
                        );
                        return wfTimestamp( TS_MW );
                }
@@ -1342,8 +1420,8 @@ abstract class ApiBase extends ContextSource {
 
                $unixTimestamp = wfTimestamp( TS_UNIX, $value );
                if ( $unixTimestamp === false ) {
-                       $this->dieUsage(
-                               "Invalid value '$value' for timestamp parameter $encParamName",
+                       $this->dieWithError(
+                               [ 'apierror-badtimestamp', $encParamName, wfEscapeWikiText( $value ) ],
                                "badtimestamp_{$encParamName}"
                        );
                }
@@ -1398,8 +1476,8 @@ abstract class ApiBase extends ContextSource {
        private function validateUser( $value, $encParamName ) {
                $title = Title::makeTitleSafe( NS_USER, $value );
                if ( $title === null || $title->hasFragment() ) {
-                       $this->dieUsage(
-                               "Invalid value '$value' for user parameter $encParamName",
+                       $this->dieWithError(
+                               [ 'apierror-baduser', $encParamName, wfEscapeWikiText( $value ) ],
                                "baduser_{$encParamName}"
                        );
                }
@@ -1455,22 +1533,19 @@ abstract class ApiBase extends ContextSource {
                if ( !is_null( $params['owner'] ) && !is_null( $params['token'] ) ) {
                        $user = User::newFromName( $params['owner'], false );
                        if ( !( $user && $user->getId() ) ) {
-                               $this->dieUsage( 'Specified user does not exist', 'bad_wlowner' );
+                               $this->dieWithError(
+                                       [ 'nosuchusershort', wfEscapeWikiText( $params['owner'] ) ], 'bad_wlowner'
+                               );
                        }
                        $token = $user->getOption( 'watchlisttoken' );
                        if ( $token == '' || !hash_equals( $token, $params['token'] ) ) {
-                               $this->dieUsage(
-                                       'Incorrect watchlist token provided -- please set a correct token in Special:Preferences',
-                                       'bad_wltoken'
-                               );
+                               $this->dieWithError( 'apierror-bad-watchlist-token', 'bad_wltoken' );
                        }
                } else {
                        if ( !$this->getUser()->isLoggedIn() ) {
-                               $this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' );
-                       }
-                       if ( !$this->getUser()->isAllowed( 'viewmywatchlist' ) ) {
-                               $this->dieUsage( 'You don\'t have permission to view your watchlist', 'permissiondenied' );
+                               $this->dieWithError( 'watchlistanontext', 'notloggedin' );
                        }
+                       $this->checkUserRightsAny( 'viewmywatchlist' );
                        $user = $this->getUser();
                }
 
@@ -1526,6 +1601,39 @@ abstract class ApiBase extends ContextSource {
                return $msg;
        }
 
+       /**
+        * Turn an array of message keys or key+param arrays into a Status
+        * @since 1.29
+        * @param array $errors
+        * @param User|null $user
+        * @return Status
+        */
+       public function errorArrayToStatus( array $errors, User $user = null ) {
+               if ( $user === null ) {
+                       $user = $this->getUser();
+               }
+
+               $status = Status::newGood();
+               foreach ( $errors as $error ) {
+                       if ( is_array( $error ) && $error[0] === 'blockedtext' && $user->getBlock() ) {
+                               $status->fatal( ApiMessage::create(
+                                       'apierror-blocked',
+                                       'blocked',
+                                       [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
+                               ) );
+                       } elseif ( is_array( $error ) && $error[0] === 'autoblockedtext' && $user->getBlock() ) {
+                               $status->fatal( ApiMessage::create(
+                                       'apierror-autoblocked',
+                                       'autoblocked',
+                                       [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
+                               ) );
+                       } else {
+                               call_user_func_array( [ $status, 'fatal' ], (array)$error );
+                       }
+               }
+               return $status;
+       }
+
        /**@}*/
 
        /************************************************************************//**
@@ -1534,745 +1642,227 @@ abstract class ApiBase extends ContextSource {
         */
 
        /**
-        * Set warning section for this module. Users should monitor this
-        * section to notice any changes in API. Multiple calls to this
-        * function will result in the warning messages being separated by
-        * newlines
-        * @param string $warning Warning message
+        * Add a warning for this module.
+        *
+        * Users should monitor this section to notice any changes in API. Multiple
+        * calls to this function will result in multiple warning messages.
+        *
+        * If $msg is not an ApiMessage, the message code will be derived from the
+        * message key by stripping any "apiwarn-" or "apierror-" prefix.
+        *
+        * @since 1.29
+        * @param string|array|Message $msg See ApiErrorFormatter::addWarning()
+        * @param string|null $code See ApiErrorFormatter::addWarning()
+        * @param array|null $data See ApiErrorFormatter::addWarning()
         */
-       public function setWarning( $warning ) {
-               $msg = new ApiRawMessage( $warning, 'warning' );
-               $this->getErrorFormatter()->addWarning( $this->getModuleName(), $msg );
+       public function addWarning( $msg, $code = null, $data = null ) {
+               $this->getErrorFormatter()->addWarning( $this->getModulePath(), $msg, $code, $data );
        }
 
        /**
-        * Adds a warning to the output, else dies
+        * Add a deprecation warning for this module.
         *
-        * @param string $msg Message to show as a warning, or error message if dying
-        * @param bool $enforceLimits Whether this is an enforce (die)
+        * A combination of $this->addWarning() and $this->logFeatureUsage()
+        *
+        * @since 1.29
+        * @param string|array|Message $msg See ApiErrorFormatter::addWarning()
+        * @param string|null $feature See ApiBase::logFeatureUsage()
+        * @param array|null $data See ApiErrorFormatter::addWarning()
         */
-       private function warnOrDie( $msg, $enforceLimits = false ) {
-               if ( $enforceLimits ) {
-                       $this->dieUsage( $msg, 'integeroutofrange' );
+       public function addDeprecation( $msg, $feature, $data = [] ) {
+               $data = (array)$data;
+               if ( $feature !== null ) {
+                       $data['feature'] = $feature;
+                       $this->logFeatureUsage( $feature );
                }
+               $this->addWarning( $msg, 'deprecation', $data );
+       }
 
-               $this->setWarning( $msg );
+       /**
+        * Add an error for this module without aborting
+        *
+        * If $msg is not an ApiMessage, the message code will be derived from the
+        * message key by stripping any "apiwarn-" or "apierror-" prefix.
+        *
+        * @note If you want to abort processing, use self::dieWithError() instead.
+        * @since 1.29
+        * @param string|array|Message $msg See ApiErrorFormatter::addError()
+        * @param string|null $code See ApiErrorFormatter::addError()
+        * @param array|null $data See ApiErrorFormatter::addError()
+        */
+       public function addError( $msg, $code = null, $data = null ) {
+               $this->getErrorFormatter()->addError( $this->getModulePath(), $msg, $code, $data );
        }
 
        /**
-        * Throw a UsageException, which will (if uncaught) call the main module's
-        * error handler and die with an error message.
+        * Add warnings and/or errors from a Status
         *
-        * @param string $description One-line human-readable description of the
-        *   error condition, e.g., "The API requires a valid action parameter"
-        * @param string $errorCode Brief, arbitrary, stable string to allow easy
-        *   automated identification of the error, e.g., 'unknown_action'
-        * @param int $httpRespCode HTTP response code
-        * @param array|null $extradata Data to add to the "<error>" element; array in ApiResult format
-        * @throws UsageException always
+        * @note If you want to abort processing, use self::dieStatus() instead.
+        * @since 1.29
+        * @param StatusValue $status
+        * @param string[] $types 'warning' and/or 'error'
         */
-       public function dieUsage( $description, $errorCode, $httpRespCode = 0, $extradata = null ) {
-               throw new UsageException(
-                       $description,
-                       $this->encodeParamName( $errorCode ),
-                       $httpRespCode,
-                       $extradata
-               );
+       public function addMessagesFromStatus( StatusValue $status, $types = [ 'warning', 'error' ] ) {
+               $this->getErrorFormatter()->addMessagesFromStatus( $this->getModulePath(), $status, $types );
+       }
+
+       /**
+        * Abort execution with an error
+        *
+        * If $msg is not an ApiMessage, the message code will be derived from the
+        * message key by stripping any "apiwarn-" or "apierror-" prefix.
+        *
+        * @since 1.29
+        * @param string|array|Message $msg See ApiErrorFormatter::addError()
+        * @param string|null $code See ApiErrorFormatter::addError()
+        * @param array|null $data See ApiErrorFormatter::addError()
+        * @param int|null $httpCode HTTP error code to use
+        * @throws ApiUsageException always
+        */
+       public function dieWithError( $msg, $code = null, $data = null, $httpCode = null ) {
+               throw ApiUsageException::newWithMessage( $this, $msg, $code, $data, $httpCode );
        }
 
        /**
-        * Throw a UsageException, which will (if uncaught) call the main module's
+        * Adds a warning to the output, else dies
+        *
+        * @param ApiMessage $msg Message to show as a warning, or error message if dying
+        * @param bool $enforceLimits Whether this is an enforce (die)
+        */
+       private function warnOrDie( ApiMessage $msg, $enforceLimits = false ) {
+               if ( $enforceLimits ) {
+                       $this->dieWithError( $msg );
+               } else {
+                       $this->addWarning( $msg );
+               }
+       }
+
+       /**
+        * Throw an ApiUsageException, which will (if uncaught) call the main module's
         * error handler and die with an error message including block info.
         *
         * @since 1.27
-        * @param Block $block The block used to generate the UsageException
-        * @throws UsageException always
+        * @param Block $block The block used to generate the ApiUsageException
+        * @throws ApiUsageException always
         */
        public function dieBlocked( Block $block ) {
                // Die using the appropriate message depending on block type
                if ( $block->getType() == Block::TYPE_AUTO ) {
-                       $this->dieUsage(
-                               'Your IP address has been blocked automatically, because it was used by a blocked user',
+                       $this->dieWithError(
+                               'apierror-autoblocked',
                                'autoblocked',
-                               0,
                                [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $block ) ]
                        );
                } else {
-                       $this->dieUsage(
-                               'You have been blocked from editing',
+                       $this->dieWithError(
+                               'apierror-blocked',
                                'blocked',
-                               0,
                                [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $block ) ]
                        );
                }
        }
 
        /**
-        * Get error (as code, string) from a Status object.
+        * Throw an ApiUsageException based on the Status object.
         *
-        * @since 1.23
-        * @param Status $status
-        * @param array|null &$extraData Set if extra data from IApiMessage is available (since 1.27)
-        * @return array Array of code and error string
-        * @throws MWException
+        * @since 1.22
+        * @since 1.29 Accepts a StatusValue
+        * @param StatusValue $status
+        * @throws ApiUsageException always
         */
-       public function getErrorFromStatus( $status, &$extraData = null ) {
+       public function dieStatus( StatusValue $status ) {
                if ( $status->isGood() ) {
                        throw new MWException( 'Successful status passed to ApiBase::dieStatus' );
                }
 
-               $errors = $status->getErrorsByType( 'error' );
-               if ( !$errors ) {
-                       // No errors? Assume the warnings should be treated as errors
-                       $errors = $status->getErrorsByType( 'warning' );
-               }
-               if ( !$errors ) {
-                       // Still no errors? Punt
-                       $errors = [ [ 'message' => 'unknownerror-nocode', 'params' => [] ] ];
-               }
-
-               // Cannot use dieUsageMsg() because extensions might return custom
-               // error messages.
-               if ( $errors[0]['message'] instanceof Message ) {
-                       $msg = $errors[0]['message'];
-                       if ( $msg instanceof IApiMessage ) {
-                               $extraData = $msg->getApiData();
-                               $code = $msg->getApiCode();
-                       } else {
-                               $code = $msg->getKey();
-                       }
-               } else {
-                       $code = $errors[0]['message'];
-                       $msg = wfMessage( $code, $errors[0]['params'] );
-               }
-               if ( isset( ApiBase::$messageMap[$code] ) ) {
-                       // Translate message to code, for backwards compatibility
-                       $code = ApiBase::$messageMap[$code]['code'];
-               }
-
-               return [ $code, $msg->inLanguage( 'en' )->useDatabase( false )->plain() ];
+               throw new ApiUsageException( $this, $status );
        }
 
-       /**
-        * Throw a UsageException based on the errors in the Status object.
-        *
-        * @since 1.22
-        * @param Status $status
-        * @throws UsageException always
-        */
-       public function dieStatus( $status ) {
-               $extraData = null;
-               list( $code, $msg ) = $this->getErrorFromStatus( $status, $extraData );
-               $this->dieUsage( $msg, $code, 0, $extraData );
-       }
-
-       // @codingStandardsIgnoreStart Allow long lines. Cannot split these.
-       /**
-        * Array that maps message keys to error messages. $1 and friends are replaced.
-        */
-       public static $messageMap = [
-               // This one MUST be present, or dieUsageMsg() will recurse infinitely
-               'unknownerror' => [ 'code' => 'unknownerror', 'info' => "Unknown error: \"\$1\"" ],
-               'unknownerror-nocode' => [ 'code' => 'unknownerror', 'info' => 'Unknown error' ],
-
-               // Messages from Title::getUserPermissionsErrors()
-               'ns-specialprotected' => [
-                       'code' => 'unsupportednamespace',
-                       'info' => "Pages in the Special namespace can't be edited"
-               ],
-               'protectedinterface' => [
-                       'code' => 'protectednamespace-interface',
-                       'info' => "You're not allowed to edit interface messages"
-               ],
-               'namespaceprotected' => [
-                       'code' => 'protectednamespace',
-                       'info' => "You're not allowed to edit pages in the \"\$1\" namespace"
-               ],
-               'customcssprotected' => [
-                       'code' => 'customcssprotected',
-                       'info' => "You're not allowed to edit custom CSS pages"
-               ],
-               'customjsprotected' => [
-                       'code' => 'customjsprotected',
-                       'info' => "You're not allowed to edit custom JavaScript pages"
-               ],
-               'cascadeprotected' => [
-                       'code' => 'cascadeprotected',
-                       'info' => "The page you're trying to edit is protected because it's included in a cascade-protected page"
-               ],
-               'protectedpagetext' => [
-                       'code' => 'protectedpage',
-                       'info' => "The \"\$1\" right is required to edit this page"
-               ],
-               'protect-cantedit' => [
-                       'code' => 'cantedit',
-                       'info' => "You can't protect this page because you can't edit it"
-               ],
-               'deleteprotected' => [
-                       'code' => 'cantedit',
-                       'info' => "You can't delete this page because it has been protected"
-               ],
-               'badaccess-group0' => [
-                       'code' => 'permissiondenied',
-                       'info' => 'Permission denied'
-               ], // Generic permission denied message
-               'badaccess-groups' => [
-                       'code' => 'permissiondenied',
-                       'info' => 'Permission denied'
-               ],
-               'titleprotected' => [
-                       'code' => 'protectedtitle',
-                       'info' => 'This title has been protected from creation'
-               ],
-               'nocreate-loggedin' => [
-                       'code' => 'cantcreate',
-                       'info' => "You don't have permission to create new pages"
-               ],
-               'nocreatetext' => [
-                       'code' => 'cantcreate-anon',
-                       'info' => "Anonymous users can't create new pages"
-               ],
-               'movenologintext' => [
-                       'code' => 'cantmove-anon',
-                       'info' => "Anonymous users can't move pages"
-               ],
-               'movenotallowed' => [
-                       'code' => 'cantmove',
-                       'info' => "You don't have permission to move pages"
-               ],
-               'confirmedittext' => [
-                       'code' => 'confirmemail',
-                       'info' => 'You must confirm your email address before you can edit'
-               ],
-               'blockedtext' => [
-                       'code' => 'blocked',
-                       'info' => 'You have been blocked from editing'
-               ],
-               'autoblockedtext' => [
-                       'code' => 'autoblocked',
-                       'info' => 'Your IP address has been blocked automatically, because it was used by a blocked user'
-               ],
-
-               // Miscellaneous interface messages
-               'actionthrottledtext' => [
-                       'code' => 'ratelimited',
-                       'info' => "You've exceeded your rate limit. Please wait some time and try again"
-               ],
-               'alreadyrolled' => [
-                       'code' => 'alreadyrolled',
-                       'info' => 'The page you tried to rollback was already rolled back'
-               ],
-               'cantrollback' => [
-                       'code' => 'onlyauthor',
-                       'info' => 'The page you tried to rollback only has one author'
-               ],
-               'readonlytext' => [
-                       'code' => 'readonly',
-                       'info' => 'The wiki is currently in read-only mode'
-               ],
-               'sessionfailure' => [
-                       'code' => 'badtoken',
-                       'info' => 'Invalid token' ],
-               'cannotdelete' => [
-                       'code' => 'cantdelete',
-                       'info' => "Couldn't delete \"\$1\". Maybe it was deleted already by someone else"
-               ],
-               'notanarticle' => [
-                       'code' => 'missingtitle',
-                       'info' => "The page you requested doesn't exist"
-               ],
-               'selfmove' => [ 'code' => 'selfmove', 'info' => "Can't move a page to itself"
-               ],
-               'immobile_namespace' => [
-                       'code' => 'immobilenamespace',
-                       'info' => 'You tried to move pages from or to a namespace that is protected from moving'
-               ],
-               'articleexists' => [
-                       'code' => 'articleexists',
-                       'info' => 'The destination article already exists and is not a redirect to the source article'
-               ],
-               'protectedpage' => [
-                       'code' => 'protectedpage',
-                       'info' => "You don't have permission to perform this move"
-               ],
-               'hookaborted' => [
-                       'code' => 'hookaborted',
-                       'info' => 'The modification you tried to make was aborted by an extension hook'
-               ],
-               'cantmove-titleprotected' => [
-                       'code' => 'protectedtitle',
-                       'info' => 'The destination article has been protected from creation'
-               ],
-               'imagenocrossnamespace' => [
-                       'code' => 'nonfilenamespace',
-                       'info' => "Can't move a file to a non-file namespace"
-               ],
-               'imagetypemismatch' => [
-                       'code' => 'filetypemismatch',
-                       'info' => "The new file extension doesn't match its type"
-               ],
-               // 'badarticleerror' => shouldn't happen
-               // 'badtitletext' => shouldn't happen
-               'ip_range_invalid' => [ 'code' => 'invalidrange', 'info' => 'Invalid IP range' ],
-               'range_block_disabled' => [
-                       'code' => 'rangedisabled',
-                       'info' => 'Blocking IP ranges has been disabled'
-               ],
-               'nosuchusershort' => [
-                       'code' => 'nosuchuser',
-                       'info' => "The user you specified doesn't exist"
-               ],
-               'badipaddress' => [ 'code' => 'invalidip', 'info' => 'Invalid IP address specified' ],
-               'ipb_expiry_invalid' => [ 'code' => 'invalidexpiry', 'info' => 'Invalid expiry time' ],
-               'ipb_already_blocked' => [
-                       'code' => 'alreadyblocked',
-                       'info' => 'The user you tried to block was already blocked'
-               ],
-               'ipb_blocked_as_range' => [
-                       'code' => 'blockedasrange',
-                       'info' => "IP address \"\$1\" was blocked as part of range \"\$2\". You can't unblock the IP individually, but you can unblock the range as a whole."
-               ],
-               'ipb_cant_unblock' => [
-                       'code' => 'cantunblock',
-                       'info' => 'The block you specified was not found. It may have been unblocked already'
-               ],
-               'mailnologin' => [
-                       'code' => 'cantsend',
-                       'info' => 'You are not logged in, you do not have a confirmed email address, or you are not allowed to send email to other users, so you cannot send email'
-               ],
-               'ipbblocked' => [
-                       'code' => 'ipbblocked',
-                       'info' => 'You cannot block or unblock users while you are yourself blocked'
-               ],
-               'ipbnounblockself' => [
-                       'code' => 'ipbnounblockself',
-                       'info' => 'You are not allowed to unblock yourself'
-               ],
-               'usermaildisabled' => [
-                       'code' => 'usermaildisabled',
-                       'info' => 'User email has been disabled'
-               ],
-               'blockedemailuser' => [
-                       'code' => 'blockedfrommail',
-                       'info' => 'You have been blocked from sending email'
-               ],
-               'notarget' => [
-                       'code' => 'notarget',
-                       'info' => 'You have not specified a valid target for this action'
-               ],
-               'noemail' => [
-                       'code' => 'noemail',
-                       'info' => 'The user has not specified a valid email address, or has chosen not to receive email from other users'
-               ],
-               'rcpatroldisabled' => [
-                       'code' => 'patroldisabled',
-                       'info' => 'Patrolling is disabled on this wiki'
-               ],
-               'markedaspatrollederror-noautopatrol' => [
-                       'code' => 'noautopatrol',
-                       'info' => "You don't have permission to patrol your own changes"
-               ],
-               'delete-toobig' => [
-                       'code' => 'bigdelete',
-                       'info' => "You can't delete this page because it has more than \$1 revisions"
-               ],
-               'movenotallowedfile' => [
-                       'code' => 'cantmovefile',
-                       'info' => "You don't have permission to move files"
-               ],
-               'userrights-no-interwiki' => [
-                       'code' => 'nointerwikiuserrights',
-                       'info' => "You don't have permission to change user rights on other wikis"
-               ],
-               'userrights-nodatabase' => [
-                       'code' => 'nosuchdatabase',
-                       'info' => "Database \"\$1\" does not exist or is not local"
-               ],
-               'nouserspecified' => [ 'code' => 'invaliduser', 'info' => "Invalid username \"\$1\"" ],
-               'noname' => [ 'code' => 'invaliduser', 'info' => "Invalid username \"\$1\"" ],
-               'summaryrequired' => [ 'code' => 'summaryrequired', 'info' => 'Summary required' ],
-               'import-rootpage-invalid' => [
-                       'code' => 'import-rootpage-invalid',
-                       'info' => 'Root page is an invalid title'
-               ],
-               'import-rootpage-nosubpage' => [
-                       'code' => 'import-rootpage-nosubpage',
-                       'info' => 'Namespace "$1" of the root page does not allow subpages'
-               ],
-
-               // API-specific messages
-               'readrequired' => [
-                       'code' => 'readapidenied',
-                       'info' => 'You need read permission to use this module'
-               ],
-               'writedisabled' => [
-                       'code' => 'noapiwrite',
-                       'info' => "Editing of this wiki through the API is disabled. Make sure the \$wgEnableWriteAPI=true; statement is included in the wiki's LocalSettings.php file"
-               ],
-               'writerequired' => [
-                       'code' => 'writeapidenied',
-                       'info' => "You're not allowed to edit this wiki through the API"
-               ],
-               'missingparam' => [ 'code' => 'no$1', 'info' => "The \$1 parameter must be set" ],
-               'invalidtitle' => [ 'code' => 'invalidtitle', 'info' => "Bad title \"\$1\"" ],
-               'nosuchpageid' => [ 'code' => 'nosuchpageid', 'info' => "There is no page with ID \$1" ],
-               'nosuchrevid' => [ 'code' => 'nosuchrevid', 'info' => "There is no revision with ID \$1" ],
-               'nosuchuser' => [ 'code' => 'nosuchuser', 'info' => "User \"\$1\" doesn't exist" ],
-               'invaliduser' => [ 'code' => 'invaliduser', 'info' => "Invalid username \"\$1\"" ],
-               'invalidexpiry' => [ 'code' => 'invalidexpiry', 'info' => "Invalid expiry time \"\$1\"" ],
-               'pastexpiry' => [ 'code' => 'pastexpiry', 'info' => "Expiry time \"\$1\" is in the past" ],
-               'create-titleexists' => [
-                       'code' => 'create-titleexists',
-                       'info' => "Existing titles can't be protected with 'create'"
-               ],
-               'missingtitle-createonly' => [
-                       'code' => 'missingtitle-createonly',
-                       'info' => "Missing titles can only be protected with 'create'"
-               ],
-               'cantblock' => [ 'code' => 'cantblock',
-                       'info' => "You don't have permission to block users"
-               ],
-               'canthide' => [
-                       'code' => 'canthide',
-                       'info' => "You don't have permission to hide user names from the block log"
-               ],
-               'cantblock-email' => [
-                       'code' => 'cantblock-email',
-                       'info' => "You don't have permission to block users from sending email through the wiki"
-               ],
-               'unblock-notarget' => [
-                       'code' => 'notarget',
-                       'info' => 'Either the id or the user parameter must be set'
-               ],
-               'unblock-idanduser' => [
-                       'code' => 'idanduser',
-                       'info' => "The id and user parameters can't be used together"
-               ],
-               'cantunblock' => [
-                       'code' => 'permissiondenied',
-                       'info' => "You don't have permission to unblock users"
-               ],
-               'cannotundelete' => [
-                       'code' => 'cantundelete',
-                       'info' => "Couldn't undelete: the requested revisions may not exist, or may have been undeleted already"
-               ],
-               'permdenied-undelete' => [
-                       'code' => 'permissiondenied',
-                       'info' => "You don't have permission to restore deleted revisions"
-               ],
-               'createonly-exists' => [
-                       'code' => 'articleexists',
-                       'info' => 'The article you tried to create has been created already'
-               ],
-               'nocreate-missing' => [
-                       'code' => 'missingtitle',
-                       'info' => "The article you tried to edit doesn't exist"
-               ],
-               'cantchangecontentmodel' => [
-                       'code' => 'cantchangecontentmodel',
-                       'info' => "You don't have permission to change the content model of a page"
-               ],
-               'nosuchrcid' => [
-                       'code' => 'nosuchrcid',
-                       'info' => "There is no change with rcid \"\$1\""
-               ],
-               'nosuchlogid' => [
-                       'code' => 'nosuchlogid',
-                       'info' => "There is no log entry with ID \"\$1\""
-               ],
-               'protect-invalidaction' => [
-                       'code' => 'protect-invalidaction',
-                       'info' => "Invalid protection type \"\$1\""
-               ],
-               'protect-invalidlevel' => [
-                       'code' => 'protect-invalidlevel',
-                       'info' => "Invalid protection level \"\$1\""
-               ],
-               'toofewexpiries' => [
-                       'code' => 'toofewexpiries',
-                       'info' => "\$1 expiry timestamps were provided where \$2 were needed"
-               ],
-               'cantimport' => [
-                       'code' => 'cantimport',
-                       'info' => "You don't have permission to import pages"
-               ],
-               'cantimport-upload' => [
-                       'code' => 'cantimport-upload',
-                       'info' => "You don't have permission to import uploaded pages"
-               ],
-               'importnofile' => [ 'code' => 'nofile', 'info' => "You didn't upload a file" ],
-               'importuploaderrorsize' => [
-                       'code' => 'filetoobig',
-                       'info' => 'The file you uploaded is bigger than the maximum upload size'
-               ],
-               'importuploaderrorpartial' => [
-                       'code' => 'partialupload',
-                       'info' => 'The file was only partially uploaded'
-               ],
-               'importuploaderrortemp' => [
-                       'code' => 'notempdir',
-                       'info' => 'The temporary upload directory is missing'
-               ],
-               'importcantopen' => [
-                       'code' => 'cantopenfile',
-                       'info' => "Couldn't open the uploaded file"
-               ],
-               'import-noarticle' => [
-                       'code' => 'badinterwiki',
-                       'info' => 'Invalid interwiki title specified'
-               ],
-               'importbadinterwiki' => [
-                       'code' => 'badinterwiki',
-                       'info' => 'Invalid interwiki title specified'
-               ],
-               'import-unknownerror' => [
-                       'code' => 'import-unknownerror',
-                       'info' => "Unknown error on import: \"\$1\""
-               ],
-               'cantoverwrite-sharedfile' => [
-                       'code' => 'cantoverwrite-sharedfile',
-                       'info' => 'The target file exists on a shared repository and you do not have permission to override it'
-               ],
-               'sharedfile-exists' => [
-                       'code' => 'fileexists-sharedrepo-perm',
-                       'info' => 'The target file exists on a shared repository. Use the ignorewarnings parameter to override it.'
-               ],
-               'mustbeposted' => [
-                       'code' => 'mustbeposted',
-                       'info' => "The \$1 module requires a POST request"
-               ],
-               'show' => [
-                       'code' => 'show',
-                       'info' => 'Incorrect parameter - mutually exclusive values may not be supplied'
-               ],
-               'specialpage-cantexecute' => [
-                       'code' => 'specialpage-cantexecute',
-                       'info' => "You don't have permission to view the results of this special page"
-               ],
-               'invalidoldimage' => [
-                       'code' => 'invalidoldimage',
-                       'info' => 'The oldimage parameter has invalid format'
-               ],
-               'nodeleteablefile' => [
-                       'code' => 'nodeleteablefile',
-                       'info' => 'No such old version of the file'
-               ],
-               'fileexists-forbidden' => [
-                       'code' => 'fileexists-forbidden',
-                       'info' => 'A file with name "$1" already exists, and cannot be overwritten.'
-               ],
-               'fileexists-shared-forbidden' => [
-                       'code' => 'fileexists-shared-forbidden',
-                       'info' => 'A file with name "$1" already exists in the shared file repository, and cannot be overwritten.'
-               ],
-               'filerevert-badversion' => [
-                       'code' => 'filerevert-badversion',
-                       'info' => 'There is no previous local version of this file with the provided timestamp.'
-               ],
-
-               // ApiEditPage messages
-               'noimageredirect-anon' => [
-                       'code' => 'noimageredirect-anon',
-                       'info' => "Anonymous users can't create image redirects"
-               ],
-               'noimageredirect-logged' => [
-                       'code' => 'noimageredirect',
-                       'info' => "You don't have permission to create image redirects"
-               ],
-               'spamdetected' => [
-                       'code' => 'spamdetected',
-                       'info' => "Your edit was refused because it contained a spam fragment: \"\$1\""
-               ],
-               'contenttoobig' => [
-                       'code' => 'contenttoobig',
-                       'info' => "The content you supplied exceeds the article size limit of \$1 kilobytes"
-               ],
-               'noedit-anon' => [ 'code' => 'noedit-anon', 'info' => "Anonymous users can't edit pages" ],
-               'noedit' => [ 'code' => 'noedit', 'info' => "You don't have permission to edit pages" ],
-               'wasdeleted' => [
-                       'code' => 'pagedeleted',
-                       'info' => 'The page has been deleted since you fetched its timestamp'
-               ],
-               'blankpage' => [
-                       'code' => 'emptypage',
-                       'info' => 'Creating new, empty pages is not allowed'
-               ],
-               'editconflict' => [ 'code' => 'editconflict', 'info' => 'Edit conflict detected' ],
-               'hashcheckfailed' => [ 'code' => 'badmd5', 'info' => 'The supplied MD5 hash was incorrect' ],
-               'missingtext' => [
-                       'code' => 'notext',
-                       'info' => 'One of the text, appendtext, prependtext and undo parameters must be set'
-               ],
-               'emptynewsection' => [
-                       'code' => 'emptynewsection',
-                       'info' => 'Creating empty new sections is not possible.'
-               ],
-               'revwrongpage' => [
-                       'code' => 'revwrongpage',
-                       'info' => "r\$1 is not a revision of \"\$2\""
-               ],
-               'undo-failure' => [
-                       'code' => 'undofailure',
-                       'info' => 'Undo failed due to conflicting intermediate edits'
-               ],
-               'content-not-allowed-here' => [
-                       'code' => 'contentnotallowedhere',
-                       'info' => 'Content model "$1" is not allowed at title "$2"'
-               ],
-
-               // Messages from WikiPage::doEit(]
-               'edit-hook-aborted' => [
-                       'code' => 'edit-hook-aborted',
-                       'info' => 'Your edit was aborted by an ArticleSave hook'
-               ],
-               'edit-gone-missing' => [
-                       'code' => 'edit-gone-missing',
-                       'info' => "The page you tried to edit doesn't seem to exist anymore"
-               ],
-               'edit-conflict' => [ 'code' => 'editconflict', 'info' => 'Edit conflict detected' ],
-               'edit-already-exists' => [
-                       'code' => 'edit-already-exists',
-                       'info' => 'It seems the page you tried to create already exist'
-               ],
-
-               // uploadMsgs
-               'invalid-file-key' => [ 'code' => 'invalid-file-key', 'info' => 'Not a valid file key' ],
-               'nouploadmodule' => [ 'code' => 'nouploadmodule', 'info' => 'No upload module set' ],
-               'uploaddisabled' => [
-                       'code' => 'uploaddisabled',
-                       'info' => 'Uploads are not enabled. Make sure $wgEnableUploads is set to true in LocalSettings.php and the PHP ini setting file_uploads is true'
-               ],
-               'copyuploaddisabled' => [
-                       'code' => 'copyuploaddisabled',
-                       'info' => 'Uploads by URL is not enabled. Make sure $wgAllowCopyUploads is set to true in LocalSettings.php.'
-               ],
-               'copyuploadbaddomain' => [
-                       'code' => 'copyuploadbaddomain',
-                       'info' => 'Uploads by URL are not allowed from this domain.'
-               ],
-               'copyuploadbadurl' => [
-                       'code' => 'copyuploadbadurl',
-                       'info' => 'Upload not allowed from this URL.'
-               ],
-
-               'filename-tooshort' => [
-                       'code' => 'filename-tooshort',
-                       'info' => 'The filename is too short'
-               ],
-               'filename-toolong' => [ 'code' => 'filename-toolong', 'info' => 'The filename is too long' ],
-               'illegal-filename' => [
-                       'code' => 'illegal-filename',
-                       'info' => 'The filename is not allowed'
-               ],
-               'filetype-missing' => [
-                       'code' => 'filetype-missing',
-                       'info' => 'The file is missing an extension'
-               ],
-
-               'mustbeloggedin' => [ 'code' => 'mustbeloggedin', 'info' => 'You must be logged in to $1.' ]
-       ];
-       // @codingStandardsIgnoreEnd
-
        /**
         * Helper function for readonly errors
         *
-        * @throws UsageException always
+        * @throws ApiUsageException always
         */
        public function dieReadOnly() {
-               $parsed = $this->parseMsg( [ 'readonlytext' ] );
-               $this->dieUsage( $parsed['info'], $parsed['code'], /* http error */ 0,
-                       [ 'readonlyreason' => wfReadOnlyReason() ] );
+               $this->dieWithError(
+                       'apierror-readonly',
+                       'readonly',
+                       [ 'readonlyreason' => wfReadOnlyReason() ]
+               );
        }
 
        /**
-        * Output the error message related to a certain array
-        * @param array|string|MessageSpecifier $error Element of a getUserPermissionsErrors()-style array
-        * @throws UsageException always
+        * Helper function for permission-denied errors
+        * @since 1.29
+        * @param string|string[] $rights
+        * @param User|null $user
+        * @throws ApiUsageException if the user doesn't have any of the rights.
+        *  The error message is based on $rights[0].
         */
-       public function dieUsageMsg( $error ) {
-               # most of the time we send a 1 element, so we might as well send it as
-               # a string and make this an array here.
-               if ( is_string( $error ) ) {
-                       $error = [ $error ];
+       public function checkUserRightsAny( $rights, $user = null ) {
+               if ( !$user ) {
+                       $user = $this->getUser();
+               }
+               $rights = (array)$rights;
+               if ( !call_user_func_array( [ $user, 'isAllowedAny' ], $rights ) ) {
+                       $this->dieWithError( [ 'apierror-permissiondenied', $this->msg( "action-{$rights[0]}" ) ] );
                }
-               $parsed = $this->parseMsg( $error );
-               $extraData = isset( $parsed['data'] ) ? $parsed['data'] : null;
-               $this->dieUsage( $parsed['info'], $parsed['code'], 0, $extraData );
        }
 
        /**
-        * Will only set a warning instead of failing if the global $wgDebugAPI
-        * is set to true. Otherwise behaves exactly as dieUsageMsg().
-        * @param array|string|MessageSpecifier $error Element of a getUserPermissionsErrors()-style array
-        * @throws UsageException
-        * @since 1.21
+        * Helper function for permission-denied errors
+        * @since 1.29
+        * @param Title $title
+        * @param string|string[] $actions
+        * @param User|null $user
+        * @throws ApiUsageException if the user doesn't have all of the rights.
         */
-       public function dieUsageMsgOrDebug( $error ) {
-               if ( $this->getConfig()->get( 'DebugAPI' ) !== true ) {
-                       $this->dieUsageMsg( $error );
+       public function checkTitleUserPermissions( Title $title, $actions, $user = null ) {
+               if ( !$user ) {
+                       $user = $this->getUser();
                }
 
-               if ( is_string( $error ) ) {
-                       $error = [ $error ];
+               $errors = [];
+               foreach ( (array)$actions as $action ) {
+                       $errors = array_merge( $errors, $title->getUserPermissionsErrors( $action, $user ) );
+               }
+               if ( $errors ) {
+                       $this->dieStatus( $this->errorArrayToStatus( $errors, $user ) );
                }
-               $parsed = $this->parseMsg( $error );
-               $this->setWarning( '$wgDebugAPI: ' . $parsed['code'] . ' - ' . $parsed['info'] );
        }
 
        /**
-        * Die with the $prefix.'badcontinue' error. This call is common enough to
-        * make it into the base method.
-        * @param bool $condition Will only die if this value is true
-        * @throws UsageException
-        * @since 1.21
+        * Will only set a warning instead of failing if the global $wgDebugAPI
+        * is set to true. Otherwise behaves exactly as self::dieWithError().
+        *
+        * @since 1.29
+        * @param string|array|Message $msg
+        * @param string|null $code
+        * @param array|null $data
+        * @param int|null $httpCode
+        * @throws ApiUsageException
         */
-       protected function dieContinueUsageIf( $condition ) {
-               if ( $condition ) {
-                       $this->dieUsage(
-                               'Invalid continue param. You should pass the original value returned by the previous query',
-                               'badcontinue' );
+       public function dieWithErrorOrDebug( $msg, $code = null, $data = null, $httpCode = null ) {
+               if ( $this->getConfig()->get( 'DebugAPI' ) !== true ) {
+                       $this->dieWithError( $msg, $code, $data, $httpCode );
+               } else {
+                       $this->addWarning( $msg, $code, $data );
                }
        }
 
        /**
-        * Return the error message related to a certain array
-        * @param array|string|MessageSpecifier $error Element of a getUserPermissionsErrors()-style array
-        * @return [ 'code' => code, 'info' => info ]
+        * Die with the 'badcontinue' error.
+        *
+        * This call is common enough to make it into the base method.
+        *
+        * @param bool $condition Will only die if this value is true
+        * @throws ApiUsageException
+        * @since 1.21
         */
-       public function parseMsg( $error ) {
-               // Check whether someone passed the whole array, instead of one element as
-               // documented. This breaks if it's actually an array of fallback keys, but
-               // that's long-standing misbehavior introduced in r87627 to incorrectly
-               // fix T30797.
-               if ( is_array( $error ) ) {
-                       $first = reset( $error );
-                       if ( is_array( $first ) ) {
-                               wfDebug( __METHOD__ . ' was passed an array of arrays. ' . wfGetAllCallers( 5 ) );
-                               $error = $first;
-                       }
-               }
-
-               $msg = Message::newFromSpecifier( $error );
-
-               if ( $msg instanceof IApiMessage ) {
-                       return [
-                               'code' => $msg->getApiCode(),
-                               'info' => $msg->inLanguage( 'en' )->useDatabase( false )->text(),
-                               'data' => $msg->getApiData()
-                       ];
-               }
-
-               $key = $msg->getKey();
-               if ( isset( self::$messageMap[$key] ) ) {
-                       $params = $msg->getParams();
-                       return [
-                               'code' => wfMsgReplaceArgs( self::$messageMap[$key]['code'], $params ),
-                               'info' => wfMsgReplaceArgs( self::$messageMap[$key]['info'], $params )
-                       ];
+       protected function dieContinueUsageIf( $condition ) {
+               if ( $condition ) {
+                       $this->dieWithError( 'apierror-badcontinue' );
                }
-
-               // If the key isn't present, throw an "unknown error"
-               return $this->parseMsg( [ 'unknownerror', $key ] );
        }
 
        /**
@@ -2288,6 +1878,7 @@ abstract class ApiBase extends ContextSource {
        /**
         * Write logging information for API features to a debug log, for usage
         * analysis.
+        * @note Consider using $this->addDeprecation() instead to both warn and log.
         * @param string $feature Feature being used.
         */
        public function logFeatureUsage( $feature ) {
@@ -2755,6 +2346,300 @@ abstract class ApiBase extends ContextSource {
                }
        }
 
+       /**
+        * @deprecated since 1.29, use ApiBase::addWarning() instead
+        * @param string $warning Warning message
+        */
+       public function setWarning( $warning ) {
+               $msg = new ApiRawMessage( $warning, 'warning' );
+               $this->getErrorFormatter()->addWarning( $this->getModulePath(), $msg );
+       }
+
+       /**
+        * Throw an ApiUsageException, which will (if uncaught) call the main module's
+        * error handler and die with an error message.
+        *
+        * @deprecated since 1.29, use self::dieWithError() instead
+        * @param string $description One-line human-readable description of the
+        *   error condition, e.g., "The API requires a valid action parameter"
+        * @param string $errorCode Brief, arbitrary, stable string to allow easy
+        *   automated identification of the error, e.g., 'unknown_action'
+        * @param int $httpRespCode HTTP response code
+        * @param array|null $extradata Data to add to the "<error>" element; array in ApiResult format
+        * @throws ApiUsageException always
+        */
+       public function dieUsage( $description, $errorCode, $httpRespCode = 0, $extradata = null ) {
+               $this->dieWithError(
+                       new RawMessage( '$1', [ $description ] ),
+                       $errorCode,
+                       $extradata,
+                       $httpRespCode
+               );
+       }
+
+       /**
+        * Get error (as code, string) from a Status object.
+        *
+        * @since 1.23
+        * @deprecated since 1.29, use ApiErrorFormatter::arrayFromStatus instead
+        * @param Status $status
+        * @param array|null &$extraData Set if extra data from IApiMessage is available (since 1.27)
+        * @return array Array of code and error string
+        * @throws MWException
+        */
+       public function getErrorFromStatus( $status, &$extraData = null ) {
+               if ( $status->isGood() ) {
+                       throw new MWException( 'Successful status passed to ApiBase::dieStatus' );
+               }
+
+               $errors = $status->getErrorsByType( 'error' );
+               if ( !$errors ) {
+                       // No errors? Assume the warnings should be treated as errors
+                       $errors = $status->getErrorsByType( 'warning' );
+               }
+               if ( !$errors ) {
+                       // Still no errors? Punt
+                       $errors = [ [ 'message' => 'unknownerror-nocode', 'params' => [] ] ];
+               }
+
+               if ( $errors[0]['message'] instanceof MessageSpecifier ) {
+                       $msg = $errors[0]['message'];
+               } else {
+                       $msg = new Message( $errors[0]['message'], $errors[0]['params'] );
+               }
+               if ( !$msg instanceof IApiMessage ) {
+                       $key = $msg->getKey();
+                       $params = $msg->getParams();
+                       array_unshift( $params, isset( self::$messageMap[$key] ) ? self::$messageMap[$key] : $key );
+                       $msg = ApiMessage::create( $params );
+               }
+
+               return [
+                       $msg->getApiCode(),
+                       ApiErrorFormatter::stripMarkup( $msg->inLanguage( 'en' )->useDatabase( false )->text() )
+               ];
+       }
+
+       /**
+        * @deprecated since 1.29. Prior to 1.29, this was a public mapping from
+        *  arbitrary strings (often message keys used elsewhere in MediaWiki) to
+        *  API codes and message texts, and a few interfaces required poking
+        *  something in here. Now we're repurposing it to map those same strings
+        *  to i18n messages, and declaring that any interface that requires poking
+        *  at this is broken and needs replacing ASAP.
+        */
+       private static $messageMap = [
+               'unknownerror' => 'apierror-unknownerror',
+               'unknownerror-nocode' => 'apierror-unknownerror-nocode',
+               'ns-specialprotected' => 'ns-specialprotected',
+               'protectedinterface' => 'protectedinterface',
+               'namespaceprotected' => 'namespaceprotected',
+               'customcssprotected' => 'customcssprotected',
+               'customjsprotected' => 'customjsprotected',
+               'cascadeprotected' => 'cascadeprotected',
+               'protectedpagetext' => 'protectedpagetext',
+               'protect-cantedit' => 'protect-cantedit',
+               'deleteprotected' => 'deleteprotected',
+               'badaccess-group0' => 'badaccess-group0',
+               'badaccess-groups' => 'badaccess-groups',
+               'titleprotected' => 'titleprotected',
+               'nocreate-loggedin' => 'nocreate-loggedin',
+               'nocreatetext' => 'nocreatetext',
+               'movenologintext' => 'movenologintext',
+               'movenotallowed' => 'movenotallowed',
+               'confirmedittext' => 'confirmedittext',
+               'blockedtext' => 'apierror-blocked',
+               'autoblockedtext' => 'apierror-autoblocked',
+               'actionthrottledtext' => 'apierror-ratelimited',
+               'alreadyrolled' => 'alreadyrolled',
+               'cantrollback' => 'cantrollback',
+               'readonlytext' => 'readonlytext',
+               'sessionfailure' => 'sessionfailure',
+               'cannotdelete' => 'cannotdelete',
+               'notanarticle' => 'apierror-missingtitle',
+               'selfmove' => 'selfmove',
+               'immobile_namespace' => 'apierror-immobilenamespace',
+               'articleexists' => 'articleexists',
+               'hookaborted' => 'hookaborted',
+               'cantmove-titleprotected' => 'cantmove-titleprotected',
+               'imagenocrossnamespace' => 'imagenocrossnamespace',
+               'imagetypemismatch' => 'imagetypemismatch',
+               'ip_range_invalid' => 'ip_range_invalid',
+               'range_block_disabled' => 'range_block_disabled',
+               'nosuchusershort' => 'nosuchusershort',
+               'badipaddress' => 'badipaddress',
+               'ipb_expiry_invalid' => 'ipb_expiry_invalid',
+               'ipb_already_blocked' => 'ipb_already_blocked',
+               'ipb_blocked_as_range' => 'ipb_blocked_as_range',
+               'ipb_cant_unblock' => 'ipb_cant_unblock',
+               'mailnologin' => 'apierror-cantsend',
+               'ipbblocked' => 'ipbblocked',
+               'ipbnounblockself' => 'ipbnounblockself',
+               'usermaildisabled' => 'usermaildisabled',
+               'blockedemailuser' => 'apierror-blockedfrommail',
+               'notarget' => 'apierror-notarget',
+               'noemail' => 'noemail',
+               'rcpatroldisabled' => 'rcpatroldisabled',
+               'markedaspatrollederror-noautopatrol' => 'markedaspatrollederror-noautopatrol',
+               'delete-toobig' => 'delete-toobig',
+               'movenotallowedfile' => 'movenotallowedfile',
+               'userrights-no-interwiki' => 'userrights-no-interwiki',
+               'userrights-nodatabase' => 'userrights-nodatabase',
+               'nouserspecified' => 'nouserspecified',
+               'noname' => 'noname',
+               'summaryrequired' => 'apierror-summaryrequired',
+               'import-rootpage-invalid' => 'import-rootpage-invalid',
+               'import-rootpage-nosubpage' => 'import-rootpage-nosubpage',
+               'readrequired' => 'apierror-readapidenied',
+               'writedisabled' => 'apierror-noapiwrite',
+               'writerequired' => 'apierror-writeapidenied',
+               'missingparam' => 'apierror-missingparam',
+               'invalidtitle' => 'apierror-invalidtitle',
+               'nosuchpageid' => 'apierror-nosuchpageid',
+               'nosuchrevid' => 'apierror-nosuchrevid',
+               'nosuchuser' => 'nosuchusershort',
+               'invaliduser' => 'apierror-invaliduser',
+               'invalidexpiry' => 'apierror-invalidexpiry',
+               'pastexpiry' => 'apierror-pastexpiry',
+               'create-titleexists' => 'apierror-create-titleexists',
+               'missingtitle-createonly' => 'apierror-missingtitle-createonly',
+               'cantblock' => 'apierror-cantblock',
+               'canthide' => 'apierror-canthide',
+               'cantblock-email' => 'apierror-cantblock-email',
+               'cantunblock' => 'apierror-permissiondenied-generic',
+               'cannotundelete' => 'cannotundelete',
+               'permdenied-undelete' => 'apierror-permissiondenied-generic',
+               'createonly-exists' => 'apierror-articleexists',
+               'nocreate-missing' => 'apierror-missingtitle',
+               'cantchangecontentmodel' => 'apierror-cantchangecontentmodel',
+               'nosuchrcid' => 'apierror-nosuchrcid',
+               'nosuchlogid' => 'apierror-nosuchlogid',
+               'protect-invalidaction' => 'apierror-protect-invalidaction',
+               'protect-invalidlevel' => 'apierror-protect-invalidlevel',
+               'toofewexpiries' => 'apierror-toofewexpiries',
+               'cantimport' => 'apierror-cantimport',
+               'cantimport-upload' => 'apierror-cantimport-upload',
+               'importnofile' => 'importnofile',
+               'importuploaderrorsize' => 'importuploaderrorsize',
+               'importuploaderrorpartial' => 'importuploaderrorpartial',
+               'importuploaderrortemp' => 'importuploaderrortemp',
+               'importcantopen' => 'importcantopen',
+               'import-noarticle' => 'import-noarticle',
+               'importbadinterwiki' => 'importbadinterwiki',
+               'import-unknownerror' => 'apierror-import-unknownerror',
+               'cantoverwrite-sharedfile' => 'apierror-cantoverwrite-sharedfile',
+               'sharedfile-exists' => 'apierror-fileexists-sharedrepo-perm',
+               'mustbeposted' => 'apierror-mustbeposted',
+               'show' => 'apierror-show',
+               'specialpage-cantexecute' => 'apierror-specialpage-cantexecute',
+               'invalidoldimage' => 'apierror-invalidoldimage',
+               'nodeleteablefile' => 'apierror-nodeleteablefile',
+               'fileexists-forbidden' => 'fileexists-forbidden',
+               'fileexists-shared-forbidden' => 'fileexists-shared-forbidden',
+               'filerevert-badversion' => 'filerevert-badversion',
+               'noimageredirect-anon' => 'apierror-noimageredirect-anon',
+               'noimageredirect-logged' => 'apierror-noimageredirect',
+               'spamdetected' => 'apierror-spamdetected',
+               'contenttoobig' => 'apierror-contenttoobig',
+               'noedit-anon' => 'apierror-noedit-anon',
+               'noedit' => 'apierror-noedit',
+               'wasdeleted' => 'apierror-pagedeleted',
+               'blankpage' => 'apierror-emptypage',
+               'editconflict' => 'editconflict',
+               'hashcheckfailed' => 'apierror-badmd5',
+               'missingtext' => 'apierror-notext',
+               'emptynewsection' => 'apierror-emptynewsection',
+               'revwrongpage' => 'apierror-revwrongpage',
+               'undo-failure' => 'undo-failure',
+               'content-not-allowed-here' => 'content-not-allowed-here',
+               'edit-hook-aborted' => 'edit-hook-aborted',
+               'edit-gone-missing' => 'edit-gone-missing',
+               'edit-conflict' => 'edit-conflict',
+               'edit-already-exists' => 'edit-already-exists',
+               'invalid-file-key' => 'apierror-invalid-file-key',
+               'nouploadmodule' => 'apierror-nouploadmodule',
+               'uploaddisabled' => 'uploaddisabled',
+               'copyuploaddisabled' => 'copyuploaddisabled',
+               'copyuploadbaddomain' => 'apierror-copyuploadbaddomain',
+               'copyuploadbadurl' => 'apierror-copyuploadbadurl',
+               'filename-tooshort' => 'filename-tooshort',
+               'filename-toolong' => 'filename-toolong',
+               'illegal-filename' => 'illegal-filename',
+               'filetype-missing' => 'filetype-missing',
+               'mustbeloggedin' => 'apierror-mustbeloggedin',
+       ];
+
+       /**
+        * @deprecated do not use
+        * @param array|string|MessageSpecifier $error Element of a getUserPermissionsErrors()-style array
+        * @return ApiMessage
+        */
+       private function parseMsgInternal( $error ) {
+               $msg = Message::newFromSpecifier( $error );
+               if ( !$msg instanceof IApiMessage ) {
+                       $key = $msg->getKey();
+                       if ( isset( self::$messageMap[$key] ) ) {
+                               $params = $msg->getParams();
+                               array_unshift( $params, self::$messageMap[$key] );
+                       } else {
+                               $params = [ 'apierror-unknownerror', wfEscapeWikiText( $key ) ];
+                       }
+                       $msg = ApiMessage::create( $params );
+               }
+               return $msg;
+       }
+
+       /**
+        * Return the error message related to a certain array
+        * @deprecated since 1.29
+        * @param array|string|MessageSpecifier $error Element of a getUserPermissionsErrors()-style array
+        * @return [ 'code' => code, 'info' => info ]
+        */
+       public function parseMsg( $error ) {
+               // Check whether someone passed the whole array, instead of one element as
+               // documented. This breaks if it's actually an array of fallback keys, but
+               // that's long-standing misbehavior introduced in r87627 to incorrectly
+               // fix T30797.
+               if ( is_array( $error ) ) {
+                       $first = reset( $error );
+                       if ( is_array( $first ) ) {
+                               wfDebug( __METHOD__ . ' was passed an array of arrays. ' . wfGetAllCallers( 5 ) );
+                               $error = $first;
+                       }
+               }
+
+               $msg = $this->parseMsgInternal( $error );
+               return [
+                       'code' => $msg->getApiCode(),
+                       'info' => ApiErrorFormatter::stripMarkup(
+                               $msg->inLanguage( 'en' )->useDatabase( false )->text()
+                       ),
+                       'data' => $msg->getApiData()
+               ];
+       }
+
+       /**
+        * Output the error message related to a certain array
+        * @deprecated since 1.29, use ApiBase::dieWithError() instead
+        * @param array|string|MessageSpecifier $error Element of a getUserPermissionsErrors()-style array
+        * @throws ApiUsageException always
+        */
+       public function dieUsageMsg( $error ) {
+               $this->dieWithError( $this->parseMsgInternal( $error ) );
+       }
+
+       /**
+        * Will only set a warning instead of failing if the global $wgDebugAPI
+        * is set to true. Otherwise behaves exactly as dieUsageMsg().
+        * @deprecated since 1.29, use ApiBase::dieWithErrorOrDebug() instead
+        * @param array|string|MessageSpecifier $error Element of a getUserPermissionsErrors()-style array
+        * @throws ApiUsageException
+        * @since 1.21
+        */
+       public function dieUsageMsgOrDebug( $error ) {
+               $this->dieWithErrorOrDebug( $this->parseMsgInternal( $error ) );
+       }
+
        /**@}*/
 }
 
index e4c9d0a..a4ea385 100644 (file)
@@ -41,22 +41,18 @@ class ApiBlock extends ApiBase {
        public function execute() {
                global $wgContLang;
 
+               $this->checkUserRightsAny( 'block' );
+
                $user = $this->getUser();
                $params = $this->extractRequestParams();
 
-               if ( !$user->isAllowed( 'block' ) ) {
-                       $this->dieUsageMsg( 'cantblock' );
-               }
-
                # bug 15810: blocked admins should have limited access here
                if ( $user->isBlocked() ) {
                        $status = SpecialBlock::checkUnblockSelf( $params['user'], $user );
                        if ( $status !== true ) {
-                               $msg = $this->parseMsg( $status );
-                               $this->dieUsage(
-                                       $msg['info'],
-                                       $msg['code'],
-                                       0,
+                               $this->dieWithError(
+                                       $status,
+                                       null,
                                        [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
                                );
                        }
@@ -68,14 +64,14 @@ class ApiBlock extends ApiBase {
                if ( $target instanceof User &&
                        ( $target->isAnon() /* doesn't exist */ || !User::isUsableName( $target->getName() ) )
                ) {
-                       $this->dieUsageMsg( [ 'nosuchuser', $params['user'] ] );
+                       $this->dieWithError( [ 'nosuchusershort', $params['user'] ], 'nosuchuser' );
                }
 
                if ( $params['hidename'] && !$user->isAllowed( 'hideuser' ) ) {
-                       $this->dieUsageMsg( 'canthide' );
+                       $this->dieWithError( 'apierror-canthide' );
                }
                if ( $params['noemail'] && !SpecialBlock::canBlockEmail( $user ) ) {
-                       $this->dieUsageMsg( 'cantblock-email' );
+                       $this->dieWithError( 'apierror-cantblock-email' );
                }
 
                $data = [
@@ -100,8 +96,7 @@ class ApiBlock extends ApiBase {
 
                $retval = SpecialBlock::processForm( $data, $this->getContext() );
                if ( $retval !== true ) {
-                       // We don't care about multiple errors, just report one of them
-                       $this->dieUsageMsg( $retval );
+                       $this->dieStatus( $this->errorArrayToStatus( $retval ) );
                }
 
                list( $target, /*...*/ ) = SpecialBlock::getTargetAndType( $params['user'] );
index 5a0edfc..4139019 100644 (file)
@@ -137,8 +137,11 @@ class ApiCSPReport extends ApiBase {
                }
                $status = FormatJson::parse( $postBody, FormatJson::FORCE_ASSOC );
                if ( !$status->isGood() ) {
-                       list( $code, ) = $this->getErrorFromStatus( $status );
-                       $this->error( $code, __METHOD__ );
+                       $msg = $status->getErrors()[0]['message'];
+                       if ( $msg instanceof Message ) {
+                               $msg = $msg->getKey();
+                       }
+                       $this->error( $msg, __METHOD__ );
                }
 
                $report = $status->getValue();
@@ -176,7 +179,7 @@ class ApiCSPReport extends ApiBase {
         *
         * @param $code String error code
         * @param $method String method that made error
-        * @throws UsageException Always
+        * @throws ApiUsageException Always
         */
        private function error( $code, $method ) {
                $this->log->info( 'Error reading CSP report: ' . $code, [
@@ -184,7 +187,9 @@ class ApiCSPReport extends ApiBase {
                        'user-agent' => $this->getRequest()->getHeader( 'user-agent' )
                ] );
                // 500 so it shows up in browser's developer console.
-               $this->dieUsage( "Error processing CSP report: $code", 'cspreport-' . $code, 500 );
+               $this->dieWithError(
+                       [ 'apierror-csp-report', wfEscapeWikiText( $code ) ], 'cspreport-' . $code, [], 500
+               );
        }
 
        public function getAllowedParams() {
index aea2819..c25920e 100644 (file)
@@ -35,7 +35,7 @@ class ApiChangeAuthenticationData extends ApiBase {
 
        public function execute() {
                if ( !$this->getUser()->isLoggedIn() ) {
-                       $this->dieUsage( 'Must be logged in to change authentication data', 'notloggedin' );
+                       $this->dieWithError( 'apierror-mustbeloggedin-changeauthenticationdata', 'notloggedin' );
                }
 
                $helper = new ApiAuthManagerHelper( $this );
@@ -50,7 +50,7 @@ class ApiChangeAuthenticationData extends ApiBase {
                        $this->getConfig()->get( 'ChangeCredentialsBlacklist' )
                );
                if ( count( $reqs ) !== 1 ) {
-                       $this->dieUsage( 'Failed to create change request', 'badrequest' );
+                       $this->dieWithError( 'apierror-changeauth-norequest', 'badrequest' );
                }
                $req = reset( $reqs );
 
index 3d2159c..3cc7a8a 100644 (file)
@@ -22,6 +22,8 @@
  * @file
  */
 
+use MediaWiki\Session\Token;
+
 /**
  * @since 1.25
  * @ingroup API
@@ -39,6 +41,11 @@ class ApiCheckToken extends ApiBase {
                $tokenObj = ApiQueryTokens::getToken(
                        $this->getUser(), $this->getRequest()->getSession(), $salts[$params['type']]
                );
+
+               if ( substr( $token, -strlen( urldecode( Token::SUFFIX ) ) ) === urldecode( Token::SUFFIX ) ) {
+                       $this->addWarning( 'apiwarn-checktoken-percentencoding' );
+               }
+
                if ( $tokenObj->match( $token, $maxage ) ) {
                        $res['result'] = 'valid';
                } elseif ( $maxage !== null && $tokenObj->match( $token ) ) {
@@ -47,7 +54,7 @@ class ApiCheckToken extends ApiBase {
                        $res['result'] = 'invalid';
                }
 
-               $ts = MediaWiki\Session\Token::getTimestamp( $token );
+               $ts = Token::getTimestamp( $token );
                if ( $ts !== null ) {
                        $mwts = new MWTimestamp();
                        $mwts->timestamp->setTimestamp( $ts );
index 13b3577..99242a8 100644 (file)
@@ -45,7 +45,7 @@ class ApiClearHasMsg extends ApiBase {
        }
 
        public function mustBePosted() {
-               return false;
+               return true;
        }
 
        protected function getExamplesMessages() {
index cbb1524..3f5bc0c 100644 (file)
@@ -57,8 +57,8 @@ class ApiClientLogin extends ApiBase {
                        $bits = wfParseUrl( $params['returnurl'] );
                        if ( !$bits || $bits['scheme'] === '' ) {
                                $encParamName = $this->encodeParamName( 'returnurl' );
-                               $this->dieUsage(
-                                       "Invalid value '{$params['returnurl']}' for url parameter $encParamName",
+                               $this->dieWithError(
+                                       [ 'apierror-badurl', $encParamName, wfEscapeWikiText( $params['returnurl'] ) ],
                                        "badurl_{$encParamName}"
                                );
                        }
index 7eb0bf3..d6867eb 100644 (file)
@@ -34,8 +34,7 @@ class ApiComparePages extends ApiBase {
                $revision = Revision::newFromId( $rev1 );
 
                if ( !$revision ) {
-                       $this->dieUsage( 'The diff cannot be retrieved, ' .
-                               'one revision does not exist or you do not have permission to view it.', 'baddiff' );
+                       $this->dieWithError( 'apierror-baddiff' );
                }
 
                $contentHandler = $revision->getContentHandler();
@@ -65,11 +64,7 @@ class ApiComparePages extends ApiBase {
                $difftext = $de->getDiffBody();
 
                if ( $difftext === false ) {
-                       $this->dieUsage(
-                               'The diff cannot be retrieved. Maybe one or both revisions do ' .
-                                       'not exist or you do not have permission to view them.',
-                               'baddiff'
-                       );
+                       $this->dieWithError( 'apierror-baddiff' );
                }
 
                ApiResult::setContentValue( $vals, 'body', $difftext );
@@ -89,22 +84,19 @@ class ApiComparePages extends ApiBase {
                } elseif ( $titleText ) {
                        $title = Title::newFromText( $titleText );
                        if ( !$title || $title->isExternal() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $titleText ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $titleText ) ] );
                        }
 
                        return $title->getLatestRevID();
                } elseif ( $titleId ) {
                        $title = Title::newFromID( $titleId );
                        if ( !$title ) {
-                               $this->dieUsageMsg( [ 'nosuchpageid', $titleId ] );
+                               $this->dieWithError( [ 'apierror-nosuchpageid', $titleId ] );
                        }
 
                        return $title->getLatestRevID();
                }
-               $this->dieUsage(
-                       'A title, a page ID, or a revision number is needed for both the from and the to parameters',
-                       'inputneeded'
-               );
+               $this->dieWithError( 'apierror-compare-inputneeded', 'inputneeded' );
        }
 
        public function getAllowedParams() {
index 19e2453..7da8ed9 100644 (file)
@@ -40,7 +40,7 @@ class ApiContinuationManager {
         * @param ApiBase $module Module starting the continuation
         * @param ApiBase[] $allModules Contains ApiBase instances that will be executed
         * @param array $generatedModules Names of modules that depend on the generator
-        * @throws UsageException
+        * @throws ApiUsageException
         */
        public function __construct(
                ApiBase $module, array $allModules = [], array $generatedModules = []
@@ -57,10 +57,7 @@ class ApiContinuationManager {
                if ( $continue !== '' ) {
                        $continue = explode( '||', $continue );
                        if ( count( $continue ) !== 2 ) {
-                               throw new UsageException(
-                                       'Invalid continue param. You should pass the original value returned by the previous query',
-                                       'badcontinue'
-                               );
+                               throw ApiUsageException::newWithMessage( $module->getMain(), 'apierror-badcontinue' );
                        }
                        $this->generatorDone = ( $continue[0] === '-' );
                        $skip = explode( '|', $continue[1] );
index 993c23e..50c24ae 100644 (file)
@@ -45,7 +45,7 @@ class ApiDelete extends ApiBase {
 
                $pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' );
                if ( !$pageObj->exists() ) {
-                       $this->dieUsageMsg( 'notanarticle' );
+                       $this->dieWithError( 'apierror-missingtitle' );
                }
 
                $titleObj = $pageObj->getTitle();
@@ -53,10 +53,7 @@ class ApiDelete extends ApiBase {
                $user = $this->getUser();
 
                // Check that the user is allowed to carry out the deletion
-               $errors = $titleObj->getUserPermissionsErrors( 'delete', $user );
-               if ( count( $errors ) ) {
-                       $this->dieUsageMsg( $errors[0] );
-               }
+               $this->checkTitleUserPermissions( $titleObj, 'delete' );
 
                // If change tagging was requested, check that the user is allowed to tag,
                // and the tags are valid
@@ -80,9 +77,6 @@ class ApiDelete extends ApiBase {
                        $status = self::delete( $pageObj, $user, $reason, $params['tags'] );
                }
 
-               if ( is_array( $status ) ) {
-                       $this->dieUsageMsg( $status[0] );
-               }
                if ( !$status->isGood() ) {
                        $this->dieStatus( $status );
                }
@@ -112,7 +106,7 @@ class ApiDelete extends ApiBase {
         * @param User $user User doing the action
         * @param string|null $reason Reason for the deletion. Autogenerated if null
         * @param array $tags Tags to tag the deletion with
-        * @return Status|array
+        * @return Status
         */
        protected static function delete( Page $page, User $user, &$reason = null, $tags = [] ) {
                $title = $page->getTitle();
@@ -124,7 +118,7 @@ class ApiDelete extends ApiBase {
                        $hasHistory = false;
                        $reason = $page->getAutoDeleteReason( $hasHistory );
                        if ( $reason === false ) {
-                               return [ [ 'cannotdelete', $title->getPrefixedText() ] ];
+                               return Status::newFatal( 'cannotdelete', $title->getPrefixedText() );
                        }
                }
 
@@ -141,7 +135,7 @@ class ApiDelete extends ApiBase {
         * @param string $reason Reason for the deletion. Autogenerated if null.
         * @param bool $suppress Whether to mark all deleted versions as restricted
         * @param array $tags Tags to tag the deletion with
-        * @return Status|array
+        * @return Status
         */
        protected static function deleteFile( Page $page, User $user, $oldimage,
                &$reason = null, $suppress = false, $tags = []
@@ -155,11 +149,11 @@ class ApiDelete extends ApiBase {
 
                if ( $oldimage ) {
                        if ( !FileDeleteForm::isValidOldSpec( $oldimage ) ) {
-                               return [ [ 'invalidoldimage' ] ];
+                               return Status::newFatal( 'invalidoldimage' );
                        }
                        $oldfile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $title, $oldimage );
                        if ( !$oldfile->exists() || !$oldfile->isLocal() || $oldfile->getRedirected() ) {
-                               return [ [ 'nodeleteablefile' ] ];
+                               return Status::newFatal( 'nodeleteablefile' );
                        }
                }
 
index fc97522..41bf9b6 100644 (file)
@@ -37,7 +37,7 @@
 class ApiDisabled extends ApiBase {
 
        public function execute() {
-               $this->dieUsage( "The \"{$this->getModuleName()}\" module has been disabled.", 'moduledisabled' );
+               $this->dieWithError( [ 'apierror-moduledisabled', $this->getModuleName() ] );
        }
 
        public function isReadMode() {
index d6de834..6b56870 100644 (file)
@@ -40,12 +40,7 @@ class ApiEditPage extends ApiBase {
                $user = $this->getUser();
                $params = $this->extractRequestParams();
 
-               if ( is_null( $params['text'] ) && is_null( $params['appendtext'] ) &&
-                       is_null( $params['prependtext'] ) &&
-                       $params['undo'] == 0
-               ) {
-                       $this->dieUsageMsg( 'missingtext' );
-               }
+               $this->requireAtLeastOneParameter( $params, 'text', 'appendtext', 'prependtext', 'undo' );
 
                $pageObj = $this->getTitleOrPageId( $params );
                $titleObj = $pageObj->getTitle();
@@ -55,9 +50,7 @@ class ApiEditPage extends ApiBase {
                        if ( $params['prependtext'] === null && $params['appendtext'] === null
                                && $params['section'] !== 'new'
                        ) {
-                               $this->dieUsage( 'You have attempted to edit using the "redirect"-following'
-                                       . ' mode, which must be used in conjuction with section=new, prependtext'
-                                       . ', or appendtext.', 'redirect-appendonly' );
+                               $this->dieWithError( 'apierror-redirect-appendonly' );
                        }
                        if ( $titleObj->isRedirect() ) {
                                $oldTitle = $titleObj;
@@ -105,10 +98,7 @@ class ApiEditPage extends ApiBase {
                if ( $params['undo'] > 0 ) {
                        // allow undo via api
                } elseif ( $contentHandler->supportsDirectApiEditing() === false ) {
-                       $this->dieUsage(
-                               "Direct editing via API is not supported for content model $model used by $name",
-                               'no-direct-editing'
-                       );
+                       $this->dieWithError( [ 'apierror-no-direct-editing', $model, $name ] );
                }
 
                if ( !isset( $params['contentformat'] ) || $params['contentformat'] == '' ) {
@@ -118,49 +108,21 @@ class ApiEditPage extends ApiBase {
                }
 
                if ( !$contentHandler->isSupportedFormat( $contentFormat ) ) {
-
-                       $this->dieUsage( "The requested format $contentFormat is not supported for content model " .
-                               " $model used by $name", 'badformat' );
+                       $this->dieWithError( [ 'apierror-badformat', $contentFormat, $model, $name ] );
                }
 
                if ( $params['createonly'] && $titleObj->exists() ) {
-                       $this->dieUsageMsg( 'createonly-exists' );
+                       $this->dieWithError( 'apierror-articleexists' );
                }
                if ( $params['nocreate'] && !$titleObj->exists() ) {
-                       $this->dieUsageMsg( 'nocreate-missing' );
+                       $this->dieWithError( 'apierror-missingtitle' );
                }
 
                // Now let's check whether we're even allowed to do this
-               $errors = $titleObj->getUserPermissionsErrors( 'edit', $user );
-               if ( !$titleObj->exists() ) {
-                       $errors = array_merge( $errors, $titleObj->getUserPermissionsErrors( 'create', $user ) );
-               }
-               if ( count( $errors ) ) {
-                       if ( is_array( $errors[0] ) ) {
-                               switch ( $errors[0][0] ) {
-                                       case 'blockedtext':
-                                               $this->dieUsage(
-                                                       'You have been blocked from editing',
-                                                       'blocked',
-                                                       0,
-                                                       [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
-                                               );
-                                               break;
-                                       case 'autoblockedtext':
-                                               $this->dieUsage(
-                                                       'Your IP address has been blocked automatically, because it was used by a blocked user',
-                                                       'autoblocked',
-                                                       0,
-                                                       [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
-                                               );
-                                               break;
-                                       default:
-                                               $this->dieUsageMsg( $errors[0] );
-                               }
-                       } else {
-                               $this->dieUsageMsg( $errors[0] );
-                       }
-               }
+               $this->checkTitleUserPermissions(
+                       $titleObj,
+                       $titleObj->exists() ? 'edit' : [ 'edit', 'create' ]
+               );
 
                $toMD5 = $params['text'];
                if ( !is_null( $params['appendtext'] ) || !is_null( $params['prependtext'] ) ) {
@@ -178,8 +140,11 @@ class ApiEditPage extends ApiBase {
                                        try {
                                                $content = ContentHandler::makeContent( $text, $this->getTitle() );
                                        } catch ( MWContentSerializationException $ex ) {
-                                               $this->dieUsage( $ex->getMessage(), 'parseerror' );
-
+                                               // @todo: Internationalize MWContentSerializationException
+                                               $this->dieWithError(
+                                                       [ 'apierror-contentserializationexception', wfEscapeWikiText( $ex->getMessage() ) ],
+                                                       'parseerror'
+                                               );
                                                return;
                                        }
                                } else {
@@ -191,17 +156,14 @@ class ApiEditPage extends ApiBase {
                        // @todo Add support for appending/prepending to the Content interface
 
                        if ( !( $content instanceof TextContent ) ) {
-                               $mode = $contentHandler->getModelID();
-                               $this->dieUsage( "Can't append to pages using content model $mode", 'appendnotsupported' );
+                               $modelName = $contentHandler->getModelID();
+                               $this->dieWithError( [ 'apierror-appendnotsupported', $modelName ] );
                        }
 
                        if ( !is_null( $params['section'] ) ) {
                                if ( !$contentHandler->supportsSections() ) {
                                        $modelName = $contentHandler->getModelID();
-                                       $this->dieUsage(
-                                               "Sections are not supported for this content model: $modelName.",
-                                               'sectionsnotsupported'
-                                       );
+                                       $this->dieWithError( [ 'apierror-sectionsnotsupported', $modelName ] );
                                }
 
                                if ( $params['section'] == 'new' ) {
@@ -213,7 +175,7 @@ class ApiEditPage extends ApiBase {
                                        $content = $content->getSection( $section );
 
                                        if ( !$content ) {
-                                               $this->dieUsage( "There is no section {$section}.", 'nosuchsection' );
+                                               $this->dieWithError( [ 'apierror-nosuchsection', wfEscapeWikiText( $section ) ] );
                                        }
                                }
                        }
@@ -238,22 +200,22 @@ class ApiEditPage extends ApiBase {
                        }
                        $undoRev = Revision::newFromId( $params['undo'] );
                        if ( is_null( $undoRev ) || $undoRev->isDeleted( Revision::DELETED_TEXT ) ) {
-                               $this->dieUsageMsg( [ 'nosuchrevid', $params['undo'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchrevid', $params['undo'] ] );
                        }
 
                        if ( $params['undoafter'] == 0 ) {
                                $undoafterRev = $undoRev->getPrevious();
                        }
                        if ( is_null( $undoafterRev ) || $undoafterRev->isDeleted( Revision::DELETED_TEXT ) ) {
-                               $this->dieUsageMsg( [ 'nosuchrevid', $params['undoafter'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchrevid', $params['undoafter'] ] );
                        }
 
                        if ( $undoRev->getPage() != $pageObj->getId() ) {
-                               $this->dieUsageMsg( [ 'revwrongpage', $undoRev->getId(),
+                               $this->dieWithError( [ 'apierror-revwrongpage', $undoRev->getId(),
                                        $titleObj->getPrefixedText() ] );
                        }
                        if ( $undoafterRev->getPage() != $pageObj->getId() ) {
-                               $this->dieUsageMsg( [ 'revwrongpage', $undoafterRev->getId(),
+                               $this->dieWithError( [ 'apierror-revwrongpage', $undoafterRev->getId(),
                                        $titleObj->getPrefixedText() ] );
                        }
 
@@ -264,7 +226,7 @@ class ApiEditPage extends ApiBase {
                        );
 
                        if ( !$newContent ) {
-                               $this->dieUsageMsg( 'undo-failure' );
+                               $this->dieWithError( 'undo-failure', 'undofailure' );
                        }
                        if ( empty( $params['contentmodel'] )
                                && empty( $params['contentformat'] )
@@ -293,7 +255,7 @@ class ApiEditPage extends ApiBase {
 
                // See if the MD5 hash checks out
                if ( !is_null( $params['md5'] ) && md5( $toMD5 ) !== $params['md5'] ) {
-                       $this->dieUsageMsg( 'hashcheckfailed' );
+                       $this->dieWithError( 'apierror-badmd5' );
                }
 
                // EditPage wants to parse its stuff from a WebRequest
@@ -347,14 +309,13 @@ class ApiEditPage extends ApiBase {
                if ( !is_null( $params['section'] ) ) {
                        $section = $params['section'];
                        if ( !preg_match( '/^((T-)?\d+|new)$/', $section ) ) {
-                               $this->dieUsage( "The section parameter must be a valid section id or 'new'",
-                                       'invalidsection' );
+                               $this->dieWithError( 'apierror-invalidsection' );
                        }
                        $content = $pageObj->getContent();
                        if ( $section !== '0' && $section != 'new'
                                && ( !$content || !$content->getSection( $section ) )
                        ) {
-                               $this->dieUsage( "There is no section {$section}.", 'nosuchsection' );
+                               $this->dieWithError( [ 'apierror-nosuchsection', $section ] );
                        }
                        $requestArray['wpSection'] = $params['section'];
                } else {
@@ -423,7 +384,7 @@ class ApiEditPage extends ApiBase {
                                return;
                        }
 
-                       $this->dieUsageMsg( 'hookaborted' );
+                       $this->dieWithError( 'hookaborted' );
                }
 
                // Do the actual save
@@ -445,67 +406,22 @@ class ApiEditPage extends ApiBase {
                                        $r['result'] = 'Failure';
                                        $apiResult->addValue( null, $this->getModuleName(), $r );
                                        return;
-                               } else {
-                                       $this->dieUsageMsg( 'hookaborted' );
                                }
-
-                       case EditPage::AS_PARSE_ERROR:
-                               $this->dieUsage( $status->getMessage(), 'parseerror' );
-
-                       case EditPage::AS_IMAGE_REDIRECT_ANON:
-                               $this->dieUsageMsg( 'noimageredirect-anon' );
-
-                       case EditPage::AS_IMAGE_REDIRECT_LOGGED:
-                               $this->dieUsageMsg( 'noimageredirect-logged' );
-
-                       case EditPage::AS_SPAM_ERROR:
-                               $this->dieUsageMsg( [ 'spamdetected', $result['spam'] ] );
+                               if ( !$status->getErrors() ) {
+                                       $status->fatal( 'hookaborted' );
+                               }
+                               $this->dieStatus( $status );
 
                        case EditPage::AS_BLOCKED_PAGE_FOR_USER:
-                               $this->dieUsage(
-                                       'You have been blocked from editing',
+                               $this->dieWithError(
+                                       'apierror-blocked',
                                        'blocked',
-                                       0,
                                        [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
                                );
 
-                       case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
-                       case EditPage::AS_CONTENT_TOO_BIG:
-                               $this->dieUsageMsg( [ 'contenttoobig', $this->getConfig()->get( 'MaxArticleSize' ) ] );
-
-                       case EditPage::AS_READ_ONLY_PAGE_ANON:
-                               $this->dieUsageMsg( 'noedit-anon' );
-
-                       case EditPage::AS_READ_ONLY_PAGE_LOGGED:
-                               $this->dieUsageMsg( 'noedit' );
-
                        case EditPage::AS_READ_ONLY_PAGE:
                                $this->dieReadOnly();
 
-                       case EditPage::AS_RATE_LIMITED:
-                               $this->dieUsageMsg( 'actionthrottledtext' );
-
-                       case EditPage::AS_ARTICLE_WAS_DELETED:
-                               $this->dieUsageMsg( 'wasdeleted' );
-
-                       case EditPage::AS_NO_CREATE_PERMISSION:
-                               $this->dieUsageMsg( 'nocreate-loggedin' );
-
-                       case EditPage::AS_NO_CHANGE_CONTENT_MODEL:
-                               $this->dieUsageMsg( 'cantchangecontentmodel' );
-
-                       case EditPage::AS_BLANK_ARTICLE:
-                               $this->dieUsageMsg( 'blankpage' );
-
-                       case EditPage::AS_CONFLICT_DETECTED:
-                               $this->dieUsageMsg( 'editconflict' );
-
-                       case EditPage::AS_TEXTBOX_EMPTY:
-                               $this->dieUsageMsg( 'emptynewsection' );
-
-                       case EditPage::AS_CHANGE_TAG_ERROR:
-                               $this->dieStatus( $status );
-
                        case EditPage::AS_SUCCESS_NEW_ARTICLE:
                                $r['new'] = true;
                                // fall-through
@@ -526,15 +442,39 @@ class ApiEditPage extends ApiBase {
                                }
                                break;
 
-                       case EditPage::AS_SUMMARY_NEEDED:
-                               // Shouldn't happen since we set wpIgnoreBlankSummary, but just in case
-                               $this->dieUsageMsg( 'summaryrequired' );
-
-                       case EditPage::AS_END:
                        default:
-                               // $status came from WikiPage::doEditContent()
-                               $errors = $status->getErrorsArray();
-                               $this->dieUsageMsg( $errors[0] ); // TODO: Add new errors to message map
+                               // EditPage sometimes only sets the status code without setting
+                               // any actual error messages. Supply defaults for those cases.
+                               $maxArticleSize = $this->getConfig()->get( 'MaxArticleSize' );
+                               $defaultMessages = [
+                                       // Currently needed
+                                       EditPage::AS_IMAGE_REDIRECT_ANON => [ 'apierror-noimageredirect-anon' ],
+                                       EditPage::AS_IMAGE_REDIRECT_LOGGED => [ 'apierror-noimageredirect-logged' ],
+                                       EditPage::AS_CONTENT_TOO_BIG => [ 'apierror-contenttoobig', $maxArticleSize ],
+                                       EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED => [ 'apierror-contenttoobig', $maxArticleSize ],
+                                       EditPage::AS_READ_ONLY_PAGE_ANON => [ 'apierror-noedit-anon' ],
+                                       EditPage::AS_NO_CHANGE_CONTENT_MODEL => [ 'apierror-cantchangecontentmodel' ],
+                                       EditPage::AS_ARTICLE_WAS_DELETED => [ 'apierror-pagedeleted' ],
+                                       EditPage::AS_CONFLICT_DETECTED => [ 'editconflict' ],
+
+                                       // Currently shouldn't be needed
+                                       EditPage::AS_SPAM_ERROR => [ 'apierror-spamdetected', wfEscapeWikiText( $result['spam'] ) ],
+                                       EditPage::AS_READ_ONLY_PAGE_LOGGED => [ 'apierror-noedit' ],
+                                       EditPage::AS_RATE_LIMITED => [ 'apierror-ratelimited' ],
+                                       EditPage::AS_NO_CREATE_PERMISSION => [ 'nocreate-loggedin' ],
+                                       EditPage::AS_BLANK_ARTICLE => [ 'apierror-emptypage' ],
+                                       EditPage::AS_TEXTBOX_EMPTY => [ 'apierror-emptynewsection' ],
+                                       EditPage::AS_SUMMARY_NEEDED => [ 'apierror-summaryrequired' ],
+                               ];
+                               if ( !$status->getErrors() ) {
+                                       if ( isset( $defaultMessages[$status->value] ) ) {
+                                               call_user_func_array( [ $status, 'fatal' ], $defaultMessages[$status->value] );
+                                       } else {
+                                               wfWarn( __METHOD__ . ": Unknown EditPage code {$status->value} with no message" );
+                                               $status->fatal( 'apierror-unknownerror-editpage', $status->value );
+                                       }
+                               }
+                               $this->dieStatus( $status );
                                break;
                }
                $apiResult->addValue( null, $this->getModuleName(), $r );
index 192378e..8aff6f8 100644 (file)
@@ -36,7 +36,16 @@ class ApiEmailUser extends ApiBase {
                // Validate target
                $targetUser = SpecialEmailUser::getTarget( $params['target'] );
                if ( !( $targetUser instanceof User ) ) {
-                       $this->dieUsageMsg( [ $targetUser ] );
+                       switch ( $targetUser ) {
+                               case 'notarget':
+                                       $this->dieWithError( 'apierror-notarget' );
+                               case 'noemail':
+                                       $this->dieWithError( [ 'noemail', $params['target'] ] );
+                               case 'nowikiemail':
+                                       $this->dieWithError( 'nowikiemailtext', 'nowikiemail' );
+                               default:
+                                       $this->dieWithError( [ 'apierror-unknownerror', $targetUser ] );
+                       }
                }
 
                // Check permissions and errors
@@ -46,7 +55,7 @@ class ApiEmailUser extends ApiBase {
                        $this->getConfig()
                );
                if ( $error ) {
-                       $this->dieUsageMsg( [ $error ] );
+                       $this->dieWithError( $error );
                }
 
                $data = [
@@ -56,25 +65,16 @@ class ApiEmailUser extends ApiBase {
                        'CCMe' => $params['ccme'],
                ];
                $retval = SpecialEmailUser::submit( $data, $this->getContext() );
-
-               if ( $retval instanceof Status ) {
-                       // SpecialEmailUser sometimes returns a status
-                       // sometimes it doesn't.
-                       if ( $retval->isGood() ) {
-                               $retval = true;
-                       } else {
-                               $retval = $retval->getErrorsArray();
-                       }
+               if ( !$retval instanceof Status ) {
+                       // This is probably the reason
+                       $retval = Status::newFatal( 'hookaborted' );
                }
 
-               if ( $retval === true ) {
-                       $result = [ 'result' => 'Success' ];
-               } else {
-                       $result = [
-                               'result' => 'Failure',
-                               'message' => $retval
-                       ];
-               }
+               $result = array_filter( [
+                       'result' => $retval->isGood() ? 'Success' : $retval->isOk() ? 'Warnings' : 'Failure',
+                       'warnings' => $this->getErrorFormatter()->arrayFromStatus( $retval, 'warning' ),
+                       'errors' => $this->getErrorFormatter()->arrayFromStatus( $retval, 'error' ),
+               ] );
 
                $this->getResult()->addValue( null, $this->getModuleName(), $result );
        }
index 6d9184f..4fb19b8 100644 (file)
@@ -43,7 +43,9 @@ class ApiErrorFormatter {
         * @param ApiResult $result Into which data will be added
         * @param Language $lang Used for i18n
         * @param string $format
-        *  - text: Error message as wikitext
+        *  - plaintext: Error message as something vaguely like plaintext
+        *    (it's basically wikitext with HTML tags stripped and entities decoded)
+        *  - wikitext: Error message as wikitext
         *  - html: Error message as HTML
         *  - raw: Raw message key and parameters, no human-readable text
         *  - none: Code and data only, no human-readable text
@@ -56,6 +58,15 @@ class ApiErrorFormatter {
                $this->format = $format;
        }
 
+       /**
+        * Fetch the Language for this formatter
+        * @since 1.29
+        * @return Language
+        */
+       public function getLanguage() {
+               return $this->lang;
+       }
+
        /**
         * Fetch a dummy title to set on Messages
         * @return Title
@@ -69,53 +80,49 @@ class ApiErrorFormatter {
 
        /**
         * Add a warning to the result
-        * @param string $moduleName
-        * @param MessageSpecifier|array|string $msg i18n message for the warning
-        * @param string $code Machine-readable code for the warning. Defaults as
-        *   for IApiMessage::getApiCode().
-        * @param array $data Machine-readable data for the warning, if any.
-        *   Uses IApiMessage::getApiData() if $msg implements that interface.
+        * @param string|null $modulePath
+        * @param Message|array|string $msg Warning message. See ApiMessage::create().
+        * @param string|null $code See ApiMessage::create().
+        * @param array|null $data See ApiMessage::create().
         */
-       public function addWarning( $moduleName, $msg, $code = null, $data = null ) {
+       public function addWarning( $modulePath, $msg, $code = null, $data = null ) {
                $msg = ApiMessage::create( $msg, $code, $data )
                        ->inLanguage( $this->lang )
                        ->title( $this->getDummyTitle() )
                        ->useDatabase( $this->useDB );
-               $this->addWarningOrError( 'warning', $moduleName, $msg );
+               $this->addWarningOrError( 'warning', $modulePath, $msg );
        }
 
        /**
         * Add an error to the result
-        * @param string $moduleName
-        * @param MessageSpecifier|array|string $msg i18n message for the error
-        * @param string $code Machine-readable code for the warning. Defaults as
-        *   for IApiMessage::getApiCode().
-        * @param array $data Machine-readable data for the warning, if any.
-        *   Uses IApiMessage::getApiData() if $msg implements that interface.
+        * @param string|null $modulePath
+        * @param Message|array|string $msg Warning message. See ApiMessage::create().
+        * @param string|null $code See ApiMessage::create().
+        * @param array|null $data See ApiMessage::create().
         */
-       public function addError( $moduleName, $msg, $code = null, $data = null ) {
+       public function addError( $modulePath, $msg, $code = null, $data = null ) {
                $msg = ApiMessage::create( $msg, $code, $data )
                        ->inLanguage( $this->lang )
                        ->title( $this->getDummyTitle() )
                        ->useDatabase( $this->useDB );
-               $this->addWarningOrError( 'error', $moduleName, $msg );
+               $this->addWarningOrError( 'error', $modulePath, $msg );
        }
 
        /**
-        * Add warnings and errors from a Status object to the result
-        * @param string $moduleName
-        * @param Status $status
+        * Add warnings and errors from a StatusValue object to the result
+        * @param string|null $modulePath
+        * @param StatusValue $status
         * @param string[] $types 'warning' and/or 'error'
         */
        public function addMessagesFromStatus(
-               $moduleName, Status $status, $types = [ 'warning', 'error' ]
+               $modulePath, StatusValue $status, $types = [ 'warning', 'error' ]
        ) {
-               if ( $status->isGood() || !$status->errors ) {
+               if ( $status->isGood() || !$status->getErrors() ) {
                        return;
                }
 
                $types = (array)$types;
-               foreach ( $status->errors as $error ) {
+               foreach ( $status->getErrors() as $error ) {
                        if ( !in_array( $error['type'], $types, true ) ) {
                                continue;
                        }
@@ -127,40 +134,37 @@ class ApiErrorFormatter {
                                $tag = 'warning';
                        }
 
-                       if ( is_array( $error ) && isset( $error['message'] ) ) {
-                               // Normal case
-                               if ( $error['message'] instanceof Message ) {
-                                       $msg = ApiMessage::create( $error['message'], null, [] );
-                               } else {
-                                       $args = isset( $error['params'] ) ? $error['params'] : [];
-                                       array_unshift( $args, $error['message'] );
-                                       $error += [ 'params' => [] ];
-                                       $msg = ApiMessage::create( $args, null, [] );
-                               }
-                       } elseif ( is_array( $error ) ) {
-                               // Weird case handled by Message::getErrorMessage
-                               $msg = ApiMessage::create( $error, null, [] );
-                       } else {
-                               // Another weird case handled by Message::getErrorMessage
-                               $msg = ApiMessage::create( $error, null, [] );
-                       }
-
-                       $msg->inLanguage( $this->lang )
+                       $msg = ApiMessage::create( $error )
+                               ->inLanguage( $this->lang )
                                ->title( $this->getDummyTitle() )
                                ->useDatabase( $this->useDB );
-                       $this->addWarningOrError( $tag, $moduleName, $msg );
+                       $this->addWarningOrError( $tag, $modulePath, $msg );
                }
        }
 
        /**
-        * Format messages from a Status as an array
-        * @param Status $status
+        * Format a message as an array
+        * @param Message|array|string $msg Message. See ApiMessage::create().
+        * @param string|null $format
+        * @return array
+        */
+       public function formatMessage( $msg, $format = null ) {
+               $msg = ApiMessage::create( $msg )
+                       ->inLanguage( $this->lang )
+                       ->title( $this->getDummyTitle() )
+                       ->useDatabase( $this->useDB );
+               return $this->formatMessageInternal( $msg, $format ?: $this->format );
+       }
+
+       /**
+        * Format messages from a StatusValue as an array
+        * @param StatusValue $status
         * @param string $type 'warning' or 'error'
         * @param string|null $format
         * @return array
         */
-       public function arrayFromStatus( Status $status, $type = 'error', $format = null ) {
-               if ( $status->isGood() || !$status->errors ) {
+       public function arrayFromStatus( StatusValue $status, $type = 'error', $format = null ) {
+               if ( $status->isGood() || !$status->getErrors() ) {
                        return [];
                }
 
@@ -168,24 +172,69 @@ class ApiErrorFormatter {
                $formatter = new ApiErrorFormatter(
                        $result, $this->lang, $format ?: $this->format, $this->useDB
                );
-               $formatter->addMessagesFromStatus( 'dummy', $status, [ $type ] );
+               $formatter->addMessagesFromStatus( null, $status, [ $type ] );
                switch ( $type ) {
                        case 'error':
-                               return (array)$result->getResultData( [ 'errors', 'dummy' ] );
+                               return (array)$result->getResultData( [ 'errors' ] );
                        case 'warning':
-                               return (array)$result->getResultData( [ 'warnings', 'dummy' ] );
+                               return (array)$result->getResultData( [ 'warnings' ] );
                }
        }
 
        /**
-        * Actually add the warning or error to the result
-        * @param string $tag 'warning' or 'error'
-        * @param string $moduleName
+        * Turn wikitext into something resembling plaintext
+        * @since 1.29
+        * @param string $text
+        * @return string
+        */
+       public static function stripMarkup( $text ) {
+               // Turn semantic quoting tags to quotes
+               $ret = preg_replace( '!</?(var|kbd|samp|code)>!', '"', $text );
+
+               // Strip tags and decode.
+               $ret = html_entity_decode( strip_tags( $ret ), ENT_QUOTES | ENT_HTML5 );
+
+               return $ret;
+       }
+
+       /**
+        * Format a Message object for raw format
+        * @param MessageSpecifier $msg
+        * @return array
+        */
+       private function formatRawMessage( MessageSpecifier $msg ) {
+               $ret = [
+                       'key' => $msg->getKey(),
+                       'params' => $msg->getParams(),
+               ];
+               ApiResult::setIndexedTagName( $ret['params'], 'param' );
+
+               // Transform Messages as parameters in the style of Message::fooParam().
+               foreach ( $ret['params'] as $i => $param ) {
+                       if ( $param instanceof MessageSpecifier ) {
+                               $ret['params'][$i] = [ 'message' => $this->formatRawMessage( $param ) ];
+                       }
+               }
+               return $ret;
+       }
+
+       /**
+        * Format a message as an array
+        * @since 1.29
         * @param ApiMessage|ApiRawMessage $msg
+        * @param string|null $format
+        * @return array
         */
-       protected function addWarningOrError( $tag, $moduleName, $msg ) {
+       protected function formatMessageInternal( $msg, $format ) {
                $value = [ 'code' => $msg->getApiCode() ];
-               switch ( $this->format ) {
+               switch ( $format ) {
+                       case 'plaintext':
+                               $value += [
+                                       'text' => self::stripMarkup( $msg->text() ),
+                                       ApiResult::META_CONTENT => 'text',
+                               ];
+                               break;
+
                        case 'wikitext':
                                $value += [
                                        'text' => $msg->text(),
@@ -201,19 +250,34 @@ class ApiErrorFormatter {
                                break;
 
                        case 'raw':
-                               $value += [
-                                       'key' => $msg->getKey(),
-                                       'params' => $msg->getParams(),
-                               ];
-                               ApiResult::setIndexedTagName( $value['params'], 'param' );
+                               $value += $this->formatRawMessage( $msg );
                                break;
 
                        case 'none':
                                break;
                }
-               $value += $msg->getApiData();
+               $data = $msg->getApiData();
+               if ( $data ) {
+                       $value['data'] = $msg->getApiData() + [
+                               ApiResult::META_TYPE => 'assoc',
+                       ];
+               }
+               return $value;
+       }
 
-               $path = [ $tag . 's', $moduleName ];
+       /**
+        * Actually add the warning or error to the result
+        * @param string $tag 'warning' or 'error'
+        * @param string|null $modulePath
+        * @param ApiMessage|ApiRawMessage $msg
+        */
+       protected function addWarningOrError( $tag, $modulePath, $msg ) {
+               $value = $this->formatMessageInternal( $msg, $this->format );
+               if ( $modulePath !== null ) {
+                       $value += [ 'module' => $modulePath ];
+               }
+
+               $path = [ $tag . 's' ];
                $existing = $this->result->getResultData( $path );
                if ( $existing === null || !in_array( $value, $existing ) ) {
                        $flags = ApiResult::NO_SIZE_CHECK;
@@ -243,19 +307,19 @@ class ApiErrorFormatter_BackCompat extends ApiErrorFormatter {
                parent::__construct( $result, Language::factory( 'en' ), 'none', false );
        }
 
-       public function arrayFromStatus( Status $status, $type = 'error', $format = null ) {
-               if ( $status->isGood() || !$status->errors ) {
+       public function arrayFromStatus( StatusValue $status, $type = 'error', $format = null ) {
+               if ( $status->isGood() || !$status->getErrors() ) {
                        return [];
                }
 
                $result = [];
                foreach ( $status->getErrorsByType( $type ) as $error ) {
-                       if ( $error['message'] instanceof Message ) {
-                               $error = [
-                                       'message' => $error['message']->getKey(),
-                                       'params' => $error['message']->getParams(),
-                               ] + $error;
-                       }
+                       $msg = ApiMessage::create( $error );
+                       $error = [
+                               'message' => $msg->getKey(),
+                               'params' => $msg->getParams(),
+                               'code' => $msg->getApiCode(),
+                       ] + $error;
                        ApiResult::setIndexedTagName( $error['params'], 'param' );
                        $result[] = $error;
                }
@@ -264,24 +328,32 @@ class ApiErrorFormatter_BackCompat extends ApiErrorFormatter {
                return $result;
        }
 
-       protected function addWarningOrError( $tag, $moduleName, $msg ) {
-               $value = $msg->plain();
+       protected function formatMessageInternal( $msg, $format ) {
+               return [
+                       'code' => $msg->getApiCode(),
+                       'info' => $msg->text(),
+               ] + $msg->getApiData();
+       }
+
+       protected function addWarningOrError( $tag, $modulePath, $msg ) {
+               $value = self::stripMarkup( $msg->text() );
 
                if ( $tag === 'error' ) {
                        // In BC mode, only one error
-                       $code = $msg->getApiCode();
-                       if ( isset( ApiBase::$messageMap[$code] ) ) {
-                               // Backwards compatibility
-                               $code = ApiBase::$messageMap[$code]['code'];
-                       }
-
                        $value = [
-                               'code' => $code,
+                               'code' => $msg->getApiCode(),
                                'info' => $value,
                        ] + $msg->getApiData();
                        $this->result->addValue( null, 'error', $value,
                                ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
                } else {
+                       if ( $modulePath === null ) {
+                               $moduleName = 'unknown';
+                       } else {
+                               $i = strrpos( $modulePath, '+' );
+                               $moduleName = $i === false ? $modulePath : substr( $modulePath, $i + 1 );
+                       }
+
                        // Don't add duplicate warnings
                        $tag .= 's';
                        $path = [ $tag, $moduleName ];
index 10fb182..6f7cf65 100644 (file)
@@ -42,11 +42,9 @@ class ApiExpandTemplates extends ApiBase {
                $this->requireMaxOneParameter( $params, 'prop', 'generatexml' );
 
                if ( $params['prop'] === null ) {
-                       $this->logFeatureUsage( 'action=expandtemplates&!prop' );
-                       $this->setWarning( 'Because no values have been specified for the prop parameter, a ' .
-                               'legacy format has been used for the output. This format is deprecated, and in ' .
-                               'the future, a default value will be set for the prop parameter, causing the new' .
-                               'format to always be used.' );
+                       $this->addDeprecation(
+                               'apiwarn-deprecation-expandtemplates-prop', 'action=expandtemplates&!prop'
+                       );
                        $prop = [];
                } else {
                        $prop = array_flip( $params['prop'] );
@@ -57,13 +55,13 @@ class ApiExpandTemplates extends ApiBase {
                if ( $revid !== null ) {
                        $rev = Revision::newFromId( $revid );
                        if ( !$rev ) {
-                               $this->dieUsage( "There is no revision ID $revid", 'missingrev' );
+                               $this->dieWithError( [ 'apierror-nosuchrevid', $revid ] );
                        }
                        $title_obj = $rev->getTitle();
                } else {
                        $title_obj = Title::newFromText( $params['title'] );
                        if ( !$title_obj || $title_obj->isExternal() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $params['title'] ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
                        }
                }
 
@@ -161,9 +159,7 @@ class ApiExpandTemplates extends ApiBase {
                                }
                                if ( isset( $prop['modules'] ) &&
                                        !isset( $prop['jsconfigvars'] ) && !isset( $prop['encodedjsconfigvars'] ) ) {
-                                       $this->setWarning( "Property 'modules' was set but not 'jsconfigvars' " .
-                                               "or 'encodedjsconfigvars'. Configuration variables are necessary " .
-                                               'for proper module usage.' );
+                                       $this->addWarning( 'apiwarn-moduleswithoutvars' );
                                }
                        }
                }
index c7dc303..97720c6 100644 (file)
@@ -43,16 +43,16 @@ class ApiFeedContributions extends ApiBase {
 
                $config = $this->getConfig();
                if ( !$config->get( 'Feed' ) ) {
-                       $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' );
+                       $this->dieWithError( 'feed-unavailable' );
                }
 
                $feedClasses = $config->get( 'FeedClasses' );
                if ( !isset( $feedClasses[$params['feedformat']] ) ) {
-                       $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' );
+                       $this->dieWithError( 'feed-invalid' );
                }
 
                if ( $params['showsizediff'] && $this->getConfig()->get( 'MiserMode' ) ) {
-                       $this->dieUsage( 'Size difference is disabled in Miser Mode', 'sizediffdisabled' );
+                       $this->dieWithError( 'apierror-sizediffdisabled' );
                }
 
                $msg = wfMessage( 'Contributions' )->inContentLanguage()->text();
index 813ac01..e0e50ed 100644 (file)
@@ -47,12 +47,12 @@ class ApiFeedRecentChanges extends ApiBase {
                $this->params = $this->extractRequestParams();
 
                if ( !$config->get( 'Feed' ) ) {
-                       $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' );
+                       $this->dieWithError( 'feed-unavailable' );
                }
 
                $feedClasses = $config->get( 'FeedClasses' );
                if ( !isset( $feedClasses[$this->params['feedformat']] ) ) {
-                       $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' );
+                       $this->dieWithError( 'feed-invalid' );
                }
 
                $this->getMain()->setCacheMode( 'public' );
@@ -98,7 +98,7 @@ class ApiFeedRecentChanges extends ApiBase {
                if ( $specialClass === 'SpecialRecentchangeslinked' ) {
                        $title = Title::newFromText( $this->params['target'] );
                        if ( !$title ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $this->params['target'] ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $this->params['target'] ) ] );
                        }
 
                        $feed = new ChangesFeed( $feedFormat, false );
index af5b1af..b9bb761 100644 (file)
@@ -56,11 +56,11 @@ class ApiFeedWatchlist extends ApiBase {
                        $params = $this->extractRequestParams();
 
                        if ( !$config->get( 'Feed' ) ) {
-                               $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' );
+                               $this->dieWithError( 'feed-unavailable' );
                        }
 
                        if ( !isset( $feedClasses[$params['feedformat']] ) ) {
-                               $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' );
+                               $this->dieWithError( 'feed-invalid' );
                        }
 
                        // limit to the number of hours going from now back
@@ -151,15 +151,26 @@ class ApiFeedWatchlist extends ApiBase {
                        $msg = wfMessage( 'watchlist' )->inContentLanguage()->escaped();
                        $feed = new $feedClasses[$feedFormat] ( $feedTitle, $msg, $feedUrl );
 
-                       if ( $e instanceof UsageException ) {
-                               $errorCode = $e->getCodeString();
+                       if ( $e instanceof ApiUsageException ) {
+                               foreach ( $e->getStatusValue()->getErrors() as $error ) {
+                                       $msg = ApiMessage::create( $error )
+                                               ->inLanguage( $this->getLanguage() );
+                                       $errorTitle = $this->msg( 'api-feed-error-title', $msg->getApiCode() );
+                                       $errorText = $msg->text();
+                                       $feedItems[] = new FeedItem( $errorTitle, $errorText, '', '', '' );
+                               }
                        } else {
-                               // Something is seriously wrong
-                               $errorCode = 'internal_api_error';
+                               if ( $e instanceof UsageException ) {
+                                       $errorCode = $e->getCodeString();
+                               } else {
+                                       // Something is seriously wrong
+                                       $errorCode = 'internal_api_error';
+                               }
+                               $errorTitle = $this->msg( 'api-feed-error-title', $msg->getApiCode() );
+                               $errorText = $e->getMessage();
+                               $feedItems[] = new FeedItem( $errorTitle, $errorText, '', '', '' );
                        }
 
-                       $errorText = $e->getMessage();
-                       $feedItems[] = new FeedItem( "Error ($errorCode)", $errorText, '', '', '' );
                        ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems );
                }
        }
index 97464d6..736898e 100644 (file)
@@ -45,7 +45,7 @@ class ApiFileRevert extends ApiBase {
                $this->validateParameters();
 
                // Check whether we're allowed to revert this file
-               $this->checkPermissions( $this->getUser() );
+               $this->checkTitleUserPermissions( $this->file->getTitle(), [ 'edit', 'upload' ] );
 
                $sourceUrl = $this->file->getArchiveVirtualUrl( $this->archiveName );
                $status = $this->file->upload(
@@ -70,23 +70,6 @@ class ApiFileRevert extends ApiBase {
                $this->getResult()->addValue( null, $this->getModuleName(), $result );
        }
 
-       /**
-        * Checks that the user has permissions to perform this revert.
-        * Dies with usage message on inadequate permissions.
-        * @param User $user The user to check.
-        */
-       protected function checkPermissions( $user ) {
-               $title = $this->file->getTitle();
-               $permissionErrors = array_merge(
-                       $title->getUserPermissionsErrors( 'edit', $user ),
-                       $title->getUserPermissionsErrors( 'upload', $user )
-               );
-
-               if ( $permissionErrors ) {
-                       $this->dieUsageMsg( $permissionErrors[0] );
-               }
-       }
-
        /**
         * Validate the user parameters and set $this->archiveName and $this->file.
         * Throws an error if validation fails
@@ -95,21 +78,23 @@ class ApiFileRevert extends ApiBase {
                // Validate the input title
                $title = Title::makeTitleSafe( NS_FILE, $this->params['filename'] );
                if ( is_null( $title ) ) {
-                       $this->dieUsageMsg( [ 'invalidtitle', $this->params['filename'] ] );
+                       $this->dieWithError(
+                               [ 'apierror-invalidtitle', wfEscapeWikiText( $this->params['filename'] ) ]
+                       );
                }
                $localRepo = RepoGroup::singleton()->getLocalRepo();
 
                // Check if the file really exists
                $this->file = $localRepo->newFile( $title );
                if ( !$this->file->exists() ) {
-                       $this->dieUsageMsg( 'notanarticle' );
+                       $this->dieWithError( 'apierror-missingtitle' );
                }
 
                // Check if the archivename is valid for this file
                $this->archiveName = $this->params['archivename'];
                $oldFile = $localRepo->newFromArchiveName( $title, $this->archiveName );
                if ( !$oldFile->exists() ) {
-                       $this->dieUsageMsg( 'filerevert-badversion' );
+                       $this->dieWithError( 'filerevert-badversion' );
                }
        }
 
index 2e917e1..8ebfe48 100644 (file)
@@ -84,8 +84,8 @@ class ApiFormatJson extends ApiFormatBase {
                                        break;
 
                                default:
-                                       $this->dieUsage( __METHOD__ .
-                                               ': Unknown value for \'formatversion\'', 'unknownformatversion' );
+                                       // Should have been caught during parameter validation
+                                       $this->dieDebug( __METHOD__, 'Unknown value for \'formatversion\'' );
                        }
                }
                $data = $this->getResult()->getResultData( null, $transform );
index fc25f47..a744f57 100644 (file)
@@ -55,7 +55,8 @@ class ApiFormatPhp extends ApiFormatBase {
                                break;
 
                        default:
-                               $this->dieUsage( __METHOD__ . ': Unknown value for \'formatversion\'', 'unknownformatversion' );
+                               // Should have been caught during parameter validation
+                               $this->dieDebug( __METHOD__, 'Unknown value for \'formatversion\'' );
                }
                $text = serialize( $this->getResult()->getResultData( null, $transforms ) );
 
@@ -67,11 +68,7 @@ class ApiFormatPhp extends ApiFormatBase {
                        in_array( 'wfOutputHandler', ob_list_handlers(), true ) &&
                        preg_match( '/\<\s*cross-domain-policy(?=\s|\>)/i', $text )
                ) {
-                       $this->dieUsage(
-                               'This response cannot be represented using format=php. ' .
-                               'See https://phabricator.wikimedia.org/T68776',
-                               'internalerror'
-                       );
+                       $this->dieWithError( 'apierror-formatphp', 'internalerror' );
                }
 
                $this->printText( $text );
index 9da040c..228b47e 100644 (file)
@@ -49,7 +49,7 @@ class ApiFormatRaw extends ApiFormatBase {
        public function getMimeType() {
                $data = $this->getResult()->getResultData();
 
-               if ( isset( $data['error'] ) ) {
+               if ( isset( $data['error'] ) || isset( $data['errors'] ) ) {
                        return $this->errorFallback->getMimeType();
                }
 
@@ -62,7 +62,7 @@ class ApiFormatRaw extends ApiFormatBase {
 
        public function initPrinter( $unused = false ) {
                $data = $this->getResult()->getResultData();
-               if ( isset( $data['error'] ) ) {
+               if ( isset( $data['error'] ) || isset( $data['errors'] ) ) {
                        $this->errorFallback->initPrinter( $unused );
                        if ( $this->mFailWithHTTPError ) {
                                $this->getMain()->getRequest()->response()->statusHeader( 400 );
@@ -74,7 +74,7 @@ class ApiFormatRaw extends ApiFormatBase {
 
        public function closePrinter() {
                $data = $this->getResult()->getResultData();
-               if ( isset( $data['error'] ) ) {
+               if ( isset( $data['error'] ) || isset( $data['errors'] ) ) {
                        $this->errorFallback->closePrinter();
                } else {
                        parent::closePrinter();
@@ -83,7 +83,7 @@ class ApiFormatRaw extends ApiFormatBase {
 
        public function execute() {
                $data = $this->getResult()->getResultData();
-               if ( isset( $data['error'] ) ) {
+               if ( isset( $data['error'] ) || isset( $data['errors'] ) ) {
                        $this->errorFallback->execute();
                        return;
                }
index a45dbeb..e4dfda0 100644 (file)
@@ -269,17 +269,17 @@ class ApiFormatXml extends ApiFormatBase {
        protected function addXslt() {
                $nt = Title::newFromText( $this->mXslt );
                if ( is_null( $nt ) || !$nt->exists() ) {
-                       $this->setWarning( 'Invalid or non-existent stylesheet specified' );
+                       $this->addWarning( 'apiwarn-invalidxmlstylesheet' );
 
                        return;
                }
                if ( $nt->getNamespace() != NS_MEDIAWIKI ) {
-                       $this->setWarning( 'Stylesheet should be in the MediaWiki namespace.' );
+                       $this->addWarning( 'apiwarn-invalidxmlstylesheetns' );
 
                        return;
                }
                if ( substr( $nt->getText(), -4 ) !== '.xsl' ) {
-                       $this->setWarning( 'Stylesheet should have .xsl extension.' );
+                       $this->addWarning( 'apiwarn-invalidxmlstylesheetext' );
 
                        return;
                }
index 02efd7b..2a6c938 100644 (file)
@@ -645,6 +645,20 @@ class ApiHelp extends ApiBase {
                                                        if ( $extra ) {
                                                                $info[] = implode( ' ', $extra );
                                                        }
+
+                                                       $allowAll = isset( $settings[ApiBase::PARAM_ALL] )
+                                                               ? $settings[ApiBase::PARAM_ALL]
+                                                               : false;
+                                                       if ( $allowAll || $settings[ApiBase::PARAM_TYPE] === 'namespace' ) {
+                                                               if ( $settings[ApiBase::PARAM_TYPE] === 'namespace' ) {
+                                                                       $allSpecifier = ApiBase::ALL_DEFAULT_STRING;
+                                                               } else {
+                                                                       $allSpecifier = ( is_string( $allowAll ) ? $allowAll : ApiBase::ALL_DEFAULT_STRING );
+                                                               }
+                                                               $info[] = $context->msg( 'api-help-param-multi-all' )
+                                                                       ->params( $allSpecifier )
+                                                                       ->parse();
+                                                       }
                                                }
                                        }
 
index 37cb80a..72fb16d 100644 (file)
@@ -56,23 +56,29 @@ class ApiImageRotate extends ApiBase {
                        $file = wfFindFile( $title, [ 'latest' => true ] );
                        if ( !$file ) {
                                $r['result'] = 'Failure';
-                               $r['errormessage'] = 'File does not exist';
+                               $r['errors'] = $this->getErrorFormatter()->arrayFromStatus(
+                                       Status::newFatal( 'apierror-filedoesnotexist' )
+                               );
                                $result[] = $r;
                                continue;
                        }
                        $handler = $file->getHandler();
                        if ( !$handler || !$handler->canRotate() ) {
                                $r['result'] = 'Failure';
-                               $r['errormessage'] = 'File type cannot be rotated';
+                               $r['errors'] = $this->getErrorFormatter()->arrayFromStatus(
+                                       Status::newFatal( 'apierror-filetypecannotberotated' )
+                               );
                                $result[] = $r;
                                continue;
                        }
 
                        // Check whether we're allowed to rotate this file
-                       $permError = $this->checkPermissions( $this->getUser(), $file->getTitle() );
-                       if ( $permError !== null ) {
+                       $permError = $this->checkTitleUserPermissions( $file->getTitle(), [ 'edit', 'upload' ] );
+                       if ( $permError ) {
                                $r['result'] = 'Failure';
-                               $r['errormessage'] = $permError;
+                               $r['errors'] = $this->getErrorFormatter()->arrayFromStatus(
+                                       $this->errorArrayToStatus( $permError )
+                               );
                                $result[] = $r;
                                continue;
                        }
@@ -80,7 +86,9 @@ class ApiImageRotate extends ApiBase {
                        $srcPath = $file->getLocalRefPath();
                        if ( $srcPath === false ) {
                                $r['result'] = 'Failure';
-                               $r['errormessage'] = 'Cannot get local file path';
+                               $r['errors'] = $this->getErrorFormatter()->arrayFromStatus(
+                                       Status::newFatal( 'apierror-filenopath' )
+                               );
                                $result[] = $r;
                                continue;
                        }
@@ -102,11 +110,13 @@ class ApiImageRotate extends ApiBase {
                                        $r['result'] = 'Success';
                                } else {
                                        $r['result'] = 'Failure';
-                                       $r['errormessage'] = $this->getErrorFormatter()->arrayFromStatus( $status );
+                                       $r['errors'] = $this->getErrorFormatter()->arrayFromStatus( $status );
                                }
                        } else {
                                $r['result'] = 'Failure';
-                               $r['errormessage'] = $err->toText();
+                               $r['errors'] = $this->getErrorFormatter()->arrayFromStatus(
+                                       Status::newFatal( ApiMessage::create( $err->getMsg() ) )
+                               );
                        }
                        $result[] = $r;
                }
@@ -130,28 +140,6 @@ class ApiImageRotate extends ApiBase {
                return $this->mPageSet;
        }
 
-       /**
-        * Checks that the user has permissions to perform rotations.
-        * @param User $user The user to check
-        * @param Title $title
-        * @return string|null Permission error message, or null if there is no error
-        */
-       protected function checkPermissions( $user, $title ) {
-               $permissionErrors = array_merge(
-                       $title->getUserPermissionsErrors( 'edit', $user ),
-                       $title->getUserPermissionsErrors( 'upload', $user )
-               );
-
-               if ( $permissionErrors ) {
-                       // Just return the first error
-                       $msg = $this->parseMsg( $permissionErrors[0] );
-
-                       return $msg['info'];
-               }
-
-               return null;
-       }
-
        public function mustBePosted() {
                return true;
        }
index 10106ff..3f48f38 100644 (file)
@@ -42,10 +42,10 @@ class ApiImport extends ApiBase {
                $isUpload = false;
                if ( isset( $params['interwikisource'] ) ) {
                        if ( !$user->isAllowed( 'import' ) ) {
-                               $this->dieUsageMsg( 'cantimport' );
+                               $this->dieWithError( 'apierror-cantimport' );
                        }
                        if ( !isset( $params['interwikipage'] ) ) {
-                               $this->dieUsageMsg( [ 'missingparam', 'interwikipage' ] );
+                               $this->dieWithError( [ 'apierror-missingparam', 'interwikipage' ] );
                        }
                        $source = ImportStreamSource::newFromInterwiki(
                                $params['interwikisource'],
@@ -56,7 +56,7 @@ class ApiImport extends ApiBase {
                } else {
                        $isUpload = true;
                        if ( !$user->isAllowed( 'importupload' ) ) {
-                               $this->dieUsageMsg( 'cantimport-upload' );
+                               $this->dieWithError( 'apierror-cantimport-upload' );
                        }
                        $source = ImportStreamSource::newFromUpload( 'xml' );
                }
@@ -83,7 +83,7 @@ class ApiImport extends ApiBase {
                try {
                        $importer->doImport();
                } catch ( Exception $e ) {
-                       $this->dieUsageMsg( [ 'import-unknownerror', $e->getMessage() ] );
+                       $this->dieWithError( [ 'apierror-import-unknownerror', wfEscapeWikiText( $e->getMessage() ) ] );
                }
 
                $resultData = $reporter->getData();
index 1017607..9a21e76 100644 (file)
@@ -49,7 +49,7 @@ class ApiLinkAccount extends ApiBase {
 
        public function execute() {
                if ( !$this->getUser()->isLoggedIn() ) {
-                       $this->dieUsage( 'Must be logged in to link accounts', 'notloggedin' );
+                       $this->dieWithError( 'apierror-mustbeloggedin-linkaccounts', 'notloggedin' );
                }
 
                $params = $this->extractRequestParams();
@@ -60,8 +60,8 @@ class ApiLinkAccount extends ApiBase {
                        $bits = wfParseUrl( $params['returnurl'] );
                        if ( !$bits || $bits['scheme'] === '' ) {
                                $encParamName = $this->encodeParamName( 'returnurl' );
-                               $this->dieUsage(
-                                       "Invalid value '{$params['returnurl']}' for url parameter $encParamName",
+                               $this->dieWithError(
+                                       [ 'apierror-badurl', $encParamName, wfEscapeWikiText( $params['returnurl'] ) ],
                                        "badurl_{$encParamName}"
                                );
                        }
index 6ac261d..723dc33 100644 (file)
@@ -72,10 +72,11 @@ class ApiLogin extends ApiBase {
 
                try {
                        $this->requirePostedParameters( [ 'password', 'token' ] );
-               } catch ( UsageException $ex ) {
+               } catch ( ApiUsageException $ex ) {
                        // Make this a warning for now, upgrade to an error in 1.29.
-                       $this->setWarning( $ex->getMessage() );
-                       $this->logFeatureUsage( 'login-params-in-query-string' );
+                       foreach ( $ex->getStatusValue()->getErrors() as $error ) {
+                               $this->addDeprecation( $error, 'login-params-in-query-string' );
+                       }
                }
 
                $params = $this->extractRequestParams();
@@ -146,15 +147,10 @@ class ApiLogin extends ApiBase {
                        switch ( $res->status ) {
                                case AuthenticationResponse::PASS:
                                        if ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
-                                               $warn = 'Main-account login via action=login is deprecated and may stop working ' .
-                                                       'without warning.';
-                                               $warn .= ' To continue login with action=login, see [[Special:BotPasswords]].';
-                                               $warn .= ' To safely continue using main-account login, see action=clientlogin.';
+                                               $this->addDeprecation( 'apiwarn-deprecation-login-botpw', 'main-account-login' );
                                        } else {
-                                               $warn = 'Login via action=login is deprecated and may stop working without warning.';
-                                               $warn .= ' To safely log in, see action=clientlogin.';
+                                               $this->addDeprecation( 'apiwarn-deprecation-login-nobotpw', 'main-account-login' );
                                        }
-                                       $this->setWarning( $warn );
                                        $authRes = 'Success';
                                        $loginType = 'AuthManager';
                                        break;
@@ -194,16 +190,16 @@ class ApiLogin extends ApiBase {
 
                        case 'NeedToken':
                                $result['token'] = $token->toString();
-                               $this->setWarning( 'Fetching a token via action=login is deprecated. ' .
-                                  'Use action=query&meta=tokens&type=login instead.' );
-                               $this->logFeatureUsage( 'action=login&!lgtoken' );
+                               $this->addDeprecation( 'apiwarn-deprecation-login-token', 'action=login&!lgtoken' );
                                break;
 
                        case 'WrongToken':
                                break;
 
                        case 'Failed':
-                               $result['reason'] = $message->useDatabase( 'false' )->inLanguage( 'en' )->text();
+                               $result['reason'] = ApiErrorFormatter::stripMarkup(
+                                       $message->useDatabase( false )->inLanguage( 'en' )->text()
+                               );
                                break;
 
                        case 'Aborted':
index 6a26e2e..d5c28f1 100644 (file)
@@ -45,9 +45,11 @@ class ApiLogout extends ApiBase {
 
                // Make sure it's possible to log out
                if ( !$session->canSetUser() ) {
-                       $this->dieUsage(
-                               'Cannot log out when using ' .
-                                       $session->getProvider()->describe( Language::factory( 'en' ) ),
+                       $this->dieWithError(
+                               [
+                                       'cannotlogoutnow-text',
+                                       $session->getProvider()->describe( $this->getErrorFormatter()->getLanguage() )
+                               ],
                                'cannotlogout'
                        );
                }
index 38299b4..fe6ed41 100644 (file)
@@ -46,6 +46,11 @@ class ApiMain extends ApiBase {
         */
        const API_DEFAULT_FORMAT = 'jsonfm';
 
+       /**
+        * When no uselang parameter is given, this language will be used
+        */
+       const API_DEFAULT_USELANG = 'user';
+
        /**
         * List of available modules: action name => module class
         */
@@ -140,7 +145,7 @@ class ApiMain extends ApiBase {
         */
        private $mPrinter;
 
-       private $mModuleMgr, $mResult, $mErrorFormatter;
+       private $mModuleMgr, $mResult, $mErrorFormatter = null;
        /** @var ApiContinuationManager|null */
        private $mContinuationManager;
        private $mAction;
@@ -229,7 +234,11 @@ class ApiMain extends ApiBase {
                        }
                }
 
-               $uselang = $this->getParameter( 'uselang' );
+               $this->mResult = new ApiResult( $this->getConfig()->get( 'APIMaxResultSize' ) );
+
+               // Setup uselang. This doesn't use $this->getParameter()
+               // because we're not ready to handle errors yet.
+               $uselang = $request->getVal( 'uselang', self::API_DEFAULT_USELANG );
                if ( $uselang === 'user' ) {
                        // Assume the parent context is going to return the user language
                        // for uselang=user (see T85635).
@@ -247,6 +256,29 @@ class ApiMain extends ApiBase {
                        }
                }
 
+               // Set up the error formatter. This doesn't use $this->getParameter()
+               // because we're not ready to handle errors yet.
+               $errorFormat = $request->getVal( 'errorformat', 'bc' );
+               $errorLangCode = $request->getVal( 'errorlang', 'uselang' );
+               $errorsUseDB = $request->getCheck( 'errorsuselocal' );
+               if ( in_array( $errorFormat, [ 'plaintext', 'wikitext', 'html', 'raw', 'none' ], true ) ) {
+                       if ( $errorLangCode === 'uselang' ) {
+                               $errorLang = $this->getLanguage();
+                       } elseif ( $errorLangCode === 'content' ) {
+                               global $wgContLang;
+                               $errorLang = $wgContLang;
+                       } else {
+                               $errorLangCode = RequestContext::sanitizeLangCode( $errorLangCode );
+                               $errorLang = Language::factory( $errorLangCode );
+                       }
+                       $this->mErrorFormatter = new ApiErrorFormatter(
+                               $this->mResult, $errorLang, $errorFormat, $errorsUseDB
+                       );
+               } else {
+                       $this->mErrorFormatter = new ApiErrorFormatter_BackCompat( $this->mResult );
+               }
+               $this->mResult->setErrorFormatter( $this->getErrorFormatter() );
+
                $this->mModuleMgr = new ApiModuleManager( $this );
                $this->mModuleMgr->addModules( self::$Modules, 'action' );
                $this->mModuleMgr->addModules( $config->get( 'APIModules' ), 'action' );
@@ -255,9 +287,6 @@ class ApiMain extends ApiBase {
 
                Hooks::run( 'ApiMain::moduleManager', [ $this->mModuleMgr ] );
 
-               $this->mResult = new ApiResult( $this->getConfig()->get( 'APIMaxResultSize' ) );
-               $this->mErrorFormatter = new ApiErrorFormatter_BackCompat( $this->mResult );
-               $this->mResult->setErrorFormatter( $this->mErrorFormatter );
                $this->mContinuationManager = null;
                $this->mEnableWrite = $enableWrite;
 
@@ -464,7 +493,9 @@ class ApiMain extends ApiBase {
        public function createPrinterByName( $format ) {
                $printer = $this->mModuleMgr->getModule( $format, 'format' );
                if ( $printer === null ) {
-                       $this->dieUsage( "Unrecognized format: {$format}", 'unknown_format' );
+                       $this->dieWithError(
+                               [ 'apierror-unknownformat', wfEscapeWikiText( $format ) ], 'unknown_format'
+                       );
                }
 
                return $printer;
@@ -542,7 +573,7 @@ class ApiMain extends ApiBase {
         */
        protected function handleException( Exception $e ) {
                // Bug 63145: Rollback any open database transactions
-               if ( !( $e instanceof UsageException ) ) {
+               if ( !( $e instanceof ApiUsageException || $e instanceof UsageException ) ) {
                        // UsageExceptions are intentional, so don't rollback if that's the case
                        try {
                                MWExceptionHandler::rollbackMasterChangesAndLog( $e );
@@ -557,7 +588,7 @@ class ApiMain extends ApiBase {
                Hooks::run( 'ApiMain::onException', [ $this, $e ] );
 
                // Log it
-               if ( !( $e instanceof UsageException ) ) {
+               if ( !( $e instanceof ApiUsageException || $e instanceof UsageException ) ) {
                        MWExceptionHandler::logException( $e );
                }
 
@@ -565,13 +596,13 @@ class ApiMain extends ApiBase {
                // If this fails, an unhandled exception should be thrown so that global error
                // handler will process and log it.
 
-               $errCode = $this->substituteResultWithError( $e );
+               $errCodes = $this->substituteResultWithError( $e );
 
                // Error results should not be cached
                $this->setCacheMode( 'private' );
 
                $response = $this->getRequest()->response();
-               $headerStr = 'MediaWiki-API-Error: ' . $errCode;
+               $headerStr = 'MediaWiki-API-Error: ' . join( ', ', $errCodes );
                $response->header( $headerStr );
 
                // Reset and print just the error message
@@ -580,14 +611,31 @@ class ApiMain extends ApiBase {
                // Printer may not be initialized if the extractRequestParams() fails for the main module
                $this->createErrorPrinter();
 
+               $failed = false;
                try {
                        $this->printResult( $e->getCode() );
+               } catch ( ApiUsageException $ex ) {
+                       // The error printer itself is failing. Try suppressing its request
+                       // parameters and redo.
+                       $failed = true;
+                       $this->addWarning( 'apiwarn-errorprinterfailed' );
+                       foreach ( $ex->getStatusValue()->getErrors() as $error ) {
+                               try {
+                                       $this->mPrinter->addWarning( $error );
+                               } catch ( Exception $ex2 ) {
+                                       // WTF?
+                                       $this->addWarning( $error );
+                               }
+                       }
                } catch ( UsageException $ex ) {
                        // The error printer itself is failing. Try suppressing its request
                        // parameters and redo.
-                       $this->setWarning(
-                               'Error printer failed (will retry without params): ' . $ex->getMessage()
+                       $failed = true;
+                       $this->addWarning(
+                               [ 'apiwarn-errorprinterfailed-ex', $ex->getMessage() ], 'errorprinterfailed'
                        );
+               }
+               if ( $failed ) {
                        $this->mPrinter = null;
                        $this->createErrorPrinter();
                        $this->mPrinter->forceDefaultParams();
@@ -958,99 +1006,145 @@ class ApiMain extends ApiBase {
        /**
         * Create an error message for the given exception.
         *
-        * If the exception is a UsageException then
-        * UsageException::getMessageArray() will be called to create the message.
+        * If an ApiUsageException, errors/warnings will be extracted from the
+        * embedded StatusValue.
+        *
+        * If a base UsageException, the getMessageArray() method will be used to
+        * extract the code and English message for a single error (no warnings).
+        *
+        * Any other exception will be returned with a generic code and wrapper
+        * text around the exception's (presumably English) message as a single
+        * error (no warnings).
         *
         * @param Exception $e
-        * @return array ['code' => 'some string', 'info' => 'some other string']
+        * @param string $type 'error' or 'warning'
+        * @return ApiMessage[]
         * @since 1.27
         */
-       protected function errorMessageFromException( $e ) {
-               if ( $e instanceof UsageException ) {
+       protected function errorMessagesFromException( $e, $type = 'error' ) {
+               $messages = [];
+               if ( $e instanceof ApiUsageException ) {
+                       foreach ( $e->getStatusValue()->getErrorsByType( $type ) as $error ) {
+                               $messages[] = ApiMessage::create( $error );
+                       }
+               } elseif ( $type !== 'error' ) {
+                       // None of the rest have any messages for non-error types
+               } elseif ( $e instanceof UsageException ) {
                        // User entered incorrect parameters - generate error response
-                       $errMessage = $e->getMessageArray();
+                       $data = $e->getMessageArray();
+                       $code = $data['code'];
+                       $info = $data['info'];
+                       unset( $data['code'], $data['info'] );
+                       $messages[] = new ApiRawMessage( [ '$1', $info ], $code, $data );
                } else {
-                       $config = $this->getConfig();
                        // Something is seriously wrong
+                       $config = $this->getConfig();
+                       $code = 'internal_api_error_' . get_class( $e );
                        if ( ( $e instanceof DBQueryError ) && !$config->get( 'ShowSQLErrors' ) ) {
-                               $info = 'Database query error';
+                               $params = [ 'apierror-databaseerror', WebRequest::getRequestId() ];
                        } else {
-                               $info = "Exception Caught: {$e->getMessage()}";
+                               $params = [
+                                       'apierror-exceptioncaught',
+                                       WebRequest::getRequestId(),
+                                       wfEscapeWikiText( $e->getMessage() )
+                               ];
                        }
-
-                       $errMessage = [
-                               'code' => 'internal_api_error_' . get_class( $e ),
-                               'info' => '[' . WebRequest::getRequestId() . '] ' . $info,
-                       ];
+                       $messages[] = ApiMessage::create( $params, $code );
                }
-               return $errMessage;
+               return $messages;
        }
 
        /**
         * Replace the result data with the information about an exception.
-        * Returns the error code
         * @param Exception $e
-        * @return string
+        * @return string[] Error codes
         */
        protected function substituteResultWithError( $e ) {
                $result = $this->getResult();
+               $formatter = $this->getErrorFormatter();
                $config = $this->getConfig();
+               $errorCodes = [];
 
-               $errMessage = $this->errorMessageFromException( $e );
-               if ( $e instanceof UsageException ) {
-                       // User entered incorrect parameters - generate error response
+               // Remember existing warnings and errors across the reset
+               $errors = $result->getResultData( [ 'errors' ] );
+               $warnings = $result->getResultData( [ 'warnings' ] );
+               $result->reset();
+               if ( $warnings !== null ) {
+                       $result->addValue( null, 'warnings', $warnings, ApiResult::NO_SIZE_CHECK );
+               }
+               if ( $errors !== null ) {
+                       $result->addValue( null, 'errors', $errors, ApiResult::NO_SIZE_CHECK );
+
+                       // Collect the copied error codes for the return value
+                       foreach ( $errors as $error ) {
+                               if ( isset( $error['code'] ) ) {
+                                       $errorCodes[$error['code']] = true;
+                               }
+                       }
+               }
+
+               // Add errors from the exception
+               $modulePath = $e instanceof ApiUsageException ? $e->getModulePath() : null;
+               foreach ( $this->errorMessagesFromException( $e, 'error' ) as $msg ) {
+                       $errorCodes[$msg->getApiCode()] = true;
+                       $formatter->addError( $modulePath, $msg );
+               }
+               foreach ( $this->errorMessagesFromException( $e, 'warning' ) as $msg ) {
+                       $formatter->addWarning( $modulePath, $msg );
+               }
+
+               // Add additional data. Path depends on whether we're in BC mode or not.
+               // Data depends on the type of exception.
+               if ( $formatter instanceof ApiErrorFormatter_BackCompat ) {
+                       $path = [ 'error' ];
+               } else {
+                       $path = null;
+               }
+               if ( $e instanceof ApiUsageException || $e instanceof UsageException ) {
                        $link = wfExpandUrl( wfScript( 'api' ) );
-                       ApiResult::setContentValue( $errMessage, 'docref', "See $link for API usage" );
+                       $result->addContentValue(
+                               $path,
+                               'docref',
+                               $this->msg( 'api-usage-docref', $link )->inLanguage( $formatter->getLanguage() )->text()
+                       );
                } else {
-                       // Something is seriously wrong
                        if ( $config->get( 'ShowExceptionDetails' ) ) {
-                               ApiResult::setContentValue(
-                                       $errMessage,
+                               $result->addContentValue(
+                                       $path,
                                        'trace',
-                                       MWExceptionHandler::getRedactedTraceAsString( $e )
+                                       $this->msg( 'api-exception-trace',
+                                               get_class( $e ),
+                                               $e->getFile(),
+                                               $e->getLine(),
+                                               MWExceptionHandler::getRedactedTraceAsString( $e )
+                                       )->inLanguage( $formatter->getLanguage() )->text()
                                );
                        }
                }
 
-               // Remember all the warnings to re-add them later
-               $warnings = $result->getResultData( [ 'warnings' ] );
+               // Add the id and such
+               $this->addRequestedFields( [ 'servedby' ] );
 
-               $result->reset();
-               // Re-add the id
-               $requestid = $this->getParameter( 'requestid' );
-               if ( !is_null( $requestid ) ) {
-                       $result->addValue( null, 'requestid', $requestid, ApiResult::NO_SIZE_CHECK );
-               }
-               if ( $config->get( 'ShowHostnames' ) ) {
-                       // servedby is especially useful when debugging errors
-                       $result->addValue( null, 'servedby', wfHostname(), ApiResult::NO_SIZE_CHECK );
-               }
-               if ( $warnings !== null ) {
-                       $result->addValue( null, 'warnings', $warnings, ApiResult::NO_SIZE_CHECK );
-               }
-
-               $result->addValue( null, 'error', $errMessage, ApiResult::NO_SIZE_CHECK );
-
-               return $errMessage['code'];
+               return array_keys( $errorCodes );
        }
 
        /**
-        * Set up for the execution.
-        * @return array
+        * Add requested fields to the result
+        * @param string[] $force Which fields to force even if not requested. Accepted values are:
+        *  - servedby
         */
-       protected function setupExecuteAction() {
-               // First add the id to the top element
+       protected function addRequestedFields( $force = [] ) {
                $result = $this->getResult();
+
                $requestid = $this->getParameter( 'requestid' );
-               if ( !is_null( $requestid ) ) {
-                       $result->addValue( null, 'requestid', $requestid );
+               if ( $requestid !== null ) {
+                       $result->addValue( null, 'requestid', $requestid, ApiResult::NO_SIZE_CHECK );
                }
 
-               if ( $this->getConfig()->get( 'ShowHostnames' ) ) {
-                       $servedby = $this->getParameter( 'servedby' );
-                       if ( $servedby ) {
-                               $result->addValue( null, 'servedby', wfHostname() );
-                       }
+               if ( $this->getConfig()->get( 'ShowHostnames' ) && (
+                       in_array( 'servedby', $force, true ) || $this->getParameter( 'servedby' )
+               ) ) {
+                       $result->addValue( null, 'servedby', wfHostname(), ApiResult::NO_SIZE_CHECK );
                }
 
                if ( $this->getParameter( 'curtimestamp' ) ) {
@@ -1058,13 +1152,23 @@ class ApiMain extends ApiBase {
                                ApiResult::NO_SIZE_CHECK );
                }
 
-               $params = $this->extractRequestParams();
+               if ( $this->getParameter( 'responselanginfo' ) ) {
+                       $result->addValue( null, 'uselang', $this->getLanguage()->getCode(),
+                               ApiResult::NO_SIZE_CHECK );
+                       $result->addValue( null, 'errorlang', $this->getErrorFormatter()->getLanguage()->getCode(),
+                               ApiResult::NO_SIZE_CHECK );
+               }
+       }
 
-               $this->mAction = $params['action'];
+       /**
+        * Set up for the execution.
+        * @return array
+        */
+       protected function setupExecuteAction() {
+               $this->addRequestedFields();
 
-               if ( !is_string( $this->mAction ) ) {
-                       $this->dieUsage( 'The API requires a valid action parameter', 'unknown_action' );
-               }
+               $params = $this->extractRequestParams();
+               $this->mAction = $params['action'];
 
                return $params;
        }
@@ -1073,13 +1177,15 @@ class ApiMain extends ApiBase {
         * Set up the module for response
         * @return ApiBase The module that will handle this action
         * @throws MWException
-        * @throws UsageException
+        * @throws ApiUsageException
         */
        protected function setupModule() {
                // Instantiate the module requested by the user
                $module = $this->mModuleMgr->getModule( $this->mAction, 'action' );
                if ( $module === null ) {
-                       $this->dieUsage( 'The API requires a valid action parameter', 'unknown_action' );
+                       $this->dieWithError(
+                               [ 'apierror-unknownaction', wfEscapeWikiText( $this->mAction ) ], 'unknown_action'
+                       );
                }
                $moduleParams = $module->extractRequestParams();
 
@@ -1098,13 +1204,13 @@ class ApiMain extends ApiBase {
                        }
 
                        if ( !isset( $moduleParams['token'] ) ) {
-                               $this->dieUsageMsg( [ 'missingparam', 'token' ] );
+                               $module->dieWithError( [ 'apierror-missingparam', 'token' ] );
                        }
 
                        $module->requirePostedParameters( [ 'token' ] );
 
                        if ( !$module->validateToken( $moduleParams['token'], $moduleParams ) ) {
-                               $this->dieUsageMsg( 'sessionfailure' );
+                               $module->dieWithError( 'apierror-badtoken' );
                        }
                }
 
@@ -1128,10 +1234,10 @@ class ApiMain extends ApiBase {
                                $response->header( 'X-Database-Lag: ' . intval( $lag ) );
 
                                if ( $this->getConfig()->get( 'ShowHostnames' ) ) {
-                                       $this->dieUsage( "Waiting for $host: $lag seconds lagged", 'maxlag' );
+                                       $this->dieWithError( [ 'apierror-maxlag', $lag, $host ] );
                                }
 
-                               $this->dieUsage( "Waiting for a database server: $lag seconds lagged", 'maxlag' );
+                               $this->dieWithError( [ 'apierror-maxlag-generic', $lag ], 'maxlag' );
                        }
                }
 
@@ -1262,19 +1368,16 @@ class ApiMain extends ApiBase {
                if ( $module->isReadMode() && !User::isEveryoneAllowed( 'read' ) &&
                        !$user->isAllowed( 'read' )
                ) {
-                       $this->dieUsageMsg( 'readrequired' );
+                       $this->dieWithError( 'apierror-readapidenied' );
                }
 
                if ( $module->isWriteMode() ) {
                        if ( !$this->mEnableWrite ) {
-                               $this->dieUsageMsg( 'writedisabled' );
+                               $this->dieWithError( 'apierror-noapiwrite' );
                        } elseif ( !$user->isAllowed( 'writeapi' ) ) {
-                               $this->dieUsageMsg( 'writerequired' );
+                               $this->dieWithError( 'apierror-writeapidenied' );
                        } elseif ( $this->getRequest()->getHeader( 'Promise-Non-Write-API-Action' ) ) {
-                               $this->dieUsage(
-                                       'Promise-Non-Write-API-Action HTTP header cannot be sent to write API modules',
-                                       'promised-nonwrite-api'
-                               );
+                               $this->dieWithError( 'apierror-promised-nonwrite-api' );
                        }
 
                        $this->checkReadOnly( $module );
@@ -1283,7 +1386,7 @@ class ApiMain extends ApiBase {
                // Allow extensions to stop execution for arbitrary reasons.
                $message = false;
                if ( !Hooks::run( 'ApiCheckCanExecute', [ $module, $user, &$message ] ) ) {
-                       $this->dieUsageMsg( $message );
+                       $this->dieWithError( $message );
                }
        }
 
@@ -1329,12 +1432,9 @@ class ApiMain extends ApiBase {
                                "Api request failed as read only because the following DBs are lagged: $laggedServers"
                        );
 
-                       $parsed = $this->parseMsg( [ 'readonlytext' ] );
-                       $this->dieUsage(
-                               $parsed['info'],
-                               $parsed['code'],
-                               /* http error */
-                               0,
+                       $this->dieWithError(
+                               'readonly_lag',
+                               'readonly',
                                [ 'readonlyreason' => "Waiting for $numLagged lagged database(s)" ]
                        );
                }
@@ -1350,12 +1450,12 @@ class ApiMain extends ApiBase {
                        switch ( $params['assert'] ) {
                                case 'user':
                                        if ( $user->isAnon() ) {
-                                               $this->dieUsage( 'Assertion that the user is logged in failed', 'assertuserfailed' );
+                                               $this->dieWithError( 'apierror-assertuserfailed' );
                                        }
                                        break;
                                case 'bot':
                                        if ( !$user->isAllowed( 'bot' ) ) {
-                                               $this->dieUsage( 'Assertion that the user has the bot right failed', 'assertbotfailed' );
+                                               $this->dieWithError( 'apierror-assertbotfailed' );
                                        }
                                        break;
                        }
@@ -1363,9 +1463,8 @@ class ApiMain extends ApiBase {
                if ( isset( $params['assertuser'] ) ) {
                        $assertUser = User::newFromName( $params['assertuser'], false );
                        if ( !$assertUser || !$this->getUser()->equals( $assertUser ) ) {
-                               $this->dieUsage(
-                                       'Assertion that the user is "' . $params['assertuser'] . '" failed',
-                                       'assertnameduserfailed'
+                               $this->dieWithError(
+                                       [ 'apierror-assertnameduserfailed', wfEscapeWikiText( $params['assertuser'] ) ]
                                );
                        }
                }
@@ -1381,7 +1480,7 @@ class ApiMain extends ApiBase {
                if ( !$request->wasPosted() && $module->mustBePosted() ) {
                        // Module requires POST. GET request might still be allowed
                        // if $wgDebugApi is true, otherwise fail.
-                       $this->dieUsageMsgOrDebug( [ 'mustbeposted', $this->mAction ] );
+                       $this->dieWithErrorOrDebug( [ 'apierror-mustbeposted', $this->mAction ] );
                }
 
                // See if custom printer is used
@@ -1396,8 +1495,7 @@ class ApiMain extends ApiBase {
                        ( $this->getUser()->isLoggedIn() &&
                                $this->getUser()->requiresHTTPS() )
                ) ) {
-                       $this->logFeatureUsage( 'https-expected' );
-                       $this->setWarning( 'HTTP used when HTTPS was expected' );
+                       $this->addDeprecation( 'apiwarn-deprecation-httpsexpected', 'https-expected' );
                }
        }
 
@@ -1481,7 +1579,9 @@ class ApiMain extends ApiBase {
                ];
 
                if ( $e ) {
-                       $logCtx['errorCodes'][] = $this->errorMessageFromException( $e )['code'];
+                       foreach ( $this->errorMessagesFromException( $e ) as $msg ) {
+                               $logCtx['errorCodes'][] = $msg->getApiCode();
+                       }
                }
 
                // Construct space separated message for 'api' log channel
@@ -1560,9 +1660,7 @@ class ApiMain extends ApiBase {
                        if ( $this->getRequest()->getArray( $name ) !== null ) {
                                // See bug 10262 for why we don't just implode( '|', ... ) the
                                // array.
-                               $this->setWarning(
-                                       "Parameter '$name' uses unsupported PHP array syntax"
-                               );
+                               $this->addWarning( [ 'apiwarn-unsupportedarray', $name ] );
                        }
                        $ret = $default;
                }
@@ -1602,8 +1700,7 @@ class ApiMain extends ApiBase {
 
                if ( !$this->mInternalMode ) {
                        // Printer has not yet executed; don't warn that its parameters are unused
-                       $printerParams = array_map(
-                               [ $this->mPrinter, 'encodeParamName' ],
+                       $printerParams = $this->mPrinter->encodeParamName(
                                array_keys( $this->mPrinter->getFinalParams() ?: [] )
                        );
                        $unusedParams = array_diff( $allParams, $paramsUsed, $printerParams );
@@ -1612,8 +1709,11 @@ class ApiMain extends ApiBase {
                }
 
                if ( count( $unusedParams ) ) {
-                       $s = count( $unusedParams ) > 1 ? 's' : '';
-                       $this->setWarning( "Unrecognized parameter$s: '" . implode( $unusedParams, "', '" ) . "'" );
+                       $this->addWarning( [
+                               'apierror-unrecognizedparams',
+                               Message::listParam( array_map( 'wfEscapeWikiText', $unusedParams ), 'comma' ),
+                               count( $unusedParams )
+                       ] );
                }
        }
 
@@ -1624,7 +1724,7 @@ class ApiMain extends ApiBase {
         */
        protected function printResult( $httpCode = 0 ) {
                if ( $this->getConfig()->get( 'DebugAPI' ) !== false ) {
-                       $this->setWarning( 'SECURITY WARNING: $wgDebugAPI is enabled' );
+                       $this->addWarning( 'apiwarn-wgDebugAPI' );
                }
 
                $printer = $this->mPrinter;
@@ -1678,9 +1778,20 @@ class ApiMain extends ApiBase {
                        'requestid' => null,
                        'servedby' => false,
                        'curtimestamp' => false,
+                       'responselanginfo' => false,
                        'origin' => null,
                        'uselang' => [
-                               ApiBase::PARAM_DFLT => 'user',
+                               ApiBase::PARAM_DFLT => self::API_DEFAULT_USELANG,
+                       ],
+                       'errorformat' => [
+                               ApiBase::PARAM_TYPE => [ 'plaintext', 'wikitext', 'html', 'raw', 'none', 'bc' ],
+                               ApiBase::PARAM_DFLT => 'bc',
+                       ],
+                       'errorlang' => [
+                               ApiBase::PARAM_DFLT => 'uselang',
+                       ],
+                       'errorsuselocal' => [
+                               ApiBase::PARAM_DFLT => false,
                        ],
                ];
        }
@@ -1732,7 +1843,7 @@ class ApiMain extends ApiBase {
                        $help['permissions'] .= Html::rawElement( 'dd', null,
                                $this->msg( 'api-help-permissions-granted-to' )
                                        ->numParams( count( $groups ) )
-                                       ->params( $this->getLanguage()->commaList( $groups ) )
+                                       ->params( Message::listParam( $groups ) )
                                        ->parse()
                        );
                }
@@ -1831,70 +1942,6 @@ class ApiMain extends ApiBase {
        }
 }
 
-/**
- * This exception will be thrown when dieUsage is called to stop module execution.
- *
- * @ingroup API
- */
-class UsageException extends MWException {
-
-       private $mCodestr;
-
-       /**
-        * @var null|array
-        */
-       private $mExtraData;
-
-       /**
-        * @param string $message
-        * @param string $codestr
-        * @param int $code
-        * @param array|null $extradata
-        */
-       public function __construct( $message, $codestr, $code = 0, $extradata = null ) {
-               parent::__construct( $message, $code );
-               $this->mCodestr = $codestr;
-               $this->mExtraData = $extradata;
-
-               // This should never happen, so throw an exception about it that will
-               // hopefully get logged with a backtrace (T138585)
-               if ( !is_string( $codestr ) || $codestr === '' ) {
-                       throw new InvalidArgumentException( 'Invalid $codestr, was ' .
-                               ( $codestr === '' ? 'empty string' : gettype( $codestr ) )
-                       );
-               }
-       }
-
-       /**
-        * @return string
-        */
-       public function getCodeString() {
-               return $this->mCodestr;
-       }
-
-       /**
-        * @return array
-        */
-       public function getMessageArray() {
-               $result = [
-                       'code' => $this->mCodestr,
-                       'info' => $this->getMessage()
-               ];
-               if ( is_array( $this->mExtraData ) ) {
-                       $result = array_merge( $result, $this->mExtraData );
-               }
-
-               return $result;
-       }
-
-       /**
-        * @return string
-        */
-       public function __toString() {
-               return "{$this->getCodeString()}: {$this->getMessage()}";
-       }
-}
-
 /**
  * For really cool vim folding this needs to be at the end:
  * vim: foldmarker=@{,@} foldmethod=marker
index 617db22..3299f73 100644 (file)
@@ -32,11 +32,9 @@ class ApiManageTags extends ApiBase {
                if ( $params['operation'] !== 'delete'
                        && !$this->getUser()->isAllowed( 'managechangetags' )
                ) {
-                       $this->dieUsage( "You don't have permission to manage change tags",
-                               'permissiondenied' );
+                       $this->dieWithError( 'tags-manage-no-permission', 'permissiondenied' );
                } elseif ( !$this->getUser()->isAllowed( 'deletechangetags' ) ) {
-                       $this->dieUsage( "You don't have permission to delete change tags",
-                               'permissiondenied' );
+                       $this->dieWithError( 'tags-delete-no-permission', 'permissiondenied' );
                }
 
                $result = $this->getResult();
index 276f1c0..357698e 100644 (file)
@@ -42,24 +42,24 @@ class ApiMergeHistory extends ApiBase {
                if ( isset( $params['from'] ) ) {
                        $fromTitle = Title::newFromText( $params['from'] );
                        if ( !$fromTitle || $fromTitle->isExternal() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $params['from'] ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['from'] ) ] );
                        }
                } elseif ( isset( $params['fromid'] ) ) {
                        $fromTitle = Title::newFromID( $params['fromid'] );
                        if ( !$fromTitle ) {
-                               $this->dieUsageMsg( [ 'nosuchpageid', $params['fromid'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchpageid', $params['fromid'] ] );
                        }
                }
 
                if ( isset( $params['to'] ) ) {
                        $toTitle = Title::newFromText( $params['to'] );
                        if ( !$toTitle || $toTitle->isExternal() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $params['to'] ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['to'] ) ] );
                        }
                } elseif ( isset( $params['toid'] ) ) {
                        $toTitle = Title::newFromID( $params['toid'] );
                        if ( !$toTitle ) {
-                               $this->dieUsageMsg( [ 'nosuchpageid', $params['toid'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchpageid', $params['toid'] ] );
                        }
                }
 
index ae66778..9d69a77 100644 (file)
@@ -36,9 +36,10 @@ interface IApiMessage extends MessageSpecifier {
        /**
         * Returns a machine-readable code for use by the API
         *
-        * The message key is often sufficient, but sometimes there are multiple
-        * messages used for what is really the same underlying condition (e.g.
-        * badaccess-groups and badaccess-group0)
+        * If no code was specifically set, the message key is used as the code
+        * after removing "apiwarn-" or "apierror-" prefixes and applying
+        * backwards-compatibility mappings.
+        *
         * @return string
         */
        public function getApiCode();
@@ -51,7 +52,7 @@ interface IApiMessage extends MessageSpecifier {
 
        /**
         * Sets the machine-readable code for use by the API
-        * @param string|null $code If null, the message key should be returned by self::getApiCode()
+        * @param string|null $code If null, uses the default (see self::getApiCode())
         * @param array|null $data If non-null, passed to self::setApiData()
         */
        public function setApiCode( $code, array $data = null );
@@ -69,14 +70,95 @@ interface IApiMessage extends MessageSpecifier {
  * @ingroup API
  */
 trait ApiMessageTrait {
+
+       /**
+        * Compatibility code mappings for various MW messages.
+        * @todo Ideally anything relying on this should be changed to use ApiMessage.
+        */
+       protected static $messageMap = [
+               'actionthrottledtext' => 'ratelimited',
+               'autoblockedtext' => 'autoblocked',
+               'badaccess-group0' => 'permissiondenied',
+               'badaccess-groups' => 'permissiondenied',
+               'badipaddress' => 'invalidip',
+               'blankpage' => 'emptypage',
+               'blockedtext' => 'blocked',
+               'cannotdelete' => 'cantdelete',
+               'cannotundelete' => 'cantundelete',
+               'cantmove-titleprotected' => 'protectedtitle',
+               'cantrollback' => 'onlyauthor',
+               'confirmedittext' => 'confirmemail',
+               'content-not-allowed-here' => 'contentnotallowedhere',
+               'deleteprotected' => 'cantedit',
+               'delete-toobig' => 'bigdelete',
+               'edit-conflict' => 'editconflict',
+               'imagenocrossnamespace' => 'nonfilenamespace',
+               'imagetypemismatch' => 'filetypemismatch',
+               'importbadinterwiki' => 'badinterwiki',
+               'importcantopen' => 'cantopenfile',
+               'import-noarticle' => 'badinterwiki',
+               'importnofile' => 'nofile',
+               'importuploaderrorpartial' => 'partialupload',
+               'importuploaderrorsize' => 'filetoobig',
+               'importuploaderrortemp' => 'notempdir',
+               'ipb_already_blocked' => 'alreadyblocked',
+               'ipb_blocked_as_range' => 'blockedasrange',
+               'ipb_cant_unblock' => 'cantunblock',
+               'ipb_expiry_invalid' => 'invalidexpiry',
+               'ip_range_invalid' => 'invalidrange',
+               'mailnologin' => 'cantsend',
+               'markedaspatrollederror-noautopatrol' => 'noautopatrol',
+               'movenologintext' => 'cantmove-anon',
+               'movenotallowed' => 'cantmove',
+               'movenotallowedfile' => 'cantmovefile',
+               'namespaceprotected' => 'protectednamespace',
+               'nocreate-loggedin' => 'cantcreate',
+               'nocreatetext' => 'cantcreate-anon',
+               'noname' => 'invaliduser',
+               'nosuchusershort' => 'nosuchuser',
+               'notanarticle' => 'missingtitle',
+               'nouserspecified' => 'invaliduser',
+               'ns-specialprotected' => 'unsupportednamespace',
+               'protect-cantedit' => 'cantedit',
+               'protectedinterface' => 'protectednamespace-interface',
+               'protectedpagetext' => 'protectedpage',
+               'range_block_disabled' => 'rangedisabled',
+               'rcpatroldisabled' => 'patroldisabled',
+               'readonlytext' => 'readonly',
+               'sessionfailure' => 'badtoken',
+               'titleprotected' => 'protectedtitle',
+               'undo-failure' => 'undofailure',
+               'userrights-nodatabase' => 'nosuchdatabase',
+               'userrights-no-interwiki' => 'nointerwikiuserrights',
+       ];
+
        protected $apiCode = null;
        protected $apiData = [];
 
        public function getApiCode() {
-               return $this->apiCode === null ? $this->getKey() : $this->apiCode;
+               if ( $this->apiCode === null ) {
+                       $key = $this->getKey();
+                       if ( isset( self::$messageMap[$key] ) ) {
+                               $this->apiCode = self::$messageMap[$key];
+                       } elseif ( $key === 'apierror-missingparam' ) {
+                               /// @todo: Kill this case along with ApiBase::$messageMap
+                               $this->apiCode = 'no' . $this->getParams()[0];
+                       } elseif ( substr( $key, 0, 8 ) === 'apiwarn-' ) {
+                               $this->apiCode = substr( $key, 8 );
+                       } elseif ( substr( $key, 0, 9 ) === 'apierror-' ) {
+                               $this->apiCode = substr( $key, 9 );
+                       } else {
+                               $this->apiCode = $key;
+                       }
+               }
+               return $this->apiCode;
        }
 
        public function setApiCode( $code, array $data = null ) {
+               if ( $code !== null && !( is_string( $code ) && $code !== '' ) ) {
+                       throw new InvalidArgumentException( "Invalid code \"$code\"" );
+               }
+
                $this->apiCode = $code;
                if ( $data !== null ) {
                        $this->setApiData( $data );
@@ -124,9 +206,25 @@ class ApiMessage extends Message implements IApiMessage {
         * @param Message|RawMessage|array|string $msg
         * @param string|null $code
         * @param array|null $data
-        * @return ApiMessage
+        * @return IApiMessage
         */
        public static function create( $msg, $code = null, array $data = null ) {
+               if ( is_array( $msg ) ) {
+                       // From StatusValue
+                       if ( isset( $msg['message'] ) ) {
+                               if ( isset( $msg['params'] ) ) {
+                                       $msg = array_merge( [ $msg['message'] ], $msg['params'] );
+                               } else {
+                                       $msg = [ $msg['message'] ];
+                               }
+                       }
+
+                       // Weirdness that comes in sometimes, including the above
+                       if ( $msg[0] instanceof MessageSpecifier ) {
+                               $msg = $msg[0];
+                       }
+               }
+
                if ( $msg instanceof IApiMessage ) {
                        return $msg;
                } elseif ( $msg instanceof RawMessage ) {
@@ -143,7 +241,6 @@ class ApiMessage extends Message implements IApiMessage {
         *  - string: passed to Message::__construct
         * @param string|null $code
         * @param array|null $data
-        * @return ApiMessage
         */
        public function __construct( $msg, $code = null, array $data = null ) {
                if ( $msg instanceof Message ) {
@@ -158,8 +255,7 @@ class ApiMessage extends Message implements IApiMessage {
                } else {
                        parent::__construct( $msg );
                }
-               $this->apiCode = $code;
-               $this->apiData = (array)$data;
+               $this->setApiCode( $code, $data );
        }
 }
 
@@ -192,7 +288,6 @@ class ApiRawMessage extends RawMessage implements IApiMessage {
                } else {
                        parent::__construct( $msg );
                }
-               $this->apiCode = $code;
-               $this->apiData = (array)$data;
+               $this->setApiCode( $code, $data );
        }
 }
index 29e67b0..7c8aa90 100644 (file)
@@ -41,23 +41,23 @@ class ApiMove extends ApiBase {
                if ( isset( $params['from'] ) ) {
                        $fromTitle = Title::newFromText( $params['from'] );
                        if ( !$fromTitle || $fromTitle->isExternal() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $params['from'] ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['from'] ) ] );
                        }
                } elseif ( isset( $params['fromid'] ) ) {
                        $fromTitle = Title::newFromID( $params['fromid'] );
                        if ( !$fromTitle ) {
-                               $this->dieUsageMsg( [ 'nosuchpageid', $params['fromid'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchpageid', $params['fromid'] ] );
                        }
                }
 
                if ( !$fromTitle->exists() ) {
-                       $this->dieUsageMsg( 'notanarticle' );
+                       $this->dieWithError( 'apierror-missingtitle' );
                }
                $fromTalk = $fromTitle->getTalkPage();
 
                $toTitle = Title::newFromText( $params['to'] );
                if ( !$toTitle || $toTitle->isExternal() ) {
-                       $this->dieUsageMsg( [ 'invalidtitle', $params['to'] ] );
+                       $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['to'] ) ] );
                }
                $toTalk = $toTitle->getTalkPage();
 
@@ -66,15 +66,15 @@ class ApiMove extends ApiBase {
                        && wfFindFile( $toTitle )
                ) {
                        if ( !$params['ignorewarnings'] && $user->isAllowed( 'reupload-shared' ) ) {
-                               $this->dieUsageMsg( 'sharedfile-exists' );
+                               $this->dieWithError( 'apierror-fileexists-sharedrepo-perm' );
                        } elseif ( !$user->isAllowed( 'reupload-shared' ) ) {
-                               $this->dieUsageMsg( 'cantoverwrite-sharedfile' );
+                               $this->dieWithError( 'apierror-cantoverwrite-sharedfile' );
                        }
                }
 
                // Rate limit
                if ( $user->pingLimiter( 'move' ) ) {
-                       $this->dieUsageMsg( 'actionthrottledtext' );
+                       $this->dieWithError( 'apierror-ratelimited' );
                }
 
                // Move the page
@@ -108,10 +108,8 @@ class ApiMove extends ApiBase {
                                $r['talkto'] = $toTalk->getPrefixedText();
                                $r['talkmoveoverredirect'] = $toTalkExists;
                        } else {
-                               // We're not gonna dieUsage() on failure, since we already changed something
-                               $error = $this->getErrorFromStatus( $status );
-                               $r['talkmove-error-code'] = $error[0];
-                               $r['talkmove-error-info'] = $error[1];
+                               // We're not going to dieWithError() on failure, since we already changed something
+                               $r['talkmove-errors'] = $this->getErrorFormatter()->arrayFromStatus( $status );
                        }
                }
 
@@ -184,7 +182,8 @@ class ApiMove extends ApiBase {
                $retval = [];
                $success = $fromTitle->moveSubpages( $toTitle, true, $reason, !$noredirect );
                if ( isset( $success[0] ) ) {
-                       return [ 'error' => $this->parseMsg( $success ) ];
+                       $status = $this->errorArrayToStatus( $success );
+                       return [ 'errors' => $this->getErrorFormatter()->arrayFromStatus( $status ) ];
                }
 
                // At least some pages could be moved
@@ -192,7 +191,8 @@ class ApiMove extends ApiBase {
                foreach ( $success as $oldTitle => $newTitle ) {
                        $r = [ 'from' => $oldTitle ];
                        if ( is_array( $newTitle ) ) {
-                               $r['error'] = $this->parseMsg( reset( $newTitle ) );
+                               $status = $this->errorArrayToStatus( $newTitle );
+                               $r['errors'] = $this->getErrorFormatter()->arrayFromStatus( $status );
                        } else {
                                // Success
                                $r['to'] = $newTitle;
index ace776c..e6fe27c 100644 (file)
@@ -391,14 +391,14 @@ class ApiOpenSearchFormatJson extends ApiFormatJson {
        }
 
        public function execute() {
-               if ( !$this->getResult()->getResultData( 'error' ) ) {
-                       $result = $this->getResult();
-
+               $result = $this->getResult();
+               if ( !$result->getResultData( 'error' ) && !$result->getResultData( 'errors' ) ) {
                        // Ignore warnings or treat as errors, as requested
                        $warnings = $result->removeValue( 'warnings', null );
                        if ( $this->warningsAsError && $warnings ) {
-                               $this->dieUsage(
-                                       'Warnings cannot be represented in OpenSearch JSON format', 'warnings', 0,
+                               $this->dieWithError(
+                                       'apierror-opensearch-json-warnings',
+                                       'warnings',
                                        [ 'warnings' => $warnings ]
                                );
                        }
index 8bfe447..466d186 100644 (file)
@@ -36,22 +36,26 @@ class ApiOptions extends ApiBase {
         */
        public function execute() {
                if ( $this->getUser()->isAnon() ) {
-                       $this->dieUsage( 'Anonymous users cannot change preferences', 'notloggedin' );
-               } elseif ( !$this->getUser()->isAllowed( 'editmyoptions' ) ) {
-                       $this->dieUsage( "You don't have permission to edit your options", 'permissiondenied' );
+                       $this->dieWithError(
+                               [ 'apierror-mustbeloggedin', $this->msg( 'action-editmyoptions' ) ], 'notloggedin'
+                       );
                }
 
+               $this->checkUserRightsAny( 'editmyoptions' );
+
                $params = $this->extractRequestParams();
                $changed = false;
 
                if ( isset( $params['optionvalue'] ) && !isset( $params['optionname'] ) ) {
-                       $this->dieUsageMsg( [ 'missingparam', 'optionname' ] );
+                       $this->dieWithError( [ 'apierror-missingparam', 'optionname' ] );
                }
 
                // Load the user from the master to reduce CAS errors on double post (T95839)
                $user = $this->getUser()->getInstanceForUpdate();
                if ( !$user ) {
-                       $this->dieUsage( 'Anonymous users cannot change preferences', 'notloggedin' );
+                       $this->dieWithError(
+                               [ 'apierror-mustbeloggedin', $this->msg( 'action-editmyoptions' ) ], 'notloggedin'
+                       );
                }
 
                if ( $params['reset'] ) {
@@ -71,7 +75,7 @@ class ApiOptions extends ApiBase {
                        $changes[$params['optionname']] = $newValue;
                }
                if ( !$changed && !count( $changes ) ) {
-                       $this->dieUsage( 'No changes were requested', 'nochanges' );
+                       $this->dieWithError( 'apierror-nochanges' );
                }
 
                $prefs = Preferences::getPreferences( $user, $this->getContext() );
@@ -98,26 +102,26 @@ class ApiOptions extends ApiBase {
                                case 'userjs':
                                        // Allow non-default preferences prefixed with 'userjs-', to be set by user scripts
                                        if ( strlen( $key ) > 255 ) {
-                                               $validation = 'key too long (no more than 255 bytes allowed)';
+                                               $validation = $this->msg( 'apiwarn-validationfailed-keytoolong', Message::numParam( 255 ) );
                                        } elseif ( preg_match( '/[^a-zA-Z0-9_-]/', $key ) !== 0 ) {
-                                               $validation = 'invalid key (only a-z, A-Z, 0-9, _, - allowed)';
+                                               $validation = $this->msg( 'apiwarn-validationfailed-badchars' );
                                        } else {
                                                $validation = true;
                                        }
                                        break;
                                case 'special':
-                                       $validation = 'cannot be set by this module';
+                                       $validation = $this->msg( 'apiwarn-validationfailed-cannotset' );
                                        break;
                                case 'unused':
                                default:
-                                       $validation = 'not a valid preference';
+                                       $validation = $this->msg( 'apiwarn-validationfailed-badpref' );
                                        break;
                        }
                        if ( $validation === true ) {
                                $user->setOption( $key, $value );
                                $changed = true;
                        } else {
-                               $this->setWarning( "Validation error for '$key': $validation" );
+                               $this->addWarning( [ 'apiwarn-validationfailed', wfEscapeWikitext( $key ), $validation ] );
                        }
                }
 
index 46c57b8..4cf896f 100644 (file)
@@ -23,6 +23,7 @@
  *
  * @file
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * This class contains a list of pages that the client has requested.
@@ -154,10 +155,10 @@ class ApiPageSet extends ApiBase {
                        }
                        $generator = $dbSource->getModuleManager()->getModule( $generatorName, null, true );
                        if ( $generator === null ) {
-                               $this->dieUsage( 'Unknown generator=' . $generatorName, 'badgenerator' );
+                               $this->dieWithError( [ 'apierror-badgenerator-unknown', $generatorName ], 'badgenerator' );
                        }
                        if ( !$generator instanceof ApiQueryGeneratorBase ) {
-                               $this->dieUsage( "Module $generatorName cannot be used as a generator", 'badgenerator' );
+                               $this->dieWithError( [ 'apierror-badgenerator-notgenerator', $generatorName ], 'badgenerator' );
                        }
                        // Create a temporary pageset to store generator's output,
                        // add any additional fields generator may need, and execute pageset to populate titles/pageids
@@ -193,13 +194,27 @@ class ApiPageSet extends ApiBase {
                        }
                        if ( isset( $this->mParams['pageids'] ) ) {
                                if ( isset( $dataSource ) ) {
-                                       $this->dieUsage( "Cannot use 'pageids' at the same time as '$dataSource'", 'multisource' );
+                                       $this->dieWithError(
+                                               [
+                                                       'apierror-invalidparammix-cannotusewith',
+                                                       $this->encodeParamName( 'pageids' ),
+                                                       $this->encodeParamName( $dataSource )
+                                               ],
+                                               'multisource'
+                                       );
                                }
                                $dataSource = 'pageids';
                        }
                        if ( isset( $this->mParams['revids'] ) ) {
                                if ( isset( $dataSource ) ) {
-                                       $this->dieUsage( "Cannot use 'revids' at the same time as '$dataSource'", 'multisource' );
+                                       $this->dieWithError(
+                                               [
+                                                       'apierror-invalidparammix-cannotusewith',
+                                                       $this->encodeParamName( 'revids' ),
+                                                       $this->encodeParamName( $dataSource )
+                                               ],
+                                               'multisource'
+                                       );
                                }
                                $dataSource = 'revids';
                        }
@@ -215,9 +230,7 @@ class ApiPageSet extends ApiBase {
                                                break;
                                        case 'revids':
                                                if ( $this->mResolveRedirects ) {
-                                                       $this->setWarning( 'Redirect resolution cannot be used ' .
-                                                               'together with the revids= parameter. Any redirects ' .
-                                                               'the revids= point to have not been resolved.' );
+                                                       $this->addWarning( 'apiwarn-redirectsandrevids' );
                                                }
                                                $this->mResolveRedirects = false;
                                                $this->initFromRevIDs( $this->mParams['revids'] );
@@ -915,7 +928,7 @@ class ApiPageSet extends ApiBase {
                }
 
                // Get gender information
-               $genderCache = GenderCache::singleton();
+               $genderCache = MediaWikiServices::getInstance()->getGenderCache();
                $genderCache->doQuery( $usernames, __METHOD__ );
        }
 
@@ -1197,7 +1210,7 @@ class ApiPageSet extends ApiBase {
                        }
                }
                // Get gender information
-               $genderCache = GenderCache::singleton();
+               $genderCache = MediaWikiServices::getInstance()->getGenderCache();
                $genderCache->doQuery( $usernames, __METHOD__ );
 
                return $linkBatch;
@@ -1411,13 +1424,7 @@ class ApiPageSet extends ApiBase {
                                ApiBase::PARAM_DFLT => false,
                                ApiBase::PARAM_HELP_MSG => [
                                        'api-pageset-param-converttitles',
-                                       new DeferredStringifier(
-                                               function ( IContextSource $context ) {
-                                                       return $context->getLanguage()
-                                                               ->commaList( LanguageConverter::$languagesWithVariants );
-                                               },
-                                               $this
-                                       )
+                                       [ Message::listParam( LanguageConverter::$languagesWithVariants, 'text' ) ],
                                ],
                        ],
                ];
index caf0cd7..a9b3dde 100644 (file)
@@ -66,14 +66,17 @@ class ApiParamInfo extends ApiBase {
                                if ( $submodules ) {
                                        try {
                                                $module = $this->getModuleFromPath( $path );
-                                       } catch ( UsageException $ex ) {
-                                               $this->setWarning( $ex->getMessage() );
+                                       } catch ( ApiUsageException $ex ) {
+                                               foreach ( $ex->getStatusValue()->getErrors() as $error ) {
+                                                       $this->addWarning( $error );
+                                               }
+                                               continue;
                                        }
                                        $submodules = $this->listAllSubmodules( $module, $recursive );
                                        if ( $submodules ) {
                                                $modules = array_merge( $modules, $submodules );
                                        } else {
-                                               $this->setWarning( "Module $path has no submodules" );
+                                               $this->addWarning( [ 'apierror-badmodule-nosubmodules', $path ], 'badmodule' );
                                        }
                                } else {
                                        $modules[] = $path;
@@ -108,8 +111,10 @@ class ApiParamInfo extends ApiBase {
                foreach ( $modules as $m ) {
                        try {
                                $module = $this->getModuleFromPath( $m );
-                       } catch ( UsageException $ex ) {
-                               $this->setWarning( $ex->getMessage() );
+                       } catch ( ApiUsageException $ex ) {
+                               foreach ( $ex->getStatusValue()->getErrors() as $error ) {
+                                       $this->addWarning( $error );
+                               }
                                continue;
                        }
                        $key = 'modules';
@@ -406,6 +411,21 @@ class ApiParamInfo extends ApiBase {
                                        $item['type'] = array_values( $item['type'] );
                                        ApiResult::setIndexedTagName( $item['type'], 't' );
                                }
+
+                               // Add 'allspecifier' if applicable
+                               if ( $item['type'] === 'namespace' ) {
+                                       $allowAll = true;
+                                       $allSpecifier = ApiBase::ALL_DEFAULT_STRING;
+                               } else {
+                                       $allowAll = isset( $settings[ApiBase::PARAM_ALL] )
+                                               ? $settings[ApiBase::PARAM_ALL]
+                                               : false;
+                                       $allSpecifier = ( is_string( $allowAll ) ? $allowAll : ApiBase::ALL_DEFAULT_STRING );
+                               }
+                               if ( $allowAll && $item['multi'] &&
+                                       ( is_array( $item['type'] ) || $item['type'] === 'namespace' ) ) {
+                                       $item['allspecifier'] = $allSpecifier;
+                               }
                        }
                        if ( isset( $settings[ApiBase::PARAM_MAX] ) ) {
                                $item['max'] = $settings[ApiBase::PARAM_MAX];
index 0cad5de..2263b8f 100644 (file)
@@ -36,18 +36,18 @@ class ApiParse extends ApiBase {
        /** @var Content $pstContent */
        private $pstContent = null;
 
-       private function checkReadPermissions( Title $title ) {
-               if ( !$title->userCan( 'read', $this->getUser() ) ) {
-                       $this->dieUsage( "You don't have permission to view this page", 'permissiondenied' );
-               }
-       }
-
        public function execute() {
                // The data is hot but user-dependent, like page views, so we set vary cookies
                $this->getMain()->setCacheMode( 'anon-public-user-private' );
 
                // Get parameters
                $params = $this->extractRequestParams();
+
+               // No easy way to say that text & title are allowed together while the
+               // rest aren't, so just do it in two calls.
+               $this->requireMaxOneParameter( $params, 'page', 'pageid', 'oldid', 'text' );
+               $this->requireMaxOneParameter( $params, 'page', 'pageid', 'oldid', 'title' );
+
                $text = $params['text'];
                $title = $params['title'];
                if ( $title === null ) {
@@ -65,21 +65,12 @@ class ApiParse extends ApiBase {
                $model = $params['contentmodel'];
                $format = $params['contentformat'];
 
-               if ( !is_null( $page ) && ( !is_null( $text ) || $titleProvided ) ) {
-                       $this->dieUsage(
-                               'The page parameter cannot be used together with the text and title parameters',
-                               'params'
-                       );
-               }
-
                $prop = array_flip( $params['prop'] );
 
                if ( isset( $params['section'] ) ) {
                        $this->section = $params['section'];
                        if ( !preg_match( '/^((T-)?\d+|new)$/', $this->section ) ) {
-                               $this->dieUsage(
-                                       'The section parameter must be a valid section id or "new"', 'invalidsection'
-                               );
+                               $this->dieWithError( 'apierror-invalidsection' );
                        }
                } else {
                        $this->section = false;
@@ -97,21 +88,20 @@ class ApiParse extends ApiBase {
 
                if ( !is_null( $oldid ) || !is_null( $pageid ) || !is_null( $page ) ) {
                        if ( $this->section === 'new' ) {
-                                       $this->dieUsage(
-                                               'section=new cannot be combined with oldid, pageid or page parameters. ' .
-                                               'Please use text', 'params'
-                                       );
+                               $this->dieWithError( 'apierror-invalidparammix-parse-new-section', 'invalidparammix' );
                        }
                        if ( !is_null( $oldid ) ) {
                                // Don't use the parser cache
                                $rev = Revision::newFromId( $oldid );
                                if ( !$rev ) {
-                                       $this->dieUsage( "There is no revision ID $oldid", 'missingrev' );
+                                       $this->dieWithError( [ 'apierror-nosuchrevid', $oldid ] );
                                }
 
-                               $this->checkReadPermissions( $rev->getTitle() );
+                               $this->checkTitleUserPermissions( $rev->getTitle(), 'read' );
                                if ( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
-                                       $this->dieUsage( "You don't have permission to view deleted revisions", 'permissiondenied' );
+                                       $this->dieWithError(
+                                               [ 'apierror-permissiondenied', $this->msg( 'action-deletedtext' ) ]
+                                       );
                                }
 
                                $titleObj = $rev->getTitle();
@@ -131,7 +121,9 @@ class ApiParse extends ApiBase {
                                        $this->content = $rev->getContent( Revision::FOR_THIS_USER, $this->getUser() );
 
                                        if ( $this->section !== false ) {
-                                               $this->content = $this->getSectionContent( $this->content, 'r' . $rev->getId() );
+                                               $this->content = $this->getSectionContent(
+                                                       $this->content, $this->msg( 'revid', $rev->getId() )
+                                               );
                                        }
 
                                        // Should we save old revision parses to the parser cache?
@@ -167,10 +159,10 @@ class ApiParse extends ApiBase {
                                $pageObj = $this->getTitleOrPageId( $pageParams, 'fromdb' );
                                $titleObj = $pageObj->getTitle();
                                if ( !$titleObj || !$titleObj->exists() ) {
-                                       $this->dieUsage( "The page you specified doesn't exist", 'missingtitle' );
+                                       $this->dieWithError( 'apierror-missingtitle' );
                                }
 
-                               $this->checkReadPermissions( $titleObj );
+                               $this->checkTitleUserPermissions( $titleObj, 'read' );
                                $wgTitle = $titleObj;
 
                                if ( isset( $prop['revid'] ) ) {
@@ -201,7 +193,7 @@ class ApiParse extends ApiBase {
                } else { // Not $oldid, $pageid, $page. Hence based on $text
                        $titleObj = Title::newFromText( $title );
                        if ( !$titleObj || $titleObj->isExternal() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $title ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $title ) ] );
                        }
                        $wgTitle = $titleObj;
                        if ( $titleObj->canExist() ) {
@@ -217,10 +209,7 @@ class ApiParse extends ApiBase {
 
                        if ( !$textProvided ) {
                                if ( $titleProvided && ( $prop || $params['generatexml'] ) ) {
-                                       $this->setWarning(
-                                               "'title' used without 'text', and parsed page properties were requested " .
-                                               "(did you mean to use 'page' instead of 'title'?)"
-                                       );
+                                       $this->addWarning( 'apiwarn-parse-titlewithouttext' );
                                }
                                // Prevent warning from ContentHandler::makeContent()
                                $text = '';
@@ -230,13 +219,17 @@ class ApiParse extends ApiBase {
                        // API title, but default to wikitext to keep BC.
                        if ( $textProvided && !$titleProvided && is_null( $model ) ) {
                                $model = CONTENT_MODEL_WIKITEXT;
-                               $this->setWarning( "No 'title' or 'contentmodel' was given, assuming $model." );
+                               $this->addWarning( [ 'apiwarn-parse-nocontentmodel', $model ] );
                        }
 
                        try {
                                $this->content = ContentHandler::makeContent( $text, $titleObj, $model, $format );
                        } catch ( MWContentSerializationException $ex ) {
-                               $this->dieUsage( $ex->getMessage(), 'parseerror' );
+                               // @todo: Internationalize MWContentSerializationException
+                               $this->dieWithError(
+                                       [ 'apierror-contentserializationexception', wfEscapeWikiText( $ex->getMessage() ) ],
+                                       'parseerror'
+                               );
                        }
 
                        if ( $this->section !== false ) {
@@ -357,10 +350,7 @@ class ApiParse extends ApiBase {
 
                if ( isset( $prop['headitems'] ) ) {
                        $result_array['headitems'] = $this->formatHeadItems( $p_result->getHeadItems() );
-                       $this->logFeatureUsage( 'action=parse&prop=headitems' );
-                       $this->setWarning( 'headitems is deprecated since MediaWiki 1.28. '
-                               . 'Use prop=headhtml when creating new HTML documents, or '
-                               . 'prop=modules|jsconfigvars when updating a document client-side.' );
+                       $this->addDeprecation( 'apiwarn-deprecation-parse-headitems', 'action=parse&prop=headitems' );
                }
 
                if ( isset( $prop['headhtml'] ) ) {
@@ -397,9 +387,7 @@ class ApiParse extends ApiBase {
 
                if ( isset( $prop['modules'] ) &&
                        !isset( $prop['jsconfigvars'] ) && !isset( $prop['encodedjsconfigvars'] ) ) {
-                       $this->setWarning( 'Property "modules" was set but not "jsconfigvars" ' .
-                               'or "encodedjsconfigvars". Configuration variables are necessary ' .
-                               'for proper module usage.' );
+                       $this->addWarning( 'apiwarn-moduleswithoutvars' );
                }
 
                if ( isset( $prop['indicators'] ) ) {
@@ -435,7 +423,7 @@ class ApiParse extends ApiBase {
 
                if ( isset( $prop['parsetree'] ) || $params['generatexml'] ) {
                        if ( $this->content->getModel() != CONTENT_MODEL_WIKITEXT ) {
-                               $this->dieUsage( 'parsetree is only supported for wikitext content', 'notwikitext' );
+                               $this->dieWithError( 'apierror-parsetree-notwikitext', 'notwikitext' );
                        }
 
                        $wgParser->startExternalParse( $titleObj, $popts, Parser::OT_PREPROCESS );
@@ -516,7 +504,7 @@ class ApiParse extends ApiBase {
                // getParserOutput will save to Parser cache if able
                $pout = $page->getParserOutput( $popts );
                if ( !$pout ) {
-                       $this->dieUsage( "There is no revision ID {$page->getLatest()}", 'missingrev' );
+                       $this->dieWithError( [ 'apierror-nosuchrevid', $page->getLatest() ] );
                }
                if ( $getWikitext ) {
                        $this->content = $page->getContent( Revision::RAW );
@@ -538,7 +526,9 @@ class ApiParse extends ApiBase {
                if ( $this->section !== false && $content !== null ) {
                        $content = $this->getSectionContent(
                                $content,
-                               !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getPrefixedText()
+                               !is_null( $pageId )
+                                       ? $this->msg( 'pageid', $pageId )
+                                       : $page->getTitle()->getPrefixedText()
                        );
                }
                return $content;
@@ -548,17 +538,17 @@ class ApiParse extends ApiBase {
         * Extract the requested section from the given Content
         *
         * @param Content $content
-        * @param string $what Identifies the content in error messages, e.g. page title.
+        * @param string|Message $what Identifies the content in error messages, e.g. page title.
         * @return Content|bool
         */
        private function getSectionContent( Content $content, $what ) {
                // Not cached (save or load)
                $section = $content->getSection( $this->section );
                if ( $section === false ) {
-                       $this->dieUsage( "There is no section {$this->section} in $what", 'nosuchsection' );
+                       $this->dieWithError( [ 'apierror-nosuchsection-what', $this->section, $what ], 'nosuchsection' );
                }
                if ( $section === null ) {
-                       $this->dieUsage( "Sections are not supported by $what", 'nosuchsection' );
+                       $this->dieWithError( [ 'apierror-sectionsnotsupported-what', $what ], 'nosuchsection' );
                        $section = false;
                }
 
index 6252882..c33542f 100644 (file)
@@ -40,19 +40,16 @@ class ApiPatrol extends ApiBase {
                if ( isset( $params['rcid'] ) ) {
                        $rc = RecentChange::newFromId( $params['rcid'] );
                        if ( !$rc ) {
-                               $this->dieUsageMsg( [ 'nosuchrcid', $params['rcid'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchrcid', $params['rcid'] ] );
                        }
                } else {
                        $rev = Revision::newFromId( $params['revid'] );
                        if ( !$rev ) {
-                               $this->dieUsageMsg( [ 'nosuchrevid', $params['revid'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchrevid', $params['revid'] ] );
                        }
                        $rc = $rev->getRecentChange();
                        if ( !$rc ) {
-                               $this->dieUsage(
-                                       'The revision ' . $params['revid'] . " can't be patrolled as it's too old",
-                                       'notpatrollable'
-                               );
+                               $this->dieWithError( [ 'apierror-notpatrollable', $params['revid'] ] );
                        }
                }
 
@@ -70,7 +67,7 @@ class ApiPatrol extends ApiBase {
                $retval = $rc->doMarkPatrolled( $user, false, $tags );
 
                if ( $retval ) {
-                       $this->dieUsageMsg( reset( $retval ) );
+                       $this->dieStatus( $this->errorArrayToStatus( $retval, $user ) );
                }
 
                $result = [ 'rcid' => intval( $rc->getAttribute( 'rc_id' ) ) ];
index d289060..746dc9a 100644 (file)
@@ -36,11 +36,7 @@ class ApiProtect extends ApiBase {
                $pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' );
                $titleObj = $pageObj->getTitle();
 
-               $errors = $titleObj->getUserPermissionsErrors( 'protect', $this->getUser() );
-               if ( $errors ) {
-                       // We don't care about multiple errors, just report one of them
-                       $this->dieUsageMsg( reset( $errors ) );
-               }
+               $this->checkTitleUserPermissions( $titleObj, 'protect' );
 
                $user = $this->getUser();
                $tags = $params['tags'];
@@ -58,8 +54,8 @@ class ApiProtect extends ApiBase {
                        if ( count( $expiry ) == 1 ) {
                                $expiry = array_fill( 0, count( $params['protections'] ), $expiry[0] );
                        } else {
-                               $this->dieUsageMsg( [
-                                       'toofewexpiries',
+                               $this->dieWithError( [
+                                       'apierror-toofewexpiries',
                                        count( $expiry ),
                                        count( $params['protections'] )
                                ] );
@@ -76,17 +72,17 @@ class ApiProtect extends ApiBase {
                        $protections[$p[0]] = ( $p[1] == 'all' ? '' : $p[1] );
 
                        if ( $titleObj->exists() && $p[0] == 'create' ) {
-                               $this->dieUsageMsg( 'create-titleexists' );
+                               $this->dieWithError( 'apierror-create-titleexists' );
                        }
                        if ( !$titleObj->exists() && $p[0] != 'create' ) {
-                               $this->dieUsageMsg( 'missingtitle-createonly' );
+                               $this->dieWithError( 'apierror-missingtitle-createonly' );
                        }
 
                        if ( !in_array( $p[0], $restrictionTypes ) && $p[0] != 'create' ) {
-                               $this->dieUsageMsg( [ 'protect-invalidaction', $p[0] ] );
+                               $this->dieWithError( [ 'apierror-protect-invalidaction', wfEscapeWikiText( $p[0] ) ] );
                        }
                        if ( !in_array( $p[1], $this->getConfig()->get( 'RestrictionLevels' ) ) && $p[1] != 'all' ) {
-                               $this->dieUsageMsg( [ 'protect-invalidlevel', $p[1] ] );
+                               $this->dieWithError( [ 'apierror-protect-invalidlevel', wfEscapeWikiText( $p[1] ) ] );
                        }
 
                        if ( wfIsInfinity( $expiry[$i] ) ) {
@@ -94,12 +90,12 @@ class ApiProtect extends ApiBase {
                        } else {
                                $exp = strtotime( $expiry[$i] );
                                if ( $exp < 0 || !$exp ) {
-                                       $this->dieUsageMsg( [ 'invalidexpiry', $expiry[$i] ] );
+                                       $this->dieWithError( [ 'apierror-invalidexpiry', wfEscapeWikiText( $expiry[$i] ) ] );
                                }
 
                                $exp = wfTimestamp( TS_MW, $exp );
                                if ( $exp < wfTimestampNow() ) {
-                                       $this->dieUsageMsg( [ 'pastexpiry', $expiry[$i] ] );
+                                       $this->dieWithError( [ 'apierror-pastexpiry', wfEscapeWikiText( $expiry[$i] ) ] );
                                }
                                $expiryarray[$p[0]] = $exp;
                        }
index 8bbd88d..324d030 100644 (file)
@@ -39,8 +39,7 @@ class ApiPurge extends ApiBase {
        public function execute() {
                $main = $this->getMain();
                if ( !$main->isInternalMode() && !$main->getRequest()->wasPosted() ) {
-                       $this->logFeatureUsage( 'purge-via-GET' );
-                       $this->setWarning( 'Use of action=purge via GET is deprecated. Use POST instead.' );
+                       $this->addDeprecation( 'apiwarn-deprecation-purge-get', 'purge-via-GET' );
                }
 
                $params = $this->extractRequestParams();
@@ -69,8 +68,7 @@ class ApiPurge extends ApiBase {
                                $page->doPurge( $flags );
                                $r['purged'] = true;
                        } else {
-                               $error = $this->parseMsg( [ 'actionthrottledtext' ] );
-                               $this->setWarning( $error['info'] );
+                               $this->addWarning( 'apierror-ratelimited' );
                        }
 
                        if ( $forceLinkUpdate || $forceRecursiveLinkUpdate ) {
@@ -114,8 +112,7 @@ class ApiPurge extends ApiBase {
                                                }
                                        }
                                } else {
-                                       $error = $this->parseMsg( [ 'actionthrottledtext' ] );
-                                       $this->setWarning( $error['info'] );
+                                       $this->addWarning( 'apierror-ratelimited' );
                                        $forceLinkUpdate = false;
                                }
                        }
index 16bd725..8196cfa 100644 (file)
@@ -310,7 +310,7 @@ class ApiQuery extends ApiBase {
                                        ApiBase::dieDebug( __METHOD__, 'Error instantiating module' );
                                }
                                if ( !$wasPosted && $instance->mustBePosted() ) {
-                                       $this->dieUsageMsgOrDebug( [ 'mustbeposted', $moduleName ] );
+                                       $this->dieWithErrorOrDebug( [ 'apierror-mustbeposted', $moduleName ] );
                                }
                                // Ignore duplicates. TODO 2.0: die()?
                                if ( !array_key_exists( $moduleName, $modules ) ) {
@@ -415,11 +415,7 @@ class ApiQuery extends ApiBase {
                }
 
                if ( !$fit ) {
-                       $this->dieUsage(
-                               'The value of $wgAPIMaxResultSize on this wiki is ' .
-                                       'too small to hold basic result information',
-                               'badconfig'
-                       );
+                       $this->dieWithError( 'apierror-badconfig-resulttoosmall', 'badconfig' );
                }
 
                if ( $this->mParams['export'] ) {
index 3073a95..b09b977 100644 (file)
@@ -41,15 +41,10 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
         * @return void
         */
        protected function run( ApiPageSet $resultPageSet = null ) {
-               $user = $this->getUser();
                // Before doing anything at all, let's check permissions
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $this->dieUsage(
-                               'You don\'t have permission to view deleted revision information',
-                               'permissiondenied'
-                       );
-               }
+               $this->checkUserRightsAny( 'deletedhistory' );
 
+               $user = $this->getUser();
                $db = $this->getDB();
                $params = $this->extractRequestParams( false );
 
@@ -75,16 +70,20 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
                        foreach ( [ 'from', 'to', 'prefix', 'excludeuser' ] as $param ) {
                                if ( !is_null( $params[$param] ) ) {
                                        $p = $this->getModulePrefix();
-                                       $this->dieUsage( "The '{$p}{$param}' parameter cannot be used with '{$p}user'",
-                                               'badparams' );
+                                       $this->dieWithError(
+                                               [ 'apierror-invalidparammix-cannotusewith', $p.$param, "{$p}user" ],
+                                               'invalidparammix'
+                                       );
                                }
                        }
                } else {
                        foreach ( [ 'start', 'end' ] as $param ) {
                                if ( !is_null( $params[$param] ) ) {
                                        $p = $this->getModulePrefix();
-                                       $this->dieUsage( "The '{$p}{$param}' parameter may only be used with '{$p}user'",
-                                               'badparams' );
+                                       $this->dieWithError(
+                                               [ 'apierror-invalidparammix-mustusewith', $p.$param, "{$p}user" ],
+                                               'invalidparammix'
+                                       );
                                }
                        }
                }
@@ -100,7 +99,7 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
                                $optimizeGenerateTitles = true;
                        } else {
                                $p = $this->getModulePrefix();
-                               $this->setWarning( "For better performance when generating titles, set {$p}dir=newer" );
+                               $this->addWarning( [ 'apiwarn-alldeletedrevisions-performance', $p ], 'performance' );
                        }
                }
 
@@ -148,12 +147,7 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
                        $this->addFields( [ 'ar_text', 'ar_flags', 'old_text', 'old_flags' ] );
 
                        // This also means stricter restrictions
-                       if ( !$user->isAllowedAny( 'undelete', 'deletedtext' ) ) {
-                               $this->dieUsage(
-                                       'You don\'t have permission to view deleted revision content',
-                                       'permissiondenied'
-                               );
-                       }
+                       $this->checkUserRightsAny( [ 'deletedtext', 'undelete' ] );
                }
 
                $miser_ns = null;
index 553995c..e3e5ed6 100644 (file)
@@ -44,10 +44,10 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
         * which may not necessarily be the same as the local DB.
         *
         * TODO: allow querying non-local repos.
-        * @return Database
+        * @return IDatabase
         */
        protected function getDB() {
-               return $this->mRepo->getSlaveDB();
+               return $this->mRepo->getReplicaDB();
        }
 
        public function execute() {
@@ -64,11 +64,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
         */
        public function executeGenerator( $resultPageSet ) {
                if ( $resultPageSet->isResolvingRedirects() ) {
-                       $this->dieUsage(
-                               'Use "gaifilterredir=nonredirects" option instead of "redirects" ' .
-                                       'when using allimages as a generator',
-                               'params'
-                       );
+                       $this->dieWithError( 'apierror-allimages-redirect', 'invalidparammix' );
                }
 
                $this->run( $resultPageSet );
@@ -81,10 +77,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
        private function run( $resultPageSet = null ) {
                $repo = $this->mRepo;
                if ( !$repo instanceof LocalRepo ) {
-                       $this->dieUsage(
-                               'Local file repository does not support querying all images',
-                               'unsupportedrepo'
-                       );
+                       $this->dieWithError( 'apierror-unsupportedrepo' );
                }
 
                $prefix = $this->getModulePrefix();
@@ -109,16 +102,24 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                        $disallowed = [ 'start', 'end', 'user' ];
                        foreach ( $disallowed as $pname ) {
                                if ( isset( $params[$pname] ) ) {
-                                       $this->dieUsage(
-                                               "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=timestamp",
-                                               'badparams'
+                                       $this->dieWithError(
+                                               [
+                                                       'apierror-invalidparammix-mustusewith',
+                                                       "{$prefix}{$pname}",
+                                                       "{$prefix}sort=timestamp"
+                                               ],
+                                               'invalidparammix'
                                        );
                                }
                        }
                        if ( $params['filterbots'] != 'all' ) {
-                               $this->dieUsage(
-                                       "Parameter '{$prefix}filterbots' can only be used with {$prefix}sort=timestamp",
-                                       'badparams'
+                               $this->dieWithError(
+                                       [
+                                               'apierror-invalidparammix-mustusewith',
+                                               "{$prefix}filterbots",
+                                               "{$prefix}sort=timestamp"
+                                       ],
+                                       'invalidparammix'
                                );
                        }
 
@@ -146,18 +147,21 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                        $disallowed = [ 'from', 'to', 'prefix' ];
                        foreach ( $disallowed as $pname ) {
                                if ( isset( $params[$pname] ) ) {
-                                       $this->dieUsage(
-                                               "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=name",
-                                               'badparams'
+                                       $this->dieWithError(
+                                               [
+                                                       'apierror-invalidparammix-mustusewith',
+                                                       "{$prefix}{$pname}",
+                                                       "{$prefix}sort=name"
+                                               ],
+                                               'invalidparammix'
                                        );
                                }
                        }
                        if ( !is_null( $params['user'] ) && $params['filterbots'] != 'all' ) {
                                // Since filterbots checks if each user has the bot right, it
                                // doesn't make sense to use it with user
-                               $this->dieUsage(
-                                       "Parameters '{$prefix}user' and '{$prefix}filterbots' cannot be used together",
-                                       'badparams'
+                               $this->dieWithError(
+                                       [ 'apierror-invalidparammix-cannotusewith', "{$prefix}user", "{$prefix}filterbots" ]
                                );
                        }
 
@@ -214,13 +218,13 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                if ( isset( $params['sha1'] ) ) {
                        $sha1 = strtolower( $params['sha1'] );
                        if ( !$this->validateSha1Hash( $sha1 ) ) {
-                               $this->dieUsage( 'The SHA1 hash provided is not valid', 'invalidsha1hash' );
+                               $this->dieWithError( 'apierror-invalidsha1hash' );
                        }
                        $sha1 = Wikimedia\base_convert( $sha1, 16, 36, 31 );
                } elseif ( isset( $params['sha1base36'] ) ) {
                        $sha1 = strtolower( $params['sha1base36'] );
                        if ( !$this->validateSha1Base36Hash( $sha1 ) ) {
-                               $this->dieUsage( 'The SHA1Base36 hash provided is not valid', 'invalidsha1base36hash' );
+                               $this->dieWithError( 'apierror-invalidsha1base36hash' );
                        }
                }
                if ( $sha1 ) {
@@ -229,7 +233,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
 
                if ( !is_null( $params['mime'] ) ) {
                        if ( $this->getConfig()->get( 'MiserMode' ) ) {
-                               $this->dieUsage( 'MIME search disabled in Miser Mode', 'mimesearchdisabled' );
+                               $this->dieWithError( 'apierror-mimesearchdisabled' );
                        }
 
                        $mimeConds = [];
index ac90605..c3636c6 100644 (file)
@@ -116,9 +116,13 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                        $matches = array_intersect_key( $prop, $this->props + [ 'ids' => 1 ] );
                        if ( $matches ) {
                                $p = $this->getModulePrefix();
-                               $this->dieUsage(
-                                       "Cannot use {$p}prop=" . implode( '|', array_keys( $matches ) ) . " with {$p}unique",
-                                       'params'
+                               $this->dieWithError(
+                                       [
+                                               'apierror-invalidparammix-cannotusewith',
+                                               "{$p}prop=" . implode( '|', array_keys( $matches ) ),
+                                               "{$p}unique"
+                                       ],
+                                       'invalidparammix'
                                );
                        }
                        $this->addOption( 'DISTINCT' );
index e0ba4ea..244effc 100644 (file)
@@ -41,7 +41,9 @@ class ApiQueryAllMessages extends ApiQueryBase {
                if ( is_null( $params['lang'] ) ) {
                        $langObj = $this->getLanguage();
                } elseif ( !Language::isValidCode( $params['lang'] ) ) {
-                       $this->dieUsage( 'Invalid language code for parameter lang', 'invalidlang' );
+                       $this->dieWithError(
+                               [ 'apierror-invalidlang', $this->encodeParamName( 'lang' ) ], 'invalidlang'
+                       );
                } else {
                        $langObj = Language::factory( $params['lang'] );
                }
@@ -50,7 +52,7 @@ class ApiQueryAllMessages extends ApiQueryBase {
                        if ( !is_null( $params['title'] ) ) {
                                $title = Title::newFromText( $params['title'] );
                                if ( !$title || $title->isExternal() ) {
-                                       $this->dieUsageMsg( [ 'invalidtitle', $params['title'] ] );
+                                       $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
                                }
                        } else {
                                $title = Title::newFromText( 'API' );
index 0ce1939..7460bd5 100644 (file)
@@ -23,6 +23,7 @@
  *
  * @file
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * Query module to enumerate all available pages.
@@ -49,11 +50,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
         */
        public function executeGenerator( $resultPageSet ) {
                if ( $resultPageSet->isResolvingRedirects() ) {
-                       $this->dieUsage(
-                               'Use "gapfilterredir=nonredirects" option instead of "redirects" ' .
-                                       'when using allpages as a generator',
-                               'params'
-                       );
+                       $this->dieWithError( 'apierror-allpages-generator-redirects', 'params' );
                }
 
                $this->run( $resultPageSet );
@@ -156,7 +153,9 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
 
                        $this->addOption( 'DISTINCT' );
                } elseif ( isset( $params['prlevel'] ) ) {
-                       $this->dieUsage( 'prlevel may not be used without prtype', 'params' );
+                       $this->dieWithError(
+                               [ 'apierror-invalidparammix-mustusewith', 'prlevel', 'prtype' ], 'invalidparammix'
+                       );
                }
 
                if ( $params['filterlanglinks'] == 'withoutlanglinks' ) {
@@ -206,7 +205,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
                        foreach ( $res as $row ) {
                                $users[] = $row->page_title;
                        }
-                       GenderCache::singleton()->doQuery( $users, __METHOD__ );
+                       MediaWikiServices::getInstance()->getGenderCache()->doQuery( $users, __METHOD__ );
                        $res->rewind(); // reset
                }
 
index b7ed9dd..2e2ac32 100644 (file)
@@ -110,9 +110,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        }
                }
 
-               if ( !is_null( $params['group'] ) && !is_null( $params['excludegroup'] ) ) {
-                       $this->dieUsage( 'group and excludegroup cannot be used together', 'group-excludegroup' );
-               }
+               $this->requireMaxOneParameter( $params, 'group', 'excludegroup' );
 
                if ( !is_null( $params['group'] ) && count( $params['group'] ) ) {
                        // Filter only users that belong to a given group. This might
index fb502e4..4c32320 100644 (file)
@@ -348,8 +348,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
 
                // only image titles are allowed for the root in imageinfo mode
                if ( !$this->hasNS && $this->rootTitle->getNamespace() !== NS_FILE ) {
-                       $this->dieUsage(
-                               "The title for {$this->getModuleName()} query must be a file",
+                       $this->dieWithError(
+                               [ 'apierror-imageusage-badtitle', $this->getModuleName() ],
                                'bad_image_title'
                        );
                }
index 8e89c32..ef7b9af 100644 (file)
@@ -238,7 +238,7 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
                        if ( isset( $show['fragment'] ) && isset( $show['!fragment'] ) ||
                                isset( $show['redirect'] ) && isset( $show['!redirect'] )
                        ) {
-                               $this->dieUsageMsg( 'show' );
+                               $this->dieWithError( 'apierror-show' );
                        }
                        $this->addWhereIf( "rd_fragment != $emptyString", isset( $show['fragment'] ) );
                        $this->addWhereIf(
index bba5375..af2aed5 100644 (file)
@@ -421,7 +421,7 @@ abstract class ApiQueryBase extends ApiBase {
 
                        $likeQuery = LinkFilter::makeLikeArray( $query, $protocol );
                        if ( !$likeQuery ) {
-                               $this->dieUsage( 'Invalid query', 'bad_query' );
+                               $this->dieWithError( 'apierror-badquery' );
                        }
 
                        $likeQuery = LinkFilter::keepOneWildcard( $likeQuery );
@@ -547,7 +547,7 @@ abstract class ApiQueryBase extends ApiBase {
                $t = Title::makeTitleSafe( $namespace, $titlePart . 'x' );
                if ( !$t || $t->hasFragment() ) {
                        // Invalid title (e.g. bad chars) or contained a '#'.
-                       $this->dieUsageMsg( [ 'invalidtitle', $titlePart ] );
+                       $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $titlePart ) ] );
                }
                if ( $namespace != $t->getNamespace() || $t->isExternal() ) {
                        // This can happen in two cases. First, if you call titlePartToKey with a title part
@@ -555,7 +555,7 @@ abstract class ApiQueryBase extends ApiBase {
                        // difficult to handle such a case. Such cases cannot exist and are therefore treated
                        // as invalid user input. The second case is when somebody specifies a title interwiki
                        // prefix.
-                       $this->dieUsageMsg( [ 'invalidtitle', $titlePart ] );
+                       $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $titlePart ) ] );
                }
 
                return substr( $t->getDBkey(), 0, -1 );
@@ -573,7 +573,7 @@ abstract class ApiQueryBase extends ApiBase {
                $t = Title::newFromText( $titlePart . 'x', $defaultNamespace );
                if ( !$t || $t->hasFragment() || $t->isExternal() ) {
                        // Invalid title (e.g. bad chars) or contained a '#'.
-                       $this->dieUsageMsg( [ 'invalidtitle', $titlePart ] );
+                       $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $titlePart ) ] );
                }
 
                return [ $t->getNamespace(), substr( $t->getDBkey(), 0, -1 ) ];
index 5d7c664..ef79efd 100644 (file)
@@ -114,16 +114,13 @@ class ApiQueryBlocks extends ApiQueryBase {
                                $cidrLimit = $blockCIDRLimit['IPv6'];
                                $prefixLen = 3; // IP::toHex output is prefixed with "v6-"
                        } else {
-                               $this->dieUsage( 'IP parameter is not valid', 'param_ip' );
+                               $this->dieWithError( 'apierror-badip', 'param_ip' );
                        }
 
                        # Check range validity, if it's a CIDR
                        list( $ip, $range ) = IP::parseCIDR( $params['ip'] );
                        if ( $ip !== false && $range !== false && $range < $cidrLimit ) {
-                               $this->dieUsage(
-                                       "$type CIDR ranges broader than /$cidrLimit are not accepted",
-                                       'cidrtoobroad'
-                               );
+                               $this->dieWithError( [ 'apierror-cidrtoobroad', $type, $cidrLimit ] );
                        }
 
                        # Let IP::parseRange handle calculating $upper, instead of duplicating the logic here.
@@ -154,7 +151,7 @@ class ApiQueryBlocks extends ApiQueryBase {
                                || ( isset( $show['range'] ) && isset( $show['!range'] ) )
                                || ( isset( $show['temp'] ) && isset( $show['!temp'] ) )
                        ) {
-                               $this->dieUsageMsg( 'show' );
+                               $this->dieWithError( 'apierror-show' );
                        }
 
                        $this->addWhereIf( 'ipb_user = 0', isset( $show['!account'] ) );
@@ -237,13 +234,19 @@ class ApiQueryBlocks extends ApiQueryBase {
 
        protected function prepareUsername( $user ) {
                if ( !$user ) {
-                       $this->dieUsage( 'User parameter may not be empty', 'param_user' );
+                       $encParamName = $this->encodeParamName( 'users' );
+                       $this->dieWithError( [ 'apierror-baduser', $encParamName, wfEscapeWikiText( $user ) ],
+                               "baduser_{$encParamName}"
+                       );
                }
                $name = User::isIP( $user )
                        ? $user
                        : User::getCanonicalName( $user, 'valid' );
                if ( $name === false ) {
-                       $this->dieUsage( "User name {$user} is not valid", 'param_user' );
+                       $encParamName = $this->encodeParamName( 'users' );
+                       $this->dieWithError( [ 'apierror-baduser', $encParamName, wfEscapeWikiText( $user ) ],
+                               "baduser_{$encParamName}"
+                       );
                }
                return $name;
        }
index 63d0f6d..f2498ca 100644 (file)
@@ -74,7 +74,7 @@ class ApiQueryCategories extends ApiQueryGeneratorBase {
                        foreach ( $params['categories'] as $cat ) {
                                $title = Title::newFromText( $cat );
                                if ( !$title || $title->getNamespace() != NS_CATEGORY ) {
-                                       $this->setWarning( "\"$cat\" is not a category" );
+                                       $this->addWarning( [ 'apiwarn-invalidcategory', wfEscapeWikiText( $cat ) ] );
                                } else {
                                        $cats[] = $title->getDBkey();
                                }
@@ -96,7 +96,7 @@ class ApiQueryCategories extends ApiQueryGeneratorBase {
                }
 
                if ( isset( $show['hidden'] ) && isset( $show['!hidden'] ) ) {
-                       $this->dieUsageMsg( 'show' );
+                       $this->dieWithError( 'apierror-show' );
                }
                if ( isset( $show['hidden'] ) || isset( $show['!hidden'] ) || isset( $prop['hidden'] ) ) {
                        $this->addOption( 'STRAIGHT_JOIN' );
index 4865ad5..02961aa 100644 (file)
@@ -65,7 +65,7 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
 
                $categoryTitle = $this->getTitleOrPageId( $params )->getTitle();
                if ( $categoryTitle->getNamespace() != NS_CATEGORY ) {
-                       $this->dieUsage( 'The category name you entered is not valid', 'invalidcategory' );
+                       $this->dieWithError( 'apierror-invalidcategory' );
                }
 
                $prop = array_flip( $params['prop'] );
@@ -153,7 +153,8 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                                        $startsortkey = Collation::singleton()->getSortKey( $params['startsortkeyprefix'] );
                                } elseif ( $params['starthexsortkey'] !== null ) {
                                        if ( !$this->validateHexSortkey( $params['starthexsortkey'] ) ) {
-                                               $this->dieUsage( 'The starthexsortkey provided is not valid', 'bad_starthexsortkey' );
+                                               $encParamName = $this->encodeParamName( 'starthexsortkey' );
+                                               $this->dieWithError( [ 'apierror-badparameter', $encParamName ], "badvalue_$encParamName" );
                                        }
                                        $startsortkey = hex2bin( $params['starthexsortkey'] );
                                } else {
@@ -163,7 +164,8 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                                        $endsortkey = Collation::singleton()->getSortKey( $params['endsortkeyprefix'] );
                                } elseif ( $params['endhexsortkey'] !== null ) {
                                        if ( !$this->validateHexSortkey( $params['endhexsortkey'] ) ) {
-                                               $this->dieUsage( 'The endhexsortkey provided is not valid', 'bad_endhexsortkey' );
+                                               $encParamName = $this->encodeParamName( 'endhexsortkey' );
+                                               $this->dieWithError( [ 'apierror-badparameter', $encParamName ], "badvalue_$encParamName" );
                                        }
                                        $endsortkey = hex2bin( $params['endhexsortkey'] );
                                } else {
index cfd0653..d0b8214 100644 (file)
@@ -39,12 +39,7 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase {
        protected function run( ApiPageSet $resultPageSet = null ) {
                $user = $this->getUser();
                // Before doing anything at all, let's check permissions
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $this->dieUsage(
-                               'You don\'t have permission to view deleted revision information',
-                               'permissiondenied'
-                       );
-               }
+               $this->checkUserRightsAny( 'deletedhistory' );
 
                $pageSet = $this->getPageSet();
                $pageMap = $pageSet->getGoodAndMissingTitlesByNamespace();
@@ -63,9 +58,7 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase {
 
                $db = $this->getDB();
 
-               if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
-                       $this->dieUsage( 'user and excludeuser cannot be used together', 'badparams' );
-               }
+               $this->requireMaxOneParameter( $params, 'user', 'excludeuser' );
 
                $this->addTables( 'archive' );
                if ( $resultPageSet === null ) {
@@ -106,12 +99,7 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase {
                        $this->addFields( [ 'ar_text', 'ar_flags', 'old_text', 'old_flags' ] );
 
                        // This also means stricter restrictions
-                       if ( !$user->isAllowedAny( 'undelete', 'deletedtext' ) ) {
-                               $this->dieUsage(
-                                       'You don\'t have permission to view deleted revision content',
-                                       'permissiondenied'
-                               );
-                       }
+                       $this->checkUserRightsAny( [ 'deletedtext', 'undelete' ] );
                }
 
                $dir = $params['dir'];
index d58efa1..6a259cd 100644 (file)
@@ -37,21 +37,12 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
        }
 
        public function execute() {
-               $user = $this->getUser();
                // Before doing anything at all, let's check permissions
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $this->dieUsage(
-                               'You don\'t have permission to view deleted revision information',
-                               'permissiondenied'
-                       );
-               }
+               $this->checkUserRightsAny( 'deletedhistory' );
 
-               $this->setWarning(
-                       'list=deletedrevs has been deprecated. Please use prop=deletedrevisions or ' .
-                       'list=alldeletedrevisions instead.'
-               );
-               $this->logFeatureUsage( 'action=query&list=deletedrevs' );
+               $this->addDeprecation( 'apiwarn-deprecation-deletedrevs', 'action=query&list=deletedrevs' );
 
+               $user = $this->getUser();
                $db = $this->getDB();
                $params = $this->extractRequestParams( false );
                $prop = array_flip( $params['prop'] );
@@ -70,9 +61,6 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
 
                if ( isset( $prop['token'] ) ) {
                        $p = $this->getModulePrefix();
-                       $this->setWarning(
-                               "{$p}prop=token has been deprecated. Please use action=query&meta=tokens instead."
-                       );
                }
 
                // If we're in a mode that breaks the same-origin policy, no tokens can
@@ -105,19 +93,19 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                        // Ignore namespace and unique due to inability to know whether they were purposely set
                        foreach ( [ 'from', 'to', 'prefix', /*'namespace', 'unique'*/ ] as $p ) {
                                if ( !is_null( $params[$p] ) ) {
-                                       $this->dieUsage( "The '{$p}' parameter cannot be used in modes 1 or 2", 'badparams' );
+                                       $this->dieWithError( [ 'apierror-deletedrevs-param-not-1-2', $p ], 'badparams' );
                                }
                        }
                } else {
                        foreach ( [ 'start', 'end' ] as $p ) {
                                if ( !is_null( $params[$p] ) ) {
-                                       $this->dieUsage( "The {$p} parameter cannot be used in mode 3", 'badparams' );
+                                       $this->dieWithError( [ 'apierror-deletedrevs-param-not-3', $p ], 'badparams' );
                                }
                        }
                }
 
                if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
-                       $this->dieUsage( 'user and excludeuser cannot be used together', 'badparams' );
+                       $this->dieWithError( 'user and excludeuser cannot be used together', 'badparams' );
                }
 
                $this->addTables( 'archive' );
@@ -162,12 +150,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                        $this->addFields( [ 'ar_text', 'ar_flags', 'ar_text_id', 'old_text', 'old_flags' ] );
 
                        // This also means stricter restrictions
-                       if ( !$user->isAllowedAny( 'undelete', 'deletedtext' ) ) {
-                               $this->dieUsage(
-                                       'You don\'t have permission to view deleted revision content',
-                                       'permissiondenied'
-                               );
-                       }
+                       $this->checkUserRightsAny( [ 'deletedtext', 'undelete' ] );
                }
                // Check limits
                $userMax = $fld_content ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1;
index e1c97e1..9476066 100644 (file)
@@ -37,7 +37,7 @@
 class ApiQueryDisabled extends ApiQueryBase {
 
        public function execute() {
-               $this->setWarning( "The \"{$this->getModuleName()}\" module has been disabled." );
+               $this->addWarning( [ 'apierror-moduledisabled', $this->getModuleName() ] );
        }
 
        public function getAllowedParams() {
index 03be491..116dbb3 100644 (file)
@@ -38,15 +38,10 @@ class ApiQueryFilearchive extends ApiQueryBase {
        }
 
        public function execute() {
-               $user = $this->getUser();
                // Before doing anything at all, let's check permissions
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $this->dieUsage(
-                               'You don\'t have permission to view deleted file information',
-                               'permissiondenied'
-                       );
-               }
+               $this->checkUserRightsAny( 'deletedhistory' );
 
+               $user = $this->getUser();
                $db = $this->getDB();
 
                $params = $this->extractRequestParams();
@@ -112,13 +107,13 @@ class ApiQueryFilearchive extends ApiQueryBase {
                        if ( $sha1Set ) {
                                $sha1 = strtolower( $params['sha1'] );
                                if ( !$this->validateSha1Hash( $sha1 ) ) {
-                                       $this->dieUsage( 'The SHA1 hash provided is not valid', 'invalidsha1hash' );
+                                       $this->dieWithError( 'apierror-invalidsha1hash' );
                                }
                                $sha1 = Wikimedia\base_convert( $sha1, 16, 36, 31 );
                        } elseif ( $sha1base36Set ) {
                                $sha1 = strtolower( $params['sha1base36'] );
                                if ( !$this->validateSha1Base36Hash( $sha1 ) ) {
-                                       $this->dieUsage( 'The SHA1Base36 hash provided is not valid', 'invalidsha1base36hash' );
+                                       $this->dieWithError( 'apierror-invalidsha1base36hash' );
                                }
                        }
                        if ( $sha1 ) {
index 7568107..6e2fb67 100644 (file)
@@ -51,7 +51,14 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase {
                $params = $this->extractRequestParams();
 
                if ( isset( $params['title'] ) && !isset( $params['prefix'] ) ) {
-                       $this->dieUsageMsg( [ 'missingparam', 'prefix' ] );
+                       $this->dieWithError(
+                               [
+                                       'apierror-invalidparammix-mustusewith',
+                                       $this->encodeParamName( 'title' ),
+                                       $this->encodeParamName( 'prefix' ),
+                               ],
+                               'invalidparammix'
+                       );
                }
 
                if ( !is_null( $params['continue'] ) ) {
index 6d9c2ca..cfd990b 100644 (file)
@@ -45,7 +45,14 @@ class ApiQueryIWLinks extends ApiQueryBase {
                $prop = array_flip( (array)$params['prop'] );
 
                if ( isset( $params['title'] ) && !isset( $params['prefix'] ) ) {
-                       $this->dieUsageMsg( [ 'missingparam', 'prefix' ] );
+                       $this->dieWithError(
+                               [
+                                       'apierror-invalidparammix-mustusewith',
+                                       $this->encodeParamName( 'title' ),
+                                       $this->encodeParamName( 'prefix' ),
+                               ],
+                               'invalidparammix'
+                       );
                }
 
                // Handle deprecated param
index d1fcfa3..0bbfad3 100644 (file)
@@ -280,8 +280,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
 
                $h = $image->getHandler();
                if ( !$h ) {
-                       $this->setWarning( 'Could not create thumbnail because ' .
-                               $image->getName() . ' does not have an associated image handler' );
+                       $this->addWarning( [ 'apiwarn-nothumb-noimagehandler', wfEscapeWikiText( $image->getName() ) ] );
 
                        return $thumbParams;
                }
@@ -292,23 +291,24 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        // we could still render the image using width and height parameters,
                        // and this type of thing could happen between different versions of
                        // handlers.
-                       $this->setWarning( "Could not parse {$p}urlparam for " . $image->getName()
-                               . '. Using only width and height' );
+                       $this->addWarning( [ 'apiwarn-badurlparam', $p, wfEscapeWikiText( $image->getName() ) ] );
                        $this->checkParameterNormalise( $image, $thumbParams );
                        return $thumbParams;
                }
 
                if ( isset( $paramList['width'] ) && isset( $thumbParams['width'] ) ) {
                        if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) {
-                               $this->setWarning( "Ignoring width value set in {$p}urlparam ({$paramList['width']}) "
-                                       . "in favor of width value derived from {$p}urlwidth/{$p}urlheight "
-                                       . "({$thumbParams['width']})" );
+                               $this->addWarning(
+                                       [ 'apiwarn-urlparamwidth', $p, $paramList['width'], $thumbParams['width'] ]
+                               );
                        }
                }
 
                foreach ( $paramList as $name => $value ) {
                        if ( !$h->validateParam( $name, $value ) ) {
-                               $this->dieUsage( "Invalid value for {$p}urlparam ($name=$value)", 'urlparam' );
+                               $this->dieWithError(
+                                       [ 'apierror-invalidurlparam', $p, wfEscapeWikiText( $name ), wfEscapeWikiText( $value ) ]
+                               );
                        }
                }
 
@@ -337,8 +337,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                // in the actual normalised version, only if we can actually normalise them,
                // so we use the functions scope to throw away the normalisations.
                if ( !$h->normaliseParams( $image, $finalParams ) ) {
-                       $this->dieUsage( 'Could not normalise image parameters for ' .
-                               $image->getName(), 'urlparamnormal' );
+                       $this->dieWithError( [ 'apierror-urlparamnormal', wfEscapeWikiText( $image->getName() ) ] );
                }
        }
 
index e04d8c8..ae6f5bf 100644 (file)
@@ -90,7 +90,7 @@ class ApiQueryImages extends ApiQueryGeneratorBase {
                        foreach ( $params['images'] as $img ) {
                                $title = Title::newFromText( $img );
                                if ( !$title || $title->getNamespace() != NS_FILE ) {
-                                       $this->setWarning( "\"$img\" is not a file" );
+                                       $this->addWarning( [ 'apiwarn-notfile', wfEscapeWikiText( $img ) ] );
                                } else {
                                        $images[] = $title->getDBkey();
                                }
index d287020..fd65038 100644 (file)
@@ -427,7 +427,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        foreach ( $this->params['token'] as $t ) {
                                $val = call_user_func( $tokenFunctions[$t], $pageid, $title );
                                if ( $val === false ) {
-                                       $this->setWarning( "Action '$t' is not allowed for the current user" );
+                                       $this->addWarning( [ 'apiwarn-tokennotallowed', $t ] );
                                } else {
                                        $pageInfo[$t . 'token'] = $val;
                                }
index a6153de..8d5b5f3 100644 (file)
@@ -51,7 +51,14 @@ class ApiQueryLangBacklinks extends ApiQueryGeneratorBase {
                $params = $this->extractRequestParams();
 
                if ( isset( $params['title'] ) && !isset( $params['lang'] ) ) {
-                       $this->dieUsageMsg( [ 'missingparam', 'lang' ] );
+                       $this->dieWithError(
+                               [
+                                       'apierror-invalidparammix-mustusewith',
+                                       $this->encodeParamName( 'title' ),
+                                       $this->encodeParamName( 'lang' )
+                               ],
+                               'nolang'
+                       );
                }
 
                if ( !is_null( $params['continue'] ) ) {
index 67f2c9e..55e3c85 100644 (file)
@@ -44,7 +44,14 @@ class ApiQueryLangLinks extends ApiQueryBase {
                $prop = array_flip( (array)$params['prop'] );
 
                if ( isset( $params['title'] ) && !isset( $params['lang'] ) ) {
-                       $this->dieUsageMsg( [ 'missingparam', 'lang' ] );
+                       $this->dieWithError(
+                               [
+                                       'apierror-invalidparammix-mustusewith',
+                                       $this->encodeParamName( 'title' ),
+                                       $this->encodeParamName( 'lang' ),
+                               ],
+                               'invalidparammix'
+                       );
                }
 
                // Handle deprecated param
index 6e5239f..e9ae132 100644 (file)
@@ -94,7 +94,7 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
                        foreach ( $params[$this->titlesParam] as $t ) {
                                $title = Title::newFromText( $t );
                                if ( !$title ) {
-                                       $this->setWarning( "\"$t\" is not a valid title" );
+                                       $this->addWarning( [ 'apiwarn-invalidtitle', wfEscapeWikiText( $t ) ] );
                                } else {
                                        $lb->addObj( $title );
                                }
index 122594d..2dcd0b4 100644 (file)
@@ -121,10 +121,10 @@ class ApiQueryLogEvents extends ApiQueryBase {
                        }
 
                        if ( !$valid ) {
-                               $valueName = $this->encodeParamName( 'action' );
-                               $this->dieUsage(
-                                       "Unrecognized value for parameter '$valueName': {$logAction}",
-                                       "unknown_$valueName"
+                               $encParamName = $this->encodeParamName( 'action' );
+                               $this->dieWithError(
+                                       [ 'apierror-unrecognizedvalue', $encParamName, wfEscapeWikiText( $logAction ) ],
+                                       "unknown_$encParamName"
                                );
                        }
 
@@ -173,7 +173,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
                if ( !is_null( $title ) ) {
                        $titleObj = Title::newFromText( $title );
                        if ( is_null( $titleObj ) ) {
-                               $this->dieUsage( "Bad title value '$title'", 'param_title' );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $title ) ] );
                        }
                        $this->addWhereFld( 'log_namespace', $titleObj->getNamespace() );
                        $this->addWhereFld( 'log_title', $titleObj->getDBkey() );
@@ -187,12 +187,12 @@ class ApiQueryLogEvents extends ApiQueryBase {
 
                if ( !is_null( $prefix ) ) {
                        if ( $this->getConfig()->get( 'MiserMode' ) ) {
-                               $this->dieUsage( 'Prefix search disabled in Miser Mode', 'prefixsearchdisabled' );
+                               $this->dieWithError( 'apierror-prefixsearchdisabled' );
                        }
 
                        $title = Title::newFromText( $prefix );
                        if ( is_null( $title ) ) {
-                               $this->dieUsage( "Bad title value '$prefix'", 'param_prefix' );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $prefix ) ] );
                        }
                        $this->addWhereFld( 'log_namespace', $title->getNamespace() );
                        $this->addWhere( 'log_title ' . $db->buildLike( $title->getDBkey(), $db->anyString() ) );
index 0c70a8a..1324f2f 100644 (file)
@@ -36,7 +36,7 @@ class ApiQueryMyStashedFiles extends ApiQueryBase {
                $user = $this->getUser();
 
                if ( $user->isAnon() ) {
-                       $this->dieUsage( 'The upload stash is only available to logged-in users.', 'stashnotloggedin' );
+                       $this->dieWithError( 'apierror-mustbeloggedin-uploadstash', 'stashnotloggedin' );
                }
 
                // Note: If user is logged in but cannot upload, they can still see
index 9ba757c..908cdee 100644 (file)
@@ -62,7 +62,7 @@ class ApiQueryQueryPage extends ApiQueryGeneratorBase {
                /** @var $qp QueryPage */
                $qp = new $this->qpMap[$params['page']]();
                if ( !$qp->userCanExecute( $this->getUser() ) ) {
-                       $this->dieUsageMsg( 'specialpage-cantexecute' );
+                       $this->dieWithError( 'apierror-specialpage-cantexecute' );
                }
 
                $r = [ 'name' => $params['page'] ];
index 8b11dc2..8d14927 100644 (file)
@@ -195,7 +195,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                || ( isset( $show['patrolled'] ) && isset( $show['unpatrolled'] ) )
                                || ( isset( $show['!patrolled'] ) && isset( $show['unpatrolled'] ) )
                        ) {
-                               $this->dieUsageMsg( 'show' );
+                               $this->dieWithError( 'apierror-show' );
                        }
 
                        // Check permissions
@@ -204,10 +204,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                || isset( $show['unpatrolled'] )
                        ) {
                                if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                                       $this->dieUsage(
-                                               'You need patrol or patrolmarks permission to request the patrolled flag',
-                                               'permissiondenied'
-                                       );
+                                       $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' );
                                }
                        }
 
@@ -239,9 +236,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        );
                }
 
-               if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
-                       $this->dieUsage( 'user and excludeuser cannot be used together', 'user-excludeuser' );
-               }
+               $this->requireMaxOneParameter( $params, 'user', 'excludeuser' );
 
                if ( !is_null( $params['user'] ) ) {
                        $this->addWhereFld( 'rc_user_text', $params['user'] );
@@ -274,10 +269,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        $this->initProperties( $prop );
 
                        if ( $this->fld_patrolled && !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                               $this->dieUsage(
-                                       'You need patrol or patrolmarks permission to request the patrolled flag',
-                                       'permissiondenied'
-                               );
+                               $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' );
                        }
 
                        /* Add fields to our query if they are specified as a needed parameter. */
@@ -571,7 +563,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                $val = call_user_func( $tokenFunctions[$t], $row->rc_cur_id,
                                        $title, RecentChange::newFromRow( $row ) );
                                if ( $val === false ) {
-                                       $this->setWarning( "Action '$t' is not allowed for the current user" );
+                                       $this->addWarning( [ 'apiwarn-tokennotallowed', $t ] );
                                } else {
                                        $vals[$t . 'token'] = $val;
                                }
index 3259927..48f6046 100644 (file)
@@ -110,19 +110,14 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
                }
 
                if ( $revCount > 0 && $enumRevMode ) {
-                       $this->dieUsage(
-                               'The revids= parameter may not be used with the list options ' .
-                                       '(limit, startid, endid, dirNewer, start, end).',
-                               'revids'
+                       $this->dieWithError(
+                               [ 'apierror-revisions-nolist', $this->getModulePrefix() ], 'invalidparammix'
                        );
                }
 
                if ( $pageCount > 1 && $enumRevMode ) {
-                       $this->dieUsage(
-                               'titles, pageids or a generator was used to supply multiple pages, ' .
-                                       'but the limit, startid, endid, dirNewer, user, excludeuser, start ' .
-                                       'and end parameters may only be used on a single page.',
-                               'multpages'
+                       $this->dieWithError(
+                               [ 'apierror-revisions-singlepage', $this->getModulePrefix() ], 'invalidparammix'
                        );
                }
 
@@ -170,14 +165,19 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
                if ( $this->fetchContent ) {
                        // For each page we will request, the user must have read rights for that page
                        $user = $this->getUser();
+                       $status = Status::newGood();
                        /** @var $title Title */
                        foreach ( $pageSet->getGoodTitles() as $title ) {
                                if ( !$title->userCan( 'read', $user ) ) {
-                                       $this->dieUsage(
-                                               'The current user is not allowed to read ' . $title->getPrefixedText(),
-                                               'accessdenied' );
+                                       $status->fatal( ApiMessage::create(
+                                               [ 'apierror-cannotviewtitle', wfEscapeWikiText( $title->getPrefixedText() ) ],
+                                               'accessdenied'
+                                       ) );
                                }
                        }
+                       if ( !$status->isGood() ) {
+                               $this->dieStatus( $status );
+                       }
 
                        $this->addTables( 'text' );
                        $this->addJoinConds(
@@ -201,17 +201,9 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
                        //  page_timestamp or usertext_timestamp if we have an IP rvuser
 
                        // This is mostly to prevent parameter errors (and optimize SQL?)
-                       if ( $params['startid'] !== null && $params['start'] !== null ) {
-                               $this->dieUsage( 'start and startid cannot be used together', 'badparams' );
-                       }
-
-                       if ( $params['endid'] !== null && $params['end'] !== null ) {
-                               $this->dieUsage( 'end and endid cannot be used together', 'badparams' );
-                       }
-
-                       if ( $params['user'] !== null && $params['excludeuser'] !== null ) {
-                               $this->dieUsage( 'user and excludeuser cannot be used together', 'badparams' );
-                       }
+                       $this->requireMaxOneParameter( $params, 'startid', 'start' );
+                       $this->requireMaxOneParameter( $params, 'endid', 'end' );
+                       $this->requireMaxOneParameter( $params, 'user', 'excludeuser' );
 
                        if ( $params['continue'] !== null ) {
                                $cont = explode( '|', $params['continue'] );
@@ -344,7 +336,7 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
                                        foreach ( $this->token as $t ) {
                                                $val = call_user_func( $tokenFunctions[$t], $title->getArticleID(), $title, $revision );
                                                if ( $val === false ) {
-                                                       $this->setWarning( "Action '$t' is not allowed for the current user" );
+                                                       $this->addWarning( [ 'apiwarn-tokennotallowed', $t ] );
                                                } else {
                                                        $rev[$t . 'token'] = $val;
                                                }
index 266d699..696ec87 100644 (file)
@@ -70,10 +70,7 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                                && $params['diffto'] != 'prev' && $params['diffto'] != 'next'
                        ) {
                                $p = $this->getModulePrefix();
-                               $this->dieUsage(
-                                       "{$p}diffto must be set to a non-negative number, \"prev\", \"next\" or \"cur\"",
-                                       'diffto'
-                               );
+                               $this->dieWithError( [ 'apierror-baddiffto', $p ], 'diffto' );
                        }
                        // Check whether the revision exists and is readable,
                        // DifferenceEngine returns a rather ambiguous empty
@@ -81,10 +78,10 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                        if ( $params['diffto'] != 0 ) {
                                $difftoRev = Revision::newFromId( $params['diffto'] );
                                if ( !$difftoRev ) {
-                                       $this->dieUsageMsg( [ 'nosuchrevid', $params['diffto'] ] );
+                                       $this->dieWithError( [ 'apierror-nosuchrevid', $params['diffto'] ] );
                                }
                                if ( !$difftoRev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
-                                       $this->setWarning( "Couldn't diff to r{$difftoRev->getId()}: content is hidden" );
+                                       $this->addWarning( [ 'apiwarn-difftohidden', $difftoRev->getId() ] );
                                        $params['diffto'] = null;
                                }
                        }
@@ -262,8 +259,12 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                        if ( $content && $this->section !== false ) {
                                $content = $content->getSection( $this->section, false );
                                if ( !$content ) {
-                                       $this->dieUsage(
-                                               "There is no section {$this->section} in r" . $revision->getId(),
+                                       $this->dieWithError(
+                                               [
+                                                       'apierror-nosuchsection-what',
+                                                       wfEscapeWikiText( $this->section ),
+                                                       $this->msg( 'revid', $revision->getId() )
+                                               ],
                                                'nosuchsection'
                                        );
                                }
@@ -294,9 +295,14 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                                        $vals['parsetree'] = $xml;
                                } else {
                                        $vals['badcontentformatforparsetree'] = true;
-                                       $this->setWarning( 'Conversion to XML is supported for wikitext only, ' .
-                                               $title->getPrefixedDBkey() .
-                                               ' uses content model ' . $content->getModel() );
+                                       $this->addWarning(
+                                               [
+                                                       'apierror-parsetree-notwikitext-title',
+                                                       wfEscapeWikiText( $title->getPrefixedText() ),
+                                                       $content->getModel()
+                                               ],
+                                               'parsetree-notwikitext'
+                                       );
                                }
                        }
                }
@@ -315,9 +321,11 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                                                ParserOptions::newFromContext( $this->getContext() )
                                        );
                                } else {
-                                       $this->setWarning( 'Template expansion is supported for wikitext only, ' .
-                                               $title->getPrefixedDBkey() .
-                                               ' uses content model ' . $content->getModel() );
+                                       $this->addWarning( [
+                                               'apierror-templateexpansion-notwikitext',
+                                               wfEscapeWikiText( $title->getPrefixedText() ),
+                                               $content->getModel()
+                                       ] );
                                        $vals['badcontentformat'] = true;
                                        $text = false;
                                }
@@ -336,9 +344,8 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                                $model = $content->getModel();
 
                                if ( !$content->isSupportedFormat( $format ) ) {
-                                       $name = $title->getPrefixedDBkey();
-                                       $this->setWarning( "The requested format {$this->contentFormat} is not " .
-                                               "supported for content model $model used by $name" );
+                                       $name = wfEscapeWikiText( $title->getPrefixedText() );
+                                       $this->addWarning( [ 'apierror-badformat', $this->contentFormat, $model, $name ] );
                                        $vals['badcontentformat'] = true;
                                        $text = false;
                                } else {
@@ -370,9 +377,8 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
                                        if ( $this->contentFormat
                                                && !ContentHandler::getForModelID( $model )->isSupportedFormat( $this->contentFormat )
                                        ) {
-                                               $name = $title->getPrefixedDBkey();
-                                               $this->setWarning( "The requested format {$this->contentFormat} is not " .
-                                                       "supported for content model $model used by $name" );
+                                               $name = wfEscapeWikiText( $title->getPrefixedText() );
+                                               $this->addWarning( [ 'apierror-badformat', $this->contentFormat, $model, $name ] );
                                                $vals['diff']['badcontentformat'] = true;
                                                $engine = null;
                                        } else {
index 6be5198..64bc43f 100644 (file)
@@ -64,12 +64,14 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
 
                // Deprecated parameters
                if ( isset( $prop['hasrelated'] ) ) {
-                       $this->logFeatureUsage( 'action=search&srprop=hasrelated' );
-                       $this->setWarning( 'srprop=hasrelated has been deprecated' );
+                       $this->addDeprecation(
+                               [ 'apiwarn-deprecation-parameter', 'srprop=hasrelated' ], 'action=search&srprop=hasrelated'
+                       );
                }
                if ( isset( $prop['score'] ) ) {
-                       $this->logFeatureUsage( 'action=search&srprop=score' );
-                       $this->setWarning( 'srprop=score has been deprecated' );
+                       $this->addDeprecation(
+                               [ 'apiwarn-deprecation-parameter', 'srprop=score' ], 'action=search&srprop=score'
+                       );
                }
 
                // Create search engine instance and set options
@@ -107,10 +109,25 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                                $matches = $search->searchText( $query );
                        }
                }
-               if ( is_null( $matches ) ) {
-                       $this->dieUsage( "{$what} search is disabled", "search-{$what}-disabled" );
-               } elseif ( $matches instanceof Status && !$matches->isGood() ) {
-                       $this->dieUsage( $matches->getWikiText( false, false, 'en' ), 'search-error' );
+
+               if ( $matches instanceof Status ) {
+                       $status = $matches;
+                       $matches = $status->getValue();
+               } else {
+                       $status = null;
+               }
+
+               if ( $status ) {
+                       if ( $status->isOK() ) {
+                               $this->getMain()->getErrorFormatter()->addMessagesFromStatus(
+                                       $this->getModuleName(),
+                                       $status
+                               );
+                       } else {
+                               $this->dieStatus( $status );
+                       }
+               } elseif ( is_null( $matches ) ) {
+                       $this->dieWithError( [ 'apierror-searchdisabled', $what ], "search-{$what}-disabled" );
                }
 
                if ( $resultPageSet === null ) {
index 0bb7ff8..6fc6aa3 100644 (file)
@@ -253,6 +253,8 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $data['maxuploadsize'] = UploadBase::getMaxUploadSize();
                $data['minuploadchunksize'] = (int)$config->get( 'MinUploadChunkSize' );
 
+               $data['galleryoptions'] = $config->get( 'GalleryOptions' );
+
                $data['thumblimits'] = $config->get( 'ThumbLimits' );
                ApiResult::setArrayType( $data['thumblimits'], 'BCassoc' );
                ApiResult::setIndexedTagName( $data['thumblimits'], 'limit' );
@@ -445,10 +447,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $showHostnames = $this->getConfig()->get( 'ShowHostnames' );
                if ( $includeAll ) {
                        if ( !$showHostnames ) {
-                               $this->dieUsage(
-                                       'Cannot view all servers info unless $wgShowHostnames is true',
-                                       'includeAllDenied'
-                               );
+                               $this->dieWithError( 'apierror-siteinfo-includealldenied', 'includeAllDenied' );
                        }
 
                        $lags = $lb->getLagTimes();
index b039a1e..981cb09 100644 (file)
@@ -33,7 +33,7 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
 
        public function execute() {
                if ( !$this->getUser()->isLoggedIn() ) {
-                       $this->dieUsage( 'You must be logged-in to have an upload stash', 'notloggedin' );
+                       $this->dieWithError( 'apierror-mustbeloggedin-uploadstash', 'notloggedin' );
                }
 
                $params = $this->extractRequestParams();
@@ -45,9 +45,7 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
 
                $result = $this->getResult();
 
-               if ( !$params['filekey'] && !$params['sessionkey'] ) {
-                       $this->dieUsage( 'One of filekey or sessionkey must be supplied', 'nofilekey' );
-               }
+               $this->requireAtLeastOneParameter( $params, 'filekey', 'sessionkey' );
 
                // Alias sessionkey to filekey, but give an existing filekey precedence.
                if ( !$params['filekey'] && $params['sessionkey'] ) {
@@ -65,10 +63,11 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
                                $result->addIndexedTagName( [ 'query', $this->getModuleName() ], $modulePrefix );
                        }
                // @todo Update exception handling here to understand current getFile exceptions
+               // @todo Internationalize the exceptions
                } catch ( UploadStashFileNotFoundException $e ) {
-                       $this->dieUsage( 'File not found: ' . $e->getMessage(), 'invalidsessiondata' );
+                       $this->dieWithError( [ 'apierror-stashedfilenotfound', wfEscapeWikiText( $e->getMessage() ) ] );
                } catch ( UploadStashBadPathException $e ) {
-                       $this->dieUsage( 'Bad path: ' . $e->getMessage(), 'invalidsessiondata' );
+                       $this->dieWithError( [ 'apierror-stashpathinvalid', wfEscapeWikiText( $e->getMessage() ) ] );
                }
        }
 
index de5a377..5b700db 100644 (file)
@@ -40,7 +40,7 @@ class ApiQueryTokens extends ApiQueryBase {
                ];
 
                if ( $this->lacksSameOriginSecurity() ) {
-                       $this->setWarning( 'Tokens may not be obtained when the same-origin policy is not applied' );
+                       $this->addWarning( [ 'apiwarn-tokens-origin' ] );
                        return;
                }
 
index b85bec4..b6d871b 100644 (file)
@@ -78,11 +78,17 @@ class ApiQueryContributions extends ApiQueryBase {
                                $this->params['user'] = [ $this->params['user'] ];
                        }
                        if ( !count( $this->params['user'] ) ) {
-                               $this->dieUsage( 'User parameter may not be empty.', 'param_user' );
+                               $encParamName = $this->encodeParamName( 'user' );
+                               $this->dieWithError(
+                                       [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName"
+                               );
                        }
                        foreach ( $this->params['user'] as $u ) {
                                if ( is_null( $u ) || $u === '' ) {
-                                       $this->dieUsage( 'User parameter may not be empty', 'param_user' );
+                                       $encParamName = $this->encodeParamName( 'user' );
+                                       $this->dieWithError(
+                                               [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName"
+                                       );
                                }
 
                                if ( User::isIP( $u ) ) {
@@ -91,7 +97,10 @@ class ApiQueryContributions extends ApiQueryBase {
                                } else {
                                        $name = User::getCanonicalName( $u, 'valid' );
                                        if ( $name === false ) {
-                                               $this->dieUsage( "User name {$u} is not valid", 'param_user' );
+                                               $encParamName = $this->encodeParamName( 'user' );
+                                               $this->dieWithError(
+                                                       [ 'apierror-baduser', $encParamName, wfEscapeWikiText( $u ) ], "baduser_$encParamName"
+                                               );
                                        }
                                        $this->usernames[] = $name;
                                }
@@ -254,7 +263,7 @@ class ApiQueryContributions extends ApiQueryBase {
                                || ( isset( $show['top'] ) && isset( $show['!top'] ) )
                                || ( isset( $show['new'] ) && isset( $show['!new'] ) )
                        ) {
-                               $this->dieUsageMsg( 'show' );
+                               $this->dieWithError( 'apierror-show' );
                        }
 
                        $this->addWhereIf( 'rev_minor_edit = 0', isset( $show['!minor'] ) );
@@ -285,10 +294,7 @@ class ApiQueryContributions extends ApiQueryBase {
                        $this->fld_patrolled
                ) {
                        if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                               $this->dieUsage(
-                                       'You need the patrol right to request the patrolled flag',
-                                       'permissiondenied'
-                               );
+                               $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' );
                        }
 
                        // Use a redundant join condition on both
index d3cd0c4..3b60478 100644 (file)
@@ -170,8 +170,13 @@ class ApiQueryUserInfo extends ApiQueryBase {
 
                if ( isset( $this->prop['preferencestoken'] ) ) {
                        $p = $this->getModulePrefix();
-                       $this->setWarning(
-                               "{$p}prop=preferencestoken has been deprecated. Please use action=query&meta=tokens instead."
+                       $this->addDeprecation(
+                               [
+                                       'apiwarn-deprecation-withreplacement',
+                                       "{$p}prop=preferencestoken",
+                                       'action=query&meta=tokens',
+                               ],
+                               "meta=userinfo&{$p}prop=preferencestoken"
                        );
                }
                if ( isset( $this->prop['preferencestoken'] ) &&
index 9b45b91..65d3797 100644 (file)
@@ -226,7 +226,7 @@ class ApiQueryUsers extends ApiQueryBase {
                                        foreach ( $params['token'] as $t ) {
                                                $val = call_user_func( $tokenFunctions[$t], $user );
                                                if ( $val === false ) {
-                                                       $this->setWarning( "Action '$t' is not allowed for the current user" );
+                                                       $this->addWarning( [ 'apiwarn-tokennotallowed', $t ] );
                                                } else {
                                                        $data[$name][$t . 'token'] = $val;
                                                }
@@ -253,7 +253,7 @@ class ApiQueryUsers extends ApiQueryBase {
                                                foreach ( $params['token'] as $t ) {
                                                        $val = call_user_func( $tokenFunctions[$t], $iwUser );
                                                        if ( $val === false ) {
-                                                               $this->setWarning( "Action '$t' is not allowed for the current user" );
+                                                               $this->addWarning( [ 'apiwarn-tokennotallowed', $t ] );
                                                        } else {
                                                                $data[$u][$t . 'token'] = $val;
                                                        }
index 42ea55d..6b5ceb7 100644 (file)
@@ -82,7 +82,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
 
                        if ( $this->fld_patrol ) {
                                if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                                       $this->dieUsage( 'patrol property is not available', 'patrol' );
+                                       $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'patrol' );
                                }
                        }
                }
@@ -134,7 +134,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
 
                        /* Check for conflicting parameters. */
                        if ( $this->showParamsConflicting( $show ) ) {
-                               $this->dieUsageMsg( 'show' );
+                               $this->dieWithError( 'apierror-show' );
                        }
 
                        // Check permissions.
@@ -142,10 +142,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                                || isset( $show[WatchedItemQueryService::FILTER_NOT_PATROLLED] )
                        ) {
                                if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                                       $this->dieUsage(
-                                               'You need the patrol right to request the patrolled flag',
-                                               'permissiondenied'
-                                       );
+                                       $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' );
                                }
                        }
 
@@ -160,9 +157,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                        }
                }
 
-               if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
-                       $this->dieUsage( 'user and excludeuser cannot be used together', 'user-excludeuser' );
-               }
+               $this->requireMaxOneParameter( $params, 'user', 'excludeuser' );
                if ( !is_null( $params['user'] ) ) {
                        $options['onlyByUser'] = $params['user'];
                }
index 806861e..a1078a5 100644 (file)
@@ -60,7 +60,7 @@ class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
                if ( isset( $show[WatchedItemQueryService::FILTER_CHANGED] )
                        && isset( $show[WatchedItemQueryService::FILTER_NOT_CHANGED] )
                ) {
-                       $this->dieUsageMsg( 'show' );
+                       $this->dieWithError( 'apierror-show' );
                }
 
                $options = [];
index d72c8a4..359d045 100644 (file)
@@ -45,7 +45,7 @@ class ApiRemoveAuthenticationData extends ApiBase {
 
        public function execute() {
                if ( !$this->getUser()->isLoggedIn() ) {
-                       $this->dieUsage( 'Must be logged in to remove authentication data', 'notloggedin' );
+                       $this->dieWithError( 'apierror-mustbeloggedin-removeauth', 'notloggedin' );
                }
 
                $params = $this->extractRequestParams();
@@ -67,7 +67,7 @@ class ApiRemoveAuthenticationData extends ApiBase {
                        }
                );
                if ( count( $reqs ) !== 1 ) {
-                       $this->dieUsage( 'Failed to create change request', 'badrequest' );
+                       $this->dieWithError( 'apierror-changeauth-norequest', 'badrequest' );
                }
                $req = reset( $reqs );
 
index 042ad69..b5fa8ed 100644 (file)
@@ -52,7 +52,7 @@ class ApiResetPassword extends ApiBase {
 
        public function execute() {
                if ( !$this->hasAnyRoutes() ) {
-                       $this->dieUsage( 'No password reset routes are available.', 'moduledisabled' );
+                       $this->dieWithError( 'apihelp-resetpassword-description-noroutes', 'moduledisabled' );
                }
 
                $params = $this->extractRequestParams() + [
@@ -65,13 +65,13 @@ class ApiResetPassword extends ApiBase {
 
                $passwordReset = new PasswordReset( $this->getConfig(), AuthManager::singleton() );
 
-               $status = $passwordReset->isAllowed( $this->getUser(), $params['capture'] );
+               $status = $passwordReset->isAllowed( $this->getUser() );
                if ( !$status->isOK() ) {
                        $this->dieStatus( Status::wrap( $status ) );
                }
 
                $status = $passwordReset->execute(
-                       $this->getUser(), $params['user'], $params['email'], $params['capture']
+                       $this->getUser(), $params['user'], $params['email']
                );
                if ( !$status->isOK() ) {
                        $status->value = null;
@@ -80,12 +80,6 @@ class ApiResetPassword extends ApiBase {
 
                $result = $this->getResult();
                $result->addValue( [ 'resetpassword' ], 'status', 'success' );
-               if ( $params['capture'] ) {
-                       $passwords = $status->getValue() ?: [];
-                       ApiResult::setArrayType( $passwords, 'kvp', 'user' );
-                       ApiResult::setIndexedTagName( $passwords, 'p' );
-                       $result->addValue( [ 'resetpassword' ], 'passwords', $passwords );
-               }
        }
 
        public function isWriteMode() {
@@ -111,7 +105,6 @@ class ApiResetPassword extends ApiBase {
                        'email' => [
                                ApiBase::PARAM_TYPE => 'string',
                        ],
-                       'capture' => false,
                ];
 
                $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
index 6e27fc8..61a4394 100644 (file)
@@ -413,11 +413,9 @@ class ApiResult implements ApiSerializable {
 
                        $newsize = $this->size + self::size( $value );
                        if ( $this->maxSize !== false && $newsize > $this->maxSize ) {
-                               /// @todo Add i18n message when replacing calls to ->setWarning()
-                               $msg = new ApiRawMessage( 'This result was truncated because it would otherwise ' .
-                                       'be larger than the limit of $1 bytes', 'truncatedresult' );
-                               $msg->numParams( $this->maxSize );
-                               $this->errorFormatter->addWarning( 'result', $msg );
+                               $this->errorFormatter->addWarning(
+                                       'result', [ 'apiwarn-truncatedresult', Message::numParam( $this->maxSize ) ]
+                               );
                                return false;
                        }
                        $this->size = $newsize;
index ed9fba2..763aef5 100644 (file)
@@ -36,24 +36,22 @@ class ApiRevisionDelete extends ApiBase {
 
                $params = $this->extractRequestParams();
                $user = $this->getUser();
-               if ( !$user->isAllowed( RevisionDeleter::getRestriction( $params['type'] ) ) ) {
-                       $this->dieUsageMsg( 'badaccess-group0' );
-               }
+               $this->checkUserRightsAny( RevisionDeleter::getRestriction( $params['type'] ) );
 
                if ( $user->isBlocked() ) {
                        $this->dieBlocked( $user->getBlock() );
                }
 
                if ( !$params['ids'] ) {
-                       $this->dieUsage( "At least one value is required for 'ids'", 'badparams' );
+                       $this->dieWithError( [ 'apierror-paramempty', 'ids' ], 'paramempty_ids' );
                }
 
                $hide = $params['hide'] ?: [];
                $show = $params['show'] ?: [];
                if ( array_intersect( $hide, $show ) ) {
-                       $this->dieUsage( "Mutually exclusive values for 'hide' and 'show'", 'badparams' );
+                       $this->dieWithError( 'apierror-revdel-mutuallyexclusive', 'badparams' );
                } elseif ( !$hide && !$show ) {
-                       $this->dieUsage( "At least one value is required for 'hide' or 'show'", 'badparams' );
+                       $this->dieWithError( 'apierror-revdel-paramneeded', 'badparams' );
                }
                $bits = [
                        'content' => RevisionDeleter::getRevdelConstant( $params['type'] ),
@@ -72,9 +70,7 @@ class ApiRevisionDelete extends ApiBase {
                }
 
                if ( $params['suppress'] === 'yes' ) {
-                       if ( !$user->isAllowed( 'suppressrevision' ) ) {
-                               $this->dieUsageMsg( 'badaccess-group0' );
-                       }
+                       $this->checkUserRightsAny( 'suppressrevision' );
                        $bitfield[Revision::DELETED_RESTRICTED] = 1;
                } elseif ( $params['suppress'] === 'no' ) {
                        $bitfield[Revision::DELETED_RESTRICTED] = 0;
@@ -88,7 +84,7 @@ class ApiRevisionDelete extends ApiBase {
                }
                $targetObj = RevisionDeleter::suggestTarget( $params['type'], $targetObj, $params['ids'] );
                if ( $targetObj === null ) {
-                       $this->dieUsage( 'A target title is required for this RevDel type', 'needtarget' );
+                       $this->dieWithError( [ 'apierror-revdel-needtarget' ], 'needtarget' );
                }
 
                $list = RevisionDeleter::createList(
@@ -124,49 +120,19 @@ class ApiRevisionDelete extends ApiBase {
                $ret = [
                        'status' => $status->isOK() ? 'Success' : 'Fail',
                ];
-               $errors = $this->formatStatusMessages( $status->getErrorsByType( 'error' ) );
+
+               $errors = $this->getErrorFormatter()->arrayFromStatus( $status, 'error' );
                if ( $errors ) {
-                       ApiResult::setIndexedTagName( $errors, 'e' );
                        $ret['errors'] = $errors;
                }
-               $warnings = $this->formatStatusMessages( $status->getErrorsByType( 'warning' ) );
+               $warnings = $this->getErrorFormatter()->arrayFromStatus( $status, 'warning' );
                if ( $warnings ) {
-                       ApiResult::setIndexedTagName( $warnings, 'w' );
                        $ret['warnings'] = $warnings;
                }
 
                return $ret;
        }
 
-       private function formatStatusMessages( $messages ) {
-               if ( !$messages ) {
-                       return [];
-               }
-               $ret = [];
-               foreach ( $messages as $m ) {
-                       if ( $m['message'] instanceof Message ) {
-                               $msg = $m['message'];
-                               $message = [ 'message' => $msg->getKey() ];
-                               if ( $msg->getParams() ) {
-                                       $message['params'] = $msg->getParams();
-                                       ApiResult::setIndexedTagName( $message['params'], 'p' );
-                               }
-                       } else {
-                               $message = [ 'message' => $m['message'] ];
-                               $msg = wfMessage( $m['message'] );
-                               if ( isset( $m['params'] ) ) {
-                                       $message['params'] = $m['params'];
-                                       ApiResult::setIndexedTagName( $message['params'], 'p' );
-                                       $msg->params( $m['params'] );
-                               }
-                       }
-                       $message['rendered'] = $msg->useDatabase( false )->inLanguage( 'en' )->plain();
-                       $ret[] = $message;
-               }
-
-               return $ret;
-       }
-
        public function mustBePosted() {
                return true;
        }
index b9911da..c802087 100644 (file)
@@ -69,24 +69,8 @@ class ApiRollback extends ApiBase {
                        $params['tags']
                );
 
-               // We don't care about multiple errors, just report one of them
                if ( $retval ) {
-                       if ( isset( $retval[0][0] ) &&
-                               ( $retval[0][0] == 'alreadyrolled' || $retval[0][0] == 'cantrollback' )
-                       ) {
-                               $error = $retval[0];
-                               $userMessage = $this->msg( $error[0], array_slice( $error, 1 ) );
-                               // dieUsageMsg() doesn't support $extraData
-                               $errorCode = $error[0];
-                               $errorInfo = isset( ApiBase::$messageMap[$errorCode] ) ?
-                                       ApiBase::$messageMap[$errorCode]['info'] :
-                                       $errorCode;
-                               $this->dieUsage( $errorInfo, $errorCode, 0, [
-                                       'messageHtml' => $userMessage->parseAsBlock()
-                               ] );
-                       }
-
-                       $this->dieUsageMsg( reset( $retval ) );
+                       $this->dieStatus( $this->errorArrayToStatus( $retval, $user ) );
                }
 
                $watch = 'preferences';
@@ -181,7 +165,7 @@ class ApiRollback extends ApiBase {
                        ? $params['user']
                        : User::getCanonicalName( $params['user'] );
                if ( !$this->mUser ) {
-                       $this->dieUsageMsg( [ 'invaliduser', $params['user'] ] );
+                       $this->dieWithError( [ 'apierror-invaliduser', wfEscapeWikiText( $params['user'] ) ] );
                }
 
                return $this->mUser;
@@ -202,17 +186,17 @@ class ApiRollback extends ApiBase {
                if ( isset( $params['title'] ) ) {
                        $this->mTitleObj = Title::newFromText( $params['title'] );
                        if ( !$this->mTitleObj || $this->mTitleObj->isExternal() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $params['title'] ] );
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
                        }
                } elseif ( isset( $params['pageid'] ) ) {
                        $this->mTitleObj = Title::newFromID( $params['pageid'] );
                        if ( !$this->mTitleObj ) {
-                               $this->dieUsageMsg( [ 'nosuchpageid', $params['pageid'] ] );
+                               $this->dieWithError( [ 'apierror-nosuchpageid', $params['pageid'] ] );
                        }
                }
 
                if ( !$this->mTitleObj->exists() ) {
-                       $this->dieUsageMsg( 'notanarticle' );
+                       $this->dieWithError( 'apierror-missingtitle' );
                }
 
                return $this->mTitleObj;
index 3412f38..5769ff6 100644 (file)
@@ -38,11 +38,9 @@ class ApiSetNotificationTimestamp extends ApiBase {
                $user = $this->getUser();
 
                if ( $user->isAnon() ) {
-                       $this->dieUsage( 'Anonymous users cannot use watchlist change notifications', 'notloggedin' );
-               }
-               if ( !$user->isAllowed( 'editmywatchlist' ) ) {
-                       $this->dieUsage( 'You don\'t have permission to edit your watchlist', 'permissiondenied' );
+                       $this->dieWithError( 'watchlistanontext', 'notloggedin' );
                }
+               $this->checkUserRightsAny( 'editmywatchlist' );
 
                $params = $this->extractRequestParams();
                $this->requireMaxOneParameter( $params, 'timestamp', 'torevid', 'newerthanrevid' );
@@ -52,8 +50,12 @@ class ApiSetNotificationTimestamp extends ApiBase {
 
                $pageSet = $this->getPageSet();
                if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
-                       $this->dieUsage(
-                               "Cannot use 'entirewatchlist' at the same time as '{$pageSet->getDataSource()}'",
+                       $this->dieWithError(
+                               [
+                                       'apierror-invalidparammix-cannotusewith',
+                                       $this->encodeParamName( 'entirewatchlist' ),
+                                       $pageSet->encodeParamName( $pageSet->getDataSource() )
+                               ],
                                'multisource'
                        );
                }
@@ -71,7 +73,7 @@ class ApiSetNotificationTimestamp extends ApiBase {
 
                if ( isset( $params['torevid'] ) ) {
                        if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
-                               $this->dieUsage( 'torevid may only be used with a single page', 'multpages' );
+                               $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'torevid' ) ] );
                        }
                        $title = reset( $pageSet->getGoodTitles() );
                        if ( $title ) {
@@ -85,7 +87,7 @@ class ApiSetNotificationTimestamp extends ApiBase {
                        }
                } elseif ( isset( $params['newerthanrevid'] ) ) {
                        if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
-                               $this->dieUsage( 'newerthanrevid may only be used with a single page', 'multpages' );
+                               $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'newerthanrevid' ) ] );
                        }
                        $title = reset( $pageSet->getGoodTitles() );
                        if ( $title ) {
index 92cbe90..e29fda5 100644 (file)
@@ -51,7 +51,7 @@ class ApiStashEdit extends ApiBase {
                $params = $this->extractRequestParams();
 
                if ( $user->isBot() ) { // sanity
-                       $this->dieUsage( 'This interface is not supported for bots', 'botsnotsupported' );
+                       $this->dieWithError( 'apierror-botsnotsupported' );
                }
 
                $cache = ObjectCache::getLocalClusterInstance();
@@ -61,9 +61,14 @@ class ApiStashEdit extends ApiBase {
                if ( !ContentHandler::getForModelID( $params['contentmodel'] )
                        ->isSupportedFormat( $params['contentformat'] )
                ) {
-                       $this->dieUsage( 'Unsupported content model/format', 'badmodelformat' );
+                       $this->dieWithError(
+                               [ 'apierror-badformat-generic', $params['contentformat'], $params['contentmodel'] ],
+                               'badmodelformat'
+                       );
                }
 
+               $this->requireAtLeastOneParameter( $params, 'stashedtexthash', 'text' );
+
                $text = null;
                $textHash = null;
                if ( strlen( $params['stashedtexthash'] ) ) {
@@ -72,15 +77,18 @@ class ApiStashEdit extends ApiBase {
                        $textKey = $cache->makeKey( 'stashedit', 'text', $textHash );
                        $text = $cache->get( $textKey );
                        if ( !is_string( $text ) ) {
-                               $this->dieUsage( 'No stashed text found with the given hash', 'missingtext' );
+                               $this->dieWithError( 'apierror-stashedit-missingtext', 'missingtext' );
                        }
                } elseif ( $params['text'] !== null ) {
                        // Trim and fix newlines so the key SHA1's match (see WebRequest::getText())
                        $text = rtrim( str_replace( "\r\n", "\n", $params['text'] ) );
                        $textHash = sha1( $text );
                } else {
-                       $this->dieUsage(
-                               'The text or stashedtexthash parameter must be given', 'missingtextparam' );
+                       $this->dieWithError( [
+                               'apierror-missingparam-at-least-one-of',
+                               Message::listParam( [ '<var>stashedtexthash</var>', '<var>text</var>' ] ),
+                               2,
+                       ], 'missingparam' );
                }
 
                $textContent = ContentHandler::makeContent(
@@ -91,11 +99,11 @@ class ApiStashEdit extends ApiBase {
                        // Page exists: get the merged content with the proposed change
                        $baseRev = Revision::newFromPageId( $page->getId(), $params['baserevid'] );
                        if ( !$baseRev ) {
-                               $this->dieUsage( "No revision ID {$params['baserevid']}", 'missingrev' );
+                               $this->dieWithError( [ 'apierror-nosuchrevid', $params['baserevid'] ] );
                        }
                        $currentRev = $page->getRevision();
                        if ( !$currentRev ) {
-                               $this->dieUsage( "No current revision of page ID {$page->getId()}", 'missingrev' );
+                               $this->dieWithError( [ 'apierror-missingrev-pageid', $page->getId() ], 'missingrev' );
                        }
                        // Merge in the new version of the section to get the proposed version
                        $editContent = $page->replaceSectionAtRev(
@@ -105,7 +113,7 @@ class ApiStashEdit extends ApiBase {
                                $baseRev->getId()
                        );
                        if ( !$editContent ) {
-                               $this->dieUsage( 'Could not merge updated section.', 'replacefailed' );
+                               $this->dieWithError( 'apierror-sectionreplacefailed', 'replacefailed' );
                        }
                        if ( $currentRev->getId() == $baseRev->getId() ) {
                                // Base revision was still the latest; nothing to merge
@@ -115,7 +123,7 @@ class ApiStashEdit extends ApiBase {
                                $baseContent = $baseRev->getContent();
                                $currentContent = $currentRev->getContent();
                                if ( !$baseContent || !$currentContent ) {
-                                       $this->dieUsage( "Missing content for page ID {$page->getId()}", 'missingrev' );
+                                       $this->dieWithError( [ 'apierror-missingcontent-pageid', $page->getId() ], 'missingrev' );
                                }
                                $handler = ContentHandler::getForModelID( $baseContent->getModel() );
                                $content = $handler->merge3( $baseContent, $editContent, $currentContent );
index f88c2db..f6c0584 100644 (file)
@@ -30,10 +30,7 @@ class ApiTag extends ApiBase {
                $user = $this->getUser();
 
                // make sure the user is allowed
-               if ( !$user->isAllowed( 'changetags' ) ) {
-                       $this->dieUsage( "You don't have permission to add or remove change tags from individual edits",
-                               'permissiondenied' );
-               }
+               $this->checkUserRightsAny( 'changetags' );
 
                if ( $user->isBlocked() ) {
                        $this->dieBlocked( $user->getBlock() );
@@ -88,7 +85,8 @@ class ApiTag extends ApiBase {
 
                if ( !$valid ) {
                        $idResult['status'] = 'error';
-                       $idResult += $this->parseMsg( [ "nosuch$type", $id ] );
+                       // Messages: apierror-nosuchrcid apierror-nosuchrevid apierror-nosuchlogid
+                       $idResult += $this->getErrorFormatter()->formatMessage( [ "apierror-nosuch$type", $id ] );
                        return $idResult;
                }
 
index 4940394..fc2951a 100644 (file)
 class ApiTokens extends ApiBase {
 
        public function execute() {
-               $this->setWarning(
-                       'action=tokens has been deprecated. Please use action=query&meta=tokens instead.'
+               $this->addDeprecation(
+                       [ 'apiwarn-deprecation-withreplacement', 'action=tokens', 'action=query&meta=tokens' ],
+                       'action=tokens'
                );
-               $this->logFeatureUsage( 'action=tokens' );
 
                $params = $this->extractRequestParams();
                $res = [
@@ -46,7 +46,7 @@ class ApiTokens extends ApiBase {
                        $val = call_user_func( $types[$type], null, null );
 
                        if ( $val === false ) {
-                               $this->setWarning( "Action '$type' is not allowed for the current user" );
+                               $this->addWarning( [ 'apiwarn-tokennotallowed', $type ] );
                        } else {
                                $res[$type . 'token'] = $val;
                        }
index ace41a4..523a888 100644 (file)
@@ -39,25 +39,18 @@ class ApiUnblock extends ApiBase {
                $user = $this->getUser();
                $params = $this->extractRequestParams();
 
-               if ( is_null( $params['id'] ) && is_null( $params['user'] ) ) {
-                       $this->dieUsageMsg( 'unblock-notarget' );
-               }
-               if ( !is_null( $params['id'] ) && !is_null( $params['user'] ) ) {
-                       $this->dieUsageMsg( 'unblock-idanduser' );
-               }
+               $this->requireOnlyOneParameter( $params, 'id', 'user' );
 
                if ( !$user->isAllowed( 'block' ) ) {
-                       $this->dieUsageMsg( 'cantunblock' );
+                       $this->dieWithError( 'apierror-permissiondenied-unblock', 'permissiondenied' );
                }
                # bug 15810: blocked admins should have limited access here
                if ( $user->isBlocked() ) {
                        $status = SpecialBlock::checkUnblockSelf( $params['user'], $user );
                        if ( $status !== true ) {
-                               $msg = $this->parseMsg( $status );
-                               $this->dieUsage(
-                                       $msg['info'],
-                                       $msg['code'],
-                                       0,
+                               $this->dieWithError(
+                                       $status,
+                                       null,
                                        [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
                                );
                        }
@@ -79,7 +72,7 @@ class ApiUnblock extends ApiBase {
                $block = Block::newFromTarget( $data['Target'] );
                $retval = SpecialUnblock::processUnblock( $data, $this->getContext() );
                if ( $retval !== true ) {
-                       $this->dieUsageMsg( $retval[0] );
+                       $this->dieStatus( $this->errorArrayToStatus( $retval ) );
                }
 
                $res['id'] = $block->getId();
index e24f2ce..7fda1ea 100644 (file)
@@ -33,18 +33,16 @@ class ApiUndelete extends ApiBase {
                $this->useTransactionalTimeLimit();
 
                $params = $this->extractRequestParams();
-               $user = $this->getUser();
-               if ( !$user->isAllowed( 'undelete' ) ) {
-                       $this->dieUsageMsg( 'permdenied-undelete' );
-               }
+               $this->checkUserRightsAny( 'undelete' );
 
+               $user = $this->getUser();
                if ( $user->isBlocked() ) {
                        $this->dieBlocked( $user->getBlock() );
                }
 
                $titleObj = Title::newFromText( $params['title'] );
                if ( !$titleObj || $titleObj->isExternal() ) {
-                       $this->dieUsageMsg( [ 'invalidtitle', $params['title'] ] );
+                       $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
                }
 
                // Check if user can add tags
@@ -76,7 +74,7 @@ class ApiUndelete extends ApiBase {
                        $params['tags']
                );
                if ( !is_array( $retval ) ) {
-                       $this->dieUsageMsg( 'cannotundelete' );
+                       $this->dieWithError( 'apierror-cantundelete' );
                }
 
                if ( $retval[1] ) {
index 7b44f40..6bdd68f 100644 (file)
@@ -36,7 +36,7 @@ class ApiUpload extends ApiBase {
        public function execute() {
                // Check whether upload is enabled
                if ( !UploadBase::isEnabled() ) {
-                       $this->dieUsageMsg( 'uploaddisabled' );
+                       $this->dieWithError( 'uploaddisabled' );
                }
 
                $user = $this->getUser();
@@ -61,11 +61,10 @@ class ApiUpload extends ApiBase {
                        if ( !$this->selectUploadModule() ) {
                                return; // not a true upload, but a status request or similar
                        } elseif ( !isset( $this->mUpload ) ) {
-                               $this->dieUsage( 'No upload module set', 'nomodule' );
+                               $this->dieDebug( __METHOD__, 'No upload module set' );
                        }
                } catch ( UploadStashException $e ) { // XXX: don't spam exception log
-                       list( $msg, $code ) = $this->handleStashException( get_class( $e ), $e->getMessage() );
-                       $this->dieUsage( $msg, $code );
+                       $this->dieStatus( $this->handleStashException( $e ) );
                }
 
                // First check permission to upload
@@ -75,19 +74,17 @@ class ApiUpload extends ApiBase {
                /** @var $status Status */
                $status = $this->mUpload->fetchFile();
                if ( !$status->isGood() ) {
-                       $errors = $status->getErrorsArray();
-                       $error = array_shift( $errors[0] );
-                       $this->dieUsage( 'Error fetching file from remote source', $error, 0, $errors[0] );
+                       $this->dieStatus( $status );
                }
 
                // Check if the uploaded file is sane
                if ( $this->mParams['chunk'] ) {
                        $maxSize = UploadBase::getMaxUploadSize();
                        if ( $this->mParams['filesize'] > $maxSize ) {
-                               $this->dieUsage( 'The file you submitted was too large', 'file-too-large' );
+                               $this->dieWithError( 'file-too-large' );
                        }
                        if ( !$this->mUpload->getTitle() ) {
-                               $this->dieUsage( 'Invalid file title supplied', 'internal-error' );
+                               $this->dieWithError( 'illegal-filename' );
                        }
                } elseif ( $this->mParams['async'] && $this->mParams['filekey'] ) {
                        // defer verification to background process
@@ -102,7 +99,7 @@ class ApiUpload extends ApiBase {
                if ( !$this->mParams['stash'] ) {
                        $permErrors = $this->mUpload->verifyTitlePermissions( $user );
                        if ( $permErrors !== true ) {
-                               $this->dieRecoverableError( $permErrors[0], 'filename' );
+                               $this->dieRecoverableError( $permErrors, 'filename' );
                        }
                }
 
@@ -110,8 +107,7 @@ class ApiUpload extends ApiBase {
                try {
                        $result = $this->getContextResult();
                } catch ( UploadStashException $e ) { // XXX: don't spam exception log
-                       list( $msg, $code ) = $this->handleStashException( get_class( $e ), $e->getMessage() );
-                       $this->dieUsage( $msg, $code );
+                       $this->dieStatus( $this->handleStashException( $e ) );
                }
                $this->getResult()->addValue( null, $this->getModuleName(), $result );
 
@@ -146,7 +142,7 @@ class ApiUpload extends ApiBase {
                // Check throttle after we've handled warnings
                if ( UploadBase::isThrottled( $this->getUser() )
                ) {
-                       $this->dieUsageMsg( 'actionthrottledtext' );
+                       $this->dieWithError( 'apierror-ratelimited' );
                }
 
                // This is the most common case -- a normal upload with no warnings
@@ -208,16 +204,12 @@ class ApiUpload extends ApiBase {
 
                // Sanity check sizing
                if ( $totalSoFar > $this->mParams['filesize'] ) {
-                       $this->dieUsage(
-                               'Offset plus current chunk is greater than claimed file size', 'invalid-chunk'
-                       );
+                       $this->dieWithError( 'apierror-invalid-chunk' );
                }
 
                // Enforce minimum chunk size
                if ( $totalSoFar != $this->mParams['filesize'] && $chunkSize < $minChunkSize ) {
-                       $this->dieUsage(
-                               "Minimum chunk size is $minChunkSize bytes for non-final chunks", 'chunk-too-small'
-                       );
+                       $this->dieWithError( [ 'apierror-chunk-too-small', Message::numParam( $minChunkSize ) ] );
                }
 
                if ( $this->mParams['offset'] == 0 ) {
@@ -229,11 +221,9 @@ class ApiUpload extends ApiBase {
                        $progress = UploadBase::getSessionStatus( $this->getUser(), $filekey );
                        if ( !$progress ) {
                                // Probably can't get here, but check anyway just in case
-                               $this->dieUsage( 'No chunked upload session with this key', 'stashfailed' );
+                               $this->dieWithError( 'apierror-stashfailed-nosession', 'stashfailed' );
                        } elseif ( $progress['result'] !== 'Continue' || $progress['stage'] !== 'uploading' ) {
-                               $this->dieUsage(
-                                       'Chunked upload is already completed, check status for details', 'stashfailed'
-                               );
+                               $this->dieWithError( 'apierror-stashfailed-complete', 'stashfailed' );
                        }
 
                        $status = $this->mUpload->addChunk(
@@ -352,16 +342,13 @@ class ApiUpload extends ApiBase {
                        list( $exceptionType, $message ) = $status->getMessage()->getParams();
                        $debugMessage = 'Stashing temporary file failed: ' . $exceptionType . ' ' . $message;
                        wfDebug( __METHOD__ . ' ' . $debugMessage . "\n" );
-                       list( $msg, $code ) = $this->handleStashException( $exceptionType, $message );
-                       $status = Status::newFatal( new ApiRawMessage( $msg, $code ) );
                }
 
                // Bad status
                if ( $failureMode !== 'optional' ) {
                        $this->dieStatus( $status );
                } else {
-                       list( $code, $msg ) = $this->getErrorFromStatus( $status );
-                       $data['stashfailed'] = $msg;
+                       $data['stasherrors'] = $this->getErrorFormatter()->arrayFromStatus( $status );
                        return null;
                }
        }
@@ -370,25 +357,25 @@ class ApiUpload extends ApiBase {
         * Throw an error that the user can recover from by providing a better
         * value for $parameter
         *
-        * @param array|string|MessageSpecifier $error Error suitable for passing to dieUsageMsg()
-        * @param string $parameter Parameter that needs revising
-        * @param array $data Optional extra data to pass to the user
-        * @param string $code Error code to use if the error is unknown
-        * @throws UsageException
+        * @param array $errors Array of Message objects, message keys, key+param
+        *  arrays, or StatusValue::getErrors()-style arrays
+        * @param string|null $parameter Parameter that needs revising
+        * @throws ApiUsageException
         */
-       private function dieRecoverableError( $error, $parameter, $data = [], $code = 'unknownerror' ) {
+       private function dieRecoverableError( $errors, $parameter = null ) {
                $this->performStash( 'optional', $data );
-               $data['invalidparameter'] = $parameter;
 
-               $parsed = $this->parseMsg( $error );
-               if ( isset( $parsed['data'] ) ) {
-                       $data = array_merge( $data, $parsed['data'] );
-               }
-               if ( $parsed['code'] === 'unknownerror' ) {
-                       $parsed['code'] = $code;
+               if ( $parameter ) {
+                       $data['invalidparameter'] = $parameter;
                }
 
-               $this->dieUsage( $parsed['info'], $parsed['code'], 0, $data );
+               $sv = StatusValue::newGood();
+               foreach ( $errors as $error ) {
+                       $msg = ApiMessage::create( $error );
+                       $msg->setApiData( $msg->getApiData() + $data );
+                       $sv->fatal( $msg );
+               }
+               $this->dieStatus( $sv );
        }
 
        /**
@@ -398,20 +385,18 @@ class ApiUpload extends ApiBase {
         * @param Status $status
         * @param string $overrideCode Error code to use if there isn't one from IApiMessage
         * @param array|null $moreExtraData
-        * @throws UsageException
+        * @throws ApiUsageException
         */
        public function dieStatusWithCode( $status, $overrideCode, $moreExtraData = null ) {
-               $extraData = null;
-               list( $code, $msg ) = $this->getErrorFromStatus( $status, $extraData );
-               $errors = $status->getErrorsByType( 'error' ) ?: $status->getErrorsByType( 'warning' );
-               if ( !( $errors[0]['message'] instanceof IApiMessage ) ) {
-                       $code = $overrideCode;
-               }
-               if ( $moreExtraData ) {
-                       $extraData = $extraData ?: [];
-                       $extraData += $moreExtraData;
+               $sv = StatusValue::newGood();
+               foreach ( $status->getErrors() as $error ) {
+                       $msg = ApiMessage::create( $error, $overrideCode );
+                       if ( $moreExtraData ) {
+                               $msg->setApiData( $msg->getApiData() + $moreExtraData );
+                       }
+                       $sv->fatal( $msg );
                }
-               $this->dieUsage( $msg, $code, 0, $extraData );
+               $this->dieStatus( $sv );
        }
 
        /**
@@ -434,7 +419,7 @@ class ApiUpload extends ApiBase {
                if ( $this->mParams['filekey'] && $this->mParams['checkstatus'] ) {
                        $progress = UploadBase::getSessionStatus( $this->getUser(), $this->mParams['filekey'] );
                        if ( !$progress ) {
-                               $this->dieUsage( 'No result in status data', 'missingresult' );
+                               $this->dieWithError( 'api-upload-missingresult', 'missingresult' );
                        } elseif ( !$progress['status']->isGood() ) {
                                $this->dieStatusWithCode( $progress['status'], 'stashfailed' );
                        }
@@ -466,7 +451,7 @@ class ApiUpload extends ApiBase {
 
                // The following modules all require the filename parameter to be set
                if ( is_null( $this->mParams['filename'] ) ) {
-                       $this->dieUsageMsg( [ 'missingparam', 'filename' ] );
+                       $this->dieWithError( [ 'apierror-missingparam', 'filename' ] );
                }
 
                if ( $this->mParams['chunk'] ) {
@@ -474,7 +459,7 @@ class ApiUpload extends ApiBase {
                        $this->mUpload = new UploadFromChunks( $this->getUser() );
                        if ( isset( $this->mParams['filekey'] ) ) {
                                if ( $this->mParams['offset'] === 0 ) {
-                                       $this->dieUsage( 'Cannot supply a filekey when offset is 0', 'badparams' );
+                                       $this->dieWithError( 'apierror-upload-filekeynotallowed', 'filekeynotallowed' );
                                }
 
                                // handle new chunk
@@ -485,7 +470,7 @@ class ApiUpload extends ApiBase {
                                );
                        } else {
                                if ( $this->mParams['offset'] !== 0 ) {
-                                       $this->dieUsage( 'Must supply a filekey when offset is non-zero', 'badparams' );
+                                       $this->dieWithError( 'apierror-upload-filekeyneeded', 'filekeyneeded' );
                                }
 
                                // handle first chunk
@@ -497,7 +482,7 @@ class ApiUpload extends ApiBase {
                } elseif ( isset( $this->mParams['filekey'] ) ) {
                        // Upload stashed in a previous request
                        if ( !UploadFromStash::isValidKey( $this->mParams['filekey'] ) ) {
-                               $this->dieUsageMsg( 'invalid-file-key' );
+                               $this->dieWithError( 'apierror-invalid-file-key' );
                        }
 
                        $this->mUpload = new UploadFromStash( $this->getUser() );
@@ -515,15 +500,15 @@ class ApiUpload extends ApiBase {
                } elseif ( isset( $this->mParams['url'] ) ) {
                        // Make sure upload by URL is enabled:
                        if ( !UploadFromUrl::isEnabled() ) {
-                               $this->dieUsageMsg( 'copyuploaddisabled' );
+                               $this->dieWithError( 'copyuploaddisabled' );
                        }
 
                        if ( !UploadFromUrl::isAllowedHost( $this->mParams['url'] ) ) {
-                               $this->dieUsageMsg( 'copyuploadbaddomain' );
+                               $this->dieWithError( 'apierror-copyuploadbaddomain' );
                        }
 
                        if ( !UploadFromUrl::isAllowedUrl( $this->mParams['url'] ) ) {
-                               $this->dieUsageMsg( 'copyuploadbadurl' );
+                               $this->dieWithError( 'apierror-copyuploadbadurl' );
                        }
 
                        $this->mUpload = new UploadFromUrl;
@@ -545,10 +530,10 @@ class ApiUpload extends ApiBase {
 
                if ( $permission !== true ) {
                        if ( !$user->isLoggedIn() ) {
-                               $this->dieUsageMsg( [ 'mustbeloggedin', 'upload' ] );
+                               $this->dieWithError( [ 'apierror-mustbeloggedin', $this->msg( 'action-upload' ) ] );
                        }
 
-                       $this->dieUsageMsg( 'badaccess-groups' );
+                       $this->dieStatus( User::newFatalPermissionDeniedStatus( $permission ) );
                }
 
                // Check blocks
@@ -583,28 +568,31 @@ class ApiUpload extends ApiBase {
                switch ( $verification['status'] ) {
                        // Recoverable errors
                        case UploadBase::MIN_LENGTH_PARTNAME:
-                               $this->dieRecoverableError( 'filename-tooshort', 'filename' );
+                               $this->dieRecoverableError( [ 'filename-tooshort' ], 'filename' );
                                break;
                        case UploadBase::ILLEGAL_FILENAME:
-                               $this->dieRecoverableError( 'illegal-filename', 'filename',
-                                       [ 'filename' => $verification['filtered'] ] );
+                               $this->dieRecoverableError(
+                                       [ ApiMessage::create(
+                                               'illegal-filename', null, [ 'filename' => $verification['filtered'] ]
+                                       ) ], 'filename'
+                               );
                                break;
                        case UploadBase::FILENAME_TOO_LONG:
-                               $this->dieRecoverableError( 'filename-toolong', 'filename' );
+                               $this->dieRecoverableError( [ 'filename-toolong' ], 'filename' );
                                break;
                        case UploadBase::FILETYPE_MISSING:
-                               $this->dieRecoverableError( 'filetype-missing', 'filename' );
+                               $this->dieRecoverableError( [ 'filetype-missing' ], 'filename' );
                                break;
                        case UploadBase::WINDOWS_NONASCII_FILENAME:
-                               $this->dieRecoverableError( 'windows-nonascii-filename', 'filename' );
+                               $this->dieRecoverableError( [ 'windows-nonascii-filename' ], 'filename' );
                                break;
 
                        // Unrecoverable errors
                        case UploadBase::EMPTY_FILE:
-                               $this->dieUsage( 'The file you submitted was empty', 'empty-file' );
+                               $this->dieWithError( 'empty-file' );
                                break;
                        case UploadBase::FILE_TOO_LARGE:
-                               $this->dieUsage( 'The file you submitted was too large', 'file-too-large' );
+                               $this->dieWithError( 'file-too-large' );
                                break;
 
                        case UploadBase::FILETYPE_BADTYPE:
@@ -612,57 +600,47 @@ class ApiUpload extends ApiBase {
                                        'filetype' => $verification['finalExt'],
                                        'allowed' => array_values( array_unique( $this->getConfig()->get( 'FileExtensions' ) ) )
                                ];
+                               $extensions = array_unique( $this->getConfig()->get( 'FileExtensions' ) );
+                               $msg = [
+                                       'filetype-banned-type',
+                                       null, // filled in below
+                                       Message::listParam( $extensions, 'comma' ),
+                                       count( $extensions ),
+                                       null, // filled in below
+                               ];
                                ApiResult::setIndexedTagName( $extradata['allowed'], 'ext' );
 
-                               $msg = 'Filetype not permitted: ';
                                if ( isset( $verification['blacklistedExt'] ) ) {
-                                       $msg .= implode( ', ', $verification['blacklistedExt'] );
+                                       $msg[1] = Message::listParam( $verification['blacklistedExt'], 'comma' );
+                                       $msg[4] = count( $verification['blacklistedExt'] );
                                        $extradata['blacklisted'] = array_values( $verification['blacklistedExt'] );
                                        ApiResult::setIndexedTagName( $extradata['blacklisted'], 'ext' );
                                } else {
-                                       $msg .= $verification['finalExt'];
+                                       $msg[1] = $verification['finalExt'];
+                                       $msg[4] = 1;
                                }
-                               $this->dieUsage( $msg, 'filetype-banned', 0, $extradata );
+
+                               $this->dieWithError( $msg, 'filetype-banned', $extradata );
                                break;
+
                        case UploadBase::VERIFICATION_ERROR:
-                               $parsed = $this->parseMsg( $verification['details'] );
-                               $info = "This file did not pass file verification: {$parsed['info']}";
-                               if ( $verification['details'][0] instanceof IApiMessage ) {
-                                       $code = $parsed['code'];
-                               } else {
-                                       // For backwards-compatibility, all of the errors from UploadBase::verifyFile() are
-                                       // reported as 'verification-error', and the real error code is reported in 'details'.
-                                       $code = 'verification-error';
-                               }
-                               if ( $verification['details'][0] instanceof IApiMessage ) {
-                                       $msg = $verification['details'][0];
+                               $msg = ApiMessage::create( $verification['details'], 'verification-error' );
+                               if ( $verification['details'][0] instanceof MessageSpecifier ) {
                                        $details = array_merge( [ $msg->getKey() ], $msg->getParams() );
                                } else {
                                        $details = $verification['details'];
                                }
                                ApiResult::setIndexedTagName( $details, 'detail' );
-                               $data = [ 'details' => $details ];
-                               if ( isset( $parsed['data'] ) ) {
-                                       $data = array_merge( $data, $parsed['data'] );
-                               }
-
-                               $this->dieUsage( $info, $code, 0, $data );
+                               $msg->setApiData( $msg->getApiData() + [ 'details' => $details ] );
+                               $this->dieWithError( $msg );
                                break;
+
                        case UploadBase::HOOK_ABORTED:
-                               if ( is_array( $verification['error'] ) ) {
-                                       $params = $verification['error'];
-                               } elseif ( $verification['error'] !== '' ) {
-                                       $params = [ $verification['error'] ];
-                               } else {
-                                       $params = [ 'hookaborted' ];
-                               }
-                               $key = array_shift( $params );
-                               $msg = $this->msg( $key, $params )->inLanguage( 'en' )->useDatabase( false )->text();
-                               $this->dieUsage( $msg, 'hookaborted', 0, [ 'details' => $verification['error'] ] );
+                               $this->dieWithError( $params, 'hookaborted', [ 'details' => $verification['error'] ] );
                                break;
                        default:
-                               $this->dieUsage( 'An unknown error occurred', 'unknown-error',
-                                       0, [ 'details' => [ 'code' => $verification['status'] ] ] );
+                               $this->dieWithError( 'apierror-unknownerror-nocode', 'unknown-error',
+                                       [ 'details' => [ 'code' => $verification['status'] ] ] );
                                break;
                }
        }
@@ -735,41 +713,31 @@ class ApiUpload extends ApiBase {
 
        /**
         * Handles a stash exception, giving a useful error to the user.
-        * @param string $exceptionType Class name of the exception we encountered.
-        * @param string $message Message of the exception we encountered.
-        * @return array Array of message and code, suitable for passing to dieUsage()
+        * @todo Internationalize the exceptions
+        * @param Exception $e
+        * @return StatusValue
         */
-       protected function handleStashException( $exceptionType, $message ) {
-               switch ( $exceptionType ) {
+       protected function handleStashException( $e ) {
+               $err = wfEscapeWikiText( $e->getMessage() );
+               switch ( get_class( $exception ) ) {
                        case 'UploadStashFileNotFoundException':
-                               return [
-                                       'Could not find the file in the stash: ' . $message,
-                                       'stashedfilenotfound'
-                               ];
+                               return StatusValue::newFatal( 'apierror-stashedfilenotfound', $err );
                        case 'UploadStashBadPathException':
-                               return [
-                                       'File key of improper format or otherwise invalid: ' . $message,
-                                       'stashpathinvalid'
-                               ];
+                               return StatusValue::newFatal( 'apierror-stashpathinvalid', $err );
                        case 'UploadStashFileException':
-                               return [
-                                       'Could not store upload in the stash: ' . $message,
-                                       'stashfilestorage'
-                               ];
+                               return StatusValue::newFatal( 'apierror-stashfilestorage', $err );
                        case 'UploadStashZeroLengthFileException':
-                               return [
-                                       'File is of zero length, and could not be stored in the stash: ' .
-                                               $message,
-                                       'stashzerolength'
-                               ];
+                               return StatusValue::newFatal( 'apierror-stashzerolength', $err );
                        case 'UploadStashNotLoggedInException':
-                               return [ 'Not logged in: ' . $message, 'stashnotloggedin' ];
+                               return StatusValue::newFatal( ApiMessage::create(
+                                       [ 'apierror-mustbeloggedin', $this->msg( 'action-upload' ) ], 'stashnotloggedin'
+                               ) );
                        case 'UploadStashWrongOwnerException':
-                               return [ 'Wrong owner: ' . $message, 'stashwrongowner' ];
+                               return StatusValue::newFatal( 'apierror-stashwrongowner', $err );
                        case 'UploadStashNoSuchKeyException':
-                               return [ 'No such filekey: ' . $message, 'stashnosuchfilekey' ];
+                               return StatusValue::newFatal( 'apierror-stashnosuchfilekey', $err );
                        default:
-                               return [ $exceptionType . ': ' . $message, 'stasherror' ];
+                               return StatusValue::newFatal( 'uploadstash-exception', get_class( $e ), $err );
                }
        }
 
@@ -821,7 +789,7 @@ class ApiUpload extends ApiBase {
                if ( $this->mParams['async'] ) {
                        $progress = UploadBase::getSessionStatus( $this->getUser(), $this->mParams['filekey'] );
                        if ( $progress && $progress['result'] === 'Poll' ) {
-                               $this->dieUsage( 'Upload from stash already in progress.', 'publishfailed' );
+                               $this->dieWithError( 'apierror-upload-inprogress', 'publishfailed' );
                        }
                        UploadBase::setSessionStatus(
                                $this->getUser(),
@@ -848,14 +816,7 @@ class ApiUpload extends ApiBase {
                                $this->mParams['text'], $watch, $this->getUser(), $this->mParams['tags'] );
 
                        if ( !$status->isGood() ) {
-                               // Is there really no better way to do this?
-                               $errors = $status->getErrorsByType( 'error' );
-                               $msg = array_merge( [ $errors[0]['message'] ], $errors[0]['params'] );
-                               $data = $status->getErrorsArray();
-                               ApiResult::setIndexedTagName( $data, 'error' );
-                               // For backwards-compatibility, we use the 'internal-error' fallback key and merge $data
-                               // into the root of the response (rather than something sane like [ 'details' => $data ]).
-                               $this->dieRecoverableError( $msg, null, $data, 'internal-error' );
+                               $this->dieRecoverableError( $status->getErrors() );
                        }
                        $result['result'] = 'Success';
                }
diff --git a/includes/api/ApiUsageException.php b/includes/api/ApiUsageException.php
new file mode 100644 (file)
index 0000000..7e21ab5
--- /dev/null
@@ -0,0 +1,217 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @defgroup API API
+ */
+
+/**
+ * This exception will be thrown when dieUsage is called to stop module execution.
+ *
+ * @ingroup API
+ * @deprecated since 1.29, use ApiUsageException instead
+ */
+class UsageException extends MWException {
+
+       private $mCodestr;
+
+       /**
+        * @var null|array
+        */
+       private $mExtraData;
+
+       /**
+        * @param string $message
+        * @param string $codestr
+        * @param int $code
+        * @param array|null $extradata
+        */
+       public function __construct( $message, $codestr, $code = 0, $extradata = null ) {
+               parent::__construct( $message, $code );
+               $this->mCodestr = $codestr;
+               $this->mExtraData = $extradata;
+
+               // This should never happen, so throw an exception about it that will
+               // hopefully get logged with a backtrace (T138585)
+               if ( !is_string( $codestr ) || $codestr === '' ) {
+                       throw new InvalidArgumentException( 'Invalid $codestr, was ' .
+                               ( $codestr === '' ? 'empty string' : gettype( $codestr ) )
+                       );
+               }
+       }
+
+       /**
+        * @return string
+        */
+       public function getCodeString() {
+               return $this->mCodestr;
+       }
+
+       /**
+        * @return array
+        */
+       public function getMessageArray() {
+               $result = [
+                       'code' => $this->mCodestr,
+                       'info' => $this->getMessage()
+               ];
+               if ( is_array( $this->mExtraData ) ) {
+                       $result = array_merge( $result, $this->mExtraData );
+               }
+
+               return $result;
+       }
+
+       /**
+        * @return string
+        */
+       public function __toString() {
+               return "{$this->getCodeString()}: {$this->getMessage()}";
+       }
+}
+
+/**
+ * Exception used to abort API execution with an error
+ *
+ * If possible, use ApiBase::dieWithError() instead of throwing this directly.
+ *
+ * @ingroup API
+ * @note This currently extends UsageException for backwards compatibility, so
+ *  all the existing code that catches UsageException won't break when stuff
+ *  starts throwing ApiUsageException. Eventually UsageException will go away
+ *  and this will (probably) extend MWException directly.
+ */
+class ApiUsageException extends UsageException {
+
+       protected $modulePath;
+       protected $status;
+
+       /**
+        * @param ApiBase|null $module API module responsible for the error, if known
+        * @param StatusValue $status Status holding errors
+        * @param int $httpCode HTTP error code to use
+        */
+       public function __construct(
+               ApiBase $module = null, StatusValue $status, $httpCode = 0
+       ) {
+               if ( $status->isOK() ) {
+                       throw new InvalidArgumentException( __METHOD__ . ' requires a fatal Status' );
+               }
+
+               $this->modulePath = $module ? $module->getModulePath() : null;
+               $this->status = $status;
+
+               // Bug T46111: Messages in the log files should be in English and not
+               // customized by the local wiki.
+               $enMsg = clone $this->getApiMessage();
+               $enMsg->inLanguage( 'en' )->useDatabase( false );
+               parent::__construct(
+                       ApiErrorFormatter::stripMarkup( $enMsg->text() ),
+                       $enMsg->getApiCode(),
+                       $httpCode,
+                       $enMsg->getApiData()
+               );
+       }
+
+       /**
+        * @param ApiBase|null $module API module responsible for the error, if known
+        * @param string|array|Message $msg See ApiMessage::create()
+        * @param string|null $code See ApiMessage::create()
+        * @param array|null $data See ApiMessage::create()
+        * @param int $httpCode HTTP error code to use
+        * @return static
+        */
+       public static function newWithMessage(
+               ApiBase $module = null, $msg, $code = null, $data = null, $httpCode = 0
+       ) {
+               return new static(
+                       $module,
+                       StatusValue::newFatal( ApiMessage::create( $msg, $code, $data ) ),
+                       $httpCode
+               );
+       }
+
+       /**
+        * @returns ApiMessage
+        */
+       private function getApiMessage() {
+               $errors = $this->status->getErrorsByType( 'error' );
+               if ( !$errors ) {
+                       $errors = $this->status->getErrors();
+               }
+               if ( !$errors ) {
+                       $msg = new ApiMessage( 'apierror-unknownerror-nocode', 'unknownerror' );
+               } else {
+                       $msg = ApiMessage::create( $errors[0] );
+               }
+               return $msg;
+       }
+
+       /**
+        * Fetch the responsible module name
+        * @return string|null
+        */
+       public function getModulePath() {
+               return $this->modulePath;
+       }
+
+       /**
+        * Fetch the error status
+        * @return StatusValue
+        */
+       public function getStatusValue() {
+               return $this->status;
+       }
+
+       /**
+        * @deprecated Do not use. This only exists here because UsageException is in
+        *  the inheritance chain for backwards compatibility.
+        * @inheritdoc
+        */
+       public function getCodeString() {
+               return $this->getApiMessage()->getApiCode();
+       }
+
+       /**
+        * @deprecated Do not use. This only exists here because UsageException is in
+        *  the inheritance chain for backwards compatibility.
+        * @inheritdoc
+        */
+       public function getMessageArray() {
+               $enMsg = clone $this->getApiMessage();
+               $enMsg->inLanguage( 'en' )->useDatabase( false );
+
+               return [
+                       'code' => $enMsg->getApiCode(),
+                       'info' => ApiErrorFormatter::stripMarkup( $enMsg->text() ),
+               ] + $enMsg->getApiData();
+       }
+
+       /**
+        * @return string
+        */
+       public function __toString() {
+               $enMsg = clone $this->getApiMessage();
+               $enMsg->inLanguage( 'en' )->useDatabase( false );
+               $text = ApiErrorFormatter::stripMarkup( $enMsg->text() );
+
+               return get_class( $this ) . ": {$enMsg->getApiCode()}: {$text} "
+                       . "in {$this->getFile()}:{$this->getLine()}\n"
+                       . "Stack trace:\n{$this->getTraceAsString()}";
+       }
+
+}
index 3a7a082..d257e90 100644 (file)
@@ -35,12 +35,10 @@ class ApiWatch extends ApiBase {
        public function execute() {
                $user = $this->getUser();
                if ( !$user->isLoggedIn() ) {
-                       $this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' );
+                       $this->dieWithError( 'watchlistanontext', 'notloggedin' );
                }
 
-               if ( !$user->isAllowed( 'editmywatchlist' ) ) {
-                       $this->dieUsage( 'You don\'t have permission to edit your watchlist', 'permissiondenied' );
-               }
+               $this->checkUserRightsAny( 'editmywatchlist' );
 
                $params = $this->extractRequestParams();
 
@@ -78,16 +76,19 @@ class ApiWatch extends ApiBase {
                        } ) );
 
                        if ( $extraParams ) {
-                               $p = $this->getModulePrefix();
-                               $this->dieUsage(
-                                       "The parameter {$p}title can not be used with " . implode( ', ', $extraParams ),
+                               $this->dieWithError(
+                                       [
+                                               'apierror-invalidparammix-cannotusewith',
+                                               $this->encodeParamName( 'title' ),
+                                               $pageSet->encodeParamName( $extraParams[0] )
+                                       ],
                                        'invalidparammix'
                                );
                        }
 
                        $title = Title::newFromText( $params['title'] );
                        if ( !$title || !$title->isWatchable() ) {
-                               $this->dieUsageMsg( [ 'invalidtitle', $params['title'] ] );
+                               $this->dieWithError( [ 'invalidtitle', $params['title'] ] );
                        }
                        $res = $this->watchTitle( $title, $user, $params, true );
                }
@@ -128,7 +129,11 @@ class ApiWatch extends ApiBase {
                        if ( $compatibilityMode ) {
                                $this->dieStatus( $status );
                        }
-                       $res['error'] = $this->getErrorFromStatus( $status );
+                       $res['errors'] = $this->getErrorFormatter()->arrayFromStatus( $status, 'error' );
+                       $res['warnings'] = $this->getErrorFormatter()->arrayFromStatus( $status, 'warning' );
+                       if ( !$res['warnings'] ) {
+                               unset( $res['warnings'] );
+                       }
                }
 
                return $res;
index 5072c66..03c9f52 100644 (file)
@@ -71,5 +71,6 @@
        "apihelp-query+allrevisions-description": "اعرض كل المراجعات.",
        "apihelp-query+blocks-example-simple": "قائمة المنع.",
        "apihelp-query+imageinfo-paramvalue-prop-userid": "إضافة هوية المستخدم الذي قام بتحميل كل إصدار ملف.",
-       "apihelp-query+prefixsearch-param-offset": "عدد النتائج المراد تخطيها."
+       "apihelp-query+prefixsearch-param-offset": "عدد النتائج المراد تخطيها.",
+       "api-feed-error-title": "خطأ ($1)"
 }
index d28165d..fccdc0f 100644 (file)
@@ -8,6 +8,11 @@
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentación]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Llista d'alderique]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anuncios de la API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Fallos y solicitúes]\n</div>\n<strong>Estau:</strong> Toles carauterístiques qu'apaecen nesta páxina tendríen de funcionar, pero la API inda ta en desendolcu activu, y puede camudar en cualquier momentu. Suscríbete a la [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ llista de corréu mediawiki-api-announce] p'avisos sobro anovamientos.\n\n<strong>Solicitúes incorreutes:</strong> Cuando s'unvíen solicitúes incorreutes a la API, unvíase una cabecera HTTP cola clave \"MediaWiki-API-Error\" y, darréu, tanto'l valor de la cabecera como'l códigu d'error devueltu pondránse al mesmu valor. Pa más información, consulta [[mw:API:Errors_and_warnings|API: Errores y avisos]].\n\n<strong>Pruebes:</strong> Pa facilitar les pruebes de solicitúes API, consulta [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Qué aición facer.",
        "apihelp-main-param-format": "El formatu de la salida.",
+       "apihelp-main-param-maxlag": "El retrasu (lag) máximu puede utilizase cuando MediaWiki ta instaláu nun conxuntu de bases de datos replicaes. Pa evitar les aiciones que pudieran causar un retrasu entá mayor na replicación del sitiu, esti parámetru puede causar que'l cliente espere hasta que'l retrasu de replicación sía menor que'l valor especificáu. En casu de retrasu escesivu, devuélvese un códigu d'error <samp>maxlag</samp> con un mensaxe asemeyáu a <samp>Esperando a $host: $lag segundos de retrasu<s/amp>.<br />Ver [[mw:Manual:Maxlag_parameter|Manual:Parámetru maxlag]] pa más información.",
+       "apihelp-main-param-smaxage": "Establez l'encabezáu HTTP <code>s-maxage</code> de control de caché a esta cantidá de segundos. Los errores nunca se guarden na caché.",
+       "apihelp-main-param-maxage": "Establez l'encabezáu HTTP <code>max-age</code> de control de caché a esta cantidá de segundos. Los errores nunca se guarden na caché.",
+       "apihelp-main-param-assert": "Comprobar que l'usuariu tien sesión aniciada si'l valor ye <kbd>user</kbd> o que tien el permisu de bot si ye <kbd>bot</kbd>.",
+       "apihelp-main-param-assertuser": "Comprobar que'l usuariu actual ye l'usuariu nomáu.",
        "apihelp-main-param-servedby": "Incluyir el nome del host que sirvió la solicitú nes resultancies.",
        "apihelp-main-param-curtimestamp": "Incluyir la marca de tiempu actual na resultancia.",
        "apihelp-block-description": "Bloquiar a un usuariu.",
index 4fe6a04..6f8f596 100644 (file)
@@ -4,5 +4,8 @@
                        "Ibrahim khashrowdi"
                ]
        },
-       "apihelp-block-description": "کار زوروکئ بستین"
+       "apihelp-block-description": "کار زوروکئ بستین",
+       "apihelp-createaccount-param-name": "کار زورؤکین نام.",
+       "apihelp-login-param-name": "کار زورؤکین نام.",
+       "apihelp-userrights-param-user": "کار زورؤکین نام."
 }
index db799e2..00aa00d 100644 (file)
        "apihelp-main-param-smaxage": "Den <code>s-maxage</code>-HTTP-Cache-Control-Header auf diese Anzahl Sekunden festlegen. Fehler werden niemals gepuffert.",
        "apihelp-main-param-maxage": "Den <code>max-age</code>-HTTP-Cache-Control-Header auf diese Anzahl Sekunden festlegen. Fehler werden niemals gecacht.",
        "apihelp-main-param-assert": "Sicherstellen, dass der Benutzer eingeloggt ist, wenn auf <kbd>user</kbd> gesetzt, oder Bot ist, wenn auf <kbd>bot</kbd> gesetzt.",
+       "apihelp-main-param-assertuser": "Überprüft, ob der aktuelle Benutzer der benannte Benutzer ist.",
        "apihelp-main-param-requestid": "Der angegebene Wert wird mit in die Antwort aufgenommen und kann zur Unterscheidung von Anfragen verwendet werden.",
        "apihelp-main-param-servedby": "Namen des bearbeitenden Hosts mit zurückgeben.",
        "apihelp-main-param-curtimestamp": "Aktuellen Zeitstempel mit zurückgeben.",
+       "apihelp-main-param-responselanginfo": "Bezieht die für <var>uselang</var> und <var>errorlang</var> verwendeten Sprachen im Ergebnis mit ein.",
        "apihelp-main-param-origin": "Beim Zugriff auf die API mit einer Kreuz-Domain-AJAX-Anfrage (CORS) muss dies als entstehende Domäne festgelegt werden. Dies muss in jeder Vorfluganfrage mit eingeschlossen werden und deshalb ein Teil der Anfragen-URI sein (nicht des POST-Körpers).\n\nFür authentifizierte Anfragen muss dies exakt einem der Ursprünge im Header <code>Origin</code> entsprechen, so dass es auf etwas wie <kbd>https://de.wikipedia.org</kbd> oder <kbd>https://meta.wikimedia.org</kbd> festgelegt werden muss. Falls dieser Parameter nicht mit dem Header <code>Origin</code> übereinstimmt, wird eine 403-Antwort zurückgegeben. Falls dieser Parameter mit dem Header <code>Origin</code> übereinstimmt und der Ursprung weißgelistet ist, werden die Header <code>Access-Control-Allow-Origin</code> und <code>Access-Control-Allow-Credentials</code> festgelegt.\n\nGib für nicht authentifizierte Anfragen den Wert <kbd>*</kbd> an. Dies verursacht, dass der Header <code>Access-Control-Allow-Origin</code> festgelegt wird, aber <code>Access-Control-Allow-Credentials</code> wird <code>false</code> sein und alle benutzerspezifischen Daten werden beschränkt.",
        "apihelp-main-param-uselang": "Zu verwendende Sprache für Nachrichtenübersetzungen. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> mit <kbd>siprop=languages</kbd> gibt eine Liste der Sprachcodes zurück. Gib <kbd>user</kbd> zum Verwenden der aktuellen Benutzerspracheinstellung oder <kbd>content</kbd> an, um die Inhaltssprache des Wikis zu verwenden.",
+       "apihelp-main-param-errorsuselocal": "Falls angegeben, verwenden Fehlertexte lokalisierte Nachrichten aus dem {{ns:MediaWiki}}-Namensraum.",
        "apihelp-block-description": "Einen Benutzer sperren.",
        "apihelp-block-param-user": "Benutzername, IP-Adresse oder IP-Bereich, der gesperrt werden soll.",
        "apihelp-block-param-expiry": "Sperrdauer. Kann relativ (z.&nbsp;B. <kbd>5 months</kbd> oder <kbd>2 weeks</kbd>) oder absolut (z.&nbsp;B. <kbd>2014-09-18T12:34:56Z</kbd>) sein. Wenn auf <kbd>infinite</kbd>, <kbd>indefinite</kbd> oder <kbd>never</kbd> gesetzt, ist die Sperre unbegrenzt.",
        "apihelp-query+allmessages-param-prop": "Zurückzugebende Eigenschaften.",
        "apihelp-query+allmessages-param-enableparser": "Setzen, um den Parser zu aktivieren. Dies wird den Wikitext der Nachricht vorverarbeiten (magische Worte ersetzen, Vorlagen berücksichtigen, usw.).",
        "apihelp-query+allmessages-param-nocontent": "Wenn gesetzt, füge nicht den Inhalt der Nachricht der Ausgabe hinzu.",
-       "apihelp-query+allmessages-param-includelocal": "Schließt auch lokale Nachrichten ein. Zum Beispiel Nachrichten die es nicht in der Software gibt, die es aber als MediaWiki: - Seite gibt. Dies listet alle MediaWiki: - Seiten auf. Daher werden auch diejenigen aufgelistet, die eigentlich keine Nachrichten sind, wie [[MediaWiki:Common.js|Common.js]].",
+       "apihelp-query+allmessages-param-includelocal": "Schließt auch lokale Nachrichten ein, zum Beispiel Nachrichten, die nicht in der Software vorhanden sind, aber dafür im {{ns:MediaWiki}}-Namensraum.\nDies listet alle Seiten im {{ns:MediaWiki}}-Namensraum auf, auch solche, die nicht wirklich Nachrichten sind, wie [[MediaWiki:Common.js|Common.js]].",
        "apihelp-query+allmessages-param-args": "Argumente die in der Nachricht ersetzt werden sollen.",
        "apihelp-query+allmessages-param-filter": "Gebe nur Nachrichten mit Namen, die diese Zeichenfolge enthalten, zurück.",
        "apihelp-query+allmessages-param-customised": "Gebe nur Nachrichten in diesem Anpassungszustand zurück.",
        "apihelp-query+allrevisions-param-generatetitles": "Wenn als Generator verwendet, werden eher Titel als Bearbeitungs-IDs erzeugt.",
        "apihelp-query+allrevisions-example-user": "Liste die letzten 50 Beiträge, sortiert nach Benutzer <kbd>Beispiel</kbd> auf.",
        "apihelp-query+allrevisions-example-ns-main": "Liste die ersten 50 Bearbeitungen im Hauptnamensraum auf.",
+       "apihelp-query+mystashedfiles-paramvalue-prop-size": "Ruft die Dateigröße und Bildabmessungen ab.",
        "apihelp-query+mystashedfiles-param-limit": "Wie viele Dateien zurückgegeben werden sollen.",
        "apihelp-query+alltransclusions-description": "Liste alle Transklusionen auf (eingebettete Seiten die &#123;&#123;x&#125;&#125; benutzen), einschließlich nicht vorhandener.",
        "apihelp-query+alltransclusions-param-from": "Der Titel der Transklusion bei dem die Auflistung beginnen soll.",
        "apihelp-phpfm-description": "Daten im serialisierten PHP-Format ausgeben (schöngedruckt in HTML).",
        "apihelp-rawfm-description": "Daten, einschließlich Fehlerbehebungselementen, im JSON-Format ausgeben (schöngedruckt in HTML).",
        "apihelp-xml-description": "Daten im XML-Format ausgeben.",
-       "apihelp-xml-param-xslt": "Falls angegeben, fügt die benannte Seite als XSL-Stylesheet hinzu. Der Wert muss ein Titel im Namensraum „{{ns:mediawiki}}“ sein und mit <code>.xsl</code> enden.",
+       "apihelp-xml-param-xslt": "Falls angegeben, fügt die benannte Seite als XSL-Stylesheet hinzu. Der Wert muss ein Titel im Namensraum „{{ns:MediaWiki}}“ sein und mit <code>.xsl</code> enden.",
        "apihelp-xml-param-includexmlnamespace": "Falls angegeben, ergänzt einen XML-Namensraum.",
        "apihelp-xmlfm-description": "Daten im XML-Format ausgeben (schöngedruckt in HTML).",
        "api-format-title": "MediaWiki-API-Ergebnis",
        "api-help-param-upload": "Muss als Dateiupload mithilfe eines multipart/form-data-Formular bereitgestellt werden.",
        "api-help-param-multi-separate": "Werte mit <kbd>|</kbd> trennen oder [[Special:ApiHelp/main#main/datatypes|Alternative]].",
        "api-help-param-multi-max": "Maximale Anzahl der Werte ist {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} für Bots).",
+       "api-help-param-multi-all": "Um alle Werte anzugeben, verwende <kbd>$1</kbd>.",
        "api-help-param-default": "Standard: $1",
        "api-help-param-default-empty": "Standard: <span class=\"apihelp-empty\">(leer)</span>",
        "api-help-param-token": "Ein „$1“-Token abgerufen von [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
index 0f184d9..02aa6db 100644 (file)
        "apihelp-main-param-requestid": "Any value given here will be included in the response. May be used to distinguish requests.",
        "apihelp-main-param-servedby": "Include the hostname that served the request in the results.",
        "apihelp-main-param-curtimestamp": "Include the current timestamp in the result.",
+       "apihelp-main-param-responselanginfo": "Include the languages used for <var>uselang</var> and <var>errorlang</var> in the result.",
        "apihelp-main-param-origin": "When accessing the API using a cross-domain AJAX request (CORS), set this to the originating domain. This must be included in any pre-flight request, and therefore must be part of the request URI (not the POST body).\n\nFor authenticated requests, this must match one of the origins in the <code>Origin</code> header exactly, so it has to be set to something like <kbd>https://en.wikipedia.org</kbd> or <kbd>https://meta.wikimedia.org</kbd>. If this parameter does not match the <code>Origin</code> header, a 403 response will be returned. If this parameter matches the <code>Origin</code> header and the origin is whitelisted, the <code>Access-Control-Allow-Origin</code> and <code>Access-Control-Allow-Credentials</code> headers will be set.\n\nFor non-authenticated requests, specify the value <kbd>*</kbd>. This will cause the <code>Access-Control-Allow-Origin</code> header to be set, but <code>Access-Control-Allow-Credentials</code> will be <code>false</code> and all user-specific data will be restricted.",
        "apihelp-main-param-uselang": "Language to use for message translations. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> with <kbd>siprop=languages</kbd> returns a list of language codes, or specify <kbd>user</kbd> to use the current user's language preference, or specify <kbd>content</kbd> to use this wiki's content language.",
+       "apihelp-main-param-errorformat": "Format to use for warning and error text output.\n; plaintext: Wikitext with HTML tags removed and entities replaced.\n; wikitext: Unparsed wikitext.\n; html: HTML.\n; raw: Message key and parameters.\n; none: No text output, only the error codes.\n; bc: Format used prior to MediaWiki 1.29. <var>errorlang</var> and <var>errorsuselocal</var> are ignored.",
+       "apihelp-main-param-errorlang": "Language to use for warnings and errors. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> with <kbd>siprop=languages</kbd> returns a list of language codes, or specify <kbd>content</kbd> to use this wiki's content language, or specify <kbd>uselang</kbd> to use the same value as the <var>uselang</var> parameter.",
+       "apihelp-main-param-errorsuselocal": "If given, error texts will use locally-customized messages from the {{ns:MediaWiki}} namespace.",
 
        "apihelp-block-description": "Block a user.",
        "apihelp-block-param-user": "Username, IP address, or IP address range to block.",
        "apihelp-query+allmessages-param-prop": "Which properties to get.",
        "apihelp-query+allmessages-param-enableparser": "Set to enable parser, will preprocess the wikitext of message (substitute magic words, handle templates, etc.).",
        "apihelp-query+allmessages-param-nocontent": "If set, do not include the content of the messages in the output.",
-       "apihelp-query+allmessages-param-includelocal": "Also include local messages, i.e. messages that don't exist in the software but do exist as a MediaWiki: page.\nThis lists all MediaWiki: pages, so it will also list those that aren't really messages such as [[MediaWiki:Common.js|Common.js]].",
+       "apihelp-query+allmessages-param-includelocal": "Also include local messages, i.e. messages that don't exist in the software but do exist as in the {{ns:MediaWiki}} namespace.\nThis lists all {{ns:MediaWiki}}-namespace pages, so it will also list those that aren't really messages such as [[MediaWiki:Common.js|Common.js]].",
        "apihelp-query+allmessages-param-args": "Arguments to be substituted into message.",
        "apihelp-query+allmessages-param-filter": "Return only messages with names that contain this string.",
        "apihelp-query+allmessages-param-customised": "Return only messages in this customisation state.",
        "apihelp-resetpassword-description-noroutes": "No password reset routes are available.\n\nEnable routes in <var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var> to use this module.",
        "apihelp-resetpassword-param-user": "User being reset.",
        "apihelp-resetpassword-param-email": "Email address of the user being reset.",
-       "apihelp-resetpassword-param-capture": "Return the temporary passwords that were sent. Requires the <code>passwordreset</code> user right.",
        "apihelp-resetpassword-example-user": "Send a password reset email to user <kbd>Example</kbd>.",
        "apihelp-resetpassword-example-email": "Send a password reset email for all users with email address <kbd>user@example.com</kbd>.",
 
        "apihelp-phpfm-description": "Output data in serialized PHP format (pretty-print in HTML).",
        "apihelp-rawfm-description": "Output data, including debugging elements, in JSON format (pretty-print in HTML).",
        "apihelp-xml-description": "Output data in XML format.",
-       "apihelp-xml-param-xslt": "If specified, adds the named page as an XSL stylesheet. The value must be a title in the {{ns:mediawiki}} namespace ending in <code>.xsl</code>.",
+       "apihelp-xml-param-xslt": "If specified, adds the named page as an XSL stylesheet. The value must be a title in the {{ns:MediaWiki}} namespace ending in <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "If specified, adds an XML namespace.",
        "apihelp-xmlfm-description": "Output data in XML format (pretty-print in HTML).",
 
        "api-help-param-upload": "Must be posted as a file upload using multipart/form-data.",
        "api-help-param-multi-separate": "Separate values with <kbd>|</kbd> or [[Special:ApiHelp/main#main/datatypes|alternative]].",
        "api-help-param-multi-max": "Maximum number of values is {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} for bots).",
+       "api-help-param-multi-all": "To specify all values, use <kbd>$1</kbd>.",
        "api-help-param-default": "Default: $1",
        "api-help-param-default-empty": "Default: <span class=\"apihelp-empty\">(empty)</span>",
        "api-help-param-token": "A \"$1\" token retrieved from [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
        "api-help-authmanagerhelper-continue": "This request is a continuation after an earlier <samp>UI</samp> or <samp>REDIRECT</samp> response. Either this or <var>$1returnurl</var> is required.",
        "api-help-authmanagerhelper-additional-params": "This module accepts additional parameters depending on the available authentication requests. Use <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> with <kbd>amirequestsfor=$1</kbd> (or a previous response from this module, if applicable) to determine the requests available and the fields that they use.",
 
+       "apierror-allimages-redirect": "Use <kbd>gaifilterredir=nonredirects</kbd> instead of <var>redirects</var> when using <kbd>allimages</kbd> as a generator.",
+       "apierror-allpages-generator-redirects": "Use <kbd>gapfilterredir=nonredirects</kbd> instead of <var>redirects</var> when using <kbd>allpages</kbd> as a generator.",
+       "apierror-appendnotsupported": "Can't append to pages using content model $1.",
+       "apierror-articleexists": "The article you tried to create has been created already.",
+       "apierror-assertbotfailed": "Assertion that the user has the <code>bot</code> right failed.",
+       "apierror-assertnameduserfailed": "Assertion that the user is \"$1\" failed.",
+       "apierror-assertuserfailed": "Assertion that the user is logged in failed.",
+       "apierror-autoblocked": "Your IP address has been blocked automatically, because it was used by a blocked user.",
+       "apierror-badconfig-resulttoosmall": "The value of <code>$wgAPIMaxResultSize</code> on this wiki is too small to hold basic result information.",
+       "apierror-badcontinue": "Invalid continue param. You should pass the original value returned by the previous query.",
+       "apierror-baddiff": "The diff cannot be retrieved, one or both revisions do not exist or you do not have permission to view them.",
+       "apierror-baddiffto": "<var>$1diffto</var> must be set to a non-negative number, <kbd>prev</kbd>, <kbd>next</kbd> or <kbd>cur</kbd>.",
+       "apierror-badformat-generic": "The requested format $1 is not supported for content model $2.",
+       "apierror-badformat": "The requested format $1 is not supported for content model $2 used by $3.",
+       "apierror-badgenerator-notgenerator": "Module <kbd>$1</kbd> cannot be used as a generator.",
+       "apierror-badgenerator-unknown": "Unknown <kbd>generator=$1</kbd>.",
+       "apierror-badip": "IP parameter is not valid.",
+       "apierror-badmd5": "The supplied MD5 hash was incorrect.",
+       "apierror-badmodule-badsubmodule": "The module <kbd>$1</kbd> does not have a submodule \"$2\".",
+       "apierror-badmodule-nosubmodules": "The module <kbd>$1</kbd> has no submodules.",
+       "apierror-badparameter": "Invalid value for parameter <var>$1</var>.",
+       "apierror-badquery": "Invalid query.",
+       "apierror-badtimestamp": "Invalid value \"$2\" for timestamp parameter <var>$1</var>.",
+       "apierror-badtoken": "Invalid CSRF token.",
+       "apierror-badupload": "File upload parameter <var>$1</var> is not a file upload; be sure to use <code>multipart/form-data</code> for your POST and include a filename in the <code>Content-Disposition</code> header.",
+       "apierror-badurl": "Invalid value \"$2\" for URL parameter <var>$1</var>.",
+       "apierror-baduser": "Invalid value \"$2\" for user parameter <var>$1</var>.",
+       "apierror-badvalue-notmultivalue": "U+001F multi-value separation may only be used for multi-valued parameters.",
+       "apierror-bad-watchlist-token": "Incorrect watchlist token provided. Please set a correct token in [[Special:Preferences]].",
+       "apierror-blockedfrommail": "You have been blocked from sending email.",
+       "apierror-blocked": "You have been blocked from editing.",
+       "apierror-botsnotsupported": "This interface is not supported for bots.",
+       "apierror-cannotreauthenticate": "This action is not available as your identity cannot be verified.",
+       "apierror-cannotviewtitle": "You are not allowed to view $1.",
+       "apierror-cantblock-email": "You don't have permission to block users from sending email through the wiki.",
+       "apierror-cantblock": "You don't have permission to block users.",
+       "apierror-cantchangecontentmodel": "You don't have permission to change the content model of a page.",
+       "apierror-canthide": "You don't have permission to hide user names from the block log.",
+       "apierror-cantimport-upload": "You don't have permission to import uploaded pages.",
+       "apierror-cantimport": "You don't have permission to import pages.",
+       "apierror-cantoverwrite-sharedfile": "The target file exists on a shared repository and you do not have permission to override it.",
+       "apierror-cantsend": "You are not logged in, you do not have a confirmed email address, or you are not allowed to send email to other users, so you cannot send email.",
+       "apierror-cantundelete": "Couldn't undelete: the requested revisions may not exist, or may have been undeleted already.",
+       "apierror-changeauth-norequest": "Failed to create change request.",
+       "apierror-chunk-too-small": "Minimum chunk size is $1 {{PLURAL:$1|byte|bytes}} for non-final chunks.",
+       "apierror-cidrtoobroad": "$1 CIDR ranges broader than /$2 are not accepted.",
+       "apierror-compare-inputneeded": "A title, a page ID, or a revision number is needed for both the <var>from</var> and the <var>to</var> parameters.",
+       "apierror-contentserializationexception": "Content serialization failed: $1",
+       "apierror-contenttoobig": "The content you supplied exceeds the article size limit of $1 {{PLURAL:$1|kilobyte|kilobytes}}.",
+       "apierror-copyuploadbaddomain": "Uploads by URL are not allowed from this domain.",
+       "apierror-copyuploadbadurl": "Upload not allowed from this URL.",
+       "apierror-create-titleexists": "Existing titles can't be protected with <kbd>create</kbd>.",
+       "apierror-csp-report": "Error processing CSP report: $1.",
+       "apierror-databaseerror": "[$1] Database query error.",
+       "apierror-deletedrevs-param-not-1-2": "The <var>$1</var> parameter cannot be used in modes 1 or 2.",
+       "apierror-deletedrevs-param-not-3": "The <var>$1</var> parameter cannot be used in mode 3.",
+       "apierror-emptynewsection": "Creating empty new sections is not possible.",
+       "apierror-emptypage": "Creating new, empty pages is not allowed.",
+       "apierror-exceptioncaught": "[$1] Exception caught: $2",
+       "apierror-filedoesnotexist": "File does not exist.",
+       "apierror-fileexists-sharedrepo-perm": "The target file exists on a shared repository. Use the <var>ignorewarnings</var> parameter to override it.",
+       "apierror-filenopath": "Cannot get local file path.",
+       "apierror-filetypecannotberotated": "File type cannot be rotated.",
+       "apierror-formatphp": "This response cannot be represented using <kbd>format=php</kbd>. See https://phabricator.wikimedia.org/T68776.",
+       "apierror-imageusage-badtitle": "The title for <kbd>$1</kbd> must be a file.",
+       "apierror-import-unknownerror": "Unknown error on import: $1.",
+       "apierror-integeroutofrange-abovebotmax": "<var>$1</var> may not be over $2 (set to $3) for bots or sysops.",
+       "apierror-integeroutofrange-abovemax": "<var>$1</var> may not be over $2 (set to $3) for users.",
+       "apierror-integeroutofrange-belowminimum": "<var>$1</var> may not be less than $2 (set to $3).",
+       "apierror-invalidcategory": "The category name you entered is not valid.",
+       "apierror-invalid-chunk": "Offset plus current chunk is greater than claimed file size.",
+       "apierror-invalidexpiry": "Invalid expiry time \"$1\".",
+       "apierror-invalid-file-key": "Not a valid file key.",
+       "apierror-invalidlang": "Invalid language code for parameter <var>$1</var>.",
+       "apierror-invalidoldimage": "The oldimage parameter has invalid format.",
+       "apierror-invalidparammix-cannotusewith": "The <kbd>$1</kbd> parameter cannot be used with <kbd>$2</kbd>.",
+       "apierror-invalidparammix-mustusewith": "The <kbd>$1</kbd> parameter may only be used with <kbd>$2</kbd>.",
+       "apierror-invalidparammix-parse-new-section": "<kbd>section=new</kbd> cannot be combined with the <var>oldid</var>, <var>pageid</var> or <var>page</var> parameters. Please use <var>title</var> and <var>text</var>.",
+       "apierror-invalidparammix": "The {{PLURAL:$2|parameters}} $1 can not be used together.",
+       "apierror-invalidsection": "The section parameter must be a valid section ID or <kbd>new</kbd>.",
+       "apierror-invalidsha1base36hash": "The SHA1Base36 hash provided is not valid.",
+       "apierror-invalidsha1hash": "The SHA1 hash provided is not valid.",
+       "apierror-invalidtitle": "Bad title \"$1\".",
+       "apierror-invalidurlparam": "Invalid value for <var>$1urlparam</var> (<kbd>$2=$3</kbd>).",
+       "apierror-invaliduser": "Invalid username \"$1\".",
+       "apierror-maxlag-generic": "Waiting for a database server: $1 {{PLURAL:$1|second|seconds}} lagged.",
+       "apierror-maxlag": "Waiting for $2: $1 {{PLURAL:$1|second|seconds}} lagged.",
+       "apierror-mimesearchdisabled": "MIME search is disabled in Miser Mode.",
+       "apierror-missingcontent-pageid": "Missing content for page ID $1.",
+       "apierror-missingparam-at-least-one-of": "{{PLURAL:$2|The parameter|At least one of the parameters}} $1 is required.",
+       "apierror-missingparam-one-of": "{{PLURAL:$2|The parameter|One of the parameters}} $1 is required.",
+       "apierror-missingparam": "The <var>$1</var> parameter must be set.",
+       "apierror-missingrev-pageid": "No current revision of page ID $1.",
+       "apierror-missingtitle-createonly": "Missing titles can only be protected with <kbd>create</kbd>.",
+       "apierror-missingtitle": "The page you specified doesn't exist.",
+       "apierror-missingtitle-byname": "The page $1 doesn't exist.",
+       "apierror-moduledisabled": "The <kbd>$1</kbd> module has been disabled.",
+       "apierror-multival-only-one-of": "{{PLURAL:$3|Only|Only one of}} $2 is allowed for parameter <var>$1</var>.",
+       "apierror-multival-only-one": "Only one value is allowed for parameter <var>$1</var>.",
+       "apierror-multpages": "<var>$1</var> may only be used with a single page.",
+       "apierror-mustbeloggedin-changeauth": "You must be logged in to change authentication data.",
+       "apierror-mustbeloggedin-generic": "You must be logged in.",
+       "apierror-mustbeloggedin-linkaccounts": "You must be logged in to link accounts.",
+       "apierror-mustbeloggedin-removeauth": "You must be logged in to remove authentication data.",
+       "apierror-mustbeloggedin-uploadstash": "The upload stash is only available to logged-in users.",
+       "apierror-mustbeloggedin": "You must be logged in to $1.",
+       "apierror-mustbeposted": "The <kbd>$1</kbd> module requires a POST request.",
+       "apierror-mustpostparams": "The following {{PLURAL:$2|parameter was|parameters were}} found in the query string, but must be in the POST body: $1.",
+       "apierror-noapiwrite": "Editing of this wiki through the API is disabled. Make sure the <code>$wgEnableWriteAPI=true;</code> statement is included in the wiki's <code>LocalSettings.php</code> file.",
+       "apierror-nochanges": "No changes were requested.",
+       "apierror-nodeleteablefile": "No such old version of the file.",
+       "apierror-no-direct-editing": "Direct editing via API is not supported for content model $1 used by $2.",
+       "apierror-noedit-anon": "Anonymous users can't edit pages.",
+       "apierror-noedit": "You don't have permission to edit pages.",
+       "apierror-noimageredirect-anon": "Anonymous users can't create image redirects.",
+       "apierror-noimageredirect": "You don't have permission to create image redirects.",
+       "apierror-nosuchlogid": "There is no log entry with ID $1.",
+       "apierror-nosuchpageid": "There is no page with ID $1.",
+       "apierror-nosuchrcid": "There is no recent change with ID $1.",
+       "apierror-nosuchrevid": "There is no revision with ID $1.",
+       "apierror-nosuchsection": "There is no section $1.",
+       "apierror-nosuchsection-what": "There is no section $1 in $2.",
+       "apierror-notarget": "You have not specified a valid target for this action.",
+       "apierror-notpatrollable": "The revision r$1 can't be patrolled as it's too old.",
+       "apierror-nouploadmodule": "No upload module set.",
+       "apierror-opensearch-json-warnings": "Warnings cannot be represented in OpenSearch JSON format.",
+       "apierror-pagecannotexist": "Namespace doesn't allow actual pages.",
+       "apierror-pagedeleted": "The page has been deleted since you fetched its timestamp.",
+       "apierror-paramempty": "The parameter <var>$1</var> may not be empty.",
+       "apierror-parsetree-notwikitext": "<kbd>prop=parsetree</kbd> is only supported for wikitext content.",
+       "apierror-parsetree-notwikitext-title": "<kbd>prop=parsetree</kbd> is only supported for wikitext content. $1 uses content model $2.",
+       "apierror-pastexpiry": "Expiry time \"$1\" is in the past.",
+       "apierror-permissiondenied": "You don't have permission to $1.",
+       "apierror-permissiondenied-generic": "Permission denied.",
+       "apierror-permissiondenied-patrolflag": "You need the <code>patrol</code> or <code>patrolmarks</code> right to request the patrolled flag.",
+       "apierror-permissiondenied-unblock": "You don't have permission to unblock users.",
+       "apierror-prefixsearchdisabled": "Prefix search is disabled in Miser Mode.",
+       "apierror-promised-nonwrite-api": "The <code>Promise-Non-Write-API-Action</code> HTTP header cannot be sent to write-mode API modules.",
+       "apierror-protect-invalidaction": "Invalid protection type \"$1\".",
+       "apierror-protect-invalidlevel": "Invalid protection level \"$1\".",
+       "apierror-ratelimited": "You've exceeded your rate limit. Please wait some time and try again.",
+       "apierror-readapidenied": "You need read permission to use this module.",
+       "apierror-readonly": "The wiki is currently in read-only mode.",
+       "apierror-reauthenticate": "You have not authenticated recently in this session, please reauthenticate.",
+       "apierror-redirect-appendonly": "You have attempted to edit using the redirect-following mode, which must be used in conjuction with <kbd>section=new</kbd>, <var>prependtext</var>, or <var>appendtext</var>.",
+       "apierror-revdel-mutuallyexclusive": "The same field cannot be used in both <var>hide</var> and <var>show</var>.",
+       "apierror-revdel-needtarget": "A target title is required for this RevDel type.",
+       "apierror-revdel-paramneeded": "At least one value is required for <var>hide</var> and/or <var>show</var>.",
+       "apierror-revisions-norevids": "The <var>revids</var> parameter may not be used with the list options (<var>$1limit</var>, <var>$1startid</var>, <var>$1endid</var>, <kbd>$1dir=newer</kbd>, <var>$1user</var>, <var>$1excludeuser</var>, <var>$1start</var>, and <var>$1end</var>).",
+       "apierror-revisions-singlepage": "<var>titles</var>, <var>pageids</var> or a generator was used to supply multiple pages, but the <var>$1limit</var>, <var>$1startid</var>, <var>$1endid</var>, <kbd>$1dir=newer</kbd>, <var>$1user</var>, <var>$1excludeuser</var>, <var>$1start</var>, and <var>$1end</var> parameters may only be used on a single page.",
+       "apierror-revwrongpage": "r$1 is not a revision of $2.",
+       "apierror-searchdisabled": "<var>$1</var> search is disabled.",
+       "apierror-sectionreplacefailed": "Could not merge updated section.",
+       "apierror-sectionsnotsupported": "Sections are not supported for content model $1.",
+       "apierror-sectionsnotsupported-what": "Sections are not supported by $1.",
+       "apierror-show": "Incorrect parameter - mutually exclusive values may not be supplied.",
+       "apierror-siteinfo-includealldenied": "Cannot view all servers' info unless <var>$wgShowHostNames</var> is true.",
+       "apierror-sizediffdisabled": "Size difference is disabled in Miser Mode.",
+       "apierror-spamdetected": "Your edit was refused because it contained a spam fragment: <code>$1</code>.",
+       "apierror-specialpage-cantexecute": "You don't have permission to view the results of this special page.",
+       "apierror-stashedfilenotfound": "Could not find the file in the stash: $1.",
+       "apierror-stashedit-missingtext": "No stashed text found with the given hash.",
+       "apierror-stashfailed-complete": "Chunked upload is already completed, check status for details.",
+       "apierror-stashfailed-nosession": "No chunked upload session with this key.",
+       "apierror-stashfilestorage": "Could not store upload in the stash: $1",
+       "apierror-stashnosuchfilekey": "No such filekey: $1.",
+       "apierror-stashpathinvalid": "File key of improper format or otherwise invalid: $1.",
+       "apierror-stashwrongowner": "Wrong owner: $1",
+       "apierror-stashzerolength": "File is of zero length, and could not be stored in the stash: $1.",
+       "apierror-templateexpansion-notwikitext": "Template expansion is only supported for wikitext content. $1 uses content model $2.",
+       "apierror-toofewexpiries": "$1 expiry {{PLURAL:$1|timestamp was|timestamps were}} provided where $2 {{PLURAL:$2|was|were}} needed.",
+       "apierror-unknownaction": "The action specified, <kbd>$1</kbd>, is not recognized.",
+       "apierror-unknownerror-editpage": "Unknown EditPage error: $1.",
+       "apierror-unknownerror-nocode": "Unknown error.",
+       "apierror-unknownerror": "Unknown error: \"$1\".",
+       "apierror-unknownformat": "Unrecognized format \"$1\".",
+       "apierror-unrecognizedparams": "Unrecognized {{PLURAL:$2|parameter|parameters}}: $1.",
+       "apierror-unrecognizedvalue": "Unrecognized value for parameter <var>$1</var>: $2.",
+       "apierror-unsupportedrepo": "Local file repository does not support querying all images.",
+       "apierror-upload-filekeyneeded": "Must supply a <var>filekey</var> when <var>offset</var> is non-zero.",
+       "apierror-upload-filekeynotallowed": "Cannot supply a <var>filekey</var> when <var>offset</var> is 0.",
+       "apierror-upload-inprogress": "Upload from stash already in progress.",
+       "apierror-upload-missingresult": "No result in status data.",
+       "apierror-urlparamnormal": "Could not normalize image parameters for $1.",
+       "apierror-writeapidenied": "You're not allowed to edit this wiki through the API.",
+
+       "apiwarn-alldeletedrevisions-performance": "For better performance when generating titles, set <kbd>$1dir=newer</kbd>.",
+       "apiwarn-badurlparam": "Could not parse <var>$1urlparam</var> for $2. Using only width and height.",
+       "apiwarn-badutf8": "The value passed for <var>$1</var> contains invalid or non-normalized data. Textual data should be valid, NFC-normalized Unicode without C0 control characters other than HT (\\t), LF (\\n), and CR (\\r).",
+       "apiwarn-checktoken-percentencoding": "Check that symbols such as \"+\" in the token are properly percent-encoded in the URL.",
+       "apiwarn-deprecation-deletedrevs": "<kbd>list=deletedrevs</kbd> has been deprecated. Please use <kbd>prop=deletedrevisions</kbd> or <kbd>list=alldeletedrevisions</kbd> instead.",
+       "apiwarn-deprecation-expandtemplates-prop": "Because no values have been specified for the <var>prop</var> parameter, a legacy format has been used for the output. This format is deprecated, and in the future, a default value will be set for the <var>prop</var> parameter, causing the new format to always be used.",
+       "apiwarn-deprecation-httpsexpected": "HTTP used when HTTPS was expected.",
+       "apiwarn-deprecation-login-botpw": "Main-account login via <kbd>action=login</kbd> is deprecated and may stop working without warning. To continue login with <kbd>action=login</kbd>, see [[Special:BotPasswords]]. To safely continue using main-account login, see <kbd>action=clientlogin</kbd>.",
+       "apiwarn-deprecation-login-nobotpw": "Main-account login via <kbd>action=login</kbd> is deprecated and may stop working without warning. To safely log in, see <kbd>action=clientlogin</kbd>.",
+       "apiwarn-deprecation-login-token": "Fetching a token via <kbd>action=login</kbd> is deprecated. Use <kbd>action=query&meta=tokens&type=login</kbd> instead.",
+       "apiwarn-deprecation-parameter": "The parameter <var>$1</var> has been deprecated.",
+       "apiwarn-deprecation-parse-headitems": "<kbd>prop=headitems</kbd> is deprecated since MediaWiki 1.28. Use <kbd>prop=headhtml</kbd> when creating new HTML documents, or <kbd>prop=modules|jsconfigvars</kbd> when updating a document client-side.",
+       "apiwarn-deprecation-purge-get": "Use of <kbd>action=purge</kbd> via GET is deprecated. Use POST instead.",
+       "apiwarn-deprecation-withreplacement": "<kbd>$1</kbd> has been deprecated. Please use <kbd>$2</kbd> instead.",
+       "apiwarn-difftohidden": "Couldn't diff to r$1: content is hidden.",
+       "apiwarn-errorprinterfailed": "Error printer failed. Will retry without params.",
+       "apiwarn-errorprinterfailed-ex": "Error printer failed (will retry without params): $1",
+       "apiwarn-invalidcategory": "\"$1\" is not a category.",
+       "apiwarn-invalidtitle": "\"$1\" is not a valid title.",
+       "apiwarn-invalidxmlstylesheetext": "Stylesheet should have <code>.xsl</code> extension.",
+       "apiwarn-invalidxmlstylesheet": "Invalid or non-existent stylesheet specified.",
+       "apiwarn-invalidxmlstylesheetns": "Stylesheet should be in the {{ns:MediaWiki}} namespace.",
+       "apiwarn-moduleswithoutvars": "Property <kbd>modules</kbd> was set but not <kbd>jsconfigvars</kbd> or <kbd>encodedjsconfigvars</kbd>. Configuration variables are necessary for proper module usage.",
+       "apiwarn-notfile": "\"$1\" is not a file.",
+       "apiwarn-nothumb-noimagehandler": "Could not create thumbnail because $1 does not have an associated image handler.",
+       "apiwarn-parse-nocontentmodel": "No <var>title</var> or <var>contentmodel</var> was given, assuming $1.",
+       "apiwarn-parse-titlewithouttext": "<var>title</var> used without <var>text</var>, and parsed page properties were requested. Did you mean to use <var>page</var> instead of <var>title</var>?",
+       "apiwarn-redirectsandrevids": "Redirect resolution cannot be used together with the <var>revids</var> parameter. Any redirects the <var>revids</var> point to have not been resolved.",
+       "apiwarn-tokennotallowed": "Action \"$1\" is not allowed for the current user.",
+       "apiwarn-tokens-origin": "Tokens may not be obtained when the same-origin policy is not applied.",
+       "apiwarn-toomanyvalues": "Too many values supplied for parameter <var>$1</var>: the limit is $2.",
+       "apiwarn-truncatedresult": "This result was truncated because it would otherwise be larger than the limit of $1 bytes.",
+       "apiwarn-unclearnowtimestamp": "Passing \"$2\" for timestamp parameter <var>$1</var> has been deprecated. If for some reason you need to explicitly specify the current time without calculating it client-side, use <kbd>now<kbd>.",
+       "apiwarn-unrecognizedvalues": "Unrecognized {{PLURAL:$3|value|values}} for parameter <var>$1</var>: $2.",
+       "apiwarn-unsupportedarray": "Parameter <var>$1</var> uses unsupported PHP array syntax.",
+       "apiwarn-urlparamwidth": "Ignoring width value set in <var>$1urlparam</var> ($2) in favor of width value derived from <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
+       "apiwarn-validationfailed-badchars": "invalid characters in key (only <code>a-z</code>, <code>A-Z</code>, <code>0-9</code>, <code>_</code>, and <code>-</code> are allowed).",
+       "apiwarn-validationfailed-badpref": "not a valid preference.",
+       "apiwarn-validationfailed-cannotset": "cannot be set by this module.",
+       "apiwarn-validationfailed-keytoolong": "key too long (no more than $1 bytes allowed).",
+       "apiwarn-validationfailed": "Validation error for <kbd>$1</kbd>: $2",
+       "apiwarn-wgDebugAPI": "<strong>Security Warning</strong>: <var>$wgDebugAPI</var> is enabled.",
+
+       "api-feed-error-title": "Error ($1)",
+       "api-usage-docref": "See $1 for API usage.",
+       "api-exception-trace": "$1 at $2($3)\n$4",
        "api-credits-header": "Credits",
        "api-credits": "API developers:\n* Yuri Astrakhan (creator, lead developer Sep 2006–Sep 2007)\n* Roan Kattouw (lead developer Sep 2007–2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Brad Jorsch (lead developer 2013–present)\n\nPlease send your comments, suggestions and questions to mediawiki-api@lists.wikimedia.org\nor file a bug report at https://phabricator.wikimedia.org/."
 }
index c23f33d..99dc57e 100644 (file)
        "apihelp-query+langlinks-param-url": "Obtener la URL completa o no (no se puede usar con <var>$1prop</var>).",
        "apihelp-query+langlinks-param-prop": "Qué propiedades adicionales obtener para cada enlace interlingüe:",
        "apihelp-query+langlinks-paramvalue-prop-url": "Añade el URL completo.",
-       "apihelp-query+langlinks-paramvalue-prop-autonym": "Añade el nombre del idioma nativo.",
+       "apihelp-query+langlinks-paramvalue-prop-autonym": "Añade el nombre nativo del idioma.",
        "apihelp-query+langlinks-param-lang": "Devolver solo enlaces de idioma con este código de idioma.",
        "apihelp-query+langlinks-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+links-param-limit": "Cuántos enlaces se devolverán.",
        "apihelp-tag-example-rev": "Añadir la etiqueta <kbd>vandalism</kbd> al identificador de revisión 123 sin especificar un motivo",
        "apihelp-tag-example-log": "Eliminar la etiqueta <kbd>spam</kbd> de la entrada del registro con identificador 123 con el motivo <kbd>Wrongly applied</kbd>",
        "apihelp-unblock-description": "Desbloquear un usuario.",
-       "apihelp-unblock-param-user": "Nombre de usuario, dirección IP o rango de direcciones IP para desbloquear. No se puede utilizar junto con <var>$1id</var>.",
+       "apihelp-unblock-param-user": "Nombre de usuario, dirección IP o intervalo de direcciones IP para desbloquear. No se puede utilizar junto con <var>$1id</var>.",
        "apihelp-unblock-param-reason": "Motivo del desbloqueo.",
        "apihelp-unblock-example-id": "Desbloquear el bloqueo de ID #<kbd>105</kbd>",
        "apihelp-unblock-example-user": "Desbloquear al usuario <kbd>Bob</kbd> con el motivo <kbd>Sorry Bob</kbd>",
        "apihelp-none-description": "No extraer nada.",
        "apihelp-php-description": "Extraer los datos de salida en formato serializado PHP.",
        "apihelp-rawfm-description": "Extraer los datos de salida, incluidos los elementos de depuración, en formato JSON (embellecido en HTML).",
-       "apihelp-xml-param-xslt": "Si se especifica, añade la página nombrada como una hoja de estilo XSL. El valor debe ser un título en el espacio de nombres {{ns:mediawiki}} que termine en <code>.xsl</code>.",
+       "apihelp-xml-param-xslt": "Si se especifica, añade la página nombrada como una hoja de estilo XSL. El valor debe ser un título en el espacio de nombres {{ns:MediaWiki}} que termine en <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "Si se especifica, añade un espacio de nombres XML.",
        "api-help-main-header": "Módulo principal",
        "api-help-flag-deprecated": "Este módulo está en desuso.",
index 84dad2c..9c71082 100644 (file)
        "apihelp-main-param-requestid": "Toute valeur fournie ici sera incluse dans la réponse. Peut être utilisé pour distinguer des demandes.",
        "apihelp-main-param-servedby": "Inclure le nom d’hôte qui a renvoyé la requête dans les résultats.",
        "apihelp-main-param-curtimestamp": "Inclure l’horodatage actuel dans le résultat.",
+       "apihelp-main-param-responselanginfo": "Inclure les langues utilisées pour <var>uselang</var> et <var>errorlang</var> dans le résultat.",
        "apihelp-main-param-origin": "En accédant à l’API en utilisant une requête AJAX inter-domaines (CORS), mettre le domaine d’origine dans ce paramètre. Il doit être inclus dans toute requête de pre-flight, et doit donc faire partie de l’URI de la requête (pas du corps du POST).\n\nPour les requêtes authentifiées, il doit correspondre exactement à une des origines dans l’entête <code>Origin</code> header, donc il doit être fixé avec quelque chose comme <kbd>https://en.wikipedia.org</kbd> ou <kbd>https://meta.wikimedia.org</kbd>. Si ce paramètre ne correspond pas à l’entête <code>Origin</code>, une réponse 403 sera renvoyée. Si ce paramètre correspond à l’entête <code>Origin</code> et que l’origine est en liste blanche, des entêtes <code>Access-Control-Allow-Origin</code> et <code>Access-Control-Allow-Credentials</code> seront positionnés.\n\nPour les requêtes non authentifiées, spécifiez la valeur <kbd>*</kbd>. Cela positionnera l’entête <code>Access-Control-Allow-Origin</code>, mais <code>Access-Control-Allow-Credentials</code> vaudra <code>false</code> et toutes les données spécifiques à l’utilisateur seront filtrées.",
        "apihelp-main-param-uselang": "Langue à utiliser pour les traductions de message. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> avec <kbd>siprop=languages</kbd> renvoie une liste de codes de langue, ou en spécifiant <kbd>user</kbd> pour utiliser la préférence de langue de l’utilisateur actuel, ou en spécifiant <kbd>content</kbd> pour utiliser le langage du contenu de ce wiki.",
+       "apihelp-main-param-errorformat": "Format à utiliser pour la sortie du texte d’avertissement et d’erreur.\n; plaintext: Wikitexte avec balises HTML supprimées et les entités remplacées.\n; wikitext: wikitexte non analysé.\n; html: HTML.\n; raw: Clé de message et paramètres.\n; none: Aucune sortie de texte, uniquement les codes erreur.\n; bc: Format utilisé avant MédiaWiki 1.29. <var>errorlang</var> et <var>errorsuselocal</var> sont ignorés.",
+       "apihelp-main-param-errorlang": "Langue à utiliser pour les avertissements et les erreurs. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> avec <kbd>siprop=languages</kbd> renvoyant une liste de codes de langue, ou spécifier <kbd>content</kbd> pour utiliser la langue du contenu de ce wiki, ou spécifier <kbd>uselang</kbd> pour utiliser la même valeur que le paramètre <var>uselang</var>.",
+       "apihelp-main-param-errorsuselocal": "S’il est fourni, les textes d’erreur utiliseront des messages adaptés à la langue dans l’espace de noms {{ns:MediaWiki}}.",
        "apihelp-block-description": "Bloquer un utilisateur.",
        "apihelp-block-param-user": "Nom d’utilisateur, adresse IP ou plage d’adresses IP que vous voulez bloquer.",
        "apihelp-block-param-expiry": "Durée d’expiration. Peut être relative (par ex. <kbd>5 months</kbd> ou <kbd>2 weeks</kbd>) ou absolue (par ex. <kbd>2014-09-18T12:34:56Z</kbd>). Si elle est mise à <kbd>infinite</kbd>, <kbd>indefinite</kbd> ou <kbd>never</kbd>, le blocage n’expirera jamais.",
        "apihelp-expandtemplates-paramvalue-prop-ttl": "Le délai maximum après lequel la mise en cache de ce résultat doit être invalidée.",
        "apihelp-expandtemplates-paramvalue-prop-modules": "Tous les modules ResourceLoader que les fonctions d’analyse ont demandé d’ajouter à la sortie. Soit <kbd>jsconfigvars</kbd> soit <kbd>encodedjsconfigvars</kbd> doit être demandé avec <kbd>modules</kbd>.",
        "apihelp-expandtemplates-paramvalue-prop-jsconfigvars": "Donne les variables de configuration JavaScript spécifiques à la page.",
-       "apihelp-expandtemplates-paramvalue-prop-encodedjsconfigvars": "Donne les variables de configuration JavaScript spécifiques à la page sous forme de chaîne JSON.",
+       "apihelp-expandtemplates-paramvalue-prop-encodedjsconfigvars": "Donne les variables de configuration JavaScript spécifiques à la page sous la forme d'une chaîne JSON.",
        "apihelp-expandtemplates-paramvalue-prop-parsetree": "L’arbre d’analyse XML de l’entrée.",
        "apihelp-expandtemplates-param-includecomments": "S’il faut inclure les commentaires HTML dans la sortie.",
        "apihelp-expandtemplates-param-generatexml": "Générer l’arbre d’analyse XML (remplacé par $1prop=parsetree).",
        "apihelp-feedcontributions-param-feedformat": "Le format du flux.",
        "apihelp-feedcontributions-param-user": "Pour quels utilisateurs récupérer les contributions.",
        "apihelp-feedcontributions-param-namespace": "Par quels espaces de nom filtrer les contributions.",
-       "apihelp-feedcontributions-param-year": "Depuis l’année (et plus récent).",
+       "apihelp-feedcontributions-param-year": "De l’année (et antérieur).",
        "apihelp-feedcontributions-param-month": "Depuis le mois (et plus récent).",
        "apihelp-feedcontributions-param-tagfilter": "Filtrer les contributions qui ont ces balises.",
        "apihelp-feedcontributions-param-deletedonly": "Afficher uniquement les contributions supprimées.",
        "apihelp-query+allmessages-param-prop": "Quelles propriétés obtenir.",
        "apihelp-query+allmessages-param-enableparser": "Si positionné pour activer l’analyseur, traitera en avance le wikitexte du message (substitution des mots magiques, gestion des modèles, etc.).",
        "apihelp-query+allmessages-param-nocontent": "Si positionné, ne pas inclure le contenu des messages dans la sortie.",
-       "apihelp-query+allmessages-param-includelocal": "Inclure aussi les messages locaux, c’est-à-dire les messages qui n’existent pas dans le logiciel mais sous forme d’une page MediaWiki:.\nCela liste toutes les pages MediaWiki:, donc aussi celles qui ne sont pas vraiment des messages, telles que [[MediaWiki:Common.js|Common.js]].",
+       "apihelp-query+allmessages-param-includelocal": "Inclure aussi les messages locaux, c’est-à-dire les messages qui n’existent pas dans le logiciel mais dans l’espace de noms {{ns:MediaWiki}}.\nCela liste toutes les pages de l’espace de noms {{ns:MediaWiki}}, donc aussi celles qui ne sont pas vraiment des messages, telles que [[MediaWiki:Common.js|Common.js]].",
        "apihelp-query+allmessages-param-args": "Arguments à substituer dans le message.",
        "apihelp-query+allmessages-param-filter": "Renvoyer uniquement les messages avec des noms contenant cette chaîne.",
        "apihelp-query+allmessages-param-customised": "Renvoyer uniquement les messages dans cet état de personnalisation.",
        "apihelp-resetpassword-description-noroutes": "Aucun chemin pour réinitialiser le mot de passe n’est disponible.\n\nActiver les chemins dans <var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var> pour utiliser ce module.",
        "apihelp-resetpassword-param-user": "Utilisateur ayant été réinitialisé.",
        "apihelp-resetpassword-param-email": "Adresse courriel de l’utilisateur ayant été réinitialisé.",
-       "apihelp-resetpassword-param-capture": "Renvoyer les mots de passe temporaires déjà envoyés. Nécessite le droit utilisateur <code>passwordreset</code>.",
        "apihelp-resetpassword-example-user": "Envoyer un courriel de réinitialisation du mot de passe à l’utilisateur <kbd>Exemple</kbd>.",
        "apihelp-resetpassword-example-email": "Envoyer un courriel pour la réinitialisation de mot de passe à tous les utilisateurs avec une adresse email <kbd>user@example.com</kbd>.",
        "apihelp-revisiondelete-description": "Supprimer et annuler la suppression des révisions.",
        "apihelp-phpfm-description": "Extraire les données au format sérialisé de PHP (affiché proprement en HTML).",
        "apihelp-rawfm-description": "Extraire les données, y compris les éléments de débogage, au format JSON (affiché proprement en HTML).",
        "apihelp-xml-description": "Extraire les données au format XML.",
-       "apihelp-xml-param-xslt": "Si spécifié, ajoute la page nommée comme une feuille de style XSL. La valeur doit être un titre dans l’espace de noms {{ns:mediawiki}} se terminant par <code>.xsl</code>.",
+       "apihelp-xml-param-xslt": "Si spécifié, ajoute la page nommée comme une feuille de style XSL. La valeur doit être un titre dans l’espace de noms {{ns:MediaWiki}} se terminant par <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "Si spécifié, ajoute un espace de noms XML.",
        "apihelp-xmlfm-description": "Extraire les données au format XML (affiché proprement en HTML).",
        "api-format-title": "Résultat de l’API de MediaWiki",
        "api-format-prettyprint-header": "Voici la représentation HTML du format $1. HTML est utile pour le débogage, mais inapproprié pour être utilisé dans une application.\n\nSpécifiez le paramètre <var>format</var> pour modifier le format de sortie. Pour voir la représentation non HTML du format $1, mettez <kbd>format=$2</kbd>.\n\nVoyez la [[mw:API|documentation complète]], ou l’[[Special:ApiHelp/main|aide de l’API]] pour plus d’information.",
        "api-format-prettyprint-header-only-html": "Ceci est une représentation HTML à des fins de déboguage, et n’est pas approprié à une utilisation applicative.\n\nVoir la [[mw:API|documentation complète]], ou l’[[Special:ApiHelp/main|aide de l’API]] pour plus d’information.",
+       "api-format-prettyprint-status": "Cette réponse serait retournée avec l'état HTTP $1 $2.",
        "api-pageset-param-titles": "Une liste des titres sur lesquels travailler.",
        "api-pageset-param-pageids": "Une liste des IDs de page sur lesquelles travailler.",
        "api-pageset-param-revids": "Une liste des IDs de révision sur lesquelles travailler.",
        "api-help-param-upload": "Doit être envoyé comme un fichier importé utilisant multipart/form-data.",
        "api-help-param-multi-separate": "Valeurs séparées par <kbd>|</kbd> ou [[Special:ApiHelp/main#main/datatypes|autre]].",
        "api-help-param-multi-max": "Le nombre maximal de valeurs est {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} pour les robots).",
+       "api-help-param-multi-all": "Pour spécifier toutes les valeurs, utiliser <kbd>$1</kbd>.",
        "api-help-param-default": "Par défaut : $1",
        "api-help-param-default-empty": "Par défaut : <span class=\"apihelp-empty\">(vide)</span>",
        "api-help-param-token": "Un jeton « $1 » récupéré par [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
        "api-help-authmanagerhelper-returnurl": "Renvoyer l’URL pour les flux d’authentification tiers, qui doit être absolue. Cela ou <var>$1continue</var> est obligatoire.\n\nDès réception d’une réponse <samp>REDIRECT</samp>, vous ouvrirez typiquement un navigateur ou un affichage web vers l’URL <samp>redirecttarget</samp> spécifiée pour un flux d’authentification tiers. Une fois ceci terminé, le tiers renverra le navigateur ou l’affichage web vers cette URL. Vous devez extraire toute requête ou paramètre POST de l’URL et les passer comme une requête <var>$1continue</var> à ce module de l’API.",
        "api-help-authmanagerhelper-continue": "Cette requête est une continuation après une précédente réponse <samp>UI</samp> ou <samp>REDIRECT</samp>. Cela ou <var>$1returnurl</var> est obligatoire.",
        "api-help-authmanagerhelper-additional-params": "Ce module accepte des paramètres supplémentaires selon les requêtes d’authentification disponibles. Utiliser <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> avec <kbd>amirequestsfor=$1</kbd> (ou une réponse précédente de ce module, le cas échéant) pour déterminer les requêtes disponibles et les champs qu’elles utilisent.",
+       "apierror-allimages-redirect": "Utiliser <kbd>gaifilterredir=nonredirects</kbd> au lieu de <var>redirects</var> quand <kbd>allimages</kbd> est utilisé comme générateur.",
+       "apierror-allpages-generator-redirects": "Utiliser <kbd>gapfilterredir=nonredirects</kbd> au lieu de <var>redirects</var> quand <kbd>allpages</kbd> est utilisé comme un générateur.",
+       "apierror-appendnotsupported": "Impossible d’ajouter aux pages utilisant le modèle de contenu $1.",
+       "apierror-articleexists": "L’article que vous essayez de créer l’a déjà été.",
+       "apierror-assertbotfailed": "La vérification que l’utilisateur a le droit <code>bot</code> a échoué.",
+       "apierror-assertnameduserfailed": "La vérification que l’utilisateur est « $1 » a échoué.",
+       "apierror-assertuserfailed": "La vérification que l’utilisateur est connecté a échoué.",
+       "apierror-autoblocked": "Votre adresse IP a été bloquée automatiquement, parce qu’elle a été utilisée par un utilisateur bloqué.",
+       "apierror-badconfig-resulttoosmall": "La valeur de <code>$wgAPIMaxResultSize</code> sur ce wiki est trop petite pour contenir des informations de résultat basiques.",
+       "apierror-badcontinue": "Paramètre de continuation non valide. Vous devez passer la valeur d’origine renvoyée par la requête précédente.",
+       "apierror-baddiff": "La différence ne peut être récupérée, une ou plusieurs révisions n’existent pas ou vous n’avez pas le droit de les voir.",
+       "apierror-baddiffto": "<var>$1diffto</var> doit être fixé à un nombre positif ou nul, <kbd>prev</kbd>, <kbd>next</kbd> ou <kbd>cur</kbd>.",
+       "apierror-badformat-generic": "Le format demandé $1 n’est pas supporté pour le modèle de contenu $2.",
+       "apierror-badformat": "Le format demandé $1 n’est pas supporté pour le modèle de contenu $2 utilisé par $3.",
+       "apierror-badgenerator-notgenerator": "Le module <kbd>$1</kbd> ne peut pas être utilisé comme générateur.",
+       "apierror-badgenerator-unknown": "<kbd>generator=$1</kbd> inconnu.",
+       "apierror-badip": "Paramètre IP non valide.",
+       "apierror-badmd5": "Le hachage MD5 fourni n’était pas correct.",
+       "apierror-badmodule-badsubmodule": "Le module <kbd>$1</kbd> n’a pas de sous-module « $2 ».",
+       "apierror-badmodule-nosubmodules": "Le module <kbd>$1</kbd> n’a pas de sous-modules.",
+       "apierror-badparameter": "Valeur non valide pour le paramètre <var>$1</var>.",
+       "apierror-badquery": "Requête invalide.",
+       "apierror-badtimestamp": "Valeur non valide « $2 » pour le paramètre de référence horaire  <var>$1</var>.",
+       "apierror-badtoken": "Jeton CSRF non valide.",
+       "apierror-badvalue-notmultivalue": "La séparation multi-valeur U+001F ne peut être utilisée que pour des paramètres multi-valeurs.",
        "api-credits-header": "Remerciements",
        "api-credits": "Développeurs de l’API :\n* Roan Kattouw (développeur en chef Sept. 2007–2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (créateur, développeur en chef Sept. 2006–Sept. 2007)\n* Brad Jorsch (développeur en chef depuis 2013)\n\nVeuillez envoyer vos commentaires, suggestions et questions à mediawiki-api@lists.wikimedia.org\nou remplir un rapport de bogue sur https://phabricator.wikimedia.org/."
 }
index 902221a..e688f8f 100644 (file)
        "apihelp-query+allmessages-param-prop": "Que propiedades obter.",
        "apihelp-query+allmessages-param-enableparser": "Marcar para activar o analizador, isto preprocesará o texto wiki da mensaxe (substituir palabras máxicas, xestionar modelo, etc.)",
        "apihelp-query+allmessages-param-nocontent": "Se se marca, non inclúe o contido das mensaxes na saída.",
-       "apihelp-query+allmessages-param-includelocal": "Tamén inclúe mensaxes locais, p.ex. mensaxes que non existen no software pero existen como unha páxina MediaWiki:. \nIsto lista todas as páxinas MediaWiki:, polo que tamén listará as que non son realmente mensaxes como [[MediaWiki:Common.js|Common.js]].",
+       "apihelp-query+allmessages-param-includelocal": "Tamén inclúe mensaxes locais, p.ex. mensaxes que non existen no software pero existen como no espazo de nomes {{ns:MediaWiki}}. \nIsto lista todas as páxinas do espazo de nomes {{ns:MediaWiki}}, polo que tamén listará as que non son realmente mensaxes como [[MediaWiki:Common.js|Common.js]].",
        "apihelp-query+allmessages-param-args": "Argumentos a substituír na mensaxe.",
        "apihelp-query+allmessages-param-filter": "Retornar só mensaxes con nomes que conteñan esta cadea.",
        "apihelp-query+allmessages-param-customised": "Devolver só mensaxes neste estado de personalización.",
        "apihelp-resetpassword-description-noroutes": "Non están dispoñibles as rutas de reinicio de contrasinal \n\nActive as rutas en <var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var> para usar este módulo.",
        "apihelp-resetpassword-param-user": "Usuario sendo reinicializado.",
        "apihelp-resetpassword-param-email": "Está reinicializándose o enderezo de correo electrónico do usuario.",
-       "apihelp-resetpassword-param-capture": "Devolve os contrasinais temporais que se enviaron. Require o dereito de usuario <code>passwordreset</code> .",
        "apihelp-resetpassword-example-user": "Enviar un correo de reinicialización de contrasinal ó usuario <kbd>Exemplo</kbd>.",
        "apihelp-resetpassword-example-email": "Enviar un correo de reinicialización de contrasinal a todos os usuarios con enderezo de correo electrónico <kbd>usario@exemplo.com</kbd>.",
        "apihelp-revisiondelete-description": "Borrar e restaurar revisións.",
        "apihelp-phpfm-description": "Datos de saída en formato serializado de PHP(impresión en HTML).",
        "apihelp-rawfm-description": "Datos de saída, incluíndo os elementos de depuración, en formato JSON (impresión en HTML).",
        "apihelp-xml-description": "Datos de saída en formato XML.",
-       "apihelp-xml-param-xslt": "Se está indicado, engade o nome da páxina como unha folla de estilo XSL. O valor debe ser un título no espazo de nomes {{ns:mediawiki}} rematando con <code>.xsl</code>.",
+       "apihelp-xml-param-xslt": "Se está indicado, engade o nome da páxina como unha folla de estilo XSL. O valor debe ser un título no espazo de nomes {{ns:MediaWiki}} rematando con <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "Se está indicado, engade un espazo de nomes XML.",
        "apihelp-xmlfm-description": "Datos de saída en formato XML(impresión en HTML).",
        "api-format-title": "Resultado de API de MediaWiki",
        "api-format-prettyprint-header": "Esta é a representación HTML do formato $1. HTML é bó para depurar, pero non é axeitado para usar nunha aplicación.\n\nEspecifique o parámetro <var>format</var> para cambiar o formato de saída. Para ver a representación non-HTML do formato $1, fixe <kbd>format=$2</kbd>.\n\n\nRevise a [[mw:API|documentación completa]], ou a [[Special:ApiHelp/main|axuda da API]] para obter máis información.",
        "api-format-prettyprint-header-only-html": "Esta é unha representación HTML empregada para a depuración de erros, e non é axeitada para o uso de aplicacións.\n\nVexa a [[mw:API|documentación completa]], ou a [[Special:ApiHelp/main|axuda da API]] para máis información.",
+       "api-format-prettyprint-status": "Esta resposta será devolta co estado de HTTP $1 $2.",
        "api-pageset-param-titles": "Lista de títulos nos que traballar.",
        "api-pageset-param-pageids": "Lista de identificadores de páxina nos que traballar.",
        "api-pageset-param-revids": "Unha lista de IDs de modificacións sobre as que traballar.",
        "api-help-param-upload": "Debe ser enviado como un ficheiro importado usando multipart/form-data.",
        "api-help-param-multi-separate": "Separe os valores con <kbd>|</kbd> ou [[Special:ApiHelp/main#main/datatypes|outros]].",
        "api-help-param-multi-max": "O número máximo de valores é {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} para os bots).",
+       "api-help-param-multi-all": "Para especificar tódolos valores use <kbd>$1</kbd>.",
        "api-help-param-default": "Por defecto: $1",
        "api-help-param-default-empty": "Por defecto: <span class=\"apihelp-empty\">(baleiro)</span>",
        "api-help-param-token": "Un identificador \"$1\" recuperado por [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
        "api-help-authmanagerhelper-returnurl": "Devolve o URL para os fluxos de autenticación de terceiros, que debe ser absoluto. Este ou <var>$1continue</var> é obrigatorio.\n\nLogo da recepción dunha resposta <samp>REDIRECT</samp>, vostede normalmente abrirá un navegador web ou un visor web para ver a URL <samp>redirecttarget</samp> especificada para un fluxo de autenticación de terceiros. Cando isto se complete, a aplicación de terceiros enviará ó navegador web ou visor web a esta URL. Vostede debe eliminar calquera consulta ou parámetros POST da URL e pasalos como unha consulta <var>$1continue</var> a este módulo API.",
        "api-help-authmanagerhelper-continue": "Esta petición é unha continucación despois dun resposta precedente <samp>UI</samp> ou <samp>REDIRECT</samp>. Esta ou <var>$1returnurl</var> é requirida.",
        "api-help-authmanagerhelper-additional-params": "Este módulo acepta parámetros adicionais dependendo das consultas de autenticación dispoñibles. Use <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> con <kbd>amirequestsfor=$1</kbd> (ou unha resposta previa deste módulo, se aplicable) para determinar as consultas dispoñibles e os campos que usan.",
+       "apierror-badquery": "A consulta non é válida.",
+       "apierror-blocked": "Foi bloqueado fronte á edición.",
+       "apierror-botsnotsupported": "Esta interface non está dispoñible para bots.",
+       "apierror-cantblock": "Non ten permisos para bloquear usuarios.",
+       "apierror-cantimport": "Non ten permisos para importar páxinas.",
+       "apierror-filedoesnotexist": "O ficheiro non existe.",
+       "apierror-noedit-anon": "Os usuarios anónimos non poden editar páxinas.",
+       "apierror-noedit": "Non ten permisos para editar páxinas.",
+       "apierror-permissiondenied-generic": "Permisos rexeitados.",
+       "apierror-unknownerror-nocode": "Erro descoñecido.",
+       "apierror-unknownerror": "Erro descoñecido: \"$1\".",
+       "apierror-unknownformat": "Formato descoñecido \"$1\".",
+       "apiwarn-invalidcategory": "\"$1\" non é unha categoría.",
+       "apiwarn-invalidtitle": "\"$1\" non é un título válido.",
+       "apiwarn-notfile": "\"$1\" non é un ficheiro.",
+       "api-feed-error-title": "Erro ($1)",
+       "api-usage-docref": "Consulte $1 para ver o uso da API.",
+       "api-exception-trace": "$1 en $2($3)\n$4",
        "api-credits-header": "Créditos",
        "api-credits": "Desenvolvedores da API:\n* Roan Kattouw (desenvolvedor principal, set. 2007-2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (creador e desenvolvedor principal, set. 2006-sep. 2007)\n* Brad Jorsch (desenvolvedor principal, 2013-actualidade)\n\nEnvía comentarios, suxerencias e preguntas a mediawiki-api@lists.wikimedia.org\nou informa dun erro en https://phabricator.wikimedia.org/."
 }
index c1dd0fa..3e4e4ce 100644 (file)
        "apihelp-query+allmessages-param-prop": "אלו מאפיינים לקבל.",
        "apihelp-query+allmessages-param-enableparser": "יש להגדיר כדי להפעיל את המפענח, יעשה קדם־עיבוד לקוד ויקי של ההודעה (יחליף מילות קסם, יטפל בתבניות, וכו').",
        "apihelp-query+allmessages-param-nocontent": "אם זה מוגדר, לא לכלול את תוכן ההודעות בפלט.",
-       "apihelp-query+allmessages-param-includelocal": "×\9c×\9b×\9c×\95×\9c ×\92×\9d ×\94×\95×\93×¢×\95ת ×\9eק×\95×\9e×\99×\95ת, ×\9b×\9c×\95×\9eר ×\94×\95×\93×¢×\95ת ×©×\90×\99× ×\9f ×§×\99×\99×\9e×\95ת ×\91ת×\9b× ×\94, ×\90×\91×\9c ×\9b×\9f ×§×\99×\99×\9e×\95ת ×\91ת×\95ר ×\93×£ ×\9e×\93×\99×\94Ö¾×\95×\99ק×\99.\n×\96×\94 ×¨×\95ש×\9d ×\90ת ×\9b×\9c ×\93פ×\99 MediaWiki: כך שזה ירשום גם דפים שאינם באמת הודעות, כגון [[MediaWiki:Common.js|Common.js]].",
+       "apihelp-query+allmessages-param-includelocal": "×\9c×\9b×\9c×\95×\9c ×\92×\9d ×\94×\95×\93×¢×\95ת ×\9eק×\95×\9e×\99×\95ת, ×\9b×\9c×\95×\9eר ×\94×\95×\93×¢×\95ת ×©×\90×\99× ×\9f ×§×\99×\99×\9e×\95ת ×\91ת×\9b× ×\94, ×\90×\91×\9c ×\9b×\9f ×§×\99×\99×\9e×\95ת ×\91×\9eר×\97×\91 {{ns:MediaWiki}}.\n×\96×\94 ×¨×\95ש×\9d ×\90ת ×\9b×\9c ×\94×\93פ×\99×\9d ×\91×\9eר×\97×\91 {{ns:MediaWiki}}, כך שזה ירשום גם דפים שאינם באמת הודעות, כגון [[MediaWiki:Common.js|Common.js]].",
        "apihelp-query+allmessages-param-args": "ארגומנטים שיוחלפו לתוך ההודעה.",
        "apihelp-query+allmessages-param-filter": "החזרה רק של הודעות עם שמות שמכילים את המחרוזת הזאת.",
        "apihelp-query+allmessages-param-customised": "להחזיר רק הודעות במצב ההתאמה הזה.",
        "apihelp-resetpassword-description-noroutes": "אין מסלולים לאיפוס ססמה.\n\nכדי להשתמש במודול הזה, יש להפעיל מסלולים ב־<var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var>.",
        "apihelp-resetpassword-param-user": "המשתמש שמאופס.",
        "apihelp-resetpassword-param-email": "כתובת הדוא\"ל של המשתמש שהסיסמה שלו מאופסת.",
-       "apihelp-resetpassword-param-capture": "החזרת הססמאות הזמניות שנשלחו. דורש את ההרשאה <code>passwordreset</code>.",
        "apihelp-resetpassword-example-user": "שליחת מכתב איפוס ססמה למשתמש <kbd>Example</kbd>.",
        "apihelp-resetpassword-example-email": "שליחת מכתב איפוס ססמה לכל המשתמשים שהכתובת שלהם היא <kbd>user@example.com</kbd>.",
        "apihelp-revisiondelete-description": "מחיקה ושחזור ממחיקה של גרסאות.",
        "apihelp-phpfm-description": "לפלוט נתונים בתסדיר PHP מוסדר (עם הדפסה יפה ב־HTML).",
        "apihelp-rawfm-description": "לפלוט את הנתונים, כולל אלמנטים לניפוי שגיאות, בתסדיר JSON (עם הדפסה יפה ב־HTML).",
        "apihelp-xml-description": "לפלוט נתונים בתסדיר XML.",
-       "apihelp-xml-param-xslt": "אם צוין, יש להוסיף את שם הדף כגיליון עיצוב XSL. על הערך להיות כותרת ב {{ns:mediawiki}} במרחב שם המשתמש, המסתיים ב-  <code>.xsl</code>.",
+       "apihelp-xml-param-xslt": "אם צוין, יש להוסיף את שם הדף כגיליון עיצוב XSL. על הערך להיות כותרת ב {{ns:MediaWiki}} במרחב שם המשתמש, המסתיים ב-  <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "אם זה צוין, מוסיף מרחב שם של XML.",
        "apihelp-xmlfm-description": "לפלוט נתונים בתסדיר XML (עם הדפסה יפה ב־HTML).",
        "api-format-title": "תוצאה של API של מדיה־ויקי",
        "api-help-param-upload": "חייב להישלח (posted) בתור העלאת קובץ באמצעות multipart/form-data.",
        "api-help-param-multi-separate": "הפרדה בין ערכים נעשית באמצעות <kbd>|</kbd> או [[Special:ApiHelp/main#main/datatypes|תו חלופי]].",
        "api-help-param-multi-max": "מספר הערכים המרבי הוא {{PLURAL:$1|$1}} (עבור בוטים – {{PLURAL:$2|$2}}).",
+       "api-help-param-multi-all": "כדי לתת את כל הערכים, יש להשתמש ב־<kbd>$1</kbd>.",
        "api-help-param-default": "ברירת מחדל: $1",
        "api-help-param-default-empty": "ברירת מחדל: <span class=\"apihelp-empty\">(ריק)</span>",
        "api-help-param-token": "אסימון \"$1\" שאוחזר מ־[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
index e0920f6..232386e 100644 (file)
@@ -92,5 +92,6 @@
        "api-help-param-limit2": "Nem engedélyezett több mint $1 (botoknak $2).",
        "api-help-param-integer-min": "Az {{PLURAL:$1|1=érték nem lehet kisebb|2=értékek nem lehetnek kisebbek}} mint $2.",
        "api-help-param-integer-max": "Az {{PLURAL:$1|1=érték nem lehet nagyobb|2=értékek nem lehetnek nagyobbak}} mint $3.",
-       "api-help-param-integer-minmax": "{{PLURAL:$1|1=Az értéknek $2 és $3 között kell lennie.|2=Az értékeknek $2 és $3 között kell lenniük.}}"
+       "api-help-param-integer-minmax": "{{PLURAL:$1|1=Az értéknek $2 és $3 között kell lennie.|2=Az értékeknek $2 és $3 között kell lenniük.}}",
+       "api-help-param-default": "Alapértelmezett: $1"
 }
index d93dc23..5ae3547 100644 (file)
@@ -4,7 +4,8 @@
                        "WongKentir",
                        "Beeyan",
                        "Rachmat.Wahidi",
-                       "Kenrick95"
+                       "Kenrick95",
+                       "Presidenvolksraad"
                ]
        },
        "apihelp-main-param-action": "Tindakan manakah yang akan dilakukan.",
@@ -60,7 +61,7 @@
        "apihelp-edit-param-tags": "Ganti tag untuk menerapkan ke revisi.",
        "apihelp-edit-param-minor": "Suntingan kecil.",
        "apihelp-edit-param-notminor": "Bukan suntingan kecil.",
-       "apihelp-edit-param-bot": "Tandai suntingan ini sebagai bot.",
+       "apihelp-edit-param-bot": "Tandai suntingan ini sebagai suntingan bot.",
        "apihelp-edit-param-basetimestamp": "Stempel waktu dari revisi asal, digunakan untuk mendeteksi konflik penyuntingan. Dapat ditemukan di [[Special:ApiHelp/query+revisions|action=query&prop=revisions&rvprop=timestamp]].",
        "apihelp-edit-param-starttimestamp": "Stempel waktu ketika proses penyuntingan dimulai, digunakan untuk mendeteksi konflik penyuntingan. Nilai yang cocok dapat ditemukan dengan menggunakan <var>[[Special:ApiHelp/main|curtimestamp]]</var> ketika memulai proses penyuntingan (seperti ketika memuat isi konten yang akan disunting).",
        "apihelp-edit-param-recreate": "Batalkan galat yang terjadi tentang halaman yang sudah dihapus pada saat itu.",
        "apihelp-emailuser-param-subject": "Tajuk subjek.",
        "apihelp-emailuser-param-text": "Badan pesan.",
        "apihelp-emailuser-param-ccme": "Kirimkan salinan pesan ini kepada saya.",
-       "apihelp-expandtemplates-description": "Tambahkan semua templat dalam teks wiki.",
+       "apihelp-expandtemplates-description": "Longgarkan semua templat dalam teks wiki.",
        "apihelp-expandtemplates-param-title": "Judul halaman.",
        "apihelp-expandtemplates-param-text": "Teks wiki yang akan diubah.",
        "apihelp-expandtemplates-param-revid": "ID revisi, untuk <nowiki>{{REVISIONID}}</nowiki> dan variabel serupa.",
        "apihelp-expandtemplates-param-prop": "Bagian informasi manakah yang ingin didapatkan.\n\nPerhatikan bahwa jika tidak ada nilai yang dipilih, hasilnya akan mengandung teks wiki, namun keluaran akan berupa format usang.",
+       "apihelp-feedcontributions-param-deletedonly": "Tampilkan hanya kontribusi terhapus.",
        "apihelp-login-example-login": "Masuk log.",
+       "apihelp-move-param-noredirect": "Jangan buat pengalihan.",
+       "apihelp-move-param-unwatch": "Hapus halaman dan pengalihan dari daftar pantauan pengguna ini.",
+       "apihelp-move-example-move": "Pindahkan <kbd>Judul buruk</kbd> ke <kbd>Judul benar</kbd> tanpa membuat pengalihan.",
+       "apihelp-opensearch-param-redirects": "Bagaimana menangani pengalihan:\n;return:Kembali ke pengalihan itu.\n;resolve:Kembali ke halaman tujuan. Mungkin hasil kembali kurang dari $1limit.\nUntuk alasan riwayat, nilai baku adalah \"kembali\" untuk $1format=json dan \"resolve\" untuk format lain.",
        "apihelp-query+prefixsearch-param-profile": "Cari profil untuk digunakan.",
        "apihelp-query+search-param-qiprofile": "Meminta profil independen untuk digunakan (berefek pada algoritma peringkat).",
-       "apihelp-revisiondelete-param-ids": "Penanda untuk perubahan yang akan dihapus"
+       "apihelp-revisiondelete-param-ids": "Penanda untuk perubahan yang akan dihapus",
+       "api-format-prettyprint-status": "Tanggapan ini akan dikembalikan dengan status $1 $2 HTTP."
 }
index 48521a1..ea3f415 100644 (file)
        "apihelp-resetpassword-description-noroutes": "Non sono disponibili rotte per la reimpostazione della password.\n\nAbilita le rotte in <var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var> per usare questo modulo.",
        "apihelp-resetpassword-param-user": "Utente in corso di ripristino.",
        "apihelp-resetpassword-param-email": "Indirizzo di posta elettronica dell'utente in corso di ripristino.",
-       "apihelp-resetpassword-param-capture": "Restituisce le password temporanee che erano state inviate. Richiede il diritto utente <code>passwordreset</code>.",
        "apihelp-resetpassword-example-user": "Invia una mail per reimpostare la password all'utente <kbd>Example</kbd>.",
        "apihelp-resetpassword-example-email": "Invia una mail per reimpostare la password a tutti gli utenti con indirizzo di posta elettronica <kbd>user@example.com</kbd>.",
        "apihelp-revisiondelete-description": "Cancella e ripristina le versioni.",
        "api-help-param-integer-minmax": "{{PLURAL:$1|1=Il valore deve essere compreso|2=I valori devono essere compresi}} tra $2 e $3.",
        "api-help-param-multi-separate": "Separa i valori con <kbd>|</kbd> o [[Special:ApiHelp/main#main/datatypes|alternativa]].",
        "api-help-param-multi-max": "Il numero massimo di valori è {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} per i bot).",
+       "api-help-param-multi-all": "Per specificare tutti i valori, utilizza <kbd>$1</kbd>.",
        "api-help-param-default": "Predefinito: $1",
        "api-help-param-default-empty": "Predefinito: <span class=\"apihelp-empty\">(vuoto)</span>",
        "api-help-param-token": "Un token \"$1\" recuperato da [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
index f85ea9f..63865ed 100644 (file)
@@ -10,7 +10,8 @@
                        "Sujiniku",
                        "Macofe",
                        "Suchichi02",
-                       "Kkairri"
+                       "Kkairri",
+                       "ネイ"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|説明文書]]\n* [[mw:API:FAQ|よくある質問]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api メーリングリスト]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API 告知]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R バグの報告とリクエスト]\n</div>\n<strong>状態:</strong> このページに表示されている機能は全て動作するはずですが、この API は未だ活発に開発されており、変更される可能性があります。アップデートの通知を受け取るには、[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce メーリングリスト]に参加してください。\n\n<strong>誤ったリクエスト:</strong> 誤ったリクエストが API に送られた場合、\"MediaWiki-API-Error\" HTTP ヘッダーが送信され、そのヘッダーの値と送り返されるエラーコードは同じ値にセットされます。より詳しい情報は [[mw:API:Errors_and_warnings|API: Errors and warnings]] を参照してください。\n\n<strong>テスト:</strong> API のリクエストのテストは、[[Special:ApiSandbox]]で簡単に行えます。",
        "apihelp-opensearch-example-te": "<kbd>Te</kbd> から始まるページを検索する。",
        "apihelp-options-param-reset": "個人設定をサイトの既定値にリセットする。",
        "apihelp-options-param-resetkinds": "<var>$1reset</var> が設定されている場合、リセットする設定項目の種類のリスト。",
-       "apihelp-options-param-change": "名前=値 の形式 (例えば skin=vector) で整形された変更のリスト。値はパイプ文字を含むことができません。optionname|otheroption|... のように値が与えられない (イコール記号すら無い) 場合、設定は既定値にリセットされます。",
+       "apihelp-options-param-change": "名前=値 の形式 (例えば skin=vector) で整形された変更のリスト。optionname|otheroption|... のように値が与えられなかった (イコール記号すら無い) 場合、設定は既定値にリセットされます。与えられた値がパイプ(<kbd>|</kbd>)を含む場合、[[Special:ApiHelp/main#main/datatypes|ほかのセパレーター]]をお使いください。",
        "apihelp-options-example-reset": "すべて初期設定に戻す。",
        "apihelp-options-example-change": "<kbd>skin</kbd> および <kbd>hideminor</kbd> の個人設定を変更する。",
        "apihelp-options-example-complex": "すべての個人設定を初期化し、<kbd>skin</kbd> および <kbd> nickname </kbd> を設定する。",
        "apihelp-phpfm-description": "データを PHP のシリアル化した形式 (HTML に埋め込んだ形式) で出力します。",
        "apihelp-rawfm-description": "データをデバッグ要素付きで JSON 形式 (HTML に埋め込んだ形式) で出力します。",
        "apihelp-xml-description": "データを XML 形式で出力します。",
-       "apihelp-xml-param-xslt": "指定すると、XSLスタイルシートとして名付けられたページを追加します。値は、必ず、{{ns:mediawiki}} 名前空間の、ページ名の末尾が <code>.xsl</code> でのタイトルである必要があります。",
+       "apihelp-xml-param-xslt": "指定すると、XSLスタイルシートとして名付けられたページを追加します。値は、必ず、{{ns:MediaWiki}} 名前空間の、ページ名の末尾が <code>.xsl</code> でのタイトルである必要があります。",
        "apihelp-xml-param-includexmlnamespace": "指定すると、XML 名前空間を追加します。",
        "apihelp-xmlfm-description": "データを XML 形式 (HTML に埋め込んだ形式) で出力します。",
        "api-format-title": "MediaWiki API の結果",
index f15bec1..98a41d4 100644 (file)
@@ -13,7 +13,8 @@
                        "Yearning",
                        "Priviet",
                        "Ykhwong",
-                       "Jonghaya"
+                       "Jonghaya",
+                       "Jerrykim306"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|설명문서]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api 메일링 리스트]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API 알림 사항]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R 버그 및 요청]\n</div>\n<strong>상태:</strong> 이 페이지에 보이는 모든 기능은 정상적으로 작동하지만, API는 여전히 활발하게 개발되고 있으며, 언제든지 변경될 수 있습니다. 업데이트 공지를 받아보려면 [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 메일링 리스트]를 구독하십시오.\n\n<strong>잘못된 요청:</strong> API에 잘못된 요청이 전송되면 \"MediaWiki-API-Error\" 키가 포함된 HTTP 헤더가 전송되며 반환되는 헤더와 오류 코드의 값은 동일한 값으로 설정됩니다. 자세한 정보에 대해서는 [[mw:API:Errors_and_warnings|API:오류와 경고]]를 참조하십시오.\n\n<strong>테스트하기:</strong> API 요청 테스트를 용이하게 하려면, [[Special:ApiSandbox]]를 보십시오.",
        "apihelp-main-param-smaxage": "<code>s-maxage</code> HTTP 캐시 컨트롤 헤더를 설정합니다. 오류는 캐시되지 않습니다.",
        "apihelp-main-param-maxage": "<code>max-age</code> HTTP 캐시 컨트롤 헤더를 설정합니다. 오류는 캐시되지 않습니다.",
        "apihelp-main-param-assert": "<kbd>user</kbd> 플래그가 설정되어 있다면 로그인 여부를 체크하며, <kbd>bot</kbd>  플래그가 설정되어 있다면 봇 사용자 권한이 설정되어 있는지 확인합니다.",
+       "apihelp-main-param-assertuser": "현재 사용자가 지명된 사용자인지 확인합니다.",
        "apihelp-main-param-requestid": "주어진 요청 값은 응답에 포함됩니다. 요청을 구분하기 위해 사용될 수 있습니다.",
        "apihelp-main-param-servedby": "결과에 요청을 처리한 호스트네임을 포함합니다.",
        "apihelp-main-param-curtimestamp": "결과의 타임스탬프를 포함합니다.",
+       "apihelp-main-param-uselang": "메시지 번역을 위한 언어입니다. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd>에 <kbd>siprop=languages</kbd>를 함께 사용하면 언어 코드의 목록을 반환하고, <kbd>user</kbd>를 지정하면 현재 사용자의 언어 환경 설정을 사용하며, <kbd>content</kbd>를 지정하면 이 위키의 콘텐츠 언어를 사용합니다.",
        "apihelp-block-description": "사용자를 차단합니다.",
        "apihelp-block-param-user": "차단하고자 하는 계정 이름, IP 주소 또는 대역",
        "apihelp-block-param-expiry": "기한. 상대값(예시: <kbd>5 months</kbd> 또는 </kbd>2 weeks</kbd>) 또는 절대값(예시: <kbd>2014-09-18T12:34:56Z</kbd>)이 될 수 있습니다. <kbd>infinite</kbd>, <kbd>indefinite</kbd> 또는 <kbd>never</kbd>로 설정하면 무기한으로 설정됩니다.",
        "apihelp-feedrecentchanges-param-invert": "선택한 항목을 제외한 모든 이름공간.",
        "apihelp-feedrecentchanges-param-associated": "관련 (토론 또는 일반) 이름공간을 포함합니다.",
        "apihelp-feedrecentchanges-param-limit": "반환할 결과의 최대 수.",
-       "apihelp-feedrecentchanges-param-from": "이후의 변경 사항을 보여줍니다.",
+       "apihelp-feedrecentchanges-param-from": "이후의 변경사항을 보여줍니다.",
        "apihelp-feedrecentchanges-param-hideminor": "사소한 편집을 숨깁니다.",
        "apihelp-feedrecentchanges-param-hidebots": "봇의 편집을 숨깁니다.",
        "apihelp-feedrecentchanges-param-hideanons": "익명 사용자의 편집을 숨깁니다.",
        "apihelp-feedwatchlist-param-feedformat": "피드 포맷.",
        "apihelp-feedwatchlist-example-default": "주시문서 목록 피드를 보여줍니다.",
        "apihelp-filerevert-description": "파일을 이전 판으로 되돌립니다.",
+       "apihelp-filerevert-param-comment": "업로드 댓글입니다.",
        "apihelp-filerevert-example-revert": "<kbd>Wiki.png</kbd>를 <kbd>2011-03-05T15:27:40Z</kbd> 판으로 되돌립니다.",
        "apihelp-help-description": "지정된 모듈의 도움말을 보여줍니다.",
        "apihelp-help-param-helpformat": "도움말 출력 포맷.",
+       "apihelp-help-example-main": "메인 모듈의 도움말입니다.",
        "apihelp-help-example-recursive": "모든 도움말을 한 페이지로 모읍니다.",
        "apihelp-imagerotate-description": "하나 이상의 그림을 회전합니다.",
        "apihelp-imagerotate-param-rotation": "시계 방향으로 회전할 그림의 각도.",
        "apihelp-query+users-example-simple": "사용자 <kbd>Example</kbd>의 정보를 반환합니다.",
        "apihelp-query+watchlist-description": "현재 사용자의 주시목록의 문서의 최근 바뀜을 가져옵니다.",
        "apihelp-query+watchlist-param-user": "이 사용자의 변경 사항만 나열합니다.",
-       "apihelp-query+watchlist-param-excludeuser": "이 사용자의 변경 사항을 나열하지 않습니다.",
+       "apihelp-query+watchlist-param-excludeuser": "이 사용자의 변경사항을 나열하지 않습니다.",
        "apihelp-query+watchlist-paramvalue-prop-ids": "판 ID와 페이지 ID를 추가합니다.",
        "apihelp-query+watchlist-paramvalue-prop-title": "문서의 제목을 추가합니다.",
        "apihelp-query+watchlist-paramvalue-prop-flags": "편집에 대한 플래그를 추가합니다.",
        "api-help-param-type-limit": "유형: 정수 또는 <kbd>max</kbd>",
        "api-help-param-type-integer": "유형: {{PLURAL:$1|1=정수|2=정수 목록}}",
        "api-help-param-type-boolean": "유형: 부울 ([[Special:ApiHelp/main#main/datatypes|자세한 정보]])",
+       "api-help-param-type-user": "유형: {{PLURAL:$1|1=사용자 이름|2=사용자 이름 목록}}",
        "api-help-param-list": "{{PLURAL:$1|1=다음 값 중 하나|2=값 (<kbd>{{!}}</kbd>로 구분)}}: $2",
        "api-help-param-list-can-be-empty": "{{PLURAL:$1|0=비어 있어야 함|비어 있을 수 있거나 $2}}",
        "api-help-param-limit": "$1 초과는 허용되지 않습니다.",
        "api-help-examples": "{{PLURAL:$1|예시}}:",
        "api-help-permissions": "{{PLURAL:$1|권한}}:",
        "api-help-permissions-granted-to": "{{PLURAL:$1|다음 그룹에 부여됨}}: $2",
+       "api-help-right-apihighlimits": "API 쿼리에서 더 높은 제한 사용 (느린 쿼리: $1, 빠른 쿼리: $2) 느린 쿼리에 대한 제한은 다중값 매개변수에도 적용됩니다.",
        "api-help-open-in-apisandbox": "<small>[연습장에서 열기]</small>",
        "api-help-authmanagerhelper-messageformat": "반환 메시지에 사용할 형식.",
-       "api-credits": "API 개발자:\n* Roan Kattouw (선임 개발자, 2007년 9월–2009년)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (초기 개발자, 선임 개발자 2006년 9월~2007년 9월)\n* Brad Jorsch (선임 개발자 2013년–현재)\n\n당신의 의견이나 제안, 질문은 mediawiki-api@lists.wikimedia.org 로 보내주시거나,\nhttps://phabricator.wikimedia.org/ 에 버그 보고를 해 주시기 바랍니다."
+       "apierror-articleexists": "작성하려는 문서가 이미 만들어져 있습니다.",
+       "apierror-badgenerator-unknown": "알 수 없는 <kbd>generator=$1</kbd>.",
+       "apierror-badip": "IP 변수가 유효하지 않습니다.",
+       "apierror-badmodule-nosubmodules": "<kbd>$1</kbd> 모듈은 하위 모듈이 없습니다.",
+       "apierror-badquery": "유효하지 않은 쿼리입니다.",
+       "apierror-badtoken": "잘못된 CSRF 토큰.",
+       "apierror-botsnotsupported": "이 인터페이스는 봇을 위해 지원되지 않습니다.",
+       "apierror-cannotviewtitle": "$1을(를) 볼 권한이 없습니다.",
+       "apierror-cantimport-upload": "업로드된 페이지를 가져올 권한이 없습니다.",
+       "apierror-databaseerror": "[$1] 데이터베이스 쿼리 오류.",
+       "apierror-filedoesnotexist": "파일이 존재하지 않습니다.",
+       "apierror-filenopath": "로컬 파일 경로를 가져올 수 없습니다.",
+       "apierror-invalidcategory": "입력한 분류 이름이 올바르지 않습니다.",
+       "apierror-invalid-file-key": "유효한 파일 키가 아닙니다.",
+       "apierror-invalidtitle": "잘못된 제목 \"$1\".",
+       "apierror-invaliduser": "잘못된 사용자 이름 \"$1\".",
+       "apierror-missingparam": "<var>$1</var> 변수는 설정해야 합니다.",
+       "apierror-missingtitle": "지정한 페이지가 존재하지 않습니다.",
+       "apierror-missingtitle-byname": "$1 문서가 존재하지 않습니다.",
+       "apierror-mustbeloggedin-generic": "로그인해야 합니다.",
+       "apierror-mustbeloggedin-linkaccounts": "계정을 연결하려면 로그인해야 합니다.",
+       "apierror-mustbeloggedin": "$1에 로그인해야 합니다.",
+       "apierror-noedit-anon": "익명 사용자는 문서를 편집할 수 없습니다.",
+       "apierror-readonly": "위키는 현재 읽기 전용 모드입니다.",
+       "apierror-revwrongpage": "r$1은(는) $2의 판이 아닙니다.",
+       "apierror-unknownerror-nocode": "알 수 없는 오류.",
+       "apierror-unknownerror": "알 수 없는 오류: \"$1\"",
+       "apierror-writeapidenied": "API를 통해 이 위키를 편집할 권한이 없습니다.",
+       "apiwarn-difftohidden": "r$1에 대한 차이를 만들 수 없습니다: 내용이 숨겨져 있습니다.",
+       "apiwarn-invalidcategory": "\"$1\"은(는) 분류가 아닙니다.",
+       "apiwarn-invalidtitle": "\"$1\"은(는) 올바른 제목이 아닙니다.",
+       "apiwarn-notfile": "\"$1\"은(는) 파일이 아닙니다.",
+       "api-feed-error-title": "오류 ($1)",
+       "api-credits": "API 개발자:\n* Yuri Astrakhan (만든이, 선임 개발자 2006년 9월~2007년 9월)\n* Roan Kattouw (선임 개발자, 2007년 9월–2009년)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Brad Jorsch (선임 개발자 2013년–현재)\n\n당신의 의견이나 제안, 질문은 mediawiki-api@lists.wikimedia.org 로 보내주시고,\n버그 보고는 https://phabricator.wikimedia.org/ 에 해주시기 바랍니다."
 }
index 47b79ab..7d5d0e8 100644 (file)
        "api-help-param-type-user": "Typ: {{PLURAL:$1|1=Benotzernumm|2=Lëscht vu Benotzernimm}}",
        "api-help-examples": "{{PLURAL:$1|Beispill|Beispiler}}:",
        "api-help-permissions": "{{PLURAL:$1|Autorisatioun|Autorisatiounen}}:",
-       "api-help-open-in-apisandbox": "<small>[an der Sandkëscht opmaachen]</small>"
+       "api-help-open-in-apisandbox": "<small>[an der Sandkëscht opmaachen]</small>",
+       "apierror-articleexists": "Den Artikel deen dir probéiert hutt unzeleeë gouf schonn ugeluecht.",
+       "apierror-autoblocked": "Är IP-Adress gouf automatesch gespaart well se vun engem gespaarte Benotzer benotzt gouf.",
+       "apierror-copyuploadbadurl": "D'Eroplueden ass vun dëser URL net erlaabt.",
+       "apierror-import-unknownerror": "Onbekannte Feeler beim Import: $1\nf",
+       "apierror-invalidtitle": "Schlechten Titel \"$1\".",
+       "apierror-missingtitle": "D'Säit déi Dir spezifizéiert hutt gëtt et net.",
+       "apierror-missingtitle-byname": "D'Säit $1 gëtt et net.",
+       "apierror-unknownerror-nocode": "Onbekannte Feeler.",
+       "apierror-writeapidenied": "Dir däerft dës Wiki net iwwer den API ännneren.",
+       "apiwarn-invalidcategory": "\"$1\" ass keng Kategorie.",
+       "apiwarn-invalidtitle": "\"$1\" ass kee valabelen Titel",
+       "apiwarn-tokennotallowed": "Aktioun \"$1\" ass net erlaabt fir den aktuelle Benotzer.",
+       "apiwarn-validationfailed-badpref": "keng valabel Astellung",
+       "api-feed-error-title": "Feeler ($1)"
 }
index 5ea8613..45680f4 100644 (file)
        "apihelp-feedrecentchanges-param-hidecategorization": "Ascondi e variaçioin d'apartegninça a-e categorie.",
        "apihelp-feedrecentchanges-param-tagfilter": "Filtra pe etichetta.",
        "apihelp-feedrecentchanges-param-target": "Mostra solo e modifiche a-e paggine collegæ da questa paggina.",
-       "apihelp-feedrecentchanges-param-showlinkedto": "Fanni védde sôlo i cangiaménti a-e pàggine colegæ a-a quella speçificâ",
+       "apihelp-feedrecentchanges-param-showlinkedto": "Fanni védde sôlo i cangiaménti a-e pàggine conligæ a-a quella speçificâ",
        "apihelp-feedrecentchanges-param-categories": "Mostra solo e variaçioin in sce-e paggine de tutte queste categorie.",
        "apihelp-feedrecentchanges-param-categories_any": "Mostra invece solo e variaçioin in sce-e paggine inte 'na qualonque categoria.",
        "apihelp-feedrecentchanges-example-simple": "Mostra i urtime modiffiche.",
        "apihelp-import-param-namespace": "Importa inte questo namespace. O no poeu ese doeuviou insemme a <var>$1rootpage</var>.",
        "apihelp-import-param-rootpage": "Importa comme sottopaggina de questa paggina. O no poeu ese doeuviou insemme a <var>$1namespace</var>.",
        "apihelp-import-example-import": "Importa [[meta:Help:ParserFunctions]] into namespace 100 con cronologia completa.",
-       "apihelp-linkaccount-description": "Colegamento de 'n'utença de 'n provider de terçe parte a l'utente corente.",
+       "apihelp-linkaccount-description": "Conligamento de 'n'utença de 'n provider de terçe parte a l'utente corente.",
        "apihelp-linkaccount-example-link": "Avvia o processo de collegamento a 'n'utença da <kbd>Example</kbd>.",
        "apihelp-login-description": "Accedi e otegni i cookie d'aotenticaçion.\n\nQuest'açion dev'ese doeuviâ escluxivamente in combinaçion con [[Special:BotPasswords]]; doeuviâla pe l'accesso a l'account prinçipâ o l'è deprecou e o poeu fallî sença preaviso. Pe acedere in moddo seguo a l'utença prinçipâ, doeuvia <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
        "apihelp-login-description-nobotpasswords": "Accedi e otegni i cookies d'aotenticaçion.\n\nQuest'açion a l'è deprecâ e a poeu fallî sença preaviso. Pe acede in moddo seguo, doeuvia [[Special:ApiHelp/clientlogin|action=clientlogin]].",
index 8240e08..b1a2280 100644 (file)
        "apihelp-phpfm-description": "Давај го изводот во серијализиран PHP-формат (подобрен испис во HTML).",
        "apihelp-rawfm-description": "Давај го изводот со елементи за отстранување грешки во JSON-формат (подобрен испис во HTML).",
        "apihelp-xml-description": "Давај го изводот во XML-формат.",
-       "apihelp-xml-param-xslt": "Ако е укажано, ја додава именуваната страница како XSL-стилска страница. Вредноста мора да биде наслов во именскиот простор „{{ns:mediawiki}}“ што ќе завршува со <code>.xsl</code>.",
+       "apihelp-xml-param-xslt": "Ако е укажано, ја додава именуваната страница како XSL-стилска страница. Вредноста мора да биде наслов во именскиот простор „{{ns:MediaWiki}}“ што ќе завршува со <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "Ако е укажано, додава именски простор XML.",
        "apihelp-xmlfm-description": "Давај го изводот во XML-формат (подобрен испис во HTML).",
        "api-format-title": "Резултат од Извршникот на МедијаВики",
index 47488c0..8ebf223 100644 (file)
@@ -3,23 +3,47 @@
                "authors": [
                        "Jeblad",
                        "Chameleon222",
-                       "Macofe"
+                       "Macofe",
+                       "Jon Harald Søby",
+                       "Event",
+                       "Kingu"
                ]
        },
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Dokumentasjon]]\n* [[mw:API:FAQ|Ofte stilte spørsmål]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-post-liste]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-kunngjøringer]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Feil & forespørsler]\n</div>\n<strong>Status:</strong> Alle funksjonene som vises på denne siden skal virke, men API-en er fortsatt i aktiv utvikling, og kan bli endret når som helst. Abonner på [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ MediaWiki sin API-kunnkjøringsepostliste] for nyheter om oppdateringer.\n\n<strong>Feile kall:</strong> Hvis det blir sendt feile kall til API-et, blir det sendt en HTTP-header med nøkkelen \"MediaWiki-API-Error\" og da blir både header-verdien og feilkoden sendt tilbake med samme verdi. For mer informasjon se [[mw:API:Errors_and_warnings|API: Feil og advarsler]].\n\n<strong>Testing:</strong> For enkelt å teste API-kall, se [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Hvilken handling skal utføres",
        "apihelp-main-param-format": "Resultatets format.",
+       "apihelp-main-param-assert": "Verifiser at brukeren er logget inn om satt til <kbd>user</kbd>, eller har botrettighet om satt til <kbd>bot</kbd>.",
+       "apihelp-main-param-assertuser": "Verifiser at den nåværende brukeren er den navngitte brukeren.",
+       "apihelp-main-param-requestid": "En gitt verdi her vil inkluderes i responsen. Kan brukes til å skille forespørsler fra hverandre.",
        "apihelp-main-param-servedby": "Inkluder navnet på tjeneren som utførte forespørselen i resultatene.",
        "apihelp-main-param-curtimestamp": "Inkluder det nåværende tidsmerket i resultatet.",
+       "apihelp-main-param-uselang": "Språk å bruke for meldingsoversettelser. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> med <kbd>siprop=languages</kbd> returnerer en liste over språkkoder, eller spesifiser <kbd>user</kbd> for å bruke den nåværende brukerens språkpreferanser, eller spesifiser <kbd>content</kbd> for å bruke denne wikiens innholdsspråk.",
        "apihelp-block-description": "Blokker en bruker.",
        "apihelp-block-param-user": "Brukernavn, IP-adresse eller IP-intervall som skal blokkeres.",
+       "apihelp-block-param-expiry": "Utløpstid. Kan være relativ (f.eks. <kbd>5 months</kbd> eller <kbd>2 weeks</kbd>) eller absolutt (f.eks. <kbd>2014-09-18T12:34:56Z</kbd>). Om den er satt til <kbd>infinite</kbd>, <kbd>indefinite</kbd> eller <kbd>never</kbd> vil blokkeringen ikke ha noen utløpsdato.",
        "apihelp-block-param-reason": "Årsak for blokkering.",
        "apihelp-block-param-anononly": "Blokker bare anonyme brukere (dvs. hindre anonyme redigeringer fra denne IP-adressen).",
        "apihelp-block-param-nocreate": "Hindre kontoopprettelse.",
        "apihelp-block-param-autoblock": "Blokker automatisk sist brukte IP-adresse og alle etterfølgende IP-adresser de prøver å logge inn fra.",
        "apihelp-block-param-noemail": "Hindre brukeren å sende e-post via wikien. (Krever rettigheten <code>blockemail</code>).",
        "apihelp-block-param-hidename": "Skjul brukernavnet fra blokkeringsloggen. (Krever rettigheten <code>hideuser</code>).",
+       "apihelp-block-param-allowusertalk": "La brukeren redigere sin egen diskusjonsside (avhenger av <var>[[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>).",
+       "apihelp-block-param-reblock": "Overstyr den gamle blokkeringen om brukeren allerede er blokkert.",
+       "apihelp-block-param-watchuser": "Overvåk brukerens eller IP-adressas bruker- og brukerdiskusjonssider.",
+       "apihelp-block-example-ip-simple": "Blokker adressa <kbd>192.0.2.5</kbd> i tre dager med årsak <kbd>First strike</kbd>.",
+       "apihelp-block-example-user-complex": "Blokker brukeren <kbd>Vandal</kbd> på ubestemnt tid med årsak <kbd>Vandalism</kbd>, og forhindre ny kontooppretting og sending av epost.",
+       "apihelp-changeauthenticationdata-description": "Endre autentiseringsdata for den nåværende brukeren.",
+       "apihelp-changeauthenticationdata-example-password": "Forsøk å endre den nåværende brukerens passord til <kbd>ExamplePassword</kbd>.",
+       "apihelp-checktoken-description": "Sjekk gyldigheten til et tegn fra <kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>.",
+       "apihelp-checktoken-param-type": "Type tegn som testes.",
+       "apihelp-checktoken-param-token": "Tegn å teste.",
+       "apihelp-checktoken-param-maxtokenage": "Maksimalt tillatt alder på tegnet, i sekunder.",
+       "apihelp-checktoken-example-simple": "Test gyldigheten til et <kbd>csrf</kbd>-tegn.",
        "apihelp-clearhasmsg-description": "Fjerner <code>hasmsg</code>-flagget for den aktuelle brukeren.",
        "apihelp-clearhasmsg-example-1": "Fjern <code>hasmsg</code>-flagget for aktuell bruker.",
+       "apihelp-clientlogin-description": "Logg inn på wikien med den interaktive flyten.",
+       "apihelp-clientlogin-example-login": "Start prosessen med å logge inn til wikien som bruker <kbd>Example</kbd> med passord <kbd>ExamplePassword</kbd>.",
+       "apihelp-clientlogin-example-login2": "Fortsett å logge inn etter en <samp>UI</samp>-respons for tofaktor-autentisering, ved å oppgi en <var>OATHToken</var> på <kbd>987654</kbd>.",
        "apihelp-compare-description": "Hent forskjellen mellom to sider.\n\nEt revisjonsnummer, en sidetittel eller en side-ID for både «fra» og «til» må sendes.",
        "apihelp-compare-param-fromtitle": "Første tittel å sammenligne.",
        "apihelp-compare-param-fromid": "Første side-ID å sammenligne.",
        "apihelp-compare-param-torev": "Andre revisjon å sammenligne.",
        "apihelp-compare-example-1": "Lag en diff mellom revisjon 1 og 2.",
        "apihelp-createaccount-description": "Opprett en ny brukerkonto.",
+       "apihelp-createaccount-param-preservestate": "Om <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> returnerte true for <samp>hashprimarypreservedstate</samp> bør forespørsler merket som <samp>primary-required</samp> omgås. Om den returnerte en ikke-tom verdi for <samp>preservedusername</samp> kan det brukernavnet brukes for <var>username</var>-parameteren.",
+       "apihelp-createaccount-example-create": "Start prosessen med å opprette brukeren <kbd>Example</kbd> med passordet <kbd>ExamplePassword</kbd>.",
        "apihelp-createaccount-param-name": "Brukernavn.",
        "apihelp-createaccount-param-password": "Passord (ignorert dersom <var>$1mailpassword</var> er satt).",
        "apihelp-createaccount-param-domain": "Domene for ekstern autentisering (valgfritt).",
+       "apihelp-createaccount-param-token": "Kontoopprettingstegn som hentet i den første forespørselen.",
        "apihelp-createaccount-param-email": "Brukerens e-postadresse (valgfritt).",
        "apihelp-createaccount-param-realname": "Brukerens virkelige navn (valgfritt).",
        "apihelp-createaccount-param-mailpassword": "Dersom satt til en verdi vil et tilfeldig passord bli sendt med e-post til brukeren.",
        "apihelp-createaccount-param-language": "Språkkode å bruke som standard for brukeren (valgfritt, standardverdien er innholdsspråket).",
        "apihelp-createaccount-example-pass": "Opprett bruker <kbd>testuser</kbd> med passordet <kbd>test123</kbd>.",
        "apihelp-createaccount-example-mail": "Opprett bruker <kbd>testmailuser</kbd> og send et tilfeldig generert passord med e-post.",
+       "apihelp-cspreport-description": "Brukes av nettlesere for å rapportere brudd på Content Security Policy. Denne modulen bør aldri brukes utenom av en CSP-mottakelig nettleser.",
        "apihelp-delete-description": "Slett en side.",
        "apihelp-delete-param-title": "Tittel til siden som skal slettes. Kan ikke brukes sammen med <var>$1pageid</var>.",
        "apihelp-delete-param-pageid": "Side-ID til siden som skal slettes. Kan ikke brukes sammen med <var>$1title</var>.",
        "apihelp-delete-param-reason": "Årsak for slettingen. Dersom ikke satt vil en automatisk generert årsak bli brukt.",
+       "apihelp-delete-param-tags": "Endringstagger å legge til oppslaget i slettingsloggen.",
        "apihelp-delete-param-watch": "Legg til siden til aktuell brukers overvåkningsliste.",
        "apihelp-delete-param-unwatch": "Fjern siden fra aktuell brukers overvåkningsliste.",
+       "apihelp-delete-param-oldimage": "Navnet på det gamle bildet som skal slettes som oppgitt av [[Special:ApiHelp/query+imageinfo|action=query&prop=imageinfo&iiprop=archivename]].",
        "apihelp-delete-example-simple": "Slett <kbd>Main Page</kbd>.",
        "apihelp-delete-example-reason": "Slett <kbd>Main Page</kbd> med grunnen <kbd>Preparing for move</kbd>.",
        "apihelp-disabled-description": "Denne modulen har blitt deaktivert",
        "apihelp-edit-param-section": "Avsnittsnummer. <kbd>0</kbd> for det øverste avsnittet, <kbd>new</kbd> for et nytt avsnitt.",
        "apihelp-edit-param-sectiontitle": "Tittelen for et nytt avsnitt.",
        "apihelp-edit-param-text": "Sideinnhold.",
+       "apihelp-edit-param-summary": "Redigeringssammendrag. Også seksjonstittel når $1section=new og $1sectiontitle ikke er satt.",
+       "apihelp-edit-param-tags": "Endringstagger som skal brukes på revisjonen.",
        "apihelp-edit-param-minor": "Mindre redigering.",
+       "apihelp-edit-param-notminor": "Ikke mindre redigering.",
        "apihelp-edit-param-bot": "Merk denne redigeringen som en botendring.",
+       "apihelp-edit-param-basetimestamp": "Tidsstempel for grunnrevisjonen, brukes for å oppdage redigeringskonflikter. Kan hentes via [[Special.ApiHelp/query+revisions|action=query&prop=revisions&rvprop=timestamp]].",
+       "apihelp-edit-param-starttimestamp": "Tidsstempel for når redigeringsprosessen begynte, brukes for å oppdage redigeringskonflikter. En gyldig verdi kan hentes med <var>[[Special:ApiHelp/main|curtimestamp]]</var> når man begynner en redigeringsprosess (f.eks. når man laster sideinnholdet som redigeres).",
+       "apihelp-edit-param-recreate": "Overstyr feil om at siden har blitt slettet i mellomtiden.",
        "apihelp-edit-param-createonly": "Ikke rediger siden dersom den finnes allerede.",
        "apihelp-edit-param-nocreate": "Gi en feilmelding dersom dersom siden ikke finnes.",
        "apihelp-edit-param-watch": "Legg til siden til aktuell brukers overvåkningsliste.",
        "apihelp-logout-description": "Logg ut og fjern sesjonsdata.",
        "apihelp-logout-example-logout": "Logg ut den aktuelle brukeren.",
        "apihelp-move-description": "Flytt en side.",
-       "apihelp-dbg-description": "Resultatdata i PHP's var_export() format.",
-       "apihelp-dbgfm-description": "Resultatdata i PHP's var_export() format (pen utskrift i HTML).",
        "apihelp-json-description": "Resultatdata i JSON-format.",
        "apihelp-none-description": "Ingen resultat.",
        "api-help-flag-readrights": "Denne modulen krever lesetilgang.",
        "api-help-flag-generator": "Denne modulen kan brukes som en generator.",
        "api-help-parameters": "{{PLURAL:$1|Parameter|Parametre}}:",
        "api-help-param-deprecated": "Utgått.",
-       "api-help-param-required": "Denne parameteren er påkrevd."
+       "api-help-param-required": "Denne parameteren er påkrevd.",
+       "apierror-multival-only-one": "Bare én verdi er tillatt for parameteret <var>$1</var>.",
+       "apierror-permissiondenied-generic": "Tilgang nektet.",
+       "apiwarn-validationfailed": "Bekreftelsesfeil <kbd>$1</kbd>: $2"
 }
index 89e2b21..ac2c8b7 100644 (file)
@@ -61,7 +61,7 @@
        "apihelp-edit-param-tags": "Wijzigingslabels om aan de versie toe te voegen.",
        "apihelp-edit-param-minor": "Kleine bewerking.",
        "apihelp-edit-param-notminor": "Geen kleine bewerking.",
-       "apihelp-edit-param-bot": "Deze bewerking als bot markeren.",
+       "apihelp-edit-param-bot": "Deze bewerking markeren als gedaan door een robot.",
        "apihelp-edit-param-createonly": "De pagina niet bewerken als die al bestaat.",
        "apihelp-edit-param-nocreate": "Een foutmelding geven als de pagina niet bestaat.",
        "apihelp-edit-param-watch": "Voeg de pagina toe aan de volglijst van de huidige gebruiker.",
index 4c31ca8..573c3f8 100644 (file)
        "api-help-param-integer-minmax": "{{PLURAL:$1|1=Wartość musi|2=Wartości muszą}} być pomiędzy $2 a $3.",
        "api-help-param-multi-separate": "Oddziel wartości za pomocą <kbd>|</kbd> lub [[Special:ApiHelp/main#main/datatypes|alternatywy]].",
        "api-help-param-multi-max": "Maksymalna liczba wartości to {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} dla botów).",
+       "api-help-param-multi-all": "Aby wskazać wszystkie wartości, użyj <kbd>$1</kbd>.",
        "api-help-param-default": "Domyślnie: $1",
        "api-help-param-default-empty": "Domyślnie: <span class=\"apihelp-empty\">(puste)</span>",
        "api-help-param-token": "Token \"$1\" zdobyty z [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
        "api-help-permissions-granted-to": "{{PLURAL:$1|Przydzielone dla}}: $2",
        "api-help-right-apihighlimits": "Użyj wyższych limitów w zapytaniach API (dla zapytań powolnych: $1; dla zapytań szbkich: $2). Limity zapytań powolnych są także stosowane dla parametrów z podanymi wieloma wartościami.",
        "api-help-open-in-apisandbox": "<small>[otwórz w brudnopisie]</small>",
+       "apierror-badgenerator-unknown": "Nieznany <kbd>generator=$1</kbd>.",
+       "apierror-badip": "Parametr IP nie jest prawidłowy.",
+       "apierror-badquery": "Nieprawidłowe zapytanie.",
+       "apierror-blockedfrommail": "Została Ci zablokowana możliwość wysyłania e-maili.",
+       "apierror-blocked": "Została Ci zablokowana możliwość edycji.",
+       "apierror-cantblock": "Nie masz uprawnień do blokowania użytkowników.",
+       "apierror-cantimport": "Nie masz uprawnień do importowania stron.",
+       "apierror-cantsend": "Nie jesteś zalogowany, nie masz potwierdzonego adresu e-mail, albo nie masz prawa wysyłać e-maili do innych użytkowników, więc nie możesz wysłać wiadomości e-mail.",
+       "apierror-filedoesnotexist": "Plik nie istnieje.",
+       "apierror-integeroutofrange-abovebotmax": "Wartość <var>$1</var> dla botów i administratorów nie może przekraczać $2 (ustawiono $3).",
+       "apierror-integeroutofrange-abovemax": "Wartość <var>$1</var> dla użytkowników nie może przekraczać $2 (ustawiono $3).",
+       "apierror-integeroutofrange-belowminimum": "Wartość <var>$1</var> nie może być mniejsza niż $2 (ustawiono $3).",
+       "apierror-invalidlang": "Nieprawidłowy kod języka dla parametru <var>$1</var>.",
+       "apierror-invalidparammix": "{{PLURAL:$2|Parametry}} $1 nie mogą być używane razem.",
+       "apierror-invalidtitle": "Zły tytuł „$1”.",
+       "apierror-invalidurlparam": "Nieprawidłowa wartość <var>$1urlparam</var> (<kbd>$2=$3</kbd>).",
+       "apierror-missingparam": "Parametr <var>$1</var> musi być podany.",
+       "apierror-missingtitle": "Wybrana przez ciebie strona nie istnieje.",
+       "apierror-missingtitle-byname": "Strona $1 nie istnieje.",
+       "apierror-moduledisabled": "Moduł <kbd>$1</kbd> został wyłączony.",
+       "apierror-mustbeloggedin-generic": "Musisz być zalogowany.",
+       "apierror-noedit-anon": "Niezarejestrowani użytkownicy nie mogą edytować stron.",
+       "apierror-noedit": "Nie masz uprawnień do edytowania stron.",
+       "apierror-permissiondenied": "Nie masz uprawnień do $1.",
+       "apierror-permissiondenied-generic": "Brak dostępu.",
+       "apierror-permissiondenied-unblock": "Nie masz uprawnień do odblokowania użytkowników.",
+       "apierror-protect-invalidaction": "Nieprawidłowy rodzaj zabezpieczenia „$1”.",
+       "apierror-protect-invalidlevel": "Nieprawidłowy poziom zabezpieczeń „$1”.",
+       "apierror-specialpage-cantexecute": "Nie masz uprawnień, aby zobaczyć wyniki tej strony specjalnej.",
+       "apierror-stashwrongowner": "Nieprawidłowy właściciel: $1",
+       "apierror-unknownerror-nocode": "Nieznany błąd.",
+       "apierror-unknownerror": "Nieznany błąd: „$1”.",
+       "apierror-unknownformat": "Nierozpoznany format „$1”.",
+       "apierror-unrecognizedvalue": "Nierozpoznana wartość parametru <var>$1</var>: $2.",
+       "apiwarn-invalidcategory": "„$1” nie jest kategorią.",
+       "apiwarn-invalidtitle": "„$1” nie jest poprawnym tytułem.",
+       "apiwarn-notfile": "„$1” nie jest plikiem.",
+       "api-feed-error-title": "Błąd ($1)",
+       "api-exception-trace": "$1 w $2($3)\n$4",
        "api-credits-header": "Twórcy",
        "api-credits": "Deweloperzy API:\n* Roan Kattouw (główny programista wrzesień 2007–2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (twórca, główny programista wrzesień 2006–wrzesień 2007)\n* Brad Jorsch (główny programista 2013–obecnie)\n\nProsimy wysyłać komentarze, sugestie i pytania do mediawiki-api@lists.wikimedia.org\nlub zgłoś błąd na https://phabricator.wikimedia.org/."
 }
index 709230a..e8980f5 100644 (file)
        "apihelp-query+allmessages-param-prop": "As propriedades a serem obtidas:",
        "apihelp-query+allmessages-param-enableparser": "Definir, para ativar o analisador sintático e pré-processar o texto da mensagem com notação wiki (substituir palavras mágicas, processar predefinições, etc.).",
        "apihelp-query+allmessages-param-nocontent": "Se definido, não incluir o conteúdo das mensagens no resultado de saída.",
-       "apihelp-query+allmessages-param-includelocal": "Incluir também as mensagens locais, isto é, mensagens que não existem no software mas existem como uma página no espaço nominal MediaWiki:.\nIsto lista todas as páginas do espaço nominal MediaWiki:, portanto, também irá listar aquelas que não são verdadeiramente mensagens, como [[MediaWiki:Common.js|Common.js]].",
+       "apihelp-query+allmessages-param-includelocal": "Incluir também as mensagens locais, isto é, mensagens que não existem no software mas existem como uma página no espaço nominal {{ns:MediaWiki}}.\nIsto lista todas as páginas do espaço nominal {{ns:MediaWiki}}, portanto, também irá listar aquelas que não são verdadeiramente mensagens, como [[MediaWiki:Common.js|Common.js]].",
        "apihelp-query+allmessages-param-args": "Os argumentos a serem substituídos na mensagem.",
        "apihelp-query+allmessages-param-filter": "Devolver só as mensagens cujos nomes contêm este texto.",
        "apihelp-query+allmessages-param-customised": "Devolver só as mensagens neste estado de personalização.",
        "apihelp-resetpassword-description-noroutes": "Não estão disponíveis rotas de reinício da palavra-passe.\n\nPara usar este módulo, ative uma rota em <var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var>.",
        "apihelp-resetpassword-param-user": "O utilizar cuja palavra-passe será reiniciada.",
        "apihelp-resetpassword-param-email": "O correio eletrónico do utilizador cuja palavra-passe será reiniciada.",
-       "apihelp-resetpassword-param-capture": "Devolver as palavras-passe temporárias que foram enviadas. Requer a permissão <code>passwordreset</code>.",
        "apihelp-resetpassword-example-user": "Enviar uma mensagem eletrónica para reinício da palavra-passe ao utilizador <kbd>Example</kbd>.",
        "apihelp-resetpassword-example-email": "Enviar uma mensagem eletrónica para reinício da palavra-passe a todos os utilizadores com o correio eletrónico <kbd>user@example.com</kbd>.",
        "apihelp-revisiondelete-description": "Eliminar e restaurar revisões.",
        "apihelp-phpfm-description": "Produzir os dados de saída em formato PHP seriado (realce sintático em HTML).",
        "apihelp-rawfm-description": "Produzir os dados de saída, incluindo elementos para despiste de erros, em formato JSON (realce sintático em HTML).",
        "apihelp-xml-description": "Produzir os dados de saída em formato XML.",
-       "apihelp-xml-param-xslt": "Se especificado, adiciona a página nomeada como uma folha de estilo XSL. O valor tem de ser um título no espaço nominal {{ns:mediawiki}} e acabar em <code>.xsl</code>.",
+       "apihelp-xml-param-xslt": "Se especificado, adiciona a página nomeada como uma folha de estilo XSL. O valor tem de ser um título no espaço nominal {{ns:MediaWiki}} e acabar em <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "Se especificado, adiciona um espaço nominal XML.",
        "apihelp-xmlfm-description": "Produzir os dados de saída em formato XML (realce sintático em HTML).",
        "api-format-title": "Resultado da API do MediaWiki.",
        "api-help-param-upload": "Tem ser enviado (''posted'') como um carregamento de ficheiro usando multipart/form-data.",
        "api-help-param-multi-separate": "Separar os valores com <kbd>|</kbd> ou [[Special:ApiHelp/main#main/datatypes|alternativas]].",
        "api-help-param-multi-max": "O número máximo de valores é {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} para robôs).",
+       "api-help-param-multi-all": "Para especificar todos os valores, use <kbd>$1</kbd>.",
        "api-help-param-default": "Valor por omissão: $1",
        "api-help-param-default-empty": "Padrão: <span class=\"apihelp-empty\">(vazio)</span>",
        "api-help-param-token": "Uma chave \"$1\" obtida de [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
index f7c750e..8cf338d 100644 (file)
        "apihelp-main-param-requestid": "{{doc-apihelp-param|main|requestid}}",
        "apihelp-main-param-servedby": "{{doc-apihelp-param|main|servedby}}",
        "apihelp-main-param-curtimestamp": "{{doc-apihelp-param|main|curtimestamp}}",
+       "apihelp-main-param-responselanginfo": "{{doc-apihelp-param|main|responselanginfo}}",
        "apihelp-main-param-origin": "{{doc-apihelp-param|main|origin}}",
        "apihelp-main-param-uselang": "{{doc-apihelp-param|main|uselang}}",
+       "apihelp-main-param-errorformat": "{{doc-apihelp-param|main|errorformat}}",
+       "apihelp-main-param-errorlang": "{{doc-apihelp-param|main|errorlang}}",
+       "apihelp-main-param-errorsuselocal": "{{doc-apihelp-param|main|errorsuselocal}}",
        "apihelp-block-description": "{{doc-apihelp-description|block}}",
        "apihelp-block-param-user": "{{doc-apihelp-param|block|user}}",
        "apihelp-block-param-expiry": "{{doc-apihelp-param|block|expiry}}\n{{doc-important|Do not translate \"5 months\", \"2 weeks\", \"infinite\", \"indefinite\" or \"never\"!}}",
        "apihelp-resetpassword-description-noroutes": "{{doc-apihelp-description|resetpassword|info=This message is used when no known routes are enabled in <var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var>.|seealso={{msg-mw|apihelp-resetpassword-description}}}}",
        "apihelp-resetpassword-param-user": "{{doc-apihelp-param|resetpassword|user}}",
        "apihelp-resetpassword-param-email": "{{doc-apihelp-param|resetpassword|email}}",
-       "apihelp-resetpassword-param-capture": "{{doc-apihelp-param|resetpassword|capture}}",
        "apihelp-resetpassword-example-user": "{{doc-apihelp-example|resetpassword}}",
        "apihelp-resetpassword-example-email": "{{doc-apihelp-example|resetpassword}}",
        "apihelp-revisiondelete-description": "{{doc-apihelp-description|revisiondelete}}",
        "api-help-param-upload": "{{technical}} Used to indicate that an 'upload'-type parameter must be posted as a file upload using multipart/form-data",
        "api-help-param-multi-separate": "Used to indicate how to separate multiple values. Not used with {{msg-mw|api-help-param-list}}.",
        "api-help-param-multi-max": "Used to indicate the maximum number of values accepted for a multi-valued parameter.\n\nParameters:\n* $1 - Maximum value without the apihighlimits right\n* $2 - Maximum value with the apihighlimits right",
+       "api-help-param-multi-all": "Used to indicate what string can be used to specify all possible values of a multi-valued parameter. \n\nParameters:\n* $1 - String to specify all possible values of the parameter",
        "api-help-param-default": "Used to display the default value for an API parameter\n\nParameters:\n* $1 - Default value\n\nSee also:\n* {{msg-mw|api-help-param-default-empty}}\n{{Identical|Default}}",
        "api-help-param-default-empty": "Used to display the default value for an API parameter when that default is an empty value\n\nSee also:\n* {{msg-mw|api-help-param-default}}",
        "api-help-param-token": "{{doc-apihelp-param|description=any 'token' parameter|paramstart=2|params=\n* $1 - Token type|noseealso=1}}",
        "api-help-authmanagerhelper-returnurl": "{{doc-apihelp-param|description=the \"returnurl\" parameter for AuthManager-using API modules|noseealso=1}}",
        "api-help-authmanagerhelper-continue": "{{doc-apihelp-param|description=the \"continue\" parameter for AuthManager-using API modules|noseealso=1}}",
        "api-help-authmanagerhelper-additional-params": "Message to display for AuthManager modules that take additional parameters to populate AuthenticationRequests. Parameters:\n* $1 - AuthManager action used by this module\n* $2 - Module parameter prefix, e.g. \"login\"\n* $3 - Module name, e.g. \"clientlogin\"\n* $4 - Module path, e.g. \"clientlogin\"",
+       "apierror-allimages-redirect": "{{doc-apierror}}",
+       "apierror-allpages-generator-redirects": "{{doc-apierror}}",
+       "apierror-appendnotsupported": "{{doc-apierror}}\n\nParameters:\n* $1 - Content model",
+       "apierror-articleexists": "{{doc-apierror}}",
+       "apierror-assertbotfailed": "{{doc-apierror}}",
+       "apierror-assertnameduserfailed": "{{doc-apierror}}\n\nParameters:\n* $1 - User name passed in.",
+       "apierror-assertuserfailed": "{{doc-apierror}}",
+       "apierror-autoblocked": "{{doc-apierror}}",
+       "apierror-badconfig-resulttoosmall": "{{doc-apierror}}",
+       "apierror-badcontinue": "{{doc-apierror}}",
+       "apierror-baddiff": "{{doc-apierror}}",
+       "apierror-baddiffto": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".",
+       "apierror-badformat-generic": "{{doc-apierror}}\n\nParameters:\n* $1 - Content format.\n* $2 - Content model.",
+       "apierror-badformat": "{{doc-apierror}}\n\nParameters:\n* $1 - Content format.\n* $2 - Content model.\n* $3 - Title using the model.",
+       "apierror-badgenerator-notgenerator": "{{doc-apierror}}\n\nParameters:\n* $1 - Generator module name.",
+       "apierror-badgenerator-unknown": "{{doc-apierror}}\n\nParameters:\n* $1 - Generator module name.",
+       "apierror-badip": "{{doc-apierror}}",
+       "apierror-badmd5": "{{doc-apierror}}",
+       "apierror-badmodule-badsubmodule": "{{doc-apierror}}\n\nParameters:\n* $1 - Module path.\n* $2 - Submodule name.",
+       "apierror-badmodule-nosubmodules": "{{doc-apierror}}\n\nParameters:\n* $1 - Module path.",
+       "apierror-badparameter": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apierror-badquery": "{{doc-apierror}}",
+       "apierror-badtimestamp": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Value of the parameter.",
+       "apierror-badtoken": "{{doc-apierror}}",
+       "apierror-badupload": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apierror-badurl": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Value of the parameter.",
+       "apierror-baduser": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Value of the parameter.",
+       "apierror-badvalue-notmultivalue": "{{doc-apierror}}",
+       "apierror-bad-watchlist-token": "{{doc-apierror}}",
+       "apierror-blockedfrommail": "{{doc-apierror}}",
+       "apierror-blocked": "{{doc-apierror}}",
+       "apierror-botsnotsupported": "{{doc-apierror}}",
+       "apierror-cannotreauthenticate": "{{doc-apierror}}",
+       "apierror-cannotviewtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Title.",
+       "apierror-cantblock-email": "{{doc-apierror}}",
+       "apierror-cantblock": "{{doc-apierror}}",
+       "apierror-cantchangecontentmodel": "{{doc-apierror}}",
+       "apierror-canthide": "{{doc-apierror}}",
+       "apierror-cantimport-upload": "{{doc-apierror}}",
+       "apierror-cantimport": "{{doc-apierror}}",
+       "apierror-cantoverwrite-sharedfile": "{{doc-apierror}}",
+       "apierror-cantsend": "{{doc-apierror}}",
+       "apierror-cantundelete": "{{doc-apierror}}",
+       "apierror-changeauth-norequest": "{{doc-apierror}}",
+       "apierror-chunk-too-small": "{{doc-apierror}}\n\nParameters:\n* $1 - Minimum size in bytes.",
+       "apierror-cidrtoobroad": "{{doc-apierror}}\n\nParameters:\n* $1 - \"IPv4\" or \"IPv6\"\n* $2 - Minimum CIDR mask length.",
+       "apierror-compare-inputneeded": "{{doc-apierror}}",
+       "apierror-contentserializationexception": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text, may end with punctuation. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-contenttoobig": "{{doc-apierror}}\n\nParameters:\n* $1 - Maximum article size in kilobytes.",
+       "apierror-copyuploadbaddomain": "{{doc-apierror}}",
+       "apierror-copyuploadbadurl": "{{doc-apierror}}",
+       "apierror-create-titleexists": "{{doc-apierror}}",
+       "apierror-csp-report": "{{doc-apierror}}\n\nParameters:\n* $1 - Error code, e.g. \"toobig\".",
+       "apierror-databaseerror": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception log ID code. This is meaningless to the end user, but can be used by people with access to the logs to easily find the logged error.",
+       "apierror-deletedrevs-param-not-1-2": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n\nSee also:\n* {{msg-mw|apihelp-query+deletedrevs-description}}",
+       "apierror-deletedrevs-param-not-3": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n\nSee also:\n* {{msg-mw|apihelp-query+deletedrevs-description}}",
+       "apierror-emptynewsection": "{{doc-apierror}}",
+       "apierror-emptypage": "{{doc-apierror}}",
+       "apierror-exceptioncaught": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception log ID code. This is meaningless to the end user, but can be used by people with access to the logs to easily find the logged error.\n* $2 - Exception message, which may end with punctuation. Probably in English.",
+       "apierror-filedoesnotexist": "{{doc-apierror}}",
+       "apierror-fileexists-sharedrepo-perm": "{{doc-apierror}}",
+       "apierror-filenopath": "{{doc-apierror}}",
+       "apierror-filetypecannotberotated": "{{doc-apierror}}",
+       "apierror-formatphp": "{{doc-apierror}}",
+       "apierror-imageusage-badtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Module name.",
+       "apierror-import-unknownerror": "{{doc-apierror}}\n\nParameters:\n* $1 - Error message returned by the import, probably in English.",
+       "apierror-integeroutofrange-abovebotmax": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name\n* $2 - Maximum allowed value\n* $3 - Supplied value",
+       "apierror-integeroutofrange-abovemax": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name\n* $2 - Maximum allowed value\n* $3 - Supplied value",
+       "apierror-integeroutofrange-belowminimum": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name\n* $2 - Minimum allowed value\n* $3 - Supplied value",
+       "apierror-invalidcategory": "{{doc-apierror}}",
+       "apierror-invalid-chunk": "{{doc-apierror}}",
+       "apierror-invalidexpiry": "{{doc-apierror}}\n\nParameters:\n* $1 - Value provided.",
+       "apierror-invalid-file-key": "{{doc-apierror}}",
+       "apierror-invalidlang": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apierror-invalidoldimage": "{{doc-apierror}}",
+       "apierror-invalidparammix-cannotusewith": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name or \"parameter=value\" text.\n* $2 - Parameter name or \"parameter=value\" text.",
+       "apierror-invalidparammix-mustusewith": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name or \"parameter=value\" text.\n* $2 - Parameter name or \"parameter=value\" text.",
+       "apierror-invalidparammix-parse-new-section": "{{doc-apierror}}",
+       "apierror-invalidparammix": "{{doc-apierror}}\n\nParameters:\n* $1 - List of parameter names or \"parameter=value\" text.\n* $2 - Number of parameters.",
+       "apierror-invalidsection": "{{doc-apierror}}",
+       "apierror-invalidsha1base36hash": "{{doc-apierror}}",
+       "apierror-invalidsha1hash": "{{doc-apierror}}",
+       "apierror-invalidtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Title that is invalid",
+       "apierror-invalidurlparam": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".\n* $2 - Key\n* $3 - Value.",
+       "apierror-invaliduser": "{{doc-apierror}}\n\nParameters:\n* $1 - User name that is invalid.",
+       "apierror-maxlag-generic": "{{doc-apierror}}\n\nParameters:\n* $1 - Database is lag in seconds.",
+       "apierror-maxlag": "{{doc-apierror}}\n\nParameters:\n* $1 - Database lag in seconds.\n* $2 - Database server that is lagged.",
+       "apierror-mimesearchdisabled": "{{doc-apierror}}",
+       "apierror-missingcontent-pageid": "{{doc-apierror}}\n\nParameters:\n* $1 - Page ID number.",
+       "apierror-missingparam-at-least-one-of": "{{doc-apierror}}\n\nParameters:\n* $1 - List of parameter names.\n* $2 - Number of parameters.",
+       "apierror-missingparam-one-of": "{{doc-apierror}}\n\nParameters:\n* $1 - List of parameter names.\n* $2 - Number of parameters.",
+       "apierror-missingparam": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apierror-missingrev-pageid": "{{doc-apierror}}\n\nParameters:\n* $1 - Page ID number.",
+       "apierror-missingtitle-createonly": "{{doc-apierror}}",
+       "apierror-missingtitle": "{{doc-apierror}}",
+       "apierror-missingtitle-byname": "{{doc-apierror}}",
+       "apierror-moduledisabled": "{{doc-apierror}}\n\nParameters:\n* $1 - Name of the module.",
+       "apierror-multival-only-one-of": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Possible values for the parameter.\n* $3 - Number of values.",
+       "apierror-multival-only-one": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apierror-multpages": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name",
+       "apierror-mustbeloggedin-changeauth": "{{doc-apierror}}",
+       "apierror-mustbeloggedin-generic": "{{doc-apierror}}",
+       "apierror-mustbeloggedin-linkaccounts": "{{doc-apierror}}",
+       "apierror-mustbeloggedin-removeauth": "{{doc-apierror}}",
+       "apierror-mustbeloggedin-uploadstash": "{{doc-apierror}}",
+       "apierror-mustbeloggedin": "{{doc-apierror}}\n\nParameters:\n* $1 - One of the action-* messages (for example {{msg-mw|action-edit}}) or other such messages tagged with {{tl|doc-action}} in their documentation\n\nPlease report at [[Support]] if you are unable to properly translate this message. Also see [[phab:T16246]] (now closed) for background.\n\nSee also:\n* {{msg-mw|apierror-permissiondenied}}\n* {{msg-mw|permissionserrorstext-withaction}}",
+       "apierror-mustbeposted": "{{doc-apierror}}\n\nParameters:\n* $1 - Module name.",
+       "apierror-mustpostparams": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter names.\n* $2 - Number of parameters.",
+       "apierror-noapiwrite": "{{doc-apierror}}",
+       "apierror-nochanges": "{{doc-apierror}}",
+       "apierror-nodeleteablefile": "{{doc-apierror}}",
+       "apierror-no-direct-editing": "{{doc-apierror}}\n\nParameters:\n* $1 - Content model.\n* $2 - Title using the model.",
+       "apierror-noedit-anon": "{{doc-apierror}}",
+       "apierror-noedit": "{{doc-apierror}}",
+       "apierror-noimageredirect-anon": "{{doc-apierror}}",
+       "apierror-noimageredirect": "{{doc-apierror}}",
+       "apierror-nosuchlogid": "{{doc-apierror}}\n\nParameters:\n* $1 - Log ID number.",
+       "apierror-nosuchpageid": "{{doc-apierror}}\n\nParameters:\n* $1 - Page ID number.",
+       "apierror-nosuchrcid": "{{doc-apierror}}\n\nParameters:\n* $1 - RecentChanges ID number.",
+       "apierror-nosuchrevid": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.",
+       "apierror-nosuchsection": "{{doc-apierror}}\n\nParameters:\n* $1 - Section identifier. Probably a number or \"T-\" followed by a number.",
+       "apierror-nosuchsection-what": "{{doc-apierror}}\n\nParameters:\n* $1 - Section identifier. Probably a number or \"T-\" followed by a number.\n* $2 - Page title, revision ID formatted with {{msg-mw|revid}}, or page ID formatted with {{msg-mw|pageid}}.",
+       "apierror-notarget": "{{doc-apierror}}",
+       "apierror-notpatrollable": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.",
+       "apierror-nouploadmodule": "{{doc-apierror}}",
+       "apierror-opensearch-json-warnings": "{{doc-apierror}}",
+       "apierror-pagecannotexist": "{{doc-apierror}}",
+       "apierror-pagedeleted": "{{doc-apierror}}",
+       "apierror-paramempty": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apierror-parsetree-notwikitext": "{{doc-apierror}}",
+       "apierror-parsetree-notwikitext-title": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title.\n* $2 - Content model.",
+       "apierror-pastexpiry": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied expiry time.",
+       "apierror-permissiondenied": "{{doc-apierror}}\n\nParameters:\n* $1 - One of the action-* messages (for example {{msg-mw|action-edit}}) or other such messages tagged with {{tl|doc-action}} in their documentation\n\nPlease report at [[Support]] if you are unable to properly translate this message. Also see [[phab:T16246]] (now closed) for background.\n\nSee also:\n* {{msg-mw|permissionserrorstext-withaction}}",
+       "apierror-permissiondenied-generic": "{{doc-apierror}}",
+       "apierror-permissiondenied-patrolflag": "{{doc-apierror}}\n\nSee also:\n* {{msg-mw|apierror-permissiondenied}}",
+       "apierror-permissiondenied-unblock": "{{doc-apierror}}\n\nSee also:\n* {{msg-mw|apierror-permissiondenied}}",
+       "apierror-prefixsearchdisabled": "{{doc-apierror}}",
+       "apierror-promised-nonwrite-api": "{{doc-apierror}}",
+       "apierror-protect-invalidaction": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied protection type.",
+       "apierror-protect-invalidlevel": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied protection level.",
+       "apierror-ratelimited": "{{doc-apierror}}",
+       "apierror-readapidenied": "{{doc-apierror}}",
+       "apierror-readonly": "{{doc-apierror}}",
+       "apierror-reauthenticate": "{{doc-apierror}}",
+       "apierror-redirect-appendonly": "{{doc-apierror}}",
+       "apierror-revdel-mutuallyexclusive": "{{doc-apierror}}",
+       "apierror-revdel-needtarget": "{{doc-apierror}}",
+       "apierror-revdel-paramneeded": "{{doc-apierror}}",
+       "apierror-revisions-norevids": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".",
+       "apierror-revisions-singlepage": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".",
+       "apierror-revwrongpage": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.\n* $2 - Page title.",
+       "apierror-searchdisabled": "{{doc-apierror}}\n\nParameters:\n* $1 - Search parameter that is disabled.",
+       "apierror-sectionreplacefailed": "{{doc-apierror}}",
+       "apierror-sectionsnotsupported": "{{doc-apierror}}\n\nParameters:\n* $1 - Content model that doesn't support sections.",
+       "apierror-sectionsnotsupported-what": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title, revision ID formatted with {{msg-mw|revid}}, or page ID formatted with {{msg-mw|pageid}}.",
+       "apierror-show": "{{doc-apierror}}",
+       "apierror-siteinfo-includealldenied": "{{doc-apierror}}",
+       "apierror-sizediffdisabled": "{{doc-apierror}}",
+       "apierror-spamdetected": "{{doc-apierror}}\n\nParameters:\n* $1 - Matching \"spam filter\".\n\nSee also:\n* {{msg-mw|spamprotectionmatch}}",
+       "apierror-specialpage-cantexecute": "{{doc-apierror}}",
+       "apierror-stashedfilenotfound": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-stashedit-missingtext": "{{doc-apierror}}",
+       "apierror-stashfailed-complete": "{{doc-apierror}}",
+       "apierror-stashfailed-nosession": "{{doc-apierror}}",
+       "apierror-stashfilestorage": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text, which may already end with punctuation. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-stashnosuchfilekey": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-stashpathinvalid": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-stashwrongowner": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text, which should already end with punctuation. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-stashzerolength": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-templateexpansion-notwikitext": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title.\n* $2 - Content model.",
+       "apierror-toofewexpiries": "{{doc-apierror}}\n\nParameters:\n* $1 - Number provided.\n* $2 - Number needed.",
+       "apierror-unknownaction": "{{doc-apierror}}\n\nParameters:\n* $1 - Action provided.",
+       "apierror-unknownerror-editpage": "{{doc-apierror}}\n\nParameters:\n* $1 - Error code (an integer).",
+       "apierror-unknownerror-nocode": "{{doc-apierror}}",
+       "apierror-unknownerror": "{{doc-apierror}}\n\nParameters:\n* $1 - Error code (possibly a message key) not handled by ApiBase::parseMsg().",
+       "apierror-unknownformat": "{{doc-apierror}}\n\nParameters:\n* $1 - Format provided.",
+       "apierror-unrecognizedparams": "{{doc-apierror}}\n\nParameters:\n* $1 - List of parameters.\n* $2 - Number of parameters.",
+       "apierror-unrecognizedvalue": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Parameter value.",
+       "apierror-unsupportedrepo": "{{doc-apierror}}",
+       "apierror-upload-filekeyneeded": "{{doc-apierror}}",
+       "apierror-upload-filekeynotallowed": "{{doc-apierror}}",
+       "apierror-upload-inprogress": "{{doc-apierror}}",
+       "apierror-upload-missingresult": "{{doc-apierror}}",
+       "apierror-urlparamnormal": "{{doc-apierror}}\n\nParameters:\n* $1 - Image title.",
+       "apierror-writeapidenied": "{{doc-apierror}}",
+       "apiwarn-alldeletedrevisions-performance": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".",
+       "apiwarn-badurlparam": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".\n* $2 - Image title.",
+       "apiwarn-badutf8": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apiwarn-checktoken-percentencoding": "{{doc-apierror}}",
+       "apiwarn-deprecation-deletedrevs": "{{doc-apierror}}",
+       "apiwarn-deprecation-expandtemplates-prop": "{{doc-apierror}}",
+       "apiwarn-deprecation-httpsexpected": "{{doc-apierror}}",
+       "apiwarn-deprecation-login-botpw": "{{doc-apierror}}",
+       "apiwarn-deprecation-login-nobotpw": "{{doc-apierror}}",
+       "apiwarn-deprecation-login-token": "{{doc-apierror}}",
+       "apiwarn-deprecation-parameter": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apiwarn-deprecation-parse-headitems": "{{doc-apierror}}",
+       "apiwarn-deprecation-purge-get": "{{doc-apierror}}",
+       "apiwarn-deprecation-withreplacement": "{{doc-apierror}}\n\nParameters:\n* $1 - Query string fragment that is deprecated, e.g. \"action=tokens\".\n* $2 - Query string fragment to use instead, e.g. \"action=tokens\".",
+       "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.",
+       "apiwarn-errorprinterfailed": "{{doc-apierror}}",
+       "apiwarn-errorprinterfailed-ex": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception message, which may already end in punctuation. Probably in English.",
+       "apiwarn-invalidcategory": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied category name.",
+       "apiwarn-invalidtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied title.",
+       "apiwarn-invalidxmlstylesheetext": "{{doc-apierror}}",
+       "apiwarn-invalidxmlstylesheet": "{{doc-apierror}}",
+       "apiwarn-invalidxmlstylesheetns": "{{doc-apierror}}",
+       "apiwarn-moduleswithoutvars": "{{doc-apierror}}",
+       "apiwarn-notfile": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied file name.",
+       "apiwarn-nothumb-noimagehandler": "{{doc-apierror}}\n\nParameters:\n* $1 - File name.",
+       "apiwarn-parse-nocontentmodel": "{{doc-apierror}}\n\nParameters:\n* $1 - Content model being assumed.",
+       "apiwarn-parse-titlewithouttext": "{{doc-apierror}}",
+       "apiwarn-redirectsandrevids": "{{doc-apierror}}",
+       "apiwarn-tokennotallowed": "{{doc-apierror}}\n\nParameters:\n* $1 - Token type being requested, typically named after the action requiring the token.",
+       "apiwarn-tokens-origin": "{{doc-apierror}}",
+       "apiwarn-toomanyvalues": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Maximum number of values allowed.",
+       "apiwarn-truncatedresult": "{{doc-apierror}}\n\nParameters:\n* $1 - Size limit in bytes.",
+       "apiwarn-unclearnowtimestamp": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Supplied value.",
+       "apiwarn-unrecognizedvalues": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - List of unknown values supplied.\n* $3 - Number of unknown values.",
+       "apiwarn-unsupportedarray": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
+       "apiwarn-urlparamwidth": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".\n* $2 - Width being ignored.\n* $3 - Width being used.",
+       "apiwarn-validationfailed-badchars": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.",
+       "apiwarn-validationfailed-badpref": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.",
+       "apiwarn-validationfailed-cannotset": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.",
+       "apiwarn-validationfailed-keytoolong": "{{doc-apierror}}\n\nUsed with {{msg-mw|apiwarn-validationfailed}}.\n\nParameters:\n* $1 - Maximum allowed key length in bytes.",
+       "apiwarn-validationfailed": "{{doc-apierror}}\n\nParameters:\n* $1 - User preference name.\n* $2 - Failure message, such as {{msg-mw|apiwarn-validationfailed-badpref}}. Probably already ends with punctuation",
+       "apiwarn-wgDebugAPI": "{{doc-apierror}}",
+       "api-feed-error-title": "Used as a feed item title when an error occurs in <kbd>action=feedwatchlist</kbd>.\n\nParameters:\n* $1 - API error code",
+       "api-usage-docref": "\n\nParameters:\n* $1 - URL of the API auto-generated documentation.",
+       "api-exception-trace": "\n\nParameters:\n* $1 - Exception class.\n* $2 - File from which the exception was thrown.\n* $3 - Line number from which the exception was thrown.\n* $4 - Exception backtrace.",
        "api-credits-header": "Header for the API credits section in the API help output\n{{Identical|Credit}}",
        "api-credits": "API credits text, displayed in the API help output"
 }
index d65fb7e..2879020 100644 (file)
@@ -19,7 +19,8 @@
                        "Гизатуллина",
                        "MaxSem",
                        "Irus",
-                       "MaxBioHazard"
+                       "MaxBioHazard",
+                       "Kareyac"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Документация]]\n* [[mw:API:FAQ|ЧаВО]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Почтовая рассылка]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Новости API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Ошибки и запросы]\n</div>\n<strong>Статус:</strong> Все отображаемые на этой странице функции должны работать, однако API находится в статусе активной разработки и может измениться в любой момент. Подпишитесь на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почтовую рассылку mediawiki-api-announce], чтобы быть в курсе обновлений.\n\n<strong>Ошибочные запросы:</strong> Если API получает запрос с ошибкой, вернётся заголовок HTTP с ключом «MediaWiki-API-Error», после чего значение заголовка и код ошибки будут отправлены обратно и установлены в то же значение. Более подробную информацию см. [[mw:API:Errors_and_warnings|API: Ошибки и предупреждения]].\n\n<strong>Тестирование:</strong> для удобства тестирования API-запросов, см. [[Special:ApiSandbox]].",
        "apihelp-edit-param-undoafter": "Отменить все изменения от $1, чтобы отменить это. Если не набор, просто отменить одну ревизию.",
        "apihelp-edit-param-redirect": "Автоматически разрешать редиректы.",
        "apihelp-edit-param-contentformat": "Формат сериализации содержимого, используемый для ввода текста.",
-       "apihelp-edit-param-contentmodel": "Ð\9cоделÑ\8c Ñ\81одеÑ\80жимого нового содержимого.",
+       "apihelp-edit-param-contentmodel": "Ð\9aонÑ\82енÑ\82наÑ\8f Ð¼Ð¾Ð´ÐµÐ»Ñ\8c нового содержимого.",
        "apihelp-edit-param-token": "Маркер всегда должен быть послан в качестве последнего параметра, или, по крайней мере, после $1текстовый параметр.",
        "apihelp-edit-example-edit": "Редактировать страницу",
        "apihelp-edit-example-prepend": "Добавить магическое слово <kbd>_&#95;NOTOC_&#95;</kbd> в начало страницы.",
        "apihelp-emailuser-param-text": "Содержание письма",
        "apihelp-emailuser-param-ccme": "Отправить копию этого сообщения мне.",
        "apihelp-emailuser-example-email": "Отправить письмо пользователю <kbd>WikiSysop</kbd> с текстом <kbd>Content</kbd>.",
-       "apihelp-expandtemplates-description": "Разворачивает все шаблоны в wikitext.",
+       "apihelp-expandtemplates-description": "Разворачивает все шаблоны в викитекст.",
        "apihelp-expandtemplates-param-title": "Заголовок страницы.",
        "apihelp-expandtemplates-param-text": "Викитекст для конвертирования",
-       "apihelp-expandtemplates-param-revid": "Ð\98денÑ\82иÑ\84икаÑ\82оÑ\80 Ñ\80евизии, Ð´Ð»Ñ\8f <nowiki>{{REVISIONID}}</nowiki> Ð¸ Ð¿Ð¾Ð´Ð¾Ð±Ð½Ñ\8bе Ð¿ÐµÑ\80еменнÑ\8bе.",
-       "apihelp-expandtemplates-param-prop": "Какие данные получить.\n\nОбратите внимание, что если значение не выбрано, то результат будет содержать тексте, но выход будет в устаревший формат.",
+       "apihelp-expandtemplates-param-revid": "Ð\9dомеÑ\80 Ð²ÐµÑ\80Ñ\81ии, Ð´Ð»Ñ\8f <nowiki>{{REVISIONID}}</nowiki> Ð¸ Ð°Ð½Ð°Ð»Ð¾Ð³Ð¸Ñ\87нÑ\8bÑ\85 Ð¿ÐµÑ\80еменнÑ\8bÑ\85.",
+       "apihelp-expandtemplates-param-prop": "Какие фрагменты информации получить.\n\nОбратите внимание, что если ни одно из значений не выбрано, результат будет содержать викитекст, но вывод будет в устаревшем формате.",
        "apihelp-expandtemplates-paramvalue-prop-wikitext": "Расширенный викитекст",
        "apihelp-expandtemplates-paramvalue-prop-categories": "Любой категории присутствуют во входных данных, которые не представлены в тексте вывод.",
        "apihelp-expandtemplates-paramvalue-prop-properties": "Страница свойств определяются расширенные волшебные слова в тексте.",
        "apihelp-expandtemplates-paramvalue-prop-volatile": "Есть ли выход летучих и не должны использоваться повторно в другом месте на странице.",
-       "apihelp-expandtemplates-paramvalue-prop-ttl": "Максимальное время, через которое кэширует результат должен быть признан недействительным.",
+       "apihelp-expandtemplates-paramvalue-prop-ttl": "Максимальное время, по прошествии которого кэш результата должен быть признан недействительным.",
        "apihelp-expandtemplates-paramvalue-prop-jsconfigvars": "Дает переменные конфигурации JavaScript конкретной странице.",
        "apihelp-expandtemplates-paramvalue-prop-encodedjsconfigvars": "Дает переменные конфигурации JavaScript, определенных на страницу в виде строки JSON.",
        "apihelp-expandtemplates-paramvalue-prop-parsetree": "Дерево разбора XML входных данных.",
        "apihelp-expandtemplates-param-includecomments": "Нужно ли включать комментарии HTML на выходе.",
        "apihelp-expandtemplates-param-generatexml": "Создать XML-дерево разбора (заменить $1prop=parsetree).",
-       "apihelp-feedcontributions-description": "Возвращает вклад пользователей корма.",
+       "apihelp-feedcontributions-description": "Возвращает список правок участника.",
        "apihelp-feedcontributions-param-feedformat": "Биреү форматы",
        "apihelp-feedcontributions-param-user": "Что пользователи, чтобы получить взносы.",
        "apihelp-feedcontributions-param-namespace": "По какому пространству имён фильтровать вклад.",
        "apihelp-filerevert-description": "Файлды иҫке версияға ҡайтарырға.",
        "apihelp-filerevert-param-filename": "Целевое имя файла без префикса File:.",
        "apihelp-filerevert-param-comment": "Загрузить комментарий.",
-       "apihelp-filerevert-example-revert": "<kbd>Wiki.png</kbd>на версии <kbd>2011-03-05T15:27:40Z</kbd> сброса.",
+       "apihelp-filerevert-example-revert": "Откат <kbd>Wiki.png</kbd> к версии от <kbd>2011-03-05T15:27:40Z</kbd>.",
        "apihelp-help-param-helpformat": "Белешмә яҙыу форматы.",
        "apihelp-help-example-main": "Помощь по главному модулю.",
        "apihelp-help-example-recursive": "Вся справка в одном разделе.",
diff --git a/includes/api/i18n/th.json b/includes/api/i18n/th.json
new file mode 100644 (file)
index 0000000..d2ea18f
--- /dev/null
@@ -0,0 +1,9 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Aefgh39622"
+               ]
+       },
+       "apihelp-imagerotate-description": "หมุนรูปภาพอย่างน้อยหนึ่งรูป",
+       "api-help-param-continue": "เมื่อมีผลลัพธ์เพิ่มเติมพร้อมใช้งาน ใช้ตัวเลือกนี้เพื่อดำเนินการต่อ"
+}
index 8b53c02..4e42a10 100644 (file)
        "apihelp-options-description": "Змінити налаштування поточного користувача.\n\nМожна встановити лише опції, які зареєстровані у ядрі або в одному з інстальованих розширень, або опції з префіксом ключів <code>userjs-</code> (призначені для використання користувацькими скриптами).",
        "apihelp-options-param-reset": "Встановлює налаштування сайту за замовчуванням.",
        "apihelp-options-param-resetkinds": "Список типів опцій для перевстановлення, коли вказана опція <var>$1reset</var>.",
-       "apihelp-options-param-change": "СпиÑ\81ок Ð·Ð¼Ñ\96н, Ð²Ñ\96дÑ\84оÑ\80маÑ\82ованиÑ\85 Ñ\8fк Ð½Ð°Ð·Ð²Ð°=знаÑ\87еннÑ\8f (напÑ\80., skin=vector). Ð\97наÑ\87еннÑ\8f Ð½Ðµ Ð¼Ð¾Ð¶Ðµ Ð¼Ñ\96Ñ\81Ñ\82иÑ\82и Ð²ÐµÑ\80Ñ\82икалÑ\8cниÑ\85 Ñ\80иÑ\81ок. Ð¯ÐºÑ\89о Ð·Ð½Ð°Ñ\87еннÑ\8f Ð½Ðµ Ð²ÐºÐ°Ð·Ð°Ð½Ðµ (навÑ\96Ñ\82Ñ\8c Ð½ÐµÐ¼Ð°Ñ\94 Ð·Ð½Ð°ÐºÐ° Ñ\80Ñ\96вноÑ\81Ñ\82Ñ\96) , Ð½Ð°Ð¿Ñ\80., optionname|otheroption|â\80¦, Ð¾Ð¿Ñ\86Ñ\96Ñ\8e Ð±Ñ\83де Ð¿ÐµÑ\80евÑ\81Ñ\82ановлено Ð´Ð¾ Ñ\97Ñ\97 Ð·Ð½Ð°Ñ\87еннÑ\8f Ð·Ð° Ð·Ð°Ð¼Ð¾Ð²Ñ\87Ñ\83ваннÑ\8fм.",
+       "apihelp-options-param-change": "СпиÑ\81ок Ð·Ð¼Ñ\96н, Ð²Ñ\96дÑ\84оÑ\80маÑ\82ованиÑ\85 Ñ\8fк Ð½Ð°Ð·Ð²Ð°=знаÑ\87еннÑ\8f (напÑ\80., skin=vector). Ð¯ÐºÑ\89о Ð·Ð½Ð°Ñ\87еннÑ\8f Ð½Ðµ Ð²ÐºÐ°Ð·Ð°Ð½Ðµ (навÑ\96Ñ\82Ñ\8c Ð½ÐµÐ¼Ð°Ñ\94 Ð·Ð½Ð°ÐºÐ° Ñ\80Ñ\96вноÑ\81Ñ\82Ñ\96) , Ð½Ð°Ð¿Ñ\80., optionname|otheroption|â\80¦, Ð¾Ð¿Ñ\86Ñ\96Ñ\8e Ð±Ñ\83де Ð¿ÐµÑ\80евÑ\81Ñ\82ановлено Ð´Ð¾ Ñ\97Ñ\97 Ð·Ð½Ð°Ñ\87еннÑ\8f Ð·Ð° Ð·Ð°Ð¼Ð¾Ð²Ñ\87Ñ\83ваннÑ\8fм. Ð¯ÐºÑ\89о Ð±Ñ\83дÑ\8c\8fке Ð·Ñ\96 Ð·Ð½Ð°Ñ\87енÑ\8c Ð¼Ñ\96Ñ\81Ñ\82иÑ\82Ñ\8c Ñ\81имвол Ð²ÐµÑ\80Ñ\82икалÑ\8cноÑ\97 Ñ\80иÑ\81ки (<kbd>|</kbd>), Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82айÑ\82е [[Special:ApiHelp/main#main/datatypes|алÑ\8cÑ\82еÑ\80наÑ\82ивний Ñ\80оздÑ\96лÑ\8eваÑ\87 Ð·Ð½Ð°Ñ\87енÑ\8c]] Ð´Ð»Ñ\8f ÐºÐ¾Ñ\80екÑ\82ного Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ\8f Ð¾Ð¿ÐµÑ\80аÑ\86Ñ\96Ñ\97.",
        "apihelp-options-param-optionname": "Назва опції, якій має бути присвоєне значення <var>$1optionvalue</var>.",
-       "apihelp-options-param-optionvalue": "Значення опції, вказане в <var>$1optionname</var>, може містити вертикальні риски.",
+       "apihelp-options-param-optionvalue": "Значення опції, вказане в <var>$1optionname</var>.",
        "apihelp-options-example-reset": "Скинути всі налаштування.",
        "apihelp-options-example-change": "Змінити налаштування <kbd>skin</kbd> та <kbd>hideminor</kbd>.",
        "apihelp-options-example-complex": "Скинути всі налаштування, потім встановити <kbd>skin</kbd> та <kbd>nickname</kbd>.",
        "apihelp-resetpassword-description-noroutes": "Немає доступних способів відновити пароль.\n\nУвімкніть способи у <var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var>, щоб використовувати цей модуль.",
        "apihelp-resetpassword-param-user": "Користувача відновлено.",
        "apihelp-resetpassword-param-email": "Адреса електронної пошти користувача відновлено.",
-       "apihelp-resetpassword-param-capture": "Повернути тимчасові паролі, які були надіслані. Вимагає право користувача <code>passwordreset</code>.",
        "apihelp-resetpassword-example-user": "Надіслати лист для скидання пароля користувачу <kbd>Example</kbd>.",
        "apihelp-resetpassword-example-email": "Надіслати лист для скидання пароля усім користувачам з адресою електронної пошти <kbd>user@example.com</kbd>.",
        "apihelp-revisiondelete-description": "Вилучити або відновити версії.",
        "apihelp-phpfm-description": "Виводити дані у форматі серіалізованого PHP (вивід відформатованого коду за допомогою HTML).",
        "apihelp-rawfm-description": "Виводити дані, включно з елементами налагодження, у форматі JSON (вивід відформатованого коду за допомогою HTML).",
        "apihelp-xml-description": "Виводити дані у форматі XML.",
-       "apihelp-xml-param-xslt": "Якщо вказано, додає названу сторінку як таблицю стилів XSL. Це значення повинне бути назвою у просторі назв {{ns:mediawiki}}, що закінчується на <code>.xsl</code>.",
+       "apihelp-xml-param-xslt": "Якщо вказано, додає названу сторінку як таблицю стилів XSL. Це значення повинне бути назвою у просторі назв {{ns:MediaWiki}}, що закінчується на <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "Якщо вказано, додає простір назв XML.",
        "apihelp-xmlfm-description": "Вивести дані у форматі XML (вивід відформатованого коду за допомогою HTML).",
        "api-format-title": "Результат запиту до API MediaWiki",
        "api-format-prettyprint-header": "Це HTML-представлення формату $1. HTML є гарним для налагодження, однак не придатний для прикладного використання.\n\nУкажіть значення для параметра <var>format</var>, для того щоб змінити формат. Для перегляду не-HTML-представлення формату, $1, вкажіть <kbd>format=$2</kbd>.\n\nДив. [[mw:API|повну документацію]], або [[Special:ApiHelp/main|довідку з API]] для детальнішої інформації.",
        "api-format-prettyprint-header-only-html": "Це HTML-представлення призначене для налагодження, однак не придатне для прикладного використання.\n\nДив. [[mw:API|повну документацію]], або [[Special:ApiHelp/main|довідку з API]] для детальнішої інформації.",
+       "api-format-prettyprint-status": "Відповідь повернеться із HTTP-статусом $1 $2.",
        "api-pageset-param-titles": "Список назв над якими працювати.",
        "api-pageset-param-pageids": "Список ідентифікаторів сторінок над якими працювати.",
        "api-pageset-param-revids": "Список ідентифікаторів версій над якими працювати.",
        "api-help-param-upload": "Повинно бути надіслано у формі надсилання файлу використовуючи multipart/form-data.",
        "api-help-param-multi-separate": "Розділіть значення з допомогою <kbd>|</kbd> або [[Special:ApiHelp/main#main/datatypes|альтернативу]].",
        "api-help-param-multi-max": "Максимальна кількість значень — {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} для ботів).",
+       "api-help-param-multi-all": "Щоб зазначити всі значення, використовуйте <kbd>$1</kbd>.",
        "api-help-param-default": "За замовчуванням: $1",
        "api-help-param-default-empty": "За замовчуванням: <span class=\"apihelp-empty\">(пусто)</span>",
        "api-help-param-token": "Токен «$1» отримано з [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
index ff2ce77..b96d3a1 100644 (file)
        "apihelp-query+recentchanges-paramvalue-prop-patrolled": "将可巡查编辑标记为已巡查或未巡查。",
        "apihelp-query+recentchanges-paramvalue-prop-loginfo": "添加日志信息(日志ID、日志类型等)至日志记录。",
        "apihelp-query+recentchanges-paramvalue-prop-tags": "列举条目的标签。",
-       "apihelp-query+recentchanges-paramvalue-prop-sha1": "Adds the content checksum for entries associated with a revision.",
+       "apihelp-query+recentchanges-paramvalue-prop-sha1": "为与某一修订版本有关的记录添加内容校验和。",
        "apihelp-query+recentchanges-param-token": "请改用<kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>。",
        "apihelp-query+recentchanges-param-show": "只显示满足这些标准的项目。例如,要只查看由登录用户做出的小编辑,设置$1show=minor|!anon。",
        "apihelp-query+recentchanges-param-limit": "返回总计更新数。",
        "apihelp-query+revisions-example-first5-not-localhost": "获取<kbd>Main Page</kbd>的前5次不是由匿名用户<kbd>127.0.0.1</kbd>做出的修订。",
        "apihelp-query+revisions-example-first5-user": "获取<kbd>Main Page</kbd>的前5次由用户<kbd>MediaWiki default</kbd>做出的修订。",
        "apihelp-query+revisions+base-param-prop": "要为每个修订获取的属性:",
-       "apihelp-query+revisions+base-paramvalue-prop-ids": "修订ID。",
+       "apihelp-query+revisions+base-paramvalue-prop-ids": "修订版本的ID。",
        "apihelp-query+revisions+base-paramvalue-prop-flags": "修订标记(小编辑)。",
        "apihelp-query+revisions+base-paramvalue-prop-timestamp": "修订的时间戳。",
        "apihelp-query+revisions+base-paramvalue-prop-user": "做出修订的用户。",
        "apihelp-query+userinfo-paramvalue-prop-groups": "列举当前用户隶属的所有群组。",
        "apihelp-query+userinfo-paramvalue-prop-implicitgroups": "列举当前用户的所有自动成为成员的用户组。",
        "apihelp-query+userinfo-paramvalue-prop-rights": "列举当前用户拥有的所有权限。",
-       "apihelp-query+userinfo-paramvalue-prop-changeablegroups": "Lists the groups the current user can add to and remove from.",
+       "apihelp-query+userinfo-paramvalue-prop-changeablegroups": "列举当前用户可以添加并移除的用户组。",
        "apihelp-query+userinfo-paramvalue-prop-options": "列举当前用户设置的所有参数设置。",
        "apihelp-query+userinfo-paramvalue-prop-preferencestoken": "<span class=\"apihelp-deprecated\">已弃用。</span>获取令牌以更改当前用户的参数设置。",
        "apihelp-query+userinfo-paramvalue-prop-editcount": "添加当前用户的编辑计数。",
        "apihelp-resetpassword-description-noroutes": "没有密码重置路由可用。\n\n在<var>[[mw:Manual:$wgPasswordResetRoutes|$wgPasswordResetRoutes]]</var>中启用路由以使用此模块。",
        "apihelp-resetpassword-param-user": "正在重置的用户。",
        "apihelp-resetpassword-param-email": "正在重置用户的电子邮件地址。",
-       "apihelp-resetpassword-param-capture": "返回已发送的临时密码。需要<code>passwordreset</code>用户权限。",
        "apihelp-resetpassword-example-user": "向用户<kbd>Example</kbd>发送密码重置邮件。",
        "apihelp-resetpassword-example-email": "向所有电子邮件地址为<kbd>user@example.com</kbd>的用户发送密码重置邮件。",
        "apihelp-revisiondelete-description": "删除和恢复修订版本。",
        "apihelp-phpfm-description": "输出数据为序列化PHP格式(HTML优质打印效果)。",
        "apihelp-rawfm-description": "输出数据为JSON格式,包含调试元素(HTML优质打印效果)。",
        "apihelp-xml-description": "输出数据为XML格式。",
-       "apihelp-xml-param-xslt": "如果指定,加入已命名的页面作为一个XSL样式表。值必须是在{{ns:mediawiki}}名字空间以<code>.xsl</code>为结尾的标题。",
+       "apihelp-xml-param-xslt": "如果指定,加入已命名的页面作为一个XSL样式表。值必须是在{{ns:MediaWiki}}名字空间以<code>.xsl</code>为结尾的标题。",
        "apihelp-xml-param-includexmlnamespace": "如果指定,添加一个XML名字空间。",
        "apihelp-xmlfm-description": "输出数据为XML格式(HTML优质打印效果)。",
        "api-format-title": "MediaWiki API 结果",
        "api-help-param-upload": "必须被公布为使用multipart/form-data的一次文件上传。",
        "api-help-param-multi-separate": "通过<kbd>|</kbd>或[[Special:ApiHelp/main#main/datatypes|替代物]]隔开各值。",
        "api-help-param-multi-max": "值的最大数量是{{PLURAL:$1|$1}}(对于机器人则是{{PLURAL:$2|$2}})。",
+       "api-help-param-multi-all": "要指定所有值,请使用<kbd>$1</kbd>。",
        "api-help-param-default": "默认:$1",
        "api-help-param-default-empty": "默认:<span class=\"apihelp-empty\">(空)</span>",
        "api-help-param-token": "从[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]取回的“$1”令牌",
index d88a5b2..e9a6edc 100644 (file)
@@ -24,6 +24,7 @@
 namespace MediaWiki\Auth;
 
 use Config;
+use MediaWiki\MediaWikiServices;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerInterface;
 use Status;
@@ -146,7 +147,7 @@ class AuthManager implements LoggerAwareInterface {
                if ( self::$instance === null ) {
                        self::$instance = new self(
                                \RequestContext::getMain()->getRequest(),
-                               \ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                               MediaWikiServices::getInstance()->getMainConfig()
                        );
                }
                return self::$instance;
index ff4569b..7fc362a 100644 (file)
@@ -108,6 +108,10 @@ abstract class AuthenticationRequest {
         *  - optional: (bool) If set and truthy, the field may be left empty
         *  - sensitive: (bool) If set and truthy, the field is considered sensitive. Code using the
         *      request should avoid exposing the value of the field.
+        *  - skippable: (bool) If set and truthy, the client is free to hide this
+        *      field from the user to streamline the workflow. If all fields are
+        *      skippable (except possibly a single button), no user interaction is
+        *      required at all.
         *
         * All AuthenticationRequests are populated from the same data, so most of the time you'll
         * want to prefix fields names with something unique to the extension/provider (although
index 88df68d..fd36887 100644 (file)
@@ -104,7 +104,7 @@ class LocalPasswordPrimaryAuthenticationProvider
                // The old hash format was just an md5 hex hash, with no type information
                if ( preg_match( '/^[0-9a-f]{32}$/', $row->user_password ) ) {
                        if ( $this->config->get( 'PasswordSalt' ) ) {
-                               $row->user_password = ":A:{$row->user_id}:{$row->user_password}";
+                               $row->user_password = ":B:{$row->user_id}:{$row->user_password}";
                        } else {
                                $row->user_password = ":A:{$row->user_password}";
                        }
@@ -132,12 +132,12 @@ class LocalPasswordPrimaryAuthenticationProvider
 
                // @codeCoverageIgnoreStart
                if ( $this->getPasswordFactory()->needsUpdate( $pwhash ) ) {
-                       $pwhash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
-                       \DeferredUpdates::addCallableUpdate( function () use ( $pwhash, $oldRow ) {
+                       $newHash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
+                       \DeferredUpdates::addCallableUpdate( function () use ( $newHash, $oldRow ) {
                                $dbw = wfGetDB( DB_MASTER );
                                $dbw->update(
                                        'user',
-                                       [ 'user_password' => $pwhash->toString() ],
+                                       [ 'user_password' => $newHash->toString() ],
                                        [
                                                'user_id' => $oldRow->user_id,
                                                'user_password' => $oldRow->user_password
@@ -242,14 +242,14 @@ class LocalPasswordPrimaryAuthenticationProvider
 
                $pwhash = null;
 
-               if ( $this->loginOnly ) {
-                       $pwhash = $this->getPasswordFactory()->newFromCiphertext( null );
-                       $expiry = null;
-                       // @codeCoverageIgnoreStart
-               } elseif ( get_class( $req ) === PasswordAuthenticationRequest::class ) {
-                       // @codeCoverageIgnoreEnd
-                       $pwhash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
-                       $expiry = $this->getNewPasswordExpiry( $username );
+               if ( get_class( $req ) === PasswordAuthenticationRequest::class ) {
+                       if ( $this->loginOnly ) {
+                               $pwhash = $this->getPasswordFactory()->newFromCiphertext( null );
+                               $expiry = null;
+                       } else {
+                               $pwhash = $this->getPasswordFactory()->newFromPlaintext( $req->password );
+                               $expiry = $this->getNewPasswordExpiry( $username );
+                       }
                }
 
                if ( $pwhash ) {
index d487e31..06060b1 100644 (file)
@@ -58,6 +58,7 @@ class RememberMeAuthenticationRequest extends AuthenticationRequest {
                                'label' => wfMessage( 'userlogin-remembermypassword' )->numParams( $expirationDays ),
                                'help' => wfMessage( 'authmanager-userlogin-remembermypassword-help' ),
                                'optional' => true,
+                               'skippable' => true,
                        ]
                ];
        }
index 42f0e70..bc7c779 100644 (file)
@@ -21,6 +21,8 @@
 
 namespace MediaWiki\Auth;
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This represents the intention to set a temporary password for the user.
  * @ingroup Auth
@@ -33,12 +35,6 @@ class TemporaryPasswordAuthenticationRequest extends AuthenticationRequest {
        /** @var bool Email password to the user. */
        public $mailpassword = false;
 
-       /**
-        * @var bool Do not fail certain operations if the password cannot be mailed, there is a
-        *   backchannel present.
-        */
-       public $hasBackchannel = false;
-
        /** @var string Username or IP address of the caller */
        public $caller;
 
@@ -67,7 +63,7 @@ class TemporaryPasswordAuthenticationRequest extends AuthenticationRequest {
         * @return TemporaryPasswordAuthenticationRequest
         */
        public static function newRandom() {
-               $config = \ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               $config = MediaWikiServices::getInstance()->getMainConfig();
 
                // get the min password length
                $minLength = $config->get( 'MinimalPasswordLength' );
index 9962fa3..44c2824 100644 (file)
@@ -154,6 +154,16 @@ class TemporaryPasswordPrimaryAuthenticationProvider
                        return $this->failResponse( $req );
                }
 
+               // Add an extra log entry since a temporary password is
+               // an unusual way to log in, so its important to keep track
+               // of in case of abuse.
+               $this->logger->info( "{user} successfully logged in using temp password",
+                       [
+                               'user' => $username,
+                               'requestIP' => $this->manager->getRequest()->getIP()
+                       ]
+               );
+
                $this->setPasswordResetFlag( $username, $status );
 
                return AuthenticationResponse::newPass( $username );
@@ -236,7 +246,7 @@ class TemporaryPasswordPrimaryAuthenticationProvider
                        $sv->merge( $this->checkPasswordValidity( $username, $req->password ) );
 
                        if ( $req->mailpassword ) {
-                               if ( !$this->emailEnabled && !$req->hasBackchannel ) {
+                               if ( !$this->emailEnabled ) {
                                        return \StatusValue::newFatal( 'passwordreset-emaildisabled' );
                                }
 
@@ -326,7 +336,7 @@ class TemporaryPasswordPrimaryAuthenticationProvider
 
                $ret = \StatusValue::newGood();
                if ( $req ) {
-                       if ( $req->mailpassword && !$req->hasBackchannel ) {
+                       if ( $req->mailpassword ) {
                                if ( !$this->emailEnabled ) {
                                        $ret->merge( \StatusValue::newFatal( 'emaildisabled' ) );
                                } elseif ( !$user->getEmail() ) {
index f47c606..6d3b2f4 100644 (file)
@@ -23,6 +23,7 @@ namespace MediaWiki\Auth;
 
 use BagOStuff;
 use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerInterface;
 use Psr\Log\LogLevel;
@@ -68,7 +69,7 @@ class Throttler implements LoggerAwareInterface {
                }
 
                if ( $conditions === null ) {
-                       $config = \ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $config = MediaWikiServices::getInstance()->getMainConfig();
                        $conditions = $config->get( 'PasswordAttemptThrottle' );
                        $params += [
                                'type' => 'password',
@@ -135,7 +136,7 @@ class Throttler implements LoggerAwareInterface {
                                $this->cache->incr( $throttleKey );
                        } else { // throttled
                                $this->logRejection( [
-                                       'type' => $this->type,
+                                       'throttle' => $this->type,
                                        'index' => $index,
                                        'ip' => $ipKey,
                                        'username' => $username,
@@ -191,7 +192,7 @@ class Throttler implements LoggerAwareInterface {
        }
 
        protected function logRejection( array $context ) {
-               $logMsg = 'Throttle {type} hit, throttled for {expiry} seconds due to {count} attempts '
+               $logMsg = 'Throttle {throttle} hit, throttled for {expiry} seconds due to {count} attempts '
                        . 'from username {username} and IP {ip}';
 
                // If we are hitting a throttle for >= warningLimit attempts, it is much more likely to be
index ee77d7b..35d6652 100644 (file)
@@ -21,6 +21,7 @@
 
 namespace MediaWiki\Auth;
 
+use MediaWiki\MediaWikiServices;
 use StatusValue;
 use User;
 
@@ -38,7 +39,7 @@ class UserDataAuthenticationRequest extends AuthenticationRequest {
        public $realname;
 
        public function getFieldInfo() {
-               $config = \ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               $config = MediaWikiServices::getInstance()->getMainConfig();
                $ret = [
                        'email' => [
                                'type' => 'string',
index fb461b7..8c70be2 100644 (file)
@@ -82,6 +82,8 @@ interface ICacheHelper {
        function setExpiry( $cacheExpiry );
 }
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * Helper class for caching various elements in a single cache entry.
  *
@@ -217,9 +219,9 @@ class CacheHelper implements ICacheHelper {
                        $subPage = explode( '/', $subPage, 2 );
                        $subPage = count( $subPage ) > 1 ? $subPage[1] : false;
 
-                       $message .= ' ' . Linker::link(
+                       $message .= ' ' . MediaWikiServices::getInstance()->getLinkRenderer()->makeLink(
                                $context->getTitle( $subPage ),
-                               $context->msg( 'cachedspecial-refresh-now' )->escaped(),
+                               $context->msg( 'cachedspecial-refresh-now' )->text(),
                                [],
                                $refreshArgs
                        );
index dc8c589..4e6b2fd 100644 (file)
@@ -144,13 +144,9 @@ class MessageCache {
         * @param bool $useDB
         * @param int $expiry Lifetime for cache. @see $mExpiry.
         */
-       function __construct( $memCached, $useDB, $expiry ) {
+       function __construct( BagOStuff $memCached, $useDB, $expiry ) {
                global $wgUseLocalMessageCache;
 
-               if ( !$memCached ) {
-                       $memCached = wfGetCache( CACHE_NONE );
-               }
-
                $this->mMemc = $memCached;
                $this->mDisable = !$useDB;
                $this->mExpiry = $expiry;
@@ -500,6 +496,7 @@ class MessageCache {
                        if ( $text === false ) {
                                // Failed to fetch data; possible ES errors?
                                // Store a marker to fetch on-demand as a workaround...
+                               // TODO Use a differnt marker
                                $entry = '!TOO BIG';
                                wfDebugLog(
                                        'MessageCache',
@@ -514,6 +511,10 @@ class MessageCache {
 
                $cache['VERSION'] = MSG_CACHE_VERSION;
                ksort( $cache );
+
+               # Hash for validating local cache (APC). No need to take into account
+               # messages larger than $wgMaxMsgCacheEntrySize, since those are only
+               # stored and fetched from memcache.
                $cache['HASH'] = md5( serialize( $cache ) );
                $cache['EXPIRY'] = wfTimestamp( TS_MW, time() + $this->mExpiry );
 
@@ -572,7 +573,8 @@ class MessageCache {
                }
 
                ScopedCallback::consume( $scopedLock );
-               // Relay the purge to APC and other DCs
+               // Relay the purge. Touching this check key expires cache contents
+               // and local cache (APC) validation hash across all datacenters.
                $this->wanCache->touchCheckKey( wfMemcKey( 'messages', $code ) );
 
                // Also delete cached sidebar... just in case it is affected
index 1262f2c..81f64a8 100644 (file)
@@ -762,6 +762,7 @@ class RecentChange {
                # # Get pageStatus for email notification
                switch ( $type . '-' . $action ) {
                        case 'delete-delete':
+                       case 'delete-delete_redir':
                                $pageStatus = 'deleted';
                                break;
                        case 'move-move':
index 993f0b7..bfabd51 100644 (file)
@@ -397,7 +397,7 @@ class ChangeTags {
                        if ( !$user->isAllowed( 'applychangetags' ) ) {
                                return Status::newFatal( 'tags-apply-no-permission' );
                        } elseif ( $user->isBlocked() ) {
-                               return Status::newFatal( 'tags-apply-blocked' );
+                               return Status::newFatal( 'tags-apply-blocked', $user->getName() );
                        }
                }
 
@@ -468,7 +468,7 @@ class ChangeTags {
                        if ( !$user->isAllowed( 'changetags' ) ) {
                                return Status::newFatal( 'tags-update-no-permission' );
                        } elseif ( $user->isBlocked() ) {
-                               return Status::newFatal( 'tags-update-blocked' );
+                               return Status::newFatal( 'tags-update-blocked', $user->getName() );
                        }
                }
 
@@ -668,12 +668,20 @@ class ChangeTags {
         * @param string $selected Tag to select by default
         * @param bool $ooui Use an OOUI TextInputWidget as selector instead of a non-OOUI input field
         *        You need to call OutputPage::enableOOUI() yourself.
+        * @param IContextSource|null $context
+        * @note Even though it takes null as a valid argument, an IContextSource is preferred
+        *       in a new code, as the null value can change in the future
         * @return array an array of (label, selector)
         */
-       public static function buildTagFilterSelector( $selected = '', $ooui = false ) {
-               global $wgUseTagFilter;
+       public static function buildTagFilterSelector(
+               $selected = '', $ooui = false, IContextSource $context = null
+       ) {
+               if ( !$context ) {
+                       $context = RequestContext::getMain();
+               }
 
-               if ( !$wgUseTagFilter || !count( self::listDefinedTags() ) ) {
+               $config = $context->getConfig();
+               if ( !$config->get( 'UseTagFilter' ) || !count( self::listDefinedTags() ) ) {
                        return [];
                }
 
@@ -681,7 +689,7 @@ class ChangeTags {
                        Html::rawElement(
                                'label',
                                [ 'for' => 'tagfilter' ],
-                               wfMessage( 'tag-filter' )->parse()
+                               $context->msg( 'tag-filter' )->parse()
                        )
                ];
 
@@ -790,7 +798,7 @@ class ChangeTags {
                        if ( !$user->isAllowed( 'managechangetags' ) ) {
                                return Status::newFatal( 'tags-manage-no-permission' );
                        } elseif ( $user->isBlocked() ) {
-                               return Status::newFatal( 'tags-manage-blocked' );
+                               return Status::newFatal( 'tags-manage-blocked', $user->getName() );
                        }
                }
 
@@ -858,7 +866,7 @@ class ChangeTags {
                        if ( !$user->isAllowed( 'managechangetags' ) ) {
                                return Status::newFatal( 'tags-manage-no-permission' );
                        } elseif ( $user->isBlocked() ) {
-                               return Status::newFatal( 'tags-manage-blocked' );
+                               return Status::newFatal( 'tags-manage-blocked', $user->getName() );
                        }
                }
 
@@ -917,7 +925,7 @@ class ChangeTags {
                        if ( !$user->isAllowed( 'managechangetags' ) ) {
                                return Status::newFatal( 'tags-manage-no-permission' );
                        } elseif ( $user->isBlocked() ) {
-                               return Status::newFatal( 'tags-manage-blocked' );
+                               return Status::newFatal( 'tags-manage-blocked', $user->getName() );
                        }
                }
 
@@ -1050,7 +1058,7 @@ class ChangeTags {
                        if ( !$user->isAllowed( 'deletechangetags' ) ) {
                                return Status::newFatal( 'tags-delete-no-permission' );
                        } elseif ( $user->isBlocked() ) {
-                               return Status::newFatal( 'tags-manage-blocked' );
+                               return Status::newFatal( 'tags-manage-blocked', $user->getName() );
                        }
                }
 
index 2dc953c..b78efaf 100644 (file)
@@ -19,6 +19,8 @@
  * @ingroup Change tagging
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * Item class for a logging table row with its associated change tags.
  * @todo Abstract out a base class for this and RevDelLogItem, similar to the
@@ -70,9 +72,9 @@ class ChangeTagsLogItem extends RevisionItemBase {
                $formatter->setAudience( LogFormatter::FOR_THIS_USER );
 
                // Log link for this page
-               $loglink = Linker::link(
+               $loglink = MediaWikiServices::getInstance()->getLinkRenderer()->makeLink(
                        SpecialPage::getTitleFor( 'Log' ),
-                       $this->list->msg( 'log' )->escaped(),
+                       $this->list->msg( 'log' )->text(),
                        [],
                        [ 'page' => $title->getPrefixedText() ]
                );
index 881c8c2..9950a11 100644 (file)
@@ -46,11 +46,13 @@ abstract class Collation {
         * @return Collation
         */
        public static function factory( $collationName ) {
+               global $wgContLang;
+
                switch ( $collationName ) {
                        case 'uppercase':
                                return new UppercaseCollation;
                        case 'numeric':
-                               return new NumericUppercaseCollation;
+                               return new NumericUppercaseCollation( $wgContLang );
                        case 'identity':
                                return new IdentityCollation;
                        case 'uca-default':
index e6b773c..7b4fce6 100644 (file)
@@ -100,6 +100,12 @@ class IcuCollation extends Collation {
                'be' => [ "Ё" ],
                'be-tarask' => [ "Ё" ],
                'bg' => [],
+               'bn' => [ 'ং', 'ঃ', 'ঁ' ],
+               'bn@collation=traditional' => [
+                       'ং', 'ঃ', 'ঁ', 'ক্', 'খ্', 'গ্', 'ঘ্', 'ঙ্', 'চ্', 'ছ্', 'জ্', 'ঝ্',
+                       'ঞ্', 'ট্', 'ঠ্', 'ড্', 'ঢ্', 'ণ্', 'ৎ', 'থ্', 'দ্', 'ধ্', 'ন্', 'প্',
+                       'ফ্', 'ব্', 'ভ্', 'ম্', 'য্', 'র্', 'ৰ্', 'ল্', 'ৱ্', 'শ্', 'ষ্', 'স্', 'হ্'
+               ],
                'bo' => [],
                'br' => [ "Ch", "C'h" ],
                'bs' => [ "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ],
index d15daec..2d2ca47 100644 (file)
  * Note that this only works in terms of sequences of digits, and the behavior for decimal fractions
  * or pretty-formatted numbers may be unexpected.
  *
+ * Digits will be based on the wiki's content language settings. If
+ * you change the content langauge of a wiki you will need to run
+ * updateCollation.php --force. Only English (ASCII 0-9) and the
+ * localized version will be counted. Localized digits from other languages
+ * or weird unicode digit equivalents (e.g. 4, 𝟜, ⓸ , ⁴, etc) will not count.
+ *
  * @since 1.28
  */
 class NumericUppercaseCollation extends UppercaseCollation {
+
+       /**
+        * @var $digitTransformLang Language How to convert digits (usually $wgContLang)
+        */
+       private $digitTransformLang;
+
+       /**
+        * Constructor
+        *
+        * @param $lang Language How to convert digits.
+        *  For example, if given language "my" than ၇ is treated like 7.
+        *
+        * It is expected that usually this is given $wgContLang.
+        */
+       public function __construct( Language $lang ) {
+               $this->digitTransformLang = $lang;
+               parent::__construct();
+       }
+
        public function getSortKey( $string ) {
                $sortkey = parent::getSortKey( $string );
-
+               $sortkey = $this->convertDigits( $sortkey );
                // For each sequence of digits, insert the digit '0' and then the length of the sequence
                // (encoded in two bytes) before it. That's all folks, it sorts correctly now! The '0' ensures
                // correct position (where digits would normally sort), then the length will be compared putting
@@ -48,11 +73,33 @@ class NumericUppercaseCollation extends UppercaseCollation {
                return $sortkey;
        }
 
+       /**
+        * Convert localized digits to english digits.
+        *
+        * based on Language::parseFormattedNumber but without commas.
+        *
+        * @param $string String sortkey to unlocalize digits of
+        * @return String Sortkey with all localized digits replaced with ASCII digits.
+        */
+       private function convertDigits( $string ) {
+               $table = $this->digitTransformLang->digitTransformTable();
+               if ( $table ) {
+                       $table = array_filter( $table );
+                       $flipped = array_flip( $table );
+                       // Some languages seem to also have commas in this table.
+                       $flipped = array_filter( $flipped, 'is_numeric' );
+                       $string = strtr( $string, $flipped );
+               }
+               return $string;
+       }
+
        public function getFirstLetter( $string ) {
-               if ( preg_match( '/^\d/', $string ) ) {
-                       // Note that we pass 0 and 9 as normal params, not numParams(). This only works for 0-9
-                       // and not localised digits, so we don't want them to be converted.
-                       return wfMessage( 'category-header-numerals' )->params( 0, 9 )->text();
+               $convertedString = $this->convertDigits( $string );
+
+               if ( preg_match( '/^\d/', $convertedString ) ) {
+                       return wfMessage( 'category-header-numerals' )
+                               ->numParams( 0, 9 )
+                               ->text();
                } else {
                        return parent::getFirstLetter( $string );
                }
index 20893bb..dfd46c8 100644 (file)
 abstract class CodeContentHandler extends TextContentHandler {
 
        /**
-        * Returns the english language, because code is english, and should be handled as such.
+        * Returns the English language, because code is English, and should be handled as such.
         *
         * @param Title $title
         * @param Content $content
         *
-        * @return Language Return of wfGetLangObj( 'en' )
+        * @return Language
         *
         * @see ContentHandler::getPageLanguage()
         */
        public function getPageLanguage( Title $title, Content $content = null ) {
-               return wfGetLangObj( 'en' );
+               return Language::factory( 'en' );
        }
 
        /**
-        * Returns the english language, because code is english, and should be handled as such.
+        * Returns the English language, because code is English, and should be handled as such.
         *
         * @param Title $title
         * @param Content $content
         *
-        * @return Language Return of wfGetLangObj( 'en' )
+        * @return Language
         *
         * @see ContentHandler::getPageViewLanguage()
         */
        public function getPageViewLanguage( Title $title, Content $content = null ) {
-               return wfGetLangObj( 'en' );
+               return Language::factory( 'en' );
        }
 
        /**
index ebedb7e..ecd274b 100644 (file)
@@ -99,7 +99,7 @@ class RequestContext implements IContextSource, MutableContext {
                if ( $this->config === null ) {
                        // @todo In the future, we could move this to WebStart.php so
                        // the Config object is ready for when initialization happens
-                       $this->config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $this->config = MediaWikiServices::getInstance()->getMainConfig();
                }
 
                return $this->config;
index 7208b7e..2f9f809 100644 (file)
@@ -28,7 +28,7 @@
 /**
  * @ingroup Database
  */
-class DatabaseMssql extends DatabaseBase {
+class DatabaseMssql extends Database {
        protected $mInsertId = null;
        protected $mLastResult = null;
        protected $mAffectedRows = null;
index 561dadb..9258506 100644 (file)
@@ -131,7 +131,7 @@ class ORAResult {
 /**
  * @ingroup Database
  */
-class DatabaseOracle extends DatabaseBase {
+class DatabaseOracle extends Database {
        /** @var resource */
        protected $mLastResult = null;
 
index 42ef685..40418fd 100644 (file)
@@ -37,6 +37,8 @@ abstract class MWLBFactory {
        public static function applyDefaultConfig( array $lbConf, Config $mainConfig ) {
                global $wgCommandLineMode;
 
+               static $typesWithSchema = [ 'postgres', 'msssql' ];
+
                $lbConf += [
                        'localDomain' => new DatabaseDomain(
                                $mainConfig->get( 'DBname' ),
@@ -70,13 +72,18 @@ abstract class MWLBFactory {
                                                        'keywordTableMap' => [ 'user' => 'mwuser', 'text' => 'pagecontent' ]
                                                ];
                                        }
-                                       $lbConf['servers'][$i] = $server + [
-                                               'schema' => $mainConfig->get( 'DBmwschema' ),
+                                       if ( in_array( $server['type'], $typesWithSchema, true ) ) {
+                                               $server += [ 'schema' => $mainConfig->get( 'DBmwschema' ) ];
+                                       }
+
+                                       $server += [
                                                'tablePrefix' => $mainConfig->get( 'DBprefix' ),
                                                'flags' => DBO_DEFAULT,
                                                'sqlMode' => $mainConfig->get( 'SQLMode' ),
                                                'utf8Mode' => $mainConfig->get( 'DBmysql5' )
                                        ];
+
+                                       $lbConf['servers'][$i] = $server;
                                }
                        } else {
                                $flags = DBO_DEFAULT;
@@ -88,7 +95,6 @@ abstract class MWLBFactory {
                                        'user' => $mainConfig->get( 'DBuser' ),
                                        'password' => $mainConfig->get( 'DBpassword' ),
                                        'dbname' => $mainConfig->get( 'DBname' ),
-                                       'schema' => $mainConfig->get( 'DBmwschema' ),
                                        'tablePrefix' => $mainConfig->get( 'DBprefix' ),
                                        'type' => $mainConfig->get( 'DBtype' ),
                                        'load' => 1,
@@ -96,6 +102,9 @@ abstract class MWLBFactory {
                                        'sqlMode' => $mainConfig->get( 'SQLMode' ),
                                        'utf8Mode' => $mainConfig->get( 'DBmysql5' )
                                ];
+                               if ( in_array( $server['type'], $typesWithSchema, true ) ) {
+                                       $server += [ 'schema' => $mainConfig->get( 'DBmwschema' ) ];
+                               }
                                if ( $server['type'] === 'sqlite' ) {
                                        $server[ 'dbDirectory'] = $mainConfig->get( 'SQLiteDataDir' );
                                } elseif ( $server['type'] === 'postgres' ) {
@@ -110,7 +119,9 @@ abstract class MWLBFactory {
                        }
                } elseif ( $lbConf['class'] === 'LBFactoryMulti' ) {
                        if ( isset( $lbConf['serverTemplate'] ) ) {
-                               $lbConf['serverTemplate']['schema'] = $mainConfig->get( 'DBmwschema' );
+                               if ( in_array( $lbConf['serverTemplate']['type'], $typesWithSchema, true ) ) {
+                                       $lbConf['serverTemplate']['schema'] = $mainConfig->get( 'DBmwschema' );
+                               }
                                $lbConf['serverTemplate']['sqlMode'] = $mainConfig->get( 'SQLMode' );
                                $lbConf['serverTemplate']['utf8Mode'] = $mainConfig->get( 'DBmysql5' );
                        }
index 4d7c84d..4614c46 100644 (file)
@@ -327,7 +327,7 @@ class LegacyLogger extends AbstractLogger {
         * @param string $channel
         * @param string $message
         * @param array $context
-        * @return null
+        * @return string
         */
        protected static function formatAsWfDebugLog( $channel, $message, $context ) {
                $time = wfTimestamp( TS_DB );
diff --git a/includes/debug/logger/monolog/LogstashFormatter.php b/includes/debug/logger/monolog/LogstashFormatter.php
new file mode 100644 (file)
index 0000000..553cbf6
--- /dev/null
@@ -0,0 +1,83 @@
+<?php
+
+namespace MediaWiki\Logger\Monolog;
+
+/**
+ * LogstashFormatter squashes the base message array and the context and extras subarrays into one.
+ * This can result in unfortunately named context fields overwriting other data (T145133).
+ * This class modifies the standard LogstashFormatter to rename such fields and flag the message.
+ *
+ * Compatible with Monolog 1.x only.
+ *
+ * @since 1.29
+ */
+class LogstashFormatter extends \Monolog\Formatter\LogstashFormatter {
+       /** @var array Keys which should not be used in log context */
+       protected $reservedKeys = [
+               // from LogstashFormatter
+               'message', 'channel', 'level', 'type',
+               // from WebProcessor
+               'url', 'ip', 'http_method', 'server', 'referrer',
+               // from WikiProcessor
+               'host', 'wiki', 'reqId', 'mwversion',
+               // from config magic
+               'normalized_message',
+       ];
+
+       /**
+        * Prevent key conflicts
+        * @param array $record
+        * @return array
+        */
+       protected function formatV0( array $record ) {
+               if ( $this->contextPrefix ) {
+                       return parent::formatV0( $record );
+               }
+
+               $context = !empty( $record['context'] ) ? $record['context'] : [];
+               $record['context'] = [];
+               $formatted = parent::formatV0( $record );
+
+               $formatted['@fields'] = $this->fixKeyConflicts( $formatted['@fields'], $context );
+               return $formatted;
+       }
+
+       /**
+        * Prevent key conflicts
+        * @param array $record
+        * @return array
+        */
+       protected function formatV1( array $record ) {
+               if ( $this->contextPrefix ) {
+                       return parent::formatV1( $record );
+               }
+
+               $context = !empty( $record['context'] ) ? $record['context'] : [];
+               $record['context'] = [];
+               $formatted = parent::formatV1( $record );
+
+               $formatted = $this->fixKeyConflicts( $formatted, $context );
+               return $formatted;
+       }
+
+       /**
+        * Check whether some context field would overwrite another message key. If so, rename
+        * and flag.
+        * @param array $fields Fields to be sent to logstash
+        * @param array $context Copy of the original $record['context']
+        * @return array Updated version of $fields
+        */
+       protected function fixKeyConflicts( array $fields, array $context ) {
+               foreach ( $context as $key => $val ) {
+                       if (
+                               in_array( $key, $this->reservedKeys, true ) &&
+                               isset( $fields[$key] ) && $fields[$key] !== $val
+                       ) {
+                               $fields['logstash_formatter_key_conflict'][] = $key;
+                               $key = 'c_' . $key;
+                       }
+                       $fields[$key] = $val;
+               }
+               return $fields;
+       }
+}
index a5a8676..bd65fb4 100644 (file)
@@ -601,28 +601,7 @@ class DifferenceEngine extends ContextSource {
                        $out->setRevisionTimestamp( $this->mNewRev->getTimestamp() );
                        $out->setArticleFlag( true );
 
-                       // NOTE: only needed for B/C: custom rendering of JS/CSS via hook
-                       if ( $this->mNewPage->isCssJsSubpage() || $this->mNewPage->isCssOrJsPage() ) {
-                               // This needs to be synchronised with Article::showCssOrJsPage(), which sucks
-                               // Give hooks a chance to customise the output
-                               // @todo standardize this crap into one function
-                               if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', [ $this->mNewContent, $this->mNewPage, $out ], '1.24' ) ) {
-                                       // NOTE: deprecated hook, B/C only
-                                       // use the content object's own rendering
-                                       $cnt = $this->mNewRev->getContent();
-                                       $po = $cnt ? $cnt->getParserOutput( $this->mNewRev->getTitle(), $this->mNewRev->getId() ) : null;
-                                       if ( $po ) {
-                                               $out->addParserOutputContent( $po );
-                                       }
-                               }
-                       } elseif ( !Hooks::run( 'ArticleContentViewCustom', [ $this->mNewContent, $this->mNewPage, $out ] ) ) {
-                               // Handled by extension
-                       } elseif ( !ContentHandler::runLegacyHooks(
-                               'ArticleViewCustom',
-                               [ $this->mNewContent, $this->mNewPage, $out ],
-                               '1.21'
-                       ) ) {
-                               // NOTE: deprecated hook, B/C only
+                       if ( !Hooks::run( 'ArticleContentViewCustom', [ $this->mNewContent, $this->mNewPage, $out ] ) ) {
                                // Handled by extension
                        } else {
                                // Normal page
index 8fdc417..b600f42 100644 (file)
@@ -60,9 +60,10 @@ class MWExceptionRenderer {
                                                        MWExceptionHandler::getLogMessage( $eNew ) .
                                                "\nBacktrace:\n" . MWExceptionHandler::getRedactedTraceAsString( $eNew );
                                } else {
-                                       $message .= "Exception caught inside exception handler.\n\n" .
-                                               "Set \$wgShowExceptionDetails = true; at the bottom of LocalSettings.php " .
-                                               "to show detailed debugging information.";
+                                       $message .= 'Original exception: ' .
+                                               MWExceptionHandler::getPublicLogMessage( $e );
+                                       $message .= "\n\nException caught inside exception handler.\n\n" .
+                                               self::getShowBacktraceError( $e );
                                }
                                $message .= "\n";
                        } else {
@@ -74,11 +75,7 @@ class MWExceptionRenderer {
                                        $message = MWExceptionHandler::getPublicLogMessage( $e );
                                }
                        }
-                       if ( self::isCommandLine() ) {
-                               self::printError( $message );
-                       } else {
-                               echo nl2br( htmlspecialchars( $message ) ) . "\n";
-                       }
+                       echo nl2br( htmlspecialchars( $message ) ) . "\n";
                }
        }
 
@@ -226,9 +223,7 @@ class MWExceptionRenderer {
                                        $logId,
                                        MWExceptionHandler::getURL()
                                ) . "</div>\n" .
-                       "<!-- Set \$wgShowExceptionDetails = true; " .
-                       "at the bottom of LocalSettings.php to show detailed " .
-                       "debugging information. -->";
+                               "<!-- " . wordwrap( self::getShowBacktraceError( $e ), 50 ) . " -->";
                }
 
                return $html;
@@ -262,8 +257,7 @@ class MWExceptionRenderer {
                                "\nBacktrace:\n" .
                                MWExceptionHandler::getRedactedTraceAsString( $e ) . "\n";
                } else {
-                       return "Set \$wgShowExceptionDetails = true; " .
-                               "in LocalSettings.php to show detailed debugging information.\n";
+                       return self::getShowBacktraceError( $e );
                }
        }
 
@@ -280,6 +274,23 @@ class MWExceptionRenderer {
                );
        }
 
+       /**
+        * @param Exception|Throwable $e
+        * @return string
+        */
+       private static function getShowBacktraceError( $e ) {
+               global $wgShowExceptionDetails, $wgShowDBErrorBacktrace;
+               $vars = [];
+               if ( !$wgShowExceptionDetails ) {
+                       $vars[] = '$wgShowExceptionDetails = true;';
+               }
+               if ( $e instanceof DBError && !$wgShowDBErrorBacktrace ) {
+                       $vars[] = '$wgShowDBErrorBacktrace = true;';
+               }
+               $vars = implode( ' and ', $vars );
+               return "Set $vars at the bottom of LocalSettings.php to show detailed debugging information";
+       }
+
        /**
         * @return bool
         */
index 7fb7a0e..f49ef88 100644 (file)
@@ -89,7 +89,7 @@ class ForeignDBRepo extends LocalRepo {
        /**
         * @return IDatabase
         */
-       function getSlaveDB() {
+       function getReplicaDB() {
                return $this->getMasterDB();
        }
 
index 129d55a..a9cd030 100644 (file)
@@ -65,7 +65,7 @@ class ForeignDBViaLBRepo extends LocalRepo {
        /**
         * @return IDatabase
         */
-       function getSlaveDB() {
+       function getReplicaDB() {
                return wfGetLB( $this->wiki )->getConnectionRef( DB_REPLICA, [], $this->wiki );
        }
 
index c4730d7..d49ae7b 100644 (file)
@@ -200,7 +200,7 @@ class LocalRepo extends FileRepo {
                        $memcKey,
                        $expiry,
                        function ( $oldValue, &$ttl, array &$setOpts ) use ( $method, $title ) {
-                               $dbr = $this->getSlaveDB(); // possibly remote DB
+                               $dbr = $this->getReplicaDB(); // possibly remote DB
 
                                $setOpts += Database::getCacheSetOptions( $dbr );
 
@@ -298,7 +298,7 @@ class LocalRepo extends FileRepo {
                        }
                };
 
-               $dbr = $this->getSlaveDB();
+               $dbr = $this->getReplicaDB();
 
                // Query image table
                $imgNames = [];
@@ -368,7 +368,7 @@ class LocalRepo extends FileRepo {
         * @return File[]
         */
        function findBySha1( $hash ) {
-               $dbr = $this->getSlaveDB();
+               $dbr = $this->getReplicaDB();
                $res = $dbr->select(
                        'image',
                        LocalFile::selectFields(),
@@ -400,7 +400,7 @@ class LocalRepo extends FileRepo {
                        return []; // empty parameter
                }
 
-               $dbr = $this->getSlaveDB();
+               $dbr = $this->getReplicaDB();
                $res = $dbr->select(
                        'image',
                        LocalFile::selectFields(),
@@ -430,7 +430,7 @@ class LocalRepo extends FileRepo {
                $selectOptions = [ 'ORDER BY' => 'img_name', 'LIMIT' => intval( $limit ) ];
 
                // Query database
-               $dbr = $this->getSlaveDB();
+               $dbr = $this->getReplicaDB();
                $res = $dbr->select(
                        'image',
                        LocalFile::selectFields(),
@@ -452,10 +452,20 @@ class LocalRepo extends FileRepo {
         * Get a connection to the replica DB
         * @return IDatabase
         */
-       function getSlaveDB() {
+       function getReplicaDB() {
                return wfGetDB( DB_REPLICA );
        }
 
+       /**
+        * Alias for getReplicaDB()
+        *
+        * @return IDatabase
+        * @deprecated Since 1.29
+        */
+       function getSlaveDB() {
+               return $this->getReplicaDB();
+       }
+
        /**
         * Get a connection to the master DB
         * @return IDatabase
index c1d5573..9188cd9 100644 (file)
@@ -1018,7 +1018,7 @@ abstract class File implements IDBAccessObject {
                        return $handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
                } else {
                        return new MediaTransformError( 'thumbnail_error',
-                               $params['width'], 0, wfMessage( 'thumbnail-dest-create' )->text() );
+                               $params['width'], 0, wfMessage( 'thumbnail-dest-create' ) );
                }
        }
 
index c041dea..df50a67 100644 (file)
@@ -136,7 +136,7 @@ class ForeignDBFile extends LocalFile {
                        return false;
                }
 
-               $touched = $this->repo->getSlaveDB()->selectField(
+               $touched = $this->repo->getReplicaDB()->selectField(
                        'page',
                        'page_touched',
                        [
@@ -179,7 +179,7 @@ class ForeignDBFile extends LocalFile {
         * @since 1.27
         */
        public function getDescriptionShortUrl() {
-               $dbr = $this->repo->getSlaveDB();
+               $dbr = $this->repo->getReplicaDB();
                $pageId = $dbr->selectField(
                        'page',
                        'page_id',
index d3a14fa..011ba87 100644 (file)
@@ -174,7 +174,7 @@ class LocalFile extends File {
         * @return bool|LocalFile
         */
        static function newFromKey( $sha1, $repo, $timestamp = false ) {
-               $dbr = $repo->getSlaveDB();
+               $dbr = $repo->getReplicaDB();
 
                $conds = [ 'img_sha1' => $sha1 ];
                if ( $timestamp ) {
@@ -259,7 +259,7 @@ class LocalFile extends File {
                        $key,
                        $cache::TTL_WEEK,
                        function ( $oldValue, &$ttl, array &$setOpts ) use ( $cache ) {
-                               $setOpts += Database::getCacheSetOptions( $this->repo->getSlaveDB() );
+                               $setOpts += Database::getCacheSetOptions( $this->repo->getReplicaDB() );
 
                                $this->loadFromDB( self::READ_NORMAL );
 
@@ -390,7 +390,7 @@ class LocalFile extends File {
 
                $dbr = ( $flags & self::READ_LATEST )
                        ? $this->repo->getMasterDB()
-                       : $this->repo->getSlaveDB();
+                       : $this->repo->getReplicaDB();
 
                $row = $dbr->selectRow( 'image', $this->getCacheFields( 'img_' ),
                        [ 'img_name' => $this->getName() ], $fname );
@@ -412,7 +412,7 @@ class LocalFile extends File {
                # Unconditionally set loaded=true, we don't want the accessors constantly rechecking
                $this->extraDataLoaded = true;
 
-               $fieldMap = $this->loadFieldsWithTimestamp( $this->repo->getSlaveDB(), $fname );
+               $fieldMap = $this->loadFieldsWithTimestamp( $this->repo->getReplicaDB(), $fname );
                if ( !$fieldMap ) {
                        $fieldMap = $this->loadFieldsWithTimestamp( $this->repo->getMasterDB(), $fname );
                }
@@ -490,7 +490,7 @@ class LocalFile extends File {
 
                $decoded['timestamp'] = wfTimestamp( TS_MW, $decoded['timestamp'] );
 
-               $decoded['metadata'] = $this->repo->getSlaveDB()->decodeBlob( $decoded['metadata'] );
+               $decoded['metadata'] = $this->repo->getReplicaDB()->decodeBlob( $decoded['metadata'] );
 
                if ( empty( $decoded['major_mime'] ) ) {
                        $decoded['mime'] = 'unknown/unknown';
@@ -1037,7 +1037,7 @@ class LocalFile extends File {
         * @return OldLocalFile[]
         */
        function getHistory( $limit = null, $start = null, $end = null, $inc = true ) {
-               $dbr = $this->repo->getSlaveDB();
+               $dbr = $this->repo->getReplicaDB();
                $tables = [ 'oldimage' ];
                $fields = OldLocalFile::selectFields();
                $conds = $opts = $join_conds = [];
@@ -1091,7 +1091,7 @@ class LocalFile extends File {
                # Polymorphic function name to distinguish foreign and local fetches
                $fname = get_class( $this ) . '::' . __FUNCTION__;
 
-               $dbr = $this->repo->getSlaveDB();
+               $dbr = $this->repo->getReplicaDB();
 
                if ( $this->historyLine == 0 ) { // called for the first time, return line from cur
                        $this->historyRes = $dbr->select( 'image',
@@ -1917,7 +1917,7 @@ class LocalFile extends File {
                                'page_namespace' => $this->title->getNamespace(),
                                'page_title' => $this->title->getDBkey()
                        ];
-                       $touched = $this->repo->getSlaveDB()->selectField( 'page', 'page_touched', $cond, __METHOD__ );
+                       $touched = $this->repo->getReplicaDB()->selectField( 'page', 'page_touched', $cond, __METHOD__ );
                        $this->descriptionTouched = $touched ? wfTimestamp( TS_MW, $touched ) : false;
                }
 
index 06fef4f..dfaae73 100644 (file)
@@ -86,7 +86,7 @@ class OldLocalFile extends LocalFile {
         * @return bool|OldLocalFile
         */
        static function newFromKey( $sha1, $repo, $timestamp = false ) {
-               $dbr = $repo->getSlaveDB();
+               $dbr = $repo->getReplicaDB();
 
                $conds = [ 'oi_sha1' => $sha1 ];
                if ( $timestamp ) {
@@ -179,7 +179,7 @@ class OldLocalFile extends LocalFile {
 
                $dbr = ( $flags & self::READ_LATEST )
                        ? $this->repo->getMasterDB()
-                       : $this->repo->getSlaveDB();
+                       : $this->repo->getReplicaDB();
 
                $conds = [ 'oi_name' => $this->getName() ];
                if ( is_null( $this->requestedTime ) ) {
@@ -201,7 +201,7 @@ class OldLocalFile extends LocalFile {
         */
        protected function loadExtraFromDB() {
                $this->extraDataLoaded = true;
-               $dbr = $this->repo->getSlaveDB();
+               $dbr = $this->repo->getReplicaDB();
                $conds = [ 'oi_name' => $this->getName() ];
                if ( is_null( $this->requestedTime ) ) {
                        $conds['oi_archive_name'] = $this->archive_name;
index cadb502..71ccaa3 100644 (file)
@@ -604,10 +604,14 @@ class HTMLForm extends ContextSource {
         */
        public function trySubmit() {
                $valid = true;
-               $hoistedErrors = [];
-               $hoistedErrors[] = isset( $this->mValidationErrorMessage )
-                       ? $this->mValidationErrorMessage
-                       : [ 'htmlform-invalid-input' ];
+               $hoistedErrors = Status::newGood();
+               if ( $this->mValidationErrorMessage ) {
+                       foreach ( (array)$this->mValidationErrorMessage as $error ) {
+                               call_user_func_array( [ $hoistedErrors, 'fatal' ], $error );
+                       }
+               } else {
+                       $hoistedErrors->fatal( 'htmlform-invalid-input' );
+               }
 
                $this->mWasSubmitted = true;
 
@@ -634,15 +638,16 @@ class HTMLForm extends ContextSource {
                        if ( $res !== true ) {
                                $valid = false;
                                if ( $res !== false && !$field->canDisplayErrors() ) {
-                                       $hoistedErrors[] = [ 'rawmessage', $res ];
+                                       if ( is_string( $res ) ) {
+                                               $hoistedErrors->fatal( 'rawmessage', $res );
+                                       } else {
+                                               $hoistedErrors->fatal( $res );
+                                       }
                                }
                        }
                }
 
                if ( !$valid ) {
-                       if ( count( $hoistedErrors ) === 1 ) {
-                               $hoistedErrors = $hoistedErrors[0];
-                       }
                        return $hoistedErrors;
                }
 
index 8390a0b..71aa275 100644 (file)
@@ -296,7 +296,7 @@ abstract class HTMLFormField {
         * @param string|array $value The value the field was submitted with
         * @param array $alldata The data collected from the form
         *
-        * @return bool|string True on success, or String error to display, or
+        * @return bool|string|Message True on success, or String/Message error to display, or
         *   false to fail validation without displaying an error.
         */
        public function validate( $value, $alldata ) {
@@ -308,7 +308,7 @@ abstract class HTMLFormField {
                        && $this->mParams['required'] !== false
                        && $value === ''
                ) {
-                       return $this->msg( 'htmlform-required' )->parse();
+                       return $this->msg( 'htmlform-required' );
                }
 
                if ( isset( $this->mValidationCallback ) ) {
index 0f86ee8..63e77ce 100644 (file)
  *   options-messages - As for HTMLSelectField
  *   options - As for HTMLSelectField
  *   options-message - As for HTMLSelectField
- *   autocomplete - Associative array mapping display text to values.
- *   autocomplete-messages - Like autocomplete, but keys are message names.
+ *   autocomplete-data - Associative array mapping display text to values.
+ *   autocomplete-data-messages - Like autocomplete, but keys are message names.
  *   require-match - Boolean, if true the value must be in the options or the
  *     autocomplete.
  *   other-message - Message to use instead of htmlform-selectorother-other for
  *      the 'other' message.
  *   other - Raw text to use for the 'other' message
+ *
+ * The old name of autocomplete-data[-messages] was autocomplete[-messages] which is still
+ * recognized but deprecated since MediaWiki 1.29 since it conflicts with how autocomplete is
+ * used in HTMLTextField.
  */
 class HTMLAutoCompleteSelectField extends HTMLTextField {
-       protected $autocomplete = [];
+       protected $autocompleteData = [];
 
        public function __construct( $params ) {
                $params += [
                        'require-match' => false,
                ];
 
+               // FIXME B/C, remove in 1.30
+               if (
+                       array_key_exists( 'autocomplete', $params )
+                       && !array_key_exists( 'autocomplete-data', $params )
+               ) {
+                       $params['autocomplete-data'] = $params['autocomplete'];
+                       unset( $params['autocomplete'] );
+               }
+               if (
+                       array_key_exists( 'autocomplete-messages', $params )
+                       && !array_key_exists( 'autocomplete-data-messages', $params )
+               ) {
+                       $params['autocomplete-data-messages'] = $params['autocomplete-messages'];
+                       unset( $params['autocomplete-messages'] );
+               }
+
                parent::__construct( $params );
 
-               if ( array_key_exists( 'autocomplete-messages', $this->mParams ) ) {
-                       foreach ( $this->mParams['autocomplete-messages'] as $key => $value ) {
+               if ( array_key_exists( 'autocomplete-data-messages', $this->mParams ) ) {
+                       foreach ( $this->mParams['autocomplete-data-messages'] as $key => $value ) {
                                $key = $this->msg( $key )->plain();
-                               $this->autocomplete[$key] = strval( $value );
+                               $this->autocompleteData[$key] = strval( $value );
                        }
-               } elseif ( array_key_exists( 'autocomplete', $this->mParams ) ) {
-                       foreach ( $this->mParams['autocomplete'] as $key => $value ) {
-                               $this->autocomplete[$key] = strval( $value );
+               } elseif ( array_key_exists( 'autocomplete-data', $this->mParams ) ) {
+                       foreach ( $this->mParams['autocomplete-data'] as $key => $value ) {
+                               $this->autocompleteData[$key] = strval( $value );
                        }
                }
-               if ( !is_array( $this->autocomplete ) || !$this->autocomplete ) {
+               if ( !is_array( $this->autocompleteData ) || !$this->autocompleteData ) {
                        throw new MWException( 'HTMLAutoCompleteSelectField called without any autocompletions' );
                }
 
@@ -69,8 +89,8 @@ class HTMLAutoCompleteSelectField extends HTMLTextField {
 
                        if ( $val === 'other' ) {
                                $val = $request->getText( $this->mName );
-                               if ( isset( $this->autocomplete[$val] ) ) {
-                                       $val = $this->autocomplete[$val];
+                               if ( isset( $this->autocompleteData[$val] ) ) {
+                                       $val = $this->autocompleteData[$val];
                                }
                        }
 
@@ -87,14 +107,14 @@ class HTMLAutoCompleteSelectField extends HTMLTextField {
                        return $p;
                }
 
-               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
+               $validOptions = HTMLFormField::flattenOptions( $this->getOptions() ?: [] );
 
                if ( in_array( strval( $value ), $validOptions, true ) ) {
                        return true;
-               } elseif ( in_array( strval( $value ), $this->autocomplete, true ) ) {
+               } elseif ( in_array( strval( $value ), $this->autocompleteData, true ) ) {
                        return true;
                } elseif ( $this->mParams['require-match'] ) {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
+                       return $this->msg( 'htmlform-select-badoption' );
                }
 
                return true;
@@ -104,7 +124,7 @@ class HTMLAutoCompleteSelectField extends HTMLTextField {
        public function getAttributes( array $list ) {
                $attribs = [
                        'type' => 'text',
-                       'data-autocomplete' => FormatJson::encode( array_keys( $this->autocomplete ) ),
+                       'data-autocomplete' => FormatJson::encode( array_keys( $this->autocompleteData ) ),
                ] + parent::getAttributes( $list );
 
                if ( $this->getOptions() ) {
@@ -152,7 +172,7 @@ class HTMLAutoCompleteSelectField extends HTMLTextField {
                if ( $valInSelect ) {
                        $value = '';
                } else {
-                       $key = array_search( strval( $value ), $this->autocomplete, true );
+                       $key = array_search( strval( $value ), $this->autocompleteData, true );
                        if ( $key !== false ) {
                                $value = $key;
                        }
index 64fe7ed..285490b 100644 (file)
@@ -113,7 +113,7 @@ class HTMLButtonField extends HTMLFormField {
         * @param string $value
         * @param array $alldata
         *
-        * @return bool
+        * @return bool|string|Message
         */
        public function validate( $value, $alldata ) {
                return true;
index 890cd7c..46172a5 100644 (file)
@@ -65,7 +65,7 @@ class HTMLCheckMatrix extends HTMLFormField implements HTMLNestedFilterable {
                if ( count( $validValues ) == count( $value ) ) {
                        return true;
                } else {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
+                       return $this->msg( 'htmlform-select-badoption' );
                }
        }
 
index 88dcd24..b43080c 100644 (file)
@@ -36,6 +36,11 @@ class HTMLDateTimeField extends HTMLTextField {
                        throw new InvalidArgumentException( "Invalid type '$this->mType'" );
                }
 
+               if ( $this->mPlaceholder === '' ) {
+                       // Messages: htmlform-date-placeholder htmlform-time-placeholder htmlform-datetime-placeholder
+                       $this->mPlaceholder = $this->msg( "htmlform-{$this->mType}-placeholder" )->text();
+               }
+
                $this->mClass .= ' mw-htmlform-datetime-field';
        }
 
@@ -43,11 +48,6 @@ class HTMLDateTimeField extends HTMLTextField {
                $parentList = array_diff( $list, [ 'min', 'max' ] );
                $ret = parent::getAttributes( $parentList );
 
-               if ( in_array( 'placeholder', $list ) && !isset( $ret['placeholder'] ) ) {
-                       // Messages: htmlform-date-placeholder htmlform-time-placeholder htmlform-datetime-placeholder
-                       $ret['placeholder'] = $this->msg( "htmlform-{$this->mType}-placeholder" )->text();
-               }
-
                if ( in_array( 'min', $list ) && isset( $this->mParams['min'] ) ) {
                        $min = $this->parseDate( $this->mParams['min'] );
                        if ( $min ) {
@@ -100,15 +100,14 @@ class HTMLDateTimeField extends HTMLTextField {
                $date = $this->parseDate( $value );
                if ( !$date ) {
                        // Messages: htmlform-date-invalid htmlform-time-invalid htmlform-datetime-invalid
-                       return $this->msg( "htmlform-{$this->mType}-invalid" )->parseAsBlock();
+                       return $this->msg( "htmlform-{$this->mType}-invalid" );
                }
 
                if ( isset( $this->mParams['min'] ) ) {
                        $min = $this->parseDate( $this->mParams['min'] );
                        if ( $min && $date < $min ) {
                                // Messages: htmlform-date-toolow htmlform-time-toolow htmlform-datetime-toolow
-                               return $this->msg( "htmlform-{$this->mType}-toolow", $this->formatDate( $min ) )
-                                       ->parseAsBlock();
+                               return $this->msg( "htmlform-{$this->mType}-toolow", $this->formatDate( $min ) );
                        }
                }
 
@@ -116,8 +115,7 @@ class HTMLDateTimeField extends HTMLTextField {
                        $max = $this->parseDate( $this->mParams['max'] );
                        if ( $max && $date > $max ) {
                                // Messages: htmlform-date-toohigh htmlform-time-toohigh htmlform-datetime-toohigh
-                               return $this->msg( "htmlform-{$this->mType}-toohigh", $this->formatDate( $max ) )
-                                       ->parseAsBlock();
+                               return $this->msg( "htmlform-{$this->mType}-toohigh", $this->formatDate( $max ) );
                        }
                }
 
index d1250c0..d2d54e2 100644 (file)
@@ -20,7 +20,7 @@ class HTMLFloatField extends HTMLTextField {
                # https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
                # with the addition that a leading '+' sign is ok.
                if ( !preg_match( '/^((\+|\-)?\d+(\.\d+)?(E(\+|\-)?\d+)?)?$/i', $value ) ) {
-                       return $this->msg( 'htmlform-float-invalid' )->parseAsBlock();
+                       return $this->msg( 'htmlform-float-invalid' );
                }
 
                # The "int" part of these message names is rather confusing.
@@ -29,7 +29,7 @@ class HTMLFloatField extends HTMLTextField {
                        $min = $this->mParams['min'];
 
                        if ( $min > $value ) {
-                               return $this->msg( 'htmlform-int-toolow', $min )->parseAsBlock();
+                               return $this->msg( 'htmlform-int-toolow', $min );
                        }
                }
 
@@ -37,7 +37,7 @@ class HTMLFloatField extends HTMLTextField {
                        $max = $this->mParams['max'];
 
                        if ( $max < $value ) {
-                               return $this->msg( 'htmlform-int-toohigh', $max )->parseAsBlock();
+                               return $this->msg( 'htmlform-int-toohigh', $max );
                        }
                }
 
index 5d8f491..a871584 100644 (file)
@@ -224,7 +224,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
                        && $this->mParams['required'] !== false
                        && !$values
                ) {
-                       return $this->msg( 'htmlform-cloner-required' )->parseAsBlock();
+                       return $this->msg( 'htmlform-cloner-required' );
                }
 
                if ( isset( $values['nonjs'] ) ) {
@@ -240,6 +240,9 @@ class HTMLFormFieldCloner extends HTMLFormField {
                                if ( !array_key_exists( $fieldname, $value ) ) {
                                        continue;
                                }
+                               if ( $field->isHidden( $alldata ) ) {
+                                       continue;
+                               }
                                $ok = $field->validate( $value[$fieldname], $alldata );
                                if ( $ok !== true ) {
                                        return false;
index c87a778..02af7de 100644 (file)
@@ -18,7 +18,7 @@ class HTMLIntField extends HTMLFloatField {
                # input does not require its value to be numeric).  If you want a tidier
                # value to, eg, save in the DB, clean it up with intval().
                if ( !preg_match( '/^((\+|\-)?\d+)?$/', trim( $value ) ) ) {
-                       return $this->msg( 'htmlform-int-invalid' )->parseAsBlock();
+                       return $this->msg( 'htmlform-int-invalid' );
                }
 
                return true;
index 58de763..05a2ba6 100644 (file)
@@ -46,7 +46,7 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
                if ( count( $validValues ) == count( $value ) ) {
                        return true;
                } else {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
+                       return $this->msg( 'htmlform-select-badoption' );
                }
        }
 
index 69dc617..06ec372 100644 (file)
@@ -27,7 +27,7 @@ class HTMLRadioField extends HTMLFormField {
                }
 
                if ( !is_string( $value ) && !is_int( $value ) ) {
-                       return $this->msg( 'htmlform-required' )->parse();
+                       return $this->msg( 'htmlform-required' );
                }
 
                $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
@@ -35,7 +35,7 @@ class HTMLRadioField extends HTMLFormField {
                if ( in_array( strval( $value ), $validOptions, true ) ) {
                        return true;
                } else {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
+                       return $this->msg( 'htmlform-select-badoption' );
                }
        }
 
index 5a18025..dbf2c8f 100644 (file)
@@ -61,7 +61,7 @@ class HTMLRestrictionsField extends HTMLTextAreaField {
         * @param string|MWRestrictions $value The value the field was submitted with
         * @param array $alldata The data collected from the form
         *
-        * @return bool|string True on success, or String error to display, or
+        * @return bool|string|Message True on success, or String/Message error to display, or
         *   false to fail validation without displaying an error.
         */
        public function validate( $value, $alldata ) {
@@ -73,7 +73,7 @@ class HTMLRestrictionsField extends HTMLTextAreaField {
                        isset( $this->mParams['required'] ) && $this->mParams['required'] !== false
                        && $value instanceof MWRestrictions && !$value->toArray()['IPAddresses']
                ) {
-                       return $this->msg( 'htmlform-required' )->parse();
+                       return $this->msg( 'htmlform-required' );
                }
 
                if ( is_string( $value ) ) {
@@ -87,7 +87,7 @@ class HTMLRestrictionsField extends HTMLTextAreaField {
                        if ( $status->isOK() ) {
                                $status->fatal( 'unknown-error' );
                        }
-                       return $status->getMessage()->parse();
+                       return $status->getMessage();
                }
 
                if ( isset( $this->mValidationCallback ) ) {
index 86e8e75..9af60e5 100644 (file)
@@ -125,7 +125,7 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
                        && $this->mParams['required'] !== false
                        && $value[1] === ''
                ) {
-                       return $this->msg( 'htmlform-required' )->parse();
+                       return $this->msg( 'htmlform-required' );
                }
 
                return true;
index c1f8e42..18c741b 100644 (file)
@@ -16,7 +16,7 @@ class HTMLSelectField extends HTMLFormField {
                if ( in_array( strval( $value ), $validOptions, true ) ) {
                        return true;
                } else {
-                       return $this->msg( 'htmlform-select-badoption' )->parse();
+                       return $this->msg( 'htmlform-select-badoption' );
                }
        }
 
index 88f5ec5..c3da746 100644 (file)
@@ -1,8 +1,19 @@
 <?php
 
+/**
+ * <input> field.
+ *
+ * Besides the parameters recognized by HTMLFormField, the following are
+ * recognized:
+ *   autocomplete - HTML autocomplete value (a boolean for on/off or a string according to
+ *     https://html.spec.whatwg.org/multipage/forms.html#autofill )
+ */
 class HTMLTextField extends HTMLFormField {
        protected $mPlaceholder = '';
 
+       /** @var bool HTML autocomplete attribute */
+       protected $autocomplete;
+
        /**
         * @param array $params
         *   - type: HTML textfield type
@@ -13,6 +24,10 @@ class HTMLTextField extends HTMLFormField {
         *     for password fields)
         */
        public function __construct( $params ) {
+               if ( isset( $params['autocomplete'] ) && is_bool( $params['autocomplete'] ) ) {
+                       $params['autocomplete'] = $params['autocomplete'] ? 'on' : 'off';
+               }
+
                parent::__construct( $params );
 
                if ( isset( $params['placeholder-message'] ) ) {
@@ -80,7 +95,8 @@ class HTMLTextField extends HTMLFormField {
                        'required',
                        'autofocus',
                        'multiple',
-                       'readonly'
+                       'readonly',
+                       'autocomplete',
                ];
 
                $attribs += $this->getAttributes( $allowedParams );
@@ -146,12 +162,24 @@ class HTMLTextField extends HTMLFormField {
                        'required',
                        'tabindex',
                        'type',
+                       'autocomplete',
                ];
 
                $attribs += OOUI\Element::configFromHtmlAttributes(
                        $this->getAttributes( $allowedParams )
                );
 
+               // FIXME T150983 downgrade autocomplete
+               if ( isset( $attribs['autocomplete'] ) ) {
+                       if ( $attribs['autocomplete'] === 'on' ) {
+                               $attribs['autocomplete'] = true;
+                       } elseif ( $attribs['autocomplete'] === 'off' ) {
+                               $attribs['autocomplete'] = false;
+                       } else {
+                               unset( $attribs['autocomplete'] );
+                       }
+               }
+
                $type = $this->getType( $attribs );
 
                return $this->getInputWidget( [
index a15b90e..3eb3f5d 100644 (file)
@@ -51,22 +51,22 @@ class HTMLTitleTextField extends HTMLTextField {
                        if ( $params ) {
                                $msg->params( $params );
                        }
-                       return $msg->parse();
+                       return $msg;
                }
 
                $text = $title->getPrefixedText();
                if ( $this->mParams['namespace'] !== false &&
                        !$title->inNamespace( $this->mParams['namespace'] )
                ) {
-                       return $this->msg( 'htmlform-title-badnamespace', $this->mParams['namespace'], $text )->parse();
+                       return $this->msg( 'htmlform-title-badnamespace', $this->mParams['namespace'], $text );
                }
 
                if ( $this->mParams['creatable'] && !$title->canExist() ) {
-                       return $this->msg( 'htmlform-title-not-creatable', $text )->escaped();
+                       return $this->msg( 'htmlform-title-not-creatable', $text );
                }
 
                if ( $this->mParams['exists'] && !$title->exists() ) {
-                       return $this->msg( 'htmlform-title-not-exists', $text )->parse();
+                       return $this->msg( 'htmlform-title-not-exists', $text );
                }
 
                return parent::validate( $value, $alldata );
index 14b5e59..12c09c1 100644 (file)
@@ -28,12 +28,12 @@ class HTMLUserTextField extends HTMLTextField {
                $user = User::newFromName( $value, false );
 
                if ( !$user ) {
-                       return $this->msg( 'htmlform-user-not-valid', $value )->parse();
+                       return $this->msg( 'htmlform-user-not-valid', $value );
                } elseif (
                        ( $this->mParams['exists'] && $user->getId() === 0 ) &&
                        !( $this->mParams['ipallowed'] && User::isIP( $value ) )
                ) {
-                       return $this->msg( 'htmlform-user-not-exists', $user->getName() )->parse();
+                       return $this->msg( 'htmlform-user-not-exists', $user->getName() );
                }
 
                return parent::validate( $value, $alldata );
index f58c3a9..7fd3e83 100644 (file)
@@ -38,11 +38,10 @@ class CurlHttpRequest extends MWHttpRequest {
        }
 
        public function execute() {
-
-               parent::execute();
+               $this->prepare();
 
                if ( !$this->status->isOK() ) {
-                       return $this->status;
+                       return Status::wrap( $this->status ); // TODO B/C; move this to callers
                }
 
                $this->curlOptions[CURLOPT_PROXY] = $this->proxy;
@@ -102,7 +101,7 @@ class CurlHttpRequest extends MWHttpRequest {
                $curlHandle = curl_init( $this->url );
 
                if ( !curl_setopt_array( $curlHandle, $this->curlOptions ) ) {
-                       throw new MWException( "Error setting curl options." );
+                       throw new InvalidArgumentException( "Error setting curl options." );
                }
 
                if ( $this->followRedirects && $this->canFollowRedirects() ) {
@@ -140,7 +139,7 @@ class CurlHttpRequest extends MWHttpRequest {
                $this->parseHeader();
                $this->setStatus();
 
-               return $this->status;
+               return Status::wrap( $this->status );  // TODO B/C; move this to callers
        }
 
        /**
index 43ae2d0..8255bb3 100644 (file)
@@ -51,6 +51,8 @@ class Http {
         *    - userAgent           A user agent, if you want to override the default
         *                          MediaWiki/$wgVersion
         *    - logger              A \Psr\Logger\LoggerInterface instance for debug logging
+        *    - username            Username for HTTP Basic Authentication
+        *    - password            Password for HTTP Basic Authentication
         * @param string $caller The method making this request, for profiling
         * @return string|bool (bool)false on failure or a string on success
         */
@@ -74,7 +76,7 @@ class Http {
                } else {
                        $errors = $status->getErrorsByType( 'error' );
                        $logger = LoggerFactory::getInstance( 'http' );
-                       $logger->warning( $status->getWikiText( false, false, 'en' ),
+                       $logger->warning( Status::wrap( $status )->getWikiText( false, false, 'en' ),
                                [ 'error' => $errors, 'caller' => $caller, 'content' => $req->getContent() ] );
                        return false;
                }
index 08883ae..fac052f 100644 (file)
@@ -46,9 +46,11 @@ class MWHttpRequest implements LoggerAwareInterface {
        protected $reqHeaders = [];
        protected $url;
        protected $parsedUrl;
+       /** @var callable  */
        protected $callback;
        protected $maxRedirects = 5;
        protected $followRedirects = false;
+       protected $connectTimeout;
 
        /**
         * @var CookieJar
@@ -60,7 +62,8 @@ class MWHttpRequest implements LoggerAwareInterface {
        protected $respStatus = "200 Ok";
        protected $respHeaders = [];
 
-       public $status;
+       /** @var StatusValue */
+       protected $status;
 
        /**
         * @var Profiler
@@ -98,9 +101,9 @@ class MWHttpRequest implements LoggerAwareInterface {
                }
 
                if ( !$this->parsedUrl || !Http::isValidURI( $this->url ) ) {
-                       $this->status = Status::newFatal( 'http-invalid-url', $url );
+                       $this->status = StatusValue::newFatal( 'http-invalid-url', $url );
                } else {
-                       $this->status = Status::newGood( 100 ); // continue
+                       $this->status = StatusValue::newGood( 100 ); // continue
                }
 
                if ( isset( $options['timeout'] ) && $options['timeout'] != 'default' ) {
@@ -116,6 +119,12 @@ class MWHttpRequest implements LoggerAwareInterface {
                if ( isset( $options['userAgent'] ) ) {
                        $this->setUserAgent( $options['userAgent'] );
                }
+               if ( isset( $options['username'] ) && isset( $options['password'] ) ) {
+                       $this->setHeader(
+                               'Authorization',
+                               'Basic ' . base64_encode( $options['username'] . ':' . $options['password'] )
+                       );
+               }
 
                $members = [ "postData", "proxy", "noProxy", "sslVerifyHost", "caInfo",
                                "method", "followRedirects", "maxRedirects", "sslVerifyCert", "callback" ];
@@ -161,7 +170,7 @@ class MWHttpRequest implements LoggerAwareInterface {
         * @param string $url Url to use
         * @param array $options (optional) extra params to pass (see Http::request())
         * @param string $caller The method making this request, for profiling
-        * @throws MWException
+        * @throws DomainException
         * @return CurlHttpRequest|PhpHttpRequest
         * @see MWHttpRequest::__construct
         */
@@ -169,7 +178,7 @@ class MWHttpRequest implements LoggerAwareInterface {
                if ( !Http::$httpEngine ) {
                        Http::$httpEngine = function_exists( 'curl_init' ) ? 'curl' : 'php';
                } elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) {
-                       throw new MWException( __METHOD__ . ': curl (http://php.net/curl) is not installed, but' .
+                       throw new DomainException( __METHOD__ . ': curl (http://php.net/curl) is not installed, but' .
                                ' Http::$httpEngine is set to "curl"' );
                }
 
@@ -186,7 +195,7 @@ class MWHttpRequest implements LoggerAwareInterface {
                                return new CurlHttpRequest( $url, $options, $caller, Profiler::instance() );
                        case 'php':
                                if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
-                                       throw new MWException( __METHOD__ . ': allow_url_fopen ' .
+                                       throw new DomainException( __METHOD__ . ': allow_url_fopen ' .
                                                'needs to be enabled for pure PHP http requests to ' .
                                                'work. If possible, curl should be used instead. See ' .
                                                'http://php.net/curl.'
@@ -194,7 +203,7 @@ class MWHttpRequest implements LoggerAwareInterface {
                                }
                                return new PhpHttpRequest( $url, $options, $caller, Profiler::instance() );
                        default:
-                               throw new MWException( __METHOD__ . ': The setting of Http::$httpEngine is not valid.' );
+                               throw new DomainException( __METHOD__ . ': The setting of Http::$httpEngine is not valid.' );
                }
        }
 
@@ -222,7 +231,7 @@ class MWHttpRequest implements LoggerAwareInterface {
         *
         * @return void
         */
-       public function proxySetup() {
+       protected function proxySetup() {
                // If there is an explicit proxy set and proxies are not disabled, then use it
                if ( $this->proxy && !$this->noProxy ) {
                        return;
@@ -300,7 +309,7 @@ class MWHttpRequest implements LoggerAwareInterface {
         * Get an array of the headers
         * @return array
         */
-       public function getHeaderList() {
+       protected function getHeaderList() {
                $list = [];
 
                if ( $this->cookieJar ) {
@@ -333,12 +342,14 @@ class MWHttpRequest implements LoggerAwareInterface {
         * bytes are reported handled than were passed to you, the HTTP fetch
         * will be aborted.
         *
-        * @param callable $callback
-        * @throws MWException
+        * @param callable|null $callback
+        * @throws InvalidArgumentException
         */
        public function setCallback( $callback ) {
-               if ( !is_callable( $callback ) ) {
-                       throw new MWException( 'Invalid MwHttpRequest callback' );
+               if ( is_null( $callback ) ) {
+                       $callback = [ $this, 'read' ];
+               } elseif ( !is_callable( $callback ) ) {
+                       throw new InvalidArgumentException( __METHOD__ . ': invalid callback' );
                }
                $this->callback = $callback;
        }
@@ -350,6 +361,7 @@ class MWHttpRequest implements LoggerAwareInterface {
         * @param resource $fh
         * @param string $content
         * @return int
+        * @internal
         */
        public function read( $fh, $content ) {
                $this->content .= $content;
@@ -359,9 +371,14 @@ class MWHttpRequest implements LoggerAwareInterface {
        /**
         * Take care of whatever is necessary to perform the URI request.
         *
-        * @return Status
+        * @return StatusValue
+        * @note currently returns Status for B/C
         */
        public function execute() {
+               throw new LogicException( 'children must override this' );
+       }
+
+       protected function prepare() {
                $this->content = "";
 
                if ( strtoupper( $this->method ) == "HEAD" ) {
@@ -371,7 +388,7 @@ class MWHttpRequest implements LoggerAwareInterface {
                $this->proxySetup(); // set up any proxy as needed
 
                if ( !$this->callback ) {
-                       $this->setCallback( [ $this, 'read' ] );
+                       $this->setCallback( null );
                }
 
                if ( !isset( $this->reqHeaders['User-Agent'] ) ) {
@@ -494,6 +511,8 @@ class MWHttpRequest implements LoggerAwareInterface {
        /**
         * Tells the MWHttpRequest object to use this pre-loaded CookieJar.
         *
+        * To read response cookies from the jar, getCookieJar must be called first.
+        *
         * @param CookieJar $jar
         */
        public function setCookieJar( $jar ) {
@@ -519,14 +538,18 @@ class MWHttpRequest implements LoggerAwareInterface {
         * Set-Cookie headers.
         * @see Cookie::set
         * @param string $name
-        * @param mixed $value
+        * @param string $value
         * @param array $attr
         */
-       public function setCookie( $name, $value = null, $attr = null ) {
+       public function setCookie( $name, $value, $attr = [] ) {
                if ( !$this->cookieJar ) {
                        $this->cookieJar = new CookieJar;
                }
 
+               if ( $this->parsedUrl && !isset( $attr['domain'] ) ) {
+                       $attr['domain'] = $this->parsedUrl['host'];
+               }
+
                $this->cookieJar->setCookie( $name, $value, $attr );
        }
 
index 2af000f..d8a9949 100644 (file)
@@ -87,6 +87,7 @@ class PhpHttpRequest extends MWHttpRequest {
         * is completely useless (something like "fopen: failed to open stream")
         * so normal methods of handling errors programmatically
         * like get_last_error() don't work.
+        * @internal
         */
        public function errorHandler( $errno, $errstr ) {
                $n = count( $this->fopenErrors ) + 1;
@@ -94,8 +95,7 @@ class PhpHttpRequest extends MWHttpRequest {
        }
 
        public function execute() {
-
-               parent::execute();
+               $this->prepare();
 
                if ( is_array( $this->postData ) ) {
                        $this->postData = wfArrayToCgi( $this->postData );
@@ -227,12 +227,12 @@ class PhpHttpRequest extends MWHttpRequest {
                                        . ': error opening connection: {errstr1}', $this->fopenErrors );
                        }
                        $this->status->fatal( 'http-request-error' );
-                       return $this->status;
+                       return Status::wrap( $this->status ); // TODO B/C; move this to callers
                }
 
                if ( $result['timed_out'] ) {
                        $this->status->fatal( 'http-timed-out', $this->url );
-                       return $this->status;
+                       return Status::wrap( $this->status ); // TODO B/C; move this to callers
                }
 
                // If everything went OK, or we received some error code
@@ -253,6 +253,6 @@ class PhpHttpRequest extends MWHttpRequest {
                }
                fclose( $fh );
 
-               return $this->status;
+               return Status::wrap( $this->status ); // TODO B/C; move this to callers
        }
 }
index d1a9bc5..328cdad 100644 (file)
@@ -23,6 +23,7 @@
  * @file
  * @ingroup SpecialPage
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * XML file reader for the page data importer.
@@ -59,7 +60,7 @@ class WikiImporter {
                $this->reader = new XMLReader();
                if ( !$config ) {
                        wfDeprecated( __METHOD__ . ' without a Config instance', '1.25' );
-                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $config = MediaWikiServices::getInstance()->getMainConfig();
                }
                $this->config = $config;
 
index 6a702e9..6a8a99f 100644 (file)
@@ -32,8 +32,6 @@ require_once __DIR__ . '/../../maintenance/Maintenance.php';
  * @since 1.17
  */
 abstract class DatabaseUpdater {
-       protected static $updateCounter = 0;
-
        /**
         * Array of updates to perform on the database
         *
@@ -423,8 +421,6 @@ abstract class DatabaseUpdater {
         * @param array $what What updates to perform
         */
        public function doUpdates( $what = [ 'core', 'extensions', 'stats' ] ) {
-               global $wgVersion;
-
                $this->db->setSchemaVars( $this->getSchemaVars() );
 
                $what = array_flip( $what );
@@ -441,12 +437,9 @@ abstract class DatabaseUpdater {
                        $this->checkStats();
                }
 
-               $this->setAppliedUpdates( $wgVersion, $this->updates );
-
                if ( $this->fileHandle ) {
                        $this->skipSchema = false;
                        $this->writeSchemaUpdateFile();
-                       $this->setAppliedUpdates( "$wgVersion-schema", $this->updatesSkipped );
                }
        }
 
@@ -482,23 +475,6 @@ abstract class DatabaseUpdater {
                $this->updates = array_merge( $this->updates, $updatesDone );
        }
 
-       /**
-        * @param string $version
-        * @param array $updates
-        */
-       protected function setAppliedUpdates( $version, $updates = [] ) {
-               $this->db->clearFlag( DBO_DDLMODE );
-               if ( !$this->canUseNewUpdatelog() ) {
-                       return;
-               }
-               $key = "updatelist-$version-" . time() . self::$updateCounter;
-               self::$updateCounter++;
-               $this->db->insert( 'updatelog',
-                       [ 'ul_key' => $key, 'ul_value' => serialize( $updates ) ],
-                       __METHOD__ );
-               $this->db->setFlag( DBO_DDLMODE );
-       }
-
        /**
         * Helper function: check if the given key is present in the updatelog table.
         * Obviously, only use this for updates that occur after the updatelog table was
index 8142abd..6fb8927 100644 (file)
@@ -9,7 +9,8 @@
                        "Kuwaity26",
                        "محمد أحمد عبد الفتاح",
                        "Maroen1990",
-                       "Super ninja2"
+                       "Super ninja2",
+                       "Zpizza"
                ]
        },
        "config-desc": "مثبت لميدياويكي",
index cd9574c..c591f1e 100644 (file)
@@ -62,6 +62,7 @@
        "config-memory-bad": "<strong>Alvertencia:</strong>: el parámetru <code>memory_limit</code> de PHP ye $1.\nProbablemente sía demasiáu baxu.\n¡La instalación puede fallar!",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] ta instaláu",
        "config-apc": "[http://www.php.net/apc APC] ta instaláu",
+       "config-apcu": "[http://www.php.net/apcu APCu] ta instaláu",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] ta instaláu",
        "config-no-cache-apcu": "<strong>Warning:</strong> Non pudo atopase[http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] o [http://www.iis.net/download/WinCacheForPhp WinCache].\nEl caxé d'oxetos nun ta activáu.",
        "config-mod-security": "<strong>Alvertencia:</strong> El to servidor web tien activáu [http://modsecurity.org/mod_security]/mod_security2 .Munches de les sos configuraciones comunes pueden causar problemes a MediaWiki o otru software que dexe a los usuarios publicar conteníu arbitrario. De ser posible, tendríes de desactivalo. Si non, consulta la  [http://modsecurity.org/documentation/ mod_security documentation] o contacta col alministrador del to servidor si atopes erros aleatorios.",
        "config-db-username": "Nome d'usuariu de base de datos:",
        "config-db-password": "Contraseña de base de datos:",
        "config-db-install-username": "Introduz un nome d'usuariu que s'usará pa coneutase cola base de datos nel procesu d'instalación. Esti nun ye'l nome d'usuariu de la cuenta MediaWiki, ye'l nome d'usuariu de la to base de datos.",
+       "config-db-install-password": "Escribe la contraseña que se va utilizar pa conectase a la base de datos mientres el procesu d'instalación.\nEsta nun ye la contraseña de la cuenta de MediaWiki, sinón la contraseña de la base de datos.",
+       "config-db-install-help": "Escribe'l nome d'usuariu y la contraseña que se van utilizar pa conectase a la base de datos mientres el procesu d'instalación.",
+       "config-db-account-lock": "Usar el mesmu nome d'usuariu y contraseña demientres la operación normal",
+       "config-db-wiki-account": "Cuenta d'usuariu pa operar normalmente",
+       "config-db-wiki-help": "Escribe'l nome d'usuariu y la contraseña que se van utilizar p'aportar a la base de datos mientres la operación normal de la wiki.\nSi esta cuenta nun esiste y la cuenta d'instalación tien permisos bastante, va crease esta cuenta d'usuariu colos mínimos permisos necesarios pa operar normalmente la wiki.",
+       "config-db-prefix": "Prefixu de tables de la base de datos:",
+       "config-db-prefix-help": "Si precises compartir una base de datos ente múltiples wikis, o ente MediaWiki y otra aplicación web, puedes optar por amestar un prefixu a tolos nomes de tabla pa evitar conflictos.\nNun utilices espacios.\n\nDe normal déxase esti campu vacío.",
        "config-type-mysql": "MySQL (o compatible)",
        "config-type-mssql": "Microsoft SQL Server",
        "config-invalid-db-type": "Triba non válida de base de datos.",
        "config-help": "Ayuda",
        "config-nofile": "Nun pudo atopase'l ficheru \"$1\". ¿Desaniciose?",
        "mainpagetext": "<strong>Instalóse MediaWiki.</strong>",
-       "mainpagedocfooter": "Consulta la [https://meta.wikimedia.org/wiki/Help:Contents Guía del usuariu] pa saber cómo usar el software wiki.\n\n== Primeros pasos ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Llista de les opciones de configuración]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ EMF de MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Llista de corréu de llanzamientos de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Llocaliza MediaWiki na to llingua]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Depriende como combatir la puxarra na to wiki]"
+       "mainpagedocfooter": "Consulta [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents] pa saber cómo usar el software wiki.\n\n== Primeros pasos ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Llista de les opciones de configuración]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ EMF de MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Llista de corréu de llanzamientos de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Llocaliza MediaWiki na to llingua]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Depriende como combatir la puxarra na to wiki]"
 }
index 92c00b1..8e1442a 100644 (file)
@@ -1,7 +1,8 @@
 {
        "@metadata": {
                "authors": [
-                       "Чаховіч Уладзіслаў"
+                       "Чаховіч Уладзіслаў",
+                       "Mechanizatar"
                ]
        },
        "config-desc": "Інсталятар MediaWiki",
@@ -15,6 +16,6 @@
        "config-page-name": "Назва",
        "config-page-options": "Настройкі",
        "config-upload-settings": "Загрузка выяў і файлаў",
-       "mainpagetext": "'''MediaWiki паспяхова ўсталяваная.'''",
+       "mainpagetext": "<strong>MediaWiki паспяхова ўсталяваная.</strong>",
        "mainpagedocfooter": "Гл. [https://meta.wikimedia.org/wiki/Help:Contents Дапаможнік карыстальніка (англ.)] па далейшыя звесткі аб карыстанні вікі-праграмамі.\n\n== З чаго пачаць ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Пералік параметраў канфігурацыі (англ.)]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ ЧАПЫ MediaWiki (англ.)]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Ліставанне аб выпусках MediaWiki (англ.)]"
 }
index f28e2c5..f9a8da8 100644 (file)
        "config-help": "সাহায্য",
        "config-help-tooltip": "প্রসারিত করতে ক্লিক করুন",
        "mainpagetext": "<strong>মিডিয়াউইকি ইনস্টল করা হয়েছে।</strong>",
-       "mainpagedocfooter": "কীভাবে উইকি সফটওয়্যারটি ব্যবহারকার করবেন, তা জানতে [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents ব্যবহারকারী সহায়িকা] দেখুন।\n\n== কোথা থেকে শুরু করবেন ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings কনফিগারেশন সেটিং তালিকা]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ প্রশ্নোত্তরে মিডিয়াউইকি]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce মিডিয়াউইকি মুক্তির মেইলিং লিস্ট]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources আপনার ভাষার জন্য মিডিয়াউইকি স্থানীয়করণ করুন]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam আপনার উইকিতে স্প্যামের সাথে লড়াই করার উপায় সম্পর্কে জানুন]"
+       "mainpagedocfooter": "কীভাবে উইকি সফটওয়্যারটি ব্যবহারকার করবেন, তা জানতে [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents ব্যবহারকারী সহায়িকা] দেখুন।\n\n== কোথা থেকে শুরু করবেন ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings কনফিগারেশন সেটিং তালিকা]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ প্রশ্নোত্তরে মিডিয়াউইকি]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce মিডিয়াউইকি মুক্তির মেইলিং লিস্ট]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources আপনার ভাষার জন্য মিডিয়াউইকি স্থানীয়করণ করুন]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam আপনার উইকিতে স্প্যামের সাথে লড়াই করার উপায় সম্পর্কে জানুন]"
 }
index 2fee258..316ed3f 100644 (file)
        "config-nofile": "Soubor „$1“ nelze nalézt. Byl smazán?",
        "config-extension-link": "Věděli jste, že vaše wiki podporuje [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions rozšíření]?\n\nMůžete si prohlédnout [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category seznam rozšíření po kategoriích].",
        "mainpagetext": "<strong>MediaWiki byla úspěšně nainstalována.</strong>",
-       "mainpagedocfooter": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Uživatelská příručka] vám napoví, jak používat MediaWiki.\n\n== Začínáme ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Nastavení konfigurace]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Často kladené otázky o MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce E-mailová konference oznámení MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Překlad MediaWiki do vašeho jazyka]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Naučte se bojovat se spamem na vaší wiki]"
+       "mainpagedocfooter": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Uživatelská příručka] vám napoví, jak používat MediaWiki.\n\n== Začínáme ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Nastavení konfigurace]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Často kladené otázky o MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce E-mailová konference oznámení MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Překlad MediaWiki do vašeho jazyka]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Naučte se bojovat se spamem na vaší wiki]"
 }
index b25ff2c..95d2ba3 100644 (file)
        "config-nofile": "File \"$1\" could not be found. Has it been deleted?",
        "config-extension-link": "Did you know that your wiki supports [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensions]?\n\nYou can browse [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensions by category] or the [https://www.mediawiki.org/wiki/Extension_Matrix Extension Matrix] to see the full list of extensions.",
        "mainpagetext": "<strong>MediaWiki has been installed.</strong>",
-       "mainpagedocfooter": "Consult the [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents] for information on using the wiki software.\n\n== Getting started ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Configuration settings list]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]"
+       "mainpagedocfooter": "Consult the [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents User's Guide] for information on using the wiki software.\n\n== Getting started ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Configuration settings list]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]"
 }
index 46e8d90..c9d2886 100644 (file)
@@ -79,5 +79,5 @@
        "config-install-tables": "Tabelite loomine",
        "config-help": "abi",
        "mainpagetext": "<strong>MediaWiki tarkvara on paigaldatud.</strong>",
-       "mainpagedocfooter": "Vikitarkvara kasutamise kohta leiad lisateavet [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents siit].\n\n== Alustamine ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Häälestussätete loend]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki KKK]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki versiooniuuenduste postiloend]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources MediaWiki lokaliseerimine]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Loe, kuidas vikis rämpspostitusi tõrjuda]"
+       "mainpagedocfooter": "Vikitarkvara kasutamise kohta leiad lisateavet [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents kasutaja teatmikust].\n\n== Alustamine ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Häälestussätete loend]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki KKK]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki versiooniuuenduste postiloend]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources MediaWiki lokaliseerimine]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Loe, kuidas vikis rämpspostitusi tõrjuda]"
 }
index dae9f2a..d1ba15a 100644 (file)
@@ -17,8 +17,8 @@
                        "Alifakoor"
                ]
        },
-       "config-desc": "Ù\86صب Ú©Ù\86Ù\86دÙ\87Ù\94 Ù\88Û\8cÚ©Û\8câ\80\8cÙ\85دÛ\8cا",
-       "config-title": "Ù\86صب Ù\88Û\8cÚ©Û\8câ\80\8cÙ\85دÛ\8cا $1",
+       "config-desc": "Ù\86صب Ú©Ù\86Ù\86دÙ\87Ù\94 Ù\85دÛ\8cاÙ\88Û\8cÚ©Û\8c",
+       "config-title": "Ù\86صب Ù\85دÛ\8cاÙ\88Û\8cÚ©Û\8c $1",
        "config-information": "اطلاعات",
        "config-localsettings-upgrade": "یک پرونده <code>LocalSettings.php</code> شناسایی شده‌است.\nبرای ارتقاء این نصب لطفاً مقدار <code>$wgUpgradeKey</code> در جعبه زیر وارد کنید.\nشما می‌توانید آن را در <code>LocalSettings.php</code> پیدا کنید.",
        "config-localsettings-cli-upgrade": "یک پرونده <code>LocalSettings.php</code> شناسایی شده است.\nبرای ارتقاء این نصب، لطفاً <code>update.php</code> را اجرا کنید.",
        "config-page-options": "گزینه‌ها",
        "config-page-install": "نصب",
        "config-page-complete": "کامل!",
-       "config-page-restart": "راÙ\87â\80\8cاÙ\86دازÛ\8c Ø¯Ù\88بارÙ\87 نصب",
+       "config-page-restart": "شرÙ\88ع Ø¯Ù\88بارÙ\87Ù\94 نصب",
        "config-page-readme": "مرا بخوان",
        "config-page-releasenotes": "یادداشت‌های انتشار",
        "config-page-copying": "تکثیر",
        "config-page-upgradedoc": "ارتقاء",
        "config-page-existingwiki": "ویکی موجود",
        "config-help-restart": "آیا می‌خواهید همهٔ اطلاعات ذخیره شده‌ای که وارد کرده‌اید را پاک کنید و دوباره روند نصب را شروع کنید؟",
-       "config-restart": "بÙ\84Ù\87Ø\8c Ø¯Ù\88بارÙ\87 Ø±Ø§Ù\87â\80\8cاÙ\86دازÛ\8c کن",
+       "config-restart": "بÙ\84Ù\87Ø\8c Ø¯Ù\88بارÙ\87 Ø´Ø±Ù\88ع کن",
        "config-welcome": "===بررسی‌های محیطی===\nبرای فهمیدن اینکه این محیط برای نصب مدیاویکی مناسب است، اکنون بررسی‌های اساسی انجام خواهد‌شد.\nاگر به دنبال پشتیبانی در چگونگی تکمیل نصب هستید،به یاد داشته باشید این اطلاعات را بگنجانید.",
-       "config-copyright": "===حق چاپ و شرایط===\n$1\nاین برنامه، یک نرم‌افزاری آزاد است. شما می‌توانید آن را بازتوزیع کرده و/یا با شرایط نگارش ۲ یا (با نظر خودتان) هر نگارش جدیدتری از پروانه جامع همگانی گنو که توسط بنیاد نرم‌افزار آزاد منتشر شده، تغییر دهید.\n\nاین برنامه با امید این که مفید واقع‌ شود توزیع شده‌است،اما '''بدون هیچ ضمانتی'''; حتی بدون اشارهٔ ضمانتی از '''قابلیت عرضه''' یا ''' صلاحیت برای یک هدف خاص'''.\nبرای جزئیات بیش‌تر پروانه جامع همگانی گنو را مشاهده کنید.\n\nشما باید <doclink href=Copying> یک نگارش ازمجوز عمومی کلی </doclink> همراه این برنامه دریافت کرده باشید. در غیر این صورت با بنیاد نرم‌افزار آزاد، ایالات متحده امریکا، بوستون، خیابان فرانکلین، پلاک ۵۱، طبقه پنجم، صندوق پستی MA۰۲۱۱۰-۱۳۰ مکاتبه کنید، یا [http://www.gnu.org/copyleft/gpl.html در این‌جا به صورت برخط بخوانید].",
+       "config-copyright": "=== حق رونوشت و شرایط ===\n\n$1\n\nاین برنامه، نرم‌افزاری آزاد است. می‌توانید تحت شرایط نگارش ۲ یا (بنا به نظر خود) هر نگارش جدیدتری از پروانهٔ جامع همگانی گنو که توسط بنیاد نرم‌افزار آزاد منتشر شده، بازنشرش کرده و/یا تغییرش دهید.\n\n\nاین برنامه با این امید توزیع شده که مفید باشد، ولی <strong>بدون هیچ ضمانتی</strong>، حتا ضمانت ضمنی <strong>معامله‌پذیری</strong> یا <strong>تناسب برای کاربردی خاص </strong>.\n\nبرای جزئیات بیش‌تر، پروانهٔ جامع همگانی گنو را ببینید.\n\n\nباید همراه این برنامه، <doclink href=Copying>نگارشی از پروانهٔ جامع همگانی گنو</doclink> را گرفته باشید. اگر چنین نیست، با بنیاد نرم‌افزار آزاد به نشانی 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA مکاتبه کرده یا [http://www.gnu.org/copyleft/gpl.html پروانه را برخط بخوانید].",
        "config-sidebar": "* [https://www.mediawiki.org صفحهٔ اصلی مدیاویکی]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents راهنمای کاربر]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents راهنمای مدیر]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ پرسش‌های رایج]\n----\n* <doclink href=Readme>مرا بخوان</doclink>\n* <doclink href=ReleaseNotes>یادداشت‌های انتشار</doclink>\n* <doclink href=Copying>نسخه برداری</doclink>\n* <doclink href=UpgradeDoc>ارتقا</doclink>",
        "config-env-good": "محیط بررسی شده‌است.\nشما می‌توانید مدیاویکی را نصب کنید.",
        "config-env-bad": "محیط بررسی شده‌است.\nشما نمی‌توانید مدیاویکی را نصب کنید.",
        "config-env-php": "پی‌اچ‌پی $1 نصب شده‌است.",
-       "config-env-hhvm": "HHVM $1 نصب شده‌است.",
-       "config-unicode-using-intl": "برای یونیکد عادی از [http://pecl.php.net/intl intl PECL extension] استفاده کنید.",
+       "config-env-hhvm": "اچ‌اچ‌وی‌ام $1 نصب شده‌است.",
+       "config-unicode-using-intl": "برای یونیکد عادی از [http://pecl.php.net/intl افزونهٔ intl برای PECL] استفاده کنید.",
        "config-unicode-pure-php-warning": "'''هشدار:''' [http://pecl.php.net/intl intl PECL extension] برای کنترل یونیکد عادی در دسترس نیست،اجرای کاملاً آهسته به تعویق می‌افتد.\n\nاگر شما یک سایت پر‌ ترافیک را اجرا می‌کنید، باید کمی [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization] را بخوانید.",
        "config-unicode-update-warning": "'''هشدار:''' نسخهٔ نصب شدهٔ پوشهٔ یونیکد عادی از ورژن قدیمی‌تر کتابخانه [http://site.icu-project.org/ the ICU project's] استفاده می‌کند.\n\nاگر کلاً علاقه‌مند به استفاده از یونیکد هستید باید [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations upgrade].",
        "config-no-db": "درایور پایگاه اطلاعاتی مناسب پیدا نشد! شما لازم دارید یک درایور پایگاه اطلاعاتی  برای پی‌اچ‌پی نصب کنید.انواع پایگاه اطلاعاتی زیر پشتیبانی شده‌اند:$1.\nاگر شما در گروه اشتراک‌گذاری هستید، از تهیه کنندهٔ گروه خود برای نصب یک درایور پایگاه اطلاعاتی مناسب {{PLURAL:$2|سوأل کنید.|سوأل کنید.}}\nاگر خود، پی‌اچ‌پی را تهیه کرده‌اید، با یک پردازشگر فعال دوباره پیکربندی کنید، برای مثال از <code>./configure --with-mysql</code> استفاده کنید.\nاگر پی‌اچ‌پی را از یک بستهٔ دبیان یا آبونتو نصب کرده‌اید، بنابراین لازم دارید بخش php5-mysql را نصب کنید.",
@@ -72,6 +72,7 @@
        "config-memory-bad": "'''هشدار:''' PHP's <code>memory_limit</code> نسخهٔ $1 است.\nاین ممکن است خیلی پایین باشد.\nممکن است نصب با مشکل رو‌به‌رو شود.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] نصب شده‌است.",
        "config-apc": "[http://www.php.net/apc APC] نصب شده‌است.",
+       "config-apcu": "[http://www.php.net/apcu APCu] نصب شده‌است",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] نصب شده‌است.",
        "config-no-cache-apcu": "<strong>هشدار:</strong> پیوند [http://www.php.net/apcu APCu]، [http://xcache.lighttpd.net/ XCache] یا [http://www.iis.net/download/WinCacheForPhp WinCache] یافت نشد. ذخیره شی فعال نیست.",
        "config-mod-security": "'''هشدار:''' وب سرور شما [http://modsecurity.org/ mod_security] فعال است.اگر اشتباه پیکربندی شده‌‌ باشد،می تواند باعث ایجاد مشکلاتی برای مدیاویکی یا دیگر نرم‌افزاری شود که به کاربران اجازه می‌دهد پیام دلخواه ارسال کنند.\nبه [http://modsecurity.org/documentation/ mod_security documentation] مراجعه کنید یا اگر با خطاهای اتفاقی مواجه شدید با پشتیبانی میزبان خود در تماس باشید.",
        "config-type-mssql": "سرور مایکروسافت اس‌کیو‌ال",
        "config-support-info": "مدیاویکی سامانه‌های پایگاه اطلاعاتی زیر را حمایت می‌کند:\n$1\nاگر متوجه سامانه پایگاه اطلاعاتی که سعی دارید از فهرست زیر استفاده کنید، نمی‌شوید، بنابراین دستورالعمل‌های مرتبط در بالا را برای فعال کردن پشتیبانی دنبال کنید.",
        "config-dbsupport-mysql": "*[{{int:version-db-mysql-url}} MySQL] مهم‌ترین هدف برای مدیاویکی است و بهترین پشتیبانی. مدیاویکی همچنین کار می‌کند با [{{int:version-db-mariadb-url}} MariaDB] و [{{int:version-db-percona-url}} Percona Server] که با MySQL سازگار هستند.([http://www.php.net/manual/en/mysqli.installation.php چگونه php را با MySQL کامپایل کنیم])",
-       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] یک منبع آزاد پر‌طرفدار دستگاه پایگاه اطلاعاتی به عنوان یک غیرمتعارف برای مای‌اس‌کیوال است.ممکن است عیوب بارز مختصری باشد، و برای استفاده در یک محیط تولیدی توصیه نمی‌شود.([http://www.php.net/manual/en/pgsql.installation.php how to compile PHP with PostgreSQL support])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} پستگرس‌کیوال] یک سامانه پایگاه اطلاعات متن‌باز پر‌طرفدار است که جایگزینی برای مای‌اس‌کیوال است. ([http://www.php.net/manual/en/pgsql.installation.php راهنمای تنظیم کردن پی‌اچ‌پی به همراه پستگرس‌کیوال])",
        "config-dbsupport-sqlite": "*[{{int:version-db-sqlite-url}} اس‌کیولایت] یک سامانه پایگاه اطلاعاتی کم حجمی است که بسیار خوب پشتیبانی شده‌است.\n([http://www.php.net/manual/en/pdo.installation.php چگونگی کامپایل پی‌اچ‌پی با اس‌کیولایت]، از PDO استفاده می‌کند)",
        "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] یک پایگاه اطلاعاتی کار تبلیغاتی است.\n([http://www.php.net/manual/en/oci8.installation.php How to compile PHP with OCI8 support])",
        "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] یک پایگاه اطلاعاتی موسسهٔ تبلیغاتی برای وینذوز است. ([http://www.php.net/manual/en/sqlsrv.installation.php How to compile PHP with SQLSRV support])",
        "config-cache-options": "تنظیمات برای ذخیره شی:",
        "config-cache-help": "کش شی برای بهتر شدن سرعت مدیا ویکی، از طریق کش کردن داده‌های با بیشترین استفاده انجام می‌گیرد.\nوبگاه‌های متوسط تا بزرگ به انجام این کار شدیدا توصیه می‌شوند، در عین حال وبگاه‌های کوچک نیز می‌توانند از مزایای ایم مورد بهره ببرند.",
        "config-cache-none": "بدون ذخیره (هیچ کارآمدی پاک نشده‌است، اما ممکن است سرعت در سایت‌های بزرگتر ویکی تأثیر داشته باشد)",
-       "config-cache-accel": "ذخیرهٔ موضوع پی‌اچ‌پی (ای‌پی‌سی، ایکس‌کیچ یا وین‌کیچ)",
+       "config-cache-accel": "کاشهٔ اشیای پی‌اچ‌پی (APC یا APCu یا XCache یا WinCahe)",
        "config-cache-memcached": "از ممکچد (که نیازمند تنظیمات اضافی و پیکربندی) استفاده کنید",
        "config-memcached-servers": "سرورهای دریافت حافظه:",
        "config-memcached-help": "فهرست آدرس‌های آی‌پی برای استفاده از ممکچد.\nباید هر یک خط را تعیین کند و درگاه مورد استفاده را تعیین کند.برای مثال: \n۱۲۷.۰.۰.۱:۱۱۲۱۱\n۱۹۲.۱۶۸.۱.۲۵:۱۲۳۴",
        "config-nofile": "پروندهٔ «$1» یافت نشد. آیا حذف شده‌است؟",
        "config-extension-link": "آیا می‌دانستید که ویکی شما [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensions] را پشتیبانی می‌کند؟\nشما می‌توانید [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensions by category]",
        "mainpagetext": "'''مدیاویکی با موفقیت نصب شد.'''",
-       "mainpagedocfooter": "از [https://meta.wikimedia.org/wiki/Help:Contents راهنمای کاربران]\nبرای استفاده از نرم‌افزار ویکی کمک بگیرید.\n\n== آغاز به کار ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings تنظیم پیکربندی]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki پرسش‌های متداول]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce فهرست ارسال نسخه‌های مدیاویکی]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise مدیاویکی برای زبان شما]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam آموزش مقابله به هرزنگاری در ویکی شما]"
+       "mainpagedocfooter": "از [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents]\nبرای اطلاعات بیشتر در مورد به‌کارگیری نرم‌افزار ویکی استفاده کنید.\n\n== آغاز به کار ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings فهرست تنظیمات پیکربندی]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ پرسش‌های متداول مدیاویکی]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce فهرست ایمیلی نسخه‌های مدیاویکی]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources محلی‌سازی مدیاویکی به زبان شما]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam یادگیری روش‌های مقابله با هرزنگاری در ویکی]"
 }
index 82a2373..6257691 100644 (file)
        "config-nofile": "Le fichier « $1 » est introuvable. A-t-il été supprimé ?",
        "config-extension-link": "Saviez-vous que votre wiki prend en charge [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions des extensions] ?\n\nVous pouvez consulter les [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensions par catégorie] ou la [https://www.mediawiki.org/wiki/Extension_Matrix matrice des extensions] pour voir la liste complète des extensions.",
        "mainpagetext": "<strong>MediaWiki a été installé.</strong>",
-       "mainpagedocfooter": "Consultez le [https://meta.wikimedia.org/wiki/Help:Contents/fr Guide de l’utilisateur] pour plus d’informations sur l’utilisation de ce logiciel de wiki.\n\n== Pour démarrer ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Liste des paramètres de configuration]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/fr Questions courantes sur MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Liste de discussion sur les distributions de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Adaptez MediaWiki dans votre langue]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Apprendre comment lutter contre le pourriel dans votre wiki]"
+       "mainpagedocfooter": "Consultez le [https://meta.wikimedia.org/wiki/Help:Contents/fr Guide de l’utilisateur du contenu] pour plus d’informations sur l’utilisation de ce logiciel de wiki.\n\n== Pour démarrer ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Liste des paramètres de configuration]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/fr Questions courantes sur MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Liste de discussion sur les distributions de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Adaptez MediaWiki dans votre langue]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Apprendre comment lutter contre le pourriel dans votre wiki]"
 }
index 4c68cf9..1d52273 100644 (file)
@@ -61,6 +61,7 @@
        "config-memory-bad": "'''Aviso:''' Le <code>memory_limit</code> de PHP es $1.\nIsto es probabilemente troppo basse.\nLe installation pote faller!",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] es installate",
        "config-apc": "[http://www.php.net/apc APC] es installate",
+       "config-apcu": "[http://www.php.net/apcu APCu] es installate",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] es installate",
        "config-no-cache-apcu": "<strong>Attention:</strong> Impossibile trovar [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] o [http://www.iis.net/download/WinCacheForPhp WinCache].\nLe cache de objectos non es activate.",
        "config-mod-security": "'''Attention''': [http://modsecurity.org/ mod_security] es active in tu servitor web. Si mal configurate, isto pote causar problemas pro MediaWiki o altere software que permitte al usatores de publicar contento arbitrari.\nConsulta le [http://modsecurity.org/documentation/ documentation de mod_security] o contacta le servicio de adjuta de tu host si tu incontra estranie errores.",
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "MediaWiki supporta le sequente systemas de base de datos:\n\n$1\n\nSi tu non vide hic infra le systema de base de datos que tu tenta usar, alora seque le instructiones ligate hic supra pro activar le supporto.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] es le systema primari pro MediaWiki e le melio supportate. MediaWiki functiona anque con [{{int:version-db-mariadb-url}} MariaDB] e con [{{int:version-db-percona-url}} Percona Server], le quales es compatibile con MySQL. ([http://www.php.net/manual/en/mysqli.installation.php Como compilar PHP con supporto de MySQL])",
-       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] es un systema de base de datos popular e open source, alternativa a MySQL. Es possibile que resta alcun minor defectos non resolvite, dunque illo non es recommendate pro uso in un ambiente de production. ([http://www.php.net/manual/en/pgsql.installation.php Como compilar PHP con supporto de PostgreSQL])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] es un systema de base de datos popular e open source, alternativa a MySQL. ([http://www.php.net/manual/en/pgsql.installation.php Como compilar PHP con supporto de PostgreSQL])",
        "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] es un systema de base de datos legier que es multo ben supportate. ([http://www.php.net/manual/en/pdo.installation.php Como compilar PHP con supporto de SQLite], usa PDO)",
        "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] es un banca de datos commercial pro interprisas. ([http://www.php.net/manual/en/oci8.installation.php Como compilar PHP con supporto de OCI8])",
        "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] es un base de datos de interprisa commercial pro Windows. ([http://www.php.net/manual/en/sqlsrv.installation.php Como compilar PHP con supporto de SQLSRV])",
        "config-cache-options": "Configuration del cache de objectos:",
        "config-cache-help": "Le cache de objectos es usate pro meliorar le rapiditate de MediaWiki per immagazinar le datos frequentemente usate.\nLe sitos medie o grande es multo incoragiate de activar isto, ma anque le sitos parve percipera le beneficios.",
        "config-cache-none": "Nulle cache (nulle functionalitate es removite, ma le rapiditate pote diminuer in grande sitos wiki)",
-       "config-cache-accel": "Cache de objectos de PHP (APC, XCache o WinCache)",
+       "config-cache-accel": "Cache de objectos PHP (APC, APCu, XCache o WinCache)",
        "config-cache-memcached": "Usar Memcached (require additional installation e configuration)",
        "config-memcached-servers": "Servitores Memcached:",
        "config-memcached-help": "Lista de adresses IP a usar pro Memcached.\nDebe specificar un per linea e specificar le porto a usar. Per exemplo:\n 127.0.0.1:11211\n 192.168.1.25:1234",
index e9e22a9..cf4eb6d 100644 (file)
@@ -19,7 +19,9 @@
                        "2nd-player",
                        "Otokoume",
                        "Rxy",
-                       "Foresttttttt"
+                       "Foresttttttt",
+                       "ネイ",
+                       "Suchichi02"
                ]
        },
        "config-desc": "MediaWiki のインストーラー",
        "config-subscribe": "[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce リリース告知のメーリングリスト]を購読する。",
        "config-subscribe-help": "これは、リリースの告知 (重要なセキュリティに関する案内を含む) に使用される、流量が少ないメーリングリストです。\nこのメーリングリストを購読して、新しいバージョンが出た場合にMediaWikiを更新してください。",
        "config-subscribe-noemail": "メールアドレスなしでリリースアナウンスのメーリングリストを購読しようとしています。\nメーリングリストを購読する場合にはメールアドレスを入力してください。",
-       "config-pingback": "ã\81\93ã\81®ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83¬ã\83¼ã\82·ã\83§ã\83³ã\81«é\96¢ã\81\99ã\82\8bã\83\87ã\83¼ã\82¿ã\82\92ã\83¡ã\83\87ã\82¤ã\82¢ã\82¦ã\82£ã\82­ã\81®é\96\8bç\99ºè\80\85ã\81«ã\82·ã\82§ã\82¢ã\81\97ã\81¦ã\81\8fã\81 ã\81\95ã\81\84。",
+       "config-pingback": "ã\81\93ã\81®ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83«ã\81«é\96¢ã\81\99ã\82\8bã\83\87ã\83¼ã\82¿ã\82\92MediaWikiã\81®é\96\8bç\99ºè\80\85ã\81¨å\85±æ\9c\89ã\81\99ã\82\8b。",
        "config-pingback-help": "もし君がこのオプションを選択したら、メデイアウィキは定期的にhttps://www.mediawiki.orgとメデイアウィキのインスタンスに関する基本的のデータをピンします。このデータはシステムのタイプ、PHPのバージョンと選択されたデータベースのバックエンドなどを含んでいます。メデイアウィキファンデーションは将来の",
        "config-almost-done": "これでほぼ終わりました!\n残りの設定を飛ばして、ウィキを今すぐインストールできます。",
        "config-optional-continue": "私にもっと質問してください。",
        "config-cache-options": "オブジェクトのキャッシュの設定:",
        "config-cache-help": "オブジェクトのキャッシュを使用すると、頻繁に使用するデータをキャッシュするため MediaWiki の動作速度を改善できます。\n中〜大規模サイトではこれを有効にすることを強くお勧めします。小規模サイトでも同様に効果があります。",
        "config-cache-none": "キャッシングしない(機能は取り払われます、しかもより大きなウィキサイト上でスピードの問題が発生します)",
-       "config-cache-accel": "PHP オブジェクト キャッシュ (APC、XCache、WinCache のいずれか)",
+       "config-cache-accel": "PHPオブジェクトキャッシュ (APC、APCu、XCache、WinCache のいずれか)",
        "config-cache-memcached": "memcached を使用 (追加の設定が必要)",
        "config-memcached-servers": "memcached サーバー:",
        "config-memcached-help": "Memcachedを使用するIPアドレスの一覧。\nカンマ区切りで、利用する特定のポートの指定が必要です。例:\n127.0.0.1:11211\n192.168.1.25:1234",
        "config-nofile": "ファイル「$1」が見つかりませんでした。削除された可能性があります。",
        "config-extension-link": "あなたのウィキは[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions 拡張機能]をサポートしていることをご存知ですか?\n\n[https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category カテゴリ別で拡張機能を見る]か[https://www.mediawiki.org/wiki/Extension_Matrix 拡張機能のマトリックス]で拡張機能すべてのリストをご覧になれます。",
        "mainpagetext": "<strong>MediaWiki はインストール済みです。</strong>",
-       "mainpagedocfooter": "ウィキソフトウェアの使い方に関する情報は[https://meta.wikimedia.org/wiki/Help:Contents 利用者案内]を参照してください。\n\n== はじめましょう ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings/ja 設定の一覧]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/ja MediaWiki よくある質問と回答]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki リリース情報メーリングリスト]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation/ja MediaWiki のあなたの言語へのローカライズ]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]"
+       "mainpagedocfooter": "ウィキソフトウェアの使い方に関する情報は[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 利用者案内]を参照してください。\n\n== はじめましょう ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings/ja 設定の一覧]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/ja MediaWiki よくある質問と回答]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki リリース情報メーリングリスト]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation/ja MediaWiki のあなたの言語へのローカライズ]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam あなたのウィキでスパムと戦う方法を学ぶ]"
 }
index ce3ae88..dd25b48 100644 (file)
        "config-install-schema": "스키마를 만드는 중",
        "config-install-pg-schema-not-exist": "PostgreSQL 스키마가 존재하지 않습니다.",
        "config-install-pg-schema-failed": "테이블을 만드는 데 실패했습니다.\n\"$2\" 스키마에 쓸 수 있는 \"$1\" 사용자가 있는지 확인하세요.",
-       "config-install-pg-commit": "ë°\94ë\80\90 사항을 적용하는 중",
+       "config-install-pg-commit": "ë³\80ê²½사항을 적용하는 중",
        "config-install-pg-plpgsql": "PL/pgSQL 언어에 대해 확인하는 중",
        "config-pg-no-plpgsql": "$1 데이터베이스에 PL/pgSQL 언어를 설치해야 합니다",
        "config-pg-no-create-privs": "설치를 위한 지정한 계정에 계정을 만드는 데 충분한 권한이 없습니다,",
index 3f20c07..b68b9d8 100644 (file)
        "config-db-install-account": "Hesabê bikarhêner bo avakirinê",
        "config-db-username": "Navê bikarhêner bo danagehê:",
        "config-db-password": "Şîfreya danegehê:",
+       "config-type-mssql": "Microsoft SQL Server",
        "config-invalid-db-type": "Cureya danegehê ya nederbasdar",
+       "config-sqlite-readonly": "Dosyeya <code>$1</code> ne nivîsbar e.",
        "config-db-web-account": "Hesabê danegehê bô têgihiştina tora înternetê",
+       "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
        "config-mysql-utf8": "UTF-8",
        "config-site-name": "Navê wîkiyê:",
index a6b1508..1fcb1cb 100644 (file)
        "config-type-mssql": "Microsoft SQLServer",
        "config-support-info": "MediaWiki støtter følgende databasesystem:\n\n$1\n\nHvis du ikke ser databasesystemet du prøver å bruke i listen nedenfor, følg instruksjonene det er lenket til over for å aktivere støtte.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] er den prefererte databasen for MediaWiki og er derfor best støttet.  MediaWiki fungerer også med [{{int:version-db-mariadb-url}} MariaDB] og [{{int:version-db-percona-url}} Percona Server], som begge er MySQL-kompatible. ([http://www.php.net/manual/en/mysqli.installation.php Hvordan kompilere med PHP med MySQL-støtte])",
-       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] er et populært åpen kildekode-databasesystem og et alternativ til MySQL. Det kan ha noen små utestående feil og det anbefales derfor ikke for bruk i et produksjonsmiljø. ([http://www.php.net/manual/en/pgsql.installation.php Hvordan kompilere PHP med PostgreSQL-støtte])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] er et populært åpen kildekode-databasesystem og et alternativ til MySQL.  ([http://www.php.net/manual/en/pgsql.installation.php Hvordan kompilere PHP med PostgreSQL-støtte])",
        "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] er et lettvekts-databasesystem som har veldig god støtte. ([http://www.php.net/manual/en/pdo.installation.php Hvordan kompilere PHP med SQLite-støtte], bruker PDO)",
        "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] er en kommersiell database for bedrifter. ([http://www.php.net/manual/en/oci8.installation.php Hvordan kompilere PHP med OCI8-støtte])",
        "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQLServer] er en kommersiell enterprise-database for Windows. ([http://www.php.net/manual/en/sqlsrv.installation.php Hvordan kompilere PHP med SQLSRV-støtte])",
        "config-nofile": "Filen \"$1\" ble ikke funnet. Kan den være blitt slettet?",
        "config-extension-link": "Visste du at wikien din kan brukes sammen med en mengde [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions utvidelser]?\n\nDu kan sjekke gjennom [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category utvidelser per kategori] eller [https://www.mediawiki.org/wiki/Extension_Matrix utvidelsesmatrisen] for å se den komplette listen av utvidelser.",
        "mainpagetext": "<strong>MediaWiki har blitt installert.</strong>",
-       "mainpagedocfooter": "Sjekk [https://meta.wikimedia.org/wiki/Help:Contents brukerveiledningen] for å få informasjon om hvordan du bruker wiki-programvaren.\n\n==Hvordan komme igang==\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Innstillingsliste]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Ofte stilte spørsmål om MediaWiki]\n*[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki e-postliste]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Tilpass MediaWiki for ditt språk]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Lær deg å beskytte deg mot spam på wikien din]"
+       "mainpagedocfooter": "Sjekk [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents brukerveiledningen] for å få informasjon om hvordan du bruker wiki-programvaren.\n\n==Hvordan komme igang==\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Innstillingsliste]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Ofte stilte spørsmål om MediaWiki]\n*[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki e-postliste]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Tilpass MediaWiki for ditt språk]\n*[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Lær deg å beskytte deg mot spam på wikien din]"
 }
index 0a77232..87a176c 100644 (file)
@@ -16,7 +16,8 @@
                        "Sjoerddebruin",
                        "Esketti",
                        "JaapDeKleine",
-                       "Macofe"
+                       "Macofe",
+                       "Hex"
                ]
        },
        "config-desc": "Het installatieprogramma voor MediaWiki",
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "MediaWiki ondersteunt de volgende databasesystemen:\n\n$1\n\nAls u het databasesysteem dat u wilt gebruiken niet in de lijst terugvindt, volg dan de handleiding waarnaar hierboven wordt verwezen om ondersteuning toe te voegen.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] is de primaire database voor MediaWiki en wordt het best ondersteund. MediaWiki werkt ook met [{{int:version-db-mariadb-url}} MariaDB] en [{{int:version-db-percona-url}} Percona Server], die MySQL compatibel zijn ([http://www.php.net/manual/en/mysqli.installation.php hoe PHP te compileren met MySQL-ondersteuning]).",
-       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] is een populair open source databasesysteem als alternatief voor MySQL. Het is mogelijk dat er een aantal bekende kleinere problemen zijn met MediaWiki in combinatie met deze database en daarom wordt PostgreSQL niet aanbevolen voor een productieomgeving ([http://www.php.net/manual/en/pgsql.installation.php hoe PHP gecompileerd moet zijn met ondersteuning voor PostgreSQL]).",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] is een populair open source databasesysteem als alternatief voor MySQL.([http://www.php.net/manual/en/pgsql.installation.php Hoe u PHP kunt compileren met ondersteuning voor PostgreSQL])",
        "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] is een zeer goed ondersteund lichtgewicht databasesysteem ([http://www.php.net/manual/en/pdo.installation.php hoe PHP gecompileerd moet zijn met ondersteuning voor SQLite]; gebruikt PDO).",
        "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] is een commerciële database voor grote bedrijven ([http://www.php.net/manual/en/oci8.installation.php PHP compileren met ondersteuning voor OCI8]).",
        "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] is een commerciële enterprisedatabase voor Windows ([http://www.php.net/manual/en/sqlsrv.installation.php PHP compileren met ondersteuning voor SQLSRV]).",
        "config-cache-options": "Instellingen voor het cachen van objecten:",
        "config-cache-help": "Het cachen van objecten wordt gebruikt om de snelheid van MediaWiki te verbeteren door vaak gebruikte gegevens te bewaren.\nMiddelgrote tot grote websites wordt geadviseerd dit in te schakelen en ook kleine sites merken de voordelen.",
        "config-cache-none": "Niets cachen.\nEr gaat geen functionaliteit verloren, maar dit kan invloed hebben op de prestaties.",
-       "config-cache-accel": "Cachen van objecten via PHP (APC, XCache of WinCache)",
+       "config-cache-accel": "Cachen van objecten via PHP (APC, APCu, XCache of WinCache)",
        "config-cache-memcached": "Memcached gebruiken (dit vereist aanvullende instellingen)",
        "config-memcached-servers": "Memcachedservers:",
        "config-memcached-help": "Lijst met IP-adressen te gebruiken voor Memcached.\nEén IP-adres per regel met een poortnummer.\nBijvoorbeeld:\n 127.0.0.1:11211\n 192.168.1.25:1234",
index 18d77e3..f9a1fef 100644 (file)
        "config-db-host-oracle-help": "Introduza um [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Nome Local de Ligação] válido; tem de estar visível para esta instalação um ficheiro tnsnames.ora.<br />Se está a usar bibliotecas cliente versão 10g ou posterior, também pode usar o método [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Ligação Fácil] de atribuição do nome.",
        "config-db-wiki-settings": "Identifique esta wiki",
        "config-db-name": "Nome da base de dados:",
-       "config-db-name-help": "Escolha um nome para identificar a sua wiki.\nO nome não deve conter espaços.\n\nSe estiver a usar um servidor partilhado, o fornecedor do alojamento deve poder fornecer-lhe o nome de uma base de dados que possa usar, ou permite-lhe criar bases de dados através de um painel de controle.",
+       "config-db-name-help": "Escolha um nome para identificar a sua wiki.\nO nome não deve conter espaços.\n\nSe estiver a usar um servidor partilhado, o fornecedor do alojamento deve poder fornecer-lhe o nome de uma base de dados que possa usar, ou permite-lhe criar bases de dados através de um painel de controlo.",
        "config-db-name-oracle": "Esquema ''(schema)'' da base de dados:",
        "config-db-account-oracle-warn": "Há três cenários suportados na instalação do servidor de base de dados Oracle:\n\nSe pretende criar a conta de acesso pela internet na base de dados durante o processo de instalação, forneça como conta para a instalação uma conta com o papel de SYSDBA na base de dados e especifique as credenciais desejadas para a conta de acesso pela internet. Se não pretende criar a conta de acesso pela internet durante a instalação, pode criá-la manualmente e fornecer só essa conta para a instalação (se ela tiver as permissões necessárias para criar os objetos do esquema ''(schema)''). A terceira alternativa é fornecer duas contas diferentes; uma com privilégios de criação e outra com privilégios limitados para o acesso pela internet.\n\nExiste um script para criação de uma conta com os privilégios necessários no diretório \"maintenance/oracle/\" desta instalação. Mantenha em mente que usar uma conta com privilégios limitados impossibilita todas as operações de manutenção com a conta padrão.",
        "config-db-install-account": "Conta do utilizador para a instalação",
index d7e86be..7b60ed0 100644 (file)
@@ -17,7 +17,8 @@
                        "Siebrand",
                        "Umherirrender",
                        "Waldir",
-                       "Jdforrester"
+                       "Jdforrester",
+                       "Liuxinyu970226"
                ]
        },
        "config-desc": "Short description of the installer.",
        "config-help": "This is used in help boxes.\n{{Identical|Help}}",
        "config-help-tooltip": "Tooltip for the 'help' links ({{msg-mw|config-help}}), to make it clear they'll expand in place rather than open a new page",
        "config-nofile": "Used as failure message. Parameters:\n* $1 - filename",
-       "config-extension-link": "Shown on last page of installation to inform about possible extensions.",
+       "config-extension-link": "Shown on last page of installation to inform about possible extensions.\n{{Identical|Did you know}}",
        "mainpagetext": "Along with {{msg-mw|mainpagedocfooter}}, the text you will see on the Main Page when your wiki is installed.",
        "mainpagedocfooter": "Along with {{msg-mw|mainpagetext}}, the text you will see on the Main Page when your wiki is installed.\nThis might be a good place to put information about <nowiki>{{GRAMMAR:}}</nowiki>. See [[{{NAMESPACE}}:{{BASEPAGENAME}}/fi]] for an example. For languages having grammatical distinctions and not having an appropriate <nowiki>{{GRAMMAR:}}</nowiki> software available, a suggestion to check and possibly amend the messages having <nowiki>{{SITENAME}}</nowiki> may be valuable. See [[{{NAMESPACE}}:{{BASEPAGENAME}}/ksh]] for an example."
 }
index 21a3297..5c4b1c3 100644 (file)
@@ -6,9 +6,14 @@
                        "Mehtab ahmed"
                ]
        },
+       "config-desc": "ميڊياوڪيءَ لاءِ تنصيبڪار",
+       "config-title": "ميڊياوڪي $1 تنصيب",
        "config-information": "معلومات",
+       "config-localsettings-key": "ڪنجي اپگريڊ ڪريو:",
        "config-localsettings-badkey": "توهان جي سنواري ڏنل ڪنجي غيردرست آهي.",
+       "config-session-error": "سيشن ھلائڻ ۾ خرابي:$1",
        "config-your-language": "توهان جي ٻولي:",
+       "config-your-language-help": "تنصيب جي عمل دوران استعمال ڪرڻ لاءِ ڪا ٻولي چونڊيو.",
        "config-wiki-language": "وڪِي ٻولي:",
        "config-back": "پوئتي ←",
        "config-continue": "اڳتي →",
@@ -24,7 +29,9 @@
        "config-page-restart": "تنصيبڪاري وري کان شروع ڪريو",
        "config-page-readme": "مون کي پڙهو",
        "config-page-copying": "پرت ڪندي",
+       "config-page-upgradedoc": "اپگريڊڪندي",
        "config-page-existingwiki": "موجوده وڪِي",
+       "config-help-restart": "ڇا توھان سڄي سانڍيل ڊيٽا ختم ڪرڻ چاھيو ٿا جيڪا توھان داخل ڪئي آھي ۽ تنصيبڪاريءَ جي عمل کي ٻيھر شروع ڪرڻ چاھيو ٿا؟",
        "config-restart": "ها، وري کان شروع ڪريو",
        "config-env-php": "PHP $1 تنصيب ٿي چڪو",
        "config-env-hhvm": "HHVM $1 تنصيب ٿي چڪو."
index e68a079..ecb8e87 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "Korrawit",
                        "Horus",
-                       "Octahedron80"
+                       "Octahedron80",
+                       "Aefgh39622"
                ]
        },
        "config-desc": "ตัวติดตั้งสำหรับมีเดียวิกิ",
@@ -74,6 +75,7 @@
        "config-admin-password": "รหัสผ่าน:",
        "config-admin-password-confirm": "รหัสผ่านอีกครั้ง:",
        "config-admin-email": "ที่อยู่อีเมล:",
+       "config-optional-continue": "ถามคำถามฉันอีก",
        "config-license-pd": "สาธารณสมบัติ",
        "config-extensions": "ส่วนขยาย",
        "config-install-step-done": "เสร็จสิ้น",
index bfd5ce6..5500097 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Andrewboltachev",
-                       "AlnashPiyash2"
+                       "AlnashPiyash2",
+                       "Zpizza"
                ]
        },
        "config-title": "MediaWiki $1 пуктон",
@@ -18,5 +19,5 @@
        "config-page-copying": "Лицензия",
        "config-page-upgradedoc": "Выльдытон",
        "config-diff3-bad": "GNU diff3 шедьтэмын ӧвӧл.",
-       "mainpagetext": "'''MediaWiki движок азинлыко пуктэмын.'''"
+       "mainpagetext": "<strong>MediaWiki движок азинлыко пуктэмын.</strong>"
 }
index 556b182..7644f41 100644 (file)
        "config-nofile": "Файл \"$1\" не знайдено. Його видалено?",
        "config-extension-link": "Чи знаєте ви, що ваше вікі підтримує [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions розширення]?\n\nВи можете переглядати [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category розширення по категорії] або в [https://www.mediawiki.org/wiki/Extension_Matrix матрицю розширень] щоб побачити повний список розширень.",
        "mainpagetext": "<strong>Програмне забезпечення «MediaWiki» встановлено.</strong>",
-       "mainpagedocfooter": "Ð\86нÑ\84оÑ\80маÑ\86Ñ\96Ñ\8e Ð¿Ñ\80о Ñ\80обоÑ\82Ñ\83 Ð· Ñ\86Ñ\96Ñ\94Ñ\8e Ð²Ñ\96кÑ\96 Ð¼Ð¾Ð¶Ð½Ð° Ð·Ð½Ð°Ð¹Ñ\82и Ð² [https://meta.wikimedia.org/wiki/Help:Contents Ð¿Ð¾Ñ\81Ñ\96бникÑ\83 ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87а].\n\n== Деякі корисні ресурси ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Список налаштувань];\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Часті питання з приводу MediaWiki];\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Розсилка повідомлень про появу нових версій MediaWiki];\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Локалізувати MediaWiki своєю мовою]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Дізнатися, як боротися зі спамом у своїй вікі]"
+       "mainpagedocfooter": "Ð\86нÑ\84оÑ\80маÑ\86Ñ\96Ñ\8e Ð¿Ñ\80о Ñ\80обоÑ\82Ñ\83 Ð· Ñ\86Ñ\96Ñ\94Ñ\8e Ð²Ñ\96кÑ\96 Ð¼Ð¾Ð¶Ð½Ð° Ð·Ð½Ð°Ð¹Ñ\82и Ð½Ð° Ñ\81Ñ\82оÑ\80Ñ\96нÑ\86Ñ\96 [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Ð\94овÑ\96дка:Ð\92мÑ\96Ñ\81Ñ\82].\n\n== Деякі корисні ресурси ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Список налаштувань];\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Часті питання з приводу MediaWiki];\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Розсилка повідомлень про появу нових версій MediaWiki];\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Локалізувати MediaWiki своєю мовою]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Дізнатися, як боротися зі спамом у своїй вікі]"
 }
index 55654bc..d2d5d3c 100644 (file)
        "config-profile-help": "如果您允许尽量多的人编写wiki,网站上的内容会更加丰富。在MediaWiki中,您可以轻松地审查最近更改,并轻易回退掉新手或破坏者造成的损害。\n\n然而,许多人觉得让MediaWiki存在多种角色将更加好用;同时,要说服所有人都愿以wiki的方式作贡献并非一件易事。因此,您可以有以下选择:\n\n<strong>{{int:config-profile-wiki}}</strong>模式允许包括未登录用户在内的所有人编辑。<strong>{{int:config-profile-no-anon}}</strong>的wiki需要额外的注册流程,这有可能会阻碍随意贡献者。\n\n<strong>{{int:config-profile-fishbowl}}</strong>方案只允许获批准的用户编辑,但对公众开放页面浏览(包括历史记录)。<strong>{{int:config-profile-private}}</strong>则只允许获批准的用户浏览、编辑页面。\n\n安装完成后,您还可以对用户权限进行更多、更复杂的配置,参见[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights 相关的使用手册]。",
        "config-license": "版权和许可证:",
        "config-license-none": "页脚无许可证",
-       "config-license-cc-by-sa": "知识共享“署名-相同方式共享”",
+       "config-license-cc-by-sa": "知识共享署名-相同方式共享",
        "config-license-cc-by": "知识共享署名",
        "config-license-cc-by-nc-sa": "知识共享署名-非商业性使用-相同方式共享",
        "config-license-cc-0": "知识共享Zero(公有领域)",
        "config-nofile": "找不到文件“$1”。它是否已被删除?",
        "config-extension-link": "您是否知道您的wiki支持[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions 扩展]?\n\n您可以浏览[https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category 扩展分类]或[https://www.mediawiki.org/wiki/Extension_Matrix 扩展矩阵]以查看完整的扩展列表。",
        "mainpagetext": "<strong>已安装MediaWiki。</strong>",
-       "mainpagedocfooter": "请查阅[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents]以获取使用本wiki软件的信息!\n\n== 入门 ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings MediaWiki配置设置列表]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/zh-hans MediaWiki常见问题]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki发布邮件列表]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources 本地化MediaWiki到您的语言]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam 了解如何在您的wiki上打击破坏]"
+       "mainpagedocfooter": "请查阅[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 用户指导]以获取使用本wiki软件的信息!\n\n== 入门 ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings MediaWiki配置设置列表]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/zh-hans MediaWiki常见问题]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki发布邮件列表]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources 本地化MediaWiki到您的语言]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam 了解如何在您的wiki上打击破坏]"
 }
index 2f2e934..b977af5 100644 (file)
        "config-profile-help": "Wiki 最佳的運作方式是盡可能讓大家都可以編輯文件。\n在 MediaWiki,可以很輕易的審查最近做的所有變更動作,並且可以還原由新手或惡意使用者造成的損害。\n\n不論如何,很多人發現 MediaWiki 可以廣泛的運用在各種地方,但並不是很容易可以說服每個人都遵守對 Wiki 有益的方式。\n所以您必須做出以下選擇。\n\n使用 <strong>{{int:config-profile-wiki}}</strong> 模式,允許所有人編輯文章,包含未匿名使用者。\n使用 <strong>{{int:config-profile-no-anon}}</strong> 模式,允許所有人編輯文章,不包含未登入的使用者。此模式較能管理所有使用者的言論,但會扼殺臨時使用者的貢獻機會。\n\n使用 <strong>{{int:config-profile-fishbowl}}</strong> 模式,僅經核准的使用者可以編輯,所有人可以檢視頁面,包含修訂的記錄。\n使用 <strong>{{int:config-profile-private}}</strong> 模式,僅經核准的使用者可以編輯、檢視頁面。\n\n有關更多複雜的使用者權限設定可在安裝程序結束後設定,請參考 [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights 相關文件說明]。",
        "config-license": "版權聲明與授權條款:",
        "config-license-none": "無授權條款頁腳",
-       "config-license-cc-by-sa": "創作共用 姓名標示-相同方式分享",
-       "config-license-cc-by": "創作共用 Attribution",
+       "config-license-cc-by-sa": "創用 CC 姓名標示-相同方式分享",
+       "config-license-cc-by": "創用 CC 姓名標示",
        "config-license-cc-by-nc-sa": "創作共用 Attribution-NonCommercial-ShareAlike",
        "config-license-cc-0": "創作共用 Zero (公有領域)",
        "config-license-gfdl": "GNU 自由文件授權條款 1.3 或更高版本",
index 910a7ca..8f5700a 100644 (file)
  * @ingroup HTTP
  */
 
+/**
+ * Cookie jar to use with MWHttpRequest. Does not handle cookie unsetting.
+ */
 class CookieJar {
+       /** @var Cookie[] */
        private $cookie = [];
 
        /**
index 2f5a454..db6869b 100644 (file)
@@ -58,7 +58,7 @@ class MapCacheLRU {
         * @return void
         */
        public function set( $key, $value ) {
-               if ( array_key_exists( $key, $this->cache ) ) {
+               if ( $this->has( $key ) ) {
                        $this->ping( $key );
                } elseif ( count( $this->cache ) >= $this->maxCacheKeys ) {
                        reset( $this->cache );
@@ -75,6 +75,9 @@ class MapCacheLRU {
         * @return bool
         */
        public function has( $key ) {
+               if ( !is_int( $key ) && !is_string( $key ) ) {
+                       throw new MWException( __METHOD__ . ' called with invalid key. Must be string or integer.' );
+               }
                return array_key_exists( $key, $this->cache );
        }
 
@@ -87,7 +90,7 @@ class MapCacheLRU {
         * @return mixed Returns null if the key was not found
         */
        public function get( $key ) {
-               if ( !array_key_exists( $key, $this->cache ) ) {
+               if ( !$this->has( $key ) ) {
                        return null;
                }
 
index 9c1ec8e..016c9b1 100644 (file)
  * <https://github.com/phacility/xhprof>. XHProf can be installed as a PECL
  * package for use with PHP5 (Zend PHP) and is built-in to HHVM 3.3.0.
  *
+ * This also supports using the Tideways profiler
+ * <https://github.com/tideways/php-profiler-extension>, which additionally
+ * has support for PHP7.
+ *
  * @since 1.28
  */
 class Xhprof {
@@ -43,10 +47,16 @@ class Xhprof {
         */
        public static function enable( $flags = 0, $options = [] ) {
                if ( self::isEnabled() ) {
-                       throw new Exception( 'Xhprof profiling is already enabled.' );
+                       throw new Exception( 'Profiling is already enabled.' );
                }
                self::$enabled = true;
-               xhprof_enable( $flags, $options );
+               if ( function_exists( 'xhprof_enable' ) ) {
+                       xhprof_enable( $flags, $options );
+               } elseif ( function_exists( 'tideways_enable' ) ) {
+                       tideways_enable( $flags, $options );
+               } else {
+                       throw new Exception( "Neither xhprof nor tideways are installed" );
+               }
        }
 
        /**
@@ -57,7 +67,12 @@ class Xhprof {
        public static function disable() {
                if ( self::isEnabled() ) {
                        self::$enabled = false;
-                       return xhprof_disable();
+                       if ( function_exists( 'xhprof_disable' ) ) {
+                               return xhprof_disable();
+                       } else {
+                               // tideways
+                               return tideways_disable();
+                       }
                }
        }
 }
index 02b3c92..6e6a3ad 100644 (file)
@@ -72,7 +72,7 @@ class APCUBagOStuff extends APCBagOStuff {
                if ( apcu_exists( $key . self::KEY_SUFFIX ) ) {
                        return apcu_inc( $key . self::KEY_SUFFIX, $value );
                } else {
-                       return apcu_set( $key . self::KEY_SUFFIX, $value );
+                       return false;
                }
        }
 
@@ -85,7 +85,7 @@ class APCUBagOStuff extends APCBagOStuff {
                if ( apcu_exists( $key . self::KEY_SUFFIX ) ) {
                        return apcu_dec( $key . self::KEY_SUFFIX, $value );
                } else {
-                       return apcu_set( $key . self::KEY_SUFFIX, -$value );
+                       return false;
                }
        }
 }
index 6996ce5..d84c959 100644 (file)
  */
 class WinCacheBagOStuff extends BagOStuff {
        protected function doGet( $key, $flags = 0 ) {
-               $casToken = null;
-
-               return $this->getWithToken( $key, $casToken, $flags );
-       }
-
-       protected function getWithToken( $key, &$casToken, $flags = 0 ) {
                $val = wincache_ucache_get( $key );
-
-               $casToken = $val;
-
                if ( is_string( $val ) ) {
                        $val = unserialize( $val );
                }
@@ -54,10 +45,6 @@ class WinCacheBagOStuff extends BagOStuff {
                return ( is_array( $result ) && $result === [] ) || $result;
        }
 
-       protected function cas( $casToken, $key, $value, $exptime = 0 ) {
-               return wincache_ucache_cas( $key, $casToken, serialize( $value ) );
-       }
-
        public function delete( $key ) {
                wincache_ucache_delete( $key );
 
diff --git a/includes/libs/rdbms/connectionmanager/ConnectionManager.php b/includes/libs/rdbms/connectionmanager/ConnectionManager.php
new file mode 100644 (file)
index 0000000..4f72f77
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+
+namespace Wikimedia\Rdbms;
+
+use Database;
+use DBConnRef;
+use IDatabase;
+use InvalidArgumentException;
+use LoadBalancer;
+
+/**
+ * Database connection manager.
+ *
+ * This manages access to master and replica databases.
+ *
+ * @since 1.29
+ *
+ * @license GPL-2.0+
+ * @author Addshore
+ */
+class ConnectionManager {
+
+       /**
+        * @var LoadBalancer
+        */
+       private $loadBalancer;
+
+       /**
+        * The symbolic name of the target database, or false for the local wiki's database.
+        *
+        * @var string|false
+        */
+       private $domain;
+
+       /**
+        * @var string[]
+        */
+       private $groups = [];
+
+       /**
+        * @param LoadBalancer $loadBalancer
+        * @param string|bool $domain Optional logical DB name, defaults to current wiki.
+        *        This follows the convention for database names used by $loadBalancer.
+        * @param string[] $groups see LoadBalancer::getConnection
+        *
+        * @throws InvalidArgumentException
+        */
+       public function __construct( LoadBalancer $loadBalancer, $domain = false, array $groups = [] ) {
+               if ( !is_string( $domain ) && $domain !== false ) {
+                       throw new InvalidArgumentException( '$dbName must be a string, or false.' );
+               }
+
+               $this->loadBalancer = $loadBalancer;
+               $this->domain = $domain;
+               $this->groups = $groups;
+       }
+
+       /**
+        * @param int $i
+        * @param string[]|null $groups
+        *
+        * @return Database
+        */
+       private function getConnection( $i, array $groups = null ) {
+               $groups = $groups === null ? $this->groups : $groups;
+               return $this->loadBalancer->getConnection( $i, $groups, $this->domain );
+       }
+
+       /**
+        * @param int $i
+        * @param string[]|null $groups
+        *
+        * @return DBConnRef
+        */
+       private function getConnectionRef( $i, array $groups = null ) {
+               $groups = $groups === null ? $this->groups : $groups;
+               return $this->loadBalancer->getConnectionRef( $i, $groups, $this->domain );
+       }
+
+       /**
+        * Returns a connection to the master DB, for updating. The connection should later be released
+        * by calling releaseConnection().
+        *
+        * @since 1.29
+        *
+        * @return Database
+        */
+       public function getWriteConnection() {
+               return $this->getConnection( DB_MASTER );
+       }
+
+       /**
+        * Returns a database connection for reading. The connection should later be released by
+        * calling releaseConnection().
+        *
+        * @since 1.29
+        *
+        * @param string[]|null $groups
+        *
+        * @return Database
+        */
+       public function getReadConnection( array $groups = null ) {
+               $groups = $groups === null ? $this->groups : $groups;
+               return $this->getConnection( DB_REPLICA, $groups );
+       }
+
+       /**
+        * @since 1.29
+        *
+        * @param IDatabase $db
+        */
+       public function releaseConnection( IDatabase $db ) {
+               $this->loadBalancer->reuseConnection( $db );
+       }
+
+       /**
+        * Returns a connection ref to the master DB, for updating.
+        *
+        * @since 1.29
+        *
+        * @return DBConnRef
+        */
+       public function getWriteConnectionRef() {
+               return $this->getConnectionRef( DB_MASTER );
+       }
+
+       /**
+        * Returns a database connection ref for reading.
+        *
+        * @since 1.29
+        *
+        * @param string[]|null $groups
+        *
+        * @return DBConnRef
+        */
+       public function getReadConnectionRef( array $groups = null ) {
+               $groups = $groups === null ? $this->groups : $groups;
+               return $this->getConnectionRef( DB_REPLICA, $groups );
+       }
+
+}
diff --git a/includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManager.php b/includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManager.php
new file mode 100644 (file)
index 0000000..fb03182
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+
+namespace Wikimedia\Rdbms;
+
+use Database;
+use DBConnRef;
+
+/**
+ * Database connection manager.
+ *
+ * This manages access to master and replica databases. It also manages state that indicates whether
+ * the replica databases are possibly outdated after a write operation, and thus the master database
+ * should be used for subsequent read operations.
+ *
+ * @note: Services that access overlapping sets of database tables, or interact with logically
+ * related sets of data in the database, should share a SessionConsistentConnectionManager.
+ * Services accessing unrelated sets of information may prefer to not share a
+ * SessionConsistentConnectionManager, so they can still perform read operations against replica
+ * databases after a (unrelated, per the assumption) write operation to the master database.
+ * Generally, sharing a SessionConsistentConnectionManager improves consistency (by avoiding race
+ * conditions due to replication lag), but can reduce performance (by directing more read
+ * operations to the master database server).
+ *
+ * @since 1.29
+ *
+ * @license GPL-2.0+
+ * @author Daniel Kinzler
+ * @author Addshore
+ */
+class SessionConsistentConnectionManager extends ConnectionManager {
+
+       /**
+        * @var bool
+        */
+       private $forceWriteConnection = false;
+
+       /**
+        * Forces all future calls to getReadConnection() to return a write connection.
+        * Use this before performing read operations that are critical for a future update.
+        *
+        * @since 1.29
+        */
+       public function prepareForUpdates() {
+               $this->forceWriteConnection = true;
+       }
+
+       /**
+        * @since 1.29
+        *
+        * @param string[]|null $groups
+        *
+        * @return Database
+        */
+       public function getReadConnection( array $groups = null ) {
+               if ( $this->forceWriteConnection ) {
+                       return parent::getWriteConnection();
+               }
+
+               return parent::getReadConnection( $groups );
+       }
+
+       /**
+        * @since 1.29
+        *
+        * @return Database
+        */
+       public function getWriteConnection() {
+               $this->prepareForUpdates();
+               return parent::getWriteConnection();
+       }
+
+       /**
+        * @since 1.29
+        *
+        * @param string[]|null $groups
+        *
+        * @return DBConnRef
+        */
+       public function getReadConnectionRef( array $groups = null ) {
+               if ( $this->forceWriteConnection ) {
+                       return parent::getWriteConnectionRef();
+               }
+
+               return parent::getReadConnectionRef( $groups );
+       }
+
+       /**
+        * @since 1.29
+        *
+        * @return DBConnRef
+        */
+       public function getWriteConnectionRef() {
+               $this->prepareForUpdates();
+               return parent::getWriteConnectionRef();
+       }
+
+}
index 7317d54..a06aad2 100644 (file)
@@ -41,7 +41,7 @@ class DatabaseSqlite extends Database {
        /** @var resource */
        protected $mLastResult;
 
-       /** @var $mConn PDO */
+       /** @var PDO */
        protected $mConn;
 
        /** @var FSLockManager (hopefully on the same server as the DB) */
index 48d76c4..c6055db 100644 (file)
@@ -1183,7 +1183,7 @@ interface IDatabase {
        /**
         * DELETE query wrapper.
         *
-        * @param array $table Table name
+        * @param string $table Table name
         * @param string|array $conds Array of conditions. See $conds in IDatabase::select()
         *   for the format. Use $conds == "*" to delete all rows
         * @param string $fname Name of the calling function
index d42fed9..634993a 100644 (file)
@@ -31,7 +31,7 @@ use Wikimedia\ScopedCallback;
 class LoadBalancer implements ILoadBalancer {
        /** @var array[] Map of (server index => server config array) */
        private $mServers;
-       /** @var array[] Map of (local/foreignUsed/foreignFree => server index => IDatabase array) */
+       /** @var IDatabase[][] Map of (local/foreignUsed/foreignFree => server index => IDatabase array) */
        private $mConns;
        /** @var float[] Map of (server index => weight) */
        private $mLoads;
@@ -390,6 +390,9 @@ class LoadBalancer implements ILoadBalancer {
                return $i;
        }
 
+       /**
+        * @param DBMasterPos|false $pos
+        */
        public function waitFor( $pos ) {
                $this->mWaitForPos = $pos;
                $i = $this->mReadIndex;
@@ -436,6 +439,10 @@ class LoadBalancer implements ILoadBalancer {
                return $ok;
        }
 
+       /**
+        * @param int $i
+        * @return IDatabase
+        */
        public function getAnyOpenConnection( $i ) {
                foreach ( $this->mConns as $connsByServer ) {
                        if ( !empty( $connsByServer[$i] ) ) {
@@ -1447,6 +1454,11 @@ class LoadBalancer implements ILoadBalancer {
                }
        }
 
+       /**
+        * @param IDatabase $conn
+        * @param DBMasterPos|false $pos
+        * @param int $timeout
+        */
        public function safeWaitForMasterPos( IDatabase $conn, $pos = false, $timeout = 10 ) {
                if ( $this->getServerCount() <= 1 || !$conn->getLBInfo( 'replica' ) ) {
                        return true; // server is not a replica DB
index 45b1d83..e374794 100644 (file)
@@ -55,8 +55,6 @@ class LoadMonitorMySQL extends LoadMonitor {
                                // https://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html
                                if ( $s->Innodb_buffer_pool_pages_total > 0 ) {
                                        $ratio = $s->Innodb_buffer_pool_pages_data / $s->Innodb_buffer_pool_pages_total;
-                               } elseif ( $s->Qcache_total_blocks > 0 ) {
-                                       $ratio = 1.0 - $s->Qcache_free_blocks / $s->Qcache_total_blocks;
                                } else {
                                        $ratio = 1.0;
                                }
index 21e40ec..c390232 100644 (file)
@@ -22,6 +22,8 @@
  * @since 1.25
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This class formats block log entries.
  *
@@ -91,6 +93,7 @@ class BlockLogFormatter extends LogFormatter {
 
        public function getActionLinks() {
                $subtype = $this->entry->getSubtype();
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
                        || !( $subtype === 'block' || $subtype === 'reblock' )
                        || !$this->context->getUser()->isAllowed( 'block' )
@@ -101,13 +104,13 @@ class BlockLogFormatter extends LogFormatter {
                // Show unblock/change block link
                $title = $this->entry->getTarget();
                $links = [
-                       Linker::linkKnown(
+                       $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( 'Unblock', $title->getDBkey() ),
-                               $this->msg( 'unblocklink' )->escaped()
+                               $this->msg( 'unblocklink' )->text()
                        ),
-                       Linker::linkKnown(
+                       $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( 'Block', $title->getDBkey() ),
-                               $this->msg( 'change-blocklink' )->escaped()
+                               $this->msg( 'change-blocklink' )->text()
                        )
                ];
 
index f130740..861ea30 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
+
 class ContentModelLogFormatter extends LogFormatter {
        protected function getMessageParameters() {
                $lang = $this->context->getLanguage();
@@ -18,9 +20,9 @@ class ContentModelLogFormatter extends LogFormatter {
                }
 
                $params = $this->extractParameters();
-               $revert = Linker::linkKnown(
+               $revert = MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
                        SpecialPage::getTitleFor( 'ChangeContentModel' ),
-                       $this->msg( 'logentry-contentmodel-change-revertlink' )->escaped(),
+                       $this->msg( 'logentry-contentmodel-change-revertlink' )->text(),
                        [],
                        [
                                'pagetitle' => $this->entry->getTarget()->getPrefixedText(),
index c205626..05973df 100644 (file)
@@ -23,6 +23,8 @@
  * @since 1.22
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This class formats delete log entries.
  *
@@ -114,6 +116,7 @@ class DeleteLogFormatter extends LogFormatter {
 
        public function getActionLinks() {
                $user = $this->context->getUser();
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( !$user->isAllowed( 'deletedhistory' )
                        || $this->entry->isDeleted( LogPage::DELETED_ACTION )
                ) {
@@ -122,14 +125,15 @@ class DeleteLogFormatter extends LogFormatter {
 
                switch ( $this->entry->getSubtype() ) {
                        case 'delete': // Show undelete link
+                       case 'delete_redir':
                                if ( $user->isAllowed( 'undelete' ) ) {
                                        $message = 'undeletelink';
                                } else {
                                        $message = 'undeleteviewlink';
                                }
-                               $revert = Linker::linkKnown(
+                               $revert = $linkRenderer->makeKnownLink(
                                        SpecialPage::getTitleFor( 'Undelete' ),
-                                       $this->msg( $message )->escaped(),
+                                       $this->msg( $message )->text(),
                                        [],
                                        [ 'target' => $this->entry->getTarget()->getPrefixedDBkey() ]
                                );
@@ -155,9 +159,9 @@ class DeleteLogFormatter extends LogFormatter {
                                if ( count( $ids ) == 1 ) {
                                        // Live revision diffs...
                                        if ( $key == 'oldid' || $key == 'revision' ) {
-                                               $links[] = Linker::linkKnown(
+                                               $links[] = $linkRenderer->makeKnownLink(
                                                        $this->entry->getTarget(),
-                                                       $this->msg( 'diff' )->escaped(),
+                                                       $this->msg( 'diff' )->text(),
                                                        [],
                                                        [
                                                                'diff' => intval( $ids[0] ),
@@ -166,9 +170,9 @@ class DeleteLogFormatter extends LogFormatter {
                                                );
                                                // Deleted revision diffs...
                                        } elseif ( $key == 'artimestamp' || $key == 'archive' ) {
-                                               $links[] = Linker::linkKnown(
+                                               $links[] = $linkRenderer->makeKnownLink(
                                                        SpecialPage::getTitleFor( 'Undelete' ),
-                                                       $this->msg( 'diff' )->escaped(),
+                                                       $this->msg( 'diff' )->text(),
                                                        [],
                                                        [
                                                                'target' => $this->entry->getTarget()->getPrefixedDBkey(),
@@ -180,9 +184,9 @@ class DeleteLogFormatter extends LogFormatter {
                                }
 
                                // View/modify link...
-                               $links[] = Linker::linkKnown(
+                               $links[] = $linkRenderer->makeKnownLink(
                                        SpecialPage::getTitleFor( 'Revisiondelete' ),
-                                       $this->msg( 'revdel-restore' )->escaped(),
+                                       $this->msg( 'revdel-restore' )->text(),
                                        [],
                                        [
                                                'target' => $this->entry->getTarget()->getPrefixedText(),
@@ -205,9 +209,9 @@ class DeleteLogFormatter extends LogFormatter {
                                        $query = implode( ',', $query );
                                }
                                // Link to each hidden object ID, $params[1] is the url param
-                               $revert = Linker::linkKnown(
+                               $revert = $linkRenderer->makeKnownLink(
                                        SpecialPage::getTitleFor( 'Revisiondelete' ),
-                                       $this->msg( 'revdel-restore' )->escaped(),
+                                       $this->msg( 'revdel-restore' )->text(),
                                        [],
                                        [
                                                'target' => $this->entry->getTarget()->getPrefixedText(),
index 0cf584b..57a7597 100644 (file)
@@ -23,6 +23,8 @@
  * @file
  */
 
+use MediaWiki\MediaWikiServices;
+
 class LogEventsList extends ContextSource {
        const NO_ACTION_LINK = 1;
        const NO_EXTRA_USER_LINKS = 2;
@@ -142,10 +144,11 @@ class LogEventsList extends ContextSource {
         */
        private function getFilterLinks( $filter ) {
                // show/hide links
-               $messages = [ $this->msg( 'show' )->escaped(), $this->msg( 'hide' )->escaped() ];
+               $messages = [ $this->msg( 'show' )->text(), $this->msg( 'hide' )->text() ];
                // Option value -> message mapping
                $links = [];
                $hiddens = ''; // keep track for "go" button
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                foreach ( $filter as $type => $val ) {
                        // Should the below assignment be outside the foreach?
                        // Then it would have to be copied. Not certain what is more expensive.
@@ -155,7 +158,7 @@ class LogEventsList extends ContextSource {
                        $hideVal = 1 - intval( $val );
                        $query[$queryKey] = $hideVal;
 
-                       $link = Linker::linkKnown(
+                       $link = $linkRenderer->makeKnownLink(
                                $this->getTitle(),
                                $messages[$hideVal],
                                [],
@@ -672,9 +675,9 @@ class LogEventsList extends ContextSource {
                                $urlParam = array_merge( $urlParam, $extraUrlParams );
                        }
 
-                       $s .= Linker::linkKnown(
+                       $s .= MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
                                SpecialPage::getTitleFor( 'Log' ),
-                               $context->msg( 'log-fulllog' )->escaped(),
+                               $context->msg( 'log-fulllog' )->text(),
                                [],
                                $urlParam
                        );
index c86eabd..ac0564d 100644 (file)
@@ -541,7 +541,7 @@ class BitmapHandler extends TransformationalImageHandler {
         * @param array $params Rotate parameters.
         *   'rotation' clockwise rotation in degrees, allowed are multiples of 90
         * @since 1.21
-        * @return bool
+        * @return bool|MediaTransformError
         */
        public function rotate( $file, $params ) {
                global $wgImageMagickConvertCommand;
index 18f75ec..a852215 100644 (file)
@@ -170,7 +170,7 @@ class DjVuHandler extends ImageHandler {
                                'thumbnail_error',
                                $width,
                                $height,
-                               wfMessage( 'thumbnail_dest_directory' )->text()
+                               wfMessage( 'thumbnail_dest_directory' )
                        );
                }
 
@@ -197,7 +197,7 @@ class DjVuHandler extends ImageHandler {
 
                        return new MediaTransformError( 'thumbnail_error',
                                $params['width'], $params['height'],
-                               wfMessage( 'filemissing' )->text()
+                               wfMessage( 'filemissing' )
                        );
                }
 
index b8b6f6c..6c857a8 100644 (file)
@@ -130,7 +130,7 @@ class JpegHandler extends ExifBitmapHandler {
         * @param array $params Rotate parameters.
         *    'rotation' clockwise rotation in degrees, allowed are multiples of 90
         * @since 1.21
-        * @return bool
+        * @return bool|MediaTransformError
         */
        public function rotate( $file, $params ) {
                global $wgJpegTran;
index b3a555a..5366c4f 100644 (file)
@@ -439,19 +439,12 @@ class ThumbnailImage extends MediaTransformOutput {
  * @ingroup Media
  */
 class MediaTransformError extends MediaTransformOutput {
-       /** @var string HTML formatted version of the error */
-       private $htmlMsg;
-
-       /** @var string Plain text formatted version of the error */
-       private $textMsg;
+       /** @var Message */
+       private $msg;
 
        function __construct( $msg, $width, $height /*, ... */ ) {
                $args = array_slice( func_get_args(), 3 );
-               $htmlArgs = array_map( 'htmlspecialchars', $args );
-               $htmlArgs = array_map( 'nl2br', $htmlArgs );
-
-               $this->htmlMsg = wfMessage( $msg )->rawParams( $htmlArgs )->escaped();
-               $this->textMsg = wfMessage( $msg )->rawParams( $htmlArgs )->text();
+               $this->msg = wfMessage( $msg )->params( $args );
                $this->width = intval( $width );
                $this->height = intval( $height );
                $this->url = false;
@@ -461,21 +454,29 @@ class MediaTransformError extends MediaTransformOutput {
        function toHtml( $options = [] ) {
                return "<div class=\"MediaTransformError\" style=\"" .
                        "width: {$this->width}px; height: {$this->height}px; display:inline-block;\">" .
-                       $this->htmlMsg .
+                       $this->getHtmlMsg() .
                        "</div>";
        }
 
        function toText() {
-               return $this->textMsg;
+               return $this->msg->text();
        }
 
        function getHtmlMsg() {
-               return $this->htmlMsg;
+               return $this->msg->escaped();
+       }
+
+       function getMsg() {
+               return $this->msg;
        }
 
        function isError() {
                return true;
        }
+
+       function getHttpStatusCode() {
+               return 500;
+       }
 }
 
 /**
@@ -488,7 +489,12 @@ class TransformParameterError extends MediaTransformError {
                parent::__construct( 'thumbnail_error',
                        max( isset( $params['width'] ) ? $params['width'] : 0, 120 ),
                        max( isset( $params['height'] ) ? $params['height'] : 0, 120 ),
-                       wfMessage( 'thumbnail_invalid_params' )->text() );
+                       wfMessage( 'thumbnail_invalid_params' )
+               );
+       }
+
+       function getHttpStatusCode() {
+               return 400;
        }
 }
 
@@ -501,14 +507,18 @@ class TransformParameterError extends MediaTransformError {
 class TransformTooBigImageAreaError extends MediaTransformError {
        function __construct( $params, $maxImageArea ) {
                $msg = wfMessage( 'thumbnail_toobigimagearea' );
+               $msg->rawParams(
+                       $msg->getLanguage()->formatComputingNumbers( $maxImageArea, 1000, "size-$1pixel" )
+               );
 
                parent::__construct( 'thumbnail_error',
                        max( isset( $params['width'] ) ? $params['width'] : 0, 120 ),
                        max( isset( $params['height'] ) ? $params['height'] : 0, 120 ),
-                       $msg->rawParams(
-                               $msg->getLanguage()->formatComputingNumbers(
-                                       $maxImageArea, 1000, "size-$1pixel" )
-                               )->text()
-                       );
+                       $msg
+               );
+       }
+
+       function getHttpStatusCode() {
+               return 400;
        }
 }
index f3b33ac..0cea6d8 100644 (file)
@@ -178,14 +178,14 @@ class SvgHandler extends ImageHandler {
 
                $metadata = $this->unpackMetadata( $image->getMetadata() );
                if ( isset( $metadata['error'] ) ) { // sanity check
-                       $err = wfMessage( 'svg-long-error', $metadata['error']['message'] )->text();
+                       $err = wfMessage( 'svg-long-error', $metadata['error']['message'] );
 
                        return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, $err );
                }
 
                if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
                        return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight,
-                               wfMessage( 'thumbnail_dest_directory' )->text() );
+                               wfMessage( 'thumbnail_dest_directory' ) );
                }
 
                $srcPath = $image->getLocalRefPath();
@@ -196,7 +196,7 @@ class SvgHandler extends ImageHandler {
 
                        return new MediaTransformError( 'thumbnail_error',
                                $params['width'], $params['height'],
-                               wfMessage( 'filemissing' )->text()
+                               wfMessage( 'filemissing' )
                        );
                }
 
@@ -219,7 +219,7 @@ class SvgHandler extends ImageHandler {
                                        wfHostname(), $lnPath, $srcPath ) );
                        return new MediaTransformError( 'thumbnail_error',
                                $params['width'], $params['height'],
-                               wfMessage( 'thumbnail-temp-create' )->text()
+                               wfMessage( 'thumbnail-temp-create' )
                        );
                }
 
index e33c27e..60aec45 100644 (file)
@@ -217,7 +217,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
 
                        return new MediaTransformError( 'thumbnail_error',
                                $scalerParams['clientWidth'], $scalerParams['clientHeight'],
-                               wfMessage( 'filemissing' )->text()
+                               wfMessage( 'filemissing' )
                        );
                }
 
@@ -267,7 +267,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
                        # Thumbnail was zero-byte and had to be removed
                        return new MediaTransformError( 'thumbnail_error',
                                $scalerParams['clientWidth'], $scalerParams['clientHeight'],
-                               wfMessage( 'unknown-error' )->text()
+                               wfMessage( 'unknown-error' )
                        );
                } elseif ( $mto ) {
                        return $mto;
@@ -565,7 +565,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
         * @param array $params Rotate parameters.
         *   'rotation' clockwise rotation in degrees, allowed are multiples of 90
         * @since 1.24 Is non-static. From 1.21 it was static
-        * @return bool
+        * @return bool|MediaTransformError
         */
        public function rotate( $file, $params ) {
                return new MediaTransformError( 'thumbnail_error', 0, 0,
index 47dae78..de49fc3 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 use \MediaWiki\MediaWikiServices;
+use \Wikimedia\WaitConditionLoop;
 
 /**
  * Class to store objects in the database
index 9a2a8e2..cc3ef26 100644 (file)
@@ -621,21 +621,9 @@ class Article implements Page {
                                        # Preload timestamp to avoid a DB hit
                                        $outputPage->setRevisionTimestamp( $this->mPage->getTimestamp() );
 
-                                       # Pages containing custom CSS or JavaScript get special treatment
-                                       if ( $this->getTitle()->isCssOrJsPage() || $this->getTitle()->isCssJsSubpage() ) {
-                                               wfDebug( __METHOD__ . ": showing CSS/JS source\n" );
-                                               $this->showCssOrJsPage();
-                                               $outputDone = true;
-                                       } elseif ( !Hooks::run( 'ArticleContentViewCustom',
+                                       if ( !Hooks::run( 'ArticleContentViewCustom',
                                                        [ $this->fetchContentObject(), $this->getTitle(), $outputPage ] ) ) {
 
-                                               # Allow extensions do their own custom view for certain pages
-                                               $outputDone = true;
-                                       } elseif ( !ContentHandler::runLegacyHooks(
-                                               'ArticleViewCustom',
-                                               [ $this->fetchContentObject(), $this->getTitle(), $outputPage ],
-                                               '1.21'
-                                       ) ) {
                                                # Allow extensions do their own custom view for certain pages
                                                $outputDone = true;
                                        }
@@ -781,47 +769,6 @@ class Article implements Page {
                $this->mPage->doViewUpdates( $user, (int)$new );
        }
 
-       /**
-        * Show a page view for a page formatted as CSS or JavaScript. To be called by
-        * Article::view() only.
-        *
-        * This exists mostly to serve the deprecated ShowRawCssJs hook (used to customize these views).
-        * It has been replaced by the ContentGetParserOutput hook, which lets you do the same but with
-        * more flexibility.
-        *
-        * @param bool $showCacheHint Whether to show a message telling the user
-        *   to clear the browser cache (default: true).
-        */
-       protected function showCssOrJsPage( $showCacheHint = true ) {
-               $outputPage = $this->getContext()->getOutput();
-
-               if ( $showCacheHint ) {
-                       $dir = $this->getContext()->getLanguage()->getDir();
-                       $lang = $this->getContext()->getLanguage()->getHtmlCode();
-
-                       $outputPage->wrapWikiMsg(
-                               "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
-                               'clearyourcache'
-                       );
-               }
-
-               $this->fetchContentObject();
-
-               if ( $this->mContentObject ) {
-                       // Give hooks a chance to customise the output
-                       if ( ContentHandler::runLegacyHooks(
-                               'ShowRawCssJs',
-                               [ $this->mContentObject, $this->getTitle(), $outputPage ],
-                               '1.24'
-                       ) ) {
-                               // If no legacy hooks ran, display the content of the parser output, including RL modules,
-                               // but excluding metadata like categories and language links
-                               $po = $this->mContentObject->getParserOutput( $this->getTitle() );
-                               $outputPage->addParserOutputContent( $po );
-                       }
-               }
-       }
-
        /**
         * Get the robot policy to be used for the current view
         * @param string $action The action= GET parameter
@@ -2331,16 +2278,6 @@ class Article implements Page {
                return $this->mPage->getRevision();
        }
 
-       /**
-        * Call to WikiPage function for backwards compatibility.
-        * @see WikiPage::getText
-        * @deprecated since 1.21 use WikiPage::getContent() instead
-        */
-       public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) {
-               wfDeprecated( __METHOD__, '1.21' );
-               return $this->mPage->getText( $audience, $user );
-       }
-
        /**
         * Call to WikiPage function for backwards compatibility.
         * @see WikiPage::getTimestamp
@@ -2503,15 +2440,6 @@ class Article implements Page {
                );
        }
 
-       /**
-        * Call to WikiPage function for backwards compatibility.
-        * @deprecated since 1.21, use prepareContentForEdit
-        * @see WikiPage::prepareTextForEdit
-        */
-       public function prepareTextForEdit( $text, $revid = null, User $user = null ) {
-               return $this->mPage->prepareTextForEdit( $text, $revid, $user );
-       }
-
        /**
         * Call to WikiPage function for backwards compatibility.
         * @see WikiPage::protectDescription
@@ -2744,15 +2672,5 @@ class Article implements Page {
                WikiPage::onArticleEdit( $title );
        }
 
-       /**
-        * @param string $oldtext
-        * @param string $newtext
-        * @param int $flags
-        * @return string
-        * @deprecated since 1.21, use ContentHandler::getAutosummary() instead
-        */
-       public static function getAutosummary( $oldtext, $newtext, $flags ) {
-               return WikiPage::getAutosummary( $oldtext, $newtext, $flags );
-       }
        // ******
 }
index 6ab3ffc..f4880d1 100644 (file)
@@ -42,6 +42,10 @@ class ImageHistoryPseudoPager extends ReverseChronologicalPager {
                $this->mImg = null;
                $this->mHist = [];
                $this->mRange = [ 0, 0 ]; // display range
+
+               // Only display 10 revisions at once by default, otherwise the list is overwhelming
+               $this->mLimitsShown = array_merge( [ 10 ], $this->mLimitsShown );
+               $this->setLimit( 10 );
        }
 
        /**
index c478550..1fa4bfa 100644 (file)
@@ -205,7 +205,7 @@ class WikiFilePage extends WikiPage {
 
                /** @var LocalRepo $repo */
                $repo = $file->getRepo();
-               $dbr = $repo->getSlaveDB();
+               $dbr = $repo->getReplicaDB();
 
                $res = $dbr->select(
                        [ 'page', 'categorylinks' ],
@@ -224,4 +224,20 @@ class WikiFilePage extends WikiPage {
 
                return TitleArray::newFromResult( $res );
        }
+
+       /**
+        * @since 1.28
+        * @return string
+        */
+       public function getWikiDisplayName() {
+               return $this->getFile()->getRepo()->getDisplayName();
+       }
+
+       /**
+        * @since 1.28
+        * @return string
+        */
+       public function getSourceURL() {
+               return $this->getFile()->getDescriptionUrl();
+       }
 }
index a5ac78f..924a395 100644 (file)
@@ -938,8 +938,8 @@ class WikiPage implements Page, IDBAccessObject {
                $dbw->startAtomic( __METHOD__ );
 
                if ( !$oldLatest || $oldLatest == $this->lockAndGetLatest() ) {
-                       $dbw->replace( 'redirect',
-                               [ 'rd_from' ],
+                       $dbw->upsert(
+                               'redirect',
                                [
                                        'rd_from' => $this->getId(),
                                        'rd_namespace' => $rt->getNamespace(),
@@ -947,6 +947,13 @@ class WikiPage implements Page, IDBAccessObject {
                                        'rd_fragment' => $rt->getFragment(),
                                        'rd_interwiki' => $rt->getInterwiki(),
                                ],
+                               [ 'rd_from' ],
+                               [
+                                       'rd_namespace' => $rt->getNamespace(),
+                                       'rd_title' => $rt->getDBkey(),
+                                       'rd_fragment' => $rt->getFragment(),
+                                       'rd_interwiki' => $rt->getInterwiki(),
+                               ],
                                __METHOD__
                        );
                }
@@ -2861,7 +2868,7 @@ class WikiPage implements Page, IDBAccessObject {
         */
        public function doDeleteArticleReal(
                $reason, $suppress = false, $u1 = null, $u2 = null, &$error = '', User $user = null,
-               $tags = []
+               $tags = [], $logsubtype = 'delete'
        ) {
                global $wgUser, $wgContentHandlerUseDB;
 
@@ -2992,7 +2999,7 @@ class WikiPage implements Page, IDBAccessObject {
                // Log the deletion, if the page was suppressed, put it in the suppression log instead
                $logtype = $suppress ? 'suppress' : 'delete';
 
-               $logEntry = new ManualLogEntry( $logtype, 'delete' );
+               $logEntry = new ManualLogEntry( $logtype, $logsubtype );
                $logEntry->setPerformer( $user );
                $logEntry->setTarget( $logTitle );
                $logEntry->setComment( $reason );
@@ -3512,28 +3519,6 @@ class WikiPage implements Page, IDBAccessObject {
                return $result;
        }
 
-       /**
-        * Return an applicable autosummary if one exists for the given edit.
-        * @param string|null $oldtext The previous text of the page.
-        * @param string|null $newtext The submitted text of the page.
-        * @param int $flags Bitmask: a bitmask of flags submitted for the edit.
-        * @return string An appropriate autosummary, or an empty string.
-        *
-        * @deprecated since 1.21, use ContentHandler::getAutosummary() instead
-        */
-       public static function getAutosummary( $oldtext, $newtext, $flags ) {
-               // NOTE: stub for backwards-compatibility. assumes the given text is
-               // wikitext. will break horribly if it isn't.
-
-               wfDeprecated( __METHOD__, '1.21' );
-
-               $handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT );
-               $oldContent = is_null( $oldtext ) ? null : $handler->unserializeContent( $oldtext );
-               $newContent = is_null( $newtext ) ? null : $handler->unserializeContent( $newtext );
-
-               return $handler->getAutosummary( $oldContent, $newContent, $flags );
-       }
-
        /**
         * Auto-generates a deletion reason
         *
@@ -3742,4 +3727,30 @@ class WikiPage implements Page, IDBAccessObject {
        public function isLocal() {
                return true;
        }
+
+       /**
+        * The display name for the site this content
+        * come from. If a subclass overrides isLocal(),
+        * this could return something other than the
+        * current site name
+        *
+        * @since 1.28
+        * @return string
+        */
+       public function getWikiDisplayName() {
+               global $wgSitename;
+               return $wgSitename;
+       }
+
+       /**
+        * Get the source URL for the content on this page,
+        * typically the canonical URL, but may be a remote
+        * link if the content comes from another site
+        *
+        * @since 1.28
+        * @return string
+        */
+       public function getSourceURL() {
+               return $this->getTitle()->getCanonicalURL();
+       }
 }
index 01cce02..4c82dda 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  * @ingroup Parser
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * Various core parser functions, registered in Parser::firstCallInit()
@@ -346,10 +347,11 @@ class CoreParserFunctions {
 
                // check parameter, or use the ParserOptions if in interface message
                $user = User::newFromName( $username );
+               $genderCache = MediaWikiServices::getInstance()->getGenderCache();
                if ( $user ) {
-                       $gender = GenderCache::singleton()->getGenderOf( $user, __METHOD__ );
+                       $gender = $genderCache->getGenderOf( $user, __METHOD__ );
                } elseif ( $username === '' && $parser->getOptions()->getInterfaceMessage() ) {
-                       $gender = GenderCache::singleton()->getGenderOf( $parser->getOptions()->getUser(), __METHOD__ );
+                       $gender = $genderCache->getGenderOf( $parser->getOptions()->getUser(), __METHOD__ );
                }
                $ret = $parser->getFunctionLang()->gender( $gender, $forms );
                return $ret;
index c7db8a1..10dfd26 100644 (file)
@@ -3599,6 +3599,9 @@ class Parser {
                                $content = $rev->getContent();
                                $text = $content ? $content->getWikitextForTransclusion() : null;
 
+                               Hooks::run( 'ParserFetchTemplate',
+                                       [ $parser, $title, $rev, &$text, &$deps ] );
+
                                if ( $text === false || $text === null ) {
                                        $text = false;
                                        break;
index 7b3d9f9..0ea3c63 100644 (file)
@@ -41,20 +41,33 @@ class EncryptedPassword extends ParameterizedPassword {
        public function crypt( $password ) {
                $secret = $this->config['secrets'][$this->params['secret']];
 
+               // Clear error string
+               while ( openssl_error_string() !== false );
+
                if ( $this->hash ) {
-                       $underlyingPassword = $this->factory->newFromCiphertext( openssl_decrypt(
-                                       base64_decode( $this->hash ), $this->params['cipher'],
-                                       $secret, 0, base64_decode( $this->args[0] )
-                               ) );
+                       $decrypted = openssl_decrypt(
+                                       $this->hash, $this->params['cipher'],
+                                       $secret, 0, base64_decode( $this->args[0] ) );
+                       if ( $decrypted === false ) {
+                               throw new PasswordError( 'Error decrypting password: ' . openssl_error_string() );
+                       }
+                       $underlyingPassword = $this->factory->newFromCiphertext( $decrypted );
                } else {
                        $underlyingPassword = $this->factory->newFromType( $this->config['underlying'] );
                }
 
                $underlyingPassword->crypt( $password );
-               $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
+               if ( count( $this->args ) ) {
+                       $iv = base64_decode( $this->args[0] );
+               } else {
+                       $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
+               }
 
                $this->hash = openssl_encrypt(
                        $underlyingPassword->toString(), $this->params['cipher'], $secret, 0, $iv );
+               if ( $this->hash === false ) {
+                       throw new PasswordError( 'Error encrypting password: ' . openssl_error_string() );
+               }
                $this->args = [ base64_encode( $iv ) ];
        }
 
@@ -65,32 +78,42 @@ class EncryptedPassword extends ParameterizedPassword {
         * @return bool True if the password was updated
         */
        public function update() {
-               if ( count( $this->args ) != 2 || $this->params == $this->getDefaultParams() ) {
+               if ( count( $this->args ) != 1 || $this->params == $this->getDefaultParams() ) {
                        // Hash does not need updating
                        return false;
                }
 
+               // Clear error string
+               while ( openssl_error_string() !== false );
+
                // Decrypt the underlying hash
                $underlyingHash = openssl_decrypt(
-                       base64_decode( $this->args[1] ),
+                       $this->hash,
                        $this->params['cipher'],
                        $this->config['secrets'][$this->params['secret']],
                        0,
                        base64_decode( $this->args[0] )
                );
+               if ( $underlyingHash === false ) {
+                       throw new PasswordError( 'Error decrypting password: ' . openssl_error_string() );
+               }
 
                // Reset the params
                $this->params = $this->getDefaultParams();
 
                // Check the key size with the new params
                $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
-               $this->hash = base64_encode( openssl_encrypt(
+               $this->hash = openssl_encrypt(
                                $underlyingHash,
                                $this->params['cipher'],
                                $this->config['secrets'][$this->params['secret']],
                                0,
                                $iv
-                       ) );
+                       );
+               if ( $this->hash === false ) {
+                       throw new PasswordError( 'Error encrypting password: ' . openssl_error_string() );
+               }
+
                $this->args = [ base64_encode( $iv ) ];
 
                return true;
index 84675c1..c48b6e6 100644 (file)
@@ -36,9 +36,11 @@ class MWOldPassword extends ParameterizedPassword {
        }
 
        public function crypt( $plaintext ) {
-               global $wgPasswordSalt;
-
-               if ( $wgPasswordSalt && count( $this->args ) === 1 ) {
+               if ( count( $this->args ) === 1 ) {
+                       // Accept (but do not generate) salted passwords with :A: prefix.
+                       // These are actually B-type passwords, but an error in a previous
+                       // version of MediaWiki caused them to be written with an :A:
+                       // prefix.
                        $this->hash = md5( $this->args[0] . '-' . md5( $plaintext ) );
                } else {
                        $this->args = [];
index 954d403..c929797 100644 (file)
@@ -90,7 +90,9 @@ abstract class ParameterizedPassword extends Password {
                        $str .= $this->getDelimiter();
                }
 
-               return $str . $this->hash;
+               $res = $str . $this->hash;
+               $this->assertIsSafeSize( $res );
+               return $res;
        }
 
        /**
index 4e395b5..13d1e6d 100644 (file)
@@ -81,6 +81,11 @@ abstract class Password {
         */
        protected $config;
 
+       /**
+        * Hash must fit in user_password, which is a tinyblob
+        */
+       const MAX_HASH_SIZE = 255;
+
        /**
         * Construct the Password object using a string hash
         *
@@ -168,9 +173,28 @@ abstract class Password {
         * are considered equivalent.
         *
         * @return string
+        * @throws PasswordError if password cannot be serialized to fit a tinyblob.
         */
        public function toString() {
-               return ':' . $this->config['type'] . ':' . $this->hash;
+               $result = ':' . $this->config['type'] . ':' . $this->hash;
+               $this->assertIsSafeSize( $result );
+               return $result;
+       }
+
+       /**
+        * Assert that hash will fit in a tinyblob field.
+        *
+        * This prevents MW from inserting it into the DB
+        * and having MySQL silently truncating it, locking
+        * the user out of their account.
+        *
+        * @param string $hash The hash in question.
+        * @throws PasswordError If hash does not fit in DB.
+        */
+       final protected function assertIsSafeSize( $hash ) {
+               if ( strlen( $hash ) > self::MAX_HASH_SIZE ) {
+                       throw new PasswordError( "Password hash is too big" );
+               }
        }
 
        /**
index 5584f6f..bf1f8ac 100644 (file)
@@ -67,12 +67,11 @@ class UserPasswordPolicy {
         * Check if a passwords meets the effective password policy for a User.
         * @param User $user who's policy we are checking
         * @param string $password the password to check
-        * @param string $purpose one of 'login', 'create', 'reset'
         * @return Status error to indicate the password didn't meet the policy, or fatal to
         *      indicate the user shouldn't be allowed to login.
         */
-       public function checkUserPassword( User $user, $password, $purpose = 'login' ) {
-               $effectivePolicy = $this->getPoliciesForUser( $user, $purpose );
+       public function checkUserPassword( User $user, $password ) {
+               $effectivePolicy = $this->getPoliciesForUser( $user );
                return $this->checkPolicies(
                        $user,
                        $password,
@@ -134,20 +133,16 @@ class UserPasswordPolicy {
         * Get the policy for a user, based on their group membership. Public so
         * UI elements can access and inform the user.
         * @param User $user
-        * @param string $purpose one of 'login', 'create', 'reset'
         * @return array the effective policy for $user
         */
-       public function getPoliciesForUser( User $user, $purpose = 'login' ) {
-               $effectivePolicy = $this->policies['default'];
-               if ( $purpose !== 'create' ) {
-                       $effectivePolicy = self::getPoliciesForGroups(
-                               $this->policies,
-                               $user->getEffectiveGroups(),
-                               $this->policies['default']
-                       );
-               }
+       public function getPoliciesForUser( User $user ) {
+               $effectivePolicy = self::getPoliciesForGroups(
+                       $this->policies,
+                       $user->getEffectiveGroups(),
+                       $this->policies['default']
+               );
 
-               Hooks::run( 'PasswordPoliciesForUser', [ $user, &$effectivePolicy, $purpose ] );
+               Hooks::run( 'PasswordPoliciesForUser', [ $user, &$effectivePolicy ] );
 
                return $effectivePolicy;
        }
index 8fc0b77..1bf4f54 100644 (file)
  * ($wgProfiler['exclude']) containing an array of function names.
  * Shell-style patterns are also accepted.
  *
+ * It is also possible to use the Tideways PHP extension, which is mostly
+ * a drop-in replacement for Xhprof. Just change the XHPROF_FLAGS_* constants
+ * to TIDEWAYS_FLAGS_*.
+ *
  * @author Bryan Davis <bd808@wikimedia.org>
  * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
  * @ingroup Profiler
  * @see Xhprof
  * @see https://php.net/xhprof
  * @see https://github.com/facebook/hhvm/blob/master/hphp/doc/profiling.md
+ * @see https://github.com/tideways/php-profiler-extension
  */
 class ProfilerXhprof extends Profiler {
        /**
diff --git a/includes/registration/ExtensionJsonValidationError.php b/includes/registration/ExtensionJsonValidationError.php
new file mode 100644 (file)
index 0000000..897d284
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+class ExtensionJsonValidationError extends Exception {
+}
diff --git a/includes/registration/ExtensionJsonValidator.php b/includes/registration/ExtensionJsonValidator.php
new file mode 100644 (file)
index 0000000..f6e76af
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+use Composer\Spdx\SpdxLicenses;
+use JsonSchema\Validator;
+
+/**
+ * @since 1.29
+ */
+class ExtensionJsonValidator {
+
+       /**
+        * @var callable
+        */
+       private $missingDepCallback;
+
+       /**
+        * @param callable $missingDepCallback
+        */
+       public function __construct( callable $missingDepCallback ) {
+               $this->missingDepCallback = $missingDepCallback;
+       }
+
+       /**
+        * @return bool
+        */
+       public function checkDependencies() {
+               if ( !class_exists( Validator::class ) ) {
+                       call_user_func( $this->missingDepCallback,
+                               'The JsonSchema library cannot be found, please install it through composer.'
+                       );
+                       return false;
+               } elseif ( !class_exists( SpdxLicenses::class ) ) {
+                       call_user_func( $this->missingDepCallback,
+                               'The spdx-licenses library cannot be found, please install it through composer.'
+                       );
+                       return false;
+               }
+
+               return true;
+       }
+
+       /**
+        * @param string $path file to validate
+        * @return bool true if passes validation
+        * @throws ExtensionJsonValidationError on any failure
+        */
+       public function validate( $path ) {
+               $data = json_decode( file_get_contents( $path ) );
+               if ( !is_object( $data ) ) {
+                       throw new ExtensionJsonValidationError( "$path is not valid JSON" );
+               }
+
+               if ( !isset( $data->manifest_version ) ) {
+                       throw new ExtensionJsonValidationError(
+                               "$path does not have manifest_version set." );
+               }
+
+               $version = $data->manifest_version;
+               if ( $version !== ExtensionRegistry::MANIFEST_VERSION ) {
+                       $schemaPath = __DIR__ . "/../../docs/extension.schema.v$version.json";
+               } else {
+                       $schemaPath = __DIR__ . '/../../docs/extension.schema.json';
+               }
+
+               // Not too old
+               if ( $version < ExtensionRegistry::OLDEST_MANIFEST_VERSION ) {
+                       throw new ExtensionJsonValidationError(
+                               "$path is using a non-supported schema version"
+                       );
+               } elseif ( $version > ExtensionRegistry::MANIFEST_VERSION ) {
+                       throw new ExtensionJsonValidationError(
+                               "$path is using a non-supported schema version"
+                       );
+               }
+
+               $licenseError = false;
+               // Check if it's a string, if not, schema validation will display an error
+               if ( isset( $data->{'license-name'} ) && is_string( $data->{'license-name'} ) ) {
+                       $licenses = new SpdxLicenses();
+                       $valid = $licenses->validate( $data->{'license-name'} );
+                       if ( !$valid ) {
+                               $licenseError = '[license-name] Invalid SPDX license identifier, '
+                                       . 'see <https://spdx.org/licenses/>';
+                       }
+               }
+
+               $validator = new Validator;
+               $validator->check( $data, (object)[ '$ref' => 'file://' . $schemaPath ] );
+               if ( $validator->isValid() && !$licenseError ) {
+                       // All good.
+                       return true;
+               } else {
+                       $out = "$path did pass validation.\n";
+                       foreach ( $validator->getErrors() as $error ) {
+                               $out .= "[{$error['property']}] {$error['message']}\n";
+                       }
+                       if ( $licenseError ) {
+                               $out .= "$licenseError\n";
+                       }
+                       throw new ExtensionJsonValidationError( $out );
+               }
+       }
+}
index 26fbfa1..d967132 100644 (file)
@@ -26,6 +26,7 @@ class ExtensionProcessor implements Processor {
                'ExtensionEntryPointListFiles',
                'ExtensionFunctions',
                'FeedClasses',
+               'FileExtensions',
                'FilterLogTypes',
                'GrantPermissionGroups',
                'GrantPermissions',
@@ -42,6 +43,7 @@ class ExtensionProcessor implements Processor {
                'LogRestrictions',
                'LogTypes',
                'MediaHandlers',
+               'PasswordPolicy',
                'RateLimits',
                'RecentChangesFlags',
                'RemoveCredentialsBlacklist',
@@ -72,6 +74,7 @@ class ExtensionProcessor implements Processor {
                'wgNamespaceContentModels' => 'array_plus',
                'wgNamespaceProtection' => 'array_plus',
                'wgNamespacesWithSubpages' => 'array_plus',
+               'wgPasswordPolicy' => 'array_merge_recursive',
                'wgRateLimits' => 'array_plus_2d',
                'wgRevokePermissions' => 'array_plus_2d',
        ];
@@ -138,6 +141,7 @@ class ExtensionProcessor implements Processor {
 
        /**
         * Things to be called once registration of these extensions are done
+        * keyed by the name of the extension that it belongs to
         *
         * @var callable[]
         */
@@ -177,11 +181,11 @@ class ExtensionProcessor implements Processor {
                $this->extractResourceLoaderModules( $dir, $info );
                $this->extractServiceWiringFiles( $dir, $info );
                $this->extractParserTestFiles( $dir, $info );
+               $name = $this->extractCredits( $path, $info );
                if ( isset( $info['callback'] ) ) {
-                       $this->callbacks[] = $info['callback'];
+                       $this->callbacks[$name] = $info['callback'];
                }
 
-               $this->extractCredits( $path, $info );
                foreach ( $info as $key => $val ) {
                        if ( in_array( $key, self::$globalSettings ) ) {
                                $this->storeToArray( $path, "wg$key", $val, $this->globals );
@@ -332,6 +336,7 @@ class ExtensionProcessor implements Processor {
        /**
         * @param string $path
         * @param array $info
+        * @return string Name of thing
         * @throws Exception
         */
        protected function extractCredits( $path, array $info ) {
@@ -357,6 +362,8 @@ class ExtensionProcessor implements Processor {
 
                $this->credits[$name] = $credits;
                $this->globals['wgExtensionCredits'][$credits['type']][] = $credits;
+
+               return $name;
        }
 
        /**
index b5c70e9..70dc624 100644 (file)
@@ -31,7 +31,7 @@ class ExtensionRegistry {
        /**
         * Bump whenever the registration cache needs resetting
         */
-       const CACHE_VERSION = 3;
+       const CACHE_VERSION = 4;
 
        /**
         * Special key that defines the merge strategy
@@ -59,6 +59,13 @@ class ExtensionRegistry {
         */
        protected $queued = [];
 
+       /**
+        * Whether we are done loading things
+        *
+        * @var bool
+        */
+       private $finished = false;
+
        /**
         * Items in the JSON file that aren't being
         * set as globals
@@ -114,12 +121,23 @@ class ExtensionRegistry {
                $this->queued[$path] = $mtime;
        }
 
+       /**
+        * @throws MWException If the queue is already marked as finished (no further things should
+        *  be loaded then).
+        */
        public function loadFromQueue() {
                global $wgVersion;
                if ( !$this->queued ) {
                        return;
                }
 
+               if ( $this->finished ) {
+                       throw new MWException(
+                               "The following paths tried to load late: "
+                               . implode( ', ', array_keys( $this->queued ) )
+                       );
+               }
+
                // A few more things to vary the cache on
                $versions = [
                        'registration' => self::CACHE_VERSION,
@@ -164,6 +182,15 @@ class ExtensionRegistry {
                $this->queued = [];
        }
 
+       /**
+        * After this is called, no more extensions can be loaded
+        *
+        * @since 1.29
+        */
+       public function finish() {
+               $this->finished = true;
+       }
+
        /**
         * Process a queue of extensions and return their extracted data
         *
@@ -285,9 +312,6 @@ class ExtensionRegistry {
                foreach ( $info['autoloaderPaths'] as $path ) {
                        require_once $path;
                }
-               foreach ( $info['callbacks'] as $cb ) {
-                       call_user_func( $cb );
-               }
 
                $this->loaded += $info['credits'];
                if ( $info['attributes'] ) {
@@ -297,6 +321,10 @@ class ExtensionRegistry {
                                $this->attributes = array_merge_recursive( $this->attributes, $info['attributes'] );
                        }
                }
+
+               foreach ( $info['callbacks'] as $name => $cb ) {
+                       call_user_func( $cb, $info['credits'][$name] );
+               }
        }
 
        /**
index 1073de0..d624c7c 100644 (file)
@@ -22,6 +22,7 @@
  * @author Trevor Parscal
  */
 
+use MediaWiki\MediaWikiServices;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerInterface;
 use Psr\Log\NullLogger;
@@ -239,7 +240,7 @@ class ResourceLoader implements LoggerAwareInterface {
 
                if ( !$config ) {
                        $this->logger->debug( __METHOD__ . ' was called without providing a Config instance' );
-                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $config = MediaWikiServices::getInstance()->getMainConfig();
                }
                $this->config = $config;
 
index 5729218..91e0b02 100644 (file)
@@ -130,26 +130,15 @@ class ResourceLoaderClientHtml {
                        'states' => [
                                // moduleName => state
                        ],
-                       'general' => [
-                               // position => [ moduleName ]
-                               'top' => [],
-                               'bottom' => [],
-                       ],
+                       'general' => [],
                        'styles' => [
                                // moduleName
                        ],
-                       'scripts' => [
-                               // position => [ moduleName ]
-                               'top' => [],
-                               'bottom' => [],
-                       ],
+                       'scripts' => [],
                        // Embedding for private modules
                        'embed' => [
                                'styles' => [],
-                               'general' => [
-                                       'top' => [],
-                                       'bottom' => [],
-                               ],
+                               'general' => [],
                        ],
 
                ];
@@ -161,16 +150,15 @@ class ResourceLoaderClientHtml {
                        }
 
                        $group = $module->getGroup();
-                       $position = $module->getPosition();
 
                        if ( $group === 'private' ) {
                                // Embed via mw.loader.implement per T36907.
-                               $data['embed']['general'][$position][] = $name;
+                               $data['embed']['general'][] = $name;
                                // Avoid duplicate request from mw.loader
                                $data['states'][$name] = 'loading';
                        } else {
                                // Load via mw.loader.load()
-                               $data['general'][$position][] = $name;
+                               $data['general'][] = $name;
                        }
                }
 
@@ -216,14 +204,13 @@ class ResourceLoaderClientHtml {
                        }
 
                        $group = $module->getGroup();
-                       $position = $module->getPosition();
                        $context = $this->getContext( $group, ResourceLoaderModule::TYPE_SCRIPTS );
                        if ( $module->isKnownEmpty( $context ) ) {
                                // Avoid needless request for empty module
                                $data['states'][$name] = 'ready';
                        } else {
                                // Load from load.php?only=scripts via <script src></script>
-                               $data['scripts'][$position][] = $name;
+                               $data['scripts'][] = $name;
 
                                // Avoid duplicate request from mw.loader
                                $data['states'][$name] = 'loading';
@@ -282,24 +269,24 @@ class ResourceLoaderClientHtml {
                }
 
                // Inline RLQ: Embedded modules
-               if ( $data['embed']['general']['top'] ) {
+               if ( $data['embed']['general'] ) {
                        $chunks[] = $this->getLoad(
-                               $data['embed']['general']['top'],
+                               $data['embed']['general'],
                                ResourceLoaderModule::TYPE_COMBINED
                        );
                }
 
                // Inline RLQ: Load general modules
-               if ( $data['general']['top'] ) {
+               if ( $data['general'] ) {
                        $chunks[] = ResourceLoader::makeInlineScript(
-                               Xml::encodeJsCall( 'mw.loader.load', [ $data['general']['top'] ] )
+                               Xml::encodeJsCall( 'mw.loader.load', [ $data['general'] ] )
                        );
                }
 
                // Inline RLQ: Load only=scripts
-               if ( $data['scripts']['top'] ) {
+               if ( $data['scripts'] ) {
                        $chunks[] = $this->getLoad(
-                               $data['scripts']['top'],
+                               $data['scripts'],
                                ResourceLoaderModule::TYPE_SCRIPTS
                        );
                }
@@ -336,33 +323,7 @@ class ResourceLoaderClientHtml {
         * @return string|WrappedStringList HTML
         */
        public function getBodyHtml() {
-               $data = $this->getData();
-               $chunks = [];
-
-               // Inline RLQ: Embedded modules
-               if ( $data['embed']['general']['bottom'] ) {
-                       $chunks[] = $this->getLoad(
-                               $data['embed']['general']['bottom'],
-                               ResourceLoaderModule::TYPE_COMBINED
-                       );
-               }
-
-               // Inline RLQ: Load only=scripts
-               if ( $data['scripts']['bottom'] ) {
-                       $chunks[] = $this->getLoad(
-                               $data['scripts']['bottom'],
-                               ResourceLoaderModule::TYPE_SCRIPTS
-                       );
-               }
-
-               // Inline RLQ: Load general modules
-               if ( $data['general']['bottom'] ) {
-                       $chunks[] = ResourceLoader::makeInlineScript(
-                               Xml::encodeJsCall( 'mw.loader.load', [ $data['general']['bottom'] ] )
-                       );
-               }
-
-               return WrappedStringList::join( "\n", $chunks );
+               return '';
        }
 
        private function getContext( $group, $type ) {
index b17200f..a1a89cb 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
 
 /**
  * Object passed around to modules which contains information about the state
@@ -137,7 +138,7 @@ class ResourceLoaderContext {
         */
        public static function newDummyContext() {
                return new self( new ResourceLoader(
-                       ConfigFactory::getDefaultInstance()->makeConfig( 'main' ),
+                       MediaWikiServices::getInstance()->getMainConfig(),
                        LoggerFactory::getInstance( 'resourceloader' )
                ), new FauxRequest( [] ) );
        }
index 07649e3..725bc6a 100644 (file)
@@ -117,9 +117,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
        /** @var string Name of group to load this module in */
        protected $group;
 
-       /** @var string Position on the page to load this module at */
-       protected $position = 'bottom';
-
        /** @var bool Link to raw files in debug mode */
        protected $debugRaw = true;
 
@@ -204,8 +201,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *         'messages' => [array of message key strings],
         *         // Group which this module should be loaded together with
         *         'group' => [group name string],
-        *         // Position on the page to load this module at
-        *         'position' => ['bottom' (default) or 'top']
         *         // Function that, if it returns true, makes the loader skip this module.
         *         // The file must contain valid JavaScript for execution in a private function.
         *         // The file must not contain the "function () {" and "}" wrapper though.
@@ -272,7 +267,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                        $this->{$member} = $option;
                                        break;
                                // Single strings
-                               case 'position':
                                case 'group':
                                case 'skipFunction':
                                        $this->{$member} = (string)$option;
@@ -445,13 +439,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                return $this->group;
        }
 
-       /**
-        * @return string
-        */
-       public function getPosition() {
-               return $this->position;
-       }
-
        /**
         * Gets list of names of modules this module depends on.
         * @param ResourceLoaderContext|null $context
@@ -573,7 +560,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        // - dependencies (provided via startup module)
                        // - targets
                        // - group (provided via startup module)
-                       // - position (only used by OutputPage)
                        'scripts',
                        'debugScripts',
                        'styles',
index 6a8957e..ff1b7b1 100644 (file)
@@ -45,9 +45,6 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
        protected $selectorWithVariant = '.{prefix}-{name}-{variant}';
        protected $targets = [ 'desktop', 'mobile' ];
 
-       /** @var string Position on the page to load this module at */
-       protected $position = 'bottom';
-
        /**
         * Constructs a new module from an options array.
         *
@@ -183,7 +180,6 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
                                        $this->{$member} = $option;
                                        break;
 
-                               case 'position':
                                case 'prefix':
                                case 'selectorWithoutVariant':
                                case 'selectorWithVariant':
@@ -448,14 +444,6 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
                return $localBasePath;
        }
 
-       /**
-        * @return string
-        */
-       public function getPosition() {
-               $this->loadFromDefinition();
-               return $this->position;
-       }
-
        /**
         * @return string
         */
index 796c575..8124f33 100644 (file)
@@ -22,6 +22,7 @@
  * @author Roan Kattouw
  */
 
+use MediaWiki\MediaWikiServices;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerInterface;
 use Psr\Log\NullLogger;
@@ -187,7 +188,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
        public function getConfig() {
                if ( $this->config === null ) {
                        // Ugh, fall back to default
-                       $this->config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $this->config = MediaWikiServices::getInstance()->getMainConfig();
                }
 
                return $this->config;
@@ -330,14 +331,13 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
        }
 
        /**
-        * Where on the HTML page should this module's JS be loaded?
-        *  - 'top': in the "<head>"
-        *  - 'bottom': at the bottom of the "<body>"
+        * From where in the page HTML should this module be loaded?
         *
+        * @deprecated since 1.29 Obsolete. All modules load async from `<head>`.
         * @return string
         */
        public function getPosition() {
-               return 'bottom';
+               return 'top';
        }
 
        /**
diff --git a/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php b/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php
deleted file mode 100644 (file)
index aef1c74..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-/**
- * ResourceLoader module for user preference customizations.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Trevor Parscal
- * @author Roan Kattouw
- */
-
-/**
- * Module for user preference customizations
- */
-class ResourceLoaderUserCSSPrefsModule extends ResourceLoaderModule {
-
-       protected $origin = self::ORIGIN_CORE_INDIVIDUAL;
-
-       /**
-        * @return bool
-        */
-       public function enableModuleContentVersion() {
-               return true;
-       }
-
-       /**
-        * @param ResourceLoaderContext $context
-        * @return array
-        */
-       public function getStyles( ResourceLoaderContext $context ) {
-               if ( !$this->getConfig()->get( 'AllowUserCssPrefs' ) ) {
-                       return [];
-               }
-
-               $options = $context->getUserObj()->getOptions();
-
-               // Build CSS rules
-               $rules = [];
-
-               // Underline: 2 = skin default, 1 = always, 0 = never
-               if ( $options['underline'] < 2 ) {
-                       $rules[] = "a { text-decoration: " .
-                               ( $options['underline'] ? 'underline' : 'none' ) . "; }";
-               }
-               $style = implode( "\n", $rules );
-               if ( $this->getFlip( $context ) ) {
-                       $style = CSSJanus::transform( $style, true, false );
-               }
-               return [ 'all' => $style ];
-       }
-
-       /**
-        * @param ResourceLoaderContext $context
-        * @return bool
-        */
-       public function isKnownEmpty( ResourceLoaderContext $context ) {
-               $styles = $this->getStyles( $context );
-               return isset( $styles['all'] ) && $styles['all'] === '';
-       }
-
-       /**
-        * @return string
-        */
-       public function getGroup() {
-               return 'private';
-       }
-
-       /**
-        * @return string
-        */
-       public function getType() {
-               return self::LOAD_STYLES;
-       }
-}
index c1b47bf..b3b3f16 100644 (file)
@@ -64,13 +64,6 @@ class ResourceLoaderUserOptionsModule extends ResourceLoaderModule {
                return false;
        }
 
-       /**
-        * @return string
-        */
-       public function getPosition() {
-               return 'top';
-       }
-
        /**
         * @return string
         */
index c8a0ff1..cea1f39 100644 (file)
@@ -74,13 +74,6 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule {
                return false;
        }
 
-       /**
-        * @return string
-        */
-       public function getPosition() {
-               return 'top';
-       }
-
        /**
         * @return string
         */
index ccb336f..14d6e05 100644 (file)
@@ -36,7 +36,6 @@
  * Safe for calls on local wikis are:
  * - Option getters:
  *   - getGroup()
- *   - getPosition()
  *   - getPages()
  * - Basic methods that strictly involve the foreign database
  *   - getDB()
@@ -44,8 +43,6 @@
  *   - getTitleInfo()
  */
 class ResourceLoaderWikiModule extends ResourceLoaderModule {
-       /** @var string Position on the page to load this module at */
-       protected $position = 'bottom';
 
        // Origin defaults to users with sitewide authority
        protected $origin = self::ORIGIN_USER_SITEWIDE;
@@ -72,7 +69,6 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
 
                foreach ( $options as $member => $option ) {
                        switch ( $member ) {
-                               case 'position':
                                case 'styles':
                                case 'scripts':
                                case 'group':
@@ -435,13 +431,6 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
                }
        }
 
-       /**
-        * @return string
-        */
-       public function getPosition() {
-               return $this->position;
-       }
-
        /**
         * @since 1.28
         * @return string
index 2d0d690..ab74dbd 100644 (file)
@@ -68,14 +68,14 @@ class RevDelArchiveItem extends RevDelRevisionItem {
        }
 
        protected function getRevisionLink() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->revision->getTimestamp(), $this->list->getUser() ) );
+               $date = $this->list->getLanguage()->userTimeAndDate(
+                       $this->revision->getTimestamp(), $this->list->getUser() );
 
                if ( $this->isDeleted() && !$this->canViewContent() ) {
-                       return $date;
+                       return htmlspecialchars( $date );
                }
 
-               return Linker::link(
+               return $this->getLinkRenderer()->makeLink(
                        SpecialPage::getTitleFor( 'Undelete' ),
                        $date,
                        [],
@@ -91,9 +91,9 @@ class RevDelArchiveItem extends RevDelRevisionItem {
                        return $this->list->msg( 'diff' )->escaped();
                }
 
-               return Linker::link(
+               return $this->getLinkRenderer()->makeLink(
                        SpecialPage::getTitleFor( 'Undelete' ),
-                       $this->list->msg( 'diff' )->escaped(),
+                       $this->list->msg( 'diff' )->text(),
                        [],
                        [
                                'target' => $this->list->title->getPrefixedText(),
index 52df2e3..decabba 100644 (file)
@@ -69,16 +69,16 @@ class RevDelArchivedFileItem extends RevDelFileItem {
        }
 
        protected function getLink() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->file->getTimestamp(), $this->list->getUser() ) );
+               $date = $this->list->getLanguage()->userTimeAndDate(
+                       $this->file->getTimestamp(), $this->list->getUser() );
 
                # Hidden files...
                if ( !$this->canViewContent() ) {
-                       $link = $date;
+                       $link = htmlspecialchars( $date );
                } else {
                        $undelete = SpecialPage::getTitleFor( 'Undelete' );
                        $key = $this->file->getKey();
-                       $link = Linker::link( $undelete, $date, [],
+                       $link = $this->getLinkRenderer()->makeLink( $undelete, $date, [],
                                [
                                        'target' => $this->list->title->getPrefixedText(),
                                        'file' => $key,
index ff01cee..06b596e 100644 (file)
@@ -116,19 +116,19 @@ class RevDelFileItem extends RevDelItem {
         * @return string
         */
        protected function getLink() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->file->getTimestamp(), $this->list->getUser() ) );
+               $date = $this->list->getLanguage()->userTimeAndDate(
+                       $this->file->getTimestamp(), $this->list->getUser() );
 
                if ( !$this->isDeleted() ) {
                        # Regular files...
-                       return Html::rawElement( 'a', [ 'href' => $this->file->getUrl() ], $date );
+                       return Html::element( 'a', [ 'href' => $this->file->getUrl() ], $date );
                }
 
                # Hidden files...
                if ( !$this->canViewContent() ) {
-                       $link = $date;
+                       $link = htmlspecialchars( $date );
                } else {
-                       $link = Linker::link(
+                       $link = $this->getLinkRenderer()->makeLink(
                                SpecialPage::getTitleFor( 'Revisiondelete' ),
                                $date,
                                [],
index 1ea7271..9e76f4c 100644 (file)
@@ -92,9 +92,9 @@ class RevDelLogItem extends RevDelItem {
                $formatter->setAudience( LogFormatter::FOR_THIS_USER );
 
                // Log link for this page
-               $loglink = Linker::link(
+               $loglink = $this->getLinkRenderer()->makeLink(
                        SpecialPage::getTitleFor( 'Log' ),
-                       $this->list->msg( 'log' )->escaped(),
+                       $this->list->msg( 'log' )->text(),
                        [],
                        [ 'page' => $title->getPrefixedText() ]
                );
index d799113..7fff366 100644 (file)
@@ -107,14 +107,14 @@ class RevDelRevisionItem extends RevDelItem {
         * @return string
         */
        protected function getRevisionLink() {
-               $date = htmlspecialchars( $this->list->getLanguage()->userTimeAndDate(
-                       $this->revision->getTimestamp(), $this->list->getUser() ) );
+               $date = $this->list->getLanguage()->userTimeAndDate(
+                       $this->revision->getTimestamp(), $this->list->getUser() );
 
                if ( $this->isDeleted() && !$this->canViewContent() ) {
-                       return $date;
+                       return htmlspecialchars( $date );
                }
 
-               return Linker::linkKnown(
+               return $this->getLinkRenderer()->makeKnownLink(
                        $this->list->title,
                        $date,
                        [],
@@ -134,9 +134,9 @@ class RevDelRevisionItem extends RevDelItem {
                if ( $this->isDeleted() && !$this->canViewContent() ) {
                        return $this->list->msg( 'diff' )->escaped();
                } else {
-                       return Linker::linkKnown(
+                       return $this->getLinkRenderer()->makeKnownLink(
                                        $this->list->title,
-                                       $this->list->msg( 'diff' )->escaped(),
+                                       $this->list->msg( 'diff' )->text(),
                                        [],
                                        [
                                                'diff' => $this->revision->getId(),
index b8e480f..0041450 100644 (file)
@@ -23,6 +23,7 @@
 
 namespace MediaWiki\Session;
 
+use MediaWiki\MediaWikiServices;
 use MWException;
 use Psr\Log\LoggerInterface;
 use BagOStuff;
@@ -152,7 +153,7 @@ final class SessionManager implements SessionManagerInterface {
                                );
                        }
                } else {
-                       $this->config = \ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $this->config = MediaWikiServices::getInstance()->getMainConfig();
                }
 
                if ( isset( $options['logger'] ) ) {
index e5d272c..6686ae6 100644 (file)
@@ -17,6 +17,7 @@
  *
  * @file
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * Generic wrapper for template functions, with interface
@@ -36,7 +37,7 @@ abstract class QuickTemplate {
                $this->translator = new MediaWikiI18N();
                if ( $config === null ) {
                        wfDebug( __METHOD__ . ' was called with no Config instance passed to it' );
-                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $config = MediaWikiServices::getInstance()->getMainConfig();
                }
                $this->config = $config;
        }
index b60aa10..96812ea 100644 (file)
@@ -217,6 +217,17 @@ abstract class Skin extends ContextSource {
                        }
                }
 
+               // Footer links (used by SkinTemplate::prepareQuickTemplate)
+               foreach ( [
+                       $this->footerLinkTitle( 'privacy', 'privacypage' ),
+                       $this->footerLinkTitle( 'aboutsite', 'aboutpage' ),
+                       $this->footerLinkTitle( 'disclaimers', 'disclaimerpage' ),
+               ] as $title ) {
+                       if ( $title ) {
+                               $titles[] = $title;
+                       }
+               }
+
                Hooks::run( 'SkinPreloadExistence', [ &$titles, $this ] );
 
                if ( $titles ) {
@@ -921,25 +932,34 @@ abstract class Skin extends ContextSource {
         * @return string HTML anchor
         */
        public function footerLink( $desc, $page ) {
-               // if the link description has been set to "-" in the default language,
-               if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
-                       // then it is disabled, for all languages.
+               $title = $this->footerLinkTitle( $desc, $page );
+               if ( !$title ) {
                        return '';
-               } else {
-                       // Otherwise, we display the link for the user, described in their
-                       // language (which may or may not be the same as the default language),
-                       // but we make the link target be the one site-wide page.
-                       $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
+               }
 
-                       if ( !$title ) {
-                               return '';
-                       }
+               return Linker::linkKnown(
+                       $title,
+                       $this->msg( $desc )->escaped()
+               );
+       }
 
-                       return Linker::linkKnown(
-                               $title,
-                               $this->msg( $desc )->escaped()
-                       );
+       /**
+        * @param string $desc
+        * @param string $page
+        * @return Title|null
+        */
+       private function footerLinkTitle( $desc, $page ) {
+               // If the link description has been set to "-" in the default language,
+               if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
+                       // then it is disabled, for all languages.
+                       return null;
                }
+               // Otherwise, we display the link for the user, described in their
+               // language (which may or may not be the same as the default language),
+               // but we make the link target be the one site-wide page.
+               $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
+
+               return $title ?: null;
        }
 
        /**
index 9c5600d..69f2e49 100644 (file)
@@ -919,19 +919,18 @@ class SkinTemplate extends Skin {
                                        $content_navigation['views']['view']['redundant'] = true;
                                }
 
-                               $isForeignFile = $title->inNamespace( NS_FILE ) && $this->canUseWikiPage() &&
-                                       $this->getWikiPage() instanceof WikiFilePage && !$this->getWikiPage()->isLocal();
+                               $page = $this->canUseWikiPage() ? $this->getWikiPage() : false;
+                               $isRemoteContent = $page && !$page->isLocal();
 
                                // If it is a non-local file, show a link to the file in its own repository
                                // @todo abstract this for remote content that isn't a file
-                               if ( $isForeignFile ) {
-                                       $file = $this->getWikiPage()->getFile();
+                               if ( $isRemoteContent ) {
                                        $content_navigation['views']['view-foreign'] = [
                                                'class' => '',
                                                'text' => wfMessageFallback( "$skname-view-foreign", 'view-foreign' )->
                                                        setContext( $this->getContext() )->
-                                                       params( $file->getRepo()->getDisplayName() )->text(),
-                                               'href' => $file->getDescriptionUrl(),
+                                                       params( $page->getWikiDisplayName() )->text(),
+                                               'href' => $page->getSourceURL(),
                                                'primary' => false,
                                        ];
                                }
@@ -955,9 +954,9 @@ class SkinTemplate extends Skin {
                                                        && $title->getDefaultMessageText() !== false
                                                )
                                        ) {
-                                               $msgKey = $isForeignFile ? 'edit-local' : 'edit';
+                                               $msgKey = $isRemoteContent ? 'edit-local' : 'edit';
                                        } else {
-                                               $msgKey = $isForeignFile ? 'create-local' : 'create';
+                                               $msgKey = $isRemoteContent ? 'create-local' : 'create';
                                        }
                                        $content_navigation['views']['edit'] = [
                                                'class' => ( $isEditing && ( $section !== 'new' || !$showNewSection )
@@ -967,7 +966,7 @@ class SkinTemplate extends Skin {
                                                'text' => wfMessageFallback( "$skname-view-$msgKey", $msgKey )
                                                        ->setContext( $this->getContext() )->text(),
                                                'href' => $title->getLocalURL( $this->editUrlOptions() ),
-                                               'primary' => !$isForeignFile, // don't collapse this in vector
+                                               'primary' => !$isRemoteContent, // don't collapse this in vector
                                        ];
 
                                        // section link
@@ -1309,12 +1308,14 @@ class SkinTemplate extends Skin {
                        if ( !$user->isAnon() ) {
                                $sur = new UserrightsPage;
                                $sur->setContext( $this->getContext() );
-                               if ( $sur->userCanExecute( $this->getUser() ) ) {
-                                       $nav_urls['userrights'] = [
-                                               'text' => $this->msg( 'tool-link-userrights', $this->getUser()->getName() )->text(),
-                                               'href' => self::makeSpecialUrlSubpage( 'Userrights', $rootUser )
-                                       ];
-                               }
+                               $canChange = $sur->userCanChangeRights( $this->getUser(), false );
+                               $nav_urls['userrights'] = [
+                                       'text' => $this->msg(
+                                               $canChange ? 'tool-link-userrights' : 'tool-link-userrights-readonly',
+                                               $this->getUser()->getName()
+                                       )->text(),
+                                       'href' => self::makeSpecialUrlSubpage( 'Userrights', $rootUser )
+                               ];
                        }
                }
 
index 01782f3..2051948 100644 (file)
@@ -141,14 +141,20 @@ abstract class ChangesListSpecialPage extends SpecialPage {
 
                $opts->add( 'hideminor', false );
                $opts->add( 'hidebots', false );
+               $opts->add( 'hidehumans', false );
                $opts->add( 'hideanons', false );
                $opts->add( 'hideliu', false );
                $opts->add( 'hidepatrolled', false );
+               $opts->add( 'hideunpatrolled', false );
                $opts->add( 'hidemyself', false );
+               $opts->add( 'hidebyothers', false );
 
                if ( $config->get( 'RCWatchCategoryMembership' ) ) {
                        $opts->add( 'hidecategorization', false );
                }
+               $opts->add( 'hidepageedits', false );
+               $opts->add( 'hidenewpages', false );
+               $opts->add( 'hidelog', false );
 
                $opts->add( 'namespace', '', FormOptions::INTNULL );
                $opts->add( 'invert', false );
@@ -234,8 +240,16 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                if ( $opts['hidebots'] ) {
                        $conds['rc_bot'] = 0;
                }
-               if ( $user->useRCPatrol() && $opts['hidepatrolled'] ) {
-                       $conds['rc_patrolled'] = 0;
+               if ( $opts['hidehumans'] ) {
+                       $conds[] = 'rc_bot = 1';
+               }
+               if ( $user->useRCPatrol() ) {
+                       if ( $opts['hidepatrolled'] ) {
+                               $conds[] = 'rc_patrolled = 0';
+                       }
+                       if ( $opts['hideunpatrolled'] ) {
+                               $conds[] = 'rc_patrolled = 1';
+                       }
                }
                if ( $botsonly ) {
                        $conds['rc_bot'] = 1;
@@ -247,6 +261,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                                $conds[] = 'rc_user != 0';
                        }
                }
+
                if ( $opts['hidemyself'] ) {
                        if ( $user->getId() ) {
                                $conds[] = 'rc_user != ' . $dbr->addQuotes( $user->getId() );
@@ -254,11 +269,28 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                                $conds[] = 'rc_user_text != ' . $dbr->addQuotes( $user->getName() );
                        }
                }
+               if ( $opts['hidebyothers'] ) {
+                       if ( $user->getId() ) {
+                               $conds[] = 'rc_user = ' . $dbr->addQuotes( $user->getId() );
+                       } else {
+                               $conds[] = 'rc_user_text = ' . $dbr->addQuotes( $user->getName() );
+                       }
+               }
+
                if ( $this->getConfig()->get( 'RCWatchCategoryMembership' )
                        && $opts['hidecategorization'] === true
                ) {
                        $conds[] = 'rc_type != ' . $dbr->addQuotes( RC_CATEGORIZE );
                }
+               if ( $opts['hidepageedits'] ) {
+                       $conds[] = 'rc_type != ' . $dbr->addQuotes( RC_EDIT );
+               }
+               if ( $opts['hidenewpages'] ) {
+                       $conds[] = 'rc_type != ' . $dbr->addQuotes( RC_NEW );
+               }
+               if ( $opts['hidelog'] ) {
+                       $conds[] = 'rc_type != ' . $dbr->addQuotes( RC_LOG );
+               }
 
                // Namespace filtering
                if ( $opts['namespace'] !== '' ) {
@@ -485,4 +517,23 @@ abstract class ChangesListSpecialPage extends SpecialPage {
        protected function getGroupName() {
                return 'changes';
        }
+
+       /**
+        * Get filters that can be rendered.
+        *
+        * Filters with 'msg' => false can be used to filter data but won't
+        * be presented as show/hide toggles in the UI. They are not returned
+        * by this function.
+        *
+        * @param array $allFilters Map of filter URL param names to properties (msg/default)
+        * @return array Map of filter URL param names to properties (msg/default)
+        */
+       protected function getRenderableCustomFilters( $allFilters ) {
+               return array_filter(
+                       $allFilters,
+                       function( $filter ) {
+                               return isset( $filter['msg'] ) && ( $filter['msg'] !== false );
+                       }
+               );
+       }
 }
index 1e03774..540ce4b 100644 (file)
@@ -149,9 +149,9 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                $entryWarning = $this->msg( $request->getVal( 'warning', '' ) );
                // bc: provide login link as a parameter for messages where the translation
                // was not updated
-               $loginreqlink = Linker::linkKnown(
+               $loginreqlink = $this->getLinkRenderer()->makeKnownLink(
                        $this->getPageTitle(),
-                       $this->msg( 'loginreqlink' )->escaped(),
+                       $this->msg( 'loginreqlink' )->text(),
                        [],
                        [
                                'returnto' => $this->mReturnTo,
@@ -294,6 +294,14 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                        return;
                }
 
+               if ( $this->canBypassForm( $button_name ) ) {
+                       $this->setRequest( [], true );
+                       $this->getRequest()->setVal( $this->getTokenName(), $this->getToken() );
+                       if ( $button_name ) {
+                               $this->getRequest()->setVal( $button_name, true );
+                       }
+               }
+
                $status = $this->trySubmit();
 
                if ( !$status || !$status->isGood() ) {
@@ -366,6 +374,46 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                }
        }
 
+       /**
+        * Determine if the login form can be bypassed. This will be the case when no more than one
+        * button is present and no other user input fields that are not marked as 'skippable' are
+        * present. If the login form were not bypassed, the user would be presented with a
+        * superfluous page on which they must press the single button to proceed with login.
+        * Not only does this cause an additional mouse click and page load, it confuses users,
+        * especially since there are a help link and forgotten password link that are
+        * provided on the login page that do not apply to this situation.
+        *
+        * @param string|null &$button_name if the form has a single button, returns
+        *   the name of the button; otherwise, returns null
+        * @return bool
+        */
+       private function canBypassForm( &$button_name ) {
+               $button_name = null;
+               if ( $this->isContinued() ) {
+                       return false;
+               }
+               $fields = AuthenticationRequest::mergeFieldInfo( $this->authRequests );
+               foreach ( $fields as $fieldname => $field ) {
+                       if ( !isset( $field['type'] ) ) {
+                               return false;
+                       }
+                       if ( !empty( $field['skippable'] ) ) {
+                               continue;
+                       }
+                       if ( $field['type'] === 'button' ) {
+                               if ( $button_name !== null ) {
+                                       $button_name = null;
+                                       return false;
+                               } else {
+                                       $button_name = $fieldname;
+                               }
+                       } elseif ( $field['type'] !== 'null' ) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
        /**
         * Show the success page.
         *
@@ -593,7 +641,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
         * @return HTMLForm
         */
        protected function getAuthForm( array $requests, $action, $msg = '', $msgType = 'error' ) {
-               global $wgSecureLogin, $wgLoginLanguageSelector;
+               global $wgSecureLogin;
                // FIXME merge this with parent
 
                if ( isset( $this->authForm ) ) {
@@ -619,7 +667,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                $form = HTMLForm::factory( 'vform', $formDescriptor, $context );
 
                $form->addHiddenField( 'authAction', $this->authAction );
-               if ( $wgLoginLanguageSelector && $this->mLanguage ) {
+               if ( $this->mLanguage ) {
                        $form->addHiddenField( 'uselang', $this->mLanguage );
                }
                $form->addHiddenField( 'force', $this->securityLevel );
@@ -654,7 +702,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
         */
        protected function getFakeTemplate( $msg, $msgType ) {
                global $wgAuth, $wgEnableEmail, $wgHiddenPrefs, $wgEmailConfirmToEdit, $wgEnableUserEmail,
-                          $wgSecureLogin, $wgLoginLanguageSelector, $wgPasswordResetRoutes;
+                          $wgSecureLogin, $wgPasswordResetRoutes;
 
                // make a best effort to get the value of fields which used to be fixed in the old login
                // template but now might or might not exist depending on what providers are used
@@ -712,7 +760,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                # Don't show a "create account" link if the user can't.
                if ( $this->showCreateAccountLink() ) {
                        # Pass any language selection on to the mode switch link
-                       if ( $wgLoginLanguageSelector && $this->mLanguage ) {
+                       if ( $this->mLanguage ) {
                                $linkq .= '&uselang=' . $this->mLanguage;
                        }
                        // Supply URL, login template creates the button.
@@ -844,7 +892,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
         * @return array
         */
        protected function getFieldDefinitions( $template ) {
-               global $wgEmailConfirmToEdit, $wgLoginLanguageSelector;
+               global $wgEmailConfirmToEdit;
 
                $isLoggedIn = $this->getUser()->isLoggedIn();
                $continuePart = $this->isContinued() ? 'continue-' : '';
@@ -1086,9 +1134,9 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                                        'type' => 'info',
                                        'raw' => true,
                                        'cssclass' => 'mw-form-related-link-container',
-                                       'default' => Linker::link(
+                                       'default' => $this->getLinkRenderer()->makeLink(
                                                SpecialPage::getTitleFor( 'PasswordReset' ),
-                                               $this->msg( 'userlogin-resetpassword-link' )->escaped()
+                                               $this->msg( 'userlogin-resetpassword-link' )->text()
                                        ),
                                        'weight' => 230,
                                ];
@@ -1100,7 +1148,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                                $linkTitle = $this->getTitleFor( $this->isSignup() ? 'Userlogin' :'CreateAccount' );
                                $linkq = $this->getReturnToQueryStringFragment();
                                // Pass any language selection on to the mode switch link
-                               if ( $wgLoginLanguageSelector && $this->mLanguage ) {
+                               if ( $this->mLanguage ) {
                                        $linkq .= '&uselang=' . $this->mLanguage;
                                }
                                $loggedIn = $this->getUser()->isLoggedIn();
@@ -1267,9 +1315,9 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                $targetLanguage = Language::factory( $lang );
                $attr['lang'] = $attr['hreflang'] = $targetLanguage->getHtmlCode();
 
-               return Linker::linkKnown(
+               return $this->getLinkRenderer()->makeKnownLink(
                        $this->getPageTitle(),
-                       htmlspecialchars( $text ),
+                       $text,
                        $attr,
                        $query
                );
index 39e3649..00fca12 100644 (file)
@@ -64,14 +64,15 @@ abstract class WantedQueryPage extends QueryPage {
         * @return string
         */
        public function formatResult( $skin, $result ) {
+               $linkRenderer = $this->getLinkRenderer();
                $title = Title::makeTitleSafe( $result->namespace, $result->title );
                if ( $title instanceof Title ) {
                        if ( $this->isCached() || $this->forceExistenceCheck() ) {
                                $pageLink = $this->existenceCheck( $title )
-                                       ? '<del>' . Linker::link( $title ) . '</del>'
-                                       : Linker::link( $title );
+                                       ? '<del>' . $linkRenderer->makeLink( $title ) . '</del>'
+                                       : $linkRenderer->makeLink( $title );
                        } else {
-                               $pageLink = Linker::link(
+                               $pageLink = $linkRenderer->makeLink(
                                        $title,
                                        null,
                                        [],
index 531c330..a01e9b2 100644 (file)
@@ -52,6 +52,10 @@ class SpecialActiveUsers extends SpecialPage {
 
                $opts->add( 'username', '' );
                $opts->add( 'groups', [] );
+               $opts->add( 'excludegroups', [] );
+               // Backwards-compatibility with old URLs
+               $opts->add( 'hidebots', false, FormOptions::BOOL );
+               $opts->add( 'hidesysops', false, FormOptions::BOOL );
 
                $opts->fetchValuesFromRequest( $this->getRequest() );
 
@@ -82,17 +86,26 @@ class SpecialActiveUsers extends SpecialPage {
                $groups = User::getAllGroups();
 
                foreach ( $groups as $group ) {
-                       $msg = User::getGroupName( $group );
+                       $msg = htmlspecialchars( User::getGroupName( $group ) );
                        $options[$msg] = $group;
                }
 
+               // Backwards-compatibility with old URLs
+               $req = $this->getRequest();
+               $excludeDefault = [];
+               if ( $req->getCheck( 'hidebots' ) ) {
+                       $excludeDefault[] = 'bot';
+               }
+               if ( $req->getCheck( 'hidesysops' ) ) {
+                       $excludeDefault[] = 'sysop';
+               }
+
                $formDescriptor = [
                        'username' => [
                                'type' => 'user',
                                'name' => 'username',
                                'label-message' => 'activeusers-from',
                        ],
-
                        'groups' => [
                                'type' => 'multiselect',
                                'dropdown' => true,
@@ -101,6 +114,15 @@ class SpecialActiveUsers extends SpecialPage {
                                'label-message' => 'activeusers-groups',
                                'options' => $options,
                        ],
+                       'excludegroups' => [
+                               'type' => 'multiselect',
+                               'dropdown' => true,
+                               'flatlist' => true,
+                               'name' => 'excludegroups',
+                               'label-message' => 'activeusers-excludegroups',
+                               'options' => $options,
+                               'default' => $excludeDefault,
+                       ],
                ];
 
                HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
index 4a2a619..4b8446a 100644 (file)
@@ -204,6 +204,7 @@ class SpecialAllPages extends IncludableSpecialPage {
                                ]
                        );
 
+                       $linkRenderer = $this->getLinkRenderer();
                        if ( $res->numRows() > 0 ) {
                                $out = Html::openElement( 'ul', [ 'class' => 'mw-allpages-chunk' ] );
 
@@ -213,7 +214,7 @@ class SpecialAllPages extends IncludableSpecialPage {
                                                $out .= '<li' .
                                                        ( $s->page_is_redirect ? ' class="allpagesredirect"' : '' ) .
                                                        '>' .
-                                                       Linker::link( $t ) .
+                                                       $linkRenderer->makeLink( $t ) .
                                                        "</li>\n";
                                        } else {
                                                $out .= '<li>[[' . htmlspecialchars( $s->page_title ) . "]]</li>\n";
@@ -269,6 +270,7 @@ class SpecialAllPages extends IncludableSpecialPage {
                $navLinks = [];
                $self = $this->getPageTitle();
 
+               $linkRenderer = $this->getLinkRenderer();
                // Generate a "previous page" link if needed
                if ( $prevTitle ) {
                        $query = [ 'from' => $prevTitle->getText() ];
@@ -281,9 +283,9 @@ class SpecialAllPages extends IncludableSpecialPage {
                                $query['hideredirects'] = $hideredirects;
                        }
 
-                       $navLinks[] = Linker::linkKnown(
+                       $navLinks[] = $linkRenderer->makeKnownLink(
                                $self,
-                               $this->msg( 'prevpage', $prevTitle->getText() )->escaped(),
+                               $this->msg( 'prevpage', $prevTitle->getText() )->text(),
                                [],
                                $query
                        );
@@ -304,9 +306,9 @@ class SpecialAllPages extends IncludableSpecialPage {
                                $query['hideredirects'] = $hideredirects;
                        }
 
-                       $navLinks[] = Linker::linkKnown(
+                       $navLinks[] = $linkRenderer->makeKnownLink(
                                $self,
-                               $this->msg( 'nextpage', $t->getText() )->escaped(),
+                               $this->msg( 'nextpage', $t->getText() )->text(),
                                [],
                                $query
                        );
index 9ee1b75..ecc030e 100644 (file)
@@ -78,9 +78,10 @@ class AncientPagesPage extends QueryPage {
 
                $d = $this->getLanguage()->userTimeAndDate( $result->value, $this->getUser() );
                $title = Title::makeTitle( $result->namespace, $result->title );
-               $link = Linker::linkKnown(
+               $linkRenderer = $this->getLinkRenderer();
+               $link = $linkRenderer->makeKnownLink(
                        $title,
-                       htmlspecialchars( $wgContLang->convert( $title->getPrefixedText() ) )
+                       $wgContLang->convert( $title->getPrefixedText() )
                );
 
                return $this->getLanguage()->specialList( $link, htmlspecialchars( $d ) );
index 74b474a..5448013 100644 (file)
@@ -77,6 +77,11 @@ class SpecialApiHelp extends UnlistedSpecialPage {
                $main = new ApiMain( $this->getContext(), false );
                try {
                        $module = $main->getModuleFromPath( $moduleName );
+               } catch ( ApiUsageException $ex ) {
+                       $this->getOutput()->addHTML( Html::rawElement( 'span', [ 'class' => 'error' ],
+                               $this->msg( 'apihelp-no-such-module', $moduleName )->inContentLanguage()->parse()
+                       ) );
+                       return;
                } catch ( UsageException $ex ) {
                        $this->getOutput()->addHTML( Html::rawElement( 'span', [ 'class' => 'error' ],
                                $this->msg( 'apihelp-no-such-module', $moduleName )->inContentLanguage()->parse()
index ce7d24e..585f70b 100644 (file)
@@ -372,12 +372,13 @@ class SpecialBlock extends FormSpecialPage {
 
                $this->getOutput()->addModuleStyles( 'mediawiki.special' );
 
+               $linkRenderer = $this->getLinkRenderer();
                # Link to the user's contributions, if applicable
                if ( $this->target instanceof User ) {
                        $contribsPage = SpecialPage::getTitleFor( 'Contributions', $this->target->getName() );
-                       $links[] = Linker::link(
+                       $links[] = $linkRenderer->makeLink(
                                $contribsPage,
-                               $this->msg( 'ipb-blocklist-contribs', $this->target->getName() )->escaped()
+                               $this->msg( 'ipb-blocklist-contribs', $this->target->getName() )->text()
                        );
                }
 
@@ -392,21 +393,24 @@ class SpecialBlock extends FormSpecialPage {
                        $message = $this->msg( 'ipb-unblock' )->parse();
                        $list = SpecialPage::getTitleFor( 'Unblock' );
                }
-               $links[] = Linker::linkKnown( $list, $message, [] );
+               $links[] = $linkRenderer->makeKnownLink(
+                       $list,
+                       new HtmlArmor( $message )
+               );
 
                # Link to the block list
-               $links[] = Linker::linkKnown(
+               $links[] = $linkRenderer->makeKnownLink(
                        SpecialPage::getTitleFor( 'BlockList' ),
-                       $this->msg( 'ipb-blocklist' )->escaped()
+                       $this->msg( 'ipb-blocklist' )->text()
                );
 
                $user = $this->getUser();
 
                # Link to edit the block dropdown reasons, if applicable
                if ( $user->isAllowed( 'editinterface' ) ) {
-                       $links[] = Linker::linkKnown(
+                       $links[] = $linkRenderer->makeKnownLink(
                                $this->msg( 'ipbreason-dropdown' )->inContentLanguage()->getTitle(),
-                               $this->msg( 'ipb-edit-dropdown' )->escaped(),
+                               $this->msg( 'ipb-edit-dropdown' )->text(),
                                [],
                                [ 'action' => 'edit' ]
                        );
index 1753396..b730ecd 100644 (file)
@@ -109,12 +109,13 @@ class BrokenRedirectsPage extends QueryPage {
                        }
                }
 
+               $linkRenderer = $this->getLinkRenderer();
                // $toObj may very easily be false if the $result list is cached
                if ( !is_object( $toObj ) ) {
-                       return '<del>' . Linker::link( $fromObj ) . '</del>';
+                       return '<del>' . $linkRenderer->makeLink( $fromObj ) . '</del>';
                }
 
-               $from = Linker::linkKnown(
+               $from = $linkRenderer->makeKnownLink(
                        $fromObj,
                        null,
                        [],
@@ -128,28 +129,22 @@ class BrokenRedirectsPage extends QueryPage {
                        // check, if the content model is editable through action=edit
                        ContentHandler::getForTitle( $fromObj )->supportsDirectEditing()
                ) {
-                       $links[] = Linker::linkKnown(
+                       $links[] = $linkRenderer->makeKnownLink(
                                $fromObj,
-                               $this->msg( 'brokenredirects-edit' )->escaped(),
+                               $this->msg( 'brokenredirects-edit' )->text(),
                                [],
                                [ 'action' => 'edit' ]
                        );
                }
-               $to = Linker::link(
-                       $toObj,
-                       null,
-                       [],
-                       [],
-                       [ 'broken' ]
-               );
+               $to = $linkRenderer->makeBrokenLink( $toObj );
                $arr = $this->getLanguage()->getArrow();
 
                $out = $from . $this->msg( 'word-separator' )->escaped();
 
                if ( $this->getUser()->isAllowed( 'delete' ) ) {
-                       $links[] = Linker::linkKnown(
+                       $links[] = $linkRenderer->makeKnownLink(
                                $fromObj,
-                               $this->msg( 'brokenredirects-delete' )->escaped(),
+                               $this->msg( 'brokenredirects-delete' )->text(),
                                [],
                                [ 'action' => 'delete' ]
                        );
index ad12046..2936754 100644 (file)
  * @ingroup SpecialPage
  */
 class DeletedContributionsPage extends SpecialPage {
+       /** @var FormOptions */
+       protected $mOpts;
+
        function __construct() {
-               parent::__construct( 'DeletedContributions', 'deletedhistory',
-                       /*listed*/true, /*function*/false, /*file*/false );
+               parent::__construct( 'DeletedContributions', 'deletedhistory' );
        }
 
        /**
@@ -40,40 +42,43 @@ class DeletedContributionsPage extends SpecialPage {
        function execute( $par ) {
                $this->setHeaders();
                $this->outputHeader();
+               $this->checkPermissions();
 
                $user = $this->getUser();
 
-               if ( !$this->userCanExecute( $user ) ) {
-                       $this->displayRestrictionError();
-
-                       return;
-               }
-
-               $request = $this->getRequest();
                $out = $this->getOutput();
                $out->setPageTitle( $this->msg( 'deletedcontributions-title' ) );
 
-               $options = [];
+               $opts = new FormOptions();
+
+               $opts->add( 'target', '' );
+               $opts->add( 'namespace', '' );
+               $opts->add( 'limit', 20 );
+
+               $opts->fetchValuesFromRequest( $this->getRequest() );
+               $opts->validateIntBounds( 'limit', 0, $this->getConfig()->get( 'QueryPageDefaultLimit' ) );
 
                if ( $par !== null ) {
-                       $target = $par;
-               } else {
-                       $target = $request->getVal( 'target' );
+                       $opts->setValue( 'target', $par );
                }
 
+               $ns = $opts->getValue( 'namespace' );
+               if ( $ns !== null && $ns !== '' ) {
+                       $opts->setValue( 'namespace', intval( $ns ) );
+               }
+
+               $this->mOpts = $opts;
+
+               $target = $opts->getValue( 'target' );
                if ( !strlen( $target ) ) {
-                       $out->addHTML( $this->getForm( '' ) );
+                       $this->getForm();
 
                        return;
                }
 
-               $options['limit'] = $request->getInt( 'limit',
-                       $this->getConfig()->get( 'QueryPageDefaultLimit' ) );
-               $options['target'] = $target;
-
                $userObj = User::newFromName( $target, false );
                if ( !$userObj ) {
-                       $out->addHTML( $this->getForm( '' ) );
+                       $this->getForm();
 
                        return;
                }
@@ -82,16 +87,9 @@ class DeletedContributionsPage extends SpecialPage {
                $target = $userObj->getName();
                $out->addSubtitle( $this->getSubTitle( $userObj ) );
 
-               $ns = $request->getVal( 'namespace', null );
-               if ( $ns !== null && $ns !== '' ) {
-                       $options['namespace'] = intval( $ns );
-               } else {
-                       $options['namespace'] = '';
-               }
-
-               $out->addHTML( $this->getForm( $options ) );
+               $this->getForm();
 
-               $pager = new DeletedContribsPager( $this->getContext(), $target, $options['namespace'] );
+               $pager = new DeletedContribsPager( $this->getContext(), $target, $opts->getValue( 'namespace' ) );
                if ( !$pager->getNumRows() ) {
                        $out->addWikiMsg( 'nocontribs' );
 
@@ -187,76 +185,35 @@ class DeletedContributionsPage extends SpecialPage {
 
        /**
         * Generates the namespace selector form with hidden attributes.
-        * @param array $options The options to be included.
-        * @return string
         */
-       function getForm( $options ) {
-               $options['title'] = $this->getPageTitle()->getPrefixedText();
-               if ( !isset( $options['target'] ) ) {
-                       $options['target'] = '';
-               } else {
-                       $options['target'] = str_replace( '_', ' ', $options['target'] );
-               }
-
-               if ( !isset( $options['namespace'] ) ) {
-                       $options['namespace'] = '';
-               }
-
-               if ( !isset( $options['contribs'] ) ) {
-                       $options['contribs'] = 'user';
-               }
-
-               if ( $options['contribs'] == 'newbie' ) {
-                       $options['target'] = '';
-               }
-
-               $f = Xml::openElement( 'form', [ 'method' => 'get', 'action' => wfScript() ] );
-
-               foreach ( $options as $name => $value ) {
-                       if ( in_array( $name, [ 'namespace', 'target', 'contribs' ] ) ) {
-                               continue;
-                       }
-                       $f .= "\t" . Html::hidden( $name, $value ) . "\n";
-               }
+       function getForm() {
+               $opts = $this->mOpts;
+
+               $formDescriptor = [
+                       'target' => [
+                               'type' => 'user',
+                               'name' => 'target',
+                               'label-message' => 'sp-contributions-username',
+                               'default' => $opts->getValue( 'target' ),
+                               'ipallowed' => true,
+                       ],
 
-               $this->getOutput()->addModules( 'mediawiki.userSuggest' );
-
-               $f .= Xml::openElement( 'fieldset' );
-               $f .= Xml::element( 'legend', [], $this->msg( 'sp-contributions-search' )->text() );
-               $f .= Xml::tags(
-                       'label',
-                       [ 'for' => 'target' ],
-                       $this->msg( 'sp-contributions-username' )->parse()
-               ) . ' ';
-               $f .= Html::input(
-                       'target',
-                       $options['target'],
-                       'text',
-                       [
-                               'size' => '20',
-                               'required' => '',
-                               'class' => [
-                                       'mw-autocomplete-user', // used by mediawiki.userSuggest
-                               ],
-                       ] + ( $options['target'] ? [] : [ 'autofocus' ] )
-               ) . ' ';
-               $f .= Html::namespaceSelector(
-                       [
-                               'selected' => $options['namespace'],
+                       'namespace' => [
+                               'type' => 'namespaceselect',
+                               'name' => 'namespace',
+                               'label-message' => 'namespace',
                                'all' => '',
-                               'label' => $this->msg( 'namespace' )->text()
                        ],
-                       [
-                               'name' => 'namespace',
-                               'id' => 'namespace',
-                               'class' => 'namespaceselector',
-                       ]
-               ) . ' ';
-               $f .= Xml::submitButton( $this->msg( 'sp-contributions-submit' )->text() );
-               $f .= Xml::closeElement( 'fieldset' );
-               $f .= Xml::closeElement( 'form' );
-
-               return $f;
+               ];
+
+               $form = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
+                       ->setWrapperLegendMsg( 'sp-contributions-search' )
+                       ->setSubmitTextMsg( 'sp-contributions-submit' )
+                       // prevent setting subpage and 'target' parameter at the same time
+                       ->setAction( $this->getPageTitle()->getLocalURL() )
+                       ->setMethod( 'get' )
+                       ->prepareForm()
+                       ->displayForm( false );
        }
 
        /**
index 0cec9d0..9140bf1 100644 (file)
@@ -137,14 +137,15 @@ class DoubleRedirectsPage extends QueryPage {
                                $result = $dbr->fetchObject( $res );
                        }
                }
+               $linkRenderer = $this->getLinkRenderer();
                if ( !$result ) {
-                       return '<del>' . Linker::link( $titleA, null, [], [ 'redirect' => 'no' ] ) . '</del>';
+                       return '<del>' . $linkRenderer->makeLink( $titleA, null, [], [ 'redirect' => 'no' ] ) . '</del>';
                }
 
                $titleB = Title::makeTitle( $result->nsb, $result->tb );
                $titleC = Title::makeTitle( $result->nsc, $result->tc, '', $result->iwc );
 
-               $linkA = Linker::linkKnown(
+               $linkA = $linkRenderer->makeKnownLink(
                        $titleA,
                        null,
                        [],
@@ -158,26 +159,24 @@ class DoubleRedirectsPage extends QueryPage {
                        // check, if the content model is editable through action=edit
                        ContentHandler::getForTitle( $titleA )->supportsDirectEditing()
                ) {
-                       $edit = Linker::linkKnown(
+                       $edit = $linkRenderer->makeKnownLink(
                                $titleA,
-                               $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->escaped(),
+                               $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->text(),
                                [],
-                               [
-                                       'action' => 'edit'
-                               ]
+                               [ 'action' => 'edit' ]
                        );
                } else {
                        $edit = '';
                }
 
-               $linkB = Linker::linkKnown(
+               $linkB = $linkRenderer->makeKnownLink(
                        $titleB,
                        null,
                        [],
                        [ 'redirect' => 'no' ]
                );
 
-               $linkC = Linker::linkKnown( $titleC );
+               $linkC = $linkRenderer->makeKnownLink( $titleC );
 
                $lang = $this->getLanguage();
                $arr = $lang->getArrow() . $lang->getDirMark();
index 252d076..476c452 100644 (file)
@@ -158,10 +158,11 @@ class SpecialEditTags extends UnlistedSpecialPage {
                        // Also set header tabs to be for the target.
                        $this->getSkin()->setRelevantTitle( $this->targetObj );
 
+                       $linkRenderer = $this->getLinkRenderer();
                        $links = [];
-                       $links[] = Linker::linkKnown(
+                       $links[] = $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( 'Log' ),
-                               $this->msg( 'viewpagelogs' )->escaped(),
+                               $this->msg( 'viewpagelogs' )->text(),
                                [],
                                [
                                        'page' => $this->targetObj->getPrefixedText(),
@@ -170,17 +171,17 @@ class SpecialEditTags extends UnlistedSpecialPage {
                        );
                        if ( !$this->targetObj->isSpecialPage() ) {
                                // Give a link to the page history
-                               $links[] = Linker::linkKnown(
+                               $links[] = $linkRenderer->makeKnownLink(
                                        $this->targetObj,
-                                       $this->msg( 'pagehist' )->escaped(),
+                                       $this->msg( 'pagehist' )->text(),
                                        [],
                                        [ 'action' => 'history' ]
                                );
                        }
                        // Link to Special:Tags
-                       $links[] = Linker::linkKnown(
+                       $links[] = $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( 'Tags' ),
-                               $this->msg( 'tags-edit-manage-link' )->escaped()
+                               $this->msg( 'tags-edit-manage-link' )->text()
                        );
                        // Logs themselves don't have histories or archived revisions
                        $this->getOutput()->addSubtitle( $this->getLanguage()->pipeList( $links ) );
index 06be7bc..085b68d 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  * @ingroup SpecialPage
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * A special page that allows users to send e-mails to other users
@@ -52,13 +53,14 @@ class SpecialEmailUser extends UnlistedSpecialPage {
        }
 
        protected function getFormFields() {
+               $linkRenderer = $this->getLinkRenderer();
                return [
                        'From' => [
                                'type' => 'info',
                                'raw' => 1,
-                               'default' => Linker::link(
+                               'default' => $linkRenderer->makeLink(
                                        $this->getUser()->getUserPage(),
-                                       htmlspecialchars( $this->getUser()->getName() )
+                                       $this->getUser()->getName()
                                ),
                                'label-message' => 'emailfrom',
                                'id' => 'mw-emailuser-sender',
@@ -66,9 +68,9 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                        'To' => [
                                'type' => 'info',
                                'raw' => 1,
-                               'default' => Linker::link(
+                               'default' => $linkRenderer->makeLink(
                                        $this->mTargetObj->getUserPage(),
-                                       htmlspecialchars( $this->mTargetObj->getName() )
+                                       $this->mTargetObj->getName()
                                ),
                                'label-message' => 'emailto',
                                'id' => 'mw-emailuser-recipient',
@@ -223,7 +225,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
        public static function getPermissionsError( $user, $editToken, Config $config = null ) {
                if ( $config === null ) {
                        wfDebug( __METHOD__ . ' called without a Config instance passed to it' );
-                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $config = MediaWikiServices::getInstance()->getMainConfig();
                }
                if ( !$config->get( 'EnableEmail' ) || !$config->get( 'EnableUserEmail' ) ) {
                        return 'usermaildisabled';
@@ -305,7 +307,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
         * @since 1.20
         * @param array $data
         * @param HTMLForm $form
-        * @return Status|string|bool
+        * @return Status|bool
         */
        public static function uiSubmit( array $data, HTMLForm $form ) {
                return self::submit( $data, $form->getContext() );
@@ -318,8 +320,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
         *
         * @param array $data
         * @param IContextSource $context
-        * @return Status|string|bool Status object, or potentially a String on error
-        * or maybe even true on success if anything uses the EmailUser hook.
+        * @return Status|bool
         */
        public static function submit( array $data, IContextSource $context ) {
                $config = $context->getConfig();
@@ -327,7 +328,7 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                $target = self::getTarget( $data['Target'] );
                if ( !$target instanceof User ) {
                        // Messages used here: notargettext, noemailtext, nowikiemailtext
-                       return $context->msg( $target . 'text' )->parseAsBlock();
+                       return Status::newFatal( $target . 'text' );
                }
 
                $to = MailAddress::newFromUser( $target );
@@ -340,9 +341,33 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                $text .= $context->msg( 'emailuserfooter',
                        $from->name, $to->name )->inContentLanguage()->text();
 
-               $error = '';
+               $error = false;
                if ( !Hooks::run( 'EmailUser', [ &$to, &$from, &$subject, &$text, &$error ] ) ) {
-                       return $error;
+                       if ( $error instanceof Status ) {
+                               return $error;
+                       } elseif ( $error === false || $error === '' || $error === [] ) {
+                               // Possibly to tell HTMLForm to pretend there was no submission?
+                               return false;
+                       } elseif ( $error === true ) {
+                               // Hook sent the mail itself and indicates success?
+                               return Status::newGood();
+                       } elseif ( is_array( $error ) ) {
+                               $status = Status::newGood();
+                               foreach ( $error as $e ) {
+                                       $status->fatal( $e );
+                               }
+                               return $status;
+                       } elseif ( $error instanceof MessageSpecifier ) {
+                               return Status::newFatal( $error );
+                       } else {
+                               // Ugh. Either a raw HTML string, or something that's supposed
+                               // to be treated like one.
+                               $type = is_object( $error ) ? get_class( $error ) : gettype( $error );
+                               wfDeprecated( "EmailUser hook returning a $type as \$error", '1.29' );
+                               return Status::newFatal( new ApiRawMessage(
+                                       [ '$1', Message::rawParam( (string)$error ) ], 'hookaborted'
+                               ) );
+                       }
                }
 
                if ( $config->get( 'UserEmailUseReplyTo' ) ) {
index b86a95e..f20829f 100644 (file)
@@ -53,12 +53,6 @@ class FewestrevisionsPage extends QueryPage {
                                'page_namespace' => MWNamespace::getContentNamespaces(),
                                'page_id = rev_page' ],
                        'options' => [
-                               'HAVING' => 'COUNT(*) > 1',
-                               // ^^^ This was probably here to weed out redirects.
-                               // Since we mark them as such now, it might be
-                               // useful to remove this. People _do_ create pages
-                               // and never revise them, they aren't necessarily
-                               // redirects.
                                'GROUP BY' => [ 'page_namespace', 'page_title', 'page_is_redirect' ]
                        ]
                ];
@@ -88,14 +82,14 @@ class FewestrevisionsPage extends QueryPage {
                                )
                        );
                }
+               $linkRenderer = $this->getLinkRenderer();
+               $text = $wgContLang->convert( $nt->getPrefixedText() );
+               $plink = $linkRenderer->makeLink( $nt, $text );
 
-               $text = htmlspecialchars( $wgContLang->convert( $nt->getPrefixedText() ) );
-               $plink = Linker::linkKnown( $nt, $text );
-
-               $nl = $this->msg( 'nrevisions' )->numParams( $result->value )->escaped();
+               $nl = $this->msg( 'nrevisions' )->numParams( $result->value )->text();
                $redirect = isset( $result->redirect ) && $result->redirect ?
                        ' - ' . $this->msg( 'isredirect' )->escaped() : '';
-               $nlink = Linker::linkKnown(
+               $nlink = $linkRenderer->makeKnownLink(
                        $nt,
                        $nl,
                        [],
index 6de127d..8021bc2 100644 (file)
@@ -208,11 +208,12 @@ class FileDuplicateSearchPage extends QueryPage {
        function formatResult( $skin, $result ) {
                global $wgContLang;
 
+               $linkRenderer = $this->getLinkRenderer();
                $nt = $result->getTitle();
                $text = $wgContLang->convert( $nt->getText() );
-               $plink = Linker::link(
+               $plink = $linkRenderer->makeLink(
                        $nt,
-                       htmlspecialchars( $text )
+                       $text
                );
 
                $userText = $result->getUser( 'text' );
index c58af60..ce88624 100644 (file)
@@ -24,6 +24,8 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * MediaWiki page data importer
  *
@@ -592,12 +594,12 @@ class ImportReporter extends ContextSource {
                }
 
                $this->mPageCount++;
-
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( $successCount > 0 ) {
                        // <bdi> prevents jumbling of the versions count
                        // in RTL wikis in case the page title is LTR
                        $this->getOutput()->addHTML(
-                               "<li>" . Linker::linkKnown( $title ) . " " .
+                               "<li>" . $linkRenderer->makeLink( $title ) . " " .
                                        "<bdi>" .
                                        $this->msg( 'import-revision-count' )->numParams( $successCount )->escaped() .
                                        "</bdi>" .
@@ -656,7 +658,7 @@ class ImportReporter extends ContextSource {
                                );
                        }
                } else {
-                       $this->getOutput()->addHTML( "<li>" . Linker::linkKnown( $title ) . " " .
+                       $this->getOutput()->addHTML( "<li>" . $linkRenderer->makeKnownLink( $title ) . " " .
                                $this->msg( 'import-nonewrevisions' )->escaped() . "</li>\n" );
                }
        }
index 39c8ae8..2c92410 100644 (file)
@@ -71,8 +71,14 @@ class SpecialListGrants extends SpecialPage {
 
                        $id = \Sanitizer::escapeId( $grant );
                        $out->addHTML( \Html::rawElement( 'tr', [ 'id' => $id ],
-                               "<td>" . $this->msg( "grant-$grant" )->escaped() . "</td>" .
-                               "<td>" . $grantCellHtml . '</td>'
+                               "<td>" .
+                               $this->msg(
+                                       "listgrants-grant-display",
+                                       \User::getGrantName( $grant ),
+                                       "<span class='mw-listgrants-grant-name'>" . $id . "</span>"
+                               )->parse() .
+                               "</td>" .
+                               "<td>" . $grantCellHtml . "</td>"
                        ) );
                }
 
index d64306b..f3d3a77 100644 (file)
@@ -71,6 +71,8 @@ class SpecialListGroupRights extends SpecialPage {
                ) );
                asort( $allGroups );
 
+               $linkRenderer = $this->getLinkRenderer();
+
                foreach ( $allGroups as $group ) {
                        $permissions = isset( $groupPermissions[$group] )
                                ? $groupPermissions[$group]
@@ -92,22 +94,22 @@ class SpecialListGroupRights extends SpecialPage {
                                // Do not make a link for the generic * group or group with invalid group page
                                $grouppage = htmlspecialchars( $groupnameLocalized );
                        } else {
-                               $grouppage = Linker::link(
+                               $grouppage = $linkRenderer->makeLink(
                                        $grouppageLocalizedTitle,
-                                       htmlspecialchars( $groupnameLocalized )
+                                       $groupnameLocalized
                                );
                        }
 
                        if ( $group === 'user' ) {
                                // Link to Special:listusers for implicit group 'user'
-                               $grouplink = '<br />' . Linker::linkKnown(
+                               $grouplink = '<br />' . $linkRenderer->makeKnownLink(
                                        SpecialPage::getTitleFor( 'Listusers' ),
-                                       $this->msg( 'listgrouprights-members' )->escaped()
+                                       $this->msg( 'listgrouprights-members' )->text()
                                );
                        } elseif ( !in_array( $group, $config->get( 'ImplicitGroups' ) ) ) {
-                               $grouplink = '<br />' . Linker::linkKnown(
+                               $grouplink = '<br />' . $linkRenderer->makeKnownLink(
                                        SpecialPage::getTitleFor( 'Listusers' ),
-                                       $this->msg( 'listgrouprights-members' )->escaped(),
+                                       $this->msg( 'listgrouprights-members' )->text(),
                                        [],
                                        [ 'group' => $group ]
                                );
@@ -165,7 +167,7 @@ class SpecialListGroupRights extends SpecialPage {
                                $this->msg( 'listgrouprights-namespaceprotection-restrictedto' )->text()
                        )
                );
-
+               $linkRenderer = $this->getLinkRenderer();
                ksort( $namespaceProtection );
                foreach ( $namespaceProtection as $namespace => $rights ) {
                        if ( !in_array( $namespace, MWNamespace::getValidNamespaces() ) ) {
@@ -183,9 +185,9 @@ class SpecialListGroupRights extends SpecialPage {
                                Html::rawElement(
                                        'td',
                                        [],
-                                       Linker::link(
+                                       $linkRenderer->makeLink(
                                                SpecialPage::getTitleFor( 'Allpages' ),
-                                               htmlspecialchars( $namespaceText ),
+                                               $namespaceText,
                                                [],
                                                [ 'namespace' => $namespace ]
                                        )
index 1d02a4f..c61609d 100644 (file)
@@ -153,11 +153,12 @@ class MIMEsearchPage extends QueryPage {
        function formatResult( $skin, $result ) {
                global $wgContLang;
 
+               $linkRenderer = $this->getLinkRenderer();
                $nt = Title::makeTitle( $result->namespace, $result->title );
                $text = $wgContLang->convert( $nt->getText() );
-               $plink = Linker::link(
+               $plink = $linkRenderer->makeLink(
                        Title::newFromText( $nt->getPrefixedText() ),
-                       htmlspecialchars( $text )
+                       $text
                );
 
                $download = Linker::makeMediaLinkObj( $nt, $this->msg( 'download' )->escaped() );
@@ -166,9 +167,9 @@ class MIMEsearchPage extends QueryPage {
                $bytes = htmlspecialchars( $lang->formatSize( $result->img_size ) );
                $dimensions = $this->msg( 'widthheight' )->numParams( $result->img_width,
                        $result->img_height )->escaped();
-               $user = Linker::link(
+               $user = $linkRenderer->makeLink(
                        Title::makeTitle( NS_USER, $result->img_user_text ),
-                       htmlspecialchars( $result->img_user_text )
+                       $result->img_user_text
                );
 
                $time = $lang->userTimeAndDate( $result->img_timestamp, $this->getUser() );
index 7683ad8..e11977f 100644 (file)
@@ -174,10 +174,11 @@ class MediaStatisticsPage extends QueryPage {
         */
        protected function outputTableRow( $mime, $count, $bytes ) {
                $mimeSearch = SpecialPage::getTitleFor( 'MIMEsearch', $mime );
+               $linkRenderer = $this->getLinkRenderer();
                $row = Html::rawElement(
                        'td',
                        [],
-                       Linker::link( $mimeSearch, htmlspecialchars( $mime ) )
+                       $linkRenderer->makeLink( $mimeSearch, $mime )
                );
                $row .= Html::element(
                        'td',
index b916c1f..f122db8 100644 (file)
@@ -277,6 +277,8 @@ class SpecialMergeHistory extends SpecialPage {
        function formatRevisionRow( $row ) {
                $rev = new Revision( $row );
 
+               $linkRenderer = $this->getLinkRenderer();
+
                $stxt = '';
                $last = $this->msg( 'last' )->escaped();
 
@@ -285,9 +287,9 @@ class SpecialMergeHistory extends SpecialPage {
 
                $user = $this->getUser();
 
-               $pageLink = Linker::linkKnown(
+               $pageLink = $linkRenderer->makeKnownLink(
                        $rev->getTitle(),
-                       htmlspecialchars( $this->getLanguage()->userTimeAndDate( $ts, $user ) ),
+                       $this->getLanguage()->userTimeAndDate( $ts, $user ),
                        [],
                        [ 'oldid' => $rev->getId() ]
                );
@@ -299,9 +301,9 @@ class SpecialMergeHistory extends SpecialPage {
                if ( !$rev->userCan( Revision::DELETED_TEXT, $user ) ) {
                        $last = $this->msg( 'last' )->escaped();
                } elseif ( isset( $this->prevId[$row->rev_id] ) ) {
-                       $last = Linker::linkKnown(
+                       $last = $linkRenderer->makeKnownLink(
                                $rev->getTitle(),
-                               $this->msg( 'last' )->escaped(),
+                               $this->msg( 'last' )->text(),
                                [],
                                [
                                        'diff' => $row->rev_id,
@@ -359,7 +361,9 @@ class SpecialMergeHistory extends SpecialPage {
                        return false;
                }
 
-               $targetLink = Linker::link(
+               $linkRenderer = $this->getLinkRenderer();
+
+               $targetLink = $linkRenderer->makeLink(
                        $targetTitle,
                        null,
                        [],
index 015701d..6095412 100644 (file)
@@ -91,10 +91,11 @@ class MostcategoriesPage extends QueryPage {
                        );
                }
 
+               $linkRenderer = $this->getLinkRenderer();
                if ( $this->isCached() ) {
-                       $link = Linker::link( $title );
+                       $link = $linkRenderer->makeLink( $title );
                } else {
-                       $link = Linker::linkKnown( $title );
+                       $link = $linkRenderer->makeKnownLink( $title );
                }
 
                $count = $this->msg( 'ncategories' )->numParams( $result->value )->escaped();
index 3e78352..210c4a2 100644 (file)
@@ -97,10 +97,11 @@ class MostinterwikisPage extends QueryPage {
                        );
                }
 
+               $linkRenderer = $this->getLinkRenderer();
                if ( $this->isCached() ) {
-                       $link = Linker::link( $title );
+                       $link = $linkRenderer->makeLink( $title );
                } else {
-                       $link = Linker::linkKnown( $title );
+                       $link = $linkRenderer->makeKnownLink( $title );
                }
 
                $count = $this->msg( 'ninterwikis' )->numParams( $result->value )->escaped();
index 01eb39e..712574c 100644 (file)
@@ -91,7 +91,8 @@ class MostlinkedPage extends QueryPage {
        function makeWlhLink( $title, $caption ) {
                $wlh = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedDBkey() );
 
-               return Linker::linkKnown( $wlh, $caption );
+               $linkRenderer = $this->getLinkRenderer();
+               return $linkRenderer->makeKnownLink( $wlh, $caption );
        }
 
        /**
@@ -115,10 +116,11 @@ class MostlinkedPage extends QueryPage {
                        );
                }
 
-               $link = Linker::link( $title );
+               $linkRenderer = $this->getLinkRenderer();
+               $link = $linkRenderer->makeLink( $title );
                $wlh = $this->makeWlhLink(
                        $title,
-                       $this->msg( 'nlinks' )->numParams( $result->value )->escaped()
+                       $this->msg( 'nlinks' )->numParams( $result->value )->text()
                );
 
                return $this->getLanguage()->specialList( $link, $wlh );
index 7fcb9d8..d102791 100644 (file)
@@ -104,7 +104,7 @@ class MostlinkedTemplatesPage extends QueryPage {
                }
 
                return $this->getLanguage()->specialList(
-                       Linker::link( $title ),
+                       $this->getLinkRenderer()->makeLink( $title ),
                        $this->makeWlhLink( $title, $result )
                );
        }
@@ -118,9 +118,9 @@ class MostlinkedTemplatesPage extends QueryPage {
         */
        private function makeWlhLink( $title, $result ) {
                $wlh = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() );
-               $label = $this->msg( 'ntransclusions' )->numParams( $result->value )->escaped();
+               $label = $this->msg( 'ntransclusions' )->numParams( $result->value )->text();
 
-               return Linker::link( $wlh, $label );
+               return $this->getLinkRenderer()->makeLink( $wlh, $label );
        }
 
        protected function getGroupName() {
index 706a1d7..37006d8 100644 (file)
@@ -133,7 +133,7 @@ class SpecialPagesWithProp extends QueryPage {
         */
        function formatResult( $skin, $result ) {
                $title = Title::newFromRow( $result );
-               $ret = Linker::link( $title, null, [], [], [ 'known' ] );
+               $ret = $this->getLinkRenderer()->makeKnownLink( $title );
                if ( $result->pp_value !== '' ) {
                        // Do not show very long or binary values on the special page
                        $valueLength = strlen( $result->pp_value );
index 82abccf..a4f16bd 100644 (file)
@@ -100,14 +100,6 @@ class SpecialPasswordReset extends FormSpecialPage {
                        ];
                }
 
-               if ( $this->getUser()->isAllowed( 'passwordreset' ) ) {
-                       $a['Capture'] = [
-                               'type' => 'check',
-                               'label-message' => 'passwordreset-capture',
-                               'help-message' => 'passwordreset-capture-help',
-                       ];
-               }
-
                return $a;
        }
 
@@ -144,22 +136,12 @@ class SpecialPasswordReset extends FormSpecialPage {
         * @return Status
         */
        public function onSubmit( array $data ) {
-               if ( isset( $data['Capture'] ) && !$this->getUser()->isAllowed( 'passwordreset' ) ) {
-                       // The user knows they don't have the passwordreset permission,
-                       // but they tried to spoof the form. That's naughty
-                       throw new PermissionsError( 'passwordreset' );
-               }
-
                $username = isset( $data['Username'] ) ? $data['Username'] : null;
                $email = isset( $data['Email'] ) ? $data['Email'] : null;
-               $capture = !empty( $data['Capture'] );
 
                $this->method = $username ? 'username' : 'email';
                $this->result = Status::wrap(
-                       $this->getPasswordReset()->execute( $this->getUser(), $username, $email, $capture ) );
-               if ( $capture && $this->result->isOK() ) {
-                       $this->passwords = $this->result->getValue();
-               }
+                       $this->getPasswordReset()->execute( $this->getUser(), $username, $email ) );
 
                if ( $this->result->hasMessage( 'actionthrottledtext' ) ) {
                        throw new ThrottledError;
@@ -169,28 +151,6 @@ class SpecialPasswordReset extends FormSpecialPage {
        }
 
        public function onSuccess() {
-               if ( $this->getUser()->isAllowed( 'passwordreset' ) && $this->passwords ) {
-                       // @todo Logging
-
-                       if ( $this->result->isGood() ) {
-                               $this->getOutput()->addWikiMsg( 'passwordreset-emailsent-capture2',
-                                       count( $this->passwords ) );
-                       } else {
-                               $this->getOutput()->addWikiMsg( 'passwordreset-emailerror-capture2',
-                                       $this->result->getMessage(), key( $this->passwords ), count( $this->passwords ) );
-                       }
-
-                       $this->getOutput()->addHTML( Html::openElement( 'ul' ) );
-                       foreach ( $this->passwords as $username => $pwd ) {
-                               $this->getOutput()->addHTML( Html::rawElement( 'li', [],
-                                       htmlspecialchars( $username, ENT_QUOTES )
-                                       . $this->msg( 'colon-separator' )->text()
-                                       . htmlspecialchars( $pwd, ENT_QUOTES )
-                               ) );
-                       }
-                       $this->getOutput()->addHTML( Html::closeElement( 'ul' ) );
-               }
-
                if ( $this->method === 'email' ) {
                        $this->getOutput()->addWikiMsg( 'passwordreset-emailsentemail' );
                } else {
index 5e3e430..4671591 100644 (file)
@@ -228,9 +228,9 @@ class SpecialPrefixindex extends SpecialAllPages {
                                                $displayed = substr( $displayed, $prefixLength );
                                        }
                                        $link = ( $title->isRedirect() ? '<div class="allpagesredirect">' : '' ) .
-                                               Linker::linkKnown(
+                                               $this->getLinkRenderer()->makeKnownLink(
                                                        $title,
-                                                       htmlspecialchars( $displayed )
+                                                       $displayed
                                                ) .
                                                ( $title->isRedirect() ? '</div>' : '' );
 
@@ -275,9 +275,9 @@ class SpecialPrefixindex extends SpecialAllPages {
                                $query['namespace'] = $namespace;
                        }
 
-                       $nextLink = Linker::linkKnown(
+                       $nextLink = $this->getLinkRenderer()->makeKnownLink(
                                $this->getPageTitle(),
-                               $this->msg( 'nextpage', str_replace( '_', ' ', $nextRow->page_title ) )->escaped(),
+                               $this->msg( 'nextpage', str_replace( '_', ' ', $nextRow->page_title ) )->text(),
                                [],
                                $query
                        );
index c800d96..fa9033c 100644 (file)
@@ -84,7 +84,7 @@ class SpecialProtectedtitles extends SpecialPage {
                        ) . "\n";
                }
 
-               $link = Linker::link( $title );
+               $link = $this->getLinkRenderer()->makeLink( $title );
                $description_items = [];
                // Messages: restriction-level-sysop, restriction-level-autoconfirmed
                $protType = $this->msg( 'restriction-level-' . $row->pt_create_perm )->escaped();
index cd3299c..4569dd2 100644 (file)
@@ -95,7 +95,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
        }
 
        /**
-        * Get custom show/hide filters
+        * Get all custom filters
         *
         * @return array Map of filter URL param names to properties (msg/default)
         */
@@ -747,9 +747,10 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                $showhide = [ 'show', 'hide' ];
 
-               foreach ( $this->getCustomFilters() as $key => $params ) {
+               foreach ( $this->getRenderableCustomFilters( $this->getCustomFilters() ) as $key => $params ) {
                        $filters[$key] = $params['msg'];
                }
+
                // Disable some if needed
                if ( !$user->useRCPatrol() ) {
                        unset( $filters['hidepatrolled'] );
index dcaff4d..8780c56 100644 (file)
@@ -241,32 +241,33 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
         * Show some useful links in the subtitle
         */
        protected function showConvenienceLinks() {
+               $linkRenderer = $this->getLinkRenderer();
                # Give a link to the logs/hist for this page
                if ( $this->targetObj ) {
                        // Also set header tabs to be for the target.
                        $this->getSkin()->setRelevantTitle( $this->targetObj );
 
                        $links = [];
-                       $links[] = Linker::linkKnown(
+                       $links[] = $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( 'Log' ),
-                               $this->msg( 'viewpagelogs' )->escaped(),
+                               $this->msg( 'viewpagelogs' )->text(),
                                [],
                                [ 'page' => $this->targetObj->getPrefixedText() ]
                        );
                        if ( !$this->targetObj->isSpecialPage() ) {
                                # Give a link to the page history
-                               $links[] = Linker::linkKnown(
+                               $links[] = $linkRenderer->makeKnownLink(
                                        $this->targetObj,
-                                       $this->msg( 'pagehist' )->escaped(),
+                                       $this->msg( 'pagehist' )->text(),
                                        [],
                                        [ 'action' => 'history' ]
                                );
                                # Link to deleted edits
                                if ( $this->getUser()->isAllowed( 'undelete' ) ) {
                                        $undelete = SpecialPage::getTitleFor( 'Undelete' );
-                                       $links[] = Linker::linkKnown(
+                                       $links[] = $linkRenderer->makeKnownLink(
                                                $undelete,
-                                               $this->msg( 'deletedhist' )->escaped(),
+                                               $this->msg( 'deletedhist' )->text(),
                                                [],
                                                [ 'target' => $this->targetObj->getPrefixedDBkey() ]
                                        );
index 9280b04..9f83832 100644 (file)
@@ -295,12 +295,12 @@ class SpecialSearch extends SpecialPage {
                $textStatus = null;
                if ( $textMatches instanceof Status ) {
                        $textStatus = $textMatches;
-                       $textMatches = null;
+                       $textMatches = $textStatus->getValue();
                }
 
                // did you mean... suggestions
                $didYouMeanHtml = '';
-               if ( $showSuggestion && $textMatches && !$textStatus ) {
+               if ( $showSuggestion && $textMatches ) {
                        if ( $textMatches->hasRewrittenQuery() ) {
                                $didYouMeanHtml = $this->getDidYouMeanRewrittenHtml( $term, $textMatches );
                        } elseif ( $textMatches->hasSuggestion() ) {
@@ -360,6 +360,25 @@ class SpecialSearch extends SpecialPage {
 
                $out->addHTML( "<div class='searchresults'>" );
 
+               $hasErrors = $textStatus && $textStatus->getErrors();
+               if ( $hasErrors ) {
+                       list( $error, $warning ) = $textStatus->splitByErrorType();
+                       if ( $error->getErrors() ) {
+                               $out->addHTML( Html::rawElement(
+                                       'div',
+                                       [ 'class' => 'errorbox' ],
+                                       $error->getHTML( 'search-error' )
+                               ) );
+                       }
+                       if ( $warning->getErrors() ) {
+                               $out->addHTML( Html::rawElement(
+                                       'div',
+                                       [ 'class' => 'warningbox' ],
+                                       $warning->getHTML( 'search-warning' )
+                               ) );
+                       }
+               }
+
                // prev/next links
                $prevnext = null;
                if ( $num || $this->offset ) {
@@ -388,7 +407,8 @@ class SpecialSearch extends SpecialPage {
                        }
                        $titleMatches->free();
                }
-               if ( $textMatches && !$textStatus ) {
+
+               if ( $textMatches ) {
                        // output appropriate heading
                        if ( $numTextMatches > 0 && $numTitleMatches > 0 ) {
                                $out->addHTML( '<div class="mw-search-visualclear"></div>' );
@@ -412,22 +432,18 @@ class SpecialSearch extends SpecialPage {
                $hasOtherResults = $textMatches &&
                        $textMatches->hasInterwikiResults( SearchResultSet::INLINE_RESULTS );
 
-               if ( $num === 0 ) {
-                       if ( $textStatus ) {
-                               $out->addHTML( '<div class="error">' .
-                                       $textStatus->getMessage( 'search-error' ) . '</div>' );
-                       } else {
-                               if ( !$this->offset ) {
-                                       // If we have an offset the create link was rendered earlier in this function.
-                                       // This class needs a good de-spaghettification, but for now this will
-                                       // do the job.
-                                       $this->showCreateLink( $title, $num, $titleMatches, $textMatches );
-                               }
-                               $out->wrapWikiMsg( "<p class=\"mw-search-nonefound\">\n$1</p>",
-                                       [ $hasOtherResults ? 'search-nonefound-thiswiki' : 'search-nonefound',
-                                                       wfEscapeWikiText( $term )
-                                       ] );
+               // If we have no results and we have not already displayed an error message
+               if ( $num === 0 && !$hasErrors ) {
+                       if ( !$this->offset ) {
+                               // If we have an offset the create link was rendered earlier in this function.
+                               // This class needs a good de-spaghettification, but for now this will
+                               // do the job.
+                               $this->showCreateLink( $title, $num, $titleMatches, $textMatches );
                        }
+                       $out->wrapWikiMsg( "<p class=\"mw-search-nonefound\">\n$1</p>", [
+                               $hasOtherResults ? 'search-nonefound-thiswiki' : 'search-nonefound',
+                               wfEscapeWikiText( $term )
+                       ] );
                }
 
                if ( $hasOtherResults ) {
index 688a6ef..b18b370 100644 (file)
@@ -118,7 +118,7 @@ class SpecialSpecialpages extends UnlistedSpecialPage {
                                        $pageClasses[] = 'mw-specialpagerestricted';
                                }
 
-                               $link = Linker::linkKnown( $title, htmlspecialchars( $desc ) );
+                               $link = $this->getLinkRenderer()->makeKnownLink( $title, $desc );
                                $out->addHTML( Html::rawElement(
                                                'li',
                                                [ 'class' => implode( ' ', $pageClasses ) ],
index 86f1e20..3342c32 100644 (file)
@@ -112,18 +112,20 @@ class SpecialStatistics extends SpecialPage {
         * @return string
         */
        private function getPageStats() {
+               $linkRenderer = $this->getLinkRenderer();
+
                $specialAllPagesTitle = SpecialPage::getTitleFor( 'Allpages' );
                $pageStatsHtml = Xml::openElement( 'tr' ) .
                        Xml::tags( 'th', [ 'colspan' => '2' ], $this->msg( 'statistics-header-pages' )
                                ->parse() ) .
                        Xml::closeElement( 'tr' ) .
-                               $this->formatRow( Linker::linkKnown( $specialAllPagesTitle,
-                                       $this->msg( 'statistics-articles' )->parse(), [], [ 'hideredirects' => 1 ] ),
+                               $this->formatRow( $linkRenderer->makeKnownLink( $specialAllPagesTitle,
+                                       $this->msg( 'statistics-articles' )->text(), [], [ 'hideredirects' => 1 ] ),
                                        $this->getLanguage()->formatNum( $this->good ),
                                        [ 'class' => 'mw-statistics-articles' ],
                                        'statistics-articles-desc' ) .
-                               $this->formatRow( Linker::linkKnown( $specialAllPagesTitle,
-                                       $this->msg( 'statistics-pages' )->parse() ),
+                               $this->formatRow( $linkRenderer->makeKnownLink( $specialAllPagesTitle,
+                                       $this->msg( 'statistics-pages' )->text() ),
                                        $this->getLanguage()->formatNum( $this->total ),
                                        [ 'class' => 'mw-statistics-pages' ],
                                        'statistics-pages-desc' );
@@ -131,8 +133,8 @@ class SpecialStatistics extends SpecialPage {
                // Show the image row only, when there are files or upload is possible
                if ( $this->images !== 0 || $this->getConfig()->get( 'EnableUploads' ) ) {
                        $pageStatsHtml .= $this->formatRow(
-                               Linker::linkKnown( SpecialPage::getTitleFor( 'MediaStatistics' ),
-                               $this->msg( 'statistics-files' )->parse() ),
+                               $linkRenderer->makeKnownLink( SpecialPage::getTitleFor( 'MediaStatistics' ),
+                               $this->msg( 'statistics-files' )->text() ),
                                $this->getLanguage()->formatNum( $this->images ),
                                [ 'class' => 'mw-statistics-files' ] );
                }
@@ -166,9 +168,9 @@ class SpecialStatistics extends SpecialPage {
                                [ 'class' => 'mw-statistics-users' ]
                        ) .
                        $this->formatRow( $this->msg( 'statistics-users-active' )->parse() . ' ' .
-                               Linker::linkKnown(
+                               $this->getLinkRenderer()->makeKnownLink(
                                        SpecialPage::getTitleFor( 'Activeusers' ),
-                                       $this->msg( 'listgrouprights-members' )->escaped()
+                                       $this->msg( 'listgrouprights-members' )->text()
                                ),
                                $this->getLanguage()->formatNum( $this->activeUsers ),
                                [ 'class' => 'mw-statistics-users-active' ],
@@ -178,6 +180,7 @@ class SpecialStatistics extends SpecialPage {
        }
 
        private function getGroupStats() {
+               $linkRenderer = $this->getLinkRenderer();
                $text = '';
                foreach ( $this->getConfig()->get( 'GroupPermissions' ) as $group => $permissions ) {
                        # Skip generic * and implicit groups
@@ -200,17 +203,17 @@ class SpecialStatistics extends SpecialPage {
                        $linkTarget = Title::newFromText( $grouppageLocalized );
 
                        if ( $linkTarget ) {
-                               $grouppage = Linker::link(
+                               $grouppage = $linkRenderer->makeLink(
                                        $linkTarget,
-                                       htmlspecialchars( $groupnameLocalized )
+                                       $groupnameLocalized
                                );
                        } else {
                                $grouppage = htmlspecialchars( $groupnameLocalized );
                        }
 
-                       $grouplink = Linker::linkKnown(
+                       $grouplink = $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( 'Listusers' ),
-                               $this->msg( 'listgrouprights-members' )->escaped(),
+                               $this->msg( 'listgrouprights-members' )->text(),
                                [],
                                [ 'group' => $group ]
                        );
index 3b502f8..8ff0527 100644 (file)
@@ -87,21 +87,29 @@ class SpecialTrackingCategories extends SpecialPage {
                }
                $batch->execute();
 
+               Hooks::run( 'SpecialTrackingCategories::preprocess', [ $this, $trackingCategories ] );
+
+               $linkRenderer = $this->getLinkRenderer();
+
                foreach ( $trackingCategories as $catMsg => $data ) {
                        $allMsgs = [];
                        $catDesc = $catMsg . '-desc';
 
-                       $catMsgTitleText = Linker::link(
+                       $catMsgTitleText = $linkRenderer->makeLink(
                                $data['msg'],
-                               htmlspecialchars( $catMsg )
+                               $catMsg
                        );
 
                        foreach ( $data['cats'] as $catTitle ) {
-                               $catTitleText = Linker::link(
+                               $html = $linkRenderer->makeLink(
                                        $catTitle,
-                                       htmlspecialchars( $catTitle->getText() )
+                                       $catTitle->getText()
                                );
-                               $allMsgs[] = $catTitleText;
+
+                               Hooks::run( 'SpecialTrackingCategories::generateCatLink',
+                                       [ $this, $catTitle, &$html ] );
+
+                               $allMsgs[] = $html;
                        }
 
                        # Extra message, when no category was found
index cff8bf4..4e683f6 100644 (file)
@@ -119,14 +119,14 @@ class SpecialUnblock extends SpecialPage {
                                $fields['Target']['type'] = 'hidden';
                                switch ( $type ) {
                                        case Block::TYPE_IP:
-                                               $fields['Name']['default'] = Linker::linkKnown(
+                                               $fields['Name']['default'] = $this->getLinkRenderer()->makeKnownLink(
                                                        SpecialPage::getTitleFor( 'Contributions', $target->getName() ),
                                                        $target->getName()
                                                );
                                                $fields['Name']['raw'] = true;
                                                break;
                                        case Block::TYPE_USER:
-                                               $fields['Name']['default'] = Linker::link(
+                                               $fields['Name']['default'] = $this->getLinkRenderer()->makeLink(
                                                        $target->getUserPage(),
                                                        $target->getName()
                                                );
@@ -175,7 +175,7 @@ class SpecialUnblock extends SpecialPage {
         * @param array $data
         * @param IContextSource $context
         * @throws ErrorPageError
-        * @return array|bool Array(message key, parameters) on failure, True on success
+        * @return array|bool Array( Array( message key, parameters ) ) on failure, True on success
         */
        public static function processUnblock( array $data, IContextSource $context ) {
                $performer = $context->getUser();
@@ -211,7 +211,7 @@ class SpecialUnblock extends SpecialPage {
 
                # Delete block
                if ( !$block->delete() ) {
-                       return [ 'ipb_cant_unblock', htmlspecialchars( $block->getTarget() ) ];
+                       return [ [ 'ipb_cant_unblock', htmlspecialchars( $block->getTarget() ) ] ];
                }
 
                # Unset _deleted fields as needed
index 91753a9..04f5be4 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  * @ingroup SpecialPage
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * Used to show archived pages and eventually restore them.
@@ -46,7 +47,7 @@ class PageArchive {
                $this->title = $title;
                if ( $config === null ) {
                        wfDebug( __METHOD__ . ' did not have a Config object passed to it' );
-                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $config = MediaWikiServices::getInstance()->getMainConfig();
                }
                $this->config = $config;
        }
@@ -996,14 +997,15 @@ class SpecialUndelete extends SpecialPage {
 
                $out->addWikiMsg( 'undeletepagetext', $this->getLanguage()->formatNum( $result->numRows() ) );
 
+               $linkRenderer = $this->getLinkRenderer();
                $undelete = $this->getPageTitle();
                $out->addHTML( "<ul>\n" );
                foreach ( $result as $row ) {
                        $title = Title::makeTitleSafe( $row->ar_namespace, $row->ar_title );
                        if ( $title !== null ) {
-                               $item = Linker::linkKnown(
+                               $item = $linkRenderer->makeKnownLink(
                                        $undelete,
-                                       htmlspecialchars( $title->getPrefixedText() ),
+                                       $title->getPrefixedText(),
                                        [],
                                        [ 'target' => $title->getPrefixedText() ]
                                );
@@ -1082,9 +1084,9 @@ class SpecialUndelete extends SpecialPage {
                        }
                }
 
-               $link = Linker::linkKnown(
+               $link = $this->getLinkRenderer()->makeKnownLink(
                        $this->getPageTitle( $this->mTargetObj->getPrefixedDBkey() ),
-                       htmlspecialchars( $this->mTargetObj->getPrefixedText() )
+                       $this->mTargetObj->getPrefixedText()
                );
 
                $lang = $this->getLanguage();
@@ -1258,14 +1260,14 @@ class SpecialUndelete extends SpecialPage {
                // FIXME This is reimplementing DifferenceEngine#getRevisionHeader
                // and partially #showDiffPage, but worse
                return '<div id="mw-diff-' . $prefix . 'title1"><strong>' .
-                       Linker::link(
+                       $this->getLinkRenderer()->makeLink(
                                $targetPage,
                                $this->msg(
                                        'revisionasof',
                                        $lang->userTimeAndDate( $rev->getTimestamp(), $user ),
                                        $lang->userDate( $rev->getTimestamp(), $user ),
                                        $lang->userTime( $rev->getTimestamp(), $user )
-                               )->escaped(),
+                               )->text(),
                                [],
                                $targetQuery
                        ) .
@@ -1549,9 +1551,9 @@ class SpecialUndelete extends SpecialPage {
                                $last = $this->msg( 'diff' )->escaped();
                        } elseif ( $remaining > 0 || ( $earliestLiveTime && $ts > $earliestLiveTime ) ) {
                                $pageLink = $this->getPageLink( $rev, $titleObj, $ts );
-                               $last = Linker::linkKnown(
+                               $last = $this->getLinkRenderer()->makeKnownLink(
                                        $titleObj,
-                                       $this->msg( 'diff' )->escaped(),
+                                       $this->msg( 'diff' )->text(),
                                        [],
                                        [
                                                'target' => $this->mTargetObj->getPrefixedText(),
@@ -1671,9 +1673,9 @@ class SpecialUndelete extends SpecialPage {
                        return '<span class="history-deleted">' . $time . '</span>';
                }
 
-               $link = Linker::linkKnown(
+               $link = $this->getLinkRenderer()->makeKnownLink(
                        $titleObj,
-                       htmlspecialchars( $time ),
+                       $time,
                        [],
                        [
                                'target' => $this->mTargetObj->getPrefixedText(),
@@ -1706,9 +1708,9 @@ class SpecialUndelete extends SpecialPage {
                        return '<span class="history-deleted">' . $time . '</span>';
                }
 
-               $link = Linker::linkKnown(
+               $link = $this->getLinkRenderer()->makeKnownLink(
                        $titleObj,
-                       htmlspecialchars( $time ),
+                       $time,
                        [],
                        [
                                'target' => $this->mTargetObj->getPrefixedText(),
@@ -1795,7 +1797,7 @@ class SpecialUndelete extends SpecialPage {
                                        $this->getUser(), $this->mComment ] );
                        }
 
-                       $link = Linker::linkKnown( $this->mTargetObj );
+                       $link = $this->getLinkRenderer()->makeKnownLink( $this->mTargetObj );
                        $out->addHTML( $this->msg( 'undeletedpage' )->rawParams( $link )->parse() );
                } else {
                        $out->setPageTitle( $this->msg( 'undelete-error' ) );
index 88c0e21..ec39ccf 100644 (file)
@@ -70,7 +70,7 @@ class UnusedCategoriesPage extends QueryPage {
        function formatResult( $skin, $result ) {
                $title = Title::makeTitle( NS_CATEGORY, $result->title );
 
-               return Linker::link( $title, htmlspecialchars( $title->getText() ) );
+               return $this->getLinkRenderer()->makeLink( $title, $title->getText() );
        }
 
        protected function getGroupName() {
index 4583305..f7e46cb 100644 (file)
@@ -588,7 +588,7 @@ class SpecialUpload extends SpecialPage {
        ) {
                if ( $config === null ) {
                        wfDebug( __METHOD__ . ' called without a Config instance passed to it' );
-                       $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $config = MediaWikiServices::getInstance()->getMainConfig();
                }
 
                $msg = [];
index 433dcab..3ba46c1 100644 (file)
@@ -48,14 +48,6 @@ class UserrightsPage extends SpecialPage {
                return true;
        }
 
-       public function isRestricted() {
-               return true;
-       }
-
-       public function userCanExecute( User $user ) {
-               return $this->userCanChangeRights( $user, false );
-       }
-
        /**
         * @param User $user
         * @param bool $checkIfSelf
@@ -82,22 +74,10 @@ class UserrightsPage extends SpecialPage {
         * @throws UserBlockedError|PermissionsError
         */
        public function execute( $par ) {
-               // If the visitor doesn't have permissions to assign or remove
-               // any groups, it's a bit silly to give them the user search prompt.
-
                $user = $this->getUser();
                $request = $this->getRequest();
                $out = $this->getOutput();
 
-               /*
-                * If the user is blocked and they only have "partial" access
-                * (e.g. they don't have the userrights permission), then don't
-                * allow them to use Special:UserRights.
-                */
-               if ( $user->isBlocked() && !$user->isAllowed( 'userrights' ) ) {
-                       throw new UserBlockedError( $user->getBlock() );
-               }
-
                if ( $par !== null ) {
                        $this->mTarget = $par;
                } else {
@@ -108,24 +88,7 @@ class UserrightsPage extends SpecialPage {
                        $this->mTarget = trim( $this->mTarget );
                }
 
-               $available = $this->changeableGroups();
-
-               if ( $this->mTarget === null ) {
-                       /*
-                        * If the user specified no target, and they can only
-                        * edit their own groups, automatically set them as the
-                        * target.
-                        */
-                       if ( !count( $available['add'] ) && !count( $available['remove'] ) ) {
-                               $this->mTarget = $user->getName();
-                       }
-               }
-
-               if ( $this->mTarget !== null && User::getCanonicalName( $this->mTarget ) === $user->getName() ) {
-                       $this->isself = true;
-               }
-
-               $fetchedStatus = $this->fetchUser( $this->mTarget );
+               $fetchedStatus = $this->fetchUser( $this->mTarget, true );
                if ( $fetchedStatus->isOK() ) {
                        $this->mFetchedUser = $fetchedStatus->value;
                        if ( $this->mFetchedUser instanceof User ) {
@@ -135,23 +98,6 @@ class UserrightsPage extends SpecialPage {
                        }
                }
 
-               if ( !$this->userCanChangeRights( $user, true ) ) {
-                       if ( $this->isself && $request->getCheck( 'success' ) ) {
-                               // bug 48609: if the user just removed its own rights, this would
-                               // leads it in a "permissions error" page. In that case, show a
-                               // message that it can't anymore use this page instead of an error
-                               $this->setHeaders();
-                               $out->wrapWikiMsg( "<div class=\"successbox\">\n$1\n</div>", 'userrights-removed-self' );
-                               $out->returnToMain();
-
-                               return;
-                       }
-
-                       // @todo FIXME: There may be intermediate groups we can mention.
-                       $msg = $user->isAnon() ? 'userrights-nologin' : 'userrights-notallowed';
-                       throw new PermissionsError( null, [ [ $msg ] ] );
-               }
-
                // show a successbox, if the user rights was saved successfully
                if ( $request->getCheck( 'success' ) && $this->mFetchedUser !== null ) {
                        $out->addModules( [ 'mediawiki.special.userrights' ] );
@@ -173,18 +119,13 @@ class UserrightsPage extends SpecialPage {
                        );
                }
 
-               $this->checkReadOnly();
-
                $this->setHeaders();
                $this->outputHeader();
 
                $out->addModuleStyles( 'mediawiki.special' );
                $this->addHelpLink( 'Help:Assigning permissions' );
 
-               // show the general form
-               if ( count( $available['add'] ) || count( $available['remove'] ) ) {
-                       $this->switchForm();
-               }
+               $this->switchForm();
 
                if (
                        $request->wasPosted() &&
@@ -192,6 +133,17 @@ class UserrightsPage extends SpecialPage {
                        $this->mTarget !== null &&
                        $user->matchEditToken( $request->getVal( 'wpEditToken' ), $this->mTarget )
                ) {
+                       /*
+                       * If the user is blocked and they only have "partial" access
+                       * (e.g. they don't have the userrights permission), then don't
+                       * allow them to change any user rights.
+                       */
+                       if ( $user->isBlocked() && !$user->isAllowed( 'userrights' ) ) {
+                               throw new UserBlockedError( $user->getBlock() );
+                       }
+
+                       $this->checkReadOnly();
+
                        // save settings
                        if ( !$fetchedStatus->isOK() ) {
                                $this->getOutput()->addWikiText( $fetchedStatus->getWikiText() );
@@ -352,7 +304,7 @@ class UserrightsPage extends SpecialPage {
         * @param string $username Name of the user.
         */
        function editUserGroupsForm( $username ) {
-               $status = $this->fetchUser( $username );
+               $status = $this->fetchUser( $username, true );
                if ( !$status->isOK() ) {
                        $this->getOutput()->addWikiText( $status->getWikiText() );
 
@@ -376,9 +328,10 @@ class UserrightsPage extends SpecialPage {
         *
         * Side effects: error output for invalid access
         * @param string $username
+        * @param bool $writing
         * @return Status
         */
-       public function fetchUser( $username ) {
+       public function fetchUser( $username, $writing = true ) {
                $parts = explode( $this->getConfig()->get( 'UserrightsInterwikiDelimiter' ), $username );
                if ( count( $parts ) < 2 ) {
                        $name = trim( $username );
@@ -389,7 +342,7 @@ class UserrightsPage extends SpecialPage {
                        if ( $database == wfWikiID() ) {
                                $database = '';
                        } else {
-                               if ( !$this->getUser()->isAllowed( 'userrights-interwiki' ) ) {
+                               if ( $writing && !$this->getUser()->isAllowed( 'userrights-interwiki' ) ) {
                                        return Status::newFatal( 'userrights-no-interwiki' );
                                }
                                if ( !UserRightsProxy::validDatabase( $database ) ) {
@@ -484,10 +437,7 @@ class UserrightsPage extends SpecialPage {
                                )
                        ) . ' ' .
                        Xml::submitButton(
-                               $this->msg(
-                                       'editusergroup',
-                                       $this->mFetchedUser === null ? '[]' : $this->mFetchedUser->getName()
-                               )->text()
+                               $this->msg( 'editusergroup' )->text()
                        ) .
                        Html::closeElement( 'fieldset' ) .
                        Html::closeElement( 'form' ) . "\n"
@@ -578,6 +528,7 @@ class UserrightsPage extends SpecialPage {
                        Linker::TOOL_LINKS_EMAIL /* Add "send e-mail" link */
                );
 
+               list( $groupCheckboxes, $canChangeAny ) = $this->groupCheckboxes( $groups, $user );
                $this->getOutput()->addHTML(
                        Xml::openElement(
                                'form',
@@ -598,33 +549,46 @@ class UserrightsPage extends SpecialPage {
                        Xml::element(
                                'legend',
                                [],
-                               $this->msg( 'userrights-editusergroup', $user->getName() )->text()
+                               $this->msg(
+                                       $canChangeAny ? 'userrights-editusergroup' : 'userrights-viewusergroup',
+                                       $user->getName()
+                               )->text()
                        ) .
-                       $this->msg( 'editinguser' )->params( wfEscapeWikiText( $user->getName() ) )
-                               ->rawParams( $userToolLinks )->parse() .
-                       $this->msg( 'userrights-groups-help', $user->getName() )->parse() .
-                       $grouplist .
-                       $this->groupCheckboxes( $groups, $user ) .
-                       Xml::openElement( 'table', [ 'id' => 'mw-userrights-table-outer' ] ) .
-                               "<tr>
-                                       <td class='mw-label'>" .
-                                               Xml::label( $this->msg( 'userrights-reason' )->text(), 'wpReason' ) .
-                                       "</td>
-                                       <td class='mw-input'>" .
-                                               Xml::input( 'user-reason', 60, $this->getRequest()->getVal( 'user-reason', false ),
-                                                       [ 'id' => 'wpReason', 'maxlength' => 255 ] ) .
-                                       "</td>
-                               </tr>
-                               <tr>
-                                       <td></td>
-                                       <td class='mw-submit'>" .
-                                               Xml::submitButton( $this->msg( 'saveusergroups', $user->getName() )->text(),
-                                                       [ 'name' => 'saveusergroups' ] +
-                                                               Linker::tooltipAndAccesskeyAttribs( 'userrights-set' )
-                                               ) .
-                                       "</td>
-                               </tr>" .
-                       Xml::closeElement( 'table' ) . "\n" .
+                       $this->msg(
+                               $canChangeAny ? 'editinguser' : 'viewinguserrights'
+                       )->params( wfEscapeWikiText( $user->getName() ) )
+                               ->rawParams( $userToolLinks )->parse()
+               );
+               if ( $canChangeAny ) {
+                       $this->getOutput()->addHTML(
+                               $this->msg( 'userrights-groups-help', $user->getName() )->parse() .
+                               $grouplist .
+                               $groupCheckboxes .
+                               Xml::openElement( 'table', [ 'id' => 'mw-userrights-table-outer' ] ) .
+                                       "<tr>
+                                               <td class='mw-label'>" .
+                                                       Xml::label( $this->msg( 'userrights-reason' )->text(), 'wpReason' ) .
+                                               "</td>
+                                               <td class='mw-input'>" .
+                                                       Xml::input( 'user-reason', 60, $this->getRequest()->getVal( 'user-reason', false ),
+                                                               [ 'id' => 'wpReason', 'maxlength' => 255 ] ) .
+                                               "</td>
+                                       </tr>
+                                       <tr>
+                                               <td></td>
+                                               <td class='mw-submit'>" .
+                                                       Xml::submitButton( $this->msg( 'saveusergroups', $user->getName() )->text(),
+                                                               [ 'name' => 'saveusergroups' ] +
+                                                                       Linker::tooltipAndAccesskeyAttribs( 'userrights-set' )
+                                                       ) .
+                                               "</td>
+                                       </tr>" .
+                               Xml::closeElement( 'table' ) . "\n"
+                       );
+               } else {
+                       $this->getOutput()->addHTML( $grouplist );
+               }
+               $this->getOutput()->addHTML(
                        Xml::closeElement( 'fieldset' ) .
                        Xml::closeElement( 'form' ) . "\n"
                );
@@ -664,7 +628,8 @@ class UserrightsPage extends SpecialPage {
         * @todo Just pass the username string?
         * @param array $usergroups Groups the user belongs to
         * @param User $user
-        * @return string XHTML table element with checkboxes
+        * @return Array with 2 elements: the XHTML table element with checkxboes, and
+        * whether any groups are changeable
         */
        private function groupCheckboxes( $usergroups, $user ) {
                $allgroups = $this->getAllGroups();
@@ -739,7 +704,7 @@ class UserrightsPage extends SpecialPage {
                }
                $ret .= Xml::closeElement( 'tr' ) . Xml::closeElement( 'table' );
 
-               return $ret;
+               return [ $ret, (bool)$columns['changeable'] ];
        }
 
        /**
@@ -747,7 +712,6 @@ class UserrightsPage extends SpecialPage {
         * @return bool Can we remove the group?
         */
        private function canRemove( $group ) {
-               // $this->changeableGroups()['remove'] doesn't work, of course. Thanks, PHP.
                $groups = $this->changeableGroups();
 
                return in_array(
@@ -817,3 +781,4 @@ class UserrightsPage extends SpecialPage {
                return 'users';
        }
 }
+
index 2cd492e..272f074 100644 (file)
@@ -785,12 +785,12 @@ class SpecialVersion extends SpecialPage {
                if ( isset( $extension['name'] ) ) {
                        $licenseName = null;
                        if ( isset( $extension['license-name'] ) ) {
-                               $licenseName = $out->parseInline( $extension['license-name'] );
+                               $licenseName = new HtmlArmor( $out->parseInline( $extension['license-name'] ) );
                        } elseif ( $this->getExtLicenseFileName( $extensionPath ) ) {
-                               $licenseName = $this->msg( 'version-ext-license' )->escaped();
+                               $licenseName = $this->msg( 'version-ext-license' )->text();
                        }
                        if ( $licenseName !== null ) {
-                               $licenseLink = Linker::link(
+                               $licenseLink = $this->getLinkRenderer()->makeLink(
                                        $this->getPageTitle( 'License/' . $extension['name'] ),
                                        $licenseName,
                                        [
@@ -956,6 +956,7 @@ class SpecialVersion extends SpecialPage {
         */
        public function listAuthors( $authors, $extName, $extDir ) {
                $hasOthers = false;
+               $linkRenderer = $this->getLinkRenderer();
 
                $list = [];
                foreach ( (array)$authors as $item ) {
@@ -963,9 +964,9 @@ class SpecialVersion extends SpecialPage {
                                $hasOthers = true;
 
                                if ( $extName && $this->getExtAuthorsFileName( $extDir ) ) {
-                                       $text = Linker::link(
+                                       $text = $linkRenderer->makeLink(
                                                $this->getPageTitle( "Credits/$extName" ),
-                                               $this->msg( 'version-poweredby-others' )->escaped()
+                                               $this->msg( 'version-poweredby-others' )->text()
                                        );
                                } else {
                                        $text = $this->msg( 'version-poweredby-others' )->escaped();
@@ -982,9 +983,9 @@ class SpecialVersion extends SpecialPage {
                }
 
                if ( $extName && !$hasOthers && $this->getExtAuthorsFileName( $extDir ) ) {
-                       $list[] = $text = Linker::link(
+                       $list[] = $text = $linkRenderer->makeLink(
                                $this->getPageTitle( "Credits/$extName" ),
-                               $this->msg( 'version-poweredby-others' )->escaped()
+                               $this->msg( 'version-poweredby-others' )->text()
                        );
                }
 
index 9bf44ad..fc0c312 100644 (file)
@@ -91,20 +91,17 @@ class WantedCategoriesPage extends WantedQueryPage {
                global $wgContLang;
 
                $nt = Title::makeTitle( $result->namespace, $result->title );
-               $text = htmlspecialchars( $wgContLang->convert( $nt->getText() ) );
+               $text = $wgContLang->convert( $nt->getText() );
 
                if ( !$this->isCached() ) {
                        // We can assume the freshest data
-                       $plink = Linker::link(
+                       $plink = $this->getLinkRenderer()->makeBrokenLink(
                                $nt,
-                               $text,
-                               [],
-                               [],
-                               [ 'broken' ]
+                               $text
                        );
                        $nlinks = $this->msg( 'nmembers' )->numParams( $result->value )->escaped();
                } else {
-                       $plink = Linker::link( $nt, $text );
+                       $plink = $this->getLinkRenderer()->makeLink( $nt, $text );
 
                        $currentValue = isset( $this->currentCategoryCounts[$result->title] )
                                ? $this->currentCategoryCounts[$result->title]
index 4824961..55400d3 100644 (file)
@@ -130,7 +130,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
        }
 
        /**
-        * Get custom show/hide filters
+        * Get all custom filters
         *
         * @return array Map of filter URL param names to properties (msg/default)
         */
@@ -465,9 +465,10 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        $filters['hidecategorization'] = 'wlshowhidecategorization';
                }
 
-               foreach ( $this->getCustomFilters() as $key => $params ) {
+               foreach ( $this->getRenderableCustomFilters( $this->getCustomFilters() ) as $key => $params ) {
                        $filters[$key] = $params['msg'];
                }
+
                // Disable some if needed
                if ( !$user->useRCPatrol() ) {
                        unset( $filters['hidepatrolled'] );
index ea906b7..645a115 100644 (file)
@@ -64,6 +64,14 @@ class ActiveUsersPager extends UsersPager {
                }
 
                $this->groups = $opts->getValue( 'groups' );
+               $this->excludegroups = $opts->getValue( 'excludegroups' );
+               // Backwards-compatibility with old URLs
+               if ( $opts->getValue( 'hidebots' ) ) {
+                       $this->excludegroups[] = 'bot';
+               }
+               if ( $opts->getValue( 'hidesysops' ) ) {
+                       $this->excludegroups[] = 'sysop';
+               }
        }
 
        function getIndexField() {
@@ -94,6 +102,13 @@ class ActiveUsersPager extends UsersPager {
                        $conds[] = 'ug_user = user_id';
                        $conds['ug_group'] = $this->groups;
                }
+               if ( $this->excludegroups !== [] ) {
+                       foreach ( $this->excludegroups as $group ) {
+                               $conds[] = 'NOT EXISTS (' . $dbr->selectSQLText(
+                                               'user_groups', '1', [ 'ug_user = user_id', 'ug_group' => $group ]
+                                       ) . ')';
+                       }
+               }
                if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
                        $conds[] = 'NOT EXISTS (' . $dbr->selectSQLText(
                                        'ipblocks', '1', [ 'ipb_user=user_id', 'ipb_deleted' => 1 ]
index 5609310..efc51ef 100644 (file)
@@ -25,6 +25,8 @@
  *
  * @ingroup Pager
  */
+use MediaWiki\MediaWikiServices;
+
 class AllMessagesTablePager extends TablePager {
 
        protected $filter, $prefix, $langcode, $displayPrefix;
@@ -297,6 +299,7 @@ class AllMessagesTablePager extends TablePager {
        }
 
        function formatValue( $field, $value ) {
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                switch ( $field ) {
                        case 'am_title' :
                                $title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix );
@@ -313,25 +316,19 @@ class AllMessagesTablePager extends TablePager {
                                );
 
                                if ( $this->mCurrentRow->am_customised ) {
-                                       $title = Linker::linkKnown( $title, $this->getLanguage()->lcfirst( $value ) );
+                                       $title = $linkRenderer->makeKnownLink( $title, $this->getLanguage()->lcfirst( $value ) );
                                } else {
-                                       $title = Linker::link(
+                                       $title = $linkRenderer->makeBrokenLink(
                                                $title,
-                                               $this->getLanguage()->lcfirst( $value ),
-                                               [],
-                                               [],
-                                               [ 'broken' ]
+                                               $this->getLanguage()->lcfirst( $value )
                                        );
                                }
                                if ( $this->mCurrentRow->am_talk_exists ) {
-                                       $talk = Linker::linkKnown( $talk, $this->talk );
+                                       $talk = $linkRenderer->makeKnownLink( $talk, $this->talk );
                                } else {
-                                       $talk = Linker::link(
+                                       $talk = $linkRenderer->makeBrokenLink(
                                                $talk,
-                                               $this->talk,
-                                               [],
-                                               [],
-                                               [ 'broken' ]
+                                               $this->talk
                                        );
                                }
 
index d822976..a4124db 100644 (file)
@@ -22,6 +22,8 @@
 /**
  * @ingroup Pager
  */
+use MediaWiki\MediaWikiServices;
+
 class BlockListPager extends TablePager {
 
        protected $conds;
@@ -72,7 +74,7 @@ class BlockListPager extends TablePager {
                        ];
 
                        foreach ( $keys as $key ) {
-                               $msg[$key] = $this->msg( $key )->escaped();
+                               $msg[$key] = $this->msg( $key )->text();
                        }
                }
 
@@ -83,6 +85,8 @@ class BlockListPager extends TablePager {
 
                $formatted = '';
 
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+
                switch ( $name ) {
                        case 'ipb_timestamp':
                                $formatted = htmlspecialchars( $language->userTimeAndDate( $value, $this->getUser() ) );
@@ -117,18 +121,18 @@ class BlockListPager extends TablePager {
                                ) );
                                if ( $this->getUser()->isAllowed( 'block' ) ) {
                                        if ( $row->ipb_auto ) {
-                                               $links[] = Linker::linkKnown(
+                                               $links[] = $linkRenderer->makeKnownLink(
                                                        SpecialPage::getTitleFor( 'Unblock' ),
                                                        $msg['unblocklink'],
                                                        [],
                                                        [ 'wpTarget' => "#{$row->ipb_id}" ]
                                                );
                                        } else {
-                                               $links[] = Linker::linkKnown(
+                                               $links[] = $linkRenderer->makeKnownLink(
                                                        SpecialPage::getTitleFor( 'Unblock', $row->ipb_address ),
                                                        $msg['unblocklink']
                                                );
-                                               $links[] = Linker::linkKnown(
+                                               $links[] = $linkRenderer->makeKnownLink(
                                                        SpecialPage::getTitleFor( 'Block', $row->ipb_address ),
                                                        $msg['change-blocklink']
                                                );
@@ -174,21 +178,21 @@ class BlockListPager extends TablePager {
                        case 'ipb_params':
                                $properties = [];
                                if ( $row->ipb_anon_only ) {
-                                       $properties[] = $msg['anononlyblock'];
+                                       $properties[] = htmlspecialchars( $msg['anononlyblock'] );
                                }
                                if ( $row->ipb_create_account ) {
-                                       $properties[] = $msg['createaccountblock'];
+                                       $properties[] = htmlspecialchars( $msg['createaccountblock'] );
                                }
                                if ( $row->ipb_user && !$row->ipb_enable_autoblock ) {
-                                       $properties[] = $msg['noautoblockblock'];
+                                       $properties[] = htmlspecialchars( $msg['noautoblockblock'] );
                                }
 
                                if ( $row->ipb_block_email ) {
-                                       $properties[] = $msg['emailblock'];
+                                       $properties[] = htmlspecialchars( $msg['emailblock'] );
                                }
 
                                if ( !$row->ipb_allow_usertalk ) {
-                                       $properties[] = $msg['blocklist-nousertalk'];
+                                       $properties[] = htmlspecialchars( $msg['blocklist-nousertalk'] );
                                }
 
                                $formatted = $language->commaList( $properties );
index b78fed8..345577d 100644 (file)
@@ -52,7 +52,6 @@ class CategoryPager extends AlphabeticPager {
                return [
                        'tables' => [ 'category' ],
                        'fields' => [ 'cat_title', 'cat_pages' ],
-                       'conds' => [ 'cat_pages > 0' ],
                        'options' => [ 'USE INDEX' => 'cat_title' ],
                ];
        }
index a145e45..39c55c8 100644 (file)
@@ -23,6 +23,8 @@
  * Pager for Special:Contributions
  * @ingroup Pager
  */
+use MediaWiki\MediaWikiServices;
+
 class ContribsPager extends ReverseChronologicalPager {
 
        public $mDefaultDirection = IndexPager::DIR_DESCENDING;
@@ -347,6 +349,8 @@ class ContribsPager extends ReverseChronologicalPager {
                $ret = '';
                $classes = [];
 
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+
                /*
                 * There may be more than just revision rows. To make sure that we'll only be processing
                 * revisions here, let's _try_ to build a revision out of our row (without displaying
@@ -367,9 +371,9 @@ class ContribsPager extends ReverseChronologicalPager {
                        $classes = [];
 
                        $page = Title::newFromRow( $row );
-                       $link = Linker::link(
+                       $link = $linkRenderer->makeLink(
                                $page,
-                               htmlspecialchars( $page->getPrefixedText() ),
+                               $page->getPrefixedText(),
                                [ 'class' => 'mw-contributions-title' ],
                                $page->isRedirect() ? [ 'redirect' => 'no' ] : []
                        );
@@ -389,9 +393,9 @@ class ContribsPager extends ReverseChronologicalPager {
                        }
                        # Is there a visible previous revision?
                        if ( $rev->userCan( Revision::DELETED_TEXT, $user ) && $rev->getParentId() !== 0 ) {
-                               $difftext = Linker::linkKnown(
+                               $difftext = $linkRenderer->makeKnownLink(
                                        $page,
-                                       $this->messages['diff'],
+                                       new HtmlArmor( $this->messages['diff'] ),
                                        [],
                                        [
                                                'diff' => 'prev',
@@ -401,9 +405,9 @@ class ContribsPager extends ReverseChronologicalPager {
                        } else {
                                $difftext = $this->messages['diff'];
                        }
-                       $histlink = Linker::linkKnown(
+                       $histlink = $linkRenderer->makeKnownLink(
                                $page,
-                               $this->messages['hist'],
+                               new HtmlArmor( $this->messages['hist'] ),
                                [],
                                [ 'action' => 'history' ]
                        );
@@ -434,9 +438,9 @@ class ContribsPager extends ReverseChronologicalPager {
                        $comment = $lang->getDirMark() . Linker::revComment( $rev, false, true );
                        $date = $lang->userTimeAndDate( $row->rev_timestamp, $user );
                        if ( $rev->userCan( Revision::DELETED_TEXT, $user ) ) {
-                               $d = Linker::linkKnown(
+                               $d = $linkRenderer->makeKnownLink(
                                        $page,
-                                       htmlspecialchars( $date ),
+                                       $date,
                                        [ 'class' => 'mw-changeslist-date' ],
                                        [ 'oldid' => intval( $row->rev_id ) ]
                                );
index 1acbba1..9ffcce9 100644 (file)
@@ -22,6 +22,8 @@
 /**
  * @ingroup Pager
  */
+use MediaWiki\MediaWikiServices;
+
 class DeletedContribsPager extends IndexPager {
 
        public $mDefaultDirection = IndexPager::DIR_DESCENDING;
@@ -39,7 +41,7 @@ class DeletedContribsPager extends IndexPager {
                parent::__construct( $context );
                $msgs = [ 'deletionlog', 'undeleteviewlink', 'diff' ];
                foreach ( $msgs as $msg ) {
-                       $this->messages[$msg] = $this->msg( $msg )->escaped();
+                       $this->messages[$msg] = $this->msg( $msg )->text();
                }
                $this->target = $target;
                $this->namespace = $namespace;
@@ -240,6 +242,8 @@ class DeletedContribsPager extends IndexPager {
        function formatRevisionRow( $row ) {
                $page = Title::makeTitle( $row->ar_namespace, $row->ar_title );
 
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+
                $rev = new Revision( [
                        'title' => $page,
                        'id' => $row->ar_rev_id,
@@ -254,7 +258,7 @@ class DeletedContribsPager extends IndexPager {
                $undelete = SpecialPage::getTitleFor( 'Undelete' );
 
                $logs = SpecialPage::getTitleFor( 'Log' );
-               $dellog = Linker::linkKnown(
+               $dellog = $linkRenderer->makeKnownLink(
                        $logs,
                        $this->messages['deletionlog'],
                        [],
@@ -264,7 +268,7 @@ class DeletedContribsPager extends IndexPager {
                        ]
                );
 
-               $reviewlink = Linker::linkKnown(
+               $reviewlink = $linkRenderer->makeKnownLink(
                        SpecialPage::getTitleFor( 'Undelete', $page->getPrefixedDBkey() ),
                        $this->messages['undeleteviewlink']
                );
@@ -272,7 +276,7 @@ class DeletedContribsPager extends IndexPager {
                $user = $this->getUser();
 
                if ( $user->isAllowed( 'deletedtext' ) ) {
-                       $last = Linker::linkKnown(
+                       $last = $linkRenderer->makeKnownLink(
                                $undelete,
                                $this->messages['diff'],
                                [],
@@ -283,17 +287,16 @@ class DeletedContribsPager extends IndexPager {
                                ]
                        );
                } else {
-                       $last = $this->messages['diff'];
+                       $last = htmlspecialchars( $this->messages['diff'] );
                }
 
                $comment = Linker::revComment( $rev );
                $date = $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $user );
-               $date = htmlspecialchars( $date );
 
                if ( !$user->isAllowed( 'undelete' ) || !$rev->userCan( Revision::DELETED_TEXT, $user ) ) {
-                       $link = $date; // unusable link
+                       $link = htmlspecialchars( $date ); // unusable link
                } else {
-                       $link = Linker::linkKnown(
+                       $link = $linkRenderer->makeKnownLink(
                                $undelete,
                                $date,
                                [ 'class' => 'mw-changeslist-date' ],
@@ -308,7 +311,7 @@ class DeletedContribsPager extends IndexPager {
                        $link = '<span class="history-deleted">' . $link . '</span>';
                }
 
-               $pagelink = Linker::link(
+               $pagelink = $linkRenderer->makeLink(
                        $page,
                        null,
                        [ 'class' => 'mw-changeslist-title' ]
index 7fc4a95..59dea02 100644 (file)
@@ -22,6 +22,8 @@
 /**
  * @ingroup Pager
  */
+use MediaWiki\MediaWikiServices;
+
 class ImageListPager extends TablePager {
 
        protected $mFieldNames = null;
@@ -422,6 +424,7 @@ class ImageListPager extends TablePager {
         * @throws MWException
         */
        function formatValue( $field, $value ) {
+               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                switch ( $field ) {
                        case 'thumb':
                                $opt = [ 'time' => wfTimestamp( TS_MW, $this->mCurrentRow->img_timestamp ) ];
@@ -449,9 +452,9 @@ class ImageListPager extends TablePager {
                                // Weird files can maybe exist? Bug 22227
                                $filePage = Title::makeTitleSafe( NS_FILE, $value );
                                if ( $filePage ) {
-                                       $link = Linker::linkKnown(
+                                       $link = $linkRenderer->makeKnownLink(
                                                $filePage,
-                                               htmlspecialchars( $filePage->getText() )
+                                               $filePage->getText()
                                        );
                                        $download = Xml::element( 'a',
                                                [ 'href' => wfLocalFile( $filePage )->getUrl() ],
@@ -462,9 +465,9 @@ class ImageListPager extends TablePager {
                                        // Add delete links if allowed
                                        // From https://github.com/Wikia/app/pull/3859
                                        if ( $filePage->userCan( 'delete', $this->getUser() ) ) {
-                                               $deleteMsg = $this->msg( 'listfiles-delete' )->escaped();
+                                               $deleteMsg = $this->msg( 'listfiles-delete' )->text();
 
-                                               $delete = Linker::linkKnown(
+                                               $delete = $linkRenderer->makeKnownLink(
                                                        $filePage, $deleteMsg, [], [ 'action' => 'delete' ]
                                                );
                                                $delete = $this->msg( 'parentheses' )->rawParams( $delete )->escaped();
@@ -479,9 +482,9 @@ class ImageListPager extends TablePager {
                        case 'img_user_text':
                                if ( $this->mCurrentRow->img_user ) {
                                        $name = User::whoIs( $this->mCurrentRow->img_user );
-                                       $link = Linker::link(
+                                       $link = $linkRenderer->makeLink(
                                                Title::makeTitle( NS_USER, $name ),
-                                               htmlspecialchars( $name )
+                                               $name
                                        );
                                } else {
                                        $link = htmlspecialchars( $value );
index 41819fc..9f6c58c 100644 (file)
@@ -22,6 +22,8 @@
 /**
  * @ingroup Pager
  */
+use MediaWiki\MediaWikiServices;
+
 class NewFilesPager extends ReverseChronologicalPager {
 
        /**
@@ -142,7 +144,10 @@ class NewFilesPager extends ReverseChronologicalPager {
                $user = User::newFromId( $row->img_user );
 
                $title = Title::makeTitle( NS_FILE, $name );
-               $ul = Linker::link( $user->getUserPage(), $user->getName() );
+               $ul = MediaWikiServices::getInstance()->getLinkRenderer()->makeLink(
+                       $user->getUserPage(),
+                       $user->getName()
+               );
                $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() );
 
                $this->gallery->add(
index b7160b3..48477f8 100644 (file)
@@ -432,7 +432,7 @@ class UploadStash {
                                . ' No user is logged in, files must belong to users' );
                }
 
-               $dbr = $this->repo->getSlaveDB();
+               $dbr = $this->repo->getReplicaDB();
                $res = $dbr->select(
                        'uploadstash',
                        'us_key',
@@ -511,7 +511,7 @@ class UploadStash {
                        // sometimes reading from the master is necessary, if there's replication lag.
                        $dbr = $this->repo->getMasterDB();
                } else {
-                       $dbr = $this->repo->getSlaveDB();
+                       $dbr = $this->repo->getReplicaDB();
                }
 
                $row = $dbr->selectRow(
index 889ec92..c1aef22 100644 (file)
@@ -22,6 +22,9 @@
 
 use MediaWiki\Auth\AuthManager;
 use MediaWiki\Auth\TemporaryPasswordAuthenticationRequest;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
+use MediaWiki\Logger\LoggerFactory;
 
 /**
  * Helper class for the password reset functionality shared by the web UI and the API.
@@ -30,16 +33,19 @@ use MediaWiki\Auth\TemporaryPasswordAuthenticationRequest;
  * EmailNotificationSecondaryAuthenticationProvider (or something providing equivalent
  * functionality) to be enabled.
  */
-class PasswordReset {
+class PasswordReset implements LoggerAwareInterface {
        /** @var Config */
        protected $config;
 
        /** @var AuthManager */
        protected $authManager;
 
+       /** @var LoggerInterface */
+       protected $logger;
+
        /**
-        * In-process cache for isAllowed lookups, by username. Contains pairs of StatusValue objects
-        * (for false and true value of $displayPassword, respectively).
+        * In-process cache for isAllowed lookups, by username.
+        * Contains a StatusValue object
         * @var HashBagOStuff
         */
        private $permissionCache;
@@ -48,6 +54,17 @@ class PasswordReset {
                $this->config = $config;
                $this->authManager = $authManager;
                $this->permissionCache = new HashBagOStuff( [ 'maxKeys' => 1 ] );
+               $this->logger = LoggerFactory::getInstance( 'authentication' );
+       }
+
+       /**
+        * Set the logger instance to use.
+        *
+        * @param LoggerInterface $logger
+        * @since 1.29
+        */
+       public function setLogger( LoggerInterface $logger ) {
+               $this->logger = $logger;
        }
 
        /**
@@ -55,13 +72,12 @@ class PasswordReset {
         * @param User $user
         * @param bool $displayPassword If set, also check whether the user is allowed to reset the
         *   password of another user and see the temporary password.
+        * @since 1.29 Second argument for displayPassword removed.
         * @return StatusValue
         */
-       public function isAllowed( User $user, $displayPassword = false ) {
-               $statuses = $this->permissionCache->get( $user->getName() );
-               if ( $statuses ) {
-                       list ( $status, $status2 ) = $statuses;
-               } else {
+       public function isAllowed( User $user ) {
+               $status = $this->permissionCache->get( $user->getName() );
+               if ( !$status ) {
                        $resetRoutes = $this->config->get( 'PasswordResetRoutes' );
                        $status = StatusValue::newGood();
 
@@ -90,19 +106,10 @@ class PasswordReset {
                                $status = StatusValue::newFatal( 'blocked-mailpassword' );
                        }
 
-                       $status2 = StatusValue::newGood();
-                       if ( !$user->isAllowed( 'passwordreset' ) ) {
-                               $status2 = StatusValue::newFatal( 'badaccess' );
-                       }
-
-                       $this->permissionCache->set( $user->getName(), [ $status, $status2 ] );
+                       $this->permissionCache->set( $user->getName(), $status );
                }
 
-               if ( !$displayPassword || !$status->isGood() ) {
-                       return $status;
-               } else {
-                       return $status2;
-               }
+               return $status;
        }
 
        /**
@@ -111,22 +118,22 @@ class PasswordReset {
         * Process the form.  At this point we know that the user passes all the criteria in
         * userCanExecute(), and if the data array contains 'Username', etc, then Username
         * resets are allowed.
+        *
+        * @since 1.29 Fourth argument for displayPassword removed.
         * @param User $performingUser The user that does the password reset
         * @param string $username The user whose password is reset
         * @param string $email Alternative way to specify the user
-        * @param bool $displayPassword Whether to display the password
         * @return StatusValue Will contain the passwords as a username => password array if the
         *   $displayPassword flag was set
         * @throws LogicException When the user is not allowed to perform the action
         * @throws MWException On unexpected DB errors
         */
        public function execute(
-               User $performingUser, $username = null, $email = null, $displayPassword = false
+               User $performingUser, $username = null, $email = null
        ) {
-               if ( !$this->isAllowed( $performingUser, $displayPassword )->isGood() ) {
-                       $action = $this->isAllowed( $performingUser )->isGood() ? 'display' : 'reset';
+               if ( !$this->isAllowed( $performingUser )->isGood() ) {
                        throw new LogicException( 'User ' . $performingUser->getName()
-                               . ' is not allowed to ' . $action . ' passwords' );
+                               . ' is not allowed to reset passwords' );
                }
 
                $resetRoutes = $this->config->get( 'PasswordResetRoutes' )
@@ -134,12 +141,14 @@ class PasswordReset {
                if ( $resetRoutes['username'] && $username ) {
                        $method = 'username';
                        $users = [ User::newFromName( $username ) ];
+                       $email = null;
                } elseif ( $resetRoutes['email'] && $email ) {
                        if ( !Sanitizer::validateEmail( $email ) ) {
                                return StatusValue::newFatal( 'passwordreset-invalidemail' );
                        }
                        $method = 'email';
                        $users = $this->getUsersByEmail( $email );
+                       $username = null;
                } else {
                        // The user didn't supply any data
                        return StatusValue::newFatal( 'passwordreset-nodata' );
@@ -150,7 +159,6 @@ class PasswordReset {
                $data = [
                        'Username' => $username,
                        'Email' => $email,
-                       'Capture' => $displayPassword ? '1' : null,
                ];
                if ( !Hooks::run( 'SpecialPasswordResetOnSubmit', [ &$users, $data, &$error ] ) ) {
                        return StatusValue::newFatal( Message::newFromSpecifier( $error ) );
@@ -199,7 +207,6 @@ class PasswordReset {
                        $req = TemporaryPasswordAuthenticationRequest::newRandom();
                        $req->username = $user->getName();
                        $req->mailpassword = true;
-                       $req->hasBackchannel = $displayPassword;
                        $req->caller = $performingUser->getName();
                        $status = $this->authManager->allowsAuthenticationDataChange( $req, true );
                        if ( $status->isGood() && $status->getValue() !== 'ignored' ) {
@@ -214,19 +221,32 @@ class PasswordReset {
                        }
                }
 
+               $logContext = [
+                       'requestingIp' => $ip,
+                       'requestingUser' => $performingUser->getName(),
+                       'targetUsername' => $username,
+                       'targetEmail' => $email,
+                       'actualUser' => $firstUser->getName(),
+               ];
+
                if ( !$result->isGood() ) {
+                       $this->logger->info(
+                               "{requestingUser} attempted password reset of {actualUser} but failed",
+                               $logContext + [ 'errors' => $result->getErrors() ]
+                       );
                        return $result;
                }
 
                $passwords = [];
                foreach ( $reqs as $req ) {
                        $this->authManager->changeAuthenticationData( $req );
-                       // TODO record mail sending errors
-                       if ( $displayPassword ) {
-                               $passwords[$req->username] = $req->password;
-                       }
                }
 
+               $this->logger->info(
+                       "{requestingUser} did password reset of {actualUser}",
+                       $logContext
+               );
+
                return StatusValue::newGood( $passwords );
        }
 
index 273d555..2ee8ed2 100644 (file)
@@ -166,7 +166,6 @@ class User implements IDBAccessObject {
                'noratelimit',
                'override-export-depth',
                'pagelang',
-               'passwordreset',
                'patrol',
                'patrolmarks',
                'protect',
@@ -301,6 +300,11 @@ class User implements IDBAccessObject {
        /** @var integer User::READ_* constant bitfield used to load data */
        protected $queryFlagsUsed = self::READ_NORMAL;
 
+       /** @var string Indicates type of block (used for eventlogging)
+        * Permitted values: 'cookie-block', 'proxy-block', 'openproxy-block', 'xff-block'
+        */
+       public $blockTrigger = false;
+
        public static $idCacheByName = [];
 
        /**
@@ -673,7 +677,7 @@ class User implements IDBAccessObject {
                );
                if ( !$row ) {
                        // No user. Create it?
-                       return $options['create'] ? self::createNew( $name ) : null;
+                       return $options['create'] ? self::createNew( $name, [ 'token' => self::INVALID_TOKEN ] ) : null;
                }
                $user = self::newFromRow( $row );
 
@@ -999,11 +1003,10 @@ class User implements IDBAccessObject {
         * able to set their password to this.
         *
         * @param string $password Desired password
-        * @param string $purpose one of 'login', 'create', 'reset'
         * @return Status
         * @since 1.23
         */
-       public function checkPasswordValidity( $password, $purpose = 'login' ) {
+       public function checkPasswordValidity( $password ) {
                global $wgPasswordPolicy;
 
                $upp = new UserPasswordPolicy(
@@ -1020,7 +1023,7 @@ class User implements IDBAccessObject {
                }
 
                if ( $result === false ) {
-                       $status->merge( $upp->checkUserPassword( $this, $password, $purpose ) );
+                       $status->merge( $upp->checkUserPassword( $this, $password ) );
                        return $status;
                } elseif ( $result === true ) {
                        return $status;
@@ -1094,20 +1097,6 @@ class User implements IDBAccessObject {
                return $name;
        }
 
-       /**
-        * Count the number of edits of a user
-        *
-        * @param int $uid User ID to check
-        * @return int The user's edit count
-        *
-        * @deprecated since 1.21 in favour of User::getEditCount
-        */
-       public static function edits( $uid ) {
-               wfDeprecated( __METHOD__, '1.21' );
-               $user = self::newFromId( $uid );
-               return $user->getEditCount();
-       }
-
        /**
         * Return a random password.
         *
@@ -1200,13 +1189,29 @@ class User implements IDBAccessObject {
                $user = $session->getUser();
                if ( $user->isLoggedIn() ) {
                        $this->loadFromUserObject( $user );
+
+                       // If this user is autoblocked, set a cookie to track the Block. This has to be done on
+                       // every session load, because an autoblocked editor might not edit again from the same
+                       // IP address after being blocked.
+                       $config = RequestContext::getMain()->getConfig();
+                       if ( $config->get( 'CookieSetOnAutoblock' ) === true ) {
+                               $block = $this->getBlock();
+                               $shouldSetCookie = $this->getRequest()->getCookie( 'BlockID' ) === null
+                                       && $block
+                                       && $block->getType() === Block::TYPE_USER
+                                       && $block->isAutoblocking();
+                               if ( $shouldSetCookie ) {
+                                       wfDebug( __METHOD__ . ': User is autoblocked, setting cookie to track' );
+                                       $block->setCookie( $this->getRequest()->response() );
+                               }
+                       }
+
                        // Other code expects these to be set in the session, so set them.
                        $session->set( 'wsUserID', $this->getId() );
                        $session->set( 'wsUserName', $this->getName() );
                        $session->set( 'wsToken', $this->getToken() );
                        return true;
                }
-
                return false;
        }
 
@@ -1609,6 +1614,31 @@ class User implements IDBAccessObject {
                // User/IP blocking
                $block = Block::newFromTarget( $this, $ip, !$bFromSlave );
 
+               // If no block has been found, check for a cookie indicating that the user is blocked.
+               $blockCookieVal = (int)$this->getRequest()->getCookie( 'BlockID' );
+               if ( !$block instanceof Block && $blockCookieVal > 0 ) {
+                       // Load the Block from the ID in the cookie.
+                       $tmpBlock = Block::newFromID( $blockCookieVal );
+                       if ( $tmpBlock instanceof Block ) {
+                               // Check the validity of the block.
+                               $blockIsValid = $tmpBlock->getType() == Block::TYPE_USER
+                                       && !$tmpBlock->isExpired()
+                                       && $tmpBlock->isAutoblocking();
+                               $config = RequestContext::getMain()->getConfig();
+                               $useBlockCookie = ( $config->get( 'CookieSetOnAutoblock' ) === true );
+                               if ( $blockIsValid && $useBlockCookie ) {
+                                       // Use the block.
+                                       $block = $tmpBlock;
+                                       $this->blockTrigger = 'cookie-block';
+                               } else {
+                                       // If the block is not valid, clear the block cookie (but don't delete it,
+                                       // because it needs to be cleared from LocalStorage as well and an empty string
+                                       // value is checked for in the mediawiki.user.blockcookie module).
+                                       $tmpBlock->setCookie( $this->getRequest()->response(), true );
+                               }
+                       }
+               }
+
                // Proxy blocking
                if ( !$block instanceof Block && $ip !== null && !in_array( $ip, $wgProxyWhitelist ) ) {
                        // Local list
@@ -1617,11 +1647,13 @@ class User implements IDBAccessObject {
                                $block->setBlocker( wfMessage( 'proxyblocker' )->text() );
                                $block->mReason = wfMessage( 'proxyblockreason' )->text();
                                $block->setTarget( $ip );
+                               $this->blockTrigger = 'proxy-block';
                        } elseif ( $this->isAnon() && $this->isDnsBlacklisted( $ip ) ) {
                                $block = new Block;
                                $block->setBlocker( wfMessage( 'sorbs' )->text() );
                                $block->mReason = wfMessage( 'sorbsreason' )->text();
                                $block->setTarget( $ip );
+                               $this->blockTrigger = 'openproxy-block';
                        }
                }
 
@@ -1640,6 +1672,7 @@ class User implements IDBAccessObject {
                                # Mangle the reason to alert the user that the block
                                # originated from matching the X-Forwarded-For header.
                                $block->mReason = wfMessage( 'xffblockreason', $block->mReason )->text();
+                               $this->blockTrigger = 'xff-block';
                        }
                }
 
@@ -1654,6 +1687,7 @@ class User implements IDBAccessObject {
                        $this->mBlockedby = '';
                        $this->mHideName = 0;
                        $this->mAllowUsertalk = false;
+                       $this->blockTrigger = false;
                }
 
                // Extensions
@@ -5017,13 +5051,27 @@ class User implements IDBAccessObject {
        /**
         * Get the description of a given right
         *
+        * @since 1.29
         * @param string $right Right to query
         * @return string Localized description of the right
         */
        public static function getRightDescription( $right ) {
                $key = "right-$right";
                $msg = wfMessage( $key );
-               return $msg->isBlank() ? $right : $msg->text();
+               return $msg->isDisabled() ? $right : $msg->text();
+       }
+
+       /**
+        * Get the name of a given grant
+        *
+        * @since 1.29
+        * @param string $grant Grant to query
+        * @return string Localized name of the grant
+        */
+       public static function getGrantName( $grant ) {
+               $key = "grant-$grant";
+               $msg = wfMessage( $key );
+               return $msg->isDisabled() ? $grant : $msg->text();
        }
 
        /**
index 5b18365..228c5c4 100644 (file)
@@ -9,6 +9,7 @@
        "--warnings-exit-nonzero": true,
        "--external": "Blob,File,HTMLDocument,HTMLElement,HTMLIframeElement,HTMLInputElement,KeyboardEvent,MouseEvent,Node,Window,XMLDocument",
        "--output": "docs/js",
+       "--exclude": "resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js",
        "--": [
                "maintenance/jsduck/external.js",
                "resources/src/mediawiki",
index 1ed9a44..0557455 100644 (file)
@@ -174,6 +174,7 @@ class Names {
                'gom' => 'गोंयची कोंकणी / Gõychi Konknni', # Goan Konkani
                'gom-deva' => 'गोंयची कोंकणी', # Goan Konkani (Devanagari script)
                'gom-latn' => 'Gõychi Konknni', # Goan Konkani (Latin script)
+               'gor' => 'Bahasa Hulontalo', # Gorontalo
                'got' => '𐌲𐌿𐍄𐌹𐍃𐌺', # Gothic
                'grc' => 'Ἀρχαία ἑλληνικὴ', # Ancient Greek
                'gsw' => 'Alemannisch', # Alemannic
@@ -241,6 +242,7 @@ class Names {
                'krc' => 'къарачай-малкъар', # Karachay-Balkar
                'kri' => 'Krio', # Krio
                'krj' => 'Kinaray-a', # Kinaray-a
+               'krl' => 'karjal', # Karelian
                'ks' => 'कॉशुर / کٲشُر', # Kashmiri (multiple scripts - defaults to Perso-Arabic)
                'ks-arab' => 'کٲشُر', # Kashmiri (Perso-Arabic script)
                'ks-deva' => 'कॉशुर', # Kashmiri (Devanagari script)
index 5ad5bd3..4f0b535 100644 (file)
        "activeusers-intro": "Nyoë nakeuh dapeuta ureuëng ngui nyang na geuteumuléh lam $1 {{PLURAL:$1|uroë}} nyoë.",
        "activeusers-count": "$1 {{PLURAL:$1|buet}} lam {{PLURAL:$3|uroë|$3 uroë}} nyoë",
        "activeusers-from": "Peuleumah ureueng ngui nyang neuawai ngön:",
-       "activeusers-hidebots": "Peusom bot",
-       "activeusers-hidesysops": "Peusom ureueng urôh",
        "activeusers-noresult": "Hana ureueng ngui nyang meutumèe.",
        "listgrouprights": "Dapeuta khut ureueng ngui",
        "listgrouprights-key": "Teuneurang:\n* <span class=\"listgrouprights-granted\">Khut nyang geubri</span>\n* <span class=\"listgrouprights-revoked\">Khut nyang hana geubri</span>",
index eb15a0e..a5c7dd0 100644 (file)
        "passwordreset-emailtitle": "Аккаунт и гъэпсыкIэхэр, мий щыI {{SITENAME}}",
        "passwordreset-emailelement": "НэбгырацIэ: \n$1\n\nTemporary password: \n$2",
        "passwordreset-emailsentemail": "Мыр регистрыгъэ емэйлэу щытмэ уи аккаунтым пае, шъэфгущыIэм и зэтедз емэйл къыпфагъэхьыщт.",
-       "passwordreset-emailsent-capture": "ШъэфгущыIэм изэтедз фэгъэхьыгъэ емэйлыр гъахьыгъэ, ычIэгъкIэ ар олъэгъу.",
        "changeemail": "Зэблэхъу е тегъэкI емэйл адресыр",
        "changeemail-no-info": "Мы нэкIубгъом занкIэу укIонэу уфаемэ, системэм ухэхьэгъэн фае.",
        "changeemail-oldemail": "Джырэ емэйл адрес:",
        "content-model-javascript": "JavaScript",
        "content-json-empty-object": "Объект нэкI",
        "content-json-empty-array": "Массив нэкI",
-       "cantcreateaccounttitle": "Аккаунт ублэн лъэкIыгъэп",
        "viewpagelogs": "Мы нэкӏубгъом и логхэр къэгъэлъагъу",
        "nohistory": "Мы нэкIубгъом и еIэзэнмэ я тарихъ щыIэп.",
        "currentrev": "Ыужрэ версие",
        "linksearch-ok": "Лъыхъу",
        "listusers-submit": "Къэгъэлъагъу",
        "listusers-noresult": "Нэбгырэ пари гъотыгъэп.",
-       "activeusers-hidebots": "Ботхэр гъэбылъ",
-       "activeusers-hidesysops": "Администраторхэр гъэбылъ",
        "activeusers-noresult": "Нэбгырэ пари гъотыгъэп.",
        "listgrouprights": "Нэбгырэмэ якупмэ яфитыныгъэхэр",
        "listgrouprights-group": "Куп",
index cb869d0..794eae2 100644 (file)
        "yourname": "اسم المستخدم:",
        "yourpassword": "كلمة السر:",
        "yourpasswordagain": "أعد كتابة كلمة السر:",
-       "remembermypassword": "تذكر دخولي على هذا الحاسوب (إلى {{PLURAL:$1||يوم واحد|يومين|$1 أيام|$1 يومًا|$1 يوم}} كحد أقصى)",
        "yourdomainname": "نطاقك:",
        "externaldberror": "هناك إما خطأ في دخول قاعدة البيانات الخارجية أو أنه غير مسموح لك بتحديث حسابك الخارجي.",
        "login": "ادخل",
index a905b3c..d435dbb 100644 (file)
        "passwordreset-emaildisabled": "E-posfunksies is afgeskakel op hierdie wiki.",
        "passwordreset-username": "Gebruiker:",
        "passwordreset-domain": "Domein:",
-       "passwordreset-capture": "Wys resulterende e-pos?",
-       "passwordreset-capture-help": "As u die boks merk, word die e-pos (met die tydelike wagwoord) aan u getoon en aan die gebruiker gestuur.",
        "passwordreset-email": "E-posadres:",
        "passwordreset-emailtitle": "Gebruiker se details op {{site name}}",
        "passwordreset-emailtext-ip": "Iemand, waarskynlik u vanaf die IP-adres $1, het u gebruikersgegewens vir {{SITENAME}} ($4) opgevra.\nDie volgende {{PLURAL:$3|gebruiker is|gebruikers is}} aan die e-posadres gekoppel:\n\n$2\n\n{{PLURAL:$3|Die tydelike wagwoord verval|Hierdie tydelike wagwoorde verval}} oor {{PLURAL:$5|een dag|$5 dae}}.\nMeld asseblief nou aan en wysig u wagwoord. As u dit nie versoek het nie, of as u die oorspronklike wagwoord nog ken en dit nie wil verander nie, ignoreer die berig en hou aan om u ou wagwoord te gebruik.",
        "userrights-reason": "Rede:",
        "userrights-no-interwiki": "U het nie toestemming om gebruikersregte op ander wiki's te verander nie.",
        "userrights-nodatabase": "Databasis $1 bestaan nie of is nie hier beskikbaar nie.",
-       "userrights-nologin": "U moet as 'n administrateur [[Special:UserLogin|aanmeld]] om gebruikersregte te kan toeken.",
-       "userrights-notallowed": "U het nie magtiging om gebruikersregte by te sit of weg te neem nie.",
        "userrights-changeable-col": "Groepe wat u kan verander",
        "userrights-unchangeable-col": "Groepe wat u nie kan verander nie",
        "userrights-conflict": "Konflik met gebruikersregte! Pas asseblief weer u wysigings toe.",
-       "userrights-removed-self": "U het u eie regte suksesvol verwyder. Gevolglik het u nie meer toegang tot hierdie bladsy nie.",
        "group": "Groep:",
        "group-user": "Gebruikers",
        "group-autoconfirmed": "Bevestigde gebruikers",
        "right-siteadmin": "Sluit en ontsluit die datbasis",
        "right-override-export-depth": "Eksporteer bladsye insluitend geskakelde bladsye tot 'n diepte van 5",
        "right-sendemail": "Stuur e-pos aan ander gebruikers",
-       "right-passwordreset": "Wys e-posse vir herstel van wagwoord",
        "newuserlogpage": "Logboek van nuwe gebruikers",
        "newuserlogpagetext": "Dit is 'n logboek van gebruikers wat onlangs ingeteken het.",
        "rightslog": "Gebruikersregtelogboek",
        "trackingcategories-disabled": "Kategorie is gedeaktiveer",
        "mailnologin": "Geen versendadres beskikbaar",
        "mailnologintext": "U moet [[Special:UserLogin|ingeteken]] wees en 'n geldige e-posadres in u [[Special:Preferences|voorkeure]] hê om e-pos aan ander gebruikers te kan stuur.",
-       "emailuser": "Stuur e-pos na hierdie gebruiker",
+       "emailuser": "Stuur e-pos na dié gebruiker",
        "emailuser-title-target": "E-pos die {{GENDER:$1|gebruiker}}",
        "emailuser-title-notarget": "E-pos gebruiker",
        "emailpagetext": "As {{GENDER:$1|dié gebruiker}} 'n geldige e-posadres in sy/haar gebruikersvoorkeure het, sal hierdie vorm 'n enkele boodskap stuur. Die e-posadres in u [[Special:Preferences|gebruikersvoorkeure]] sal verskyn as die \"Van\"-adres van die pos. Dus sal die ontvanger kan terug antwoord.",
        "namespace_association": "Gekoppelde naamruimte",
        "tooltip-namespace_association": "Merk die boks om die besprekings- en onderwerpnaamruimte die by die geselekteerde naamruimte in te sluit",
        "blanknamespace": "(Hoof)",
-       "contributions": "{{GENDER:$1|Gebruikersbydraes}}",
+       "contributions": "{{GENDER:$1|Gebruikers­bydraes}}",
        "contributions-title": "$1 se bydraes",
        "mycontris": "Bydraes",
        "anoncontribs": "Bydraes",
        "specialpage-securitylevel-not-allowed-title": "Nie toegestaan",
        "cannotauth-not-allowed-title": "Geen toegang",
        "cannotauth-not-allowed": "U word nie toegelaat om die bladsy te gebruik nie",
-       "credentialsform-account": "Gebruikersnaam:",
-       "edit-error-short": "Fout: $1",
-       "edit-error-long": "Foute:\n\n$1"
+       "credentialsform-account": "Gebruikersnaam:"
 }
index 23da0fa..5f9ab04 100644 (file)
        "yourname": "Nofka:",
        "yourpassword": "Fjalëkalimi:",
        "yourpasswordagain": "Fjalëkalimi përsëdyti:",
-       "remembermypassword": "Mbaj mend fjalëkalimin tem në këtë shfletues (për $1 {{PLURAL:$1|ditë|ditë}})",
        "yourdomainname": "Domena juej:",
        "externaldberror": "Ose pat gabim në databazën e autentifikimit, ose nuk lejoheni me ndryshue llogarinë tuej të jashtme.",
        "login": "Kyçu",
        "undo-failure": "Redaktimi nuk mund të kthehej për shkak të përplasjeve të ndërmjetshme.",
        "undo-norev": "S'mund të zhbëja këtë redaktim pasi nuk ekziston ose është grisur.",
        "undo-summary": "U kthye versioni $1 i bërë nga [[Special:Contributions/$2]] ([[User talk:$2]])",
-       "cantcreateaccounttitle": "Nuk mundet të krijohet llogaria",
        "cantcreateaccount-text": "Hapja e llogarive nga kjo adresë IP ('''$1''') është bllokuar nga [[User:$3|$3]].\n\nArsyeja e dhënë nga $3 është ''$2''.",
        "viewpagelogs": "Shih regjistrat për këtë faqe",
        "nohistory": "Nuk ka histori redaktimesh për këtë faqe.",
index 712dc1f..0033e3e 100644 (file)
        "yourpasswordagain": "መግቢያ ቃልዎን ዳግመኛ ይስጡ",
        "createacct-yourpasswordagain": "የመግቢያ ቃሉን ይድገሙ",
        "createacct-yourpasswordagain-ph": "የመግቢያ ቃሉን ይድገሙ",
-       "remembermypassword": "ለሚቀጥለው ጊዜ በዚ ኮምፒውተር ላይ በአባልነት ስሜ መግባቴን ( ቢባዛ ለ $1 {{PLURAL:$1|ቀን|ቀናት}}) አስታውስ።",
        "yourdomainname": "የእርስዎ ከባቢ (domain)፦",
        "password-change-forbidden": "በዚሁ ዊኪ መግቢያ ቃልን መቀይር አልተፈቀደም።",
        "externaldberror": "ወይም አፍአዊ የማረጋገጫ መረጃ-ቤት ስኅተት ነበረ፣ ወይም አፍአዊ አባልነትዎን ማሳደስ አልተፈቀዱም።",
        "passwordreset-email": "የኢ-ሜል አድራሻ:",
        "passwordreset-emailelement": "የአባል ስም፦ \n$1\n\nጊዜያዊ መግቢያ ቃል፦ \n$2",
        "passwordreset-emailsentemail": "የማስታወሻ ኢ-ሜል ተልኳል።",
-       "passwordreset-emailsent-capture": "የማስታወሻ ኢ-ሜል ተልኳል፤ ከዚህም ታች ይታያል።",
-       "passwordreset-emailerror-capture": "የማስታወሻ ኢ-ሜል ተልኳል፤ ከዚህም ታች ይታያል፤ ነገር ግን ወደ ተጠቃሚው ለመላክ ስንል አልተከናወነም፡",
        "changeemail": "ኢ-ሜል አድራሻዎን ለመቀይር",
        "changeemail-header": "የአባልነትዎን ኢ-ሜል አድራሻ ለመቀይር",
        "changeemail-no-info": "ይህንን ገጽ በቀጥታ ለማግኘት አስቀድሞ መግባት ያስፈልጋል።",
        "undo-failure": "ከዚሁ ለውጥ በኋላ ቅራኔ ለውጦች ስለ ገቡ ሊገለበጥ አይቻልም።",
        "undo-norev": "ለውጡ አይኖርም ወይም ጠፍቷልና ሊገለበጥ አልተቻለም።",
        "undo-summary": "አንድ ለውጥ $1 ከ[[Special:Contributions/$2|$2]] ([[User talk:$2|ውይይት]]) ገለበጠ",
-       "cantcreateaccounttitle": "ብዕር ስም ለመፍጠር አይቻልም",
        "cantcreateaccount-text": "ከዚሁ የቁጥር አድራሻ ('''$1''') የብዕር ስም መፍጠር በ[[User:$3|$3]] ታግዷል።\n\nበ$3 የተሰጠው ምክንያት ''$2'' ነው።",
        "viewpagelogs": "መዝገቦች ለዚሁ ገጽ",
        "nohistory": "ለዚሁ ገጽ የዕትሞች ታሪክ የለም።",
        "activeusers": "ተግባራዊ አባላት ዝርዝር",
        "activeusers-intro": "እነዚህ አባላት ባለፈው $1 ቀን ውስጥ ማናቸውንም አይነት ተግባር ፈጸሙ።",
        "activeusers-count": "$1 {{PLURAL:$1|ለውጥ|ለውጦች}} ባለፈው $3 ቀን ውስጥ",
-       "activeusers-hidebots": "ሎሌዎች ይደበቁ",
-       "activeusers-hidesysops": "መጋቢዎች ይደበቁ",
        "activeusers-noresult": "ማንም ተጠቃሚ አልተገኘም።",
        "listgrouprights": "የተጠቃሚ ስብስባ መብቶች",
        "listgrouprights-group": "ስብስባ",
index 75e8de8..f3d19ec 100644 (file)
        "passwordreset-disabled": "S'ha desactivau o restablimiento de claus en ista wiki.",
        "passwordreset-username": "Nombre d'usuario:",
        "passwordreset-domain": "Dominio:",
-       "passwordreset-capture": "Veyer o mensache resultant?",
-       "passwordreset-capture-help": "Si marca ista caixeta, se li amostrará o correu electronico (con a clau temporal) amás de ninviar-lo ta l'usuario.",
        "passwordreset-email": "Adreza de correu electronico:",
        "passwordreset-emailtitle": "Detalles d'a cuenta en {{SITENAME}}",
        "passwordreset-emailtext-ip": "Belún (probablement vusté, dende l'adreza IP $1) ha demandau un recordatorio d'a información d'a suya cuenta en  {{SITENAME}} ($4). {{PLURAL:$3|A cuenta d'usuario siguient ye asociata|As cuentas d'usuario siguients son asociatas}} a ista adreza de correu-e:\n\n$2\n\n{{PLURAL:$3|Ista clau temporal circumducirá|Istas claus temporals circumducirán}} en {{PLURAL:$5|un día|$5 días}}. Habría de connectar-se agora y trigar una nueva clau. Si ista demanda no dimana de vusté, u ya se'n ha acordau d'a suya clau inicial y ya no deseya modificar-la, puet ignorar iste mensache y continar emplegando a suya viella clau.",
        "userrights-reason": "Razón:",
        "userrights-no-interwiki": "No tiene premiso ta editar os dreitos d'usuario en atras wikis.",
        "userrights-nodatabase": "A base de datos $1 no existe u no ye local.",
-       "userrights-nologin": "Ha d'[[Special:UserLogin|encetar una sesión]] con una cuenta d'almenistrador ta poder dar dreitos d'usuario.",
-       "userrights-notallowed": "A suya cuenta no tien permisos ta asignar u desasignar permisos d'usuario.",
        "userrights-changeable-col": "Grupos que puede cambiar",
        "userrights-unchangeable-col": "Collas que no puede cambiar",
        "group": "Colla:",
        "right-siteadmin": "Trancar y destrancar a base de datos",
        "right-override-export-depth": "Exporta pachinas que incluigan as enlazadas dica un fundaria de 5",
        "right-sendemail": "Ninviar un correu electronico a atros usuarios",
-       "right-passwordreset": "Veyer os correus electronicos de restabimiento de claus",
        "newuserlogpage": "Rechistro de nuevos usuarios",
        "newuserlogpagetext": "Isto ye un rechistro de creyación d'usuarios.",
        "rightslog": "Rechistro de cambios en os dreitos d'os usuarios",
        "booksources-search": "Mirar",
        "booksources-text": "Contino ye una lista de vinclos ta atros puestos an que venden libros nuevos y usatos, talment bi haiga más información sobre os libros que ye mirando.",
        "booksources-invalid-isbn": "O numero d'ISBN dato pareix que no ye conforme; comprebe si no bi ha garra error en copiar d'a fuent orichinal.",
+       "magiclink-tracking-rfc": "Pachinas que fan servir vinclos machicos RFC",
+       "magiclink-tracking-rfc-desc": "Ista pachina fa servir vinclos machicos de RFC. Se veiga [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sobre cómo migrar.",
+       "magiclink-tracking-pmid": "Pachinas que fan servir vinclos machicos PMID",
+       "magiclink-tracking-pmid-desc": "Ista pachina fa servir vinclos machicos de PMID. Se veiga [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sobre cómo migrar.",
+       "magiclink-tracking-isbn": "Pachinas que fan servir vinclos machicos d'ISBN",
+       "magiclink-tracking-isbn-desc": "Ista pachina fa servir vinclos machicos d'ISBN. Se veiga [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sobre cómo migrar.",
        "specialloguserlabel": "Fedor:",
        "speciallogtitlelabel": "Obchectivo (titol u usuario):",
        "log": "Rechistros",
        "activeusers-intro": "Ista ye una lista d'usuarios que han teniu bella actividat en os zaguers $1 {{PLURAL:$1|diya|diyas}}.",
        "activeusers-count": "$1 {{PLURAL:$1|edición|edicions}} en os zaguers {{PLURAL:$3|diya|$3 diyas}}",
        "activeusers-from": "Amostrar nombres d'usuario que prencipien por:",
-       "activeusers-hidebots": "Amagar robots",
-       "activeusers-hidesysops": "Amagar administradors",
        "activeusers-noresult": "No s'han trobato usuarios.",
        "listgrouprights": "Dreitos d'a colla d'usuarios",
        "listgrouprights-summary": "Contino trobará a lista de collas d'usuario definitas en iste wiki, con os suyos dreitos d'acceso asociatos. Tamién puet trobar aquí [[{{MediaWiki:Listgrouprights-helppage}}|información adicional]] sobre os dreitos individuals.",
index 5a3781b..56bbdfe 100644 (file)
        "createacct-yourpassword-ph": "कूटशब्द दर्ज करऽ",
        "createacct-yourpasswordagain": "कूटशब्द केरऽ पुष्टि करऽ",
        "createacct-yourpasswordagain-ph": "कूटशब्द पुनः लिखऽ",
-       "remembermypassword": "इ कंप्यूटर पर हमरॊ लॉग-इन सूचना याद रखॊ (अधिकतम $1 {{PLURAL:$1|दिन|दिन}} लेली)",
        "userlogin-remembermypassword": "हमरा लॉगिन रखऽ",
        "login": "लॉग इन",
        "nav-login-createaccount": "सत्रारंभ / खाता खोलॊ",
index 3289983..f6c6636 100644 (file)
        "views": "معاينة",
        "toolbox": "أدوات",
        "tool-link-userrights": "تغيير مجموعات {{GENDER:$1|المستخدم|المستخدمة}}",
+       "tool-link-userrights-readonly": "عرض مجموعات {{GENDER:$1|المستخدم|المستخدمة}}",
        "tool-link-emailuser": "أرسل رسالة {{GENDER:$1|لهذا المستخدم|لهذه المستخدمة}}",
        "userpage": "طالع صفحة المستخدم",
        "projectpage": "طالع صفحة المشروع",
        "passwordreset-emaildisabled": "تم تعطيل ميزات البريد الإلكتروني على هذه الويكي.",
        "passwordreset-username": "اسم المستخدم:",
        "passwordreset-domain": "النطاق:",
-       "passwordreset-capture": "أأعرض البريد الإلكتروني الناتج؟",
-       "passwordreset-capture-help": "إذا علّمت هذا الصندوق فسيعرض لك البريد الإلكتروني (الذي يحتوي كلمة سر مؤقتة) وسيرسل أيضا للمستخدم.",
        "passwordreset-email": "عنوان البريد الإلكتروني:",
        "passwordreset-emailtitle": "تفاصيل حساب {{SITENAME}}",
        "passwordreset-emailtext-ip": "أحد ما (قد يكون أنت، من العنوان $1)  طلب إعادة ضبط كلمة سر حسابك على {{SITENAME}} ($4). {{PLURAL:$3||الحساب|الحسابان| الحسابات}} أدناه قد اقترنت ببريدك الإلكتروني :\n\n$2\n\n{{PLURAL:$3||كلمة السر المؤقتة|كلمات السر المؤقتة}} ستنتهي صلاحيتها في {{PLURAL:$5||يوم واحد|يومين|$5 أيام|$5 يوما|$5 يوم}}\nيمكنك تسجيل الدخول واختيار كلمة سر جديدة. إذا كان هذا الطلب تم بواسطة شخص أخر، أو إذا تذكرت كلمة السر الأصلية الخاصة بك، ولم تعد ترغب في تغييرها، يمكنك تجاهل هذه الرسالة ومتابعة استخدام كلمة السر القديمة.",
        "passwordreset-emailelement": "اسم {{GENDER:$1\n|المستخدم|المستخدمة}}: \n$1\n\nكلمة السر المؤقتة: \n$2",
        "passwordreset-emailsentemail": "إذا كان هذا العنوان البريد مرتبط بحسابك، من ثم سيتم إرسال بريد إلكتروني لإعادة تعيين كلمة السر.",
        "passwordreset-emailsentusername": "إذا كان هناك عنوان بريد إلكتروني مرتبط بهذا المستخدم، ثم سيتم إرسال بريد إلكتروني لإعادة تعيين كلمة السر.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|رسالة|رسائل}} البريد الإلكتروني لضبط كلمة السر تم إرسالها. {{PLURAL:$1|اسم المستخدم وكلمة السر معروضان|قائمة أسماء المستخدمين وكلمات السر معروضة}} هنا.",
-       "passwordreset-emailerror-capture2": "إرسال بريد إلى {{GENDER:$2|المستخدم|المستخدمة}} فشل: $1 {{PLURAL:$3|اسم المستخدم وكلمة السر معروضان|قائمة أسماء المستخدمين وكلمات السر معروضة}} هنا.",
        "passwordreset-nocaller": "يجب أن يتم توفير مستدعي",
        "passwordreset-nosuchcaller": "المستدعي غير موجود: $1",
        "passwordreset-ignored": "إعادة ضبط كلمة السر لم تتم التعامل معها. ربما لا موفر تم ضبطه؟",
-       "passwordreset-invalideamil": "عنوان بريد إلكتروني غير صالح",
+       "passwordreset-invalidemail": "عنوان بريد إلكتروني غير صالح",
        "passwordreset-nodata": "لا اسم مستخدم ولا عنوان بريد الإلكتروي تم توفيره",
        "changeemail": "تغيير أو إزالة عنوان البريد الإلكتروني",
        "changeemail-header": "إكمال هذا النموذج لتغيير عنوان البريد الإلكتروني الخاص بك. إذا كنت ترغب في إزالة جمعية أي عنوان البريد الإلكتروني من حسابك، وترك الفراغ عنوان البريد الإلكتروني الجديد عند تقديم النموذج",
        "search-external": "بحث خارجي",
        "searchdisabled": "البحث في {{SITENAME}} معطل.\nيمكنك البحث من خلال جوجل في الوقت الحالي.\nلاحظ أن فهارسه لمحتوى {{SITENAME}} ربما تكون غير محدثة.",
        "search-error": "حدث خطأ ما أثناء البحث: $1",
+       "search-warning": "حدث خطأ أثناء البحث: $1",
        "preferences": "تفضيلات",
        "mypreferences": "تفضيلات",
        "prefs-edits": "عدد التعديلات:",
        "prefs-help-recentchangescount": "بما في ذلك أحدث التغييرات وتاريخ الصفحات والسجلات.",
        "prefs-help-watchlist-token2": "هذا هو المفتاح السري لتغذية الويب لقائمة مراقبتك.\nيمكن لأي شخص يعرفه أن يقرأ قائمة مراقبتك، ولذا لا تتشاركه مع أحد. [[Special:ResetTokens|انقر هنا إذا أردت إعادة ضبطه]].",
        "savedprefs": "تم حفظ تفضيلاتك.",
-       "savedrights": "حُفظت الصلاحيات الجديدة {{GENDER:$1|للمستخدم|للمستخدمة}} $1.",
+       "savedrights": "حُفظت المجموعات الجديدة {{GENDER:$1|للمستخدم|للمستخدمة}} $1.",
        "timezonelegend": "المنطقة الزمنية:",
        "localtime": "الوقت المحلي:",
        "timezoneuseserverdefault": "استخدام الويكي الافتراضي ($1)",
        "prefswarning-warning": "لقد أجريت تعديلات على تفضيلاتك، ولم تُحفَظ بعد.\nإذا غادرت هذه الصفحة دون أن تنقر على «$1» لن يتم تحديث تفضيلاتك.",
        "prefs-tabs-navigation-hint": "تلميح: يمكنك استخدام مفتاحي السهمين الأيمن والأيسر للتنقل بين الألسنة في قائمة الألسنة.",
        "userrights": "صلاحيات المستخدم",
-       "userrights-lookup-user": "أدÙ\90ر Ù\85جÙ\85Ù\88عات المستخدم",
+       "userrights-lookup-user": "اختÙ\8aار المستخدم",
        "userrights-user-editname": "أدخل اسم مستخدم:",
-       "editusergroup": "عدÙ\84 Ù\85جÙ\85Ù\88عات {{GENDER:$1|اÙ\84Ù\85ستخدÙ\85|اÙ\84Ù\85ستخدÙ\85Ø©}}",
+       "editusergroup": "تحÙ\85Ù\8aÙ\84 Ù\85جÙ\85Ù\88عات Ø§Ù\84Ù\85ستخدÙ\85",
        "editinguser": "تغيير صلاحيات {{GENDER:$1|المستخدم|المستخدمة}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "عرض صلاحيات المستخدم {{GENDER:$1|للمستخدم|للمستخدمة}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "تعديل مجموعات المستخدم",
+       "userrights-viewusergroup": "عرض مجموعات المستخدم",
        "saveusergroups": "احفظ مجموعات {{GENDER:$1|المستخدم|المستخدمة}}",
        "userrights-groupsmember": "عضو في:",
        "userrights-groupsmember-auto": "عضو ضمني في:",
        "userrights-reason": "السبب:",
        "userrights-no-interwiki": "أنت لا تمتلك الصلاحية لتعديل صلاحيات المستخدمين على الويكيات الأخرى.",
        "userrights-nodatabase": "قاعدة البيانات $1 غير موجودة أو ليست محلية.",
-       "userrights-nologin": "يجب عليك [[Special:UserLogin|تسجيل الدخول]] بحساب إداري لتعديل صلاحيات المستخدم.",
-       "userrights-notallowed": "ليس لديك إذن لإضافة أو إزالة صلاحيات المستخدمين.",
        "userrights-changeable-col": "المجموعات التي يمكنك تغييرها",
        "userrights-unchangeable-col": "المجموعات التي لا يمكنك تغييرها",
        "userrights-conflict": "تضارب في تغيير صلاحيات المستخدم! الرجاء مراجعة تغييراتك مجدّدا وتأكيدها.",
-       "userrights-removed-self": "أزلت بنجاح صلاحياتك، ولن تتمكن من الوصول لهذه الصفحة مجددا.",
        "group": "المجموعة:",
        "group-user": "مستخدمون",
        "group-autoconfirmed": "مستخدمون مؤكدون تلقائيا",
        "right-siteadmin": "غلق ورفع غلق قاعدة البيانات",
        "right-override-export-depth": "تصدير الصفحات متضمنة الصفحات الموصولة حتى عمق 5",
        "right-sendemail": "إرسال رسائل بريد إلكتروني إلى مستخدمين آخرين",
-       "right-passwordreset": "عرض رسائل إعادة ضبط كلمات السر",
        "right-managechangetags": "إنشاء وتعطيل [[Special:Tags|الوسوم]]",
        "right-applychangetags": "تطبيق [[Special:Tags|الوسوم]]  مع التغييرات التي أجريتها.",
        "right-changetags": "إضافة وإزالة [[Special:Tags|وسوم]] في مراجعات ومدخلات سجل فردية",
        "action-upload_by_url": "رفع هذا الملف من عنوان مسار",
        "action-writeapi": "استخدام API الكتابة",
        "action-delete": "حذف هذه الصفحة",
-       "action-deleterevision": "حذف هذه المراجعة",
-       "action-deletedhistory": "رؤية تاريخ هذه الصفحة المحذوف",
+       "action-deleterevision": "حذف المراجعات",
+       "action-deletelogentry": "حذف مدخلات السجل",
+       "action-deletedhistory": "رؤية تاريخ الصفحات المحذوف",
+       "action-deletedtext": "رؤية تاريخ المراجعات المحذوف",
        "action-browsearchive": "البحث في الصفحات المحذوفة",
-       "action-undelete": "استرجاع هذه الصفحة",
-       "action-suppressrevision": "مراجعة واسترجاع هذه المراجعة المخفية",
+       "action-undelete": "استرجاع الصفحات",
+       "action-suppressrevision": "مراجعة واسترجاع المراجعات المخفية",
        "action-suppressionlog": "رؤية هذا السجل الخاص",
        "action-block": "منع هذا المستخدم من التعديل",
        "action-protect": "تغيير مستويات الحماية لهذه الصفحة",
        "action-userrights-interwiki": "تعديل صلاحيات المستخدم للمستخدمين في الويكيات الأخرى",
        "action-siteadmin": "غلق أو رفع غلق قاعدة البيانات",
        "action-sendemail": "إرسال رسائل بريد إلكتروني",
+       "action-editmyoptions": "تعديل تفضيلاتك",
        "action-editmywatchlist": "تعديل قائمة مراقبتك",
        "action-viewmywatchlist": "مشاهدة قائمة مراقبتك",
        "action-viewmyprivateinfo": "مشاهدة معلوماتك الخاصة",
        "apisandbox-continue": "استمرار",
        "apisandbox-continue-clear": "إفراغ",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} س [https://www.mediawiki.org/wiki/API:Query#Continuing_queries يستمر] في الطلب الأخير؛ {{int:apisandbox-continue-clear}} سيفرغ المعاملات المرتبطة بالاستمرار.",
+       "apisandbox-param-limit": "أدخل <kbd>max</kbd> لاستخدام الحد الأقصى.",
+       "apisandbox-multivalue-all-namespaces": "$1 (كل النطاقات)",
+       "apisandbox-multivalue-all-values": "$1 (كل القيم)",
        "booksources": "مصادر كتاب",
        "booksources-search-legend": "البحث عن مصادر الكتب",
        "booksources-isbn": "ردمك:",
        "booksources-search": "بحث",
        "booksources-text": "توجد أدناه قائمة بوصلات لمواقع أخرى تبيع الكتب الجديدة والمستعملة، أيضا يمكنك أن تحصل على معلومات إضافية عن الكتب التي تبحث عنها من هناك:",
        "booksources-invalid-isbn": "رقم 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",
+       "magiclink-tracking-pmid-desc": "هذه الصفحة تستخدم الوصلات السحرية لPMID. انظر [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] حول كيفية التغيير.",
+       "magiclink-tracking-isbn": "الصفحات التي تستخدم الوصلات السحرية لISBN",
+       "magiclink-tracking-isbn-desc": "هذه الصفحة تستخدم الوصلات السحرية لISBN. انظر [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] حول كيفية التغيير.",
        "specialloguserlabel": "المؤدي:",
        "speciallogtitlelabel": "الهدف (عنوان أو {{ns:user}}:اسم المستخدم للمستخدم):",
        "log": "سجلات",
        "activeusers-count": "{{PLURAL:$1|لا أفعال|فعل واحد|فعلان اثنان|$1 أفعال|$1 فعلا|$1 فعل}} منذ {{PLURAL:$3||يوم|يومين|$3 أيام|$3 يوما|$1 يوم}}",
        "activeusers-from": "اعرض المستخدمين ابتداء من:",
        "activeusers-groups": "عرض المستخدمين المنتمين للمجموعات:",
+       "activeusers-excludegroups": "استثن المستخدمين المنتمين للمجموعات:",
        "activeusers-noresult": "لم يعثر على أي مستخدمين",
        "activeusers-submit": "عرض المستخدمين النشطين",
        "listgrouprights": "صلاحيات مجموعات المستخدمين",
        "emailccsubject": "نسخة من رسالتك إلى $1: $2",
        "emailsent": "أُرسل البريد الإلكتروني",
        "emailsenttext": "أُرسلت رسالتك الإلكترونية.",
-       "emailuserfooter": "هذا البريد الإلكتروني {{GENDER:$1|تم إرساله}} بواسطة $1 إلى {{GENDER:$2|$2}} بواسطة وظيفة \"{{int:emailuser}}\" في {{SITENAME}}.",
+       "emailuserfooter": "هذا البريد الإلكتروني {{GENDER:$1|تم إرساله}} بواسطة $1 إلى {{GENDER:$2|$2}} بواسطة وظيفة \"{{int:emailuser}}\" في {{SITENAME}}. عنوان البريد الخاص {{GENDER:$2|بك}} سيتم إرساله مباشرة {{GENDER:$1|للمرسل الأصلي|للمرسلة الأصلية}}، مما يكشف عنوان البريد الإلكتروني الخاص {{GENDER:$2|بك}} {{GENDER:$1|لهم}}.",
        "usermessage-summary": "ترك رسالة نظام.",
        "usermessage-editor": "مراسل النظام",
        "watchlist": "قائمة مراقبتي",
        "unprotectedarticle": "أزال الحماية من \"[[$1]]\"",
        "movedarticleprotection": "نقل إعدادات الحماية من \"[[$2]]\" إلى \"[[$1]]\"",
        "protectedarticle-comment": "{{GENDER:$2|محمي}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|غير مستوى الحماية|غيرت مستوى الحماية}} ل\"[[$1]]\"",
+       "unprotectedarticle-comment": "{{GENDER:$2|أزال الحماية|أزالت الحماية}} من \"[[$1]]\"",
        "protect-title": "ضبط حماية \"$1\"",
        "protect-title-notallowed": "عرض مستوى حماية \"$1\"",
        "prot_1movedto2": "نُقلت [[$1]] إلى [[$2]]",
        "patrol-log-header": "هذا سجل بالمراجعات المراجعة.",
        "log-show-hide-patrol": "$1 سجل الخفر",
        "log-show-hide-tag": "$1 سجل الوسوم",
+       "confirm-markpatrolled-button": "موافق",
+       "confirm-markpatrolled-top": "علم على المراجعة $3 من $2 كمراجعة؟",
        "deletedrevision": "حذف المراجعة القديمة $1",
        "filedeleteerror-short": "خطأ حذف الملف: $1",
        "filedeleteerror-long": "حدثت أخطاء أثناء حذف الملف:\n\n$1",
        "tags-deactivate": "تعطيل",
        "tags-hitcount": "{{PLURAL:$1|لا تغييرات|تغيير واحد|تغييران|$1 تغييرات|$1 تغييرا|$1 تغيير}}",
        "tags-manage-no-permission": "ليس لديك صلاحية إدارة وسوم التغيير.",
-       "tags-manage-blocked": "لا يمكنك إدارة علامات التغيير في حين منعت.",
+       "tags-manage-blocked": "لا يمكنك إدارة وسوم التغيير أثناء {{GENDER:$1|منعك}}.",
        "tags-create-heading": "إنشاء وسم جديد",
        "tags-create-explanation": "في الوضع الافتراضي، الوسوم الجديدة المنشأة سيتاح استخدامها للبوتات والمستخدمين.",
        "tags-create-tag-name": "اسم الوسم:",
        "tags-deactivate-not-allowed": "من غير الممكن تعطيل الوسم \"$1\".",
        "tags-deactivate-submit": "عطل",
        "tags-apply-no-permission": "ليس لديك إذن لتطبيق علامات التغيير جنبا إلى جنب مع التغييرات.",
-       "tags-apply-blocked": "لا يمكنك تطبيق علامات التغيير جنبا إلى جنب مع التغييرات في حين منعت.",
+       "tags-apply-blocked": "لا يمكنك تطبيق وسوم التغيير جنبا إلى جنب مع تغييراتك أثناء {{GENDER:$1|منعك}}.",
        "tags-apply-not-allowed-one": "الوسم \"$1\" غير مسموح أن يتم تطبيقه يدويا.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|الوسم|الوسوم}} التالية غير مسموح أن يتم تطبيقها يدويا: $1",
        "tags-update-no-permission": "أنت لا تمتلك السماح لإضافة أو إزالة وسوم التغيير من المراجعات أو مدخلات السجل الفردية.",
-       "tags-update-blocked": "لا يمكنك إضافة أو إزالة العلامات التغيير بينماهي محظورة.",
+       "tags-update-blocked": "لا يمكنك إضافة أو إزالة وسوم التغيير أثناء {{GENDER:$1|منعك}}.",
        "tags-update-add-not-allowed-one": "الوسم \"$1\" غير مسموح أن تتم إضافته يدويا.",
        "tags-update-add-not-allowed-multi": "The following {{PLURAL:$2|الوسم|الوسوم}} التالية غير مسموح أن تتم إضافتها يدويا: $1",
        "tags-update-remove-not-allowed-one": "من غير المسموح بإزالة وسم \"$1\".",
        "htmlform-user-not-exists": "<strong>$1</strong> غير موجود",
        "htmlform-user-not-valid": "اسم المستخدم <strong>$1</strong> غير صالح.",
        "logentry-delete-delete": "{{GENDER:$2|حذف|حذفت}} $1 صفحة $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|حذف|حذفت}} التحويلة $3 بواسطة إعادة الكتابة",
        "logentry-delete-restore": "{{GENDER:$2|استرجع|استرجعت}} $1 صفحة $3",
        "logentry-delete-event": "{{GENDER:$2|غيّر|غيّرت}} $1 إمكانية مشاهدة {{PLURAL:$5||حدث|حدثين|$5 أحداث|$5 حدثًا|$5 حدث}} في سجل $3: $4",
        "logentry-delete-revision": "غيّر{{GENDER:$2||ت}} $1 إمكانية مشاهدة {{PLURAL:$5||مراجعة واحدة|مراجعتين|$5 مراجعات|$5 مراجعة}} في صفحة $3: $4",
        "special-characters-title-emdash": "واصلة طويلة",
        "special-characters-title-minus": "علامة الطرح",
        "mw-widgets-dateinput-no-date": "لا تاريخ تم اختياره",
+       "mw-widgets-mediasearch-input-placeholder": "البحث عن ملفات",
+       "mw-widgets-mediasearch-noresults": "لم يتم العثور على نتائج.",
        "mw-widgets-titleinput-description-new-page": "الصفحة غير موجودة بعد",
        "mw-widgets-titleinput-description-redirect": "تحويل إلى $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "أضف تصنيفا...",
        "sessionmanager-tie": "لا يمكن جمع أنواع استيثاق متعددة: $1.",
        "sessionprovider-generic": "جلسات $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "جلسات قائمة على ملفات تعريف الارتباط (كوكيز)",
        "log-action-filter-contentmodel-change": "تغيير موديل المحتوى",
        "log-action-filter-contentmodel-new": "إنشاء صفحة بموديل محتوى غير قياسي",
        "log-action-filter-delete-delete": "حذف الصفحات",
+       "log-action-filter-delete-delete_redir": "إعادة الكتابة فوق التحويلة",
        "log-action-filter-delete-restore": "استرجاع الصفحات",
        "log-action-filter-delete-event": "حذف السجلات",
        "log-action-filter-delete-revision": "حذف المراجعات",
        "restrictionsfield-badip": "عنوان أيبي أو نطاق غير صحيح: $1",
        "restrictionsfield-label": "نطاقات الأيبي المسموح بها:",
        "restrictionsfield-help": "عنوان أيبي أو نطاق CIDR واحد لكل سطر. لتفعيل كل شيء، استخدم<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "خطأ: $1",
-       "edit-error-long": "الأخطاء:\n\n$1"
+       "pageid": "معرف الصفحة $1"
 }
index 3907c46..8d20e95 100644 (file)
        "yourpasswordagain": "ܟܬܘܒ ܡܠܬܐ ܕܥܠܠܐ ܙܒܢܬܐ ܐܚܪܬܐ:",
        "createacct-yourpasswordagain": "ܫܪܪ ܡܠܬܐ ܕܥܠܠܐ",
        "createacct-yourpasswordagain-ph": "ܐܥܠ ܡܠܬܐ ܕܥܠܠܐ ܙܒܢ ܐܚܪܝܢ",
-       "remembermypassword": "ܕܟܘܪ ܥܠܠܬܝ ܥܠ ܡܦܐܬܢܐ ܗܢܐ (ܠܡܬܚܐ ܥܠܝܐ ܕ $1 {{PLURAL:$1|ܝܘܡܐ|ܝܘܡܬ̈ܐ}})",
        "userlogin-remembermypassword": "ܫܒܘܩ ܠܝ ܥܠܝܠܐ ܒܚܘܫܒܢܝ",
        "userlogin-signwithsecure": "ܐܚܫܚ ܕܒܝܩܘܬܐ ܡܫܝܢܢܬܐ",
        "login": "ܥܘܠ",
        "edit-already-exists": "ܒܪܝܐ ܕܦܐܬܐ ܚܕܬܐ ܠܐ ܡܬܡܨܝܢܐ.\nܗܕܐ ܦܐܬܐ ܐܝܬ ܡܢ ܟܕܘ.",
        "editwarning-warning": "ܐܢ ܫܒܩܬ ܦܐܬܐ ܗܕܐ ܡܬܡܨܝܢܬܐ ܐܝܬܝܗ ܕܚܣܪܬ ܟܠ ܫܘܚܠܦ̈ܐ ܕܥܒܝܕܬ ܗܪܟܐ.\nܡܨܬ ܕܬܒܛܠ ܙܘܗܪܐ ܗܢܐ ܐܢ ܥܠܝܠܐ ܐܝܬܝܟ ܒܡܢܬܐ ܕ\"ܫܚܠܦܬܐ\" ܒܨܒܝܢܝܘܬ̈ܐ.",
        "undo-summary": "ܠܐ ܬܥܒܕ $1 ܒܝܕ [[Special:Contributions/$2|$2]] ([[User talk:$2|ܡܡܠܠܐ]])",
-       "cantcreateaccounttitle": "ܒܪܝܐ ܕܚܘܫܒܢܐ ܠܐ ܡܬܡܨܝܢܐ",
        "viewpagelogs": "ܚܙܝ ܣܓܠ̈ܐ ܕܦܐܬܐ ܗܕܐ",
        "nohistory": "ܠܝܬ ܬܫܥܝܬܐ ܕܫܘܚܠܦ̈ܐ ܠܦܐܬܐ ܗܕܐ",
        "currentrev": "ܬܢܝܬܐ ܗܫܝܬܐ",
        "activeusers": "ܡܟܬܒܘܬܐ ܕܗܕ̈ܡܐ ܙܪ̄ܝܙܐ",
        "activeusers-count": "$1 {{PLURAL:$1|ܥܒܕܐ|ܥܒܕ̈ܐ}} ܒ {{PLURAL:$3|ܝܘܡܐ ܐܚܪܝܐ|$3 ܝܘܡܬ̈ܐ ܐܚܪ̈ܝܐ}}",
        "activeusers-from": "ܚܘܝ ܡܦܠܚܢ̈ܐ ܕܫܪܐ ܥܡ:",
-       "activeusers-hidebots": "ܛܫܝ ܒܘܬ̈ܐ (bots)",
-       "activeusers-hidesysops": "ܛܫܝ ܡܕܒܪ̈ܢܐ",
        "activeusers-noresult": "ܠܐ ܐܫܬܟܚ ܡܦܠܚܢ̈ܐ ܐܢܫ̈ܝܢ.",
        "listgrouprights": "ܙܕ̈ܩܐ ܕܟܢܘܫܬܐ ܕܡܦܠܚܢ̈ܐ",
        "listgrouprights-group": "ܟܢܘܫܬܐ",
index 3dfb6ab..79fc096 100644 (file)
        "yourpasswordagain": "عاود كتبت كلمت السر:",
        "createacct-yourpasswordagain": "أكّد كلمت` السرّ",
        "createacct-yourpasswordagain-ph": "عاود دخّل كلمت` السرّ",
-       "remembermypassword": "اتفكر الدخول تاعي ب هاذ النافيكاتور (ب مدّة حدها{{PLURAL:$1||يوم واحد|يومين|$1 إيّام|$1 يوم}})",
        "userlogin-remembermypassword": "خلّيني مسجّل داخل",
        "userlogin-signwithsecure": "استعمل التوصال المأمون.",
        "yourdomainname": "الدومان تاعك:",
        "passwordreset-emailtext-user": "المستعملي $1 ف {{SITENAME}} راه طلب تبدال ف كلمت` السرّ تاعك ف {{SITENAME}}\n($4). {{PLURAL:$3|الحساب|الحسايات}} تاع المستعملي {{PLURAL:$3|راه مربوط|راهم مربوطين}} ب لادريسة تاع ليمال هادي:\n\n$2\n\n{{PLURAL:$3|هاد كلمت` السرّ المأقّتة|هادي كلمات` السرّ المأقّتة}} غادي يكمل صلوحها منّا على {{PLURAL:$5|نهار واحد|$5 إيّام}}.\nمادابيك تسجّل داخل ضركا و تختار كلمت` سرّ جديدة. يلا كان وحداخُر دار هاد المطلب، ولا راك ضركا تفكّرت كلمت` السرّ تاعك القديمة و ما بقيتش باغي تبدّلها، تنجم برك تتنسّا هاد الميساج و تدخُل ب كلمت` السرّ تاعك تاع مضاري.",
        "passwordreset-emailelement": "سميّت` المستعملي: \n$1\n\nكلمت` السرّ المأقّتة: \n$2",
        "passwordreset-emailsentemail": "راه نبعَت إيمال تاع تبدال كلمت` السرّ.",
-       "passwordreset-emailsent-capture": "راه اترسل إيمال تاع تبدال كلمت` السرّ، و راه محطوط هنا لتحت.",
-       "passwordreset-emailerror-capture": "راه اترسل الإيمال تاع تبدال كلمت` السرّ، الّي راح محطوط هنا لتحت، بصّح البعيت تاعهُ لل {{GENDER:$2|مستعملي}} ما نجحش: $1",
        "changeemail": "بدّل لادريسة تاع الإيمال",
        "changeemail-header": "كمّل الكتبة ف` الجدوال هادا باش تبدّل لادريسة تاع الإيمال تاعك. يلزم لك تدخّل كلمت` السرّ تاعك باش تأكّد هاد التبدال.",
        "changeemail-no-info": "لازم لك تكون مسجّل داخل باش توصَل ل هاد الپاجة بسّراح.",
index 74c6dec..dcab5ec 100644 (file)
        "yourname": "smiṫ l-mosṫĥdim:",
        "yourpassword": "Saroṫ:",
        "yourpasswordagain": "aaawd ktb lmot de passe dyalk",
-       "remembermypassword": "Ĝqel ĝla smiyṫ l-ḫsab dyali fe had l-ordinaṫør (ġir limoddaṫ {{PLURAL:$1|yom waḫed|$1 iyyam}})",
        "yourdomainname": "domain dyalk",
        "externaldberror": "kayn imma ċi ĥata' f-doĥol qaĝidaṫ l-bayanaṫ wlla rah ma msmoḫ-likċ baċ ṫḫddṫ l-ḫisab l-ĥariji taĝk.",
        "login": "Dĥel",
        "undo-failure": "ma ṣlaḫ-ċ ṫredd ṫ-ṫĝdil ḫiṫ tra ċi ṫĝdil mn morah.",
        "undo-norev": "ma ṣlaḫ-ċ ṫredd ṫ-ṫĝdil ḫiṫ ma kayn-ċ wlla ṫhyyed.",
        "undo-summary": "reḍḍ l-morajaĝa $1 d-[[Special:Contributions/$2|$2]] ([[User talk:$2|niqaċ]])",
-       "cantcreateaccounttitle": "lcont maymknch tnchaa",
        "viewpagelogs": "Ċof l-ĝamaliyaṫ dyal had ṣ-ṣefḫa",
        "nohistory": "ma kayn ḫṫṫa istorik d-ṫĝdilaṫ l-had ṣfḫa.",
        "currentrev": "Ċof l-versyon l-leĥĥra",
        "listusers-blocked": "(mbloki)",
        "activeusers": "lista dyal lmostkhdimin nachtin",
        "activeusers-from": "wrri l-mosṫĥdimin lli badyin mn:",
-       "activeusers-hidebots": "khbbi lbotat",
-       "activeusers-hidesysops": "Khbbi lidariyin",
        "activeusers-noresult": "ta mostakhdim matlgach.",
        "listgrouprights": "salahiyat mjmoat lmostkhdimin",
        "listgrouprights-key": "* <span class=\"listgrouprights-granted\">ḫoqoq mĝtiyya</span>\n* <span class=\"listgrouprights-revoked\">ḫoqoq mḫeyyda</span>",
        "htmlform-submit": "ṣift",
        "htmlform-reset": "rojoa an taadilat",
        "htmlform-selectorother-other": "okhra",
-       "sqlite-has-fts": "$1 maa imkaniyat lbaht f nass kaml",
-       "sqlite-no-fts": "$1 imkaniyat lbaht f nass kaml",
        "revdelete-restricted": "tḅḅq ḍ-ḍawaḅit ll-idariyyin",
        "revdelete-unrestricted": "ḫyyd ḍ-ḍawaḅit ll-idariyyin",
        "rightsnone": "(walo)",
index 0e51642..947d17d 100644 (file)
        "userlogin-yourpassword": "الباسورد:",
        "yourpasswordagain": "اكتب الباسورد تاني:",
        "createacct-yourpasswordagain": "أكد كلمه السر",
-       "remembermypassword": " (لمدة   $1 {{PLURAL:$1|يوم|يوم}})خليك فاكر دخولى على الكمبيوتر دا",
        "yourdomainname": "النطاق بتاعك:",
        "externaldberror": "يا إما فى حاجة غلط فى الدخول على قاعدة البيانات الخارجية أو انت مش مسموح لك تعمل تحديث لحسابك الخارجي.",
        "login": "دخول",
        "activeusers-intro": "دى قايمه اليوزرات اللى عملوا نشاط فى آخر $1 {{PLURAL:$1|يوم|يوم}}.",
        "activeusers-count": "$1 {{PLURAL:$1|تعديل|تعديل}} فى آخر {{PLURAL:$3|يوم|$3 يوم}}",
        "activeusers-from": "عرض اليوزرات بداية من:",
-       "activeusers-hidebots": "خبى البوتات",
-       "activeusers-hidesysops": "خبى السيسوبات",
        "activeusers-noresult": "مالقيناش اى يوزر",
        "listgrouprights": "حقوق مجموعات اليوزرز",
        "listgrouprights-summary": "دى لستة بمجموعات اليوزرز المتعرفة فى الويكى دا، بالحقوق اللى معاهم.\nممكن تلاقى معلومات زيادة عن الحقوق بتاعة كل واحد  [[{{MediaWiki:Listgrouprights-helppage}}|هنا]].",
index 8a8a45a..70a1442 100644 (file)
        "activeusers-intro": "যোৱা  {{PLURAL:$1|দিন|দিন}}ৰ ভিতৰত অৱদান আগবঢ়োৱা ব্যৱহাৰকাৰীৰ তালিকা",
        "activeusers-count": "যোৱা {{PLURAL:$3|দিনত|$3 দিনত}} সৰ্বমুঠ $1 {{PLURAL:$1|টা কাম}}",
        "activeusers-from": "ইয়াৰে আৰম্ভ হোৱা ব্যৱহাৰকাৰী সকল দেখুৱাওক:",
-       "activeusers-hidebots": "বট নেদেখুৱাব",
-       "activeusers-hidesysops": "প্ৰশাসক নেদেখুৱাব",
        "activeusers-noresult": "কোনো সদস্য পোৱা নগ'ল।",
        "listgrouprights": "ব্যৱহাৰকাৰী গোটৰ অধিকাৰ",
        "listgrouprights-summary": "এই ৱিকিত থকা গোটসমূহৰ তালিকা সেইবোৰৰ প্ৰৱেশাধিকাৰসহ তলত দিয়া হ’ল ।\nসুকীয়া অধিকাৰ সম্পৰ্কে [[{{MediaWiki:Listgrouprights-helppage}}|অধিক তথ্য]] থাকিব পাৰে ।",
index dde90d0..48ab3ee 100644 (file)
        "yourpasswordagain": "M535x523S14c50508x492S14c58469x492S22520503x477S22520465x477 M518x531S33b00482x483S1f711482x509 M516x515S10018484x485S1f010487x485 M528x514S15a39472x487S28802506x486S18250481x499 S38a00464x490",
        "createacct-yourpasswordagain": "M535x523S14c50508x492S14c58469x492S22520503x477S22520465x477 M518x531S33b00482x483S1f711482x509 M516x515S10018484x485S1f010487x485 M528x514S15a39472x487S28802506x486S18250481x499",
        "createacct-yourpasswordagain-ph": "M535x523S14c50508x492S14c58469x492S22520503x477S22520465x477 M518x531S33b00482x483S1f711482x509 M516x515S10018484x485S1f010487x485 M528x514S15a39472x487S28802506x486S18250481x499",
-       "remembermypassword": "M538x567S1f548504x543S1f520513x534S1f520513x481S22b04522x499S2ff00482x483 M514x514S15a01491x487S20500487x503 M538x521S2a200497x480S20b00462x508S11530523x482S15a37462x483S11551470x493 M536x521S2ff00482x483S10011515x491S28108515x461 M508x525S10004493x475S22a04494x510 M523x528S14011492x504S15a00477x495S2b800483x473 S38b00470x493 M536x521S2ff00482x483S10011515x491S28108515x461 M519x530S18210496x475S18218482x471S20b00496x483S22b00495x500 $1 {{PLURAL:$1|M526x534S15a1a499x522S10010507x467S28903478x486S37706474x522S37700520x495}} S38b04470x493",
        "userlogin-remembermypassword": "M521x526S1f750501x511S1f758480x511S26620493x474 M521x517S10043491x483S20500479x506 M538x521S2a200497x480S20b00462x508S11530523x482S15a37462x483S11551470x493",
        "password-change-forbidden": "M518x584S10004492x534S22a04493x569S30a00482x483 M518x633S19220493x614S14020479x583S19220493x561S18620491x530S30a00482x483 S38700463x496 M508x523S10040493x493S26500493x477 M527x521S10059473x479S10051497x479S20e00494x491S22a04493x506 M521x532S10609498x496S10621487x512S21100500x483S2df20479x468 M518x531S33b00482x483S1f711482x509 M516x515S10018484x485S1f010487x485 S38800464x496",
        "login": "M538x521S2a200497x480S20b00462x508S11530523x482S15a37462x483S11551470x493",
        "permissionserrorstext": "M508x523S10040493x493S26500493x477 M534x542S2ff00482x483S26500520x505S20e00521x526S1f540493x518 M531x528S15a40511x472S15a48478x472S2d200505x505S2d211470x505 {{PLURAL:$1|M547x518S30a00482x483S22124511x473S1c517522x483}} S38900464x493",
        "permissionserrorstext-withaction": "M508x523S10040493x493S26500493x477 M534x542S2ff00482x483S26500520x505S20e00521x526S1f540493x518 M531x528S15a40511x472S15a48478x472S2d200505x505S2d211470x505 $2 {{PLURAL:$1|M547x518S30a00482x483S22124511x473S1c517522x483}} S38900464x493",
        "log-fulllog": "M525x524S2ff00482x483S10e00507x494S26500511x474 M520x529S20e00493x504S20348493x486S15a51497x471S26503480x516 M518x536S15a37483x465S18550493x476S15a37483x509S15a51486x513",
-       "cantcreateaccounttitle": "M527x521S10059473x479S10051497x479S20e00494x491S22a04493x506 M532x519S20302493x485S2030a489x502S21100509x504S26900516x482S26910468x501 M518x517S15a30482x489S1f750484x484S20500496x506S22a04505x495",
        "viewpagelogs": "M525x524S2ff00482x483S10e00507x494S26500511x474 M531x512S15a37501x488S1f550507x495S20e00487x499S26502469x498 M518x536S15a37483x465S18550493x476S15a37483x509S15a51486x513",
        "currentrev-asof": "M521x524S1f740501x509S1f748479x498S20e00503x494S22a00502x476 M536x534S35610482x483S10601513x506S21600525x501 M521x532S10609498x496S10621487x512S21100500x483S2df20479x468 M557x536S36d00479x503S10001536x498S10009510x506S2b711518x476S2b700531x465 $1",
        "revisionasof": "M513x542S1ce50491x458S22a00492x492S14c50487x511 M519x539S14402488x485S1440a481x461S22b04503x509 M536x521S2ff00482x483S10011515x491S28108515x461 $1",
        "logentry-newusers-autocreate": "M526x522S15a56499x510S11520503x479S20e00489x496S26a02474x489 M518x517S15a30482x489S1f750484x484S20500496x506S22a04505x495 $1 M531x531S14c30506x469S2a204508x503S2a21c470x503S14c38470x469 {{GENDER:$2|M532x519S20302493x485S2030a489x502S21100509x504S26900516x482S26910468x501}} M520x525S15a18480x490S10a02483x476S23100494x508S20e00500x494",
        "log-name-managetags": "M519x514S15a28482x487S11502489x498 M530x529S10640507x503S10648479x489S26c08503x484S26c18470x471 M518x536S15a37483x465S18550493x476S15a37483x509S15a51486x513",
        "log-name-tag": "M519x514S15a28482x487S11502489x498 M518x536S15a37483x465S18550493x476S15a37483x509S15a51486x513",
-       "feedback-error-title": "M518x526S2ff00482x483S19a00487x506",
        "searchsuggest-search": "M546x525S2ff00482x483S16d10492x505S2e502519x502",
        "api-error-mustbeloggedin": "M539x579S10e27506x534S10e09480x534S22a07495x565S22a17469x564S21b00531x528S21b00504x528S30a00482x483 M520x576S14c19480x549S15a01497x550S20710483x530S30a00482x483 S38700463x496 M516x519S10651485x482S22a04493x504 M538x521S2a200497x480S20b00462x508S11530523x482S15a37462x483S11551470x493 S38800464x496",
        "api-error-unclassified": "M536x518S2ff00482x483S15a11513x486S28108513x453 M518x526S2ff00482x483S19a00487x506 M528x529S10030509x499S10038477x499S2a200505x472S2a218473x472",
index 51b24c5..8a6dc4c 100644 (file)
        "views": "Vistes",
        "toolbox": "Ferramientes",
        "tool-link-userrights": "Cambiar los grupos {{GENDER:$1|del usuariu|de la usuaria}}",
+       "tool-link-userrights-readonly": "Ver los grupos {{GENDER:$1|del usuariu|de la usuaria}}",
        "tool-link-emailuser": "Unviar un corréu electrónicu a {{GENDER:$1|esti usuariu|esta usuaria}}",
        "userpage": "Ver la páxina d'usuariu",
        "projectpage": "Ver la páxina del proyeutu",
        "passwordreset-emaildisabled": "Les funciones de corréu electrónicu tan desactivaes nesta wiki.",
        "passwordreset-username": "Nome d'usuariu:",
        "passwordreset-domain": "Dominiu:",
-       "passwordreset-capture": "¿Ver el corréu electrónicu resultante?",
-       "passwordreset-capture-help": "Si marques esta caxella, podrás ver el corréu (cola contraseña temporal) amás d'unvialu al usuariu.",
        "passwordreset-email": "Direición de corréu electrónicu:",
        "passwordreset-emailtitle": "Detalles de la cuenta en {{SITENAME}}",
        "passwordreset-emailtext-ip": "Dalguién (seique vusté, dende la direición IP $1)solicitó'l reaniciu de la so contraseña de {{SITENAME}} ($4).\n{{PLURAL:$3|La cuenta d'usuariu siguiente ta asociada|Les cuentes d'usuariu siguientes tán asociaes}}\na esta direición de corréu electrónicu:\n\n$2\n\n{{PLURAL:$3|Esta contraseña provisional caduca|Estes contraseñes provisionales caduquen}} {{PLURAL:$5|nun día|en $5 díes}}.\nTendría d'aniciar sesión y escoyer una contraseña nueva agora. Si esta solicitú la fizo otra persona,\no si recordó la clave orixinal y yá nun quier camudala, pue escaecer esti mensaxe y siguir\nusando la contraseña antigua.",
        "passwordreset-emailelement": "Nome d'usuariu: \n$1\n\nContraseña temporal: \n$2",
        "passwordreset-emailsentemail": "Si esta direición de corréu electrónicu ta asociada cola to cuenta, unviaráse un corréu pa reaniciar la contraseña.",
        "passwordreset-emailsentusername": "Si hai una direición de corréu electrónicu asociada con esti nome d'usuariu, unviaráse un corréu electrónicu pa reaniciar la contraseña.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Unvióse'l corréu|Unviáronse los correos}} de reaniciu de contraseña. {{PLURAL:$1|El nome d'usuariu y la contraseña|La llista de nomes d'usuarios y contraseñes}} amuésase equí.",
-       "passwordreset-emailerror-capture2": "Nun pudo unviase un corréu electrónicu {{GENDER:$2|al usuariu|a la usuaria}}: $1 {{PLURAL:$3|El nome d'usuariu y la contraseña|La llista de nomes d'usuarios y contraseñes}} amuésase equí.",
        "passwordreset-nocaller": "Tien d'apurrise un llamador",
        "passwordreset-nosuchcaller": "El llamador nun esiste: $1",
        "passwordreset-ignored": "Nun se llogró'l reaniciu de la contraseña. ¿Seique nun se configuró un proveedor?",
-       "passwordreset-invalideamil": "Direición de corréu inválida",
+       "passwordreset-invalidemail": "Direición de corréu inválida",
        "passwordreset-nodata": "Nun s'apurrió nin un nome d'usuariu nin una dirección de corréu electrónicu",
        "changeemail": "Camudar o desaniciar la dirección de corréu electrónicu",
        "changeemail-header": "Completa esti formulariu pa camudar la dirección de corréu electrónicu. Si quies desaniciar l'asociación de cualquier dirección de corréu electrónicu de la to cuenta, dexa en blancu la nueva dirección de corréu electrónicu cuando unvies el formulariu.",
        "search-external": "Busca esterna",
        "searchdisabled": "La busca en {{SITENAME}} ta desactivada. Mentanto, pues buscar en Google.\nHas fixate en que'l conteníu de los sos índices de {{SITENAME}} pué tar desfasáu.",
        "search-error": "Hebo un error al buscar: $1",
+       "search-warning": "Hebo un avisu al buscar: $1",
        "preferences": "Preferencies",
        "mypreferences": "Preferencies",
        "prefs-edits": "Númberu d'ediciones:",
        "prefs-watchlist-edits-max": "Númberu máximu: 1000",
        "prefs-watchlist-token": "Pase de la llista de siguimientu:",
        "prefs-misc": "Varios",
-       "prefs-resetpass": "Camudar la conseña",
+       "prefs-resetpass": "Camudar la contraseña",
        "prefs-changeemail": "Camudar o desaniciar la dirección de corréu electrónicu",
        "prefs-setemail": "Conseñar una direición de corréu electrónicu",
        "prefs-email": "Opciones de corréu",
        "prefs-help-recentchangescount": "Incluye los cambios recientes, los historiales de páxines y los rexistros.",
        "prefs-help-watchlist-token2": "Esta ye la clave secreta pa la canal de noticies web de la so llista de vixilancia.\nCualquiera que la sepa podrá lleer la so llista de vixilancia; nun la comparta.\n[[Special:ResetTokens|Calque equí si necesita reaniciala]].",
        "savedprefs": "Guardáronse les preferencies.",
-       "savedrights": "Guardáronse los permisos d'{{GENDER:$1|usuariu|usuaria}} de $1.",
+       "savedrights": "Guardáronse los grupos {{GENDER:$1|del usuariu|de la usuaria}} $1.",
        "timezonelegend": "Estaya horaria:",
        "localtime": "Hora llocal:",
        "timezoneuseserverdefault": "Usar la predeterminada de la wiki ($1)",
        "prefs-help-gender": "Configurar esta preferencia ye opcional. El software usa esti valor pa dirixise a ti y pa mentate a terceros col xéneru gramatical correchu.\nEsta información sedrá pública.",
        "email": "Corréu",
        "prefs-help-realname": "El nome real ye opcional.\nSi se da, pue usase pa date reconocimientu pol to trabayu.",
-       "prefs-help-email": "La direición de corréu ye opcional, pero ye necesaria pa unviate una conseña nueva si escaeces la tuya.",
+       "prefs-help-email": "La direición de corréu ye opcional, pero ye necesaria pa unviate una contraseña nueva si escaeces la tuya.",
        "prefs-help-email-others": "Tamién pues escoyer permitir qu'otres persones contauten contigo pela to páxina d'usuariu o la d'alderique ensin necesidá de revelar la to identidá.",
        "prefs-help-email-required": "Necesítase una direición de corréu electrónicu.",
        "prefs-info": "Información básica",
        "prefswarning-warning": "Ficisti cambios nes tos preferencies qu'inda nun se guardaron.\nSi abandones esta páxina ensin calcar \"$1\" les preferencies nun s'anovarán.",
        "prefs-tabs-navigation-hint": "Gabitu: pue usar les tecles de flecha izquierda y drecha pa navegar peles llingüetes de la llista.",
        "userrights": "Xestión de permisos d'usuariu",
-       "userrights-lookup-user": "Xestión de grupos del usuariu",
+       "userrights-lookup-user": "Seleiciona un usuariu",
        "userrights-user-editname": "Escribe un nome d'usuariu:",
-       "editusergroup": "Editar los grupos {{GENDER:$1|del usuariu|de la usuaria}}",
+       "editusergroup": "Cargar los grupos d'usuariu",
        "editinguser": "Camudando los permisos {{GENDER:$1|del usuariu|de la usuaria}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Editar los grupos d'usuariu",
        "saveusergroups": "Guardar los grupos {{GENDER:$1|del usuariu|de la usuaria}}",
        "userrights-reason": "Motivu:",
        "userrights-no-interwiki": "Nun tienes permisu pa editar los derechos d'usuariu n'otres wikis.",
        "userrights-nodatabase": "La base de datos $1 nun esiste o nun ye llocal.",
-       "userrights-nologin": "Tien d'[[Special:UserLogin|aniciar sesión]] con una cuenta d'alministrador pa dar permisos d'usuariu.",
-       "userrights-notallowed": "Nun tien autorización p'amestar o desaniciar permisos d'usuariu.",
        "userrights-changeable-col": "Grupos que pues camudar",
        "userrights-unchangeable-col": "Grupos que nun pues camudar",
        "userrights-conflict": "¡Conflictu de cambiu de permisos d'usuariu! Por favor, revise y confirme los cambios.",
-       "userrights-removed-self": "Desaniciasti los tos propios permisos. Poro, yá nun tienes accesu a esta páxina.",
        "group": "Grupu:",
        "group-user": "Usuarios",
        "group-autoconfirmed": "Usuarios autoconfirmaos",
        "right-siteadmin": "Candar y descandar la base de datos",
        "right-override-export-depth": "Esportar páxines, incluyendo páxines enllazaes fasta una fondura de 5",
        "right-sendemail": "Unviar corréu a otros usuarios",
-       "right-passwordreset": "Ver los correos de reestablecimientu de conseña",
        "right-managechangetags": "Crear y (des)activar [[Special:Tags|etiquetes]]",
        "right-applychangetags": "Aplicar [[Special:Tags|etiquetes]] xunto colos cambios propios",
        "right-changetags": "Amestar y desaniciar [[Special:Tags|etiquetes]] arbitraries en revisiones individuales y entraes del rexistru",
        "apisandbox-continue": "Siguir",
        "apisandbox-continue-clear": "Llimpiar",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries siguirá] cola última solicitú; {{int:apisandbox-continue-clear}} llimpiará los parámetros rellacionaos con siguir.",
+       "apisandbox-param-limit": "Escribe <kbd>max</kbd> pa usar la llende máxima.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Tolos espacios de nomes)",
+       "apisandbox-multivalue-all-values": "$1 (Tolos valores)",
        "booksources": "Fontes de llibros",
        "booksources-search-legend": "Busca de fontes de llibros",
        "booksources-search": "Buscar",
        "activeusers-count": "$1 {{PLURAL:$1|edición|ediciones}} {{PLURAL:$3|nel caberu día|nos caberos $3 díes}}",
        "activeusers-from": "Amosar usuarios principiando dende:",
        "activeusers-groups": "Amosar los usuarios que pertenecen a los grupos:",
+       "activeusers-excludegroups": "Excluir a los usuarios que pertenezan a los grupos:",
        "activeusers-noresult": "Nun s'alcontraron usuarios.",
        "activeusers-submit": "Amosar los usuarios activos",
        "listgrouprights": "Drechos de los grupos d'usuariu",
        "pageinfo-few-visiting-watchers": "Puede haber, o non, un usuariu que vixila páxines que visita les ediciones recientes",
        "pageinfo-redirects-name": "Númberu de redireiciones a esta páxina",
        "pageinfo-subpages-name": "Subpáxines d'esta páxina",
-       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|redireición|redireiciones}}; $3 {{PLURAL:$3|non-redireición|non-redireiciones}})",
+       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|redireición|redireiciones}}; $3 {{PLURAL:$3|non redireición|non redireiciones}})",
        "pageinfo-firstuser": "Creador de la páxina",
        "pageinfo-firsttime": "Data de creación de la páxina",
        "pageinfo-lastuser": "Caberu editor",
        "tags-deactivate": "desactivar",
        "tags-hitcount": "$1 {{PLURAL:$1|cambiu|cambios}}",
        "tags-manage-no-permission": "Nun tienes permisu p'alministrar etiquetes de cambiu.",
-       "tags-manage-blocked": "Nun puedes xestionar etiquetes de cambiu mentanto teas bloquiáu.",
+       "tags-manage-blocked": "Nun puedes xestionar etiquetes de cambiu mentanto teas {{GENDER:$1|bloquiáu|bloquiada}}.",
        "tags-create-heading": "Crear una etiqueta nueva",
        "tags-create-explanation": "De mou predetermináu, les etiquetes nueves que se creen tarán disponibles pa que les usen los usuarios y bots.",
        "tags-create-tag-name": "Nome de la etiqueta:",
        "tags-deactivate-not-allowed": "Nun ye posible desactivar la etiqueta «$1».",
        "tags-deactivate-submit": "Desactivar",
        "tags-apply-no-permission": "Nun tienes permisu p'aplicar etiquetes de cambios xunto colos cambios.",
-       "tags-apply-blocked": "Nun puedes aplicar etiquetes de cambiu xunto colos cambios mentanto teas bloquiáu.",
+       "tags-apply-blocked": "Nun puedes aplicar etiquetes de cambiu xunto colos cambios mentanto teas {{GENDER:$1|bloquiáu|bloquiada}}.",
        "tags-apply-not-allowed-one": "Nun se permite aplicar manualmente la etiqueta «$1».",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|La siguiente etiqueta nun pue|Les siguientes etiquetes nun puen}} aplicase manualmente: $1",
        "tags-update-no-permission": "Nun tienes permisu p'amestar o desaniciar etiquetes de cambiu nes revisiones individuales o entraes del rexistru.",
-       "tags-update-blocked": "Nun puedes amestar o desaniciar etiquetes de cambiu mentanto teas bloquiáu.",
+       "tags-update-blocked": "Nun puedes amestar o desaniciar etiquetes de cambiu mentanto teas {{GENDER:$1|bloquiáu|bloquiada}}.",
        "tags-update-add-not-allowed-one": "Nun se permite amestar manualmente la etiqueta «$1».",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|La siguiente etiqueta nun pue|Les siguientes etiquetes nun puen}} amestase manualmente: $1",
        "tags-update-remove-not-allowed-one": "Nun se permite desaniciar la etiqueta «$1».",
        "htmlform-user-not-exists": "<strong>$1</strong> nun esiste.",
        "htmlform-user-not-valid": "<strong>$1</strong> nun ye un nome d'usuariu válidu.",
        "logentry-delete-delete": "$1 {{GENDER:$2|desanició}} la páxina $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|desanició}} la redireición $3 sobreescribiéndola",
        "logentry-delete-restore": "$1 {{GENDER:$2|restauró}} la páxina $3",
        "logentry-delete-event": "$1 {{GENDER:$2|camudó}} la visibilidá {{PLURAL:$5|d'un socesu del rexistru|de $5 socesos del rexistru}} en $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|camudó}} la visibilidá {{PLURAL:$5|d'una revisión|de $5 revisiones}} na páxina $3: $4",
        "mw-widgets-dateinput-no-date": "Nenguna data seleicionada",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Buscar multimedia",
+       "mw-widgets-mediasearch-noresults": "Nun s'alcontraron resultaos.",
        "mw-widgets-titleinput-description-new-page": "la páxina inda nun esiste",
        "mw-widgets-titleinput-description-redirect": "redirixir a $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Amestar una categoría...",
        "sessionmanager-tie": "Nun puen combinase dellos tipos de solicitú d'identificación: $1.",
        "sessionprovider-generic": "sesiones $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sesiones basaes en cookies",
        "log-action-filter-contentmodel-change": "Cambéu de modelu de conteníu",
        "log-action-filter-contentmodel-new": "Creación de páxina con modelu de conteníu non estándar",
        "log-action-filter-delete-delete": "Desaniciu de páxines",
+       "log-action-filter-delete-delete_redir": "Sobreescritura de redireición",
        "log-action-filter-delete-restore": "Restauración de páxines",
        "log-action-filter-delete-event": "Desaniciu de rexistros",
        "log-action-filter-delete-revision": "Desaniciu de revisión",
        "usercssispublic": "Atención: les subpáxines CSS nun tendríen de contener datos acutaos porque son visibles pa otros usuarios.",
        "restrictionsfield-badip": "Direición o rangu IP inválidu: $1",
        "restrictionsfield-label": "Rangos d'IP permitíos:",
-       "restrictionsfield-help": "Una única direición IP o rangu CIDR per llinia. P'activar toos, utiliza<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Error: $1",
-       "edit-error-long": "Errores:\n\n$1"
+       "restrictionsfield-help": "Una única direición IP o rangu CIDR per llinia. P'activar toos, utiliza<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index dca9dfe..e2ea9aa 100644 (file)
        "yourpasswordagain": "Пароль такрар гьабе:",
        "createacct-yourpasswordagain": "Пароль ритIухъ гьабе",
        "createacct-yourpasswordagain-ph": "Пароль цоги нухалъ хъвай",
-       "remembermypassword": "Дир цIарги парольги гьаб компьютералда цIунизе (гIицIго $1 {{PLURAL:$1|къоялъ}})",
        "userlogin-remembermypassword": "Системаялда чӀезе",
        "yourdomainname": "Дур домен:",
        "password-change-forbidden": "Гьаб викиялда пароль хисизабун бажаруларо дуда.",
index 0081c7e..b8ca12d 100644 (file)
        "yourname": "Rinaf favesikyolt",
        "yourpassword": "Rinaf remravlem",
        "yourpasswordagain": "Va rinaf remravlem tolon bazel",
-       "remembermypassword": "Setikera va jinaf remravlem koe bati nedisiki (kali cugon $1 {{PLURAL:$1|viel|viel}})",
        "yourdomainname": "Rinaf ind",
        "externaldberror": "Ont divefa origakrokla va pilkomodara ont va rinafa divefa pata me ronuskel.",
        "login": "Pilkomodá",
        "undo-failure": "Betaks me zo rodimaskir golde kobodas walif betaks yo.",
        "undo-norev": "Dimbetara tir merotisa golde metira ok sulara.",
        "undo-summary": "Dimaskira va $1 betaks ke [[Special:Contributions/$2|$2]] ([[User talk:$2|Prilara]])",
-       "cantcreateaccounttitle": "Pataredura me tir",
        "cantcreateaccount-text": "Pataredura male bate IP ('''$1''') mane gan [[User:$3|$3]] zo elekayar.\n\nBazeyena lazava ke $3 tir ''$2''.",
        "viewpagelogs": "Wira va \"logs\" ke batu bu",
        "nohistory": "Nedoy izvot va batu bu.",
index 1a6b71d..96529ac 100644 (file)
        "yourpasswordagain": "गुप्त कुंजी एक दाँइ अउर लिखो:",
        "createacct-yourpasswordagain": "गुप्त कुंजी कय पुष्टि करो",
        "createacct-yourpasswordagain-ph": "गुप्त कुंजी फिर से लिखो",
-       "remembermypassword": "इ ब्राउज़र पे हमार लॉगिन याद रखो (अधिकतम $1 {{PLURAL:$1|दिन|दिन}} कय लिए)",
        "userlogin-remembermypassword": "हम्मै लॉग्ड इन रखो",
        "userlogin-signwithsecure": "सुरक्षित कनेक्शन कय प्रयोग करो",
        "yourdomainname": "आप कय डोमेन:",
        "passwordreset-emailtext-user": "{{SITENAME}} ($4) पे सदस्य $1 आपकय {{PLURAL:$3|खाता}} कय गुप्तकुंजी कय रीसेट करेक अनुरोध करे हैं। इ ई-मेल ठहर से इ {{PLURAL:$3|खाता जोडान है}}:\n\n$2\n\n{{PLURAL:$3|ई}} अस्थायी गुप्तकुंजी {{PLURAL:$5|दिन}} कय बाद काम नाइ करि।\nआप लॉग इन कइकै एकठु नँवा गुप्त कुंजी अभीन लै लेक चाहि। यदि इ अनुरोध केहु दुसर करे है, या फिर आप कय आपन गुप्त कुंजी याद आई गा है, अव आप {{PLURAL:$3|आपन}} गुप्तकुंजी नाई बदलेक चाहा जात है, आप इ संदेश कय अनदेखा कई कय आपन पुरान गुप्तकुंजी कय प्रयोग कइ सका जात है।",
        "passwordreset-emailelement": "सदस्यनाँव: \n$1\n\nअस्थायी गुप्तकुंजी: \n$2",
        "passwordreset-emailsentemail": "एक गुप्तकुंजी रीसेट ई-मेल भेज दिहा गा है।",
-       "passwordreset-emailsent-capture": "नीचे जवन देखावा है ओकर गुप्तकुंजी रीसेट ई-मेल भेज दिहा गा है।",
-       "passwordreset-emailerror-capture": "नीचे दिहा गुप्त कुंजी रीसेट ई-मेल पैदा भा रहा, लेकिन ओका {{GENDER:$2|सदस्य}} कय भेजब असफल रहा।\nत्रुटि: $1",
        "changeemail": "ईमेल ठाँव बदला जाय",
        "changeemail-header": "अपना ई-मेल पता परिवर्तित करने के लिए इस फ़ॉर्म को पूरा करें। इस बदलाव की पुष्टि करने के लिये आपको अपना कूटशब्द पुनः लिखना पड़ेगा।",
        "changeemail-no-info": "इ पन्ना कय सीधय प्रयोग करेक लिए आप कय लॉग इन करेक परि।",
        "undo-nochange": "अईसन लागत है की ई सम्पादन कय पहिलवे पहिले जैसन कई दीहा है ।",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|बातचीत]]) कय करल बदलाव $1 कय पहिले जईसन कई गय",
        "undo-summary-username-hidden": "लुकुआवल सदस्यन् कय करल बदलाव $1 कय पहिले जईसन कई गय",
-       "cantcreateaccounttitle": "खाता नाई खोली सका जात है",
        "cantcreateaccount-text": "इ आइ॰पी ठहर ('''$1''') कय खाता बनावे कय [[User:$3|$3]] रोक लगाए हैँ।\n\nएकरे लिये $3 ''$2'' कारण दिहे हैं।",
        "cantcreateaccount-range-text": "<strong>$1</strong> कय श्रेणी में आवे वाला आई॰पी ठहर से, जवनेमें आप कय आई॰पी ठहर (<strong>$4</strong>) शामिल है, नँवा खाता बनावे कय लिए [[User:$3|$3]] अवरोधित कई गा है। \n\n$3 द्वारा दिया गया कारण है: \"$2\"",
        "viewpagelogs": "इस पन्ना कय लॉग देखा जाय",
        "activeusers-intro": "इ सक्रिय सदस्यन् कय सूची होय जे पिछला $1 {{PLURAL:$1|दिन}} में कुछ काम करें है।",
        "activeusers-count": "$1 {{PLURAL:$1|काम}} पिछला $3 {{PLURAL:$3|दिन}} में",
        "activeusers-from": "इ अक्षर से शुरु होय वाले सदस्य देखावा जाय:",
-       "activeusers-hidebots": "बॉट लुकुआवा जाय",
-       "activeusers-hidesysops": "प्रबंधक लुकुआवा जाय",
        "activeusers-noresult": "कवनो सदस्य नाइ मिलें ।",
        "listgrouprights": "सदस्य समूह अधिकार",
        "listgrouprights-summary": "नीचे इ विकि खर्तीन परिभाषित सदस्य समूहन् कय सूची होय, सथवे में हर समूह से जोड़ान अधिकारो है।\nहर अधिकार कय बारे में [[{{MediaWiki:Listgrouprights-helppage}}|ढेर जानकरीओ]] उपलब्ध है।",
        "htmlform-chosen-placeholder": "एक्ठु विकल्प चुना जाय",
        "htmlform-cloner-create": "अउर जोडा जाय",
        "htmlform-cloner-delete": "हटावा जाय",
-       "sqlite-has-fts": "$1 पूर्ण पाठ खोज समर्थन कय साथ",
-       "sqlite-no-fts": "$1पूर्ण-पाठ खोज समर्थन कय बिना",
        "logentry-delete-delete": "$1 ने पृष्ठ $3 {{GENDER:$2|हटा}} दिहा गय",
        "logentry-delete-restore": "$1 ने पृष्ठ $3 कय {{GENDER:$2|पुनर्स्थापित}} कै गय",
        "logentry-delete-event": "$1 ने $3 पृष्ठ की लॉग {{PLURAL:$5|प्रविष्टि|प्रविष्टियों}} की दृश्यता {{GENDER:$2|बदली}}: $4",
        "feedback-cancel": "रद्द करा जाय",
        "feedback-close": "होइ गवा",
        "feedback-dialog-title": "प्रतिक्रिया भेजा जाय",
-       "feedback-error-title": "त्रुटि",
        "feedback-error1": "त्रुटि: न पहचाना गया परिणाम एपीआई से",
        "feedback-error2": "त्रुटि: संपादन विफल रहा है",
        "feedback-error3": "त्रुटि: एपीआई से कोई प्रतिक्रिया नहीं",
index d16eafd..b48c450 100644 (file)
        "aboutpage": "Project:İzah",
        "copyright": "Bu məzmun $1 əhatəsindədir.",
        "copyrightpage": "{{ns:project}}:Müəllif",
-       "currentevents": "Güncəl hadisələr",
-       "currentevents-url": "Project:Güncəl hadisələr",
+       "currentevents": "Aktual hadisələr",
+       "currentevents-url": "Project:Aktual hadisələr",
        "disclaimers": "Məsuliyyətdən imtina",
        "disclaimerpage": "Project:Məsuliyyətdən imtina",
        "edithelp": "Redaktə kömək",
        "userrights-reason": "Səbəb:",
        "userrights-no-interwiki": "Sizə başqa vikilayihələrdəki istifadəçilərin statusunu dəyişməyə icazə verilməyib",
        "userrights-nodatabase": "$1 verilənlər bazası ya mövcud deyil, ya da lokal deyil.",
-       "userrights-nologin": "Siz istifadəçilərin hüquqlarını dəyişmək üçün sistemə idarəçi olaraq [[Special:UserLogin|daxil olmalısınız]].",
-       "userrights-notallowed": "Sizin digər istifadəçilərə hüquqlar vermək və ya almaq icazəniz yoxdur.",
        "userrights-changeable-col": "Dəyişdirə bildiyiniz qruplar",
        "userrights-unchangeable-col": "Dəyişdirə bilmədiyiniz qruplar",
        "userrights-irreversible-marker": "$1*",
index 0f353de..d06e28e 100644 (file)
        "hidden-category-category": "گیزلی بؤلمه‌لر",
        "category-subcat-count": "{{PLURAL:$2|بۇ بؤلمه‌ده تکجه آشاغیداکی آلت‌بؤلمه واردیر.|بۇ بؤلمه‌ده، جمعی $2-دن، آشاغیداکی {{PLURAL:$1|آلت‌بؤلمه|$1 آلت‌بؤلمه}} واردیر.}}",
        "category-subcat-count-limited": "بۇ بؤلمه‌ده آشاغیداکی {{PLURAL:$1|آلت‌بؤلمه|$1 آلت‌بؤلمه}} واردیر.",
-       "category-article-count": "{{PLURAL:$2|بۇ بؤلمه‌ده یالنیز آشاغیداکی صحیفه واردیر.|بۇ بؤلمه‌ده توْپلام $2 صحیفه‌دن، آشاغیداکی {{PLURAL:$1|صحیفه|$1 صحیفه}} واردیر.}}",
-       "category-article-count-limited": "بۇ بؤلمه‌ده، آشاغیداکی {{PLURAL:$1|صحیفه|$1 صحیفه}} واردیر.",
+       "category-article-count": "{{PLURAL:$2|بۇ بؤلمه‌ده تکجه آشاغیداکی صفحه واردیر.|بۇ بؤلمه‌ده جمعی $2 صفحه‌دن، آشاغیداکی {{PLURAL:$1|صفحه|$1 صفحه}} واردیر.}}",
+       "category-article-count-limited": "بۇ بؤلمه‌ده، آشاغیداکی {{PLURAL:$1|صفحه|$1 صفحه}} واردیر.",
        "category-file-count": "{{PLURAL:$2|بۇ بؤلمه‌ده یالنیز آشاغیداکی فایل واردیر.|بۇ بؤلمه‌ده توْپلام $1-دن، آشاغیداکی {{PLURAL:$1|فایل|$1 فایل}} واردیر.}}",
        "category-file-count-limited": "بۇ بؤلمه‌ده، آشاغیداکی {{PLURAL:$1|فایل|$1 فایل}} واردیر.",
        "listingcontinuesabbrev": "(قالانی)",
        "virus-badscanner": "پیس تنظیملر: تانینمامیش ویروس یوخلایان: ''$1''",
        "virus-scanfailed": "یوخلاماق باشا چاتمادی (کود $1)",
        "virus-unknownscanner": "تانینمامیش آنتی‌ویروس:",
-       "logouttext": "<strong>سÛ\8cز Ø§Û\8cÙ\86دÛ\8c Ø³Û\8cستÙ\90Ù\85â\80\8cدÙ\86 Ú\86Û\8cخدÛ\8cÙ\86Û\8cز.</strong>\n\nبÙ\88Ù\86ا Ø¯Û\8cÙ\82ت Ø§Ø¦Ø¯Û\8cÙ\86 Ú©Û\8c Ù\88ب Ø­Ø§Ù\81Û\8cظÙ\87 Ù\86Û\8cزÛ\8c Ø³Û\8cÙ\84Ù\85Ù\87 Û\8cÙ\86Ø\8cبعضÛ\8c ØµØ­Û\8cÙ\81Ù\87â\80\8cÙ\84ر Ú©Ù\8eØ´-Û\8cÙ\86Û\8cزÛ\8c Ø³Û\8cÙ\84Ù\85Ù\87â\80\8cÙ\85Û\8cØ´ Ú©Û\8cÙ\85Û\8cØ\8c Ù\87Ù\84Ù\87 Ø¯Ù\87 Ø³Û\8cزÛ\8cÙ\86 Ú¯Û\8cرÛ\8cØ´ Ø§Ø¦ØªØ¯Û\8cÚ¯Û\8cÙ\86Û\8cز Ú©Û\8cÙ\85Û\8c Ú¯Ø¤Ø³ØªØ±Û\8cÙ\84Ù\87â\80\8cجکلر.",
+       "logouttext": "<strong>سÛ\8cز Ø§Û\8cÙ\86دÛ\8c Ø³Û\8cستÙ\90Ù\85â\80\8cدÙ\86 Ú\86Û\8cخدÛ\8cÙ\86Û\8cز.</strong>\n\nدÛ\8cÙ\82تï¼\9aÙ\88ب Ø­Ø§Ù\81Û\8cظÙ\87 Ù\86Û\8cزÛ\8c Ø³Û\8cÙ\84Ù\85Ù\87 Û\8cÙ\86Ù\87 Ù\82درØ\8cبعضÛ\8c ØµÙ\81Ø­Ù\87â\80\8cÙ\84ر Ù\87Ù\84Ù\87 Ø¯Ù\87 Ø³Û\8cستÙ\85دÛ\8cÙ\85Û\8cشسÛ\8cÙ\86ز Ú©Û\8cÙ\85Û\8c Ú¯Ø¤Ø±Ù\88Ù\86Ù\87 Ø¨Û\8cلر.",
        "cannotlogoutnow-title": "ایندی چیخیش اوْلونمازدیر",
        "cannotlogoutnow-text": "$1-ی ایشلدرکن چیخیش اوْلونمازدیر.",
        "welcomeuser": "خوش گلمیسینیز، $1!",
        "userlogin-yourpassword-ph": "رمزینیزی یازین",
        "createacct-yourpassword-ph": "رمزی یازین",
        "yourpasswordagain": "رمزی یئنی‌دن یازین:",
-       "createacct-yourpasswordagain": "رÙ\85زÛ\8c Ø¯Ù\88غرÙ\88Ù\84اÛ\8cین",
+       "createacct-yourpasswordagain": "رÙ\85زÛ\8c ØªØ£Û\8cÛ\8cد Ø§Ø¦Ø¯ین",
        "createacct-yourpasswordagain-ph": "رمزی یئنی‌دن یازین",
        "userlogin-remembermypassword": "منی ایچری‌ده ساخلا",
        "userlogin-signwithsecure": "آرخایین باغلانتی ایشلدین",
        "botpasswords-updated-title": "روْبات پسووْردو آپدئیت اوْلوندو.",
        "botpasswords-deleted-title": "روْبات پسووْردو سیلیندی",
        "resetpass_forbidden": "رمزلر دَییشیلمز",
-       "resetpass-no-info": "بو صحیفه‌نی دوغرو گؤردوگونوز اوچون سیستمه گیرمه‌لیسینیز.",
+       "resetpass-no-info": "بو صفحه‌نی بیرباشا آچماق اوچون سیستمه گیرمه‌لیسینیز.",
        "resetpass-submit-loggedin": "رمزی دَییشدیر",
        "resetpass-submit-cancel": "وازگئچ",
        "resetpass-wrong-oldpass": "یانلیش گئچیجی و یا ایندیکی رمز.\nسیز باجارییلا رمزینیزی دَییشدیریب یوخسا یئنی گئچرلی رمز ایسته‌میش اوْلدوغونوز مؤحتمل‌دیر.",
        "passwordreset-emaildisabled": "ایمیل اؤزل‌لیکلری بو ویکی‌ده باغلانیب‌دیر.",
        "passwordreset-username": "ایشلدن آدی:",
        "passwordreset-domain": "دامنه:",
-       "passwordreset-capture": "سون نتیجه ایمیل گؤستریلسین؟",
-       "passwordreset-capture-help": "بو قوطویا علامت قویساز، (گئچیجی رمزی اولان) ایمیل ایستیفاده‌چی‌یه گؤندریلن کیمی بوردا سیزه گؤستریله‌جکدیر.",
        "passwordreset-email": "ایمیل آدرسی:",
        "passwordreset-emailtitle": "{{SITENAME}}-ده حساب بیلگیلری",
        "passwordreset-emailtext-ip": "بیر کس (احتیمالاً سیز، $1 آی‌پی آدرسی‌له)، {{SITENAME}} ($4) سایتینداکی حسابینیز اوچون رمزی یئنیله‌مک ایسته‌ییب‌دیر. آشاغیداکی ایستیفاده‌چی {{PLURAL:$3|حسابی|حسابلاری}} بو ایمیل ایله ایلگی‌لی‌دیرلر:\n\n$2\n\nبو گئچیجی {{PLURAL:$3|رمز|رمزلر}}، {{PLURAL:$5|بیر گون|$5 گون}}‌ده {{PLURAL:$3|واختی|واختلاری}} قورتاراجاق‌دیر.\nسیز گرک ایندی سایتا گیریب و یئنی بیر رمز سئچه‌سینیز. باشقا آدام بو ایستَگی وئرمیش‌سه، یوخسا سیز اسکی رمزینیزی یادا گتیرمیشسینیزسه، و داها اونو چئویرمک ایسته‌میرسینیزسه، بو مئساژی سایماییب و اسکی رمزینیزی ایشلدمگه داوام ائده بیلرسینیز.",
        "passwordreset-emailsentemail": "بۇ ایمئیل آدرسی حسابینیزا ثبت اوْلونموشسا٬ بیر رمز یئنیله‌مه ایمئیلی گؤندریله‌جکدیر.",
        "changeemail": "ایمیل آدرسینی دَییشدیر یا سیل",
        "changeemail-header": "ایمیل آدرسیزی دَییشدیرمک اوچون بو فورمو دولدورون. حسابیزا بوتون ایمیل‌لرین ارتباطینی کسمک اوچون، یئنی ایمیل آدرسینی بوش ساخلایین.",
-       "changeemail-no-info": "بو صحیفه‌نی دوغرو گؤردوگونوز اوچون سیستمه گیرمه‌لیسینیز.",
+       "changeemail-no-info": "بو صفحه‌نی بیرباشا آچماق اوچون سیستمه گیرمه‌لیسینیز.",
        "changeemail-oldemail": "ایندیکی ایمیل آدرس:",
        "changeemail-newemail": "یئنی ایمیل آدرسی:",
        "changeemail-none": "(هئچ)",
        "accmailtext": "[[User talk:$1|$1]] اوچون بیر راست‌گله رمز یارادیلیب و $2-ه گؤندریلدی.\n\nبو یئنی حسابین رمزی، گیرندن سونرا <em>[[Special:ChangePassword|رمز دَییشدیرمه]]</em> صحیفه‌سیندن دَییشیله بیلر.",
        "newarticle": "(یئنی)",
        "newarticletext": "مووجود اوْلمايان صفحه‌‌يه اوْلان لینکی ایزله‌دینیز. \nآشاغیداکی یئره یازیلارینیزی يازیب، بۇ صفحه‌‌نی '''سیز''' يارادا بیلرسینیز. (آرتیق معلومات اۆچون [$1 کؤمک صفحه‌‌سینه] باخین). اگر بۇ صفحه‌‌يه ایشتباه گلمیسینیزسه تکجه براوزرین '''قایید''' دۆيمه‌سینه وۇرون.",
-       "anontalkpagetext": "''بو صحیفه قئیدیات‌دان کئچممیش و یا داخیل اولمامیش آنونیم ایستیفادچییه عایید موذاکیره صحیفه‌سی‌دیر.\nاونا گؤره بو ایستیفادچینی رقم‌لردن عبارت ایپ اونوانی ایله معین ائتمک مجبوریتیندییک.\nبئله ایپ اونوان بیر نئچه فرد طرفین‌دن ایستیفاده‌ده اولا بیلر.\nاگر سیز آنونیم ایستیفادچیسینیزسه و بو مئساژین سیزه عایید اولمادیغینی دوشونورسونوزسه، اوندا  [[Special:CreateAccount|قئیدیات‌دان کئچین]] و یا [[Special:UserLogin|داخی اولون]].''",
+       "anontalkpagetext": "----<em>بو صفحه حسابسیز و یا سیستمه گیرمه میش تانیلماز ایشلدنه مربوط دانیشیق صفحه‌سی‌دیر.\nاونا گؤره بو ایشلدنی رقم‌لردن عبارت ایپی آدرسی ایله بللیلشدیریلیبدیر.</em>\nبئله آیپی آدرسی بیر نئچه فرد طرفین‌دن ایستیفاده‌ده اولا بیلر.\nاگر سیز تانیلماز ایشلدنسینیز و بو پیامین سیزه مربوط اولمادیغینی دوشونورسونوزسه، اوندا  [[Special:CreateAccount|حساب یارادین]] و یا [[Special:UserLogin|سیستمه گیرین]].''",
        "noarticletext": "ایندی بو صفحه‌ده یازی یوخدور.\nسیز آیری صفحه‌‌لرده [[Special:Search/{{PAGENAME}}|بو باشلیق اوچون آختارا بیلرسیز]]،\nیا دا <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} باغلی قئیدلری آختارا بیلرسیز]،\nیا دا [{{fullurl:{{FULLPAGENAME}}|action=edit}} بو صفحه‌نی دَییشدیره بیلرسیز]</span>.",
        "noarticletext-nopermission": "بو صحیفه‌‌ ایندی بوشدور. \nباشقا صحیفه‌‌لرده عینی آددا صحیفه‌‌نی  [[Special:Search/{{PAGENAME}}| آختار]], علاقه‌‌لی قئيدلره \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} باخا],\nو يا صحیفه‌‌نی  [{{fullurl:{{FULLPAGENAME}}|action=edit}} redaktə]</span> ائده بیلرسینیز.",
        "missing-revision": "«{{FULLPAGENAME}}» صحیفه‌سی اوچون $1 نومره‌لی نوسخه یوخدور.\n\nعموماُ بو ایشکال، واختی گئچمیش بیر باغلانتی ایله سیلینمیش بیر صحیفه‌یه گلنده، قاباغا گلر.\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیلمک سیاهی]‌سینده باشقا بیلگیلر اولا بیلر.",
        "userinvalidcssjstitle": "خاتیرلادیرق:' '\"$1\" آدییلا بیر پوشه یوخ‌دور. پوشه-آدی.css و. js فایل‌لارینین آدلاری کیچیک حرف ایله یازماسی لازیم‌دیر، یعنی {{ns:user}}: تمل / vector.css دئییل، {{ns:user}}: تمل / Vector.css.",
        "updated": "(گونجل‌لندی)",
        "note": "'''دیقت:'''",
-       "previewnote": "'''بونون ساده‌جه بیر سیناق گؤستریشی اولدوغونو نظرده آلین.'''\nسیزین دییشیکلرینیز هله قئید اولونماییب!",
+       "previewnote": "<strong>بونون تکجه بیر سیناق گؤستریشی اولدوغونو نظرده آلین.</strong>\nسیزین دییشیکلرینیز هله ذخیره اولونماییب!",
        "continue-editing": "دَییشدیرمه یئرینه گئت",
        "previewconflict": "بو سیناق گؤستریشی‌دیر و یادداشدا ساخلایاجاغینیز تق‌دیرده متنین دییشدیر صحیفه‌سی‌نین یوخاری حیسه‌سینده نتیجه‌نین نئجه اولاجاغینی گؤستریر.",
        "session_fail_preview": "'''عۆذر ایسته‌ییریک! سیزین دییشدیرمه‌نیز یازدیریلمادی. \nسیستمدن چیخمیش اوْلدوغونوز مؤحتمل‌دیر. لۆطفاً سیستمه گیرمیش اوْلدوغونوزدان آرخایین اوْلوب بیر داها تکرار ائدین. \nمۆشکول حل اوْلونماسا حسابینیزدان [[Special:UserLogout|چیخیب]] یئنی‌دن گیریش ائدین٬ براوزرینیزین بۇ سایتا کوکی وئرمه ایجازه‌سینی وئردیگیندن ده آرخایین اوْلون.'''",
        "longpageerror": "خطا: داخیل متنین اوزون‌لوغو قبول ائدیله بیلر ان چوخ اوزونلوق اولان {{PLURAL:$2 | بیر کیلوبایت | $2 کیلوبایت}} دان چوخ‌دور و {{PLURAL:$1 | بیر کیلوبایت | $1 کیلوبایت}} بؤیوکلوگونده‌دیر.'\nدییشیک‌لیگی‌نین کایدئدیلئمئز.",
        "readonlywarning": "'''دیقت: باخیم سببی ایله دیتابیس بو آندا قیفیللی‌دیر. بو سببله دییشیک‌لیکلری‌نین بو آندا قئید ائدیل میه‌جکدیر. یازدیقلارینیزی باشقا بیر فایل‌دا آلیب ساخلایا و داها سونرا یئنی‌دن بورا گتیریب یازا بیلرسینیز.\n\nاونو قیفیل‌لایان ایداره‌چی، بو شرحی وئریب‌دیر: $1",
        "protectedpagewarning": "' 'خاطیرلیریق: بو ​​صحیفه باغلانیب دیر و یالنیز مودیر اولان‌لار طرفین‌دن دییش‌دیریله بیلر.'\nسون گونده‌لیک گیردی‌سی ایستیناد مقصدلی آشاغیدا وئریلمیش‌دیر:",
-       "semiprotectedpagewarning": "'قئید:' بو صحیفه محافظه‌لی اولدوغو اوچون یالنیز قئیدیات‌دان کئچمیش ایستیفاده‌چی‌لر دییشدیر ائده بیلرلر.",
+       "semiprotectedpagewarning": "<strong>دیقت:</strong> بو صفحه نی قوروندوغو اوچون تکجه تایید اولونموش ایشلدنلر دییشدیره بیلر.\n\nسون قورومالار ژورنالی آشاغیدا گلیبدیر:",
        "cascadeprotectedwarning": "<strong>خاطیرلایریق:</strong> بو صحیفه بو یئرده {{PLURAL:$1|صحیفهٔ|صحیفه‌لر}} یئرلشمگه گوره آبشاری حفظ اولونوب آلتیندا باغلانیب بونجه مودیر فقط ائلیه بیله‌لر دییشدیر ائده بیلسینلر",
        "titleprotectedwarning": "'دیققت! بو صحیفه محافظه‌لی‌دیر، یالنیز [[Special:ListGroupRights|ایجازه سی اولان]] ایستیفاده‌چی‌لر اونو دییشدیر ائده بیلرلر.'",
        "templatesused": "{{PLURAL:$1|شابلون}} بو صفحه‌ده ایشلنیب‌دیر:",
        "content-failed-to-parse": "تجزیه محتوای $2  مدل اوچون $1: $3 موفقیت اله گلمه دی",
        "invalid-content-data": "اعتبارسیز مضمون معلوماتی",
        "content-not-allowed-here": "\"$1\" مقاله‌سینه، [[$2]] صحیفه‌سینده ایجازه وئریلممیش دیر.",
-       "editwarning-warning": "بو صحیفه‌نی ترک ائتمک، دَییشدیرمه‌لرینیزی الدن وئرمگه سبب اولا بیلر. اگر گیریش ائتمیسینیز بو ایخطاری، ترجیحلرینیزین «دَییشدیرمک» بؤلوموندن، \"{{int:prefs-editing}}\"ایشدن سالا بیلرسینیز.",
+       "editwarning-warning": "بو صفحه‌دن چیخماق، دَییشدیرمه‌لرینیزی الدن وئرمگه سبب اولا بیلر. اگر گیریش ائتمیسینیز بو ایخطاری، ترجیحلرینیزین «دَییشدیرمک» بؤلوموندن، \"{{int:prefs-editing}}\"ایشدن سالا بیلرسینیز.",
        "editpage-notsupportedcontentformat-title": "فایلین فرمتی دستکلنمیر.",
        "editpage-notsupportedcontentformat-text": "$1 فایلین فرمتی  $2 فایل مدلی ایله دستکلنمیر.",
        "content-model-wikitext": "ویکی‌یازی",
        "currentrev-asof": "$1 تاریخینه کیمی سون حال",
        "revisionasof": "$1 نوسخه‌سی",
        "revision-info": "$1- یارادیلمیش نوسخه{{GENDER:$6|$2}}$7 الیله",
-       "previousrevision": "قاباق‌کی سۆروم",
+       "previousrevision": "قاباقکی نوسخه",
        "nextrevision": "داها یئنی نوسخه ←",
        "currentrevisionlink": "سون نوسخه",
        "cur": "ایندی",
        "page_last": "سون",
        "histlegend": "فرقلری سئچمه: موقاییسه ائتمک ایسته‌دیگینیز دییشیک‌لیکلرین یانینداکی گیرده دۆیمه‌لره علامت قویون و سوْنرا Enter-ی وۇروب یوْخسا آشاغیداکی دۆیمه‌نی وورون.<br />\nآچیقلاما:'''({{int:cur}})''' =سون نوسخه ایله فرقلر ، '''({{int:last}})''' = قاباقکی نوسخه ایله فرقلر، '''{{int:minoreditletter}}''' = کیچیک دییشیک‌لیک.",
        "history-fieldset-title": "گئچمیشی آختار",
-       "history-show-deleted": "یالنیز سیلینَنلر",
+       "history-show-deleted": "تکجه سیلینَنلر",
        "histfirst": "ان اسکی",
        "histlast": "ان یئنی",
        "historysize": "({{PLURAL:$1|بیر|$1}} بایت)",
        "difference-title-multipage": "«$1» و «$2» صحیفه‌لرین آراسینداکی فرقلر",
        "difference-multipage": "(صفحه‌لر آراسینداکی فرق‌لر)",
        "lineno": "خط $1:",
-       "compareselectedversions": "سئÚ\86Û\8cÙ\84Ù\85Û\8cØ´ Ù\86Ù\88سخÙ\87â\80\8cÙ\84رÛ\8c Ù\82ارشÛ\8cÙ\84اشدÛ\8cر",
+       "compareselectedversions": "سئÚ\86Û\8cÙ\84Ù\85Û\8cØ´ Ù\86Ù\88سخÙ\87â\80\8cÙ\84رÛ\8c Ù\85Ù\88Ù\82اÛ\8cسÙ\87 Ø§Ø¦Øª",
        "showhideselectedversions": "سئچیلمیش نوسخه‌لری گؤستر/گیزلد",
        "editundo": "قایتار",
        "diff-empty": "فرقیسیز",
        "searchprofile-advanced-tooltip": "تاپشیریلان آدفضالاریندا آختار",
        "search-result-size": "$1 ({{PLURAL:$2|۱ سؤزجوک|$2 سؤزجوک}})",
        "search-result-category-size": "{{PLURAL:$1|بیر|$1}} عوضو ({{PLURAL:$2|بیر|$}} آلت‌بؤلمه، {{PLURAL:$3|بیر|$3}} فایل)",
-       "search-redirect": "یول‌لاندیرما $1",
+       "search-redirect": "($1-دن يوْل‌لاندیریلمیش)",
        "search-section": "(بؤلوم $1)",
        "search-category": "(رده  $1)",
        "search-file-match": "(فایلین ایچری اوخشاری)",
        "userrights-reason": "ندن:",
        "userrights-no-interwiki": "سیزه باشقا ویکی لايیهه‌لرده‌کی ایستیفاده‌چیلرین ائستاتوسونو ديَیشمه‌يه ایزین وئریلمه‌يیب",
        "userrights-nodatabase": "$1 وئریلنلر بازاسی يا مؤوجود دئيیل، يا دا لوکال دئيیل.",
-       "userrights-nologin": "سیز ایستیفاده‌چی‌لرین حقوق‌لارینی دییشمک اوچون سیستئمه ایداره‌چی اولا‌راق [[Special:UserLogin|daxil olmalısınız]].",
-       "userrights-notallowed": "سیزین ایستیفاده‌چی حسابینیزا دیگر ایستیفاده‌چی‌لره حقوق‌لار وئرمک و یا آلماغا ایجازه وئریلمه‌ییب.",
        "userrights-changeable-col": "ديَیشدیره بیلدیگینیز قروپلار",
        "userrights-unchangeable-col": "ديَیشدیره بیلمه‌دیگینیز قروپلار",
        "userrights-conflict": "ایستیفاده‌چی حاقلاری توققوشماسی! لوطفاً گوزله ین و دَییشدیرمه‌لرینیزی یئنی‌دن ائدین.",
-       "userrights-removed-self": "سیز باشاریلیق‌لا اؤز حاق‌لارینیزی قالدیردینیز. اونا گؤره داها بو صحیفه‌یه یول تاپماغا قادیر دئییل‌سینیز.",
        "group": "گروه:",
        "group-user": "ایستفاده‌چیلر",
        "group-autoconfirmed": "اوتوماتیک دوغرولانمیش ایستیفاده‌چیلر",
-       "group-bot": "بÙ\88تلار",
+       "group-bot": "رÙ\88باتلار",
        "group-sysop": "ایداره‌چیلر",
        "group-bureaucrat": "بوروکراتلار",
        "group-suppress": "باخانلار",
        "right-siteadmin": "دیتابیسی قیفیل‌لا و قیفیلینی آچ",
        "right-override-export-depth": "ایچری باغلانتیلاری اولان صحیفه‌لری، چوخو ۵ درجه درینلیگی ایله، ایخراج ائت",
        "right-sendemail": "باشقا ایستیفاده‌چیلره ایمیل گؤندر",
-       "right-passwordreset": "رمز یئنی‌له‌مه ایمیل‌لرینه باخ",
        "grant-group-email": "ایمئیل گؤندر",
        "newuserlogpage": "ایشلدن یارادیلما ژورنالی",
        "newuserlogpagetext": "بۇ ایشلدن یارادماق لیستی‌دیر.",
        "action-edit": "بو صحیفه‌نی دَییشدیر",
        "action-createpage": "صفحه یارات",
        "action-createtalk": "دانیشیق صفحه‌سی یارات",
-       "action-createaccount": "بÙ\88 Ø§Û\8cستÛ\8cÙ\81ادÙ\87â\80\8cÚ\86Û\8c Ø­Ø³Ø§Ø¨Û\8cÙ\86Û\8c Û\8cاراد",
+       "action-createaccount": "بÙ\88 Ø§Û\8cØ´Ù\84دÙ\86 Ø­Ø³Ø§Ø¨Û\8cÙ\86Û\8c Û\8cارات",
        "action-history": "بو صفحه نین گئچمیشین گور",
        "action-minoredit": "بو دَییشیکلیگی، کیچیک اولاراق نیشانلا",
        "action-move": "بو صحیفه‌‌نین آدینی ديَیشدیر",
        "brokenredirectstext": "آشاغی‌داکی ایستیقامتلندیرمه‌لر مؤوجود اولمایان صحیفه‌لره کئچید وئریر:",
        "brokenredirects-edit": "دَییشدیر",
        "brokenredirects-delete": "سیل",
-       "withoutinterwiki": "دیل باغلانتیلاری اولمایان صحیفه‌لر",
+       "withoutinterwiki": "دیل باغلانتیلاری اولمایان صفحه‌لر",
        "withoutinterwiki-summary": "آشاغیداکی صفحه‌لر، آیری دیل‌لره باغلانتیلاری یوخدور.",
        "withoutinterwiki-legend": "اؤن‌اَک",
        "withoutinterwiki-submit": "گؤستر",
        "longpages": "اۇزون صفحه‌‌لر",
        "deadendpages": "کئچید وئرمه‌ين صحیفه‌‌لر",
        "deadendpagestext": "آشاغیداکی صحیفه‌‌لردن بو ویکیپئدیياداکی دیگر صحیفه‌‌لره هئچ بیر کئچید يوخدور.",
-       "protectedpages": "Ù\85حاÙ\81ظÙ\87â\80\8câ\80\8cÙ\84Û\8c ØµØ­Û\8cÙ\81ه‌‌لر",
+       "protectedpages": "Ù\82Ù\88Ù\92رÙ\88Ù\86اÙ\86 ØµÙ\81Ø­ه‌‌لر",
        "protectedpages-indef": "يالنیز مدتسیز محافظه‌‌لر",
        "protectedpages-summary": "بۇ صحیفه، ایندیکی قوْرونان موْجود اوْلان صحیفه‌لری لیست ائدیر. یارانماق‌دان قوْرونان باشلیقلارین لیستینی گؤرمک اۆچون [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]]-ه باخین.",
        "protectedpages-cascade": "یالنیز کاسکاد محافظه‌لر",
        "protectedpages-noredirect": "یوْل‌لاندیرمالاری گیزلت",
        "protectedpagesempty": "حال-حاضردا بو پارامئتره اویغون هئچ بیر محافظه‌لی صحیفه یوخ‌دور",
-       "protectedpages-timestamp": "واخت دامغاسی",
+       "protectedpages-timestamp": "چاغ اتیکتی",
        "protectedpages-page": "صفحه",
-       "protectedpages-expiry": "بیتمک تاریخی",
-       "protectedpages-performer": "Ù\82Ù\88Ù\92رÙ\88Û\8cاÙ\86 Ø§Û\8cستÛ\8cÙ\81ادÙ\87â\80\8cÚ\86Û\8c",
+       "protectedpages-expiry": "قورتارماق تاریخی",
+       "protectedpages-performer": "Ù\82Ù\88Ù\92رÙ\88Û\8cاÙ\86 Ø§Û\8cØ´Ù\84دÙ\86",
        "protectedpages-params": "قوْروماق پارامئترلری",
        "protectedpages-reason": "نَدَن‌لیگی",
        "protectedpages-unknown-timestamp": "بیلینمه‌ین",
        "watchlist-hide": "گیزلت",
        "wlshowtime": "بو تاریخه قدر گؤستر:",
        "wlshowhideminor": "کیچیک دَییشدیرمه‌لر",
+       "wlshowhidebots": "روباتلار",
        "wlshowhideliu": "یازیلمیش ایشلدنلر",
        "wlshowhidemine": "منیم دَییشدیرمه‌لریم",
        "wlshowhidecategorization": "صفحه‌ بؤلمه‌لندیرمه‌سی",
        "rollbacklinkcount-morethan": "$1-دن چوْخ دییشدیرمه‌نی قایتار",
        "rollbackfailed": "گئری قایتارما اوغورسوزدور",
        "cantrollback": "دییشدیر گئری قایتاریلا بیلمز؛ آخیرینجی دییشدیر صحیفه‌ده اولان یئگانه فالیت‌دیر.",
-       "alreadyrolled": "[[User:$2|$2]] ([[User talk:$2|موزاکیره]] {{int:pipe-separator}} [[Special:Contributions/$2| {{int:contribslink}}]]) طرفین‌دن [[:$1]] صحیفه‌سینده ائدیلمیش سون دییشیک‌لیک گئرییه آلینا بیلمیر؛\nباشقا بیری صحیفه‌ده دییشیک‌لیک ائتدی یا دا صحیفنی گئرییه آلدی.\n\nسون دییشیک‌لیگی ائدن: [[User:$3|$3]] ([[User talk:$3|تالک]] {{int:pipe-separator}} [[Special:Contributions/$3| {{int:contribslink}}]] ).",
+       "alreadyrolled": "[[User:$2|$2]] ([[User talk:$2|دانیشیق]] {{int:pipe-separator}} [[Special:Contributions/$2| {{int:contribslink}}]]) طرفین‌دن [[:$1]] صفحه‌سینده ائدیلمیش سون دییشیک‌لیک قایتاریلمیر؛\nآیری بیری صفحه‌ده دییشیک‌لیک ائتدی یوخسا صفحه‌نی قایتاردی.\n\nسون دییشیک‌لیگی ائدن: [[User:$3|$3]] ([[User talk:$3|دانیشیق]] {{int:pipe-separator}} [[Special:Contributions/$3| {{int:contribslink}}]] ).",
        "editcomment": "دییشیک‌لیک خلاصه‌سی: ''\" $1''\" ایدی.",
        "revertpage": "[[Special:Contributions/$2|$2]] ([[User talk:$2|دانیشیق]]) طرفین‌دن ائدیلمیش دییشیک‌لیک‌لر [[User:$1|$1]] طرفین‌دن ائدیلمیش دییشیک‌لیک‌لره قایتاریلدی.",
        "revertpage-nouser": "{{GENDER:$1|[[User:$1|$1]]}} ایله ائدیلمیش سون نوسخه‌یه، بیر گیزلی ایشلدن طرفین‌دن قایتاریلان دییشیکلیک‌لر",
-       "rollback-success": "$1 Ø·Ø±Ù\81Û\8cÙ\86â\80\8cدÙ\86 Ø§Ø¦Ø¯Û\8cÙ\84Ù\85Û\8cØ´ Ø¯Û\8cÛ\8cشدÛ\8cرâ\80\8cÙ\84ر Ú¯Ø¦Ø±Û\8c Ù\82اÛ\8cتارÛ\8cÙ\84دÛ\8cØ\9b $2 Ø·Ø±Ù\81Û\8cÙ\86â\80\8cدÙ\86 Û\8cارادÛ\8cÙ\84Ù\85Û\8cØ´ Ø³Ù\88Ù\86 Ù\88ئرسÛ\8cا Ø¨Ø±Ù¾Ø§ Ø§Ù\88Ù\84Ù\88Ù\86دو.",
+       "rollback-success": "$1 Ø·Ø±Ù\81Û\8cÙ\86â\80\8cدÙ\86 Ø§Ø¦Ø¯Û\8cÙ\84Ù\85Û\8cØ´ Ø¯Û\8cÛ\8cشدÛ\8cرâ\80\8cÙ\85Ù\87 Ù\84ر Ù\82اÛ\8cتارÛ\8cÙ\84دÛ\8cØ\9b $2 Ø·Ø±Ù\81Û\8cÙ\86â\80\8cدÙ\86 Û\8cارادÛ\8cÙ\84Ù\85Û\8cØ´ Ø³Ù\88Ù\86 Ù\86Ù\88سخÙ\87 Ù\82Ù\88رÙ\88Ù\84دو.",
        "sessionfailure-title": "گیریش خطاسی",
        "sessionfailure": "گیریش اوتورومونوزلا ایلگی‌لی بیر سورون وار گیبی گؤرونویور؛\nبو ائیلئم، اوتوروم گاسپینا کارشی اؤنلئم اولاراک ایپتال ائدیلدی.\nلوتفن \"گئری\" گیدین و گئلدیغینیز سایفایی یئنی‌دئن یوکلئیین، سونرا تئکرار دئنئیین.",
        "changecontentmodel-title-label": "صحیفه باشلیقی",
        "protect-expiry-options": "1 ساهات:1 hour,1 گون:1 day,1 هفته:1 week,2 هفته:2 weeks,1 آی:1 month,3 آی:3 months,6 آی:6 months,1 ایل:1 year,سون سوز:infinite",
        "restriction-type": "حقوقلار",
        "restriction-level": "محدودیت درجه‌‌سی:",
-       "minimum-size": "ان کوچیک بویوت",
-       "maximum-size": "اÙ\86 Ø¨Ù\88Û\8cÙ\88Ú© Ø¨Ù\88Û\8cÙ\88ت",
+       "minimum-size": "ان کیچیک حجم",
+       "maximum-size": "اÙ\86 Ø¨Ù\88Û\8cÙ\88Ú© Ø­Ø¬Ù\85ï¼\9a",
        "pagesize": "(بایت)",
        "restriction-edit": "دَییشدیر",
        "restriction-move": "آدینی دَییشدیر",
        "sp-contributions-suppresslog": "باسدیریلمیش ایشلدن فعالیت‌لری",
        "sp-contributions-deleted": "سیلینمیش ایشلدن چالیشمالاری",
        "sp-contributions-uploads": "یوکله‌نَنلر",
-       "sp-contributions-logs": "قئیدلر",
+       "sp-contributions-logs": "ژورناللار",
        "sp-contributions-talk": "دانیشیق",
        "sp-contributions-userrights": "ایستیفاده‌چی حاقلارین ایداره‌ ائتمه‌سی",
        "sp-contributions-blocked-notice": "بو ایستیفاده‌چی حال-حاضردا بلوکلانمیش‌دیر.\nبلوکلاما قئیدلری‌نین سونونجوسو آشاغیدا گؤستریلمیش‌دیر:",
        "sp-contributions-username": "آی‌پی آدرسی یوْخسا ایشلدن آدی:",
        "sp-contributions-toponly": "تکجه سون نوسخه اولان دییشیکلری گؤستر",
        "sp-contributions-newonly": "تکجه صفحه یاراتماق دَییشیکلیکلرینی گؤستر",
+       "sp-contributions-hideminor": "کیچیک دییشیکلیکلری گیزلت",
        "sp-contributions-submit": "آختار",
        "whatlinkshere": "بۇ صفحه‌‌يه باغلانتیلار",
        "whatlinkshere-title": "«$1»-ه باغلانان صفحه‌لر",
        "whatlinkshere-hidelinks": "$1 باغلانتیلاری",
        "whatlinkshere-hideimages": "فایل باغلانتیلارینی $1",
        "whatlinkshere-filters": "سۆزگَجلر",
+       "whatlinkshere-submit": "گئت",
        "autoblockid": "اوتوماتیک باغلانما #$1",
        "block": "ایستیفادچینی باغلاما",
        "unblock": "ایستیفاده‌چی‌نین باغلانماسین گؤتور",
        "tooltip-compareselectedversions": "بو صحیفه‌نین ایکی سئچیلمیش نوسخه‌لری‌نین فرقلرینه باخ",
        "tooltip-watch": "بو صفحه‌نی ایزله‌دیکلرینیزه آرتیر",
        "tooltip-watchlistedit-normal-submit": "باشلیغین سیلینمه‌سی",
-       "tooltip-watchlistedit-raw-submit": "ایزلدیگیم صحیفه‌لرین سیاهی‌سینین یئنی‌لنمه‌سی",
+       "tooltip-watchlistedit-raw-submit": "ایزلدیگیم صفحه‌لرین لیستینی یئنی‌له",
        "tooltip-recreate": "اول سیلینمه‌سینه باخمایا‌راق صحیفنی برپا ائت",
        "tooltip-upload": "یوکلمنی باشلات",
        "tooltip-rollback": "سوْنونجو ایشلدن طرفیندن ائدیلمیش بۆتون ديَیشیکلیک‌لری بیر دفعه‌‌يه گئری قايتار",
        "pageinfo-category-subcats": "آلت‌بؤلمه‌لرین سایی",
        "pageinfo-category-files": "فایل‌لارین سایی",
        "markaspatrolleddiff": "ایداره ائدیلمیش اولا‌راق ایشاره‌له",
-       "markaspatrolledtext": "صحیفنی پاتروللانمیش کیمی ایشاره‌له",
+       "markaspatrolledtext": "صفحه‌نی یوخلانیلمیش کیمی علامتله",
        "markedaspatrolled": "یوخلانیلدی",
        "markedaspatrolledtext": "[[:$1]] اوچون سئچیلمیش نوسخه گؤزدن کئچیریله‌رک ایشاره‌لندی.",
        "rcpatroldisabled": "سون دییشیک‌لیک‌لرین پاتروللانماسی قاداغان‌دیر",
        "markedaspatrollederrornotify": "دولانماق برچسبی مووفقیت سیز اولدو",
        "patrol-log-page": "دولانما ژورنالی",
        "patrol-log-header": "بو یوخلانمیش دییشیک‌لیک‌لرین ژورنالی‌دیر.",
-       "log-show-hide-patrol": "$1 پاترول گونده‌لیگی",
+       "log-show-hide-patrol": "$1 دولانما ژورنالی",
        "log-show-hide-tag": "اِتیکت ژورنالی $1",
        "deletedrevision": "کؤهنه نوسخه لری سیلیندی $1.",
        "filedeleteerror-short": "فایل سیلینرکن ختا: $1",
        "lag-warn-normal": "$1 {{PLURAL:$1 | سانیيه‌دن | سانیيه‌ده}} يئنی ديَیشیکلیکلر بو سیياهیدا گؤرولمه‌يه.",
        "lag-warn-high": "وئریلنلر بازاسی سونوجوسونداکی هددیندن آرتیق گئجیکمه‌دن گؤره، $1 {{PLURAL:$1 | سانیيه‌دن | سانیيه‌دن}} يئنی ديَیشیکلیکلر بو سیياهیدا گؤرونمئيئبیلیر.",
        "watchlistedit-normal-title": "ایزله‌دیکلریم صفحه‌‌لری دَییشدیر",
-       "watchlistedit-normal-legend": "ایزله‌مه سیياهیسیندان باشلیقلارین سیلینمه‌سی",
-       "watchlistedit-normal-explain": "ایزله‌مه سیياهینیزدا باشلیقلار آشاغیدا گؤستریلمیشدیر. \nبیر باشلیغی چیخارماق اوچون، يانینداکی قوتوجوغو ایشارله‌يین و «{{int:Watchlistedit-normal-submit}}» دويمه‌سینی باسین. \n[[Special:EditWatchlist/raw|سطرلر سیياهیسینی]] ده تشکیل ائده بیلرسینیز",
+       "watchlistedit-normal-legend": "ایزله‌مه لیستیندن عونوانلارین سیلینمه‌سی",
+       "watchlistedit-normal-explain": "ایزله‌مه لیستینیزدکی عونوانلار آشاغیدا گؤستریلمیشدیر. \nبیر باشلیغی سیلمک اوچون، يانینداکی قوتونو علامتله‌يین و «{{int:Watchlistedit-normal-submit}}» دويمه‌سینی باسین. \n[[Special:EditWatchlist/raw|چی لیستی]] ده دییشدیره بیلرسینیز.",
        "watchlistedit-normal-submit": "باشلیقین سیلینمه‌سی",
        "watchlistedit-normal-done": "{{PLURAL:$1|$1 صحیفه‌‌}} ایزله‌مه صحیفه‌‌لرینیزدن سیلیندی:",
        "watchlistedit-raw-title": "چیی ایزله‌دیکلری دَییشدیر",
        "watchlistedit-raw-legend": "چیی ایزله‌دیکلری دَییشدیر",
        "watchlistedit-raw-explain": "ایزله‌مه سیياهینیزدا باشلیقلار آشاغیدا گؤستریلیر. هر سطرده بیر باشلیق اولماق عذره، باشلیقلاری علاوه‌‌ ائده‌رک يا دا سیله‌رک سیياهینی تشکیل ائده بیلرسینیز. \nبیتدیگینده «{{int:Watchlistedit-raw-submit}}» يئ تیکلايینیز. \nآيریجا [[Special:EditWatchlist|استاندارت تنزیمله‌مه صحیفه‌‌سینی]] دا ایستیفاده ائده بیلرسینیز.",
-       "watchlistedit-raw-titles": "باشÙ\84Û\8cÙ\82لار:",
-       "watchlistedit-raw-submit": "ایزلدیگیم صحیفه‌لرین سیاهی‌سینین یئنی‌لنمه‌سی",
+       "watchlistedit-raw-titles": "عÙ\88Ù\86Ù\88اÙ\86لار:",
+       "watchlistedit-raw-submit": "ایزلدیگیم صفحه‌لرین لیستینی یئنی‌له",
        "watchlistedit-raw-done": "ایزله‌دیکلرینیز گونجل‌لندی.",
        "watchlistedit-raw-added": "{{PLURAL:$1|بیر|$1}} باشلیق آرلیریلدی:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|بیر|$1}} باشلیق چیخاریلدی:",
+       "watchlistedit-clear-title": "ایزلدیکلریمین لیستین سیل",
        "watchlistedit-clear-legend": "ایزلدیکلریمین لیستین سیل",
        "watchlistedit-clear-titles": "باشلیق‌لار:",
        "watchlisttools-clear": "ایزلدیکلریمین لیستین سیل",
        "version-ext-license": "لیسانس",
        "version-ext-colheader-name": "اوزانتی",
        "version-skin-colheader-name": "قابیق",
-       "version-ext-colheader-version": "سۆروم",
+       "version-ext-colheader-version": "نوسخه",
        "version-ext-colheader-license": "لیسانس",
        "version-ext-colheader-description": "آچیقلاما",
        "version-ext-colheader-credits": "یازیچی‌لار",
        "intentionallyblankpage": "بو صحیفه خصوصیله بوش‌دور.",
        "external_image_whitelist": " #بو سطری اولدوغو کیمی بوراخین <pre>\n#دوزگون ایفاده (رِقولار اِکسپرِشِن) پارچالارینی (یالنیز // آراسیندا اولان قیسمی) آشاغی‌يا قویون\n#بونلار ائشیک‌ده‌کی عکسلرین آدرسلریله تطبیق اولاجاقلار\n#تطبیق اولانلار، عکس کیمی گؤستریله‌جکلر، اولمایانلارا یالنیز بیر باغلانتی گؤستریله‌جکدیر\n#بو # نیشانی ایله باشلایان سطرلر، شرح کیمی نظرده توتولاجاقلار\n#بو حرفلرین کیچیک/بؤیوک اولماغینا حساس دئییل\n\n#بوتون دوزگون ایفاده پارچالارینی، بو سطرین اوستونه قویون. بو سطری اولدوغو کیمی بوراخین</pre>",
        "tags": "مومکون دییشیک‌لیک ائتیکئت‌لری",
-       "tag-filter": "[[Special:Tags|اِتیکِت]] سۆزگُجی:",
+       "tag-filter": "[[Special:Tags|اِتیکِت]] فیلتری:",
        "tag-filter-submit": "سۆزگَج",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|اِتیکِت|اِتیکِتلر}}]]: $2)",
        "tags-title": "اِتیکتلر",
        "feedback-submit": "گؤندر",
        "feedback-thanks": "تشکورلر! سیزین گئری-بیلدیریمینیز «[$2 $1]» صحیفه‌سینه گؤندریلدی.",
        "feedback-thanks-title": "تشکورلر!",
-       "searchsuggest-search": "آختار",
+       "searchsuggest-search": "{{SITENAME}}-دا آختار",
        "searchsuggest-containing": "ساخلانیلیر...",
        "api-error-badaccess-groups": "سیزین بو ویکی‌یه فایل یوکله‌مک ایجازه‌نیز یوخدور.",
        "api-error-badtoken": "ایچری خطاسی: پیس کود.",
index 9a33968..ce5b1f9 100644 (file)
@@ -27,7 +27,8 @@
                        "Кутлубаева Кунсулу Закиевна",
                        "Вильданова Гюзель",
                        "Ilmira",
-                       "Irus"
+                       "Irus",
+                       "Khanmarat"
                ]
        },
        "tog-underline": "Һылтанмалар аҫтына һыҙыу:",
        "talk": "Әңгәмә",
        "views": "Ҡарауҙар",
        "toolbox": "Ҡоралдар",
+       "tool-link-userrights": "{{GENDER:$1|Ҡатнашыусы}} төркөмдәрен үҙгәртергә",
+       "tool-link-emailuser": "{{GENDER:$1|Ҡатнашыусыға}} хат яҙырға",
        "userpage": "Ҡулланыусы битен ҡарарға",
        "projectpage": "Проект битен ҡарарға",
        "imagepage": "Файл битен ҡарарға",
        "passwordreset-emaildisabled": "Был викиҙа электрон почта функцияһы һүндерелгән.",
        "passwordreset-username": "Ҡулланыусы исеме:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Хәбәрҙең һуңғы хәлен ҡарарғамы?",
-       "passwordreset-capture-help": "Әгәр был билдәне ҡуйһағыҙ, ҡулланыусыға ебәрелгән ваҡытлыса серһүҙ һеҙгә күрһәтеләсәк.",
        "passwordreset-email": "Электрон почта адресы:",
        "passwordreset-emailtitle": "{{SITENAME}} иҫәп яҙыуы мәғлүмәттәре",
        "passwordreset-emailtext-ip": "Берәү (бәлки һәҙ, $1 IP-адресынан ) {{SITENAME}} ($4) проектындағы иҫәп яҙыуығыҙҙы хәтерләтеүҙе һоратты.\nКиләһе ҡулланыусы {{PLURAL:$3|1=иҫәп яҙыуы|иҫәп яҙыуҙары}} был электрон почта адресы менән бәйле:\n\n$2\n\nБыл ваҡытлыса {{PLURAL:$3|1=серһүҙ|серһүҙҙәр}} {{PLURAL:$5|$5 көн}} ғәмәлдә буласаҡ.\nҺеҙ системала танылырға һәм яңы серһүҙ һайларға тейешһегеҙ.\nӘгәр, һеҙ быны һоратмаған булһағыҙ йәки элекке серһүҙегеҙҙе киренән иҫләһәгеҙ һәм уны үҙгәртергә теләмәһәгеҙ, был хатҡа иғтибар итмәгеҙ һәм элекке серһүҙегеҙҙе ҡулланыуҙы дауам итегеҙ.",
        "passwordreset-emailelement": "Ҡулланыусы исеме: \n$1\n\nВаҡытлыса серһүҙ: \n$2",
        "passwordreset-emailsentemail": "Серһүҙҙе ташлау тураһындағы мәғлүмәт менән электрон почта аша хат ебәрелде.",
        "passwordreset-emailsentusername": "Әгәр был ҡатнашыусының исеменә бәйле  электрон почтаһының адресы булһа, ул саҡта  серһүҙҙе тергеҙеү өсөн  хат ебәреләсәк.",
-       "passwordreset-invalideamil": "Электрон почта адресы ҡабул ителмәй",
+       "passwordreset-invalidemail": "Электрон почта адресы ҡабул ителмәй",
        "changeemail": "Электрон почта адресын үҙгәртергә",
        "changeemail-header": "Электрон почта адресын үҙгәртеү",
        "changeemail-no-info": "Был биткә туранан ирешеү өсөн һеҙгә системала танылыу кәрәк.",
        "minoredit": "Әҙ генә үҙгәрештәр",
        "watchthis": "Күҙәтеү исемлегенә",
        "savearticle": "Яҙҙырып ҡуйырға",
+       "savechanges": "Яҙҙырып ҡуйырға",
        "publishpage": "Битте баҫтырырға",
+       "publishchanges": "Яҙҙырып ҡуйырға",
        "preview": "Ҡарап сығыу",
        "showpreview": "Ҡарап сығырға",
        "showdiff": "Индерелгән үҙгәрештәр",
        "searchprofile-advanced-tooltip": "Махсус исем арауыҡтарында эҙләргә",
        "search-result-size": "$1 ({{PLURAL:$2|1=$2 һүҙ|$2 һүҙ}})",
        "search-result-category-size": "{{PLURAL:$1|1=$1 ағза}} ({{PLURAL:$2|$2 эске категория}}, {{PLURAL:$3|$3 файл}})",
-       "search-redirect": "(йүнәлтеү $1)",
+       "search-redirect": "($1 битенән йүнәлтеү)",
        "search-section": "($1 бүлеге)",
        "search-category": "(категория $1)",
        "search-file-match": "(файл эстәлеге менән тура килә)",
        "userrights-reason": "Сәбәп:",
        "userrights-no-interwiki": "Һеҙҙең башҡа вики-проекттарҙа ҡатнашыусыларҙың хоҡуҡтарын үҙгәртергә хоҡуҡтарығыҙ юҡ.",
        "userrights-nodatabase": "$1 базаһы юҡ йәки урындағы (локаль) база түгел.",
-       "userrights-nologin": "Ҡатнашыусыларҙың хоҡуҡтарын билдәләр өсөн, һеҙ хаким хоҡуҡтары менән [[Special:UserLogin|танылырға]] тейешһегеҙ.",
-       "userrights-notallowed": "Һеҙгә ҡатнашыусыларҙың хоҡуҡтарын өҫтәргә йәки юҡ итергә рөхсәт ителмәгән.",
        "userrights-changeable-col": "Һеҙ үҙгәртә алған төркөмдәр",
        "userrights-unchangeable-col": "Һеҙ үҙгәртә алмаған төркөмдәр",
        "userrights-conflict": "Ҡатнашыусының хоҡуҡтарын үҙгәртеү яраманы! Зинһар, үҙгәрештәрҙе тикшерегеҙ һәм яңынан индерегеҙ.",
-       "userrights-removed-self": "Һеҙ үҙ хоҡуҡтарығыҙҙы уңышлы юҡ иттегеҙ. Шулай итеп, был биткә башҡаса инә алмаясаҡһығыҙ.",
        "group": "Төркөм:",
        "group-user": "Ҡулланыусылар",
        "group-autoconfirmed": "Автоматик раҫланған ҡулланыусылар",
        "right-siteadmin": "Мәғлүмәттәр базаһын асыу һәм ябыу",
        "right-override-export-depth": "5-се тәрәнлеккә тиклем бәйле биттәре менән бергә биттәрҙе сығарыу",
        "right-sendemail": "Башҡа ҡатнашыусыларға электрон почта аша хат ебәреү",
-       "right-passwordreset": "Серһүҙҙе яңыртыу осраҡтарын ҡарау",
        "right-managechangetags": "[[Special:Tags|Билдәләрҙе]] төҙөү һәм (де)активация",
        "right-applychangetags": " [[Special:Tags|тамғаһын]] үҙегеҙҙең төҙөтеү менән ҡулланырға",
        "right-changetags": "Айырым үҙгәртеүҙәрҙә һәм журнал яҙмаланыда[[Special:Tags|тамғаһын]] өҫтәү һәм юйыу",
        "contributions": "{{GENDER:$1|Ҡатнашыусы}} башҡарған эш",
        "contributions-title": "$1 исемле ҡатнашыусы башҡарған эш",
        "mycontris": "Башҡарған эштәр",
-       "anoncontribs": "Ð\98Ò\93Ó\99нÓ\99ләр",
+       "anoncontribs": "Ð\91аÑ\88ҡаÑ\80Ò\93ан Ñ\8dÑ\88Ñ\82әр",
        "contribsub2": "{{GENDER:$3|$1}} башҡарған эше ($2)",
        "contributions-userdoesnotexist": "«$1» исемле иҫәп яҙыуы юҡ.",
        "nocontribs": "Күрһәтелгән шарттарға яуап биргән үҙгәртеүҙәр табылманы.",
        "tags-deactivate-not-allowed": "«$1» тамғаһын һүндереп булмай.",
        "tags-deactivate-submit": "һүндерергә",
        "tags-apply-no-permission": "Һеҙҙең үҙгәртеү тамғаһы ҡуйыу хоҡуғы юҡ.",
-       "tags-apply-blocked": "Һеҙ бикле булғас, үҙгәртеүҙәргә тамға ҡуйырға һеҙҙең хоҡуҡ юҡ, һеҙ бикләнгән.",
+       "tags-apply-blocked": "Бикле булғансы, үҙгәртеүҙәргә тамға ҡуйырға хоҡуғығыҙ юҡ.",
        "tags-apply-not-allowed-one": " «$1» тамғаһын ҡулдан файҙаланып булмай",
        "tags-apply-not-allowed-multi": "Ҡулдан {{PLURAL:$2|түбәндәге тамғаны өҫтәп булмай}}: $1",
        "tags-update-no-permission": "Һеҙҙең айырым өлгөләрҙә һәм журнал яҙмаларында тамға йәки үҙгәртеү тамғаһы ҡуйырға хоҡуғығыҙ юҡ.",
-       "tags-update-blocked": "Һеҙгә блок ҡуйылған, үҙгәртеү тамғалары менән идара итә алмайһығыҙ.",
+       "tags-update-blocked": "Блок алынғансы, үҙгәртеү тамғалары менән идара итә алмайһығыҙ.",
        "tags-update-add-not-allowed-one": " «$1» тамғаһын ҡулдан файҙаланып булмай",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|түбәндәге тег}} ҡулдан өҫтәлмәй: $1",
        "tags-update-remove-not-allowed-one": " «$1» тамғаһын юйып булмай",
        "feedback-thanks": "Рәхмәт! Һеҙҙең фекерегеҙ «[$2 $1]» битенә өҫтәлде.",
        "feedback-thanks-title": "Рәхмәт!",
        "feedback-useragent": "Браузер:",
-       "searchsuggest-search": "Эҙләү",
+       "searchsuggest-search": "{{SITENAME}} эсендә эҙләү",
        "searchsuggest-containing": "эстәлегендә...",
        "api-error-badaccess-groups": "Һеҙгә был викиға файлдар күсереү рөхсәт ителмәй",
        "api-error-badtoken": "Эске хата: дөрөҫ булмаған токен",
        "changecredentials-submit": "Иҫәп мәғлүмәттәрен үҙгәртеү",
        "removecredentials": "Иҫәп мәғлүмәттәрен юйырға",
        "removecredentials-submit": "Иҫәп мәғлүмәттәрен юйырға",
-       "credentialsform-account": "Иҫәп яҙмаһы исеме:",
-       "edit-error-short": "Хата: $1"
+       "credentialsform-account": "Иҫәп яҙмаһы исеме:"
 }
index 76dcb87..585cb1e 100644 (file)
        "yourname": "pesengan penganggen",
        "yourpassword": "kruna sandi",
        "yourpasswordagain": "jumunin kruna sandi",
-       "remembermypassword": "elingang kruna sandi padewekan ring computer niki ( suwennyane $1{{PLURAL:$1|dina}})",
        "login": "malebu ring log",
        "nav-login-createaccount": "malebu log / ngawe pepalihan",
        "userlogin": "malebu log / ngawe pepalihan",
index fceddbc..3808477 100644 (file)
        "yourname": "Nutzanama:",
        "yourpassword": "Passwort:",
        "yourpasswordagain": "Es Passwort no amoi eigebm",
-       "remembermypassword": "Mitm Brausa dauahoft ogmejd bleibm (maximoi $1 {{PLURAL:$1|Dog|Dog}})",
        "yourdomainname": "Dei Domain:",
        "externaldberror": "Entweder es ligt a Feeler bai da externen Authentifiziarung vur oder du derfst dai externs Benytzerkonto ned aktualisirn.",
        "login": "Eilogga",
index c54c9eb..23b877e 100644 (file)
        "yourpasswordagain": "کلمه رمز دگه نویس",
        "createacct-yourpasswordagain": "چه دوبارگ پسوردء بلک ات",
        "createacct-yourpasswordagain-ph": "چه دوبارگ پسوردء بلک ات",
-       "remembermypassword": "می ورودءَ ته ای کامپیوتر بدار (په $1 {{PLURAL:$1|روچ|روچ}})",
        "userlogin-remembermypassword": "منء همک وهد برجاه بدار",
        "userlogin-signwithsecure": "چه ایمنین کنکشنء کارمرز بکن ات",
        "yourdomainname": "شمی دامین",
        "passwordreset-emailtext-user": "کاربر $1 چه {{SITENAME}} شمئی پسوردء واترء لوٹ مان {{SITENAME}} ($4) کتگ انت. {{PLURAL:$3|اکانت|اکانتان}} چیریگین کاربر گون ائ ایمیل ادرس همگرنچ انت:\n\n$2\n\n{{PLURAL:$3|ائ موکتین پسورد|ائ موکتین پسوردان}} رند چه {{PLURAL:$5|یک روچ|$5 روچ}} باطل بیت انت.\nشما ضرور انت انیگء لاگین کن ات ءُ نوکین پسوردء بزیر ات. اگان ادگر شهسء ائ لوٹء راهیگ کتگ انت، یانکه وتی اصلیگین پسوردء هیال کت ات ءُ رندء نلوٹ ات آئرا ٹگل دئیت، بیت که ائ پیگامء نگند بزان ات ءُ وتی پیسریگین پسوردء کارمرز کن ات.",
        "passwordreset-emailelement": "یوزرنام: \n$1\n\nموکتین پسورد: \n$2",
        "passwordreset-emailsentemail": "یک ایمیلء گون پسوردء واترء راهیگ بوت.",
-       "passwordreset-emailsent-capture": "یک ایمیلء پر پسورد واترء واسته که جهلیگء پیش دارگ بیت، راهیگ بیتگ انت.",
-       "passwordreset-emailerror-capture": "واترین ایمیل، که جهلیگء پیش دارگ بیت، اڈ بوت، بلئی آئی راهیگ پر {{GENDER:$2|کاربر}} پکا نبوت: $1",
        "changeemail": "ایمیل ادرسء ٹگل بدئ",
        "changeemail-header": "وتی اکانتء ایمیل ادرسء ٹگل بدئ",
        "changeemail-no-info": "پر یکپارگین دزرسی مان ائ تاکء پیکن لاگین کن ات.",
        "undo-nochange": "چوش که پیداگ انت ویرایش مان انیگء باطل بوتگ انت.",
        "undo-summary": "بازبینی برگردین $1 گون [[Special:مشارکتان/$2|$2]] ([[User talk:$2|گپ]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]])",
        "undo-summary-username-hidden": "بی اثر کتن نسخهٔ $1 گون یک نامالومین کاربرء واسته",
-       "cantcreateaccounttitle": "نه نونیت حساب شرکنت",
        "cantcreateaccount-text": "شرکتن حساب چی ای آدرس آی پی ('''$1''') محدود بوتت توسط [[User:$3|$3]].\n\nدلیلی داتگین توسط $3  شی انت ''$2''",
        "cantcreateaccount-range-text": "اکانتء اڈ کتن چه آی پی ادرسء مان ائ هوار <strong>$1</strong>، که شمئی آی پی (<strong>$4</strong>) مان آئی توکاانت، گون [[User:$3|$3]] متوقف بیتگ انت.\nدرشان کتگین دلیل گون $3، $2 انت.",
        "viewpagelogs": "آمار ای صفحه بچار",
index abacb5a..2fc4b3c 100644 (file)
        "yourpasswordagain": "Pakilaog giraray kan sekretong panlaog:",
        "createacct-yourpasswordagain": "Kumpirmaron an sekretong panlaog",
        "createacct-yourpasswordagain-ph": "Pakikaag otro an sekretong panlaog",
-       "remembermypassword": "Giromdoma an sakong paglaog sa kilyaw (browser) na ini (para sa maksimum na $1 {{PLURAL:$1|aldaw|mga aldaw}})",
        "userlogin-remembermypassword": "Dagos mo akong giromdomon na nakalaog",
        "userlogin-signwithsecure": "Gamiton an seguradong koneksyon",
        "yourdomainname": "An saimong kasakupan:",
        "activeusers-intro": "Iyo in an listahan kan mga paragamit na nagkaigwa nin mga ginibo sa laog kan nakaaging $1 {{PLURAL:$1|aldaw|mga aldaw}}.",
        "activeusers-count": "$1 {{PLURAL:$1|aksyon|mga aksyon}} sa nakaaging {{PLURAL:$3|aldaw|$3 mga aldaw}}",
        "activeusers-from": "Ipahiling an mga paragamit magpoon sa:",
-       "activeusers-hidebots": "Itago an mga panalnga",
-       "activeusers-hidesysops": "Itago an mga administrador",
        "activeusers-noresult": "Mayong mga paragamit na nanagboan.",
        "listgrouprights": "Mga karapatan kan grupo nin paragamit",
        "listgrouprights-summary": "An minasunod iyo an listahan kan mga grupo nin paragamit na pinaghunsay kaining wiki, kaiba an saindang asosyadong mga karapatan nin paggamit.\nPuwedeng magkakaigwa nin [[{{MediaWiki:Listgrouprights-helppage}}|kadagdagang impormasyon]] mapanungod sa indibidwal na mga karapatan.",
        "htmlform-chosen-placeholder": "Magpili nin sarong opsyon",
        "htmlform-title-not-creatable": "\"$1\" bako sarong maimumuknang titulo kan pahina",
        "htmlform-title-not-exists": "$1 bakong eksistido.",
-       "sqlite-has-fts": "$1 na igwang suporta sa kabilogang-teksto nin paghahanap",
-       "sqlite-no-fts": "$1 na mayong suporta sa kabilogang-teksto nin paghahanap",
        "logentry-delete-delete": "$1 {{GENDER:$2|pinagpura na}} pahina $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|pinagbalik}} na pahina $3",
        "logentry-delete-event": "$1 {{GENDER:$2|pinagliwat}}an bisibilidad kan {{PLURAL:$5|sarong talaan nin pangyayari|$5 talaan nin mga pangyayari}} kan $3: $4",
index d5a8fb8..2065f52 100644 (file)
@@ -15,7 +15,8 @@
                        "Тест",
                        "아라",
                        "Liashko",
-                       "Macofe"
+                       "Macofe",
+                       "Kareyac"
                ]
        },
        "tog-underline": "Падкрэсьліваць спасылкі:",
        "views": "Рэжымы",
        "toolbox": "Інструмэнты",
        "tool-link-userrights": "Зьмяніць групы {{GENDER:$1|ўдзельніка|ўдзельніцы}}",
+       "tool-link-userrights-readonly": "Паказаць групы {{GENDER:$1|ўдзельніка|ўдзельніцы}}",
        "tool-link-emailuser": "Даслаць {{GENDER:$1|удзельніку|удзельніцы}} ліст электроннай поштай",
        "userpage": "Паказаць старонку ўдзельніка",
        "projectpage": "Паказаць старонку праекту",
        "passwordreset-emaildisabled": "Функцыі электроннай пошты ў гэтай вікі былі адключаныя.",
        "passwordreset-username": "Імя ўдзельніка:",
        "passwordreset-domain": "Дамэн:",
-       "passwordreset-capture": "Паказаць выніковы электронны ліст?",
-       "passwordreset-capture-help": "Калі Вы пазначыце гэтае поле, электронны ліст (з часовым паролем) будзе паказаны Вам, як толькі ён будзе дасланы ўдзельніку.",
        "passwordreset-email": "Адрас электроннай пошты:",
        "passwordreset-emailtitle": "Падрабязнасьці рахунку ў {{GRAMMAR:месны|{{SITENAME}}}}",
        "passwordreset-emailtext-ip": "Нехта (магчыма Вы, з IP-адрасу $1) зрабіў запыт на скіданьне вашага паролю ў {{GRAMMAR:месны|{{SITENAME}}}} ($4). {{PLURAL:$3|1=Наступны рахунак удзельніка зьвязаны|Наступныя рахункі ўдзельнікаў зьвязаныя}} з гэтым адрасам электроннай пошты:\n\n$2\n\n{{PLURAL:$3|1=Гэты часовы пароль будзе|Гэтыя часовыя паролі будуць}} дзейнічаць $5 {{PLURAL:$5|дзень|дні|дзён}}.\nЦяпер Вам неабходна ўвайсьці і выбраць новы пароль. Калі нехта іншы зрабіў гэты запыт, ці Вы ўспомнілі Ваш пачатковы пароль, які ня хочаце мяняць, Вы можаце праігнараваць гэтае паведамленьне, і працягваць выкарыстоўваць стары пароль.",
        "passwordreset-emailelement": "Імя ўдзельніка: \n$1\n\nЧасовы пароль: \n$2",
        "passwordreset-emailsentemail": "Калі гэты адрас электроннай пошты далучаны да вашага рахунку, тады будзе дасланы ліст пра скідваньне паролю.",
        "passwordreset-emailsentusername": "Калі ёсьць адрас электроннай пошты, злучаны з гэтым імем удзельніка, тады будзе дасланы ліст пра скідваньне паролю.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|1=Электронны ліст|Электронныя лісты}} скіданьня паролю {{PLURAL:$1|1=быў дасланы|былі дасланыя}}. {{PLURAL:$1|1=Імя ўдзельніка і пароль|Сьпіс імёнаў удзельнікаў і паролі}} паказаныя тут.",
-       "passwordreset-emailerror-capture2": "Не атрымалася даслаць {{GENDER:$2|удзельніку|удзельніцы}} ліст электроннай поштай: $1 {{PLURAL:$3|1=Імя ўдзельніка і пароль|Сьпіс імёнаў удзельнікаў і паролі}} паказаныя тут.",
        "passwordreset-nocaller": "Мусіць быць пададзены той, хто робіць выклік",
        "passwordreset-nosuchcaller": "Аўтар выкліку не існуе: $1",
        "passwordreset-ignored": "Скіданьне паролю не адбылося. Магчыма, ня быў наладжаны пастаўшчык?",
-       "passwordreset-invalideamil": "Няслушны адрас электроннай пошты",
+       "passwordreset-invalidemail": "Няслушны адрас электроннай пошты",
        "passwordreset-nodata": "Не былі пададзеныя ні імя ўдзельніка, ні адрас электроннай пошты",
        "changeemail": "Зьмяніць або выдаліць адрас электроннай пошты",
        "changeemail-header": "Запоўніце гэтую форму, каб зьмяніць ваш адрас электроннай пошты. Калі вы жадаеце выдаліць адрас электроннай пошты, далучаны да вашага рахунку, пакіньце поле новага адрасу электроннай пошты пустым пры запаўненьні формы.",
        "usercssyoucanpreview": "<strong>Падказка:</strong> выкарыстоўвайце кнопку «{{int:showpreview}}», каб паспрабаваць новы CSS-код перад яго захаваньнем.",
        "userjsyoucanpreview": "<strong>Падказка:</strong> выкарыстоўвайце кнопку «{{int:showpreview}}», каб паспрабаваць новы код JavaScript перад тым, як яго захаваць.",
        "usercsspreview": "<strong>Памятайце, што гэта толькі папярэдні прагляд вашага CSS. Ён яшчэ не запісаны!</strong>",
-       "userjspreview": "'''Памятайце, што гэта толькі папярэдні прагляд Вашага JavaScript, ён яшчэ не запісаны!'''",
-       "sitecsspreview": "'''Памятайце, што гэта толькі папярэдні прагляд гэтага CSS.'''\n'''Ён яшчэ не захаваны!'''",
-       "sitejspreview": "'''Памятайце, што гэта толькі папярэдні прагляд гэтага коду JavaScript.'''\n'''Ён яшчэ не захаваны!'''",
-       "userinvalidcssjstitle": "'''Папярэджаньне:''' няма тэмы афармленьня «$1».\nПамятайце, што ўласныя старонкі .css і .js павінны мець назву, якая складаецца з малых літараў, напрыклад, {{ns:user}}:Хтосьці/vector.css, а не {{ns:user}}:Хтосьці/Vector.css.",
+       "userjspreview": "<strong>Памятайце, што гэта толькі папярэдні прагляд Вашага JavaScript. Ён яшчэ не запісаны!</strong>",
+       "sitecsspreview": "<strong>Памятайце, што гэта толькі папярэдні прагляд гэтага CSS.\nЁн яшчэ не захаваны!</strong>",
+       "sitejspreview": "<strong>Памятайце, што гэта толькі папярэдні прагляд гэтага коду JavaScript.\nЁн яшчэ не захаваны!</strong>",
+       "userinvalidcssjstitle": "<strong>Папярэджаньне:</strong> няма тэмы афармленьня «$1».\nПамятайце, што ўласныя старонкі .css і .js павінны мець назву, якая складаецца з малых літараў, напрыклад, {{ns:user}}:Хтосьці/vector.css, а не {{ns:user}}:Хтосьці/Vector.css.",
        "updated": "(Абноўлена)",
-       "note": "'''Заўвага: '''",
-       "previewnote": "'''Гэта толькі папярэдні прагляд.'''\nВашыя зьмены яшчэ не былі захаваныя!",
+       "note": "<strong>Заўвага:</strong>",
+       "previewnote": "<strong>Гэта толькі папярэдні прагляд.</strong>\nВашыя зьмены яшчэ не былі захаваныя!",
        "continue-editing": "Перайсьці да рэдагаваньня",
        "previewconflict": "Гэта папярэдні прагляд тэксту зь верхняга вакна рэдагаваньня, так ён будзе выглядаць, калі Вы вырашыце яго захаваць.",
        "session_fail_preview": "Выбачайце! Мы не змаглі апрацаваць вашую праўку праз страту зьвестак сэсіі.\n\nМагчыма, вы выйшлі з сыстэмы. <strong>Калі ласка, праверце, што вы знаходзіцеся ў сыстэме і паспрабуйце яшчэ раз<strong>. Калі не спрацуе, паспрабуйце [[Special:UserLogout|выйсьці]] і ўвайсьці яшчэ раз, а таксама праверце, што ваш браўзэр дазваляе файлы-кукі з гэтага сайту.",
        "session_fail_preview_html": "Выбачайце! Мы не змаглі апрацаваць вашую праўку праз страту зьвестак сэсіі.\n\n<em>Таму што ў {{GRAMMAR:месны|{{SITENAME}}}} дазволена выкарыстоўваць чысты HTML, папярэдні прагляд быў адключаны для засьцярогі ад атакаў праз JavaScript.</em>\n\n<strong>Калі гэта сапраўдная спроба рэдагаваньня, калі ласка, паспрабуйце яшчэ раз.</strong>\nКалі гэта не дапамагае, паспрабуйце [[Special:UserLogout|выйсьці з сыстэмы]] і ўвайсьці ізноў, а таксама праверце, што ваш браўзер дазваляе кукі-файлы з гэтага сайту.",
-       "token_suffix_mismatch": "'''Вашае рэдагаваньне было адхіленае, таму што Ваш кліент ня можа апрацоўваць знакі пунктуацыі ў акне рэдагаваньня.\nРэдагаваньне было скасаванае для таго, каб пазьбегнуць зьнішчэньня тэксту старонкі.\nТакія памылкі здараюцца, калі Вы выкарыстоўваеце ананімны проксі-сэрвэр, які ўтрымлівае памылкі.'''",
-       "edit_form_incomplete": "'''Некаторыя часткі формы рэдагаваньня не дасягнулі сэрвэра. Упэўніцеся, што Вашыя рэдагаваньні не пашкоджаныя і паспрабуйце зноў.'''",
+       "token_suffix_mismatch": "<strong>Вашае рэдагаваньне было адхіленае, таму што Ваш кліент псуе знакі пунктуацыі ў жэтоне рэдагаваньня.</strong>\nРэдагаваньне было скасаванае для таго, каб пазьбегнуць зьнішчэньня тэксту старонкі.\nТакія памылкі здараюцца, калі Вы выкарыстоўваеце ананімны проксі-сэрвэр, які ўтрымлівае памылкі.",
+       "edit_form_incomplete": "<strong>Некаторыя часткі формы рэдагаваньня не дасягнулі сэрвэра. Упэўніцеся, што Вашыя рэдагаваньні не пашкоджаныя і паспрабуйце зноў.</strong>",
        "editing": "Рэдагаваньне: $1",
        "creating": "Стварэньне «$1»",
        "editingsection": "Рэдагаваньне $1 (разьдзел)",
-       "editingcomment": "Рэдагаваньне: $1 (новая сэкцыя)",
+       "editingcomment": "Рэдагаваньне $1 (новы разьдзел)",
        "editconflict": "Канфлікт рэдагаваньняў: $1",
-       "explainconflict": "Ð\9dеÑ\85Ñ\82а Ð·Ñ\8cмÑ\8fнÑ\96Ñ\9e Ñ\81Ñ\82аÑ\80онкÑ\83 Ð¿Ð°Ð´Ñ\87аÑ\81 Ð\92аÑ\88ага Ñ\80Ñ\8dдагаванÑ\8cнÑ\8f.\nУ Ð²ÐµÑ\80Ñ\85нÑ\96м Ñ\82Ñ\8dкÑ\81Ñ\82авÑ\8bм Ð°ÐºÐ½Ðµ Ð·Ð½Ð°Ñ\85одзÑ\96Ñ\86Ñ\86а Ñ\86Ñ\8fпеÑ\80аÑ\88нÑ\96 Ð·Ñ\8cмеÑ\81Ñ\82 Ñ\81Ñ\82аÑ\80онкÑ\96.\nÐ\92аÑ\88Ñ\8bÑ\8f Ð·Ñ\8cменÑ\8b Ð¿Ð°ÐºÐ°Ð·Ð°Ð½Ñ\8bÑ\8f Ñ\9e Ð½Ñ\96жнÑ\96м Ð°ÐºÐ½Ðµ.\nÐ\92ам Ñ\82Ñ\80Ñ\8dба Ð¿ÐµÑ\80анеÑ\81Ñ\8cÑ\86Ñ\96 Ð\92аÑ\88Ñ\8bÑ\8f Ð·Ñ\8cменÑ\8b Ñ\9e Ñ\86Ñ\8fпеÑ\80аÑ\88нÑ\96 Ñ\82Ñ\8dкÑ\81Ñ\82.\nÐ\9aалÑ\96 Ð\92Ñ\8b Ð½Ð°Ñ\86Ñ\96Ñ\81Ñ\8cнÑ\96Ñ\86е Â«{{int:savearticle}}», Ð±Ñ\83дзе Ð·Ð°Ñ\85аванÑ\8b '''Ñ\82олÑ\8cкÑ\96''' тэкст верхняга вакна.",
+       "explainconflict": "Ð\9dеÑ\85Ñ\82а Ð·Ñ\8cмÑ\8fнÑ\96Ñ\9e Ñ\81Ñ\82аÑ\80онкÑ\83 Ð¿Ð°Ð´Ñ\87аÑ\81 Ð²Ð°Ñ\88ага Ñ\80Ñ\8dдагаванÑ\8cнÑ\8f.\nУ Ð²ÐµÑ\80Ñ\85нÑ\96м Ñ\82Ñ\8dкÑ\81Ñ\82авÑ\8bм Ð°ÐºÐ½Ðµ Ð·Ð½Ð°Ñ\85одзÑ\96Ñ\86Ñ\86а Ñ\86Ñ\8fпеÑ\80аÑ\88нÑ\96 Ð·Ñ\8cмеÑ\81Ñ\82 Ñ\81Ñ\82аÑ\80онкÑ\96.\nÐ\92аÑ\88Ñ\8bÑ\8f Ð·Ñ\8cменÑ\8b Ð¿Ð°ÐºÐ°Ð·Ð°Ð½Ñ\8bÑ\8f Ñ\9e Ð½Ñ\96жнÑ\96м Ð°ÐºÐ½Ðµ.\nÐ\92ам Ñ\82Ñ\80Ñ\8dба Ð¿ÐµÑ\80анеÑ\81Ñ\8cÑ\86Ñ\96 Ð²Ð°Ñ\88Ñ\8bÑ\8f Ð·Ñ\8cменÑ\8b Ñ\9e Ñ\86Ñ\8fпеÑ\80аÑ\88нÑ\96 Ñ\82Ñ\8dкÑ\81Ñ\82.\nÐ\9aалÑ\96 Ð²Ñ\8b Ð½Ð°Ñ\86Ñ\96Ñ\81Ñ\8cнÑ\96Ñ\86е Â«{{int:savearticle}}», Ð±Ñ\83дзе Ð·Ð°Ñ\85аванÑ\8b <strong>Ñ\82олÑ\8cкÑ\96</strong> тэкст верхняга вакна.",
        "yourtext": "Ваш тэкст",
        "storedversion": "Захаваная вэрсія",
-       "nonunicodebrowser": "'''ПАПЯРЭДЖАНЬНЕ: Ваш браўзэр не працуе з кадаваньнем UTF-8 (Unicode).\nУ выніку гэтага ўсе сымбалі ня ўключаныя ў ASCII будуць замененыя на іх шаснаццаткавыя коды.'''",
-       "editingold": "'''ПАПЯРЭДЖАНЬНЕ: Вы рэдагуеце састарэлую вэрсію гэтай старонкі.\nКалі Вы паспрабуеце захаваць яе, любыя зьмены, зробленыя пасьля гэтай вэрсіі, будуць страчаныя.'''",
+       "nonunicodebrowser": "<strong>Папярэджаньне: ваш браўзэр не падтрымлівае Unicode-кадаваньне.</strong>\nУ выніку гэтага ўсе сымбалі ў полі рэдагаваньня, ня ўключаныя ў ASCII, будуць замененыя на іх шаснаццаткавыя коды.",
+       "editingold": "<strong>Папярэджаньне: вы рэдагуеце састарэлую вэрсію гэтай старонкі.</strong>\nКалі вы паспрабуеце захаваць яе, любыя зьмены, зробленыя пасьля гэтай вэрсіі, будуць страчаныя.",
        "yourdiff": "Адрозьненьні",
-       "copyrightwarning": "Ð\9aалÑ\96 Ð»Ð°Ñ\81ка, Ð·Ñ\8cвÑ\8fÑ\80нÑ\96Ñ\86е Ñ\9eвагÑ\83 Ð½Ð° Ñ\82ое, Ñ\88Ñ\82о Ñ\9eÑ\81е Ð´Ð°Ð´Ð°Ñ\82кÑ\96 Ñ\96 Ð·Ñ\8cменÑ\8b Ñ\9e {{GRAMMAR:меÑ\81нÑ\8b|{{SITENAME}}}} Ñ\80азглÑ\8fдаÑ\8eÑ\86Ñ\86а Ñ\8fк Ð²Ñ\8bдадзенÑ\8bÑ\8f Ñ\9e Ð°Ð´Ð¿Ð°Ð²ÐµÐ´Ð½Ð°Ñ\81Ñ\8cÑ\86Ñ\96 Ð· Ñ\83мовамÑ\96 Ð»Ñ\96Ñ\86Ñ\8dнзÑ\96Ñ\96 $2 (глÑ\8fдзÑ\96Ñ\86е Ð¿Ð°Ð´Ñ\80абÑ\8fзнаÑ\81Ñ\8cÑ\86Ñ\96 Ð½Ð° $1). Ð\9aалÑ\96 Ð\92Ñ\8b Ñ\81Ñ\83пÑ\80аÑ\86Ñ\8c Ñ\82аго, ÐºÐ°Ð± Ð\92аÑ\88Ñ\8bÑ\8f Ð¼Ð°Ñ\82Ñ\8dÑ\80Ñ\8bÑ\8fлÑ\8b Ð½ÐµÐ°Ð±Ð¼ÐµÐ¶Ð°Ð²Ð°Ð½Ð° Ñ\80Ñ\8dдагавалаÑ\81Ñ\8f Ñ\96 Ñ\80аÑ\81паÑ\9eÑ\81Ñ\8eджвалаÑ\81Ñ\8f, Ð½Ðµ Ð´Ð°Ð´Ð°Ð²Ð°Ð¹Ñ\86е Ñ\96Ñ\85.<br />\nÐ\92Ñ\8b Ñ\82акÑ\81ама Ð°Ð±Ð°Ð²Ñ\8fзÑ\83еÑ\86еÑ\81Ñ\8f, Ñ\88Ñ\82о Ð\92аÑ\88 Ð¼Ð°Ñ\82Ñ\8dÑ\80Ñ\8bÑ\8fл Ð½Ð°Ð¿Ñ\96Ñ\81анÑ\8b Ð°Ñ\81абÑ\96Ñ\81Ñ\82а Ð\92амÑ\96 Ð°Ð±Ð¾ Ð·Ñ\8cÑ\8fÑ\9eлÑ\8fеÑ\86Ñ\86а Ð³Ñ\80амадзкÑ\96м Ð½Ð°Ð±Ñ\8bÑ\82кам, Ð°Ð»Ñ\8cбо Ñ\9eзÑ\8fÑ\82Ñ\8b Ð· Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ\8bÑ\85 Ð²Ð¾Ð»Ñ\8cнÑ\8bÑ\85 ÐºÑ\80Ñ\8bнÑ\96Ñ\86аÑ\9e.\n'''Ð\9dÐ\95Ð\9bЬÐ\93Ð\90 Ð\91Ð\95Ð\97 Ð\94Ð\90Ð\97Ð\92Ð\9eÐ\9bУ Ð\94Ð\90Ð\94Ð\90Ð\92Ð\90ЦЬ Ð\9cÐ\90ТЭРЫЯÐ\9bЫ, Ð\90Ð\91Ð\90РÐ\9eÐ\9dÐ\95Ð\9dЫЯ Ð\90Ð\8eТÐ\90РСÐ\9aÐ\86Ð\9c Ð\9fРÐ\90Ð\92Ð\90Ð\9c!'''",
-       "copyrightwarning2": "Ð\9aалÑ\96 Ð»Ð°Ñ\81ка, Ð·Ð°Ñ\9eважÑ\86е, Ñ\88Ñ\82о Ñ\9eвеÑ\81Ñ\8c Ñ\83нÑ\91Ñ\81ак Ñ\9e {{GRAMMAR:вÑ\96навалÑ\8cнÑ\8b|{{SITENAME}}}} Ð¼Ð¾Ð¶Ð° Ñ\80Ñ\8dдагаваÑ\86Ñ\86а, Ð·Ñ\8cмÑ\8fнÑ\8fÑ\86Ñ\86а Ñ\96 Ð²Ñ\8bдалÑ\8fÑ\86Ñ\86а Ñ\96нÑ\88Ñ\8bмÑ\96 Ñ\9eдзелÑ\8cнÑ\96камÑ\96.\nÐ\9aалÑ\96 Ð\92Ñ\8b Ð· Ð³Ñ\8dÑ\82Ñ\8bм Ð½Ñ\8f Ð·Ð³Ð¾Ð´Ð½Ñ\8bÑ\8f, ÐºÐ°Ð»Ñ\96 Ð»Ð°Ñ\81ка, Ð½Ðµ Ð·Ñ\8cмÑ\8fÑ\88Ñ\87айÑ\86е Ñ\81Ñ\8eдÑ\8b Ð\92аÑ\88Ñ\8bÑ\8f Ñ\82Ñ\8dкÑ\81Ñ\82Ñ\8b.<br />\nРазÑ\8cмÑ\8fÑ\88Ñ\87Ñ\8dнÑ\8cнем Ñ\82Ñ\83Ñ\82 Ñ\82Ñ\8dкÑ\81Ñ\82аÑ\9e, Ð\92Ñ\8b Ð´Ñ\8dклÑ\8fÑ\80Ñ\83еÑ\86е, Ñ\88Ñ\82о Ð\92Ñ\8b Ð·Ñ\8cÑ\8fÑ\9eлÑ\8fеÑ\86еÑ\81Ñ\8f Ñ\96Ñ\85 Ð°Ñ\9eÑ\82аÑ\80ам, Ñ\86Ñ\96 Ð\92Ñ\8b Ñ\81капÑ\96Ñ\8fвалÑ\96 Ñ\96Ñ\85 Ð· ÐºÑ\80Ñ\8bнÑ\96Ñ\86Ñ\8b, Ñ\8fкаÑ\8f Ð´Ð°Ð·Ð²Ð°Ð»Ñ\8fе Ð²Ð¾Ð»Ñ\8cнае Ð²Ñ\8bкаÑ\80Ñ\8bÑ\81Ñ\82анÑ\8cне Ñ\81ваÑ\96Ñ\85 Ñ\82Ñ\8dкÑ\81Ñ\82аÑ\9e (дзелÑ\8f Ð¿Ð°Ð´Ñ\80абÑ\8fзнаÑ\81Ñ\8cÑ\86Ñ\8fÑ\9e Ð³Ð»Ñ\8fдзÑ\96Ñ\86е $1).\n\n'''Ð\9aÐ\90Ð\9bÐ\86 Ð\9bÐ\90СÐ\9aÐ\90, Ð\9dÐ\95 Ð\97ЬÐ\9cЯШЧÐ\90Ð\99ЦÐ\95 Ð¢Ð£Ð¢ Ð\91Ð\95Ð\97 Ð\94Ð\90Ð\97Ð\92Ð\9eÐ\9bУ Ð\9cÐ\90ТЭРЫЯÐ\9bЫ, Ð¯Ð\9aÐ\86Я Ð\90Ð¥Ð\9eÐ\8eÐ\92Ð\90ЮЦЦÐ\90 Ð\90Ð\8eТÐ\90РСÐ\9aÐ\86Ð\9c Ð\9fРÐ\90Ð\92Ð\90Ð\9c!'''",
+       "copyrightwarning": "Ð\9aалÑ\96 Ð»Ð°Ñ\81ка, Ð·Ñ\8cвÑ\8fÑ\80нÑ\96Ñ\86е Ñ\9eвагÑ\83 Ð½Ð° Ñ\82ое, Ñ\88Ñ\82о Ñ\9eÑ\81е Ð´Ð°Ð´Ð°Ñ\82кÑ\96 Ñ\96 Ð·Ñ\8cменÑ\8b Ñ\9e {{GRAMMAR:меÑ\81нÑ\8b|{{SITENAME}}}} Ñ\80азглÑ\8fдаÑ\8eÑ\86Ñ\86а Ñ\8fк Ð²Ñ\8bдадзенÑ\8bÑ\8f Ñ\9e Ð°Ð´Ð¿Ð°Ð²ÐµÐ´Ð½Ð°Ñ\81Ñ\8cÑ\86Ñ\96 Ð· Ñ\83мовамÑ\96 Ð»Ñ\96Ñ\86Ñ\8dнзÑ\96Ñ\96 $2 (глÑ\8fдзÑ\96Ñ\86е Ð¿Ð°Ð´Ñ\80абÑ\8fзнаÑ\81Ñ\8cÑ\86Ñ\96 Ð½Ð° $1). Ð\9aалÑ\96 Ð²Ñ\8b Ñ\81Ñ\83пÑ\80аÑ\86Ñ\8c Ñ\82аго, ÐºÐ°Ð± Ð²Ð°Ñ\88Ñ\8bÑ\8f Ð¼Ð°Ñ\82Ñ\8dÑ\80Ñ\8bÑ\8fлÑ\8b Ð½ÐµÐ°Ð±Ð¼ÐµÐ¶Ð°Ð²Ð°Ð½Ð° Ñ\80Ñ\8dдагавалаÑ\81Ñ\8f Ñ\96 Ñ\80аÑ\81паÑ\9eÑ\81Ñ\8eджвалаÑ\81Ñ\8f, Ð½Ðµ Ð´Ð°Ð´Ð°Ð²Ð°Ð¹Ñ\86е Ñ\96Ñ\85.<br />\nÐ\92Ñ\8b Ñ\82акÑ\81ама Ð°Ð±Ð°Ð²Ñ\8fзÑ\83еÑ\86еÑ\81Ñ\8f, Ñ\88Ñ\82о Ð²Ð°Ñ\88 Ð¼Ð°Ñ\82Ñ\8dÑ\80Ñ\8bÑ\8fл Ð½Ð°Ð¿Ñ\96Ñ\81анÑ\8b Ð°Ñ\81абÑ\96Ñ\81Ñ\82а Ð²Ð°Ð¼Ñ\96 Ð°Ð±Ð¾ Ð·Ñ\8cÑ\8fÑ\9eлÑ\8fеÑ\86Ñ\86а Ð³Ñ\80амадзкÑ\96м Ð½Ð°Ð±Ñ\8bÑ\82кам, Ð°Ð»Ñ\8cбо Ñ\9eзÑ\8fÑ\82Ñ\8b Ð· Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ\8bÑ\85 Ð²Ð¾Ð»Ñ\8cнÑ\8bÑ\85 ÐºÑ\80Ñ\8bнÑ\96Ñ\86аÑ\9e.\n<strong>Ð\9dелÑ\8cга Ð±ÐµÐ· Ð´Ð°Ð·Ð²Ð¾Ð»Ñ\83 Ð´Ð°Ð´Ð°Ð²Ð°Ñ\86Ñ\8c Ð¼Ð°Ñ\82Ñ\8dÑ\80Ñ\8bÑ\8fлÑ\8b, Ð°Ð±Ð°Ñ\80оненÑ\8bÑ\8f Ð°Ñ\9eÑ\82аÑ\80Ñ\81кÑ\96м Ð¿Ñ\80авам!</strong>",
+       "copyrightwarning2": "Ð\9aалÑ\96 Ð»Ð°Ñ\81ка, Ð·Ð°Ñ\9eважÑ\86е, Ñ\88Ñ\82о Ñ\9eвеÑ\81Ñ\8c Ñ\83нÑ\91Ñ\81ак Ñ\9e {{GRAMMAR:вÑ\96навалÑ\8cнÑ\8b|{{SITENAME}}}} Ð¼Ð¾Ð¶Ð° Ñ\80Ñ\8dдагаваÑ\86Ñ\86а, Ð·Ñ\8cмÑ\8fнÑ\8fÑ\86Ñ\86а Ñ\96 Ð²Ñ\8bдалÑ\8fÑ\86Ñ\86а Ñ\96нÑ\88Ñ\8bмÑ\96 Ñ\9eдзелÑ\8cнÑ\96камÑ\96.\nÐ\9aалÑ\96 Ð²Ñ\8b Ð· Ð³Ñ\8dÑ\82Ñ\8bм Ð½Ñ\8f Ð·Ð³Ð¾Ð´Ð½Ñ\8bÑ\8f, ÐºÐ°Ð»Ñ\96 Ð»Ð°Ñ\81ка, Ð½Ðµ Ð·Ñ\8cмÑ\8fÑ\88Ñ\87айÑ\86е Ñ\81Ñ\8eдÑ\8b Ð\92аÑ\88Ñ\8bÑ\8f Ñ\82Ñ\8dкÑ\81Ñ\82Ñ\8b.<br />\nРазÑ\8cмÑ\8fÑ\88Ñ\87Ñ\8dнÑ\8cнем Ñ\82Ñ\83Ñ\82 Ñ\82Ñ\8dкÑ\81Ñ\82аÑ\9e, Ð²Ñ\8b Ð´Ñ\8dклÑ\8fÑ\80Ñ\83еÑ\86е, Ñ\88Ñ\82о Ð·Ñ\8cÑ\8fÑ\9eлÑ\8fеÑ\86еÑ\81Ñ\8f Ñ\96Ñ\85 Ð°Ñ\9eÑ\82аÑ\80ам, Ñ\86Ñ\96 Ñ\81капÑ\96Ñ\8fвалÑ\96 Ñ\96Ñ\85 Ð· ÐºÑ\80Ñ\8bнÑ\96Ñ\86Ñ\8b, Ñ\8fкаÑ\8f Ð´Ð°Ð·Ð²Ð°Ð»Ñ\8fе Ð²Ð¾Ð»Ñ\8cнае Ð²Ñ\8bкаÑ\80Ñ\8bÑ\81Ñ\82анÑ\8cне Ñ\81ваÑ\96Ñ\85 Ñ\82Ñ\8dкÑ\81Ñ\82аÑ\9e (дзелÑ\8f Ð¿Ð°Ð´Ñ\80абÑ\8fзнаÑ\81Ñ\8cÑ\86Ñ\8fÑ\9e Ð³Ð»Ñ\8fдзÑ\96Ñ\86е $1).\n\n<strong>Ð\9dе Ð·Ñ\8cмÑ\8fÑ\88Ñ\87айÑ\86е Ñ\82Ñ\83Ñ\82 Ð±ÐµÐ· Ð´Ð°Ð·Ð²Ð¾Ð»Ñ\83 Ð¼Ð°Ñ\82Ñ\8dÑ\80Ñ\8bÑ\8fлÑ\8b, Ñ\8fкÑ\96Ñ\8f Ð°Ñ\85оÑ\9eваÑ\8eÑ\86Ñ\86а Ð°Ñ\9eÑ\82аÑ\80Ñ\81кÑ\96м Ð¿Ñ\80авам!</strong>",
        "editpage-cannot-use-custom-model": "Мадэль зьместу гэтай старонкі ня можа быць зьмененая.",
-       "longpageerror": "'''Памылка: Аб’ём тэксту, які Вы спрабуеце запісаць складае $1 {{PLURAL:$1|кілябайт|кілябайты|кілябайтаў}}, што болей устаноўленага абмежаваньня на $2 {{PLURAL:$2|кілябайт|кілябайты|кілябайтаў}}.'''\nСтаронка ня можа быць захаваная.",
+       "longpageerror": "<strong>Памылка: аб’ём тэксту, які вы спрабуеце запісаць складае $1 {{PLURAL:$1|кілябайт|кілябайты|кілябайтаў}}, што болей за ўсталяванае абмежаваньне на $2 {{PLURAL:$2|кілябайт|кілябайты|кілябайтаў}}.</strong>\nСтаронка ня можа быць захаваная.",
        "readonlywarning": "<strong>Папярэджаньне: База зьвестак была заблякаваная для тэхнічнага абслугоўваньня, таму немагчыма цяпер захаваць Вашыя зьмены.</strong>\nВы можаце скапіяваць тэкст у файл на Вашым кампутары, а пазьней захаваць сюды.\n\nСыстэмны адміністратар, які заблякаваў базу зьвестак, прапанаваў наступнае тлумачэньне: $1",
        "protectedpagewarning": "'''Папярэджаньне: Гэтая старонка была абароненая, таму толькі адміністратары могуць рэдагаваць яе.'''\nАпошні запіс з журнала пададзены ніжэй для даведкі:",
        "semiprotectedpagewarning": "'''Заўвага:''' Гэтая старонка была абароненая, і рэдагаваць яе могуць толькі зарэгістраваныя ўдзельнікі.\nАпошні запіс з журнала пададзены ніжэй для даведкі:",
        "search-external": "Вонкавы пошук",
        "searchdisabled": "Функцыя пошуку ў {{GRAMMAR:месны|{{SITENAME}}}} адключаная.\nВы можаце пашукаць з дапамогай Google, але заўважце, што там інфармацыя пра старонкі {{GRAMMAR:родны|{{SITENAME}}}} можа быць састарэлай.",
        "search-error": "Узьнікла памылка пры пошуку: $1",
+       "search-warning": "Пры пошуку зьявілася папярэджаньне: $1",
        "preferences": "Налады",
        "mypreferences": "Налады",
        "prefs-edits": "Колькасьць рэдагаваньняў:",
        "prefs-help-recentchangescount": "Гэта датычыцца апошніх зьменах, гісторый старонак і журналаў.",
        "prefs-help-watchlist-token2": "Гэта сакрэтны ключ да стужкі вашага сьпісу назіраньня.\nКожны, хто ведае яго, можа набыць доступ да вашага сьпісу назіраньня, таму не дзяліцеся ім.\n[[Special:ResetTokens|Пстрыкніце тут, калі вам трэба скінуць яго]].",
        "savedprefs": "Вашыя налады былі захаваныя.",
-       "savedrights": "Ð\9fÑ\80авы {{GENDER:$1|ўдзельніка|ўдзельніцы}} $1 былі захаваныя.",
+       "savedrights": "Ð\93Ñ\80Ñ\83пы {{GENDER:$1|ўдзельніка|ўдзельніцы}} $1 былі захаваныя.",
        "timezonelegend": "Часавы пояс:",
        "localtime": "Мясцовы час:",
        "timezoneuseserverdefault": "Выкарыстоўваць стандартныя налады {{GRAMMAR:родны|{{SITENAME}}}} ($1)",
        "prefswarning-warning": "Вы зрабілі зьмены ў вашых наладах, якія яшчэ не былі захаваныя.\nКалі вы закрыеце гэтую старонку і не націсьніце «$1», вашыя налады ня будуць абноўленыя.",
        "prefs-tabs-navigation-hint": "Падказка: вы можаце пераходзіць паміж укладкамі ў сьпісе ўкладак з дапамогай клявішаў налева і направа.",
        "userrights": "Кіраваньне правамі ўдзельнікаў і ўдзельніц",
-       "userrights-lookup-user": "Ð\9aÑ\96Ñ\80аванÑ\8cне Ð³Ñ\80Ñ\83памÑ\96 Ñ\9eдзелÑ\8cнÑ\96каÑ\9e Ñ\96 Ñ\9eдзелÑ\8cнÑ\96Ñ\86",
+       "userrights-lookup-user": "Ð\92Ñ\8bбаÑ\80 Ñ\83дзелÑ\8cнÑ\96ка",
        "userrights-user-editname": "Увядзіце імя ўдзельніка:",
-       "editusergroup": "РÑ\8dдагаваÑ\86Ñ\8c Ð³Ñ\80Ñ\83пÑ\8b {{GENDER:$1|Ñ\9eдзелÑ\8cнÑ\96каÑ\9e Ñ\96 Ñ\9eдзелÑ\8cнÑ\96Ñ\86}}",
+       "editusergroup": "Ð\97агÑ\80Ñ\83зÑ\96Ñ\86Ñ\8c Ð³Ñ\80Ñ\83пÑ\8b Ñ\9eдзелÑ\8cнÑ\96ка",
        "editinguser": "Зьмена правоў {{GENDER:$1|удзельніка|удзельніцы}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Прагляд правоў {{GENDER:$1|удзельніка|удзельніцы}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Рэдагаваць групы ўдзельнікаў і ўдзельніц",
+       "userrights-viewusergroup": "Прагляд групаў удзельніка",
        "saveusergroups": "Захаваць групы {{GENDER:$1|ўдзельнікаў і ўдзельніц}}",
        "userrights-groupsmember": "Уваходзіць у:",
        "userrights-groupsmember-auto": "Няяўны чалец:",
        "userrights-reason": "Прычына:",
        "userrights-no-interwiki": "Вы ня маеце дазволу зьмяняць правы ўдзельнікаў іншых вікаў.",
        "userrights-nodatabase": "Базы зьвестак $1 не існуе альбо яна не зьяўляецца лякальнай.",
-       "userrights-nologin": "Вы павінны [[Special:UserLogin|ўвайсьці ў сыстэму]] як адміністратар, каб прызначаць правы ўдзельнікам.",
-       "userrights-notallowed": "Вы ня маеце права прызначаць ці выдаляць правы ўдзельнікам.",
        "userrights-changeable-col": "Групы, якія Вы можаце мяняць",
        "userrights-unchangeable-col": "Групы, якія Вы ня можаце мяняць",
        "userrights-conflict": "Канфлікт пры зьмене правоў удзельнікаў! Калі ласка, праверце і захавайце вашыя зьмены.",
-       "userrights-removed-self": "Вы пазбавілі сябе ўласных правоў. З гэтай прычыны вы больш ня маеце доступу да гэтай старонкі.",
        "group": "Група:",
        "group-user": "Удзельнікі",
        "group-autoconfirmed": "Аўтаматычна пацьверджаныя ўдзельнікі",
        "right-siteadmin": "блякаваньне і разблякаваньне базы зьвестак",
        "right-override-export-depth": "экспартаваньне старонак, уключаючы зьвязаныя старонкі з глыбінёй да 5",
        "right-sendemail": "адпраўка электронных лістоў іншым удзельнікам",
-       "right-passwordreset": "прагляд электронных лістоў з ачысткай паролю",
        "right-managechangetags": "стварэньне і (дэ)актывацыя [[Special:Tags|метак]]",
        "right-applychangetags": "дадаваць [[Special:Tags|меткі]] пры рэдагаваньні",
        "right-changetags": "дадаваць і выдаляць адвольныя [[Special:Tags|меткі]] да асобных вэрсіяў і запісаў у журнале падзеяў",
        "action-upload_by_url": "загрузку гэтага файла з URL-адрасу",
        "action-writeapi": "выкарыстаньне API для запісаў",
        "action-delete": "выдаленьне гэтай старонкі",
-       "action-deleterevision": "вÑ\8bдаленÑ\8cне Ð³Ñ\8dÑ\82ай Ð²Ñ\8dÑ\80Ñ\81Ñ\96Ñ\96",
+       "action-deleterevision": "вÑ\8bдаленÑ\8cне Ð²Ñ\8dÑ\80Ñ\81Ñ\96Ñ\8fÑ\9e",
        "action-deletedhistory": "прагляд выдаленай гісторыі гэтай старонкі",
        "action-browsearchive": "пошук выдаленых старонак",
        "action-undelete": "аднаўленьне гэтай старонкі",
        "apisandbox-continue": "Працягнуць",
        "apisandbox-continue-clear": "Ачысьціць",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries працягне] апошні запыт; {{int:apisandbox-continue-clear}} ачысьціць парамэтры, зьвязаныя з працягам.",
+       "apisandbox-param-limit": "Увядзіце <kbd>max</kbd>, каб выкарыстаць максымальны ліміт.",
+       "apisandbox-multivalue-all-namespaces": "$1 (усе прасторы назваў)",
+       "apisandbox-multivalue-all-values": "$1 (усе значэньні)",
        "booksources": "Крыніцы кніг",
        "booksources-search-legend": "Пошук кніг",
        "booksources-isbn": "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",
+       "magiclink-tracking-pmid-desc": "На гэтай старонцы ўжываюцца магічныя спасылкі PMID. Глядзіце [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] пра тое, як зладзіць міграцыю.",
+       "magiclink-tracking-isbn": "Старонкі, на якіх ужытыя магічныя спасылкі ISBN",
+       "magiclink-tracking-isbn-desc": "На гэтай старонцы ўжываюцца магічныя спасылкі ISBN. Глядзіце [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] пра тое, як зладзіць міграцыю.",
        "specialloguserlabel": "Выканаўца:",
        "speciallogtitlelabel": "Мэта (назва ці {{ns:user}}:імя_ўдзельніка для ўдзельніка):",
        "log": "Журналы падзеяў",
        "activeusers-intro": "Гэта сьпіс удзельнікаў, якія былі актыўнымі на працягу $1 {{PLURAL:$1|апошняга дня|апошніх дзён|апошніх дзён}}.",
        "activeusers-count": "$1 {{PLURAL:$1|дзеяньне|дзеяньні|дзеяньняў}} за $3 {{PLURAL:$3|апошні дзень|апошнія дні|апошніх дзён}}",
        "activeusers-from": "Паказваць ўдзельнікаў, пачынаючы з:",
+       "activeusers-groups": "Паказаць удзельнікаў, якія належаць да групаў:",
+       "activeusers-excludegroups": "Выключыць удзельнікаў, якія належаць да групаў:",
        "activeusers-noresult": "Удзельнікі ня знойдзеныя.",
        "activeusers-submit": "Паказаць актыўных удзельнікаў",
        "listgrouprights": "Правы групаў удзельнікаў",
        "emailccsubject": "Копія Вашага ліста да $1: $2",
        "emailsent": "Ліст адасланы",
        "emailsenttext": "Ваш ліст быў адасланы.",
-       "emailuserfooter": "Гэты ліст быў дасланы {{GENDER:$1|ўдзельнікам|ўдзельніцай}} $1 да {{GENDER:$2|ўдзельніка|ўдзельніцы}} $2 з дапамогай функцыі «{{int:emailuser}}» {{GRAMMAR:родны|{{SITENAME}}}}.",
+       "emailuserfooter": "Гэты ліст быў дасланы {{GENDER:$1|ўдзельнікам|ўдзельніцай}} $1 да {{GENDER:$2|ўдзельніка|ўдзельніцы}} $2 з дапамогай функцыі «{{int:emailuser}}» {{GRAMMAR:родны|{{SITENAME}}}}. {{GENDER:$2|Ваш}} ліст у адказ будзе дасланы {{GENDER:$1|адпраўніку|адпраўніцы}}, і {{GENDER:$1|яму|ёй}} будзе бачны {{GENDER:$2|ваш}} адрас электроннай пошты.",
        "usermessage-summary": "Паведамленьне пра выхад з сыстэмы.",
        "usermessage-editor": "Дастаўка сыстэмных паведамленьняў",
        "watchlist": "Сьпіс назіраньня",
        "modifiedarticleprotection": "зьменены ўзровень абароны старонкі «[[$1]]»",
        "unprotectedarticle": "зьнятая абарона з «[[$1]]»",
        "movedarticleprotection": "перанесеныя налады абароны з «[[$2]]» на «[[$1]]»",
+       "protectedarticle-comment": "{{GENDER:$2|Абараніў|Абараніла}} «[[$1]]»",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Зьмяніў узровень|Зьмяніла ўзровень}} абароны для «[[$1]]»",
+       "unprotectedarticle-comment": "{{GENDER:$2|Зьняў|Зьняла}} абарону з «[[$1]]»",
        "protect-title": "Абарона «$1»",
        "protect-title-notallowed": "Прагляд узроўню абароны «$1»",
        "prot_1movedto2": "[[$1]] перанесеная ў [[$2]]",
        "movelogpagetext": "Ніжэй пададзены сьпіс перанесеных старонак.",
        "movesubpage": "{{PLURAL:$1|1=Падстаронка|Падстаронкі}}",
        "movesubpagetext": "Гэтая старонка мае $1 {{PLURAL:$1|падстаронку|падстаронкі|падстаронак}}, {{PLURAL:$1|1=якая паказаная ніжэй|якія паказаныя ніжэй}}.",
+       "movesubpagetalktext": "Адпаведная старонка абмеркаваньня мае $1 {{PLURAL:$1|падстаронку, паказаную|падстаронкі, паказаныя|падстаронак, паказаныя}} ніжэй.",
        "movenosubpage": "Гэтая старонка ня мае падстаронак.",
        "movereason": "Прычына:",
        "revertmove": "адкат",
        "pageinfo-category-pages": "Колькасьць старонак",
        "pageinfo-category-subcats": "Колькасьць падкатэгорыяў",
        "pageinfo-category-files": "Колькасьць файлаў",
+       "pageinfo-user-id": "Ідэнтыфікатар удзельніка",
        "markaspatrolleddiff": "Пазначыць як «патруляваную»",
        "markaspatrolledtext": "Пазначыць гэтую старонку як «патруляваную»",
        "markaspatrolledtext-file": "Пазначыць гэтую вэрсію файлу як патруляваную",
        "patrol-log-header": "Гэта журнал патруляваных вэрсіяў.",
        "log-show-hide-patrol": "$1 журнал патруляваньняў",
        "log-show-hide-tag": "$1 журнал метак",
+       "confirm-markpatrolled-button": "Добра",
+       "confirm-markpatrolled-top": "Пазначыць вэрсію $3 старонкі $2 як патруляваную?",
        "deletedrevision": "Выдаленая старая вэрсія $1",
        "filedeleteerror-short": "Памылка выдаленьня файла: $1",
        "filedeleteerror-long": "У часе выдаленьня файла ўзьніклі наступныя памылкі:\n\n$1",
        "tags-deactivate": "адключыць",
        "tags-hitcount": "$1 {{PLURAL:$1|зьмена|зьмены|зьменаў}}",
        "tags-manage-no-permission": "Вы ня маеце правоў на зьмену метак.",
-       "tags-manage-blocked": "Вы ня можаце мяняць меткі, калі вы заблякаваныя.",
+       "tags-manage-blocked": "Вы ня можаце мяняць меткі, калі {{GENDER:$1|вы}} заблякаваныя.",
        "tags-create-heading": "Стварэньне новай меткі",
        "tags-create-explanation": "Па змоўчаньні, наваствораныя меткі будуць даступныя для выкарыстаньня ўдзельнікамі і робатамі.",
        "tags-create-tag-name": "Назва меткі:",
        "tags-deactivate-not-allowed": "Немагчыма дэактываваць метку «$1».",
        "tags-deactivate-submit": "Адключыць",
        "tags-apply-no-permission": "Вы ня маеце права прымяняць меткі да вашых рэдагаваньняў.",
-       "tags-apply-blocked": "Вы ня можаце мяняць меткі да вашых зьменаў, калі вы заблякаваныя.",
+       "tags-apply-blocked": "Вы ня можаце мяняць меткі да вашых зьменаў, калі {{GENDER:$1|вы}} заблякаваныя.",
        "tags-apply-not-allowed-one": "Метка «$1» ня можа быць прызначаная ўручную.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Наступную метку|Наступныя меткі}} нельга дадаваць уручную: $1",
        "tags-update-no-permission": "Вы ня маеце права на дадаваньне ці выдаленьне метак зьменаў для асобных вэрсіяў ці запісаў журналаў.",
-       "tags-update-blocked": "Ð\9fакÑ\83лÑ\8c Ð\92Ñ\8b Ð·Ð°Ð±Ð»Ñ\8fкаванÑ\8bÑ\8f, Ð\92Ñ\8b Ð½Ñ\8f Ð¼Ð¾Ð¶Ð°Ñ\86е Ð´Ð°Ð´Ð°Ð²Ð°Ñ\86Ñ\8c Ñ\96 Ð²Ñ\8bдалÑ\8fÑ\86Ñ\8c Ð¼ÐµÑ\82кÑ\96 Ð·Ñ\8cменаÑ\9e.",
+       "tags-update-blocked": "Ð\92Ñ\8b Ð½Ñ\8f Ð¼Ð¾Ð¶Ð°Ñ\86е Ð´Ð°Ð´Ð°Ð²Ð°Ñ\86Ñ\8c Ñ\96 Ð²Ñ\8bдалÑ\8fÑ\86Ñ\8c Ð¼ÐµÑ\82кÑ\96 Ð·Ñ\8cменаÑ\9e, Ð¿Ð°ÐºÑ\83лÑ\8c {{GENDER:$1|вÑ\8b}} Ð·Ð°Ð±Ð»Ñ\8fкаванÑ\8bÑ\8f.",
        "tags-update-add-not-allowed-one": "Метка «$1» ня можа быць дададзеная ўручную.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|1=Наступную метку|Наступныя меткі}} нельга дадаваць уручную: $1",
        "tags-update-remove-not-allowed-one": "Метка «$1» ня можа быць выдаленая.",
        "htmlform-user-not-exists": "<strong>$1</strong> не існуе.",
        "htmlform-user-not-valid": "<strong>$1</strong> — некарэктнае імя карыстальніка.",
        "logentry-delete-delete": "$1 {{GENDER:$2|выдаліў|выдаліла}} старонку $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|выдаліў|выдаліла}} перанакіраваньне $3 шляхам перазапісу",
        "logentry-delete-restore": "$1 {{GENDER:$2|аднавіў|аднавіла}} старонку $3",
        "logentry-delete-event": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|1=падзеі ў журнале|падзеяў у журнале}} на $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|вэрсіі|вэрсіяў}} старонкі $3: $4",
index a0b0d44..4da0c06 100644 (file)
        "views": "Віды",
        "toolbox": "Прылады",
        "tool-link-userrights": "Змяніць групы {{GENDER:$1|ўдзельніка|ўдзельніцы}}",
+       "tool-link-userrights-readonly": "Паказаць групы {{GENDER:$1|ўдзельніка|ўдзельніцы}}",
        "tool-link-emailuser": "Напісаць ліст {{GENDER:$1|удзельніку|удзельніцы}}",
        "userpage": "Паказаць старонку ўдзельніка",
        "projectpage": "Паказаць старонку праекта",
        "passwordreset-emaildisabled": "Функцыі эл.пошты адключаны на гэтай Вікі.",
        "passwordreset-username": "Імя ўдзельніка:",
        "passwordreset-domain": "Дамен:",
-       "passwordreset-capture": "Праглядзець напісаны ліст?",
-       "passwordreset-capture-help": "Калі вы паставіце адзнаку, то вам будзе паказаны ліст з часовым паролем, які адпраўляецца ўдзельніку.",
        "passwordreset-email": "Адрас электроннай пошты:",
        "passwordreset-emailtitle": "Інфармацыя пра рахунак на сайце {{SITENAME}}",
        "passwordreset-emailtext-ip": "Нехта (магчыма вы, з IP-адрасу $1) запытаў скід  вашага пароля ў праекце {{SITENAME}} ($4).\n{{PLURAL:$3|Наступны ўліковы запіс звязаны|Наступныя ўліковыя запісы звязаны}} з гэтым адрасам электроннай пошты:\n\n$2\n\n{{PLURAL:$3|Гэты часовы пароль будзе|Гэтыя часовыя паролі будуць}} дзейнічаць {{PLURAL:$5|адзін дзень|$5 дні|$5 дзён}}.\nВы павінны зараз увайсці ў сістэму і абраць новы пароль. Калі вы не рабілі гэтага запыту, ці ўспомнілі свой зыходны пароль і не жадаеце яго мяняць, вы можаце праігнараваць гэтае паведамленне і працягнуць выкарыстоўваць свой стары пароль.",
        "passwordreset-emailelement": "Імя ўдзельніка: \n$1\n\nЧасовы пароль: \n$2",
        "passwordreset-emailsentemail": "Калі гэты адрас электроннай пошты злучаны з вашым уліковым запісам, будзе адпраўлены ліст пра скід пароля.",
        "passwordreset-emailsentusername": "Калі ёсць адрас электроннай пошты, злучаны з гэтым імем удзельніка, то будзе дасланы ліст пра скід пароля.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Электронны ліст|электронныя лісты}} скіду пароля адпраўлены. {{PLURAL:$1|Імя ўдзельніка і пароль|Спіс імён удзельнікаў і паролі}} паказаны ніжэй.",
-       "passwordreset-emailerror-capture2": "Не ўдалося даслаць {{GENDER:$2|удзельніку|удзельніцы}} ліст электроннай поштай: $1 {{PLURAL:$3|Імя ўдзельніка і пароль|Спіс імён удзельнікаў і паролі}} паказаны ніжэй.",
        "passwordreset-nocaller": "Мусіць быць указана, хто выклікае",
        "passwordreset-nosuchcaller": "Аўтар выкліку не існуе: $1",
        "passwordreset-ignored": "Скід пароля не быў апрацаваны. Магчыма, не настроены пастаўшчык?",
-       "passwordreset-invalideamil": "Няслушны адрас электроннай пошты",
+       "passwordreset-invalidemail": "Няслушны адрас электроннай пошты",
        "passwordreset-nodata": "Не былі пададзены ні імя ўдзельніка, ні адрас электроннай пошты",
        "changeemail": "Змяніць або выдаліць адрас электроннай пошты",
        "changeemail-header": "Запоўніце гэтую форму, каб змяніць свой адрас электроннай пошты. Калі хочаце выдаліць адрас электроннай пошты, злучаны з вашым уліковым запісам, пакіньце поле новага адраса электроннай пошты пустым пры адпраўцы формы.",
        "usercssyoucanpreview": "<strong>Парада:</strong> Карыстайцеся кнопкай \"''{{int:showpreview}}''\", каб паспрабаваць новы код CSS перад тым, як яго запісваць.",
        "userjsyoucanpreview": "<strong>Парада:</strong> Карыстайцеся кнопкай \"''{{int:showpreview}}''\", каб паспрабаваць новы код JavaScript перад тым, як яго запісваць.",
        "usercsspreview": "'''Памятайце, што гэта толькі папярэдні паказ вашага ўласнага CSS. Праўкі яшчэ не замацаваныя!'''",
-       "userjspreview": "'''Памятайце, што гэта выпрабаванне/папярэдні паказ вашага ўласнага Яваскрыпту, які яшчэ не быў замацаваны!'''",
-       "sitecsspreview": "'''Памятайце, што гэта толькі папярэдні паказ вашага CSS.'''\n'''Праўкі яшчэ не замацаваныя!'''",
-       "sitejspreview": "'''Памятайце, што гэта толькі папярэдні паказ вашага JavaScript.'''\n'''Праўкі яшчэ не замацаваныя!'''",
-       "userinvalidcssjstitle": "'''Увага:''' Няма вокладкі з назвай \"$1\". Памятайце, што свае старонкі .css і .js называюцца толькі малымі літарамі, такім чынам, напр., {{ns:user}}:Foo/vector.css, а не {{ns:user}}:Foo/Vector.css.",
+       "userjspreview": "<strong>Памятайце, што гэта толькі выпрабаванне/папярэдні паказ вашага JavaScript. Праўкі яшчэ не замацаваныя!</strong>",
+       "sitecsspreview": "<strong>Памятайце, што гэта толькі папярэдні паказ вашага CSS.\nПраўкі яшчэ не замацаваныя!</strong>",
+       "sitejspreview": "<strong>Памятайце, што гэта толькі папярэдні паказ вашага JavaScript.\nПраўкі яшчэ не замацаваныя!</strong>",
+       "userinvalidcssjstitle": "<strong>Увага:</strong> Няма вокладкі з назвай \"$1\". Памятайце, што свае старонкі .css і .js называюцца толькі малымі літарамі, такім чынам, напр., {{ns:user}}:Foo/vector.css, а не {{ns:user}}:Foo/Vector.css.",
        "updated": "(Абноўлена)",
        "note": "<strong>Заўвага:</strong>",
        "previewnote": "<strong>Памятайце, гэта толькі папярэдні паказ.</strong> Праўкі яшчэ не замацаваныя!",
        "session_fail_preview": "Не ўдалося апрацаваць вашу праўку, таму што сервер згубіў звесткі аб вашым сеансе.\n\nМагчыма, вы выйшлі з сістэмы. <strong>Калі ласка, праверце, што вы ўвайшлі ў сістэму і паспрабуйце яшчэ раз.</strong>\nКалі і тады не атрымаецца, паспрабуйце [[Special:UserLogout|выйсці з сістэмы]] і зайсці ізноў, таксама праверце, што ваш браўзер дазваляе кукі з гэтага сайта.",
        "session_fail_preview_html": "Не ўдалося апрацаваць вашу праўку з-за таго, што згубіліся даныя аб сеансе.\n\n<em>Перадпаказ не зроблены, бо на пляцоўцы {{SITENAME}} дазволены сыры код HTML, што робіць магчымымі атакі праз Яваскрыпт.</em>\n\n<strong>Калі гэта нармальная спроба праўкі, паспрабуйце паўтарыць запісванне.</strong>\nКалі і гэта не дапаможа, паспрабуйце [[Special:UserLogout|выйсці з сістэмы]] і ўвайсці ізноў, таксама праверце, што ваш браўзер дазваляе кукі з гэтага сайта.",
        "token_suffix_mismatch": "'''Ваша праўка была адхілена, каб пазбегнуць сапсавання тэксту старонкі, таму што ваш браўзер папсаваў знакі прыпынку ў квітку праўкі.\nМагчыма, прычына ў выкарыстанні вамі ананімнага проксі-сервера, праграмы якога працуюць некарэктна.'''",
-       "edit_form_incomplete": "'''Некаторыя часткі формы рэдагавання не дасягнулі сервера. Упэўніцеся, што Вашыя рэдагаванні не пашкоджаныя і паспрабуйце зноў.'''",
+       "edit_form_incomplete": "<strong>Некаторыя часткі формы рэдагавання не дасягнулі сервера. Упэўніцеся, што Вашыя рэдагаванні не пашкоджаныя і паспрабуйце зноў.</strong>",
        "editing": "Правім $1",
        "creating": "Стварэнне старонкі «$1»",
        "editingsection": "Правім $1 (раздзел)",
        "explainconflict": "Нехта іншы змяніў старонку пасля таго, як вы пачалі працу з ёю.\nВерхняе тэкставае поле паказвае актуальны зыходны тэкст старонкі.\nВашы праўкі паказаны ў ніжнім тэкставым полі.\nВам трэба будзе далучыць іх да актуальнага зыходнага тэксту.\nКалі націснуць \"{{int:savearticle}}\", будзе запісаны '''толькі''' тэкст у верхнім полі.",
        "yourtext": "Свой тэкст",
        "storedversion": "Захаваная версія",
-       "nonunicodebrowser": "'''УВАГА: ваш браўзер не працуе з Унікодам. Каб вы маглі карэктна  правіць старонкі, ужываецца такая штука, што знакі з па-за абсягу ASCII паказваюцца ў рэдактарскім акне як шаснаццаткавыя коды.'''",
-       "editingold": "'''УВАГА: Вы правіце такую версію артыкула, якая не з'яўляецца актуальнай.\nКалі вы яе зараз запішаце, то страціце змены ў артыкуле, зробленыя пасля колішняга запісу гэтай версіі.'''",
+       "nonunicodebrowser": "<strong>Увага: ваш браўзер не працуе з Unicode-кадаваннем.</strong> Каб вы маглі карэктна правіць старонкі, усе знакі, не ўключаныя ў ASCII, паказваюцца ў рэдактарскім акне як шаснаццаткавыя коды.",
+       "editingold": "<strong>Увага: Вы правіце састарэлую версію гэтай старонкі.</strong>\nКалі Вы паспрабуеце захаваць яе, то страціце змены ў артыкуле, зробленыя пасля колішняга запісу гэтай версіі.",
        "yourdiff": "Адрозненні",
        "copyrightwarning": "Заўважце, што ўсе ўклады на {{SITENAME}} лічацца выданымі на ўмовах $2 (бач падрабязнасці на $1). Калі вы не жадаеце, каб вашыя матэрыялы бязлітасна правіліся, і свабодна распаўсюджваліся, то і не аддавайце іх сюды.<br />\nТаксама вы нам абяцаеце, што напісалі гэта самі, або скапіравалі з рэсурсу, які знаходзіцца ў публічнай уласнасці, або з аналагічнага свабоднага рэсурсу.\n'''НЕ КЛАДЗІЦЕ СЮДЫ, БЕЗ АДПАВЕДНАГА ДАЗВОЛУ, МАТЭРЫЯЛУ, ЯКІ АХОЎВАЕЦЦА АЎТАРСКІМ ПРАВАМ!'''",
        "copyrightwarning2": "Заўважце, што кожны ўклад на {{SITENAME}} можа быць папраўлены, зменены або выдалены іншымі ўдзельнікамі. Калі вы не жадаеце, каб вашыя матэрыялы бязлітасна правіліся, то і не давайце іх сюды.<br />\nТаксама вы нам абяцаеце, што напісалі гэта самі, або скапіравалі з рэсурсу, які знаходзіцца ў публічнай уласнасці, або з аналагічнага свабоднага рэсурсу (бач падрабязнасці на $1).\n'''НЕ КЛАДЗІЦЕ СЮДЫ, БЕЗ АДПАВЕДНАГА ДАЗВОЛУ, МАТЭРЫЯЛУ, ЯКІ АХОЎВАЕЦЦА АЎТАРСКІМ ПРАВАМ!'''",
        "search-external": "Вонкавы пошук",
        "searchdisabled": "Функцыя пошуку {{SITENAME}} не працуе. Тымчасова можна шукаць з дапамогай Google. Заўважце, што тамтэйшыя індэксы зместу {{SITENAME}} могуць не быць актуальнымі.",
        "search-error": "Памылка пошуку: $1",
+       "search-warning": "Пры пошуку з'явілася папярэджанне: $1",
        "preferences": "Настройкі",
        "mypreferences": "Настройкі",
        "prefs-edits": "Колькасць правак:",
        "userrights-reason": "Прычына:",
        "userrights-no-interwiki": "Вам не дазволена мяняць дазволаў карыстальнікам на іншых Вікі-ах.",
        "userrights-nodatabase": "Не знойдзена тут, або не існуе база даных $1.",
-       "userrights-nologin": "Належыць [[Special:UserLogin|увайсці ў сістэму]] на рахунак адміністратара, каб прызначаць дазволы ўдзельнікам.",
-       "userrights-notallowed": "Вам не дазволена дадаваць ці выдаляць правы ўдзельнікаў.",
        "userrights-changeable-col": "Групы, якія вам дазволена мяняць",
        "userrights-unchangeable-col": "Групы, якія вам не дазволена мяняць",
        "userrights-conflict": "Канфлікт змянення ўдзельніцкіх дазволаў! Калі ласка, праверце і пацвердзіце змены.",
-       "userrights-removed-self": "Вы выдалілі свае ўласныя правы. Такім чынам, Вы больш не зможаце атрымаць доступ да гэтай старонкі.",
        "group": "Група:",
        "group-user": "Удзельнікі",
        "group-autoconfirmed": "Аўта-пацверджаныя ўдзельнікі",
        "right-siteadmin": "Замыкаць і адмыкаць базу даных",
        "right-override-export-depth": "Экспартаваць старонкі, у тым ліку звязаныя, да глыбіні спасылак 5.",
        "right-sendemail": "Адпраўляць электронныя лісты іншым удзельнікам",
-       "right-passwordreset": "Бачыць электронныя лісты аб змяненні пароля",
        "right-managechangetags": "Ствараць і (дэ)актываваць [[Special:Tags|біркі]]",
        "right-applychangetags": "Прымяняць [[Special:Tags|біркі]] са сваімі праўкамі",
        "right-changetags": "Дадаваць і выдаляць адвольныя [[Special:Tags|біркі]] да асобных версій і запісаў у журнале падзей",
        "apisandbox-results-fixtoken": "Папраўце токен і паўтарыце адпраўку",
        "apisandbox-alert-page": "Палі на гэтай старонцы недапушчальныя.",
        "apisandbox-alert-field": "Значэнне гэтага поля недапушчальнае.",
+       "apisandbox-continue": "Працягнуць",
+       "apisandbox-continue-clear": "Ачысціць",
+       "apisandbox-param-limit": "Увядзіце <kbd>max</kbd>, каб выкарыстаць максімальны ліміт.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Усе прасторы назваў)",
+       "apisandbox-multivalue-all-values": "$1 (Усе значэнні)",
        "booksources": "Кнігі",
        "booksources-search-legend": "Знайсці, дзе купіць кнігі",
        "booksources-search": "Пошук",
        "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",
+       "magiclink-tracking-pmid-desc": "На гэтай старонцы ўжываюцца чароўныя спасылкі PMID. Глядзіце [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] пра тое, як перанесці.",
+       "magiclink-tracking-isbn": "Старонкі, на якіх ужытыя чароўныя спасылкі ISBN",
+       "magiclink-tracking-isbn-desc": "На гэтай старонцы ўжываюцца чароўныя спасылкі ISBN. Глядзіце [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] пра тое, як перанесці.",
        "specialloguserlabel": "Выканаўца:",
        "speciallogtitlelabel": "Мэта (назва ці {{ns:user}}:імя_ўдзельніка для ўдзельніка):",
        "log": "Журналы",
        "activeusers-intro": "Гэта пералік удзельнікаў, якія нешта рабілі за апошнія $1 {{PLURAL:$1|дзень|дзён}}.",
        "activeusers-count": "$1 {{PLURAL:$1|дзеянне|дзеянні|дзеянняў}} за апошні{{PLURAL:$3| дзень|я $3 дні|я $3 дзён}}",
        "activeusers-from": "Паказ, пачынаючы з:",
+       "activeusers-groups": "Паказаць удзельнікаў, якія належаць да групаў:",
        "activeusers-noresult": "Няма такіх удзельнікаў.",
        "activeusers-submit": "Паказаць актыўных удзельнікаў",
        "listgrouprights": "Дазволы для груп удзельнікаў",
        "modifiedarticleprotection": "зменены ўзровень аховы \"[[$1]]\"",
        "unprotectedarticle": "знятая ахова з \"[[$1]]\"",
        "movedarticleprotection": "настройкі аховы перанесеныя з \"[[$2]]\" у \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Абараніў|Абараніла}} «[[$1]]»",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Змяніў узровень|Змяніла ўзровень}} абароны для «[[$1]]»",
+       "unprotectedarticle-comment": "{{GENDER:$2|Зняў|Зняла}} абарону з «[[$1]]»",
        "protect-title": "Ахова «$1»",
        "protect-title-notallowed": "Прагляд узроўня аховы «$1»",
        "prot_1movedto2": "[[$1]] перанесена ў [[$2]]",
        "pageinfo-category-pages": "Колькасць старонак",
        "pageinfo-category-subcats": "Колькасць падкатэгорый",
        "pageinfo-category-files": "Колькасць файлаў",
+       "pageinfo-user-id": "Ідэнтыфікатар удзельніка",
        "markaspatrolleddiff": "Пазначыць як ухваленае",
        "markaspatrolledtext": "Пазначыць старонку як ухваленую",
        "markaspatrolledtext-file": "Пазначыць версію файла як ухваленую",
        "patrol-log-header": "Журнал ухваленых версій",
        "log-show-hide-patrol": "$1 журнал ухваленняў",
        "log-show-hide-tag": "$1 журнал бірак",
+       "confirm-markpatrolled-button": "Добра",
+       "confirm-markpatrolled-top": "Пазначыць версію $3 старонкі $2 як патруляваную?",
        "deletedrevision": "Сцёрта старая версія $1",
        "filedeleteerror-short": "Памылка пры сціранні файла: $1",
        "filedeleteerror-long": "Памылкі пры спробе сцірання файла:\n\n$1",
        "confirm-watch-top": "Дабавіць старонку ў спіс назірання",
        "confirm-unwatch-button": "ОК",
        "confirm-unwatch-top": "Выняць гэту старонку з вашага спіса назірання?",
+       "confirm-rollback-button": "Добра",
        "confirm-rollback-top": "Адкаціць праўкі гэтай старонкі?",
        "quotation-marks": "«$1»",
        "imgmultipageprev": "← папярэдняя старонка",
        "tags-actions-header": "Дзеянні",
        "tags-active-yes": "Да",
        "tags-active-no": "Не",
-       "tags-source-extension": "Ð\92Ñ\8bзнаÑ\87аеÑ\86Ñ\86а ÐºÐ°Ð½Ñ\87аÑ\82кам Ð½Ð°Ð·Ð²Ñ\8b",
+       "tags-source-extension": "Ð\92Ñ\8bзнаÑ\87аеÑ\86Ñ\86а Ð¿Ñ\80агÑ\80амнÑ\8bм Ð·Ð°Ð±ÐµÑ\81пÑ\8fÑ\87Ñ\8dннем",
        "tags-source-manual": "Ставіцца ўручную ўдзельнікамі і робатамі",
        "tags-source-none": "Больш не выкарыстоўваецца",
        "tags-edit": "правіць",
        "tags-activate": "актываваць",
        "tags-deactivate": "адключыць",
        "tags-hitcount": "$1 {{PLURAL:$1|змена|змены|змен}}",
-       "tags-manage-blocked": "Вы не можаце мяняць меткі, калі вы заблакаваныя.",
+       "tags-manage-no-permission": "У вас няма дазволу на кіраванне біркамі змен.",
+       "tags-manage-blocked": "Вы не можаце мяняць меткі, калі {{GENDER:$1|Вы}} заблакаваныя.",
        "tags-create-heading": "Стварыць новую бірку",
        "tags-create-explanation": "Калі не ўказана іншае, новыя біркі будуць даступны для выкарыстання ўдзельнікам і робатам.",
        "tags-create-tag-name": "Назва біркі:",
        "tags-create-invalid-chars": "Назвы бірак не павінны ўтрымліваць коскі (<code>,</code>) або касыя рысы (<code>/</code>).",
        "tags-create-invalid-title-chars": "Назвы бірак не павінны ўтрымліваць сімвалы, якія нельга выкарыстоўваць у назвах старонак.",
        "tags-create-already-exists": "Бірка \"$1\" ужо ёсць.",
+       "tags-create-warnings-above": "Пры спробе стварыць бірку \"$1\" {{PLURAL:$2|выяўлена наступнае папярэджанне|выяўлены наступныя папярэджанні}}:",
        "tags-create-warnings-below": "Вы хочаце прадоўжыць стварэнне біркі?",
        "tags-delete-title": "Сцерці бірку",
        "tags-delete-explanation-initial": "Вы збіраецеся выдаліць бірку \"$1\" з базы звестак.",
        "tags-delete-not-found": "Бірка \"$1\" не існуе.",
        "tags-delete-too-many-uses": "Бірка \"$1\" прыменена ў больш чым $2 {{PLURAL:$2|версіі|версіях}}, а значыць, яна не можа быць сцёрта.",
        "tags-delete-warnings-after-delete": "Бірка \"$1\" была сцёрта, але {{PLURAL:$2|1=атрымана наступнае папярэджанне|атрыманы наступныя папярэджанні}}:",
+       "tags-delete-no-permission": "У вас няма дазволу на выдаленне бірак змен.",
        "tags-activate-title": "Актываваць бірку",
        "tags-activate-question": "Вы збіраецеся актываваць бірку \"$1\".",
        "tags-activate-reason": "Прычына:",
        "tags-deactivate-reason": "Прычына:",
        "tags-deactivate-not-allowed": "Немагчыма дэактываваць бірку \"$1\".",
        "tags-deactivate-submit": "Дэактываваць",
-       "tags-apply-blocked": "Вы не можаце мяняць меткі да Вашых зменаў, калі вы заблакаваныя.",
+       "tags-apply-no-permission": "У вас няма дазволу на прымяненне бірак змен разам а вашымі зменамі.",
+       "tags-apply-blocked": "Вы не можаце мяняць меткі да вашых зменаў, калі {{GENDER:$1|вы}}  заблакаваныя.",
+       "tags-apply-not-allowed-one": "Бірку \"$1\" нельга прызначаць уручную.",
+       "tags-apply-not-allowed-multi": "{{PLURAL:$2|Наступную бірку|Наступныя біркі}} нельга прызначаць уручную: $1",
+       "tags-update-no-permission": "У вас няма дазволу на дадаванне ці выдаленне бірак змен з асобных версій ці запісаў журнала.",
+       "tags-update-blocked": "Вы не можаце дадаваць або выдаляць біркі змен, калі {{GENDER:$1|Вы}} заблакаваныя.",
        "tags-update-add-not-allowed-one": "Бірку \"$1\" нельга дадаваць уручную.",
+       "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Наступную бірку|Наступныя біркі}} нельга дадаць уручную: $1",
        "tags-update-remove-not-allowed-one": "Бірку \"$1\" нельга выдаляць.",
        "tags-update-remove-not-allowed-multi": "{{PLURAL:$2|Наступную бірку|Наступныя біркі}} нельга выдаляць уручную: $1",
        "tags-edit-title": "Правіць біркі",
        "htmlform-user-not-exists": "<strong>$1</strong> не існуе.",
        "htmlform-user-not-valid": "<strong>$1</strong> - недапушчальная назва уліковага запісу.",
        "logentry-delete-delete": "$1 {{GENDER:$2|сцёр|сцёрла}} старонку $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|выдаліў|выдаліла}} перанакіраванне $3 шляхам перазапісу",
        "logentry-delete-restore": "$1 {{GENDER:$2|аднавіў|аднавіла}} старонку $3",
        "logentry-delete-event": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць {{PLURAL:$5|запісу журнала|$5 запісаў журнала}} $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць {{PLURAL:$5|версіі|$5 версій|$5 версій}} старонкі $3: $4",
        "feedback-submit": "Даслаць",
        "feedback-thanks": "Дзякуй! Ваш водгук размешчаны на старонцы «[$2 $1]».",
        "feedback-thanks-title": "Дзякуем!",
-       "searchsuggest-search": "Шукаць у {{SITENAME}}",
+       "searchsuggest-search": "Шукаць у {{GRAMMAR:месны|{{SITENAME}}}}",
        "searchsuggest-containing": "змяшчае...",
        "api-error-badaccess-groups": "У Вас няма дазволу загружаць файлы ў гэтую вікі.",
        "api-error-badtoken": "Унутраная памылка: няслушны ключ.",
        "authmanager-autocreate-noperm": "Аўтаматычнае стварэнне уліковых запісаў не дапускаецца.",
        "authmanager-autocreate-exception": "Аўтаматычнае стварэнне уліковых запісаў часова адключана з-за памылак папярэдніх.",
        "authmanager-userdoesnotexist": "Уліковы запіс удзельніка \"$1\" не зарэгістраваны.",
+       "authmanager-userlogin-remembermypassword-help": "Ці трэба памятаць пароль даўжэй за працягласць сеанса.",
        "authmanager-username-help": "Імя карыстальніка для праверкі сапраўднасці.",
        "authmanager-password-help": "Пароль для праверкі сапраўднасці.",
        "authmanager-domain-help": "Дамен для знешняй праверкі сапраўднасці.",
        "linkaccounts-success-text": "Акаўнт быў звязаны.",
        "linkaccounts-submit": "Звязаць акаўнты",
        "unlinkaccounts": "Адмяніць сувязь уліковых запісаў",
-       "unlinkaccounts-success": "Сувязь акаўнтаў была выдалена."
+       "unlinkaccounts-success": "Сувязь акаўнтаў была выдалена.",
+       "userjsispublic": "Звярніце ўвагу: укладзеныя JavaScript-старонкі не павінны ўтрымліваць канфідэнцыйныя звесткі, бо іх могуць бачыць іншыя ўдзельнікі.",
+       "usercssispublic": "Звярніце ўвагу: укладзеныя CSS-старонкі не павінны ўтрымліваць канфідэнцыйныя звесткі, бо іх могуць бачыць іншыя ўдзельнікі.",
+       "restrictionsfield-badip": "Няслушны IP-адрас ці дыяпазон: $1",
+       "restrictionsfield-label": "Дазволеныя дыяпазоны IP-адрасоў:"
 }
index 4d8d730..649847c 100644 (file)
        "passwordreset-emaildisabled": "Функцията за електронна поща е изключена в това уики.",
        "passwordreset-username": "Потребителско име:",
        "passwordreset-domain": "Домейн:",
-       "passwordreset-capture": "Преглеждане на електронното писмо?",
-       "passwordreset-capture-help": "Поставянето на отметка в това поле ще покаже електронното писмо (с временната парола), което ще бъде изпратено и до потребителя.",
        "passwordreset-email": "Електронна поща:",
        "passwordreset-emailtitle": "Подробности за сметката в {{SITENAME}}",
        "passwordreset-emailtext-ip": "Някой (вероятно вие, от IP адрес $1) поиска възстановяване на паролата за сметката в {{SITENAME}} ($4). За {{PLURAL:$3|следната сметка|следните сметки}}\nе посочен този адрес за електронна поща:\n\n$2\n\n{{PLURAL:$3|Тази временна парола ще бъде активна|Тези временни пароли ще бъдат активни}} {{PLURAL:$5|един ден|$5 дни}}.\nСега би трябвало да влезете в системата и да си изберете нова парола. Ако заявката е направена от друг или пък сте си спомнили паролата и не искате да я променяте, можете да пренебрегнете това съобщение и да продължите да използвате старата си парола.",
        "passwordreset-emailelement": "Потребителско име: \n$1\n\nВременна парола: \n$2",
        "passwordreset-emailsentemail": "Ако електронната Ви поща е свързана със сметката Ви, на нея е изпратено писмо за възстановяване на паролата.",
        "passwordreset-emailsentusername": "Ако това потребителско име е свързано с електронна поща, е изпратено писмо за възстановяване на паролата.",
-       "passwordreset-invalideamil": "Неправилен email адрес",
+       "passwordreset-invalidemail": "Неправилен email адрес",
        "changeemail": "Промяна или премахване на адреса за е-поща",
        "changeemail-header": "Попълнете формуляра, за да промените адреса на електронната си поща. Ако искате да премахнете адреса на електронната си поща, при попълване на формуляра оставете полето за новия адрес празно.",
        "changeemail-no-info": "За да достъпвате тази страница директно, необходимо е да влезете в системата.",
        "previewnote": "<strong>Обърнете внимание, че това е само предварителен преглед.</strong>\nПромените все още не са съхранени!",
        "continue-editing": "Продължаване към полето за редактиране",
        "previewconflict": "Този предварителен преглед отразява текста в горната текстова кутия така, както би се показал, ако съхраните.",
-       "session_fail_preview": "За съжаление редакцията ви не успя да бъде обработена поради загуба на данните за текущата сесия.\n\nМоже би сте излезли от системата. <strong>Моля, уверете се, че сте влезли в профила си и опитайте отново. \nАко все още не работи, опитайте да [[Special:UserLogout|излезете]] и да влезете отново, също така проверете дали браузърът ви позволява бисквитки от този сайт.",
+       "session_fail_preview": "За съжаление редакцията ви не успя да бъде обработена поради загуба на данните за текущата сесия.\n\nМоже би сте излезли от системата. <strong>Моля, уверете се, че сте влезли в профила си и опитайте отново.</strong>\nАко все още не работи, опитайте да [[Special:UserLogout|излезете]] и да влезете отново, също така проверете дали браузърът ви позволява бисквитки от този сайт.",
        "session_fail_preview_html": "'''За съжаление редакцията ви не беше записана поради изтичането на сесията ви.'''\n\n''Тъй като {{SITENAME}} приема обикновен HTML, предварителният преглед е скрит като предпазна мярка срещу атаки чрез Джаваскрипт.''\n\n'''Опитайте отново. Ако все още не сработва, пробвайте да [[Special:UserLogout|излезете]] и влезете отново.'''",
        "token_suffix_mismatch": "'''Редакцията ви беше отхвърлена, защото браузърът ви е развалил пунктуационните знаци в редакционната отметка. Евентуалното съхранение би унищожило съдържанието на страницата. Понякога това се случва при използването на грешно работещи анонимни междинни сървъри.'''",
        "edit_form_incomplete": "'''Някои части от формуляра за редактиране не достигнаха до сървъра; проверете дали редакциите ви са непокътнати и опитайте отново.'''",
        "userrights-reason": "Причина:",
        "userrights-no-interwiki": "Нямате права да редактирате потребителските групи на други уикита.",
        "userrights-nodatabase": "Базата данни $1 не съществува или не е на локалния сървър.",
-       "userrights-nologin": "За управление на потребителските права е необходимо [[Special:UserLogin|влизане]] с администраторска сметка.",
-       "userrights-notallowed": "Нямате права да добавяте или премахвате потребителски права.",
        "userrights-changeable-col": "Групи, които можете да променяте",
        "userrights-unchangeable-col": "Групи, които не можете да променяте",
        "group": "Потребителска група:",
        "right-siteadmin": "заключване и отключване на базата от данни",
        "right-override-export-depth": "Изнасяне на страници, включително свързаните с тях в дълбочина до пето ниво",
        "right-sendemail": "Изпращане на е-писма до другите потребители",
-       "right-passwordreset": "Преглеждане на е-писма за възстановяване на парола",
        "grant-group-email": "Изпращане на е-писмо",
        "grant-blockusers": "Блокиране и отблокиране на потребители",
        "grant-createaccount": "Създаване на сметки",
        "authmanager-provider-temporarypassword": "Временна парола",
        "authprovider-resetpass-skip-label": "Пропусни",
        "specialpage-securitylevel-not-allowed-title": "Не е позволено",
-       "cannotauth-not-allowed-title": "Достъпът е отказан",
-       "edit-error-short": "Грешка: $1",
-       "edit-error-long": "Грешки:\n\n$1"
+       "cannotauth-not-allowed-title": "Достъпът е отказан"
 }
index 8182cc1..cdc13ad 100644 (file)
        "october-date": "$1 اکتوبر",
        "november-date": "$1 نوامبر",
        "december-date": "$1 ڈ\tسمبر",
+       "period-am": "سوب",
+       "period-pm": "دي‌گر/نواشام",
        "pagecategories": "{{PLURAL:$1|تهر|تهرئان}}",
        "category_header": "تهرِ تاکدیمان «$1»",
        "subcategories": "گونڈ\t تهرئان",
        "category-file-count-limited": "{{PLURAL:$1|جهلگین فایل|$1 جهلگین فایلان}} بی انونین تهرئ تا قرار دارنت.",
        "listingcontinuesabbrev": "(ادامه)",
        "index-category": "آ تاکدیمان که دیسته بوته گنت",
-       "noindex-category": "Ø¢ ØªØ§Ú©Ø¯Û\8cÙ\85اÙ\86 Ú©Ù\87 Ø¯Û\8cستÙ\87 Ù\86Ù\87 Ø¨Ù\88تÙ\87 Ú¯نت",
+       "noindex-category": "Ø¢ ØªØ§Ú©Ø¯Û\8cÙ\85اÙ\86 Ú©Ù\87 Ø§Û\8cÙ\86دÛ\8cکس Ù\86Ù\87 Ø¨Ù\88تÙ\87â\80\8cانت",
        "broken-file-category": "تاکدیمان گو خرابین لینکان بی فایلا",
        "about": "بی باره ها",
        "article": "محتوائین تاکدیم",
        "newwindow": "(نوکین دروازگئ تا پاچ بکنێت)",
        "cancel": "کنسیل",
        "moredotdotdot": "گیشتیر...",
-       "morenotlisted": "ای لڑ\t لیست کامل نه اینت.",
+       "morenotlisted": "ای لڑ\t لیست مومکین اینت که کامل مه‌بيت.",
        "mypage": "تاکدیم",
-       "mytalk": "گپ",
-       "anontalk": "اÛ\8c Ø¢Û\8c Ù¾Û\8c Ù\86شاÙ\86Û\8c Ø¦Û\8c Ø¨Ø§Ø±Ù\87 Ø¦Ø§ گپ",
+       "mytalk": "حبر/گپ",
+       "anontalk": "حبر/گپ",
        "navigation": "جهت یابي",
        "and": "&#32;و",
        "qbfind": "ودی کورتین",
        "unprotectthispage": "ای تاکدیمی قُلپئ ٹگل داتین",
        "newpage": "نوکین تاکدیم",
        "talkpage": "ای تاکدیم باره ئا هبر و گپ",
-       "talkpagelinktext": "گپ",
+       "talkpagelinktext": "حبر/گپ",
        "specialpage": "خاصین تاکدیم",
        "personaltools": "شخصین وسایل",
        "articlepage": "تاکدیمی محتوائانی نمایش",
        "talk": "هبر و گپ",
        "views": "دیستینین",
        "toolbox": "وسایللان",
+       "tool-link-userrights": "{{GENDER:$1|کار زوروکین}} گروپاني تغیر داتین",
+       "tool-link-emailuser": "په ای {{GENDER:$1|کار زوروکا}} ایمیلئ دیم داتین",
        "userpage": "کارزوروکین تاکدیمی دیستین",
        "projectpage": "پروژه ئی تاکدیمی دیستین",
        "imagepage": "فایلی تاکدیما نشان داتین",
        "nocookieslogin": "{{SITENAME}} په کارزوروکانی لوگین بوتینا شه کوکی ئان ایستیپاده ئه کننت.\nشما کوکی ئانه شه کار پرینته ایت.\nمهربانی بکنیت کوکی ئانه په کار بگریت و پدا کوشش بکنیت.",
        "nocookiesfornew": "کارزوروکی هیساب جۆڑ نه بوت، په خاتیریکه نتوانتن آیی منبه ئا تایید بکنن.\nموتمه ئین به یت که کوکی په ئال انت، آ وختا شه سری ن\tۆک بارگیری بکینت و پدا امتیهان بکنیت .",
        "noname": "شما یک موتبرین کار زوروکی ئین نامی ئا مشخص نه کورته ئیت.",
-       "loginsuccesstitle": "کامیابین لوگین",
+       "loginsuccesstitle": "لوگین بوتین",
        "loginsuccess": "'''شما انون گو «$1» ئی نا بی {{SITENAME}} ئی تا داخل بوته ایت.'''",
-       "nosuchuser": "کار زوروکئ گۆ «$1» ئی ناما موجود نه اینت.\nکار زورکئ نام گۆ گۆنڈی یا توُهی ئا هوروپ ئان هساس اینت.\nنامی املا ئا بگنیدیت، یا [[Special:CreateAccount|یک نوکین کار زورکی هسابئ جۆڑ بکنیت]].",
+       "nosuchuser": "کار زوروکئ گۆ «$1»‌ئی ناما موجود نه اینت.\nکار زورکئ نام گۆ گۆنڈین یا ٹوُهین حروفان حساس اینت.\nنامی املا ئا بگنیدیت، یا [[Special:CreateAccount|یک نوکین کار زورکی حسابئ جۆڑ بکنیت]].",
        "nosuchusershort": "هیچ کار زوروکئ بی نامئ  ''$1'' ئا وجود نداریت.\nوتئ املا ئا چیک بکنیت.",
        "nouserspecified": "باید یک کار زوروکئ نام مشخص بکنیت.",
        "login-userblocked": "ای کار زوروک بلاک بوته، په داخل بوتینا اجازه نه اینت.",
        "resetpass_submit": "پاسوردی تنظیم و داخل بوتین",
        "changepassword-success": "شمی پاسوردئ تغیر کامیاب بوت و پاسورد تغیر کورت",
        "changepassword-throttled": "شما بیخی باز وار په لوگین بوتینا کوشش کورته ایت.\nمهربانئ بکنیت دیم شه آیی که پدا کوشش بکنیت $1 صبر کنیت.",
+       "botpasswords-label-create": "جوڑ\t کورتین",
+       "botpasswords-label-update": "اپڈیٹ",
+       "botpasswords-label-cancel": "کنسیل",
+       "botpasswords-label-delete": "پاک کورتین",
+       "botpasswords-label-resetpassword": "پاسوردئ پاک کورتین",
        "resetpass_forbidden": "نه توانیت که پاسوردا تغیر بدهیت",
        "resetpass-no-info": "په ای تاکدیمی دسترسی ئی خاتیرا داخل بئیت.",
        "resetpass-submit-loggedin": "پاسوردی تغیر داتین",
        "passwordreset-emaildisabled": "ایمیلی گزینه بی ای یکی ئی تا پئال نه ونت.",
        "passwordreset-username": "کار زوروکین نام:",
        "passwordreset-domain": "دامنه:",
-       "passwordreset-capture": "ایمیلی آخیر نشان داته بیئت؟",
-       "passwordreset-capture-help": "اگه ای گزینه ئا بگیندیت ، ایمیل (گو موقتین پاسوردا) بی شما نشان داته ئه بیئت و په کار زوروکا هم دیم داته ئه بیئت.",
        "passwordreset-email": "ایمیل ادرس:",
        "passwordreset-emailtitle": "حسابئ مئلومات بی {{SITENAME}}",
        "passwordreset-emailelement": "کار زوروکئ نام: \n$1\n\nموقت ئین چیهرگال: \n$2",
        "revdelete-unsuppress": "محدودیتانئ پاک بوتین بئ پدا دیستین ئی تا ترمیم بوته",
        "revdelete-log": "دلیل:",
        "revdelete-submit": "اعمال بئ {{PLURAL:$1|نخسه|نخسه هان}} ئی سرا انتخاب بوته",
-       "revdelete-success": "'''نخسه ئی ودی بوتین گو کامیابیا اپڈیٹ بوت.'''",
+       "revdelete-success": "'''نخسه‌ئی ودي بوتین گو کامیابیا اپڈیٹ بوت.'''",
        "revdelete-failure": "'''نخسه ئی ودی بوتینئ اپڈیٹ بوتن امکان وجود نداریت :'''\n$1",
-       "logdelete-success": "Ù\84Ù\88Ú¯Û\8cÙ\86 Ø¦Û\8c Ù\82ابÙ\84Û\8cت Ø¯Û\8cست Ú¯Ù\88 Ú©Ø§Ù\85Û\8cابÛ\8cا انجام بوت.",
+       "logdelete-success": "Ù\85Ù\88رÛ\8cدئ Ù\88دÙ\8a Ø¨Ù\88تÛ\8cÙ\86 ØªØºÛ\8cر انجام بوت.",
        "logdelete-failure": "'''لوگین ئی قابلیت دیست تنظیم ئه نه بیئنت:'''\n$1",
        "revdel-restore": "نمایش/نهفتن",
        "pagehist": "تاکدیمی تاریخچه",
        "userrights-reason": "دلیل:",
        "userrights-no-interwiki": "شما دیگه ویکی هانی کار زوروکانئ اختیارانی تغیر داتینی اجازه ئا نداریت.",
        "userrights-nodatabase": " $1 مئلوماتئ بانک وجود نداریت یا محلی نه اینت.",
-       "userrights-nologin": "شما باید گو یک مدیرئی  [[Special:UserLogin|کار زوروکین حسابا لوگین بیئیت]] تا که بتوانیت دیگه کار زوروکانئ اختیارانا تعین بکنیت.",
-       "userrights-notallowed": "شما په کار زوروکئ حقوق ئی پاک کورتین یا افاضه کورتینی اجازه ئه نداریت.",
        "userrights-changeable-col": "ئا گروپان که شما توانیت آوانا ٹگل بدهیت",
        "userrights-unchangeable-col": "ئا گروپان که شما نتوانیت آوانا ٹگل بدهیت",
        "userrights-conflict": "حمله بئ کار زوروکئ حقان! مهربانی بکنیت بگیندیت و تغیرانا تائید بکنیت.",
-       "userrights-removed-self": "شما وتئ دسترسی ئانه سیستیت. انون شما دیگه بئ ای تاکدیما دسترسی نداریت.",
        "group": "گروپ:",
        "group-user": "کار زوروکان",
        "group-autoconfirmed": "تائید بُوته ئین کار زوروکان",
        "group-sysop-member": "{{GENDER:$1|مدیر}}",
        "group-bureaucrat-member": "{{GENDER:$1|دیوان‌سالار}}",
        "group-suppress-member": "{{GENDER:$1|نظارت}}",
-       "grouppage-user": "{{ns:project}}:کارزورک ئان",
+       "grouppage-user": "{{ns:project}}:کارزورکئان",
        "grouppage-autoconfirmed": "{{ns:project}}:تائید بُوته ئین کار زوروک ئان",
        "grouppage-bot": "{{ns:project}}:ربات‌ ئان",
        "grouppage-sysop": "{{ns:project}}:مدیر ئان",
        "right-userrights-interwiki": "دیگه ویکی ئی کار زوروکانئ اختیارانی ایڈیٹ کورتین",
        "right-siteadmin": "مئلومات ئین بانکئ قُلپ و یا پاچ کورتین",
        "right-sendemail": "دیم داتین ایمل په دیگه کار زوروکان",
-       "right-passwordreset": "پاسوردی نوک تنظیم کورتینی ایمیل",
        "right-managechangetags": "[[Special:Tags|برچسپ ئانی]] جۆڑ و پاک کورتین مه لوماتین بانکا",
        "newuserlogpage": "کار زوروکئ جوڑ کورتینی سیاه چال",
        "newuserlogpagetext": "ای سیاه چال شه نوکین کار زوروکئ ناما جوڑ بوته.",
        "all-logs-page": "عمومین موچین سیاه چال هان",
        "logempty": "شمی منطبقین آیتم بی سیاه چالئ تا ودی نه بوت.",
        "log-title-wildcard": "آ تاکدیمیانی پدا بگرد که آوانی ئنوان که گۆ ای ئبارت ئا شرو ئه بیئت",
+       "checkbox-all": "موچ",
        "allpages": "موچین تاکدیمان",
        "nextpage": "بعدین تاکدیم ($1)",
        "prevpage": "دیمی تاکدیم ($1)",
        "actionfailed": "کار نه بوت",
        "deletedtext": "«$1» پاک بوت.\nپه آخیرین پاک بوتینین سابقه ئا بئ $2 ئی تا مراجعه بکنیت.",
        "dellogpage": "پاک بوته‌ئانی کورم",
-       "dellogpagetext": "جهلگین لڑلیستا که گیندیت په آخیرئین پاک بوته‌ئین فابلاني خاتیرا اینت.\nموچین نشان داته بوته‌ئین وخت گو (گرینویچ‌ئی وختا) مطابق انت.",
+       "dellogpagetext": "جهلگین لڑلیستا که گیندیت په آخیرئین پاک بوته‌ئین فایلاني خاتیرا اینت.\nموچین نشان داته بوته‌ئین وخت گو (گرینویچ‌ئی وختا) مطابق انت.",
        "deletionlog": "پاک بوته‌ئانی کورم",
        "reverted": "بی دیمتیرین نخسه ئا بیئرگردینته بوت",
        "deletecomment": "دلیل:",
        "sp-contributions-newbies": "فقط نوکین مشارکتان نشان داته بیئنت",
        "sp-contributions-newbies-sub": "په نوک کاران",
        "sp-contributions-newbies-title": "په نوک کارین حسابانی خاتیرا کار زوروکئ شراکت ئان",
-       "sp-contributions-blocklog": "بلاک بوته ئین ئانی سیاهه",
+       "sp-contributions-blocklog": "بلاک بوته ئین‌ئانی کورم‌جاه",
        "sp-contributions-suppresslog": "کار زوروکئ کومک اوشتاته انت",
-       "sp-contributions-deleted": "کار زوروکئ پاک بوئین شراکت ئان",
-       "sp-contributions-uploads": "بُرز بوته هان",
-       "sp-contributions-logs": "سیاهه‌ها",
-       "sp-contributions-talk": "گپ",
-       "sp-contributions-userrights": "کار گیروکی اختیارانی مدیریت",
+       "sp-contributions-deleted": "{{GENDER:$1|کار زوروکئ}} پاک بوته‌ئین دستکاریان",
+       "sp-contributions-uploads": "بُرز بوته‌ئین فایلان",
+       "sp-contributions-logs": "کورم",
+       "sp-contributions-talk": "حبر/گپ",
+       "sp-contributions-userrights": "کار زوروکاني اختیاراني مدیریت کورتین",
        "sp-contributions-blocked-notice": "ای کار زوروکئ دسترسی بی انونین وختا بسته بوته.\nآخرین مورد شه دسترسی ئی سیستین به جهلگا آته:",
        "sp-contributions-blocked-notice-anon": "ای کار زوروکئ دسترسی بی انونین وختا بسته بوته.\nآخرین مورد شه دسترسی ئی سیستین به جهلگا آته:",
        "sp-contributions-search": "گشتین په شراکتان",
        "blocklist-nousertalk": "وتئ گپ ئی تاکدیما نتوان ایڈیٹ کورت",
        "ipblocklist-empty": "بسته بوته ئین ئانی لیست خالی اینت.",
        "blocklink": "بلاک یا بستین",
-       "unblocklink": "پاچ یا انبلاک بێت",
-       "change-blocklink": "بلاک ئی تغیرداتین",
+       "unblocklink": "پاچ کورتین",
+       "change-blocklink": "بلاک‌ئی تغیر داتین",
        "contribslink": "شراکت‌ئان",
        "emaillink": "ایمیلی دیم داتین",
        "blocklogpage": "بستینئ کورم",
        "javascripttest-qunit-intro": "[$1 آزمایشی مشتندانا] بئ mediawiki.org تا بگیندیت.",
        "tooltip-pt-userpage": "{{GENDER:|شمئ کار زُورۆکین}} تاکدیم",
        "tooltip-pt-mytalk": "{{GENDER:|شمئ}} حبر و گپئ تاکدیم",
+       "tooltip-pt-anontalk": "ای آی‌پی ادرس‌ئی دستکاریاني موریدا حبر/گپ",
        "tooltip-pt-preferences": "{{GENDER:|شمئ}} تنظیماتان",
        "tooltip-pt-watchlist": "آ دیمانی لیست که شما آوانی تغیرانا پدگیری ئا کنیت",
        "tooltip-pt-mycontris": "{{GENDER:|شمئ}} شراکتاني لڑ",
        "logentry-protect-modify-cascade": "$1 $3 $4 ئ قُلپئ اندازه گا په {{GENDER:$2|تغییر دات}}[آپشاری]",
        "logentry-rights-rights": "$1 ، $3 ئی عضویتا شه $4 ئی گروپا بئ $5 {{GENDER:$2|تغییر دات}}",
        "logentry-rights-rights-legacy": "$1 عضویتئ گروپا بئ $3 ئا {{GENDER:$2|تغییر دات}}",
-       "logentry-rights-autopromote": "$1 بئ اوتوماتیکین رکما وتر شه $4 بئ $5 {{GENDER:$2|ارتقاء دات}}",
+       "logentry-rights-autopromote": "$1 بِه اوتوماتیکین رقما شه $4 بِه $5‌ئا {{GENDER:$2|ارتقاء کورت}}",
        "logentry-upload-upload": "$1 $3 ئا {{GENDER:$2|بُرز کورت}}",
        "logentry-upload-overwrite": "$1 نوکین نخسه ئی شه $3 ئا {{GENDER:$2|بُرز کورت}}",
        "logentry-upload-revert": "$1 {{GENDER:$2|بُرز کورت}} $3 ئا",
        "special-characters-title-endash": "پاسیله خت",
        "special-characters-title-emdash": "تچکین پاسیله خت",
        "special-characters-title-minus": "منپی نشانگ",
-       "mw-widgets-titleinput-description-redirect": "گردینتین به $1 یی تا"
+       "mw-widgets-titleinput-description-redirect": "گردینتین به $1 یی تا",
+       "log-action-filter-delete": "پاک بوتین‌ئی رقم:",
+       "log-action-filter-all": "موچ"
 }
index 5ca09c0..244ac7a 100644 (file)
        "tog-numberheadings": "हेडिंग के ऑटो-नंबरिंग",
        "tog-showtoolbar": "संपादन औजारपट्टी के देखावल जाव",
        "tog-editondblclick": "दुइ क्लिक पर पन्ना सभ के संपादन करीं",
-       "tog-editsectiononrightclick": "à¤\96à¤\82ड à¤\95à¥\80 à¤¹à¥\87डिà¤\82à¤\97 à¤ªà¤° à¤¦à¤¾à¤¯à¤¾à¤\81 à¤\95à¥\8dलिà¤\95 à¤\95à¤\87 à¤\95à¥\87 à¤\96à¤\82ड à¤\95à¥\87 à¤¸à¤®à¥\8dपादित करीं",
-       "tog-watchcreations": "हमार बनावल पन्ना आ हमार अपलोड कइल फाइल सभ के हमरी धियानसूची में जोड़ दिहल जाव",
-       "tog-watchdefault": "हम जौना पन्ना आ फाइलन के संपादित करीं उनहन के हमरी धियानसूची में जोड़ दिहल जाव",
-       "tog-watchmoves": "हमरा द्वारा स्थानांतरित पन्ना आ फाइलन के हमरा धियानसूची में जोड़ दिहल जाव",
-       "tog-watchdeletion": "हमरा द्वारा हटावल पन्ना आ फाइल सभ के हमार धियानसूची में जोड़ दिहल जाव",
+       "tog-editsectiononrightclick": "हà¥\87डिà¤\82à¤\97 à¤ªà¤° à¤¦à¤¾à¤¯à¤¾à¤\81 à¤\95à¥\8dलिà¤\95 à¤\95à¤\87 à¤\95à¥\87 à¤\96à¤\82ड à¤\95à¥\87 à¤¸à¤\82पादन à¤¸à¤\82भव करीं",
+       "tog-watchcreations": "हमार बनावल पन्ना आ हमार अपलोड कइल फाइल सभ के हमरी धियानसूची में जोड़ल जाव",
+       "tog-watchdefault": "हम जौना पन्ना आ फाइलन के संपादित करीं उनहन के हमरी धियानसूची में जोड़ल जाव",
+       "tog-watchmoves": "हमरा द्वारा स्थानांतरित पन्ना आ फाइलन के हमरा धियानसूची में जोड़ल जाव",
+       "tog-watchdeletion": "हमरा द्वारा हटावल पन्ना आ फाइल सभ के हमार धियानसूची में जोड़ल जाव",
        "tog-watchuploads": "हम नया फाइल अपलोड करीं त उनहना के हमार धियानसूची में जोड़ल जाय",
-       "tog-watchrollback": "हमरा द्वारा रोलबैक कइल गइल पन्ना सभ के हमार धियानसूची में जोड़ दिहल जाव",
-       "tog-minordefault": "डिफालà¥\8dà¤\9f à¤°à¥\82प à¤¸à¥\87 à¤¸à¤\97रà¥\80 à¤¸à¤\82पादन à¤\95à¥\81ल à¤\95à¥\87 à¤\9bà¥\8bà¤\9f à¤¸à¤\82पादन à¤\95à¥\80 à¤°à¥\81प à¤®à¥\87à¤\82 à¤\9aिनà¥\8dहित à¤\95à¤\87ल à¤\9cाव",
+       "tog-watchrollback": "हमरा द्वारा रोलबैक कइल गइल पन्ना सभ के हमार धियानसूची में जोड़ल जाव",
+       "tog-minordefault": "डिफाल्ट रूप से सगरी संपादन के छोट संपादन की रुप में चिन्हित कइल जाव",
        "tog-previewontop": "झलक (प्रीव्यू) संपादन बक्सा से पहिले देखावल जाय",
        "tog-previewonfirst": "पहिला संपादन पर झलक (प्रीव्यू) देखावल जाय",
-       "tog-enotifwatchlistpages": "हमार धियानसूची में दर्ज कौनो भी पन्ना या फाइल में बदलाव होखला पर हमके ई-मेल कइल जाव",
-       "tog-enotifusertalkpages": "अगर हमरे बातचीत पन्ना पर कौनो बदलाव होखे त हमके ई-मेल कइल जाव",
-       "tog-enotifminoredits": "पन्ना आ फाइल पर छोटो बदलाव होखे त हमके ई-मेल कइल जाव",
-       "tog-enotifrevealaddr": "नोटिफिकेशन ई-मेल में हमार ई-मेल पता देखावल जाव",
-       "tog-shownumberswatching": "धियान रखे वालन सदस्यन के देखावल जाव",
+       "tog-enotifwatchlistpages": "हमार धियानसूची में दर्ज कौनो भी पन्ना या फाइल में बदलाव होखला पर हमके ईमेल कइल जाव",
+       "tog-enotifusertalkpages": "अगर हमरे बातचीत पन्ना पर कौनो बदलाव होखे त हमके ईमेल कइल जाव",
+       "tog-enotifminoredits": "पन्ना आ फाइल पर छोटो बदलाव होखे त हमके ईमेल कइल जाव",
+       "tog-enotifrevealaddr": "नोटिफिकेशन ईमेल में हमार ईमेल पता देखावल जाव",
+       "tog-shownumberswatching": "धियान à¤°à¤\96à¥\87 à¤µà¤¾à¤²à¤¨ à¤¸à¤¦à¤¸à¥\8dयन à¤\95à¥\87 à¤¸à¤\82à¤\96à¥\8dया à¤¦à¥\87à¤\96ावल à¤\9cाव",
        "tog-oldsig": "राउर वर्तमान दसखत:",
        "tog-fancysig": "दसखत के विकी पाठ के रुप में उपयोग करीं (बिना ऑटोमेटिक कड़ी के)",
        "tog-uselivepreview": "लगातार झलक (लाइव प्रीव्यू) इस्तेमाल कइल जाव",
-       "tog-forceeditsummary": "यदि à¤¸à¤\82पादन à¤¸à¤¾à¤°à¤¾à¤\82श à¤¨à¤¾ à¤¦à¤¿à¤¹ल होखे त हमके सूचित कइल जाय",
-       "tog-watchlisthideown": "हमरà¥\80 à¤§à¤¿à¤¯à¤¾à¤¨à¤¸à¥\82à¤\9aà¥\80 à¤¸à¥\87 à¤¹à¤®à¤¾à¤° à¤\96à¥\81द à¤\95à¥\87 à¤¸à¤\82पादन à¤\9bिपाà¤\88à¤\82",
+       "tog-forceeditsummary": "सà¤\82पादन à¤¸à¤\82à¤\9bà¥\87प à¤¨à¤¾ à¤­à¤°à¤² à¤\97à¤\87ल होखे त हमके सूचित कइल जाय",
+       "tog-watchlisthideown": "धियानसà¥\82à¤\9aà¥\80 à¤¸à¥\87 à¤¹à¤®à¤¾à¤° à¤\96à¥\81द à¤\95à¥\87 à¤¸à¤\82पादन à¤\9bिपावल à¤\9cाय",
        "tog-watchlisthidebots": "धियानसूची से बॉट संपादन छिपावल जाय",
        "tog-watchlisthideminor": "धियानसूची से छोट संपादन छिपावल जाय",
-       "tog-watchlisthideliu": "धियानसà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤²à¥\89à¤\97-à¤\87न à¤­à¤\87ल à¤¸à¤¦à¤¸à¥\8dयन à¤\95à¥\87 à¤¸à¤\82पादन छिपावल जाय",
+       "tog-watchlisthideliu": "à¤\96ाता à¤®à¥\87à¤\82 à¤ªà¥\8dरवà¥\87श à¤­à¤\87ल à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤\95à¥\87 à¤¸à¤\82पादन à¤§à¤¿à¤¯à¤¾à¤¨à¤¸à¥\82à¤\9aà¥\80 à¤¸à¥\87 छिपावल जाय",
        "tog-watchlistreloadautomatically": "जब कौनों फिल्टर बदलल जाय तब धियानसूची ऑटोमेटिक दोबारा लोड होखे (जावास्क्रिप्ट जरूरी)",
-       "tog-watchlisthideanons": "à¤\86à¤\87॰पà¥\80॰ à¤¸à¤¦à¤¸à¥\8dयन à¤¦à¥\8dवारा à¤\95रल à¤\97à¤\87ल à¤¸à¤®à¥\8dपादन à¤\95à¥\87 à¤¹à¤®à¤¾à¤° à¤§à¤¿à¤¯à¤¾à¤¨à¤¸à¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 से छिपावल जाय",
-       "tog-watchlisthidepatrolled": "à¤\9cाà¤\81à¤\9aल à¤\97à¤\87ल à¤¸à¤®à¥\8dपादन à¤\95à¥\87 à¤¹à¤®à¤¾à¤° à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 से छिपावल जाय",
+       "tog-watchlisthideanons": "बà¥\87नाम à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤\95à¥\87 à¤¸à¤\82पादन à¤§à¤¿à¤¯à¤¾à¤¨à¤¸à¥\82à¤\9aà¥\80 से छिपावल जाय",
+       "tog-watchlisthidepatrolled": "à¤\9cाà¤\81à¤\9aल à¤\97à¤\87ल à¤¸à¤\82पादन à¤\95à¥\87 à¤§à¤¿à¤¯à¤¾à¤¨à¤¸à¥\82à¤\9aà¥\80 से छिपावल जाय",
        "tog-watchlisthidecategorization": "पन्ना श्रेणीकरण छिपावल जाय",
-       "tog-ccmeonemails": "हमरा à¤¦à¥\8dवारा à¤\85नà¥\8dय à¤¸à¤¦à¤¸à¥\8dयन à¤\95à¥\87 à¤­à¥\87à¤\9cल à¤\97à¤\87ल à¤\88मà¥\87ल à¤\95à¥\87 à¤\95à¥\89पà¥\80 à¤¹à¤®à¤°à¥\8b के भेजल जाय",
+       "tog-ccmeonemails": "हमरा à¤¦à¥\8dवारा à¤\85नà¥\8dय à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤\95à¥\87 à¤­à¥\87à¤\9cल à¤\97à¤\87ल à¤\88मà¥\87ल à¤\95à¥\87 à¤\95à¥\89पà¥\80 à¤¹à¤®के भेजल जाय",
        "tog-diffonly": "अंतर देखावत समय नीचे पन्ना के सामग्री न देखावल जाय",
        "tog-showhiddencats": "छिपल श्रेणियन के भी देखावल जाय",
        "tog-norollbackdiff": "रोलबैक कइला के बाद अंतर न देखावल जाय",
        "tog-useeditwarning": "जो हम कौनों पन्ना पर संपादन करत घरी परिवर्तन के बिना सहेजले छोड़ देईं त हमके खबर कइल जाय",
-       "tog-prefershttps": "लà¥\89à¤\97िन रहले पर हमेशा सुरक्षित कनेक्शन के प्रयोग कइल जाय",
+       "tog-prefershttps": "à¤\96ाता à¤®à¥\87à¤\82 à¤ªà¥\8dरवà¥\87श रहले पर हमेशा सुरक्षित कनेक्शन के प्रयोग कइल जाय",
        "underline-always": "हमेशा",
        "underline-never": "कभी ना",
        "underline-default": "जिल्द (स्किन) या ब्राउजर डिफॉल्ट",
        "december-date": "दिसंबर $1",
        "period-am": "AM",
        "period-pm": "PM",
-       "pagecategories": "{{PLURAL:$1|श्रेणी|श्रेणी}}",
-       "category_header": "\"$1\" श्रेणी में पन्ना",
+       "pagecategories": "{{PLURAL:$1|श्रेणी|श्रेणीसभ}}",
+       "category_header": "\"$1\" à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤®à¥\8cà¤\9cà¥\82द à¤ªà¤¨à¥\8dना",
        "subcategories": "उपश्रेणी",
-       "category-media-header": "\"$1\" श्रेणी में मीडिया",
-       "category-empty": "''इ श्रेणी में इ समय कउनो पन्ना या मीडिया नइखे।''",
+       "category-media-header": "\"$1\" à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤®à¥\8cà¤\9cà¥\82द à¤®à¥\80डिया",
+       "category-empty": "<em>ए श्रेणी में एह समय कौनों पन्ना भा मीडिया नइखे।</em>",
        "hidden-categories": "{{PLURAL:$1|छिपावल गइल श्रेणी|छिपावल गइल श्रेणी सब}}",
        "hidden-category-category": "छिपावल गइल श्रेणी",
-       "category-subcat-count": "{{PLURAL:$2|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤\96ालà¥\80 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित à¤¶à¥\8dरà¥\87णà¥\80 à¤¬à¤¾|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤\95à¥\81ल $2 à¤®à¥\87à¤\82 à¤¸à¥\87 {{PLURAL:$1|à¤\89पशà¥\8dरà¥\87णà¥\80|$1 à¤\89पशà¥\8dरà¥\87णà¥\80 à¤¸à¤¬}} बा।}}",
-       "category-subcat-count-limited": "à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित {{PLURAL:$1|à¤\89पशà¥\8dरà¥\87णà¥\80 à¤¬à¤¾|$1 à¤\89पशà¥\8dरà¥\87णà¥\80 बाड़ीं।}}",
-       "category-article-count": "{{PLURAL:$2|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤®à¤¾à¤¤à¥\8dर à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित à¤ªà¤¨à¥\8dन à¤¬à¤¾à¥¤|à¤\87 à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित {{PLURAL:$1|पनà¥\8dना à¤¬à¤¾|$1 à¤ªà¤¨à¥\8dना à¤¬à¤¾à¤¡à¤¼à¥\87}}, à¤\95à¥\81ल à¤ªà¤¨à¥\8dना $2}}",
-       "category-article-count-limited": "निमà¥\8dनलिà¤\96ित {{PLURAL:$1|पनà¥\8dना|$1 à¤ªà¤¨à¥\8dना}} à¤\87 à¤¶à¥\8dरà¥\87णà¥\80à¤\82 à¤®à¥\87à¤\82 à¤¬à¤¾।",
-       "category-file-count": "{{PLURAL:$2|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤\96ालà¥\80 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित à¤«à¤\87ल à¤¬à¤¾à¥¤|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित à¤\95à¥\81ल à¤«à¤¼à¤¾à¤\87लà¤\82 $2 {{PLURAL:$1|फाà¤\87ल|$1फाà¤\87लà¤\82}} à¤¬à¤¾à¤¡à¤¼à¥\87}}",
-       "category-file-count-limited": "वरà¥\8dतमान à¤®à¥\87à¤\82 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित {{PLURAL:$1|पनà¥\8dना|$1 à¤ªà¤¨à¥\8dनाà¤\82}} à¤\87 à¤¶à¥\8dरà¥\87णà¥\80à¤\82 à¤®à¥\87à¤\82 à¤¬à¤¾à¤¡à¤¼à¥\87।",
+       "category-subcat-count": "{{PLURAL:$2|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² à¤\96ालà¥\80 à¤\8fà¤\95 à¤ à¥\8b à¤¶à¥\8dरà¥\87णà¥\80 à¤¬à¤¾|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤®à¥\8cà¤\9cà¥\82द à¤\95à¥\81ल $2 à¤®à¥\87à¤\82 à¤¸à¥\87 {{PLURAL:$1|à¤\89पशà¥\8dरà¥\87णà¥\80|$1 à¤\89पशà¥\8dरà¥\87णà¥\80 à¤¸à¤¬}} à¤¨à¥\80à¤\9aà¥\87 à¤¦à¥\87à¤\96ावल à¤\9cात बा।}}",
+       "category-subcat-count-limited": "à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¥\80à¤\9aà¥\87 à¤¦à¥\87à¤\96ावल {{PLURAL:$1|à¤\89पशà¥\8dरà¥\87णà¥\80 à¤¬à¤¾|$1 à¤\89पशà¥\8dरà¥\87णà¥\80 à¤\95à¥\81ल बाड़ीं।}}",
+       "category-article-count": "{{PLURAL:$2|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² à¤\8fà¤\95हà¥\80 à¤ à¥\8b à¤ªà¤¨à¥\8dना à¤­à¤° à¤¬à¤¾à¤\9fà¥\87।|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤®à¥\8cà¤\9cà¥\82द à¤\95à¥\81ल $2 à¤®à¥\87à¤\82 à¤¸à¥\87 {{PLURAL:$1|पनà¥\8dना à¤¨à¥\80à¤\9aà¥\87 à¤¦à¥\87à¤\96ावल à¤\9cात à¤¬à¤¾|$1 à¤ªà¤¨à¥\8dनासभ à¤¨à¥\80à¤\9aà¥\87 à¤¦à¥\87à¤\96ावल à¤\9cात à¤¬à¤¾à¤¡à¤¼à¥\87à¤\82}}।}}",
+       "category-article-count-limited": "वरà¥\8dतमान à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² {{PLURAL:$1|पनà¥\8dना à¤¬à¤¾|$1 à¤ªà¤¨à¥\8dना à¤¬à¤¾à¤¡à¤¼à¥\87à¤\82}}।",
+       "category-file-count": "{{PLURAL:$2|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² à¤\8fà¤\95हà¥\80 à¤ à¥\8b à¤«à¤¾à¤\87ल à¤­à¤° à¤¬à¤¾à¤\9fà¥\87।|à¤\8f à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤®à¥\8cà¤\9cà¥\82द à¤\95à¥\81ल $2 à¤®à¥\87à¤\82 à¤¸à¥\87 {{PLURAL:$1|फाà¤\87ल à¤¨à¥\80à¤\9aà¥\87 à¤¦à¥\87à¤\96ावल à¤\9cात à¤¬à¤¾|$1 à¤«à¤¾à¤\87लसभ à¤¨à¥\80à¤\9aà¥\87 à¤¦à¥\87à¤\96ावल à¤\9cात à¤¬à¤¾à¤¡à¤¼à¥\80à¤\82}}।}}",
+       "category-file-count-limited": "वरà¥\8dतमान à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² {{PLURAL:$1|फाà¤\87ल à¤¬à¤¾|$1 à¤«à¤¾à¤\87ल à¤¬à¤¾à¤¡à¤¼à¥\80à¤\82}}।",
        "listingcontinuesabbrev": "जारी...",
        "index-category": "सूचीबद्ध पन्ना",
        "noindex-category": "बिनासूचीबद्ध पन्ना",
        "moredotdotdot": "अउर...",
        "morenotlisted": "हो सकेला कि ई लिस्ट पूरा न होखे।",
        "mypage": "पन्ना",
-       "mytalk": "हमार à¤¬à¤¾à¤¤à¤\9aà¥\80त à¤ªà¤¨à¥\8dना",
+       "mytalk": "बातà¤\9aà¥\80त",
        "anontalk": "बातचीत",
        "navigation": "नेविगेशन",
        "and": "&#32;अउर",
        "qbedit": "संपादन",
        "qbpageoptions": "ई पन्ना",
        "qbmyoptions": "हमार पन्ना",
-       "faq": "साधारण सवाल",
+       "faq": "à¤\86म सवाल",
        "faqpage": "Project:अक्सर पूछल जाए वाला सवाल",
-       "actions": "à¤\95ारà¥\8dयवाहà¥\80",
+       "actions": "à¤\8fà¤\95à¥\8dशन",
        "namespaces": "नाँवस्थान",
        "variants": "अउरी प्रकार",
-       "navigation-heading": "नà¥\87विà¤\97à¥\87शन à¤®à¥\87नà¥\81",
+       "navigation-heading": "नà¥\87विà¤\97à¥\87शन à¤®à¥\87नà¥\82",
        "errorpagetitle": "खराबी",
-       "returnto": "$1 à¤ªà¤° à¤²à¥\8cà¤\9f à¤\9cाà¤\88ं।",
+       "returnto": "$1 à¤ªà¤° à¤²à¤µà¤\9fà¥\80ं।",
        "tagline": "भोजपुरी {{SITENAME}} से",
        "help": "मदद",
        "search": "खोज",
        "searcharticle": "जाईं",
        "history": "पन्ना के इतिहास",
        "history_short": "इतिहास",
-       "updatedmarker": "हमार à¤\85नà¥\8dतिम à¤\86à¤\97मन à¤¸े बदलाव",
+       "updatedmarker": "हमरà¥\87 à¤\85à¤\82तिम à¤¬à¥\87र à¤¦à¥\87à¤\96लà¥\87 à¤\95à¥\87 à¤¬à¤¾à¤¦ à¤\95े बदलाव",
        "printableversion": "छापे लायक संस्करण",
        "permalink": "स्थायी कड़ी",
        "print": "छापीं",
-       "view": "दà¥\87à¤\96à¥\80à¤\82",
+       "view": "वà¥\8dयà¥\82",
        "view-foreign": "$1 पर देखीं",
        "edit": "संपादन",
        "edit-local": "लोकल विवरण देखीं",
        "create": "बनाईं",
        "create-local": "लोकल विवरण जोड़ीं",
-       "editthispage": "à¤\8f à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¸à¤®à¥\8dपादन करीं",
-       "create-this-page": "à¤\8f à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¨à¤¿à¤°à¥\8dमाण à¤\95रà¥\80ं",
+       "editthispage": "à¤\8f à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¸à¤\82पादन करीं",
+       "create-this-page": "à¤\88 à¤ªà¤¨à¥\8dना à¤¬à¤¨à¤¾à¤\88ं",
        "delete": "मिटाईं",
        "deletethispage": "ई पन्ना के मिटाईं",
        "undeletethispage": "ई पन्ना के फिर से स्थापित करीं",
-       "undelete_short": "{{PLURAL:$1|à¤\8fà¤\97à¥\8b à¤¹à¤\9fावल à¤\97à¤\88ल|$1 à¤¹à¤\9fावल à¤\97à¤\88लà¤\82}} à¤¬à¤¦à¤²à¤¾à¤µ à¤µà¤¾à¤ªà¤¸ à¤²à¤¾à¤\88ं",
-       "viewdeleted_short": "देखें {{PLURAL:$1|एगो हटावल गईल सम्पादन|$1 हटावल गईल कुल सम्पादन}}",
-       "protect": "सà¤\82रà¤\95à¥\8dषण करीं",
+       "undelete_short": "{{PLURAL:$1|à¤\8fà¤\95 à¤ à¥\8b à¤¹à¤\9fावल à¤\97à¤\87ल à¤¸à¤\82पादन|$1 à¤ à¥\87 à¤¹à¤\9fावल à¤\97à¤\87ल à¤¸à¤\82पादन à¤\95à¥\81ल}} à¤¬à¤¿à¤¨à¤¾à¤®à¥\87à¤\9fावल à¤\95रà¥\80ं",
+       "viewdeleted_short": "{{PLURAL:$1|एक ठो हटावल गइल संपादन|$1 हटावल गइल संपादन कुल}} देखीं",
+       "protect": "सà¥\81रà¤\95à¥\8dषित करीं",
        "protect_change": "बदलीं",
-       "protectthispage": "à¤\87 पन्ना के सुरक्षित करीं।",
+       "protectthispage": "à¤\8f पन्ना के सुरक्षित करीं।",
        "unprotect": "सुरक्षा बदलीं",
-       "unprotectthispage": "à¤\87 पन्ना के सुरक्षा बदलीं",
+       "unprotectthispage": "à¤\8f पन्ना के सुरक्षा बदलीं",
        "newpage": "नया पन्ना",
-       "talkpage": "à¤\87 पन्ना पर चर्चा करीं",
-       "talkpagelinktext": "बात-चीत",
+       "talkpage": "à¤\8f पन्ना पर चर्चा करीं",
+       "talkpagelinktext": "बातचीत",
        "specialpage": "खास पन्ना",
-       "personaltools": "वà¥\8dयà¤\95à¥\8dतिà¤\97त औजार",
+       "personaltools": "निà¤\9cà¥\80 औजार",
        "articlepage": "सामग्री पन्ना देखीं",
-       "talk": "बात-चीत",
-       "views": "à¤\95à¤\87सन à¤²à¤\89à¤\95à¥\80?",
+       "talk": "बातचीत",
+       "views": "वà¥\8dयà¥\82",
        "toolbox": "औजार",
-       "tool-link-userrights": "{{GENDER:$1|पà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता}} à¤\95à¥\87 à¤¸à¤¦à¤¸à¥\8dयसमà¥\82ह बदलीं",
+       "tool-link-userrights": "{{GENDER:$1|पà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता}} à¤\95à¥\87 à¤®à¤\82डलà¥\80 बदलीं",
        "tool-link-emailuser": "{{GENDER:$1|प्रयोगकर्ता}} के ईमेल करीं",
        "userpage": "प्रयोगकर्ता पन्ना देखीं",
        "projectpage": "परियोजना पन्ना देखीं",
        "imagepage": "फाइल पन्ना देखीं",
-       "mediawikipage": "सनà¥\8dदà¥\87श पन्ना देखीं",
+       "mediawikipage": "सनà¥\87सा पन्ना देखीं",
        "templatepage": "टेम्पलेट पन्ना देखीं",
        "viewhelppage": "मदद पन्ना देखीं",
        "categorypage": "श्रेणी पन्ना देखीं",
-       "viewtalkpage": "बात-à¤\9aà¥\80त देखीं",
+       "viewtalkpage": "à¤\9aरà¥\8dà¤\9aा देखीं",
        "otherlanguages": "दुसरी भाषा में",
        "redirectedfrom": "($1 से अनुप्रेषित)",
        "redirectpagesub": "अनुप्रेषण पन्ना",
        "redirectto": "अनुप्रेषित:",
-       "lastmodifiedat": "$1 à¤\95à¥\87 $2 à¤ªà¤° à¤\8f à¤ªà¤¨à¥\8dना à¤ªà¤° à¤\85नà¥\8dतिम बेर बदलाव भइल।",
-       "viewcount": "à¤\88 à¤ªà¤¨à¥\8dना {{PLURAL:$1|à¤\8fà¤\95|$1}} à¤¬à¤¾à¤° à¤¦à¥\87à¤\96ल à¤\97à¤\88ल बा।",
+       "lastmodifiedat": "$1 à¤\95à¥\87 $2 à¤¬à¤\9cà¥\87 à¤\8f à¤ªà¤¨à¥\8dना à¤ªà¤° à¤\85à¤\82तिम बेर बदलाव भइल।",
+       "viewcount": "à¤\88 à¤ªà¤¨à¥\8dना {{PLURAL:$1|à¤\8fà¤\95|$1}} à¤¬à¥\87र à¤¦à¥\87à¤\96ल à¤\97à¤\87ल बा।",
        "protectedpage": "सुरक्षित पन्ना",
        "jumpto": "इहाँ जाईं:",
        "jumptonavigation": "नेविगेशन",
        "jumptosearch": "खोजीं",
-       "view-pool-error": "à¤\95à¥\8dषमा à¤\95रà¥\80à¤\82, à¤\88 à¤¸à¤®à¤¯ à¤¸à¤°à¥\8dवर à¤ªà¤° à¤¬à¤¹à¥\81त à¤\9cà¥\8dयादा à¤²à¥\8bड à¤¬à¤¢à¤¼ à¤\97à¤\88ल à¤¬à¤¾à¥¤\nà¤\88 à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¬à¤¹à¥\81तà¥\87 à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤¦à¥\87à¤\96à¥\87 à¤\95à¥\87 à¤\95à¥\8bशिश à¤\95र à¤°à¤¹à¤² à¤¬à¤¾à¤¨à¥\80।\nà¤\88 à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤«à¤¿à¤° à¤¸à¥\87 à¤¦à¥\87à¤\96à¥\87 à¤¸à¥\87 à¤ªà¤¹à¤¿à¤²à¥\87 à¤\95à¥\83पया à¤\95à¥\81à¤\9b à¤¦à¥\87र à¤¤à¤\95 à¤\87नà¥\8dतजार करीं।\n\n$1",
-       "generic-pool-error": "à¤\95à¥\8dषमा à¤\95रà¥\80à¤\82, à¤\88 à¤¸à¤®à¤¯ à¤¸à¤°à¥\8dवर à¤ªà¤° à¤¬à¤¹à¥\81त à¤\9cà¥\8dयादा à¤²à¥\8bड à¤¬à¤¢à¤¼ à¤\97à¤\88ल à¤¬à¤¾à¥¤\nà¤\88 à¤¸à¤\82साधन à¤\95à¥\87 à¤¬à¤¹à¥\81तà¥\87 à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤¦à¥\87à¤\96à¥\87 à¤\95à¥\87 à¤\95à¥\8bशिश à¤\95र à¤°à¤¹à¤² à¤¬à¤¾à¤¨à¥\80।\nà¤\88 à¤¸à¤\82साधन à¤¤à¤\95 à¤ªà¤¹à¥\81à¤\81à¤\9a à¤¬à¤¨à¤¾à¤µà¥\87 à¤\95à¥\87 à¤\95à¥\8bशिश à¤¸à¥\87 à¤ªà¤¹à¤¿à¤²à¥\87 à¤\95à¥\83पया à¤\95à¥\81à¤\9b à¤¦à¥\87र à¤¤à¤\95 à¤\87नà¥\8dतजार करीं।",
-       "pool-timeout": "तालाबनà¥\8dदà¥\80 à¤\96ातिर à¤ªà¥\8dरतà¥\80à¤\95à¥\8dषा समय समाप्त",
+       "view-pool-error": "माफ à¤\95रà¥\80à¤\82, à¤\8f à¤¸à¤®à¤¯ à¤¸à¤°à¥\8dवर à¤ªà¤° à¤¬à¤¹à¥\81त à¤\9cà¥\8dयादा à¤²à¥\8bड à¤¬à¤¢à¤¼ à¤\97à¤\87ल à¤¬à¤¾à¥¤\nà¤\8f à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¬à¤¹à¥\81तà¥\87 à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤¦à¥\87à¤\96à¥\87 à¤\95à¥\87 à¤\95à¥\8bशिश à¤\95र à¤°à¤¹à¤² à¤¬à¤¾à¥¤\nà¤\8f à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤«à¤¿à¤° à¤¸à¥\87 à¤¦à¥\87à¤\96à¥\87 à¤¸à¥\87 à¤ªà¤¹à¤¿à¤²à¥\87 à¤\95à¥\83पया à¤\95à¥\81à¤\9b à¤¦à¥\87र à¤¤à¤\95 à¤\87à¤\82तजार करीं।\n\n$1",
+       "generic-pool-error": "माफ à¤\95रà¥\80à¤\82, à¤\8f à¤¸à¤®à¤¯ à¤¸à¤°à¥\8dवर à¤ªà¤° à¤¬à¤¹à¥\81त à¤\9cà¥\8dयादा à¤²à¥\8bड à¤¬à¤¢à¤¼ à¤\97à¤\87ल à¤¬à¤¾à¥¤\nà¤\8f à¤¸à¤\82साधन à¤\95à¥\87 à¤¬à¤¹à¥\81तà¥\87 à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤¦à¥\87à¤\96à¥\87 à¤\95à¥\87 à¤\95à¥\8bशिश à¤\95र à¤°à¤¹à¤² à¤¬à¤¾à¥¤\nà¤\8f à¤¸à¤\82साधन à¤¤à¤\95 à¤ªà¤¹à¥\81à¤\81à¤\9a à¤¬à¤¨à¤¾à¤µà¥\87 à¤\95à¥\87 à¤\95à¥\8bशिश à¤¸à¥\87 à¤ªà¤¹à¤¿à¤²à¥\87 à¤\95à¥\83पया à¤\95à¥\81à¤\9b à¤¦à¥\87र à¤¤à¤\95 à¤\87à¤\82तजार करीं।",
+       "pool-timeout": "तालाबनà¥\8dदà¥\80 à¤\96ातिर à¤\87à¤\82तà¤\9cार समय समाप्त",
        "pool-queuefull": "पूल पंक्ति भर गइल",
-       "pool-errorunknown": "à¤\85à¤\9cà¥\8dà¤\9eात à¤¤à¥\8dरà¥\81à¤\9fि",
-       "pool-servererror": "पà¥\82ल à¤\95ाà¤\89à¤\82à¤\9fर à¤¸à¥\87वा à¤\89पलबà¥\8dध à¤¨à¤¾à¤¹à¥\80 à¤¬à¤¾ ($1)।",
-       "poolcounter-usage-error": "à¤\89पयà¥\8bà¤\97 à¤¤à¥\8dरà¥\81à¤\9fि: $1",
+       "pool-errorunknown": "नामालà¥\82म à¤\96राबà¥\80",
+       "pool-servererror": "पà¥\82ल à¤\95ाà¤\89à¤\82à¤\9fर à¤¸à¤°à¥\8dविस à¤\89पलबà¥\8dध à¤¨à¤\87à¤\96à¥\87 ($1)।",
+       "poolcounter-usage-error": "à¤\87सà¥\8dतमाल à¤\96राबà¥\80: $1",
        "aboutsite": "{{SITENAME}} के बारे में",
        "aboutpage": "Project:बारे में",
-       "copyright": "à¤\89पलबà¥\8dध à¤¸à¤¾à¤®à¤\97à¥\8dरà¥\80 $1 à¤\95à¥\87 à¤\85धà¥\80न à¤\89पलबà¥\8dध à¤¬à¤¾ à¤\9cब à¤¤à¤\95 à¤\95à¥\80 à¤\85लà¤\97 à¤¸à¥\87 à¤\89लà¥\8dलà¥\87à¤\96 à¤¨à¤¾ à¤\95रल à¤\97à¤\88ल à¤¹à¥\8bà¤\96à¥\87 ।",
+       "copyright": "à¤\89पलबà¥\8dध à¤¸à¤¾à¤®à¤\97à¥\8dरà¥\80 $1 à¤\95à¥\87 à¤\85धà¥\80न à¤\89पलबà¥\8dध à¤¬à¤¾ à¤\9cब à¤¤à¤\95 à¤\95à¥\80 à¤\85लà¤\97 à¤¸à¥\87 à¤\89लà¥\8dलà¥\87à¤\96 à¤¨à¤¾ à¤\95à¤\87ल à¤\97à¤\87ल à¤¹à¥\8bà¤\96à¥\87।",
        "copyrightpage": "{{ns:project}}:कापीराइट सब",
        "currentevents": "हाल के घटना सब",
        "currentevents-url": "Project:हाल के घटना सब",
        "portal-url": "Project:सदस्य-समाज मुख्यपन्ना",
        "privacy": "गोपनीयता नीति",
        "privacypage": "Project:गोपनीयता नीति",
-       "badaccess": "à¤\85नà¥\81मति à¤¤à¥\8dरà¥\81à¤\9fी",
-       "badaccess-group0": "रà¤\89à¤\86 à¤\9cवन à¤\95ारà¥\8dरवाà¤\88 à¤\96ातिर à¤\85नà¥\81रà¥\8bध à¤\95à¤\88लà¥\87 à¤¬à¤¾à¤¨à¥\80 à¤\89 à¤\95à¥\87 à¤¨à¤¿à¤·à¥\8dपादन à¤\95रà¥\87 à¤\95à¥\87 à¤\85नà¥\81मति à¤¨à¤\88खे।",
-       "badaccess-groups": "रà¤\89à¤\86 à¤\9cà¥\8cन à¤\95à¥\8dरिया à¤\95à¥\87 à¤¨à¤¿à¤µà¥\87दन à¤\95à¤\87लà¥\87 à¤¬à¤¾à¤¨à¥\80 à¤\89 à¤®à¤¾à¤¤à¥\8dर {{PLURAL:$2|$1 à¤¸à¤®à¥\82ह|$1 à¤¸à¤®à¥\82हà¤\82}} à¤\95à¥\87 à¤¸à¤¦à¤¸à¥\8dय à¤¹à¥\80 à¤\95र à¤¸à¤\95त à¤¬à¤¾à¤¡à¤¼à¥\87।",
+       "badaccess": "परमà¥\80शन à¤\96राबी",
+       "badaccess-group0": "à¤\9cवन à¤\95ारà¥\8dरवाà¤\88 à¤\95à¥\87 à¤®à¤¾à¤\81à¤\97 à¤\95à¤\87लà¥\87 à¤¬à¤¾à¤¨à¥\80, à¤\93à¤\95रा à¤²à¤¾à¤\97à¥\82 à¤\95रà¥\87 à¤\95à¥\87 à¤\87à¤\9cाà¤\9cत à¤°à¤\89à¤\86à¤\81 à¤\95à¥\87 à¤¨à¤\87खे।",
+       "badaccess-groups": "रà¤\89à¤\86 à¤\9cà¥\8cन à¤\95ारवाà¤\88 à¤\95à¥\87 à¤®à¤¾à¤\81à¤\97 à¤\95à¤\87लà¥\87 à¤¬à¤¾à¤¨à¥\80 à¤\8a {{PLURAL:$2|$1 à¤®à¤\82डलà¥\80|$1 à¤®à¤\82डलà¥\80 à¤¸à¤­}} à¤\95à¥\87 à¤¸à¤¦à¤¸à¥\8dय à¤²à¥\8bà¤\97 à¤­à¤° à¤\95र à¤¸à¤\95त à¤¬à¤¾।",
        "versionrequired": "मिडीयाविकी के संस्करण $1 के होखल जरुरी बा",
-       "versionrequiredtext": "à¤\87 à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रà¥\87 à¤\96ातिर à¤®à¥\80डियाविà¤\95à¥\80 à¤\95à¥\87 $1 à¤¸à¤\82सà¥\8dà¤\95रण à¤\9c़रà¥\82रà¥\80 à¤¬à¤¾à¥¤\nदà¥\87à¤\96à¥\80à¤\82 [[Special:Version|सà¤\82सà¥\8dà¤\95रण à¤ªà¤¨à¥\8dना]]।",
-       "ok": "ठिक",
+       "versionrequiredtext": "à¤\8f à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रà¥\87 à¤\96ातिर à¤®à¥\80डियाविà¤\95à¥\80 à¤\95à¥\87 à¤µà¤°à¥\8dशन $1 à¤\9cरà¥\82रà¥\80 à¤¬à¤¾à¥¤\n[[Special:Version|वरà¥\8dशन à¤ªà¤¨à¥\8dना]] à¤¦à¥\87à¤\96à¥\80à¤\82।",
+       "ok": "ठà¥\80क",
        "retrievedfrom": "\"$1\" से लिहल गइल",
        "youhavenewmessages": "रउआ लगे बा $1 ($2).",
-       "youhavenewmessagesfromusers": "रउआ खातिर {{PLURAL:$3|एगो अन्य सदस्य|$3 अन्य सदस्यन}} के $1 बा। ($2)",
-       "youhavenewmessagesmanyusers": "रà¤\89à¤\86 à¤\96ातिर à¤\95à¤\88 à¤¸à¤¦à¤¸à¥\8dयन à¤¦à¥\8dवारा $1 à¤¬à¤¾à¥¤ ($2)",
-       "newmessageslinkplural": "{{PLURAL:$1|à¤\8fà¤\95 à¤¨à¤¯à¤¾ à¤¸à¤¨à¥\8dदà¥\87श|999=नयà¤\95ा à¤¸à¤¨à¥\8dदà¥\87श}}",
-       "newmessagesdifflinkplural": "पिछला {{PLURAL:$1|बदलाव|999=बदलाव}}",
-       "youhavenewmessagesmulti": "रà¤\89à¤\86 à¤²à¤\97à¥\87 $1 à¤ªà¤° à¤¨à¤¯à¤¾ à¤¸à¤¨à¥\8dदà¥\87श बा",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|रउवाँ खातिर}}{{PLURAL:$3|अउरी प्रयोगकर्ता के|$3 प्रयोगकर्ता लोग}} के $1 बा ($2)।",
+       "youhavenewmessagesmanyusers": "रà¤\89वाà¤\81 à¤\96ातिर à¤\95à¤\88 à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤\95à¥\87 à¤­à¥\87à¤\9cल $1 à¤¬à¤¾ ($2)।",
+       "newmessageslinkplural": "{{PLURAL:$1|नया à¤¸à¤¨à¥\87सा|999=नया à¤¸à¤¨à¥\87सा à¤¸à¤­}}",
+       "newmessagesdifflinkplural": "पिछला {{PLURAL:$1|बदलाव|999=बदलाव}}",
+       "youhavenewmessagesmulti": "राà¤\89वाà¤\81 à¤\96ातिर $1 à¤ªà¤° à¤¨à¤¯à¤¾ à¤¸à¤¨à¥\87सा बा",
        "editsection": "संपादन",
        "editold": "संपादन",
        "viewsourceold": "स्रोत देखीं",
        "editlink": "संपादन",
        "viewsourcelink": "स्रोत देखीं",
-       "editsectionhint": "सà¤\82पादन à¤\96à¤\82ड: $1",
-       "toc": "सामà¤\97à¥\8dरी",
-       "showtoc": "दà¥\87à¤\96ाà¤\88ं",
-       "hidetoc": "à¤\9bà¥\81पाईं",
+       "editsectionhint": "à¤\96à¤\82ड à¤\95à¥\87 à¤¸à¤\82पादन: $1",
+       "toc": "बिसयसà¥\82à¤\9aी",
+       "showtoc": "दà¥\87à¤\96à¥\80ं",
+       "hidetoc": "à¤\9bिपाईं",
        "collapsible-collapse": "सेकुड़ीं",
-       "collapsible-expand": "फà¥\88लाईं",
+       "collapsible-expand": "फà¤\87लाईं",
        "confirmable-confirm": "का {{GENDER:$1|आप}} निश्चित बानी?",
        "confirmable-yes": "जी",
        "confirmable-no": "ना",
-       "thisisdeleted": "दà¥\87à¤\96à¥\80à¤\82 à¤¯à¤¾ à¤­à¤\82डार करीं $1?",
-       "viewdeleted": "$1 à¤¦à¥\87à¤\96ब?",
-       "restorelink": "देखीं {{PLURAL:$1|एगो हटावल गईल सम्पादन|$1 हटावल गईल कुल सम्पादन}}",
-       "feedlinks": "फ़à¥\80ड:",
-       "feed-invalid": "à¤\97लत à¤¸à¤¬à¥\8dसà¥\8dà¤\95à¥\8dरà¥\80पà¥\8dशन à¤«à¤¼ीड प्रकार",
-       "feed-unavailable": "सà¤\82à¤\98 à¤«à¤¼à¥\80ड à¤\89पलबà¥\8dध à¤¨à¤\87à¤\96à¥\87",
-       "site-rss-feed": "$1 आर एस एस फिड",
+       "thisisdeleted": "दà¥\87à¤\96à¥\80à¤\82 à¤¯à¤¾ à¤°à¤¿à¤¸à¥\8dà¤\9fà¥\8bर करीं $1?",
+       "viewdeleted": "$1 à¤¦à¥\87à¤\96ावल à¤\9cाय?",
+       "restorelink": "{{PLURAL:$1|एक ठो हटावल संपादन|$1 ठे हटावल संपादन}}",
+       "feedlinks": "फीड:",
+       "feed-invalid": "à¤\85वà¥\88ध à¤¸à¤¬à¤¸à¥\8dà¤\95à¥\8dरिपà¥\8dशन à¤«ीड प्रकार",
+       "feed-unavailable": "सिà¤\82डिà¤\95à¥\87शन à¤«à¥\80ड à¤\89पलबà¥\8dध à¤¨à¤\87à¤\96à¥\87à¤\82",
+       "site-rss-feed": "$1 आरएसएस फीड",
        "site-atom-feed": "$1 एटम फीड",
-       "page-rss-feed": "\"$1\" आर एस एस फिड",
+       "page-rss-feed": "\"$1\" आरएसएस फिड",
        "page-atom-feed": "\"$1\" एटम फीड",
        "red-link-title": "$1 (पन्ना मौजूद नइखे)।",
        "sort-descending": "उतरत क्रम में",
        "sort-ascending": "चढ़त क्रम में",
        "nstab-main": "पन्ना",
-       "nstab-user": "सदसà¥\8dय पन्ना",
+       "nstab-user": "पà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता पन्ना",
        "nstab-media": "मीडिया पन्ना",
        "nstab-special": "विशेष पन्ना",
        "nstab-project": "प्रोजेक्ट पन्ना",
        "nstab-image": "फाइल",
-       "nstab-mediawiki": "सनà¥\8dदà¥\87श",
+       "nstab-mediawiki": "सनà¥\87सा",
        "nstab-template": "टेम्पलेट",
        "nstab-help": "मदद पन्ना",
        "nstab-category": "श्रेणी",
        "mainpage-nstab": "मुख्य पन्ना",
-       "nosuchaction": "à¤\85à¤\88सन à¤\95à¥\8cनà¥\8b à¤\95ारà¥\8dरवाà¤\88 à¤¨à¤¾à¤¹à¤¿",
-       "nosuchactiontext": "à¤\87 à¤¯à¥\82॰à¤\86र॰à¤\8fल à¤¦à¥\8dवारा à¤¨à¤¿à¤°à¥\8dदिषà¥\8dà¤\9f à¤\95à¥\8dरिया à¤\85वà¥\88ध à¤¬à¤¾à¥¤\nरà¤\89à¤\86 à¤¯à¥\82॰à¤\86र॰à¤\8fल à¤\97लत à¤²à¤¿à¤\96लà¥\87 à¤¹à¥\8bà¤\96ब, à¤¯à¤¾ à¤\95à¤\89नà¥\8b à¤\97लत à¤\95ड़à¥\80 à¤\95à¥\87 à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95à¤\87लà¥\87 à¤¹à¥\8bà¤\96ब।\nà¤\87 {{SITENAME}} à¤\95à¥\87 à¤¸à¥\89फ़à¥\8dà¤\9fवà¥\87यर à¤®à¥\87à¤\82 à¤¤à¥\8dरà¥\81à¤\9fि भी हो सकत बा।",
-       "nosuchspecialpage": "à¤\85à¤\88सन à¤\95à¥\8cनà¥\8b à¤\96़ाश à¤ªà¤¨à¥\8dना à¤¨à¤¾à¤¹à¤¿",
-       "nospecialpagetext": "<strong>रउआ एगो अवैद्य विशेष पन्ना के अनुरोध कईले बानी।</strong>\n\nवैद्य विशेष पन्ना के सूची मिल सकत बा [[Special:SpecialPages|{{int:specialpages}}]] पर।",
-       "error": "तà¥\8dरà¥\81à¤\9fी",
-       "databaseerror": "डà¥\87à¤\9fाबà¥\87स à¤¤à¥\8dरà¥\81à¤\9fी",
-       "databaseerror-text": "डाà¤\9fाबà¥\87स à¤\85नà¥\81रà¥\8bध à¤¤à¥\8dरà¥\81à¤\9fि  à¤­à¤\87ल à¤¬à¤¾à¥¤\nसà¤\82भवतà¤\83 à¤¸à¥\89फ़्टवेयर में गड़बड़ी बा।",
-       "databaseerror-textcl": "डाà¤\9fाबà¥\87स à¤\85नà¥\81रà¥\8bध à¤¤à¥\8dरà¥\81à¤\9fि à¤\89तà¥\8dतà¥\8dपनà¥\8dन à¤¹à¥\8b à¤\97à¤\88ल बा।",
+       "nosuchaction": "à¤\85à¤\87सन à¤\95à¥\8cनà¥\8b à¤\95ारà¥\8dरवाà¤\88 à¤¨à¤\87à¤\96à¥\87",
+       "nosuchactiontext": "à¤\8f à¤¯à¥\82॰à¤\86र॰à¤\8fल à¤¦à¥\8dवारा à¤¬à¤¤à¤¾à¤µà¤² à¤\95ारà¥\8dरवाà¤\88 à¤\85वà¥\88ध à¤¬à¤¾à¥¤\nरà¤\89वाà¤\81 à¤¯à¥\82॰à¤\86र॰à¤\8fल à¤\97लत à¤²à¤¿à¤\96लà¥\87 à¤¹à¥\8bà¤\96ब, à¤¯à¤¾ à¤\95वà¥\8dनà¥\8b à¤\97लत à¤\95ड़à¥\80 à¤\95à¥\87 à¤\87सà¥\8dतà¥\87माल à¤\95à¤\87लà¥\87 à¤¹à¥\8bà¤\96ब।\n{{SITENAME}} à¤®à¥\87à¤\82 à¤\87सà¥\8dतमाल à¤¹à¥\8b à¤°à¤¹à¤² à¤¸à¥\89फà¥\8dà¤\9fवà¥\87यर à¤®à¥\87à¤\82 à¤\96राबà¥\80 à¤\95à¥\87 à¤²à¤\9aà¥\8dà¤\9bन भी हो सकत बा।",
+       "nosuchspecialpage": "à¤\85à¤\87सन à¤\95à¥\8cनà¥\8b à¤\96ास à¤ªà¤¨à¥\8dना à¤¨à¤\87à¤\96à¥\87",
+       "nospecialpagetext": "<strong>रउआँ एगो अवैध खास पन्ना के अनुरोध कइले बानी।</strong>\n\nबैध खास पन्नासभ के लिस्ट [[Special:SpecialPages|{{int:specialpages}}]] पर देखल जा सकत बा।",
+       "error": "à¤\96राबी",
+       "databaseerror": "डà¥\87à¤\9fाबà¥\87स à¤\96राबी",
+       "databaseerror-text": "à¤\95à¥\8cनà¥\8bà¤\82 à¤¡à¤¾à¤\9fाबà¥\87स à¤\95à¥\8dवà¥\88रà¥\80 à¤\96राबà¥\80 à¤­à¤\87ल à¤¬à¤¾à¥¤\nसà¤\82भवतà¤\83 à¤¸à¥\89फ्टवेयर में गड़बड़ी बा।",
+       "databaseerror-textcl": "à¤\95à¥\8cनà¥\8bà¤\82 à¤¡à¤¾à¤\9fाबà¥\87स à¤\85नà¥\81रà¥\8bध à¤\96राबà¥\80 à¤\89तà¥\8dतà¥\8dपनà¥\8dन à¤¹à¥\8b à¤\97à¤\87ल बा।",
        "databaseerror-query": "अनुरोध: $1",
-       "databaseerror-function": "फ़ंक्शन: $1",
-       "databaseerror-error": "त्रुटि: $1",
-       "laggedslavemode": "'''चेतावनी:''' इ पन्ना पर हाल के बदलाव ना होखे के आशंका बा।",
-       "readonly": "डेटाबेस लॉक बा",
-       "enterlockreason": "लॉक करे के कारण दिहीं, साथे लॉक खुले के समय के लगभग आकलन दिहीं।",
-       "readonlytext": "डाटाबेस नया संपादन आ अन्य बदलाव खातिर लॉक करल गइल बा, शायद रुटीन मेंटेनन्स के चलते, जेकरा बाद ए के सामान्य स्थिती में आ जाये के चाहीं।\n\nजउन सिस्टम प्रबंधक एह के लॉक कइले रहलन कारण देहले बाड़न कि: $1",
-       "missing-article": "डेटाबास ऊ पन्ना के पाठ्य के ना खोज पाईल जौन ई के खोजे के रहल, नामित \"$1\" $2.\nई सब साधारणत: निम्नलिखीत अप्रचलित अन्तर अथवा एगो पन्ना पर इतिहास के लिंक जौन मिटा दिहल गईल बा के कारण भईल।\n\nयदि ई बात नईखे, त हो सकत बा सॉफ्टवेयर में बग पावत होखब।\nकृपया ई एगो  [[Special:ListUsers/sysop|प्रबन्धक]] के यू आर एल के बारे में एगो नोट बनाके खबर करीं।",
-       "missingarticle-rev": "(संशोधन#: $1)",
+       "databaseerror-function": "फंक्शन: $1",
+       "databaseerror-error": "खराबी: $1",
+       "transaction-duration-limit-exceeded": "हाई रिप्लिकेशन लैग बनावे से बचे खातिर ई ट्रांजेक्शन निरस्त कर दिहल गइल, काहें से की राइट करे में लागे वाला समय ($1), $2 के सीमा से अधिक रहल ह।\nअगर आप कई ठो आइटम एकही साथ बदलत होखीं, तब कई टुकड़ा में ई काम करे के कोसिस करीं।",
+       "laggedslavemode": "<strong>चेतावनी:</strong> अइसन भी हो सकेला कि पन्ना पर हाल के अपडेट न होखे।",
+       "readonly": "डेटाबेस तालाबंदी बा",
+       "enterlockreason": "तालाबंदी के कारण दीं, आ अनुमान बताईं कि कब तालाबंदी हटी",
+       "readonlytext": "नया संपादन आ अन्य बदलाव खातिर डाटाबेस पर तालाबंदी बा, शायद रुटीन मेंटेनन्स के चलते, जेकरा बाद ए के सामान्य स्थिती में आ जाये के चाहीं।\n\nतालाबंदी करे वाला सिस्टम प्रबंधक के बतावल कारण: $1",
+       "missing-article": "डेटाबास के ओ पन्ना के पाठ ना मिलल जवन मिले के चाहत रहल, एकर नाँव रहल \"$1\" $2।\nआमतौर पर अइसन तब होला पुरान हो चुकल अंतर या हटावल पन्ना के इतिहास के कड़ी के पीछा कइल जा रहल होखे।\n\nयदि ई बात नइखे, तब हो सकेला आपके कौनों सॉफ्टवेयर बग मिल गइल होखे।\n[[Special:ListUsers/sysop|प्रबंधक]] के ई यूआरएल दे के खबर करीं।",
+       "missingarticle-rev": "(बदलाव#: $1)",
        "missingarticle-diff": "(अंतर: $1, $2)",
-       "readonly_lag": "उपमुख्य डाटाबेस सर्वर मुख्य डाटाबेस के बराबर परावर्तित होत समय मुख्य डाटाबेस सर्वर अपने आप लॉक हो गइल।",
-       "internalerror": "आन्तरिक त्रुटि",
-       "internalerror_info": "आन्तरिक त्रुटि: $1",
-       "internalerror-fatal-exception": "प्रकार के गंभीर अपवाद \"$1\"",
-       "filecopyerror": "\"$1\" फ़ाइल के \"$2\" पर प्रतिलिपि ना बन पाईल।",
-       "filerenameerror": "\"$1\" फ़ाइल के नाम बदल के \"$2\" नइखे रखल जा सकत।",
-       "filedeleteerror": "\"$1\" फ़ाइल के ना हटावल जा सकल।",
+       "readonly_lag": "निचला डाटाबेस सर्वर जबले मुख्य डाटाबेस सर्वर के गति पकड़ पावे, डाटाबेस अपने आप लॉक हो गइल।",
+       "nonwrite-api-promise-error": "'Promise-Non-Write-API-Action' ऍचटीटीपी हेडर भेजल गइल रहल बाकी ई रिक्वेस्ट एपीआइ राइट मॉड्यूल खातिर रहल।",
+       "internalerror": "अंदरूनी खराबी",
+       "internalerror_info": "अंदरूनी खराबी: $1",
+       "internalerror-fatal-exception": "\"$1\" प्रकार के घातक अपवाद",
+       "filecopyerror": "फाइल \"$1\" के \"$2\" पर नकल ना बन पावल।",
+       "filerenameerror": "फाइल \"$1\" के नाँव बदल के \"$2\" नइखे रखल जा सकत।",
+       "filedeleteerror": "फाइल \"$1\" के हटावल ना जा सकल।",
        "directorycreateerror": "\"$1\" डाइरेक्टरी ना बनावल जा सकल।",
-       "directoryreadonlyerror": "निरà¥\8dदà¥\87शिà¤\95ा \"$1\" à¤¸à¤¿à¤°à¥\8dफ à¤ªà¤ à¤¨à¥\80य बा।",
-       "directorynotreadableerror": "निरà¥\8dदà¥\87शिà¤\95ा \"$1\" à¤ªà¤ à¤¨à¥\80य नइखे।",
-       "filenotfound": "\"$1\" फ़ाइल ना मिलल।",
-       "unexpected": "à¤\85नपà¥\87à¤\95à¥\8dषित à¤®à¥\82लà¥\8dय: \"$1\"=\"$2\".",
-       "formerror": "तà¥\8dरà¥\81à¤\9fि: à¤«à¤¼à¥\89रà¥\8dम à¤¸à¤¬à¤®à¤¿à¤\9f à¤¨à¤¾ à¤\95रल जा सकल।",
-       "badarticleerror": "à¤\87 à¤ªà¤¨à¥\8dना à¤ªà¤° à¤\87 à¤\95ारà¥\8dय à¤¨à¤\87à¤\96à¥\87 à¤\95रल à¤\9cा à¤¸à¤\95त।",
-       "cannotdelete": "\"$1\" à¤ªà¤¨à¥\8dना à¤¯à¤¾ à¤«à¤¾à¤\87ल à¤\95à¥\87 à¤¹à¤\9fावल à¤¨à¤\87à¤\96à¥\87 à¤\9cा à¤¸à¤\95त।\nशायद à¤\95à¥\87हà¥\81 à¤\85à¤\89र à¤\87 à¤\95à¥\87 à¤ªà¤¹à¤¿à¤²à¥\87 à¤¹à¤¿ हटा चुकल होखे।",
+       "directoryreadonlyerror": "डाà¤\87रà¥\87à¤\95à¥\8dà¤\9fरà¥\80 \"$1\" à¤\96ालà¥\80 à¤ªà¤¢à¤¼à¥\87 à¤\96ातिर बा।",
+       "directorynotreadableerror": "डाà¤\87रà¥\87à¤\95à¥\8dà¤\9fरà¥\80 \"$1\" à¤ªà¤¢à¤¼à¥\87 à¤²à¤¾à¤¯à¤\95 नइखे।",
+       "filenotfound": "फाइल \"$1\" ना मिलल।",
+       "unexpected": "à¤\89मà¥\87द à¤¸à¥\87 à¤¹à¤\9f à¤\95à¥\87 à¤µà¥\88लà¥\8dयà¥\82: \"$1\"=\"$2\".",
+       "formerror": "à¤\96राबà¥\80: à¤«à¤¾à¤°à¥\8dम à¤\9cमा à¤¨à¤¾ à¤\95à¤\87ल जा सकल।",
+       "badarticleerror": "à¤\8f à¤ªà¤¨à¥\8dना à¤ªà¤° à¤\88 à¤\95ाम à¤¨à¤¾ à¤¹à¥\8b à¤¸à¤\95à¥\80।",
+       "cannotdelete": "\"$1\" à¤¨à¤¾à¤\81व à¤\95à¥\87 à¤ªà¤¨à¥\8dना à¤¯à¤¾ à¤«à¤¾à¤\87ल à¤\95à¥\87 à¤¨à¤¾ à¤¹à¤\9fावल à¤\9cा à¤¸à¤\95त à¤¬à¤¾à¥¤\nहà¥\8b à¤¸à¤\95à¥\87ला à¤\95à¥\87हà¥\82 à¤ªà¤¹à¤¿à¤²à¤¹à¥\80à¤\82 à¤\8fà¤\95रा à¤\95à¥\87 हटा चुकल होखे।",
        "cannotdelete-title": "\"$1\" पन्ना के हटावल नइखे जा सकत",
-       "delete-hook-aborted": "हà¥\81à¤\95 à¤¦à¥\8dवारा à¤¹à¤\9fायà¥\87à¤\95à¥\87 à¤\95à¥\8dरिया à¤¬à¥\80à¤\9aà¥\87 à¤®à¥\87à¤\82 à¤\9bà¥\8bड़ल à¤\97à¤\88ल।\nà¤\87 à¤\95à¤\89नà¥\8b à¤\95ारण à¤¨à¤\88à¤\96à¥\87 बतवले।",
-       "no-null-revision": "पनà¥\8dना \"$1\" à¤\96ातिर à¤¨à¤¯à¤¾ à¤\85शà¤\95à¥\8dत à¤¸à¤\82शोधन ना बन सकल",
+       "delete-hook-aborted": "हà¥\81à¤\95 à¤¦à¥\8dवारा à¤¹à¤\9fावà¥\87 à¤\95à¥\87 à¤\95ारà¥\8dरवाà¤\88 à¤¬à¥\80à¤\9aà¥\87 à¤®à¥\87à¤\82 à¤\9bà¥\8bड़ल à¤\97à¤\87ल।\nबिना à¤\95à¥\8cनà¥\8bà¤\82 à¤\95ारण बतवले।",
+       "no-null-revision": "पनà¥\8dना \"$1\" à¤\96ातिर à¤¨à¤¯à¤¾ à¤\96ालà¥\80 à¤¸à¤\82सोधन ना बन सकल",
        "badtitle": "खराब टाइटिल",
-       "badtitletext": "रà¤\89à¤\86 à¤¦à¥\8dवारा à¤\85नà¥\81रà¥\8bधित à¤¶à¥\80रà¥\8dषà¤\95 à¤\85यà¥\8bà¤\97à¥\8dय, à¤\96़ालà¥\80 à¤¯à¤¾ à¤\97लत à¤\9cà¥\81ड़ल à¤\85à¤\82तर-भाषà¥\80य à¤¯à¤¾ à¤\85à¤\82तर-विà¤\95ि à¤¶à¥\80रà¥\8dषà¤\95 à¤¬à¤¾à¥¤\nà¤\8f à¤®à¥\87à¤\82 à¤\8fà¤\95 à¤¯à¤¾ à¤\8fà¤\95 à¤¸à¥\87 à¤¢à¥\87र à¤\85à¤\87सन à¤\95à¥\85रà¥\87à¤\95à¥\8dà¤\9fर à¤¹à¥\8b à¤¸à¤\95त à¤¬à¤¾ à¤\9cवन à¤¶à¥\80रà¥\8dषà¤\95 à¤®à¥\87à¤\82 à¤ªà¥\8dरयà¥\8bà¤\97 à¤¨à¤\87à¤\96à¥\87 à¤\95à¤\87ल à¤\9cा à¤¸à¤\95त।",
-       "title-invalid-empty": "माà¤\81à¤\97ल à¤\9cा à¤°à¤¹à¤² à¤ªà¤¨à¥\8dना à¤\9fाà¤\87à¤\9fिल à¤¯à¤¾ à¤¤ à¤\96ालà¥\80 à¤¬à¤¾ à¤¯à¤¾ à¤«à¤¿à¤° à¤\96ालà¥\80 à¤\95à¥\8cनà¥\8bà¤\82 à¤¨à¤¾à¤\81वसà¥\8dथान à¤\95à¥\87 à¤¨à¤¾à¤\81व à¤­à¤° à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¬à¤¾à¤\9fà¥\87।",
+       "badtitletext": "à¤\85नà¥\81रà¥\8bधित à¤\9fाà¤\87à¤\9fिल à¤\85वà¥\88ध, à¤\96ालà¥\80 à¤¯à¤¾ à¤\97लत à¤\9cà¥\81ड़ल à¤\85à¤\82तर-भाषà¥\80य à¤¯à¤¾ à¤\85à¤\82तर-विà¤\95ि à¤\9fाà¤\87à¤\9fिल à¤¬à¤¾à¥¤\nबà¥\81à¤\9dात à¤¬à¤¾ à¤\95ि à¤\8fह à¤®à¥\87à¤\82 à¤\9fाà¤\87à¤\9fिल à¤®à¥\87à¤\82 à¤¨à¤¾ à¤\87सà¥\8dतà¥\87माल à¤¹à¥\8b à¤¸à¤\95à¥\87 à¤²à¤¾à¤¯à¤\95 à¤\8fà¤\95 à¤¯à¤¾ à¤\8fà¤\95 à¤¸à¥\87 à¤¢à¥\87र à¤\95à¥\85रà¥\87à¤\95à¥\8dà¤\9fर à¤¬à¤¾।",
+       "title-invalid-empty": "माँगल जा रहल पन्ना टाइटिल या त खाली बा या फिर कौनों नाँवस्थान के नाँव भर दिहल गइल बाटे।",
        "title-invalid-utf8": "माँगल जा रहल पन्ना टाइटिल में अइसन UTF-8 सीक्वेंस बा जेवन मान्य नइखे।",
        "title-invalid-interwiki": "माँगल जा रहल पन्ना टाइटिल में इंटरविकि कड़ी बा जेवन टाइटिल में ना प्रयोग कइल जा सकत बा।",
        "title-invalid-talk-namespace": "माँगल जा रहल पन्ना टाइटिल एगो अइसन वार्ता पन्ना के रेफर करत बा जेवना के होखल संभव नइखे।",
        "title-invalid-magic-tilde": "माँगल जा रहल पन्ना टाइटिल में अमान्य जादुई टिल्ड सीक्वेंस (<nowiki>~~~</nowiki>) बाटे।",
        "title-invalid-too-long": "माँगल जा रहल पन्ना टाइटिल बहुत ढेर लंबा बा। ई UTF-8 की एनकोडिंग में $1 {{PLURAL:$1|बाइट|बाइट्स}} से ढेर ना होखे के चाहीं।",
        "title-invalid-leading-colon": "माँगल जा रहल पन्ना टाइटिल में सुरुआते में अमान्य कोलन (:) बाटे।",
-       "perfcached": "नà¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¡à¥\87à¤\9fा à¤\95à¥\88शà¥\87 à¤®à¥\87मà¥\8bरà¥\80 à¤¸à¥\87 à¤²à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¬à¤¾, à¤\85तà¤\83 à¤¹à¥\8b à¤¸à¤\95ता à¤¬à¤¾ à¤\95ि à¤\87 à¤\95à¥\87 à¤ªà¥\82रà¥\8dण à¤\85दà¥\8dयतन à¤¨à¤¾ à¤­à¤\87ल à¤¹à¥\8bà¤\96à¥\87। à¤\95à¥\88शà¥\87 à¤®à¥\87मà¥\8bरà¥\80 à¤®à¥\87à¤\82 à¤\85धिà¤\95तम {{PLURAL:$1|à¤\8fà¤\95  à¤¨à¤¤à¥\80à¤\9cा|$1 à¤¨à¤¤à¥\80à¤\9cà¤\82}} à¤\89पलबà¥\8dध à¤¬à¤¾à¤¡à¤¼à¥\87।",
-       "perfcachedts": "नà¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¡à¥\87à¤\9fा à¤\95à¥\88शà¥\87 à¤®à¥\87मà¥\8bरà¥\80 à¤¸à¥\87 à¤¬à¤¾, à¤\86 à¤\8fà¤\95र à¤\85à¤\82तिम à¤\85पडà¥\87à¤\9f $1 à¤\95à¥\87 à¤­à¤\87ल à¤°à¤¹à¤²à¥¤ à¤\95à¥\88श à¤®à¥\87मà¥\8bरà¥\80 à¤®à¥\87à¤\82 à¤\85धिà¤\95तम {{PLURAL:$4|à¤\8fà¤\95  à¤¨à¤¤à¥\80à¤\9cा|$4 à¤¨à¤¤à¥\80à¤\9cाà¤\82}} उपलब्ध बा।",
-       "querypage-no-updates": "à¤\87 à¤ªà¥\83षà¥\8dठ à¤\95à¥\87 à¤\85पडà¥\87à¤\9f à¤\95रल à¤\85यà¥\8bà¤\97à¥\8dय à¤¬à¤¾à¥¤ à¤\85भà¥\80 à¤\85हिà¤\9cा à¤\95à¥\87 à¤¡à¤¾à¤\9fा à¤\95à¥\87 à¤¤à¤¾à¤\9c़ा à¤¨à¤\87à¤\96à¥\87 à¤\95रल जा सकत।",
+       "perfcached": "नà¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤\86à¤\81à¤\95ड़ा à¤\95à¥\88शà¥\87 à¤®à¥\87मà¥\8bरà¥\80 à¤¸à¥\87 à¤²à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¬à¤¾, à¤¹à¥\8b à¤¸à¤\95ता à¤¬à¤¾ à¤\95ि à¤\88 à¤\8fà¤\95दम à¤\85पडà¥\87à¤\9f à¤¨à¤¾ à¤¹à¥\8bà¤\96à¥\87। à¤\95à¥\88शà¥\87 à¤®à¥\87मà¥\8bरà¥\80 à¤®à¥\87à¤\82 à¤\85धिà¤\95तम {{PLURAL:$1|à¤\8fà¤\95 à¤ à¥\8b  à¤¨à¤¤à¥\80à¤\9cा|$1 à¤¨à¤¤à¥\80à¤\9cा}} à¤\89पलबà¥\8dध à¤¬à¤¾।",
+       "perfcachedts": "नà¥\80à¤\9aà¥\87 à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤\86à¤\81à¤\95ड़ा à¤\95à¥\88शà¥\87 à¤®à¥\87मà¥\8bरà¥\80 à¤¸à¥\87 à¤¬à¤¾, à¤\86 à¤\8fà¤\95र à¤\85à¤\82तिम à¤\85पडà¥\87à¤\9f $1 à¤\95à¥\87 à¤­à¤\87ल à¤°à¤¹à¤²à¥¤ à¤\95à¥\88श à¤®à¥\87मà¥\8bरà¥\80 à¤®à¥\87à¤\82 à¤\85धिà¤\95तम {{PLURAL:$4|à¤\8fà¤\95 à¤ à¥\8b à¤¨à¤¤à¥\80à¤\9cा|$4 à¤¨à¤¤à¥\80à¤\9cा}} उपलब्ध बा।",
+       "querypage-no-updates": "à¤\8fह à¤ªà¤¨à¥\8dना à¤¸à¥\87 à¤¸à¤\82बà¤\82धित à¤\85पडà¥\87à¤\9f à¤µà¤°à¥\8dतमान à¤®à¥\87à¤\82 à¤¨à¤¿à¤°à¤¸à¥\8dत à¤¬à¤¾à¥¤ à¤\85भà¥\80 à¤\85हिà¤\9cा à¤\95à¥\87 à¤¡à¤¾à¤\9fा à¤\95à¥\87 à¤¤à¤¾à¤\9cा à¤¨à¤\87à¤\96à¥\87 à¤\95à¤\87ल जा सकत।",
        "viewsource": "स्रोत देखीं",
        "viewsource-title": "$1 के स्रोत देखीं",
-       "actionthrottled": "à¤\95ारà¥\8dय समाप्त कर दिहल गइल बा",
-       "actionthrottledtext": "दुरुपयोग रोकथाम उपाय के रूप में, एह काम के बहुत कम समय में एक सीमा से अधिक बे करे के मना बा, आ रउआ ई सीमा के पार कर चुकल बानी।\nकृपया कुछ समय बाद दोबारा कोसिस करीं।",
-       "protectedpagetext": "à¤\87 à¤ªà¤¨à¥\8dना à¤¸à¤\82पादन à¤\86 à¤\85नà¥\8dय à¤\95ारà¥\8dयà¤\82 à¤¸à¥\87 à¤¬à¤\9aाव खातिर सुरक्षित कर दिहल गइल बा।",
+       "actionthrottled": "à¤\95ारà¥\8dरवाà¤\88 समाप्त कर दिहल गइल बा",
+       "actionthrottledtext": "दुरुपयोग रोकथाम उपाय के रूप में, एह काम के बहुत कम समय में एक सीमा से अधिक बे करे के मना बा, आ रउआ ई सीमा के पार कर चुकल बानी।\nकृपया कुछ समय बाद दोबारा कोसिस करीं।",
+       "protectedpagetext": "à¤\8f à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¸à¤\82पादन à¤\86 à¤\85नà¥\8dय à¤\95ारà¥\8dरवाà¤\88 à¤¸à¥\87 à¤¬à¤\9aावà¥\87 खातिर सुरक्षित कर दिहल गइल बा।",
        "viewsourcetext": "रउआँ एह पन्ना के स्रोत देख सकत बानी आ एकर नकल उतार सकत बानी:",
-       "viewyourtext": "à¤\8fह à¤ªà¤¨à¥\8dना à¤ªà¤° <strong>राà¤\89र à¤\86पन à¤¸à¤\82पादन à¤¸à¤¬</strong>के स्रोत देख सकत बानी आ ओकर नकल ले सकत बानी।",
-       "protectedinterface": "à¤\87 à¤ªà¤¨à¥\8dना à¤\87 à¤µà¤¿à¤\95à¥\80 à¤\95à¥\87 à¤¸à¥\89फ़à¥\8dà¤\9fवà¥\87यर à¤\95à¥\87 à¤\87à¤\82à¤\9fरफ़à¥\87स à¤ªà¤¾à¤ à¥\8dय à¤\95à¥\87 à¤¦à¥\87वà¥\87ला, à¤\86 à¤\87 à¤\95à¥\87 à¤\97लत à¤ªà¥\8dरयà¥\8bà¤\97 à¤¸à¥\87 à¤¬à¤\9aावà¥\87 à¤\96ातिर à¤¸à¥\81रà¤\95à¥\8dषित à¤\95र à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¬à¤¾à¥¤\nसभन à¤µà¤¿à¤\95ियन à¤\96ातिर à¤\85नà¥\81वाद à¤\9cà¥\8bड़à¥\87 à¤¯à¤¾ à¤¬à¤¦à¤²à¥\87 à¤\96ातिर à¤\95à¥\83पया à¤®à¥\80डियाविà¤\95ि à¤\95à¥\87 à¤\95à¥\8dषà¥\87तà¥\8dरà¥\80यà¤\95रण à¤ªà¥\8dरà¤\95लà¥\8dप [https://translatewiki.net/ translatewiki.net] à¤\95à¥\87 à¤ªà¥\8dरयà¥\8bà¤\97 करीं।",
-       "editinginterface": "<strong>à¤\9aà¥\87तावनà¥\80:</strong> à¤\86प à¤\8fà¤\97à¥\8b à¤\85à¤\87सन à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¬à¤¦à¤² à¤¬à¤¦à¤² à¤°à¤¹à¤² à¤¬à¤¾à¤¨à¥\80 à¤\9cवन à¤¸à¥\89फ़à¥\8dà¤\9fवà¥\87यर à¤\95à¥\87 à¤\87à¤\82à¤\9fरफ़à¥\87स à¤ªà¤¾à¤  à¤ªà¥\8dरदान à¤\95रà¥\87ला। à¤\87 à¤ªà¥\83षà¥\8dठ à¤\95à¥\87 à¤¬à¤¦à¤²à¥\87 à¤¸à¥\87 à¤\85नà¥\8dय à¤¸à¤¦à¤¸à¥\8dयवन à¤\95à¥\87 à¤ªà¥\8dरदरà¥\8dशित à¤\87à¤\82à¤\9fरफ़à¥\87स à¤\95à¥\87 à¤¶à¤\95à¥\8dलà¥\8bसà¥\82रत à¤®à¥\87à¤\82 à¤¬à¤¦à¤²à¤¾à¤µ à¤\86à¤\88।",
+       "viewyourtext": "à¤\8fह à¤ªà¤¨à¥\8dना à¤ªà¤° <strong>à¤\86पन à¤\96à¥\81द à¤\95à¥\87 à¤¸à¤\82पादन</strong>के स्रोत देख सकत बानी आ ओकर नकल ले सकत बानी।",
+       "protectedinterface": "à¤\88 à¤ªà¤¨à¥\8dना à¤\8fह à¤µà¤¿à¤\95ि à¤\95à¥\87 à¤¸à¥\89फà¥\8dà¤\9fवà¥\87यर à¤\95à¥\87 à¤\87à¤\82à¤\9fरफà¥\87स à¤ªà¤¾à¤  à¤\89पलबà¥\8dध à¤\95रावà¥\87 à¤²à¤¾, à¤\86 à¤¦à¥\81रà¥\82पयà¥\8bà¤\97 à¤°à¥\8bà¤\95à¥\87 à¤\96ातिर à¤\8fà¤\95रा à¤\95à¥\87 à¤¸à¥\81रà¤\95à¥\8dषित à¤\95र à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¬à¤¾à¥¤\nबिनमà¥\8dर à¤\85नà¥\81रà¥\8bध à¤¬à¤¾ à¤\95ि, à¤¸à¤\97रà¥\80 à¤µà¤¿à¤\95ि à¤¸à¤­ à¤\96ातिर à¤\85नà¥\81वाद à¤\95रà¥\87 à¤¯à¤¾ à¤\85नà¥\81वाद à¤®à¥\87à¤\82 à¤¬à¤¦à¤²à¤¾à¤µ à¤\95रà¥\87 à¤\96ातिर à¤®à¥\80डियाविà¤\95ि à¤\95à¥\87 à¤²à¥\8bà¤\95लाà¤\87à¤\9cà¥\87शन à¤ªà¥\8dरà¥\8bà¤\9cà¥\87à¤\95à¥\8dà¤\9f [https://translatewiki.net/ translatewiki.net] à¤\95à¥\87 à¤\87सà¥\8dतà¥\87माल करीं।",
+       "editinginterface": "<strong>à¤\9aà¥\87तावनà¥\80:</strong> à¤\86प à¤\8fà¤\97à¥\8b à¤\85à¤\87सन à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤¸à¤\82पादन à¤\95र à¤°à¤¹à¤² à¤¬à¤¾à¤¨à¥\80 à¤\9cवन à¤¸à¥\89फà¥\8dà¤\9fवà¥\87यर à¤\95à¥\87 à¤\87à¤\82à¤\9fरफà¥\87स à¤ªà¤¾à¤  à¤\89पलबà¥\8dध à¤\95रावà¥\87 à¤²à¤¾à¥¤ à¤\8fह à¤ªà¤¨à¥\8dना à¤ªà¤° à¤¹à¥\8bà¤\96à¥\87 à¤µà¤¾à¤²à¤¾ à¤¬à¤¦à¤²à¤¾à¤µ à¤\8fह à¤µà¤¿à¤\95ि à¤ªà¤° à¤\95à¥\87 à¤\85नà¥\8dय à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤²à¥\8bà¤\97 à¤\95à¥\87 à¤²à¤\89à¤\95à¥\87 à¤µà¤¾à¤²à¤¾ à¤\87à¤\82à¤\9fरफà¥\87स à¤\95à¥\87 à¤¸à¤\95लसà¥\82रत à¤\95à¥\87 à¤ªà¤°à¤­à¤¾à¤µà¤¿à¤¤ à¤\95रà¥\80।",
        "translateinterface": "सभन विकियन खातिर अनुवाद जोड़े या बदले खातिर मीडियाविकि क्षेत्रीयकरण परियोजना [https://translatewiki.net/ translatewiki.net] के प्रयोग करीं।",
        "cascadeprotected": "ए पन्ना के संपादन कइल सुरक्षित क दिहल गइल बा काहें कि ई {{PLURAL:$1|पन्ना में, जौना के|पन्ना सब में, जिन्हन के}} \"कैस्केडिंग\" (बिस्तारित) सुरक्षा चालू क के सुरक्षित कइल गइल बा, में समाइल बाटे:\n$2",
        "namespaceprotected": "रउआ के '''$1''' नामस्थान के पन्नं में सम्पादन करे के अधिकार नइखे दिहल गइल।",
        "mypreferencesprotected": "रउआ लगे आपन वरियतां ‍‍‍‍(पसंद) बदले के अधिकार नइखे।",
        "ns-specialprotected": "विशेष पन्ना के सम्पादन सम्भव नइखे",
        "titleprotected": "सदस्य [[User:$1|$1]] द्वारा इ शीर्षक के पन्ना बनावे से बचाव खातिर इ के सुरक्षित कर दिहल गइल बा।\nइ खातिर निम्न कारण दिहल गइल बा: <em>$2</em>",
-       "filereadonlyerror": "फाइल \"$1\" के बदलल सक्षम नइखे काहे कि संग्रह \"$2\" 'खाली पाठन हेतु' (रिड ऑन्ली) मोड में बा।\n\nजउन प्रबंधक इ प्रबंध लगउले बानी उहाँ के निम्न विवरण प्रदान कइले बानी: \"$3\"।",
+       "filereadonlyerror": "फाइल \"$1\" के बदलल सक्षम नइखे काहें कि संग्रह \"$2\" 'खाली पढ़े हेतु' (रीड ऑनली) मोड में बा।\n\nजे सिस्टम प्रबंधक ई प्रतिबंध लगावल ऊ नीचे दिहल कारण बतवले रहल: \"$3\"।",
        "invalidtitle-knownnamespace": "\"$2\" नामस्थान आ \"$3\" पाठ्य वाला गलत शीर्षक",
        "invalidtitle-unknownnamespace": "अज्ञात नामस्थान संख्या $1 आ नाम \"$2\" वाला गलत शीर्षक",
        "exception-nologin": "खाता में प्रवेश नइखे",
        "createacct-email-ph": "आपन ई-मेल पता लिखीं",
        "createacct-another-email-ph": "ई-मेल पता लिखीं",
        "createaccountmail": "एगो अस्थायी यादृच्छिक (रैन्डम) गुप्तशब्द के प्रयोग करीं आ निर्दिष्ट ई-मेल पता पर भेजीं",
+       "createaccountmail-help": "एकर इस्तेमाल केहू दुसरा खातिर खाता बनावे में कइल जा सके ला, बिना पासवर्ड जनले।",
        "createacct-realname": "असली नाम (वैकल्पिक)",
        "createaccountreason": "कारण:",
        "createacct-reason": "कारण",
        "eauthentsent": "दर्ज करावल गइल ई-मेल पता पर एगो पुष्टिकरण ई-मेल भेज दिहल गइल बा।\nउ खाता पर कौनो दुसर ईमेल भेजल जाओ उ से पहिले, रउआ भेजल गईल ई-मेल पर दिहल गइल निर्देश के अनुसरण कर के ई-मेल पता के पुष्टिकरण करावे के पड़ी ताकि पता चले की सही में उ राउरे खाता ह।",
        "throttled-mailpassword": "पिछला {{PLURAL:$1|एक घंटा|$1 घंटा}} के अंदर एगो गुप्तशब्द पुनर्स्थापन ई-मेल भेजल जा चुकल बा।\nदुरुपयोग से बचावे खातिर {{PLURAL:$1|एक घंटा|$1 घंटा}} में सिर्फ एगो गुप्तशब्द पुनर्स्थापन ई-मेल भेजल जाई।",
        "mailerror": "ई-मेल भेजे में त्रुटि: $1",
-       "acct_creation_throttle_hit": "राउर आइपी पता से आइल आगंतुक लोग पिछला चौबीस घंटा में एह विकि पर {{PLURAL:$1|एक ठो खाता|$1 खाता}} बना चुकल बा जवन एह समयअवधि में अधिकतम सीमा बा।\nएही कारण, एह आइपी पता के इस्तेमाल करे वाला आगंतुक अब कौनों अउरी खाता एह समय नइखें बना सकत।",
+       "acct_creation_throttle_hit": "राउर आइपी पता से आइल आगंतुक लोग पिछला $2 में एह विकि पर {{PLURAL:$1|एक ठो खाता|$1 खाता}} बना चुकल बा जवन एह समयअवधि में अधिकतम सीमा बा।\nएही कारण, एह आइपी पता के इस्तेमाल करे वाला आगंतुक अब कौनों अउरी खाता एह समय नइखें बना सकत।",
        "emailauthenticated": "$2 के $3 पर राउर ई-मेल पता के पुष्टीकरण हो चुकल बा।",
        "emailnotauthenticated": "राउर ई-मेल पता के अभी तक प्रमाणिकरण नइखे भईल।\nनिम्नलिखित कउनो भी सुविधा खातिर रउआ के कौनो भी ई-मेल ना भेजल जाई।",
        "noemailprefs": "इ सुविधा के प्रयोग करे खातिर आपन वरियता में एगो ई-मेल पता दिहीं।",
        "botpasswords-label-cancel": "कैंसिल",
        "botpasswords-label-delete": "मिटाईं",
        "botpasswords-label-resetpassword": "पासवर्ड रिसेट करीं",
+       "botpasswords-label-grants": "लागू हो सके वाला अनुमोदन:",
        "botpasswords-label-grants-column": "मंजूर भइल",
        "botpasswords-bad-appid": "बॉट नाँव \"$1\" वैध नइखे।",
+       "botpasswords-insert-failed": "बॉट नाँव $1 जोड़ल फेल हो गइल। का ई पहिलहीं जोड़ल जा चुकल बा?",
+       "botpasswords-update-failed": "बॉट नाँव \"$1\" अपडेट कइल फेल हो गइल। का ई मिटा दिहल बा?",
        "botpasswords-created-title": "बॉट पासवर्ड बनावल गइल",
+       "botpasswords-created-body": "प्रयोगकर्ता \"$2\" के बॉट नाँव \"$1\" खातिर बॉट पासवर्ड बना दिहल गइल।",
+       "botpasswords-updated-title": "बॉट पासवर्ड अपडेट भइल",
+       "botpasswords-updated-body": "प्रयोगकर्ता \"$2\" के बॉट नाँव \"$1\" खातिर बॉट पासवर्ड अपडेट भइल।",
+       "botpasswords-deleted-title": "बॉट पासवर्ड मिटावल गइल",
+       "botpasswords-deleted-body": "प्रयोगकर्ता \"$2\" के बॉट नाँव \"$1\" खातिर बॉट पासवर्ड मिटावल गइल।",
        "resetpass_forbidden": "गुप्तशब्द बदलल नइखे जा सकत",
        "resetpass-no-info": "इ पन्ना के सिधे प्रयोग करे खातिर रउआ पहिले खाता में प्रवेश करे के पड़ी।",
        "resetpass-submit-loggedin": "गुप्त शब्द बदलीं",
        "passwordreset-emaildisabled": "इ विकि पर ई-मेल सुविधा अक्षम कर दिहल गईल बा।",
        "passwordreset-username": "प्रयोगकर्ता नाम",
        "passwordreset-domain": "डोमेन:",
-       "passwordreset-capture": "परिणामस्वरूप बनल ई-मेल देखब?",
-       "passwordreset-capture-help": "अगर रउआ इ चेकबॉक्स पर टिक करत बानी त ई-मेल (अस्थायी गुप्तशब्द के साथ) रउआ के दिखावल जाई आ सदस्य के भेजल भी जाई।",
        "passwordreset-email": "ई-मेल पता:",
        "passwordreset-emailtitle": "{{SITENAME}} पर खाता विवरण",
        "passwordreset-emailtext-ip": "केहु (शायद रउए, $1 आइ॰पी पता से) {{SITENAME}} ($4) पर आपन {{PLURAL:$3|गुप्तशब्द}} के रीसेट करे के अनुरोध कईले बानी। इ ई-मेल पता से निम्न {{PLURAL:$3|खाता जुड़ल बा}}:\n\n$2\n\n{{PLURAL:$3|इ}} अस्थायी गुप्तशब्द {{PLURAL:$5|एक दिन|$5 दिन}} के बाद काम ना करी। रउआ खाता में प्रवेश करके एगो नया गुप्तशब्द अभी चुन लेवे के चाहीं। यदि इ अनुरोध केहु अउर कइले बा, या फिर रउआ आपन मूल गुप्तशब्द याद आ गईल बा, अउर आप {{PLURAL:$3|आपन}} गुप्तशब्द नइखी बदले के चाहत त, रउआ इ संदेश के अनदेखा कर के आपन पुरानका गुप्तशब्द के प्रयोग जारी रख सकत बानी।",
        "passwordreset-emailtext-user": "{{SITENAME}} ($4) पर सदस्य $1 राउर {{PLURAL:$3|खाता}} के गुप्तशब्द के पुनर्स्थापित करे के अनुरोध कइले बानी। इ ई-मेल पता से निम्न {{PLURAL:$3|खाता जुड़ल बा}}:\n\n$2\n\n{{PLURAL:$3|इ}} अस्थायी गुप्तशब्द {{PLURAL:$5|एक दिन|$5 दिन}} के बाद काम ना करी।\nरउआ खाता में प्रवेश करके एगो नया गुप्तशब्द अभीये चुन लेवे के चाहीं। यदि इ अनुरोध केहु अउर कइले बा, या फिर रउआ आपन मूल गुप्तशब्द याद आ गईल बा, अउर रउआ {{PLURAL:$3|आपन}} गुप्तशब्द नईखीं बदले के चाहत त, रउआ इ संदेश के अनदेखा कर के आपन पुरनका गुप्तशब्द के प्रयोग जारी रख सकत बानीं।",
        "passwordreset-emailelement": "सदस्यनाम: \n$1\n\nअस्थायी गुप्तशब्द: \n$2",
        "passwordreset-emailsentemail": "एगो गुप्तशब्द रिसेट ई-मेल भेजल जा चुकल बा।",
-       "passwordreset-invalideamil": "अवैध ईमेल पता",
+       "passwordreset-invalidemail": "अवैध ईमेल पता",
        "changeemail": "ई-मेल पता बदलीं",
        "changeemail-header": "खाता के ई-मेल पता बदलीं",
        "changeemail-no-info": "इ पन्ना के सिधे प्रयोग करे खातिर रउआ पहिले खाता में प्रवेश करे के पड़ी।",
        "created": "बनावल गईल",
        "actioncomplete": "काम पुरा भइल",
        "dellogpage": "हटवले के लिस्ट",
-       "rollbacklink": "वापिस à¤²à¥\80à¤\82",
+       "rollbacklink": "रà¥\8bलबà¥\88à¤\95",
        "rollbacklinkcount": "रोलबैक $1 {{PLURAL:$1|संपादन|संपादन सब}}",
        "protectlogpage": "सुरक्षा लॉग",
        "protectlogtext": "नीचे पन्ना सुरक्षा में भइल बदलावकुल के सूची बा।\nहाल में सुरक्षित पन्नन के सूची खातिर [[Special:ProtectedPages|सुरक्षित पन्नन के सूची]] देखीं।",
        "undelete": "हटावल पन्ना देखीं",
        "undeletepage": "हटावल पन्ना देखीं आ वापिस ले आईं",
        "undeletelink": "देखीं/बहाल करीं",
-       "namespace": "नामस्थान:",
+       "namespace": "नाà¤\81वस्थान:",
        "invert": "चुनाव पलटीं",
        "tooltip-invert": "चुनल गइल नामस्थान की संघे बदलाव छिपावे खातिर ए बाकस के चिन्हित करीं (सम्बन्धित नामस्थान के भी, अगर चिन्हित होखे)",
        "namespace_association": "संबंधित नामस्थान",
        "mycontris": "हमार योगदान",
        "anoncontribs": "योगदान",
        "nocontribs": "ई मानदंड से मिलत जुलत कौनो बदलाव ना मिलल।",
-       "uctop": "(हाल à¤\95à¥\87)",
+       "uctop": "(वरà¥\8dतमान)",
        "month": "महीना से (आ ओ से पहिले):",
        "year": "साल से (आ ओ से पहिले):",
        "sp-contributions-newbies": "खाली नया खाता के योगदान देखीं।",
        "sp-contributions-newbies-sub": "नया खाता खातिर",
        "sp-contributions-newbies-title": "नया खाता खातिर प्रयोगकर्ता के योगदान।",
-       "sp-contributions-blocklog": "निषà¥\8dà¤\95à¥\8dरà¥\80य à¤\96ाता",
+       "sp-contributions-blocklog": "बà¥\8dलà¥\89à¤\95 à¤²à¥\89à¤\97",
        "sp-contributions-deleted": "नष्ट प्रयोगकर्ता के योगदान।",
-       "sp-contributions-logs": "लà¥\8cग",
-       "sp-contributions-talk": "बात-चीत",
+       "sp-contributions-logs": "लà¥\89ग",
+       "sp-contributions-talk": "बातचीत",
        "sp-contributions-userrights": "प्रयोगकर्ता अधिकार प्रबन्धन",
        "sp-contributions-blocked-notice": "ई प्रयोगकर्ता के ई समय निष्क्रीय करल गईल बा।\nनविनतम नष्ट लौग प्रविष्टी उद्धरण खातिर निचे दिहल बा:",
        "whatlinkshere": "इहाँ का जुड़ल बा",
        "tooltip-p-logo": "मुख्य पन्ना पर जाईं",
        "tooltip-n-mainpage": "मुख्य पन्ना पर जाईं",
        "tooltip-n-mainpage-description": "मुख्य पन्ना पर जाईं",
-       "tooltip-n-portal": "पà¥\8dरà¥\8bà¤\9cà¥\87à¤\95à¥\8dà¤\9f à¤\95à¥\80 à¤¬à¤¾à¤°à¥\87 à¤®à¥\87à¤\81, रउआँ का कर सकत बानी, कौनों चीज कहाँ खोजब",
+       "tooltip-n-portal": "पà¥\8dरà¥\8bà¤\9cà¥\87à¤\95à¥\8dà¤\9f à¤\95à¥\80 à¤¬à¤¾à¤°à¥\87 à¤®à¥\87à¤\82, रउआँ का कर सकत बानी, कौनों चीज कहाँ खोजब",
        "tooltip-n-currentevents": "वर्तमान के घटना पर पृष्ठभूमी जानकारी खोजीं",
        "tooltip-n-recentchanges": "विकि पर तुरंत भइल बदलाव के लिस्ट",
        "tooltip-n-randompage": "बेतरतीब पन्ना लोड करीं",
        "exif-iimcategory": "श्रेणी",
        "exif-orientation-1": "सामान्य",
        "namespacesall": "सगरी",
-       "monthsall": "सब",
-       "confirmemail": "à¤\87-मेल पता कन्फर्म करीं",
+       "monthsall": "सà¤\97रà¥\80",
+       "confirmemail": "à¤\88मेल पता कन्फर्म करीं",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|बात करीं]])",
        "version-no-ext-name": "[अज्ञात नाम]",
        "fileduplicatesearch": "नकल प्रति फाइल खोजीं",
        "logentry-newusers-create": "खाता $1 {{GENDER:$2|बनावल गइल}}",
        "revdelete-summary": "सारांश संपादन",
        "searchsuggest-search": "खोजीं",
-       "api-error-nomodule": "भितरà¥\80 à¤¤à¥\8dरà¥\81à¤\9fी:कउनो अपलोड मॉड्युल सेट नइखे",
-       "expandtemplates": "फà¥\88लल à¤\96ाà¤\81à¤\9aा",
-       "mediastatistics": "मिडिया à¤¤à¤¥à¥\8dयाà¤\82à¤\95"
+       "api-error-nomodule": "भितरà¥\80 à¤\96राबी:कउनो अपलोड मॉड्युल सेट नइखे",
+       "expandtemplates": "à¤\9fà¥\87मà¥\8dपलà¥\87à¤\9f à¤¬à¤¿à¤¸à¥\8dतार",
+       "mediastatistics": "मà¥\80डिया à¤¸à¤¾à¤\82à¤\96à¥\8dयिà¤\95à¥\80"
 }
index 8a0eb59..3e79912 100644 (file)
        "yourname": "Ngaran pamakai:",
        "yourpassword": "Katasunduk:",
        "yourpasswordagain": "Katik pulang katasunduk:",
-       "remembermypassword": "Ingatakan log babuat ulun dalam komputer naya (salawas $1 {{PLURAL:$1|hari|hari}})",
        "yourdomainname": "Domain Pian:",
        "password-change-forbidden": "Pian kada kawa ma-ubah kata sunduk pada wiki ngini.",
        "externaldberror": "Ada kasalahan apakah kacucukan basis data atawa Pian kada bulih mamutakhirakan akun luar.",
        "passwordreset-emailtext-user": "Ada urang (pinanya Pian, matan alamat IP $1) maminta sabuting pangingat hagan rarincian akun Pian gasan {{SITENAME}} ($4). Pamakai barikut {{PLURAL:$3|akun|akun}}\ntarait awan suril:\n\n$2\n\n{{PLURAL:$3|katasunduk pahadangan ngini|kakatasunduk pahadangan ngini}} akan kadaluarsa dalam {{PLURAL:$5|asa hari|$5 hari}}.\nPian parlu babuat log wan mamilih katasunduk hanyar wayah ini jua. Amun urang lain nang maminta ngini, atawa amun Pian sudah paingatan awan katasunduk Pian, wan Pian kada handak maubahnya, Pian kawa kada mahuwal pasan ngini wan manyambung mamuruk katasunduk lawas Pian.",
        "passwordreset-emailelement": "Ngaran pamakai: \n$1\n\nKatasunduk pahadangan: \n$2",
        "passwordreset-emailsentemail": "Sabuting suril pangingat sudah takirim.",
-       "passwordreset-emailsent-capture": "Sabuting suril pangingat sudah dikirim, nangkaya ditampaiakan di bawah.",
-       "passwordreset-emailerror-capture": "Suril paugingat, nang ditampaikan di bawah, hudah dihasilakan, tagal gagal mangirimakannya ka pamakai: $1",
        "changeemail": "Ganti alamat suril",
        "changeemail-header": "Ganti akun alamat suril",
        "changeemail-no-info": "Pian musti babuat log hagan babuat ka tungkaran ngini langsung.",
        "undo-failure": "Babakan ini kada kawa diwalangi karana ada cakutan di tangah babakan-babakan.",
        "undo-norev": "Babakan kada kawa diwalangi karana ini kadada atawa tahapus.",
        "undo-summary": "←Mawalangakan ralatan $1 ulih [[Special:Contributions/$2|$2]] ([[User talk:$2|Pandir]])",
-       "cantcreateaccounttitle": "Akun kada kawa diulah",
        "cantcreateaccount-text": "Paulahan akun matan alamat IP ('''$1''') sudah diblukir ulih [[User:$3|$3]].\n\nAlasan nang dibari ulih $3 adalah ''$2''",
        "viewpagelogs": "Tiringi log tungkaran ini",
        "nohistory": "Kadada halam babakan gasan tungkaran ini.",
        "activeusers-intro": "Ngini adalah sabuah daptar papamuruk sabuah bantuk kagiatan dalam tauncit $1 {{PLURAL:$1|hari|hahari}}.",
        "activeusers-count": "$1 {{PLURAL:$1|babak|babakan}} dalam tauncit {{PLURAL:$3|hari|$3 hahari}}",
        "activeusers-from": "Manampaiakan papamuruk mulai matan:",
-       "activeusers-hidebots": "Sungkupakan bot",
-       "activeusers-hidesysops": "Sungkupakan pambakal",
        "activeusers-noresult": "Kadada papamuruk tatamu.",
        "listgrouprights": "Galambang hak pamuruk",
        "listgrouprights-summary": "Barikut adalah sabuah daptar matan galambang pamuruk nang ada di wiki ngini, lawan hak ungkai masing-masing.\nAda di [[{{MediaWiki:Listgrouprights-helppage}}|tambahan panjalasan]] pasal hak par urangan.",
        "htmlform-submit": "Kirim",
        "htmlform-reset": "Walangi paubahan",
        "htmlform-selectorother-other": "Lain-lain",
-       "sqlite-has-fts": "$1 awan sukungan panggagaian naskah-hibak",
-       "sqlite-no-fts": "$1 kada-awan sukungan panggagaian naskah-hibak",
        "logentry-delete-delete": "$1 mahapus tungkaran $3",
        "logentry-delete-restore": "$1 dibulikakan tungkaran $3",
        "logentry-delete-event": "$1 mangganti kakawaan dijanaki {{PLURAL:$5|sabuah log kajadian|$5 log kajadian}} pintangan $3: $4",
index 31ecf59..58781ab 100644 (file)
@@ -30,7 +30,8 @@
                        "Bodhisattwa",
                        "Matma Rex",
                        "আজিজ",
-                       "Kayser Ahmad"
+                       "Kayser Ahmad",
+                       "NahidSultan"
                ]
        },
        "tog-underline": "সংযোগগুলির নিচে দাগ দেখানো হোক:",
        "views": "দৃষ্টিকোণ",
        "toolbox": "সরঞ্জাম",
        "tool-link-userrights": "{{GENDER:$1|ব্যবহারকারী}} দল পরিবর্তন করুন",
+       "tool-link-userrights-readonly": "{{GENDER:$1|ব্যবহারকারী}} দল দেখুন",
        "tool-link-emailuser": "এই {{GENDER:$1|ব্যবহারকারী}}কে ইমেইল পাঠান",
        "userpage": "ব্যাবহারকারীর পাতা দেখুন",
        "projectpage": "মেটা-পাতা দেখুন",
        "passwordreset-emaildisabled": "এই উইকিতে ইমেইল অপশনটি বন্ধ করা হয়েছে।",
        "passwordreset-username": "ব্যবহারকারী নাম:",
        "passwordreset-domain": "ডোমেইন:",
-       "passwordreset-capture": "অনুসন্ধানের ফলাফলের ইমেইল দেখুন?",
-       "passwordreset-capture-help": "আপনি যদি এই পরীক্ষা বক্সে ক্লিক করেন, তবে অস্থায়ী পাসওয়ার্ডসহ একটি ইমেইল আপনাকে দেখানো হবে ও সেইসাথে ব্যবহারকারীকে তা পাঠানো হবে।",
        "passwordreset-email": "ইমেইল ঠিকানা:",
        "passwordreset-emailtitle": "{{SITENAME}} সাইটে ব্যবহারকারীর বিস্তারিত তথ্যাদি",
        "passwordreset-emailtext-ip": "কেউ একজন (সম্ভবত আপনি, $1 আইপি ঠিকানা থেকে) {{SITENAME}} ($4) সাইটের জন্য আপনার\nপাসওয়ার্ড বদলের জন্য অনুরোধ করেছে। নিচের ব্যবহারকারী {{PLURAL:$3|অ্যাকাউন্টটি|অ্যাকাউন্টগুলো}}\nএই ই-মেইল ঠিকানার সাথে সংযুক্ত:\n\n$2\n\n{{PLURAL:$3|এই অস্থায়ী পাসওয়ার্ডটি|এই অস্থায়ী পাসওয়ার্ডগুলো}} আগামী {{PLURAL:$5|এক দিন|$5 দিন}} পর মেয়াদোত্তীর্ণ হয়ে যাবে।\nআপনার অবশ্যই লগ-ইন করে একটি নতুন পাসওয়ার্ড পছন্দ করা উচিত। যদি অন্য কেউ এই অনুরোধ করে থাকে,\nঅথবা আপনি যদি পুরোনো পাসওয়ার্ড মনে করতে পারেন, এবং আপনার সেটি পরিবর্তন করার কোনো ইচ্ছা না থাকে, তবে\nআপনি এই বার্তাটি উপেক্ষা করতে পারে, এবং আপনার পুরোনো পাসওয়ার্ড ব্যবহার করা চালিয়ে যেতে পারেন।",
        "passwordreset-emailelement": "ব্যবহারকারী নাম: \n$1\n\nঅস্থায়ী পাসওয়ার্ড: \n$2",
        "passwordreset-emailsentemail": "যদি এই ই-মেইল ঠিকানা আপনার অ্যাকাউন্টের সাথে সংযুক্ত করা থাকে, তাহলে একটি পাসওয়ার্ড বদলের ইমেইল পাঠানো হবে।",
        "passwordreset-emailsentusername": "যদি এই ব্যবহারকারী নামের সাথে ই-মেইল ঠিকানা সংযুক্ত করা থাকে, তাহলে একটি পাসওয়ার্ড বদলের ইমেইল পাঠানো হবে।",
-       "passwordreset-emailsent-capture2": "পাসওয়ার্ড পুনঃধার্যকরণের {{PLURAL:$1|ইমেইল পাঠানো}} হয়েছে। {{PLURAL:$1|ব্যবহারকারী নাম ও পাসওয়ার্ড|ব্যবহারকারী নাম ও পাসওয়ার্ডের তালিকা}} এখানে দেখা যাবে।",
-       "passwordreset-emailerror-capture2": "{{GENDER:$2|ব্যবহারকারীকে}} ইমেইল পাঠানো যায়নি: $1 {{PLURAL:$3|ব্যবহারকারী নাম ও পাসওয়ার্ড|ব্যবহারকারী নাম ও পাসওয়ার্ডের তালিকা}} এখানে দেখা যাবে।",
        "passwordreset-nocaller": "একটি আহ্বানকারী প্রদান করা আবশ্যক",
        "passwordreset-nosuchcaller": "আহ্বানকারীর অস্তিত্ব নেই: $1",
        "passwordreset-ignored": "পাসওয়ার্ড পুনঃধার্যকরণ করা যায়নি। হয়তো কোন প্রদানকারী কনফিগার করা হয়েনি?",
-       "passwordreset-invalideamil": "ভুল ইমেইল ঠিকানা",
+       "passwordreset-invalidemail": "ভুল ইমেইল ঠিকানা",
        "passwordreset-nodata": "একটি ব্যবহারকারীর নাম বা একটি ইমেল ঠিকানা দুটির একটিও সরবরা দেয়া হয়নি",
        "changeemail": "ই-মেইল ঠিকানা পরিবর্তন বা বাতিল",
        "changeemail-header": "আপনার ইমেল ঠিকানা পরিবর্তন করতে এই ফরমটি পূরণ করুন। আপনি যদি আপনার একাউন্ট থেকে যে কোন ইমেল ঠিকানার এসোসিয়েশন অপসারণ করতে চান, তাহলে ফরমটি জমা দেওয়ার সময় নতুন ইমেইল ঠিকানা খালি রাখুন।",
        "diff-multi-sameuser": "(একই ব্যবহারকারী দ্বারা সম্পাদিত {{PLURAL:$1|একটি মধ্যবর্তী সংশোধন|$1টি মধ্যবর্তী সংশোধন}} দেখানো হচ্ছে না)",
        "diff-multi-otherusers": "({{PLURAL:$2|একজন|$2 জন}} ব্যবহারকারী দ্বারা সম্পাদিত {{PLURAL:$1|একটি|$1টি}} মধ্যবর্তী সংশোধন দেখানো হচ্ছে না)",
        "diff-multi-manyusers": "($2 জন {{PLURAL:$2|ব্যবহারাকারীর}} সম্পাদিত {{PLURAL:$1|একটি সাম্প্রতিক সংস্করণ|$1 টি সাম্প্রতিক সংস্করণ}} প্রদর্শিত হচ্ছে না)",
-       "difference-missing-revision": "$1 পার্থক্যের {{PLURAL:$2|একটি সংস্করণ|$2টি সংস্করণসমূহ}} খুজে পাওয়া যাচ্ছে না।\n\nসাধারণত মুছে ফেলা হয়েছে এমন পাতার মেয়াদ উত্তীর্ণ ইতিহাস পাতার লিংক ওপেন করার কারণে এটি হতে পারে। \n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} অপসারণ লগে] বিস্তারিত তথ্য জানা যাবে।",
+       "difference-missing-revision": "$1 পার্থক্যের {{PLURAL:$2|একটি সংস্করণ|$2টি সংস্করণ}} খুঁজে পাওয়া যাচ্ছে না।\n\nসাধারণত মুছে ফেলা হয়েছে এমন পাতার মেয়াদ উত্তীর্ণ ইতিহাস পাতার লিংক খোলার কারণে এটি হতে পারে। \n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} অপসারণ লগে] বিস্তারিত তথ্য জানা যাবে।",
        "searchresults": "অনুসন্ধানের ফলাফল",
        "searchresults-title": "\"$1\" অনুসন্ধানের ফলাফল",
        "titlematches": "নিবন্ধের শিরোনাম মিলেছে",
        "search-external": "বহিঃস্থ অনুসন্ধান",
        "searchdisabled": "{{SITENAME}} অনুসন্ধান এখন নিষ্ক্রিয় আছে। আপনি গুগলের মাধ্যমে অনুসন্ধান চালাতে পারেন। লক্ষ্য করুন যে {{SITENAME}}-এর বিষয়বস্তুর উপর গুগলের ইন্ডেক্সগুলি হালনাগাদ না-ও করা থাকতে পারে।",
        "search-error": "অনুসন্ধানের সময় একটি ত্রুটি হয়েছে: $1",
+       "search-warning": "অনুসন্ধানের সময় একটি সতর্কীকরণ দেখিয়েছে: $1",
        "preferences": "আমার পছন্দ",
        "mypreferences": "পছন্দসমূহ",
        "prefs-edits": "সম্পাদনা সংখ্যা:",
        "prefs-help-recentchangescount": "এতে সাম্প্রতিক পরিবর্তনসমূহ, পাতার ইতিহাস এবং লগ অন্তর্ভুক্ত।",
        "prefs-help-watchlist-token2": "এটি আপনার নজরতালিকার ওয়েব ফিডের গোপন চাবি। যে কেউ যিনি এটা জানেন তিনি আপনার নজরতালিকা পড়তে সক্ষম হবেন, তাই এটি প্রকাশ করবেন না। [[Special:ResetTokens|আপনার এটি পুনরায় সেট করার প্রয়োজন হলে এখানে ক্লিক করুন]]।",
        "savedprefs": "আপনার পছন্দগুলো সংরক্ষণ করা হয়েছে।",
-       "savedrights": "{{GENDER:$1|$1}}-à¦\8fর à¦¬à§\8dযবহারà¦\95ারà§\80 à¦\85ধিà¦\95ার সংরক্ষিত হয়েছে।",
+       "savedrights": "{{GENDER:$1|$1}}-à¦\8fর à¦¬à§\8dযবহারà¦\95ারà§\80 à¦¦à¦² সংরক্ষিত হয়েছে।",
        "timezonelegend": "সময়স্থান:",
        "localtime": "স্থানীয় সময়:",
        "timezoneuseserverdefault": "উইকির পূর্বনির্ধারিত সময় ব্যবহার করো ($1)",
        "prefswarning-warning": "আপানি পছন্দসমূহ পাতায় পাতায় পরিবর্তন করেছেন যেগুলো সংরক্ষণ করা হয়নি। আপনি যদি এই পাতাটি ছেড়ে যাওয়ার আগে \"$1\" ক্লিক না করেন তবে পছন্দসমূহ হালনাগাদ হবে না।",
        "prefs-tabs-navigation-hint": "সাহায্য: আপনি ডান এবং বাম অ্যারো বাটন ব্যবহার করে বিভিন্ন ট্যাবগুলোতে যেতে পারবেন।",
        "userrights": "ব্যবহারকারী অধিকার ব্যবস্থাপনা",
-       "userrights-lookup-user": "বà§\8dযবহারà¦\95ারà§\80 à¦¦à¦² à¦¬à§\8dযবসà§\8dথাপনা করুন",
+       "userrights-lookup-user": "à¦\8fà¦\95à¦\9cন à¦¬à§\8dযবহারà¦\95ারà§\80 à¦¨à¦¿à¦°à§\8dবাà¦\9aন করুন",
        "userrights-user-editname": "ব্যবহারকারীর নাম লিখুন:",
-       "editusergroup": "{{GENDER:$1|ব্যবহারকারীর}} দল সম্পাদনা করো",
+       "editusergroup": "ব্যবহারকারী দল লোড করুন",
        "editinguser": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|ব্যবহারকারীর}} জন্য ব্যবহারকারী অধিকার পরিবর্তন করছেন",
        "userrights-editusergroup": "ব্যবহারকারীর দল সম্পাদনা করো",
        "saveusergroups": "{{GENDER:$1|ব্যবহারকারীর}} দল সংরক্ষণ করো",
        "userrights-reason": "কারণ (বাংলায় লিখুন):",
        "userrights-no-interwiki": "আপনার অন্য উইকিতে ব্যবহারকারী অধিকার সম্পাদনা করার অনুমতি নেই।",
        "userrights-nodatabase": "$1 ডাটাবেজটির হয় কোন অস্তিত্ব নেই অথবা এটি স্থানীয় ডাটাবেজ নয়।",
-       "userrights-nologin": "ব্যবহারকারী অধিকার প্রযুক্ত করতে হলে আপনাকে কোন প্রশাসকের অ্যাকাউন্টে [[Special:UserLogin|প্রবেশ]] করতে হবে।",
-       "userrights-notallowed": "আপনার, ব্যবহারকারী অধিকার যুক্ত বা অপসারণ করার অনুমতি নেই।",
        "userrights-changeable-col": "দল যা আপনি পরিবর্তন করতে পারেন",
        "userrights-unchangeable-col": "দল যা আপনি পরিবর্তন করতে পারবেন না",
        "userrights-conflict": "ব্যবহারকারী অধিকার দ্বন্দ্ব! অনুগ্রহ করে নিশ্চিত হোন এবং পুনরায় চেষ্টা করুন।",
-       "userrights-removed-self": "আপনি আপনার নিজের অধিকার পরিবর্তন করেছেন। এর ফলে এখন থেকে আপনি আর এই পাতায় প্রবেশ করতে পারবেন না।",
        "group": "দল:",
        "group-user": "ব্যবহারকারীগণ",
        "group-autoconfirmed": "স্বয়ংনিশ্চিতকৃত ব্যবহারকারীগণ",
        "right-createpage": "পাতা তৈরি করো (আলাপের পাতা নয়)",
        "right-createtalk": "আলোচনা পাতা তৈরি করুন",
        "right-createaccount": "নতুন ব্যবহারকারীর অ্যাকাউন্ট তৈরি করুন",
+       "right-autocreateaccount": "স্বয়ংক্রিয়ভাবে একটি বাহ্যিক ব্যবহারকারী অ্যাকাউন্ট দিয়ে প্রবেশ করুন",
        "right-minoredit": "অনুল্লেখ্য সম্পাদনা হিসেবে চিহ্নিত",
        "right-move": "পাতা সরান",
        "right-move-subpages": "পাতাগুলোকে তার উপপাতাসহ সরিয়ে নিন",
        "right-siteadmin": "ডাটাবেজ বন্ধ এবং খুলুন",
        "right-override-export-depth": "৫ম স্তর পর্যন্ত সংযুক্তিসহ একটি পাতা রপ্তানী করুন",
        "right-sendemail": "অন্য ব্যবহারকারীকে ইমেইল পাঠান",
-       "right-passwordreset": "পাসওয়ার্ড পুনঃস্থাপনের ইমেইল দেখুন",
        "right-managechangetags": "[[Special:Tags|ট্যাগ]] তৈরি ও সক্রিয়/নিষ্ক্রিয় করুন",
        "right-applychangetags": "সম্পাদনার সাথে [[Special:Tags|ট্যাগ]] যুক্ত করুন",
        "right-changetags": "নির্দিষ্ট সংস্করণ এবং দীর্ঘ সম্পাদনাগুলোতে [[Special:Tags|ট্যাগ]] সংযোজন ও অপসারণ করুন",
        "right-deletechangetags": "ডাটাবেজ থেকে [[Special:Tags|ট্যাগ]] অপসারণ করা",
+       "grant-generic": "\"$1\" অধিকার স্তর",
        "grant-group-email": "ইমেইল পাঠান",
        "grant-group-customization": "অনুকূলকরণ ও পছন্দ",
        "grant-group-administration": "প্রশাসনিক কাজ সঞ্চালন করুন",
        "grant-editmywatchlist": "আপনার নজরতালিকা সম্পাদনা করুন",
        "grant-editpage": "বিদ্যমান পাতা সম্পাদনা করুন",
        "grant-editprotected": "সংরক্ষিত পাতা সম্পাদনা করুন",
+       "grant-highvolume": "উচ্চ-মাত্রার সম্পাদনা",
+       "grant-oversight": "ব্যবহারকারী লুকান ও ইতিহাস অপসারণ",
        "grant-privateinfo": "ব্যক্তিগত তথ্যে প্রবেশাধিকার",
+       "grant-protect": "পাতাসমূহ সুরক্ষা ও অরক্ষিত করুন",
        "grant-sendemail": "অন্য ব্যবহারকারীকে ইমেইল পাঠান",
        "grant-uploadeditmovefile": "ফাইল আপলোড, প্রতিস্থাপন এবং স্থানান্তর",
        "grant-uploadfile": "নতুন ফাইল আপলোড করুন",
        "grant-basic": "মৌলিক অধিকার",
        "grant-viewdeleted": "অপসারিত ফাইল ও পাতাগুলি দেখুন",
        "grant-viewmywatchlist": "আপনার নজরতালিকা দেখুন",
+       "grant-viewrestrictedlogs": "লগের সীমাবদ্ধ ভুক্তিগুলি দেখুন",
        "newuserlogpage": "ব্যবহারকারী সৃষ্টির লগ",
        "newuserlogpagetext": "এটি নতুন ব্যবহারকারী সৃষ্টির লগ",
        "rightslog": "ব্যবহারকারীর অধিকার লগ",
        "backend-fail-store": "\"$2\"-এ \"$1\" ফাইলটি সংরক্ষন করা সম্ভব নয়।",
        "backend-fail-copy": "\"$1\" ফাইলটি \"$2\"-তে অনুলিপি করা সম্ভব নয়।",
        "backend-fail-move": "\"$2\"-এ \"$1\" ফাইলটি স্থানান্তর করা সম্ভব নয়।",
-       "backend-fail-opentemp": "à¦\85সà§\8dথায়à§\80 à¦«à¦¾à¦\87লà¦\9fি à¦\93পà§\87ন à¦\95রা à¦¯à¦¾à¦\9aà§\8dà¦\9bে না।",
+       "backend-fail-opentemp": "à¦\85সà§\8dথায়à§\80 à¦«à¦¾à¦\87লà¦\9fি à¦\96à§\8bলা à¦¯à¦¾à¦¬ে না।",
        "backend-fail-writetemp": "অস্থায়ী ফাইলটিতে লেখা যাচ্ছে না।",
        "backend-fail-closetemp": "অস্থায়ী ফাইলটি বন্ধ করা যাচ্ছে না।",
-       "backend-fail-read": "$1 ফাইলটি ওপেন করা যাচ্ছে না।",
+       "backend-fail-read": "\"$1\" ফাইলটি পড়া যাচ্ছে না।",
        "backend-fail-create": "$1 ফাইলটি তৈরী করা যাচ্ছে না।",
        "backend-fail-maxsize": "\"$1\" ফাইলে লেখা যাচ্ছে না কারণ এটি {{PLURAL:$2|এক বাইট|$2 বাইট}} থেকে বড়।",
        "backend-fail-readonly": "\"$1\" স্টোরেজ ব্যাকএন্ড থেকে বর্তমানে শুধু-পঠনে রয়েছে। প্রদত্ত কারণ: <em>$2</em>",
        "newpages": "নতুন পাতাসমূহ",
        "newpages-submit": "দেখাও",
        "newpages-username": "ব্যবহারকারী নাম:",
-       "ancientpages": "পà§\81রানà§\8b à¦¨à¦¿à¦¬à¦¨à§\8dধ",
+       "ancientpages": "পà§\81রানà§\8b à¦ªà¦¾à¦¤à¦¾",
        "move": "সরিয়ে ফেলুন",
        "movethispage": "সরিয়ে ফেলুন",
        "unusedimagestext": "নিচের ফাইলগুলি কোনো পাতার অন্তর্ভুক্ত নয়।\nঅনুগ্রহ করে খেয়াল রাখবেন যে অন্য ওয়েবসাইট থেকে কোন ফাইলে সরাসরি URL-এর মাধ্যমে সংযোগ দেওয়া থাকতে পারে, এবং সেজন্য সক্রিয়ভাবে ব্যবহৃত হওয়া সত্ত্বেও ফাইলটি এখানে তালিকাভুক্ত হতে পারে।",
        "apisandbox-dynamic-parameters-add-label": "প্যারামিটার যোগ করুন:",
        "apisandbox-dynamic-parameters-add-placeholder": "প্যারামিটারের নাম",
        "apisandbox-dynamic-error-exists": "\"$1\" নামক একটি প্যারামিটার আগে থেকেই বিদ্যমান।",
+       "apisandbox-deprecated-parameters": "অননুমোদিত প্যারামিটার",
+       "apisandbox-fetch-token": "স্বয়ংক্রিয়ভাবে টোকেন পূরণ করুন",
+       "apisandbox-submit-invalid-fields-title": "কিছু ঘর অবৈধ",
+       "apisandbox-submit-invalid-fields-message": "দয়া করে চিহ্নিত ঘরগুলো সংশোধন করে, পুনরায় চেষ্ঠা করুন।",
        "apisandbox-results": "ফলাফল",
        "apisandbox-sending-request": "API অনুরোধ পাঠানো হচ্ছে...",
        "apisandbox-loading-results": "API ফলাফল গ্রহণ করা হচ্ছে...",
        "apisandbox-request-url-label": "অনুরোধের URL:",
        "apisandbox-request-time": "অনুরোধের সময়: {{PLURAL:$1|$1 মি.সে.}}",
+       "apisandbox-results-fixtoken": "টোকেন সংশোধন ও পুনরায় জমা",
+       "apisandbox-alert-page": "এই পাতার ঘরগুলো বৈধ নয়।",
+       "apisandbox-alert-field": "এই ক্ষেত্রের মান বৈধ নয়।",
        "apisandbox-continue": "অব্যাহত",
        "apisandbox-continue-clear": "পরিস্কার",
+       "apisandbox-param-limit": "সর্বোচ্চ সীমা ব্যবহার করতে <kbd>max</kbd> লিখুন।",
+       "apisandbox-multivalue-all-namespaces": "$1 (সব নামস্থান)",
+       "apisandbox-multivalue-all-values": "$1 (সব মান)",
        "booksources": "বইয়ের উৎস",
        "booksources-search-legend": "বইয়ের উৎসের জন্য অনুসন্ধান করা হোক",
        "booksources-isbn": "আইএসবিএন:",
        "booksources-text": "নতুন ও পুরাতন ব্যবহৃত বই বিক্রি করে, এমন কতগুলি সাইটের সংযোগের তালিকা নিচে দেওয়া হল, যে সাইটগুলিতে আপনার অনুসন্ধানকৃত বইগুলির উপর আরও তথ্য থাকতে পারে:",
        "booksources-invalid-isbn": "উল্লেখিত ISBN সঠিক নয়; অনুগ্রহ করে মূল উৎস থেকে আবার পরীক্ষা করুন।",
        "magiclink-tracking-rfc": "আরএফসি জাদু সংযোগ ব্যবহার করা পাতা",
+       "magiclink-tracking-rfc-desc": "এই পাতাটি RFC যাদু সংযোগ ব্যবহার করে। কিভাবে মাইগ্রেট করবেন জানতে [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] দেখুন।",
        "magiclink-tracking-pmid": "পিএমআইডি জাদু সংযোগ ব্যবহার করা পাতা",
+       "magiclink-tracking-pmid-desc": "এই পাতাটি পিএমআইডি যাদু সংযোগ ব্যবহার করে। কিভাবে মাইগ্রেট করবেন জানতে [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] দেখুন।",
        "magiclink-tracking-isbn": "আইএসবিএন জাদু সংযোগ ব্যবহার করা পাতা",
+       "magiclink-tracking-isbn-desc": "এই পাতাটি আইএসবিএন যাদু সংযোগ ব্যবহার করে। কিভাবে মাইগ্রেট করবেন জানতে [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] দেখুন।",
        "specialloguserlabel": "সম্পাদক:",
        "speciallogtitlelabel": "লক্ষ্য (শিরোনাম বা {{ns:user}}:ব্যবহারকারীর জন্য ব্যবহারকারী নাম):",
        "log": "লগগুলি",
        "allpagesbadtitle": "প্রদত্ত পাতার শিরোনামটি অবৈধ ছিল অথবা এটিতে কোন আন্তঃভাষা বা আন্তঃউইকি উপসর্গ ছিল। এটিতে এক বা একাধিক ক্যারেক্টার থাকতে পারে যা শিরোনামে ব্যবহার করা সম্ভব নয়।",
        "allpages-bad-ns": "{{SITENAME}}-এ \"$1\" নামের কোন নামস্থান নেই।",
        "allpages-hide-redirects": "পুনর্নির্দেশনাগুলো লুকাও",
-       "cachedspecial-viewing-cached-ttl": "à¦\86পনার à¦\93পà§\87ন à¦\95রা à¦ªà¦¾à¦¤à¦¾à¦\9fি à¦\95à§\8dযাশ à¦¥à§\87à¦\95à§\87 à¦ªà§\8dরদরà§\8dশিত à¦¹à¦\9aà§\8dà¦\9bà§\87, à¦\8fà¦\9fি $1 দিনের পুরানো হতে পারে।",
-       "cachedspecial-viewing-cached-ts": "à¦\86পনার à¦\93পà§\87ন à¦\95রা à¦ªà¦¾à¦¤à¦¾à¦\9fি à¦\95à§\8dযাশ à¦¥à§\87à¦\95à§\87 à¦ªà§\8dরদরà§\8dশিত à¦¹à¦\9aà§\8dà¦\9bà§\87, à¦\8fà¦\9fি à¦¸à¦®à§\8dপà§\82রà§\8dণ à¦¨à¦¤à§\81ন হতে পারে।",
+       "cachedspecial-viewing-cached-ttl": "à¦\86পনি à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠায় à¦\8fà¦\95à¦\9fি à¦\95à§\8dযাশà§\87 à¦¸à¦\82সà§\8dà¦\95রণ à¦¦à§\87à¦\96à¦\9bà§\87ন, à¦¯à¦¾ $1 দিনের পুরানো হতে পারে।",
+       "cachedspecial-viewing-cached-ts": "à¦\86পনি à¦\8fà¦\87 à¦ªà§\83ষà§\8dঠায় à¦\8fà¦\95à¦\9fি à¦\95à§\8dযাশà§\87 à¦¸à¦\82সà§\8dà¦\95রণ à¦¦à§\87à¦\96à¦\9bà§\87ন, à¦¯à¦¾ à¦¸à¦®à§\8dপà§\82রà§\8dণরà§\82পà§\87 à¦¹à¦¾à¦²à¦¨à¦¾à¦\97াদà¦\95à§\83ত à¦¨à¦¾à¦\93 হতে পারে।",
        "cachedspecial-refresh-now": "সাম্প্রতিকগুলো প্রদর্শন করো।",
        "categories": "বিষয়শ্রেণীসমূহ",
        "categories-submit": "দেখাও",
        "activeusers-intro": "এটি ব্যবহারকারী তালিকা যাদের $1 {{PLURAL:$1|দিনে|দিনে}} যেকোন কর্মকান্ড রয়েছে।",
        "activeusers-count": "গত {{PLURAL:$3|কালে|$3 দিনে}} সর্বমোট {{PLURAL:$1|কর্মের}} সংখ্যা $1টি",
        "activeusers-from": "ব্যবহারকারী দেখাও যাদের নাম এই অক্ষর দিয়ে শুরু:",
+       "activeusers-groups": "এই দলভুক্ত ব্যবহারকারী দেখান:",
        "activeusers-noresult": "কোনো ব্যবহারকারী পাওয়া যায়নি।",
        "activeusers-submit": "সক্রিয় ব্যবহারকারী প্রদর্শন করুন",
        "listgrouprights": "দলগত ব্যবহারকারী অধিকার",
        "emailuserfooter": "এই ইমেইলটি {{SITENAME}} সাইটের \"{{int:emailuser}}\" সুবিধা ব্যবহার করে $1-এর পক্ষ থেকে {{GENDER:$2|$2}}-এর নিকট {{GENDER:$1|পাঠানো হয়েছে}}।",
        "usermessage-summary": "বাদবাকি সিস্টেম বার্তা",
        "usermessage-editor": "সিস্টেম ম্যাসেঞ্জার",
+       "usermessage-template": "MediaWiki:ব্যবহারকারী বার্তা",
        "watchlist": "নজর তালিকা",
        "mywatchlist": "নজর তালিকা",
        "watchlistfor2": "$1 ($2)-এর জন্য",
        "pageinfo-header-restrictions": "পাতা সুরক্ষা",
        "pageinfo-header-properties": "পাতা বৈশিষ্টসমূহ",
        "pageinfo-display-title": "শিরনাম প্রদর্শন",
-       "pageinfo-default-sort": "ডিফলà§\8dà¦\9f à¦¸à¦°à§\8dà¦\9f à¦\95ি",
+       "pageinfo-default-sort": "পà§\82রà§\8dবনিরà§\8dধারিত à¦¬à¦¾à¦\9bাà¦\87য়à§\87র à¦\9aাবি",
        "pageinfo-length": "পাতার দৈর্ঘ্য (বাইটে)",
        "pageinfo-article-id": "পাতার আইডি",
        "pageinfo-language": "পাতার তথ্যের ভাষা",
        "patrol-log-header": "এটি যাচাইকৃত রিভিশনের তালিকা।",
        "log-show-hide-patrol": "পরীক্ষণ লগ $1",
        "log-show-hide-tag": "ট্যাগ লগ $1",
+       "confirm-markpatrolled-button": "ঠিক আছে",
+       "confirm-markpatrolled-top": "$2-এর $3 নং সংস্করণটি পরীক্ষিত হিসেবে চিহ্নিত করবেন?",
        "deletedrevision": "মুছে ফেলা পুরাতন সংশোধন $1",
        "filedeleteerror-short": "ফাইল মুছতে গিয়ে ত্রুটি: $1",
        "filedeleteerror-long": "ফাইলটি মুছার সময় ত্রুটি দেখা দিয়েছে:\n\n$1",
        "table_pager_prev": "পূর্ববর্তী পাতা",
        "table_pager_first": "প্রথম পাতা",
        "table_pager_last": "শেষ পাতা",
-       "table_pager_limit": "প্রতি পাতায় $1 গুলো বিষয়বস্তু দেখাও",
+       "table_pager_limit": "প্রতি পাতায় $1টি উপাদান দেখাও",
        "table_pager_limit_label": "প্রতি পাতায় আইটেম সংখ্যা:",
        "table_pager_limit_submit": "চলো",
        "table_pager_empty": "ফলাফল শূন্য",
        "hijri-calendar-m11": "জ্বিলকদ",
        "hijri-calendar-m12": "জ্বিলহজ্জ",
        "hebrew-calendar-m1": "তিশরেই",
+       "hebrew-calendar-m2": "হেশভান",
+       "hebrew-calendar-m3": "কিসলেভ",
+       "hebrew-calendar-m4": "তেভেত",
+       "hebrew-calendar-m5": "শেভাত",
+       "hebrew-calendar-m6": "আদার",
+       "hebrew-calendar-m6a": "আদার ১",
+       "hebrew-calendar-m6b": "আদার ২",
+       "hebrew-calendar-m7": "নিসান",
+       "hebrew-calendar-m8": "ইয়্যার",
+       "hebrew-calendar-m9": "সিভান",
        "hebrew-calendar-m10": "তামুয",
        "hebrew-calendar-m11": "আভ",
        "hebrew-calendar-m12": "এলুল",
+       "hebrew-calendar-m1-gen": "তিশরি",
+       "hebrew-calendar-m2-gen": "হেশভান",
+       "hebrew-calendar-m3-gen": "কিসলেভ",
+       "hebrew-calendar-m4-gen": "তেভেত",
+       "hebrew-calendar-m5-gen": "শেভাত",
+       "hebrew-calendar-m6-gen": "আদার",
+       "hebrew-calendar-m6a-gen": "আদার ১",
+       "hebrew-calendar-m6b-gen": "আদার ২",
        "hebrew-calendar-m7-gen": "নিসান",
+       "hebrew-calendar-m8-gen": "ইয়্যার",
+       "hebrew-calendar-m9-gen": "সিভান",
+       "hebrew-calendar-m10-gen": "তামুয",
+       "hebrew-calendar-m11-gen": "আভ",
+       "hebrew-calendar-m12-gen": "এলুল",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|আলাপ]])",
        "timezone-utc": "ইউটিসি",
        "timezone-local": "স্থানীয়",
        "htmlform-user-not-exists": "<strong>$1</strong>-এর অস্তিত্ব নেই।",
        "htmlform-user-not-valid": "<strong>$1</strong> একটি বৈধ ব্যবহারকারীর নাম নয়।",
        "logentry-delete-delete": "$1 কর্তৃক $3 পাতাটি অপসারিত হয়েছে",
+       "logentry-delete-delete_redir": "$1 পুনর্লিখনের দ্বারা $3 পুনর্নির্দেশ {{GENDER:$2|অপসারণ করেছেন}}",
        "logentry-delete-restore": "$1 কর্তৃক $3 পাতাটি {{GENDER:$2|ফিরিয়ে আনা}} হয়েছে",
        "logentry-delete-event": "$1 {{PLURAL:$5|একটি লগ ইভেন্টের|$5 লগ ইভেন্টসমূহের}} দৃশ্যমানতা {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
        "logentry-delete-revision": "$1 {{PLURAL:$5|একটি সংস্করণের|$5টি সংস্করণের}} দৃশ্যমানতা {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
        "mw-widgets-dateinput-no-date": "কোন তারিখ নির্বাচন করা হয়নি",
        "mw-widgets-dateinput-placeholder-day": "বববব-মম-দদ",
        "mw-widgets-dateinput-placeholder-month": "বববব-মম",
+       "mw-widgets-mediasearch-input-placeholder": "মিডিয়ার জন্য অনুসন্ধান",
+       "mw-widgets-mediasearch-noresults": "কোনো ফলাফল পাওয়া যায়নি।",
        "mw-widgets-titleinput-description-new-page": "পাতা এখনো বিদ্যমান নয়",
        "mw-widgets-titleinput-description-redirect": "$1-এ পুনঃনির্দেশিত",
+       "mw-widgets-categoryselector-add-category-placeholder": "একটি বিষয়শ্রেণী যোগ করুন...",
        "sessionmanager-tie": "একাধিক অনুরোধের প্রমাণীকরণের ধরন একত্রিত করা যাবে না: $1।",
        "sessionprovider-generic": "$1টি সেশন",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "কুকি-ভিত্তিক সেশন",
        "authmanager-authn-no-primary": "সরবরাহকৃত পরিচয়পত্রের অনুমোদন যাচাই করা যায়নি।",
        "authmanager-authn-autocreate-failed": "একটি স্থানীয় অ্যাকাউন্টের স্বয়ংক্রিয়-সৃষ্টি ব্যর্থ হয়েছে: $1",
        "authmanager-create-disabled": "অ্যাকাউন্ট সৃষ্টিকরণ নিষ্ক্রিয় করা হয়েছে।",
-       "authmanager-create-from-login": "à¦\86পনার à¦\8fà¦\95াà¦\89নà§\8dà¦\9f à¦¤à§\88রি à¦\95রতà§\87, à¦¨à§\80à¦\9aà§\87র à¦\95à§\8dষà§\87তà§\8dরà¦\97à§\81লি à¦ªà§\82রণ à¦\95রà§\81ন।",
+       "authmanager-create-from-login": "আপনার একাউন্ট তৈরি করতে, ক্ষেত্রগুলি পূরণ করুন।",
        "authmanager-authplugin-setpass-failed-title": "পাসওয়ার্ড পরিবর্তন ব্যর্থ হয়েছে",
        "authmanager-authplugin-setpass-bad-domain": "অবৈধ ডোমেইন।",
        "authmanager-autocreate-noperm": "স্বয়ংক্রিয় অ্যাকাউন্ট সৃষ্টি মঞ্জুরিপ্রাপ্ত নয়।",
        "usercssispublic": "অনুগ্রহ করে লক্ষ্য করুন: সিএসএসের উপপাতাগুলিতে গোপনীয় তথ্য থাকা উচিত নয় যেহেতু অন্যান্য ব্যবহারকারীও এগুলি দেখতে পান।",
        "restrictionsfield-badip": "আইপি ঠিকানা অথবা পরিসীমা অবৈধ: $1",
        "restrictionsfield-label": "অনুমোদিত আইপি পরিসীমা:",
-       "restrictionsfield-help": "লাইন প্রতি একটি আইপি ঠিকানা বা CIDR পরিসীমা। সবকিছু সক্রিয় করতে<br><code>0.0.0.0/0</code><br><code>::/0</code><br>ব্যবহার করুন",
-       "edit-error-short": "ত্রুটি: $1",
-       "edit-error-long": "ত্রুটিসমূহ:\n\n$1"
+       "restrictionsfield-help": "লাইন প্রতি একটি আইপি ঠিকানা বা CIDR পরিসীমা। সবকিছু সক্রিয় করতে<br><code>0.0.0.0/0</code><br><code>::/0</code><br>ব্যবহার করুন"
 }
index 5553398..085bd1f 100644 (file)
        "yourpassword": "ལམ་ཡིག",
        "userlogin-yourpassword-ph": "ཁྱེད་ཀྱི་གསང་བའི་ཨང་གྲངས་བླུག་རོགས།",
        "yourpasswordagain": "གསང་བའི་ཨང་ངོས་འཛིན་གནང་རོགས།",
-       "remembermypassword": "ངའི་ལམ་ཡིག་འདིར་(མང་མཐའ་ཉིན $1 {{PLURAL:$1}}) དྲན་པར་བྱས།",
        "yourdomainname": "ཁྱེད་ཀྱི་ཁྱབ་ཁུལ།",
        "login": "ནང་འཛུལ།",
        "nav-login-createaccount": "ནང་འཛུལ། / ཐོ་འགོད།",
index 152a1ec..0bdaf65 100644 (file)
        "yourname": "আতাকুরার নাংহান (Username)",
        "yourpassword": "খন্তাচাবিগ (password)",
        "yourpasswordagain": "খন্তাচাবিগ (password) আরাকমু ইকর",
-       "remembermypassword": "আহার গজে সেশনর কা খন্তাচাবি মনে থ(সর্বোচ্চ $1 {{PLURAL:$1|দিনর|দিনর}} কা)",
        "yourdomainname": "তর ডোমেইনগ",
        "externaldberror": "ডাটেবেজর মা বেসেপ আহান ইসে নাইলে তরতা বারেদের একাউন্ট বদালানির য়্যাথাং নেই।",
        "login": "হমানি",
        "post-expand-template-argument-warning": "' ' ' সিঙুইস: ' ' ' এরে পাতাহাত তিলসে টেম্পলেট এহার যুক্তি আহান লাম হেলসে। অহানে যুক্তি অহান বেলানি অইল।",
        "post-expand-template-argument-category": "পতাহাত পুসিসি মডেলর জর থা পরসেগা",
        "parser-template-loop-warning": "মডেলর তরিগ দেখরাং: [[$1]]",
-       "cantcreateaccounttitle": "একাউন্টহান হঙকরানি নাইব",
        "viewpagelogs": "পাতাহানর লগ চা",
        "nohistory": "পাতা এহান পতানির কোন ইতিহাস নেই।",
        "currentrev": "হাদিএহানর পতানি",
index e18bf6c..407a2a7 100644 (file)
        "history_short": "گزارش تاریخی",
        "printableversion": "نوسقئ پئلا ڤابیدٙئنی",
        "permalink": "لینک دایمی",
+       "print": "چاپ گرهڌن",
        "view": "ديئن",
        "view-foreign": "مئن $1 نه بوینین",
        "edit": "اصلاح",
+       "create": "راس كردن",
+       "create-local": "یأ توزی ڤولات نشيني إزافإ کونين",
        "editthispage": "اصلاح ای صفحه",
        "delete": "حذف",
        "protect": "حفاظت وحمایت",
        "otherlanguages": "درزبانهای دیگر",
        "redirectedfrom": "(تصحیح مجدداز$1)",
        "redirectpagesub": "صفحه تصحیح وهدایت مجدد",
+       "redirectto": "ڤاگردۈنی سی:",
        "lastmodifiedat": "این صفحه اخیرا تغییر واصلاح شددر $1, در $2.",
        "viewcount": "این صفحه قابل دسترسی شده است {{PLURAL:$1|once|$1 times}}.",
        "protectedpage": "صفحه حمایت شده",
        "toc": "محتواها",
        "showtoc": "نمایش",
        "hidetoc": "قایم",
+       "confirmable-yes": "هرإ",
+       "confirmable-no": "نأ",
        "thisisdeleted": "دیدن یا اعاده $1?",
        "viewdeleted": "دیدن$1?",
        "restorelink": "{{PLURAL:$1|پاک کردن یه اصلاح|$1 پاک کردن اصلاحات}}",
        "nstab-template": "قالب یا الگو",
        "nstab-category": "دسته",
        "mainpage-nstab": "سأرآسوٙنە",
+       "error": "خطا",
        "badtitle": "عنوان بد",
        "badtitletext": "عنوان درخواستی نامعتبر، خالی، یا عنوانی بین زبانی یا بین‌ویکی‌ای با پیوند نادرسته\nو ممکنه دارای یک یا چند کاراکتر بوه که در عنوان مربوط نوا زش استفاده کنین",
        "viewsource": "مشاهده منبع",
        "login": "اویدن به سیستم",
        "nav-login-createaccount": "اویدن به سیستم",
        "userlogin": "اویدن به سیستم / درست کردن حساب کاربری",
+       "userloginnocreate": "ڤامین اوڤیڌن",
        "logout": "رهدن زه سیستم",
        "userlogout": "رهدن زه سیستم",
+       "userlogin-noaccount": "یأ هساڤ کارياري دارين؟",
+       "userlogin-joinproject": "أندوم ديارگأ {{SITENAME}} ڤابۈین",
        "nologin": "آیا ایسا حساب کاربری ندارین? '''$1'''.",
        "nologinlink": "درست کردن یه حساب کاربری",
        "createaccount": "درست کردن حساب کاربری",
        "eauthentsent": "یه ایمیل سی تایید آدرس ایمیل به آدرس مورنظر ارسال وابید. قبل زه یو که ایمیل دیگری قابل ارسال به این آدرس بوه، وا دستورهایی که در آن ایمیل اویده را جهت تأیید ای مساله که ای آدرس مال ایسانه اجرا کنین.",
        "loginlanguagelabel": "زۈن:$1",
        "pt-login": "ڤامین اوڤیڌن",
+       "pt-login-button": "ڤامین اوڤیڌن",
        "pt-createaccount": "راسد کردن هساڤ کارياري",
        "pt-userlogout": "ز سامۈنإ درأڤوڌن",
        "retypenew": "تایپ دوباره رمز:",
+       "passwordreset": "ز نۉ داڌن رازينإ گوأرتن",
        "bold_sample": "متن گپ نما",
        "bold_tip": "متن گپ نما",
        "italic_sample": "متن شکسته",
        "blockedtext": " \"'''دسترسی نام کاربری یا نشانی اینترنتی ایسا بسته وابیده.'''\nای کار توسط $1 انجام شده‌است.\nدلیلی که گده اینه: $2''\n* آغاز قطع دسترسی: $8\n* زمان اتمام ای قطع دسترسی: $6\n* کاربری که قطع دسترسی‌اش در نظر بیده: $7\nایساترین با $1 یا یکی از [[{{MediaWiki:Grouppage-sysop}}|مدیران]] تماس بگیرین و در ای باره صحبت کنین.\nتوجه کنین که ایسا نترین زه امکان «ارسال پست الکترونیکی به ای کاربر» استفاده کنین مگر این که نشانی پست الکترونیکی معتبری در [[Special:Preferences|اولویتهای کاربری]]خود ثبت کرده بوین.\nنشانی IP ایسا $3 و شماره قطع دسترسی ایسا $5 است. لطفاً ای شماره‌ها را در همه کاوشهاتون ذکر کنین.\nایسا ترین با $1 یا یکی دیه زه [[{{MediaWiki:Grouppage-sysop}}|مدیران]] تماس بگیرین، تا در باره ای قطع دسترسی صحبت کنین.\nدقت کنین که سی ارسال پست الکترونیکی در ویکی، وا پست الکترونیکی خود را زه طریق صفحه[[Special:Preferences|تنظیمات]] فعال کرده بوین، و نیز، وا امکان استفاده زه ای ویژگی سی ایساقطع نبوه.\nنشانی اینترنتی الان ایسا $3 است و شماره قطع دسترسی $5 است.\nلطفاً ای شماره را در هر درخواستی که در ای مورد مطرح اکنین ذکر کنین",
        "loginreqlink": "ڤامین اوڤیڌن",
        "newarticle": "(تازه)",
-       "newarticletext": "ایسا لینکی را دنبال کردین و به صفحه‌ای رسیدین که هنی درست نوابیده.\nسی ایجاد صفحه، داخل مستطیل زیر شروع به تایپ کنین (سی اطلاعات بیشتر به [[{{ns:project}}:راهنما|صفحه راهنما] برین).\nایر اشتباهی ایچو اویدین دکمه «برگشت» مرورگرتو را بزنین.",
-       "noarticletext": " Ø§Ù\84اÙ\86 Ø§Û\8c ØµÙ\81Ø­Ù\87 Ù\85تÙ\86Û\8c Ù\86دارÙ\87Ø\8c Ø§Û\8cسا ØªØ±Û\8cÙ\86 [[Special:Search/{{PAGENAME}}عÙ\86Ù\88اÙ\86 Ø§Û\8c ØµÙ\81Ø­Ù\87 Ø±Ø§ Ø¯Ø± ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c Ø¯Û\8cگر Ø¬Ø³ØªØ¬Ù\88 Ú©Ù\86Û\8cÙ\86]] Û\8cا [{{fullurl:{{FULLPAGENAME}}|action=edit}} Ø§Û\8c ØµÙ\81Ø­Ù\87 Ø±Ø§ Ø§ØµÙ\84اح Ú©Ù\86Û\8cن].",
+       "newarticletext": "ايسا ز دين یأ هومپیڤأندي هڌين کإ نيڌس. سي رأڤأندياري بألگإ شورۈ کونين مإن اي جأڤإ دإڤۈني بنڤيسين(سي دونسدن بیشدر سإیل [$1]کونین).\nأر ايسا سي إشتڤاکاري ايچونين، دوگمإ رأهڌن ڤاپوشد نأ بپۈرنين.",
+       "noarticletext": " Ø§Ù\8aسإ Ø§Ù\8a Ø¨Ø£Ù\84گإ Ù\86إڤشدإÛ\8cÙ\8a Ù\86ارإØ\8c Ø§Ù\8aسا ØªØ¥Ø±Ù\8aÙ\86 [[Special:Search/{{PAGENAME}}داسÛ\88Ù\86 Ø§Ù\8a Ø¨Ø£Ù\84گإ Ù\86Ø¥ Ù\85Ø¥Ù\86 Ø¨Ø£Ù\84گإآ Ø¯Ù\8aأرÙ\8a Ù¾Û\8c Ø¬Û\88رÙ\8a Ú©Ù\88Ù\86Ù\8aÙ\86]] Û\8cا [{{fullurl:{{FULLPAGENAME}}|action=edit}} Ø§Ù\8a Ø¨Ø£Ù\84گإ Ù\86Ø£ Ú¤Ù\8aراÛ\8cشد Ú©Ù\88Ù\86Ù\8aن].",
        "previewnote": "'''ای فقط یه پیش نمایشه;\nتغییراتی که ایسا دادین هنی ضبط نوابیده!'''",
        "editing": "درحال اصلاح $1",
+       "creating": "راسد کردن $1",
        "editingsection": "درحال اصلاح $1 (قسمت)",
        "copyrightwarning": "لطفاً دقت کنین که درنظر گریده ابوه که همه شراکتهای ایسا  {{SITENAME}} تحت «$2» منتشر ابون ).\n\n\n(سی دیدن  جزئیات بیشتر به $1 برین\n\nایر نه خوین نوشته‌هاتو بی‌رحمانه اصلاح بوه و به دلخواه ارسال بوه، ایچو نفرستن.<br />\nدرضمن ایسادارین به ایما قول ادین که خودتو یونه نوشتین یا هونه زه یک منبع آزاد با مالکیت عمومی یا مثل هو ورداشتین. '''کارهای دارای کارهای دارای حق کپی رایت را بی‌اجازه نفرستین!'''',",
-       "templatesused": "قالبهای استفاده شده من ای صفحه:",
+       "templatesused": "{{PLURAL:$1|چوٙأ|چوٙأیل}} ب کار گرهڌأ ڤابيڌإ مإن اي بألگأ:",
        "templatesusedpreview": "قالبها  یا الگوهای استفاده وابیده در ای پیش نمایش:",
        "template-protected": "(تحت حمایت)",
        "template-semiprotected": "(نیمه حمایت وابیده)",
        "viewpagelogs": "نشودادن نمایه ها سی ای صفحه",
        "currentrev": "نسخه جاری",
        "revisionasof": "اصلاح $1",
-       "revision-info": "یه نسخه اصلاح شده درتاریخ  $1 بوسیله $2",
+       "revision-info": "نوسقإ ڤانيأري ڤابيڌإ جۈر $1 ڤا $2",
        "previousrevision": "← اصلاح قبلی",
        "nextrevision": "نسخه بعدی →",
        "currentrevisionlink": "نسخه جاری",
        "histfirst": "کهنه ترین",
        "histlast": "تازه ترین",
        "history-feed-item-nocomment": "$1 در $2",
-       "history-title": "گزارش تاریخی نسخه زه \"$1\"",
+       "history-title": "دڤارتإ دیئن ڤيرگار $1",
        "lineno": "سطر $1:",
        "compareselectedversions": "مقایسه نسخه‌های انتخاب‌ وابیده",
        "editundo": "لغو اصلاح آخر",
        "recentchanges-feed-description": "ردیابی آخرین تغییرات  ویکی در ای خورد",
        "recentchanges-label-newpage": "ای ويرايشت يه بلگه تازه راس كرده",
        "recentchanges-label-minor": "یو یه ويرايشت کوچيره",
+       "recentchanges-label-bot": "اي ڤيرایشد نأ یأ بوت أنجوم داڌإ",
        "recentchanges-label-unpatrolled": "ای ويرايشت هنی تيه واداشت نوابيه",
        "recentchanges-legend-heading": "<strong>میراث:</strong>",
        "rcnotefrom": "در زیر تغییرات زه تاریخ <b>$2</b> آمده‌اند (تا <b>$1</b> مورد نشو داده ابوه).",
        "rclistfrom": "نشودادن تغییرات تازه با شروع زه $3 $2",
        "rcshowhideminor": "اصلاحات کوچیک $1",
+       "rcshowhideminor-show": "نشون دائن",
        "rcshowhideminor-hide": "قام کردن",
        "rcshowhidebots": "$1 ربات‌ها یا بوتها",
        "rcshowhidebots-show": "نشون دائن",
+       "rcshowhidebots-hide": "قام کردن",
        "rcshowhideliu": "$1 کاریارا ثوت نام کرده",
        "rcshowhideliu-hide": "قام کئردئن",
        "rcshowhideanons": "$1 کاربران داخل نوابیده",
+       "rcshowhideanons-show": "نشون دائن",
        "rcshowhideanons-hide": "قام کئردئن",
        "rcshowhidepatr": "$1 اصلاحات پاسداری شده",
        "rcshowhidemine": "$1 اصلاحات مو",
+       "rcshowhidemine-show": "نشون دائن",
        "rcshowhidemine-hide": "قام کئردئن",
        "rclinks": "نشودادن آخرین $1 تغییر در $2 روز اخیر؛ $3",
        "diff": "تفاوت",
        "ancientpages": "کهنه ترین صفحات",
        "move": "جابجا کردن",
        "movethispage": "جابجایی ای صفحه",
+       "pager-older-n": "{{PLURAL:$1|گپسالتر 1|گپسالتر $1}}",
        "booksources": "منابع کتاب",
+       "booksources-search-legend": "پی جۈري سي سرچشمإیل کتاڤ",
+       "booksources-search": "پی جۈري",
        "specialloguserlabel": "کاربر:",
        "speciallogtitlelabel": "عنوان:",
        "log": "نمایه ها",
        "deleteotherreason": "دیه/دلیل اضافی:",
        "deletereasonotherlist": "دلیل دیه",
        "rollbacklink": "عقب گرد",
+       "rollbacklinkcount": "چڤاسإ کردن $1 {{PLURAL:$1|ویرایشت|ویرایشتیا}}",
        "protectlogpage": "نمایه حفاظت وحمایت",
        "prot_1movedto2": "[[$1]] جابجا وابید به[[$2]]",
        "protectcomment": "دلیل:",
        "nolinkshere": "هیچ صفحه ای پیوند نداردبه '''[[:$1]]'''.",
        "isredirect": "صفحه تغییر مسیر",
        "istemplate": "استفاده‌ وابیده داخل صفحه",
+       "isimage": "جانیا هوم پیوند",
        "whatlinkshere-prev": "{{PLURAL:$1|قبلی |مورد قبلی$1}}",
        "whatlinkshere-next": "{{PLURAL:$1|بعدی |مورد بعدی $1}}",
        "whatlinkshere-links": "← لینکها",
        "thumbnail_error": "خطا سی درست کردن ناخن دانه: $1",
        "importlogpage": "داخل نمایه کردن",
        "tooltip-pt-userpage": "{{GENDER:|بألگأ کارياريتۈن}} بألگأ",
-       "tooltip-pt-mytalk": "صفحه صحبت مو",
+       "tooltip-pt-mytalk": "{{GENDER:|بألگأ چأک چنإ کارياري مو}}",
        "tooltip-pt-preferences": "{{GENDER:|ايسا}} أصل کاريا",
        "tooltip-pt-watchlist": "لیست صفحه‌هایی که ایسا تغییرات هونو  دنبال اکنین",
-       "tooltip-pt-mycontris": "لیست شراکتهای مو",
+       "tooltip-pt-mycontris": "یأ نومگأ ز هومياري {{GENDER:|ايسا}}",
        "tooltip-pt-login": "توصیه ابوه که به سیستم داخل بوین اما اجباری نه.",
        "tooltip-pt-logout": "رهدن زه سیستم",
        "tooltip-ca-talk": "صحبت درباره صفحه محتوا",
        "tooltip-t-recentchangeslinked": "تغییرات آخری  درصفحاتی که لینک شده اند به ای صفحه",
        "tooltip-feed-rss": "تغذیه آراس اس برای ای صفحه",
        "tooltip-feed-atom": "تغذیه کوچیک ترین جزء  ای صفحه",
-       "tooltip-t-contributions": "دیدن فهرست مشارکت کننده ها ومقاله دهنده های ای صفحه",
+       "tooltip-t-contributions": "ديإن نومگأآیي کإ {{GENDER:$1|اي کاریار}} هومياريسۈن کردإ",
        "tooltip-t-emailuser": "ارسال یه امیل به ای کاربر",
        "tooltip-t-upload": "آپلودکردن فایلها",
        "tooltip-t-specialpages": "فهرست همه صفحات مخصوص",
        "metadata-help": " ای فایل دارای اطلاعات اضافه‌ای است که احتمالاً با دوربین دیجیتالی‌ یا پویشگری که سی ایجاد یا دیجیتالی‌کردن آن به کار رهده اضاف وابیده . ایر فایل زه وضعیت اولیه اس تغییر داده وابیده بوه ممکنه همه توضیحات موجود اطلاعات عکس را منعکس نکنه",
        "metadata-expand": "نشودادن جزئیات تفصیلی",
        "metadata-collapse": "قایم کردن جزئیات تفصیلی",
-       "metadata-fields": "فراداده EXIF نشو داده وابیده در این پیام وقتی جدول فراداده‌های تصویر جمع وابیده بوه هم نمایش داده ابوه.\nبقیه موارد فقط وقتی نشوداده ابوه که جدول یادشده واز بوه.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
+       "metadata-fields": "رشنه یا یا گپ دونسمنیا که د ای پیغوم نومگه کاری بینه د ور گرته بلگه عسگ ن که گات وختی که جدول گپ دونسمنیا واز بوئه نشون دئیه بوئن.\nچی یا هنی سی یه که پیش فرضن قام بوئن.\n*راست کو\n*مدل\n*دم وخت اصل\n*وخت آشگار\n*اف ان شماره\n*ایزو نرخ من سرعت\n*فوکالنس\n*هنرمن\n*کپی رایت\n*حالت جی پی اس \n*جی پی اس گپ حالت\n*جی پی اس همه حالت",
        "exif-orientation": "سرچشمأ",
        "exif-xresolution": "گپ نما کردن اوفقي",
        "exif-yresolution": "گپ نما کردن ز وارو",
        "tag-filter": "[[Special:سرديسا|سرديس]] فيلتر:",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|سرديس|سرديسا}}]]: $2)",
        "logentry-delete-delete": "$1 بألگأ {{GENDER:$2|پاکسا ڤابيأ}} $3",
+       "logentry-move-move": "$1 {{GENDER:$2|جا ب جا کردإ}} بألگأ $3 نأ سي $4",
+       "logentry-upload-upload": "$1 {{GENDER:$2|سوڤار کرده}} $3",
        "searchsuggest-search": "جستن {{SITENAME}}"
 }
index c0c6e29..8962400 100644 (file)
        "activeusers-intro": "Setu aze ur roll eus an implijerien zo bet oberiant mui pe vui e-pad an $1 {{PLURAL:$1|deiz|deiz}} diwezhañ.",
        "activeusers-count": "$1 {{PLURAL:$1|oberiadenn}} abaoe an {{PLURAL:$3|deiz|$3 deiz}} diwezhañ",
        "activeusers-from": "Diskouez an implijerien adal :",
-       "activeusers-hidebots": "Kuzhat ar botoù",
-       "activeusers-hidesysops": "Kuzhat ar verourien",
        "activeusers-noresult": "N'eus bet kavet implijer ebet.",
        "listgrouprights": "Gwirioù ar strolladoù implijer",
        "listgrouprights-summary": "Da-heul ez eus ur roll eus ar strolladoù implijerien termenet war ar wiki-mañ, gant ar gwirioù moned stag outo.\nGallout a ra bezañ [[{{MediaWiki:Listgrouprights-helppage}}|titouroù ouzhpenn]] diwar-benn ar gwirioù hiniennel.",
        "feedback-bugornote": "Ma'z oc'h prest da zeskrivañ ur gudenn deknikel dre ar munud e c'hallit [$1 kemenn un draen].\nA-hend-all e c'hallit ober gant ar furmskrid eeunaet dindan. Ouzhpennet e vo hoc'h evezhiadenn d'ar bajenn \"[$3 $2]\", a-gevret gant hoc'h anv implijer hag anv ar merdeer a rit gantañ.",
        "feedback-cancel": "Nullañ",
        "feedback-close": "Graet",
-       "feedback-error-title": "Fazi",
        "feedback-error1": "Fazi : disoc'h dianav a-berzh an API",
        "feedback-error2": "Fazi : N'eus ket bet gallet degemer ar c'hemmoù",
        "feedback-error3": "Fazi : respont ebet a-berzh an API",
index 114b000..2a3c356 100644 (file)
        "nocookiesfornew": "Korisnički račun nije napravljen, jer nismo mogli da potvrdimo njegov izvor.\nProvjerite da li su cookies omogućeni, ponovo učitajte ovu stranicu i pokušajte ponovo.",
        "noname": "Niste izabrali ispravno korisničko ime.",
        "loginsuccesstitle": "Prijavljen",
-       "loginsuccess": "'''Sad ste prijavljeni na {{SITENAME}} kao \"$1\".'''",
+       "loginsuccess": "<strong>Prijavili ste se na {{GRAMMAR:akuzativ|{{SITENAME}}}} kao \"$1\".</strong>",
        "nosuchuser": "Ne postoji korisnik s imenom \"$1\".\nKorisnička imena razlikuju velika i mala slova.\nProvjerite jeste li ga tačno upisali ili [[Special:CreateAccount|otvorite novi račun]].",
        "nosuchusershort": "Ne postoji korisnik s imenom \"$1\".\nProvjerite jeste li dobro ukucali.",
        "nouserspecified": "Morate izabrati korisničko ime.",
        "passwordreset-emaildisabled": "E-pošta je onemogućena na ovom wikiju.",
        "passwordreset-username": "Korisničko ime:",
        "passwordreset-domain": "Domen:",
-       "passwordreset-capture": "Pogledati krajnji e-mail?",
-       "passwordreset-capture-help": "Ako označite ovu kućicu, e-poruka (s privremenom lozinkom) će biti prikazana i poslata korisniku.",
        "passwordreset-email": "Adresa e-pošte:",
        "passwordreset-emailtitle": "Detalji računa na {{SITENAME}}",
        "passwordreset-emailtext-ip": "Neko (vjerovatno Vi, s IP adrese $1) je zatražio podsjetnik Vaših detalja računa za {{SITENAME}} ($4). Sljedeći {{PLURAL:$3|račun korisnika je|računi korisnika su}} povezani s ovom e-mail adresom:\n\n$2\n\n{{PLURAL:$3|Ova privremena šifra|Ove privremene šifre}} će isteći za {{PLURAL:$5|jedan dan|$5 dana}}.\nTrebate se prijaviti i odabrati novu šifru. Ako je neko drugi napravio ovaj zahtjev, ili ako ste se sjetili Vaše početne šifre, a ne želite je promijeniti, možete zanemariti ovu poruku i nastaviti koristiti staru šifru.",
        "userpage-userdoesnotexist": "Korisnički račun \"<nowiki>$1</nowiki>\" nije registrovan.\nMolimo provjerite da li želite napraviti/izmijeniti ovu stranicu.",
        "userpage-userdoesnotexist-view": "Korisnički račun \"$1\" nije registrovan.",
        "blocked-notice-logextract": "Ovaj korisnik je trenutno blokiran.\nPosljednje stavke zapisnika blokiranja možete pogledati ispod:",
-       "clearyourcache": "'''Pažnja:''' Nakon što sačuvate izmjene, morate \"osvježiti\" keš memoriju vašeg pretraživača da bi ste vidjeli nova podešenja.'''\n*'''Firefox / Safari:''' držite ''Shift'' tipku i kliknite na ''Reload'' dugme ili pritisnite ''Ctrl-F5'' ili ''Ctrl-R'' (''⌘-R'' na Macu)\n*'''Google Chrome:''' pritisnite ''Ctrl-Shift-R'' (''⌘-Shift-R'' na Macu)\n*'''Internet Explorer:''' držite tipku ''Ctrl'' i kliknite na ''Refresh'' ili pritisnite ''Ctrl-F5''\n*'''Opera:''' očistite \"keš\" preko izbornika ''Tools → Preferences''",
+       "clearyourcache": "<strong>Napomena:</strong> Nakon što sačuvate izmjene, možda ćete morati osvježiti keš preglednika da biste vidjeli izmjene.\n* <strong>Firefox / Safari:</strong> Držite <em>Shift</em> i kliknite na <em>Reload</em> ili pritisnite <em>Ctrl-F5</em> ili <em>Ctrl-R</em> (<em>⌘-R</em> na Macu)\n* <strong>Google Chrome:</strong> Pritisnite <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> na Macu)\n* <strong>Internet Explorer:</strong> Držite <em>Ctrl</em> i kliknite na <em>Refresh</em> ili pritisnite <em>Ctrl-F5</em>\n* <strong>Opera:</strong> Idite na <em>Menu → Settings</em> (<em>Opera → Preferences</em> na Macu) i zatim <em>Privacy & security → Clear browsing data → Cached images and files</em>.",
        "usercssyoucanpreview": "'''Pažnja:''' Koristite dugme \"{{int:showpreview}}\" da testirate svoj novi CSS prije nego što sačuvate.",
        "userjsyoucanpreview": "'''Pažnja:''' Koristite dugme \"{{int:showpreview}}\" da testirate svoj novi JavaScript prije nego što sačuvate.",
        "usercsspreview": "'''Zapamtite ovo je samo izgled Vašeg CSS-a.'''\n'''Ovaj pregled još uvijek nije sačuvan!'''",
        "searchprofile-advanced-tooltip": "Traži u ostalim imenskim prostorima",
        "search-result-size": "$1 ({{PLURAL:$2|$2 riječ|$2 riječi}})",
        "search-result-category-size": "{{PLURAL:$1|1 član|$1 člana|$1 članova}} ({{PLURAL:$2|1 potkategorija|$2 potkategorije|$2 potkategorija}}, {{PLURAL:$3|1 datoteka|$3 datoteke|$3 datoteka}})",
-       "search-redirect": "(preusmjeravanje $1)",
+       "search-redirect": "(preusmjereno sa $1)",
        "search-section": "(sekcija $1)",
        "search-category": "(kategorija $1)",
        "search-file-match": "(podudara se sadržaj datoteke)",
        "userrights-reason": "Razlog:",
        "userrights-no-interwiki": "Nemate dopuštenja da uređujete korisnička prava na drugim wikijima.",
        "userrights-nodatabase": "Baza podataka $1 ne postoji ili nije lokalna baza.",
-       "userrights-nologin": "Morate se [[Special:UserLogin|prijaviti]] sa administratorskim računom da bi ste mogli postavljati korisnička prava.",
-       "userrights-notallowed": "Nemate dopuštenje za dodavanje ili uklanjanje korisničkih prava.",
        "userrights-changeable-col": "Grupe koje možete mijenjati",
        "userrights-unchangeable-col": "Grupe koje ne možete mijenjati",
        "userrights-conflict": "Sukob u izmjeni korisničkih prava! Molimo da razmotrite i potvrdite Vaše promjene.",
-       "userrights-removed-self": "Uklonili ste vlastita prava. Zbog toga više ne možete pristupiti ovoj stranici.",
        "group": "Grupa:",
        "group-user": "Korisnici",
        "group-autoconfirmed": "Potvrđeni korisnici",
        "right-siteadmin": "Zaključavanje i otključavanje baze podataka",
        "right-override-export-depth": "Izvoz stranica uključujući povezane stranice do dubine od 5 linkova",
        "right-sendemail": "Slanje e-maila drugim korisnicima",
-       "right-passwordreset": "Pogledaj e-mailove za obnavljanje šifre",
        "right-managechangetags": "Napravi i (de)aktiviraj [[Special:Tags|oznake]]",
        "right-applychangetags": "Primijeni [[Special:Tags|oznake]] na nečije izmjene",
        "right-changetags": "Dodavanje ili uklanjanje raznih [[Special:Tags|oznaka]] na pojedinačnim verzijama i unosima zapisnika",
        "modifiedarticleprotection": "{{GENDER:|promijenio|promijenila}} je stepen zaštite stranice \"[[$1]]\"",
        "unprotectedarticle": "uklonjena zaštita sa stranice \"[[$1]]\"",
        "movedarticleprotection": "podešavanja zaštite premještena sa \"[[$2]]\" na \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Zaštitio|Zaštitila}} je stranicu \"[[$1]]\"",
        "protect-title": "Mijenjate nivo zašite za \"$1\"",
        "protect-title-notallowed": "Pregled stepena zaštite za \"$1\"",
        "prot_1movedto2": "članak [[$1]] premješten na [[$2]]",
        "htmlform-user-not-exists": "<strong>$1</strong> ne postoji.",
        "htmlform-user-not-valid": "<strong>$1</strong> nije ispravno korisničko ime.",
        "logentry-delete-delete": "$1 {{GENDER:$2|obrisao|obrisala}} je stranicu $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|obrisao|obrisala}} je preusmjerenje $3 prepisivanjem",
        "logentry-delete-restore": "$1 {{GENDER:$2|vratio|vratila}} je stranicu $3",
        "logentry-delete-event": "$1 {{GENDER:$2|promijenio|promijenila}} je vidljivost {{PLURAL:$5|unosa|$5 unosa}} u zapisniku na $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|promijenio|promijenila}} je vidljivost {{PLURAL:$5|izmjene|$5 izmjene|$5 izmjena}} na stranici $3: $4",
        "feedback-thanks": "Hvala! Vaša povratna informacija postavljena je na stranicu \"[$2 $1]\".",
        "feedback-thanks-title": "Hvala!",
        "feedback-useragent": "Korisnički agent:",
-       "searchsuggest-search": "Traži",
+       "searchsuggest-search": "Pretraži {{GRAMMAR:akuzativ|{{SITENAME}}}}",
        "searchsuggest-containing": "sadrži...",
        "api-error-badaccess-groups": "Nemate ovlasti da postavljate datoteke na ovoj wiki.",
        "api-error-badtoken": "Unutrašnja greška: token nije ispravan.",
index bf8c180..8bed43c 100644 (file)
        "content-model-text": "simpleng teksto",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
-       "cantcreateaccounttitle": "Diri makagibo sa account",
        "next": "sunod",
        "last": "sinundan",
        "page_first": "una",
        "deletedcontributions": "Napurang mga ambag ka user",
        "linksearch-ok": "Pag-anapon",
        "listusers-submit": "Ipabayad",
-       "activeusers-hidebots": "Itago a bots",
        "listgrouprights-group": "Grupo",
        "listgrouprights-addgroup": "Mairurugang a {{PLURAL:$2|grupo|mga grupo}}: $1",
        "listgrouprights-addgroup-all": "Irugang ngamin na mga grupo",
index 00bb056..1574bb1 100644 (file)
        "views": "Vistes",
        "toolbox": "Eines",
        "tool-link-userrights": "Canvia els grups de l'{{GENDER:$1|usuari|usuària}}",
+       "tool-link-userrights-readonly": "Mostra els grups d'{{GENDER:$1|usuari}}",
        "tool-link-emailuser": "Envia un missatge electrònic a l'{{GENDER:$1|usuari|usuària}}",
        "userpage": "Visualitza la pàgina d'usuari",
        "projectpage": "Visualitza la pàgina del projecte",
        "passwordreset-emaildisabled": "Les opcions de correu electrònic no estan habilitades en aquest wiki.",
        "passwordreset-username": "Nom d'usuari:",
        "passwordreset-domain": "Domini",
-       "passwordreset-capture": "Veure el missatge de correu electrònic?",
-       "passwordreset-capture-help": "Si marqueu aquesta casella, el missatge de correu electrònic (amb la contrasenya temporal) es mostrarà al mateix moment que sigui enviat a l'usuari.",
        "passwordreset-email": "Adreça electrònica:",
        "passwordreset-emailtitle": "Detalls del compte a {{SITENAME}}",
        "passwordreset-emailtext-ip": "Algú (vós mateix segurament, des de l'adreça IP $1) ha demanat una reinicialització de la vostra contrasenya al projecte {{SITENAME}} ($4). {{PLURAL:$3|El següent compte d'usuari està associat|Els següents comptes d'usuari estan associats}} amb aquesta adreça de correu electrònic:\n\n$2\n\n{{PLURAL:$3|Aquesta contrasenya temporal caducarà|Aquestes contrasenyes temporals caducaran}} en {{PLURAL:$5|un dia|$5 dies}}.\nHauríeu d'entrar al compte per a fixar-hi una nova contrasenya al més aviat possible. Si algú que no sou vós és qui ha fet aquesta petició o si heu recordat la contrasenya original i ja no la voleu canviar, podeu ignorar aquest missatge i seguir utilitzant la vostra antiga contrasenya.",
        "passwordreset-emailelement": "Nom d'usuari: \n$1\n\nContrasenya temporal: \n$2",
        "passwordreset-emailsentemail": "Si aquesta adreça electrònica està associada al vostre compte, s’enviarà un missatge de restabliment de contrasenya.",
        "passwordreset-emailsentusername": "Si existeix una adreça electrònica associada a aquest nom d'usuari, s’hi enviarà un missatge de reestabliment de contrasenya.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|S'ha enviat el correu|S'han enviat els correus}} de restabliment de {{PLURAL:$1|contrasenya|contrasenyes}}. A continuació es mostra {{PLURAL:$1|l'usuari i contrasenya|la llista d'usuaris i contrasenyes}}.",
-       "passwordreset-invalideamil": "Adreça de correu electrònic no vàlida",
+       "passwordreset-invalidemail": "Adreça de correu electrònic no vàlida",
        "passwordreset-nodata": "No s'ha proporcionat cap nom d'usuari ni adreça electrònica",
        "changeemail": "Canvia o elimina l’adreça electrònica",
        "changeemail-header": "Empleneu aquest formulari per canviar la vostra adreça electrònica. Si voleu eliminar qualssevol associacions d’adreces electròniques del vostre compte, deixeu en blanc el camp i envieu el formulari.",
        "invalid-content-data": "Dades de contingut no vàlides",
        "content-not-allowed-here": "No és permès el contingut \"$1\" a la pàgina [[$2]]",
        "editwarning-warning": "Si sortiu d'aquesta pàgina, perdreu tots els canvis que hàgiu fet.\nSi teniu un compte d'usuari, podeu eliminar aquest avís en la secció «{{int:prefs-editing}}» de les vostres preferències.",
+       "editpage-invalidcontentmodel-title": "Model de contingut no permès",
+       "editpage-invalidcontentmodel-text": "El model de contingut «$1» no és permès.",
        "editpage-notsupportedcontentformat-title": "No s'admet el format del contingut",
        "editpage-notsupportedcontentformat-text": "No s'admet el format del contingut $1 pel model de contingut $2.",
        "content-model-wikitext": "wikitext",
        "mergehistory-fail-bad-timestamp": "La marca horària no és vàlida.",
        "mergehistory-fail-invalid-source": "La pàgina font no és vàlida.",
        "mergehistory-fail-invalid-dest": "La pàgina de destinació no és vàlida.",
+       "mergehistory-fail-no-change": "La fusió d'historial no ha fusionat cap revisió. Comproveu de nou la pàgina i els paràmetres temporals.",
        "mergehistory-fail-permission": "No hi ha permisos suficients per fusionar l'historial.",
        "mergehistory-fail-self-merge": "Les pàgines d'origen i de destinació no poden ser la mateixa",
        "mergehistory-fail-toobig": "No s'ha pogut fer la fusió de l'historial perquè es mourien més del límit de $1 {{PLURAL:$1|revisió|revisions}}.",
        "search-external": "Cerca externa",
        "searchdisabled": "La cerca dins el projecte {{SITENAME}} està inhabilitada. Mentrestant, podeu cercar a través de Google, però tingueu en compte que la seua base de dades no estarà actualitzada.",
        "search-error": "S'ha produït un error durant la recerca: $1",
+       "search-warning": "S'ha produït un avís en cercar: $1",
        "preferences": "Preferències",
        "mypreferences": "Preferències",
        "prefs-edits": "Nombre d'edicions:",
        "prefs-help-recentchangescount": "Inclou els canvis recents, els historials de pàgines i els registres.",
        "prefs-help-watchlist-token2": "Aquesta és la clau secreta pel canal de continguts de la vostra llista de seguiment.\nQualsevol que la conegui podria llegir la vostra llista de seguiment, així que no la compartiu.\n[[Special:ResetTokens|Cliqueu aquí si voleu restaurar-la]].",
        "savedprefs": "S’han desat les vostres preferències.",
-       "savedrights": "S'han desat els permisos d'usuari de {{GENDER:$1|$1}}.",
+       "savedrights": "S'han desat els grups d'usuari de {{GENDER:$1|$1}}.",
        "timezonelegend": "Fus horari:",
        "localtime": "Hora local:",
        "timezoneuseserverdefault": "Utilitza l'hora per defecte del wiki ($1)",
        "prefswarning-warning": "Heu fet canvis a les preferències que encara no s'han desat.\nSi abandoneu la pàgina sense fer clic a «$1», les preferències no s'actualitzaran.",
        "prefs-tabs-navigation-hint": "Consell: Podeu utilitzar les tecles de cursor de dreta i esquerra per a navegar entre les pestanyes.",
        "userrights": "Gestió dels permisos d’usuari",
-       "userrights-lookup-user": "Gestiona els grups d'usuari",
+       "userrights-lookup-user": "Seleccioneu un usuari",
        "userrights-user-editname": "Introduïu un nom d'usuari:",
-       "editusergroup": "Edita els grups d'{{GENDER:$1|usuari}}",
+       "editusergroup": "Carrega els grups d'usuari",
        "editinguser": "Modificació dels permisos de {{GENDER:$1|l'usuari|la usuària}} <strong>[[User:$1|$1]]</strong>$2",
        "userrights-editusergroup": "Edita els grups d'usuaris",
+       "userrights-viewusergroup": "Mostra els grups d'usuari",
        "saveusergroups": "Desa els grups d'{{GENDER:$1|usuari}}",
        "userrights-groupsmember": "Membre de:",
        "userrights-groupsmember-auto": "Membre implícit de:",
        "userrights-reason": "Motiu:",
        "userrights-no-interwiki": "No teniu permisos per a editar els permisos d'usuari d'altres wikis.",
        "userrights-nodatabase": "La base de dades $1 no existeix o no és local.",
-       "userrights-nologin": "Heu [[Special:UserLogin|d'iniciar una sessió]] amb un compte d'administrador per a poder assignar permisos d'usuari.",
-       "userrights-notallowed": "No teniu autorització per concedir o retirar permisos d'usuari.",
        "userrights-changeable-col": "Grups que podeu canviar",
        "userrights-unchangeable-col": "Grups que no podeu canviar",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Conflicte de canvis dels permisos d'usuari. Reviseu i confirmeu els canvis.",
-       "userrights-removed-self": "Heu suprimit els vostres propis permisos. Per tant, ja no podeu tornar a accedir a aquesta pàgina.",
        "group": "Grup:",
        "group-user": "Usuaris",
        "group-autoconfirmed": "Usuaris autoconfirmats",
        "right-siteadmin": "Blocar i desblocar la base de dades",
        "right-override-export-depth": "Exportar pàgines incloent aquelles enllaçades fins a una fondària de 5",
        "right-sendemail": "Enviar missatges de correu electrònic a altres usuaris",
-       "right-passwordreset": "Veure les sol·licituds de restabliment de contrasenya per correu electrònic",
        "right-managechangetags": "Crear, activar i desactivar [[Special:Tags|etiquetes]]",
        "right-applychangetags": "Aplica les [[Special:Tags|etiquetes]] juntament amb els canvis propis",
        "right-changetags": "Afegeix i suprimeix [[Special:Tags|etiquetes]] en revisions individuals i entrades de registre",
        "action-upload_by_url": "carregar aquest fitxer des d'una adreça URL",
        "action-writeapi": "fer servir l'API d'escriptura",
        "action-delete": "esborrar aquesta pàgina",
-       "action-deleterevision": "esborrar aquesta revisió",
-       "action-deletedhistory": "visualitzar l'historial esborrat d'aquesta pàgina",
+       "action-deleterevision": "suprimeix les revisions",
+       "action-deletelogentry": "suprimeix les entrades de registre",
+       "action-deletedhistory": "mostra l'historial esborrat d'una pàgina",
        "action-browsearchive": "cercar pàgines esborrades",
        "action-undelete": "recuperar aquesta pàgina",
        "action-suppressrevision": "revisar i recuperar aquesta revisió oculta",
        "action-userrights-interwiki": "modificar permisos d'usuari en altres wikis",
        "action-siteadmin": "bloquejar o desbloquejar la base de dades",
        "action-sendemail": "enviar missatges de correu",
+       "action-editmyoptions": "modifiqueu les vostres preferències",
        "action-editmywatchlist": "edita la llista de seguiment",
        "action-viewmywatchlist": "mostra la llista de seguiment",
        "action-viewmyprivateinfo": "mostra la informació personal",
        "filerevert-submit": "Reverteix",
        "filerevert-success": "S'ha revertit '''[[Media:$1|$1]]''' a la [$4 versió de $3, $2].",
        "filerevert-badversion": "No hi ha cap versió local anterior d'aquest fitxer amb la marca horària que es proporciona.",
+       "filerevert-identical": "La versió actual del fitxer ja és idèntica a la seleccionada.",
        "filedelete": "Suprimeix $1",
        "filedelete-legend": "Suprimeix el fitxer",
        "filedelete-intro": "Esteu eliminant el fitxer '''[[Media:$1|$1]]''' juntament amb el seu historial.",
        "unusedtemplates": "Plantilles no utilitzades",
        "unusedtemplatestext": "Aquesta pàgina mostra les pàgines en l'espai de noms {{ns:template}}, que no estan incloses en cap altra pàgina. Recordeu de comprovar les pàgines que hi enllacen abans d'esborrar-les.",
        "unusedtemplateswlh": "altres enllaços",
-       "randompage": "Pàgina a l'atzar",
+       "randompage": "Pàgina a latzar",
        "randompage-nopages": "No hi ha cap pàgina en {{PLURAL:$2|l'espai de noms següent|els espais de noms següents}}: $1.",
        "randomincategory": "Pàgina aleatòria en una categoria",
        "randomincategory-invalidcategory": "«$1» no és un nom de categoria vàlid.",
        "randomincategory-category": "Categoria:",
        "randomincategory-legend": "Pàgina a l’atzar en la categoria",
        "randomincategory-submit": "Vés-hi",
-       "randomredirect": "Redirecció a l'atzar",
+       "randomredirect": "Redirecció a latzar",
        "randomredirect-nopages": "No hi ha cap redirecció a l'espai de noms «$1».",
        "statistics": "Estadístiques",
        "statistics-header-pages": "Estadístiques de pàgines",
        "apisandbox-request-time": "Temps de sol·licitud: {{PLURAL:$1|$1 ms}}",
        "apisandbox-continue": "Continua",
        "apisandbox-continue-clear": "Neteja",
+       "apisandbox-multivalue-all-namespaces": "$1 (tots els espais de noms)",
+       "apisandbox-multivalue-all-values": "$1 (tots els valors)",
        "booksources": "Obres de referència",
        "booksources-search-legend": "Cerca fonts de llibres",
        "booksources-isbn": "ISBN:",
        "booksources-search": "Cerca",
        "booksources-text": "A sota hi ha una llista d'enllaços d'altres llocs que venen llibres nous i de segona mà, i també podrien tenir més informació dels llibres que esteu cercant:",
        "booksources-invalid-isbn": "El codi ISBN donat no és vàlid. Comproveu si l'heu copiat correctament.",
+       "magiclink-tracking-rfc": "Pàgines que usen enllaços màgics RFC",
+       "magiclink-tracking-pmid": "Pàgines que usen enllaços màgics PMID",
+       "magiclink-tracking-isbn": "Pàgines que usen enllaços màgics d'ISBN",
        "specialloguserlabel": "Realitzador:",
        "speciallogtitlelabel": "Objectiu (títol o «{{ns:user}}:nom d’usuari» per a un usuari):",
        "log": "Registres",
        "activeusers-intro": "Aquí hi ha una llista d'usuaris que han tingut algun tipus d'activitat en {{PLURAL:$1|el darrer dia|els darrers $1 dies}}.",
        "activeusers-count": "$1 {{PLURAL:$1|acció|accions}} en {{PLURAL:$3|el darrer dia|els $3 darrers dies}}",
        "activeusers-from": "Mostra els usuaris començant per:",
-       "activeusers-hidebots": "Amaga bots",
-       "activeusers-hidesysops": "Amaga administradors",
+       "activeusers-excludegroups": "Exclou els usuaris que pertanyen als grups:",
        "activeusers-noresult": "No s'han trobat usuaris.",
        "activeusers-submit": "Mostra els usuaris actius",
        "listgrouprights": "Drets dels grups d'usuaris",
        "tooltip-n-portal": "Sobre el projecte, què podeu fer, on podeu trobar coses",
        "tooltip-n-currentevents": "Per trobar informació general sobre l'actualitat",
        "tooltip-n-recentchanges": "Llista de canvis recents al wiki",
-       "tooltip-n-randompage": "Pàgina a l'atzar",
+       "tooltip-n-randompage": "Carrega una pàgina a l’atzar",
        "tooltip-n-help": "El lloc per saber més coses",
        "tooltip-t-whatlinkshere": "Llista de totes les pàgines wiki que enllacen aquí",
        "tooltip-t-recentchangeslinked": "Canvis recents a pàgines enllaçades des d'aquesta pàgina",
        "patrol-log-header": "Això és un registre de les revisions patrullades.",
        "log-show-hide-patrol": "$1 el registre de patrulla",
        "log-show-hide-tag": "$1 el registre d’etiquetes",
+       "confirm-markpatrolled-button": "D'acord",
        "deletedrevision": "S'ha eliminat la revisió antiga $1.",
        "filedeleteerror-short": "Error en suprimir el fitxer: $1",
        "filedeleteerror-long": "S'han produït errors en suprimir el fitxer:\n\n$1",
        "filedelete-old-unregistered": "La revisió de fitxer especificada «$1» no es troba a la base de dades.",
        "filedelete-current-unregistered": "El fitxer especificat «$1» no es troba a la base de dades.",
        "filedelete-archive-read-only": "El directori d'arxiu «$1» no té permisos d'escriptura per al servidor web.",
-       "previousdiff": "← Vés a l'edició anterior",
-       "nextdiff": "Vés a l'edició següent →",
+       "previousdiff": "← Edició anterior",
+       "nextdiff": "Edició següent →",
        "mediawarning": "'''Advertència''': Aquest fitxer podria contenir codi maliciós.\nSi l'executeu, podeu comprometre la seguretat del vostre sistema.",
        "imagemaxsize": "Límit de mida d'imatges:<br />''(per a pàgines de descripció de fitxers)''",
        "thumbsize": "Mida de la miniatura:",
        "tags-actions-header": "Accions",
        "tags-active-yes": "Sí",
        "tags-active-no": "No",
-       "tags-source-extension": "Definit per una extensió",
+       "tags-source-extension": "Definit pel programari",
        "tags-source-manual": "Aplicat manualment per usuaris i bots",
        "tags-source-none": "Ja no està en ús",
        "tags-edit": "modifica",
        "tags-deactivate": "desactiva",
        "tags-hitcount": "$1 {{PLURAL:$1|canvi|canvis}}",
        "tags-manage-no-permission": "No teniu permisos per administrar etiquetes de canvi",
+       "tags-manage-blocked": "No podeu canviar etiquetes mentre esteu {{GENDER:$1|blocat|blocada}}.",
        "tags-create-heading": "Crea una nova etiqueta",
        "tags-create-explanation": "Per defecte, les etiquetes acabades de crear estaran disponibles per usuaris i bots",
        "tags-create-tag-name": "Nom de l'etiqueta:",
        "api-error-autoblocked": "S'ha blocat la vostra IP automàticament perquè la va utilitzar un usuari blocat.",
        "api-error-badaccess-groups": "No teniu permís per a carregar fitxers en aquest wiki.",
        "api-error-badtoken": "Error intern: argument incorrecte.",
+       "api-error-blocked": "Heu estat blocat per poder editar.",
        "api-error-copyuploaddisabled": "Les càrregues via URL estan desactivades en aquest servidor.",
        "api-error-duplicate": "Ja hi ha {{PLURAL:$1|un altre fitxer|altres fitxers}} en aquest lloc web amb el mateix contingut.",
        "api-error-duplicate-archive": "Aquí ja hi ha hagut {{PLURAL:$1|un altre fitxer|altres fitxers}} amb el mateix contingut, i {{PLURAL:$1|va ser esborrat|varen ser esborrats}}.",
        "mw-widgets-dateinput-no-date": "No s'ha seleccionat cap data",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Cerca de fitxers multimèdia",
+       "mw-widgets-mediasearch-noresults": "No s'han trobat resultats.",
        "mw-widgets-titleinput-description-new-page": "la pàgina no existeix encara",
        "mw-widgets-titleinput-description-redirect": "redirigeix a $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Afegeix una categoria...",
        "sessionmanager-tie": "No es poden combinar diferents tipus de sol·licituds d'autenticació: $1.",
        "sessionprovider-generic": "$1 sessions",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessions basades en galetes",
        "sessionprovider-nocookies": "Pot ser que les galetes estiguin inhabilitades. Assegureu-vos que teniu les galetes habilitades i inicieu de nou.",
        "randomrootpage": "Pàgina arrel aleatòria",
        "log-action-filter-block": "Tipus de blocatge:",
+       "log-action-filter-contentmodel": "Tipus de modificació del model de contingut:",
        "log-action-filter-delete": "Tipus de supressió:",
        "log-action-filter-import": "Tipus d'importació:",
        "log-action-filter-managetags": "Tipus d'acció de gestió d'etiquetes:",
        "log-action-filter-block-block": "Bloca",
        "log-action-filter-block-reblock": "Bloca la modificació",
        "log-action-filter-block-unblock": "Desbloca",
+       "log-action-filter-contentmodel-change": "Canvi del model de contingut",
        "log-action-filter-delete-delete": "Supressió de pàgines",
+       "log-action-filter-delete-delete_redir": "Sobreescriptura de la redirecció",
        "log-action-filter-delete-restore": "Restauració de pàgines",
        "log-action-filter-delete-event": "Registre de supressió",
        "log-action-filter-delete-revision": "Supressió de revisions",
        "log-action-filter-managetags-create": "Creació de l'etiqueta",
        "log-action-filter-managetags-delete": "Supressió de l'etiqueta",
        "log-action-filter-managetags-activate": "Activació de l'etiqueta",
+       "log-action-filter-managetags-deactivate": "Desactivació d'etiquetes",
+       "log-action-filter-newusers-create2": "Creació per usuari registrat",
        "log-action-filter-newusers-autocreate": "Creació automàtica",
        "log-action-filter-patrol-patrol": "Patrullatge manual",
        "log-action-filter-patrol-autopatrol": "Patrullatge automàtic",
        "log-action-filter-protect-protect": "Protecció",
        "log-action-filter-protect-modify": "Modificació de la protecció",
        "log-action-filter-protect-unprotect": "Desprotecció",
+       "log-action-filter-protect-move_prot": "Protecció de reanomenaments",
        "log-action-filter-rights-rights": "Canvi manual",
        "log-action-filter-rights-autopromote": "Canvi automàtic",
        "log-action-filter-suppress-event": "Supressió de registres",
        "authmanager-authn-autocreate-failed": "Ha fallat la creació automàtica d'un compte local: $1",
        "authmanager-create-disabled": "S'ha inhabilitat la creació de comptes.",
        "authmanager-create-from-login": "Per crear un compte, ompliu els camps de sota.",
+       "authmanager-authplugin-setpass-failed-title": "El canvi de contrasenya ha fallat",
        "authmanager-authplugin-setpass-bad-domain": "Domini invàlid.",
+       "authmanager-userdoesnotexist": "El compte d'usuari «$1» no està registrat.",
        "authmanager-retype-help": "Contrasenya de nou per confirmar",
        "authmanager-email-label": "Correu electrònic",
        "authmanager-email-help": "Adreça electrònica",
        "authmanager-provider-password": "Autenticació basada en contrasenya",
        "authmanager-provider-password-domain": "Autenticació basada en contrasenya i en domini",
        "authmanager-provider-temporarypassword": "Contrasenya temporal",
+       "authprovider-confirmlink-request-label": "Comptes que caldrien enllaçar-se",
+       "authprovider-confirmlink-success-line": "$1: s'ha enllaçat satisfactòriament.",
        "authprovider-resetpass-skip-label": "Omet",
+       "authprovider-resetpass-skip-help": "Omet el restabliment de contrasenya.",
        "specialpage-securitylevel-not-allowed-title": "No permès",
        "authpage-cannot-login": "No s'ha pogut iniciar la sessió.",
        "authpage-cannot-login-continue": "No es pot continuar amb l'inicio de sessió. Probablement la vostra sessió ha expirat.",
        "cannotauth-not-allowed": "No teniu permisos per utilitzar la pàgina",
        "changecredentials": "Canvi de dades credencials",
        "changecredentials-submit": "Canvia les dades credencials",
+       "removecredentials": "Suprimeix les credencials",
+       "removecredentials-submit": "Suprimeix les credencials",
+       "removecredentials-success": "S'ha suprimit les vostres credencials.",
        "credentialsform-provider": "Tipus de dades credencials:",
        "credentialsform-account": "Nom del compte:",
        "cannotlink-no-provider-title": "No hi ha cap compte enllaçable",
        "unlinkaccounts": "Desenllaça els comptes",
        "unlinkaccounts-success": "El compte s'ha desenllaçat.",
        "authenticationdatachange-ignored": "No s'ha gestionat el canvi de dades d'autenticació. Potser no s'ha configurat cap proveïdor?",
-       "edit-error-short": "Error: $1",
-       "edit-error-long": "Errors:\n\n$1"
+       "restrictionsfield-badip": "Adreça o interval d'IP no vàlid: $1",
+       "restrictionsfield-label": "Intervals d'IP permesos:",
+       "pageid": "ID de pàgina $1"
 }
index bde0e77..c61e871 100644 (file)
        "passwordreset-emaildisabled": "Электронан поштан функцеш хӀокху вики чохь дӀаяйина ю.",
        "passwordreset-username": "Декъашхочун цӀе:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Хьажа беанчу хааме?",
-       "passwordreset-capture-help": "Ахьа хӀара билгало хӀотта яхь хьона гур бу декъашхочо баийта чохь хана пароль йолу хаам.",
        "passwordreset-email": "Электронан поштан адрес:",
        "passwordreset-emailtitle": "{{SITENAME}}: декъашхочун дӀаяздарх лаьцна хаам",
        "passwordreset-emailtext-ip": "{{SITENAME}} ($4) проектехь цхьам я ахьа хӀокху IP-адрес $1 тӀера хьа декъашхочун пароль кхоссар дехна,\nоьцу электронан адресца дихкина ду {{PLURAL:$3|1хӀара декъашхочун дӀаяздар|хӀара декъашхочун дӀаяздар}}:\n\n$2\n\n{{PLURAL:$3|ХӀара хана пароль|ХӀара хана паролаш}} лелар ю {{PLURAL:$5|$5 дийнахь}}.\nСистемин чугӀой харжа керла пароль. \nХьой пароль кхоссар дехна дацахь я хьалхалера пароль дага еънехь хӀума цадеш Ӏад битта хӀара хаам хьа йиш ю шира пароль лелаян.",
        "userrights-groups-help": "Хьоьга хийцалун хӀокху декъашхочун бакъонаш.\n* Бакъона цӀера юххехь билгало елахь, цуна и бакъо йолуш ю.\n* Билгало яцахь — декъашхочун и бакъо яц.\n* Хьаьрко * билгала до ахьа бакъо еллачул тӀаьхьа хьуна и дӀаяккха цалуш хилар.",
        "userrights-reason": "Бахьана:",
        "userrights-no-interwiki": "Хьан бакъо яц декъашхой бакъо хийца кхечу википеди чохь.",
-       "userrights-nologin": "Куьйгалхочунна бакъо йолу [[Special:UserLogin|дӀаяздарца]] ло декъашхочун бакъо.",
-       "userrights-notallowed": "Хьан дӀаяздарца магийна дац декъашхошна бакъо яла а дӀаяккха а.",
        "userrights-changeable-col": "Хьоьга хийцалун бакъонаш",
        "userrights-unchangeable-col": "Хьоьга хийцалун бакъонаш",
        "group": "Тоба:",
        "right-siteadmin": "хаамийн гуламан блоктохар а, блокдӀаяккхар а",
        "right-override-export-depth": "агӀонаш экспорт ян, 5 кхаччалц къорга агӀонаш цхьан",
        "right-sendemail": "кхечу декъашхошка электронан хаамаш кхехьийта",
-       "right-passwordreset": "пароль хийцарца электроннан хаамашка хьажар",
        "right-managechangetags": "Хаамийн базан чохь [[Special:Tags|билгалонаш]] кхолла а, дӀаяха а",
        "grant-generic": "Бакъонийн гулам «$1»",
        "grant-group-page-interaction": "АгӀонашца зӀе",
        "booksources-search-legend": "Жайнех лаьцна хаам лахар",
        "booksources-search": "Лахар",
        "booksources-text": "ХӀокху агӀонгахь гул бина сайтийн тӀе хьажоргийн могӀам оцу чохь шуна жайнах лаьцна хаам каро мега. И ю интернет-туьканаш а категорийн библиотекийн категорешкахь лахаран система а.",
+       "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 хьажоргаш лелош йолу агӀонаш",
+       "magiclink-tracking-pmid-desc": "ХӀокху агӀогахь лелош ю PMID хьажоргаш. Хьажа [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] дихьаяккхар муха кхочушдан деза дуьйцу.",
+       "magiclink-tracking-isbn": "ISBN хьажоргаш лелош йолу агӀонаш",
+       "magiclink-tracking-isbn-desc": "ХӀокху агӀогахь лелош ю ISBN хьажоргаш. Хьажа [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] дихьаяккхар муха кхочушдан деза дуьйцу.",
        "specialloguserlabel": "Декъашхо:",
        "speciallogtitlelabel": "Ӏалашо (цӀе я декъашхо):",
        "log": "Тéптарш",
        "activeusers-intro": "Лахахь гойтуш бу  {{PLURAL:$1|1=тӀаьхьара $1 динахь|тӀаьхьара $1 деношкахь}} хийцамаш бина декъашхой.",
        "activeusers-count": "{{PLURAL:$3|1=тӀаьхьарчу $3 динахь|тӀаьхьара $3 деношкахь}} $1 {{PLURAL:$1|1=нисдар|нисдарш}} дина",
        "activeusers-from": "Гучé баха декъашхой, болалуш болу тӀера:",
-       "activeusers-hidebots": "Къайлабаха боташ",
-       "activeusers-hidesysops": "Къайлабаха куьйгалхой",
        "activeusers-noresult": "Декъашхой цакарий.",
        "activeusers-submit": "Гайта жигара декъашхой",
        "listgrouprights": "Декъашхойн тобанийн бакъонаш",
        "revdelete-unrestricted": "куьйгалхойн доза тохар дӀаяьккхина",
        "logentry-block-block": "$1 {{GENDER:$2|блоктоьхна}} {{GENDER:$4|$3}} $5 $6 хан чекхйолу",
        "logentry-block-unblock": "$1 {{GENDER:$2|блокдаяьккхина}} {{GENDER:$4|$3}}",
+       "logentry-block-reblock": "$1 {{GENDER:$2|хийцина}} блоктоьхна хан {{GENDER:$4|$3}} → $5 $6",
        "logentry-suppress-block": "$1 {{GENDER:$2|блоктоьхна}} {{GENDER:$4|$3}} $5 $6 хан чекхйолу",
+       "logentry-suppress-reblock": "$1 {{GENDER:$2|хийцина}} блоктоьхна хан {{GENDER:$4|$3}} → $5 $6",
        "logentry-merge-merge": "$1 {{GENDER:$2|вовшахтоьхна}} $3 $4 чохь ($5 кхаччалц версеш)",
        "logentry-move-move": "$1 {{GENDER:$2|цӀе хийцина}} $3 → $4",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|цӀе хийцина}} $3 → $4 дӀасахьажорг цаюьтуш",
index 8dccaba..2a9ecd5 100644 (file)
        "yourname": "Ngalan sa tiggamit:",
        "yourpassword": "Pasword:",
        "yourpasswordagain": "Itayp og usab ang pasword:",
-       "remembermypassword": "Hinumdomi ako niining brawser (sa kadugayon nga $1 {{PLURAL:$1|ka adlaw|ka mga adlaw}})",
        "yourdomainname": "Ang imong domain:",
        "externaldberror": "May nahitabong authentication database error o kaha wala ka tugoti nga mag-update sa imong eksternal nga akawnt.",
        "login": "Sulod",
        "undo-failure": "Ang pag-usab dili puyde mapa-way-bili tungod sa mga naka-conflict nga intermediate nga mga pag-usab.",
        "undo-norev": "Ang pag-usab dili puyde mapa-way-bili tungod kay wala pa ni mahimo o kaha natangtang na kini.",
        "undo-summary": "Giway-bili  ang rebisyon  $1 ni [[Special:Contributions/$2|$2]] ([[User talk:$2|Hisgot]])",
-       "cantcreateaccounttitle": "Dili makahimo og akawnt",
        "cantcreateaccount-text": "Ang paghimo og akawnt gikan niining IP address ('''$1''') gi-block ni [[User:$3|$3]].\n\nAng rason nga gihatag ni $3 mao nga ''$2''",
        "viewpagelogs": "Tan-awa ang mga log niining panid",
        "nohistory": "Walay kaagi sa pag-usab niining panid.",
index 4274025..b104745 100644 (file)
        "yourname": "Nå'an ni muna'setbi:",
        "yourpassword": "Password:",
        "yourpasswordagain": "Taip ta'lo i password:",
-       "remembermypassword": "Na'hasso iyo-ku login gi este na komputer (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "Lugat-mu:",
        "login": "Log in",
        "nav-login-createaccount": "Hålom / fa'tinas kuenta-mu",
        "expensive-parserfunction-category": "Påhinas siha ni meggai mampos na inagang fungksion parser",
        "post-expand-template-inclusion-warning": "Adahi: Mampos dangkolo i mineddong muna'saonao plantiyas.\nTi para u na'saonao palu na plantiyas.",
        "post-expand-template-inclusion-category": "Påhina siha ni maloffan i mineddong muna'saonao plantiyas",
-       "cantcreateaccounttitle": "Ti siña mama'tinas kuenta",
        "cantcreateaccount-text": "Chinemma' mama'tinas kuenta ginen i IP ('''$1''') as [[User:$3|$3]].\n\nNina'i i rasion ''$2'' as $3",
        "viewpagelogs": "Atan i historian påhina",
        "nohistory": "Tåya' historian tinilaika este na påhina.",
index 71a2c6b..18887a3 100644 (file)
        "passwordreset": "ڕێکخستنەوەی تێپەڕوشە",
        "passwordreset-username": "ناوی بەکارھێنەری:",
        "passwordreset-domain": "پاوان:",
-       "passwordreset-capture": "بینینی ئیمەیڵی ئەنجام؟",
        "passwordreset-email": "ناونیشانی ئیمەیل:",
        "passwordreset-emailtitle": "وردەکارییەکانی ھەژمار لە {{SITENAME}}",
        "passwordreset-emailtext-ip": "‫کەسێک (لەوانەیە خۆت، بە ناونیشانی ئایپیی $1) داوای ڕیسێتکردنەوەی تێپەڕوشەکەت لە {{SITENAME}}دا ($4) کردووە. {{PLURAL:$3|ھەژماری بەکارھێنەریی ژێرەوە پەیوەندیی ھەیە|ھەژمارە بەکارھێنەرییەکانی ژێرەوە پەیوەندییان ھەیە}} بەم ناونیشانەی ئیمەیلەوە:\n\n$2\n\n{{PLURAL:$3|ئەم تێپەڕوشە کاتییە|ئەم تێپەڕوشە کاتییانە}} لە {{PLURAL:$5|ڕۆژێک|$5 ڕۆژ}}دا بەسەردەچێت.\nدەبێ بچیتە ژوورەوە و ھەر ئێستا تێپەڕوشەیەکی نوێ ھەڵبژێریت. ئەگەر کەسێکی تر ئەم داواکارییەی کردووە،\nیان ئەگەر تێپەڕوشە سەرەتاییەکەت ھاتووەتەوە بیرت و ئیتر ناتەوێ بیگۆڕی، دەتوانی گوێ بەم پەیامە نەدەیت و ھەر لە تێپەڕوشە کۆنەکەت کەڵک وەربگریت.",
        "searchprofile-advanced-tooltip": "گەڕان لەناو بۆشایی‌ناوە دڵخوازەکان",
        "search-result-size": "$1 ({{PLURAL:$2|یەک وشە|$2 وشە}})",
        "search-result-category-size": "{{PLURAL:$1|١ ئەندام|$1 ئەندام}} ({{PLURAL:$2|١ ژێرپۆل|$2 ژێرپۆل}}, {{PLURAL:$3|١ پەڕگە|$3 پەڕگە}})",
-       "search-redirect": "(ڕەوانەکەر $1)",
+       "search-redirect": "(ڕەوانەکراوە لە $1ەوە)",
        "search-section": "(بەشی $1)",
        "search-category": "(پۆلی $1)",
        "search-suggest": "ئایا مەبەستت ئەمە بوو: $1",
        "userrights-reason": "هۆکار:",
        "userrights-no-interwiki": "دەسەڵاتی گۆڕینی مافەکانی بەکارهێنەر لە ویکی‌یەکانی دیکەت نیە.",
        "userrights-nodatabase": "بنکەدراوی $1 بوونی نیە یا لەم شوێنە نیە.",
-       "userrights-nologin": "بۆ دانانی مافەکانی بەکارهێنەر دەبێ بە هەژماری بەڕێوبەری [[Special:UserLogin|بچیتە ژووروە]].",
-       "userrights-notallowed": "تۆ دەسەڵاتی دانان یان لابردنی مافەکانی بەکارھێنەرانت نییە.",
        "userrights-changeable-col": "ئەو گرووپانەی دەتوانی بیگۆڕی",
        "userrights-unchangeable-col": "ئەو گرووپانەی ناتوانی بیگۆڕی",
        "group": "گرووپ:",
        "right-siteadmin": "داخستن و کردنەوەی بنکەدراو",
        "right-override-export-depth": "هەناردنی لاپەڕەکان کە لاپەڕەکانی بەستەر پێ‌دراو تا قووڵایی 5 لەخۆ بگرێت",
        "right-sendemail": "ناردنی ئیمەیل بۆ بەکارھێنەرانی تر",
-       "right-passwordreset": "دیتنی ئیمەیلەکانی ڕێکخستنەوەی تێپەڕوشە",
        "right-managechangetags": "دروستکردن و سڕینەوەی [[Special:Tags|تاگەکان]] لە بنکەدراوە",
        "newuserlogpage": "لۆگی دروستکردنی بەکارھێنەر",
        "newuserlogpagetext": "ئەمە لۆگێکی دروستکردنی بەکارھێنەرە.",
        "activeusers-intro": "ئەمە لیستێکی ئەو بەکارھێنەرانەیە کە لە  $1 {{PLURAL:$1|ڕۆژ|ڕۆژ}}ی ڕابردوودا بە جۆرێک چالاکییەکیان ھەبووە.",
        "activeusers-count": "$1 {{PLURAL:$1|کردەوە}} لە دوایین {{PLURAL:$3|ڕۆژ|$3 ڕۆژ}}دا",
        "activeusers-from": "نیشاندانی بەکارھێنەران بە دەستپێکردن لە:",
-       "activeusers-hidebots": "بۆتەکان بشارەوە",
-       "activeusers-hidesysops": "بەڕێوبەران بشارەوە",
        "activeusers-noresult": "هیچ بەکارهێنەرێک نەدۆزرایەوە",
        "listgrouprights": "مافەکانی گرووپی بەکارھێنەر",
        "listgrouprights-summary": "ئەمە لیستێکە لە گرووپەکانی بەکارهێنەر لەسەر ئەم ویکی‌یە، دەگەڵ مافەکانی دەست‌پێ‌گەیشتنی هاوپەیوەندیان.\nلێرەدا لەوانەیە [[{{MediaWiki:Listgrouprights-helppage}}|زانیاری زیاترت]] دەست‌کەوێت سەبارەت بە مافە تاکەکەسیەکان.",
        "feedback-message": "پەیام:",
        "feedback-subject": "بابەت:",
        "feedback-submit": "ناردن",
-       "searchsuggest-search": "گەڕان",
+       "searchsuggest-search": "لە {{SITENAME}}دا بگەڕێ",
        "searchsuggest-containing": "بە لەبەرگرتنەوەی ...",
        "api-error-empty-file": "ئەو پەڕگەیە کە ناردووتە واڵا بوو.",
        "api-error-file-too-large": "ئەو پەڕگەیە ناردووتە زۆر گەورەیە.",
index 9eee086..457ee31 100644 (file)
        "post-expand-template-inclusion-warning": "'''Attenti:''' a dimensione di i mudelli inclusi è troppa maiò.\nParechji mudelli ùn seranu micca inclusi.",
        "post-expand-template-inclusion-category": "Pagine per e quale a dimensione di i mudelli inclusi supereghja a limita",
        "post-expand-template-argument-category": "Pagine cuntinenti argumenti di mudellu mancanti",
-       "cantcreateaccounttitle": "Registramentu micca pussibile",
        "currentrev": "Ultima revisione",
        "currentrev-asof": "Versione attuale di e $1",
        "revisionasof": "Versione di e $1",
index 9829a07..0899e65 100644 (file)
        "yourname": "Hayo (username):",
        "yourpassword": "Password:",
        "yourpasswordagain": "Liwata ka pindot ang password:",
-       "remembermypassword": "Dumduma ang pagsulod ko sa mini nga kompyuter (pinakadamu na ang $1 {{PLURAL:$1|adlaw|mga adlaw}})",
        "yourdomainname": "Imo domain:",
        "login": "Mag sulod",
        "nav-login-createaccount": "Magsulod / mag-ubra sang account",
index 4d8a73c..e48be9f 100644 (file)
        "yourpasswordagain": "Parolni bir daa yazıñız:",
        "createacct-yourpasswordagain": "Parolni tasdıqlav",
        "createacct-yourpasswordagain-ph": "Parolni bir daa yazıñız",
-       "remembermypassword": "Kirişimni bu kompyuterde hatırla (eñ çoq $1 {{PLURAL:$1|kün|kün}} içün)",
        "userlogin-remembermypassword": "Sistemada qalayım",
        "userlogin-signwithsecure": "Telükesiz bağlama qullanılsın",
        "yourdomainname": "Domen adıñız",
        "undo-failure": "Aradaki deñiştirmeler bir-birine kelişikli olmağanı içün deñiştirme lâğu etilip olamay.",
        "undo-norev": "Deñiştirme lâğu etilip olamaz, çünki o ya da yoq, ya da bar edi, amma yoq etilgen.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|muzakere]]) qullanıcısınıñ $1 nomeralı deñiştirmesini lâğu etüv.",
-       "cantcreateaccounttitle": "Esap yaratmaqnıñ iç çaresi yoq.",
        "cantcreateaccount-text": "Bu IP adresinden ('''$1''') esap yaratuv [[User:$3|$3]] tarafından blok etildi.\n\n$3 mına bu sebepni bildirdi: ''$2''",
        "viewpagelogs": "Bu saifeniñ jurnallarını köster",
        "nohistory": "Bu saifeniñ keçmiş versiyası yoq.",
index d3d8dbd..7c54e02 100644 (file)
        "views": "Zobrazení",
        "toolbox": "Nástroje",
        "tool-link-userrights": "Změnit uživatelské skupiny {{GENDER:$1|tohoto uživatele|této uživatelky}}",
+       "tool-link-userrights-readonly": "Zobrazit {{GENDER:$1|uživatelské}} skupiny",
        "tool-link-emailuser": "Poslat e-mail {{GENDER:$1|tomuto uživateli|této uživatelce}}",
        "userpage": "Prohlédnout si uživatelskou stránku",
        "projectpage": "Prohlédnout si stránku projektu",
        "passwordreset-emaildisabled": "E-mailové funkce byly na této wiki vypnuty.",
        "passwordreset-username": "Uživatelské jméno:",
        "passwordreset-domain": "Doména:",
-       "passwordreset-capture": "Prohlédnout si výsledný e-mail?",
-       "passwordreset-capture-help": "Pokud zaškrtnete toto políčko, bude e-mail (s dočasným heslem) kromě zaslání uživateli zobrazen i vám.",
        "passwordreset-email": "E-mailová adresa:",
        "passwordreset-emailtitle": "Informace k účtu na {{grammar:6sg|{{SITENAME}}}}",
        "passwordreset-emailtext-ip": "Někdo (patrně vy, z IP adresy $1) zažádal na {{grammar:6sg|{{SITENAME}}}} ($4) o nastavení nového hesla k vašemu účtu. K této adrese {{PLURAL:$3|je přiřazen následující účet|jsou přiřazeny následující účty}}:\n\n$2\n\n{{PLURAL:$3|Toto dočasné heslo|Tato dočasná hesla}} vyprší za {{PLURAL:$5|jeden den|$5 dny|$5 dnů}}.\nNyní byste se měli přihlásit a zvolit si nové heslo. Pokud tento požadavek poslal někdo jiný nebo jste si na své staré heslo vzpomněli, a nechcete ho tedy změnit, můžete tuto zprávu ignorovat a nadále používat původní heslo.",
        "passwordreset-emailelement": "Uživatelské jméno: \n$1\n\nDočasné heslo: \n$2",
        "passwordreset-emailsentemail": "Pokud je u vašeho účtu nastavena tato e-mailová adresa, bude vám zaslán e-mail pro získání nového hesla.",
        "passwordreset-emailsentusername": "Pokud je u tohoto účtu nastavena e-mailová adresa, bude vám zaslán e-mail pro získání nového hesla.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Byl odeslán e-mail|Byly odeslány e-maily}} pro získání nového hesla. Zde {{PLURAL:$1|jsou zobrazeny uživatelské jméno a heslo|je zobrazen seznam uživatelských jmen a hesel}}.",
-       "passwordreset-emailerror-capture2": "{{GENDER:$2|Uživateli|Uživatelce}} se nepodařilo odeslat e-mail: $1 Zde {{PLURAL:$3|jsou zobrazeny uživatelské jméno a heslo|je zobrazen seznam uživatelských jmen a hesel}}.",
        "passwordreset-nocaller": "Musí být uveden volající",
        "passwordreset-nosuchcaller": "Volající neexistuje: $1",
        "passwordreset-ignored": "Žádost o nové heslo nebyla zpracována. Možná není nakonfigurován žádný poskytovatel?",
-       "passwordreset-invalideamil": "Neplatná e-mailová adresa",
+       "passwordreset-invalidemail": "Neplatná e-mailová adresa",
        "passwordreset-nodata": "Nebylo zadáno uživatelské jméno ani e-mailová adresa",
        "changeemail": "Změna nebo odstranění e-mailové adresy",
        "changeemail-header": "Vyplněním tohoto formuláře můžete změnit svou e-mailovou adresu. Pokud chcete ze svého účtu odstranit vazbu na všechny e-mailové adresy, ponechte při odeslání formuláře novou e-mailovou adresu prázdnou.",
        "search-external": "Externí hledání",
        "searchdisabled": "<p>Omlouváme se. Plnotextové vyhledávání je dočasně nedostupné. Zatím můžete zkusit vyhledávání Googlem; je ale možné, že jeho výsledky nemusí být aktuální.</p>",
        "search-error": "Při hledání došlo k chybě: $1",
+       "search-warning": "Při hledání došlo k varování: $1",
        "preferences": "Nastavení",
        "mypreferences": "Nastavení",
        "prefs-edits": "Počet editací:",
        "prefs-help-recentchangescount": "Týká se posledních změn, historie stránek a protokolovacích záznamů.",
        "prefs-help-watchlist-token2": "Toto je tajný klíč k webovému kanálu vašich sledovaných stránek. Kdokoli, kdo bude tento klíč znát, bude moci váš seznam sledovaných stránek číst, takže ho nešiřte.\n[[Special:ResetTokens|Kliknutím sem ho můžete reinicializovat.]]",
        "savedprefs": "Nastavení byla uložena.",
-       "savedrights": "Práva {{GENDER:$1|uživatele|uživatelky}} $1 byla uložena.",
+       "savedrights": "Skupiny {{GENDER:$1|uživatele|uživatelky}} $1 byly uloženy.",
        "timezonelegend": "Časové pásmo:",
        "localtime": "Místní čas:",
        "timezoneuseserverdefault": "Použít časové pásmo wiki ($1)",
        "prefswarning-warning": "Provedli jste změny nastavení, které dosud nejsou uloženy. Pokud tuto stránku opustíte, aniž byste klikli na „$1“, vaše nastavení se nezmění.",
        "prefs-tabs-navigation-hint": "Tip: Pro přepínání mezi záložkami můžete používat šipky vlevo a vpravo.",
        "userrights": "Správa uživatelských skupin",
-       "userrights-lookup-user": "Spravovat uživatelské skupiny",
+       "userrights-lookup-user": "Vybrat uživatele",
        "userrights-user-editname": "Zadejte uživatelské jméno:",
-       "editusergroup": "Upravit {{GENDER:$1|uživatelské}} skupiny",
+       "editusergroup": "Načíst uživatelské skupiny",
        "editinguser": "Úprava práv {{GENDER:$1|uživatele|uživatelky}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Prohlížení práv {{GENDER:$1|uživatele|uživatelky}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Upravit uživatelské skupiny",
+       "userrights-viewusergroup": "Zobrazit uživatelské skupiny",
        "saveusergroups": "Uložit {{GENDER:$1|uživatelské}} skupiny",
        "userrights-groupsmember": "{{GENDER:$2|Člen|Členka}} {{PLURAL:$1|skupiny|skupin}}:",
        "userrights-groupsmember-auto": "Automaticky {{GENDER:$2|člen|členka}} {{PLURAL:$1|skupiny|skupin}}:",
        "userrights-reason": "Důvod:",
        "userrights-no-interwiki": "Nemáte povoleno měnit uživatelská práva na jiných wiki.",
        "userrights-nodatabase": "Databáze $1 neexistuje nebo není místní.",
-       "userrights-nologin": "Musíte se [[Special:UserLogin|přihlásit]] k účtu správce, abyste mohli měnit uživatelská práva.",
-       "userrights-notallowed": "Nemáte oprávnění měnit uživatelská práva.",
        "userrights-changeable-col": "Skupiny, které můžete měnit",
        "userrights-unchangeable-col": "Skupiny, které nemůžete měnit",
        "userrights-conflict": "Konflikt změn uživatelských práv! Zkontrolujte a potvrďte požadované změny.",
-       "userrights-removed-self": "Odebrali jste si vlastní práva. Tudíž už nemáte k této stránce přístup.",
        "group": "Skupina:",
        "group-user": "Uživatelé",
        "group-autoconfirmed": "Automaticky schválení uživatelé",
        "right-siteadmin": "Zamykání a odemykání databáze",
        "right-override-export-depth": "Exportovat stránky včetně odkazovaných stránek až do hloubky 5",
        "right-sendemail": "Odesílání e-mailů ostatním uživatelům",
-       "right-passwordreset": "Prohlížení e-mailů pro znovunastavení hesla",
        "right-managechangetags": "Vytváření a (de)aktivace [[Special:Tags|značek]]",
        "right-applychangetags": "Přidávání [[Special:Tags|značek]] k vlastním změnám",
        "right-changetags": "Přidávání libovolných [[Special:Tags|značek]] na jednotlivé revize a protokolovací záznamy a jejich odebírání",
        "apisandbox-continue": "Pokračovat",
        "apisandbox-continue-clear": "Vymazat",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} bude [https://www.mediawiki.org/wiki/API:Query#Continuing_queries pokračovat] v posledním požadavku; {{int:apisandbox-continue-clear}} vymaže parametry související s pokračováním.",
+       "apisandbox-param-limit": "Pro použití maximálního limitu zadejte <kbd>max</kbd>.",
+       "apisandbox-multivalue-all-namespaces": "$1 (všechny jmenné prostory)",
+       "apisandbox-multivalue-all-values": "$1 (všechny hodnoty)",
        "booksources": "Zdroje knih",
        "booksources-search-legend": "Vyhledat knižní zdroje",
        "booksources-search": "Hledat",
        "booksources-text": "Níže je seznam odkazů na servery prodávající knihy, nebo které mohou mít další informace o knihách, které hledáte.",
        "booksources-invalid-isbn": "Zadané ISBN se zdá být neplatné. Zkontrolujte jej s originálním zdrojem.",
-       "magiclink-tracking-rfc": "Stránky používající kouzelné odkazy RFC",
+       "magiclink-tracking-rfc": "Stránky obsahující kouzelné odkazy RFC",
        "magiclink-tracking-rfc-desc": "Tato stránka používá kouzelné odkazy RFC. Více informací k migraci najdete na [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
-       "magiclink-tracking-pmid": "Stránky používající kouzelné odkazy PMID",
+       "magiclink-tracking-pmid": "Stránky obsahující kouzelné odkazy PMID",
        "magiclink-tracking-pmid-desc": "Tato stránka používá kouzelné odkazy PMID. Více informací k migraci najdete na [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
-       "magiclink-tracking-isbn": "Stránky používající kouzelné odkazy ISBN",
+       "magiclink-tracking-isbn": "Stránky obsahující kouzelné odkazy ISBN",
        "magiclink-tracking-isbn-desc": "Tato stránka používá kouzelné odkazy ISBN. Více informací k migraci najdete na [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
        "specialloguserlabel": "Původce:",
        "speciallogtitlelabel": "Cíl (název nebo {{ns:user}}:Jméno pro uživatele):",
        "activeusers-count": "$1 {{PLURAL:$1|akce|akce|akcí}} během {{PLURAL:$3|posledního dne|posledních $3 dnů}}",
        "activeusers-from": "Zobrazit uživatele počínaje od:",
        "activeusers-groups": "Zobrazit uživatele patřící do skupin:",
+       "activeusers-excludegroups": "Nezobrazovat uživatele patřící do skupin:",
        "activeusers-noresult": "Nenalezen žádný uživatel.",
        "activeusers-submit": "Zobrazit aktivní uživatele",
        "listgrouprights": "Práva skupin uživatelů",
        "tags-deactivate": "deaktivovat",
        "tags-hitcount": "$1 {{PLURAL:$1|změna|změny|změn}}",
        "tags-manage-no-permission": "Nemáte oprávnění spravovat značky pro změny.",
-       "tags-manage-blocked": "Nemůžete spravovat značky, když jste {{GENDER:|zablokován|zablokována|zablokováni}}.",
+       "tags-manage-blocked": "Nemůžete spravovat značky, když jste {{GENDER:$1|zablokován|zablokována|zablokováni}}.",
        "tags-create-heading": "Vytvořit novou značku",
        "tags-create-explanation": "Nově vytvořené značky jsou implicitně k dispozici uživatelům a botům.",
        "tags-create-tag-name": "Název značky:",
        "tags-deactivate-not-allowed": "Značku „$1“ nelze deaktivovat.",
        "tags-deactivate-submit": "Deaktivovat",
        "tags-apply-no-permission": "Nemáte oprávnění přidávat značky k vlastním změnám",
-       "tags-apply-blocked": "Nemůžete ke svým změnám přidávat značky, když jste {{GENDER:|zablokován|zablokována|zablokováni}}.",
+       "tags-apply-blocked": "Nemůžete ke svým změnám přidávat značky, když jste {{GENDER:$1|zablokován|zablokována|zablokováni}}.",
        "tags-apply-not-allowed-one": "Značku „$1“ není dovoleno ručně přidávat.",
        "tags-apply-not-allowed-multi": "Následující {{PLURAL:$2|značku|značky}} není dovoleno ručně přidávat: $1",
        "tags-update-no-permission": "Nemáte oprávnění přidávat libovolné značky na jednotlivé revize a protokolovací záznamy a odebírat je",
-       "tags-update-blocked": "Nemůžete přidávat nebo odebírat značky, když jste {{GENDER:|zablokován|zablokována|zablokováni}}.",
+       "tags-update-blocked": "Nemůžete přidávat nebo odebírat značky, když jste {{GENDER:$1|zablokován|zablokována|zablokováni}}.",
        "tags-update-add-not-allowed-one": "Značku „$1“ není dovoleno ručně přidávat.",
        "tags-update-add-not-allowed-multi": "Následující {{PLURAL:$2|značku|značky}} není dovoleno ručně přidávat: $1",
        "tags-update-remove-not-allowed-one": "Značku „$1“ není dovoleno odebírat.",
        "htmlform-user-not-exists": "Uživatel <strong>$1</strong> neexistuje.",
        "htmlform-user-not-valid": "<strong>$1</strong> není platné uživatelské jméno.",
        "logentry-delete-delete": "$1 {{GENDER:$2|smazal|smazala}} stránku $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|smazal|smazala}} přesunem přesměrování $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|obnovil|obnovila}} stránku $3",
        "logentry-delete-event": "$1 {{GENDER:$2|změnil|změnila}} viditelnost {{PLURAL:$5|protokolovacího záznamu|$5 protokolovacích záznamů}} ke stránce $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|změnil|změnila}} viditelnost {{PLURAL:$5|revize|$5 revizí}} stránky $3: $4",
        "mw-widgets-dateinput-no-date": "Nevybráno žádné datum",
        "mw-widgets-dateinput-placeholder-day": "RRRR-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "RRRR-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Hledat média",
+       "mw-widgets-mediasearch-noresults": "Nebyly nalezeny žádné výsledky.",
        "mw-widgets-titleinput-description-new-page": "stránka zatím neexistuje",
        "mw-widgets-titleinput-description-redirect": "přesměrování na $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Přidat kategorii…",
        "sessionmanager-tie": "Nelze kombinovat několik typů autentizace požadavků: $1.",
        "sessionprovider-generic": "relace pomocí $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "relace pomocí cookies",
        "log-action-filter-contentmodel-change": "Změna modelu obsahu",
        "log-action-filter-contentmodel-new": "Založení stránky s nestandardním modelem obsahu",
        "log-action-filter-delete-delete": "Smazání stránky",
+       "log-action-filter-delete-delete_redir": "Smazání přesměrování",
        "log-action-filter-delete-restore": "Obnovení stránky",
        "log-action-filter-delete-event": "Smazání záznamu",
        "log-action-filter-delete-revision": "Smazání revize",
        "usercssispublic": "Uvědomte si prosím, že podstránky s CSS by neměly obsahovat tajné údaje, protože jsou viditelné ostatním uživatelům.",
        "restrictionsfield-badip": "Neplatná IP adresa nebo rozsah: $1",
        "restrictionsfield-label": "Povolené rozsahy IP adres:",
-       "restrictionsfield-help": "Jedna IP adresa nebo CIDR rozsah na řádek. Všechno povolíte pomocí<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Chyba: $1",
-       "edit-error-long": "Chyby:\n\n$1"
+       "restrictionsfield-help": "Jedna IP adresa nebo CIDR rozsah na řádek. Všechno povolíte pomocí<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 44f9503..8877f73 100644 (file)
        "yourname": "Miono brëkòwnika",
        "yourpassword": "Twòja parola",
        "yourpasswordagain": "Pòwtórzë parolã",
-       "remembermypassword": "Spamiãtôj mòją parolã na tim kòmpùtrze (maksymalno przez $1 {{PLURAL:$1|dzéń|dni|dniów}})",
        "yourdomainname": "Twòjô domena",
        "login": "Wlogùjë mie",
        "nav-login-createaccount": "Logòwanié",
index d614209..7b44e84 100644 (file)
        "userlogin-yourname": "Усă куракан ят",
        "yourpassword": "Вăрттăн сăмах:",
        "yourpasswordagain": "Вăрттăн сăмах тепре çырăр:",
-       "remembermypassword": "Ку компьютер çинче мана астуса хăвармалла (for a maximum of $1 {{PLURAL:$1|1=day|days}})",
        "yourdomainname": "Сирĕн доменă:",
        "login": "Кĕрĕр",
        "nav-login-createaccount": "Сайта кĕр / регистрацилен",
        "post-expand-template-argument-category": "Шаблон аргуменчĕсене сиктерсе хăварнă страницăсем",
        "undo-norev": "Ку тӳрлетĕве пăрахăçлама май çук — вăл е пулман та, е ăна кăларса пăрахнă.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|сӳтсе яв]]) $1 улăштарнине тавăрчĕ",
-       "cantcreateaccounttitle": "Хутшăнакана кĕртме май çук",
        "viewpagelogs": "Ку страницăн журналĕсене пăхмалли",
        "nohistory": "Ку страницăн улшăнусен журналĕ çук.",
        "currentrev": "Хальхи верси",
        "listusers-noresult": "Хутшăнакансем тупăнмарĕç.",
        "listusers-blocked": "(чарса хунă)",
        "activeusers-count": "$1 {{PLURAL:$1|тӳрлетни|тӳрлетнисем}} юлашки {{PLURAL:$3|кун|$3 кунсенче}}",
-       "activeusers-hidesysops": "Администраторĕсене пытар",
        "listgrouprights-group": "Ушкăн",
        "listgrouprights-helppage": "Help:Ушкăн прависем",
        "listgrouprights-members": "(хутшăнакансен списокĕ)",
index ceb726e..1ef05f9 100644 (file)
        "passwordreset-emailelement": "Enw'r defnyddiwr: \n$1\n\nY cyfrinair dros dro: \n$2",
        "passwordreset-emailsentemail": "Anfonwyd e-bost i ailosod eich cyfrinair atoch.",
        "passwordreset-ignored": "Ailosod y cyfrinair nad ymdriniwyd â. Efallai y nid y darparwr yn osod?",
-       "passwordreset-invalideamil": "Cyfeiriad e-bost annilys",
+       "passwordreset-invalidemail": "Cyfeiriad e-bost annilys",
        "changeemail": "Newid y cyfeiriad e-bost",
        "changeemail-header": "Cwbwlhewch y ffurflen hon i newid cyfeiriad e-bost y cyfrifi. I ddileu pob cysylltiad i bob cyfeiriad ebost, gadewch e'n wag.",
        "changeemail-no-info": "Ni allwch fynd at y dudalen hon heblaw eich bod wedi mewngofnodi.",
        "activeusers-intro": "Dyma restr y defnyddwyr a fuont yn weithgar o fewn y {{PLURAL:$1|diwrnod|diwrnod|deuddydd|tridiau|$1 diwrnod|$1 diwrnod}} diwethaf.",
        "activeusers-count": "$1 {{PLURAL:$1|golygiad|golygiad|olygiad|golygiad}} yn ystod y {{PLURAL:$3|diwrnod|diwrnod|deuddydd|tridiau|$3 diwrnod}} diwethaf",
        "activeusers-from": "Rhestru'r defnyddwyr gan ddechrau gyda:",
-       "activeusers-hidebots": "Cuddio botiau",
-       "activeusers-hidesysops": "Cuddio gweinyddwyr",
        "activeusers-noresult": "Dim defnyddwyr i'w cael.",
        "activeusers-submit": "Dangos defnyddwyr byw",
        "listgrouprights": "Galluoedd grwpiau defnyddwyr",
index df0b4e1..5b56d6d 100644 (file)
@@ -58,7 +58,8 @@
                        "Ribewiki",
                        "Jens Jensen",
                        "Nemo bis",
-                       "Anders Feder"
+                       "Anders Feder",
+                       "Jhertel"
                ]
        },
        "tog-underline": "Understreg henvisninger:",
        "talk": "Diskussion",
        "views": "Visninger",
        "toolbox": "Værktøjer",
+       "tool-link-userrights": "Ændre {{GENDER:$1|bruger}}grupper",
+       "tool-link-userrights-readonly": "Se {{GENDER:$1|bruger}}grupper",
+       "tool-link-emailuser": "Send e-mail til denne {{GENDER:$1|bruger}}",
        "userpage": "Se brugersiden",
        "projectpage": "Se projektsiden",
        "imagepage": "Se filside",
        "createacct-yourpasswordagain-ph": "Indtast adgangskode igen",
        "userlogin-remembermypassword": "Husk mig",
        "userlogin-signwithsecure": "Brug sikker forbindelse",
+       "cannotlogin-title": "Kan ikke logge ind",
+       "cannotlogin-text": "Det er ikke muligt at logge ind.",
        "cannotloginnow-title": "Kan ikke logge ind på nuværende tidspunkt",
        "cannotloginnow-text": "Det er ikke muligt at logge på når du bruger $1.",
+       "cannotcreateaccount-title": "Kan ikke oprette konti",
+       "cannotcreateaccount-text": "Direkte kontooprettelse er ikke aktiveret på denne wiki.",
        "yourdomainname": "Dit domænenavn:",
        "password-change-forbidden": "Du kan ikke ændre adgangskoder på denne wiki.",
        "externaldberror": "Der er opstået en fejl i en ekstern adgangsdatabase, eller du har ikke rettigheder til at opdatere denne.",
        "createaccountreason": "Begrundelse:",
        "createacct-reason": "Årsag",
        "createacct-reason-ph": "Hvorfor du vil oprette endnu en konto",
+       "createacct-reason-help": "Besked vist i kontooprettelsesloggen.",
        "createacct-submit": "Opret din konto",
        "createacct-another-submit": "Opret konto",
+       "createacct-continue-submit": "Fortsæt kontooprettelse",
+       "createacct-another-continue-submit": "Fortsæt kontooprettelse",
        "createacct-benefit-heading": "{{SITENAME}} laves af mennesker som dig.",
        "createacct-benefit-body1": "{{PLURAL:$1|redigering|redigeringer}}",
        "createacct-benefit-body2": "{{PLURAL:$1|side|sider}}",
        "nocookiesnew": "Din brugerkonto er nu oprettet, men du er ikke logget på. {{SITENAME}} bruger cookies til at logge brugere på.\nDu har slået cookies fra. \nVær venlig at slå cookies til og log derefter på med dit nye brugernavn og adgangskode.",
        "nocookieslogin": "{{SITENAME}} bruger cookies til at logge brugere på. Du har slået cookies fra. Slå dem venligst til og prøv igen.",
        "nocookiesfornew": "Denne brugerkonto er ikke oprettet, da vi ikke kunne bekræfte dens kilde.\nSørg for, at du har aktivereret cookies, genindlæs siden og prøv igen.",
+       "createacct-loginerror": "Kontoen blev oprettet, men du kunne ikke blive logget ind automatisk. Fortsæt venligst til [[Special:UserLogin|manuel log ind]].",
        "noname": "Du har ikke angivet et gyldigt brugernavn.",
-       "loginsuccesstitle": "Du er nu logget på",
+       "loginsuccesstitle": "Logget ind",
        "loginsuccess": "'''Du er nu logget på {{SITENAME}} som \"$1\".'''",
        "nosuchuser": "Der er ingen bruger med navnet \"$1\".\nDer skelnes mellem store og bogstaver i brugernavne.\nKontrollér stavemåden, eller [[Special:CreateAccount|opret en ny konto]].",
        "nosuchusershort": "Der er ingen bruger ved navn \"$1\". Tjek din stavning.",
        "passwordreset-emaildisabled": "E-mailfunktioner er slået fra på denne wiki.",
        "passwordreset-username": "Brugernavn:",
        "passwordreset-domain": "Domæne:",
-       "passwordreset-capture": "Se den resulterende e-mail?",
-       "passwordreset-capture-help": "Hvis du krydser dette felt af, vil e-mailen (med den midlertidige adgangskode) blive vist til dig i tillæg til at blive sendt til brugeren.",
        "passwordreset-email": "E-mailadresse:",
        "passwordreset-emailtitle": "Kontooplysninger på {{SITENAME}}",
        "passwordreset-emailtext-ip": "Nogen (sandsynligvis dig, fra IP-adressen $1) har anmodet om at få nulstillet din adgangskode til {{SITENAME}} ($4). {{PLURAL:$3|Den følgende brugerkonto er associeret|De følgende brugerkonti er associerede}} med denne e-mailadresse:\n\n$2\n\n{{PLURAL:$3|Denne midlertidige adgangskode|Disse midlertidige adgangskoder}} vil udløbe om {{PLURAL:$5|en dag|$5 dage}}.\nDu bør logge på og vælge en ny adgangskode nu. Hvis en anden end dig har lavet denne anmodning, eller hvis du er kommet i tanke om din oprindelig adgangskode og ikke længere ønsker at ændre den, kan du ignorere denne meddelelse og fortsætte med at bruge din gamle adgangskode.",
        "changeemail-password": "Din adgangskode til {{SITENAME}}:",
        "changeemail-submit": "Ændre e-mail",
        "changeemail-throttled": "Du har forsøgt at logge på for mange gange.\nVent venligst $1, før du prøver igen.",
+       "changeemail-nochange": "Angiv venligst en anden ny e-mailadresse.",
        "resettokens": "Nulstil nøgler",
        "resettokens-text": "Du kan nulstille nøgler, som giver adgang til visse private data i forbindelse med din konto her.\n\nDu bør gøre det, hvis du ved et uheld deler dem med nogen, eller hvis din konto er blevet kompromitteret.",
        "resettokens-no-tokens": "Der er ingen nøgler at nulstille.",
        "missingcommenttext": "Skriv venligst en kommentar nedenfor.",
        "missingcommentheader": "<strong>Bemærk:</strong> Du har ikke angivet en overskrift/emne for denne kommentar. Hvis du trykker \"{{int:savearticle}}\" én gang til, gemmes dine ændringer uden overskrift/emne.",
        "summary-preview": "Forhåndsvisning af beskrivelsen:",
-       "subject-preview": "Forhåndsvisning af emnet:",
+       "subject-preview": "Forhåndsvisning af emne/overskrift:",
        "previewerrortext": "Der opstod en fejl under forsøget på at lave en forhåndsvisning af dine ændringer.",
        "blockedtitle": "Du eller din IP-adresse er blokeret",
        "blockedtext": "'''Dit brugernavn eller din IP-adresse er blevet blokeret.'''\n\nBlokeringen er foretaget af $1.\nDen anførte grund er ''$2''.\n\nBlokeringen starter: $8\nBlokeringen udløber: $6\nBlokeringen er rettet mod: $7\n\nDu kan kontakte $1 eller en af de andre [[{{MediaWiki:Grouppage-sysop}}|administratorer]] for at diskutere blokeringen.\nDu kan ikke bruge funktionen 'e-mail til denne bruger' medmindre der er angivet en gyldig e-mailadresse i dine\n[[Special:Preferences|kontoindstillinger]], og du ikke er blevet blokeret fra at bruge den.\n\nDin nuværende IP-adresse er $3, og blokerings-id er #$5.\nAngiv venligst alle ovenstående detaljer ved henvendelser om blokeringen.",
        "accmailtext": "En tilfældigt dannet adgangskode for [[User talk:$1|$1]] er sendt til $2. Den kan ændres på siden ''[[Special:ChangePassword|skift adgangskode]]'', når du logger på.",
        "newarticle": "(Ny)",
        "newarticletext": "Du har fulgt en henvisning til en side som endnu ikke findes.\nFor at oprette siden skal du begynde at skrive i boksen nedenfor\n(se [$1 hjælpesiden] for yderligere information).\nHvis du er her ved en fejl, så tryk på din browsers '''tilbage'''-knap.",
-       "anontalkpagetext": "---- ''Dette er en diskussionsside for en anonym bruger, der ikke har oprettet en konto endnu eller ikke bruger den.\nVi er derfor nødt til at bruge den numeriske IP-adresse til at identificere ham eller hende.\nEn IP-adresse kan være delt mellem flere brugere.\nHvis du er en anonym bruger og synes, at du har fået irrelevante kommentarer på sådan en side, så vær venlig at [[Special:CreateAccount|oprette en brugerkonto]] og [[Special:UserLogin|logge på]], så vi undgår fremtidige forvekslinger med andre anonyme brugere.''",
+       "anontalkpagetext": "----\n<em>Dette er en diskussionsside for en anonym bruger, der ikke har oprettet en konto endnu eller ikke bruger den.</em>\nVi er derfor nødt til at bruge den numeriske IP-adresse til at identificere vedkommende.\nEn sådan IP-adresse kan være delt mellem flere brugere.\nHvis du er en anonym bruger og synes, at irrelevante kommentarer er blevet rettet mod dig, så [[Special:CreateAccount|opret en brugerkonto]] eller [[Special:UserLogin|log på]] for at undgå fremtidige forvekslinger med andre anonyme brugere.",
        "noarticletext": "Der er i øjeblikket ikke nogen tekst på denne side.\nDu kan [[Special:Search/{{PAGENAME}}|søge efter sidenavnet]] på andre sider,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} søge i relaterede logger]\neller [{{fullurl:{{FULLPAGENAME}}|action=edit}} oprette siden]</span>.",
        "noarticletext-nopermission": "Der er i øjeblikket ikke nogen tekst på denne side.\nDu kan [[Special:Search/{{PAGENAME}}|søge efter sidenavnet]] på andre sider,\neller <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} søge i relaterede loglister]</span>,\nmen du har ikke tilladelse til at oprette denne side.",
        "missing-revision": "Revision #$1 af siden med navnet \"{{FULLPAGENAME}}\" eksisterer ikke.\n\nDette skyldes normalt at et forældet historik-link er fulgt til en side der er slettet.\nDetaljer kan findes i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} sletningsloggen].",
        "userpage-userdoesnotexist": "Brugerkontoen \"<nowiki>$1</nowiki>\" findes ikke. Overvej om du ønsker at oprette eller redigere denne side.",
        "userpage-userdoesnotexist-view": "Brugerkontoen \"$1\" er ikke oprettet.",
        "blocked-notice-logextract": "Denne bruger er i øjeblikket blokeret.\nLoggen over den seneste blokering ses nedenfor:",
-       "clearyourcache": "'''Bemærk:''' Efter at have gemt er du måske nødt til at tømme din browsers cache for at kunne se ændringerne.\n* '''Firefox / Safari:''' Hold ''Shift'' nede og klik på ''Reload'', eller tryk enten ''Ctrl-F5'' eller ''Ctrl-R'' (''⌘-R'' på en Mac).\n* '''Google Chrome:''' Tryk ''Ctrl-Shift-R'' (''⌘-Shift-R'' på en Mac).\n* '''Internet Explorer:''' Hold ''Ctrl'' nede og klik på ''Refresh'' eller tryk på ''Ctrl-F5''.\n* '''Opera:''' Tøm cachen i ''Tools → Preferences''.",
+       "clearyourcache": "<strong>Bemærk:</strong> Efter at have gemt er du måske nødt til at tømme din browsers cache for at kunne se ændringerne.\n* <strong>Firefox / Safari:</strong> Hold <em>Shift</em> nede og klik på <em>Reload</em>, eller tryk enten <em>Ctrl-F5</em> eller <em>Ctrl-R</em> (<em>⌘-R</em> på en Mac).\n* <strong>Google Chrome:</strong> Tryk <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> på en Mac).\n* <strong>Internet Explorer:</strong> Hold <em>Ctrl</em> nede og klik på <em>Refresh</em>, eller tryk på <em>Ctrl-F5</em>.\n* <strong>Opera:</strong> Go to <em>Menu → Settings</em> (<em>Opera → Preferences</em> on a Mac) and then to <em>Privacy & security → Clear browsing data → Cached images and files</em>",
        "usercssyoucanpreview": "'''Tip:''' Brug \"{{int:showpreview}}\"-knappen for at teste dit nye CSS inden du gemmer.",
        "userjsyoucanpreview": "'''Tip:''' Brug \"{{int:showpreview}}\"-knappen for at teste dit nye JavaScript inden du gemmer.",
        "usercsspreview": "'''Husk at dette kun er en forhåndsvisning af dit eget css.\n'''Det er ikke gemt endnu!'''",
        "previewnote": "'''Husk at dette er kun en forhåndsvisning.'''\nDine ændringer er endnu ikke blevet gemt!",
        "continue-editing": "Gå til redigeringsfeltet",
        "previewconflict": "Denne forhåndsvisning er resultatet af den redigérbare tekst ovenfor, sådan vil det komme til at se ud hvis du vælger at gemme teksten.",
-       "session_fail_preview": "'''Din ændring kunne ikke gemmes, da dine sessionsdata er gået tabt.\nPrøv venligst igen. Hvis problemet fortsætter, log af og log på igen.'''",
-       "session_fail_preview_html": "'''Din ændring kunne ikke gemmes, da dine sessionsdata er gået tabt.'''\n\n''Da ren HTM er aktiveret i denne Wiki, er forhåndsvisningen blændet ud for at forebygge JavaScript-angreb.''\n\n'''Forsøg venligst igen. Hvis problemet fortsætter, log af og log på igen.'''",
+       "session_fail_preview": "Beklager! Vi kunne ikke behandle din redigering på grund af et tab af sessionsdata.\n\nDu er måske blevet logget ud. <strong>Kontroller venligst, at du stadig er logget ind, og prøv så igen</strong>.\nHvis det stadig ikke virker, så prøv at [[Special:UserLogout|logge ud]] og logge ind igen. Du kan også kontrollere, at din browser tillader cookies fra dette websted.",
+       "session_fail_preview_html": "Beklager! Vi kunne ikke behandle din redigering på grund af et tab af sessionsdata.\n\n<em>Fordi {{SITENAME}} har rå HTML aktiveret, er forhåndsvisningen skjult som en sikkerhedsforanstaltning mod JavaScript-angreb.</em>\n\n<strong>Hvis dette er et legitimt forsøg på redigere, så prøv venligst igen.</strong>\nHvis det stadig ikke virker, så prøv at [[Special:UserLogout|logge ud]] og logge ind igen. Du kan også kontrollere, at din browser tillader cookies fra dette websted.",
        "token_suffix_mismatch": "'''Din redigering er afvist, da din browser har forvansket tegnsætningen i redigeringskontrolfilen. Afvisningen sker for at forhindre utilsigtede ændringer i artiklen. Denne fejl opstår nogle gange, når du redigerer gennem en fejlprogrammeret webbaseret anonymiseringstjeneste.'''",
        "edit_form_incomplete": "'''Nogle dele af redigeringsformularen nåede ikke serveren; dobbelttjek, at redigeringerne er intakte, og prøv igen.'''",
        "editing": "Redigerer $1",
        "yourdiff": "Forskelle",
        "copyrightwarning": "Bemærk venligst at alle bidrag til {{SITENAME}} er at betragte som udgivne under $2 (se $1 for detaljer).\nHvis du ikke ønsker at din tekst skal udsættes for nådesløse redigeringer og at den kan blive kopieret efter forgodtbefindende, så skal du ikke placere den her.<br />\nDu lover os også, at du selv har forfattet teksten eller har kopieret den fra en public domain-kilde eller en tilsvarende fri kilde.\n'''Læg aldrig materiale her som er beskyttet af andres ophavsret uden deres tilladelse!'''",
        "copyrightwarning2": "Bemærk venligst at alle bidrag til {{SITENAME}} kan bearbejdes, ændres eller slettes af andre brugere.\nLæg ingen tekster ind, hvis du ikke kan acceptere at disse kan ændres.\n\nDu bekræfter hermed også, at du selv har skrevet denne tekst eller kopieret den fra en fri kilde (se $1 for detaljer).\n'''OVERFØR IKKE OPHAVSRETSLIGT BESKYTTET INDHOLD UDEN TILLADELSE!'''",
+       "editpage-cannot-use-custom-model": "Indholdsmodellen for denne side kan ikke ændres.",
        "longpageerror": "'''Fejl: Teksten, som du ville gemme, er {{PLURAL:$1|en kilobyte|$1 kilobytes}} stor, hvilket er mere end det tilladte maksimum på {{PLURAL:$2|en kilobyte|$2 kilobytes}}.'''\nDet er ikke muligt at gemme den.",
-       "readonlywarning": "'''Advarsel: Databasen er låst på grund af vedligeholdelse, så du kan ikke gemme dine ændringer lige nu.'''\nDet kan godt være en god ide at kopiere din tekst til en tekstfil, så du kan gemme den til senere.\n\nAdministratoren som låste databasen, gav denne forklaring: $1",
+       "readonlywarning": "<strong>Advarsel: Databasen er låst på grund af vedligeholdelse, så du kan ikke gemme dine ændringer lige nu.</strong>\nDet kan være en god idé at kopiere din tekst over i en tekstfil og gemme den til senere.\n\nAdministratoren, som låste databasen, gav denne forklaring: $1",
        "protectedpagewarning": "'''ADVARSEL: Denne side er skrivebeskyttet, så kun administratorer kan redigere den.'''<br />\nDen seneste logpost vises nedenfor:",
        "semiprotectedpagewarning": "'''Bemærk: Siden er låst, så kun registrerede brugere kan ændre den.'''\n<br />Den seneste logpost vises nedenfor:",
        "cascadeprotectedwarning": "<strong>Advarsel:</strong> Denne side er blevet beskyttet, så den kun kan ændres af brugere med administratorrettigheder, fordi indholdet er inkluderet i følgende {{PLURAL:$1|side|sider}} med nedarvet sidebeskyttelse:",
        "prefswarning-warning": "Du har foretaget ændringer af dine indstillinger, som ikke er gemt endnu.\nHvis du forlader denne side uden at klikke \"$1\", vil dine indstillinger ikke blive opdateret.",
        "prefs-tabs-navigation-hint": "Tip: Du kan bruge venstre og højre piletasterne til at navigere mellem fanerne i fanelisten.",
        "userrights": "Håndtering af brugerrettigheder",
-       "userrights-lookup-user": "Administrér brugergrupper",
+       "userrights-lookup-user": "Vælg en bruger",
        "userrights-user-editname": "Skriv et brugernavn:",
-       "editusergroup": "Redigér {{GENDER:$1|brugergrupper}}",
+       "editusergroup": "Indlæs brugergrupper",
        "editinguser": "Ændrer brugerrettigheder for {{GENDER:$1|brugeren}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Redigér brugergrupper",
        "saveusergroups": "Gem {{GENDER:$1|brugergrupper}}",
        "userrights-reason": "Årsag:",
        "userrights-no-interwiki": "Du har ikke tilladelse til at redigere brugerrettigheder på andre wikier.",
        "userrights-nodatabase": "Databasen $1 eksisterer ikke lokalt.",
-       "userrights-nologin": "Du skal [[Special:UserLogin|logge på]] med en administrativ konto, før du kan ændre brugerrettigheder.",
-       "userrights-notallowed": "Du har ikke tilladelse til at tilføje eller fjerne brugerrettigheder.",
        "userrights-changeable-col": "Redigerbare grupper",
        "userrights-unchangeable-col": "Uredigerbare grupper",
        "userrights-conflict": "Konflikt i ændringer af brugerrettigheder!\nVær venlig at gennemse og bekræft dine ændringer.",
-       "userrights-removed-self": "Du har fjernet dine egne rettigheder. Du har derfor ikke længere adgang til denne side.",
        "group": "Gruppe:",
        "group-user": "Brugere",
        "group-autoconfirmed": "Registrerede brugere",
        "right-createpage": "Oprette andre sider end diskussionssider",
        "right-createtalk": "Oprette diskussionssider",
        "right-createaccount": "Oprette nye brugere",
+       "right-autocreateaccount": "Log automatisk ind med en ekstern brugerkonto",
        "right-minoredit": "Markere redigeringer som mindre",
        "right-move": "Flytte sider",
        "right-move-subpages": "Flytte sider og undersider",
        "right-siteadmin": "Låse og frigive databasen",
        "right-override-export-depth": "Eksportere sider inkl. henviste sider op til en dybde på 5",
        "right-sendemail": "Sende e-mail til andre brugere",
-       "right-passwordreset": "Se e-mails til nulstilling af adgangskoder",
-       "right-managechangetags": "Oprette og slette [[Special:Tags|tags]] fra databasen",
+       "right-managechangetags": "Opret og (de)aktivér [[Special:Tags|tags]]",
        "right-applychangetags": "Tilføje [[Special:Tags|tags]] sammen med ens ændringer",
        "right-changetags": "Tilføje og fjerne vilkårlige [[Special:Tags|tags]] for enkelte versioner og logposter",
+       "right-deletechangetags": "Slet [[Special:Tags|tags]] fra databasen",
+       "grant-generic": "Rettighedspakke \"$1\"",
+       "grant-group-page-interaction": "Interagere med sider",
+       "grant-group-file-interaction": "Interagere med medier",
+       "grant-group-watchlist-interaction": "Interagere med din overvågningsliste",
+       "grant-group-email": "Sende e-mail",
+       "grant-group-high-volume": "Udføre højvolumenaktivitet",
+       "grant-group-customization": "Tilpasning og indstillinger",
+       "grant-group-administration": "Udføre administrative handlinger",
+       "grant-group-private-information": "Tilgå private oplysninger om dig",
+       "grant-group-other": "Diverse aktivitet",
+       "grant-blockusers": "Blokering og ophævelse af blokering af brugere",
+       "grant-createaccount": "Oprette af konti",
+       "grant-createeditmovepage": "Oprette, redigere og flytte sider",
+       "grant-delete": "Slette sider, revisioner og logposter",
+       "grant-editinterface": "Redigere MediaWiki-navnerummet og bruger-CSS/JavaScript",
+       "grant-editmycssjs": "Redigere din bruger-CSS/JavaScript",
+       "grant-editmyoptions": "Redigere dine brugerindstillinger",
+       "grant-editmywatchlist": "Redigere din overvågningsliste",
+       "grant-editpage": "Redigere eksisterende sider",
+       "grant-editprotected": "Redigere beskyttede sider",
+       "grant-highvolume": "Højvolumen-redigering",
+       "grant-oversight": "Skjule brugere og undertrykke revisioner",
+       "grant-patrol": "Patruljere sideændringer",
+       "grant-privateinfo": "Tilgå private oplysninger",
+       "grant-protect": "Beskytte og fjerne beskyttelsen af sider",
+       "grant-rollback": "Tilbagerulle ændringer til sider",
+       "grant-sendemail": "Sende e-mail til andre brugere",
+       "grant-uploadeditmovefile": "Uploade, udskifte og flytte filer",
+       "grant-uploadfile": "Uploade nye filer",
+       "grant-basic": "Grundlæggende rettigheder",
+       "grant-viewdeleted": "Se slettede filer og sider",
+       "grant-viewmywatchlist": "Se din overvågningsliste",
+       "grant-viewrestrictedlogs": "Vise adgangsbeskyttede logposter",
        "newuserlogpage": "Brugeroprettelseslog",
        "newuserlogpagetext": "Dette er en log over de senest oprettede brugere.",
        "rightslog": "Rettighedslog",
        "action-createpage": "oprette denne side",
        "action-createtalk": "oprette denne diskussionsside",
        "action-createaccount": "Oprette denne brugerkonto",
+       "action-autocreateaccount": "automatisk at oprette denne eksterne brugerkonto",
        "action-history": "se historik for denne side",
        "action-minoredit": "markere denne redigering som mindre",
        "action-move": "flytte denne side",
        "action-viewmyprivateinfo": "se din private information",
        "action-editmyprivateinfo": "rediger dine private oplysninger",
        "action-editcontentmodel": "redigere indholdsmodellen for en side",
-       "action-managechangetags": "oprette og slette tags fra databasen",
+       "action-managechangetags": "oprette og (de)aktivere tags",
        "action-applychangetags": "tilføje tags sammen med dine ændringer",
        "action-changetags": "tilføje og fjerne vilkårlige tags for enkelte versioner og logposter",
+       "action-deletechangetags": "slette tags fra databasen",
+       "action-purge": "rense denne side",
        "nchanges": "$1 {{PLURAL:$1|ændring|ændringer}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|siden sidste besøg}}",
        "enhancedrc-history": "historik",
        "recentchangeslinked-page": "Sidenavn:",
        "recentchangeslinked-to": "Vis ændringer i sider der henviser til den angivne side i stedet",
        "recentchanges-page-added-to-category": "[[:$1]] tilføjet til kategori",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] og [[Special:WhatLinksHere/$1|{{PLURAL:$2|én side|$2 sider}}]] tilføjet til kategori",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] tilføjet til kategorien, [[Special:WhatLinksHere/$1|denne side er inkluderet i andre sider]]",
+       "recentchanges-page-removed-from-category": "[[:$1]] fjernet fra kategori",
        "upload": "Læg en fil op",
        "uploadbtn": "Læg en fil op",
        "reuploaddesc": "Tilbage til formularen til at lægge filer op.",
        "enotif_subject_created": "{{SITENAME}} side $1 er blevet oprettet af {{gender:$2|$2}}",
        "enotif_subject_moved": "{{SITENAME}} side $1 er blevet flyttet af {{gender:$2|$2}}",
        "enotif_subject_restored": "{{SITENAME}} side $1 er blevet gendannet af {{gender:$2|$2}}",
-       "enotif_subject_changed": "{{SITENAME}} side $1 er blevet ændret af {{gender:$2|$2}}",
+       "enotif_subject_changed": "{{SITENAME}}-side $1 er blevet ændret af {{gender:$2|$2}}",
        "enotif_body_intro_deleted": "{{SITENAME}}siden $1 er blevet slettet $PAGEEDITDATE af {{gender:$2|$2}}, se $3.",
        "enotif_body_intro_created": "{{SITENAME}} siden $1 er blevet oprettet den $PAGEEDITDATE af {{gender:$2|$2}}, se $3 for den aktuelle version.",
        "enotif_body_intro_moved": "{{SITENAME}} siden $1 er blevet flyttet den $PAGEEDITDATE af {{gender:$2|$2}}, se $3 for den aktuelle revision.",
        "enotif_body_intro_restored": "{{SITENAME}} siden $1 er blevet gendannet den $PAGEEDITDATE af {{gender:$2|$2}}, se $3 for den aktuelle version.",
-       "enotif_body_intro_changed": "{{SITENAME}} siden $1 er blevet ændret den $PAGEEDITDATE af {{gender:$2|$2}}, se $3 for den aktuelle version.",
-       "enotif_lastvisited": "Se $1 for alle ændringer siden dit sidste besøg.",
-       "enotif_lastdiff": "Se $1 for at vise denne ændring.",
+       "enotif_body_intro_changed": "{{SITENAME}}-siden $1 er blevet ændret den $PAGEEDITDATE af {{gender:$2|$2}}, se $3 for den aktuelle version.",
+       "enotif_lastvisited": "Gå til $1 for at se alle ændringer siden dit sidste besøg.",
+       "enotif_lastdiff": "Gå til $1 for at se denne ændring.",
        "enotif_anon_editor": "anonym bruger $1",
-       "enotif_body": "Kære $WATCHINGUSERNAME\n\n$PAGEINTRO $NEWPAGE\n\nBidragyderens opsummering: $PAGESUMMARY $PAGEMINOREDIT\n\nKontakt bidragyderen:\ne-mail: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nDu vil ikke modtage flere beskeder om yderligere aktivitet medmindre du besøger denne side. På din overvågningsliste kan du også nulstille alle markeringer for de sider, du overvåger.\n\n         Med venlig hilsen {{SITENAME}}s informationssystem\n\n--\nFor at ændre dine indstillinger for e-mail meddelelser, besøg\n{{canonicalurl:{{#special:Preferences}}}}\n\nFor at ændre indstillingerne for din overvågningsliste, besøg\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nFor at slette siden fra din overvågningsliste, besøg\n$UNWATCHURL\n\nTilbagemelding og yderligere hjælp:\n$HELPPAGE",
+       "enotif_body": "Kære $WATCHINGUSERNAME\n\n$PAGEINTRO $NEWPAGE\n\nBidragyderens opsummering: $PAGESUMMARY $PAGEMINOREDIT\n\nKontakt bidragyderen:\ne-mail: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nDu vil ikke modtage flere beskeder om yderligere aktivitet medmindre du besøger denne side. På din overvågningsliste kan du også nulstille alle markeringer for de sider, du overvåger.\n\n         Med venlig hilsen {{SITENAME}}s informationssystem\n\n--\nFor at ændre dine indstillinger for e-mail-meddelelser, besøg\n{{canonicalurl:{{#special:Preferences}}}}\n\nFor at ændre indstillingerne for din overvågningsliste, besøg\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nFor at slette siden fra din overvågningsliste, besøg\n$UNWATCHURL\n\nTilbagemelding og yderligere hjælp:\n$HELPPAGE",
        "created": "oprettet",
        "changed": "ændret",
        "deletepage": "Slet side",
        "log-action-filter-protect-modify": "Ændring af beskyttelse",
        "log-action-filter-protect-unprotect": "Fjernede beskyttelse",
        "log-action-filter-protect-move_prot": "Flyttede beskyttelse",
-       "authmanager-provider-temporarypassword": "Midlertidig adgangskode",
-       "edit-error-short": "Fejl: $1"
+       "authmanager-provider-temporarypassword": "Midlertidig adgangskode"
 }
index 792991a..4ae7a73 100644 (file)
        "views": "Ansichten",
        "toolbox": "Werkzeuge",
        "tool-link-userrights": "{{GENDER:$1|Benutzergruppen}} ändern",
+       "tool-link-userrights-readonly": "{{GENDER:$1|Benutzergruppen}} ansehen",
        "tool-link-emailuser": "E-Mail an {{GENDER:$1|diesen Benutzer|diese Benutzerin}} senden",
        "userpage": "Benutzerseite anzeigen",
        "projectpage": "Projektseite anzeigen",
        "passwordreset-emaildisabled": "Die E-Mail-Funktionen wurden auf diesem Wiki deaktiviert.",
        "passwordreset-username": "Benutzername:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "Die E-Mail-Nachricht ansehen?",
-       "passwordreset-capture-help": "Wenn du dieses Kästchen ankreuzt, wird die E-Mail-Nachricht mit dem temporären Passwort sowohl dir angezeigt als auch dem Benutzer zugesandt.",
        "passwordreset-email": "E-Mail-Adresse:",
        "passwordreset-emailtitle": "Benutzerkontoinformationen auf {{SITENAME}}",
        "passwordreset-emailtext-ip": "Jemand mit der IP-Adresse $1, wahrscheinlich du selbst, hat eine Zurücksetzung deines Passworts bei {{SITENAME}} angefordert ($4). {{PLURAL:$3|Das folgende Benutzerkonto ist|Die folgenden Benutzerkonten sind}} mit dieser E-Mail-Adresse verknüpft:\n\n$2\n\n{{PLURAL:$3|Dieses temporäre Passwort läuft|Diese temporären Passwörter laufen}} innerhalb von {{PLURAL:$5|einem Tag|$5 Tagen}} ab.\nDu solltest dich anmelden und ein neues Passwort vergeben. Falls jemand anderes diese Anfrage getätigt hat oder du dich wieder an dein ursprüngliches Passwort erinnern kannst und es nicht länger ändern möchtest, kannst du diese Nachricht ignorieren und weiterhin dein altes Passwort benutzen.",
        "passwordreset-emailelement": "Benutzername: \n$1\n\nTemporäres Passwort: \n$2",
        "passwordreset-emailsentemail": "Falls diese E-Mail-Adresse mit deinem Benutzerkonto verknüpft ist, wird eine Passwort-Zurücksetzungs-E-Mail versandt.",
        "passwordreset-emailsentusername": "Falls es eine E-Mail-Adresse gibt, die mit diesem Benutzernamen verknüpft ist, wird eine Passwort-Zurücksetzungs-E-Mail versandt.",
-       "passwordreset-emailsent-capture2": "Die Passwort-Zurücksetzungs-{{PLURAL:$1|E-Mail wurde|E-Mails wurden}} versandt. {{PLURAL:$1|Der Benutzername und das Passwort|Die Liste der Benutzernamen und Passwörter}} wird hier angezeigt.",
-       "passwordreset-emailerror-capture2": "Das Senden der E-Mail an {{GENDER:$2|den Benutzer|die Benutzerin}} ist fehlgeschlagen: $1 {{PLURAL:$3|Der Benutzername und das Passwort|Die Liste der Benutzernamen und Passwörter}} wird hier angezeigt.",
        "passwordreset-nocaller": "Es muss ein Rufer angegeben werden",
        "passwordreset-nosuchcaller": "Rufer ist nicht vorhanden: $1",
        "passwordreset-ignored": "Die Passwortzurücksetzung konnte nicht verarbeitet werden. Vielleicht wurde kein Dienstanbieter konfiguriert?",
-       "passwordreset-invalideamil": "Ungültige E-Mail-Adresse",
+       "passwordreset-invalidemail": "Ungültige E-Mail-Adresse",
        "passwordreset-nodata": "Weder ein Benutzername noch eine E-Mail-Adresse wurde angegeben",
        "changeemail": "E-Mail-Adresse ändern oder entfernen",
        "changeemail-header": "Fülle dieses Formular vollständig aus, um deine E-Mail-Adresse zu ändern. Falls du die Zuweisung einer E-Mail-Adresse zu deinem Benutzerkonto entfernen möchtest, lasse beim Übermitteln des Formulars das Feld für die neue E-Mail-Adresse leer.",
        "search-external": "Externe Suche",
        "searchdisabled": "Die {{SITENAME}}-Suche ist deaktiviert. Du kannst unterdessen mit Google suchen. Bitte bedenke, dass der Suchindex von {{SITENAME}} veraltet sein kann.",
        "search-error": "Bei der Suche ist ein Fehler aufgetreten: $1",
+       "search-warning": "Beim Suchen ist eine Warnung aufgetreten: $1",
        "preferences": "Einstellungen",
        "mypreferences": "Einstellungen",
        "prefs-edits": "Anzahl der Bearbeitungen:",
        "prefs-help-recentchangescount": "Dies umfasst die Liste der letzten Änderungen, die Versionsgeschichte und die Logbücher.",
        "prefs-help-watchlist-token2": "Dies ist der geheime Schlüssel zum Webfeed deiner Beobachtungsliste.\nJeder, der ihn kennt, kann deine Beobachtungsliste lesen. Teile ihn deshalb nicht Anderen mit.\nSofern notwendig, [[Special:ResetTokens|kannst du ihn zurücksetzen]].",
        "savedprefs": "Deine Einstellungen wurden gespeichert.",
-       "savedrights": "Die Benutzerrechte von {{GENDER:$1|$1}} wurden gespeichert.",
+       "savedrights": "Die Benutzergruppen von {{GENDER:$1|$1}} wurden gespeichert.",
        "timezonelegend": "Zeitzone:",
        "localtime": "Ortszeit:",
        "timezoneuseserverdefault": "Standardzeit dieses Wikis nutzen ($1)",
        "prefswarning-warning": "Du hast Änderungen an deinen Einstellungen durchgeführt, die noch nicht gespeichert wurden.\nWenn du diese Seite verlässt ohne auf „$1“ zu klicken, werden deine Einstellungen nicht aktualisiert.",
        "prefs-tabs-navigation-hint": "Tipp: Du kannst die linke und rechte Pfeiltasten benutzen, um zwischen den Registerkarten in der Reiterliste zu navigieren.",
        "userrights": "Benutzerrechte verwalten",
-       "userrights-lookup-user": "Gruppenzugehörigkeit verwalten",
+       "userrights-lookup-user": "Einen Benutzer auswählen",
        "userrights-user-editname": "Benutzername:",
-       "editusergroup": "{{GENDER:$1|Benutzergruppen}} verwalten",
+       "editusergroup": "Benutzergruppen laden",
        "editinguser": "Ändere Benutzerrechte {{GENDER:$1|des Benutzers|der Benutzerin}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Benutzerrechte {{GENDER:$1|des Benutzers|der Benutzerin}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Benutzer-Gruppenzugehörigkeit bearbeiten",
+       "userrights-viewusergroup": "Benutzergruppen ansehen",
        "saveusergroups": "{{GENDER:$1|Gruppenzugehörigkeit}} ändern",
        "userrights-groupsmember": "Mitglied von:",
        "userrights-groupsmember-auto": "Automatisch Mitglied von:",
        "userrights-reason": "Grund:",
        "userrights-no-interwiki": "Du hast nicht die erforderliche Berechtigung, um Benutzerrechte in anderen Wikis ändern zu können.",
        "userrights-nodatabase": "Die Datenbank $1 ist nicht vorhanden oder nicht lokal.",
-       "userrights-nologin": "Du musst dich mit einem Administrator-Benutzerkonto [[Special:UserLogin|anmelden]], um Benutzerrechte zu ändern.",
-       "userrights-notallowed": "Du verfügst nicht über die erforderlichen Berechtigungen, um Benutzerrechte vergeben oder entziehen zu können.",
        "userrights-changeable-col": "Gruppenzugehörigkeit, die du ändern kannst",
        "userrights-unchangeable-col": "Gruppenzugehörigkeit, die du nicht ändern kannst",
        "userrights-conflict": "Benutzerrechteänderungskonflikt! Bitte überprüfe und bestätige deine Änderungen.",
-       "userrights-removed-self": "Du hast deine eigenen Rechte entfernt. Du kannst nicht länger auf diese Seite zugreifen.",
        "group": "Gruppe:",
        "group-user": "Benutzer",
        "group-autoconfirmed": "Automatisch bestätigte Benutzer",
        "right-siteadmin": "Datenbank sperren und entsperren",
        "right-override-export-depth": "Exportiere Seiten einschließlich verlinkter Seiten bis zu einer Tiefe von 5",
        "right-sendemail": "E-Mails an andere Benutzer senden",
-       "right-passwordreset": "Passwort eines Benutzers zurücksetzen und die dazu verschickte E-Mail einsehen",
        "right-managechangetags": "[[Special:Tags|Markierungen]] erstellen und (de)aktivieren",
        "right-applychangetags": "[[Special:Tags|Markierungen]] zusammen mit den Änderungen anwenden",
        "right-changetags": "Beliebige [[Special:Tags|Markierungen]] zu einzelnen Versionen und Logbucheinträgen hinzufügen und entfernen",
        "action-writeapi": "die API mit Schreibzugriffen zu verwenden",
        "action-delete": "Seiten zu löschen",
        "action-deleterevision": "Versionen zu löschen",
+       "action-deletelogentry": "Logbucheinträge zu löschen",
        "action-deletedhistory": "die Liste der gelöschten Versionen zu sehen",
+       "action-deletedtext": "gelöschten Versionstext anzusehen",
        "action-browsearchive": "nach gelöschten Seiten zu suchen",
-       "action-undelete": "die Seite wiederherzustellen",
-       "action-suppressrevision": "die versteckte Version einzusehen und wiederherzustellen",
+       "action-undelete": "Seiten wiederherzustellen",
+       "action-suppressrevision": "versteckte Versionen einzusehen und wiederherzustellen",
        "action-suppressionlog": "das private Logbuch einzusehen",
        "action-block": "den Benutzer zu sperren",
        "action-protect": "den Schutzstatus von Seiten zu ändern",
        "action-userrights-interwiki": "die Rechte von Benutzern in anderen Wikis zu ändern",
        "action-siteadmin": "die Datenbank zu sperren oder freizugeben",
        "action-sendemail": "E-Mails zu senden",
+       "action-editmyoptions": "deine Einstellungen zu bearbeiten",
        "action-editmywatchlist": "deine Beobachtungsliste zu bearbeiten",
        "action-viewmywatchlist": "deine Beobachtungsliste anzusehen",
        "action-viewmyprivateinfo": "deine privaten Informationen einzusehen",
        "apisandbox-continue": "Fortfahren",
        "apisandbox-continue-clear": "Löschen",
        "apisandbox-continue-help": "Mit „{{int:apisandbox-continue}}“ kann man die letzte Anfrage [https://www.mediawiki.org/wiki/API:Query#Continuing_queries fortfahren]; „{{int:apisandbox-continue-clear}}“ löscht fortsetzungsbezogene Parameter.",
+       "apisandbox-param-limit": "Gib <kbd>max</kbd> ein, um das maximale Limit zu verwenden.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Alle Namensräume)",
+       "apisandbox-multivalue-all-values": "$1 (Alle Werte)",
        "booksources": "ISBN-Suche",
        "booksources-search-legend": "Suche nach Bezugsquellen für Bücher",
        "booksources-search": "Suchen",
        "activeusers-count": "$1 {{PLURAL:$1|Aktion|Aktionen}} in den {{PLURAL:$3|letzten 24 Stunden|vergangenen $3 Tagen}}",
        "activeusers-from": "Zeige Benutzer ab:",
        "activeusers-groups": "Benutzer anzeigen, die zu diesen Gruppen gehören:",
+       "activeusers-excludegroups": "Benutzer ausschließen, die zu diesen Gruppen gehören:",
        "activeusers-noresult": "Keine Benutzer gefunden.",
        "activeusers-submit": "Aktive Benutzer anzeigen",
        "listgrouprights": "Benutzergruppenrechte",
        "emailccsubject": "Kopie deiner Nachricht an $1: $2",
        "emailsent": "E-Mail verschickt",
        "emailsenttext": "Deine E-Mail wurde verschickt.",
-       "emailuserfooter": "Diese E-Mail wurde von „$1“ an „{{GENDER:$2|$2}}“ durch die Funktion „{{int:emailuser}}“ bei {{SITENAME}} {{GENDER:$1|gesendet}}.",
+       "emailuserfooter": "Diese E-Mail wurde von „$1“ an „{{GENDER:$2|$2}}“ durch die Funktion „{{int:emailuser}}“ bei {{SITENAME}} {{GENDER:$1|gesendet}}. {{GENDER:$2|Deine}} E-Mail wird direkt an {{GENDER:$1|den Originalabsender|die Originalabsenderin}} gesendet mit der Preisgabe {{GENDER:$2|deiner}} E-Mail-Adresse an {{GENDER:$1|ihn|sie}}.",
        "usermessage-summary": "Systemnachricht gespeichert.",
        "usermessage-editor": "System-Messenger",
        "usermessage-template": "MediaWiki:Benutzernachricht",
        "tags-deactivate": "deaktivieren",
        "tags-hitcount": "$1 {{PLURAL:$1|Änderung|Änderungen}}",
        "tags-manage-no-permission": "Du hast keine Berechtigung, Änderungsmarkierungen zu verwalten.",
-       "tags-manage-blocked": "Du kannst keine Änderungsmarkierungen verwalten, während du gesperrt bist.",
+       "tags-manage-blocked": "Du kannst keine Änderungsmarkierungen verwalten, während {{GENDER:$1|du}} gesperrt bist.",
        "tags-create-heading": "Eine neue Markierung erstellen",
        "tags-create-explanation": "Standardmäßig werden neu erstellte Markierungen für die Verwendung durch Benutzer und Bots verfügbar gemacht.",
        "tags-create-tag-name": "Name der Markierung:",
        "tags-deactivate-not-allowed": "Es ist nicht möglich, die Markierung „$1“ zu deaktivieren.",
        "tags-deactivate-submit": "Deaktivieren",
        "tags-apply-no-permission": "Du hast keine Berechtigung, um Änderungsmarkierungen zusammen mit deinen Änderungen anzuwenden.",
-       "tags-apply-blocked": "Du kannst keine Änderungsmarkierungen zusammen mit deinen Änderungen anwenden, während du gesperrt bist.",
+       "tags-apply-blocked": "Du kannst keine Änderungsmarkierungen zusammen mit deinen Änderungen anwenden, während {{GENDER:$1|du}} gesperrt bist.",
        "tags-apply-not-allowed-one": "Die Markierung „$1“ darf nicht manuell angewendet werden.",
        "tags-apply-not-allowed-multi": "Die {{PLURAL:$2|folgende Markierung darf|folgenden Markierungen dürfen}} nicht manuell angewendet werden: $1",
        "tags-update-no-permission": "Du hast keine Berechtigung, um Änderungsmarkierungen von einzelnen Versionen oder Logbucheinträgen hinzuzufügen oder zu entfernen.",
-       "tags-update-blocked": "Du kannst keine Änderungsmarkierungen hinzufügen oder entfernen, während du gesperrt bist.",
+       "tags-update-blocked": "Du kannst keine Änderungsmarkierungen hinzufügen oder entfernen, während {{GENDER:$1|du}} gesperrt bist.",
        "tags-update-add-not-allowed-one": "Die Markierung „$1“ darf nicht manuell hinzugefügt werden.",
        "tags-update-add-not-allowed-multi": "Die {{PLURAL:$2|folgende Markierung darf|folgenden Markierungen dürfen}} nicht manuell hinzugefügt werden: $1",
        "tags-update-remove-not-allowed-one": "Die Markierung „$1“ darf nicht entfernt werden.",
        "htmlform-user-not-exists": "<strong>$1</strong> ist nicht vorhanden.",
        "htmlform-user-not-valid": "<strong>$1</strong> ist kein gültiger Benutzername.",
        "logentry-delete-delete": "$1 {{GENDER:$2|löschte}} Seite $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|löschte}} die Weiterleitung $3 durch Überschreiben",
        "logentry-delete-restore": "$1 {{GENDER:$2|stellte}} Seite $3 wieder her",
        "logentry-delete-event": "$1 {{GENDER:$2|änderte}} die Sichtbarkeit {{PLURAL:$5|eines Logbucheintrags|von $5 Logbucheinträgen}} auf $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|änderte}} die Sichtbarkeit {{PLURAL:$5|einer Version|von $5 Versionen}} der Seite $3: $4",
        "mw-widgets-dateinput-no-date": "Kein Datum ausgewählt",
        "mw-widgets-dateinput-placeholder-day": "JJJJ-MM-TT",
        "mw-widgets-dateinput-placeholder-month": "JJJJ-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Nach Medien suchen",
+       "mw-widgets-mediasearch-noresults": "Keine Ergebnisse gefunden.",
        "mw-widgets-titleinput-description-new-page": "Seite ist noch nicht vorhanden",
        "mw-widgets-titleinput-description-redirect": "Weiterleitung nach $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Eine Kategorie hinzufügen …",
        "sessionmanager-tie": "Mehrere Anfrageauthentifikationstypen konnten nicht kombiniert werden: $1.",
        "sessionprovider-generic": "$1-Sitzungen",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "cookiebasierten Sitzungen",
        "log-action-filter-contentmodel-change": "Inhaltsmodelländerung",
        "log-action-filter-contentmodel-new": "Erstellung einer Seite mit einem Nicht-Standard-Inhaltsmodell",
        "log-action-filter-delete-delete": "Seitenlöschung",
+       "log-action-filter-delete-delete_redir": "Überschreiben einer Weiterleitung",
        "log-action-filter-delete-restore": "Seitenwiederherstellung",
        "log-action-filter-delete-event": "Logbucheintrag-Löschung",
        "log-action-filter-delete-revision": "Versionslöschung",
        "restrictionsfield-badip": "Ungültige IP-Adresse oder ungültiger IP-Adressbereich: $1",
        "restrictionsfield-label": "Erlaubte IP-Adressbereiche:",
        "restrictionsfield-help": "Eine IP-Adresse oder ein CIDR-Bereich pro Zeile. Um alles zu aktivieren, verwende<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Fehler: $1",
-       "edit-error-long": "Fehler:\n\n$1"
+       "revid": "v$1",
+       "pageid": "Seitenkennung $1"
 }
index d5a49eb..0950300 100644 (file)
@@ -85,7 +85,7 @@
        "tuesday": "Sêşeme",
        "wednesday": "Çarşeme",
        "thursday": "Pancşeme",
-       "friday": "Yene",
+       "friday": "Êne",
        "saturday": "Şeme",
        "sun": "Krê",
        "mon": "Dış",
        "categoryviewer-pagedlinks": "($1) ($2)",
        "about": "Heqa cı de",
        "article": "Pela zerreki",
-       "newwindow": "(pençereyê newey de beno a)",
-       "cancel": "Bıtekelne",
+       "newwindow": "(pençerey newey de beno a)",
+       "cancel": "Bıtexelne",
        "moredotdotdot": "Vêşi...",
        "morenotlisted": "Na lista qay kemi ya.",
        "mypage": "Pele",
        "mytalk": "Mesac",
-       "anontalk": "Werênayış",
+       "anontalk": "Vaten",
        "navigation": "Pusula",
        "and": "&#32;u",
        "qbfind": "Bıvêne",
        "history_short": "Tarix",
        "updatedmarker": "cıkewtena mına peyêne ra dıme biyo rocane",
        "printableversion": "Asayışê çapkerdışi",
-       "permalink": "Gıreyo daimi",
+       "permalink": "Gıreyo bêpeyni",
        "print": "Çap ke",
        "view": "Bıvêne",
        "view-foreign": "$1 de bıvêne",
        "unprotectthispage": "Starkerdışe ena peler bıvurne",
        "newpage": "Pela newiye",
        "talkpage": "Ena pele sero werêne",
-       "talkpagelinktext": "werênayış",
-       "specialpage": "Pela xısusiye",
+       "talkpagelinktext": "Mesac",
+       "specialpage": "Pelê hısusiy",
        "personaltools": "Hacetê şexsiy",
        "articlepage": "Pera zerreki bıvin",
        "talk": "Werênayış",
        "viewhelppage": "Pera peşti bıvin",
        "categorypage": "Pela kategoriya bıasne",
        "viewtalkpage": "Werênayışi bıvêne",
-       "otherlanguages": "Zederna zıwani",
+       "otherlanguages": "Zıwananê binan dı",
        "redirectedfrom": "($1 ra kırışı yê)",
        "redirectpagesub": "Pela berdışi",
        "redirectto": "Beno hetê:",
-       "lastmodifiedat": "Per roca $1, sehat $2 de biya anewe.",
+       "lastmodifiedat": "Tewr peyên ena pele $1 dı $2 dı vuriyaya.",
        "viewcount": "Ena pele {{PLURAL:$1|rae|$1 rey}} vêniya.",
        "protectedpage": "Pela pawıtiye",
        "jumpto": "Şo be:",
-       "jumptonavigation": "Pusula",
+       "jumptonavigation": "Navigasyon",
        "jumptosearch": "cı geyre",
        "view-pool-error": "Qaytê qısuri mekerên, serverê ma enıka zêde bar gırewto xo ser.\nHedê xo ra zêde karberi kenê ke seyrê na pele bıkerê.\nŞıma rê zehmet, tenê vınderên, heta ke reyna kenê ke ena pele kewê.\n\n$1",
        "generic-pool-error": "Üzgünüz, şu an sunucular aşırı yüklendi.\nÇok fazla kullanıcı bu sayfayı görüntülemeye çalışıyor.\nLütfen bu sayfaya  tekrar erişmeyi denemeden önce biraz bekleyin.",
        "currentevents": "Hediseyê rocaneyi",
        "currentevents-url": "Project:Hediseyê rocaneyi",
        "disclaimers": "Redê mesuliyeti",
-       "disclaimerpage": "Project:Reddê mesuliyetê bıngey",
+       "disclaimerpage": "Project:Redê mesulêtê pêroyi",
        "edithelp": "Peştdariya vurnayışi",
        "helppage-top-gethelp": "Peşti",
        "mainpage": "Pela Seri",
        "mainpage-description": "Pela seri",
        "policy-url": "Project:Terzê hereketi",
        "portal": "Portalê cemaeti",
-       "portal-url": "Project:Portalë Å\9fëlıgi",
-       "privacy": "Politikaya nımıteyiye",
+       "portal-url": "Project:Portalê cemaeti",
+       "privacy": "Politikay nımıtışi",
        "privacypage": "Project:Xısusiyetê nımıtışi",
        "badaccess": "Xeta mısadey",
        "badaccess-group0": "Heqa şıma çıniya, karo ke şıma waşt, bıkerê.",
        "editlink": "bıvurne",
        "viewsourcelink": "çımey bıvêne",
        "editsectionhint": "Leteyo ke bıvuriyo: $1",
-       "toc": "Sernameyê meselan",
+       "toc": "Tedeestey",
        "showtoc": "bımocne",
        "hidetoc": "bınımne",
        "collapsible-collapse": "Teng kı",
        "nstab-template": "Şablon",
        "nstab-help": "Pela peşti",
        "nstab-category": "Kategoriye",
-       "mainpage-nstab": "Pera esas",
+       "mainpage-nstab": "Pela seri",
        "nosuchaction": "Fealiyeto wınasi çıniyo",
        "nosuchactiontext": "URL ra kar qebul nêbı.\nŞıma belka URL şaş nuşt, ya zi gıreyi şaş ra ameyi.\nKeyepelê {{SITENAME}} eşkeno xeta eşkera bıkero.",
-       "nosuchspecialpage": "Pela xasa wınasiye çıniya",
+       "nosuchspecialpage": "Pela hısusiya wınasiyên çıniya.",
        "nospecialpagetext": "<strong>To yew pela xasa nêvêrdiye waşte.</strong>\n\nSeba lista pelanê xasanê vêrdeyan reca kena: [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Xeta",
        "databaseerror": "Ğetay ardoği",
        "databaseerror-error": "Xeta: $1",
        "laggedslavemode": "Diqet: Pel de newe vıraşteyi belka çini .",
        "readonly": "database kılit biyo",
-       "enterlockreason": "Database kılit biyo",
+       "enterlockreason": "Kılitkerdışi rê tarixê abiyayışê kılit ra piya yew sebeb bınusê.",
        "readonlytext": "Qey pawıtış ri yew sebeb vace. Texmini yew tarix vace şıma key pawıtış wedarneni:  $1",
        "missing-article": "Banqa, pela be nameyê \"$1\" $2 ke gani bıbo, nêdiye.\n\nEna belki seba yew vurnayışo kıhan ya zi tarixê gıreyê yew pele esteriya.\n\nEke wına niyo, belki ''software'' de yew xeta esta.\nKerem kerên, naye be nameyê ''URL''yi yew [[Special:ListUsers/sysop|karber]]i ra vacên.",
        "missingarticle-rev": "(rewizyon#: $1)",
        "perfcached": "Datay cı ver hazır biye. No semedê ra nıkayin niyo! tewr zaf {{PLURAL:$1|netice|$1 netice}} debêno de",
        "perfcachedts": "Cêr de malumatê nımıteyi esti, demdê newe kerdışo peyın: $1. Tewr zaf {{PLURAL:$4|netice|$4 neticey cı}} debyayo de",
        "querypage-no-updates": "Rocanebiyayışê na pele nıka cadayiyê.\nDayiyi tiya nıka newe nêbenê.",
-       "viewsource": "Çemi bıvin",
+       "viewsource": "Çımey bıvêne",
        "viewsource-title": "Cı geyrayışê $1'i bıvin",
        "actionthrottled": "Kerden peysnaya",
        "actionthrottledtext": "Riyê tedbirê anti-spami ra,  wextê do kılmek de şıma nê fealiyeti nêşkenê zaf zêde bıkerê, şıma ki no hedi viyarna ra.\nÇend deqey ra tepeya reyna bıcerrebnên.",
        "welcomecreation-msg": "Hesabê şıma abiyo.\n[[Special:Preferences|{{SITENAME}} vurnayişê tercihanê xo]], xo vir ra mekere.",
        "yourname": "Namey karberi:",
        "userlogin-yourname": "Namey karberi",
-       "userlogin-yourname-ph": "Nameyê xoyê karberi cı kewe",
+       "userlogin-yourname-ph": "Namey xoyê karberi cı kewe",
        "createacct-another-username-ph": "Nameyê karberi cı kewe",
        "yourpassword": "Parola",
        "userlogin-yourpassword": "Parola",
-       "userlogin-yourpassword-ph": "Parolaya xo cıkewe",
+       "userlogin-yourpassword-ph": "Parolay xo cı kewe",
        "createacct-yourpassword-ph": "Parola cıkewe",
        "yourpasswordagain": "Parola reyna bınusne:",
        "createacct-yourpasswordagain": "Parola tesdiq ke",
        "passwordreset-text-many": "{{PLURAL:$1|Qande parola yana e-posta reset kerdışi cayanra taynın pırkeri.}}",
        "passwordreset-disabled": "Parola reset kerdış ena viki sera qefılneyayo.",
        "passwordreset-emaildisabled": "Na wikid hısusiyeté e-posta dewera vıcyayé",
-       "passwordreset-username": "Nameyê karberi:",
+       "passwordreset-username": "Namey karberi:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "neticey e-postay bıasne yo?",
-       "passwordreset-capture-help": "Şıma na dorek morkerê se, e-posta (idareten eposta ya) şıma rê yana karbera rê rışêno.",
        "passwordreset-email": "Adresa e-postey:",
        "passwordreset-emailtitle": "Hesab timarê {{SITENAME}}",
        "passwordreset-emailtext-ip": "Jeweri, {{SITENAME}} ra (ma heta şımayê, $1 IP adresi ra) ($4) teferuatê hesabdê şıma  va wa biyaro xo viri. Karbero ke cêrdeyo {{PLURAL:$3|hesaba|eno hesaba}} ena e-posta adresiya aleqey cı esto:\n\n$2\n\n{{PLURAL:$3|ena parola idaretena|ena parola idareten}} {{PLURAL:$5|jew roc|$5  roca}}rêya.\nEna parolaya deqewe de u xorê ju parolaya newi bıweçine. Parolaya şıma emaya şıma viri se  yana  ena e-posta şıma nê weştase u şıma qayıl niye parolaya xo bıvurnese, ena mesacer peygoş bıkerê.",
        "passwordreset-emailtext-user": "$1 enê karberi, {{SITENAME}}  ra ($4) teferuatê hesab dê şıma  va wa biyaro xo viri. Karbero ke cêrdeyo {{PLURAL:$3|hesaba|eno hesaba}} ena e-posta adresiya aleqey cı esto:\n\n$2\n\n{{PLURAL:$3|ena parola idaretena|ena parola idareten}} {{PLURAL:$5|jew roc|$5  roca}}rêya.\nEna parolaya deqewe de u xorê ju parolaya newi bıweçine. Parolaya şıma emaya şıma viri se  yana  ena e-posta şıma nê weştase u şıma qayıl niye parolaya xo bıvurnese, ena mesacer peygoş bıkerê.",
        "passwordreset-emailelement": "Nameyê karberi: \n$1\n\nParolaya vêrdiye: \n$2",
        "passwordreset-emailsentemail": "Eger kı ena e-posta şıma rê se, yew e-posta do bırışiyo eno hesab.",
-       "passwordreset-invalideamil": "Adresê eposta raşt niya",
+       "passwordreset-invalidemail": "Adresê eposta raşt niya",
        "changeemail": "E-posta adresa xo wedarne",
        "changeemail-header": "E-posta adresa xo vuriyayışi rë ena former pır kerë. Eger kı şıma qayılë kı e postay adresi ra wedarnë se formi rıştış dı heruna e posta veng verdë",
        "changeemail-no-info": "Şıma gani bıkewê pele ke derdest bıresê na pele.",
        "bold_tip": "Metno qalın",
        "italic_sample": "Metno çewt",
        "italic_tip": "Metno çewt",
-       "link_sample": "Sernameyê gırey",
-       "link_tip": "Gıreyê miyani",
+       "link_sample": "Sernamey gırey",
+       "link_tip": "Gıreyo zerrên",
        "extlink_sample": "http://www.misal.com sernameyê gırey",
        "extlink_tip": "Gırey teberi (xo vira mekerên http:// prefix)",
        "headline_sample": "metnê sernamey",
        "summary": "Xulasa:",
        "subject": "Mewzu:",
        "minoredit": "No yew vurnayışo werdiyo",
-       "watchthis": "Na pele seyr ke",
-       "savearticle": "Qeyd ke",
-       "savechanges": "Vurnayışan qeyd ke",
+       "watchthis": "Bewnı ena pele",
+       "savearticle": "Pele qeyd kı",
+       "savechanges": "Vurnayışan qeyd kı",
        "publishpage": "Perer bıhesırne",
        "publishchanges": "Vurnayışa vıla ke",
        "preview": "Verqayt",
-       "showpreview": "Verqayti bıvêne",
-       "showdiff": "Vurriyayışan bımocne",
+       "showpreview": "Verasayışi bımocne",
+       "showdiff": "Vurnayışan bımocne",
        "anoneditwarning": "<strong>İqaz:</strong> Şıma be hesabê xo nêkewtê cı. \nAdresê şımayê IP tarixê vırnayışê na pele de do qeyd bo. Eke şıma <strong>[$1 cıkewê]</strong> ya zi <strong>[$2 hesab vırazê]</strong>, vurnayışê şıma be zewbina kare ra nameyê şıma rê bar beno.",
        "anonpreviewwarning": "\"Şıma be hesabê xo nêkewtê cı. Eke qeyd kerê, adresê şımaê IP tarixê vırnayışê na pele de do qeyd bo.\"",
        "missingsummary": "'''DİQET:''' Şıma jû xulasa nênuşte.\nEke şıma \"{{int:savearticle}}\" reyna bıtıknê, vırnayışê şıma bê xulasa qeyd beno.",
        "token_suffix_mismatch": "'''Vurnayişê şıma tepeya ameyo çunke qutiyê imla xerıbya.\nVurnayişê şıma qey nêxerepyayişê peli tepeya geyra a.\nEke şıma servisê proksi yo anonim şuxulneni sebebê ey noyo.'''",
        "edit_form_incomplete": "'''Qandê form dê vurnayışa tay wastera ma nêreşti; Vurnayışê ke şıma kerdê nêalızyayê, çım ra ravyarnê u fına bıcerbnê.'''",
        "editing": "$1 vuriyeno",
-       "creating": "$1 vıraziyeno",
+       "creating": "$1 vırazeno.",
        "editingsection": "Per da $1 de şımaye kenê ke leti bıvurnê",
        "editingcomment": "$1 vuryeno (qısmo newe)",
        "editconflict": "Têverabiyayışê vurnayışi: $1",
        "templatesusedpreview": "{{PLURAL:$1|Sablon|Sabloni}}  ke na verqayt de xebetnayê:",
        "templatesusedsection": "{{PLURAL:$1|Template|Templateyan}}  ke na qısım de xebetniyenê:",
        "template-protected": "(kılit biyo)",
-       "template-semiprotected": "(nimey ena pele kılit biya)",
+       "template-semiprotected": "(nêmê ena pele kılit biyo)",
        "hiddencategories": "Ena per de {{PLURAL:$1|1 kategoriyo nımıte|$1 kategoriyê nımıtey}} muhtewa benê:",
        "edittools": "<div id=\"specialcharss\" class=\"toccolours specialchars\" style=\"margin-top:.5em; padding: .3em .5em; font-size: 100%; color:#aaa; text-align:left;\" title=\"{{int:bw-edittools-tooltip}}\">\n<p class=\"specialbasic\" id=\"Standard\">\n'''{{int:bw-edittools-lead-in}}''' \n<charinsert>Á á É é Í í Ó ó Ú ú Ý ý</charinsert> –\n<charinsert>À à È è Ì ì Ò ò Ù ù </charinsert> –\n<charinsert> â Ê ê Î î Ô ô Û û </charinsert> –\n<charinsert>Ä ä Ë ë Ï ï Ö ö Ü ü Ÿ ÿ</charinsert> –\n<charinsert>Æ æ Ø ø Œ œ ẞ ß </charinsert> –\n<charinsert>Å å Ů ů </charinsert> –\n<charinsert>àã Ẽ ẽ ɛ̃ Ĩ ĩ Ñ ñ Õ õ ɔ̃ Ũ ũ </charinsert> –\n<charinsert>Рð Þ þ </charinsert> –\n<charinsert>Ç ç Ģ ģ Ķ ķ Ļ ļ Ņ ņ Ŗ ŗ Ş ş Ţ ţ </charinsert> –\n<charinsert>Ć ć Ĺ ĺ Ń ń Ŕ ŕ Ś ś Ý ý Ź ź </charinsert> –\n<charinsert>Č č Ď ď Ľ ľ Ň ň Ř ř Š š Ť ť Ž ž </charinsert> –\n<charinsert>Ǎ ǎ Ě ě Ǐ ǐ Ǒ ǒ Ǔ ǔ </charinsert> –\n<charinsert>Ā ā Ē ē Ī ī Ō ō Ū ū </charinsert> –\n<charinsert>ǖ ǘ ǚ ǜ </charinsert> –\n<charinsert>Ĉ ĉ Ĝ ĝ Ĥ ĥ Ĵ ĵ Ŝ ŝ Ŵ ŵ Ŷ ŷ </charinsert> –\n<charinsert>Ă ă Ğ ğ Ŭ ŭ </charinsert> –\n<charinsert>Ċ ċ Ė ė Ġ ġ Għ għ İ ı Ż ż </charinsert> –\n<charinsert>Ą ą Ę ę Į į Ų ų </charinsert> –\n<charinsert>Ő ő Ű ű </charinsert> –\n<charinsert>Đ đ Ħ ħ Ł ł Ŀ ŀ </charinsert> –\n<charinsert>Ɖ ɖ Ɛ ɛ Ƒ ƒ Ɣ ɣ Ŋ ŋ Ɔ ɔ Ʋ ʋ </charinsert> -\n<charinsert>Ə ə </charinsert> –\n<charinsert>– — ’</charinsert> –\n<charinsert>~ | ° ¹ ² ³ ⅛ ¼ ⅓ ⅜ ½ ⅝ ¾ ⅔ ⅞ € $ ¥ £ † × ← → ↔ ↑ ± ≠ © ® ™ ‰ «+» ‹+› „+“ „+” ‚+‘ ¡ ¿ …</charinsert> –\n<charinsert>&amp;nbsp; &nbsp; [[Category:+]] #REDIRECT[[+]] {{msg-mw|+|notext=1}} &#33;!FUZZY!! ~~~~  &lt;nowiki>+</nowiki></charinsert>\n<charinsert>ڈ ڑ ٹ </charinsert>\n<charinsert>ټ څ ځ ډ ړ ږ ښ ڼ ؤ ي ې ۍ ئ </charinsert>\n<charinsert>{{{+}}} {{+}} {{subst:+}} <noinclude>+</noinclude></charinsert>\n<charinsert>&lt;!--&nbsp;+&nbsp;--> &lt;br&nbsp;/></charinsert>\n</p></div>",
        "edittools-upload": "-",
        "nohistory": "Verê vurnayışanê na pele çıniyo.",
        "currentrev": "Çımraviyarnayışo rocane",
        "currentrev-asof": "$1 ra tepya mewcud weziyeta pela",
-       "revisionasof": "Verziyonê roca $1ine",
+       "revisionasof": "Çımraviyarnayışê $1",
        "revision-info": "Vurnayışo ke $1 de terefê {{GENDER:$6|$2}}$7 ra biyo",
        "previousrevision": "← Çımraviyarnayışo kıhanêr",
        "nextrevision": "Rewizyono newên →",
        "lineno": "Xeta $1:",
        "compareselectedversions": "Rewizyonanê weçineyan pêver ke",
        "showhideselectedversions": "Revizyonanê weçinıtan bımocne/bınımne",
-       "editundo": "peyser biya",
+       "editundo": "Peyser bıgêre",
        "diff-empty": "(Babetna niyo)",
        "diff-multi-sameuser": "(Terefê eyni karberi ra {{PLURAL:$1|yew revizyono miyanên nêmocno|$1 revizyonê miyanêni nêmocnê}})",
        "diff-multi-otherusers": "(Terefê {{PLURAL:$2|yew karberi|$2 karberan}} ra {{PLURAL:$1|yew revizyono miyanên nêmocno|$1 revizyonê miyanêni nêmocnê}})",
        "diff-multi-manyusers": "({{PLURAL:$1|jew timar kerdışo qıckeko|$1 timar kerdışo qıckeko}} timar kerdo, $2 {{PLURAL:$2|Karber|karberi}} memocne)",
        "difference-missing-revision": "Ferqê {{PLURAL:$2|Yew rewizyonê|$2 rewizyonê}} {{PLURAL:$2|dı|dı}} ($1) sero çıniyo.\n\nNo normal de werênayış dê pelanê besterneyan dı ena xırabin asena.\nDetayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} tiya dı] aseno.",
-       "searchresults": "Neticeyê geyrayışi",
+       "searchresults": "Peyniyê cıgeyrayışi",
        "searchresults-title": "Qandê \"$1\" neticeyê geyrayışi",
        "titlematches": "Tekê (zewcê) sernameyê pele",
        "textmatches": "Tekê (zewcê) nuştey pele",
        "next-page": "Pela peyên",
        "prevn-title": "$1o verên  {{PLURAL:$1|netice|neticeyan}}",
        "nextn-title": "$1o ke yeno {{PLURAL:$1|netice|neticey}}",
-       "shown-title": "Herg per sero $1 {{PLURAL:$1|netici|netica}} bıasne",
+       "shown-title": "Her pele sero $1 {{PLURAL:$1|netici|netica}} bımocne",
        "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) bıvênên",
        "searchmenu-exists": "''Ena 'Wikipediya de ser \"[[:$1]]\" yew pel esto'''",
        "searchmenu-new": "<strong>Na wiki de pela \"[[:$1]]\" vıraze!</strong> {{PLURAL:$2|0=|Sewbina pela ke şıma geyrayê cı aye bıvênê.|Yew zi neticanê cıgeyrayışê xo bıvênê.}}",
-       "searchprofile-articles": "Perrê muhteway",
+       "searchprofile-articles": "Pelê zerreki",
        "searchprofile-images": "Zafınmedya",
        "searchprofile-everything": "Pêro çi",
        "searchprofile-advanced": "Herayen",
        "searchprofile-articles-tooltip": "$1 de cı geyre",
        "searchprofile-images-tooltip": "Dosya cı geyre",
-       "searchprofile-everything-tooltip": "Tedeesteyan hemine cı geyre (pelanê mınaqeşeyi zi tey)",
+       "searchprofile-everything-tooltip": "Tedeesteyan hemine cı geyre (pelanê werênayışi zi tey)",
        "searchprofile-advanced-tooltip": "Cayê nameyanê xısusiyan de cı geyre",
        "search-result-size": "$1 ({{PLURAL:$2|1 çeku|$2 çekuy}})",
        "search-result-category-size": "{{PLURAL:$1|1 eza|$1 ezayan}} ({{PLURAL:$2|1 kategoriyê bini|$2 kategirayanê binan}}, {{PLURAL:$3|1 dosya|$3 dosyayan}})",
        "searchdisabled": "{{SITENAME}} no keyepel de cıgerayiş muweqqet bıryayo. no benatê de şıma pê Google eşkeni zerreyê {{SITENAME}} de cıgerayiş bıkeri.",
        "search-error": "Cıgeyrayış de yew xeta emê meydan: $1",
        "preferences": "Tercihi",
-       "mypreferences": "Tercihi",
+       "mypreferences": "Weçinıtışi",
        "prefs-edits": "Amarê vurnayışan:",
        "prefsnologintext2": "Kerem ke, seba vurnayışê tercihanê xo cı kewe.",
        "prefs-skin": "Çerme",
        "datedefault": "Tercih çıniyo",
        "prefs-labs": "Xacetê labs",
        "prefs-user-pages": "Pelê karberi",
-       "prefs-personal": "Pela karberi",
+       "prefs-personal": "Profilê karberi",
        "prefs-rc": "Vurriyayışê peyêni",
        "prefs-watchlist": "Lista seyrkerdışi",
        "prefs-editwatchlist": "Lista seyrkerdışi bıvurne",
        "prefs-reset-intro": "ena pele de şıma tercihanê xo şenê bıçarnê be tercihanê keyepelê ke verê coy eyar biy.\nNa game tepeya nêerziyena.",
        "prefs-emailconfirm-label": "Tesdiqiya E-posta:",
        "youremail": "E-Mail (mecbur niyo) *:",
-       "username": "{{GENDER:$1|Nameyê karberi}}:",
+       "username": "{{GENDER:$1|Namey karberi}}:",
        "prefs-memberingroups": "{{GENDER:$2|Ezayê}} {{PLURAL:$1|grube|gruban}}:",
        "prefs-memberingroups-type": "$1",
        "prefs-registration": "Wextê qeydbiyayışi",
        "userrights-reason": "Sebeb:",
        "userrights-no-interwiki": "Heqa şıma çıniya ke heqanê karberanê Wikipediyanê binan sero bıgureyê.",
        "userrights-nodatabase": "Database $1 çıniyo ya zi mehelli niyo.",
-       "userrights-nologin": "Eke şıma wazenê ke heqa karberi/karbere cı dê, şıma gani be [[Special:UserLogin|cikewtiye]] pê yew hesabê idarekeran cı kewê",
-       "userrights-notallowed": "Hesabdê şımadı heqanê xo hewadayış u xorê heq dekerdış çıno.",
        "userrights-changeable-col": "Grubê ke şıma şenê bıvurnê",
        "userrights-unchangeable-col": "Grubê ke şıma nêşenê bıvurnê",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Heqan de karberi de dıbare vıcyayo! Kerem ke vurnayışane xo çımser ra ravyarne  u tesdiq keri.",
-       "userrights-removed-self": "Heqi şıma usula hewadeyay. Qan de coy şıma hendana nişeni ena pela resi.",
        "group": "Grube:",
        "group-user": "Karberi",
        "group-autoconfirmed": "Karberê ke otomatikmen biyê araşt",
        "right-bot": "Zey yew kardê otomotiki kar bıvin",
        "right-nominornewtalk": "Pelanê werênayışan rê vurnayışê qıckeki çıniyê, qutiya mesacanê newiyan bıgurene",
        "right-apihighlimits": "Persanê API de sinoranê berzêran bıgurene",
-       "right-writeapi": "İstıfadey APIyê nuştey",
+       "right-writeapi": "Xebtnayışê API nusnayışi",
        "right-delete": "Pele bestere",
        "right-bigdelete": "Pelanê be tarixanê dergan bestere",
        "right-deletelogentry": "Qeydanê cıkewtışanê xısusiyan bestere û peyser biya",
        "right-siteadmin": "Database kilit bike u a bike",
        "right-override-export-depth": "Peleyanê ke tede linkanê 5 ra zafyer estê ay export bike",
        "right-sendemail": "Karberanê binî ra e-mail bişirav",
-       "right-passwordreset": "E-postayanê parola reset kerdışa vineno",
        "right-managechangetags": "[[Special:Tags|Etiketi]] vıraz u aktiv (me)ke",
        "right-applychangetags": "[[Special:Tags|Etiketa]]  vurnayışana piya dezge fi.",
        "grant-group-page-interaction": "Peran na tesiri",
        "nchanges": "$1 {{PLURAL:$1|vurnayış|vurnayışi}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|ziyaretê peyêni ra nata}}",
        "enhancedrc-history": "tarix",
-       "recentchanges": "Vurriyayışê peyêni",
+       "recentchanges": "Vurnayışê peyêni",
        "recentchanges-legend": "Tercihê vurnayışanê peyênan",
-       "recentchanges-summary": "Wiki sero vurriyayışê peyêni asenê.",
+       "recentchanges-summary": "Wiki sero vurnayışê peyêni asenê.",
        "recentchanges-noresult": "Goreyê kriteranê kıfşkerdeyan ra qet yew vurnayış nêvêniya.",
        "recentchanges-feed-description": "Ena feed dı vurnayişanê tewr peniyan teqip bık.",
-       "recentchanges-label-newpage": "Enê vurnayışi ra yu pera newi vıraziya ya",
+       "recentchanges-label-newpage": "Enê vurnayışi yew pela newiye vıraşta.",
        "recentchanges-label-minor": "No yew vurnayışo werdiyo",
        "recentchanges-label-bot": "Eno vurnayış terefê yew boti ra vıraziyo",
        "recentchanges-label-unpatrolled": "Eno vurnayış hewna dewriya nêbiyo",
        "recentchanges-submit": "Bımocne",
        "rcnotefrom": "Cêr de <strong>$2</strong> ra nata {{PLURAL:$5|vurnayışiyê}} asenê (tewr vêşi <strong>$1</strong> asenê) <strong>$3, $4</strong>",
        "rclistfrom": "$3 $2 ra tepiya vurnayışanê neweyan bımocne",
-       "rcshowhideminor": "Vurriyayışê werdiy $1",
+       "rcshowhideminor": "Vurriyayışanê werdiya $1",
        "rcshowhideminor-show": "Bımocne",
        "rcshowhideminor-hide": "Bınımne",
        "rcshowhidebots": "botan $1",
        "rcshowhidebots-show": "Bımocne",
        "rcshowhidebots-hide": "Bınımne",
-       "rcshowhideliu": "karberê qeydbiyayeyi $1",
+       "rcshowhideliu": "karberanê qeydina $1",
        "rcshowhideliu-show": "Bımocne",
        "rcshowhideliu-hide": "Bınımne",
-       "rcshowhideanons": "karberê bênameyi $1",
+       "rcshowhideanons": "karberê bênamey $1",
        "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": "vurnayışanê mı $1",
+       "rcshowhidemine": "vurnayışê mı $1",
        "rcshowhidemine-show": "Bımocne",
        "rcshowhidemine-hide": "Bınımne",
        "rcshowhidecategorization": "kategorizasyonê pele $1",
        "rc_categories": "Kategoriyan rêz kı ( \"|“ ya ciya yo):",
        "rc_categories_any": "Weçinayiyan ra her yew",
        "rc-change-size": "$1",
-       "rc-change-size-new": "Vurnayışa dıma $1 {{PLURAL:$1|bayt|bayt}}",
+       "rc-change-size-new": "$1 {{PLURAL:$1|bayt|bayti}} ra dıma vurnayış",
        "newsectionsummary": "/* $1 */ qısımo newe",
        "rc-enhanced-expand": "Detaya bıvin (JavaScript lazımo)",
        "rc-enhanced-hide": "Melumat bınımne",
        "recentchangeslinked-toolbox": "Vurnayışê elaqeyıni",
        "recentchangeslinked-title": "Heqa \"$1\" de vurnayışi",
        "recentchangeslinked-summary": "Lista cêrêne, pela bêlikerdiye rê (ya zi karberanê kategoriya bêlikerdiye rê) pelanê gırêdayoğan de lista de vurnayışê peyênana.\n[[Special:Watchlist|Lista şımaya seyrkedışi de]] peli be nuşteyo '''qolınd''' bêli kerdê.",
-       "recentchangeslinked-page": "Nameyê pele:",
+       "recentchangeslinked-page": "Namey pele:",
        "recentchangeslinked-to": "Heruna pela ke yena dayene, vurnayışanê pelanê ke daye ra gırêdayiyê inan bımocne",
        "recentchanges-page-added-to-category": "[[:$1]] kerd kategoriye miyan",
        "recentchanges-page-removed-from-category": "[[:$1]] kategoriye ra vet",
        "imagelinks": "Gurenayışê dosya",
        "linkstoimage": "Ena {{PLURAL:$1|pela|$1 pela}} gıreye ena dosya:",
        "linkstoimage-more": "$1 ra ziyed {{PLURAL:$1|pel|pel}} re gırey dano.\nlisteya ke ha ver a têna na {{PLURAL:$1|dosyaya ewwili|dosyaya $1 ewwili}} mocnena.\n[[Special:WhatLinksHere/$2|pêroyê liste]] mevcud o.",
-       "nolinkstoimage": "Pelanê ser ena dosyayê link biyê çin o.",
+       "nolinkstoimage": "Pele çıniya ke ena dosya ra bestiyena.",
        "morelinkstoimage": "[[Special:WhatLinksHere/$1|Linkanê zafyerî]] ena pele ra link biyo bivîne.",
        "linkstoimage-redirect": "$1 (Dosya raçarnayış) $2",
        "duplicatesoffile": "a {{PLURAL:$1|dosya|$1 dosya}}, kopyayê na dosyayi ([[Special:FileDuplicateSearch/$2|teferruati]]):",
        "listredirects": "Listeya Hetenayışan",
        "listduplicatedfiles": "Lista dosyeyanê ke kopyaya cı vêniyena",
        "listduplicatedfiles-entry": "[[$3|{{PLURAL:$2|kapyay|$2 kopyey}}]] dosya da [[:File:$1|$1]]'i est a",
-       "unusedtemplates": "Şablonê ke nêguriyenê",
+       "unusedtemplates": "Şablonê kı nêgurweyênê",
        "unusedtemplatestext": "no pel, {{ns:template}} pelê ke pelê binan de nêaseni, ninan keno.",
        "unusedtemplateswlh": "linkanê binî",
        "randompage": "Pela raştameyiye",
        "randompage-nopages": "Na {{PLURAL:$2|heruna namey|heruna nameyan}} de nê peli çıniyê: $1.",
-       "randomincategory": "Ğoseri pera kategoriya",
+       "randomincategory": "Ena kategoriye dı pela raştameye",
        "randomincategory-invalidcategory": "\"$1\" yew nameyê kategoriya vêrdiye niyo.",
        "randomincategory-nopages": "Kategori da [[:Category:$1|$1]] de qet  per çıniya.",
        "randomincategory-category": "Kategoriye:",
        "statistics-users": "[[Special:ListUsers|Karber]]ê qeydıni",
        "statistics-users-active": "Karberê aktifi",
        "statistics-users-active-desc": "{{PLURAL:$1|roco peyin de|$1 roco peyin de}} karber ê ke kar kerdê.",
-       "pageswithprop": "Peli be yew xısusiyetê pele",
+       "pageswithprop": "Perrê kı hendê ju perrer rê",
        "pageswithprop-legend": "Peli be yew xısusiyetê pele",
        "pageswithprop-text": "Na per pimanen pera kena liste.",
        "pageswithprop-prop": "Nameyo xısusi:",
        "brokenredirectstext": "Redireksiyonê ey ki pelanê hama çiniyeno ra link dano:",
        "brokenredirects-edit": "bıvurne",
        "brokenredirects-delete": "bestere",
-       "withoutinterwiki": "Pelê ke zıwananê binan rê gıreyê cı çıniyo",
+       "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ımocne",
-       "fewestrevisions": "Pelê be senık çımraviyarnayışi",
+       "fewestrevisions": "Perrê kı tewr tayn timaryayê",
        "nbytes": "$1 {{PLURAL:$1|bayt|bayti}}",
        "ncategories": "$1 {{PLURAL:$1|Kategori|Kategoriy}}",
        "ninterwikis": "$1 {{PLURAL:$1|interwiki|interwikiy}}",
        "nimagelinks": "$1 {{PLURAL:$1|pele de|pelan de}} gureyeno",
        "ntransclusions": "$1 {{PLURAL:$1|pele de|pelan de}} gureyeno",
        "specialpage-empty": "Seba na rapore netice çıniyo.",
-       "lonelypages": "Pelê seyi",
+       "lonelypages": "Perrê kı cı rê gre çıni yo",
        "lonelypagestext": "Ena pelî link nibiyê ya zi pelanê binî {{SITENAME}} de transclude biy.",
        "uncategorizedpages": "Pelê ke kategorize nêbiyê",
        "uncategorizedcategories": "Kategoriyê ke kategorize nêbiyê",
-       "uncategorizedimages": "Dosyeyê ke bêkategoriyê",
+       "uncategorizedimages": "Dosyeyê kategorinêbiyay.",
        "uncategorizedtemplates": "Şablonê ke bêkategoriyê",
-       "unusedcategories": "Kategoriyê ke nêgureniyê",
+       "unusedcategories": "Kategoriyê ke nêguriyay",
        "unusedimages": "Dosyeyê ke nêguriyenê",
        "wantedcategories": "Kategoriyê ke waziyayê",
        "wantedpages": "Pelê ke waziyayê",
        "wantedpages-badtitle": "sernuşte meqbul niyo: $1",
-       "wantedfiles": "Dosyeyê cıgeyriyayeyi",
+       "wantedfiles": "Dosyeyê waştey",
        "wantedfiletext-cat": "Dosyaya cêrên karvıstedeya lakin çınya. Mewcud dosyayan de xeriba miyan de liste bena. Xırabiya wınisin dana <del>ateber</del>. Zewbi zi, şırê pela da dosyeyê ke çınyaya [[:$1]].",
        "wantedfiletext-nocat": "Dosyeyê cêrêni estê lekin karnêvıstê. Dosyeyê xeribi liste benê. bo babeta dano <del>ateber</del>",
        "wantedtemplates": "Şablonê ke waziyenê",
        "mostimages": "Dosyayan ke tewr zaf link estê.",
        "mostinterwikis": "Pelan ke tewr zaf interwiki biyê.",
        "mostrevisions": "Pelan ke tewr zaf revizyonî biyê.",
-       "prefixindex": "Veroleya peley pêro",
+       "prefixindex": "Verbenda pelli heme",
        "prefixindex-namespace": "Peleyê Veroleyıni ($1 cay nami)",
        "prefixindex-submit": "Bımocne",
        "prefixindex-strip": "Listeya réz bıyayışi",
-       "shortpages": "Pelê kılmeki",
-       "longpages": "Pelê dergeki",
-       "deadendpages": "Pelê nêgıredayeyi",
+       "shortpages": "Pelê kılmi",
+       "longpages": "Pelê dergi",
+       "deadendpages": "Perrê kı perranê binan rê grey c çıni yo",
        "deadendpagestext": "Ena pelan ke {{SITENAME}} de zerrî ey de link çini yo.",
-       "protectedpages": "Pelê pawıteyi",
+       "protectedpages": "Pellê kı pawıyayeyè",
        "protectedpages-indef": "têna pawıteyê bêmuddeti",
        "protectedpages-summary": "Listeya ena peler newke pawıtiya.Sername de  ena lista rê pawıte vıraştışi rê [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]] bıvinê.",
        "protectedpages-cascade": "Kilit biyaye ke teyna cascadiye",
        "newpages": "Pelê newey",
        "newpages-submit": "Bımocne",
        "newpages-username": "Nameyê karberi:",
-       "ancientpages": "Pelê kehenêri",
+       "ancientpages": "Tewr pelê kıhani",
        "move": "Bıkırışe",
        "movethispage": "Ena pele bıkırışe",
        "unusedimagestext": "Enê dosyey estê, feqet zerrey yew pele de wedardey niyê.\nXo vira mekerê ke, sıteyê webiê bini şenê direkt ebe URLi yew dosya ra gırê bê, u wına şenê verba gurênayışo feal de tiya hewna lista bê.",
        "apisandbox-sending-request": "API waştış rışêno...",
        "apisandbox-request-url-label": "URL waştış:",
        "apisandbox-request-time": "Demê waştışi: {{PLURAL:$1|$1 ms}}",
-       "booksources": "Çımeyê kıtaban",
+       "booksources": "Çımey kıtabi",
        "booksources-search-legend": "Seba çımeyanê kıtaban cı geyre",
        "booksources-isbn": "ISBN:",
        "booksources-search": "Cı geyre",
        "checkbox-all": "Pêro",
        "checkbox-none": "Temam",
        "checkbox-invert": "Rageyre",
-       "allpages": "Peli pêro",
+       "allpages": "Pêro peli",
        "nextpage": "Pela badê cû ($1)",
        "prevpage": "Pela verêne ($1)",
        "allpagesfrom": "Pera liste kerdışi bıasne:",
        "removedwatchtext": "Ena pela \"[[:$1]]\" biya wedariya [[Special:Watchlist|listeyê seyr-kerdışi şıma]].",
        "removedwatchtext-short": "Pera $1`i listeya seyran de şıma ra wedari yê",
        "watch": "Seyr ke",
-       "watchthispage": "Na pele seyr ke",
+       "watchthispage": "Bewnı ena pele",
        "unwatch": "Teqib meke",
        "unwatchthispage": "temaşa kerdışê peli vındarn.",
        "notanarticle": "mebhesê peli niyo",
        "delete-warning-toobig": "no pel wayirê tarixê vurnayiş ê derg o, $1 {{PLURAL:$1|revizyonê|revizyonê}} seri de.\nhewn a kerdışê ıney {{SITENAME}} şuxul bıne gırano;\nbı diqqet dewam kerê.",
        "deleteprotected": "Şıma nêşenê ena perer esternê,  çıkı per starya ya.",
        "rollback": "vurnayişan tepiya bıger",
-       "rollbacklink": "peyser biya",
+       "rollbacklink": "peyser biyare",
        "rollbacklinkcount": "$1 {{PLURAL:$1|vurnayış|vurnayışi}} peyd gıroti",
        "rollbacklinkcount-morethan": "$1 {{PLURAL:$1|vurnayış|vuranyışi}} tewr peyd gırot",
        "rollbackfailed": "Peyserardış nêbi",
        "rollback-success": "vurnayişê no kesi $1 tepiya geriyayo u hetê no\n$2 kesi ra cıwa ver o ke revizyon biyo no revizyon tepiya anciyayo.",
        "sessionfailure-title": "Seans xeripiya",
        "sessionfailure": "cıkewtışê hesabê şıma de yew problem aseno;\nno kar semedê dızdiyê hesabi ibtal biyo.\nkerem kerê \"tepiya\" şiyerê u pel o ke şıma tera ameyî u o pel newe ra bar kerê , newe ra tesel/cereb kerê.",
+       "changecontentmodel": "Modelê zerrekê pele bıvurne",
        "changecontentmodel-title-label": "Sernameyê pele",
        "changecontentmodel-model-label": "Modelê zerrekiyo newe",
        "changecontentmodel-reason-label": "Sebeb:",
        "sp-contributions-deleted": "iştırakê {{GENDER:$1|karberi}} esterdi",
        "sp-contributions-uploads": "Barkerdışi",
        "sp-contributions-logs": "qeydi",
-       "sp-contributions-talk": "werênayış",
+       "sp-contributions-talk": "vaten",
        "sp-contributions-userrights": "idareyê heqanê karberan",
        "sp-contributions-blocked-notice": "verniyê no/na karber/e geriyayo/a\nqê referansi qeydê vernigrewtışi cêr de eşkera biyo:",
        "sp-contributions-blocked-notice-anon": "Eno adresê IPi bloke biyo.\nCıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:",
        "sp-contributions-hideminor": "Vurriyayışanê werdiyan bınımne",
        "sp-contributions-submit": "Cı geyre",
        "whatlinkshere": "Linkê tedeestey",
-       "whatlinkshere-title": "Per da \"$1\" rê perê ke gre danê",
+       "whatlinkshere-title": "Pelê ke \"$1\" ra bestiyenê",
        "whatlinkshere-page": "Pele:",
        "linkshere": "Ena peleyan grey biya '''[[:$1]]''':",
        "nolinkshere": "Per da '''[[:$1]]''' rê pera ke gıre dana çıniya.",
        "tooltip-pt-createaccount": "Şıma rê tewsiyey ma xorê jew hesab akerê. Fına zi hesab akerdış mecburi niyo.",
        "tooltip-ca-talk": "Heqa zerrekê pele de werênayış",
        "tooltip-ca-edit": "Ena pele bıvurne",
-       "tooltip-ca-addsection": "Zu bınnusteya newi ak",
+       "tooltip-ca-addsection": "Bınleteyo newe akerê",
        "tooltip-ca-viewsource": "Ena pele kılit biya.\nŞıma şenê çımeyê aye bıvênê",
        "tooltip-ca-history": "Versiyonê verênê ena pele",
        "tooltip-ca-protect": "Ena pele bışevekne",
        "tooltip-t-emailuser": "Ena karber ri yew email bırış",
        "tooltip-t-upload": "Dosyeyan bar ke",
        "tooltip-t-specialpages": "Yew lista pelanê xasanê pêroyinan",
-       "tooltip-t-print": "Hewl versiyona ploğnayışa na perer",
+       "tooltip-t-print": "Versiyonê peleyo ke şeno çap bıkeriyo.",
        "tooltip-t-permalink": "Gırêyo daimi be ena versiyonê pele",
        "tooltip-ca-nstab-main": "Pela zerreki bıvêne",
        "tooltip-ca-nstab-user": "Pela karberi bıvêne",
        "tooltip-ca-nstab-media": "Pela medya bıvêne",
        "tooltip-ca-nstab-special": "Na yew pela xasa, şıma nêşenê sero vurnayış bıkerê",
        "tooltip-ca-nstab-project": "Pela proceyi bıvêne",
-       "tooltip-ca-nstab-image": "Pera dosyayer bıvin",
+       "tooltip-ca-nstab-image": "Pela dosya bıvêne",
        "tooltip-ca-nstab-mediawiki": "Mesacê sistemi bımocne",
        "tooltip-ca-nstab-template": "Şabloni bıvêne",
        "tooltip-ca-nstab-help": "Pela peşti bıvêne",
        "tooltip-minoredit": "Nay vırnayışa werdi nışan bıkeré",
        "tooltip-save": "Vurnayışanê xo qeyd ke",
        "tooltip-publish": "Vurnayışê xo vıla kı",
-       "tooltip-preview": "VurnayıÅ\9fané Ä\9fo Ã§Ä±mra ravyarné. Verdé qeyd kerdıÅ\9fi eneri bıkarné!",
+       "tooltip-preview": "VurnayıÅ\9fanê xo Ã§Ä±m ra bıviyarnê. QeydkerdıÅ\9f ra ver bıgurê cı!",
        "tooltip-diff": "Metni sero vurnayışan mocneno",
        "tooltip-compareselectedversions": "Ena per de ferqê rewziyonan de dı weçinaya bıvinê",
        "tooltip-watch": "Ena pele lista xoya seyrkerdışi ke",
        "tooltip-rollback": "\"Peyser biya\" be yew tık pela iştıraqanê peyênan peyser ano",
        "tooltip-undo": "\"Undo\" ena vurnayışê newi iptal kena u vurnayışê verni a kena.\nTı eşkeno yew sebeb bınus.",
        "tooltip-preferences-save": "Terciha qeyd ke",
-       "tooltip-summary": "Yew xulasaya kilm binuse",
+       "tooltip-summary": "Xulasa kılmek bınuse",
        "interlanguage-link-title": "$1 - $2",
        "common.css": "/************************************************\n * COMMON CSS\n *\n * Any CSS placed in this page will be used on \n * all skins, please think carefully about if it\n * belongs here (and not in one of the skin CSS\n * pages) before adding it. Thanks.\n ************************************************/\n\n/* <table class=\"highlighthovertable\"> */\ntable.highlighthovertable tr:hover,\ntable.highlighthovertable tr:hover td,\ntable.mw-ext-translate-groupstatistics tr:hover,\ntable.mw-ext-translate-groupstatistics tr:hover td {\n background-color: white;\n}\n\n\n/* Babel wrapper layout. */\n/* XXX: This is either redundant or should be in-core */\n/* @noflip */table.mw-babel-wrapper {\n\twidth:        238px;\n\tfloat:        right;\n\tclear:        right;\n\tmargin:       1em;\n\tborder-style: solid;\n\tborder-width: 1px;\n\tborder-color: #99B3FF;\n}\n\n/* Babel box layout. */\n/* @noflip */div.mw-babel-box {\n\tfloat:  left;\n\tclear:  left;\n\tmargin: 1px;\n}\n\ndiv.mw-babel-box table {\n\twidth: 238px;\n}\n\ndiv.mw-babel-box table th {\n\twidth:       238px;\n\twidth:       45px;\n\theight:      45px;\n\tfont-size:   14pt;\n\tfont-family: monospace;\n}\n\ndiv.mw-babel-box table td {\n\tfont-size:   8pt;\n\tpadding:     4pt;\n\tline-height: 1.25em;\n}\n\n/* Babel box colours. */\ndiv.mw-babel-box-0 {\n\tborder: solid #B7B7B7 1px;\n}\n\ndiv.mw-babel-box-1 {\n\tborder: solid #C0C8FF 1px;\n}\n\ndiv.mw-babel-box-2 {\n\tborder: solid #77E0E8 1px;\n}\n\ndiv.mw-babel-box-3 {\n\tborder: solid #99B3FF 1px;\n}\n\ndiv.mw-babel-box-4 {\n\tborder: solid #CCCC00 1px;\n}\n\ndiv.mw-babel-box-5 {\n\tborder: solid #F99C99 1px;\n}\n\ndiv.mw-babel-box-N {\n\tborder: solid #6EF7A7 1px;\n}\n\ndiv.mw-babel-box-0 table th {\n\tbackground-color: #B7B7B7;\n}\n\ndiv.mw-babel-box-1 table th {\n\tbackground-color: #C0C8FF;\n}\n\ndiv.mw-babel-box-2 table th {\n\tbackground-color: #77E0E8;\n}\n\ndiv.mw-babel-box-3 table th {\n\tbackground-color: #99B3FF;\n}\n\ndiv.mw-babel-box-4 table th {\n\tbackground-color: #CCCC00;\n}\n\ndiv.mw-babel-box-5 table th {\n\tbackground-color: #F99C99;\n}\n\ndiv.mw-babel-box-N table th{\n\tbackground-color: #6EF7A7;\n}\n\ndiv.mw-babel-box-0 table {\n\tbackground-color: #E8E8E8;\n}\n\ndiv.mw-babel-box-1 table {\n\tbackground-color: #F0F8FF;\n}\n\ndiv.mw-babel-box-2 table {\n\tbackground-color: #D0F8FF;\n}\n\ndiv.mw-babel-box-3 table {\n\tbackground-color: #E0E8FF;\n}\n\ndiv.mw-babel-box-4 table {\n\tbackground-color: #FFFF99;\n}\n\ndiv.mw-babel-box-5 table {\n\tbackground-color: #F9CBC9;\n}\n\ndiv.mw-babel-box-N table {\n\tbackground-color: #C5FCDC;\n}\n\n.babel-box td.babel-footer {\n\ttext-align: center;\n}\n\n/* Styling for portals. */\ndiv.table {\n    display:        table;\n    vertical-align: top;\n    width:          100%;\n}\n\ndiv.table-row {\n    display:        table-row;\n    vertical-align: top;\n}\n\ndiv.table-cell {\n    display:        table-cell;\n    vertical-align: top;\n}\n\nbody.ns-100 table.mw-babel-wrapper {\n    border:           solid 1px #bbbbbb;\n    background-color: #f0f0f0;\n    margin-left:      1em;\n}\n\n.graytext {\n    color: #aaa;\n}\n\n/* On [[Special:RecentChanges]] and [[Special:Watchlist]] make the new pages symbol bold green and the minor edit symbol gray. */\n.newpage {\n    color:       green;\n    font-weight: bold\n}\n\n.minoredit,\n.minor {\n    color: gray;\n}\n\n/* Monospace diffs, this makes more sense since diffs show what would be seen in the edit box. */\n/* Note: Anno 2012 many browsers don't use monospace in the textarea anymore by default, notably Chrome and Safari don't (unless the user overrides this in the preferences) */\n.diff-context,\n.diff-deletedline,\n.diff-addedline {\n    font-family: monospace, \"Courier New\";\n/* Just guess does the stupid wikidiff2 extensions add extra whitespace around..... */\n    white-space: -moz-pre-wrap;\n    white-space: pre-wrap;\n}\n \n.diffchange {\n    border: 1px dotted rgb( 170, 170, 170 );\n}\n\n/* It is unclear what the following CSS does, please add comments if you can clarify. */\n/* The box which is 400px high and if its content is longer, it gets the scrollbar */\n.scrollme {\n    overflow: scroll;\n    width:    100%;\n    height:   400px;\n}\n\n/* Standard Navigationsleisten, aka box hiding thingy from .de.  Documentation at [[Wikipedia:NavFrame]]. */\ndiv.Boxmerge, div.NavFrame { margin: 0; padding: 4px; border-collapse: collapse;}\ndiv.Boxmerge div.NavFrame { border-style: none; border-style: hidden; }\ndiv.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; }\ndiv.NavFrame div.NavHead { height: 1.6em; position:relative; }\ndiv.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; }\na.NavToggle { position: absolute; top: 0; right: 5px; }\n.note-flaggedrevs * a.NavToggle { right: 12px; } /* For [[Template:Flagged Revs]] */\n\n/* Template:Languages */\n.bw-languages {\n    border:          1px solid #aaaaaa;\n    padding:         0.2em;\n    border-collapse: collapse;\n    line-height:     1.2;\n    font-size:       95%;\n    margin:          1px 1px;\n}\n.bw-languages-title {\n    width:        180px;\n    border:       1px solid #aaaaaa;\n    background:   #EEF3E2;\n    padding:      0.5em;\n    font-weight:  bold;\n}\n.bw-languages-links { padding:0.5em; background:#F6F9ED; }\n\n/* Senseless in this project */\n#editpage-copywarn { display: none; }\n\n/* Hide warnings about bad links on MediaWiki:Common.css */\n.page-MediaWiki_Common_css .mw-translate-messagechecks { display: none; }\n\n/*******************\n** Faciliate RTL translation\n*******************/\n/* @noflip */\n#bodyContent .arabic a {\n\tpadding-right:0;\n\tbackground:none;\n}\n\n.vatop tr, tr.vatop, .vatop td, .vatop th {\n vertical-align: top;\n}\n\n.bw-languages {\n direction: ltr;\n}\n\n/* prevent wrapping of lines in LQT TOC if not necessary */\ntable.lqt_toc {\n\twidth: auto;\n}\n\n/* [[m:MediaZilla:35337]] */\n@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 1.5dppx) {\n        #p-logo a {\n                background-image: url(\"//translatewiki.net/images/thumb/7/7c/Translatewiki-logo-bare.svg/152px-Translatewiki-logo-bare.svg.png\") !important;\n                background-size: auto 135px;\n        }\n}\n@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {\n        #p-logo a {\n                background-image: url(\"//translatewiki.net/images/thumb/7/7c/Translatewiki-logo-bare.svg/202px-Translatewiki-logo-bare.svg.png\") !important;\n                background-size: auto 135px;\n        }\n}\n\n/* qqq visibility, [[Thread:Support/Suggestion: Add this CSS to MediaWiki:Common.css]] */\n \n.mw-sp-translate-edit-info .mw-content-ltr {\n  background-position:left center;\n  padding-left:45px;\n}\nfieldset.mw-sp-translate-edit-info .mw-centent-rtl {\n  background-position:right center;\n  padding-right:45px;\n}\n\n/* Semantic MediaWiki - make special properties easier to identify */\n\n.smwbuiltin a,\n.smwbuiltin a.new {\n\tcolor: #FF8000;\n}\n\n/* Recentchangestext toggle link */\n.white-link a {\n    color: #fff;\n}",
        "common.js": "/* Any JavaScript here will be loaded for all users on every page load. */",
        "widthheight": "$1 - $2",
        "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|pele|peli}}",
        "file-info": "ebatê dosyayi: $1, MIME tip: $2",
-       "file-info-size": "$1 × $2 pixelan, ebatê dosya: $3, MIME type: $4",
+       "file-info-size": "$1 × $2 pikselan, ebatê dosya: $3, MIME tipê cı: $4",
        "file-info-size-pages": "$1 × $2 pikse, dergeya dosyay: $3, MIME tipiya cı: $4, $5 {{PLURAL:$5|pela|pela}}",
        "file-nohires": "Deha berz agozney cı çıniyo",
        "svg-long-desc": "Dosyay SVG, zek vanê $1 × $2 piksela, ebatê dosya: $3",
        "svg-long-desc-animated": "SVG dosya, nominalin $1 × $2 piksela, ebatê dosya: $3",
        "svg-long-error": "Nêmeqbul dosyaya SVG'i: $1",
        "show-big-image": "Dosyaya oricinale",
-       "show-big-image-preview": "Verqaytê dergiya: $1.",
+       "show-big-image-preview": "Vervênayışê ebatê : $1.",
        "show-big-image-other": "Zewmi{{PLURAL:$2|Vılêşnayış|Vılêşnayışê}}: $1.",
        "show-big-image-size": "$1 × $2 piksel",
        "file-info-gif-looped": "viyariye biyo",
        "file-info-png-frames": "$1 {{PLURAL:$1|çerçeve|çerçeveyi}}",
        "file-no-thumb-animation": "'''Not: Dılet tekniko limit, gırd agozneya resm de qıckek de animasyoni miyan dı nêbo.'''",
        "file-no-thumb-animation-gif": "'''Not: Dılet tekniko limit, gırd agozneya resm de qıckek de  GIF imaci de animasyon do nêbo.'''",
-       "newimages": "Galeriya dosyanê neweyan",
+       "newimages": "Galeriya dosyanê newan",
        "imagelisttext": "Cêr de yew listeyê '''$1''' esto {{PLURAL:$1|dosya|dosyayi}} veçiniya $2.",
        "newimages-summary": "Ena pela xasi dosyayi ke peni de bar biyayeyi mocnane.",
        "newimages-legend": "Avrêc",
        "exif-primarychromaticities": "Kromaticitiyê eveli",
        "exif-ycbcrcoefficients": "Cayê rengi yê transformasyon metriksê koefişinti",
        "exif-referenceblackwhite": "Çiftyê siya u sipe değerê referansi",
-       "exif-datetime": "Zeman u tarixê vurnayişê dosyayi",
+       "exif-datetime": "Zeman u tarixê vurnayışê dosya",
        "exif-imagedescription": "Serê resimi",
        "exif-make": "Vıraştoğê kamera",
        "exif-model": "Modelê kamera",
-       "exif-software": "Software ke hebitiyeno",
+       "exif-software": "Softwaro ke xebıtiyeno",
        "exif-artist": "Nuştoğ",
        "exif-copyright": "Wahirê copyrighti",
        "exif-exifversion": "Versiyonê Exif",
        "exif-usercomment": "Mışewreyê karberi",
        "exif-relatedsoundfile": "Derhekê dosya yê vengi",
        "exif-datetimeoriginal": "Demê afernayışê dayeyo sıfteyıni",
-       "exif-datetimedigitized": "Zeman û tarixê dicitalkerdışi",
+       "exif-datetimedigitized": "Zeman u tarixê dijitalkerdışi",
        "exif-subsectime": "ZemanTarix saniyeyibini",
        "exif-subsectimeoriginal": "ZemanTarixOricinal saniyeyibini",
        "exif-subsectimedigitized": "ZemanTarixDicital saniyeyibini",
        "version": "Versiyon",
        "version-extensions": "Ekstensiyonî ke ronaye",
        "version-skins": "Bar kerde bejni",
-       "version-specialpages": "Pelê xısusiyi",
+       "version-specialpages": "Pelê hısusiy",
        "version-parserhooks": "Çengelê Parserî",
        "version-variables": "Vurnayeyî",
        "version-antispam": "Spam vındarnayış",
        "version-libraries-license": "Lisans",
        "version-libraries-description": "Şınasnayış",
        "version-libraries-authors": "Nuştekari",
-       "redirect": "Serşıkıtena dosya, karberi, pele ya ki revizyonê kamiya dosya",
+       "redirect": "Kırıştena dosya, karberi, perra ya ki revizyonê ID",
        "redirect-summary": "Na pela xase to hetê yew dosya (nameyê dosya dayeyo), yew pele (kamiya revizyoni ya zi pele dayiya) ya zi yew pela karberi (kamiya karberiya reqemkiye dayiya) ser şıknena. Gurenayış: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], ya zi  [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Şo",
        "redirect-lookup": "Bewni",
        "fileduplicatesearch-result-1": "Dosyayê ''$1î'' de hem-kopya çini yo.",
        "fileduplicatesearch-result-n": "Dosyayê ''$1î'' de {{PLURAL:$2|1 hem-kopya|$2 hem-kopyayî'}} esto.",
        "fileduplicatesearch-noresults": "Ebe namey \"$1\" ra dosya nêdiyayê.",
-       "specialpages": "Pelê xısusiyi",
+       "specialpages": "Pelê hısusiy",
        "specialpages-note-top": "Kıtabek",
        "specialpages-note": "* Pelê xasê normali.\n* <span class=\"mw-specialpagerestricted\">Pelê xasê nımıtey.</span>",
        "specialpages-group-maintenance": "Raporê pawıtışi",
        "specialpages-group-login": "Dekew / hesab vıraz",
        "specialpages-group-changes": "Vurnayışê peyêni û qeydi",
        "specialpages-group-media": "Raporê medya û barkerdışi",
-       "specialpages-group-users": "Karberi û heqi",
+       "specialpages-group-users": "Karberi u heqê inan",
        "specialpages-group-highuse": "Peleyê ke vêşi karênê",
        "specialpages-group-pages": "Listeyê pelan",
        "specialpages-group-pagetools": "Haletê pelan",
        "tags-create-reason": "Sebeb:",
        "tags-create-submit": "Vıraze",
        "tags-edit-reason": "Sebeb:",
-       "comparepages": "Pela miqeyese ke",
+       "comparepages": "Pelan têversanê",
        "compare-page1": "Pele 1",
        "compare-page2": "Pele 2",
        "compare-rev1": "Revizyonê 1i",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|bayt|bayti}}",
        "limitreport-expansiondepth": "Tewr veşi herayina dergbiyayışi",
        "limitreport-expensivefunctioncount": "Amoriya fonksiyonde vay agozni",
-       "expandtemplates": "Å\9fablonan hêra ker",
+       "expandtemplates": "Å\9eablonan hera kı",
        "expand_templates_intro": "Na pela xususi metın geno u şablonê ke tedeyê reyna reyna hêra keno.\nU hem zi nê fonksiyonan hêra keno\n<nowiki>{{</nowiki>#language:…}}</code>, u zey nê parametreyan\n<nowiki>{{</nowiki>CURRENTDAY}}</code>\nEneri Medya wiki sera xo keno.",
        "expand_templates_title": "Sernameyê weziyeti, misal qandê {{FULLPAGENAME}}.:",
        "expand_templates_input": "sernameyê cıkewtışi:",
        "mw-widgets-dateinput-placeholder-day": "SSSS-AA-RR",
        "mw-widgets-dateinput-placeholder-month": "SSSS-AA",
        "mw-widgets-titleinput-description-redirect": "berd be $1",
-       "log-action-filter-newusers": "Babetê hesabvıraştışi:"
+       "randomrootpage": "Pela raştmameya rıçıkıne",
+       "log-action-filter-newusers": "Babetê hesabvıraştışi:",
+       "changecredentials": "Malumatanê karberi bıvurnê",
+       "removecredentials": "Kamiye wedarne",
+       "removecredentials-submit": "Kamiyer wedarne"
 }
index cf025f0..f59d719 100644 (file)
        "yourpasswordagain": "Šćitne gronidło hyšći raz zapódaś:",
        "createacct-yourpasswordagain": "Gronidło wobkšuśiś",
        "createacct-yourpasswordagain-ph": "Zapódaj gronidło hyšći raz",
-       "remembermypassword": "Na toś tom licadle pśizjawjony wóstaś (za maksimalnje $1 {{PLURAL:$1|źeń|dnja|dny|dnjow}})",
        "userlogin-remembermypassword": "Pśizjawjony wóstaś",
        "userlogin-signwithsecure": "Wěsty zwisk wužywaś",
        "yourdomainname": "Twója domejna",
        "activeusers-intro": "To jo lisćina wužywarjow, kotrež su byli aktiwne za {{PLURAL:$1|slědny źeń|slědnej $1 dnja|slědne $1 dny|slědnych $1 dnjow}}.",
        "activeusers-count": "$1 {{PLURAL:$1|akcija|akciji|akcije|akcijow}} w {{PLURAL:$3|slědnem dnju|slědnyma $3 dnjoma|slědnych $3 dnjach}}",
        "activeusers-from": "Wužywarjow zwobrazniś, zachopinajucy z:",
-       "activeusers-hidebots": "Boty schowaś",
-       "activeusers-hidesysops": "Administratorow schowaś",
        "activeusers-noresult": "Žedne wužywarje namakane.",
        "listgrouprights": "Pšawa wužywarskeje kupki",
        "listgrouprights-summary": "To jo lisćina wužywarskich kupkow definěrowanych w toś tom wikiju z jich zwězanymi pśistupnymi pšawami. Móžo [[{{MediaWiki:Listgrouprights-helppage}}|pśidatne informacije]] wó jadnotliwych pšawach daś.",
        "htmlform-cloner-create": "Wěcej pśidaś",
        "htmlform-cloner-delete": "Wótpóraś",
        "htmlform-cloner-required": "Nanejmjenjej jadna gódnota jo trěbna.",
-       "sqlite-has-fts": "Wersija $1 z pódpěru za połnotekstowe pytanje",
-       "sqlite-no-fts": "Wersija $1 bźez pódpěry za połnotekstowe pytanje",
        "logentry-delete-delete": "$1 jo bok $3 {{GENDER:$2|wulašował|wulašowała}}",
        "logentry-delete-restore": "$1 jo bok $3 {{GENDER:$2|wótnowił|wótnowiła}}",
        "logentry-delete-event": "$1 jo {{GENDER:$2|změnił|změniła}} widobnosć {{PLURAL:$5|protokolowego zapiska|$5 protokoloweju zapiskowu|$5 protokolowych zapiskow}} na $3: $4",
index e40e405..68ce13c 100644 (file)
        "yourpasswordagain": "Mintaipo kaatalib:",
        "createacct-yourpasswordagain": "Kompomo borospanalib",
        "createacct-yourpasswordagain-ph": "Posuango kaagu borospanalib",
-       "remembermypassword": "Soroho ot loginku id popogihuman diti (gisom solinaid do $1 {{PLURAL:$1|tadau|madau}})",
        "userlogin-remembermypassword": "Potilombuso oku do poinsuang log",
        "userlogin-signwithsecure": "Gunoo noputan noumoligan",
        "yourdomainname": "Damin nu:",
        "passwordreset-emailtitle": "Kointalangan takaun id {{SITENAME}}",
        "passwordreset-emailelement": "Ngaranmoguno: \n$1\n\nKaatalib daamot: \n$2",
        "passwordreset-emailsentemail": "Surat-i pononsorou nakaatod noh.",
-       "passwordreset-emailsent-capture": "Surat-i pononsorou nakaatod noh, miagal id siriba diti.",
-       "passwordreset-emailerror-capture": "Surat-i pononsorou nopudali noh, miagal id siriba diti, nga awu kaatod id momomoguno: $1",
        "changeemail": "Alanai porikatan surat-i",
        "changeemail-header": "Alanai akaun porikatan surat-i",
        "changeemail-no-info": "Mositi sumuang log ko do mongoguno monilombus id bolikon diti.",
index 2a4bf50..b6e1b18 100644 (file)
        "category-file-count-limited": "निम्न {{PLURAL:$1|फाइल|$1 फाइलहरू}} यै श्रेणीमी रया छ ।",
        "listingcontinuesabbrev": "निरन्तरता...",
        "index-category": "क्रमाङ्कित पानाहरू",
-       "noindex-category": "à¤\95à¥\8dरमाà¤\99à¥\8dà¤\95न à¤¨à¤\97रà¥\80याà¤\95ा à¤ªà¤¾à¤¨à¤¾à¤¹à¤°à¥\82",
+       "noindex-category": "à¤\85नà¥\81à¤\95à¥\8dरमित à¤¨à¤\85रियाऽ à¤ªà¤¨à¥\8dनाà¤\85न",
        "broken-file-category": "टुटेको फाइल लिङ्कहरूसितको पाना",
        "about": "बारेमी",
        "article": "सामाग्री पानो",
        "passwordreset": "पासवर्ड पूर्वनिर्धारित गर",
        "passwordreset-username": "प्रयोगकर्ता-नाम:",
        "passwordreset-domain": "डोमेन",
-       "passwordreset-capture": "निस्कने इमेलको नमुना हेर्ने ?",
        "passwordreset-email": "इमेल ठेगाना:",
        "passwordreset-emailtitle": "{{SITENAME}}मा खाता विवरण",
        "passwordreset-emailelement": "प्रयोगकर्ताको नाम: \n$1\n\nअस्थाई पासवर्ड: \n$2",
        "passwordreset-emailsentemail": "यदि यो इमेल ठेगाना तम सित सम्बन्धित छ भण्या, तब यक पासवर्ड रिसेट इमेल पठाएलो।",
-       "passwordreset-invalideamil": "अबैध ई-मेल ठेगाना",
+       "passwordreset-invalidemail": "अबैध ई-मेल ठेगाना",
        "changeemail": "इमेल ठेगाना बदेल वा हटा",
        "changeemail-header": "तमरो इमेल ठेगाना बदेल्लाइ एइ फाराम पुराइ भरऽ। यदि तम तमरा खाता बठेइ कसै लै इमेल ठेगाना सितोऽ सम्बन्ध हटौन चाहन्छऽ भण्या, फाराम बुजौन्ज्याँ नौलो इमेल ठेगाना भण्ण्या ठौर खालि छाण्याऽ।",
        "changeemail-oldemail": "अईलको इमेल-ठेगाना:",
        "searchprofile-advanced-tooltip": "अनुकुल नेमस्पेसमा खोज्या",
        "search-result-size": "$1 ({{PLURAL:$2|1 आँखर|$2 आँखर}})",
        "search-result-category-size": "{{PLURAL:$1|एक सदस्य|$1 सदस्यहरू}} ({{PLURAL:$2|1 उपश्रेणी|$2  उपश्रेणीहरू}}, {{PLURAL:$3|एउटा फाइल|$3 फाइलहरू}})",
-       "search-redirect": "(जान्या $1)",
+       "search-redirect": "($1 बठेइ पुन:निर्देशित)",
        "search-section": "(खण्ड $1)",
        "search-category": "(श्रेणी $1)",
        "search-file-match": "(भेटिईया फाइल सामाग्री)",
        "userrights-changeable-col": "तमले परिवर्तन गद्द सक्दया समूहअन",
        "userrights-unchangeable-col": "तमीले परिवर्तन गद्द नसक्ने समूहहरू",
        "userrights-conflict": "प्रयोगकर्ताको अधिकार परिवर्तनमी मतभेद भयो ! कृपया तमरो परिवर्तन पुनरावलोकन तथा पुष्टि गर ।",
-       "userrights-removed-self": "तमले सफलतापूर्वक आफनो अधिकारहरूलाई मेटाया । त्यै कारण तम आब यो पानो हेद्द नाइसक्दा ।",
        "group": "समूह:",
        "group-user": "प्रयोगकर्ताहरू",
        "group-autoconfirmed": "स्वत स्थापित प्रयोगकर्ताहरू",
        "activeusers-intro": "यो सूची ती प्रयोगकर्तानको हो जनले विगत $1 {{PLURAL:$1|दिन| दिन}}मी  गतिविधि देखायाकाछन्।",
        "activeusers-count": "विगत {{PLURAL:$3|दिनमी|$3 दिनहरूमी}}  $1 {{PLURAL:$1|सम्पादन गरियो|सम्पादनहरू गरिया}}",
        "activeusers-from": "यहाँबठे सुरु हुन्या प्रयोगकर्ताहरू धेकाओ:",
-       "activeusers-hidesysops": "प्रवन्धकहरू लुकाउन्या",
        "activeusers-noresult": "प्रयोगकर्ताहरू भेटियानन्",
        "mailnologintext": "तमीले अरु प्रयोगकर्तानलाई ईमेल पठाउनको लागि आफु पहिली [[Special:UserLogin|प्रवेश(लगइन)गर्याको]] हुनुपडन्छ र [[Special:Preferences|आफ्नो रोजाइहरूमी]] एउटा वैध ईमेल ठेगाना भयाको हुनुपडन्छ ।",
        "emailpagetext": "तल दियाको फार्मले तमी यै {{GENDER:$1|प्रयोगकर्ता}}लाई इमेल पठाउन सक्द्या हौ । तमीले जो ठेगाना [[Special:Preferences|आफ्नो प्रयोगकर्ता रोजाईहरू]]मी दियाका छियौ त्यो यै इमेललाई \"पठाउने\" को रूपमी आउन्याछ, अतः प्राप्तकर्ता तमीलाई सिधै जवाफ दिनसक्द्याछ ।",
        "logentry-newusers-create": "प्रयोगकर्ता खाता $1 {{GENDER:$2|खोलियो}}",
        "logentry-upload-upload": "$1 ले $3 {{GENDER:$2|अपलोड अरेका छन्}}",
        "feedback-bugornote": "यदि तमी कुनै प्राविधिक समस्यालाई विस्तारले सम्झाउन तयार छौ भण्या कृपया [$1 बग राख]।\nयदि हैन, भण्या तमी तल दियाको सरल फारमको प्रयोग गद्दसक्द्याहौ । तमरो टिप्पणी, तमरो प्रयोगकर्ता नाम र तमरो ब्राउजरको नाम सहित \"[$3 $2]\" पानामी जोडिन्याछ ।",
-       "searchsuggest-search": "खोज:",
+       "searchsuggest-search": "{{SITENAME}} खोजऽ",
        "api-error-duplicate": "यै साइटमी पहिलीबठे यस्तै सामग्री {{PLURAL:$1|भयाको अर्को फाइल छ|भयाका  केहि अरु फाइलहरू छन्}} ।",
        "api-error-duplicate-archive": "यै साइटमी पहिलेबाट यस्तै सामग्री {{PLURAL:$1|भयाको अर्को फाइल थियो|भयाका केहि अरु फाइलहरू थिए}} ।\nतर {{PLURAL:$1|यो मेट्याको थियो|यी मेटायाका थिए}} ।",
        "expand_templates_preview_fail_html": "<em>किनकि {{SITENAME}} सिधै एचटिएमयल सक्षम छ र तमीले लग इन गर्या छैनौ, पूर्वावलोकन लुकाइयाको छ ताकि सम्भावित जाभास्क्रिप्ट आक्रमणलाई रोक्द सकियोस् ।</em>\n\n<strong>यदि यो मान्य पूर्ववावलोकन प्रयास हो भण्या पुन प्रयास गर ।</strong>\nयदि यसले कार्य पूर्ण भएन भण्या [[Special:UserLogout|लग आउट गरिबर]] फेरी लग इन गर्या ।",
index 8e70898..40d6931 100644 (file)
        "categories": "ގިސްމުތައް",
        "categoriespagetext": "ތިރީގައި މިވާ ގިސްމުތައް ވިކީ ގައި މައުޖޫދުވެގެން ވެއެވެ.\n[[Special:UnusedCategories|Unused categories]] are not shown here.\nAlso see [[Special:WantedCategories|wanted categories]].",
        "activeusers": "ހަރަކާތްތެރި މެމްބަރުންގެ ލިސްޓު",
-       "activeusers-hidebots": "ބޮޓް ފޮރުއްވާ",
-       "activeusers-hidesysops": "އެޑްމިނިސްޓްރޭޓަރުން ފޮރުއްވާ",
        "listgrouprights-members": "(މެމްބަރުންގެ ލިސްޓު)",
        "emailuser": "މި މެންބަރަށް އީމޭލު ފޮނުއްވާ",
        "watchlist": "މަގޭ ނަޒަރު",
index dcb9f4c..3cfb2c2 100644 (file)
        "cannotloginnow-title": "Δεν μπορείτε να συνδεθείτε τώρα",
        "cannotloginnow-text": "Η σύνδεση δεν είναι δυνατή όταν χρησιμοποιείτε την $1.",
        "cannotcreateaccount-title": "Αδυναμία δημιουργίας λογαριασμού",
+       "cannotcreateaccount-text": "Άμεση δημιουργία λογαριασμού δεν είναι ενεργοποιημένη σε αυτό το wiki.",
        "yourdomainname": "Το domain σας:",
        "password-change-forbidden": "Δεν μπορείτε να αλλάξετε τους κωδικούς πρόσβασης σε αυτό το βίκι.",
        "externaldberror": "Είτε συνέβη κάποιο σφάλμα εξωτερικής πιστοποίησης της βάσης δεδομένων είτε δεν σας έχει επιτραπεί να ενημερώσετε τον εξωτερικό σας λογαριασμό.",
        "botpasswords-newpassword": "Ο νέος κωδικός πρόσβασης για να συνδεθείτε με το <strong>$1</strong> είναι <strong>$2</strong>. <em>Παρακαλούμε σημειώστε το για μελλοντική αναφορά.</em><br />(Για παλιά bot που απαιτούν το όνομα σύνδεσης να είναι το ίδιο με το τελικό όνομα χρήστη, μπορείτε επίσης να χρησιμοποιήσετε το  <strong>$3</strong> ως όνομα χρήστη και <strong>$4</strong> ως κωδικό.)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider δεν είναι διαθέσιμο.",
        "botpasswords-restriction-failed": "Περιορισμοί κωδικών πρόσβασης bot εμποδίζουν τη συγκεκριμένη σύνδεση.",
+       "botpasswords-invalid-name": "Το όνομα χρήστη που ορίζεται δεν περιέχει το διαχωριστικό κωδικό πρόσβασης bot (\"$1\").",
+       "botpasswords-not-exist": "Ο χρήστης \"$1\" δεν έχει κωδικό bot με όνομα \"$2\"",
        "resetpass_forbidden": "Οι κωδικοί πρόσβασης δεν μπορούν να αλλαχθούν",
        "resetpass_forbidden-reason": "Οι κωδικοί πρόσβασης δεν μπορούν να αλλαχθούν: $1",
        "resetpass-no-info": "Πρέπει να είστε συνδεδεμένος για να δείτε αυτήν την σελίδα απευθείας",
        "passwordreset-emaildisabled": "Τα χαρακτηριστικά ηλεκτρονικού ταχυδρομείου έχουν απενεργοποιηθεί σ' αυτό το wiki.",
        "passwordreset-username": "Όνομα χρήστη:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "Προβολή του μηνύματος ηλεκτρονικού ταχυδρομείου που δημιουργήθηκε;",
-       "passwordreset-capture-help": "Εάν μαρκάρετε αυτό το πλαίσιο, το μήνυμα ηλεκτρονικού ταχυδρομείου (με το προσωρινό κωδικό πρόσβασης) θα εμφανιστεί σε σας καθώς θα αποσταλεί στο χρήστη.",
        "passwordreset-email": "Διεύθυνση ηλεκτρονικού ταχυδρομείου:",
        "passwordreset-emailtitle": "Λεπτομέρειες λογαριασμού για {{SITENAME}}",
        "passwordreset-emailtext-ip": "Κάποιος (πιθανώς εσείς, από την διεύθυνση IP $1) ζήτησε την επαναφορά του κωδικού σας σε {{SITENAME}} ($4).  {{PLURAL:$3|Ο ακόλουθος λογαριασμός|Οι ακόλουθοι λογαριασμοί}} χρήστη συνδέονται με αυτή τη διεύθυνση e-mail:\n\n$2\n\n{{PLURAL:$3|Αυτός ο προσωρινός κωδικός πρόσβασης θα λήξει|Αυτοί οι προσωρινοί κωδικοί πρόσβασης θα λήξουν}} σε {{PLURAL:$5|μία ημέρα|$5 ημέρες}}.\nΘα πρέπει να συνδεθείτε τώρα και να επιλέξετε ένα νέο κωδικό. Αν κάποιος άλλος έκανε αυτό το αίτημα ή αν έχετε θυμηθεί τον αρχικό κωδικό πρόσβασής σας, και δεν επιθυμείτε πια να τον αλλάξετε, μπορείτε να αγνοήσετε αυτό το μήνυμα και να συνεχίσετε να χρησιμοποιείτε τον παλιό σας κωδικό πρόσβασης.",
        "passwordreset-emailelement": "Όνομα χρήστη: \n$1\n\nΠροσωρινός κωδικός πρόσβασης:\n$2",
        "passwordreset-emailsentemail": "Αν αυτή η διεύθυνση ηλεκτρονικού ταχυδρομείου συνδέεται με το  λογαριασμό σας, τότε  θα σας αποσταλεί μήνυμα ηλεκτρονικού ταχυδρομείου για την επαναφορά του κωδικού πρόσβασης.",
        "passwordreset-emailsentusername": "Αν υπάρχει μια διεύθυνση ηλεκτρονικού ταχυδρομείου που συνδέεται με αυτό το όνομα χρήστη, τότε θα σας αποσταλεί ένα μήνυμα ηλεκτρονικού ταχυδρομείου για την επαναφορά του κωδικού πρόσβασης.",
-       "passwordreset-invalideamil": "Μη έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου",
+       "passwordreset-invalidemail": "Μη έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου",
        "changeemail": "Αλλαγή ή αφαίρεση της διεύθυνσης ηλεκτρονικού ταχυδρομείου",
        "changeemail-header": "Συμπληρώστε αυτήν τη φόρμα για να αλλάξετε τη διεύθυνσή σας ηλεκτρονικού ταχυδρομείου. Αν θέλετε να καταργήσετε τη σύνδεση οποιασδήποτε διεύθυνσης ηλεκτρονικού ταχυδρομείου με το λογαριασμό σας, αφήστε τη νέα διεύθυνση ηλεκτρονικού ταχυδρομείου κενή κατά την υποβολή της φόρμας.",
        "changeemail-no-info": "Πρέπει να έχετε συνδεθεί για άμεση πρόσβαση σε αυτήν τη σελίδα.",
        "prefs-help-recentchangescount": "Αυτό περιλαμβάνει τις πρόσφατες αλλαγές, τα ιστορικά των σελίδων, και τα αρχεία διαγραφών.",
        "prefs-help-watchlist-token2": "Αυτό είναι το μυστικό κλειδί για την web τροφοδοσία  της λίστας παρακολούθησής σας.\nΌποιος το γνωρίζει θα είναι σε θέση να διαβάσει την λίστα παρακολούθησης σας, οπότε μην τον μοιράζεστε.\n[[Special:ResetTokens|Κάνε κλικ εδώ εάν θέλετε να τον επαναφέρετε]].",
        "savedprefs": "Οι προτιμήσεις σας έχουν αποθηκευτεί.",
-       "savedrights": "Τα Î´Î¹ÎºÎ±Î¹Ï\8eμαÏ\84α Ï\87Ï\81ήÏ\83Ï\84η Î±Ï\80Ï\8c {{GENDER:$1|$1}} έχουν αποθηκευτεί.",
+       "savedrights": "Î\9fι Î¿Î¼Î¬Î´ÎµÏ\82 Ï\87Ï\81ηÏ\83Ï\84Ï\8eν {{GENDER:$1|Ï\84οÏ\85 $1|Ï\84ηÏ\82 $1}} έχουν αποθηκευτεί.",
        "timezonelegend": "Ζώνη ώρας:",
        "localtime": "Εμφάνιση τοπικής ώρας:",
        "timezoneuseserverdefault": "Χρήση της προεπιλογής του wiki ($1)",
        "userrights-reason": "Αιτία:",
        "userrights-no-interwiki": "Δεν έχετε άδεια να επεξεργαστείτε τα δικαιώματα χρηστών σε άλλα wiki.",
        "userrights-nodatabase": "Η βάση δεδομένων $1 δεν υπάρχει ή δεν είναι τοπική.",
-       "userrights-nologin": "Πρέπει να [[Special:UserLogin|συνδεθείτε]] με έναν λογαριασμό διαχειριστή συστήματος ώστε να ορίσετε δικαιώματα χρηστών.",
-       "userrights-notallowed": "Δεν έχετε άδεια να προσθέσετε ή να καταργήσετε δικαιώματα χρήστη.",
        "userrights-changeable-col": "Ομάδες που μπορείτε να αλλάξετε",
        "userrights-unchangeable-col": "Ομάδες που δεν μπορείτε να αλλάξετε",
        "userrights-conflict": "Σύγκρουση αλλαγών στα δικαιώματα χρήστη! Παρακαλώ επανεξετάστε και επικυρώστε τις αλλαγές σας.",
-       "userrights-removed-self": "Έχετε καταργήσει τα δικά σας δικαιώματα. Ως εκ τούτου, δεν είστε πλέον σε θέση να έχετε πρόσβαση σε αυτή τη σελίδα.",
        "group": "Ομάδα:",
        "group-user": "Χρήστες",
        "group-autoconfirmed": "Αυτοεπιβεβαιωμένοι χρήστες",
        "right-siteadmin": "Κλείδωμα και ξεκλείδωμα της βάσης δεδομένων",
        "right-override-export-depth": "Εξαγωγή σελίδων συμπεριλαμβάνοντας συνδεδεμένες σελίδες έως ένα βάθος 5 επιπέδων",
        "right-sendemail": "Αποστολή ηλεκτρονικού μηνύματος σε άλλους χρήστες",
-       "right-passwordreset": "Εμφάνιση email επαναφοράς κωδικού πρόσβασης",
        "right-managechangetags": "Δημιουργία και (απ)ενεργοποίηση [[Special:Tags|ετικετών]]",
        "right-applychangetags": "Εφαρμόστε [[Special:Tags|ετικέτες]] μαζί με τις αλλαγές",
        "right-changetags": "Προσθέστε και αφαιρέστε αυθαίρετες [[Special:Tags|ετικέτες]] σε μεμονωμένες εκδόσεις και καταχωρήσεις καταγραφών",
        "activeusers-intro": "Αυτή είναι μια λίστα από χρήστες που είχαν κάποιου είδους δραστηριότητα {{PLURAL:$1|την τελευταία $1 μέρα|τις τελευταίες $1 μέρες}}.",
        "activeusers-count": "$1 {{PLURAL:$1|ενέργεια|ενέργειες}} {{PLURAL:$3|την τελευταία μέρα|τις τελευταίες $3 μέρες}}",
        "activeusers-from": "Προβολή χρηστών ξεκινώντας από:",
-       "activeusers-hidebots": "Απόκρυψη bots",
-       "activeusers-hidesysops": "Απόκρυψη διαχειριστών",
        "activeusers-noresult": "Δεν βρέθηκε χρήστης.",
        "activeusers-submit": "Προβολή ενεργών χρηστών",
        "listgrouprights": "Δικαιώματα ομάδων χρηστών",
        "htmlform-user-not-exists": "Δεν υπάρχει χρήστης με όνομα <strong>$1</strong>.",
        "htmlform-user-not-valid": "Το <strong>$1</strong> δεν είναι έγκυρο όνομα χρήστη.",
        "logentry-delete-delete": "{{GENDER:$2|Ο|Η}} $1 διέγραψε τη σελίδα $3",
+       "logentry-delete-delete_redir": "{{GENDER:$2|Ο|Η}} $1 διέγραψε την ανακατεύθυνση $3 με αντικατάσταση",
        "logentry-delete-restore": "Ο/Η $1 αποκατέστησε τη σελίδα $3",
        "logentry-delete-event": "{{GENDER:$2|Ο|Η}} $1 άλλαξε την ορατότητα {{PLURAL:$5|ενός καταγραφόμενου συμβάντος|$5 καταγραφόμενων συμβάντων}} στο $3: $4",
        "logentry-delete-revision": "{{GENDER:$2|Ο|Η}} $1 άλλαξε την ορατότητα {{PLURAL:$5|μίας αναθεώρησης|$5 αναθεωρήσεων}} στη σελίδα $3: $4",
        "feedback-thanks": "Ευχαριστούμε! Τα σχόλιά σας έχουν καταχωρηθεί στη σελίδα \"[$2 $1]\".",
        "feedback-thanks-title": "Σας ευχαριστούμε!",
        "feedback-useragent": "User agent:",
-       "searchsuggest-search": "Αναζήτηση",
+       "searchsuggest-search": "Αναζήτηση σε {{SITENAME}}",
        "searchsuggest-containing": "περιέχει...",
        "api-error-badaccess-groups": "Δεν επιτρέπεται να ανεβάσετε αρχεία σε αυτό το wiki.",
        "api-error-badtoken": "Εσωτερικό σφάλμα: εσφαλμένο διακριτικό.",
index a033edd..2004e0f 100644 (file)
        "views": "Views",
        "toolbox": "Tools",
        "tool-link-userrights": "Change {{GENDER:$1|user}} groups",
+       "tool-link-userrights-readonly": "View {{GENDER:$1|user}} groups",
        "tool-link-emailuser": "Email this {{GENDER:$1|user}}",
        "userpage": "View user page",
        "projectpage": "View project page",
        "passwordreset-emaildisabled": "Email features have been disabled on this wiki.",
        "passwordreset-username": "Username:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "View the resulting email?",
-       "passwordreset-capture-help": "If you check this box, the email (with the temporary password) will be shown to you as well as being sent to the user.",
        "passwordreset-email": "Email address:",
        "passwordreset-emailtitle": "Account details on {{SITENAME}}",
        "passwordreset-emailtext-ip": "Someone (probably you, from IP address $1) requested a reset of your\npassword for {{SITENAME}} ($4). The following user {{PLURAL:$3|account is|accounts are}}\nassociated with this email address:\n\n$2\n\n{{PLURAL:$3|This temporary password|These temporary passwords}} will expire in {{PLURAL:$5|one day|$5 days}}.\nYou should log in and choose a new password now. If someone else made this\nrequest, or if you have remembered your original password, and you no longer\nwish to change it, you may ignore this message and continue using your old\npassword.",
        "passwordreset-emailelement": "Username:\n$1\n\nTemporary password:\n$2",
        "passwordreset-emailsentemail": "If this email address is associated with your account, then a password reset email will be sent.",
        "passwordreset-emailsentusername": "If there is an email address associated with this username, then a password reset email will be sent.",
-       "passwordreset-emailsent-capture2": "The password reset {{PLURAL:$1|email has|emails have}} been sent. The {{PLURAL:$1|username and password|list of usernames and passwords}} is shown here.",
-       "passwordreset-emailerror-capture2": "Emailing the {{GENDER:$2|user}} failed: $1 The {{PLURAL:$3|username and password|list of usernames and passwords}} is shown here.",
        "passwordreset-nocaller": "A caller must be provided",
        "passwordreset-nosuchcaller": "Caller does not exist: $1",
        "passwordreset-ignored": "The password reset was not handled. Maybe no provider was configured?",
-       "passwordreset-invalideamil": "Invalid email address",
+       "passwordreset-invalidemail": "Invalid email address",
        "passwordreset-nodata": "Neither a username nor an email address was supplied",
        "changeemail": "Change or remove email address",
        "changeemail-summary": "",
        "searchdisabled": "{{SITENAME}} search is disabled.\nYou can search via Google in the meantime.\nNote that their indexes of {{SITENAME}} content may be out of date.",
        "googlesearch": "<form method=\"get\" action=\"//www.google.com/search\" id=\"googlesearch\">\n\t<input type=\"hidden\" name=\"domains\" value=\"{{SERVER}}\" />\n\t<input type=\"hidden\" name=\"num\" value=\"50\" />\n\t<input type=\"hidden\" name=\"ie\" value=\"$2\" />\n\t<input type=\"hidden\" name=\"oe\" value=\"$2\" />\n\n\t<input type=\"text\" name=\"q\" size=\"31\" maxlength=\"255\" value=\"$1\" />\n\t<input type=\"submit\" name=\"btnG\" value=\"$3\" />\n  <div>\n\t<input type=\"radio\" name=\"sitesearch\" id=\"gwiki\" value=\"{{SERVER}}\" checked=\"checked\" /><label for=\"gwiki\">{{SITENAME}}</label>\n\t<input type=\"radio\" name=\"sitesearch\" id=\"gWWW\" value=\"\" /><label for=\"gWWW\">WWW</label>\n  </div>\n</form>",
        "search-error": "An error has occurred while searching: $1",
+       "search-warning": "A warning has occured while searching: $1",
        "opensearch-desc": "{{SITENAME}} ({{CONTENTLANGUAGE}})",
        "preferences": "Preferences",
        "preferences-summary": "",
        "prefs-help-recentchangescount": "This includes recent changes, page histories, and logs.",
        "prefs-help-watchlist-token2": "This is the secret key to the web feed of your watchlist.\nAnyone who knows it will be able to read your watchlist, so do not share it.\nIf you need to, [[Special:ResetTokens|you can reset it]].",
        "savedprefs": "Your preferences have been saved.",
-       "savedrights": "The user rights of {{GENDER:$1|$1}} have been saved.",
+       "savedrights": "The user groups of {{GENDER:$1|$1}} have been saved.",
        "timezonelegend": "Time zone:",
        "localtime": "Local time:",
        "timezoneuseserverdefault": "Use wiki default ($1)",
        "prefs-tabs-navigation-hint": "Tip: You can use the left and right arrow keys to navigate between the tabs in the tabs list.",
        "userrights": "User rights management",
        "userrights-summary": "",
-       "userrights-lookup-user": "Manage user groups",
+       "userrights-lookup-user": "Select a user",
        "userrights-user-editname": "Enter a username:",
-       "editusergroup": "Edit {{GENDER:$1|user}} groups",
+       "editusergroup": "Load user groups",
        "editinguser": "Changing user rights of {{GENDER:$1|user}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Viewing user rights of {{GENDER:$1|user}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Edit user groups",
+       "userrights-viewusergroup": "View user groups",
        "saveusergroups": "Save {{GENDER:$1|user}} groups",
        "userrights-groupsmember": "Member of:",
        "userrights-groupsmember-auto": "Implicit member of:",
        "userrights-reason": "Reason:",
        "userrights-no-interwiki": "You do not have permission to edit user rights on other wikis.",
        "userrights-nodatabase": "Database $1 does not exist or is not local.",
-       "userrights-nologin": "You must [[Special:UserLogin|log in]] with an administrator account to assign user rights.",
-       "userrights-notallowed": "You do not have permission to add or remove user rights.",
        "userrights-changeable-col": "Groups you can change",
        "userrights-unchangeable-col": "Groups you cannot change",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Conflict of user rights changes! Please review and confirm your changes.",
-       "userrights-removed-self": "You removed your own rights. As such, you are no longer able to access this page.",
        "group": "Group:",
        "group-user": "Users",
        "group-autoconfirmed": "Autoconfirmed users",
        "right-siteadmin": "Lock and unlock the database",
        "right-override-export-depth": "Export pages including linked pages up to a depth of 5",
        "right-sendemail": "Send email to other users",
-       "right-passwordreset": "View password reset emails",
        "right-managechangetags": "Create and (de)activate [[Special:Tags|tags]]",
        "right-applychangetags": "Apply [[Special:Tags|tags]] along with one's changes",
        "right-changetags": "Add and remove arbitrary [[Special:Tags|tags]] on individual revisions and log entries",
        "action-upload_by_url": "upload this file from a URL",
        "action-writeapi": "use the write API",
        "action-delete": "delete this page",
-       "action-deleterevision": "delete this revision",
-       "action-deletedhistory": "view this page's deleted history",
+       "action-deleterevision": "delete revisions",
+       "action-deletelogentry": "delete log entries",
+       "action-deletedhistory": "view a page's deleted history",
+       "action-deletedtext": "view deleted revision text",
        "action-browsearchive": "search deleted pages",
-       "action-undelete": "undelete this page",
-       "action-suppressrevision": "review and restore this hidden revision",
+       "action-undelete": "undelete pages",
+       "action-suppressrevision": "review and restore hidden revisions",
        "action-suppressionlog": "view this private log",
        "action-block": "block this user from editing",
        "action-protect": "change protection levels for this page",
        "action-userrights-interwiki": "edit user rights of users on other wikis",
        "action-siteadmin": "lock or unlock the database",
        "action-sendemail": "send emails",
+       "action-editmyoptions": "edit your preferences",
        "action-editmywatchlist": "edit your watchlist",
        "action-viewmywatchlist": "view your watchlist",
        "action-viewmyprivateinfo": "view your private information",
        "apisandbox-continue": "Continue",
        "apisandbox-continue-clear": "Clear",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} will [https://www.mediawiki.org/wiki/API:Query#Continuing_queries continue] the last request; {{int:apisandbox-continue-clear}} will clear continuation-related parameters.",
+       "apisandbox-param-limit": "Enter <kbd>max</kbd> to use the maximum limit.",
+       "apisandbox-multivalue-all-namespaces": "$1 (All namespaces)",
+       "apisandbox-multivalue-all-values": "$1 (All values)",
        "booksources": "Book sources",
        "booksources-summary": "",
        "booksources-search-legend": "Search for book sources",
        "activeusers-count": "$1 {{PLURAL:$1|action|actions}} in the last {{PLURAL:$3|day|$3 days}}",
        "activeusers-from": "Display users starting at:",
        "activeusers-groups": "Display users belonging to groups:",
+       "activeusers-excludegroups": "Exclude users belonging to groups:",
        "activeusers-noresult": "No users found.",
        "activeusers-submit": "Display active users",
        "listgrouprights": "User group rights",
        "listgrants-summary": "The following is a list of grants with their associated access to user rights. Users can authorize applications to use their account, but with limited permissions based on the grants the user gave to the application. An application acting on behalf of a user cannot actually use rights that the user does not have however.\nThere may be [[{{MediaWiki:Listgrouprights-helppage}}|additional information]] about individual rights.",
        "listgrants-grant": "Grant",
        "listgrants-rights": "Rights",
+       "listgrants-grant-display": "$1 <code>($2)</code>",
        "trackingcategories": "Tracking categories",
        "trackingcategories-summary": "This page lists tracking categories which are automatically populated by the MediaWiki software. Their names can be changed by altering the relevant system messages in the {{ns:8}} namespace.",
        "trackingcategories-msg": "Tracking category",
        "emailccsubject": "Copy of your message to $1: $2",
        "emailsent": "Email sent",
        "emailsenttext": "Your email message has been sent.",
-       "emailuserfooter": "This email was {{GENDER:$1|sent}} by $1 to {{GENDER:$2|$2}} by the \"{{int:emailuser}}\" function at {{SITENAME}}.",
+       "emailuserfooter": "This email was {{GENDER:$1|sent}} by $1 to {{GENDER:$2|$2}} by the \"{{int:emailuser}}\" function at {{SITENAME}}. {{GENDER:$2|Your}} email will be sent directly to the {{GENDER:$1|original sender}}, revealing {{GENDER:$2|your}} email address to {{GENDER:$1|them}}.",
        "usermessage-summary": "Leaving system message.",
        "usermessage-editor": "System messenger",
        "usermessage-template": "MediaWiki:UserMessage",
        "tags-deactivate": "deactivate",
        "tags-hitcount": "$1 {{PLURAL:$1|change|changes}}",
        "tags-manage-no-permission": "You do not have permission to manage change tags.",
-       "tags-manage-blocked": "You cannot manage change tags while you are blocked.",
+       "tags-manage-blocked": "You cannot manage change tags while {{GENDER:$1|you}} are blocked.",
        "tags-create-heading": "Create a new tag",
        "tags-create-explanation": "By default, newly created tags will be made available for use by users and bots.",
        "tags-create-tag-name": "Tag name:",
        "tags-deactivate-not-allowed": "It is not possible to deactivate the tag \"$1\".",
        "tags-deactivate-submit": "Deactivate",
        "tags-apply-no-permission": "You do not have permission to apply change tags along with your changes.",
-       "tags-apply-blocked": "You cannot apply change tags along with your changes while you are blocked.",
+       "tags-apply-blocked": "You cannot apply change tags along with your changes while {{GENDER:$1|you}} are blocked.",
        "tags-apply-not-allowed-one": "The tag \"$1\" is not allowed to be manually applied.",
        "tags-apply-not-allowed-multi": "The following {{PLURAL:$2|tag is|tags are}} not allowed to be manually applied: $1",
        "tags-update-no-permission": "You do not have permission to add or remove change tags from individual revisions or log entries.",
-       "tags-update-blocked": "You cannot add or remove change tags while you are blocked.",
+       "tags-update-blocked": "You cannot add or remove change tags while {{GENDER:$1|you}} are blocked.",
        "tags-update-add-not-allowed-one": "The tag \"$1\" is not allowed to be manually added.",
        "tags-update-add-not-allowed-multi": "The following {{PLURAL:$2|tag is|tags are}} not allowed to be manually added: $1",
        "tags-update-remove-not-allowed-one": "The tag \"$1\" is not allowed to be removed.",
        "htmlform-user-not-valid": "<strong>$1</strong> isn't a valid username.",
        "rawmessage": "$1",
        "logentry-delete-delete": "$1 {{GENDER:$2|deleted}} page $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|deleted}} redirect $3 by overwriting",
        "logentry-delete-restore": "$1 {{GENDER:$2|restored}} page $3",
        "logentry-delete-event": "$1 {{GENDER:$2|changed}} visibility of {{PLURAL:$5|a log event|$5 log events}} on $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|changed}} visibility of {{PLURAL:$5|a revision|$5 revisions}} on page $3: $4",
        "mw-widgets-dateinput-no-date": "No date selected",
        "mw-widgets-dateinput-placeholder-day": "YYYY-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "YYYY-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Search for media",
+       "mw-widgets-mediasearch-noresults": "No results found.",
        "mw-widgets-titleinput-description-new-page": "page does not exist yet",
        "mw-widgets-titleinput-description-redirect": "redirect to $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Add a category...",
        "sessionmanager-tie": "Cannot combine multiple request authentication types: $1.",
        "sessionprovider-generic": "$1 sessions",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "cookie-based sessions",
        "log-action-filter-contentmodel-change": "Change of Contentmodel",
        "log-action-filter-contentmodel-new": "Creation of page with non-standard Contentmodel",
        "log-action-filter-delete-delete": "Page deletion",
+       "log-action-filter-delete-delete_redir": "Redirect overwrite",
        "log-action-filter-delete-restore": "Page undeletion",
        "log-action-filter-delete-event": "Log deletion",
        "log-action-filter-delete-revision": "Revision deletion",
        "restrictionsfield-badip": "Invalid IP address or range: $1",
        "restrictionsfield-label": "Allowed IP ranges:",
        "restrictionsfield-help": "One IP address or CIDR range per line. To enable everything, use<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Error: $1",
-       "edit-error-long": "Errors:\n\n$1"
+       "revid": "r$1",
+       "pageid": "page ID $1"
 }
index b4df263..31f0641 100644 (file)
        "passwordreset-nocaller": "Vokanto devas esti provizita",
        "passwordreset-nosuchcaller": "Vokanto ne ekzistas: $1",
        "passwordreset-ignored": "La pasvorta reensignado ne estis pritraktita. Eble neniu provizanto estis formita?",
-       "passwordreset-invalideamil": "Nevalida retpoŝta adreso",
+       "passwordreset-invalidemail": "Nevalida retpoŝta adreso",
        "passwordreset-nodata": "Nek salutnomo nek retpoŝta adreso estis provizita",
        "changeemail": "Ŝanĝi aŭ forigi retpoŝtadreson",
        "changeemail-header": "Plenigu ĉi tiun formularon por ŝanĝi vian retpoŝtadreson. Se vi volas forigi la difinon de retpoŝtadreso por via uzantokonto, lasu la kampon por la nova retpoŝtadreso malplena ĉe la transigo.",
index cda6edc..6b8740b 100644 (file)
                        "Irus",
                        "Sophivorus",
                        "Pompilos",
-                       "Igv"
+                       "Igv",
+                       "Juanpabl"
                ]
        },
        "tog-underline": "Subrayar los enlaces:",
        "passwordreset-emaildisabled": "Se han desactivado las funciones de correo electrónico en este wiki.",
        "passwordreset-username": "Nombre de usuario:",
        "passwordreset-domain": "Dominio:",
-       "passwordreset-capture": "¿Ver el mensaje resultante?",
-       "passwordreset-capture-help": "Si marcas esta casilla, se te mostrará el correo electrónico (con la contraseña temporal) además de enviarse al usuario.",
        "passwordreset-email": "Dirección de correo electrónico:",
        "passwordreset-emailtitle": "Detalles de la cuenta en {{SITENAME}}",
        "passwordreset-emailtext-ip": "Alguien (probablemente tú, desde la dirección IP $1) ha solicitado el restablecimiento de tu contraseña en {{SITENAME}} ($4). {{PLURAL:$3|La siguiente cuenta está asociada|Las siguientes cuentas están asociadas}}\na esta dirección de correo electrónico:\n\n$2\n\n{{PLURAL:$3|Esta contraseña temporal|Estas contraseñas temporales}} caducarán en {{PLURAL:$5|un día|$5 días}}.\nAhora puedes iniciar sesión y establecer una nueva contraseña. Si fue otra persona la que realizó esta solicitud, o si ya recuerdas tu contraseña original y, por tanto, no deseas cambiarla, puedes ignorar este mensaje y continuar usando tu contraseña anterior.",
        "passwordreset-emailelement": "Nombre de {{GENDER:$1|usuario|usuaria}}: \n$1\n\nContraseña temporal: \n$2",
        "passwordreset-emailsentemail": "Si esta dirección de correo electrónico está asociada a tu cuenta, entonces se enviará un correo electrónico para restablecer la contraseña.",
        "passwordreset-emailsentusername": "Si existe una dirección de correo electrónico asociada a este nombre de usuario, entonces se enviará un correo para restablecer la contraseña.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Se ha enviado el mensaje de restablecimiento de contraseña|Se han enviado los mensajes de restablecimiento de contraseña}}. {{PLURAL:$1|El nombre de usuario y la contraseña|La lista de nombres de usuarios y contraseñas}} se muestra aquí.",
-       "passwordreset-emailerror-capture2": "No fue posible mandar un correo electrónico {{GENDER:$2|al usuario|a la usuaria}}: $1 {{PLURAL:$3|El nombre de usuario y la contraseña|La lista de nombres de usuarios y contraseñas}} se muestra aquí.",
        "passwordreset-nocaller": "Debe de proporcionarse un interlocutor",
        "passwordreset-nosuchcaller": "La persona que llama no existe: $1",
        "passwordreset-ignored": "No se logró el reestablecimiento de la contraseña. ¿Tal vez no se configuró un proveedor?",
-       "passwordreset-invalideamil": "Dirección de correo electrónico no válida.",
+       "passwordreset-invalidemail": "Dirección de correo electrónico no válida.",
        "passwordreset-nodata": "No se ha proporcionado ni un nombre de usuario ni una dirección de correo electrónico",
        "changeemail": "Cambiar o eliminar la dirección de correo electrónico",
        "changeemail-header": "Completa este formulario para cambiar tu dirección de correo electrónico. Si quieres eliminar la asociación de cualquier dirección de correo electrónico con tu cuenta, deja en blanco la nueva dirección de correo electrónico cuando envíes el formulario.",
        "userrights-reason": "Motivo:",
        "userrights-no-interwiki": "No tienes permiso para editar permisos de usuario en otros wikis.",
        "userrights-nodatabase": "La base de datos $1 no existe o no es local.",
-       "userrights-nologin": "Debes [[Special:UserLogin|iniciar sesión]] con una cuenta de administrador para poder editar los grupos de los usuarios.",
-       "userrights-notallowed": "No tienes permiso para añadir o quitar permisos de usuario.",
        "userrights-changeable-col": "Grupos que puedes cambiar",
        "userrights-unchangeable-col": "Grupos que no puedes cambiar",
        "userrights-conflict": "¡Conflicto de cambio de los permisos de usuario! Por favor, revisa y confirma tus cambios.",
-       "userrights-removed-self": "Has eliminado tus propios permisos. Por tanto, ya no podrás volver a acceder a esta página.",
        "group": "Grupo:",
        "group-user": "Usuarios",
        "group-autoconfirmed": "Autoconfirmados",
        "right-block": "Bloquear a otros usuarios para que no editen",
        "right-blockemail": "Bloquear a un usuario para que no pueda mandar correos electrónicos",
        "right-hideuser": "Bloquear un nombre de usuario, haciéndolo invisible",
-       "right-ipblock-exempt": "Quedar exento de bloqueos a IPs, autobloqueos y bloqueos de rango.",
+       "right-ipblock-exempt": "Evitar bloqueos a IP, automáticos y por intervalos",
        "right-unblockself": "Desbloquearse a sí mismo",
        "right-protect": "Cambiar niveles de protección y editar páginas protegidas en cascada",
        "right-editprotected": "Editar páginas protegidas como «{{int:protect-level-sysop}}»",
        "right-siteadmin": "Bloquear y desbloquear la base de datos",
        "right-override-export-depth": "Exportar páginas, incluyendo aquellas enlazadas hasta una profundidad de 5",
        "right-sendemail": "Enviar correo electrónico a otros usuarios",
-       "right-passwordreset": "Ver los mensajes de restablecimiento de contraseña",
        "right-managechangetags": "Crear y (des)activar [[Special:Tags|etiquetas]]",
        "right-applychangetags": "Aplicar [[Special:Tags|etiquetas]] junto con los cambios propios",
        "right-changetags": "Agregar y quitar [[Special:Tags|etiquetas]] arbitrarias a revisiones individuales y entradas del registro",
        "apisandbox-alert-field": "El valor de este campo no es válido.",
        "apisandbox-continue": "Continuar",
        "apisandbox-continue-clear": "Vaciar",
+       "apisandbox-param-limit": "Escribe <kbd>max</kbd> para usar el límite máximo.",
        "booksources": "Fuentes de libros",
        "booksources-search-legend": "Buscar fuentes de libros",
        "booksources-search": "Buscar",
        "booksources-text": "Abajo hay una lista de enlaces a otros sitios que venden libros nuevos y usados, puede que contengan más información sobre los libros que estás buscando.",
        "booksources-invalid-isbn": "El número de ISBN no parece ser válido; comprueba los errores copiándolo de la fuente original.",
-       "magiclink-tracking-rfc": "Páginas que usan enlaces mágicos RFC",
-       "magiclink-tracking-rfc-desc": "Esta página usa enlaces mágicos RFC. Véase [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sobre cómo migrar.",
-       "magiclink-tracking-pmid": "Páginas que usan enlaces mágicos PMID",
-       "magiclink-tracking-pmid-desc": "Esta página usa enlaces mágicos PMID. Véase [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sobre cómo migrar.",
+       "magiclink-tracking-rfc": "Páginas que usan enlaces mágicos de RFC",
+       "magiclink-tracking-rfc-desc": "Esta página usa enlaces mágicos de RFC. Véase [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sobre cómo migrar.",
+       "magiclink-tracking-pmid": "Páginas que usan enlaces mágicos de PMID",
+       "magiclink-tracking-pmid-desc": "Esta página usa enlaces mágicos de PMID. Véase [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sobre cómo migrar.",
        "magiclink-tracking-isbn": "Páginas que usan enlaces mágicos de ISBN",
        "magiclink-tracking-isbn-desc": "Esta página usa enlaces mágicos de ISBN. Véase [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sobre cómo migrar.",
        "specialloguserlabel": "Usuario:",
        "activeusers": "Lista de usuarios activos",
        "activeusers-intro": "Esta es una lista de usuarios que han tenido alguna actividad en los últimos $1 {{PLURAL:$1|día|días}}.",
        "activeusers-count": "$1 {{PLURAL:$1|acción|acciones}} en {{PLURAL:$3|el último día|los últimos $3 días}}",
-       "activeusers-from": "Mostrando a los usuarios empezando por:",
+       "activeusers-from": "Mostrar los usuarios que empiezan por:",
        "activeusers-groups": "Mostrar los usuarios que pertenecen a los grupos:",
+       "activeusers-excludegroups": "Excluir a los usuarios que pertenezcan a los grupos:",
        "activeusers-noresult": "No se encontraron usuarios.",
        "activeusers-submit": "Mostrar usuarios activos",
        "listgrouprights": "Permisos de los grupos de usuarios",
        "modifiedarticleprotection": "cambió el nivel de protección de «[[$1]]»",
        "unprotectedarticle": "desprotegió «[[$1]]»",
        "movedarticleprotection": "cambiadas protecciones de «[[$2]]» a «[[$1]]»",
-       "protectedarticle-comment": "{{GENDER:$2|Protegido}} \"[[$1]]\"",
-       "modifiedarticleprotection-comment": "{{GENDER:$2|Cambiado el nivel de protección}}\" de [[$1]]\"",
-       "unprotectedarticle-comment": "{{GENDER:$2|Quitar la protección}} de \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Protegió}} «[[$1]]»",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Cambió el nivel de protección}} de «[[$1]]»",
+       "unprotectedarticle-comment": "{{GENDER:$2|Eliminó la protección}} de «[[$1]]»",
        "protect-title": "Cambiando el nivel de protección de «$1»",
        "protect-title-notallowed": "Ver el nivel de protección de «$1»",
        "prot_1movedto2": "[[$1]] se trasladó a [[$2]]",
        "undeletehistorynoadmin": "El artículo ha sido borrado. La razón de su eliminación se indica abajo en el resumen, así como los detalles de las ediciones realizadas antes del borrado. El texto completo del artículo está disponible sólo para usuarios con permisos de administrador.",
        "undelete-revision": "Edición borrada de $1 (fechada el $4, a las $5) por $3:",
        "undeleterevision-missing": "Revisión no válida o perdida. Puede deberse a un enlace incorrecto,\no a que la revisión haya sido restaurada o eliminada del archivo.",
-       "undeleterevision-duplicate-revid": "{{PLURAL:$1|Una revisión|$1 revisiones}} no se han podido restaurar, porque {{PLURAL:$1|su|su}} <code>rev_id</code> ya estaba en uso.",
+       "undeleterevision-duplicate-revid": "No se {{PLURAL:$1|pudo restaurar una modificación|pudieron restaurar $1 modificaciones}} porque {{PLURAL:$1|su <code>rev_id</code> ya se estaba|sus <code>rev_id</code> ya se estaban}} utilizando.",
        "undelete-nodiff": "No existe una revisión previa.",
        "undeletebtn": "Restaurar",
        "undeletelink": "ver/restaurar",
        "filemissing": "Falta archivo",
        "thumbnail_error": "Error al crear miniatura: $1",
        "thumbnail_error_remote": "Mensaje de error de $1:\n$2",
-       "djvu_page_error": "Página DjVu fuera de rango",
+       "djvu_page_error": "Página DjVu fuera de los límites",
        "djvu_no_xml": "Imposible obtener XML para el archivo DjVu",
        "thumbnail-temp-create": "No se ha podido crear el archivo temporal de la miniatura",
        "thumbnail-dest-create": "No se ha podido guardar la miniatura",
        "pageinfo-redirects-name": "Número de redirecciones a esta página",
        "pageinfo-redirects-value": "$1",
        "pageinfo-subpages-name": "Subpáginas de esta página",
-       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|redirección|redirecciones}}; $3 {{PLURAL:$3|no-redirección|no-redirecciones}})",
+       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|redirección|redirecciones}}; $3 {{PLURAL:$3|no redirección|no redirecciones}})",
        "pageinfo-firstuser": "Creador de la página",
        "pageinfo-firsttime": "Fecha de creación de la página",
        "pageinfo-lastuser": "Último editor",
        "confirmemail_sendfailed": "No fue posible enviar el correo de confirmación. Por favor, comprueba la validez de la dirección de correo.\n\nEl servidor indicó el error: $1",
        "confirmemail_invalid": "Código de confirmación incorrecto.\nEl código debe haber expirado.",
        "confirmemail_needlogin": "Necesitas $1 para confirmar tu dirección electrónica.",
-       "confirmemail_success": "Su dirección de correo ha sido confirmada\nAhora puedes [[Special:UserLogin|identificarte]] y colaborar en el wiki.",
+       "confirmemail_success": "Se ha confirmado tu dirección de correo electrónico.\nAhora puedes [[Special:UserLogin|acceder]] y disfrutar del wiki.",
        "confirmemail_loggedin": "Tu dirección de correo electrónico ha sido confirmada.",
        "confirmemail_subject": "confirmación de la dirección de correo de {{SITENAME}}",
        "confirmemail_body": "Alguien, probablemente tú mismo, ha registrado desde la dirección IP $1 la cuenta \"$2\" en {{SITENAME}}, utilizando esta dirección de correo.\n\nPara confirmar que esta cuenta realmente te pertenece y activar el correo en {{SITENAME}}, sigue este enlace en tu navegador:\n\n$3\n\nSi la cuenta *no* es tuya, sigue este otro enlace para cancelar la confirmación de la dirección de correo:\n\n$5\n\nEl código de confirmación expirará el $4.",
        "tags-deactivate": "desactivar",
        "tags-hitcount": "$1 {{PLURAL:$1|cambio|cambios}}",
        "tags-manage-no-permission": "No tienes permiso para gestionar las etiquetas de cambios.",
-       "tags-manage-blocked": "No puedes gestionar el cambio de etiquetas mientras estés bloqueado.",
+       "tags-manage-blocked": "No puedes gestionar etiquetas de cambio mientras estés {{GÉNERO:$1|bloqueado|bloqueada}}.",
        "tags-create-heading": "Crear una etiqueta",
        "tags-create-explanation": "De manera predeterminada, las etiquetas nuevas estarán disponibles para su uso por usuarios y bots.",
        "tags-create-tag-name": "Nombre de la etiqueta:",
        "tags-deactivate-not-allowed": "No es posible desactivar la etiqueta «$1».",
        "tags-deactivate-submit": "Desactivar",
        "tags-apply-no-permission": "No tienes permiso para aplicar etiquetas de cambios, junto con tus cambios.",
-       "tags-apply-blocked": "No puedes aplicar etiquetas de cambio con tus cambios mientras estés {{GENDER:|bloqueado|bloqueada}}.",
+       "tags-apply-blocked": "No puedes aplicar etiquetas de cambio junto a tus cambios mientras estés {{GENDER:$1|bloqueado|bloqueada}}.",
        "tags-apply-not-allowed-one": "No se permite aplicar manualmente la etiqueta «$1».",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|La siguiente etiqueta no se puede|Las siguientes etiquetas no se pueden}} aplicar manualmente: $1",
        "tags-update-no-permission": "No tienes permiso para agregar o quitar etiquetas de cambio de las revisiones individuales o las entradas del registro.",
-       "tags-update-blocked": "No puedes añadir o eliminar etiquetas de cambio mientras estés {{GENDER:|bloqueado|bloqueada}}.",
+       "tags-update-blocked": "No puedes añadir o eliminar etiquetas de cambio mientras estés {{GENDER:$1|bloqueado|bloqueada}}.",
        "tags-update-add-not-allowed-one": "No se permite la adición manual de la etiqueta «$1».",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|La siguiente etiqueta no se puede|Las siguientes etiquetas no se pueden}} agregar manualmente: $1",
        "tags-update-remove-not-allowed-one": "No se permite eliminar la etiqueta «$1».",
        "authmanager-authn-autocreate-failed": "Falló la creación automática de una cuenta local: $1",
        "authmanager-change-not-supported": "Las credenciales proporcionadas no se pueden cambiar, ya que no hay nada que fuera a hacer uso de ellas.",
        "authmanager-create-disabled": "Está desactivada la creación de cuentas.",
-       "authmanager-create-from-login": "Para crear su cuenta, por favor, complete los campos.",
+       "authmanager-create-from-login": "Para crear una cuenta, rellena los campos.",
        "authmanager-create-not-in-progress": "El proceso de creación de la cuenta no está en progreso o se perdieron los datos de la sesión. Empieza de nuevo desde el principio.",
        "authmanager-create-no-primary": "Las credenciales suministradas no pueden usarse para la creación de la cuenta.",
        "authmanager-link-no-primary": "Las credenciales proporcionadas no se han podido utilizar para enlazar cuentas.",
        "usercssispublic": "Recuerda: las subpáginas CSS no deberían contener datos confidenciales, pues otros usuarios los pueden ver.",
        "restrictionsfield-badip": "Dirección o intervalo IP no válidos: $1",
        "restrictionsfield-label": "Intervalos de IP permitidos:",
-       "restrictionsfield-help": "Una dirección IP o intervalo de CIDR por renglón. Para activar todo, utiliza<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Error: $1",
-       "edit-error-long": "Errores:\n\n$1"
+       "restrictionsfield-help": "Una dirección IP o intervalo de CIDR por renglón. Para activar todo, utiliza<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index ec27ab5..9933fed 100644 (file)
        "tagline": "Allikas: {{SITENAME}}",
        "help": "Juhend",
        "search": "Otsing",
+       "search-ignored-headings": " #<!-- Jäta see rida muutmata kujule. --> <pre>\n# Pealkirjad, mida otsingus eiratakse.\n# Muudatused jõustuvad kohe, kui vastava pealkirjaga lehekülg on indekseeritud.\n# Saad teha tühimuudatuse, selleks et sundida lehekülg uuesti indekseerimisele.\n# Süntaks on järgmine:\n#   * Kõik alates märgist \"#\" kuni rea lõpuni on kommentaar.\n#   * Iga rida, mis ei ole tühi, on eiratava pealkirja täpne tõstutundlik kuju.\nViited\nVälislingid\nVaata ka\n #</pre> <!-- Jäta see rida muutmata kujule. -->",
        "searchbutton": "Otsi",
        "go": "Mine",
        "searcharticle": "Mine",
        "views": "vaatamisi",
        "toolbox": "Tööriistad",
        "tool-link-userrights": "Muuda {{GENDER:$1|kasutajarühmi}}",
+       "tool-link-userrights-readonly": "Vaata {{GENDER:$1|kasutajarühmi}}",
        "tool-link-emailuser": "Saada {{GENDER:$1|kasutajale}} e-kiri",
        "userpage": "Vaata kasutajalehekülge",
        "projectpage": "Vaata projektilehekülge",
        "mainpage-nstab": "Esileht",
        "nosuchaction": "Sellist toimingut pole.",
        "nosuchactiontext": "Viki ei tunne internetiaadressile vastavat tegevust.\nVõimalik, et sa sisestasid aadressi valesti või kasutasid vigast linki.\nSamuti ei ole välistatud, et tarkvaras, mida {{SITENAME}} kasutatab, on viga.",
-       "nosuchspecialpage": "Sellist erilehekülge pole.",
+       "nosuchspecialpage": "Sellist erilehekülge pole",
        "nospecialpagetext": "<strong>Viki ei tunne erilehekülge, mille poole pöördusid.</strong>\n\nKäibel olevad erileheküljed on loetletud leheküljel [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Viga",
        "databaseerror": "Andmebaasi viga",
        "virus-scanfailed": "skaneerimine ebaõnnestus (veakood $1)",
        "virus-unknownscanner": "tundmatu viirusetõrje:",
        "logouttext": "<strong>Oled nüüd välja loginud.</strong>\n\nPane tähele, et seni, kuni sa pole veebilehitseja puhvrit tühjendanud, võidakse mõni lehekülg endiselt kuvada nii nagu oleksid ikka sisse logitud.",
+       "cannotlogoutnow-title": "Praegu ei saa välja logida",
+       "cannotlogoutnow-text": "Väljalogimine pole võimalik, kui kasutad $1.",
        "welcomeuser": "Tere tulemast, $1!",
        "welcomecreation-msg": "Sinu konto on loodud.\nÄra unusta seada oma {{GRAMMAR:genitive|{{SITENAME}}}} [[Special:Preferences|eelistusi]].",
        "yourname": "Kasutajanimi:",
        "createacct-yourpasswordagain-ph": "Sisesta uuesti parool",
        "userlogin-remembermypassword": "Jää sisseloginuks",
        "userlogin-signwithsecure": "Kasuta turvalist ühendust",
+       "cannotlogin-title": "Ei saa sisse logida",
+       "cannotlogin-text": "Sisselogimine pole võimalik.",
+       "cannotloginnow-title": "Praegu ei saa sisse logida",
+       "cannotloginnow-text": "Sisselogimine pole võimalik, kui kasutad $1.",
+       "cannotcreateaccount-title": "Ei saa kontosid luua",
+       "cannotcreateaccount-text": "Kontode käsitsi loomine pole selles vikis lubatud.",
        "yourdomainname": "Sinu domeen:",
        "password-change-forbidden": "Selles vikis ei saa paroole muuta.",
        "externaldberror": "Esines autentimistõrge või sul pole õigust konto andmeid muuta.",
        "botpasswords-label-appid": "Roboti nimi:",
        "botpasswords-label-create": "Loo",
        "resetpass_forbidden": "Paroole ei saa muuta",
+       "resetpass_forbidden-reason": "Paroole ei saa muuta: $1",
        "resetpass-no-info": "Pead olema sisselogitud, et sellele lehele pääseda.",
        "resetpass-submit-loggedin": "Muuda parool",
        "resetpass-submit-cancel": "Loobu",
        "passwordreset-emaildisabled": "E-posti funktsioonid on selles vikis keelatud.",
        "passwordreset-username": "Kasutajanimi:",
        "passwordreset-domain": "Domeen:",
-       "passwordreset-capture": "Näita lähetatavat e-kirja?",
-       "passwordreset-capture-help": "Kui valid selle märkeruudu, näidatakse sulle ajutist parooli sisaldavat e-kirja, mis ühtlasi kasutajale saadetakse.",
        "passwordreset-email": "E-posti aadress:",
        "passwordreset-emailtitle": "{{GRAMMAR:genitive|{{SITENAME}}}} konto andmed",
        "passwordreset-emailtext-ip": "Keegi, arvatavasti sina ise, IP-aadressilt $1 palus lähtestada sinu {{GRAMMAR:genitive|{{SITENAME}}}} ($4) parooli. Selle e-posti aadressiga on seotud {{PLURAL:$3|järgmine konto|järgmised kontod}}:\n\n$2\n\n{{PLURAL:$3|See ajutine parool aegub|Need ajutised paroolid aeguvad}} {{PLURAL:$5|ühe|$5}} päeva pärast.\nPeaksid nüüd sisse logima ja uue parooli valima. Kui selle palve esitas keegi teine või kui sulle meenus su parool ja sa ei soovi seda enam muuta, võid teadet eirata ja jätkata vana parooli kasutamist.",
        "passwordreset-emailelement": "Kasutajanimi: \n$1\n\nAjutine parool: \n$2",
        "passwordreset-emailsentemail": "Kui oled sidunud konto selle e-posti aadressiga, siis saadetakse sulle parooli lähtestamise e-kiri.",
        "passwordreset-emailsentusername": "Parooli lähtestamise e-kiri saadetakse, kui olemas on kontoga seotud e-posti aadress.",
+       "passwordreset-ignored": "Parooli lähtestamine jäi rahuldamata. Võimalik, et ühtegi pakkujat polnud häälestatud.",
+       "passwordreset-invalidemail": "Vigane e-posti aadress",
+       "passwordreset-nodata": "Ära toomata jäid nii kasutajanimi kui ka e-posti aadress",
        "changeemail": "E-posti aadressi muutmine või eemaldamine",
        "changeemail-header": "Täida see vorm, et muuta oma e-posti aadress. Kui soovid, et konto poleks enam seotud ühegi e-posti aadressiga, siis jäta vormi esitamisel e-posti aadressi väli tühjaks.",
        "changeemail-no-info": "Otselingi kaudu sellele lehele jõudmiseks pead olema sisse loginud.",
        "content-model-css": "CSS",
        "content-json-empty-object": "Tühi objekt",
        "content-json-empty-array": "Tühi massiiv",
+       "deprecated-self-close-category": "Vigaste endassesuletud HTML-siltidega leheküljed",
        "duplicate-args-warning": "<strong>Hoiatus:</strong> [[:$1]] kutsub malli [[:$2]] nii, et parameetrile \"$3\" vastab rohkem kui üks väärtus. Väärtustest kasutatakse ainult viimast.",
        "duplicate-args-category": "Leheküljed, kus mallikutses on topeltargument",
        "duplicate-args-category-desc": "Lehekülg sisaldab mallikutseid, kus mõnd argumenti on kasutatud mitu korda, näiteks <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> või <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "prefs-help-recentchangescount": "See käib viimaste muudatuste, lehekülgede ajalugude ja logide kohta.",
        "prefs-help-watchlist-token2": "See on sinu jälgimisloendi veebivoo salavõti.\nIgaüks, kes seda teab, saab lugeda sinu jälgimisloendit. Seega ära jaga seda.\n[[Special:ResetTokens|Klõpsa siia, kui sul on vaja see lähtestada]].",
        "savedprefs": "Sinu eelistused on salvestatud.",
-       "savedrights": "Kasutaja $1 õigused on salvestatud.",
+       "savedrights": "Kasutaja $1 rühmad on salvestatud.",
        "timezonelegend": "Ajavöönd:",
        "localtime": "Kohalik aeg:",
        "timezoneuseserverdefault": "Kasuta serveri vaikesätet ($1)",
        "prefswarning-warning": "Oled teinud eelistustes muudatusi, mida pole veel salvestatud.\nKui lahkud sellelt leheküljelt ilma nupul \"$1\" klõpsamata, jäävad kehtima senised eelistused.",
        "prefs-tabs-navigation-hint": "Spikker: Kaardiloendis toodud kaartide vahel liikumiseks saad kasutada vasakut ja paremat nooleklahvi.",
        "userrights": "Kasutajaõiguste haldus",
-       "userrights-lookup-user": "Kasutajarühma muutmine",
+       "userrights-lookup-user": "Kasutaja valimine",
        "userrights-user-editname": "Sisesta kasutajanimi:",
-       "editusergroup": "Muuda {{GENDER:$1|kasutajarühmi}}",
+       "editusergroup": "Laadi kasutajarühmad",
        "editinguser": "Kasutaja '''[[User:$1|$1]]''' $2 õiguste muutmine",
        "userrights-editusergroup": "Kasutajarühmade muutmine",
        "saveusergroups": "Salvesta {{GENDER:$1|kasutajarühmad}}",
        "userrights-reason": "Põhjus:",
        "userrights-no-interwiki": "Sul ei ole luba muuta kasutajaõigusi teistes vikides.",
        "userrights-nodatabase": "Andmebaasi $1 ei ole olemas või pole see kohalik.",
-       "userrights-nologin": "Et kasutajaõigusi jagada, pead administraatori kontoga [[Special:UserLogin|sisse logima]].",
-       "userrights-notallowed": "Sul pole õigust kasutajaõigusi lisada ega eemaldada.",
        "userrights-changeable-col": "Rühmad, mida sa saad muuta",
        "userrights-unchangeable-col": "Rühmad, mida sa ei saa muuta",
        "userrights-conflict": "Kasutajaõiguste muutmise konflikt! Palun vaata oma muudatused üle ja kinnita need.",
-       "userrights-removed-self": "Võtsid endalt õigused. Seetõttu sellele leheküljele sa enam ligi ei pääse.",
        "group": "Rühm:",
        "group-user": "Kasutajad",
        "group-autoconfirmed": "Automaatselt kinnitatud kasutajad",
        "right-siteadmin": "Panna lukku ja lukust lahti teha andmebaasi",
        "right-override-export-depth": "Eksportida lehekülgi, kaasates viidatud leheküljed kuni viienda tasemeni",
        "right-sendemail": "Saata teistele kasutajatele e-kirju",
-       "right-passwordreset": "Vaadata parooli lähtestamise e-kirju",
        "right-managechangetags": "Koostada ja (in)aktiveerida [[Special:Tags|märgiseid]]",
        "right-applychangetags": "Rakendada [[Special:Tags|märgiseid]] enda muudatuste suhtes",
        "right-changetags": "Lisada ja eemaldada käsitsi rakendatavaid [[Special:Tags|märgiseid]] üksikute redaktsioonide ja logisissekannete juures",
        "grant-editpage": "Olemasolevate lehekülgede redigeerimine",
        "grant-editprotected": "Kaitstud lehekülgede redigeerimine",
        "grant-highvolume": "Suuremahuline redigeerimine",
+       "grant-oversight": "Kasutajate peitmine ja redaktsioonide varjamine",
        "grant-patrol": "Lehekülgede muudatuste kontroll",
        "grant-protect": "Lehekülgede kaitsmine ja kaitse eemaldamine",
        "grant-rollback": "Lehekülgede muudatuste tühistamine",
        "statistics-files": "Üleslaaditud faile",
        "statistics-edits": "Redigeerimisi alates {{GRAMMAR:genitive|{{SITENAME}}}} loomisest",
        "statistics-edits-average": "Keskmiselt redigeerimisi lehekülje kohta",
-       "statistics-users": "Registreeritud [[Special:ListUsers|kasutajaid]]",
-       "statistics-users-active": "Aktiivseid kasutajaid",
+       "statistics-users": "Registreeritud [[Special:ListUsers|kasutajad]]",
+       "statistics-users-active": "Aktiivsed kasutajad",
        "statistics-users-active-desc": "Kasutajad, kes on viimase {{PLURAL:$1|päeva|$1 päeva}} jooksul tegutsenud",
        "pageswithprop": "Leheatribuudiga leheküljed",
        "pageswithprop-legend": "Leheatribuudiga leheküljed",
        "booksources-search": "Otsi",
        "booksources-text": "Allpool on linke teistele lehekülgedele, kus müüakse uusi ja kasutatud raamatuid. Lehekülgedel võib olla ka lisainfot raamatute kohta:",
        "booksources-invalid-isbn": "Antud ISBN-number ei ole korrektne; kontrolli algallikast kopeerides vigu.",
+       "magiclink-tracking-rfc": "RFC-võlulingiga leheküljed",
+       "magiclink-tracking-pmid": "PMID-võlulingiga leheküljed",
+       "magiclink-tracking-isbn": "ISBN-võlulingiga leheküljed",
        "specialloguserlabel": "Täitja:",
        "speciallogtitlelabel": "Objekt (pealkiri või {{ns:user}}:kasutajanimi):",
        "log": "Logid",
        "activeusers-intro": "See on loetelu kasutajatest, kes on viimase $1 {{PLURAL:$1|päev|päeva}} jooksul midagi teinud.",
        "activeusers-count": "$1 {{PLURAL:$1|toiming|toimingut}} viimase {{PLURAL:$3|päeva|$3 päeva}} jooksul",
        "activeusers-from": "Näita kasutajaid alates:",
+       "activeusers-groups": "Kuva kasutajad, kes kuuluvad järgmistesse rühmadesse:",
+       "activeusers-excludegroups": "Ära kuva kasutajaid, kes kuuluvad järgmistesse rühmadesse:",
        "activeusers-noresult": "Kasutajaid ei leidunud.",
        "activeusers-submit": "Kuva aktiivsed kasutajad",
        "listgrouprights": "Kasutajarühma õigused",
        "trackingcategories-msg": "Süsteemikategooria",
        "trackingcategories-name": "Sõnumi nimi",
        "trackingcategories-desc": "Kategooriasse arvamise kriteeriumid",
+       "restricted-displaytitle-ignored": "Eiratava kuvapealkirjaga leheküljed",
        "noindex-category-desc": "Robotid ei indekseeri lehekülge, sest sellel on võlusõna <code><nowiki>__NOINDEX__</nowiki></code> ja lehekülg on nimeruumis, kus see silt on lubatud.",
        "index-category-desc": "Leheküljel on <code><nowiki>__INDEX__</nowiki></code> ja lehekülg on nimeruumis, kus see silt on lubatud ning seetõttu indekseerivad robotid lehekülge seal, kus nad muidu seda ei teeks.",
        "post-expand-template-inclusion-category-desc": "Kõigi mallide hõrendamise järel on lehekülg suurem kui <code>$wgMaxArticleSize</code>, mistõttu jäid mõned mallid hõrendamata.",
        "emailccsubject": "Koopia sinu sõnumist kasutajale $1: $2",
        "emailsent": "E-kiri saadetud",
        "emailsenttext": "Sinu teade on e-kirjaga saadetud.",
-       "emailuserfooter": "Selle e-kirja saatis $1 {{GRAMMAR:elative|{{SITENAME}}}} kasutajale $2 toimingu \"{{int:emailuser}}\" abil.",
+       "emailuserfooter": "Selle e-kirja saatis $1 {{GRAMMAR:elative|{{SITENAME}}}} kasutajale $2 toimingu \"{{int:emailuser}}\" abil. Sinu kiri saadetakse otse algse kirja saatjale, mistõttu saab ta sinu e-posti aadressi teada.",
        "usermessage-summary": "Jätan süsteemiteate.",
        "usermessage-editor": "Süsteemiteadete edastaja",
        "watchlist": "Jälgimisloend",
        "pageinfo-category-pages": "Lehekülgi",
        "pageinfo-category-subcats": "Alamkategooriaid",
        "pageinfo-category-files": "Faile",
+       "pageinfo-user-id": "Kasutaja identifikaator",
        "markaspatrolleddiff": "Märgi kontrollituks",
        "markaspatrolledtext": "Märgi see leht kontrollituks",
        "markaspatrolledtext-file": "Märgi see failiversioon kontrollituks",
        "patrol-log-header": "See on kontrollitud redaktsioonide logi.",
        "log-show-hide-patrol": "$1 kontrollimislogi",
        "log-show-hide-tag": "$1 märgiste logi",
+       "confirm-markpatrolled-button": "Sobib",
        "deletedrevision": "Kustutatud vanem versioon $1",
        "filedeleteerror-short": "Tõrge faili kustutamisel: $1",
        "filedeleteerror-long": "Faili kustutamisel esines tõrkeid:\n\n$1",
        "newimages-label": "Failinimi (või selle osa):",
        "newimages-showbots": "Näita robotite üles laaditud faile",
        "noimages": "Uusi pilte ei ole.",
+       "gallery-slideshow-toggle": "Lülita pisipildid ümber",
        "ilsubmit": "Otsi",
        "bydate": "kuupäeva järgi",
        "sp-newimages-showfrom": "Näita uusi faile alates kuupäevast $2, kell $1",
        "tags-deactivate": "keela",
        "tags-hitcount": "$1 {{PLURAL:$1|muudatus|muudatust}}",
        "tags-manage-no-permission": "Sul pole õigust muudatusmärgiseid hallata.",
-       "tags-manage-blocked": "Muudatusmärgiseid ei saa hallata, kui oled blokeeritud.",
+       "tags-manage-blocked": "Muudatusmärgiseid ei saa hallata, kui {{GENDER:$1|oled}} blokeeritud.",
        "tags-create-heading": "Uue märgise koostamine",
        "tags-create-explanation": "Vaikimisi on vastkoostatud märgised kasutajate ja robotite jaoks kasutatavad.",
        "tags-create-tag-name": "Märgise nimi:",
        "tags-deactivate-not-allowed": "Märgist \"$1\" pole võimalik keelata.",
        "tags-deactivate-submit": "Keela",
        "tags-apply-no-permission": "Sul pole lubatud rakendada muudatusmärgiseid enda muudatuste suhtes.",
-       "tags-apply-blocked": "Muudatusmärgiseid ei saa enda muudatustele rakendada, kui oled blokeeritud.",
+       "tags-apply-blocked": "Muudatusmärgiseid ei saa enda muudatustele rakendada, kui {{GENDER:$1|oled}} blokeeritud.",
        "tags-apply-not-allowed-one": "Märgist \"$1\" pole lubatud käsitsi rakendada.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Järgmist märgist|Järgmiseid märgiseid}} pole lubatud käsitsi rakendada: $1",
        "tags-update-no-permission": "Sul pole lubatud üksikute redaktsioonide ega logisissekannete juures muudatusmärgiseid lisada ega eemaldada.",
-       "tags-update-blocked": "Muudatusmärgiseid ei saa lisada ega eemaldada, kui oled blokeeritud.",
+       "tags-update-blocked": "Muudatusmärgiseid ei saa lisada ega eemaldada, kui {{GENDER:$1|oled}} blokeeritud.",
        "tags-update-add-not-allowed-one": "Märgist \"$1\" pole lubatud käsitsi lisada.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Järgmist märgist|Järgmiseid märgiseid}} pole lubatud käsitsi lisada: $1",
        "tags-update-remove-not-allowed-one": "Märgist \"$1\" pole lubatud eemaldada.",
        "htmlform-user-not-exists": "Kasutajat <strong>$1</strong> pole olemas.",
        "htmlform-user-not-valid": "<strong>$1</strong> pole sobiv kasutajanimi.",
        "logentry-delete-delete": "$1 {{GENDER:$2|kustutas}} lehekülje $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|kustutas}} ülekirjutamise teel ümbersuunamise $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|taastas}} lehekülje $3",
        "logentry-delete-event": "$1 {{GENDER:$2|muutis}} leheküljel $3 {{PLURAL:$5|ühe|$5}} logisündmuse nähtavust: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|muutis}} leheküljel $3 {{PLURAL:$5|ühe|$5}} redaktsiooni nähtavust: $4",
        "special-characters-group-ipa": "IPA-laiendid",
        "special-characters-group-symbols": "Sümbolid",
        "special-characters-group-greek": "Kreeka",
+       "special-characters-group-greekextended": "Kreeka (laiendatud)",
        "special-characters-group-cyrillic": "Kirillitsa",
        "special-characters-group-arabic": "Araabia",
        "special-characters-group-arabicextended": "Araabia (laiendatud)",
        "mw-widgets-dateinput-placeholder-month": "AAAA-KK",
        "mw-widgets-titleinput-description-new-page": "lehekülge pole veel",
        "mw-widgets-titleinput-description-redirect": "ümbersuunamine leheküljele \"$1\"",
+       "mw-widgets-categoryselector-add-category-placeholder": "Lisa kategooria...",
+       "sessionprovider-generic": "klassi $1 seansse",
+       "sessionprovider-mediawiki-session-cookiesessionprovider": "küpsisepõhiseid seansse",
        "randomrootpage": "Juhuslik juurlehekülg",
        "log-action-filter-block": "Blokeeringu tüüp:",
+       "log-action-filter-contentmodel": "Sisumudeli muudatuse tüüp:",
+       "log-action-filter-delete": "Kustutamise tüüp:",
+       "log-action-filter-import": "Impordi tüüp:",
+       "log-action-filter-managetags": "Märgiste haldamistegevuse tüüp:",
+       "log-action-filter-move": "Teisaldamise tüüp:",
+       "log-action-filter-newusers": "Konto loomise tüüp:",
+       "log-action-filter-patrol": "Kontrolli tüüp:",
+       "log-action-filter-protect": "Kaitsmise tüüp:",
+       "log-action-filter-rights": "Õiguste muudatuse tüüp:",
+       "log-action-filter-suppress": "Varjamise tüüp:",
+       "log-action-filter-upload": "Üleslaadimise tüüp:",
        "log-action-filter-all": "Kõik",
        "log-action-filter-block-block": "Blokeerimine",
        "log-action-filter-block-reblock": "Blokeeringu muutmine",
        "log-action-filter-block-unblock": "Blokeeringu tühistamine",
+       "log-action-filter-contentmodel-change": "Sisumudeli muudatus",
+       "log-action-filter-contentmodel-new": "Ebastandardse sisumudeliga lehekülje loomine",
+       "log-action-filter-delete-delete": "Lehekülje kustutamine",
+       "log-action-filter-delete-delete_redir": "Ümbersuunamise ülekirjutamine",
+       "log-action-filter-delete-restore": "Lehekülje taastamine",
+       "log-action-filter-delete-event": "Logi kustutamine",
+       "log-action-filter-delete-revision": "Redaktsiooni kustutamine",
+       "log-action-filter-import-interwiki": "Vikidevaheline import",
+       "log-action-filter-import-upload": "XML-faili üleslaadimisega import",
+       "log-action-filter-managetags-create": "Märgise koostamine",
+       "log-action-filter-managetags-delete": "Märgise kustutamine",
+       "log-action-filter-managetags-activate": "Märgise lubamine",
+       "log-action-filter-managetags-deactivate": "Märgise keelamine",
+       "log-action-filter-move-move": "Teisaldamine ümbersuunamise ülekirjutamiseta",
+       "log-action-filter-move-move_redir": "Teisaldamine ümbersuunamise ülekirjutamisega",
+       "log-action-filter-newusers-create": "Loonud anonüümne kasutaja",
+       "log-action-filter-newusers-create2": "Loonud registreeritud kasutaja",
+       "log-action-filter-newusers-autocreate": "Loodud automaatselt",
+       "log-action-filter-newusers-byemail": "Loodud e-kirjatsi saadetud parooliga",
+       "log-action-filter-patrol-patrol": "Kontrollitud käsitsi",
+       "log-action-filter-patrol-autopatrol": "Kontrollitud automaatselt",
+       "log-action-filter-protect-protect": "Kaitsmine",
+       "log-action-filter-protect-modify": "Kaitse muutmine",
+       "log-action-filter-protect-unprotect": "Kaitse eemaldamine",
+       "log-action-filter-protect-move_prot": "Kaitse teisaldamine",
+       "log-action-filter-rights-rights": "Muudetud käsitsi",
+       "log-action-filter-rights-autopromote": "Muudetud automaatselt",
+       "log-action-filter-suppress-event": "Logi varjamine",
+       "log-action-filter-suppress-revision": "Redaktsiooni varjamine",
+       "log-action-filter-suppress-delete": "Lehekülje varjamine",
+       "log-action-filter-suppress-block": "Kasutaja varjamine blokeerimise teel",
+       "log-action-filter-suppress-reblock": "Kasutaja varjamine taasblokeerimise teel",
+       "log-action-filter-upload-upload": "Uus üleslaadimine",
+       "log-action-filter-upload-overwrite": "Uuesti üleslaadimine",
        "authmanager-provider-password": "Paroolipõhine autentimine",
        "authmanager-provider-password-domain": "Parooli- ja domeenipõhine autentimine",
        "authmanager-provider-temporarypassword": "Ajutine parool",
        "userjsispublic": "Pea silmas, et JavaScripti alamleheküljed ei tohiks sisaldada konfidentsiaalseid andmeid, kuna neid näevad teised kasutajad.",
        "restrictionsfield-badip": "Vigane IP-aadress või -aadressivahemik: $1",
        "restrictionsfield-label": "Lubatud IP-aadressivahemikud:",
-       "restrictionsfield-help": "Üks IP-aadress või CIDR-vahemik rea kohta. Et lubada kõik, kasuta süntaksit <br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Tõrge: $1",
-       "edit-error-long": "Tõrked:\n\n$1"
+       "restrictionsfield-help": "Üks IP-aadress või CIDR-vahemik rea kohta. Et lubada kõik, kasuta süntaksit <br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 187d68c..5c5d846 100644 (file)
@@ -26,7 +26,8 @@
                        "Xð",
                        "Asierog",
                        "Matma Rex",
-                       "Gorkaazk"
+                       "Gorkaazk",
+                       "Vriullop"
                ]
        },
        "tog-underline": "Azpimarratu loturak:",
        "passwordreset-emaildisabled": "E-posta aukerak ez daude eskuragarri wiki honetan.",
        "passwordreset-username": "Lankide izena:",
        "passwordreset-domain": "Domeinua:",
-       "passwordreset-capture": "Bidaliko den e-posta ikusi nahi?",
-       "passwordreset-capture-help": "Kutxa hau hautatzen baduzu behin-behineko pasahitza duen e-posta erakutsiko zatzaizu, eta erabiltzaileari bidaliko zaio.",
        "passwordreset-email": "E-mail helbidea:",
        "passwordreset-emailtitle": "{{SITENAME}}-rako kontuaren xehetasunak",
        "passwordreset-emailelement": "Erabiltzaile izena: \n$1\n\nBehin-behineko pasahitza: \n$2",
        "userrights-reason": "Arrazoia:",
        "userrights-no-interwiki": "Ez duzu beste wikietan erabiltzaile eskumenak aldatzeko baimenik.",
        "userrights-nodatabase": "$1 datubasea ez da existitzen edo ez dago lokalki.",
-       "userrights-nologin": "Administratzaile kontu batekin [[Special:UserLogin|hasi behar duzu saioa]] erabiltzaile eskubideak esleitzeko.",
-       "userrights-notallowed": "Zure kontuak ez du baimenik erabiltzaile eskumenak aldatzeko.",
        "userrights-changeable-col": "Alda ditzakezun taldeak",
        "userrights-unchangeable-col": "Aldatu ezin ditzakezun taldeak",
        "userrights-conflict": "Gatazka gertatu da erabiltzaile eskubideak aldatzean. Mesedez, berrikusi eta baieztatu zure aldaketak.",
-       "userrights-removed-self": "Zure eskumenak kendu dituzu. Beraz jada ezin duzu orrialde hau gehiago ikusi.",
        "group": "Taldea:",
        "group-user": "Erabiltzaileak",
        "group-autoconfirmed": "Lankide autokonfirmatuak",
        "right-siteadmin": "Blokeatu eta desblokeatu datu basea blokeatu",
        "right-override-export-depth": "5eko sakonerararteko loturiko orrialdeak barne esportatu",
        "right-sendemail": "Beste erabiltzaileei e-posta bidali",
-       "right-passwordreset": "Ikusi pasahitza berrezartze e-postak",
        "grant-group-email": "E-posta bidali",
        "grant-createaccount": "Kontuak sortu",
        "grant-editmycssjs": "Zure CSS/JavaScript aldatu",
        "confirm-unwatch-button": "Ados",
        "confirm-unwatch-top": "Orrialde hau zure jarraipen-zerrendatik kendu?",
        "confirm-rollback-button": "Ados",
+       "word-separator": "&#32;",
        "quotation-marks": "«$1»",
        "imgmultipageprev": "&larr; aurreko orrialdea",
        "imgmultipagenext": "hurrengo orrialdea &rarr;",
        "feedback-subject": "Gaia:",
        "feedback-submit": "Bidali",
        "feedback-thanks-title": "Eskerrik asko!",
-       "searchsuggest-search": "Bilatu",
+       "searchsuggest-search": "{{SITENAME}} wikian bilatu",
        "searchsuggest-containing": "edukian...",
        "api-error-badaccess-groups": "Ez duzu baimendik fitxategi hauek wiki honetara igotzeko.",
        "api-error-badtoken": "Barne akatsa: token okerra.",
index 38189f2..486fc28 100644 (file)
        "number_of_watching_users_pageview": "[$1 {{PLURAL:$1|usuáriu está|usuárius están}} vehilandu]",
        "rc_categories": "Arrayal a categorias (separás pol \"|\")",
        "rc_categories_any": "Cualisquiá",
-       "rc-change-size-new": "$1{{PLURAL:$1|byte|bytes}} dempués el chambu",
+       "rc-change-size-new": "$1 {{PLURAL:$1|byte|bytes}} dempués el chambu",
        "newsectionsummary": "/* $1 */ seción nueva",
        "rc-enhanced-expand": "muestral detallis (es mestel JavaScript)",
        "rc-enhanced-hide": "Açonchal detallis",
index c435b73..27c22a5 100644 (file)
                ]
        },
        "tog-underline": "خط کشیدن زیر پیوندها:",
-       "tog-hideminor": "نهفتن تغییرات جزئی از فهرست تغییرات اخیر",
-       "tog-hidepatrolled": "Ù\86Ù\87Ù\81تÙ\86 Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ú¯Ø´Øªâ\80\8cØ®Ù\88ردÙ\87 Ø§Ø² Ù\81Ù\87رست ØªØºÛ\8cÛ\8cرات Ø§Ø®Û\8cر",
-       "tog-newpageshidepatrolled": "نهفتن صفحه‌های گشت‌خورده از فهرست صفحه‌های تازه",
+       "tog-hideminor": "تغییرات جزئی از فهرست تغییرات اخیر پنهان شود",
+       "tog-hidepatrolled": "Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ú¯Ø´Øªâ\80\8cØ®Ù\88ردÙ\87 Ø§Ø² Ù\81Ù\87رست ØªØºÛ\8cÛ\8cرات Ø§Ø®Û\8cر Ù¾Ù\86Ù\87اÙ\86 Ø´Ù\88د",
+       "tog-newpageshidepatrolled": "صفحه‌های گشت‌خورده از فهرست صفحه‌های تازه پنهان شود",
        "tog-hidecategorization": "نهفتن رده‌بندی صفحه‌ها",
        "tog-extendwatchlist": "گسترش فهرست پیگیری‌ها برای نمایش همهٔ تغییرات، نه فقط جدیدترین‌ها",
-       "tog-usenewrc": "گروه‌بندی تغییرات بر پایهٔ صفحه‌ در تغییرات اخیر و فهرست پیگیری‌ها",
+       "tog-usenewrc": "در تغییرات اخیر و فهرست پیگیری‌ها تغییرات بر پایهٔ صفحه‌ گروه‌بندی شود",
        "tog-numberheadings": "شماره‌گذاری خودکار عنوان‌ها",
-       "tog-showtoolbar": "Ù\86Ù\85اÛ\8cØ´ Ù\86Ù\88ار Ø§Ø¨Ø²Ø§Ø± Ù\88Û\8cراÛ\8cØ´",
+       "tog-showtoolbar": "Ù\86Ù\88ار Ø§Ø¨Ø²Ø§Ø± Ù\88Û\8cراÛ\8cØ´ Ù\86Ù\85اÛ\8cØ´ Ø¯Ø§Ø¯Ù\87 Ø´Ù\88د",
        "tog-editondblclick": "ویرایش صفحات با دو کلیک",
        "tog-editsectiononrightclick": "فعال کردن ویرایش بخش‌ها با کلیک راست روی عنوان بخش‌ها",
-       "tog-watchcreations": "اÙ\81زÙ\88دÙ\86 ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ù\85Û\8câ\80\8cسازÙ\85 Ù\88 Ù¾Ø±Ù\88Ù\86دÙ\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ø¨Ø§Ø±Ú¯Ø°Ø§Ø±Û\8c Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8c Ù\85Ù\86",
-       "tog-watchdefault": "اÙ\81زÙ\88دÙ\86 ØµÙ\81Ø­Ù\87â\80\8cÙ\87ا Ù\88 Ù¾Ø±Ù\88Ù\86دÙ\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ù\88Û\8cراÛ\8cØ´ Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8c Ù\85Ù\86",
-       "tog-watchmoves": "اÙ\81زÙ\88دÙ\86 ØµÙ\81Ø­Ù\87â\80\8cÙ\87ا Ù\88 Ù¾Ø±Ù\88Ù\86دÙ\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ù\85Ù\86تÙ\82Ù\84 Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8c Ù\85Ù\86",
-       "tog-watchdeletion": "اÙ\81زÙ\88دÙ\86 ØµÙ\81حات Ù\88 Ù¾Ø±Ù\88Ù\86دÙ\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ø­Ø°Ù\81 Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8c Ù\85Ù\86",
-       "tog-watchuploads": "افزودن پرونده‌های جدید به فهرست پیگیری من",
+       "tog-watchcreations": "صÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ù\85Û\8câ\80\8cسازÙ\85 Ù\88 Ù¾Ø±Ù\88Ù\86دÙ\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ø¨Ø§Ø±Ú¯Ø°Ø§Ø±Û\8c Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8c Ù\85Ù\86 Ø§Ù\81زÙ\88دÙ\87 Ø´Ù\88د",
+       "tog-watchdefault": "صÙ\81Ø­Ù\87â\80\8cÙ\87ا Ù\88 Ù¾Ø±Ù\88Ù\86دÙ\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ù\88Û\8cراÛ\8cØ´ Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8c Ù\85Ù\86 Ø§Ù\81زÙ\88دÙ\87 Ø´Ù\88د",
+       "tog-watchmoves": "صÙ\81Ø­Ù\87â\80\8cÙ\87ا Ù\88 Ù¾Ø±Ù\88Ù\86دÙ\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ù\85Ù\86تÙ\82Ù\84 Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8c Ù\85Ù\86 Ø§Ù\81زÙ\88دÙ\87 Ø´Ù\88د",
+       "tog-watchdeletion": "صÙ\81Ø­Ù\87â\80\8cÙ\87ا Ù\88 Ù¾Ø±Ù\88Ù\86دÙ\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ø­Ø°Ù\81 Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8c Ù\85Ù\86 Ø§Ù\81زÙ\88دÙ\87 Ø´Ù\88د",
+       "tog-watchuploads": "پرونده‌های جدیدی که بارگذاری می‌کنم به فهرست پیگیری من افزوده شود",
        "tog-watchrollback": "افزودن صفحاتی که واگردانی می‌کنم به فهرست پیگیری‌های من",
-       "tog-minordefault": "علامت زدن همهٔ ویرایش‌ها به عنوان «جزئی» به طور پیش‌فرض",
-       "tog-previewontop": "Ù\86Ù\85اÛ\8cØ´ Ø¯Ø§Ø¯Ù\86 Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ø¨Ø§Ù\84اÛ\8c Ø¬Ø¹Ø¨Ù\87Ù\94 Ù\88Û\8cراÛ\8cØ´",
-       "tog-previewonfirst": "Ù\86Ù\85اÛ\8cØ´ Ø¯Ø§Ø¯Ù\86 Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ù\87Ù\86گاÙ\85 Ø§Ù\88Ù\84Û\8cÙ\86 Ù\88Û\8cراÛ\8cØ´",
+       "tog-minordefault": "همهٔ ویرایش‌ها به طور پیش‌فرض به عنوان «جزئی» علامت زده شود",
+       "tog-previewontop": "Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ø¨Ø§Ù\84اÛ\8c Ø¬Ø¹Ø¨Ù\87Ù\94 Ù\88Û\8cراÛ\8cØ´ Ù\86Ù\85اÛ\8cØ´ Ø¯Ø§Ø¯Ù\87 Ø´Ù\88د",
+       "tog-previewonfirst": "Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ù\87Ù\86گاÙ\85 Ø§Ù\88Ù\84Û\8cÙ\86 Ù\88Û\8cراÛ\8cØ´ Ù\86Ù\85اÛ\8cØ´ Ø¯Ø§Ø¯Ù\87 Ø´Ù\88د",
        "tog-enotifwatchlistpages": "اگر صفحه یا پرونده‌ای از فهرست پی‌گیری‌هایم ویرایش شد به من ایمیلی فرستاده شود",
        "tog-enotifusertalkpages": "هنگامی که در صفحهٔ بحث کاربری‌ام تغییری صورت می‌گیرد به من ایمیلی فرستاده شود",
        "tog-enotifminoredits": "برای تغییرات جزئی در صفحه‌ها و پرونده‌ها هم به من ایمیلی فرستاده شود",
        "tog-enotifrevealaddr": "نشانی پست الکترونیکی من در ایمیل‌های اطلاع‌رسانی هویدا گردد",
        "tog-shownumberswatching": "نمایشِ شمار کاربران پی‌گیری کننده",
-       "tog-oldsig": "امضای کنونی:",
+       "tog-oldsig": "امضای کنونی شما:",
        "tog-fancysig": "امضا به صورت ویکی‌متن در نظر گرفته شود (بدون درج خودکار پیوند)",
-       "tog-uselivepreview": "استÙ\81ادÙ\87 Ø§Ø² Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ø²Ù\86دÙ\87",
+       "tog-uselivepreview": "از Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ø²Ù\86دÙ\87 Ø§Ø³ØªÙ\81ادÙ\87 Ø´Ù\88د",
        "tog-forceeditsummary": "هنگامی که خلاصهٔ ویرایش ننوشته‌ام به من اطلاع داده شود",
-       "tog-watchlisthideown": "Ù\86Ù\87Ù\81تÙ\86 Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ø®Ù\88دÙ\85 Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا",
-       "tog-watchlisthidebots": "Ù\86Ù\87Ù\81تÙ\86 Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ø±Ø¨Ø§Øªâ\80\8cÙ\87ا Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا",
-       "tog-watchlisthideminor": "Ù\86Ù\87Ù\81تÙ\86 Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ø¬Ø²Ø¦Û\8c Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا",
-       "tog-watchlisthideliu": "Ù\86Ù\87Ù\81تÙ\86 Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ú©Ø§Ø±Ø¨Ø±Ø§Ù\86 Ù\88ارد Ø´Ø¯Ù\87 Ø¨Ù\87 Ø³Ø§Ù\85اÙ\86Ù\87 Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا",
-       "tog-watchlistreloadautomatically": "زمانی که یک پالایه تغییر کرد فهرست پیگیری به صورت خودکار به روز می‌شود (نیازمند جاوا اسکریپت)",
-       "tog-watchlisthideanons": "Ù\86Ù\87Ù\81تÙ\86 Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ú©Ø§Ø±Ø¨Ø±Ø§Ù\86 Ù\86اشÙ\86اس Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا",
-       "tog-watchlisthidepatrolled": "Ù\86Ù\87Ù\81تÙ\86 Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ú¯Ø´Øªâ\80\8cØ®Ù\88ردÙ\87 Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا",
+       "tog-watchlisthideown": "Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ø®Ù\88دÙ\85 Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا Ù¾Ù\86Ù\87اÙ\86 Ø´Ù\88د",
+       "tog-watchlisthidebots": "Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ø±Ø¨Ø§Øªâ\80\8cÙ\87ا Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا Ù¾Ù\86Ù\87اÙ\86 Ø´Ù\88د",
+       "tog-watchlisthideminor": "Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ø¬Ø²Ø¦Û\8c Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا Ù¾Ù\86Ù\87اÙ\86 Ø´Ù\88د",
+       "tog-watchlisthideliu": "Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ú©Ø§Ø±Ø¨Ø±Ø§Ù\86 Ù\88ارد Ø´Ø¯Ù\87 Ø¨Ù\87 Ø³Ø§Ù\85اÙ\86Ù\87 Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا Ù¾Ù\86Ù\87اÙ\86 Ø´Ù\88د",
+       "tog-watchlistreloadautomatically": "زمانی که یک پالایه تغییر کرد فهرست پیگیری به صورت خودکار به روز شود (نیازمند جاوااسکریپت)",
+       "tog-watchlisthideanons": "Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ú©Ø§Ø±Ø¨Ø±Ø§Ù\86 Ù\86اشÙ\86اس Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا Ù¾Ù\86Ù\87اÙ\86 Ø´Ù\88د",
+       "tog-watchlisthidepatrolled": "Ù\88Û\8cراÛ\8cØ´â\80\8cÙ\87اÛ\8c Ú¯Ø´Øªâ\80\8cØ®Ù\88ردÙ\87 Ø¯Ø± Ù\81Ù\87رست Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87ا Ù¾Ù\86Ù\87اÙ\86 Ø´Ù\88د",
        "tog-watchlisthidecategorization": "نهفتن رده‌بندی صفحه‌ها",
        "tog-ccmeonemails": "رونوشتی از ایمیلی که به دیگران ارسال می‌کنم برای خودم هم فرستاده شود",
        "tog-diffonly": "محتوای صفحه، زیر تفاوت نمایش داده نشود",
-       "tog-showhiddencats": "نمایش رده‌های پنهان",
+       "tog-showhiddencats": "رده‌های پنهان نمایش داده شود",
        "tog-norollbackdiff": "بعد از واگردانی، تفاوت نشان داده نشود",
        "tog-useeditwarning": "زمان خروج از صفحهٔ ویرایش در صورت داشتن ویرایش‌های‌ ذخیره‌نشده به من هشدار داده شود",
        "tog-prefershttps": "هنگامی که به سامانه وارد شده‌ام، همواره از اتصال امن استفاده شود",
        "newwindow": "(در پنجرهٔ تازه باز می‌شود)",
        "cancel": "لغو",
        "moredotdotdot": "بیشتر...",
-       "morenotlisted": "این فهرست کامل نیست.",
+       "morenotlisted": "این فهرست ممکن است کامل نباشد.",
        "mypage": "صفحه",
        "mytalk": "بحث",
        "anontalk": "بحث",
        "views": "بازدیدها",
        "toolbox": "ابزارها",
        "tool-link-userrights": "تغییر گروه‌های {{GENDER:$1|کاربر}}",
+       "tool-link-userrights-readonly": "نمایش گروه‌های {{GENDER:$1|کاربر}}",
        "tool-link-emailuser": "فرستادن نامه به {{GENDER:$1|کاربر}}",
        "userpage": "نمایش صفحهٔ کاربر",
        "projectpage": "نمایش صفحهٔ پروژه",
        "createacct-yourpasswordagain-ph": "گذرواژه را وارد کنید برای بار دوم",
        "userlogin-remembermypassword": "من را واردشده نگه‌دار",
        "userlogin-signwithsecure": "از ورود امن استفاده کنید",
+       "cannotlogin-title": "ناتوان از ورود به سامانه",
+       "cannotlogin-text": "ورود به سامانه ممکن نیست.",
        "cannotloginnow-title": "الان امکان وررود به سامانه نیست",
        "cannotloginnow-text": "در زمان استفاده از $1 امکان ورود به سامانه وجود ندارد.",
+       "cannotcreateaccount-title": "ناتوان از ایجاد حساب",
+       "cannotcreateaccount-text": "در این ویکی ایجاد مستقیم حساب فعال نشده‌است.",
        "yourdomainname": "دامنهٔ شما:",
        "password-change-forbidden": "شما نمی‌توانید گذرواژه‌ها را در این ویکی تغییر دهید.",
        "externaldberror": "خطایی در ارتباط با پایگاه داده رخ داده است یا اینکه شما اجازهٔ به‌روزرسانی حساب خارجی خود را ندارید.",
        "eauthentsent": "یک ایمیل تأیید برای آدرس ایمیل به نشانی مورد نظر ارسال شد.\nقبل از اینکه ایمیل دیگری قابل ارسال به این آدرس باشد، باید دستورهایی که در آن ایمیل آمده است را جهت تأیید این مساله که این آدرس متعلق به شماست، اجرا کنید.",
        "throttled-mailpassword": "یک ایمیل بازنشانی گذرواژه در $1 {{PLURAL:$1|ساعت|ساعت}} گذشته فرستاده شده است.\nبرای جلوگیری از سوءاستفاده، هر $1 {{PLURAL:$1|ساعت|ساعت}} تنها یک ایمیل بازنشانی گذرواژه فرستاده می‌شود.",
        "mailerror": "خطا در ارسال ایمیل: $1",
-       "acct_creation_throttle_hit": "بازدیدکنندگان این ویکی که از نشانی آی‌پی شما استفاده می‌کنند در روز گذشته {{PLURAL:$1|یک حساب کاربری|$1 حساب کاربری}} ساخته‌اند، که بیشترین تعداد مجاز در آن بازهٔ زمانی است.\nبه همین خاطر، بازدیدکنندگانی که از این نشانی آی‌پی استفاده می‌کنند نمی‌توانند در حال حاضر حساب جدیدی بسازند.",
+       "acct_creation_throttle_hit": "بازدیدکنندگان این ویکی که از نشانی آی‌پی شما استفاده می‌کنند در $2 گذشته {{PLURAL:$1|یک حساب کاربری|$1 حساب کاربری}} ساخته‌اند، که بیشترین تعداد مجاز در آن بازهٔ زمانی است.\nبه همین خاطر، بازدیدکنندگانی که از این نشانی آی‌پی استفاده می‌کنند نمی‌توانند در حال حاضر حساب جدیدی بسازند.",
        "emailauthenticated": "نشانی ایمیل شما در $2 ساعت $3 تأیید شده است.",
        "emailnotauthenticated": "آدرس ایمیل شما هنوز تأیید نشده است.\nبرای هیچ‌یک از ویژگی‌های زیر، ایمیل ارسال نخواهد شد.",
        "noemailprefs": "برای راه‌اندازی این قابلیت‌ها یک آدرس ایمیل در ترجیحات خود مشخص کنید.",
        "botpasswords-label-delete": "حذف",
        "botpasswords-label-resetpassword": "بازگردانی گذرواژه",
        "botpasswords-label-grants": "اعطاهای اجرا شدنی:",
-       "botpasswords-help-grants": "Ù\87ر Ø§Ø¬Ø§Ø²Ù\87 Ø¨Ù\87 Ø­Ù\82Ù\88Ù\82 Ú©Ø§Ø±Ø¨Ø±Û\8c Ú©Ù\87 Û\8cÚ© Ø­Ø³Ø§Ø¨ Ú©Ø§Ø±Ø¨Ø±Û\8c Ø¯Ø§Ø±د. [[Special:ListGrants|table of grants]] را برای اطلاعات بیشتر مشاهده کنید.",
+       "botpasswords-help-grants": "Ù\87ر Ø§Ø¬Ø§Ø²Ù\87 Ø¨Ù\87 Ø±Ø¨Ø§Øª Ø§Ø¬Ø§Ø²Ù\87 Ø¯Ø³ØªØ±Ø³Û\8c Ø¨Ù\87 Ø§Ø®ØªÛ\8cاراتÛ\8c Ø±Ø§ Ú©Ù\87 Ø­Ø³Ø§Ø¨ Ø´Ù\85ا Ø¯Ø§Ø±Ø¯ Ù\85Û\8câ\80\8cدÙ\87د. Ù\81عاÙ\84 Ú©Ø±Ø¯Ù\86 Û\8cÚ© Ø§Ø¬Ø§Ø²Ù\87 Ø¯Ø± Ø§Û\8cÙ\86جا Ù\87Û\8cÚ\86 Ø¯Ø³ØªØ±Ø³Û\8c Ø¬Ø¯Û\8cدÛ\8c Ú©Ù\87 Ø­Ø³Ø§Ø¨ Ø´Ù\85ا Ù\87Ù\85Û\8cÙ\86Ú© Ø¯Ø§Ø±Ø§ Ù\86Û\8cست Ø±Ø§ Ø¨Ù\87 Ø¢Ù\86 Ù\86Ù\85Û\8câ\80\8cبخشد. [[Special:ListGrants|table of grants]] را برای اطلاعات بیشتر مشاهده کنید.",
        "botpasswords-label-grants-column": "اعطا شد",
        "botpasswords-bad-appid": "نام ربات \"$1\" معتبر نیست.",
        "botpasswords-insert-failed": "شکست در افزودن نام ربات «$1». در حال حاضر اضافه شده است؟",
        "botpasswords-updated-body": "گذرواژهٔ رباتی برای ربات «$1» و کاربر «$2» به‌روز شد.",
        "botpasswords-deleted-title": "گذرواژه ربات حذف شد",
        "botpasswords-deleted-body": "گذرواژهٔ رباتی برای ربات «$1» و کاربر «$2» حذف شد.",
-       "botpasswords-newpassword": "<strong>$2</strong> گذرواژهٔ جدید برای ورود با <strong>$1</strong> است. <em>لطفاً این را برای ارجاع در آینده ذخیره کنید.</em>",
+       "botpasswords-newpassword": "<strong>$2</strong> گذرواژهٔ جدید برای ورود با حساب <strong>$1</strong> است. <em>لطفاً آن را برای ارجاع در آینده ذخیره کنید.</em> <br> (برای ربات‌های قدیمی که نیاز به نام کاربری مطابق با حساب کاربری‌شان دارد، شما می‌توانید از <strong>$3</strong> به عنوان نام کاربری و از <strong>$4</strong> به عنوان گذرواژه استفاده کنید.)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider موجود نیست.",
        "botpasswords-restriction-failed": "محدودیت‌های گذرواژهٔ ربات از این ورود جلوگیری می‌کند.",
        "botpasswords-invalid-name": "نام کاربری مشخص شده دارای جداکنندهٔ گذرواژهٔ رباتی نیست (\"$1\").",
        "passwordreset-emaildisabled": "قابلیت‌های ایمیل در این ویکی غیرفعال شده‌اند.",
        "passwordreset-username": "نام کاربری:",
        "passwordreset-domain": "دامنه:",
-       "passwordreset-capture": "ایمیل نهایی نشان داده شود؟",
-       "passwordreset-capture-help": "اگر این گزینه را علامت بزنید، ایمیل (حاوی گذرواژهٔ موقت) به شما نشان داده خواهد شد و برای کاربر نیز فرستاده خواهد شد.",
        "passwordreset-email": "نشانی ایمیل:",
        "passwordreset-emailtitle": "جزئیات حساب در {{SITENAME}}",
        "passwordreset-emailtext-ip": "یک نفر (احتمالاً شما، با نشانی آی‌پی $1) درخواست بازنشانی گذرواژه‌تان در {{SITENAME}} ($4) را کرده‌است. {{PLURAL:$3|حساب|حساب‌های}} کاربری زیر با این آدرس ایمیل مرتبط هستند:\n\n$2\n\n{{PLURAL:$3|این گذرواژهٔ موقت|این گذرواژه‌های موقت}} پس از {{PLURAL:$5|یک روز|$5 روز}} باطل خواهند شد.\nشما باید هم‌اکنون ثبت ورود کنید و گذرواژه‌ای جدید برگزینید. اگر فکر می‌کنید شخص دیگری این درخواست را داده است یا اگر گذرواژهٔ اصلی‌تان را به یاد آوردید و دیگر نمی‌خواهید آن را تغییر دهید، می‌توانید این پیغام را نادیده بگیرید و به استفاده از گذرواژهٔ قبلی‌تان ادامه دهید.",
        "passwordreset-emailelement": "نام کاربری: \n$1\n\nگذرواژهٔ موقت: \n$2",
        "passwordreset-emailsentemail": "اگر نشانی پست الکترونیکی که وارد کردید برای حساب کاربریتان ثبت شده باشد، یک نامهٔ بازنشانی گذرواژه به آن فرستاده می‌شود.",
        "passwordreset-emailsentusername": "اگر نشانی پست الکترونیکی مرتبطی موجود باشد، یک نامه برای بازنشانی گذرواژه به آن ارسال خواهد شد.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|نامهٔ|نامهٔ}} بازنشانی گذرواژه ارسال شد. در زير $1 نام کاربری و گذرواژه در حال نمایش است.",
-       "passwordreset-emailerror-capture2": "ارسال ناموفق نامه به $2: $1\nدر زير $3 نام کاربری و گذرواژه در حال نمایش است",
        "passwordreset-nocaller": "فراخواننده می‌بايست مشخص شده باشد",
        "passwordreset-nosuchcaller": "اين فراخواننده وجود ندارد:$1",
        "passwordreset-ignored": "به بازنشانی گذرواژه پرداخته نشد. آیا ممکن است که هيچ مهياکننده‌ای برای این کار تنظيم نشده باشد؟",
-       "passwordreset-invalideamil": "آدرس ایمیل نامعتبر",
+       "passwordreset-invalidemail": "آدرس ایمیل نامعتبر",
        "passwordreset-nodata": "یک نام کاربری و یا یک آدرس ايميل، هيچکدام ارائه نشده",
        "changeemail": "تغییر یا حذف نشانی ایمیل",
        "changeemail-header": "برای تغییر ایمیلتان این فرم را کامل کنید. برای حذف ایملیتان کافی است بخش ایمیل را خالی رها کنید و فرم را ارسال کنید.",
        "invalid-content-data": "داده محتوای نامعتبر",
        "content-not-allowed-here": "محتوای «$1» در صفحهٔ [[$2]] مجاز نیست",
        "editwarning-warning": "خروج از این صفحه ممکن است باعث شود که شما هر شانسی که به وجود آورده‌اید را از دست بدهید.\nاگر شما وارد سامانه شده‌اید، می‌توانید این هشدار را در بخش «{{int:prefs-editing}}» ترجیحاتتان غیرفعال کنید.",
+       "editpage-invalidcontentmodel-title": "مدل محتوای پشتیبانی نشده",
+       "editpage-invalidcontentmodel-text": "مدل محتوای «$1» پشتیبای نمی‌شود.",
        "editpage-notsupportedcontentformat-title": "فرمت محتوا پشتیبانی نشده",
        "editpage-notsupportedcontentformat-text": "فرمت محتوای $1 توسط مدل محتوای $2 پشتیبانی نشده‌است.",
        "content-model-wikitext": "ویکی‌متن",
        "searchprofile-advanced-tooltip": "جستجو در فضاهای نام دلخواه",
        "search-result-size": "$1 ({{PLURAL:$2|یک واژه|$2 واژه}})",
        "search-result-category-size": "{{PLURAL:$1|یک عضو|$1 عضو}} ({{PLURAL:$2|یک زیررده|$2 زیررده}}، {{PLURAL:$3|یک پرونده|$3 پرونده}})",
-       "search-redirect": "(تغییرمسیر $1)",
+       "search-redirect": "(تغییرمسیر از $1)",
        "search-section": "(بخش $1)",
        "search-category": "(رده  $1)",
        "search-file-match": "(تشابه محتوی پرونده)",
        "search-external": "جستجوی خارجی",
        "searchdisabled": "جستجو در {{SITENAME}} فعال نیست.\nموقتاً می‌توانید از جستجوی Google استفاده کنید.\nتوجه کنید که نتایج حاصل از جستجو با آن روش ممکن است به‌روز نباشند.",
        "search-error": "خطایی هنگام جست‌وجو رخ داده است: $1",
+       "search-warning": "هشداری هنگام جست‌وجو رخ داده است: $1",
        "preferences": "ترجیحات",
        "mypreferences": "ترجیحات",
        "prefs-edits": "تعداد ویرایش‌ها:",
        "prefs-rc": "تغییرات اخیر",
        "prefs-watchlist": "فهرست پی‌گیری‌ها",
        "prefs-editwatchlist": "ویرایش فهرست پی‌گیری‌ها",
-       "prefs-editwatchlist-label": "Ù\88Û\8cراÛ\8cØ´ Ù\87Ù\85Ù\87 Ù\81Ù\87رست Ù¾Û\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8cتاÙ\86:",
+       "prefs-editwatchlist-label": "ویرایش فهرست پیگیری‌هایتان:",
        "prefs-editwatchlist-edit": "دیدن و حذف عنوان‌ها از فهرست پیگیری‌هایتان",
        "prefs-editwatchlist-raw": "ویرایش فهرست خام پیگیری‌ها",
        "prefs-editwatchlist-clear": "پاک کردن فهرست پیگیری‌هایتان",
        "prefs-help-recentchangescount": "این گزینه شامل تغییرات اخیر، تاریخچهٔ صفحه‌ها و سیاهه‌ها می‌شود.",
        "prefs-help-watchlist-token2": "این کلید رمز خوراک وب فهرست پی‌گیری‌های شماست.\nهرکس آن را بداند می‌تواند فهرست پی‌گیری‌هایتان را بخواند، بنابراین آن را به اشتراک نگذارید. [[Special:ResetTokens|اگر لازم است آن را تغییر دهید اینجا را کلیک کنید]].",
        "savedprefs": "ترجیحات شما ذخیره شد.",
-       "savedrights": "دسترسی کاربری {{GENDER:$1|$1}} ذخیره شده‌است.",
+       "savedrights": "گروه‌های کاربری {{GENDER:$1|$1}} ذخیره شده‌است.",
        "timezonelegend": "منطقهٔ زمانی:",
        "localtime": "زمان محلی:",
        "timezoneuseserverdefault": "استفاده از پیش‌فرض ویکی ($1)",
        "timezoneregion-europe": "اروپا",
        "timezoneregion-indian": "اقیانوس هند",
        "timezoneregion-pacific": "اقیانوس آرام",
-       "allowemail": "اÙ\85کاÙ\86 Ø¯Ø±Û\8cاÙ\81ت Ø§Û\8cÙ\85Û\8cÙ\84 Ø§Ø² Ø¯Û\8cگر Ú©Ø§Ø±Ø¨Ø±Ø§Ù\86",
+       "allowemail": "درÛ\8cاÙ\81ت Ø§Û\8cÙ\85Û\8cÙ\84 Ø§Ø² Ø¯Û\8cگر Ú©Ø§Ø±Ø¨Ø±Ø§Ù\86 Ù\85Ù\85Ú©Ù\86 Ø¨Ø§Ø´Ø¯",
        "prefs-searchoptions": "جستجو",
        "prefs-namespaces": "فضاهای نام",
        "default": "پیش‌فرض",
        "prefs-advancedwatchlist": "گزینه‌های پیشرفته",
        "prefs-displayrc": "گزینه‌های نمایش",
        "prefs-displaywatchlist": "گزینه‌های نمایش",
-       "prefs-tokenwatchlist": "نشانه",
+       "prefs-tokenwatchlist": "بلیط",
        "prefs-diffs": "تفاوت‌ها",
        "prefs-help-prefershttps": "تأثیر این ترجیح بعد از ورود بعدی شما اعمال خواهد شد.",
        "prefswarning-warning": "تغییراتتان به ترجیحات هنوز ذحیره نشده است.\nاگر این صفحه بدون کلیک بر «$1» ترک کنید ترجیحاتتان ذخیره نخواهد شد.",
        "prefs-tabs-navigation-hint": "نکته: شما می توانید از کلیدهای جهت‌نمای چپ و راست برای حرکت بین زبانه‌ها در فهرست زبانه‌ها استفاده کنید.",
        "userrights": "مدیریت اختیارات کاربر",
-       "userrights-lookup-user": "مدیریت گروه‌های کاربری",
+       "userrights-lookup-user": "انتخاب یک کاربر",
        "userrights-user-editname": "یک نام کاربری وارد کنید:",
-       "editusergroup": "ویرایش گروه‌های {{GENDER:$1|کاربری}}",
+       "editusergroup": "بارگیری گروه‌های کاربر",
        "editinguser": "تغییر اختیارات کاربری کاربر {{GENDER:$1|کاربر}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "ویرایش گروه‌های کاربری",
        "saveusergroups": "ثبت گروه‌های {{GENDER:$1|کاربری}}",
        "userrights-reason": "دلیل:",
        "userrights-no-interwiki": "شما اجازهٔ تغییر اختیارات کاربران دیگر ویکی‌ها را ندارید.",
        "userrights-nodatabase": "پایگاه دادهٔ $1 وجود ندارد یا محلی نیست.",
-       "userrights-nologin": "شما باید با یک حساب کاربری مدیر [[Special:UserLogin|به سامانه وارد شوید]] تا بتوانید اختیارات کاربران را تعیین کنید.",
-       "userrights-notallowed": "شما مجوز برای افزودن یا حذف حقوق کاربر را ندارید.",
        "userrights-changeable-col": "گروه‌هایی که می‌توانید تغییر دهید",
        "userrights-unchangeable-col": "گروه‌هایی که نمی‌توانید تغییر دهید",
        "userrights-conflict": "تعارض دسترسی‌های کاربری! لطفاً بررسی کنید و تغییرات را تأیید کنید.",
-       "userrights-removed-self": "شما دسترسی‌های خود را واستاندید. به این ترتیب شما دیگر به این صفحه دسترسی ندارید.",
        "group": "گروه:",
        "group-user": "کاربران",
        "group-autoconfirmed": "کاربران تأییدشدهٔ خودکار",
        "right-siteadmin": "قفل‌کردن و بازکردن پایگاه داده‌ها",
        "right-override-export-depth": "برون‌بری صفحه‌ها شامل صفحه‌های پیوند شده تا عمق ۵",
        "right-sendemail": "ارسال ایمیل به دیگر کاربران",
-       "right-passwordreset": "مشاهدهٔ نامه‌های تنظیم مجدد گذرواژه",
        "right-managechangetags": "ایجاد و غیرفعال کردن [[Special:Tags|برچسب‌ها]]",
        "right-applychangetags": "تائید [[Special:Tags|برچسب]] بر روی تغییرات یک نفر",
        "right-changetags": "افزودن یا حذف [[Special:Tags|برچسب]] قراردادی بر روی نسخه یا سیاهه ورودی‌ها",
        "grant-basic": "دسترسی‌های اولیه",
        "grant-viewdeleted": "مشاهدهٔ پرونده و صفحات حذف شده",
        "grant-viewmywatchlist": "مشاهدۀ فهرست پیگیری‌هایتان",
+       "grant-viewrestrictedlogs": "دیدن سیاه‌های محدود شده",
        "newuserlogpage": "سیاههٔ ایجاد کاربر",
        "newuserlogpagetext": "این سیاهه‌ای از نام‌های کاربری تازه‌ساخته‌شده است.",
        "rightslog": "سیاههٔ اختیارات کاربر",
        "file-thumbnail-no": "نام پرونده با <strong>$1</strong> آغاز می‌شود.\nبه نظر می‌رسد که این پرونده، یک تصویر ''بندانگشتی'' ''(thumbnail)'' از تصویر بزرگتر اصلی باشد.\nاگر تصویر با اندازهٔ اصلی را دارید، آن را بارگذاری کنید؛ در غیر این صورت، نام پرونده را تغییر دهید.",
        "fileexists-forbidden": "در حال حاضر، پرونده‌ای به همین نام وجود دارد، و قابل رونویسی نیست.\nاگر هم‌چنان می‌خواهید که پروندهٔ خود را بارگذاری کنید، لطفاً برگردید و نام دیگری استفاده کنید.\n[[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "در حال حاضر، پرونده‌ای با همین نام در انبارهٔ مشترک پرونده‌ها وجود دارد.\nاگر هنوز می‌خواهید پرونده خود را بار کنید، لطفاً برگردید و پروندهٔ موردنظر خود را با نام دیگری بار کنید.\n[[File:$1|thumb|center|$1]]",
+       "fileexists-no-change": "آنچه بارگذاری شده دقیقاً نسخه‌ای تکراری از نسخهٔ فعلی <strong>[[:$1]]</strong> است.",
+       "fileexists-duplicate-version": "آنچه بارگذاری شده دقیقاً نسخه‌ای تکراری از {{PLURAL:$2|یک نسخهٔ قدیمی|نسخه‌های قدیمی}} <strong>[[:$1]]</strong> است.",
        "file-exists-duplicate": "به نظر می‌رسد این پرونده نسخه‌ای تکراری از {{PLURAL:$1|پروندهٔ|پرونده‌های}} زیر باشد:",
        "file-deleted-duplicate": "یک پرونده نظیر این پرونده ([[:$1]]) قبلاً حذف شده‌است.\nشما باید تاریخچهٔ حذف آن پرونده را قبل از بارگذاری مجدد آن ببینید.",
        "file-deleted-duplicate-notitle": "یک پرونده یکسان بااین پرونده قبلاً حذف شده است و عنوان متوقف شده‌است.\nشما باید از کسی که دسترسی مشاهدهٔ پرونده متوقف شده را دارد، درخواست کنید تا شرایط را قبل از بارگذاری مجدد بررسی کند.",
        "upload-dialog-disabled": "در اين ويکی، بارگذاری پرونده‌هااز طريق اين رابط کاربری غير فعال است",
        "upload-dialog-title": "بارگذاری پرونده",
        "upload-dialog-button-cancel": "لغو",
+       "upload-dialog-button-back": "بازگشت",
        "upload-dialog-button-done": "انجام شد",
        "upload-dialog-button-save": "ذخیره",
        "upload-dialog-button-upload": "بارگذاری",
        "filerevert-submit": "برو",
        "filerevert-success": "<strong>[[Media:$1|$1]]</strong> به [$4 نسخهٔ مورخ $2 ساعت $3] واگردانده شد.",
        "filerevert-badversion": "نسخهٔ قدیمی‌تری از این پرونده وجود نداشت.",
+       "filerevert-identical": "نسخهٔ فعلی پرونده با نسخه‌ای که انتخاب کردید یکسان است.",
        "filedelete": "حذف $1",
        "filedelete-legend": "حذف پرونده",
        "filedelete-intro": "شما در حال حذف کردن پروندهٔ '''[[Media:$1|$1]]''' به همراه تمام تاریخچه‌اش هستید.",
        "apisandbox-results-fixtoken-fail": "خطا در دریافت توکن \"$1\"",
        "apisandbox-alert-page": "بخش‌ها در این صفحه معتبر نیستند.",
        "apisandbox-alert-field": "مقدار این بخش معتبر نیست.",
+       "apisandbox-continue": "ادامه",
+       "apisandbox-continue-clear": "پاک‌کردن",
+       "apisandbox-continue-help": "{{int:apisandbox-continue}} آخرین درخواست را [https://www.mediawiki.org/wiki/API:Query#Continuing_queries ادامه خواهد داد]؛ {{int:apisandbox-continue-clear}} پارامترهای مرتبط به ادامه دادن را پاک خواهد کرد.",
+       "apisandbox-param-limit": "برای استفاده از یک حداکثر، <kbd>max</kbd> را وارد کنید.",
+       "apisandbox-multivalue-all-namespaces": "$1 (تمام فضاهای نام)",
+       "apisandbox-multivalue-all-values": "$1 (تمام مقادیر)",
        "booksources": "منابع کتاب",
        "booksources-search-legend": "جستجوی منابع کتاب",
        "booksources-isbn": "شابک:",
        "booksources-search": "جستجو",
        "booksources-text": "در زیر فهرستی از پیوندها به وبگاه‌های دیگر آمده‌است که کتاب‌های نو و دست دوم می‌فروشند، و همچنین ممکن است اطلاعات بیشتری راجع به کتاب مورد نظر شما داشته باشند:",
        "booksources-invalid-isbn": "شابک داده شده مجاز به نظر نمی‌رسد؛ از جهت اشکالات هنگام کپی کردن از منبع اصلی بررسی کنید.",
+       "magiclink-tracking-rfc": "صفحه‌های حاوی پیوند جادویی آراف‌سی",
+       "magiclink-tracking-rfc-desc": "این صفحه حاوی پیوندهای جادویی آراف‌سی است. برای چگونگی مهاجرت [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] را ببینید.",
+       "magiclink-tracking-pmid": "صفحه‌های حاوی پیوند جادویی پی‌ام‌آی‌دی",
+       "magiclink-tracking-pmid-desc": "این صفحه حاوی پیوندهای جادویی پی‌ام‌آی‌دی است. برای چگونگی مهاجرت [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] را ببینید.",
+       "magiclink-tracking-isbn": "صفحه‌های حاوی پیوند جادویی آی‌اس‌بی‌ان",
+       "magiclink-tracking-isbn-desc": "این صفحه حاوی پیوندهای جادویی آی‌اس‌بی‌ان است. برای چگونگی مهاجرت [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] را ببینید.",
        "specialloguserlabel": "مجری:",
        "speciallogtitlelabel": "هدف (عنوان یا {{ns:user}}:نام کاربر برای کاربر):",
        "log": "سیاهه‌ها",
        "activeusers-intro": "در زیر فهرستی از کاربرانی را می‌بینید که در $1 {{PLURAL:$1|روز|روز}} گذشته فعالیتی داشته‌اند.",
        "activeusers-count": "$1 {{PLURAL:$1|فعالیت|فعالیت}} در {{PLURAL:$3|روز|$3 روز}} اخیر",
        "activeusers-from": "نمایش کاربران با آغاز از:",
-       "activeusers-hidebots": "نهفتن ربات‌ها",
-       "activeusers-hidesysops": "نهفتن مدیران",
+       "activeusers-groups": "نمایش کاربران متعلق به گروه:",
+       "activeusers-excludegroups": "در نظر نگرفتن کاربران متعلق به گروه:",
        "activeusers-noresult": "کاربری پیدا نشد.",
        "activeusers-submit": "نمایش کاربران فعال",
        "listgrouprights": "اختیارات گروه‌های کاربری",
        "modifiedarticleprotection": "وضعیت محافظت «[[$1]]» را تغییر داد",
        "unprotectedarticle": "صفحهٔ «[[$1]]» را از محافظت بیرون آورد",
        "movedarticleprotection": "تنظیمات محافظت را از «[[$2]]» به «[[$1]]» منتقل کرد",
+       "protectedarticle-comment": "«[[$1]]» را {{GENDER:$2|محافظت کرد}}",
+       "modifiedarticleprotection-comment": "سطح محاظفت «[[$1]]» را {{GENDER:$2|تغییر داد}}",
+       "unprotectedarticle-comment": "«[[$1]]» را از محافظت {{GENDER:$2|در آورد}}",
        "protect-title": "تغییر وضعیت محافظت «$1»",
        "protect-title-notallowed": "مشاهده سطح حفاظت  \" $1 \"",
        "prot_1movedto2": "[[$1]] به [[$2]] منتقل شد",
        "movelogpagetext": "در زیر فهرستی از انتقال صفحات آمده‌است.",
        "movesubpage": "{{PLURAL:$1|زیرصفحه|زیرصفحه‌ها}}",
        "movesubpagetext": "این صفحه $1 زیرصفحه دارد که در زیر نمایش {{PLURAL:$1|یافته‌است|یافته‌اند}}.",
+       "movesubpagetalktext": "صفحهٔ بحث مربوط دارای $1 زیرصفحه است که در زیر نمایش {{PLURAL:$1|یافته‌است|یافته‌اند}}.",
        "movenosubpage": "این صفحه هیچ زیرصفحه‌ای ندارد.",
        "movereason": "دلیل:",
        "revertmove": "واگردانی",
        "importlogpagetext": "درون‌ریزی صفحات به همراه تاریخچهٔ ویرایش آن‌ها از ویکی‌های دیگر.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} واردشده",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} واردشده از $2",
-       "javascripttest": "آزمایش جاوا اسکریپت",
+       "javascripttest": "آزمایش جاوااسکریپت",
        "javascripttest-pagetext-unknownaction": "تابع ناشناختهٔ \"$1\".",
        "javascripttest-qunit-intro": "[$1 مستندات آزمایش] را در mediawiki.org ببینید.",
        "tooltip-pt-userpage": "صفحهٔ {{GENDER:|کاربری شما}}",
        "pageinfo-article-id": "شناسهٔ صفحه",
        "pageinfo-language": "زبان محتوای صفحه",
        "pageinfo-content-model": "ساختار محتوای صفحه",
+       "pageinfo-content-model-change": "تغییر",
        "pageinfo-robot-policy": "‌فهرست‌کردن توسط ربات‌ها",
        "pageinfo-robot-index": "مجاز",
        "pageinfo-robot-noindex": "نامجاز",
        "pageinfo-category-pages": "تعداد صفحات",
        "pageinfo-category-subcats": "تعداد زیررده‌ها",
        "pageinfo-category-files": "تعداد پرونده‌ها",
+       "pageinfo-user-id": "شناسه کاربر",
        "markaspatrolleddiff": "برچسب گشت بزن",
        "markaspatrolledtext": "به این صفحه برچسب گشت بزن",
        "markaspatrolledtext-file": "انتخاب این نسخهٔ پرونده به عنوان گشت خورده",
        "patrol-log-header": "این سیاهه‌ای از ویرایش‌های گشت‌خورده است.",
        "log-show-hide-patrol": "$1 سیاههٔ گشت‌زنی",
        "log-show-hide-tag": "$1 سیاهه برچسب",
+       "confirm-markpatrolled-button": "تأیید",
+       "confirm-markpatrolled-top": "نسخهٔ $3 از $2 علامت گشت بخورد؟",
        "deletedrevision": "$1 نسخهٔ حذف شدهٔ قدیمی",
        "filedeleteerror-short": "خطا در حذف پرونده: $1",
        "filedeleteerror-long": "در زمان حذف پرونده خطا رخ داد:\n\n$1",
        "newimages-showbots": "نمایش بارگذاری‌ها توسط ربات‌ها",
        "newimages-hidepatrolled": "مخفی کردن بارگذاری گشت‌زن‌ها",
        "noimages": "چیزی برای دیدن نیست.",
+       "gallery-slideshow-toggle": "فعال یا غیرفعال کردن تصاویر بندانگشتی",
        "ilsubmit": "جستجو",
        "bydate": "از روی تاریخ",
        "sp-newimages-showfrom": "نشان‌دادن تصویرهای جدید از $2، $1 به بعد",
        "tag-filter": "پالایش [[Special:Tags|برچسب‌ها]]:",
        "tag-filter-submit": "پالایه",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|برچسب|برچسب‌ها}}]]: $2)",
+       "tag-mw-contentmodelchange": "تغییر مدل محتوا",
+       "tag-mw-contentmodelchange-description": "ویرایش‌هایی که [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel مدل محتوای صفحه را تغییر می‌دهند]",
        "tags-title": "برچسب‌ها",
        "tags-intro": "این صفحه فهرستی‌است از برچسب‌هایی که نرم‌افزار با آن‌ها ویرایش‌ها را علامت‌گذری می‌کند، به همراه معانی آن‌ها.",
        "tags-tag": "نام برچسب",
        "tags-actions-header": "فعالیت‌ها",
        "tags-active-yes": "بله",
        "tags-active-no": "خیر",
-       "tags-source-extension": "تعرÛ\8cÙ\81â\80\8cشدÙ\87 Ø¨Ø± Ù¾Ø§Û\8cÙ\87 Ø§Ù\81زÙ\88Ù\86Ù\87",
+       "tags-source-extension": "تعرÛ\8cÙ\81â\80\8cشدÙ\87 ØªÙ\88سط Ù\86رÙ\85â\80\8cاÙ\81زار",
        "tags-source-manual": "اعمال شده به صورت دستی توسط ربات‌ها یا کاربرها",
        "tags-source-none": "دیگر استفاده نمی‌شود",
        "tags-edit": "ویرایش",
        "tags-delete": "حذف",
        "tags-activate": "فعال‌سازی",
-       "tags-deactivate": "غیرفعال کردن/إکار کةتن",
+       "tags-deactivate": "غیرفعال کردن",
        "tags-hitcount": "$1 {{PLURAL:$1|تغییر|تغییر}}",
        "tags-manage-no-permission": "شما اجازه مدیریت تغییر تگ‌ها را ندارید.",
-       "tags-manage-blocked": "امکان تغییر برچسب‌ها را در زمان بسته‌بودن ندارید",
+       "tags-manage-blocked": "امکان تغییر برچسب‌ها را در زمان بسته‌بودن {{GENDER:$1|ندارید}}",
        "tags-create-heading": "ایجاد یک برچسب جدید",
        "tags-create-explanation": "به طور پیش‌فرض، تگ‌های تازه ایجاد شده برای استفاده کاربران و ربات‌ها در دسترس قرار می‌گیرند.",
        "tags-create-tag-name": "نام برچسب:",
        "tags-deactivate-not-allowed": "غیرفعال‌سازی تگ «$1» ممکن نیست.",
        "tags-deactivate-submit": "غیرفعال‌سازی",
        "tags-apply-no-permission": "دسترسی برای تغییر برچسب تغییراتتان را ندارید.",
-       "tags-apply-blocked": "در زمان بسته‌بودن امکان اعمال تغییراتتان بر روی برچسب‌ها را ندارید.",
+       "tags-apply-blocked": "در زمان بسته‌بودن امکان اعمال تغییراتتان بر روی برچسب‌ها را {{GENDER:$1|ندارید}}.",
        "tags-apply-not-allowed-one": "اجازهٔ تائید برچسب «$1» به صورت دستی وجود ندارد.",
        "tags-apply-not-allowed-multi": "اجازهٔ تائید {{PLURAL:$2|برچسب|برچسب}} به صورت دستی وجود ندارد:$1",
        "tags-update-no-permission": "شما اجازهٔ افزودن یا حذف برچسب از خود نسخه یا سیاهه را ندارید.",
-       "tags-update-blocked": "در زمان بسته بودن امکان حذف برچسب‌ها را ندارید.",
+       "tags-update-blocked": "در زمان بسته بودن امکان حذف برچسب‌ها را {{GENDER:$1|ندارید}}.",
        "tags-update-add-not-allowed-one": "اجازهٔ افزودن برچسب «$1» به صورت دستی وجود ندارد.",
        "tags-update-add-not-allowed-multi": "اجازهٔ افزودن {{PLURAL:$2|برچسب|برچسب}} به صورت دستی وجود ندارد:$1",
        "tags-update-remove-not-allowed-one": "اجازهٔ حذف برچسب «$1» به صورت دستی وجود ندارد.",
        "htmlform-cloner-create": "افزودن بیشتر",
        "htmlform-cloner-delete": "حذف",
        "htmlform-cloner-required": "حداقل یک مقدار مورد نیاز است.",
+       "htmlform-date-placeholder": "YYYY-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "YYYY-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "مقداری وارد کردید یک تاریخ معتبر نیست. لطفاً از قالب سال چهاررقمی، ماه دورقمی و روز دورقمی به شکل YYYY-MM-DD استفاده کنید.",
+       "htmlform-time-invalid": "مقداری وارد کردید یک زمان معتبر نیست. لطفاً از قالب ساعت دورقمی، دقیقه دورقمی و ثانیه دورقمی به شکل HH:MM:SS استفاده کنید.",
+       "htmlform-datetime-invalid": "مقداری وارد کردید یک تاریخ و ساعت معتبر نیست. لطفاً از قالب سال چهاررقمی، ماه دورقمی و روز دورقمی، ساعت دورقمی، دقیقه دورقمی و ثانیه دورقمی به شکل YYYY-MM-DD HH:MM:SS استفاده کنید.",
+       "htmlform-date-toolow": "مقداری که مشخص کردید پیش از زودترین تاریخ مجاز $1 است.",
+       "htmlform-date-toohigh": "مقداری که مشخص کردید پس از دیرترین تاریخ مجاز $1 است.",
+       "htmlform-time-toolow": "مقداری که مشخص کردید پیش از زودترین ساعت مجاز $1 است.",
+       "htmlform-time-toohigh": "مقداری که مشخص کردید پس از دیرترین ساعت مجاز $1 است.",
+       "htmlform-datetime-toolow": "مقداری که مشخص کردید پیش از زودترین تاریخ و ساعت مجاز $1 است.",
+       "htmlform-datetime-toohigh": "مقداری که مشخص کردید پس از دیرترین تاریخ و ساعت مجاز $1 است.",
        "htmlform-title-badnamespace": "[[:$1]] در فضای نام \"{{ns:$2}}\"  موجود نیست.",
        "htmlform-title-not-creatable": "\"$1\" عنوان قابل ایجاد نیست",
        "htmlform-title-not-exists": "$1 وجود ندارد.",
        "htmlform-user-not-exists": "<strong>$1</strong> وجود ندارد.",
        "htmlform-user-not-valid": "حساب کاربری <strong>$1</strong> معتبر نیست.",
        "logentry-delete-delete": "$1 صفحهٔ $3 را {{GENDER:$2|حذف کرد}}",
+       "logentry-delete-delete_redir": "$1 تغییرمسیر $3 را با رونویسی {{GENDER:$2|حذف کرد}}",
        "logentry-delete-restore": "$1 صفحهٔ $3 را {{GENDER:$2|احیا کرد}}",
        "logentry-delete-event": "$1 پیدایی {{PLURAL:$5|یک مورد سیاهه|$5 مورد سیاهه}} را در $3 {{GENDER:$2|تغییر داد}}: $4",
        "logentry-delete-revision": "$1 پیدایی {{PLURAL:$5|یک نسخه|$5 نسخه}} صفحه $3 را {{GENDER:$2|تغییر داد}}: $4",
        "feedback-thanks": "سپاس! بازخورد شما در صفحهٔ «[$1 $2]» ثبت شد.",
        "feedback-thanks-title": "با تشکر!",
        "feedback-useragent": "رابط کاربر:",
-       "searchsuggest-search": "جستجو",
+       "searchsuggest-search": "جستجو در {{SITENAME}}",
        "searchsuggest-containing": "صفحه‌های دربردارنده...",
        "api-error-autoblocked": "نشانی آی‌پی شما به صورت خودکار بسته شده‌است، چون توسط یک کاربر بسته‌شده استفاده می‌شد.",
        "api-error-badaccess-groups": "شما اجازهٔ بارگذاری پرونده‌ها را در این ویکی ندارید.",
        "expand_templates_generate_xml": "نمایش درخت تجزیهٔ XML",
        "expand_templates_generate_rawhtml": "نمایش اچ‌تی‌ام‌ال خام",
        "expand_templates_preview": "پیش‌نمایش",
-       "expand_templates_preview_fail_html": "<em>زÛ\8cرا {{SITENAME}} ØªØ§ Ø¨Ù\87 HTML Ø®Ø§Ù\85 Ù\81عاÙ\84 Ù\88 Û\8cÚ© Ø¯Ø³Øª Ø±Ù\81تÙ\86 Ø§Ø·Ù\84اعات Ù\86شست Ù\88جÙ\88د Ø¯Ø§Ø±Ø¯Ø\8c Ù¾Û\8cØ´ Ù\86Ù\85اÛ\8cØ´ Ø¨Ù\87 Ø¹Ù\86Ù\88اÙ\86 Û\8cÚ© Ø§Ù\82داÙ\85 Ø§Ø­ØªÛ\8cاطÛ\8c Ø¯Ø± Ø¨Ø±Ø§Ø¨Ø± Ø­Ù\85Ù\84ات Ø¬Ø§Ù\88ا Ø§Ø³Ú©Ø±Û\8cپت Ù¾Ù\86Ù\87اÙ\86 Ø§Ø³Øª.</em>\n\n<strong>اگر Ø§Û\8cÙ\86 ØªÙ\84اش Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ù\85شرÙ\88ع Ø§Ø³ØªØ\8c Ù\84Ø·Ù\81ا Ø¯Ù\88بارÙ\87 Ø³Ø¹Û\8c Ú©Ù\86Û\8cد. Ø§Ú¯Ø± Ù\87Ù\86Ù\88ز Ú©Ø§Ø± Ù\86Ù\85Û\8c Ú©Ù\86د، سعی کنید [[Special:UserLogout|خروج از سیستم]] را کلیک نموده و دوباره وارد شوید، و از این‌ که مرورگر شما اجازه دریافت کوکی از این وب‌گاه را می‌دهد اطمینان حاصل کنید.",
-       "expand_templates_preview_fail_html_anon": "<em>زÛ\8cرا {{SITENAME}} ØªØ§ Ø¨Ù\87 HTML Ø®Ø§Ù\85 Ù\81عاÙ\84 Ù\88 Û\8cÚ© Ø¯Ø³Øª Ø±Ù\81تÙ\86 Ø§Ø·Ù\84اعات Ù\86شست Ù\88جÙ\88د Ø¯Ø§Ø±Ø¯Ø\8c Ù¾Û\8cØ´ Ù\86Ù\85اÛ\8cØ´ Ø¨Ù\87 Ø¹Ù\86Ù\88اÙ\86 Û\8cÚ© Ø§Ù\82داÙ\85 Ø§Ø­ØªÛ\8cاطÛ\8c Ø¯Ø± Ø¨Ø±Ø§Ø¨Ø± Ø­Ù\85Ù\84ات Ø¬Ø§Ù\88ا Ø§Ø³Ú©Ø±Û\8cپت Ù¾Ù\86Ù\87اÙ\86 Ø§Ø³Øª.</em>\n\n<strong>اگر Ø§Û\8cÙ\86 ØªÙ\84اش Ù¾Û\8cØ´Ù\86Ù\85اÛ\8cØ´ Ù\85شرÙ\88ع Ø§Ø³ØªØ\8c Ù\84Ø·Ù\81ا Ø¯Ù\88بارÙ\87 Ø³Ø¹Û\8c Ú©Ù\86Û\8cد. Ø§Ú¯Ø± Ù\87Ù\86Ù\88ز Ú©Ø§Ø± Ù\86Ù\85Û\8c Ú©Ù\86دØ\8c Ø³Ø¹Û\8c Ú©Ù\86Û\8cد [[Special:UserLogout|خرÙ\88ج Ø§Ø² Ø³Û\8cستÙ\85]] Ø±Ø§ Ú©Ù\84Û\8cÚ© Ù\86Ù\85Ù\88دÙ\87 Ù\88 Ø¯Ù\88بارÙ\87 Ù\88ارد Ø´Ù\88Û\8cد.",
+       "expand_templates_preview_fail_html": "<em>بÙ\87 Ø¯Ù\84Û\8cÙ\84 Ø§Û\8cÙ\86 Ú©Ù\87 Ø¯Ø± {{SITENAME}} Ø§Ú\86â\80\8cتÛ\8câ\80\8cاÙ\85â\80\8cاÙ\84 Ø®Ø§Ù\85 Ù\81عاÙ\84 Ø§Ø³Øª Ù\88 Ø§Ø·Ù\84اعات Ù\86شست Ú©Ø§Ø±Ø¨Ø±Û\8c Ø§Ø² Ø¯Ø³Øª Ø±Ù\81تØ\8c Ù¾Û\8cØ´ Ù\86Ù\85اÛ\8cØ´ Ø¨Ù\87 Ø¹Ù\86Ù\88اÙ\86 Û\8cÚ© Ø§Ù\82داÙ\85 Ø§Ø­ØªÛ\8cاطÛ\8c Ø¯Ø± Ø¨Ø±Ø§Ø¨Ø± Ø­Ù\85Ù\84ات Ø¬Ø§Ù\88ااسکرÛ\8cپت Ù¾Ù\86Ù\87اÙ\86 Ø§Ø³Øª.</em>\n\n<strong>اگر Ø§Û\8cÙ\86 ØªÙ\84اش Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ù\85شرÙ\88ع Ø§Ø³ØªØ\8c Ù\84Ø·Ù\81اÙ\8b Ø¯Ù\88بارÙ\87 Ø³Ø¹Û\8c Ú©Ù\86Û\8cد.</strong>\nاگر Ù\87Ù\86Ù\88ز Ú©Ø§Ø± Ù\86کرد، سعی کنید [[Special:UserLogout|خروج از سیستم]] را کلیک نموده و دوباره وارد شوید، و از این‌ که مرورگر شما اجازه دریافت کوکی از این وب‌گاه را می‌دهد اطمینان حاصل کنید.",
+       "expand_templates_preview_fail_html_anon": "<em>بÙ\87 Ø¯Ù\84Û\8cÙ\84 Ø§Û\8cÙ\86 Ú©Ù\87 Ø¯Ø± {{SITENAME}} Ø§Ú\86â\80\8cتÛ\8câ\80\8cاÙ\85â\80\8cاÙ\84 Ø®Ø§Ù\85 Ù\81عاÙ\84 Ø§Ø³Øª Ù\88 Ø§Ø·Ù\84اعات Ù\86شست Ú©Ø§Ø±Ø¨Ø±Û\8c Ø§Ø² Ø¯Ø³Øª Ø±Ù\81تØ\8c Ù¾Û\8cØ´ Ù\86Ù\85اÛ\8cØ´ Ø¨Ù\87 Ø¹Ù\86Ù\88اÙ\86 Û\8cÚ© Ø§Ù\82داÙ\85 Ø§Ø­ØªÛ\8cاطÛ\8c Ø¯Ø± Ø¨Ø±Ø§Ø¨Ø± Ø­Ù\85Ù\84ات Ø¬Ø§Ù\88ااسکرÛ\8cپت Ù¾Ù\86Ù\87اÙ\86 Ø§Ø³Øª.</em>\n\n<strong>اگر Ø§Û\8cÙ\86 ØªÙ\84اش Ù¾Û\8cØ´â\80\8cÙ\86Ù\85اÛ\8cØ´ Ù\85شرÙ\88ع Ø§Ø³ØªØ\8c Ù\84Ø·Ù\81ا [[Special:UserLogin|بÙ\87 Ø³Ø§Ù\85اÙ\86Ù\87 Ù\88ارد Ø´Ù\88Û\8cد]] Ù\88 Ø¯Ù\88بارÙ\87 ØªÙ\84اش Ú©Ù\86Û\8cد.</strong>",
        "expand_templates_input_missing": "شما نیازمندید که حداقل متن‌هایی را برای وارد کردن تهیه کنید.",
        "pagelanguage": "تغییر زبان صفحه",
        "pagelang-name": "صفحه",
        "special-characters-title-emdash": "خط فاسله کشیده",
        "special-characters-title-minus": "علامت منفی",
        "mw-widgets-dateinput-no-date": "هیچ داده‌ای انتخاب نشده",
+       "mw-widgets-mediasearch-input-placeholder": "جستجو برای رسانه‌ها",
+       "mw-widgets-mediasearch-noresults": "هیچ نتیجه‌ای پیدا نشد.",
        "mw-widgets-titleinput-description-new-page": "این صفحه هنوز وجود ندارد",
        "mw-widgets-titleinput-description-redirect": "تغییر مسیر به $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "در حال افزودن رده ...",
        "sessionmanager-tie": "نمی‌توان چندین نوع درخواست هویت‌سنجی را ترکیب کرد: $1.",
        "sessionprovider-generic": "$1 فصل",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "فصل‌های کوکی‌محور",
        "log-action-filter-contentmodel-change": "تغییر نوع محتوا",
        "log-action-filter-contentmodel-new": "ایجاد صفحه با contentmodel غیر استاندارد",
        "log-action-filter-delete-delete": "حذف صفحه",
+       "log-action-filter-delete-delete_redir": "رونویسی تغییرمسیر",
        "log-action-filter-delete-restore": "احیای صفحه",
        "log-action-filter-delete-event": "حذف سیاهه",
        "log-action-filter-delete-revision": "حذف ویرایش",
        "unlinkaccounts-success": "پیوند کاربری بدون پیوند شد.",
        "authenticationdatachange-ignored": "به تغيير اطلاعات احراز هويت پرداخته نشد. آیا ممکن است که هيچ مهيا کننده‌ای برای اين کار تنظيم نشده باشد؟",
        "userjsispublic": "لطفاً توجه کنید: زیرصفحه‌های جاوااسکریپت نباید حاوی اطلاعات محرمانه باشند چون توسط دیگران قابل مشاهده هستند.",
-       "usercssispublic": "لطفاً توجه کنید: زیرصفحه‌های سی‌اس‌اس نباید حاوی اطلاعات محرمانه باشند چون توسط دیگران قابل مشاهده هستند."
+       "usercssispublic": "لطفاً توجه کنید: زیرصفحه‌های سی‌اس‌اس نباید حاوی اطلاعات محرمانه باشند چون توسط دیگران قابل مشاهده هستند.",
+       "restrictionsfield-badip": "نشانی یا بازهٔ آی‌پی نامعتبر: $1",
+       "restrictionsfield-label": "بازه‌های آی‌پی مجاز:",
+       "restrictionsfield-help": "یک نشانی آی‌پی یا بازهٔ سی‌آی‌دی‌ار در هر خط وارد کنید. برای فعال کردن همه‌چیز، این مقدار را استفاده کنید: <code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 3a8baf3..1a5a9a9 100644 (file)
        "views": "Näkymät",
        "toolbox": "Työkalut",
        "tool-link-userrights": "Muokkaa {{GENDER:$1|käyttäjän}} ryhmiä",
+       "tool-link-userrights-readonly": "Katso {{GENDER:$1|käyttäjän}} ryhmiä",
        "tool-link-emailuser": "Lähetä sähköpostia tälle {{GENDER:$1|käyttäjälle}}",
        "userpage": "Näytä käyttäjäsivu",
        "projectpage": "Näytä projektisivu",
        "passwordreset-emaildisabled": "Sähköpostitoiminnot on poistettu käytöstä tässä wikissä.",
        "passwordreset-username": "Käyttäjätunnus:",
        "passwordreset-domain": "Verkkotunnus:",
-       "passwordreset-capture": "Näytä lähetettävä sähköpostiviesti?",
-       "passwordreset-capture-help": "Jos valitset tämän, sähköposti (tilapäisellä salasanalla) näytetään sinulle sekä lähetetään käyttäjälle.",
        "passwordreset-email": "Sähköpostiosoite:",
        "passwordreset-emailtitle": "Tunnuksen tiedot {{GRAMMAR:inessive|{{SITENAME}}}}",
        "passwordreset-emailtext-ip": "Joku (todennäköisesti sinä, IP-osoitteesta $1) pyysi salasanasi\nvaihtamista sivustolla {{SITENAME}} ($4). {{PLURAL:$3|Seuraava käyttäjätunnus on|Seuraavat käyttäjätunnukset ovat}}\nyhdistettynä tähän sähköpostiosoitteeseen:\n\n$2\n\n{{PLURAL:$3|Tämä väliaikainen salasana vanhentuu|Nämä väliaikaiset salasanat vanhentuvat}} {{PLURAL:$5|yhden päivän|$5 päivän}} kuluttua.\nKirjaudu sisään nyt ja valitse uusi salasana heti. Jos joku toinen teki tämän pyynnön \ntai jos muistitkin vanhan salasanasi etkä halua enää muuttaa sitä,\nvoit jättää tämän viestin huomiotta ja jatkaa vanhan salasanasi käyttämistä.",
        "passwordreset-emailelement": "Käyttäjätunnus: \n$1\n\nVäliaikainen salasana: \n$2",
        "passwordreset-emailsentemail": "Jos tämä on sinun tunnuksellesi rekisteröity sähköpostiosoite, salasanan uudistamisesta kertova viesti lähetetään.",
        "passwordreset-emailsentusername": "Jos on olemassa vastaava rekisteröity sähköpostiosoite, salasanan uudistamisesta kertova viesti lähetetään.",
-       "passwordreset-emailsent-capture2": "Salasananpalautus{{PLURAL:$1|sähköposti|sähköpostit}} on lähetetty. {{PLURAL:$1|Käyttäjä ja salasana|Luettelo käyttäjistä ja salasanoista}} näytetään alapuolella.",
-       "passwordreset-emailerror-capture2": "Sähköpostin lähettäminen {{GENDER:$2|käyttäjälle}} epäonnistui: $1 {{PLURAL:$3|Käyttäjänimi ja salasana|Luettelo käyttäjänimistä ja salasanoista}} näytetään alla.",
        "passwordreset-ignored": "Salasanan palauttamista ei käsitelty. Ehkä tarjoajaa ei ollut määritetty?",
-       "passwordreset-invalideamil": "Virheellinen sähköpostiosoite",
+       "passwordreset-invalidemail": "Virheellinen sähköpostiosoite",
        "passwordreset-nodata": "Käyttäjätunnusta ja salasanaa ei annettu",
        "changeemail": "Muuta tai poista sähköpostiosoite",
        "changeemail-header": "Täydennä tämä lomake, jolla voit muuttaa sähköpostiosoitettasi. Jos haluat poistaa sähköpostiosoitteesi kokonaan tunnuksesi yhteydestä, älä kirjoita uudeksi osoitteeksi mitään vaan jätä se tyhjäksi.",
        "prefswarning-warning": "Olet tehnyt asetuksiisi muutoksia, joita ei ole vielä tallennettu.\nJos poistut sivulta klikkaamatta \"$1\", asetuksiasi ei päivitetä.",
        "prefs-tabs-navigation-hint": "Vihje: Voit käyttää vasenta ja oikeata nuolinäppäintä liikkumiseen välilehtien välillä.",
        "userrights": "Käyttöoikeuksien hallinta",
-       "userrights-lookup-user": "Hallinnoi käyttäjän ryhmiä",
+       "userrights-lookup-user": "Valitse käyttäjä",
        "userrights-user-editname": "Käyttäjätunnus:",
-       "editusergroup": "Muokkaa {{GENDER:$1|käyttäjän}} ryhmiä",
+       "editusergroup": "Lataa käyttäjäryhmät",
        "editinguser": "Muutetaan {{GENDER:$1|käyttäjän}} <strong>[[User:$1|$1]]</strong> $2 oikeuksia",
        "userrights-editusergroup": "Muuta käyttäjän ryhmiä",
        "saveusergroups": "Tallenna {{GENDER:$1|käyttäjän}} ryhmät",
        "userrights-reason": "Syy:",
        "userrights-no-interwiki": "Sinulla ei ole oikeutta muokata käyttöoikeuksia muissa wikeissä.",
        "userrights-nodatabase": "Tietokantaa $1 ei ole tai se ei ole paikallinen.",
-       "userrights-nologin": "Sinun täytyy [[Special:UserLogin|kirjautua sisään]] ylläpitäjän tunnuksella, jotta voisit muuttaa käyttöoikeuksia.",
-       "userrights-notallowed": "Sinulla ei ole oikeutta lisätä tai poistaa käyttäjien oikeuksia.",
        "userrights-changeable-col": "Ryhmät, joita voit muuttaa",
        "userrights-unchangeable-col": "Ryhmät, joita et voi muuttaa",
        "userrights-conflict": "Päällekkäinen käyttöoikeuksien muutos! Tarkista tekemäsi muutokset ja vahvista ne.",
-       "userrights-removed-self": "Poistit omat oikeutesi. Tämän vuoksi sinulla ei enää ole oikeutta päästä tälle sivulle.",
        "group": "Ryhmä",
        "group-user": "käyttäjät",
        "group-autoconfirmed": "automaattisesti hyväksytyt käyttäjät",
        "right-siteadmin": "Lukita tietokanta",
        "right-override-export-depth": "Viedä sivuja sisältäen viitatut sivut viiden syvyydellä",
        "right-sendemail": "Lähettää sähköpostia muille käyttäjille",
-       "right-passwordreset": "Tarkastella salasanan alustusviestejä",
        "right-managechangetags": "Luoda ja ottaa käyttöön [[Special:Tags|merkkauksia]]",
        "right-applychangetags": "Asettaa [[Special:Tags|merkkauksia]] omien muutosten yhteyteen",
        "right-changetags": "Lisätä ja poistaa satunnaisia [[Special:Tags|merkkauksia]] yksittäisissä sivuversioissa tai lokimerkinnöissä",
        "apisandbox-alert-field": "Tässä kentässä oleva arvo ei ole kelvollinen.",
        "apisandbox-continue": "Jatka",
        "apisandbox-continue-clear": "Tyhjennä",
+       "apisandbox-multivalue-all-namespaces": "$1 (Kaikki nimiavaruudet)",
+       "apisandbox-multivalue-all-values": "$1 (Kaikki arvot)",
        "booksources": "Kirjalähteet",
        "booksources-search-legend": "Etsi kirjalähteitä",
        "booksources-isbn": "ISBN",
        "changecontentmodel-legend": "Muuta sisältömallia",
        "changecontentmodel-title-label": "Sivun otsikko",
        "changecontentmodel-model-label": "Uusi sisältömalli",
-       "changecontentmodel-reason-label": "Syy:",
+       "changecontentmodel-reason-label": "Syy",
        "changecontentmodel-submit": "Tee muutos",
        "changecontentmodel-success-title": "Sisältömallia on muutettu",
        "changecontentmodel-success-text": "Sisältötyyppiä kohteessa [[:$1]] on muutettu.",
        "htmlform-user-not-exists": "Käyttäjää <strong>$1</strong> ei ole olemassa.",
        "htmlform-user-not-valid": "<strong>$1</strong> ei ole kelvollinen käyttäjänimi.",
        "logentry-delete-delete": "$1 {{GENDER:$2|poisti}} sivun $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|poisti}} ohjaussivun $3 korvaamalla",
        "logentry-delete-restore": "$1 {{GENDER:$2|palautti}} sivun $3",
        "logentry-delete-event": "$1 {{GENDER:$2|muutti}} {{PLURAL:$5|lokitapahtuman|$5 lokitapahtuman}} näkyvyyttä kohteessa $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|muutti}} {{PLURAL:$5|version|$5 version}} näkyvyyttä sivulla $3: $4",
        "mw-widgets-dateinput-placeholder-month": "VVVV-KK",
        "mw-widgets-titleinput-description-new-page": "sivua ei ole olemassa vielä",
        "mw-widgets-titleinput-description-redirect": "ohjaus kohteeseen $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Lisää luokka...",
        "sessionmanager-tie": "!!FYZZ!!Cannot combine multiple request authentication types: $1.",
        "sessionprovider-generic": "$1 istuntoa",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "istuntoja, joissa on evästeet käytössä",
        "unlinkaccounts-success": "Tunnuksen linkitys poistettiin.",
        "authenticationdatachange-ignored": "Varmennustietojen muutosta ei käsitelty. Ehkä palveluntarjoajaa ei määritelty?",
        "restrictionsfield-badip": "Virheellinen IP-osoite tai alue: $1",
-       "restrictionsfield-label": "Sallitut IP-alueet:",
-       "edit-error-short": "$1",
-       "edit-error-long": "Virheet:\n\n$1"
+       "restrictionsfield-label": "Sallitut IP-alueet:"
 }
index 7ae303f..1b352f2 100644 (file)
                        "Dcausse",
                        "Lucas",
                        "Mabroukb",
-                       "Pymouss"
+                       "Pymouss",
+                       "Derugon"
                ]
        },
        "tog-underline": "Soulignement des liens :",
        "index-category": "Pages indexées",
        "noindex-category": "Pages non indexées",
        "broken-file-category": "Pages avec des liens de fichiers brisés",
+       "categoryviewer-pagedlinks": "($1) ($2)",
+       "category-header-numerals": "$1–$2",
        "about": "À propos",
        "article": "Page de contenu",
        "newwindow": "(ouvre dans une nouvelle fenêtre)",
        "views": "Affichages",
        "toolbox": "Outils",
        "tool-link-userrights": "Modifier les groupes de {{GENDER:$1|l’utilisateur|l’utilisatrice}}",
+       "tool-link-userrights-readonly": "Voir les {{GENDER:$1|groupes utilisateur}}",
        "tool-link-emailuser": "Envoyer un courriel à {{GENDER:$1|l’utilisateur|l’utilisatrice}}",
        "userpage": "Voir la page utilisateur",
        "projectpage": "Voir la page du projet",
        "versionrequiredtext": "La version $1 de MediaWiki est nécessaire pour utiliser cette page.\nConsultez [[Special:Version|la page des versions]].",
        "ok": "Valider",
        "pagetitle": "$1 — {{SITENAME}}",
+       "pagetitle-view-mainpage": "{{SITENAME}}",
+       "backlinksubtitle": "← $1",
        "retrievedfrom": "Récupérée de « $1 »",
        "youhavenewmessages": "{{PLURAL:$3|Vous avez}} $1 ($2).",
        "youhavenewmessagesfromusers": "{{PLURAL:$4|Vous avez}} $1 {{PLURAL:$3|d'un autre utilisateur|de $3 autres utilisateurs}} ($2).",
        "site-atom-feed": "Flux Atom de $1",
        "page-rss-feed": "Flux RSS de « $1 »",
        "page-atom-feed": "Flux Atom de « $1 »",
+       "feed-atom": "Atom",
+       "feed-rss": "RSS",
        "red-link-title": "$1 (page inexistante)",
        "sort-descending": "Tri décroissant",
        "sort-ascending": "Tri croissant",
        "nocookiesnew": "Le compte utilisateur a été créé, mais vous n’êtes pas connecté{{GENDER:||e|(e)}}.\n{{SITENAME}} utilise des témoins (''cookies'') pour conserver la connexion mais vous les avez désactivés.\nVeuillez les activer et vous reconnecter avec le même nom et le même mot de passe.",
        "nocookieslogin": "{{SITENAME}} utilise des témoins (''cookies'') pour conserver la connexion mais vous les avez désactivés.\nVeuillez les activer et vous reconnecter.",
        "nocookiesfornew": "Le compte utilisateur n’a pas été créé, car nous n’avons pas pu identifier son origine.\nVérifiez que vous avez activé les témoins (''cookies''), rechargez la page et essayez à nouveau.",
+       "nocookiesforlogin": "{{int:nocookieslogin}}",
        "createacct-loginerror": "Le compte a bien été créé mais vous ne pouvez pas vous connecter automatiquement. Veuillez vous [[Special:UserLogin|connecter manuellement]].",
        "noname": "Vous n’avez pas saisi un nom d’utilisateur valide.",
        "loginsuccesstitle": "Connecté",
        "passwordreset-emaildisabled": "Les fonctionnalités de courriel ont été désactivées sur ce wiki.",
        "passwordreset-username": "Nom d'utilisateur :",
        "passwordreset-domain": "Domaine :",
-       "passwordreset-capture": "Voir le courriel résultant ?",
-       "passwordreset-capture-help": "Si vous cochez cette case, le courriel (avec le mot de passe temporaire) vous sera affiché en même temps qu’il sera envoyé à l’utilisateur.",
        "passwordreset-email": "Adresse de courriel :",
        "passwordreset-emailtitle": "Détails du compte sur {{SITENAME}}",
        "passwordreset-emailtext-ip": "Quelqu’un (probablement vous, depuis l’adresse IP $1) a demandé une réinitialisation de votre mot de passe pour {{SITENAME}} ($4). {{PLURAL:$3|Le compte utilisateur suivant est associé|Les comptes utilisateurs suivants sont associés}} à cette adresse de courriel :\n\n$2\n\n{{PLURAL:$3|Ce mot de passe temporaire expirera|Ces mots de passe temporaires expireront}} dans {{PLURAL:$5|un jour|$5 jours}}. \nVous devez maintenant vous connecter et choisir un nouveau mot de passe. Si cette demande ne provient pas de vous, ou si vous avez retrouvé votre mot de passe initial, et ne souhaitez plus le modifier, vous pouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.",
        "passwordreset-emailelement": "Nom d’utilisateur : \n$1\n\nMot de passe temporaire : \n$2",
        "passwordreset-emailsentemail": "Si cette adresse de courriel est associée à votre compte, alors un courriel de réinitialisation de mot de passe sera envoyé.",
        "passwordreset-emailsentusername": "S’il y a une adresse de courriel associée à ce nom d’utilisateur, alors un courriel de réinitialisation de mot de passe sera envoyé.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Le courriel de réinitialisation du mot de passe a été envoyé|Les courriels de réinitialisation du mot de passe ont été envoyés}}. {{PLURAL:$1|Le nom d’utilisateur et le mot de passe sont affichés|La liste des noms d’utilisateur et mots de passe est affichée}} ici.",
-       "passwordreset-emailerror-capture2": "L’envoi de courriel à {{GENDER:$2|l’utilisateur|l’utilisatrice}} a échoué : $1 {{PLURAL:$3|Le nom d’utilisateur et le mot de passe sont affichés|La liste des noms d’utilisateur et des mots de passe est affichée}} ici.",
        "passwordreset-nocaller": "Un appelant doit être fourni",
        "passwordreset-nosuchcaller": "L’appelant n’existe pas : $1",
        "passwordreset-ignored": "La réinitialisation du mot de passe n’a pas été gérée. Peut-être qu’aucun fournisseur n’a été configuré ?",
-       "passwordreset-invalideamil": "Adresse de messagerie non valide",
+       "passwordreset-invalidemail": "Adresse de messagerie non valide",
        "passwordreset-nodata": "Aucun nom d’utilisateur ou adresse de messagerie n’a été fourni",
        "changeemail": "Changer ou supprimer l’adresse de courriel",
        "changeemail-header": "Complétez ce formulaire pour modifier votre adresse de courriel. Si vous voulez supprimer l’association d’une adresse de courriel avec votre compte, laissez la nouvelle adresse de courriel vide lors de la soumission du formulaire.",
        "subject-preview": "Aperçu du sujet :",
        "previewerrortext": "Une erreur s’est produite lors de la tentative de prévisualisation de vos modifications.",
        "blockedtitle": "L’utilisateur est bloqué.",
-       "blockedtext": "'''Votre compte utilisateur ou votre adresse IP a été bloqué.'''\n\nLe blocage a été effectué par $1.\nLa raison invoquée est la suivante : ''$2''.\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Compte bloqué : $7.\n\nVous pouvez contacter $1 ou un autre [[{{MediaWiki:Grouppage-sysop}}|administrateur]] pour en discuter.\nVous ne pouvez utiliser la fonction « {{int:emailuser}} » que si une adresse de courriel valide est spécifiée dans vos [[Special:Preferences|préférences]] et que si cette fonctionnalité n’a pas été bloquée.\nVotre adresse IP actuelle est $3 et votre identifiant de blocage est $5.\nVeuillez préciser ces indications dans toutes les requêtes que vous ferez.",
+       "blockedtext": "<strong>Votre compte utilisateur ou votre adresse IP a été bloqué.</strong>\n\nLe blocage a été effectué par $1.\nLa raison invoquée est la suivante : <em>$2</em>.\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Compte bloqué : $7.\n\nVous pouvez contacter $1 ou un autre [[{{MediaWiki:Grouppage-sysop}}|administrateur]] pour en discuter.\nVous ne pouvez utiliser la fonction « {{int:emailuser}} » que si une adresse de courriel valide est spécifiée dans vos [[Special:Preferences|préférences]] et que si cette fonctionnalité n’a pas été bloquée.\nVotre adresse IP actuelle est $3 et votre identifiant de blocage est $5.\nVeuillez préciser ces indications dans toutes les requêtes que vous ferez.",
        "autoblockedtext": "Votre adresse IP a été bloquée automatiquement car elle a été utilisée par un autre utilisateur, lui-même bloqué par $1.\nLa raison invoquée est :\n\n:<em>$2:</em>\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Compte bloqué : $7\n\nVous pouvez contacter $1 ou l’un des autres [[{{MediaWiki:Grouppage-sysop}}|administrateurs]] pour discuter de ce blocage.\n\nNotez que vous ne pourrez utiliser la fonctionnalité d’envoi de courriel que si vous avez une adresse de courriel validée dans vos [[Special:Preferences|préférences]] et que cette fonctionnalité n’a pas été désactivée.\n\nVotre adresse IP actuelle est $3, et le numéro de blocage est $5.\nVeuillez préciser ces indications dans toutes les requêtes que vous ferez.",
        "blockednoreason": "aucune raison donnée",
        "whitelistedittext": "Vous devez vous $1 pour avoir la permission de modifier le contenu.",
        "content-model-text": "texte brut",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
+       "content-model-json": "JSON",
        "content-json-empty-object": "Objet vide",
        "content-json-empty-array": "Tableau vide",
        "deprecated-self-close-category": "Pages utilisant des balises HTML auto-fermantes non valides",
        "search-external": "Recherche externe",
        "searchdisabled": "La recherche sur {{SITENAME}} est désactivée. En attendant la réactivation, vous pouvez effectuer une recherche via Google. Attention, leur indexation du contenu de {{SITENAME}} peut ne pas être à jour.",
        "search-error": "Une erreur s'est produite en recherchant : $1",
+       "search-warning": "Un avertissement a été signalé lors de la recherche : $1",
        "preferences": "Préférences",
        "mypreferences": "Préférences",
        "prefs-edits": "Nombre de modifications :",
        "prefswarning-warning": "Vous avez effectué des modifications dans vos préférences qui n’ont pas encore été enregistrées.\nSi vous quittez cette page sans cliquer sur « $1 », vos préférences ne seront pas mises à jour.",
        "prefs-tabs-navigation-hint": "Astuce : Vous pouvez utiliser les flèches de gauche et de droite pour naviguer entre les onglets.",
        "userrights": "Gestion des droits des utilisateurs",
-       "userrights-lookup-user": "Gestion des groupes d'utilisateurs",
+       "userrights-lookup-user": "Sélectionner un utilisateur",
        "userrights-user-editname": "Entrez un nom d'utilisateur :",
-       "editusergroup": "Modification des groupes d’{{GENDER:$1|utilisateurs}}",
+       "editusergroup": "Charger des groupes d’utilisateurs",
        "editinguser": "Modification des droits de l’{{GENDER:$1|utilisateur|utilisatrice}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Affichage des droits utilisateur de {{GENDER:$1|l’utilisateur|l’utilisatrice}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modifier les groupes de l'utilisateur",
+       "userrights-viewusergroup": "Afficher les groupes d'utilisateurs",
        "saveusergroups": "Enregistrer les groupes de l’{{GENDER:$1|utilisateur|utilisatrice}}",
        "userrights-groupsmember": "Membre de :",
        "userrights-groupsmember-auto": "Membre implicite de :",
+       "userrights-groupsmember-type": "$1",
        "userrights-groups-help": "Vous pouvez modifier les groupes auxquels appartient {{GENDER:$1|cet utilisateur|cette utilisatrice}} :\n* Une case cochée signifie que l’utilisat{{GENDER:$1|eur|rice}} se trouve dans ce groupe.\n* Une case non cochée signifie qu’{{GENDER:$1|il|elle}} ne s’y trouve pas.\n* Un astérisque (*) indique que vous ne pouvez pas retirer ce groupe une fois que vous l’avez ajouté, ou vice-versa.",
        "userrights-reason": "Motif :",
        "userrights-no-interwiki": "Vous n'avez pas la permission de modifier les droits utilisateur sur d'autres wikis.",
        "userrights-nodatabase": "La base de données « $1 » n'existe pas ou n'est pas locale.",
-       "userrights-nologin": "Vous devez vous [[Special:UserLogin|connecter]] avec un compte d'administrateur pour modifier les droits utilisateur.",
-       "userrights-notallowed": "Vous n’avez pas la permission d’ajouter ou de supprimer des droits utilisateur.",
        "userrights-changeable-col": "Les groupes que vous pouvez modifier",
        "userrights-unchangeable-col": "Les groupes que vous ne pouvez pas modifier",
+       "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Conflit de modification des droits utilisateur ! Veuillez relire et confirmer vos modifications.",
-       "userrights-removed-self": "Vous avez supprimé vos propres droits. Par conséquent, vous ne pouvez plus accéder à cette page.",
        "group": "Groupe :",
        "group-user": "Utilisateurs",
        "group-autoconfirmed": "Utilisateurs autoconfirmés",
        "right-move-rootuserpages": "Renommer la page principale d'un utilisateur",
        "right-move-categorypages": "Renommer des pages de catégorie",
        "right-movefile": "Renommer des fichiers",
-       "right-suppressredirect": "Ne pas créer de redirection depuis le titre d'origine en renommant les pages",
+       "right-suppressredirect": "Ne pas créer de redirection depuis le titre dorigine en renommant les pages",
        "right-upload": "Importer des fichiers",
        "right-reupload": "Écraser un fichier existant",
        "right-reupload-own": "Écraser un fichier que l'on a soi-même importé",
        "right-siteadmin": "Verrouiller ou déverrouiller la base de données",
        "right-override-export-depth": "Exporter les pages en incluant les pages liées jusqu'à une profondeur de 5 niveaux",
        "right-sendemail": "Envoyer un courriel aux autres utilisateurs",
-       "right-passwordreset": "Voir les courriels de réinitialisation des mots de passe",
        "right-managechangetags": "Créer et (dés)activer des [[Special:Tags|balises]]",
        "right-applychangetags": "Appliquer [[Special:Tags|les balises]] avec ses propres modifications",
        "right-changetags": "Ajouter et supprimer de façon arbitraire [[Special:Tags|des balises]] sur des révisions individuelles et des entrées de journal",
        "action-upload_by_url": "importer ce fichier à partir d'une adresse URL",
        "action-writeapi": "utiliser l‘API d'écriture",
        "action-delete": "supprimer cette page",
-       "action-deleterevision": "supprimer cette version",
-       "action-deletedhistory": "voir l’historique supprimé de cette page",
+       "action-deleterevision": "supprimer les révisions",
+       "action-deletelogentry": "supprimer les entrées de la trace",
+       "action-deletedhistory": "voir l’historique supprimé d’une page",
+       "action-deletedtext": "Afficher le texte de la révision supprimée",
        "action-browsearchive": "rechercher des pages supprimées",
-       "action-undelete": "restaurer cette page",
-       "action-suppressrevision": "visionner et rétablir cette version supprimée",
+       "action-undelete": "restaurer des pages",
+       "action-suppressrevision": "visionner et rétablir des révisions supprimées",
        "action-suppressionlog": "voir ce journal privé",
        "action-block": "bloquer en écriture cet utilisateur",
        "action-protect": "modifier les niveaux de protection pour cette page",
        "action-userrights-interwiki": "modifier les droits des utilisateurs sur d'autres wikis",
        "action-siteadmin": "verrouiller ou déverrouiller la base de données",
        "action-sendemail": "envoyer des courriels",
+       "action-editmyoptions": "modifier vos préférences",
        "action-editmywatchlist": "modifier votre liste de suivi",
        "action-viewmywatchlist": "afficher votre liste de suivi",
        "action-viewmyprivateinfo": "voir vos informations personnelles",
        "minoreditletter": "m",
        "newpageletter": "N",
        "boteditletter": "b",
+       "unpatrolledletter": "!",
        "number_of_watching_users_pageview": "[$1 utilisateur{{PLURAL:$1||s}} en train de suivre]",
        "rc_categories": "Limiter aux catégories (séparées par « | ») :",
        "rc_categories_any": "Une des sélectionnées",
+       "rc-change-size": "$1",
        "rc-change-size-new": "$1 {{PLURAL:$1|octet|octets}} après changement",
        "newsectionsummary": "/* $1 */ nouvelle section",
        "rc-enhanced-expand": "Voir les détails",
        "emptyfile": "Le fichier que vous voulez importer semble vide.\nCeci peut être dû à une erreur dans le nom du fichier.\nVeuillez vérifier que vous désirez vraiment importer ce fichier.",
        "windows-nonascii-filename": "Ce wiki ne prend pas en charge les noms de fichiers avec des caractères spéciaux.",
        "fileexists": "Un fichier existe déjà sous ce nom.\nMerci de vérifier <strong>[[:$1]]</strong> si vous n'êtes pas certain{{GENDER:||e|}} de vouloir le remplacer.\n[[$1|thumb]]",
-       "filepageexists": "La page de description pour ce fichier a déjà été créée ici <strong>[[:$1]]</strong>, mais aucun fichier n'existe actuellement sous ce nom.\nLe résumé que vous allez spécifier n'apparaîtra pas sur la page de description.\nPour que ce soit le cas, vous devrez modifier manuellement la page. \n[[$1|thumb]]",
+       "filepageexists": "La page de description pour ce fichier a déjà été créée ici <strong>[[:$1]]</strong>, mais aucun fichier n’existe actuellement sous ce nom.\nLe résumé que vous allez spécifier n’apparaîtra pas sur la page de description.\nPour que ce soit le cas, vous devrez modifier manuellement la page.\n[[$1|thumb]]",
        "fileexists-extension": "Un fichier existe avec un nom proche : [[$2|thumb]]\n* Nom du fichier à importer : <strong>[[:$1]]</strong>\n* Nom du fichier existant : <strong>[[:$2]]</strong>\nPeut-être voulez-vous utiliser un nom plus explicite ?",
        "fileexists-thumbnail-yes": "Le fichier semble être une image en taille réduite <em>(vignette)</em>. \n[[$1|thumb]]\nVeuillez vérifier le fichier <strong>[[:$1]]</strong>.\nSi le fichier vérifié est la même image avec la taille initiale, il n'y a pas besoin d'importer une version réduite.",
        "file-thumbnail-no": "Le nom du fichier commence par <strong>$1</strong>.\nIl est possible qu'il s'agisse d'une version réduite <em>(vignette)</em>.\nSi vous disposez du fichier en haute résolution, importez-le, sinon veuillez modifier son nom.",
        "uploaded-setting-event-handler-svg": "Positionner les attributs du gestionnaire d’événements n'est pas possbile, <code>&lt;$1 $2=\"$3\"&gt;</code> trouvé dans le fichier SVG téléchargé.",
        "uploaded-setting-href-svg": "L’utilisation de la balise « set » pour ajouter un attribut « href » à l’élément parent est interdite.",
        "uploaded-wrong-setting-svg": "L’utilisation de la balise « set » pour ajouter une cible distante/données/script à un attribut quelconque est interdite. <code>&lt;set to=\"$1\"&gt;</code> a été trouvé dans le fichier SVG téléchargé.",
-       "uploaded-setting-handler-svg": "Les SVG qui positionnent l’attribut « handler » avec distant/données/script sont interdits. <code>$1=\"$2\"</code> a été trouvé dans le fichier SVG téléchargé.",
+       "uploaded-setting-handler-svg": "Les SVG qui positionnent l’attribut « handler » avec distant/données/script sont bloqués. <code>$1=\"$2\"</code> a été trouvé dans le fichier SVG téléchargé.",
        "uploaded-remote-url-svg": "Les SVG qui positionnent un attribut de style avec une URL distante sont bloqués. <code>$1=\"$2\"</code> trouvé dans le fichier SVG téléchargé.",
        "uploaded-image-filter-svg": "Filtre d’image avec URL trouvé : <code>&lt;$1 $2=\"$3\"&gt;</code> dans le fichier SVG téléchargé.",
        "uploadscriptednamespace": "Ce fichier SVG contient un espace de noms '$1' non autorisé.",
        "apisandbox-continue": "Continuer",
        "apisandbox-continue-clear": "Effacer",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries continuera] la dernière requête ; {{int:apisandbox-continue-clear}} effacera les paramètres relatifs à la continuation.",
+       "apisandbox-param-limit": "Saisir <kbd>max</kbd> pour utiliser la limite maximale.",
+       "apisandbox-multivalue-all-namespaces": "$1 (tous les espaces de noms)",
+       "apisandbox-multivalue-all-values": "$1 (Toutes les valeurs)",
        "booksources": "Ouvrages de référence",
        "booksources-search-legend": "Rechercher parmi des ouvrages de référence",
        "booksources-isbn": "ISBN :",
        "activeusers-count": "$1 {{PLURAL:$1|action|actions}} lors {{PLURAL:$3|du dernier jour|des $3 derniers jours}}",
        "activeusers-from": "Afficher les utilisateurs depuis :",
        "activeusers-groups": "Afficher les utilisateurs appartenant aux groupes :",
+       "activeusers-excludegroups": "Exclure les utilisateurs appartenant aux groupes :",
        "activeusers-noresult": "Aucun utilisateur trouvé.",
        "activeusers-submit": "Afficher les utilisateurs actifs",
        "listgrouprights": "Droits des groupes d'utilisateurs",
        "emailccsubject": "Copie de votre message à $1 : $2",
        "emailsent": "Courriel envoyé",
        "emailsenttext": "Votre message a été envoyé par courriel.",
-       "emailuserfooter": "Ce courriel a été {{GENDER:$1|envoyé}} par « $1 » à « {{GENDER:$2|$2}} » par la fonction « {{int:emailuser}} » de {{SITENAME}}.",
+       "emailuserfooter": "Ce courriel a été {{GENDER:$1|envoyé}} par « $1 » à « {{GENDER:$2|$2}} » par la fonction « {{int:emailuser}} » de {{SITENAME}}. {{GENDER:$2|Votre}} courriel sera envoyé directement à l'{{GENDER:$1|émetteur initial}}, en {{GENDER:$1|lui}} mentionnant {{GENDER:$2|votre}} adresse courriel .",
        "usermessage-summary": "Laisser un message système.",
        "usermessage-editor": "Messager du système",
        "watchlist": "Liste de suivi",
        "movepagebtn": "Renommer la page",
        "pagemovedsub": "Renommage réussi",
        "movepage-moved": "<strong>« $1 » a été renommée en « $2 »</strong>",
-       "movepage-moved-redirect": "Une redirection depuis l'ancien nom a été créée.",
-       "movepage-moved-noredirect": "La création d'une redirection depuis l'ancien nom a été annulée.",
+       "movepage-moved-redirect": "Une redirection depuis lancien nom a été créée.",
+       "movepage-moved-noredirect": "La création d’une redirection depuis l’ancien nom a été annulée.",
        "articleexists": "Il existe déjà une page portant ce titre, ou le titre que vous avez choisi n'est pas correct.\nVeuillez en choisir un autre.",
        "cantmove-titleprotected": "Vous ne pouvez pas déplacer une page vers cet emplacement car la création de page avec ce nouveau titre a été protégée.",
        "movetalk": "Renommer aussi la page de discussion associée",
        "exif-copyrighted-false": "État des droits d’auteur non défini",
        "exif-photometricinterpretation-1": "Noir et blanc (0 pour le noir)",
        "exif-photometricinterpretation-4": "Masque de transparence",
+       "exif-photometricinterpretation-32803": "Matrice de Filtre de Couleur",
        "exif-unknowndate": "Date inconnue",
        "exif-orientation-1": "Normale",
        "exif-orientation-2": "Inversée horizontalement",
        "tags-deactivate": "désactiver",
        "tags-hitcount": "$1 modification{{PLURAL:$1||s}}",
        "tags-manage-no-permission": "Vous n'avez pas la permission de gérer les modifications de balises.",
-       "tags-manage-blocked": "Vous ne pouvez pas accéder à l’interface de modification des balises lorsque vous êtes bloqué{{GENDER:||e}}.",
+       "tags-manage-blocked": "Vous ne pouvez pas accéder à l’interface de modification des balises lorsque vous êtes bloqué{{GENDER:$1||e}}.",
        "tags-create-heading": "Créer une nouvelle balise",
        "tags-create-explanation": "Par défaut, les nouvelles balises créées seront disponibles pour les utilisateurs et les robots.",
        "tags-create-tag-name": "Nom de la balise :",
        "tags-deactivate-reason": "Motif :",
        "tags-deactivate-not-allowed": "Il n'est pas possible de désactiver la balise « $1 ».",
        "tags-deactivate-submit": "Désactiver",
-       "tags-apply-no-permission": "Vous n’avez pas le droit d’appliquer des balises de changement avec vos modifications.",
-       "tags-apply-blocked": "Vous ne pouvez pas appliquer les modifications de balises et vos modifications lorsque vous êtes bloqué{{GENDER:||e}}.",
+       "tags-apply-no-permission": "Vous n’avez pas le droit d’appliquer des balises de changement en même temps que vos modifications.",
+       "tags-apply-blocked": "Vous ne pouvez pas appliquer les modifications de balises et vos modifications lorsque vous êtes bloqué{{GENDER:$1||e}}.",
        "tags-apply-not-allowed-one": "La balise « $1 » n’est pas autorisée à être appliquée manuellement.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|La balise suivante n’est pas autorisée à être appliquée|Les balises suivantes ne sont pas autorisées à être appliquées}} manuellement : $1",
-       "tags-update-no-permission": "Vous n’avez pas le droit d’ajouter ou de supprimer des balises de modification des révisions individuelles ou des entrées de journal.",
-       "tags-update-blocked": "Vous ne pouvez pas ajouter ou supprimer des balises de modifications lorsque vous êtes bloqué{{GENDER:||e}}.",
+       "tags-update-no-permission": "Vous n’avez pas le droit d’ajouter ou de supprimer \nles balises de modification des révisions individuelles ou des entrées de journal.",
+       "tags-update-blocked": "Vous ne pouvez pas ajouter ou supprimer des balises de modifications lorsque vous êtes bloqué{{GENDER:$1||e}}.",
        "tags-update-add-not-allowed-one": "La balise « $1 » ne peut pas être ajoutée manuellement.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|La balise suivante ne peut pas être ajoutée|Les balises suivantes ne peuvent pas être ajoutées}} manuellement : $1",
        "tags-update-remove-not-allowed-one": "La balise « $1 » ne peut pas être enlevée.",
        "dberr-info": "(Accès à la base de données impossible : $1)",
        "dberr-info-hidden": "(Accès à la base de données impossible)",
        "dberr-usegoogle": "Vous pouvez essayer de chercher avec Google pendant ce temps.",
-       "dberr-outofdate": "Notez que leurs index de notre contenu peuvent être dépassés.",
-       "dberr-cachederror": "Ceci est une copie cachée de la page demandée et peut être dépassée.",
-       "htmlform-invalid-input": "Des problèmes sont survenus avec certaines valeurs",
+       "dberr-outofdate": "Notez que leurs index de notre contenu peuvent ne plus être actuels.",
+       "dberr-cachederror": "Ceci est une copie cachée de la page demandée et peut ne plus être actuelle.",
+       "htmlform-invalid-input": "Des problèmes sont survenus avec certaines de vos valeurs.",
        "htmlform-select-badoption": "La valeur que vous avez spécifiée n'est pas une option valide.",
        "htmlform-int-invalid": "La valeur que vous avec spécifiée n'est pas un entier.",
        "htmlform-float-invalid": "La valeur que vous avez spécifiée n'est pas un nombre.",
        "htmlform-time-invalid": "La valeur que vous avez spécifiée n’est pas une heure reconnue. Essayez en utilisant le format HH:MM:SS.",
        "htmlform-datetime-invalid": "La valeur que vous avez spécifiée n’est pas un horodatage reconnu. Essayez en utilisant le format AAAA-MM-JJ HH:MM:SS.",
        "htmlform-date-toolow": "La valeur que vous avez spécifiée est antérieure à la date autorisée la plus ancienne, qui est $1.",
-       "htmlform-date-toohigh": "La valeur que vous avez spécifiée est postérieure à la date autorisée la plus lointaine, qui est $1.",
+       "htmlform-date-toohigh": "La valeur que vous avez spécifiée est postérieure à la plus grande date autorisée qui est $1.",
        "htmlform-time-toolow": "La valeur que vous avez spécifiée est antérieure à la plus petite heure autorisée, qui est $1.",
        "htmlform-time-toohigh": "La valeur que vous avez spécifiée est postérieure à la plus grande heure autorisée, qui est $1.",
        "htmlform-datetime-toolow": "La valeur que vous avez spécifiée est antérieure à l’horodatage autorisé le plus ancien, qui est $1.",
        "htmlform-user-not-exists": "<strong>$1</strong> n’existe pas.",
        "htmlform-user-not-valid": "<strong>$1</strong> n’est pas un nom d’utilisateur valide.",
        "logentry-delete-delete": "$1 {{GENDER:$2|a supprimé}} la page $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|supprimé}} redirigé vers $3 par écrasement.",
        "logentry-delete-restore": "$1 {{GENDER:$2|a restauré}} la page $3",
        "logentry-delete-event": "$1 {{GENDER:$2|a modifié}} la visibilité {{PLURAL:$5|d'un événement du journal|de $5 événements du journal}} sur $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|a modifié}} la visibilité {{PLURAL:$5|d'une révision|de $5 révisions}} sur la page $3 : $4",
        "revdelete-uname-unhid": "nom d'utilisateur affiché",
        "revdelete-restricted": "restrictions appliquées aux administrateurs",
        "revdelete-unrestricted": "restrictions retirées pour les administrateurs",
-       "logentry-block-block": "$1 {{GENDER:$2|a bloqué}} {{GENDER:$4|$3}} $5 $6",
+       "logentry-block-block": "$1 {{GENDER:$2|a bloqué}} {{GENDER:$4|$3}} avec la durée $5 $6",
        "logentry-block-unblock": "$1 {{GENDER:$2|a débloqué}} {{GENDER:$4|$3}}",
-       "logentry-block-reblock": "$1 {{GENDER:$2|a modifié}} les paramètres de blocage pour {{GENDER:$4|$3}} $5 $6",
-       "logentry-suppress-block": "$1 {{GENDER:$2|a bloqué}} {{GENDER:$4|$3}} $5 $6",
-       "logentry-suppress-reblock": "$1 {{GENDER:$2|a modifié}} les paramètres de blocage pour {{GENDER:$4|$3}} $5 $6",
+       "logentry-block-reblock": "$1 {{GENDER:$2|a modifié}} les paramètres de blocage pour {{GENDER:$4|$3}} avec une durée de $5 $6",
+       "logentry-suppress-block": "$1 {{GENDER:$2|a bloqué}} {{GENDER:$4|$3}} avec une durée de $5 $6",
+       "logentry-suppress-reblock": "$1 {{GENDER:$2|a modifié}} les paramètres de blocage pour {{GENDER:$4|$3}} avec une durée de $5 $6",
        "logentry-import-upload": "$1 {{GENDER:$2|a importé}} $3 par téléchargement de fichier",
        "logentry-import-upload-details": "$1 {{GENDER:$2|a importé}} $3 par téléchargement de fichier ($4 {{PLURAL:$4|révision|révisions}})",
        "logentry-import-interwiki": "$1 {{GENDER:$2|a importé}} $3 depuis un autre wiki",
        "feedback-external-bug-report-button": "Signaler un bogue technique",
        "feedback-dialog-title": "Soumettre un commentaire",
        "feedback-dialog-intro": "Vous pouvez utiliser le simple formulaire ci-dessous pour faire parvenir vos commentaires. Votre commentaire sera ajouté à la page « $1 », ainsi que votre nom d’utilisateur.",
-       "feedback-error1": "Erreur : Résultat de l'IPA non reconnu",
+       "feedback-error1": "Erreur : résultat de l'API non reconnu",
        "feedback-error2": "Erreur : la modification a échoué",
        "feedback-error3": "Erreur : aucune réponse de l'API",
        "feedback-error4": "Erreur : Impossible de publier sous le titre d’avis donné",
        "searchsuggest-search": "Rechercher sur {{SITENAME}}",
        "searchsuggest-containing": "contenant...",
        "api-error-autoblocked": "Votre adresse IP a été bloquée automatiquement, parce qu’elle a été utilisée par un utilisateur bloqué.",
-       "api-error-badaccess-groups": "Vous n'êtes pas autorisé à verser des fichiers sur ce wiki.",
+       "api-error-badaccess-groups": "Vous n'êtes pas autorisé à téléverser des fichiers sur ce wiki.",
        "api-error-badtoken": "Erreur interne : mauvais « jeton ».",
        "api-error-blocked": "Vous avez été bloqué en édition.",
        "api-error-copyuploaddisabled": "Les versements via URL sont désactivés sur ce serveur.",
        "limitreport-expansiondepth": "Plus grande profondeur d’expansion",
        "limitreport-expensivefunctioncount": "Nombre de fonctions d’analyse coûteuses",
        "expandtemplates": "Expansion des modèles",
-       "expand_templates_intro": "Cette page spéciale accepte un texte wiki source et permet de réaliser récursivement l’expansion des modèles qu’il contient.\nElle réalise aussi l’expansion des fonctions du parseur telles que\n<code><nowiki>{{</nowiki>#language:...}}</code> et des variables telles que\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nEn fait, elle réalise l'expansion de pratiquement tout ce qui est encadré par des doubles accolades.",
+       "expand_templates_intro": "Cette page spéciale accepte un texte wiki source et permet de réaliser récursivement l’expansion de tous les modèles qu’il contient.\nElle réalise aussi l’expansion des fonctions supportées d'analyse telles que\n<code><nowiki>{{</nowiki>#language:...}}</code> et des variables telles que\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nEn fait, elle réalise l'expansion de pratiquement tout ce qui est encadré par des doubles accolades.",
        "expand_templates_title": "Titre de la page, si le code utilise {{FULLPAGENAME}}, etc. :",
        "expand_templates_input": "Texte wiki source :",
        "expand_templates_output": "Texte wiki obtenu après expansion",
        "mw-widgets-dateinput-no-date": "Aucune date sélectionnée",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-JJ",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Rechercher des médias",
+       "mw-widgets-mediasearch-noresults": "Aucun résultat trouvé.",
        "mw-widgets-titleinput-description-new-page": "la page n’existe pas encore",
        "mw-widgets-titleinput-description-redirect": "redirection vers $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Ajouter une catégorie...",
        "sessionmanager-tie": "Impossible de combiner des types multiples de demandes d’authentification : $1.",
        "sessionprovider-generic": "sessions $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessions basées sur les témoins (''cookies'')",
        "log-action-filter-contentmodel-change": "Changement de modèle de contenu",
        "log-action-filter-contentmodel-new": "Création de page avec un modèle de contenu non-standard",
        "log-action-filter-delete-delete": "Suppression de pages",
+       "log-action-filter-delete-delete_redir": "Rediriger l'écrasement",
        "log-action-filter-delete-restore": "Restauration de page",
        "log-action-filter-delete-event": "Suppression du journal",
        "log-action-filter-delete-revision": "Suppression de révison",
        "restrictionsfield-badip": "Adresse IP ou plage non valide : $1",
        "restrictionsfield-label": "Plages IP autorisées :",
        "restrictionsfield-help": "Une adresse IP ou une plage CIDR par ligne. Pour tout activer, utiliser <br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Erreur : $1",
-       "edit-error-long": "Erreurs :\n\n$1"
+       "pageid": "ID de page $1"
 }
index 8e542fb..3ae9648 100644 (file)
        "yourpasswordagain": "Mot de passe encore:",
        "createacct-yourpasswordagain": "Confirmes le mot de passe",
        "createacct-yourpasswordagain-ph": "Entres à nouveau le mot de passe",
-       "remembermypassword": "Garder mon mot de passe dans cette browser (pour un maximum of $1 {{PLURAL:$1|jour|jours}})",
        "yourdomainname": "Votre domaine:",
        "externaldberror": "Soit y avait une erreur avec la base d'information de certification extérieur, soit vous avez pas la permission de renouveler votre compte extérieur.",
        "login": "Connecter",
        "undo-success": "Le changement peut être renversé.  Regardez donc la comparaison en bas pour être sûr que c'est comme vous voulez, et puis sauvez les changements en bas pour finir le renversage du changement.",
        "undo-failure": "Le changement pouvait pas être renversé à cause d'une dispute de changements.",
        "undo-summary": "Défaire la révision $1 par [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussion]])",
-       "cantcreateaccounttitle": "Impossible de créer le compte",
        "viewpagelogs": "Voir les notes pour cette page",
        "nohistory": "Y a pas de changements pour cette page.",
        "currentrev": "Version courante",
index d3828ca..006492e 100644 (file)
        "yourpasswordagain": "Confirmâd lo contresegno :",
        "createacct-yourpasswordagain": "Confirmâd lo contresegno",
        "createacct-yourpasswordagain-ph": "Tornâd buchiér lo contresegno",
-       "remembermypassword": "Sè rapelar de mon contresegno sur cél navegator (por lo més $1 jorn{{PLURAL:$1||s}})",
        "userlogin-remembermypassword": "Gouardar ma sèssion activa",
        "userlogin-signwithsecure": "Empleyér un branchement sècurisâ",
        "cannotloginnow-title": "Ora y at pas moyen de sè branchiér",
        "botpasswords-label-resetpassword": "Rebetar a zérô lo contresegno",
        "botpasswords-label-grants": "Drêts aplicâblos :",
        "botpasswords-help-grants": "Châque drêt balye accès ux drêts d’utilisator listâs qu’at ja un comptio. Vêde la [[Special:ListGrants|grelye des drêts]] por més d’enformacions.",
-       "botpasswords-label-restrictions": "Rèstriccions d’usâjo :",
        "botpasswords-label-grants-column": "Acordâ",
        "botpasswords-bad-appid": "Lo nom de robot « $1 » est pas justo.",
        "botpasswords-insert-failed": "Falyita de l’aponsa du nom de robot « $1 ». Est-o qu’il est ja étâ apondu ?",
        "passwordreset-emailelement": "Nom d’utilisator :\n$1\n\nContresegno temporèro :\n$2",
        "passwordreset-emailsentemail": "Se cel’adrèce èlèctronica est associyêe a voutron comptio, adonc un mèssâjo de remês’a zérô de contresegno serat mandâ.",
        "passwordreset-emailsentusername": "S’y at un’adrèce èlèctronica associyêe a cél nom d’utilisator, adonc un mèssâjo de remês’a zérô de contresegno serat mandâ.",
-       "passwordreset-emailsent-capture": "Un mèssâjo de remês’a zérô de contresegno est étâ mandâ, qu’il est montrâ ce-desot.",
-       "passwordreset-emailerror-capture": "Un mèssâjo de remês’a zérô de contresegno est étâ fêt, qu’il est montrâ ce-desot, mas l’èxpèdicion a l’utilisat{{GENDER:$2|or|rice}} at pas reussi : $1",
        "changeemail": "Changiér enlevar l’adrèce èlèctronica",
        "changeemail-header": "Complètâd cél formulèro por changiér voutron adrèce èlèctronica. Se vos voléd enlevar l’associacion d’un’adrèce èlèctronica avouéc voutron comptio, lèssiéd la novèl’adrèce èlèctronica voueda pendent la somission du formulèro.",
-       "changeemail-passwordrequired": "Vos devréd buchiér voutron contresegno por confirmar cél changement.",
        "changeemail-no-info": "Vos dête étre branchiê por arrevar tot drêt a cela pâge.",
        "changeemail-oldemail": "Adrèce èlèctronica d’ora :",
        "changeemail-newemail": "Novèl’adrèce èlèctronica :",
        "undo-nochange": "Semble que lo changement seye ja étâ dèfêt.",
        "undo-summary": "Dèfêta du changement $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|discutar]])",
        "undo-summary-username-hidden": "Dèfêta du changement $1 d’un utilisator cachiê",
-       "cantcreateaccounttitle": "Y at pas moyen de fâre lo comptio",
        "cantcreateaccount-text": "La crèacion de comptio dês cel’adrèce IP (<strong>$1</strong>) est étâye blocâye per [[User:$3|$3]].\n\nLa rêson balyêe per $3 ére <em>$2</em>",
        "cantcreateaccount-range-text": "La crèacion de comptio dês les adrèces IP dedens la plage <strong>$1</strong>, que comprend voutron adrèce IP (<strong>$4</strong>), sont étâye blocâyes per [[User:$3|$3]].\n\nLa rêson balyêe per $3 ére <em>$2</em>",
        "viewpagelogs": "Vêde los jornâls de cela pâge",
        "activeusers-intro": "O est na lista des utilisators qu’ant ègzèrciê un’activitât quinta que seye pendent {{PLURAL:$1|lo jorn passâ|los $1 jorns passâs}}.",
        "activeusers-count": "$1 accion{{PLURAL:$1||s}} pendent {{PLURAL:$3|lo jorn passâ|los $3 jorns passâs}}",
        "activeusers-from": "Fâre vêre los utilisators dês :",
-       "activeusers-hidebots": "Cachiér los robots",
-       "activeusers-hidesysops": "Cachiér los administrators",
        "activeusers-noresult": "Nion utilisator est étâ trovâ.",
        "activeusers-submit": "Fâre vêre los utilisators actifs",
        "listgrouprights": "Drêts de les tropes d’utilisators",
        "htmlform-submit": "Sometre",
        "htmlform-reset": "Dèfâre los changements",
        "htmlform-selectorother-other": "Ôtro",
-       "sqlite-has-fts": "$1 avouéc rechèrche en tèxto complèt recognua",
-       "sqlite-no-fts": "$1 sen rechèrche en tèxto complèt recognua",
        "logentry-delete-delete": "$1 {{GENDER:$2|at suprimâ}} la pâge $3",
        "logentry-delete-restore": "$1 at refêt la pâge $3",
        "logentry-delete-event": "$1 at changiê la visibilitât {{PLURAL:$5|d’un èvènement|de $5 èvènements}} du jornal dessus $3 : $4",
index d361eae..a9446ce 100644 (file)
        "yourpasswordagain": "Skriiw det paaswurd noch ans weder hen:",
        "createacct-yourpasswordagain": "Paaswurd gudkään",
        "createacct-yourpasswordagain-ph": "Du det paaswurd noch ans iin",
-       "remembermypassword": "Üüb diheer reegner üüb düür uunmelde (maksimaal för $1 {{PLURAL:$1|dai|daar}})",
        "userlogin-remembermypassword": "Uunmeldet bliiw",
        "userlogin-signwithsecure": "Seeker ferbinjang brük",
        "yourdomainname": "Din domain:",
        "botpasswords-label-resetpassword": "Paaswurd turagsaat",
        "botpasswords-label-grants": "Mögelk brükerrochten:",
        "botpasswords-help-grants": "Mä arke brükerrocht könst dü üüb ööder brükerrochten faan en brükerkonto tugrip. Luke iin uun det [[Special:ListGrants|tabel]] am muar informatjuun.",
-       "botpasswords-label-restrictions": "Kört brükerrochten:",
        "botpasswords-label-grants-column": "Tugestenen",
        "botpasswords-bad-appid": "Di bot-nööm \"$1\" gongt ei.",
        "botpasswords-insert-failed": "Di bot-nööm \"$1\" küd ei apnimen wurd. Ferlicht as hi al diar?",
        "passwordreset-emailtext-user": "Di brüker $1 üüb {{SITENAME}} hää am brükerinformatsjuunen för {{SITENAME}} uunfraaget ($4). {{PLURAL:$3|Detdiar brükerkonto as|Jodiar brükerkontos san}} mä detdiar E-Mail-Adres ferbünjen:\n\n$2\n\n{{PLURAL:$3|Detheer tidjwiis paaswurd lääpt|Joheer tidjwiis paaswurden luup}} efter {{PLURAL:$5|ään dai|$5 daar}} uf. Dü skulst di uunmelde an en nei paaswurd iinracht. Wan hoker ööders detheer uunfraag steld hää of dü din ual paaswurd käänst, säärst dü niks widjer onernem. Melde di ianfach mä din ual paaswurd uun.",
        "passwordreset-emailelement": "Brükernööm: \n$1\n\nTidjwiis paaswurd: \n$2",
        "passwordreset-emailsentemail": "Diar as en E-Mail tu di onerwais.",
-       "passwordreset-emailsent-capture": "Detdiar E-Mail, wat oner uunwiset woort, as tu di onerwais.",
-       "passwordreset-emailerror-capture": "Detdiar E-Mail, wat oner uunwiset woort, wiar tu di onerwais, oober küd ei tu di {{GENDER:$2|brüker}} ufsjüürd wurd: $1",
        "changeemail": "Feranre det E-Mail-adres",
        "changeemail-header": "Feranre det E-Mail-adres",
        "changeemail-no-info": "Dü möist önjmälded weese am ju sid diräkt tu tu gripen.",
        "undo-nochange": "Detdiar feranrang as wel al ans turagsaat wurden.",
        "undo-summary": "Feranrang $1 faan [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskuschuun]]) turagsaat.",
        "undo-summary-username-hidden": "Feranrang $1 faan en ferbürgenen brüker turagsaat",
-       "cantcreateaccounttitle": "Det brükerkonto koon ei iinracht wurd",
        "cantcreateaccount-text": "Det iinrachten faan en brükerkonto faan det IP-adres '''($1)''' as faan [[User:$3|$3]] speret wurden.\n\nGrünj för det sper: ''$2''",
        "cantcreateaccount-range-text": "Det iinrachten faan brükerkontos uun det IP-adresfial <strong>$1</strong>, huar uk din IP (<strong>$4</strong>) uun as, as faan [[User:$3|$3]] speret wurden.\n\nDi grünj faan $3 wiar: <em>$2</em>",
        "viewpagelogs": "Logbuken faan detdiar sidj uunwise",
        "activeusers-intro": "Jodiar brükern wiar {{PLURAL:$1|di leetst dai| a leetst $1 daar}} aktiif.",
        "activeusers-count": "$1 {{PLURAL:$1|aktjuun|aktjuunen}} uun a {{PLURAL:$3|leetst 24 stünj|leetst $3 daar}}",
        "activeusers-from": "Wise brükern mä began üüb:",
-       "activeusers-hidebots": "Bots fersteeg",
-       "activeusers-hidesysops": "Administratooren fersteeg",
        "activeusers-noresult": "Nään brükern fünjen.",
        "listgrouprights": "Brükersköölrochten",
        "listgrouprights-summary": "Jodiar brükersköölen an hör rochten san uun detheer Wiki fäästlaanj wurden.\nMuar diartu fanjst dü üüb  [[{{MediaWiki:Listgrouprights-helppage}}|detdiar sidj]].",
        "htmlform-title-not-exists": "$1 jaft at ei.",
        "htmlform-user-not-exists": "<strong>$1</strong> jaft at ei.",
        "htmlform-user-not-valid": "<strong>$1</strong> as nään tuläät brükernööm",
-       "sqlite-has-fts": "Werjuun $1 mä halep för't schüken uun di hialer tekst.",
-       "sqlite-no-fts": "Werjuun $1 saner halep för't schüken uun di hialer tekst.",
        "logentry-delete-delete": "$1 {{Gender:$2}} hää det sidj $3 stregen",
        "logentry-delete-restore": "$1 {{GENDER:$2}} hää det sidj $3 weder iinsteld",
        "logentry-delete-event": "$1 {{GENDER:$2}} hää det uunsicht feranert faan {{PLURAL:$5|en logbuk iindrach|$5 logbuk iindracher}} üüb $3: $4",
        "feedback-external-bug-report-button": "En technisk apgoow iinschüür",
        "feedback-dialog-title": "Komentaar ufsjüür",
        "feedback-dialog-intro": "Dü könst det ianfach formulaar diar oner för dan komentaar brük. Dan komentaar komt tuup mä dan brükernööm tu det sidj „$1“.",
-       "feedback-error-title": "Diar as wat skiaf gingen",
        "feedback-error1": "Feeler: Ünbekäänd API-bööd",
        "feedback-error2": "Feeler: Bewerkin as skiaf gingen.",
        "feedback-error3": "Feeler: Nian API-oonswaar",
index 20c4d1c..159834d 100644 (file)
        "yourpasswordagain": "Torne a scrivile",
        "createacct-yourpasswordagain": "Conferme la password",
        "createacct-yourpasswordagain-ph": "Torne a scrivi la tô password",
-       "remembermypassword": "Visiti di me di une session a chê altre (fin a $1 {{PLURAL:$1|zornade|zornadis}})",
        "userlogin-remembermypassword": "Tegnimi colegât",
        "yourdomainname": "Il to domini",
        "login": "Jentre",
        "activeusers-intro": "Cheste e je une liste dai utents che a àn vût cualchi gjenar di ativitât {{PLURAL:$1|te ultime dì|tai ultins $1 diis}}.",
        "activeusers-count": "$1 {{PLURAL:$1|cambiament|cambiaments}} {{PLURAL:$3|te ultime dì|tai ultins $3 diis}}",
        "activeusers-from": "Mostre i utents scomençant di:",
-       "activeusers-hidebots": "Plate i bots",
-       "activeusers-hidesysops": "Plate i aministradôrs",
        "activeusers-noresult": "Nissun utent cjatât.",
        "listgrouprights": "Dirits dai grups di utents",
        "listgrouprights-group": "Grup",
index 93caec8..e10b921 100644 (file)
        "yourpasswordagain": "Jo wachtwurd (nochris)",
        "createacct-yourpasswordagain": "Befêstigje wachtwurd",
        "createacct-yourpasswordagain-ph": "Befêstigje wachtwurd nochris",
-       "remembermypassword": "Oare kear fansels oanmelde (maksimaal $1 {{PLURAL:$1|dei|dagen}})",
        "userlogin-remembermypassword": "Ynlogd bliuwe",
        "userlogin-signwithsecure": "Feilige ferbining brûke",
        "yourdomainname": "Jo domein:",
        "undo-failure": "De feroarings kinne net werom set wurde troch in konflikt mei oare feroarings tuskentroch.",
        "undo-norev": "De feroaring kin werom set wurde, omdat it net bestiet of is wiske.",
        "undo-summary": "Werom sette fan ferzje $1 fan [[Special:Contributions/$2|$2]] ([[User talk:$2|Oerlis]])",
-       "cantcreateaccounttitle": "Registrearjen is mislearre.",
        "cantcreateaccount-text": "Registraasje fan in brûker fia dit IP-adres ('''$1''') is blokkearre troch [[User:$3|$3]].\n\nDe fan $3 opjûne reden is ''$2''",
        "viewpagelogs": "Lochboek foar dizze side sjen litte",
        "nohistory": "Dit is de earste ferzje fan de side.",
        "listusers-blocked": "(blokkearre)",
        "activeusers": "Aktive meidoggers",
        "activeusers-count": "$1 {{PLURAL:$1|aksje|aksjes}} yn de lêste {{PLURAL:$3|dei|$3 dagen}}",
-       "activeusers-hidebots": "Bots ferbergje",
-       "activeusers-hidesysops": "Behearders ferbergje",
        "activeusers-noresult": "Gjin meidoggers fûn.",
        "listgrouprights": "Rjochten fan brûkersgroepen",
        "listgrouprights-summary": "Op dizze side steane de brûkersgroepen yn dizze wiki beskreaun, mei har derby hearrende rjochten.\nDer kin [[{{MediaWiki:Listgrouprights-helppage}}|ekstra ynformaasje]] oer yndividuele rjochten oanwêzich wêze.",
        "feedback-back": "Foarige",
        "feedback-cancel": "Annulearje",
        "feedback-close": "Dien",
-       "feedback-error-title": "Flater",
        "feedback-message": "Berjocht:",
        "feedback-subject": "Ûnderwerp:",
        "feedback-submit": "Ferstjoere",
index 25c12fd..8509a8a 100644 (file)
        "tog-hidepatrolled": "Folaigh giotaí eagartha smachtaithe sna athruithe is déanaí",
        "tog-newpageshidepatrolled": "Folaigh leathanaigh smachtaithe ó liosta leathanaigh úire",
        "tog-extendwatchlist": "Leathnaigh an liosta faire chun gach athrú cuí a thaispeáint",
-       "tog-usenewrc": "Stíl nua do na hathruithe is déanaí (JavaScript riachtanach)",
+       "tog-usenewrc": "Athruithe a ghrúpáil de réir leathanaigh sna hathruithe le déanaí agus sa liosta faire",
        "tog-numberheadings": "Uimhrigh ceannteidil go huathoibríoch",
-       "tog-showtoolbar": "Taispeáin an barra uirlisí eagair (JavaScript)",
-       "tog-editondblclick": "Déghliogáil chun leathanaigh a chur in eagar (JavaScript)",
-       "tog-editsectiononrightclick": "Cumasaigh mír-eagarthóireacht le deaschliceáil<br /> ar cheannteidil (JavaScript)",
+       "tog-showtoolbar": "Taispeáin an barra uirlisí eagair",
+       "tog-editondblclick": "Déchliceáil chun leathanaigh a chur in eagar",
+       "tog-editsectiononrightclick": "Cumasaigh mír-eagarthóireacht le deaschliceáil ar cheannteidil",
        "tog-watchcreations": "Cuir ar mo liosta faire leathanaigh a chruthaím",
-       "tog-watchdefault": "Déan faire ar leathanaigh a athraím",
-       "tog-watchmoves": "Cuir ar mo liosta faire leathanaigh a athainmnaím",
-       "tog-watchdeletion": "Cuir ar mo liosta faire leathanaigh a scriosaim",
+       "tog-watchdefault": "Cuir leathanaigh agus comhaid a athraím le mo liosta faire",
+       "tog-watchmoves": "Cuir ar mo liosta faire leathanaigh agus comhaid a bhogaim",
+       "tog-watchdeletion": "Cuir ar mo liosta faire leathanaigh agus comhaid a scriosaim",
        "tog-minordefault": "Déan mionathruithe de gach aon athrú, mar réamhshocrú",
        "tog-previewontop": "Cuir an réamhamharc os cionn an bhosca eagair, <br />agus ná cuir é taobh thíos de",
        "tog-previewonfirst": "Taispeáin réamhamharc don chéad athrú",
-       "tog-enotifwatchlistpages": "Cuir ríomhphost chugam nuair a athraítear leathanaigh",
+       "tog-enotifwatchlistpages": "Cuir ríomhphost chugam nuair a athraítear leathanach nó comhad atá ar mo liosta faire",
        "tog-enotifusertalkpages": "Cuir ríomhphost chugam nuair a athraítear mo leathanach phlé úsáideora",
        "tog-enotifminoredits": "Cuir ríomhphost chugam nuair a dhéantar mionathruithe chomh maith",
        "tog-enotifrevealaddr": "Taispeáin mo sheoladh ríomhphoist i dteachtaireachtaí fógra",
        "tog-shownumberswatching": "Taispeán an méid úsáideoirí atá ag faire",
-       "tog-oldsig": "Réamhamharc ar an síniú atá ann:",
+       "tog-oldsig": "An síniú atá agat faoi láthair:",
        "tog-fancysig": "Sínithe bunúsacha mar vicítéacs (gan nasc uathoibríoch)",
-       "tog-uselivepreview": "Bain úsáid as réamhamharc beo (JavaScript) (Turgnamhach)",
+       "tog-uselivepreview": "Bain úsáid as réamhamharc beo",
        "tog-forceeditsummary": "Cuir in iúl dom nuair a chuirim isteach achoimre eagair folamh",
        "tog-watchlisthideown": "Folaigh mo chuid athruithe ón liosta faire",
        "tog-watchlisthidebots": "Folaigh athruithe de chuid róbat ón liosta faire",
        "moredotdotdot": "Tuilleadh...",
        "mypage": "Leathanach",
        "mytalk": "Plé",
-       "anontalk": "Plé don seoladh IP seo",
+       "anontalk": "Plé",
        "navigation": "Nascleanúint",
        "and": "&#32;agus",
        "qbfind": "Aimsigh",
        "protect": "Glasáil",
        "protect_change": "athraigh",
        "protectthispage": "Glasáil an lch seo",
-       "unprotect": "Díghlasáil",
-       "unprotectthispage": "Díghlasáil an lch seo",
+       "unprotect": "Athraigh an chosaint",
+       "unprotectthispage": "Athraigh an chosaint atá ag an lch seo",
        "newpage": "Leathanach nua",
        "talkpage": "Pléigh an lch seo",
        "talkpagelinktext": "Plé",
        "pool-errorunknown": "Earráid anaithnid",
        "aboutsite": "Maidir leis an {{SITENAME}}",
        "aboutpage": "Project:Maidir leis",
-       "copyright": "Tá an t-ábhar le fáil faoin $1.",
+       "copyright": "Tá an t-ábhar le fáil faoin $1 mura sonraítear a mhalairt.",
        "copyrightpage": "{{ns:project}}:Cóipchearta",
        "currentevents": "Cúrsaí reatha",
        "currentevents-url": "Project:Cúrsaí reatha",
        "laggedslavemode": "Rabhadh: B'fhéidir nach bhfuil na nuashonrúcháin is déanaí le feiceáil ar an leathanach seo.",
        "readonly": "Bunachar sonraí faoi ghlas",
        "enterlockreason": "Iontráil cúis don glasáil, agus meastachán\nden uair a díghlasálfar an bunachar sonraí.",
-       "readonlytext": "Tá an bunachar sonraí {{GRAMMAR:genitive|{{SITENAME}}}} glasáilte anois do iontráilí agus athruithe nua\n(is dócha go bhfuil sé do gnáthchothabháil).\nTar éis seo, díghlasálfar an bunachar sonraí arís.\nTugadh an míniú seo ag an riarthóir a ghlasáil é:\n$1",
+       "readonlytext": "Tá an bunachar sonraí glasáilte anois agus ní féidir iontrálacha nua ná athruithe eile a dhéanamh. Gach seans go bhfuil gnáthchothabháil ar siúl, agus beidh gach rud ar ais mar a bhí nuair a bheidh sin thart.\n\nThug an riarthóir a ghlasáil é an míniú seo:\n$1",
        "missing-article": "Ní bhfuarthas téacs an leathanaigh ceart, darbh ainm \"$1\" $2.\n\nDe ghnáth, tarlaíonn sé seo nuair a leantar nasc stáire nó difr chuig leathanach a scriosadh.\n\nMurab fhíor é seo, is féidir go bhfuair tú fabht sa bhogearraí. Beimid buíoch duit é a chur in iúl do [[Special:ListUsers/sysop|riarthóir]], chomh maith le URL an suíoimh.",
        "missingarticle-rev": "(leagan#: $1)",
        "missingarticle-diff": "(Dif: $1, $2)",
        "cannotdelete": "Ní féidir an leathanach nó comhad \"$1\" a scriosadh.\nB'fhéidir gur scrios duine eile é cheana féin.",
        "badtitle": "Teideal neamhbhailí",
        "badtitletext": "Bhí teideal an leathanaigh a d'iarr tú ar neamhbhailí, folamh, nó\nteideal idirtheangach nó idirvicí nasctha go mícheart.",
-       "perfcached": "Fuarthas na sonraí a leanas as taisce, agus is dócha go bhfuil siad as dáta. A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.",
+       "perfcached": "Fuarthas na sonraí a leanas as taisce, agus seans go bhfuil siad as dáta. Tá {{PLURAL:$1|aon toradh amháin|$1 thoradh}} ar fáil sa taisce.",
        "perfcachedts": "Tá na sonraí seo a leanas sa taisce, nuashonraithe $1. A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.",
        "viewsource": "Féach ar fhoinse",
        "actionthrottled": "Gníomh scóigthe",
-       "actionthrottledtext": "Mar theicníc frithurscair, ní féidir lear an gníomh seo a dhéanamh barraíocht taobh istigh de thréimhse ghairid ama, agus tá an méid sáraithe agat.\nBain trial arís as i gcionn cúpla bomaite más é do thoil é.",
+       "actionthrottledtext": "Mar theicníc frithurscair, ní féidir lear an gníomh seo a dhéanamh barraíocht taobh istigh de thréimhse ghairid ama, agus tá an méid sáraithe agat.\nBain triail arís as i gcionn cúpla bomaite más é do thoil é.",
        "protectedpagetext": "Tá an leathanach seo glasáilte chun coisc ar eagarthóireacht.",
        "viewsourcetext": "Is féidir foinse an leathanach seo a fheiceáil ná a cóipeáil:",
        "editinginterface": "'''Rabhadh:''' Tá tú ag athrú leathanaigh a bhfuil téacs comhéadain do na bogearraí air. Cuirfear athruithe ar an leathanach seo i bhfeidhm ar an gcomhéadan úsáideora.\nMás maith leat MediaWiki a aistriú, cuimhnigh ar [https://translatewiki.net/wiki/Main_Page?setlang=ga translatewiki.net] (tionscadal logánaithe MediaWiki) a úsáid.",
        "nocookieslogin": "Úsáideann {{SITENAME}} fianáin chun úsáideoirí a logáil isteach.\nTá fianáin díchumasaithe agat.\nCumasaigh iad agus bain triail eile as, le do thoil.",
        "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "Níor thug tú ainm úsáideora bailí.",
-       "loginsuccesstitle": "Logáladh isteach thú",
+       "loginsuccesstitle": "Logáilte isteach",
        "loginsuccess": "'''Tá tú logáilte isteach anois sa {{SITENAME}} mar \"<nowiki>$1</nowiki>\".'''",
-       "nosuchuser": "Níl aon úsáideoir ann leis an ainm \"$1\".\nTá ainmneacha úsáideoir cásíogair.\nCinntigh do litriú, nó [[Special:CreateAccount|bain úsáid as an foirm thíos]] chun cuntas úsáideora nua a chruthú.",
+       "nosuchuser": "Níl aon úsáideoir ann darb ainm \"$1\".\nTá ainmneacha úsáideoir cásíogair.\nSeiceáil an litriú, nó [[Special:CreateAccount|cruthaigh cuntas nua]].",
        "nosuchusershort": "Níl aon úsáideoir ann leis an ainm \"$1\". Cinntigh do litriú.",
        "nouserspecified": "Caithfidh ainm úsáideoir a shonrú.",
        "login-userblocked": "Tá an t-úsáideoir seo faoi bhac. Níl cead aige/aici logáil isteach.",
        "wrongpassword": "D'iontráil tú focal faire mícheart.<br />\nBain triail eile as.",
        "wrongpasswordempty": "Níor iontráil tú focal faire. Bain triail eile as.",
        "passwordtooshort": "Is riachtanach go bhfuil {{PLURAL:$1|carachtar amháin|$1 carachtair}} ann ar a laghad i bhfocal faire.",
-       "mailmypassword": "Seol m'fhocal faire chugam.",
+       "mailmypassword": "Focal faire a athshocrú",
        "passwordremindertitle": "Cuimneachán an fhocail faire ó {{SITENAME}}",
        "passwordremindertext": "D'iarr duine éigin (tusa de réir cosúlachta, ón seoladh IP $1) go sheolfaimis focal faire {{GRAMMAR:genitive|{{SITENAME}}}} nua  ($4).\n\"$3\" an focal faire don úsáideoir \"$2\" anois. Ba chóir duit lógail isteach anois agus d'fhocal faire a athrú.\n\nRachaidh d'fhocail faire sealadach as feidhm i gceann {{PLURAL:$5|lá amháin|$5 lae}}.",
        "noemail": "Níl aon seoladh ríomhphoist i gcuntas don úsáideoir \"$1\".",
        "search-section": "(gearradh $1)",
        "search-suggest": "An raibh $1 á lorg agat?",
        "search-interwiki-caption": "Comhthionscadail",
-       "search-interwiki-default": "$1 torthaí:",
+       "search-interwiki-default": "Torthaí ó $1:",
        "search-interwiki-more": "(níos mó)",
        "search-relatedarticle": "Gaolmhar",
        "searchrelated": "gaolmhara",
        "prefs-rc": "Athruithe is déanaí",
        "prefs-watchlist": "Liosta faire",
        "prefs-watchlist-days": "Líon na laethanta le taispeáint sa liosta faire:",
-       "prefs-watchlist-days-max": "Maximum $1 {{PLURAL:$1|day|days}}",
+       "prefs-watchlist-days-max": "$1 {{PLURAL:$1|lá}} ar a mhéad",
        "prefs-watchlist-edits": "Líon na n-athruithe le taispeáint sa liosta leathnaithe faire:",
        "prefs-watchlist-edits-max": "Uasmhéid: 1000",
        "prefs-misc": "Éagsúla",
        "savedprefs": "Sábháladh do chuid sainroghanna.",
        "timezonelegend": "Crios ama:",
        "localtime": "An t-am áitiúil:",
-       "timezoneuseserverdefault": "Úsáid am réamhshocraithe an fhreastalaí",
+       "timezoneuseserverdefault": "Úsáid am réamhshocraithe an vicí ($1)",
        "timezoneuseoffset": "Eile (cuir isteach an difear)",
        "servertime": "Am an fhreastalaí:",
        "guesstimezone": "Líon ón mbrabhsálaí",
index e6cbbcb..42b617f 100644 (file)
        "yourname": "Kullanıcı adınız",
        "yourpassword": "Parol",
        "yourpasswordagain": "Parolu enidän yaz",
-       "remembermypassword": "Parolu hatırla (en fazla $1 {{PLURAL:$1|gün|gün}} için)",
        "yourdomainname": "Domen adınız",
        "login": "Gir",
        "nav-login-createaccount": "Gir / esap yarat",
        "permissionserrors": "İzin yannışları",
        "permissionserrorstext-withaction": "Aşaadaki {{PLURAL:$1|sebep|sebepler}}ä deyni yok $2 kuvediniz:",
        "recreate-moveddeleted-warn": "'''Bak: Siz yarattınız o sayfayı angısı ilerdän silindi.'''\n\nLäazım düşünmää bu sayfayı redaktat etmää devam etmää deyni.\nSayfanın silmää jurnalı raatlık için yazılêr burada:",
-       "cantcreateaccounttitle": "Yok nicä esap yaratılsın",
        "viewpagelogs": "Bu yaprak için jurnalları göster",
        "currentrev": "Şindiki versiya",
        "currentrev-asof": "$1 sayfanın şindiki halı",
index d6b8a34..e3a2daf 100644 (file)
        "yourname": "用户名:",
        "yourpassword": "密码:",
        "yourpasswordagain": "输过道密码:",
-       "remembermypassword": "记定我𠮶密码(顶多$1{{PLURAL:$1|日|日}})",
        "yourdomainname": "倷𠮶域名:",
        "externaldberror": "外部验证数据库出错,或倷更新伓正倷𠮶外部帐户。",
        "login": "登入",
        "undo-success": "个只编辑可以拖取销。请检查吖以确定个系倷想扤𠮶,接到保存修改去完成撤销编辑。",
        "undo-failure": "半中𠮶编辑有人挭仗,个只编辑伓可以拖取销。",
        "undo-summary": "取消由[[Special:Contributions/$2|$2]] ([[User talk:$2|对话]])所修订𠮶 $1",
-       "cantcreateaccounttitle": "新开伓正帐户",
        "cantcreateaccount-text": "IP 地址伓能 ('''$1''') 新开帐户。个可能系因为经常有来自倷𠮶学堂或网络供应商 (ISP)故意𠮶破坏扤得。",
        "viewpagelogs": "眵吖个页𠮶日志",
        "nohistory": "个页冇修改历史。",
index 1cb2ad7..3a58c92 100644 (file)
        "yourname": "用戶名:",
        "yourpassword": "密碼:",
        "yourpasswordagain": "輸過道密碼:",
-       "remembermypassword": "記定我嗰密碼(頂多$1{{PLURAL:$1|日|日}})",
        "yourdomainname": "倷嗰域名:",
        "externaldberror": "外部驗證資料庫出錯,或倷更新伓正倷嗰外部帳戶。",
        "login": "登入",
        "undo-success": "箇隻編輯可以拕取銷。請檢查吖以確定箇係倷想扤嗰,接到保存修改去完成撤銷編輯。",
        "undo-failure": "半中嗰編輯有人挭仗,箇隻編輯伓可以拕取銷。",
        "undo-summary": "取消由[[Special:Contributions/$2|$2]] ([[User talk:$2|對話]])所修訂嗰 $1",
-       "cantcreateaccounttitle": "新開伓正帳戶",
        "cantcreateaccount-text": "IP 位址伓能 ('''$1''') 新開帳戶。箇可能係因為經常有來自倷嗰學堂或網絡供應商 (ISP)故意嗰破壞扤得。",
        "viewpagelogs": "眵吖箇頁嗰日誌",
        "nohistory": "箇頁冇修改歷史。",
index c658811..93fb479 100644 (file)
        "yourpasswordagain": "Ath-sgrìobh facal-faire",
        "createacct-yourpasswordagain": "Dearbhaich am facal-faire",
        "createacct-yourpasswordagain-ph": "Cuir a-steach am facal-faire a-rithist",
-       "remembermypassword": "Cuimhnich gu bheil mi air logadh a-steach air a' choimpiutair seo (suas gu $1 {{PLURAL:$1|latha|latha|làithean|latha}})",
        "userlogin-remembermypassword": "Cum air logadh a-steach mi",
        "userlogin-signwithsecure": "Cleachd ceangal tèarainte",
        "yourdomainname": "An àrainn-lìn agad:",
        "activeusers-intro": "Seo liosta dhe na cleachdaichean a rinn gnìomh air choireigin am broinn {{PLURAL:$1|an $1 latha|an $1 latha|nan $1 làithean|an $1 latha}} mu dheireadh.",
        "activeusers-count": "$1 {{PLURAL:$1|ghnìomh|ghnìomh|gnìomhan|gnìomh}} am broinn {{PLURAL:$3|an $3 latha|an $3 latha|nan $3 làithean|an $3 latha}} mu dheireadh.",
        "activeusers-from": "Seall cleachdaichean o seo a-mach:",
-       "activeusers-hidebots": "Falaich na botaichean",
-       "activeusers-hidesysops": "Falaich na rianairean",
        "activeusers-noresult": "Cha deach cleachdaiche a lorg.",
        "listgrouprights": "Ceadan nam buidhnean chleachdaichean",
        "listgrouprights-summary": "chì thu liosta dhe na buidhnean chleachdaichean a tha san uicidh seo 's na ceadan inntrigidh aca.\nDh'fhaoidte gu bheil [[{{MediaWiki:Listgrouprights-helppage}}|barrachd fiosrachaidh]] mu cheadan fa leth ann.",
        "htmlform-cloner-create": "Cuir barrachd ris",
        "htmlform-cloner-delete": "Thoir air falbh",
        "htmlform-cloner-required": "Tha luach a dhìth.",
-       "sqlite-has-fts": "$1 le taic ri lorg teacsa shlàin",
-       "sqlite-no-fts": "$1 gun taic ri lorg teacsa shlàin",
        "logentry-delete-delete": "Sguab $1 às duilleag $3",
        "logentry-delete-restore": "Dh'aisig $1 duilleag $3",
        "logentry-delete-event": "Dh'atharraich $1 an fhaicsinneachd aig $5 {{PLURAL:$5|tachartas|thachartas|tachartasan|tachartas}} an loga air $3: $4",
index e8675d5..eba3cb5 100644 (file)
        "views": "Vistas",
        "toolbox": "Ferramentas",
        "tool-link-userrights": "Modificar os grupos {{GENDER:$1|do usuario|da usuaria}}",
+       "tool-link-userrights-readonly": "Ver os {{GENDER:$1|grupos de usuario}}",
        "tool-link-emailuser": "Enviar un correo electrónico {{GENDER:$1|ao usuario|á usuaria}}",
        "userpage": "Ver a páxina {{GENDER:{{BASEPAGENAME}}|do usuario|da usuaria}}",
        "projectpage": "Ver a páxina do proxecto",
        "laggedslavemode": "'''Aviso:''' A páxina pode non conter as actualizacións recentes.",
        "readonly": "Base de datos pechada",
        "enterlockreason": "Dea unha razón para o peche, incluíndo unha estimación de até cando se manterá",
-       "readonlytext": "Nestes intres a base de datos está pechada a novas entradas e outras modificacións, probablemente debido a procesos de mantemento, tras os que volverá á normalidade.\n\nO administrador de sistemas que a pechou deu esta explicación: $1",
+       "readonlytext": "Nestes intres a base de datos está pechada a novas entradas e outras modificacións, probablemente debido a procesos de mantemento, tralos que volverá á normalidade.\n\nO administrador do sistema que a pechou deu esta explicación: $1",
        "missing-article": "A base de datos non atopou o texto da páxina chamada \"$1\" $2, que debera ter atopado.\n\nNormalmente, isto está causado por seguir unha ligazón cara a unha diferenza vella ou a unha páxina que foi borrada.\n\nSe este non é o caso, poida que atopase un erro no software.\nPor favor, comuníquello a un [[Special:ListUsers/sysop|administrador]] tomando nota do enderezo URL.",
        "missingarticle-rev": "(nº de revisión: $1)",
        "missingarticle-diff": "(dif: $1, $2)",
        "readonly_lag": "A base de datos bloqueouse automaticamente mentres os servidores levan a cabo a sincronización co servidor principal",
-       "nonwrite-api-promise-error": "A cabeceira HTTP  'Promise-Non-Write-API-Action' foi enviada pero a petición foi feita a un módulo de escritura da API.",
+       "nonwrite-api-promise-error": "Enviouse a cabeceira HTTP \"Promise-Non-Write-API-Action\", pero a petición fíxose a un módulo de escritura da API.",
        "internalerror": "Erro interno",
        "internalerror_info": "Erro interno: $1",
        "internalerror-fatal-exception": "Excepción grave de tipo \"$1\"",
        "no-null-revision": "Non se puido crear a nova revisión nula para a páxina \"$1\"",
        "badtitle": "Título incorrecto",
        "badtitletext": "O título da páxina pedida non era válido, estaba baleiro ou proviña dunha ligazón interlingüística ou interwiki incorrecta.\nPoida que conteña un ou máis caracteres dos que non se poden empregar nos títulos.",
-       "title-invalid-empty": "O título de páxina solicitado está baleiro ou só contén o nome do espazo de nomes.",
+       "title-invalid-empty": "O título de páxina solicitado está baleiro ou só contén o nome dun espazo de nomes.",
        "title-invalid-utf8": "O título de páxina solicitado contén unha secuencia UTF-8 inválida.",
-       "title-invalid-interwiki": "O título da páxina solicitada contén unha ligazón interwiki que non pode usarse nos títulos.",
-       "title-invalid-talk-namespace": "O título de páxina solicitado refírese a unha páxina de conversa que pode non existir.",
+       "title-invalid-interwiki": "O título de páxina solicitado contén unha ligazón interwiki que non se pode utilizar nos títulos.",
+       "title-invalid-talk-namespace": "O título de páxina solicitado fai referencia a unha páxina de conversa que pode non existir.",
        "title-invalid-characters": "O título de páxina solicitado contén caracteres inválidos: \"$1\".",
-       "title-invalid-relative": "O título ten unha ruta relativa. Os títulos de páxina relativos (./, ../) son inválidos, porque non van ser accesibles cando se consulten co navegador do usuario.",
+       "title-invalid-relative": "O título ten unha ruta relativa. Os títulos de páxina relativos (./, ../) son inválidos, porque a miúdo non son accesibles cando se consultan desde o navegador do usuario.",
        "title-invalid-magic-tilde": "O título de páxina solicitado contén unha secuencia con tiles inválida (<nowiki>~~~</nowiki>).",
-       "title-invalid-too-long": "O título de páxina solicitado é moi longo. Non pode ser maior de {{PLURAL:$1|byte|bytes}} en codificación UTF-8.",
-       "title-invalid-leading-colon": "O título de páxina solicitado contén un punto e coma inválido ó comezo.",
+       "title-invalid-too-long": "O título de páxina solicitado é moi longo. Non pode ser maior de $1 {{PLURAL:$1|byte|bytes}} en codificación UTF-8.",
+       "title-invalid-leading-colon": "O título de páxina solicitado contén un carácter de dous puntos non permitido ao comezo.",
        "perfcached": "Esta información é da memoria caché e pode ser que non estea completamente actualizada. Hai un máximo de {{PLURAL:$1|$1 resultado dispoñible|$1 resultados dispoñibles}} na caché.",
        "perfcachedts": "Esta información é da memoria caché. Última actualización: $2 ás $3. Hai un máximo de {{PLURAL:$4|$4 resultado dispoñible|$4 resultados dispoñibles}} na caché.",
        "querypage-no-updates": "Neste momento están desactivadas as actualizacións nesta páxina. O seu contido non se modificará.",
        "viewsource": "Ver o código fonte",
        "viewsource-title": "Ver o código fonte de \"$1\"",
        "actionthrottled": "Acción limitada",
-       "actionthrottledtext": "Como medida contra os abusos, a acción que está realizando está limitada a un número determinado de veces nun periodo curto de tempo, e superou ese límite.\nInténteo de novo nuns minutos.",
+       "actionthrottledtext": "Como medida contra os abusos, ten limitada a acción que está realizando a un número determinado de veces nun período curto de tempo, e vostede superou ese límite.\nInténteo de novo nuns minutos.",
        "protectedpagetext": "Esta páxina foi protexida para evitar a edición e outras accións.",
        "viewsourcetext": "Pode ver e copiar o código fonte desta páxina.",
        "viewyourtext": "Pode ver e copiar o código fonte <strong>das súas edicións</strong> nesta páxina.",
        "mypreferencesprotected": "Non ten os permisos necesarios para editar as súas preferencias.",
        "ns-specialprotected": "Non se poden editar as páxinas no espazo de nomes \"{{ns:special}}\".",
        "titleprotected": "Este título foi protexido da creación por [[User:$1|$1]].\nO motivo achegado é <em>$2</em>.",
-       "filereadonlyerror": "Non se puido modificar o ficheiro \"$1\" porque o repositorio \"$2\" está en modo de só lectura.\n\nO administrador de sistemas que bloqueou o repositorio achegou este motivo: \"$3\".",
+       "filereadonlyerror": "Non se puido modificar o ficheiro \"$1\" porque o repositorio \"$2\" está en modo de só lectura.\n\nO administrador do sistema que bloqueou o repositorio achegou este motivo: \"$3\".",
        "invalidtitle-knownnamespace": "Título inválido co espazo de nomes \"$2\" e o texto \"$3\"",
        "invalidtitle-unknownnamespace": "Título inválido cun número de espazo de nomes, $1, descoñecido e o texto \"$2\"",
        "exception-nologin": "Non accedeu ao sistema",
        "exception-nologin-text": "Acceda ao sistema para poder realizar esa acción ou acceder a esa páxina.",
        "exception-nologin-text-manual": "Debe $1 para poder realizar esa acción ou acceder a esa páxina.",
-       "virus-badscanner": "Configuración errónea: escáner de virus descoñecido: ''$1''",
+       "virus-badscanner": "Configuración errónea: Escáner de virus descoñecido: <em>$1</em>",
        "virus-scanfailed": "fallou o escaneado (código $1)",
        "virus-unknownscanner": "antivirus descoñecido:",
        "logouttext": "'''Agora está fóra do sistema.'''\n\nTeña en conta que algunhas páxinas poden continuar aparecendo como se aínda estivese dentro do sistema, ata que limpe a caché do seu navegador.",
        "cannotlogoutnow-title": "Non se pode saír da sesión agora mesmo",
        "cannotlogoutnow-text": "Non é posible saír da sesión cando se usa $1.",
        "welcomeuser": "Reciba a nosa benvida, $1!",
-       "welcomecreation-msg": "A súa conta foi creada correctamente.\nNon esqueza personalizar as súas [[Special:Preferences|preferencias de {{SITENAME}}]].",
+       "welcomecreation-msg": "A súa conta creouse correctamente.\nNon esqueza personalizar as súas [[Special:Preferences|preferencias]] de {{SITENAME}}.",
        "yourname": "Nome de usuario:",
        "userlogin-yourname": "Nome de usuario",
        "userlogin-yourname-ph": "Insira o seu nome de usuario",
        "createacct-yourpasswordagain-ph": "Insira o contrasinal outra vez",
        "userlogin-remembermypassword": "Manter a miña conexión",
        "userlogin-signwithsecure": "Utilizar a conexión segura",
-       "cannotlogin-title": "Non se pode acceder ó sistema",
-       "cannotlogin-text": "O acceso ó sistema non está dispoñible.",
+       "cannotlogin-title": "Non se pode acceder ao sistema",
+       "cannotlogin-text": "O acceso ao sistema non está dispoñible.",
        "cannotloginnow-title": "Non se pode iniciar a sesión agora mesmo",
        "cannotloginnow-text": "Non é posible iniciar a sesión cando se usa $1.",
        "cannotcreateaccount-title": "Non se poden crear contas de usuario",
-       "cannotcreateaccount-text": "A creación directa de contas de usuario non está habilitada nesta wiki.",
+       "cannotcreateaccount-text": "A creación directa de contas de usuario non está activada neste wiki.",
        "yourdomainname": "O seu dominio:",
        "password-change-forbidden": "Non pode mudar os contrasinais neste wiki.",
        "externaldberror": "Ou ben se produciu un erro da base de datos na autenticación externa ou ben non se lle permite actualizar a súa conta externa.",
        "userlogin-resetpassword-link": "Esqueceu o contrasinal?",
        "userlogin-helplink2": "Axuda co rexistro",
        "userlogin-loggedin": "Xa accedeu ao sistema como {{GENDER:$1|$1}}.\nUtilice o formulario inferior para acceder como outro usuario.",
-       "userlogin-reauth": "Debe conectarse de novo para verificar que é {{GENDER:$1|$1}}.",
+       "userlogin-reauth": "Debe conectarse de novo para verificar que vostede é {{GENDER:$1|$1}}.",
        "userlogin-createanother": "Crear outra conta",
        "createacct-emailrequired": "Enderezo de correo electrónico",
        "createacct-emailoptional": "Enderezo de correo electrónico (opcional)",
        "createaccountreason": "Motivo:",
        "createacct-reason": "Motivo",
        "createacct-reason-ph": "Por que crea outra conta?",
-       "createacct-reason-help": "Mensaxe que se mostra no rexistro de creación de contas",
+       "createacct-reason-help": "Mensaxe mostrada no rexistro de creación de contas",
        "createacct-submit": "Crear a conta",
        "createacct-another-submit": "Crear a conta",
        "createacct-continue-submit": "Continuar a creación da conta",
        "nocookiesnew": "A conta de usuario foi creada, pero non accedeu ao sistema.\n{{SITENAME}} para rexistrar os usuarios.\nVostede ten as cookies deshabilitadas.\nPor favor, habilíteas e logo acceda ao sistema co seu novo nome de usuario e contrasinal.",
        "nocookieslogin": "{{SITENAME}} usa cookies para rexistrar os usuarios.\nVostede ten as cookies deshabilitadas.\nPor favor, habilíteas e inténteo de novo.",
        "nocookiesfornew": "Non se creou a conta de usuario porque non puidemos confirmar a súa orixe.\nAsegúrese de que ten as cookies habilitadas, volva cargar a páxina e inténteo de novo.",
-       "createacct-loginerror": "A conta creouse correctamente, pero non se puido conectar automaticamente. Proceda ó [[Special:UserLogin|acceso manual]].",
+       "createacct-loginerror": "A conta creouse correctamente, pero non se puido conectar automaticamente. Vaia ao [[Special:UserLogin|acceso manual]].",
        "noname": "Non especificou un nome de usuario válido.",
-       "loginsuccesstitle": "Conectado",
+       "loginsuccesstitle": "Accedeu ao sistema",
        "loginsuccess": "<strong>Accedeu ao sistema de {{SITENAME}} como \"$1\".</strong>",
        "nosuchuser": "Non existe ningún usuario chamado \"$1\".\nOs nomes de usuario diferencian entre maiúsculas e minúsculas.\nVerifique a ortografía ou [[Special:CreateAccount|cree unha nova conta]].",
        "nosuchusershort": "Non existe ningún usuario chamado \"$1\".\nVerifique o nome que inseriu.",
        "wrongpassword": "O contrasinal escrito é incorrecto.\nPor favor, insira outro.",
        "wrongpasswordempty": "O campo do contrasinal estaba en branco.\nPor favor, inténteo de novo.",
        "passwordtooshort": "Os contrasinais deben conter, como mínimo, {{PLURAL:$1|1 carácter|$1 caracteres}}.",
-       "passwordtoolong": "Os contrasinais non deben ser máis longo de {{PLURAL:$1|1 carácter|$1 caracteres}}.",
-       "passwordtoopopular": "Os contrasinais escollidos máis habitualmente non poden usarse. Por favor, escolle un contrasinal máis único.",
+       "passwordtoolong": "Os contrasinais non poden ser máis longo de {{PLURAL:$1|1 carácter|$1 caracteres}}.",
+       "passwordtoopopular": "Non pode utilizar un contrasinal dos habitualmente elixidos pola xente. Por favor, escolla un contrasinal máis orixinal.",
        "password-name-match": "O seu contrasinal debe ser diferente do seu nome de usuario.",
        "password-login-forbidden": "O uso deste nome de usuario e contrasinal foi prohibido.",
        "mailmypassword": "Restablecer o contrasinal",
        "passwordremindertitle": "Novo contrasinal temporal para {{SITENAME}}",
-       "passwordremindertext": "Alguén (probablemente vostede, desde o enderezo IP $1) solicitou un novo\ncontrasinal para acceder a {{SITENAME}} ($4). Un contrasinal temporal para o usuario\n\"$2\" foi creado e fixado como \"$3\". Se esa foi a súa\nintención, necesitará acceder ao sistema e escoller un novo contrasinal agora.\nO seu contrasinal temporal caducará {{PLURAL:$5|nun día|en $5 días}}.\n\nSe foi alguén diferente o que fixo esta solicitude ou se xa se lembra do seu contrasinal\ne non o quere modificar, pode ignorar esta mensaxe e\ncontinuar a utilizar o seu contrasinal vello.",
+       "passwordremindertext": "Alguén (probablemente vostede, desde o enderezo IP $1) solicitou un novo\ncontrasinal para acceder a {{SITENAME}} ($4). Creouse un contrasinal temporal para o usuario\n\"$2\" e quedou establecido como \"$3\". Se esa foi a súa\nintención, terá que acceder ao sistema e escoller un novo contrasinal agora.\nO seu contrasinal temporal caducará {{PLURAL:$5|nun día|en $5 días}}.\n\nSe foi outra persoa a que fixo esta solicitude ou se xa se lembra do seu contrasinal\ne non o quere modificar, pode ignorar esta mensaxe e\ncontinuar a utilizar o seu contrasinal vello.",
        "noemail": "O usuario \"$1\" non posúe ningún enderezo de correo electrónico rexistrado.",
        "noemailcreate": "Ten que proporcionar un enderezo de correo electrónico válido",
        "passwordsent": "Enviouse un contrasinal novo ao enderezo de correo electrónico rexistrado de \"$1\".\nPor favor, acceda ao sistema de novo tras recibilo.",
-       "blocked-mailpassword": "O seu enderezo IP está bloqueado para editar. Tampouco se lle permite usar a función de recuperación do contrasinal para evitar abusos do sistema.",
+       "blocked-mailpassword": "O seu enderezo IP está bloqueado fronte á edición. Tampouco se lle permite usar a función de recuperación do contrasinal para evitar abusos do sistema.",
        "eauthentsent": "Envióuselle un correo electrónico de confirmación ao enderezo especificado.\nAntes de que se lle envíe calquera outro correo a esta conta terá que seguir as instrucións que aparecen nesa mensaxe para confirmar que a conta é realmente súa.",
        "throttled-mailpassword": "Enviouse un correo electrónico de restablecemento do contrasinal {{PLURAL:$1|na última hora|nas últimas $1 horas}}.\nPara evitar o abuso do sistema só se enviará unha mensaxe de restablecemento cada {{PLURAL:$1|hora|$1 horas}}.",
        "mailerror": "Produciuse un erro ao enviar o correo electrónico: $1",
-       "acct_creation_throttle_hit": "Alguén que visitou este wiki co seu enderezo IP creou {{PLURAL:$1|unha conta|$1 contas}} nos últimos ̩$2 días, que é o máximo permitido neste período de tempo.\nComo resultado, os visitantes que usen este enderezo IP non poden crear máis contas nestes intres.",
+       "acct_creation_throttle_hit": "Alguén que visitou este wiki co seu enderezo IP creou {{PLURAL:$1|unha conta|$1 contas}} nun breve período de tempo ($2), que é o máximo permitido neste período de tempo.\nComo resultado, os visitantes que usen este enderezo IP non poden crear máis contas nestes intres.",
        "emailauthenticated": "O seu enderezo de correo electrónico foi confirmado o $2 ás $3.",
        "emailnotauthenticated": "O seu enderezo de correo electrónico aínda non foi confirmado.\nNon se enviará ningunha mensaxe por ningunha das seguintes características.",
        "noemailprefs": "Especifique un enderezo de correo electrónico se quere que funcione esta opción.",
        "createacct-another-realname-tip": "O nome real é opcional.\nSe escolle dalo utilizarase para atribuír ao usuario o seu traballo.",
        "pt-login": "Acceder ao sistema",
        "pt-login-button": "Acceder ao sistema",
-       "pt-login-continue-button": "Continuar a conexión",
+       "pt-login-continue-button": "Continuar co inicio de sesión",
        "pt-createaccount": "Crear unha conta",
        "pt-userlogout": "Saír",
        "php-mail-error-unknown": "Erro descoñecido na función mail() do PHP.",
        "newpassword": "Contrasinal novo:",
        "retypenew": "Insira outra vez o novo contrasinal:",
        "resetpass_submit": "Establecer o contrasinal e acceder ao sistema",
-       "changepassword-success": "O seu contrasinal foi modificado!",
+       "changepassword-success": "Modificouse o seu contrasinal!",
        "changepassword-throttled": "Fixo demasiados intentos de acceder ao sistema.\nPor favor, agarde $1 antes de probar outra vez.",
        "botpasswords": "Contrasinais de bots",
        "botpasswords-summary": "Os <em>contrasinais de bots</em> permiten acceder a unha conta de usuario por medio da API sen usar as crecenciais de acceso da conta principal. Os dereitos de usuario dispoñibles cando se accede ao sistema cun contrasinal de bot poden estar restrinxidos.\n\nSe non sabe por que quere facer isto, probablemente signifique que non o queira facer. Ningunha persoa debería pedirlle a vostede que xere unha destas claves para entregarlla.",
        "botpasswords-label-delete": "Borrar",
        "botpasswords-label-resetpassword": "Restablecer o contrasinal",
        "botpasswords-label-grants": "Permisos aplicables:",
-       "botpasswords-help-grants": "Cada permiso dá acceso aos permisos de usuario listados que a conta xa teña. Consulte a [[Special:ListGrants|táboa de permisos]] para obter máis información.",
+       "botpasswords-help-grants": "As concesións permiten o acceso aos dereitos que xa teña a conta de usuario. A activación dunha concesión non dá acceso a ningún dereito que a súa conta de usuario non tivese doutro xeito. Consulte a [[Special:ListGrants|táboa de permisos]] para obter máis información.",
        "botpasswords-label-grants-column": "Concedido",
        "botpasswords-bad-appid": "O nome de bot \"$1\" non é válido.",
        "botpasswords-insert-failed": "Erro ao engadir o nome de bot \"$1\". Revise se xa foi engadido previamente.",
        "resetpass-abort-generic": "Unha extensión cancelou a modificación do contrasinal.",
        "resetpass-expired": "O seu contrasinal caducou. Defina un novo contrasinal para acceder.",
        "resetpass-expired-soft": "O seu contrasinal caducou e debe restablecelo. Escolla un novo contrasinal ou prema en \"{{int:authprovider-resetpass-skip-label}}\" para restablecelo máis tarde.",
-       "resetpass-validity-soft": "O seu contrasinal non é válido: $1\n\nEscolla un novo contrasinal ou prema en \"{{int:authprovider-resetpass-skip-label}}\" para restablecelo máis tarde.",
+       "resetpass-validity-soft": "O seu contrasinal non é válido: $1\n\nEscolla un novo contrasinal agora ou prema en \"{{int:authprovider-resetpass-skip-label}}\" para restablecelo máis tarde.",
        "passwordreset": "Restablecer o contrasinal",
        "passwordreset-text-one": "Encha este formulario para restablecer o seu contrasinal.",
        "passwordreset-text-many": "{{PLURAL:$1|Encha un dos campos para recibir por correo electrónico un contrasinal temporal.}}",
        "passwordreset-emaildisabled": "As funcións do correo electrónico están desactivadas neste wiki.",
        "passwordreset-username": "Nome de usuario:",
        "passwordreset-domain": "Dominio:",
-       "passwordreset-capture": "Quere ollar o correo electrónico?",
-       "passwordreset-capture-help": "Se marca esta caixa, poderá ver o correo electrónico (co contrasinal temporal) que se envía ao usuario.",
        "passwordreset-email": "Enderezo de correo electrónico:",
        "passwordreset-emailtitle": "Detalles da conta de {{SITENAME}}",
        "passwordreset-emailtext-ip": "Alguén (probablemente vostede, desde o enderezo IP $1) solicitou o restablecemento do seu\ncontrasinal de {{SITENAME}} ($4). {{PLURAL:$3|A seguinte conta de usuario está asociada|As seguintes contas de usuarios están asociadas}}\na este enderezo de correo electrónico:\n\n$2\n\n{{PLURAL:$3|Este contrasinal temporal caducará|Estes contrasinais temporais caducarán}} {{PLURAL:$5|nun día|en $5 días}}.\nDebería acceder ao sistema e elixir un novo contrasinal agora. Se outra persoa fixo esta\nsolicitude ou se lembrou o seu contrasinal orixinal e xa non o quere cambiar,\nignore esta mensaxe e continúe empregando o seu contrasinal vello.",
        "passwordreset-emailtext-user": "O usuario $1 solicitou o restablecemento do contrasinal de {{SITENAME}}\n($4). {{PLURAL:$3|A seguinte conta de usuario está asociada|As seguintes contas de usuarios están asociadas}}\na este enderezo de correo electrónico:\n\n$2\n\n{{PLURAL:$3|Este contrasinal temporal caducará|Estes contrasinais temporais caducarán}} {{PLURAL:$5|nun día|en $5 días}}.\nDebería acceder ao sistema e elixir un novo contrasinal agora. Se outra persoa fixo esta\nsolicitude ou se lembrou o seu contrasinal orixinal e xa non o quere cambiar,\nignore esta mensaxe e continúe empregando o seu contrasinal vello.",
        "passwordreset-emailelement": "Nome de usuario: \n$1\n\nContrasinal temporal: \n$2",
-       "passwordreset-emailsentemail": "Se esta é unha dirección de correo electrónico asociada á súa conta, entón enviarase un correo electrónico para o restablecemento do seu contrasinal.",
-       "passwordreset-emailsentusername": "Se hai unha dirección de correo electrónico asociada con este nome de usuario, entón enviarase un correo electrónico para o restablecemento do contrasinal.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|O correo de reinicialización do contrasinal foi enviado|Os correos de reinicialización do contrasinal foron enviados}}. {{PLURAL:$1|O nome de usuario e contrasinal móstrase aquí|A lista de nomes de usuarios e contrasinais móstranse aquí}}.",
-       "passwordreset-emailerror-capture2": "O envío do correo {{GENDER:$2|ó usuario|á usuaria}} fallou: $1 {{PLURAL:$3|O nome de usuario e contrasinal móstrase aquí|A lista de usuarios e contrasinais móstranse aquí}}.",
+       "passwordreset-emailsentemail": "Se este enderezo de correo electrónico está asociado á súa conta, entón enviarase un correo electrónico para o restablecemento do seu contrasinal.",
+       "passwordreset-emailsentusername": "Se hai un enderezo de correo electrónico asociado a este nome de usuario, entón enviarase un correo electrónico para o restablecemento do contrasinal.",
        "passwordreset-nocaller": "Cómpre proporcionar un chamador",
        "passwordreset-nosuchcaller": "O chamador non existe: $1",
-       "passwordreset-ignored": "A reinicialización do contrasinal non puido realizarse. Quizais non configurou o provedor?",
-       "passwordreset-invalideamil": "O enderezo de correo electrónico non é válido",
-       "passwordreset-nodata": "Non se indicou o nome de usuario ou a dirección de correo electrónico",
+       "passwordreset-ignored": "Non se puido completar o restablecemento do contrasinal. Quizais non configurou o provedor?",
+       "passwordreset-invalidemail": "O enderezo de correo electrónico non é válido",
+       "passwordreset-nodata": "Non se indicou nin un nome de usuario nin un enderezo de correo electrónico",
        "changeemail": "Cambiar ou eliminar o enderezo de correo electrónico",
-       "changeemail-header": "Encha este formulario para cambiar o seu enderezo de correo electrónico. Se vostede quere eliminar a asociación da dirección de correo electrónico da súa conta, deixe en branco a nova dirección de correo electrónico cando envíe o formulario.",
+       "changeemail-header": "Encha este formulario para cambiar o seu enderezo de correo electrónico. Se quere eliminar a asociación do enderezo de correo electrónico á súa conta, deixe en branco o novo enderezo de correo electrónico cando envíe o formulario.",
        "changeemail-no-info": "Debe rexistrarse para acceder directamente a esta páxina.",
        "changeemail-oldemail": "Enderezo de correo electrónico actual:",
        "changeemail-newemail": "Novo enderezo de correo electrónico:",
-       "changeemail-newemail-help": "Este campo debe deixarse en branco se quere eliminar o seu enderezo de correo electrónico. Non será capaz de redefinir a súa clave nin recibir mensaxes electrónicas desta wiki se elimina o correo electrónico.",
+       "changeemail-newemail-help": "Este campo debe deixarse en branco se quere eliminar o seu enderezo de correo electrónico. Non poderá restablecer o seu contrasinal se o esquece nin recibir mensaxes de correo electrónico desde este wiki se elimina o enderezo.",
        "changeemail-none": "(ningún)",
        "changeemail-password": "O seu contrasinal en {{SITENAME}}:",
        "changeemail-submit": "Cambiar o correo electrónico",
        "anoneditwarning": "<strong>Aviso:</strong> Non accedeu ao sistema. O seu enderezo IP será visible se fai algunha edición. Se <strong>[$1 accede ao sistema]</strong> ou <strong>[$2 crea unha conta]</strong>, as súas edicións serán atribuídas ao seu nome de usuario e obterá outros beneficios.",
        "anonpreviewwarning": "''Non accedeu ao sistema. Se garda a páxina, o seu enderezo IP quedará rexistrado no historial de edicións.''",
        "missingsummary": "'''Aviso:''' Esqueceu incluír o texto do campo resumo.\nSe preme en \"{{int:savearticle}}\" a súa edición gardarase sen ningunha descrición da edición.",
-       "selfredirect": "<strong>Atención:</strong> Está redirecionando esta páxina a ela mesma. Vostede pode ter especificado a páxina incorrecta para a redireción, ou pode que estea a editar a páxina incorrecta. Se preme \"{{int:savearticle}}\" de novo, crearase a redireción de tódolos xeitos.",
+       "selfredirect": "<strong>Atención:</strong> Está redirixindo esta páxina a si mesma.\nQuizais especificou incorrectamente a páxina de destino ou poida que estea a editar unha páxina errónea.\nSe preme en \"{{int:savearticle}}\" de novo, crearase a redireción de calquera xeito.",
        "missingcommenttext": "Por favor, escriba un comentario a continuación.",
-       "missingcommentheader": "<strong>Aviso:</strong> Non escribiu ningún texto no asunto deste comentario.\nSe preme sobre \"{{int:savearticle}}\", a súa edición gardarase sen el.",
+       "missingcommentheader": "<strong>Aviso:</strong> Non escribiu ningún texto no asunto deste comentario.\nSe preme en \"{{int:savearticle}}\" de novo, a súa edición gardarase sen el.",
        "summary-preview": "Vista previa do resumo:",
        "subject-preview": "Vista previa do asunto:",
        "previewerrortext": "Produciuse un erro ao intentar previsualizar os cambios.",
        "blockedtitle": "O usuario está bloqueado",
-       "blockedtext": "'''O seu nome de usuario ou enderezo IP foi bloqueado.'''\n\nO bloqueo foi realizado por $1.\nA razón que deu foi ''$2''.\n\n* Inicio do bloqueo: $8\n* Caducidade do bloqueo: $6\n* Pretendeuse bloquear: $7\n\nPode contactar con $1 ou con calquera outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir este bloqueo.\nNon pode empregar a característica \"Enviar un correo electrónico a este usuario\" a non ser que dispoña dun enderezo electrónico válido rexistrado nas súas [[Special:Preferences|preferencias de usuario]] e que o seu uso non fose bloqueado.\nO seu enderezo IP actual é $3 e o ID do bloqueo é #$5.\nPor favor, inclúa eses datos nas consultas que faga.",
+       "blockedtext": "<strong>Bloqueouse o seu nome de usuario ou enderezo IP.</strong>\n\n$1 estableceu o bloqueo.\nO motivo que achegou foi <em>$2</em>.\n\n* Inicio do bloqueo: $8\n* Caducidade do bloqueo: $6\n* Pretendeuse bloquear: $7\n\nPode contactar con $1 ou con calquera outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir este bloqueo.\nNon pode empregar a característica \"Enviar un correo electrónico a este usuario\" a non ser que dispoña dun enderezo electrónico válido rexistrado nas súas [[Special:Preferences|preferencias de usuario]] e que o seu uso non fose bloqueado.\nO seu enderezo IP actual é $3 e o identificador do bloqueo é #$5.\nPor favor, inclúa todos estes datos nas consultas que faga.",
        "autoblockedtext": "O seu enderezo IP foi bloqueado automaticamente porque foi empregado por outro usuario que foi bloqueado por $1.\nA razón que deu foi a seguinte:\n\n:''$2''\n\n* Inicio do bloqueo: $8\n* Caducidade do bloqueo: $6\n* Pretendeuse bloquear: $7\n\nPode contactar con $1 ou con calquera outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir este bloqueo.\n\nTeña en conta que non pode empregar a característica \"Enviar un correo electrónico a este usuario\" a non ser que dispoña dun enderezo electrónico válido rexistrado nas súas [[Special:Preferences|preferencias de usuario]] e e que o seu uso non fose bloqueado.\n\nO seu enderezo IP actual é $3 e o ID do bloqueo é #$5.\nPor favor, inclúa eses datos nas consultas que faga.",
        "blockednoreason": "non se deu ningunha razón",
        "whitelistedittext": "Debe $1 para poder editar páxinas.",
        "userpage-userdoesnotexist": "A conta de usuario \"$1\" non está rexistrada.\nComprobe se desexa crear/editar esta páxina.",
        "userpage-userdoesnotexist-view": "A conta de usuario \"$1\" non está rexistrada.",
        "blocked-notice-logextract": "Este usuario está bloqueado.\nVelaquí está a última entrada do rexistro de bloqueos, por se quere consultala:",
-       "clearyourcache": "<strong>Nota:</strong> Despois de gardar, cómpre limpar a memoria caché do seu navegador para ver os cambios.\n* <strong>Firefox/Safari:</strong> Prema <em>Maiúsculas</em> á vez que en <em>Recargar</em>, ou prema en <em>Ctrl-F5</em> ou <em>Ctrl-R</em> (<em>⌘-R</em> nos Mac)\n* <strong>Google Chrome:</strong> Prema en <em>Ctrl-Maiús-R</em> (<em>⌘-Maiús-R</em> nos Mac)\n* <strong>Internet Explorer:</strong> Prema <em>Ctrl</em> ao tempo que fai clic en <em>Refrescar</em>, ou prema en <em>Ctrl-F5</em>\n* <strong>Opera:<strong> Vaia a  <em>Menú → Configuración</em> (<em>Opera → Preferencias</em> nun Mac) e logo a <em>Privacidade & seguridade → Limpar datos de navegación → Ficheiros e imaxes na caché</em>.",
+       "clearyourcache": "<strong>Nota:</strong> Despois de gardar, cómpre limpar a memoria caché do seu navegador para ver os cambios.\n* <strong>Firefox/Safari:</strong> Prema <em>Maiúsculas</em> á vez que en <em>Recargar</em>, ou prema en <em>Ctrl-F5</em> ou <em>Ctrl-R</em> (<em>⌘-R</em> nos Mac).\n* <strong>Google Chrome:</strong> Prema en <em>Ctrl-Maiús-R</em> (<em>⌘-Maiús-R</em> nos Mac).\n* <strong>Internet Explorer:</strong> Prema <em>Ctrl</em> ao tempo que fai clic en <em>Refrescar</em>, ou prema en <em>Ctrl-F5</em>.\n* <strong>Opera:</strong> Vaia a <em>Menú → Configuración</em> (<em>Opera → Preferencias</em> nos Mac) e logo a <em>Privacidade e seguridade → Limpar os datos de navegación → Ficheiros e imaxes na caché</em>.",
        "usercssyoucanpreview": "'''Nota:''' Use o botón \"{{int:showpreview}}\" para verificar o novo CSS antes de gardalo.",
        "userjsyoucanpreview": "<strong>Nota:</strong> Use o botón \"{{int:showpreview}}\" para verificar o novo JavaScript antes de gardalo.",
        "usercsspreview": "'''Lembre que só está vendo a vista previa do seu CSS de usuario.'''\n'''Este aínda non foi gardado!'''",
        "userinvalidcssjstitle": "<strong>Aviso:</strong> Non hai ningunha aparencia chamada \"$1\".\nLembre que as páxinas .css e .js personalizadas utilizan un título en minúsculas, como por exemplo \"{{ns:user}}:Exemplo/vector.css\" no canto de \"{{ns:user}}:Exemplo/Vector.css\".",
        "updated": "(Actualizado)",
        "note": "'''Nota:'''",
-       "previewnote": "'''Lembre que esta é só unha vista previa e que aínda non gardou os seus cambios!'''",
+       "previewnote": "<strong>Lembre que esta é só unha vista previa.</strong>\nAínda non gardou os seus cambios!",
        "continue-editing": "Ir ata a caixa de edición",
        "previewconflict": "Esta vista previa mostra o texto na área superior tal e como aparecerá se escolle gardar.",
-       "session_fail_preview": "Sentímolo! Non puidemos procesar a súa edición porque se perderon os datos de inicio da sesión.\n\nPoida que se pechase a súa sesión. <strong>Por favor, verifique que ten a sesión aberta e probe de novo.</strong>\nEn caso de que siga sen funcionar, intente [[Special:UserLogout|saír]] e volver entrar na súa conta e verifique que o seu navegador permite o uso de cookies neste sitio.",
-       "session_fail_preview_html": "Sentímolo! Non foi posible procesar a edición debido á pérdida de datos da súa sesión.\n\n<em>Como a wiki {{SITENAME}} posibilita o uso de HTML puro, a vista previa está oculta por precaución contra ataques con JavaScript.</em>\n\n<strong>Se este é un intento lexítimo de edición probe de novo, por favor</strong>. \nEn caso de que continúe sen funcionar, intente [[Special:UserLogout|saír]] e volver a entrar na súa conta, e verifique se o seu navegador permite o uso de ''cookies'' deste sitio.",
+       "session_fail_preview": "Sentímolo! Non puidemos procesar a súa edición porque se perderon os datos de inicio da sesión.\n\nPoida que se pechase a súa sesión. <strong>Por favor, comprobe que ten a sesión aberta e probe de novo.</strong>\nEn caso de que siga sen funcionar, intente [[Special:UserLogout|saír]] e volver entrar na súa conta e verifique que o seu navegador permite o uso de cookies neste sitio.",
+       "session_fail_preview_html": "Sentímolo! Non foi posible procesar a edición debido á perda dos datos da súa sesión.\n\n<em>Dado que {{SITENAME}} ten activado o uso de HTML puro, a vista previa está oculta por precaución contra ataques mediante JavaScript.</em>\n\n<strong>Se este é un intento lexítimo de edición, probe de novo.</strong>\nEn caso de que siga sen funcionar, intente [[Special:UserLogout|saír]] e volver entrar na súa conta e verifique que o seu navegador permite o uso de cookies neste sitio.",
        "token_suffix_mismatch": "'''Rexeitouse a súa edición porque o seu cliente confundiu os signos de puntuación na edición.'''\nRexeitouse a edición para evitar que se corrompa o texto do artigo.\nIsto pode acontecer porque estea a empregar un servizo de proxy anónimo defectuoso baseado na web.",
        "edit_form_incomplete": "'''Algunhas partes do formulario de edición non chegaron ao servidor; comprobe que a súa modificación está intacta e inténteo de novo.'''",
        "editing": "Editando \"$1\"",
        "nonunicodebrowser": "'''Atención: O seu navegador non soporta o Unicode.'''\nExiste unha solución que lle permite editar páxinas con seguridade: os caracteres non incluídos no ASCII aparecerán na caixa de edición como códigos hexadecimais.",
        "editingold": "'''Atención: Está editando unha revisión vella desta páxina.'''\nSe a garda, perderanse os cambios realizados tras esta revisión.",
        "yourdiff": "Diferenzas",
-       "copyrightwarning": "Por favor, teña en conta que todas as contribucións a {{SITENAME}} considéranse publicadas baixo a $2 (vexa $1 para máis detalles). Se non quere que o que escriba se edite sen piedade e se redistribúa sen límites, entón non o envíe aquí.<br />\nAo mesmo tempo, prométanos que o que escribiu é da súa autoría ou que está copiado dun recurso do dominio público ou que permite unha liberdade semellante.\n'''NON ENVÍE MATERIAL CON DEREITOS DE AUTOR SEN PERMISO!'''",
-       "copyrightwarning2": "Por favor, decátese de que todas as súas contribucións a {{SITENAME}} poden ser editadas, alteradas ou eliminadas por outras persoas. Se non quere que os seus escritos sexan editados sen piedade, non os publique aquí.<br />\nDo mesmo xeito, comprométese a que o que vostede escriba sexa da súa autoría ou copiado dunha fonte de dominio público ou recurso público semellante (vexa $1 para detalles).\n'''NON ENVÍE SEN PERMISO TRABALLOS CON DEREITOS DE COPIA!'''",
+       "copyrightwarning": "Por favor, teña en conta que todas as contribucións feitas en {{SITENAME}} se consideran publicadas baixo a $2 (consulte $1 para obter máis detalles).\nSe non quere que os seus escritos sexan editados sen piedade e redistribuídos sen límites, entón non os publique aquí.<br />\nDo mesmo xeito, comprométese a que o que vostede escriba é da súa autoría ou está copiado dun recurso de dominio público ou que procede dunha fonte libre.\n<strong>Non envíe material con dereitos de autoría sen permiso!</strong>",
+       "copyrightwarning2": "Por favor, teña en conta que todas as contribucións feitas en {{SITENAME}} poden ser editadas, alteradas ou eliminadas por outras persoas.\nSe non quere que os seus escritos sexan editados sen piedade, entón non os publique aquí.<br />\nDo mesmo xeito, comprométese a que o que vostede escriba é da súa autoría ou está copiado dun recurso de dominio público ou que procede dunha fonte libre (consulte $1 para obter máis detalles).\n<strong>Non envíe material con dereitos de autoría sen permiso!</strong>",
        "editpage-cannot-use-custom-model": "O modelo de contido desta páxina non se pode modificar.",
        "longpageerror": "'''Erro: O texto que pretende gardar ocupa {{PLURAL:$1|$1 kilobyte|$1 kilobytes}}, e existe un límite dun máximo de {{PLURAL:$2|$2 kilobyte|$2 kilobytes}}.'''\nPolo tanto, non se pode gardar.",
-       "readonlywarning": "<strong>Atención: A base de datos foi pechada para facer mantemento, polo que non vai poder gardar as súas edicións polo de agora.</strong>\nSe cadra, pode cortar e pegar o texto nun ficheiro de texto e gardalo para despois.\n\nO administrador de sistemas que a pechou deu esta explicación: $1",
+       "readonlywarning": "<strong>Atención: Pechouse a base de datos para facer mantemento, polo que non vai poder gardar as súas edicións polo de agora.</strong>\nSe cadra, pode cortar e pegar o texto nun ficheiro de texto e gardalo para despois.\n\nO administrador do sistema que a pechou deu esta explicación: $1",
        "protectedpagewarning": "'''Aviso: Esta páxina foi protexida de xeito que só os usuarios con privilexios de administrador a poidan editar.'''\nVelaquí está a última entrada no rexistro, por se quere consultala:",
        "semiprotectedpagewarning": "'''Nota:''' Esta páxina foi protexida de xeito que só os usuarios rexistrados a poidan editar.\nVelaquí está a última entrada no rexistro, por se quere consultala:",
-       "cascadeprotectedwarning": "<strong>Aviso:</strong> Esta páxina foi protexida de xeito que só a poden editar os usuarios con privilexios de administrador debido a que está transcluída {{PLURAL:$1|na seguinte páxina protexida|nas seguintes páxinas protexidas}} coa opción \"protección en serie\" activada:",
+       "cascadeprotectedwarning": "<strong>Atención:</strong> Protexeuse esta páxina de xeito que só a poden editar os usuarios con privilexios de administrador debido a que está transcluída {{PLURAL:$1|na seguinte páxina protexida|nas seguintes páxinas protexidas}} coa opción \"protección en serie\" activada:",
        "titleprotectedwarning": "'''Aviso: Esta páxina foi protexida de xeito que [[Special:ListGroupRights|só algúns usuarios]] a poidan crear.'''\nVelaquí está a última entrada no rexistro, por se quere consultala:",
        "templatesused": "{{PLURAL:$1|Modelo usado|Modelos usados}} nesta páxina:",
        "templatesusedpreview": "{{PLURAL:$1|Modelo usado|Modelos usados}} nesta vista previa:",
        "template-semiprotected": "(semiprotexido)",
        "hiddencategories": "Esta páxina forma parte {{PLURAL:$1|dunha categoría oculta|de $1 categorías ocultas}}:",
        "edittools": "<!-- O texto que apareza aquí mostrarase por debaixo dos formularios de edición e envío. -->",
-       "nocreatetext": "{{SITENAME}} ten restrinxida a posibilidade de crear páxinas novas.\nPode volver e editar unha páxina que xa existe ou, se non, [[Special:UserLogin|rexistrarse ou crear unha conta]].",
+       "nocreatetext": "{{SITENAME}} ten restrinxida a posibilidade de crear páxinas novas.\nPode volver e editar unha páxina que xa existe ou ben [[Special:UserLogin|acceder ao sistema ou crear unha conta]].",
        "nocreate-loggedin": "Non ten os permisos necesarios para crear páxinas novas.",
        "sectioneditnotsupported-title": "A edición de seccións non está soportada",
        "sectioneditnotsupported-text": "A edición de seccións non está soportada nesta páxina.",
        "permissionserrors": "Erro de permisos",
        "permissionserrorstext": "Non ten os permisos necesarios para facelo {{PLURAL:$1|pola seguinte razón|polas seguintes razóns}}:",
        "permissionserrorstext-withaction": "Non ten os permisos necesarios para $2, {{PLURAL:$1|pola seguinte razón|polas seguintes razóns}}:",
-       "contentmodelediterror": "Non pode editar esta revisión porque o seu modelo de contido é <code>$1</code>, o cal difire do modelo de contido actual da páxina <code>$2</code>.",
+       "contentmodelediterror": "Non pode editar esta revisión porque o seu modelo de contido é \"<code>$1</code>\", o cal difire do modelo de contido \"<code>$2</code>\", que é o actual da páxina.",
        "recreate-moveddeleted-warn": "'''Atención: Vai volver crear unha páxina que xa foi eliminada anteriormente.'''\n\nDebería considerar se é apropiado continuar a editar esta páxina.\nVelaquí están o rexistro de borrados e mais o de traslados desta páxina, por se quere consultalos:",
        "moveddeleted-notice": "Esta páxina foi borrada.\nA continuación pódese ver o rexistro de borrados e traslados desta páxina, por se quere consultalos.",
-       "moveddeleted-notice-recent": "Sentímolo, esta página foi borrada recentemente (dentro das últimas 24 horas).\nO rexistro de borrado e traslado da páxina amósanse abaixo como referencia.",
+       "moveddeleted-notice-recent": "Sentímolo, borrouse esta páxina recentemente (nas últimas 24 horas).\nVelaquí están o rexistro de borrados e traslados da páxina, por se os quere consultar.",
        "log-fulllog": "Ver o rexistro completo",
        "edit-hook-aborted": "A edición foi abortada polo asociador.\nEste non deu ningunha explicación.",
        "edit-gone-missing": "Non se pode actualizar a páxina.\nSemella que foi borrada.",
        "invalid-content-data": "Datos de contido inválidos",
        "content-not-allowed-here": "O contido \"$1\" non está permitido na páxina \"[[$2]]\"",
        "editwarning-warning": "Deixar esta páxina pode causar a perda de calquera cambio feito.\nSe accedeu ao sistema, pode desactivar esta mensaxe de advertencia na sección \"{{int:prefs-editing}}\" das súas preferencias.",
-       "editpage-invalidcontentmodel-title": "Modelo de contido non válido",
-       "editpage-invalidcontentmodel-text": "O modelo de contido \"$1\" non é válido.",
+       "editpage-invalidcontentmodel-title": "O modelo de contido non está soportado",
+       "editpage-invalidcontentmodel-text": "O modelo de contido \"$1\" non está soportado.",
        "editpage-notsupportedcontentformat-title": "Formato de contido non admitido",
        "editpage-notsupportedcontentformat-text": "O formato de contido $1 non é compatible co modelo de contido $2.",
        "content-model-wikitext": "texto wiki",
        "content-json-empty-object": "Obxecto baleiro",
        "content-json-empty-array": "Matriz baleira",
        "deprecated-self-close-category": "Páxinas que usan etiquetas HTML de auto-pechado non válidas",
-       "deprecated-self-close-category-desc": "Páxinas que conteñen unha etiqueta HTML de auto-pechado non válida, como <code>&lt;b/></code> ou <code>&lt;span/></code>. O comportamento destas etiquetas vai cambiar para gardar a consistencia coa especificación HTML5, polo que o seu uso no texto wiki está desbotado.",
-       "duplicate-args-warning": "<strong>Advertencia:</strong> [[:$1]] está chamando a [[:$2]] con máis dun valor para o parámetro \"$3\". Só se usará o último valor proporcionado.",
+       "deprecated-self-close-category-desc": "A páxina contén algunha etiqueta HTML de auto-pechado non válida, como <code>&lt;b/></code> ou <code>&lt;span/></code>. O comportamento destas etiquetas vai cambiar axiña para gardar a consistencia coa especificación HTML5, polo que cómpre desbotar o seu uso no texto wiki.",
+       "duplicate-args-warning": "<strong>Atención:</strong> \"[[:$1]]\" está chamando a \"[[:$2]]\" con máis dun valor para o parámetro \"$3\". Só se usará o último valor proporcionado.",
        "duplicate-args-category": "Páxinas con argumentos duplicados nas chamadas aos modelos",
        "duplicate-args-category-desc": "Esta páxina contén as chamadas aos modelos que utilizan argumentos duplicados, como <code><nowiki>{{exemplo|bar=1|bar=2}}</nowiki></code> ou <code><nowiki>{{exemplo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "'''Aviso:''' Esta páxina contén demasiadas chamadas a funcións analíticas custosas.\n\nDebe ter menos {{PLURAL:$2|dunha chamada|de $2 chamadas}}, e agora hai $1.",
        "undo-summary": "Desfíxose a edición $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|conversa]])",
        "undo-summary-username-hidden": "Desfíxose a edición $1 dun usuario agochado",
        "cantcreateaccount-text": "A creación de contas desde este enderezo IP ('''$1''') foi bloqueada por [[User:$3|$3]].\n\nA razón dada por $3 foi ''$2''",
-       "cantcreateaccount-range-text": "O usuario [[User:$3|$3]] bloqueou a creación de contas desde enderezos IP no rango <strong>$1</strong>, no que se inclúe o seu enderezo IP (<strong>$4</strong>).\n\nA razón que deu $3 foi <em>$2</em>.",
+       "cantcreateaccount-range-text": "O usuario [[User:$3|$3]] bloqueou a creación de contas desde enderezos IP no rango <strong>$1</strong>, no que se atopa o seu enderezo IP (<strong>$4</strong>).\n\nA razón que deu $3 foi <em>$2</em>.",
        "viewpagelogs": "Ver os rexistros desta páxina",
        "nohistory": "Esta páxina non posúe ningún historial de edicións.",
        "currentrev": "Revisión actual",
        "history-feed-title": "Historial de revisións",
        "history-feed-description": "Historial de revisións desta páxina no wiki",
        "history-feed-item-nocomment": "$1 o $2",
-       "history-feed-empty": "A páxina solicitada non existe.\nPuido borrarse ou moverse a outro nome.\nProbe a [[Special:Search|buscar no wiki]] para atopar as páxinas relacionadas.",
+       "history-feed-empty": "A páxina solicitada non existe.\nPoida que se borrase do wiki ou que se trasladase a outro nome.\nProbe a [[Special:Search|buscar no wiki]] para atopar as páxinas novas relevantes.",
        "history-edit-tags": "Editar as etiquetas das revisións seleccionadas",
        "rev-deleted-comment": "(resumo de edición eliminado)",
        "rev-deleted-user": "(nome de usuario eliminado)",
        "search-external": "Procura externa",
        "searchdisabled": "As procuras en {{SITENAME}} están deshabilitadas por cuestións de rendemento.\nMentres tanto pode procurar usando o Google.\nNote que os seus índices do contido de {{SITENAME}} poden estar desactualizados.",
        "search-error": "Produciuse un erro durante a procura: $1",
+       "search-warning": "Houbo un aviso ó facer a buscaː $1",
        "preferences": "Preferencias",
        "mypreferences": "Preferencias",
        "prefs-edits": "Número de edicións:",
        "rows": "Filas:",
        "columns": "Columnas:",
        "searchresultshead": "Procurar",
-       "stub-threshold": "Límite superior de tamaño para o formato das ligazóns cara bosquexos ($1):",
+       "stub-threshold": "Límite superior de tamaño para o formato das ligazóns cara bosquexos ($1):",
        "stub-threshold-sample-link": "exemplo",
        "stub-threshold-disabled": "Desactivado",
        "recentchangesdays": "Número de días a mostrar nos cambios recentes:",
        "prefs-help-recentchangescount": "Isto inclúe os cambios recentes, os historiais e mais os rexistros.",
        "prefs-help-watchlist-token2": "Esta é a clave secreta da fonte de novas web para a súa lista de vixilancia.\nCalquera persoa que a saiba poderá ler a súa lista de vixilancia; non comparta esta clave.\n[[Special:ResetTokens|Prema aquí se necesita restablecela]].",
        "savedprefs": "Gardáronse as súas preferencias.",
-       "savedrights": "Gardáronse os permisos de {{GENDER:$1|$1}}.",
+       "savedrights": "Gardáronse os grupos de {{GENDER:$1|usuario|usuaria}} de $1.",
        "timezonelegend": "Fuso horario:",
        "localtime": "Hora local:",
        "timezoneuseserverdefault": "Usar a hora do servidor por defecto ($1)",
        "prefs-help-variant": "A variante ou ortografía preferida na que mostrar o contido das páxinas deste wiki.",
        "yournick": "Sinatura:",
        "prefs-help-signature": "Os comentarios feitos nas páxinas de conversa deben asinarse con catro tiles (\"<nowiki>~~~~</nowiki>\"), que se converterán na súa sinatura con data e hora.",
-       "badsig": "Sinatura non válida; comprobe o código HTML utilizado.",
+       "badsig": "A sinatura non é válida.\nComprobe as etiquetas HTML.",
        "badsiglength": "A súa sinatura é demasiado longa.\nHa de ter menos {{PLURAL:$1|dun carácter|de $1 caracteres}}.",
        "yourgender": "Cal das seguintes oracións referidas a vostede é a máis axeitada?",
        "gender-unknown": "Ao facer mención á súa persoa, o software empregará verbas de xénero neutro sempre que sexa posible",
        "prefswarning-warning": "Fixo cambios nas súas preferencias que aínda non se gardaron.\nSe deixa esta páxina sen premer en \"$1\", non se actualizarán as súas preferencias.",
        "prefs-tabs-navigation-hint": "Consello: Pode empregar as frechas esquerda e dereita para navegar polas lapelas da lista.",
        "userrights": "Xestión dos dereitos de usuario",
-       "userrights-lookup-user": "Administrar os grupos do usuario",
+       "userrights-lookup-user": "Seleccionar un usuario",
        "userrights-user-editname": "Escriba un nome de usuario:",
-       "editusergroup": "Editar os grupos {{GENDER:$1|do usuario|da usuaria}}",
+       "editusergroup": "Cargar os grupos de usuario",
        "editinguser": "Mudando os dereitos {{GENDER:$1|do usuario|da usuaria}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Editar os grupos do usuario",
+       "userrights-viewusergroup": "Consultar os grupos do usuario",
        "saveusergroups": "Gardar os grupos {{GENDER:$1|do usuario|da usuaria}}",
        "userrights-groupsmember": "Membro de:",
        "userrights-groupsmember-auto": "Membro implícito de:",
        "userrights-reason": "Motivo:",
        "userrights-no-interwiki": "Non ten os permisos necesarios para editar os dereitos de usuario noutros wikis.",
        "userrights-nodatabase": "A base de datos \"$1\" non existe ou non é local.",
-       "userrights-nologin": "Debe [[Special:UserLogin|acceder ao sistema]] cunta conta de administrador para asignar dereitos de usuario.",
-       "userrights-notallowed": "Non dispón dos permisos necesarios para asignar ou retirar dereitos de usuario.",
        "userrights-changeable-col": "Os grupos que pode cambiar",
        "userrights-unchangeable-col": "Os grupos que non pode cambiar",
        "userrights-conflict": "Hai un conflito na modificación dos dereitos de usuario! Por favor, revíseo e confirme os seus cambios.",
-       "userrights-removed-self": "Retirou os seus propios dereitos. Polo tanto, xa non ten acceso a esta páxina.",
        "group": "Grupo:",
        "group-user": "Usuarios",
        "group-autoconfirmed": "Usuarios autoconfirmados",
        "right-siteadmin": "Pechar e abrir a base de datos",
        "right-override-export-depth": "Exportar páxinas incluíndo as páxinas ligadas ata unha profundidade de 5",
        "right-sendemail": "Enviar correos electrónicos a outros usuarios",
-       "right-passwordreset": "Ver os correos electrónicos de restablecemento de contrasinais",
        "right-managechangetags": "Crear e (des)activar [[Special:Tags|etiquetas]]",
        "right-applychangetags": "Aplicar [[Special:Tags|etiquetas]] xunto coas modificacións propias",
        "right-changetags": "Engadir e quitar [[Special:Tags|etiquetas]] arbitrarias a revisións individuais e entradas do rexistro",
        "grant-basic": "Dereitos básicos",
        "grant-viewdeleted": "Ver ficheiros e páxinas eliminados",
        "grant-viewmywatchlist": "Ver a súa lista de vixilancia",
-       "grant-viewrestrictedlogs": "Ver as entradas de rexistro confidenciais",
+       "grant-viewrestrictedlogs": "Ver as entradas de rexistro restrinxidas",
        "newuserlogpage": "Rexistro de creación de usuarios",
        "newuserlogpagetext": "Este é un rexistro de creación de contas de usuario.",
        "rightslog": "Rexistro de dereitos de usuario",
        "action-upload_by_url": "cargar este ficheiro desde un enderezo URL",
        "action-writeapi": "usar a escritura API",
        "action-delete": "borrar esta páxina",
-       "action-deleterevision": "borrar esta revisión",
-       "action-deletedhistory": "ver o historial borrado desta páxina",
+       "action-deleterevision": "borrar revisións",
+       "action-deletelogentry": "borrar entradas do rexistro",
+       "action-deletedhistory": "ver o historial borrado dunha páxina",
+       "action-deletedtext": "ver o texto dunha revisión borrada",
        "action-browsearchive": "procurar páxinas borradas",
-       "action-undelete": "restaurar esta páxina",
-       "action-suppressrevision": "revisar e restaurar esta revisión agochada",
+       "action-undelete": "restaurar páxinas",
+       "action-suppressrevision": "revisar e restaurar revisións agochadas",
        "action-suppressionlog": "ver este rexistro privado",
        "action-block": "bloquear o usuario fronte á edición",
        "action-protect": "cambiar o nivel de protección desta páxina",
        "action-userrights-interwiki": "editar os permisos de usuario dos usuarios doutros wikis",
        "action-siteadmin": "bloquear ou desbloquear a base de datos",
        "action-sendemail": "enviar correos electrónicos",
+       "action-editmyoptions": "Editar as súas preferencias",
        "action-editmywatchlist": "editar a súa lista de vixilancia",
        "action-viewmywatchlist": "ver a súa lista de vixilancia",
        "action-viewmyprivateinfo": "ver a súa información privada",
        "uploadstash-badtoken": "A acción fallou, probablemente porque caducou a información de acceso. Por favor, inténteo de novo.",
        "uploadstash-errclear": "Fallou o borrado de ficheiros.",
        "uploadstash-refresh": "Actualizar a lista de ficheiros",
-       "uploadstash-thumbnail": "ver miniatura",
+       "uploadstash-thumbnail": "ver miniatura",
        "uploadstash-exception": "Imposible gardar a subida na reserva ($1): \"$2\".",
        "invalid-chunk-offset": "Desprazamento inválido do fragmento",
        "img-auth-accessdenied": "Acceso rexeitado",
        "http-bad-status": "Houbo un problema durante a solicitude HTTP: $1 $2",
        "upload-curl-error6": "Non se puido acceder ao enderezo URL",
        "upload-curl-error6-text": "Non se puido acceder ao enderezo URL especificado.\nComprobe que ese enderezo URL é correcto e que o sitio está activo.",
-       "upload-curl-error28": "Rematou o tempo de espera",
+       "upload-curl-error28": "Rematou o tempo de espera da subida",
        "upload-curl-error28-text": "O sitio tardou demasiado en responder.\nPor favor, comprobe que está activo, agarde un anaco e inténteo de novo.\nTamén pode reintentalo cando haxa menos actividade.",
        "license": "Licenza:",
        "license-header": "Licenza",
        "filerevert-defaultcomment": "Volveuse á versión do $1 ás $2 ($3)",
        "filerevert-submit": "Reverter",
        "filerevert-success": "Reverteuse \"'''[[Media:$1|$1]]'''\" á [$4 versión do $2 ás $3].",
-       "filerevert-badversion": "Non existe unha versión local anterior deste ficheiro coa data e hora indicadas.",
-       "filerevert-identical": "A versión actual do ficheiro é igual á seleccionada.",
+       "filerevert-badversion": "Non existe ningunha versión local anterior deste ficheiro coa data e hora indicadas.",
+       "filerevert-identical": "A versión actual do ficheiro é idéntica á seleccionada.",
        "filedelete": "Borrar \"$1\"",
        "filedelete-legend": "Eliminar un ficheiro",
        "filedelete-intro": "Está a piques de eliminar o ficheiro \"'''[[Media:$1|$1]]'''\" xunto con todo o seu historial.",
        "apisandbox-jsonly": "É preciso activar o JavaScript para usar a zona de probas.",
        "apisandbox-api-disabled": "API está desactivado neste sitio.",
        "apisandbox-intro": "Use esta páxina para experimentar co <strong>servizo web da API de MediaWiki</strong>.\nConsulte a [[mw:API:Main page| documentación da API]] para obter máis información sobre o uso da API. Exemplo: [https://www.mediawiki.org/wiki/API#A_simple_example obter o contido dunha páxina de inicio]. Seleccione unha acción para ollar máis exemplos.\n\nTeña en conta que, aínda que esta é unha páxina de probas, as accións que realice nesta páxina poden modificar o wiki.",
-       "apisandbox-fullscreen": "Expandir panel",
+       "apisandbox-fullscreen": "Expandir panel",
        "apisandbox-fullscreen-tooltip": "Expande o panel da zona de probas para encher a pantalla do navegador.",
        "apisandbox-unfullscreen": "Mostrar a páxina",
-       "apisandbox-unfullscreen-tooltip": "Reduce o panel da zona de probas, así as ligazóns de navegación MediaWiki están dispoñibles.",
+       "apisandbox-unfullscreen-tooltip": "Reduce o panel da zona de probas para que as ligazóns de navegación de MediaWiki estean dispoñibles.",
        "apisandbox-submit": "Facer a solicitude",
        "apisandbox-reset": "Limpar",
        "apisandbox-retry": "Reintentar",
-       "apisandbox-loading": "Cargando información para módulo de API \"$1\"...",
-       "apisandbox-load-error": "Houbo un erro mentres se cargaba a información do módulo API \"$1\": $2",
-       "apisandbox-no-parameters": "O módulo de API non ten parámetros.",
+       "apisandbox-loading": "Cargando a información para módulo \"$1\" da API...",
+       "apisandbox-load-error": "Produciuse un erro mentres se cargaba a información do módulo \"$1\" da API: $2",
+       "apisandbox-no-parameters": "Este módulo da API non ten parámetros.",
        "apisandbox-helpurls": "Ligazóns de axuda",
        "apisandbox-examples": "Exemplos",
        "apisandbox-dynamic-parameters": "Parámetros adicionais",
-       "apisandbox-dynamic-parameters-add-label": "Engadir parámetro:",
+       "apisandbox-dynamic-parameters-add-label": "Engadir un parámetro:",
        "apisandbox-dynamic-parameters-add-placeholder": "Nome do parámetro",
        "apisandbox-dynamic-error-exists": "Xa existe un parámetro co nome \"$1\".",
        "apisandbox-deprecated-parameters": "Parámetros obsoletos",
-       "apisandbox-fetch-token": "Auto-enchido do identificador",
+       "apisandbox-fetch-token": "Encher automaticamente o identificador",
        "apisandbox-submit-invalid-fields-title": "Algúns campos non son válidos",
        "apisandbox-submit-invalid-fields-message": "Por favor, amañe os campos marcados e inténteo de novo.",
        "apisandbox-results": "Resultados",
        "apisandbox-sending-request": "Enviando a petición á API...",
        "apisandbox-loading-results": "Recibindo os resultados da API...",
-       "apisandbox-results-error": "Houbo un erro mentres se cargaba a resposta á consulta da API: $1.",
+       "apisandbox-results-error": "Produciuse un erro mentres se cargaba a resposta da petición á API: $1.",
        "apisandbox-request-url-label": "URL da solicitude:",
        "apisandbox-request-time": "Duración da solicitude: {{PLURAL:$1|$1 ms}}",
-       "apisandbox-results-fixtoken": "Correxir identificador e reenviar",
-       "apisandbox-results-fixtoken-fail": "Erro ó recuperar o identificador \"$1\".",
-       "apisandbox-alert-page": "Os campos nesta páxina non son válidos.",
+       "apisandbox-results-fixtoken": "Corrixir o identificador e reenviar",
+       "apisandbox-results-fixtoken-fail": "Erro ao recuperar o identificador \"$1\".",
+       "apisandbox-alert-page": "Os campos desta páxina non son válidos.",
        "apisandbox-alert-field": "O valor deste campo non é válido.",
        "apisandbox-continue": "Continuar",
        "apisandbox-continue-clear": "Limpar",
-       "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries continuará] a última petición; {{int:apisandbox-continue-clear}} limpará os parámetros relativos á continuación.",
+       "apisandbox-continue-help": "\"{{int:apisandbox-continue}}\" [https://www.mediawiki.org/wiki/API:Query#Continuing_queries continuará] a última petición; \"{{int:apisandbox-continue-clear}}\" limpará os parámetros relativos á continuación.",
+       "apisandbox-param-limit": "Indicar <kbd>max</kbd> para usar o límite máximo.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Tódolos espazos de nomes)",
+       "apisandbox-multivalue-all-values": "$1 (Tódolos valores)",
        "booksources": "Fontes bibliográficas",
        "booksources-search-legend": "Procurar fontes bibliográficas",
        "booksources-search": "Procurar",
-       "booksources-text": "A continuación aparece unha lista de ligazóns cara a outros sitios web que venden libros novos e usados, neles tamén pode obter máis información sobre as obras que está a buscar:",
-       "booksources-invalid-isbn": "O ISBN inserido parece non ser válido; comprobe que non haxa erros ao copialo da fonte orixinal.",
+       "booksources-text": "A continuación aparece unha lista de ligazóns cara a outros sitios web que venden libros novos e usados; neles tamén pode obter máis información sobre as obras que está a buscar:",
+       "booksources-invalid-isbn": "O ISBN inserido semella non ser válido; comprobe que non se producisen erros ao copialo da fonte orixinal.",
        "magiclink-tracking-rfc": "Páxinas que usan ligazóns máxicas RFC",
        "magiclink-tracking-rfc-desc": "Esta páxina utiliza ligazóns máxicas RFC. Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] para descubrir como facer a migración.",
        "magiclink-tracking-pmid": "Páxinas que usan ligazóns máxicas PMID",
        "magiclink-tracking-isbn": "Páxinas que usan ligazóns máxicas ISBN",
        "magiclink-tracking-isbn-desc": "Esta páxina utiliza ligazóns máxicas ISBN. Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] para descubrir como facer a migración.",
        "specialloguserlabel": "Executante:",
-       "speciallogtitlelabel": "Obxectivo (título ou {{ns:user}}:nome de usuario):",
+       "speciallogtitlelabel": "Obxectivo (título ou \"{{ns:user}}:nome de usuario\" para un usuario):",
        "log": "Rexistros",
        "logeventslist-submit": "Mostrar",
        "all-logs-page": "Todos os rexistros públicos",
        "logempty": "Non se atopou ningún elemento relacionado no rexistro.",
        "log-title-wildcard": "Procurar os títulos que comecen con este texto",
        "showhideselectedlogentries": "Mostrar/agochar as entradas do rexistro seleccionadas",
-       "log-edit-tags": "Editar as etiquetas das entradas do registro seleccionadas",
+       "log-edit-tags": "Editar as etiquetas das entradas de rexistro seleccionadas",
        "checkbox-select": "Seleccionar: $1",
        "checkbox-all": "Todos",
        "checkbox-none": "Ningún",
        "activeusers-intro": "Esta é unha lista cos usuarios que tiveron algún tipo de actividade {{PLURAL:$1|no último día|nos últimos $1 días}}.",
        "activeusers-count": "$1 {{PLURAL:$1|acción|accións}} {{PLURAL:$3|no último día|nos últimos $3 días}}",
        "activeusers-from": "Mostrar os usuarios que comecen por:",
-       "activeusers-groups": "Mostrar os usuarios que pertencen ós grupos:",
+       "activeusers-groups": "Mostrar os usuarios que pertencen aos grupos:",
+       "activeusers-excludegroups": "Excluír ós usuarios que pertenzan ós grupos:",
        "activeusers-noresult": "Non se atopou ningún usuario.",
-       "activeusers-submit": "Mostrar usuarios activos",
+       "activeusers-submit": "Mostrar os usuarios activos",
        "listgrouprights": "Dereitos dun usuario segundo o seu grupo",
        "listgrouprights-summary": "A seguinte lista mostra os grupos de usuario definidos neste wiki, cos seus dereitos de acceso asociados.\nSe quere máis información acerca dos dereitos individuais, pode atopala [[{{MediaWiki:Listgrouprights-helppage}}|aquí]].",
        "listgrouprights-key": "Lenda:\n* <span class=\"listgrouprights-granted\">Dereito concedido</span>\n* <span class=\"listgrouprights-revoked\">Dereito revogado</span>",
        "listgrouprights-namespaceprotection-namespace": "Espazo de nomes",
        "listgrouprights-namespaceprotection-restrictedto": "Dereito(s) que permite(n) ao usuario editar",
        "listgrants": "Permisos",
-       "listgrants-summary": "Esta é unha lista de permisos cos seus accesos asoaciados aos permisos de usuario. Os usuarios poden autorizar aplicacións para usar a súa conta, pero con permisos limitados baseados nos permisos que o usuario dá á aplicación. Porén, unha aplicación que actúa no lugar do usuario non pode empregar permisos que o propio usuario non posúe.\nPode ver máis información sobre dereitos individuais [[{{MediaWiki:Listgrouprights-helppage}}|aquí]].",
+       "listgrants-summary": "Esta é unha lista de permisos cos seus accesos asociados aos permisos de usuario. Os usuarios poden autorizar aplicacións para que usen a súa conta, pero con acceso limitado en función dos permisos que o usuario concede á aplicación. Porén, unha aplicación que actúa no nome dun usuario non pode empregar permisos que o propio usuario non posúe.\nPode obter máis información sobre os dereitos individuais [[{{MediaWiki:Listgrouprights-helppage}}|nesta páxina]].",
        "listgrants-grant": "Outorgar",
        "listgrants-rights": "Dereitos",
        "trackingcategories": "Categorías de seguimento",
        "hidden-category-category-desc": "A categoría contén a palabra máxica <code><nowiki>__HIDDENCAT__</nowiki></code>, que impide que se mostre por defecto na caixa de categorías das páxinas.",
        "trackingcategories-nodesc": "Non hai ningunha descrición dispoñible.",
        "trackingcategories-disabled": "A categoría está desactivada",
-       "mailnologin": "Non existe enderezo para o envío",
+       "mailnologin": "Non hai enderezo de envío",
        "mailnologintext": "Debe [[Special:UserLogin|acceder ao sistema]] e ter rexistrado un enderezo de correo electrónico válido nas súas [[Special:Preferences|preferencias]] para enviar correos electrónicos a outros usuarios.",
        "emailuser": "Enviar un correo electrónico a {{GENDER:{{BASEPAGENAME}}|este usuario|esta usuaria}}",
        "emailuser-title-target": "Enviar un correo electrónico a {{GENDER:$1|este usuario|esta usuaria}}",
        "defemailsubject": "Correo electrónico do usuario $1 de {{SITENAME}}",
        "usermaildisabled": "O correo electrónico do usuario está desactivado",
        "usermaildisabledtext": "Non pode enviar correos electrónicos a outros usuarios deste wiki",
-       "noemailtitle": "Sen enderezo de correo electrónico",
+       "noemailtitle": "Non hai enderezo de correo electrónico",
        "noemailtext": "Este usuario non especificou un enderezo de correo electrónico válido.",
        "nowikiemailtext": "Este usuario elixiu non recibir correos electrónicos doutros usuarios.",
        "emailnotarget": "O nome de usuario do destinatario non existe ou é incorrecto.",
        "emailsubject": "Asunto:",
        "emailmessage": "Mensaxe:",
        "emailsend": "Enviar",
-       "emailccme": "Enviar unha copia da mensaxe para min.",
+       "emailccme": "Enviar unha copia da mensaxe ao meu enderezo de correo electrónico.",
        "emailccsubject": "Copia da súa mensaxe para $1: $2",
        "emailsent": "Mensaxe enviada",
        "emailsenttext": "A súa mensaxe de correo electrónico foi enviada.",
-       "emailuserfooter": "Este correo electrónico foi {{GENDER:$1|enviado}} por $1 a {{GENDER:$2|$2}} mediante a función \"{{int:emailuser}}\" en {{SITENAME}}.",
+       "emailuserfooter": "$1 {{GENDER:$1|enviou}} este correo electrónico a {{GENDER:$2|$2}} mediante a función \"{{int:emailuser}}\" de {{SITENAME}}.",
        "usermessage-summary": "Mensaxe deixada polo sistema.",
        "usermessage-editor": "Editor das mensaxes do sistema",
        "watchlist": "Lista de vixilancia",
        "watchnologin": "Non accedeu ao sistema",
        "addwatch": "Engadir á lista vixilancia",
        "addedwatchtext": "A páxina \"[[:$1]]\" e mais a súa conversa foron engadidas á súa [[Special:Watchlist|lista de vixilancia]].",
-       "addedwatchtext-talk": "\"[[:$1]]\" xunto coa súa páxina asociada foron engadidas á túa [[Special:Watchlist|lista de vixilancia]].",
+       "addedwatchtext-talk": "\"[[:$1]]\" e a súa páxina asociada engadíronse á súa [[Special:Watchlist|lista de vixilancia]].",
        "addedwatchtext-short": "A páxina \"$1\" foi engadida á súa lista de vixilancia.",
        "removewatch": "Eliminar da lista de vixilancia",
        "removedwatchtext": "A páxina \"[[:$1]]\" e mais a súa conversa foron eliminadas da súa [[Special:Watchlist|lista de vixilancia]].",
-       "removedwatchtext-talk": "\"[[:$1]]\" xunto coa súa páxina asociada foron eliminadas da túa [[Special:Watchlist|lista de vixilancia]].",
+       "removedwatchtext-talk": "\"[[:$1]]\" e a súa páxina asociada elimináronse da súa [[Special:Watchlist|lista de vixilancia]].",
        "removedwatchtext-short": "A páxina \"$1\" foi eliminada da súa lista de vixilancia.",
        "watch": "Vixiar",
        "watchthispage": "Vixiar esta páxina",
        "wlshowlast": "Mostrar as últimas $1 horas e os últimos $2 días",
        "watchlist-hide": "Agochar",
        "watchlist-submit": "Mostrar",
-       "wlshowtime": "Periodo de tempo a amosar:",
+       "wlshowtime": "Período de tempo a mostrar:",
        "wlshowhideminor": "edicións menores",
        "wlshowhidebots": "bots",
        "wlshowhideliu": "usuarios rexistrados",
        "deletepage": "Borrar a páxina",
        "confirm": "Confirmar",
        "excontent": "o contido era: \"$1\"",
-       "excontentauthor": "o contido era: \"$1\", e o único editor foi \"[[Special:Contributions/$2|$2]]\" ([[User talk:$2|conversa]])",
+       "excontentauthor": "o contido era \"$1\", e o único editor foi [[Special:Contributions/$2|$2]] ([[User talk:$2|conversa]])",
        "exbeforeblank": "o contido antes do baleirado era: \"$1\"",
        "delete-confirm": "Borrar \"$1\"",
        "delete-legend": "Borrar",
        "historywarning": "<strong>Atención:</strong> A páxina que está a piques de borrar ten un historial con $1 {{PLURAL:$1|revisión|revisións}}:",
        "historyaction-submit": "Mostrar",
-       "confirmdeletetext": "Está a piques de borrar de xeito permanente unha páxina ou imaxe con todo o seu historial na base de datos.\nPor favor, confirme que é realmente a súa intención, que comprende as consecuencias e que está obrando de acordo coas regras [[{{MediaWiki:Policy-url}}|da política e normas]].",
+       "confirmdeletetext": "Está a piques de borrar de xeito permanente unha páxina con todo o seu historial.\nPor favor, confirme que é realmente a súa intención, que comprende as consecuencias e que está obrando de acordo coas [[{{MediaWiki:Policy-url}}|políticas]].",
        "actioncomplete": "Completouse a acción",
        "actionfailed": "Fallou a acción",
        "deletedtext": "Borrouse a páxina \"$1\".\nNo $2 pode ver unha lista cos borrados máis recentes.",
        "rollbacklinkcount-morethan": "reverter máis de $1 {{PLURAL:$1|edición|edicións}}",
        "rollbackfailed": "Houbo un erro ao reverter as edicións",
        "rollback-missingparam": "Faltan parámetros obrigatorios na solicitude.",
-       "rollback-missingrevision": "Non se poden cargar datos da revisión.",
+       "rollback-missingrevision": "Non se poden cargar os datos da revisión.",
        "cantrollback": "Non se pode desfacer a edición; o último colaborador é o único autor desta páxina.",
        "alreadyrolled": "Non se pode desfacer a edición en \"[[:$1]]\" feita por [[User:$2|$2]] ([[User talk:$2|conversa]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); alguén máis editou ou desfixo os cambios desta páxina.\n\nA última edición fíxoa [[User:$3|$3]] ([[User talk:$3|conversa]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "O resumo de edición foi: <em>$1</em>.",
        "revertpage": "Desfixéronse as edicións de [[Special:Contributions/$2|$2]] ([[User talk:$2|conversa]]); cambiado á última versión feita por [[User:$1|$1]]",
        "revertpage-nouser": "Desfixéronse as edicións dun usuario agochado; cambiado á última versión feita por {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Desfixéronse as edicións de $1;\nvolveuse á última edición, feita por $2.",
-       "rollback-success-notify": "Modificacións anuladas por $1; restaurado á última revisión de $2. [$3 Mostrar os cambios]",
+       "rollback-success-notify": "Revertéronse as edicións de $1;\nrestaurouse a última revisión de $2. [$3 Mostrar os cambios]",
        "sessionfailure-title": "Erro de sesión",
        "sessionfailure": "Parece que hai un problema co rexistro da súa sesión;\nesta acción cancelouse como precaución fronte ao secuestro de sesións.\nPrema no botón \"atrás\", volva cargar a páxina da que proviña e inténteo de novo.",
-       "changecontentmodel": "Cambiar o modelo do contido dunha páxina",
-       "changecontentmodel-legend": "Cambiar o modelo do contido",
+       "changecontentmodel": "Cambiar o modelo de contido dunha páxina",
+       "changecontentmodel-legend": "Cambiar o modelo de contido",
        "changecontentmodel-title-label": "Título da páxina",
        "changecontentmodel-model-label": "Novo modelo de contido",
        "changecontentmodel-reason-label": "Motivo:",
        "changecontentmodel-submit": "Cambiar",
-       "changecontentmodel-success-title": "O modelo de contido foi modificado",
-       "changecontentmodel-success-text": "O tipo de contido de [[:$1]] foi modificado.",
-       "changecontentmodel-cannot-convert": "O contido en [[:$1]] non pode converterse ó tipo de $2.",
-       "changecontentmodel-nodirectediting": "O modelo de contido $1 non permite a modificación directa",
+       "changecontentmodel-success-title": "Modificouse o modelo de contido",
+       "changecontentmodel-success-text": "Modificouse o tipo de contido de \"[[:$1]]\".",
+       "changecontentmodel-cannot-convert": "O contido de \"[[:$1]]\" non se pode converter ao tipo \"$2\".",
+       "changecontentmodel-nodirectediting": "O modelo de contido \"$1\" non permite a modificación directa",
        "changecontentmodel-emptymodels-title": "Non hai modelos de contido dispoñibles",
-       "changecontentmodel-emptymodels-text": "O contido de [[:$1]] non pode converterse a ningún tipo.",
-       "log-name-contentmodel": "Rexistro de cambios de modelo de contido",
+       "changecontentmodel-emptymodels-text": "O contido de \"[[:$1]]\" non se pode converter a ningún tipo.",
+       "log-name-contentmodel": "Rexistro de cambios no modelo de contido",
        "log-description-contentmodel": "Eventos relacinados cos modelos de contido dunha páxina",
-       "logentry-contentmodel-new": "$1 {{GENDER:$2|creou}} a páxina $3 usando un modelo de contido non predeterminado \"$5\"",
-       "logentry-contentmodel-change": "$1 {{GENDER:$2|cambiou}} o modelo de contido da páxina $3 de \"$4\" a \"$5\"",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|creou}} a páxina \"$3\" usando o modelo de contido non predeterminado \"$5\"",
+       "logentry-contentmodel-change": "$1 {{GENDER:$2|cambiou}} o modelo de contido da páxina \"$3\" de \"$4\" a \"$5\"",
        "logentry-contentmodel-change-revertlink": "reverter",
        "logentry-contentmodel-change-revert": "reverter",
        "protectlogpage": "Rexistro de proteccións",
        "modifiedarticleprotection": "modificou o nivel de protección de \"[[$1]]\"",
        "unprotectedarticle": "eliminou a protección de \"[[$1]]\"",
        "movedarticleprotection": "cambiou as características da protección de \"[[$2]]\" a \"[[$1]]\"",
-       "protectedarticle-comment": "{{GENDER:$2|Protexido}} \"[[$1]]\"",
-       "modifiedarticleprotection-comment": "{{GENDER:$2|Cambiado o nivel de protección}} para \"[[$1]]\"",
-       "unprotectedarticle-comment": "{{GENDER:$2|Eliminada a protección}} para \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Protexo}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Cambio o nivel de protección}} de \"[[$1]]\"",
+       "unprotectedarticle-comment": "{{GENDER:$2|Elimino a protección}} de \"[[$1]]\"",
        "protect-title": "Cambiar o nivel de protección de \"$1\"",
        "protect-title-notallowed": "Ollar o nivel de protección de \"$1\"",
        "prot_1movedto2": "moveu \"[[$1]]\" a \"[[$2]]\"",
        "protectcomment": "Motivo:",
        "protectexpiry": "Caducidade:",
        "protect_expiry_invalid": "O tempo de duración da protección non é válido.",
-       "protect_expiry_old": "O momento de remate da protección corresponde ao pasado.",
+       "protect_expiry_old": "A data de caducidade da protección corresponde ao pasado.",
        "protect-unchain-permissions": "Desbloquear as opcións de protección adicionais",
-       "protect-text": "Aquí é onde pode ver e cambiar os niveis de protección da páxina chamada \"'''$1'''\".",
-       "protect-locked-blocked": "Non pode modificar os niveis de protección mentres exista un bloqueo. Velaquí a configuración actual da páxina  '''$1''':",
-       "protect-locked-dblock": "Os niveis de protección non se poden modificar debido a un bloqueo da base de datos activa.\nVelaquí a configuración actual da páxina '''$1''':",
-       "protect-locked-access": "A súa conta non dispón de permisos para mudar os niveis de protección.\nVelaquí a configuración actual da páxina '''$1''':",
+       "protect-text": "Aquí pode ver e modificar o nivel de protección da páxina \"<strong>$1</strong>\".",
+       "protect-locked-blocked": "Non pode modificar o nivel de protección durante un bloqueo.\nVelaquí está a configuración actual da páxina \"<strong>$1</strong>\":",
+       "protect-locked-dblock": "Os niveis de protección non se poden modificar debido a un bloqueo activo da base de datos.\nVelaquí está a configuración actual da páxina \"<strong>$1</strong>\":",
+       "protect-locked-access": "A súa conta non dispón dos permisos necesarios para modificar os niveis de protección.\nVelaquí está a configuración actual da páxina \"<strong>$1</strong>\":",
        "protect-cascadeon": "Esta páxina está protexida actualmente porque está transcluída {{PLURAL:$1|na seguinte páxina, que foi protexida|nas seguintes páxinas, que foron protexidas}} coa opción \"protección en serie\" activada.\nOs cambios no nivel de protección desta páxina non afectarán á protección en serie.",
        "protect-default": "Permitir a todos os usuarios",
        "protect-fallback": "Permitir só aos usuarios con permisos de \"$1\"",
        "sp-contributions-username": "Enderezo IP ou nome de usuario:",
        "sp-contributions-toponly": "Mostrar só as últimas revisións",
        "sp-contributions-newonly": "Mostrar só as edicións que crearon páxinas",
-       "sp-contributions-hideminor": "Ocultar edicións menores",
+       "sp-contributions-hideminor": "Agochar as edicións pequenas",
        "sp-contributions-submit": "Procurar",
        "whatlinkshere": "Páxinas que ligan con esta",
        "whatlinkshere-title": "Páxinas que ligan con \"$1\"",
        "whatlinkshere-hideredirs": "$1 as redireccións",
        "whatlinkshere-hidetrans": "$1 as inclusións",
        "whatlinkshere-hidelinks": "$1 as ligazóns",
-       "whatlinkshere-hideimages": "$1 ligazóns ao ficheiro",
+       "whatlinkshere-hideimages": "$1 as ligazóns ao ficheiro",
        "whatlinkshere-filters": "Filtros",
        "whatlinkshere-submit": "Ir",
        "autoblockid": "Bloqueo automático nº$1",
        "unblock-hideuser": "Non pode desbloquear o usuario porque o seu nome foi agochado.",
        "ipb_cant_unblock": "Erro: Non se atopa o identificador do bloqueo $1. Posiblemente xa foi desbloqueado.",
        "ipb_blocked_as_range": "Erro: O enderezo IP $1 non está bloqueado directamente e non se pode desbloquear. Porén, está bloqueado por estar no rango $2, que si se pode desbloquear.",
-       "ip_range_invalid": "Rango IP non válido.",
+       "ip_range_invalid": "Rango de enderezos IP non válido.",
        "ip_range_toolarge": "Non están permitidos os rangos de bloqueo maiores que /$1.",
        "proxyblocker": "Bloqueador de proxy",
        "proxyblockreason": "O seu enderezo IP foi bloqueado porque é un proxy aberto.\nPor favor, contacte co seu fornecedor de acceso á Internet ou co seu soporte técnico e informe deste grave problema de seguridade.",
        "allmessages": "Mensaxes do sistema",
        "allmessagesname": "Nome",
        "allmessagesdefault": "Texto predeterminado",
-       "allmessagescurrent": "Texto actual",
-       "allmessagestext": "Esta é unha lista de todas as mensaxes dispoñibles no espazo de nomes MediaWiki.\nPor favor, visite a páxina de [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation localización de MediaWiki] e [https://translatewiki.net translatewiki.net] se quere contribuír á localización xenérica de MediaWiki.",
+       "allmessagescurrent": "Texto actual da mensaxe",
+       "allmessagestext": "Esta é unha lista de todas as mensaxes dispoñibles no espazo de nomes MediaWiki.\nPor favor, visite a páxina de [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation localización] e [https://translatewiki.net translatewiki.net] se quere contribuír á localización xenérica de MediaWiki.",
        "allmessagesnotsupportedDB": "Esta páxina non está dispoñible porque '''$wgUseDatabaseMessages''' está desactivado.",
        "allmessages-filter-legend": "Filtrar",
        "allmessages-filter": "Filtrar por estado de personalización:",
        "import-interwiki-text": "Seleccione o wiki e o título da páxina que queira importar.\nAs datas das revisións e os nomes dos editores manteranse.\nTodas as importacións doutros wikis poden consultarse no [[Special:Log/import|rexistro de importacións]].",
        "import-interwiki-sourcewiki": "Wiki de orixe:",
        "import-interwiki-sourcepage": "Páxina de orixe:",
-       "import-interwiki-history": "Copiar todas as versións que hai no historial desta páxina",
+       "import-interwiki-history": "Copiar todas as revisións do historial desta páxina",
        "import-interwiki-templates": "Incluír todos os modelos",
        "import-interwiki-submit": "Importar",
        "import-mapping-default": "Importar aos lugares predeterminados",
        "import-revision-count": "$1 {{PLURAL:$1|revisión|revisións}}",
        "importnopages": "Non hai páxinas para importar.",
        "imported-log-entries": "{{PLURAL:$1|Importouse unha entrada|Importáronse $1 entradas}} do rexisto.",
-       "importfailed": "A importación fallou: $1",
-       "importunknownsource": "Fonte de importación descoñecida",
+       "importfailed": "Fallou a importación: <nowiki>$1</nowiki>",
+       "importunknownsource": "Descoñécese o tipo de fonte de importación",
        "importcantopen": "Non se pode abrir o ficheiro importado",
        "importbadinterwiki": "Ligazón interwiki incorrecta",
-       "importsuccess": "A importación rematou!",
+       "importsuccess": "Rematou a importación!",
        "importnosources": "Non se defininiu ningún wiki desde o que importar e os envíos directos dos historiais están desactivados.",
-       "importnofile": "Non se enviou ningún ficheiro de importación.",
-       "importuploaderrorsize": "Fallou o envío do ficheiro de importación. O ficheiro é máis grande que o tamaño de envío permitido.",
-       "importuploaderrorpartial": "Fallou o envío do ficheiro de importación. O ficheiro só se enviou parcialmente.",
-       "importuploaderrortemp": "Fallou o envío do ficheiro de importación. Falta un cartafol temporal.",
-       "import-parse-failure": "Fallo de análise da importación de XML",
-       "import-noarticle": "Ningunha páxina para importar!",
+       "importnofile": "Non se subiu ningún ficheiro de importación.",
+       "importuploaderrorsize": "Fallou o envío do ficheiro de importación.\nO ficheiro é máis grande que o tamaño de envío permitido.",
+       "importuploaderrorpartial": "Fallou o envío do ficheiro de importación.\nO ficheiro só se enviou parcialmente.",
+       "importuploaderrortemp": "Fallou o envío do ficheiro de importación.\nFalta un cartafol temporal.",
+       "import-parse-failure": "Fallo na análise da importación dos datos XML",
+       "import-noarticle": "Non hai ningunha páxina para importar!",
        "import-nonewrevisions": "Non se importou ningunha revisión (xa estaban todas presentes ou saltáronse por erros).",
        "xml-error-string": "$1 na liña $2, columna $3 (byte $4): $5",
        "import-upload": "Cargar datos XML",
-       "import-token-mismatch": "Perda de datos da sesión.\n\nA súa sesión puido ser pechada. <strong>Por favor, verifique se aínda está conectado e probe de novo</strong>. \nEn caso de que continúe sen funcionar, intente [[Special:UserLogout|saír]] e volver a entrar na súa conta, e verifique se o seu navegador permite o uso de ''cookies'' deste sitio.",
+       "import-token-mismatch": "Perda dos datos da sesión.\n\nPoida que se pechase a súa sesión. <strong>Por favor, comprobe que ten a sesión aberta e probe de novo.</strong>\nEn caso de que siga sen funcionar, intente [[Special:UserLogout|saír]] e volver entrar na súa conta e verifique que o seu navegador permite o uso de cookies neste sitio.",
        "import-invalid-interwiki": "Non se pode importar desde o wiki escificado.",
        "import-error-edit": "Non foi posible importar a páxina \"$1\" porque non ten os permisos necesarios para editala.",
        "import-error-create": "Non foi posible importar a páxina \"$1\" porque non ten os permisos necesarios para creala.",
        "import-logentry-upload-detail": "{{PLURAL:$1|Importouse $1 revisión|Importáronse $1 revisións}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|Importouse $1 revisión|Importáronse $1 revisións}} desde $2",
        "javascripttest": "Proba de JavaScript",
-       "javascripttest-pagetext-unknownaction": "Acción descoñecida \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Descoñécese a acción \"$1\".",
        "javascripttest-qunit-intro": "Bótelle unha ollada á [$1 documentación das probas] en mediawiki.org.",
        "tooltip-pt-userpage": "A súa páxina de {{GENDER:|usuario|usuaria}}",
        "tooltip-pt-anonuserpage": "A páxina de usuario do enderezo IP desde o que está a editar",
        "tooltip-pt-preferences": "{{GENDER:|As súas}} preferencias",
        "tooltip-pt-watchlist": "A lista de páxinas cuxas modificacións está a seguir",
        "tooltip-pt-mycontris": "Lista das súas contribucións",
-       "tooltip-pt-anoncontribs": "Unha lista de modificacións feitas desde esta dirección IP",
+       "tooltip-pt-anoncontribs": "Unha lista das modificacións feitas desde este enderezo IP",
        "tooltip-pt-login": "Recoméndaselle rexistrarse, se ben non é obrigatorio",
        "tooltip-pt-logout": "Saír ao anonimato",
        "tooltip-pt-createaccount": "Recoméndaselle crear unha conta e acceder ao sistema, se ben non é obrigatorio",
        "tooltip-ca-protect": "Protexer esta páxina",
        "tooltip-ca-unprotect": "Cambiar a protección desta páxina",
        "tooltip-ca-delete": "Eliminar esta páxina",
-       "tooltip-ca-undelete": "Restaurar as edicións feitas nesta páxina antes de que fose eliminada",
+       "tooltip-ca-undelete": "Restaurar as edicións feitas nesta páxina antes de que fose borrada",
        "tooltip-ca-move": "Mover esta páxina",
        "tooltip-ca-watch": "Engadir esta páxina á lista de vixilancia",
        "tooltip-ca-unwatch": "Eliminar esta páxina da lista de vixilancia",
        "tooltip-ca-nstab-template": "Ver o modelo",
        "tooltip-ca-nstab-help": "Ver a páxina de axuda",
        "tooltip-ca-nstab-category": "Ver a páxina da categoría",
-       "tooltip-minoredit": "Marcar isto coma unha edición pequena",
+       "tooltip-minoredit": "Marcar isto como unha edición pequena",
        "tooltip-save": "Gravar os seus cambios",
        "tooltip-publish": "Publicar os seus cambios",
        "tooltip-preview": "Vista previa dos seus cambios; por favor, úsea antes de gravalos!",
        "patrol-log-page": "Rexistro de revisións patrulladas",
        "patrol-log-header": "Este é un rexistro das revisións patrulladas.",
        "log-show-hide-patrol": "$1 o rexistro de patrullas",
-       "log-show-hide-tag": "$1 rexistro de etiquetas",
-       "confirm-markpatrolled-button": "OK",
-       "confirm-markpatrolled-top": "Marcar a revisión $3 de $2 como patrullada?",
-       "deletedrevision": "A revisión vella $1 foi borrada.",
+       "log-show-hide-tag": "$1 rexistro de etiquetas",
+       "confirm-markpatrolled-button": "Aceptar",
+       "confirm-markpatrolled-top": "Quere marcar a revisión $3 de \"$2\" como patrullada?",
+       "deletedrevision": "Revisión vella e borrada de \"$1\"",
        "filedeleteerror-short": "Erro ao eliminar o ficheiro: $1",
        "filedeleteerror-long": "Atopáronse erros ao eliminar o ficheiro:\n\n$1",
        "filedelete-missing": "Non se pode eliminar o ficheiro \"$1\" porque non existe.",
        "svg-long-error": "Ficheiro SVG non válido: $1",
        "show-big-image": "Ficheiro orixinal",
        "show-big-image-preview": "Tamaño desta vista previa: $1.",
-       "show-big-image-preview-differ": "Tamaño desta revisión $3 do ficheiro $2: $1.",
+       "show-big-image-preview-differ": "Tamaño desta vista previa en $3 do ficheiro en formato $2: $1.",
        "show-big-image-other": "{{PLURAL:$2|Outra resolución|Outras resolucións}}: $1.",
        "show-big-image-size": "$1 × $2 píxeles",
        "file-info-gif-looped": "en bucle",
        "newimages-legend": "Filtro",
        "newimages-label": "Nome do ficheiro (ou parte del):",
        "newimages-showbots": "Mostrar as cargas feitas por bots",
-       "newimages-hidepatrolled": "Ocultar as subas verificadas",
-       "noimages": "Non hai imaxes para ver.",
-       "gallery-slideshow-toggle": "Intercambiar miniaturas",
+       "newimages-hidepatrolled": "Agochar as subidas patrulladas",
+       "noimages": "Non hai imaxes que mostrar.",
+       "gallery-slideshow-toggle": "Intercambiar as miniaturas",
        "ilsubmit": "Procurar",
        "bydate": "por data",
        "sp-newimages-showfrom": "Mostrar os novos ficheiros comezando polo $1 ás $2",
        "exif-imagelength": "Alto",
        "exif-bitspersample": "Bits por compoñente",
        "exif-compression": "Esquema de compresión",
-       "exif-photometricinterpretation": "Composición do píxel",
+       "exif-photometricinterpretation": "Composición de píxeles",
        "exif-orientation": "Orientación",
        "exif-samplesperpixel": "Número de compoñentes",
        "exif-planarconfiguration": "Disposición dos datos",
        "exif-stripoffsets": "Localización dos datos da imaxe",
        "exif-rowsperstrip": "Número de filas por tira",
        "exif-stripbytecounts": "Bytes por tira comprimida",
-       "exif-jpeginterchangeformat": "Distancia ao inicio (SOI) do JPEG",
+       "exif-jpeginterchangeformat": "Desprazamento do SOI do JPEG",
        "exif-jpeginterchangeformatlength": "Bytes de datos JPEG",
-       "exif-whitepoint": "Coordenadas cromáticas de referencia do branco",
+       "exif-whitepoint": "Cromacidade do punto branco",
        "exif-primarychromaticities": "Cromacidades primarias",
        "exif-ycbcrcoefficients": "Coeficientes da matriz de transformación do espazo de cores",
        "exif-referenceblackwhite": "Par de valores de referencia branco e negro",
        "exif-relatedsoundfile": "Ficheiro de son relacionado",
        "exif-datetimeoriginal": "Data e hora de xeración do ficheiro",
        "exif-datetimedigitized": "Data e hora de dixitalización",
-       "exif-subsectime": "DataHora subsegundos",
-       "exif-subsectimeoriginal": "DataHoraOrixinal subsegundos",
-       "exif-subsectimedigitized": "DataHoraDixitalización subsegundos",
+       "exif-subsectime": "Subsegundo da data e hora",
+       "exif-subsectimeoriginal": "Subsegundo da data e hora orixinais",
+       "exif-subsectimedigitized": "Subsegundo da data e hora de dixitalización",
        "exif-exposuretime": "Tempo de exposición",
        "exif-exposuretime-format": "$1 segundos ($2)",
        "exif-fnumber": "Número f",
        "exif-exposureprogram": "Programa de exposición",
        "exif-spectralsensitivity": "Sensibilidade espectral",
-       "exif-isospeedratings": "Relación da velocidade ISO",
+       "exif-isospeedratings": "Relación de velocidade ISO",
        "exif-shutterspeedvalue": "Velocidade de obturación APEX",
        "exif-aperturevalue": "Apertura APEX",
        "exif-brightnessvalue": "Brillo APEX",
-       "exif-exposurebiasvalue": "Corrección da exposición",
+       "exif-exposurebiasvalue": "Corrección da exposición mediante APEX",
        "exif-maxaperturevalue": "Máxima apertura do diafragma",
        "exif-subjectdistance": "Distancia do suxeito",
        "exif-meteringmode": "Modo de medida da exposición",
        "exif-sensingmethod": "Tipo de sensor",
        "exif-filesource": "Fonte do ficheiro",
        "exif-scenetype": "Tipo de escena",
-       "exif-customrendered": "Procesamento da imaxe personalizado",
+       "exif-customrendered": "Procesamento de imaxe personalizado",
        "exif-exposuremode": "Modo de exposición",
        "exif-whitebalance": "Balance de brancos",
        "exif-digitalzoomratio": "Valor do zoom dixital",
        "exif-saturation": "Saturación",
        "exif-sharpness": "Nitidez",
        "exif-devicesettingdescription": "Descrición da configuración do dispositivo",
-       "exif-subjectdistancerange": "Distancia ao suxeito",
+       "exif-subjectdistancerange": "Rango de distancia ao suxeito",
        "exif-imageuniqueid": "ID único da imaxe",
        "exif-gpsversionid": "Versión da etiqueta GPS",
        "exif-gpslatituderef": "Latitude norte ou sur",
        "exif-gpstrack": "Dirección do movemento",
        "exif-gpsimgdirectionref": "Referencia para a dirección da imaxe",
        "exif-gpsimgdirection": "Dirección da imaxe",
-       "exif-gpsmapdatum": "Usados datos xeodésicos de enquisas",
+       "exif-gpsmapdatum": "Datos xeodésicos usados",
        "exif-gpsdestlatituderef": "Referencia para a latitude do destino",
        "exif-gpsdestlatitude": "Latitude do destino",
        "exif-gpsdestlongituderef": "Referencia para a lonxitude do destino",
        "exif-gpsdestlongitude": "Lonxitude do destino",
-       "exif-gpsdestbearingref": "Referencia para a coordenada de destino",
-       "exif-gpsdestbearing": "Coordenada de destino",
+       "exif-gpsdestbearingref": "Referencia para a orientación de destino",
+       "exif-gpsdestbearing": "Orientación de destino",
        "exif-gpsdestdistanceref": "Referencia para a distancia ao destino",
        "exif-gpsdestdistance": "Distancia ao destino",
        "exif-gpsprocessingmethod": "Nome do método de procesamento GPS",
        "exif-orientation-6": "Rotada 90° en sentido antihorario",
        "exif-orientation-7": "Rotada 90° en sentido horario e volteada verticalmente",
        "exif-orientation-8": "Rotada 90° en sentido horario",
-       "exif-planarconfiguration-1": "Formato de paquete de píxeles",
-       "exif-planarconfiguration-2": "Formato de planos",
+       "exif-planarconfiguration-1": "formato de paquete de píxeles",
+       "exif-planarconfiguration-2": "formato de planos",
        "exif-colorspace-65535": "Sen calibrar",
-       "exif-componentsconfiguration-0": "non hai",
+       "exif-componentsconfiguration-0": "non existe",
        "exif-exposureprogram-0": "Sen definir",
        "exif-exposureprogram-1": "Manual",
        "exif-exposureprogram-2": "Programa normal",
        "exif-exposureprogram-3": "Prioridade da apertura",
-       "exif-exposureprogram-4": "Prioridade da obturación",
+       "exif-exposureprogram-4": "Prioridade do obturador",
        "exif-exposureprogram-5": "Programa creativo (preferencia pola profundidade de campo)",
-       "exif-exposureprogram-6": "Programa de acción (preferencia por unha velocidade de exposición máis rápida)",
+       "exif-exposureprogram-6": "Programa de acción (preferencia por unha velocidade do obturador máis rápida)",
        "exif-exposureprogram-7": "Modo retrato (para primeiros planos co fondo desenfocado)",
        "exif-exposureprogram-8": "Modo paisaxe (para paisaxes co fondo enfocado)",
        "exif-subjectdistance-value": "$1 metros",
        "exif-meteringmode-0": "Descoñecido",
        "exif-meteringmode-1": "Media",
-       "exif-meteringmode-2": "Ponderado no centro",
-       "exif-meteringmode-3": "Un punto",
-       "exif-meteringmode-4": "Varios puntos",
-       "exif-meteringmode-5": "Patrón de medición",
+       "exif-meteringmode-2": "Media ponderada no centro",
+       "exif-meteringmode-3": "Puntual",
+       "exif-meteringmode-4": "Multipuntual",
+       "exif-meteringmode-5": "Patrón",
        "exif-meteringmode-6": "Parcial",
        "exif-meteringmode-255": "Outro",
        "exif-lightsource-0": "Descoñecida",
        "exif-lightsource-9": "Bo tempo",
        "exif-lightsource-10": "Tempo anubrado",
        "exif-lightsource-11": "Sombra",
-       "exif-lightsource-12": "Fluorescente luz de día (D 5700 – 7100K)",
-       "exif-lightsource-13": "Fluorescente branco día (N 4600 – 5400K)",
-       "exif-lightsource-14": "Fluorescente branco frío (W 3900 – 4500K)",
+       "exif-lightsource-12": "Fluorescente de luz de día (D 5700 – 7100K)",
+       "exif-lightsource-13": "Fluorescente de branco diurno (N 4600 – 5400K)",
+       "exif-lightsource-14": "Fluorescente de branco frío (W 3900 – 4500K)",
        "exif-lightsource-15": "Fluorescente branco (WW 3200 – 3700K)",
        "exif-lightsource-17": "Luz estándar A",
        "exif-lightsource-18": "Luz estándar B",
        "exif-sensingmethod-2": "Sensor da área de cor dun chip",
        "exif-sensingmethod-3": "Sensor da área de cor de dous chips",
        "exif-sensingmethod-4": "Sensor da área de cor de tres chips",
-       "exif-sensingmethod-5": "Sensor secuencial da área de cor",
-       "exif-sensingmethod-7": "Sensor trilineal",
-       "exif-sensingmethod-8": "Sensor secuencial da liña de cor",
+       "exif-sensingmethod-5": "Sensor da área de cor secuencial",
+       "exif-sensingmethod-7": "Sensor trilinear",
+       "exif-sensingmethod-8": "Sensor da cor linear secuencial",
        "exif-filesource-3": "Cámara fotográfica dixital",
        "exif-scenetype-1": "Unha imaxe fotografada directamente",
        "exif-customrendered-0": "Procesamento normal",
        "exif-customrendered-1": "Procesamento personalizado",
        "exif-exposuremode-0": "Exposición automática",
        "exif-exposuremode-1": "Exposición manual",
-       "exif-exposuremode-2": "Compensación de exposición automática",
+       "exif-exposuremode-2": "Compensación automática da exposición",
        "exif-whitebalance-0": "Balance de brancos automático",
        "exif-whitebalance-1": "Balance de brancos manual",
        "exif-scenecapturetype-0": "Estándar",
        "exif-subjectdistancerange-0": "Descoñecida",
        "exif-subjectdistancerange-1": "Macro",
        "exif-subjectdistancerange-2": "Primeiro plano",
-       "exif-subjectdistancerange-3": "Paisaxe",
+       "exif-subjectdistancerange-3": "Vista distante",
        "exif-gpslatitude-n": "Latitude norte",
        "exif-gpslatitude-s": "Latitude sur",
        "exif-gpslongitude-e": "Lonxitude leste",
        "confirmemail_body_set": "Alguén, probablemente vostede, desde o enderezo IP $1,\nestableceu este enderezo de correo electrónico como o da conta \"$2\" en {{SITENAME}}.\n\nPara confirmar que realmente esta conta lle pertence a vostede e activar\nas características do correo electrónico en {{SITENAME}}, abra esta ligazón no seu navegador:\n\n$3\n\nSe a conta *non* é súa, siga estoutra ligazón\npara cancelar a confirmación do enderezo de correo electrónico:\n\n$5\n\nO código de confirmación caduca o $6 ás $7.",
        "confirmemail_invalidated": "A confirmación do enderezo de correo electrónico foi cancelada",
        "invalidateemail": "Cancelar a confirmación do correo electrónico",
-       "notificationemail_subject_changed": "A dirección de correo rexistrada en {{SITENAME}} foi modificada",
-       "notificationemail_subject_removed": "A dirección de correo rexistrada en {{SITENAME}} foi eliminada",
-       "notificationemail_body_changed": "Alguén, probablemente vostede, dende a dirección IP $1, cambiou a dirección de correo electrónico da conta \"$2\" a \"$3\" en {{SITENAME}}.\n\nSe non foi vostede, contacte cun administrador inmediatamente.",
-       "notificationemail_body_removed": "Alguén, probablemente vostede, dende a dirección IP $1, eliminou a dirección de correo electrónico da conta \"$2\" en {{SITENAME}}.\n\nSe non foi vostede, contacte cun administrador inmediatamente.",
+       "notificationemail_subject_changed": "Modificouse o enderezo de correo electrónico rexistrado en {{SITENAME}}",
+       "notificationemail_subject_removed": "Eliminouse o enderezo de correo electrónico rexistrado en {{SITENAME}}",
+       "notificationemail_body_changed": "Alguén, probablemente vostede, dende o enderezo IP $1,\ncambiou o enderezo de correo electrónico da conta \"$2\" a \"$3\" en {{SITENAME}}.\n\nSe non foi vostede, contacte cun administrador inmediatamente.",
+       "notificationemail_body_removed": "Alguén, probablemente vostede, dende o enderezo IP $1,\neliminou o enderezo de correo electrónico da conta \"$2\" en {{SITENAME}}.\n\nSe non foi vostede, contacte cun administrador inmediatamente.",
        "scarytranscludedisabled": "[A transclusión interwiki está desactivada]",
        "scarytranscludefailed": "[Fallou a busca do modelo \"$1\"]",
        "scarytranscludefailed-httpstatus": "[Fallou a busca do modelo \"$1\": HTTP $2]",
        "scarytranscludetoolong": "[O enderezo URL é demasiado longo]",
        "deletedwhileediting": "'''Aviso:''' Esta páxina foi borrada despois de que comezase a editala!",
-       "confirmrecreate": "O usuario [[User:$1|$1]] ([[User talk:$1|conversa]]) {{GENDER:$1|borrou}} esta páxina despois de que vostede comezara a editala, dando o seguinte motivo:\n: <em>$2</em>\nPor favor, confirme que realmente quere recrear esta páxina.",
-       "confirmrecreate-noreason": "O usuario [[User:$1|$1]] ([[User talk:$1|conversa]]) {{GENDER:$1|borrou}} esta páxina despois de que vostede comezara a editala. Por favor, confirme que realmente quere recrear esta páxina.",
+       "confirmrecreate": "O usuario [[User:$1|$1]] ([[User talk:$1|conversa]]) {{GENDER:$1|borrou}} esta páxina despois de que vostede comezase a editala, achegando o seguinte motivo:\n: <em>$2</em>\nPor favor, confirme que realmente quere recrear esta páxina.",
+       "confirmrecreate-noreason": "O usuario [[User:$1|$1]] ([[User talk:$1|conversa]]) {{GENDER:$1|borrou}} esta páxina despois de que vostede comezase a editala. Por favor, confirme que realmente quere recrear esta páxina.",
        "recreate": "Recrear",
        "confirm_purge_button": "Aceptar",
        "confirm-purge-top": "Quere limpar a memoria caché desta páxina?",
        "confirm-unwatch-button": "Aceptar",
        "confirm-unwatch-top": "Quere eliminar esta páxina da lista de vixilancia?",
        "confirm-rollback-button": "Aceptar",
-       "confirm-rollback-top": "Reverter as edicións desta páxina?",
+       "confirm-rollback-top": "Quere reverter as edicións desta páxina?",
        "colon-separator": ":&#32;",
        "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← páxina anterior",
        "version-variables": "Variables",
        "version-antispam": "Prevención contra spam",
        "version-other": "Outros",
-       "version-mediahandlers": "Executadores de multimedia",
+       "version-mediahandlers": "Manipuladores de ficheiros multimedia",
        "version-hooks": "Asociadores",
        "version-parser-extensiontags": "Etiquetas das extensións do analizador",
-       "version-parser-function-hooks": "Asociadores da función do analizador",
+       "version-parser-function-hooks": "Asociadores das funcións do analizador",
        "version-hook-name": "Nome do asociador",
        "version-hook-subscribedby": "Subscrito por",
        "version-version": "($1)",
        "version-software": "Software instalado",
        "version-software-product": "Produto",
        "version-software-version": "Versión",
-       "version-entrypoints": "Enderezos URL de punto de entrada",
+       "version-entrypoints": "Enderezos URL do punto de entrada",
        "version-entrypoints-header-entrypoint": "Punto de entrada",
        "version-entrypoints-header-url": "URL",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Ruta dos artigos]",
        "version-libraries-license": "Licenza",
        "version-libraries-description": "Descrición",
        "version-libraries-authors": "Autores",
-       "redirect": "Redirixir por nome de ficheiro, usuario, páxina, modificación ou identificador de rexistro",
-       "redirect-summary": "Esta páxina especial redirixe cara a un ficheiro (dado o nome), unha páxina (dado o ID da páxina ou o dunha revisión) ou unha páxina de usuario (dado o ID dun usuario), ou unha entrada do rexistro (dada polo ID do rexistro). Utilización: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] ou [[{{#Special:Redirect}}/user/101]], ou [[{{#Special:Redirect}}/logid/186]].",
+       "redirect": "Redirixir por nome de ficheiro, ID de usuario, ID de páxina, ID de revisión ou ID de rexistro",
+       "redirect-summary": "Esta páxina especial redirixe cara a un ficheiro (dado o nome), unha páxina (dado o ID da páxina ou o dunha revisión), unha páxina de usuario (dado o ID dun usuario) ou unha entrada do rexistro (dada o ID do rexistro). Utilización: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]] ou [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Continuar",
        "redirect-lookup": "Procurar:",
        "redirect-value": "Valor:",
-       "redirect-user": "ID de usuario",
-       "redirect-page": "ID de páxina",
+       "redirect-user": "Identificador de usuario",
+       "redirect-page": "Identificador de páxina",
        "redirect-revision": "Revisión de páxina",
        "redirect-file": "Nome de ficheiro",
        "redirect-logid": "Identificador de rexistro",
        "tags-deactivate": "desactivar",
        "tags-hitcount": "$1 {{PLURAL:$1|modificación|modificacións}}",
        "tags-manage-no-permission": "Non ten os permisos necesarios para modificar etiquetas.",
-       "tags-manage-blocked": "Non pode acceder á interface de modificación de etiquetas mentres estea bloqueado.",
+       "tags-manage-blocked": "Non pode acceder á interface de modificación de etiquetas mentres estea {{GENDER:$1|bloqueado|bloqueada}}.",
        "tags-create-heading": "Crear unha nova etiqueta",
        "tags-create-explanation": "Por defecto, as etiquetas creadas recentemente poderán ser empregadas polos usuarios e os bots.",
        "tags-create-tag-name": "Nome da etiqueta:",
        "tags-deactivate-not-allowed": "Non é posible reactivar a páxina \"$1\".",
        "tags-deactivate-submit": "Desactivar",
        "tags-apply-no-permission": "Non ten permisos para aplicar etiquetas de cambios xunto cos seus tus cambios.",
-       "tags-apply-blocked": "Non pode aplicar os cambios das etiquetas cos seus cambios mentras estea bloqueado.",
+       "tags-apply-blocked": "Non pode aplicar os cambios nas etiquetas nin as súas modificacións mentras estea {{GENDER:$1|bloqueado|bloqueada}}.",
        "tags-apply-not-allowed-one": "A etiqueta \"$1\" non se puede aplicar manualmente.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|A seguinte etiqueta non se pode|As seguintes etiquetas non se poden}} aplicar manualmente: $1",
        "tags-update-no-permission": "Non ten permisos para engadir ou quitar etiquetas de cambio das revisións individuais ou das entradas do rexistro.",
-       "tags-update-blocked": "Non pode engadir nin quitar de modificación etiquetas mentras estea bloqueado.",
+       "tags-update-blocked": "Non pode engadir nin eliminar etiquetas mentras estea {{GENDER:$1|bloqueado|bloqueada}}.",
        "tags-update-add-not-allowed-one": "A etiqueta \"$1\" non se pode engadir manualmente.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|A seguinte etiqueta non se pode|As seguintes etiquetas non se poden}} engadir manualmente: $1",
        "tags-update-remove-not-allowed-one": "A etiqueta \"$1\" non se pode eliminar.",
        "htmlform-user-not-exists": "\"<strong>$1</strong>\" non existe.",
        "htmlform-user-not-valid": "\"<strong>$1</strong>\" non é un nome de usuario válido.",
        "logentry-delete-delete": "$1 {{GENDER:$2|borrou}} a páxina \"$3\"",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|eliminou}} a redirección $3 sobreescribíndoa",
        "logentry-delete-restore": "$1 {{GENDER:$2|restaurou}} a páxina \"$3\"",
        "logentry-delete-event": "$1 {{GENDER:$2|mudou}} a visibilidade {{PLURAL:$5|dunha entrada|de $5 entradas}} do rexistro de $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|mudou}} a visibilidade {{PLURAL:$5|dunha revisión|de $5 revisións}} da páxina \"$3\": $4",
        "expand_templates_generate_xml": "Mostrar a árbore de análise XML",
        "expand_templates_generate_rawhtml": "Mostrar o HTML en bruto",
        "expand_templates_preview": "Vista previa",
-       "expand_templates_preview_fail_html": "<em>Dado que o código HTML puro está activado en {{SITENAME}} e produciuse unha perda dos datos da sesión, a vista previa está oculta como precaución contra ataques mediante código JavaScript.</em>\n\n<strong>Se este é un intento lexítimo de acceso á vista previa, inténteo de novo.</strong>\nSe segue sen funcionar, probe a [[Special:UserLogout|saír]] e volver a entrar coa súa conta, e revise que o seu navegador permite o uso de \"cookies\" deste sitio.",
+       "expand_templates_preview_fail_html": "<em>Dado que o código HTML puro está activado en {{SITENAME}} e se produciu unha perda dos datos da sesión, a vista previa está oculta como precaución contra ataques mediante código JavaScript.</em>\n\n<strong>Se este é un intento lexítimo de acceso á vista previa, probe de novo.</strong>\nEn caso de que siga sen funcionar, intente [[Special:UserLogout|saír]] e volver entrar na súa conta e verifique que o seu navegador permite o uso de cookies neste sitio.",
        "expand_templates_preview_fail_html_anon": "<em>Dado que o código HTML puro está activado en {{SITENAME}} e produciuse unha perda dos datos da sesión, a vista previa está oculta como precaución contra ataques mediante código JavaScript.</em>\n\n<strong>Se este é un intento lexítimo de acceso á vista previa, probe a [[Special:UserLogout|saír]] e volver a entrar coa súa conta.</strong>",
        "expand_templates_input_missing": "Necesita proporcionar polo menos algún texto de entrada.",
        "pagelanguage": "Cambiar a lingua da páxina",
        "mw-widgets-dateinput-no-date": "Non se seleccionou ningunha data",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Procurar ficheiros multimedia",
+       "mw-widgets-mediasearch-noresults": "Non se atopou ningún resultado.",
        "mw-widgets-titleinput-description-new-page": "a páxina aínda non existe",
        "mw-widgets-titleinput-description-redirect": "redirección cara a $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Engadir unha categoría...",
        "sessionmanager-tie": "Non pode combinar peticións múltiples de tipos de autenticación: $1.",
        "sessionprovider-generic": "sesións $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sesións baseadas nas cookies",
        "log-action-filter-contentmodel-change": "Cambio de modelo de contido",
        "log-action-filter-contentmodel-new": "Creación de páxins cun modelo de contido non estándar",
        "log-action-filter-delete-delete": "Borrado de páxinas",
+       "log-action-filter-delete-delete_redir": "Sobreescritura de redirección",
        "log-action-filter-delete-restore": "Restauración de páxinas",
        "log-action-filter-delete-event": "Borrado de rexistros",
        "log-action-filter-delete-revision": "Borrado de revisión",
        "restrictionsfield-badip": "Enderezo IP ou rango de IP non válido: $1",
        "restrictionsfield-label": "Rangos de IP permitidos:",
        "restrictionsfield-help": "Un único enderezo IP ou rango CIDR por liña. Para habilitalos todos, utilice<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Erro: $1",
-       "edit-error-long": "Erros:\n\n$1"
+       "pageid": "identificador de páxina $1"
 }
index 2dc66a3..4e4e804 100644 (file)
        "yourpasswordagain": "رمزه دۊمارته بنويس",
        "createacct-yourpasswordagain": "رمزه تأىيد بکۊن",
        "createacct-yourpasswordagain-ph": "هندئه رمزه بنويس",
-       "remembermypassword": "رمزه (تا حدأکثر $1 {{PLURAL:$1|رۊز|رۊزؤن}}) اي وبمجˇ مئن ىاد بدأر.",
        "userlogin-remembermypassword": "مره دۊيرين بمأ بدأر",
        "cannotloginnow-title": "هسأ دۊيرين أمأ منين",
        "cannotloginnow-text": "وختي $1 کاردره، نشأنه دۊيرين أمأن.",
        "categories": "جرگه'ن",
        "listusers-noresult": "هيچ کارگيري پىدا نۊبؤ.",
        "activeusers": "فعال کارگيرؤنˇ ليست",
-       "activeusers-hidesysops": "کيا'نه جيگا دأن",
        "activeusers-noresult": "هيچ کارگيري پىدا نۊبؤ.",
        "listgrouprights": "کارگيري پأره دسفأرسؤن",
        "listgrouprights-group": "پأره",
index d4040cb..a12ef51 100644 (file)
        "yourpasswordagain": "गुपीत उतर परतें टायप करात",
        "createacct-yourpasswordagain": "गुपीतउतराची खात्री कर",
        "createacct-yourpasswordagain-ph": "गुपितउतर परत घालात",
-       "remembermypassword": "ह्या ब्राउजराचेर म्हजें लॉग इन याद दवरात (चडांतचड $1 {{PLURAL:$1|दिस|दिसां}} खातीर)",
        "userlogin-remembermypassword": "म्हजें सत्र चालू दवर",
        "userlogin-signwithsecure": "सुरक्षित कनेक्शन वापर",
        "yourdomainname": "तुमचो डोमेन:",
index 975cb88..a3d9b83 100644 (file)
        "yourpasswordagain": "Gupit utor porot boroi:",
        "createacct-yourpasswordagain": "Gupitutrachi khatri kor",
        "createacct-yourpasswordagain-ph": "Gupitutor porot boroi",
-       "remembermypassword": "Hea internet browseran mhojem sotrachem ugdas dovor (chodan chod $1 {{PLURAL:$1|disak|disank}})",
        "userlogin-remembermypassword": "Mhojem sotr chalu dovor",
        "userlogin-signwithsecure": "Surokxit onubondh vapor",
        "yourdomainname": "Tuzo domain:",
index 2aa61b6..1006cc8 100644 (file)
@@ -35,7 +35,7 @@
        "tog-enotifminoredits": "Lawoli surel olo wa'u to'u lo'ubawa ngo'idi halaamani wawu berkas",
        "tog-enotifrevealaddr": "Popobilohe alamati lo surel ola'u to surel lopo'ota",
        "tog-shownumberswatching": "Popobilohe jumula lo ta he'awasiyalo",
-       "tog-oldsig": "Pali lo ulu'u masatiya",
+       "tog-oldsig": "Pali lo ulu'umu masatiya",
        "tog-fancysig": "Popopasiya pali lo'ulu'u odelo tuladuwiki (diyalu tuwawu pranala otomatis)",
        "tog-uselivepreview": "Popohunawa mopobilohu langsung",
        "tog-forceeditsummary": "Popo'eelawa wa'u wonu dosi monguba diipo otuwa",
@@ -52,7 +52,7 @@
        "tog-showhiddencats": "Popobilehe kategori u hewanto'a",
        "tog-norollbackdiff": "Japopobilohe u beda yilapato pilopohalingo",
        "tog-useeditwarning": "Popo'ingatiya wa'u wonu molola halaman he'ubalo wonu dipo tilahu",
-       "tog-prefershttps": "Layito momake koneksi amaani wonu mo maso log",
+       "tog-prefershttps": "Layito momake koneksi aamani wonu tumuwato log",
        "underline-always": "Layito",
        "underline-never": "Dila ta",
        "underline-default": "Alipo meyalo browser dudelo",
        "category-file-count-limited": "Woluwo {{PLURAL:$1|berkas|S1 berkas}} to delomo kategori.",
        "listingcontinuesabbrev": "wumb",
        "index-category": "Halaman to indeks",
-       "noindex-category": "Haalaman dila to indeks",
+       "noindex-category": "Halaman diila to indeks",
        "broken-file-category": "Halaamani wolo pranala berkas ma lorusa",
        "about": "Tomimbihu",
        "article": "Tuwango halaman",
        "newwindow": "hu'owa to janela bohu",
        "cancel": "Batali",
        "moredotdotdot": "Uweewo",
-       "morenotlisted": "Daputari boti dipo ganapu",
+       "morenotlisted": "Daputari boti kira-kira diipo ganapu",
        "mypage": "Halaamani",
        "mytalk": "Lo'iya",
        "anontalk": "Bisala",
        "invalidtitle-knownnamespace": "Judul u ja sah wolo huwali tanggulo \"$2\" wawu teks \"$3\"",
        "exception-nologin": "Diipo tilumuwoto log",
        "exception-nologin-text": "Toduwolo tumuwoto log alihu mowali mokalaja to halaman botiye meyalo huhutu botiye.",
-       "exception-nologin-text-manual": "Toduwolo tumuwoto alihu mowali mohutu halaman meyalo huhutu uweewo.",
+       "exception-nologin-text-manual": "Toduwoolo $1 tumuwoto alihu mowali mohutu halaman meyalo uweewo.",
        "virus-badscanner": "Tilala konfigurasi: pemindai virus ja iloonuhe: ''$1''",
        "virus-scanfailed": "Pemindaian ja lowali (kode $1)",
        "virus-unknownscanner": "antivirus ja'otaawa",
        "loginlanguagelabel": "Bahasa: $1",
        "pt-login": "Tumuwoto log",
        "pt-login-button": "Tumuwoto log",
+       "pt-login-continue-button": "Turusi tumuwoto log",
        "pt-createaccount": "Mohutu akun",
        "pt-userlogout": "Lumuwalo log",
        "botpasswords-label-create": "Mohutu",
        "searchprofile-everything-tooltip": "Mololohe nga'amila tuwango situs (wolo halaman polo'iyalo)",
        "searchprofile-advanced-tooltip": "Mololohu to huwali lo tanggulo biasa",
        "search-result-size": "$1 ({{PLURAL:$2|1 tahe|$2 tahe}})",
-       "search-redirect": "(mopobale $1)",
+       "search-redirect": "(pilobale lonto $1)",
        "search-section": "(tayadu) $1",
        "search-suggest": "Patujumu yito:$1",
        "searchall": "nga'amila",
index 06bfece..99c0a74 100644 (file)
        "yourpasswordagain": "Ἀνατυπῶσαι σύνθημα:",
        "createacct-yourpasswordagain": "Ἐπιβεβαιώσειν σῆμα",
        "createacct-yourpasswordagain-ph": "Παρέχειν σῆμα πάλιν",
-       "remembermypassword": "Μίμνῃσκε ἐνθάδε συνδεῖσθαι (μέγιστον $1 {{PLURAL:$1|ἡμέρα|ἡμέραι}})",
        "userlogin-remembermypassword": "Διατήρησις συνδέσεως",
        "yourdomainname": "Ὁ τομεύς σου:",
        "externaldberror": "Συνέβη εἴτε σφάλμα τι πιστοποιήσεως τῆς βάσεως δεδομένων εἴτε οὐκ ἔξεστί σοι ἐνημεροῦν τὸν ἐξωτερικὸν λογισμόν σου.",
        "undo-failure": "Ἀδύνατος ἡ μεταστροφὴ λόγῳ ἀντικρουομένων ἐνδιαμέσων μεταγραφῶν.",
        "undo-norev": "Ἀδύνατος ἡ μεταστροφὴ τῆσδε τῆς μεταγραφῆς λόγῳ μὴ ὑπάρξεως ἢ προτέρας διαγραφῆς ταύτης.",
        "undo-summary": "Ἀναίρεσις μεταγραφῆς $1 ὑπὸ τὸν/τὴν [[Special:Contributions/$2|$2]] ([[User talk:$2|Διάλεξις]])",
-       "cantcreateaccounttitle": "Μὴ δυνατὴ ἡ ποίησις λογισμοῦ",
        "viewpagelogs": "Ὁρᾶν καταλόγους διὰ ταύτην τὴν δέλτον",
        "nohistory": "Οὐκ ἔστι ἱστορικὸν μεταγραφῶν διὰ τήνδε τὴν δέλτον.",
        "currentrev": "Τὸ νῦν",
        "activeusers": "Κατάλογος ἐνεργῶν χρωμένων",
        "activeusers-count": "$1 {{PLURAL:$1|μεταγραφή|μεταγραφαὶ}} κατὰ {{PLURAL:$3|τὴν πρόσφατον ἡμέραν|τὰς προσφάτους $3 ἡμέρας}}",
        "activeusers-from": "Δεικνύειν χρωμένους ἐκκινήσει ἐκ:",
-       "activeusers-hidebots": "Κρύπτειν αὐτόματα",
-       "activeusers-hidesysops": "Κρύπτειν ἐπιτρόπους",
        "activeusers-noresult": "Οὐδεὶς χρώμενος εὑρέθη.",
        "listgrouprights": "Δικαιώματα ὁμάδος χρωμένου",
        "listgrouprights-group": "Ὁμάς",
index 7639217..4a3207f 100644 (file)
        "activeusers-intro": "Des isch e Lischt vu Benutzer, wu irgedebis bearbeitet hän {{PLURAL:$1|am letschte Tag|in dr letschte $1 Täg}}.",
        "activeusers-count": "$1 {{PLURAL:$1|Aktion|Aktione}} {{PLURAL:$3|am letschte Tag|in dr letschte $3 Täg}}",
        "activeusers-from": "Zeig Benutzer ab:",
-       "activeusers-hidebots": "Bötli uusblände",
-       "activeusers-hidesysops": "Ammanne (Administratore) uusblände",
        "activeusers-noresult": "Kei Benutzer gfunde.",
        "listgrouprights": "Benutzergruppe-Rächt",
        "listgrouprights-summary": "Des isch e Liste vu dr Benutzergruppe, wu in däm Wiki definiert sin, un dr Rächt, wu dermit verbunde sin.\nZuesätzligi Informatione iber einzelni Rächt git s [[{{MediaWiki:Listgrouprights-helppage}}|doo]].",
        "feedback-external-bug-report-button": "E technischi Ufgab yreiche",
        "feedback-dialog-title": "Rückmäldig gä",
        "feedback-dialog-intro": "Du chasch ds eifache Formular unde bruuche, für’ne Rückmäldig z gä. Dy Kommentar chunt zäme mit dym Benutzernamen uf d Syte «$1».",
-       "feedback-error-title": "Fähler",
        "feedback-error1": "Fäälermäldig: Unbekannts Ergebniss vo de API",
        "feedback-error2": "Fääler: Bearbeitig fehlgschlo",
        "feedback-error3": "Fäälermäldig: Kei Antwort vo de API",
index c1757c9..7c47068 100644 (file)
        "yourname": "Dt'ennym ymmydeyr:",
        "yourpassword": "Fockle yn arrey:",
        "yourpasswordagain": "Aascreeu dt'ockle arrey:",
-       "remembermypassword": "Cooinnee m'ockle arrey (rish wheesh as $1 {{PLURAL:$1|laa|laa|laa|laaghyn}})",
        "login": "Log stiagh",
        "nav-login-createaccount": "Log stiagh / croo coontys",
        "userlogin": "Log stiagh / croo coontys",
        "passwordreset-email": "Enmys post-L:",
        "passwordreset-emailelement": "Ennym ymmydeyr: \n$1\n\nFockle arrey shallidagh: \n$2",
        "passwordreset-emailsentemail": "Ta post-l cur gys cooinaghtyn er ny chur dhyt.",
-       "passwordreset-emailsent-capture": "Ta post-l cur gys cooinaghtyn er ny chur dhyt, as eshyn heese.",
-       "passwordreset-emailerror-capture": "Ta post-l cur gys cooinaghtyn er ny chur dhyt, as eshyn heese, agh cha rosh eh yn ymmydeyr: $1",
        "changeemail-none": "(gyn)",
        "bold_sample": "Clou trome",
        "bold_tip": "Clou trome",
        "permissionserrorstext-withaction": "Cha nel kiart ayd $2, er {{PLURAL:$1|y fa|y fa|y fa|ny faghyn}} heese:",
        "recreate-moveddeleted-warn": "'''Raaue: T’ou aachroo duillag as eh er ve scrysst hannah hene.'''\n\nBy chair dhyt smooinagh vel eh kiart goll er oai lesh reaghey yn duillag shoh.<br />\nTa lioar ny scryssaghyn magh kiarit ayns shoh rere dty chaays hene:",
        "editwarning-warning": "My faagys oo y duillag, hed caghlaaghyn erbee er coayl, foddee.\nMy t'ou uss loggalt stiagh, foddee oo lhiettal y raaue shoh 'sy tosheeaghtyn ayd, 'sy rheynn \"Reaghey\".",
-       "cantcreateaccounttitle": "Cha nod coontys y chroo",
        "viewpagelogs": "Jeeagh er ny lioaryn cooishyn son y duillag shoh",
        "currentrev": "Aavriwnys roie",
        "currentrev-asof": "Aavriwnys s'noa er $1",
index 2de6b59..5dcfbd5 100644 (file)
        "yourpasswordagain": "E kikokiko hou i ka ʻōlelo hūnā:",
        "createacct-yourpasswordagain": "E hōʻoia i ka ʻōlelo hūnā",
        "createacct-yourpasswordagain-ph": "E kikokiko hou i ka ʻōlelo hūnā",
-       "remembermypassword": "Hoʻomanaʻo iaʻu ma kēia lolo uila (no ka palena nui o $1 {{PLURAL:$1|lā|mau lā}})",
        "userlogin-remembermypassword": "Hoʻomanaʻo iaʻu",
        "login": "ʻEʻe",
        "nav-login-createaccount": "ʻEʻe / Kāinoa",
index 3af5f05..bf53e1c 100644 (file)
        "views": "צפיות",
        "toolbox": "כלים",
        "tool-link-userrights": "שינוי הרשאות ה{{GENDER:$1|משתמש|משתמשת}}",
+       "tool-link-userrights-readonly": "צפייה בהרשאות ה{{GENDER:$1|משתמש|משתמשת}}",
        "tool-link-emailuser": "שליחת דוא\"ל ל{{GENDER:$1|משתמש|משתמשת}}",
        "userpage": "צפייה בדף המשתמש",
        "projectpage": "צפייה בדף המיזם",
        "passwordreset-emaildisabled": "שירותי הדוא\"ל בוטלו באתר ויקי זה.",
        "passwordreset-username": "שם משתמש:",
        "passwordreset-domain": "תחום:",
-       "passwordreset-capture": "לצפות בדוא\"ל הנשלח?",
-       "passwordreset-capture-help": "אם תסמנו תיבה זו, הדואר האלקטרוני (יחד עם הסיסמה הזמנית) יוצג לכם במקביל לשליחתו למשתמש.",
        "passwordreset-email": "כתובת דוא\"ל:",
        "passwordreset-emailtitle": "פרטי חשבון ב{{grammar:תחילית|{{SITENAME}}}}",
        "passwordreset-emailtext-ip": "מישהו (ככל הנראה אתם, מכתובת ה־IP מספר $1) ביקש איפוס של\nהסיסמה שלכם ב{{grammar:תחילית|{{SITENAME}}}} ($4). {{PLURAL:$3|חשבון המשתמש הבא שייך|חשבונות המשתמש הבאים שייכים}}\nלכתובת הדואר האלקטרוני הזאת:\n\n$2\n\n{{PLURAL:$3|סיסמה זמנית זו תפקע|סיסמאות זמניות אלה יפקעו}} תוך {{PLURAL:$5|יום|יומיים|$5 ימים}}.\nעליכם להיכנס ולבחור סיסמה חדשה עכשיו. אם מישהו אחר ביצע בקשה זו, או שנזכרתם בסיסמתכם\nהמקורית ואינכם רוצים עוד לשנות אותה, באפשרותכם להתעלם מהודעה זו ולהמשיך להשתמש בסיסמה\nהישנה.",
        "passwordreset-emailelement": "שם משתמש:\n$1\n\nסיסמה זמנית:\n$2",
        "passwordreset-emailsentemail": "אם כתובת הדואר האלקטרוני הזאת משויכת לחשבון שלך, אז יישלח דואר אלקטרוני לאיפוס הסיסמה.",
        "passwordreset-emailsentusername": "אם יש כתובת דואר אלקטרוני שמשויכת לשם המשתמש הזה, אז יישלח דואר אלקטרוני לאיפוס הסיסמה.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|דוא\"ל איפוס הסיסמה נשלח|הודעות דוא\"ל של איפוס הסיסמה נשלחו}}. {{PLURAL:$1|שם המשתמשים והסיסמה מוצגים|רשימה של שמות המשתמשים והסיסמאות מוצגת}} כאן.",
-       "passwordreset-emailerror-capture2": "לא ניתן היה לשלוח דוא\"ל ל{{GENDER:$2|משתמש|משתמשת}}: $1 {{PLURAL:$3|שם המשתמש והסיסמה מוצגים|רשימה של שמות המשתמשים והסיסמאות מוצגת}} כאן.",
        "passwordreset-nocaller": "לא סופק הקורא הנדרש",
        "passwordreset-nosuchcaller": "הקורא אינו קיים: $1",
        "passwordreset-ignored": "איפוס הסיסמה לא בוצע. ייתכן שלא הוגדר ספק.",
-       "passwordreset-invalideamil": "כתובת דוא\"ל לא תקינה",
+       "passwordreset-invalidemail": "כתובת דוא\"ל לא תקינה",
        "passwordreset-nodata": "לא סופק שם משתמש או כתובת דוא\"ל",
        "changeemail": "שינוי או הסרת כתובת דוא\"ל",
        "changeemail-header": "יש למלא את הטופס הזה כדי לשנות את כתובת הדוא\"ל שלך. אם ברצונך להימנע משיוך כתובת דוא\"ל כלשהי לחשבון שלך, יש להשאיר את שדה כתובת הדוא\"ל החדשה ריק בעת שליחת הטופס.",
        "search-external": "חיפוש חיצוני",
        "searchdisabled": "חיפוש ב{{grammar:תחילית|{{SITENAME}}}} אינו מופעל כעת.\nבינתיים אפשר לחפש באמצעות גוגל.\nשימו לב שייתכן שהמידע של {{SITENAME}} שם אינו מעודכן.",
        "search-error": "אירעה שגיאה במהלך החיפוש: $1",
+       "search-warning": "אירעה אזהרה במהלך החיפוש: $1",
        "preferences": "העדפות",
        "mypreferences": "העדפות",
        "prefs-edits": "מספר העריכות:",
        "prefs-help-recentchangescount": "ההעדפה הזאת כוללת את דף השינויים האחרונים, דפי היסטוריית גרסאות ויומנים.",
        "prefs-help-watchlist-token2": "זהו המפתח הסודי להזנה של רשימת המעקב שלך.\nכל מי שיודע אותו יכול לקרוא את רשימת המעקב שלך, לכן אין לשתף אותו.\nבמקרה הצורך, אפשר [[Special:ResetTokens|לאפס את האסימון]].",
        "savedprefs": "ההעדפות שלך נשמרו.",
-       "savedrights": "×\94×\94רש×\90×\95ת ×©×\9c {{GENDER:$1|×\94×\9eשת×\9eש|×\94×\9eשת×\9eשת}} \"$1\" נשמרו.",
+       "savedrights": "ק×\91×\95צ×\95ת {{GENDER:$1|×\94×\9eשת×\9eש|×\94×\9eשת×\9eשת}} ×©×\9c \"$1\" נשמרו.",
        "timezonelegend": "אזור זמן:",
        "localtime": "שעה מקומית:",
        "timezoneuseserverdefault": "ברירת המחדל של האתר ($1)",
        "prefswarning-warning": "ביצעת שינויים בהעדפות שלך, והם עדיין לא נשמרו.\nעזיבת דף זה ללא לחיצה על \"$1\" תגרום לכך שההעדפות שלך לא יעודכנו.",
        "prefs-tabs-navigation-hint": "טיפ: ניתן להשתמש במקשי החצים הימני והשמאלי כדי לנווט בין הלשוניות ברשימת הלשוניות.",
        "userrights": "ניהול הרשאות משתמש",
-       "userrights-lookup-user": "× ×\99×\94×\95×\9c ×§×\91×\95צ×\95ת משתמש",
+       "userrights-lookup-user": "×\91×\97×\99רת משתמש",
        "userrights-user-editname": "שם משתמש:",
-       "editusergroup": "ער×\99×\9bת ×\94ק×\91×\95צ×\95ת ×©×\9c ×\94{{GENDER:$1|×\9eשת×\9eש}}",
+       "editusergroup": "×\98×¢×\99נת ×§×\91×\95צ×\95ת ×\94×\9eשת×\9eש",
        "editinguser": "שינוי ההרשאות של {{GENDER:$1|המשתמש|המשתמשת}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "צפייה בהרשאות של {{GENDER:$1|המשתמש|המשתמשת}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "עריכת קבוצות משתמש",
+       "userrights-viewusergroup": "צפייה בקבוצות משתמש",
        "saveusergroups": "שמירת הקבוצות של ה{{GENDER:$1|משתמש|משתמשת}}",
        "userrights-groupsmember": "{{GENDER:$2|חבר|חברה}} ב{{PLURAL:$1|קבוצה|קבוצות}}:",
        "userrights-groupsmember-auto": "{{GENDER:$2|חבר|חברה}} אוטומטית ב{{PLURAL:$1|קבוצה|קבוצות}}:",
        "userrights-reason": "סיבה:",
        "userrights-no-interwiki": "אין לך הרשאה לערוך הרשאות משתמש באתרים אחרים.",
        "userrights-nodatabase": "בסיס הנתונים $1 אינו קיים או אינו מקומי.",
-       "userrights-nologin": "עליכם [[Special:UserLogin|להיכנס לחשבון]] עם הרשאות מתאימות כדי לשנות הרשאות של משתמשים.",
-       "userrights-notallowed": "אין לך הרשאה להוסיף או להסיר הרשאות של משתמשים.",
        "userrights-changeable-col": "{{PLURAL:$1|קבוצה|קבוצות}} שבאפשרותך לשנות",
        "userrights-unchangeable-col": "{{PLURAL:$1|קבוצה|קבוצות}} שאין באפשרותך לשנות",
        "userrights-conflict": "התנגשות בין שינויי הרשאות משתמש! אנא בִּדקו את השינויים שלכם ואשרו אותם.",
-       "userrights-removed-self": "הסרת את הרשאות המשתמש של עצמך. לכן אין לך כעת אפשרות לגשת לדף זה.",
        "group": "קבוצה:",
        "group-user": "משתמשים",
        "group-autoconfirmed": "משתמשים ותיקים",
        "right-siteadmin": "נעילה וביטול נעילה של בסיס הנתונים",
        "right-override-export-depth": "ייצוא דפים כולל הדפים המקושרים (עד עומק של 5 דפים)",
        "right-sendemail": "שליחת דואר אלקטרוני למשתמשים אחרים",
-       "right-passwordreset": "צפייה בדואר אלקטרוני של איפוס סיסמה",
        "right-managechangetags": "יצירה, הפעלה וביטול של [[Special:Tags|תגיות]]",
        "right-applychangetags": "החלת [[Special:Tags|תגיות]] יחד עם שינויים",
        "right-changetags": "הוספה והסרה של [[Special:Tags|תגיות]] לגרסאות ולרשומות יומן",
        "action-upload_by_url": "להעלות קובץ זה מכתובת URL",
        "action-writeapi": "להשתמש ב־API לשינוי דפים",
        "action-delete": "למחוק דף זה",
-       "action-deleterevision": "למחוק גרסה זו",
-       "action-deletedhistory": "לצפות בהיסטוריה המחוקה של דפים",
+       "action-deleterevision": "למחוק גרסאות",
+       "action-deletelogentry": "למחוק פריטי יומן",
+       "action-deletedhistory": "לצפות בהיסטוריה מחוקה של דף",
+       "action-deletedtext": "לצפות בטקסט של גרסה מחוקה",
        "action-browsearchive": "לחפש דפים מחוקים",
-       "action-undelete": "×\9cש×\97×\96ר ×\93×£ ×\96×\94",
-       "action-suppressrevision": "×\9c×\91×\93×\95ק ×\95×\9cש×\97×\96ר ×\92רס×\94 ×\9e×\95סתרת ×\96×\95",
+       "action-undelete": "×\9cש×\97×\96ר ×\93פ×\99×\9d",
+       "action-suppressrevision": "×\9cסק×\95ר ×\95×\9cש×\97×\96ר ×\92רס×\90×\95ת ×\9e×\95סתר×\95ת",
        "action-suppressionlog": "לצפות ביומן הפרטי הזה",
        "action-block": "לחסום משתמשים מעריכה",
        "action-protect": "לשנות את רמת ההגנה של דף זה",
        "action-userrights-interwiki": "לשנות הרשאות של משתמשים באתרי ויקי אחרים",
        "action-siteadmin": "לנעול או לבטל את הנעילה של בסיס הנתונים",
        "action-sendemail": "לשלוח דואר אלקטרוני למשתמשים",
+       "action-editmyoptions": "לערוך את ההעדפות {{GENDER:|שלך|שלך|שלכם}}",
        "action-editmywatchlist": "לערוך את רשימת המעקב {{GENDER:|שלך|שלך|שלכם}}",
        "action-viewmywatchlist": "לצפות ברשימת המעקב {{GENDER:|שלך|שלך|שלכם}}",
        "action-viewmyprivateinfo": "לצפות במידע הפרטי {{GENDER:|שלך|שלך|שלכם}}",
        "apisandbox-continue": "המשך",
        "apisandbox-continue-clear": "ניקוי",
        "apisandbox-continue-help": "\"{{int:apisandbox-continue}}\" [https://www.mediawiki.org/wiki/API:Query#Continuing_queries ימשיך] את הבקשה האחרונה; \"{{int:apisandbox-continue-clear}}\" ינקה את הפרמטרים הקשורים להמשך.",
+       "apisandbox-param-limit": "יש לכתוב <kbd>max</kbd> כדי להשתמש בערך המרבי האפשרי.",
+       "apisandbox-multivalue-all-namespaces": "$1 (כל מרחבי השם)",
+       "apisandbox-multivalue-all-values": "$1 (כל הערכים)",
        "booksources": "משאבי ספרות חיצוניים",
        "booksources-search-legend": "חיפוש משאבי ספרות חיצוניים",
        "booksources-isbn": "מסת\"ב (ISBN):",
        "activeusers-count": "{{PLURAL:$1|פעולה אחת|$1 פעולות}} ב{{PLURAL:$3|יום האחרון|יומיים האחרונים|־$3 הימים האחרונים}}",
        "activeusers-from": "הצגת משתמשים החל מ:",
        "activeusers-groups": "הצגת משתמשים השייכים לקבוצות:",
+       "activeusers-excludegroups": "הסתרת משתמשים השייכים לקבוצות:",
        "activeusers-noresult": "לא נמצאו משתמשים.",
        "activeusers-submit": "הצגת משתמשים פעילים",
        "listgrouprights": "רשימת הרשאות לקבוצה",
        "emailccsubject": "העתק של הודעתך למשתמש $1: $2",
        "emailsent": "הדואר נשלח",
        "emailsenttext": "הודעת הדואר האלקטרוני שלך נשלחה.",
-       "emailuserfooter": "$1 {{GENDER:$1|שלח|שלחה}} את הדוא\"ל הזה ל{{GENDER:$2|משתמש|משתמשת}} $2 באמצעות התכונה \"{{int:emailuser}}\" באתר {{SITENAME}}.",
+       "emailuserfooter": "$1 {{GENDER:$1|שלח|שלחה}} את הדוא\"ל הזה ל{{GENDER:$2|משתמש|משתמשת}} $2 באמצעות התכונה \"{{int:emailuser}}\" באתר {{SITENAME}}. התשובה שלך תישלח ישירות {{GENDER:$1|לשולח המקורי|לשולחת המקורית}}, והיא תחשוף {{GENDER:$1|בפניו|בפניה}} את כתובת הדוא\"ל שלך.",
        "usermessage-summary": "השארת הודעת מערכת.",
        "usermessage-editor": "שולח הודעות המערכת",
        "watchlist": "רשימת המעקב",
        "tags-deactivate": "ביטול הפעלה",
        "tags-hitcount": "{{PLURAL:$1|שינוי אחד|$1 שינויים}}",
        "tags-manage-no-permission": "אין לך הרשאה לנהל תגיות שינויים.",
-       "tags-manage-blocked": "×\9c×\90 × ×\99ת×\9f ×\9c× ×\94×\9c ×ª×\92×\99×\95ת ×©×\99× ×\95×\99×\99×\9d ×\9e×\97ש×\91×\95×\9f ×\9eשת×\9eש חסום.",
+       "tags-manage-blocked": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9c× ×\94×\9c ×ª×\92×\99×\95ת ×©×\99× ×\95×\99×\99×\9d ×\9b×\90שר ×\97ש×\91×\95×\9f ×\94×\9eשת×\9eש {{GENDER:$1|ש×\9c×\9a}} חסום.",
        "tags-create-heading": "יצירת תגית חדשה",
        "tags-create-explanation": "כברירת מחדל, תגיות חדשות שנוצרות יהיו זמינות לשימושם של משתמשים ובוטים.",
        "tags-create-tag-name": "שם התגית:",
        "tags-deactivate-not-allowed": "לא ניתן לבטל את הפעלת התגית \"$1\".",
        "tags-deactivate-submit": "ביטול הפעלה",
        "tags-apply-no-permission": "אין לך הרשאה להחיל תגיות שינויים יחד עם השינויים שלך.",
-       "tags-apply-blocked": "×\9c×\90 × ×\99ת×\9f ×\9c×\94×\97×\99×\9c ×ª×\92×\99×\95ת ×©×\99× ×\95×\99×\99×\9d ×\99×\97×\93 ×¢×\9d ×\94ש×\99× ×\95×\99×\99×\9d ×©×\9c×\9a ×\9e×\97ש×\91×\95×\9f ×\9eשת×\9eש חסום.",
+       "tags-apply-blocked": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9c×\94×\97×\99×\9c ×ª×\92×\99×\95ת ×©×\99× ×\95×\99×\99×\9d ×\99×\97×\93 ×¢×\9d ×\94ש×\99× ×\95×\99×\99×\9d ×©×\9c×\9a ×\9b×\90שר ×\97ש×\91×\95×\9f ×\94×\9eשת×\9eש {{GENDER:$1|ש×\9c×\9a|ש×\9c×\9a}} חסום.",
        "tags-apply-not-allowed-one": "לא ניתן להחיל את התגית \"$1\" ידנית.",
        "tags-apply-not-allowed-multi": "לא ניתן להחיל את {{PLURAL:$2|התגית הבאה|התגיות הבאות}} ידנית: $1",
        "tags-update-no-permission": "אין לך הרשאה להוסיף או להסיר תגיות שינויים לגרסאות מסוימות או לרשומות יומן.",
-       "tags-update-blocked": "×\9c×\90 × ×\99ת×\9f ×\9c×\94×\95ס×\99×£ ×\90×\95 ×\9c×\94ס×\99ר ×ª×\92×\99×\95ת ×©×\99× ×\95×\99×\99×\9d ×\9e×\97ש×\91×\95×\9f ×\9eשת×\9eש חסום.",
+       "tags-update-blocked": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9c×\94×\95ס×\99×£ ×\90×\95 ×\9c×\94ס×\99ר ×ª×\92×\99×\95ת ×©×\99× ×\95×\99×\99×\9d ×\9b×\90שר ×\97ש×\91×\95×\9f ×\94×\9eשת×\9eש {{GENDER:$1|ש×\9c×\9a|ש×\9c×\9a}} חסום.",
        "tags-update-add-not-allowed-one": "לא ניתן להוסיף את התגית \"$1\" ידנית.",
        "tags-update-add-not-allowed-multi": "לא ניתן להוסיף את {{PLURAL:$2|התגית הבאה|התגיות הבאות}} ידנית: $1",
        "tags-update-remove-not-allowed-one": "לא ניתן להסיר את התגית \"$1\".",
        "htmlform-user-not-exists": "<strong>$1</strong> אינו קיים.",
        "htmlform-user-not-valid": "<strong>$1</strong> אינו שם משתמש תקין.",
        "logentry-delete-delete": "$1 {{GENDER:$2|מחק|מחקה}} את הדף $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|מחק|מחקה}} את ההפניה $3 באמצעות דריסה",
        "logentry-delete-restore": "$1 {{GENDER:$2|שחזר|שחזרה}} את הדף $3",
        "logentry-delete-event": "$1 {{GENDER:$2|שינה|שינתה}} את מצב התצוגה של {{PLURAL:$5|פעולת יומן|$5 פעולות יומן}} של $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|שינה|שינתה}} את מצב התצוגה של {{PLURAL:$5|גרסה|$5 גרסאות}} בדף $3: $4",
        "special-characters-title-emdash": "קו מפריד ארוך",
        "special-characters-title-minus": "מינוס",
        "mw-widgets-dateinput-no-date": "לא נבחר תאריך",
+       "mw-widgets-mediasearch-input-placeholder": "חיפוש מדיה",
+       "mw-widgets-mediasearch-noresults": "לא נמצאו תוצאות.",
        "mw-widgets-titleinput-description-new-page": "הדף עדיין לא קיים",
        "mw-widgets-titleinput-description-redirect": "הפניה ל{{GRAMMAR:תחילית|$1}}",
+       "mw-widgets-categoryselector-add-category-placeholder": "הוספת קטגוריה...",
        "sessionmanager-tie": "לא ניתן לצרף מספר סוגי אימות זהות: $1.",
        "sessionprovider-generic": "התחברויות של $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "התחברויות המבוססות על עוגיות",
        "log-action-filter-contentmodel-change": "שינויים במודל התוכן של דפים קיימים",
        "log-action-filter-contentmodel-new": "יצירות של דפים עם מודל תוכן שונה מברירת המחדל",
        "log-action-filter-delete-delete": "מחיקות של דפים",
+       "log-action-filter-delete-delete_redir": "דריסות של הפניות",
        "log-action-filter-delete-restore": "שחזורים של דפים מחוקים",
        "log-action-filter-delete-event": "מחיקות של פעולות יומן",
        "log-action-filter-delete-revision": "מחיקות של גרסאות",
        "restrictionsfield-badip": "כתובת או טווח כתובות IP בלתי תקין: $1",
        "restrictionsfield-label": "טווחי כתובות IP מותרים:",
        "restrictionsfield-help": "כתובת IP אחת או טווח CIDR אחד בשורה. כדי לאפשר את הכול, ניתן להשתמש ב:<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "שגיאה: $1",
-       "edit-error-long": "שגיאות:\n\n$1"
+       "revid": "גרסה $1",
+       "pageid": "מזהה דף $1"
 }
index 3c7cc5b..753316c 100644 (file)
        "tog-enotifminoredits": "छोटे परिवर्तनों के लिए भी मुझे ईमेल भेजें",
        "tog-enotifrevealaddr": "अधिसूचना ईमेल में मेरा ईमेल पता दर्शायें",
        "tog-shownumberswatching": "ध्यान रखने वाले सदस्यों की संख्या दिखायें",
-       "tog-oldsig": "वर्तमान हस्ताक्षर:",
+       "tog-oldsig": "à¤\86पà¤\95ा à¤µà¤°à¥\8dतमान à¤¹à¤¸à¥\8dताà¤\95à¥\8dषर:",
        "tog-fancysig": "हस्ताक्षर का विकिपाठ के समान मानें (बिना स्वचालित कड़ी के)",
        "tog-uselivepreview": "सजीवन झलक का उपयोग करें",
        "tog-forceeditsummary": "यदि सम्पादन सारांश ना दिया गया हो तो मुझे सूचित करें",
        "category-file-count-limited": "इस श्रेणी में निम्नलिखित {{PLURAL:$1|फ़ाइल है।|फ़ाइलें हैं।}}",
        "listingcontinuesabbrev": "जारी",
        "index-category": "सूचीबद्ध पृष्ठ",
-       "noindex-category": "असूचीबद्ध पृष्ठों",
+       "noindex-category": "असूचीबद्ध पृष्ठ",
        "broken-file-category": "टूटी हुई फ़ाइल कड़ियों वाले पृष्ठ",
        "about": "के बारे में",
        "article": "सामग्री लेख",
        "newwindow": "(नई विंडो में खुलता है)",
        "cancel": "रद्द करें",
        "moredotdotdot": "और...",
-       "morenotlisted": "यह सूची पूर्ण नहीं है।",
+       "morenotlisted": "शायद à¤¯à¥\87 सूची पूर्ण नहीं है।",
        "mypage": "पृष्ठ",
        "mytalk": "वार्ता",
        "anontalk": "वार्ता",
        "talk": "चर्चा",
        "views": "दर्शाव",
        "toolbox": "उपकरण",
+       "tool-link-userrights": "{{GENDER:$1|सदस्य}} समूह बदलें",
+       "tool-link-userrights-readonly": "{{GENDER:$1|सदस्य}} समूह देखें",
+       "tool-link-emailuser": "इस {{GENDER:$1|सदस्य}} को ई-मेल करें।",
        "userpage": "सदस्य पृष्ठ देखें",
        "projectpage": "परियोजना पृष्ठ देखें",
        "imagepage": "फ़ाइल पृष्ठ देखें",
        "pagetitle-view-mainpage": "{{SITENAME}}",
        "backlinksubtitle": "← $1",
        "retrievedfrom": "\"$1\" से लिया गया",
-       "youhavenewmessages": "आपके लिए $1 हैं। ($2)",
-       "youhavenewmessagesfromusers": "आपके लिये {{PLURAL:$3|एक अन्य सदस्य|$3 अन्य सदस्यों}} के $1 हैं। ($2)",
+       "youhavenewmessages": "{{PLURAL:$3|आपके लिए}} $1 हैं। ($2)",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|आपके लिये}} {{PLURAL:$3|एक अन्य सदस्य|$3 अन्य सदस्यों}} के $1 हैं। ($2)",
        "youhavenewmessagesmanyusers": "आपके लिये $1 हैं। ($2)",
        "newmessageslinkplural": "{{PLURAL:$1|एक नया सन्देश|999=नये सन्देश}}",
        "newmessagesdifflinkplural": "{{PLURAL:$1|पिछला|999=पिछले}} बदलाव",
        "createacct-yourpasswordagain-ph": "कूटशब्द पुनः लिखें",
        "userlogin-remembermypassword": "मुझे लॉग्ड इन रखें",
        "userlogin-signwithsecure": "सुरक्षित कनेक्शन का प्रयोग करें",
+       "cannotlogin-title": "अभी प्रवेश नहीं हो रहा",
+       "cannotlogin-text": "प्रवेश संभव नहीं है",
        "cannotloginnow-title": "अभी प्रवेश नहीं हो रहा है",
        "cannotloginnow-text": "$1 का उपयोग करते समय प्रवेश नहीं हो सकता है।",
+       "cannotcreateaccount-title": "खाता नहीं खोल सकते",
+       "cannotcreateaccount-text": "सीधे खाता बनाना इस विकि में सक्रिय नहीं है।",
        "yourdomainname": "आपका डोमेन:",
        "password-change-forbidden": "आप इस विकि पर कूटशब्द नहीं बदल सकते हैं।",
        "externaldberror": "या तो प्रमाणिकरण डाटाबेस में त्रुटि हुई है या फिर आपको अपना बाह्य खाता अपडेट करने की अनुमति नहीं है।",
        "noemail": "\"$1\" सदस्य के लिये कोई भी ई-मेल पता दर्ज नहीं किया गया है।",
        "noemailcreate": "आपको वैध ई-मेल पता देने होगा।",
        "passwordsent": "\"$1\" के ई-मेल पते पर एक नया कूटशब्द भेज दिया गया है।\nई-मेल पाने बाद कृपया दुबारा लॉग इन करें।",
-       "blocked-mailpassword": "à¤\86पà¤\95à¥\87 à¤\86à¤\87॰पà¥\80 à¤ªà¤¤à¥\87 à¤\95à¥\8b à¤¸à¤®à¥\8dपादन à¤\95रनà¥\87 à¤¸à¥\87 à¤\85वरà¥\81दà¥\8dध à¤\95र à¤¦à¤¿à¤¯à¤¾ à¤\97या à¤¹à¥\88, à¤\94र à¤\97लत à¤\87सà¥\8dतà¥\87माल à¤°à¥\8bà¤\95नà¥\87 à¤\95à¥\87 à¤²à¤¿à¤¯à¥\87 à¤\95à¥\82à¤\9fशबà¥\8dद à¤ªà¥\81नà¤\83 à¤ªà¥\8dरापà¥\8dति à¤\95à¥\80 à¤¸à¥\81विधा à¤\87स à¤\86à¤\87॰पà¥\80 पर बंद कर दी गई है।",
+       "blocked-mailpassword": "à¤\86पà¤\95à¥\87 à¤\86à¤\87॰पà¥\80 à¤ªà¤¤à¥\87 à¤\95à¥\8b à¤¸à¤®à¥\8dपादन à¤\95रनà¥\87 à¤¸à¥\87 à¤\85वरà¥\81दà¥\8dध à¤\95र à¤¦à¤¿à¤¯à¤¾ à¤\97या à¤¹à¥\88, à¤\94र à¤\97लत à¤\87सà¥\8dतà¥\87माल à¤°à¥\8bà¤\95नà¥\87 à¤\95à¥\87 à¤²à¤¿à¤¯à¥\87 à¤\95à¥\82à¤\9fशबà¥\8dद à¤ªà¥\81नà¤\83 à¤ªà¥\8dरापà¥\8dति à¤\95à¥\80 à¤¸à¥\81विधा à¤\87स à¤\86à¤\88॰ à¤ªà¥\80॰ पर बंद कर दी गई है।",
        "eauthentsent": "दर्ज किये हुए ई-मेल पते पर एक सत्यापन ई-मेल भेजा दिया गया है।\nआपको उस ई-मेल में दिये हुए निर्देशों के अनुसार ई-मेल पते का सत्यापन करना होगा, उसके पश्चात ही यहाँ से कोई दूसरा ई-मेल भेजा जाएगा।",
        "throttled-mailpassword": "पिछले {{PLURAL:$1|एक घंटे|$1 घंटों}} के दरमियान एक कूटशब्द स्मरण-पत्र भेजा जा चुका है।\nदुरुपयोग से बचाव के लिए हर {{PLURAL:$1|एक घंटे|$1 घंटों}} में एक कूटशब्द स्मरण-पत्र ही भेजा जाता है।",
        "mailerror": "ई-मेल भेजने में त्रुटि: $1",
        "passwordreset-emaildisabled": "इस विकि पर ई-मेल सुविधा अक्षम कर दी गयी है।",
        "passwordreset-username": "सदस्यनाम:",
        "passwordreset-domain": "डोमेन:",
-       "passwordreset-capture": "परिणामस्वरूप बना ई-मेल देखें?",
-       "passwordreset-capture-help": "अगर आप इस चेकबॉक्स को टिक करते हैं तो ई-मेल (अस्थायी कूटशब्द के साथ) आप को दिखया जाएगा और सदस्य को भेजा भी जयेगा।",
        "passwordreset-email": "ई-मेल पता:",
        "passwordreset-emailtitle": "{{SITENAME}} पर खाते का विवरण",
        "passwordreset-emailtext-ip": "किसी ने (शायद आपने ही, $1 आइ॰पी पते से) {{SITENAME}} ($4) पर अपने {{PLURAL:$3|कूटशब्द|कूटशब्दों}} को रीसेट करने का अनुरोध किया है। इस ई-मेल पते से निम्न {{PLURAL:$3|खाता जुड़ा है|खाते जुड़े हैं}}:\n\n$2\n\n{{PLURAL:$3|यह|ये}} अस्थायी कूटशब्द {{PLURAL:$5|एक दिन|$5 दिनों}} के बाद काम नहीं करेंगे। आपको लॉग इन करके एक नया कूटशब्द अभी चुन लेना चाहिए। यदि यह अनुरोध किसी और ने किया है, या फिर आपको अपना मूल कूटशब्द याद आ गया है, और आप {{PLURAL:$3|अपना|अपने}} कूटशब्द नहीं बदलना चाहते, आप इस संदेश को अनदेखा कर के अपने पुराने कूटशब्द का प्रयोग जारी रख सकते हैं।",
        "passwordreset-emailelement": "सदस्यनाम: \n$1\n\nअस्थायी कूटशब्द: \n$2",
        "passwordreset-emailsentemail": "यदि आपका यह ईमेल आपके खाते के साथ जोड़ा गया है तो पासवर्ड बदलने का ईमेल इसमें भेज दिया गया है।",
        "passwordreset-emailsentusername": "यदि कोई ईमेल इस खाते से जुड़ी है तो पासवर्ड आपके ईमेल में भेज दिया जाएगा।",
-       "passwordreset-emailerror-capture2": "{{GENDER:$2|सदस्य}} को ईमेल भेजना विफल : $1 {{PLURAL:$3|सदस्य नाम और पासवर्ड|सदस्य नाम और पासवर्ड की सूची}} नीचे दिया गया है।",
-       "passwordreset-invalideamil": "अवैध ईमेल पता",
+       "passwordreset-invalidemail": "अवैध ईमेल पता",
        "changeemail": "ई-मेल पता परिवर्तित करें",
        "changeemail-header": "अपना ईमेल पता परिवर्तन हेतु इसे पूरा करें। यदि आप अपना वर्तमान ईमेल पता हटाना चाहते हैं, तो इसे खाली छोड़ दें और इसे भेजें।",
        "changeemail-no-info": "इस पृष्ठ का सीधे प्रयोग करने के लिए आपको लॉग इन करना होगा।",
        "nextn-title": "{{PLURAL:$1|अगला|अगले}} $1 परिणाम",
        "shown-title": "हर पृष्ठ पर $1 {{PLURAL:$1|परिणाम}} दिखाएँ",
        "viewprevnext": "देखें ($1 {{int:pipe-separator}} $2) ($3)",
-       "searchmenu-exists": "'''इस विकि पर \"[[:$1]]\" नाम का एक पृष्ठ है'''",
+       "searchmenu-exists": "<strong>इस विकि पर \"[[:$1]]\" नाम से एक पृष्ठ है।</strong> {{PLURAL:$2|0=|अन्य प्राप्त खोज परिणामों को भी देखें।}}",
        "searchmenu-new": "<strong>इस विकि पर \"[[:$1]]\" नाम का पृष्ठ बनाएँ!</strong>{{PLURAL:$2|0=|आपकी खोज से मिला पृष्ठ भी देखें।|खोज परिणाम भी देखें।}}",
        "searchprofile-articles": "सामग्री पृष्ठ",
        "searchprofile-images": "मल्टीमीडिया",
        "userrights-reason": "कारण:",
        "userrights-no-interwiki": "आपको अन्य विकियों पर सदस्य अधिकार बदलने की अनुमति नहीं हैं।",
        "userrights-nodatabase": "डाटाबेस $1 या तो मौजूद नहीं है या फिर स्थानीय नहीं है।",
-       "userrights-nologin": "सदस्य अधिकार बदलने के लिये प्रबंधक खाते से [[Special:UserLogin|लॉग इन]] किया हुआ होना आवश्यक है।",
-       "userrights-notallowed": "आपके पास सदस्य अधिकार जोड़ने या हटाने की अनुमति नहीं है।",
        "userrights-changeable-col": "समूह जिन्हें आप बदल सकते हैं",
        "userrights-unchangeable-col": "समूह जिन्हें आप नहीं बदल सकते हैं",
        "userrights-conflict": "सदस्य अधिकार बदलावों में अंतर्विरोध! कृपया अपने बदलाव जाँचें और पुनः सुनिश्चित करें।",
-       "userrights-removed-self": "आपने सफलतापूर्वक अपने अधिकार हटा दिए हैं। अतः आप अब यह पृष्ठ नहीं देख सकते हैं।",
        "group": "समूह:",
        "group-user": "सदस्य",
        "group-autoconfirmed": "स्वतः स्थापित सदस्य",
        "right-siteadmin": "डाटाबेस को ताला लगायें या खोलें",
        "right-override-export-depth": "पृष्ठ निर्यात करें, पाँच स्तर की गहराई तक जुड़े हुए पृष्ठों समेत",
        "right-sendemail": "अन्य सदस्यों को ई-मेल भेजें",
-       "right-passwordreset": "कूटशब्द रीसेट ई-मेल देखें",
        "right-managechangetags": "डेटाबेस से [[Special:Tags|चिप्पियाँ]] बनायें और हटायें",
        "right-applychangetags": "प्रयोग में लाइये [[Special:Tags|tags]] किसी के बदलाव के साथ।",
        "right-changetags": "जमा करो और हटाओ स्वतंत्र [[Special:Tags|टैग]] व्यक्तिगत अवतरणों और लॉग प्रविक्तियों पर",
        "grant-group-high-volume": "उच्च कार्य गतिविधि करें",
        "grant-group-customization": "पसंद और तय",
        "grant-group-administration": "प्रबंधकीय कार्य करें",
+       "grant-group-private-information": "अपने बारे में निजी जानकारी देखें",
        "grant-group-other": "अन्य गतिविधि",
        "grant-blockusers": "प्रतिबंधित और अप्रतिबंधित करना",
        "grant-createaccount": "खाता बनाएँ",
        "grant-highvolume": "अत्यधिक तेजी से सम्पादन",
        "grant-oversight": "सदस्य को छुपाना और अवतरण हटाना",
        "grant-patrol": "पृष्ठों को जांचा हुआ चिन्हित करना",
+       "grant-privateinfo": "निजी जानकारी देखें",
        "grant-protect": "पृष्ठों को सुरक्षित व असुरक्षित करना",
        "grant-rollback": "पृष्ठ से सम्पादन वापस लेना",
        "grant-sendemail": "अन्य सदस्यों को ई-मेल भेजें",
        "rightslogtext": "यह सदस्य अधिकारों में हुए बदलावों की सूची है।",
        "action-read": "इस पृष्ठ को पढ़ने",
        "action-edit": "इस पृष्ठ को सम्पादित करने",
-       "action-createpage": "पà¥\83षà¥\8dठ à¤¬à¤¨à¤¾à¤¨à¥\87",
-       "action-createtalk": "वारà¥\8dता à¤ªà¥\83षà¥\8dठ à¤¬à¤¨à¤¾à¤¨à¥\87",
+       "action-createpage": "à¤\87स à¤ªà¤¨à¥\8dनà¥\87 à¤\95à¥\8b à¤¬à¤¨à¤¾à¤¯à¥\87à¤\82",
+       "action-createtalk": "à¤\87स à¤µà¤¾à¤°à¥\8dता à¤ªà¤¨à¥\8dनà¥\87 à¤\95à¥\8b à¤¬à¤¨à¤¾à¤¯à¥\87à¤\82",
        "action-createaccount": "यह सदस्य खाता खोलने",
        "action-autocreateaccount": "स्वतः ही बाहरी सदस्य खाता बनायें",
        "action-history": "इस पृष्ठ का इतिहास देखने",
        "action-managechangetags": "डेटाबेस से चिप्पि बनायें और हटायें",
        "action-applychangetags": "अपमे बदलाव के साथ टैग जोड़ें।",
        "action-changetags": "जमा करें और हटाएँ स्वतंत्र टैग व्यक्तिगत अवतरणों और लॉग प्रविक्तियों पर",
+       "action-purge": "पृष्ठ ताजा करें",
        "nchanges": "$1 {{PLURAL:$1|बदलाव}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|अंतिम बार देखने के बाद से}}",
        "enhancedrc-history": "इतिहास",
        "upload-foreign-cant-upload": "यह विकि अन्य फ़ाइल संग्रह में अपलोड हेतु तय नहीं किया गया है।",
        "upload-dialog-title": "फ़ाइल डालें",
        "upload-dialog-button-cancel": "रद्द करें",
+       "upload-dialog-button-back": "पीछे",
        "upload-dialog-button-done": "पूर्ण हुआ",
        "upload-dialog-button-save": "सहेजें",
        "upload-dialog-button-upload": "डालें",
        "apisandbox-results-fixtoken-fail": "टोकन \"$1\" डालने में विफल",
        "apisandbox-alert-page": "इस पृष्ठ के जगह अमान्य है।",
        "apisandbox-alert-field": "जगह में डाला गया जानकारी अमान्य है।",
+       "apisandbox-continue": "जारी रखें",
+       "apisandbox-continue-clear": "खाली करें",
+       "apisandbox-multivalue-all-namespaces": "$1 (सभी नामस्थान)",
+       "apisandbox-multivalue-all-values": "$1 (सभी मूल्य)",
        "booksources": "पुस्तकों के स्रोत",
        "booksources-search-legend": "पुस्तकों के स्रोत खोजें",
        "booksources-isbn": "आइ॰एस॰बी॰एन:",
        "activeusers-intro": "यह सक्रिय सदस्यों की सूची है जिन्होंने पिछले $1 {{PLURAL:$1|दिन|दिनों}} में कुछ गतिविधि करी है।",
        "activeusers-count": "$1 {{PLURAL:$1|कार्य}} पिछले $3 {{PLURAL:$3|दिन|दिनों}} में",
        "activeusers-from": "इस अक्षर से शुरू होने वाले सदस्य दिखाएँ:",
-       "activeusers-hidebots": "बॉट छुपाएँ",
-       "activeusers-hidesysops": "प्रबंधक छुपाएँ",
        "activeusers-noresult": "कोई सदस्य नहीं मिले।",
        "activeusers-submit": "सक्रिय सदस्यों को दिखायें",
        "listgrouprights": "सदस्य समूह अधिकार",
        "rollbacklinkcount": "$1 {{PLURAL:$1|सम्पादन}} वापिस लें",
        "rollbacklinkcount-morethan": "$1 से अधिक {{PLURAL:$1|सम्पादन}} वापिस लें",
        "rollbackfailed": "वापिस लेना असफल रहा",
+       "rollback-missingrevision": "अवतरण डाटा दिखाने में असमर्थ।",
        "cantrollback": "पुराने अवतरण को पूर्ववत नहीं कर सकते हैं;\nइस पृष्ठ का अन्तिम योगदानकर्ता इस लेख का एकमात्र लेखक है।",
        "alreadyrolled": "[[User:$2|$2]] ([[User talk:$2|वार्ता]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) द्वारा किए गए  [[:$1]] के पिछले संपादन को वापिस पुरानी स्थिति पर नहीं लाया जा सकता है;\nकिसी और ने इस बीच या तो इस पृष्ठ को फिर से संपादित कर दिया है या पहले ही पृष्ठ पुरानी स्थिति पर लाया जा चुका है।\n\nइस पृष्ठ का अन्तिम संपादन [[User:$3|$3]] ([[User talk:$3|वार्ता]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) ने किया है।",
        "editcomment": "संपादन सारांश था: <em>$1</em>।",
        "sp-contributions-username": "आईपी पता या सदस्यनाम:",
        "sp-contributions-toponly": "केवल उन सम्पादनों को दिखाएँ जो नवीनतम संशोधन हैं",
        "sp-contributions-newonly": "केवल वे सम्पादन दिखाएँ जिनसे पृष्ठ निर्मित हुए हों",
+       "sp-contributions-hideminor": "छोटे सम्पादन छुपाएँ",
        "sp-contributions-submit": "खोजें",
        "whatlinkshere": "यहाँ के हवाले कहाँ कहाँ हैं",
        "whatlinkshere-title": "$1 से जुड़े हुए पृष्ठ",
        "pageinfo-article-id": "पृष्ठ आइ॰डी",
        "pageinfo-language": "पृष्ठ सामग्री भाषा",
        "pageinfo-content-model": "पृष्ठ सामग्री का नमूना",
+       "pageinfo-content-model-change": "बदलें",
        "pageinfo-robot-policy": "सर्च इंजन बॉट द्वारा अनुक्रमण",
        "pageinfo-robot-index": "अनुमतित",
        "pageinfo-robot-noindex": "नहीं अनुमतित",
        "pageinfo-category-pages": "पृष्ठ संख्या",
        "pageinfo-category-subcats": "उपश्रेणियों की संख्या",
        "pageinfo-category-files": "फ़ाइलों की संख्या",
+       "pageinfo-user-id": "सदस्य पता",
        "markaspatrolleddiff": "जाँचा हुआ चिन्हित करें",
        "markaspatrolledtext": "इस पृष्ठ को जाँचा हुआ चिन्हित करें",
        "markaspatrolledtext-file": "इस फ़ाइल संस्करण को जांचा हुआ चिन्हित करें",
        "patrol-log-header": "यह परीक्षित अवतरणों की लॉग है।",
        "log-show-hide-patrol": "परीक्षण लॉग $1",
        "log-show-hide-tag": "$1 टैग लॉग",
+       "confirm-markpatrolled-button": "ठीक है",
        "deletedrevision": "पुराना अवतरण $1 हटा दिया",
        "filedeleteerror-short": "फ़ाईल हटानेमें समस्या: $1",
        "filedeleteerror-long": "फ़ाईल हटानेमें आईं समस्यायें:\n\n$1",
        "htmlform-cloner-create": "अधिक जोड़ें",
        "htmlform-cloner-delete": "हटाएँ",
        "htmlform-cloner-required": "कम से कम एक मूल्य की आवश्यकता है।",
+       "htmlform-date-placeholder": "वववव-मम-दद",
+       "htmlform-time-placeholder": "घघ:मम:सस",
+       "htmlform-datetime-placeholder": "वववव-मम-दद हह:मम:सस",
        "htmlform-title-badnamespace": "[[:$1]] अभी \"{{ns:$2}}\" नामस्थान में नहीं है।",
        "htmlform-title-not-creatable": "\"$1\" निर्माण करने लायक शीर्षक नहीं है।",
        "htmlform-title-not-exists": "$1 नहीं बना है।",
        "feedback-thanks": "धन्यवाद! आपकी प्रतिक्रिया पृष्ठ में नियुक्त किया गया है \"[ $2  $1 ]\"।",
        "feedback-thanks-title": "धन्यवाद!",
        "feedback-useragent": "सदस्य कर्ता:",
-       "searchsuggest-search": "खोज",
+       "searchsuggest-search": "खोजें {{SITENAME}}",
        "searchsuggest-containing": "...से युक्त",
        "api-error-autoblocked": "आपका आईपी पता अपने आप अवरोधित हो गया, क्योंकि यह किसी अवरोधित सदस्य द्वारा उपयोग किया गया था।",
        "api-error-badaccess-groups": "आपको इस विकि के लिए फ़ाइलें अपलोड करने की अनुमति नहीं है.",
        "mw-widgets-dateinput-placeholder-day": "DD-MM-YYYY",
        "mw-widgets-titleinput-description-new-page": "पृष्ठ अभी मौजूद नहीं है",
        "mw-widgets-titleinput-description-redirect": "$1 को अनुप्रेषित",
+       "mw-widgets-categoryselector-add-category-placeholder": "श्रेणी जोड़ें...",
        "sessionmanager-tie": "एक साथ कई अनुरोध को नहीं मिला सकता: $1",
        "sessionprovider-generic": "$1 सत्र",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "कुकी-आधारित सत्र",
        "log-action-filter-delete-restore": "पृष्ठ न हटाना",
        "log-action-filter-delete-event": "पृष्ठ हटाने का लॉग",
        "log-action-filter-delete-revision": "अवतरण हटाना",
+       "log-action-filter-import-interwiki": "अंतरविकि आयात",
+       "log-action-filter-import-upload": "एक्सएमएल अपलोड द्वारा आयात",
        "log-action-filter-managetags-create": "चिप्पि निर्मित",
        "log-action-filter-newusers-create": "अज्ञात सदस्य द्वारा निर्मित",
        "log-action-filter-newusers-create2": "पंजीकृत सदस्य द्वारा निर्मित",
index 9197873..f694e21 100644 (file)
        "yourpasswordagain": "Password fir se type karo:",
        "createacct-yourpasswordagain": "Aapan password ke confirm karo",
        "createacct-yourpasswordagain-ph": "Hame lagged in rahan do",
-       "remembermypassword": "Ii computer pe hamaar login yaad rakho (jaada se jaada $1 {{PLURAL:$1|din|din}} talak)",
        "userlogin-remembermypassword": "Secure connection ke kaam me lao",
        "userlogin-signwithsecure": "Secure connection ke kaam me lao",
        "yourdomainname": "Aap ke domain:",
        "passwordreset-emailelement": "Sadasya ke naam: \n$1\n\nKuchh din ke khatir password: \n$2",
        "passwordreset-emailsentemail": "Agar ii email aap ke account se associated hai tab ek password reset email ke bheja jaai.",
        "passwordreset-emailsentusername": "Agar ii email aap ke username se associated hai tab ek password reset email ke bheja jaai.",
-       "passwordreset-emailsent-capture": "Ek password yaad karae waala e-mail, jiske niche dekhawa jaawe hae, ke bhej dewa gais hae.",
-       "passwordreset-emailerror-capture": "Ek password yaad karae waala e-mail ke banawa gais hae, jiske niche dekhawa jaawe hae, lekin jiske {{GENDER:$2|user}} ke lage bheje nai jawa sake hae: $1",
        "changeemail": "E-mail address ke badlo, nai to, hatao",
        "changeemail-header": "Aapan email ke badle ke khatir ii form ke bharo. Agar aap koi email ke aapan account se nai associate kare mangtaa hai tab form ke submit kare ke time email address ke blank chhorr do.",
-       "changeemail-passwordrequired": "Ii badlao ke confirm kare ke khatir aap ke aapan password ke enter kare ke parri.",
        "changeemail-no-info": "Ii panna ke sidha dekhe ke khaatir, aap ke login kare ke parri.",
        "changeemail-oldemail": "Abhi ke E-mail address:",
        "changeemail-newemail": "Nawaa E-mail address:",
        "undo-nochange": "Janae hae ki badlao ke pahile delete kar dewa gais hae.",
        "undo-summary": "$1 badlao [[Special:Contributions/$2|$2]] se, ke pahile jaise karo ([[User talk:$2|Talk]])",
        "undo-summary-username-hidden": "Hidden sadasya ke badalo $1 ke pahile jaise karo",
-       "cantcreateaccounttitle": "Account nai banae sakta hai",
        "cantcreateaccount-text": "Ii IP address ('''$1''') se nawaa account banae ke [[User:$3|$3]] block kar diis hai.\n\nIske kaaran, jon ki $3 diis hai, ''$2'' hai",
        "cantcreateaccount-range-text": "Nawaa account banae ke IP addresses range <strong>$1</strong>, jisme aap ke IP address (<strong>$4</strong>) hae, ke[[User:$3|$3]] block kar diis hae.\n\n$3 ke kaaran hae <em>$2</em>",
        "viewpagelogs": "Ii panna ke suchi dekho",
        "activeusers-intro": "Ii suchi uu sadasya ke hae jon ki pahile {{PLURAL:$1|din|din}} me kuchh karin hae.",
        "activeusers-count": "$1 haali ke {{PLURAL:$1|badlao}} pichhle {{PLURAL:$3|din}} me",
        "activeusers-from": "Sadasya jon ki hian se suruu hoe hai ke dekhao:",
-       "activeusers-hidebots": "Bots ke lukao",
-       "activeusers-hidesysops": "Administrator log ke lukao",
        "activeusers-noresult": "koi sadasya ke pawa nai gais hai.",
        "listgrouprights": "Sadasya  ke group adhikar",
        "listgrouprights-summary": "Niche likha hai ek suchi hai groups ke jon ki ii wiki me defined hai, aapan  associated access rights ke saathe\n[[{{MediaWiki:Listgrouprights-helppage}}|additional information]] individual rights ke baare me sait hoi.",
        "htmlform-cloner-create": "Aur add karo",
        "htmlform-cloner-delete": "Remove karo",
        "htmlform-cloner-required": "Kamti se kamti ek value ke jaruri hae",
-       "sqlite-has-fts": "$1 with full-text search support",
-       "sqlite-no-fts": "$1 without full-text search support",
        "logentry-delete-delete": "$1 {{GENDER:$2|deleted}} panna $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|restored}} panna $3",
        "logentry-delete-event": "$1 {{GENDER:$2|changed}} visibility of {{PLURAL:$5|a log event|$5 log events}} on $3: $4",
index 0869b55..59ff3f2 100644 (file)
        "userlogin-yourname-ph": "Ipasulod ang imo nga ngalan-taggamit",
        "yourpassword": "Kontra-senyas:",
        "yourpasswordagain": "Suliton ang kontra-senyas:",
-       "remembermypassword": "Dumdumon ang akon pagsulod sa sini nga brawser (para sa indi magsobra $1 {{PLURAL:$1|nga adlaw|nga mga adlaw}})",
        "yourdomainname": "Imo dominyo",
        "password-change-forbidden": "Indi ka mahimo nga makailis sang pasword sa sini nga wiki.",
        "externaldberror": "Mahimo nga may ara sang sala sa pagpamatood sang database ukon wala ka sa lugar nga magbag-o sang imo pang-guha nga akawnt.",
        "passwordreset-emailtext-user": "Ang manuggamit nga si $1 sa {{SITENAME}} nagpangabay sang pahanumdom sang mga detalye sang imo akawnt para sa {{SITENAME}} \n($4). Ang masunod nga {{PLURAL:$3|akawnt|mga akawnt}} sang manuggamit may kabahin sa sini nga adres sang e-mail:\n\n$2\n\n{{PLURAL:$3|Ang ini nga temporaryo nga pasword|Ang mga ini nga temporaryo nga pasword}} indi na magamit sa {{PLURAL:$5|isa ka adlaw|$5 ka adlaw}}.\nKinahanglan mo nga magsulod kag magpili sang bag-o nga pasword subong. Kon lain nga tawo ang nagbuhat sini\nnga pagpangabay, ukon nadumduman mo na ang imo pasword, kag indi mo na kinahanglan nga ini\npaga-ilisan, mahimo mo nga pabay-an ang ini nga pahanumdom kag magpadayon sa paggamit sang imo daan nga pasword.",
        "passwordreset-emailelement": "Gamit-pangalan: \n$1\n\nTemporaryo nga pasword: \n$2",
        "passwordreset-emailsentemail": "May pahanumdom nga e-mail nga ginpadala.",
-       "passwordreset-emailsent-capture": "May e-mail nga nagapahanumdum, nga ginapakita sa idalom.",
-       "passwordreset-emailerror-capture": "May e-mail nga nagapahanumdom nga ginbuhat, nga ginapakita sa idalom, apang ang pagpadala sa manuggamit indi madinalag-on: $1",
        "changeemail": "Ilisan ang E-mail adres",
        "changeemail-header": "Ilisan ang e-mail adres sang akawnt",
        "changeemail-no-info": "Kinahanglan nga nakasulod ka agod nga makadtoan ang ini nga panid sing derecho.",
        "undo-failure": "Ang pag-ilis indi na maliwat pa tungod sang nagakonplikto nga mga pang-tunga nga pag-ilis.",
        "undo-norev": "Ang pag-ilis indii na maliwat pa tungod kay ini wala naga-eksister ukon ginpanas na.",
        "undo-summary": "Liwaton ang pagbag-o sang $1 sa [[Special:Contributions/$2|$2]] ([[User talk:$2|$2]])",
-       "cantcreateaccounttitle": "Indi mabuhat ang akawnt",
        "cantcreateaccount-text": "Ang pagbuhat sang akawnt sang sini nga adres sang IP ('''$1''') ginpunggan ni [[User:$3|$3]].\n\nAng rason nga ginhatag ni $3 amo ang ''$2''",
        "viewpagelogs": "Tan-awon ang mga log para sa sini nga pahina",
        "nohistory": "Wala sang kasaysayan sang pag-ilis sang sini nga panid.",
index 7d15d79..999d03b 100644 (file)
        "passwordreset-emaildisabled": "Funkcija e-pošte je onemogućena na ovom wikiju.",
        "passwordreset-username": "Suradničko ime:",
        "passwordreset-domain": "Domena:",
-       "passwordreset-capture": "Pogledati krajnju poruku?",
-       "passwordreset-capture-help": "Ako označite ovu kućicu, e-poruka s privremenom lozinkom će biti prikazana i poslana korisniku.",
        "passwordreset-email": "E-mail adresa:",
        "passwordreset-emailtitle": "Pojedinosti o računu na {{SITENAME}}",
        "passwordreset-emailtext-ip": "Netko (vjerojatno Vi, s IP adrese $1) zatražio je podsjetnik za Vaše detalje računa\nza {{SITENAME}} ($4). Sljedeći {{PLURAL:$3|račun suradnika je|računi suradnika su}}\npovezani s ovom e-mail adresom:\n\n$2\n\n{{PLURAL:$3|Ova privremena zaporka|Ove privremene zaporke}} će isteći u {{PLURAL:$5|jedan dan|$5 dana}}.\nTrebate se prijaviti i odabrati novu zaporku. Ukoliko je netko drugi napravio ovaj\nzahtjev, ili ako ste se sjetili Vaše izvorne zaporke, a više je ne želite promijeniti, \nmožete zanemariti ovu poruku i nastavite koristiti staru zaporku.",
        "userrights-reason": "Razlog:",
        "userrights-no-interwiki": "Nemate dopuštenje za uređivanje suradničkih prava na drugim wikijima.",
        "userrights-nodatabase": "Baza podataka $1 ne postoji ili nije lokalno dostupna.",
-       "userrights-nologin": "Morate se [[Special:UserLogin|prijaviti]] s administratorskim računom da bi mogli dodijeliti suradnička prava.",
-       "userrights-notallowed": "Vaš trenutačni suradnički račun nema ovlasti mijenjanja suradničkih prava.",
        "userrights-changeable-col": "Skupine koje možete promijeniti",
        "userrights-unchangeable-col": "Skupine koje ne možete promijeniti",
        "userrights-conflict": "Sukob promjene suradničkih prava! Molimo provjerite i potvrdite svoje promjene.",
-       "userrights-removed-self": "Uspješno ste uklonili svoja vlastita prava. Kao takvi, više niste u mogućnosti pristupiti ovoj stranici.",
        "group": "Skupina:",
        "group-user": "Suradnici",
        "group-autoconfirmed": "automatski potvrđeni suradnici",
        "right-siteadmin": "Zaključavanje i otključavanje baze podataka",
        "right-override-export-depth": "Izvezi stranice uključujući i povezane stranice do dubine od 5",
        "right-sendemail": "Slanje e-pošte drugim suradnicima",
-       "right-passwordreset": "Vidi poruku e-pošte o ponovnom postavljanju lozinke",
        "grant-group-email": "Pošalji e-mail",
        "grant-blockusers": "Blokiraj i odblokiraj korisnike",
        "grant-createaccount": "Otvori račune",
        "booksources-search": "Traži",
        "booksources-text": "Ovdje je popis vanjskih poveznica na internetskim stranicama koje prodaju nove i rabljene knjige, ali mogu sadržavati i ostale podatke o knjigama koje tražite:",
        "booksources-invalid-isbn": "Čini se da dani ISBN nije valjan; provjerite greške kopirajući iz izvornika.",
+       "magiclink-tracking-isbn": "Stranice s čarobnim ISBN poveznicama",
+       "magiclink-tracking-isbn-desc": "Ova stranica rabi čarobne ISBN poveznice. Za njihovu migraciju vidi [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
        "specialloguserlabel": "Suradnik:",
        "speciallogtitlelabel": "Cilj (naslov ili suradnik):",
        "log": "Evidencije",
        "rollback-success": "uklonjeno uređivanje {{GENDER:$1|suradnika|suradnice}} $1\nvraćeno na posljednju inačicu {{GENDER:$2|suradnika|suradnice}} $2.",
        "sessionfailure-title": "Prekid sesije",
        "sessionfailure": "Uočili smo problem s Vašom prijavom. Zadnja naredba nije izvršena kako bi se izbjegla zloupotreba. Molimo Vas da se u pregledniku vratite natrag na prethodnu stranicu, ponovno je učitate i zatim pokušate opet.",
-       "changecontentmodel": "Promijeni model sadržaja stranice",
+       "changecontentmodel": "Promjena modela sadržaja stranice",
        "changecontentmodel-legend": "Promijeni model sadržaja",
        "changecontentmodel-title-label": "Naziv stranice",
        "changecontentmodel-model-label": "Novi model sadržaja",
        "changecontentmodel-reason-label": "Razlog:",
+       "changecontentmodel-submit": "Promijeni",
        "changecontentmodel-success-title": "Sadržaj modela je promijenjen",
        "protectlogpage": "Evidencija zaštićivanja",
        "protectlogtext": "Ispod je evidencija zaštićivanja i uklanjanja zaštite pojedinih stranica.\nPogledajte [[Special:ProtectedPages|zaštićene stranice]] za popis trenutačno zaštićenih stranica.",
        "modifiedarticleprotection": "promijenjen stupanj zaštite za \"[[$1]]\"",
        "unprotectedarticle": "uklonjena zaštita članka \"[[$1]]\"",
        "movedarticleprotection": "premještene postavke zaštite s \"[[$2]]\" na \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|$2 je zaštitio|$2 je zaštitila}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|$2 je promijenio nivo zaštite|$2 je promijenila nivo zaštite}} za \"[[$1]]\"",
+       "unprotectedarticle-comment": "{{GENDER:$2|$2 je uklonio zaštitu|$2 je uklonila zaštitu}} za \"[[$1]]\"",
        "protect-title": "Zaštićujem \"$1\"",
        "protect-title-notallowed": "Vidi stupanj zaštite stranice \"$1\"",
        "prot_1movedto2": "$1 premješteno na $2",
        "pageinfo-robot-index": "Stranicu je moguće indeksirati",
        "pageinfo-robot-noindex": "Indeksiranje stranice onemogućeno",
        "pageinfo-watchers": "Broj pratitelja stranice",
+       "pageinfo-visiting-watchers": "Broj suradnika pratitelja ove stranice koji su posjetili nedavne promjene",
        "pageinfo-few-watchers": "Manje od $1 {{PLURAL:$1|suradnika koji prate ovu stranicu|suradnika koji prate ovu stranicu}}",
        "pageinfo-redirects-name": "Broj preusmjeravanja na ovu stranicu",
        "pageinfo-subpages-name": "Podstranice",
        "patrol-log-page": "Evidencija pregledavanja promjena",
        "patrol-log-header": "Ovo su evidencije ophođenih izmjena.",
        "log-show-hide-patrol": "$1 evidenciju patroliranja",
+       "confirm-markpatrolled-button": "U redu",
+       "confirm-markpatrolled-top": "Označiti izmjenu $3 stranice $2 pregledanom?",
        "deletedrevision": "izbrisana stara inačica $1",
        "filedeleteerror-short": "Pogrješka u brisanju datoteke: $1",
        "filedeleteerror-long": "Dogodila se pogrješka prilikom brisanja datoteke:\n\n$1",
        "confirm-watch-top": "Dodajte ovu stranicu na Vaš popis praćenih stranica",
        "confirm-unwatch-button": "U redu",
        "confirm-unwatch-top": "Ukloni ovu stranicu s popisa praćenja?",
+       "confirm-rollback-button": "U redu",
+       "confirm-rollback-top": "Ukloniti uređivanja na ovoj stranici?",
        "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← prethodna slika",
        "imgmultipagenext": "sljedeća slika →",
        "htmlform-time-invalid": "Unesena vrijednost nije prepoznati format vremena. Pokušajte koristiti format HH:MM:SS.",
        "htmlform-datetime-toohigh": "Uneseni datum i vrijeme su veći od $1",
        "logentry-delete-delete": "$1 je {{GENDER:$2|obrisao|obrisala}} stranicu $3",
+       "logentry-delete-delete_redir": "$1 je {{GENDER:$2|obrisao|obrisala}} preusmjeravanje $3 prepisivanjem",
        "logentry-delete-restore": "$1 je {{GENDER:$2|vratio|vratila}} stranicu $3",
        "logentry-delete-event": "$1 je {{GENDER:$2|promijenio|promijenila}} vidljivost {{PLURAL:$5|zapisa u evidenciji|$5 zapisa u evidenciji}} na $3: $4",
        "logentry-delete-revision": "$1 je {{GENDER:$2|promijenio|promijenila}} vidljivost {{PLURAL:$5|uređivanja|$5 uređivanja}} na stranici $3: $4",
index 70d984b..6bc52f5 100644 (file)
        "yourpasswordagain": "Passwort repetiere:",
        "createacct-yourpasswordagain": "Passwort bestätiche",
        "createacct-yourpasswordagain-ph": "Geb das Passwort erneit ren",
-       "remembermypassword": "Mit dem Browser dauerhaft oongemeldet bleiwe (maximal $1 {{PLURAL:$1|Tooch|Tooche}})",
        "userlogin-remembermypassword": "Oongemeldt bleiwe",
        "userlogin-signwithsecure": "Sichre Verbinnung verwenne",
        "yourdomainname": "Dein Domain:",
        "passwordreset-emailtext-user": "Benutzer $1 bei {{SITENAME}} hot en Zurücksetzung von dein Passwort bei {{SITENAME}} oongefordert ($4). {{PLURAL:$3|Das follichend Benutzerkonto ist|Die follichend Benutzerkonte sind}} mit der E-Mail-Adress verknüpft:\n\n$2\n\n{{PLURAL:$3|Das temporär Passwort looft|Die temporäre Passwörter loofe}} innerhalb von {{PLURAL:$5|em Tooch|$5 Tooche}} ab. Du sollst dich oonmelde und en neies Passwort vergewe. Falls jemand annres die Oonfroch getäticht hot orrer du dich wieder an den ursprüngliches Passwort erinnre kannst und das net ännre möchst, kannst du die Nachricht ignoriere und weiterhin dein altes Passwort benutze.",
        "passwordreset-emailelement": "Benutzernoome: \n$1\n\nTemporäres Passwort: \n$2",
        "passwordreset-emailsentemail": "En Passwortzurücksetzung-E-Mail woard versandt.",
-       "passwordreset-emailsent-capture": "En Passwortzurücksetzung-E-Mail woard versandt, die unne oongezeicht weard.",
-       "passwordreset-emailerror-capture": "Die unne oongezeichte Passwortzurücksetzungs-E-Mail woard generiert, awer der Versand an {{GENDER:$2|den Benutzer|die Benutzrin}} ist gescheitert: $1",
        "changeemail": "E-Mail-Adress ännre",
        "changeemail-header": "E-Mail-Adress ännre",
        "changeemail-no-info": "Du musst dich oonmelde, um uff die Seit direkt zuzugreife.",
        "undo-nochange": "Anscheinnd woard die Beoorbeitung schon rückgängich gemacht.",
        "undo-summary": "Ändrung $1 von [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussion]]) rückgängich gemacht.",
        "undo-summary-username-hidden": "Ännrung $1 von en versteckte Benutzer rückgängich gemacht.",
-       "cantcreateaccounttitle": "Das Benutzerkonto kann net erstellt sin",
        "cantcreateaccount-text": "Die Erstellung von en Benutzerkonto raus von der IP-Adresse '''($1)''' woor doorrich [[User:$3|$3]] gesperrt.\n\nGrund der Sperr: ''$2''",
        "cantcreateaccount-range-text": "Das Erstell von Benutzerkonte von IP-Adressen im Bereich <strong>$1</strong>, wo dein IP-Adress (<strong>$4</strong>) enthält, woor von [[User:$3|$3]] gesperrt.\n\nDer oongebne Grund von $3 laut: <em>$2</em>",
        "viewpagelogs": "Logbücher von der Seit oonzeiche",
        "activeusers-intro": "Das ist en List von Benutzer, wo innerhalleb {{PLURAL:$1|vom letzte Tooch|von der letzte $1 Tooch}} Aktivitäte uffwies.",
        "activeusers-count": "$1 {{PLURAL:$1|Aktion|Aktione}} in den {{PLURAL:$3|letzte 24 Stunne|vergangene $3 Tooche}}",
        "activeusers-from": "Zeich Benutzer ab:",
-       "activeusers-hidebots": "Bots ausblende",
-       "activeusers-hidesysops": "Administratore ausblende (verstecke)",
        "activeusers-noresult": "Kene Benutzer gefund.",
        "listgrouprights": "Benutzergrupperechte",
        "listgrouprights-summary": "Das ist ein List vom in dem Wiki definierte Benutzergruppe und ehre damit verbündne Rechte.\nZusätzliche Informatione üwer einzelne Rechte könne [[{{MediaWiki:Listgrouprights-helppage}}|hier]] gefund sin.",
        "htmlform-cloner-create": "Weitre dozu tun",
        "htmlform-cloner-delete": "Entferne",
        "htmlform-cloner-required": "Es ist minschtens en Weart erforderlich.",
-       "sqlite-has-fts": "Version $1 mit Unnerstützung für die Volltextsuch",
-       "sqlite-no-fts": "Version $1 ohne Unnerstützung für die Volltextsuch",
        "logentry-delete-delete": "$1 {{GENDER:$2|löschte}} Seit $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|stellte}} Seit $3 wieder her",
        "logentry-delete-event": "$1 {{GENDER:$2|ännerte}}  die Sichtbarkeit {{PLURAL:$5|von ein Logbucheintrooch|von $5 Logbucheinträch}} uff $3: $4",
        "feedback-bugornote": "Soweit du ganz detalhiert en technisches Problem beschreiben möchst, meld bittschön [$1 en Fehler].\nAnnerfalls kannst du ooch das do unne stehende ganz enfache Formular benutze. Dein Kommentar weard, zusammer mit deinem Benutzernoome und der Version von der von dir verwenndt Webbrowsers sowie Betriebssystems, uff der Seit \"[$3 $2]\" hinzugefücht.",
        "feedback-cancel": "Abbreche",
        "feedback-close": "Erledicht (fertich)",
-       "feedback-error-title": "Fehler",
        "feedback-error1": "Fehler: Unbekanntes Ergebnis von der API",
        "feedback-error2": "Fehler: Beoorbeitung gescheitert",
        "feedback-error3": "Fehler: Ken Antwort von der API",
index 007eada..558b166 100644 (file)
        "yourpasswordagain": "Hesło znowa zapodać:",
        "createacct-yourpasswordagain": "Hesło wobkrućić",
        "createacct-yourpasswordagain-ph": "Zapodaj hesło hišće raz",
-       "remembermypassword": "Na tutym ličaku přizjewjeny wostać (za maksimalnje $1 {{PLURAL:$1|dźeń|dnjej|dny|dnjow}})",
        "userlogin-remembermypassword": "Přizjewjeny wostać",
        "userlogin-signwithsecure": "Wěsty zwisk wužiwać",
        "yourdomainname": "Twoja domejna:",
        "activeusers-intro": "To je lisćina wužiwarjow, kotřiž běchu aktiwni za {{PLURAL:$1|posledni dźeń|poslednjej $1 dnjej|poslednje $1 dny|poslednich $1 dnjow}}:",
        "activeusers-count": "$1 {{PLURAL:$1|akcija|akciji|akcije|akcijow}} w {{PLURAL:$3|zańdźenej dnju|zańdźenymaj $3 dnjomaj|zańdźenych $3 dnjach}}",
        "activeusers-from": "Wužiwarjow zwobraznić, započinajo z:",
-       "activeusers-hidebots": "Boćiki schować",
-       "activeusers-hidesysops": "Administratorow schować",
        "activeusers-noresult": "Žani wužiwarjo namakani.",
        "listgrouprights": "Prawa wužiwarskeje skupiny",
        "listgrouprights-summary": "Slěduje lisćina wužiwarskich skupinow na tutej wikiju z jich wotpowědnymi přistupnymi prawami. Tu móžeš [[{{MediaWiki:Listgrouprights-helppage}}|dalše informacije]] wo jednotliwych prawach namakać.",
        "htmlform-cloner-create": "Wjace přidać",
        "htmlform-cloner-delete": "Wotstronić",
        "htmlform-cloner-required": "Znjamjeńša jedna hódnota je trěbna.",
-       "sqlite-has-fts": "$1 połnotekstowe pytanje podpěruje.",
-       "sqlite-no-fts": "$1 połnotekstowe pytanje njepodpěruje",
        "logentry-delete-delete": "$1 je stronu $3 {{GENDER:$1|zhašał|zhašała}}",
        "logentry-delete-restore": "$1 je stronu $3 {{GENDER:$1wobnowił|wobnowiła}}",
        "logentry-delete-event": "$1 je widźomnosć {{PLURAL:$5|protokoloweho zapiska|$5 protokoloweju zapiskow|$5 protokolowych zapiskow}} na $3 {{GENDER:$2|změnił|změniła}}: $4",
        "feedback-close": "Dokónčeny",
        "feedback-external-bug-report-button": "Techniski nadawk zapodać",
        "feedback-dialog-title": "Komentar pósłać",
-       "feedback-error-title": "Zmylk",
        "feedback-error1": "Zmylk: Njepřipóznaty wuslědk wot API",
        "feedback-error2": "Zmylk: Wobdźěłanje je so njeporadźiło",
        "feedback-error3": "Zmylk: Žana wotmołwa wot API",
index 17df2d7..edb8a7c 100644 (file)
        "yourpasswordagain": "Mete mopas ou an ankò :",
        "createacct-yourpasswordagain": "Konfime modpas la",
        "createacct-yourpasswordagain-ph": "Rantre modpas la ankò",
-       "remembermypassword": "Sonje mopas mwen an nan òdinatè mwen an (pou yon maximum de $1 {{PLURAL:$1|jou|jou}})",
        "userlogin-remembermypassword": "Pa dekonekte m",
        "userlogin-signwithsecure": "Sèvi ak yon koneksyon sekirize",
        "yourdomainname": "Domèn ou an",
index 0b91499..ce3aaba 100644 (file)
        "passwordreset-nocaller": "A hívó megadása kötelező",
        "passwordreset-nosuchcaller": "A hívó nem létezik: $1",
        "passwordreset-ignored": "A jelszó-visszaállítás nem lett kezelve. Talán nincs konfigurálva szolgáltató?",
-       "passwordreset-invalideamil": "Érvénytelen e-mail cím",
+       "passwordreset-invalidemail": "Érvénytelen e-mail cím",
        "passwordreset-nodata": "Se felhasználónevet, sem e-mail-címet nem adtál meg",
        "changeemail": "E-mail cím megváltoztatása vagy eltávolítása",
        "changeemail-header": "Töltsd ki ezt az űrlapot az e-mail-címed megváltoztatásához. Ha nem szeretnél semmilyen e-mail-címet kapcsolni a fiókodhoz, hagyd üresen az új e-mail-cím mezőjét az űrlap elküldésekor.",
index b272913..9735a24 100644 (file)
        "cannotdelete": "Չհաջողվեց ջնջել «$1» էջը կամ ֆայլը։\nՀավանաբար այն արդեն ջնջվել է մեկ այլ մասնակցի կողմից։",
        "cannotdelete-title": "Հնարավոր չէ ջնջել $1 էջը",
        "delete-hook-aborted": "Խմբագրել չեղյալ է.\nԼրացուցիչ պարզաբանումներ չի դրվել.",
-       "no-null-revision": "Չի հաջողվել ստեղծել նոր զրոյական правку համար էջը \"$1\"",
+       "no-null-revision": "Չի հաջողվել ստեղծել նոր զրոյական խմբագրում էջի համար \"$1\"",
        "badtitle": "Անընդունելի անվանում",
        "badtitletext": "Հարցված էջի անվանումը անընդունելի է, դատարկ է կամ սխալ միջ-լեզվական կամ ինտերվիքի անվանում է։ Հնարավոր է, որ այն պարունակում է անթույլատրելի սիմվոլներ։",
        "title-invalid-empty": "Էջի հայցվող վերնագիրը դատարկ է կամ պարունակում է միայն անվանատարածքի անունը։",
        "userlogin-signwithsecure": "Օգտագործել անվտանգ միացում",
        "cannotloginnow-title": "Այժմ դուրս գալ անհնար է",
        "cannotloginnow-text": "$1 օգտագործելիս դուրս գալն անհնար է:",
+       "cannotcreateaccount-title": "Անհնար է ստեղծել հաշիվներ",
+       "cannotcreateaccount-text": "Հաշիվների ուղղակի ստեղծումը ներառված է այս վիքիյում",
        "yourdomainname": "Ձեր դոմենը՝",
        "password-change-forbidden": "Այս վիքիում չեք կարող փոխել գաղտնաբառ։",
        "externaldberror": "Տեղի է ունեցել վավերացման արտաքին տվյալների բազայի սխալ, կամ դուք չունեք բավարար իրավունքներ ձեր արտաքին հաշվի փոփոխման համար։",
        "login": "Մտնել համակարգ",
+       "login-security": "Հաստատեք Ձեր ինքնությունը",
        "nav-login-createaccount": "Մտնել / Գրանցվել",
        "userlogin": "Մտնել / Գրանցվել",
        "userloginnocreate": "Մտնել",
        "userlogin-resetlink": "Մոռացե՞լ եք Ձեր հաշվի տվյալները։",
        "userlogin-resetpassword-link": "Մոռացե՞լ եք գաղտնաբառը",
        "userlogin-helplink2": "Մուտք գործելու օգնություն",
+       "userlogin-loggedin": "Դուք արդեն մտել է որպես {{GENDER:$1|$1}}.\nՕգտագործեք ստորև բերված ձևը մուտք գործելու համար այլ հաշից",
+       "userlogin-reauth": "Դուք պետք է կրկին համակարգ մուտք գործեք  հաստատելու որ դուք դուք եք {{GENDER:$1|$1}}.",
        "userlogin-createanother": "Ստեղծել այլ հաշիվ",
        "createacct-emailrequired": "Էլ–փոստի հասցե",
        "createacct-emailoptional": "Էլ–փոստի հասցե (ոչ պարտադիր)",
        "createacct-reason-ph": "Ինչո՞ւ եք փորձում ստեղծել մեկ այլ հաշիվ",
        "createacct-submit": "Ստեղծել ձեր հաշիվը",
        "createacct-another-submit": "Ստեղծել հաշիվ",
+       "createacct-continue-submit": "Շարունակել ստեղծել հաշիվ",
+       "createacct-another-continue-submit": "Շարունակել ստեղծել հաշիվ",
        "createacct-benefit-heading": "{{SITENAME}}՝ ստեղծվում է ձեր պես մարդկանց կողմից։",
        "createacct-benefit-body1": "{{PLURAL:$1|խմբագրում}}",
        "createacct-benefit-body2": "{{PLURAL:$1|էջ}}",
        "createacct-benefit-body3": "վերջերս ակտիվ {{PLURAL:$1|մասնակից}}",
        "badretype": "Ձեր մուտքագրած գաղտնաբառերը չեն համընկնում։",
+       "usernameinprogress": "Տվյալ մասնակցի համար հաշվի ստեղծումը  արդեն իրականացվում է:\nԽնդրում ենք սպասել:",
        "userexists": "Այս մասնակցի անունը արդեն զբաղված է։ Խնդրում ենք ընտրել մեկ այլ անուն։",
        "loginerror": "Մուտքի սխալ",
        "createacct-error": "Հաշվի ստեղծման սխալ",
        "defaultmessagetext": "Լռելյան տեքստը",
        "editwarning-warning": "Այս էջը լքելով դուք կարող եք կորցնել ձեր կատարած փոփոխությունները։\nԵթե դուք գրանցված եք համակարգում, կարող եք անջատել այս նախազգուշացումը ձեր նախընրությունների «{{int:prefs-editing}}» բաժնում։",
        "content-model-wikitext": "վիքիտեքստ",
+       "content-model-text": "պարզ տեքստ",
        "content-model-javascript": "ՋավաՍկրիպտ",
        "content-model-css": "ՍիԷսԷս",
+       "content-json-empty-object": "Դատարկ օբյեկտ",
        "duplicate-args-category": "Կաղապարներում կրկնվող արգումենտներով էջեր",
        "undo-success": "Խմբագրումը կարող է հետ շրջվել։ Ստուգեք տարբերակների համեմատությունը ստորև, որպեսզի համոզվեք, որ դա է ձեզ հետաքրքրող փոփոխությունը և մատնահարեք «Հիշել էջը»՝ գործողությունն ավարտելու համար։",
        "undo-failure": "Խմբագրումը չի կարող հետ շրջվել միջանկյալ խմբագրումների ընդհարման պատճառով։",
        "prefs-timeoffset": "Ժամային տարբերություն",
        "prefs-advancedediting": "Ընդլայնված ընրանքներ",
        "prefs-editor": "Խմբագիր",
+       "prefs-preview": "Նախադիտել",
        "prefs-advancedrc": "Ընդլայնված ընրանքներ",
        "prefs-advancedrendering": "Ընդլայնված ընրանքներ",
        "prefs-advancedsearchoptions": "Ընդլայնված ընրանքներ",
        "right-writeapi": "API գրի օգտագործումը",
        "right-delete": "Էջերի ջնջում",
        "right-rollback": "Արագ հետ գլորել տվյալ էջը վերջին անգամ խմբագրած մասնակցի խմբագրումները",
+       "grant-group-email": "Ուղարկել էլ. նամակ",
        "grant-createaccount": "Ստեղծել հաշիվներ",
        "grant-createeditmovepage": "Ստեղծել․ խմբագրել և տեղափոխել էջեր",
+       "grant-basic": "Հիմնական իրավունքներ",
        "newuserlogpage": "Մասնակիցների գրանցման տեղեկամատյան",
        "newuserlogpagetext": "Սա նոր մասնակիցների գրանցման տեղեկամատյանն է.",
        "rightslog": "Մասնակցի իրավունքների տեղեկամատյան",
        "tags-activate-submit": "Ակտիվացնել",
        "tags-deactivate-reason": "Պատճառ՝",
        "tags-deactivate-submit": "Ապաակտիվացնել",
+       "tags-update-blocked": "Դուք չեք կարող ավելացնել կամ հեռացնել թեգեր, քանի դեռ {{GENDER:$1|դուք}} արգելափակված եք",
        "comparepages": "Համեմատել էջեր",
        "compare-page1": "Էջ 1",
        "compare-page2": "Էջ 2",
        "special-characters-title-endash": "ո գծիկ (en dash)",
        "special-characters-title-emdash": "ա գծիկ (em dash)",
        "special-characters-title-minus": "հանածի նշան",
+       "mw-widgets-mediasearch-noresults": "Ոչինչ չի գտնվել",
        "authmanager-create-from-login": "Հաշիվ ստեղծելու համար, խնդրում ենք լրացնել ստորև դաշտերը"
 }
index ad6acb0..face238 100644 (file)
        "views": "Representationes",
        "toolbox": "Instrumentos",
        "tool-link-userrights": "Modificar le gruppos del {{GENDER:$1|usator|usatrice}}",
+       "tool-link-userrights-readonly": "Vider gruppos de {{GENDER:$1|usator}}",
        "tool-link-emailuser": "Inviar e-mail a iste {{GENDER:$1|usator|usatrice}}",
        "userpage": "Vider pagina del usator",
        "projectpage": "Vider pagina de projecto",
        "passwordreset-emaildisabled": "Le functionalitate de e-mail ha essite disactivate in iste wiki.",
        "passwordreset-username": "Nomine de usator:",
        "passwordreset-domain": "Dominio:",
-       "passwordreset-capture": "Vider le e-mail resultante?",
-       "passwordreset-capture-help": "Si tu marca iste quadrato, le e-mail (con le contrasigno temporari) non solmente essera inviate al usator, ma anque monstrate a te.",
        "passwordreset-email": "Adresse de e-mail:",
        "passwordreset-emailtitle": "Detalios del conto in {{SITENAME}}",
        "passwordreset-emailtext-ip": "Un persona (probabilemente tu, ab le adresse IP $1) requestava le reinitialisation de tu\ncontrasigno de {{SITENAME}} ($4). Le {{PLURAL:$3|conto|contos}} de usator sequente es\nassociate con iste adresse de e-mail:\n\n$2\n\nIste {{PLURAL:$3|contrasigno|contrasignos}} temporari expirara post {{PLURAL:$5|un die|$5 dies}}.\nTu deberea ora aperir session e eliger un nove contrasigno. Si un altere persona faceva iste\nrequesta, o si tu te ha rememorate tu contrasigno original e non plus\nvole cambiar lo, tu pote ignorar iste message e continuar a usar le ancian\ncontrasigno.",
        "passwordreset-emailelement": "Nomine de usator: \n$1\n\nContrasigno temporari: \n$2",
        "passwordreset-emailsentemail": "Si iste adresse es associate a tu conto, alora un e-mail pro reinitialisar le contrasigno essera inviate.",
        "passwordreset-emailsentusername": "Si il ha un adresse de e-mail associate a iste conto, alora un e-mail pro reinitialisar le contrasigno essera inviate.",
-       "passwordreset-emailsent-capture2": "Le {{PLURAL:$1|message|messages}} de e-mail pro reinitialisation de contrasigno ha essite inviate. Le {{PLURAL:$1|nomine de usator e contrasigno|lista de nomines de usator e contrasignos}} es monstrate hic.",
-       "passwordreset-emailerror-capture2": "Le invio de e-mail al {{GENDER:$2|usator}} ha fallite: $1 Le {{PLURAL:$3|nomine de usator e contrasigno|lista de nomines de usator e contrasignos}} es monstrate hic.",
        "passwordreset-nocaller": "Un appellator debe esser fornite",
        "passwordreset-nosuchcaller": "Appellator non existe: $1",
        "passwordreset-ignored": "Le reinitialisation del contrasigno non ha essite realisate. Es possibile que nulle fornitor ha essite configurate?",
-       "passwordreset-invalideamil": "Adresse de e-mail invalide",
+       "passwordreset-invalidemail": "Adresse de e-mail invalide",
        "passwordreset-nodata": "Ni un nomine de usator ni un adresse de e-mail ha essite fornite",
        "changeemail": "Cambiar o remover adresse de e-mail",
        "changeemail-header": "Completa iste formulario pro cambiar tu adresse de e-mail. Si tu vole remover le association de omne adresse de e-mail ab tu conto, lassa le campo pro le nove adresse de e-mail vacue quando tu submitte le formulario.",
        "search-external": "Recerca externe",
        "searchdisabled": "Le recerca in {{SITENAME}} es disactivate.\nTu pote cercar via Google in le interim.\nNota que lor indices del contento de {{SITENAME}} pote esser obsolete.",
        "search-error": "Un error ha occurrite durante le recerca: $1",
+       "search-warning": "Un aviso se ha producite durante le recerca: $1",
        "preferences": "Preferentias",
        "mypreferences": "Preferentias",
        "prefs-edits": "Numero de modificationes:",
        "prefs-help-recentchangescount": "Isto include modificationes recente, historias de paginas, e registros.",
        "prefs-help-watchlist-token2": "Isto es le clave secrete pro le syndication web de tu observatorio.\nOmne persona qui lo cognosce pote leger tu observatorio, dunque, non divide lo.\n[[Special:ResetTokens|Clicca hic pro reinitialisar lo]].",
        "savedprefs": "Tu preferentias ha essite confirmate.",
-       "savedrights": "Le derectos de usator de {{GENDER:$1|$1}} ha essite salveguardate.",
+       "savedrights": "Le gruppos de usator de {{GENDER:$1|$1}} ha essite salveguardate.",
        "timezonelegend": "Fuso horari:",
        "localtime": "Hora local:",
        "timezoneuseserverdefault": "Usar le valor predefinite del wiki ($1)",
        "prefswarning-warning": "To ha facite modificationes in tu preferentias que non ha ancora essite confirmate. Si tu quita iste pagina sin cliccar sur \"$1\", tu preferentias non essera cambiate.",
        "prefs-tabs-navigation-hint": "Consilio: Tu pote usar le claves de sagitta sinistre e dextre pro navigar inter le schedas in le lista.",
        "userrights": "Gestion de derectos de usator",
-       "userrights-lookup-user": "Gerer gruppos de usatores",
+       "userrights-lookup-user": "Selige un usator",
        "userrights-user-editname": "Entra un nomine de usator:",
-       "editusergroup": "Modificar gruppos de {{GENDER:$1|usator}}",
+       "editusergroup": "Cargar gruppos de usator",
        "editinguser": "Cambia le derectos del {{GENDER:$1|usator}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Ecce le derectos del {{GENDER:$1|usator}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modificar gruppos de usatores",
+       "userrights-viewusergroup": "Vider gruppos del usator",
        "saveusergroups": "Salveguardar gruppos de {{GENDER:$1|usator}}",
        "userrights-groupsmember": "Membro de:",
        "userrights-groupsmember-auto": "Membro implicite de:",
        "userrights-reason": "Motivo:",
        "userrights-no-interwiki": "Tu non ha le permission de modificar le derectos de usatores in altere wikis.",
        "userrights-nodatabase": "Le base de datos $1 non existe o non es local.",
-       "userrights-nologin": "Tu debe [[Special:UserLogin|aperir un session]] con un conto de administrator pro poter assignar derectos de usator.",
-       "userrights-notallowed": "Tu non ha le permission de adder o remover derectos de usator.",
        "userrights-changeable-col": "Gruppos que tu pote modificar",
        "userrights-unchangeable-col": "Gruppos que tu non pote modificar",
        "userrights-conflict": "Conflicto inter cambiamentos de derectos de usator! Per favor revide e confirma tu cambiamentos.",
-       "userrights-removed-self": "Tu ha removite tu proprie derectos. In consequentia, tu non plus pote acceder a iste pagina.",
        "group": "Gruppo:",
        "group-user": "Usatores",
        "group-autoconfirmed": "Usatores autoconfirmate",
        "right-siteadmin": "Blocar e disblocar le base de datos",
        "right-override-export-depth": "Exportar paginas includente paginas ligate usque a un profunditate de 5",
        "right-sendemail": "Inviar e-mail a altere usatores",
-       "right-passwordreset": "Vider le e-mails pro reinitialisar le contrasigno",
        "right-managechangetags": "Crear e (de)activar [[Special:Tags|etiquettas]]",
        "right-applychangetags": "Applicar [[Special:Tags|etiquettas]] al proprie modificationes",
        "right-changetags": "Adder e remover qualcunque [[Special:Tags|etiquettas]] sur individual versiones e entratas de registro",
        "action-upload_by_url": "incargar iste file ab un adresse URL",
        "action-writeapi": "usar le API pro modificar le wiki",
        "action-delete": "deler iste pagina",
-       "action-deleterevision": "deler iste version",
-       "action-deletedhistory": "vider le historia delite de iste pagina",
+       "action-deleterevision": "deler versiones",
+       "action-deletelogentry": "deler entratas de registro",
+       "action-deletedhistory": "vider le historia delite de un pagina",
+       "action-deletedtext": "vider le texto de un version delite",
        "action-browsearchive": "cercar in paginas delite",
-       "action-undelete": "restaurar iste pagina",
-       "action-suppressrevision": "revider e restaurar iste version celate",
+       "action-undelete": "restaurar paginas",
+       "action-suppressrevision": "revider e restaurar versiones celate",
        "action-suppressionlog": "vider iste registro private",
        "action-block": "blocar iste usator de facer modificationes",
        "action-protect": "cambiar le nivellos de protection pro iste pagina",
        "action-userrights-interwiki": "modificar le derectos de usatores in altere wikis",
        "action-siteadmin": "blocar e disblocar le base de datos",
        "action-sendemail": "inviar e-mail",
+       "action-editmyoptions": "modificar tu preferentias",
        "action-editmywatchlist": "modificar le proprie observatorio",
        "action-viewmywatchlist": "vider le proprie observatorio",
        "action-viewmyprivateinfo": "vider le proprie information private",
        "apisandbox-continue": "Continuar",
        "apisandbox-continue-clear": "Rader",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries continuara] le ultime requesta; {{int:apisandbox-continue-clear}} radera le parametros relative al continuation.",
+       "apisandbox-param-limit": "Scribe <kbd>max</kbd> pro usar le limite maxime.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Tote le spatios de nomines)",
+       "apisandbox-multivalue-all-values": "$1 (Tote le valores)",
        "booksources": "Fontes de libros",
        "booksources-search-legend": "Cercar fontes de libros",
        "booksources-search": "Cercar",
        "activeusers-count": "$1 {{PLURAL:$1|action|actiones}} in le ultime {{PLURAL:$3|die|$3 dies}}",
        "activeusers-from": "Presentar usatores a partir de:",
        "activeusers-groups": "Monstrar usatores pertinente a gruppos:",
+       "activeusers-excludegroups": "Excluder usatores pertinente a gruppos:",
        "activeusers-noresult": "Nulle usator trovate.",
        "activeusers-submit": "Monstrar usatores active",
        "listgrouprights": "Derectos del gruppos de usatores",
        "movedarticleprotection": "displaciava le configurationes de protection ab \"[[$2]]\" verso \"[[$1]]\"",
        "protectedarticle-comment": "{{GENDER:$2|Protegeva}} \"[[$1]]\"",
        "modifiedarticleprotection-comment": "{{GENDER:$2|Cambiar nivello de protection}} pro \"[[$1]]\"",
+       "unprotectedarticle-comment": "{{GENDER:$2|Removeva le protection}} de \"[[$1]]\"",
        "protect-title": "Cambiar nivello de protection de \"$1\"",
        "protect-title-notallowed": "Vider nivello de protection de \"$1\"",
        "prot_1movedto2": "displaciava [[$1]] verso [[$2]]",
        "movelogpagetext": "Infra es un lista de paginas renominate.",
        "movesubpage": "{{PLURAL:$1|Subpagina|Subpaginas}}",
        "movesubpagetext": "Iste pagina ha $1 {{PLURAL:$1|subpagina, le qual|subpaginas, le quales}} se monstra infra.",
+       "movesubpagetalktext": "Le pagina de discussion correspondente ha $1 {{PLURAL:$1|subpagina|subpaginas}} monstrate infra.",
        "movenosubpage": "Iste pagina non ha subpaginas.",
        "movereason": "Motivo:",
        "revertmove": "reverter",
        "pageinfo-category-pages": "Numero de paginas",
        "pageinfo-category-subcats": "Numero de subcategorias",
        "pageinfo-category-files": "Numero de files",
+       "pageinfo-user-id": "ID de usator",
        "markaspatrolleddiff": "Marcar como patruliate",
        "markaspatrolledtext": "Marcar iste pagina como patruliate",
        "markaspatrolledtext-file": "Marcar iste version del file como patruliate",
        "patrol-log-header": "Isto es un registro de versiones patruliate.",
        "log-show-hide-patrol": "$1 le registro de versiones patruliate",
        "log-show-hide-tag": "$1 registro de etiquettas",
+       "confirm-markpatrolled-button": "OK",
+       "confirm-markpatrolled-top": "Marcar le version $3 de $2 como patruliate?",
        "deletedrevision": "Deleva le ancian version $1",
        "filedeleteerror-short": "Error durante le deletion del file: $1",
        "filedeleteerror-long": "Se incontrava errores durante le deletion del file:\n\n$1",
        "tags-deactivate": "disactivar",
        "tags-hitcount": "$1 {{PLURAL:$1|modification|modificationes}}",
        "tags-manage-no-permission": "Tu non ha le permission de gerer le etiquettas de modification.",
-       "tags-manage-blocked": "Tu non pote gerer etiquettas de cambiamento durante que tu es blocate.",
+       "tags-manage-blocked": "Tu non pote gerer etiquettas de cambiamento durante que {{GENDER:$1|tu}} es blocate.",
        "tags-create-heading": "Crear un nove etiquetta",
        "tags-create-explanation": "Per configuration predefinite, le etiquettas novemente create essera disponibile pro le uso per usatores e robots.",
        "tags-create-tag-name": "Nomine del etiquetta:",
        "tags-deactivate-not-allowed": "Non es possibile disactivar le etiquetta \"$1\".",
        "tags-deactivate-submit": "Disactivar",
        "tags-apply-no-permission": "Tu non ha le permission de adjunger etiquettas de cambiamento a tu cambiamentos.",
-       "tags-apply-blocked": "Tu non pote applicar etiquettas de cambiamento con tu cambiamentos durante que tu es blocate.",
+       "tags-apply-blocked": "Tu non pote applicar etiquettas de cambiamento con tu cambiamentos durante que {{GENDER:$1|tu}} es blocate.",
        "tags-apply-not-allowed-one": "Non es permittite applicar le etiquetta \"$1\" manualmente.",
        "tags-apply-not-allowed-multi": "Le sequente {{PLURAL:$2|etiquetta|etiquettas}} non es autorisate a esser manualmente applicate: $1",
        "tags-update-no-permission": "Tu non ha le permission de adder o remover etiquettas de cambiamento sur individual versiones o entratas de registro.",
-       "tags-update-blocked": "Tu non pote adder o remover etiquettas de cambiamento durante que tu es blocate.",
+       "tags-update-blocked": "Tu non pote adder o remover etiquettas de cambiamento durante que {{GENDER:$1|tu}} es blocate.",
        "tags-update-add-not-allowed-one": "Non es permittite adjunger le etiquetta \"$1\" manualmente.",
        "tags-update-add-not-allowed-multi": "Le sequente {{PLURAL:$2|etiquetta|etiquettas}} non es autorisate a esser manualmente adjungite: $1",
        "tags-update-remove-not-allowed-one": "Non es permittite remover le etiquetta \"$1\".",
        "htmlform-user-not-exists": "<strong>$1</strong> non existe.",
        "htmlform-user-not-valid": "<strong>$1</strong> non es un nomine de usator valide.",
        "logentry-delete-delete": "$1 {{GENDER:$2|deleva}} le pagina $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|deleva}} le redirection $3 superscribente lo",
        "logentry-delete-restore": "$1 {{GENDER:$2|restaurava}} le pagina $3",
        "logentry-delete-event": "$1 {{GENDER:$2|cambiava}} le visibilitate de {{PLURAL:$5|un entrata|$5 entratas}} de registro in $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|cambiava}} le visibilitate de {{PLURAL:$5|un version|$5 versiones}} del pagina $3: $4",
        "mw-widgets-dateinput-no-date": "Nulle data seligite",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Cercar multimedia",
+       "mw-widgets-mediasearch-noresults": "Nulle resultato trovate.",
        "mw-widgets-titleinput-description-new-page": "pagina non existe ancora",
        "mw-widgets-titleinput-description-redirect": "redirection a $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Adder un categoria…",
        "sessionmanager-tie": "Impossibile combinar plure typos de authentication de requesta: $1.",
        "sessionprovider-generic": "sessiones $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessiones basate sur cookies",
        "log-action-filter-contentmodel-change": "Cambio de modello de contento",
        "log-action-filter-contentmodel-new": "Creation de pagina con modello de contento non standard",
        "log-action-filter-delete-delete": "Deletion de pagina",
+       "log-action-filter-delete-delete_redir": "Superscriptura de redirection",
        "log-action-filter-delete-restore": "Restauration de pagina",
        "log-action-filter-delete-event": "Deletion de registro",
        "log-action-filter-delete-revision": "Deletion de version",
        "authmanager-authn-autocreate-failed": "Le creation automatic de un conto local ha fallite: $1",
        "authmanager-change-not-supported": "Le credentiales fornite non pote esser cambiate perque nihil los usarea.",
        "authmanager-create-disabled": "Le creation de contos es disactivate.",
-       "authmanager-create-from-login": "Pro crear tu conto, completa le campos hic infra.",
+       "authmanager-create-from-login": "Pro crear tu conto, completa le campos.",
        "authmanager-create-not-in-progress": "Nulle creation de conto es in curso, o le datos del session ha essite perdite. Per favor, recomencia ab initio.",
        "authmanager-create-no-primary": "Le credentiales fornite non pote esser usate pro crear un conto.",
        "authmanager-link-no-primary": "Le credentiales fornite non pote esser usate pro ligar un conto.",
        "usercssispublic": "Nota ben: Subpaginas CSS non debe continer datos confidential perque altere usatores pote vider los.",
        "restrictionsfield-badip": "Adresse o intervallo IP non valide: $1",
        "restrictionsfield-label": "Intervallos IP permittite:",
-       "restrictionsfield-help": "Un adresse IP o intervallo CIDR per linea. Pro activar toto, usa<br><code>0.0.0.0/0</code><br><code>::/0</code>"
+       "restrictionsfield-help": "Un adresse IP o intervallo CIDR per linea. Pro activar toto, usa<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "pageid": "ID de pagina $1"
 }
index 69ad3b6..998280b 100644 (file)
@@ -49,7 +49,8 @@
                        "Mbrt",
                        "Beeyan",
                        "Bonaditya",
-                       "Irus"
+                       "Irus",
+                       "Presidenvolksraad"
                ]
        },
        "tog-underline": "Garis bawahi pranala:",
        "tagline": "Dari {{SITENAME}}",
        "help": "Bantuan",
        "search": "Pencarian",
+       "search-ignored-headings": "# <pre>\n# Judul yang akan diabaikan oleh pencarian.\n# Suntingan ini akan diterapkan setelah halaman dengan judul ini diindeks.\n# Anda bisa memaksakan pengindeksan kembali halaman ini dengan melakukan suntingan kosong (''null edit'')\n# Sintaksisnya adalah seperti berikut:\n#   * Semuanya dari karakter \"#\" ke akhir baris adalah sebuah komentar.\n#   * Setiap baris tak-kosong adalah judul tepat yang akan diabaikan.\nReferensi\nPranala luar\nLihat pula\n #</pre>",
        "searchbutton": "Cari",
        "go": "Tuju ke",
        "searcharticle": "Lanjut",
        "views": "Tampilan",
        "toolbox": "Perkakas",
        "tool-link-userrights": "Simpan kelompok {{GENDER:$1|pengguna}}",
+       "tool-link-userrights-readonly": "Lihat kelompok {{GENDER:$1|pengguna}}",
        "tool-link-emailuser": "Kirim surel ke {{GENDER:$1|pengguna}} ini",
        "userpage": "Lihat halaman pengguna",
        "projectpage": "Lihat halaman proyek",
        "createacct-yourpasswordagain-ph": "Masukkan lagi kata sandi",
        "userlogin-remembermypassword": "Biarkan saya tetap masuk",
        "userlogin-signwithsecure": "Gunakan server aman",
-       "cannotlogin-title": "Tidak dapat masuk",
-       "cannotlogin-text": "Login ini tidak mungkin.",
+       "cannotlogin-title": "Tidak dapat log masuk",
+       "cannotlogin-text": "Log masuk tidak mungkin.",
        "cannotloginnow-title": "Tidak dapat masuk log saat ini",
        "cannotloginnow-text": "Masuk log tidak memungkinkan ketika menggunakan $1.",
        "cannotcreateaccount-title": "Akun tak dapat dibuat",
        "eauthentsent": "Sebuah surel untuk konfirmasi telah dikirim ke alamat surel. Sebelum surel lainnya dikirim ke akun tersebut, Anda harus mengikuti instruksi di dalam surel tersebut, untuk melakukan konfirmasi bahwa alamat tersebut adalah benar kepunyaan Anda.",
        "throttled-mailpassword": "Suatu pengingat kata sandi telah dikirimkan dalam {{PLURAL:$1|$1 jam}} terakhir.\nUntuk menghindari penyalahgunaan, hanya satu kata sandi yang akan dikirimkan setiap {{PLURAL:$1|$1 jam}}.",
        "mailerror": "Kesalahan dalam mengirimkan surel: $1",
-       "acct_creation_throttle_hit": "Pengunjung wiki ini dengan alamat IP yang sama dengan Anda telah membuat {{PLURAL:$1|1 akun|$1 akun}} dalam satu hari terakhir, hingga jumlah maksimum yang diizinkan.\nKarenanya, pengunjung dengan alamat IP ini tidak dapat lagi membuat akun lain untuk sementara.",
+       "acct_creation_throttle_hit": "Pengunjung wiki ini dengan alamat IP yang sama dengan Anda telah membuat {{PLURAL:$1|1 akun|$1 akun}} dalam $2 terakhir, hingga jumlah maksimum yang diizinkan.\nKarenanya, pengunjung dengan alamat IP ini tidak dapat lagi membuat akun lain untuk sementara.",
        "emailauthenticated": "Alamat surel Anda telah dikonfirmasi pada $3, $2.",
        "emailnotauthenticated": "Alamat surel Anda belum dikonfirmasi.\nSebelum dikonfirmasi Anda tidak akan menerima surel dari fitur berikut.",
        "noemailprefs": "Anda harus memasukkan alamat surel di preferensi Anda untuk dapat menggunakan fitur-fitur ini.",
        "botpasswords-label-delete": "Hapus",
        "botpasswords-label-resetpassword": "Setel ulang kata sandi",
        "botpasswords-label-grants": "Akses yang dapat diberikan:",
-       "botpasswords-help-grants": "Tiap izin memberikan akses ke hak-hak pengguna yang telah dimiliki suatu akun pengguna. Lihat [[Special:ListGrants|tabel izin]] untuk informasi lebih lanjut.",
+       "botpasswords-help-grants": "Izin ke akses tertentu telah dimiliki oleh akun pengguna Anda. Mengaktifkan sebuah hak di sini tidak memberikan akses ke akses lain yang tidak dimiliki oleh akun pengguna Anda. Lihat [[Special:ListGrants|daftar hak akses]] untuk informasi selengkapnya.",
        "botpasswords-label-grants-column": "Izin diberikan",
        "botpasswords-bad-appid": "Nama bot \"$1\" tidak valid.",
        "botpasswords-insert-failed": "Gagal menambah nama bot \"$1\". Apakah sudah ditambahkan sebelum ini?",
        "botpasswords-updated-body": "Kata sandi bot \"$1\" dari pengguna \"$2\" berhasil diperbarui.",
        "botpasswords-deleted-title": "Kata sandi bot dihapus",
        "botpasswords-deleted-body": "Kata sandi bot \"$1\" dari pengguna \"$2\" telah dihapus.",
-       "botpasswords-newpassword": "Kata sandi baru untuk masuk log dengan '''$1''' adalah '''$2'''. ''Mohon simpan untuk referensi di kemudian hari.''",
+       "botpasswords-newpassword": "Kata sandi baru untuk masuk log dengan <strong>$1</strong> adalah <strong>$2</strong>. <em>Catatlah kata sandi ini untuk referensi ke depan.</em> <br> (Untuk bot lama yang memerlukan nama masuk log yang sama dengan nama pengguna, dapat menggunakan <strong>$3</strong> sebagai nama pengguna dan <strong>$4</strong> sebagai kata sandi.)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider tidak tersedia.",
        "botpasswords-restriction-failed": "Batasan kata sandi menghalangi masuk log ini.",
        "botpasswords-invalid-name": "Nama pengguna yang diberikan tidak mengandung pemisah kata sandi bot (\"$1\").",
        "passwordreset-emaildisabled": "Fitur surel telah dinonaktifkan pada wiki ini.",
        "passwordreset-username": "Nama pengguna:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "Lihat surel yang dihasilkan?",
-       "passwordreset-capture-help": "Jika Anda mencentang kotak ini, surel (dengan kata sandi sementara) akan ditampilkan ke Anda dan juga dikirim ke pengguna.",
        "passwordreset-email": "Alamat surel:",
        "passwordreset-emailtitle": "Detail akun di {{SITENAME}}",
        "passwordreset-emailtext-ip": "Seseorang (mungkin Anda, dari alamat IP $1) meminta pengingat\ndetail akun untuk {{SITENAME}} ($4). {{PLURAL:$3|Akun|Akun-akun}} berikut\nterkait dengan alamat surel ini:\n\n$2\n\n{{PLURAL:$3|Sandi sementara}} berikut akan kedaluwarsa dalam {{PLURAL:$5|$5 hari}}.\nAnda harus masuk dan memilih sandi baru sekarang. Jika orang lain membuat\npermintaan ini atau jika Anda ingat sandi asli dan tidak lagi\ningin mengubahnya, Anda dapat mengabaikan pesan ini dan terus menggunakan sandi lama.",
        "passwordreset-emailelement": "Nama pengguna: \n$1\n\nSandi sementara: \n$2",
        "passwordreset-emailsentemail": "Jika alamat surel ini berkaitan dengan akun Anda, maka surel untuk menyetel ulang kata sandi akan dikirim.",
        "passwordreset-emailsentusername": "Jika ada alamat surel yang berkaitan dengan nama pengguna ini, maka surel untuk menyetel ulang kata sandi akan dikirim.",
-       "passwordreset-emailsent-capture2": "Pemulihan kata sandi {{PLURAL:$1|surel|surel}} telah dikirim. {{PLURAL:$1|Nama pengguna dan kata sandi|Daftar nama pengguna dan kata sandi}} ditampilkan di bawah.",
-       "passwordreset-emailerror-capture2": "Pengiriman surel kepada {{GENDER:$2|pengguna}} gagal: $1 {{PLURAL:$3|Nama pengguna dan kata sandi|Daftar nama pengguna dan kata sandi}} ditampilkan di bawah.",
        "passwordreset-nocaller": "Pemanggil harus diberikan",
        "passwordreset-nosuchcaller": "Pemanggil tidak ada: $1",
        "passwordreset-ignored": "Pemulihan kata sandi tidak tertangani. Mungkin penyedia tidak diatur?",
-       "passwordreset-invalideamil": "Alamat surel tidak sah",
+       "passwordreset-invalidemail": "Alamat surel tidak sah",
        "passwordreset-nodata": "Nama pengguna ataupun alamat surel tidak diberikan",
        "changeemail": "Ubah atau hapus alamat surel",
        "changeemail-header": "Lengkapi formulir ini untuk mengubah alamat surel Anda. Jika Anda ingin menghapus seluruh alamat surel yang berkaitan dengan akun Anda, kosongkan alamat surel ketika mengirim formulir.",
        "savearticle": "Simpan halaman",
        "savechanges": "Simpan perubahan",
        "publishpage": "Terbitkan halaman",
+       "publishchanges": "Terbitkan perubahan",
        "preview": "Pratayang",
        "showpreview": "Lihat pratayang",
        "showdiff": "Lihat perubahan",
        "invalid-content-data": "Data konten tidak sah",
        "content-not-allowed-here": "Konten \"$1\" tidak diizinkan di halaman [[$2]]",
        "editwarning-warning": "Meninggalkan halaman ini dapat menyebabkan semua perubahan yang belum tersimpan hilang.\nJika Anda telah masuk log, Anda dapat mematikan peringatan ini lewat bagian \"Penyuntingan\" pada halaman preferensi Anda.",
+       "editpage-invalidcontentmodel-title": "Model konten tidak didukung",
+       "editpage-invalidcontentmodel-text": "Model konten \"$1\" tidak didukung.",
        "editpage-notsupportedcontentformat-title": "Format konten tidak didukung",
        "editpage-notsupportedcontentformat-text": "Format konten $1 tidak didukung oleh model konten $2.",
        "content-model-wikitext": "teks wiki",
        "content-model-css": "CSS",
        "content-json-empty-object": "Objek kosong",
        "content-json-empty-array": "Larik kosong",
+       "deprecated-self-close-category": "Halaman yang menggunakan tag HTML tertutup-sendiri tidak sah",
        "duplicate-args-warning": "<strong>Peringatan:</strong> [[:$1]] memanggil [[:$2]] dengan nilai lebih dari satu untuk parameter \"$3\". Hanya nilai terakhir yang tersedia yang akan digunakan.",
        "duplicate-args-category": "Halaman dengan argumen ganda di pemanggilan templat",
        "duplicate-args-category-desc": "Halaman ini berisi pemanggilan templat yang menggunakan argumen ganda, seperti <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> atau <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "search-external": "Pencarian eksternal",
        "searchdisabled": "Pencarian {{SITENAME}} sementara dimatikan.\nAnda dapat mencari melalui Google untuk sementara waktu.\nPerlu diingat bahwa indeks Google untuk konten {{SITENAME}} mungkin belum mencakup perubahan-perubahan terakhir.",
        "search-error": "Kesalahan terjadi saat mencari: $1",
+       "search-warning": "Peringatan terjadi ketika mencari: $1",
        "preferences": "Preferensi",
        "mypreferences": "Preferensi",
        "prefs-edits": "Jumlah suntingan:",
        "prefs-help-recentchangescount": "Opsi ini berlaku untuk perubahan terbaru, versi terdahulu halaman, dan log.",
        "prefs-help-watchlist-token2": "Ini adalah kunci rahasia (token) ke umpan web dari daftar pantauan Anda.\nSiapa saja yang tahu akan dapat melihat daftar pantauan Anda, jadi jangan dibagikan. Jika diperlukan\n[[Special:ResetTokens|Anda dapat mengatur ulang kunci tersebut]].",
        "savedprefs": "Preferensi Anda telah disimpan",
-       "savedrights": "Hak pengguna {{GENDER:$1|$1}} telah disimpan.",
+       "savedrights": "Kelompok hak pengguna {{GENDER:$1|$1}} telah disimpan.",
        "timezonelegend": "Zona waktu:",
        "localtime": "Waktu setempat:",
        "timezoneuseserverdefault": "Gunakan bawaan wiki ($1)",
        "prefswarning-warning": "Perubahan preferensi anda belum tersimpan. Apabila anda meninggalkan halaman ini tanpa men-klik \"$1\" preferensi anda tidak akan diperbarui.",
        "prefs-tabs-navigation-hint": "Tip: Anda dapat menggunakan tombol panah kiri dan kanan untuk bernavigasi antartab di dalam daftar tab.",
        "userrights": "Manajemen hak pengguna",
-       "userrights-lookup-user": "Mengatur kelompok pengguna",
+       "userrights-lookup-user": "Pilih seorang pengguna",
        "userrights-user-editname": "Masukkan nama pengguna:",
-       "editusergroup": "Sunting kelompok {{GENDER:$1|pengguna}}",
+       "editusergroup": "Muat kelompok pengguna",
        "editinguser": "Mengubah hak pengguna untuk {{GENDER:$1|pengguna}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Melihat hak pengguna dari {{GENDER:$1|pengguna}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Sunting kelompok pengguna",
+       "userrights-viewusergroup": "Lihat kelompok pengguna",
        "saveusergroups": "Simpan kelompok {{GENDER:$1|pengguna}}",
        "userrights-groupsmember": "Anggota dari:",
        "userrights-groupsmember-auto": "Anggota implisit dari:",
        "userrights-reason": "Alasan:",
        "userrights-no-interwiki": "Anda tidak memiliki hak untuk mengubah hak pengguna di wiki yang lain.",
        "userrights-nodatabase": "Basis data $1 tidak ada atau bukan lokal.",
-       "userrights-nologin": "Anda harus [[Special:UserLogin|masuk log]] dengan menggunakan akun pengurus untuk dapat mengubah hak pengguna.",
-       "userrights-notallowed": "AkunAnda tidak berhak untuk menambahkan atau membuang hak pengguna.",
        "userrights-changeable-col": "Kelompok yang dapat Anda ubah",
        "userrights-unchangeable-col": "Kelompok yang tidak dapat Anda ubah",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Konflik perubahan hak pengguna! Silakan tinjau ulang dan konfirmasi perubahan Anda.",
-       "userrights-removed-self": "Anda telah mencabut hak-hak Anda sendiri. Anda tidak bisa lagi mengakses halaman ini.",
        "group": "Kelompok:",
        "group-user": "Pengguna",
        "group-autoconfirmed": "Pengguna terkonfirmasi otomatis",
        "right-siteadmin": "Mengunci dan membuka kunci basis data",
        "right-override-export-depth": "Ekspor halaman termasuk halaman-halaman terkait hingga kedalaman 5",
        "right-sendemail": "Mengirim surel ke pengguna lain",
-       "right-passwordreset": "Lihat surel pengaturulangan kata sandi",
        "right-managechangetags": "Buat dan matikan [[Special:Tags|tag]]",
        "right-applychangetags": "Terapkan [[Special:Tags|tags]] bersamaan dengan perubahan pengguna",
        "right-changetags": "Tambah dan hapus [[Special:Tags|tag]] arbitrari pada revisi masing-masing dan entri log",
        "grant-group-high-volume": "Melakukan aktivitas yang amat banyak",
        "grant-group-customization": "Kustomisasi dan preferensi",
        "grant-group-administration": "Melakukan tindakan administratif",
+       "grant-group-private-information": "Akses data pribadi tentang Anda",
        "grant-group-other": "Aktivitas lain-lain",
        "grant-blockusers": "Blokir dan buka pemblokiran pengguna",
        "grant-createaccount": "Buat akun",
        "grant-highvolume": "Penyuntingan dengan volume tinggi",
        "grant-oversight": "Sembunyikan pengguna dan revisinya",
        "grant-patrol": "Tandai halaman terpatroli",
+       "grant-privateinfo": "Akses informasi pribadi",
        "grant-protect": "Melindungi dan membuka perlindungan halaman",
        "grant-rollback": "Membalikkan perubahan pada halaman",
        "grant-sendemail": "Mengirim surel kepada pengguna lain",
        "grant-basic": "Akses dasar",
        "grant-viewdeleted": "Melihat halaman dan berkas yang dihapus",
        "grant-viewmywatchlist": "Lihat daftar pantauan Anda",
+       "grant-viewrestrictedlogs": "Lihat entri log terbatas",
        "newuserlogpage": "Log pengguna baru",
        "newuserlogpagetext": "Di bawah ini adalah log pendaftaran pengguna baru",
        "rightslog": "Log perubahan hak akses",
        "action-upload_by_url": "memuatkan berkas ini dari sebuah alamat URL",
        "action-writeapi": "menggunakan API penulisan",
        "action-delete": "menghapus halaman ini",
-       "action-deleterevision": "menghapus revisi ini",
-       "action-deletedhistory": "melihat versi terdahulu halaman yang telah dihapus ini",
+       "action-deleterevision": "menghapus revisi",
+       "action-deletelogentry": "hapus entri log",
+       "action-deletedhistory": "melihat versi terdahulu halaman yang telah dihapus",
+       "action-deletedtext": "lihat teks revisi yang dihapus",
        "action-browsearchive": "mencari halaman-halaman yang telah dihapus",
-       "action-undelete": "membatalkan penghapusan halaman ini",
-       "action-suppressrevision": "meninjau dan mengembalikan revisi yang disembunyikan ini",
+       "action-undelete": "batalkan penghapusan halaman",
+       "action-suppressrevision": "tinjau dan kembalikan revisi yang disembunyikan",
        "action-suppressionlog": "melihat log privat ini",
        "action-block": "Blokir pengguna ini dari penyuntingan",
        "action-protect": "mengganti tingkat pelindungan halaman ini",
        "action-userrights-interwiki": "menyunting hak akses dari pengguna di wiki lain",
        "action-siteadmin": "mengunci atau membuka kunci basis data",
        "action-sendemail": "kirim surel",
+       "action-editmyoptions": "sunting preferensi Anda",
        "action-editmywatchlist": "sunting daftar pantauan Anda",
        "action-viewmywatchlist": "lihat daftar pantau Anda",
        "action-viewmyprivateinfo": "lihat informasi pribadi Anda",
        "action-applychangetags": "terapkan tag bersamaan dengan perubahan Anda",
        "action-changetags": "menambah dan menghapus tag semaunya pada revisi individu dan entri log",
        "action-deletechangetags": "hapus tag dari basis data",
+       "action-purge": "hapus singgahan halaman ini",
        "nchanges": "$1 {{PLURAL:$1|perubahan|perubahan}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|sejak kunjungan terakhir}}",
        "enhancedrc-history": "riwayat",
        "upload-http-error": "Kesalahan HTTP terjadi: $1",
        "upload-copy-upload-invalid-domain": "Unggahan salinan tidak tersedia dari domain ini.",
        "upload-foreign-cant-upload": "Wiki ini tidak diatur untuk mengunggah berkas ke gudang penyimpangan asing.",
-       "upload-dialog-disabled": "Upload file menggunakan dialog ini dinonaktifkan pada wiki ini.",
+       "upload-dialog-disabled": "Unggah berkas menggunakan dialog ini dinonaktifkan pada wiki ini.",
        "upload-dialog-title": "Unggah berkas",
        "upload-dialog-button-cancel": "Batalkan",
+       "upload-dialog-button-back": "Kembali",
        "upload-dialog-button-done": "Selesai",
        "upload-dialog-button-save": "Simpan",
        "upload-dialog-button-upload": "Unggah",
        "apisandbox-results-fixtoken-fail": "Gagal mendapatkan token \"$1\".",
        "apisandbox-alert-page": "Kolom dalam halaman ini tidak valid.",
        "apisandbox-alert-field": "Nilai dalam kolom ini tidak valid.",
+       "apisandbox-continue": "Lanjutkan",
+       "apisandbox-continue-clear": "Kosongkan",
        "booksources": "Sumber buku",
        "booksources-search-legend": "Cari di sumber buku",
        "booksources-isbn": "ISBN:",
        "emailccsubject": "Salinan pesan Anda untuk $1: $2",
        "emailsent": "Surel terkirim",
        "emailsenttext": "Surel Anda telah dikirimkan.",
-       "emailuserfooter": "Email ini dikirimkan oleh $1 ke $2 dengan fungsi \"{{int:emailuser}}\" di {{SITENAME}}.",
+       "emailuserfooter": "Surel ini telah {{GENDER:$1|dikirim}} oleh $1 kepada {{GENDER:$2|$2}} dengan fungsi \"{{int:emailuser}}\" pada {{SITENAME}}. Surel {{GENDER:$2|Anda}} akan dikirim langsung kepada {{GENDER:$1|pengirim asal}}, dengan menampilkan alamat surel {{GENDER:$2|Anda}} kepada {{GENDER:$1|mereka}}.",
        "usermessage-summary": "Tinggalkan pesan sistem.",
        "usermessage-editor": "Penyampai pesan sistem",
        "usermessage-template": "MediaWiki:UserMessage",
        "modifiedarticleprotection": "mengubah tingkat pelindungan \"[[$1]]\"",
        "unprotectedarticle": "menghilangkan perlindungan dari \"[[$1]]\"",
        "movedarticleprotection": "memindahkan pengaturan proteksi dari \"[[$2]]\" ke \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Melindungi}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Mengubah tingkat perlindungan}} untuk \"[[$1]]\"",
+       "unprotectedarticle-comment": "{{GENDER:$2|Menghapus perlindungan}} dari \"[[$1]]\"",
        "protect-title": "Melindungi \"$1\"",
        "protect-title-notallowed": "Lihat tingkat perlindungan dari \"$1\"",
        "prot_1movedto2": "[[$1]] dipindahkan ke [[$2]]",
        "undeletehistorynoadmin": "Halaman ini telah dihapus.\nAlasan penghapusan diberikan pada ringkasan di bawah ini, berikut rincian pengguna yang telah melakukan penyuntingan pada halaman ini sebelum dihapus. Isi terakhir dari revisi yang telah dihapus ini hanya tersedia untuk pengurus.",
        "undelete-revision": "Revisi yang telah dihapus dari $1 (pada $5, $4) oleh $3:",
        "undeleterevision-missing": "Revisi salah atau tak ditemukan. Anda mungkin mengikuti pranala yang salah, atau revisi tersebut telah dipulihkan atau dibuang dari arsip.",
+       "undeleterevision-duplicate-revid": "{{PLURAL:$1|Sebuah revisi|$1 revisi}} tidak dapat dipulihkan, karena <code>rev_id</code> {{PLURAL:$1|mereka|mereka}} sedang digunakan.",
        "undelete-nodiff": "Tidak ada revisi yang lebih lama.",
        "undeletebtn": "Kembalikan",
        "undeletelink": "lihat/kembalikan",
        "undeletedrevisions": "$1 {{PLURAL:$1|revisi|revisi}} telah dikembalikan",
        "undeletedrevisions-files": "$1 {{PLURAL:$1|revisi|revisi}} and $2 berkas dikembalikan",
        "undeletedfiles": "$1 {{PLURAL:$1|berkas|berkas}} dikembalikan",
-       "cannotundelete": "Pembatalan penghapusan gagal:\n$1",
+       "cannotundelete": "Beberapa pembatalan penghapusan gagal:\n$1",
        "undeletedpage": "'''$1 berhasil dikembalikan'''\n\nLihat [[Special:Log/delete|log penghapusan]] untuk data penghapusan dan pengembalian.",
        "undelete-header": "Lihat [[Special:Log/delete|log penghapusan]] untuk daftar halaman yang baru dihapus.",
        "undelete-search-title": "Cari halaman yang dihapus",
        "sp-contributions-newbies-sub": "Untuk pengguna baru",
        "sp-contributions-newbies-title": "Kontribusi pengguna baru",
        "sp-contributions-blocklog": "log pemblokiran",
-       "sp-contributions-suppresslog": "kontribusi pengguna yang disembunyikan",
-       "sp-contributions-deleted": "kontribusi pengguna yang dihapus",
+       "sp-contributions-suppresslog": "kontribusi {{GENDER:$1|pengguna}} yang disembunyikan",
+       "sp-contributions-deleted": "kontribusi {{GENDER:$1|pengguna}} yang dihapus",
        "sp-contributions-uploads": "unggahan",
        "sp-contributions-logs": "log",
        "sp-contributions-talk": "bicara",
        "sp-contributions-username": "Alamat IP atau nama pengguna:",
        "sp-contributions-toponly": "Tampilkan hanya revisi teratas",
        "sp-contributions-newonly": "Hanya tampilkan suntingan yang berupa pembuatan halaman",
+       "sp-contributions-hideminor": "Sembunyikan suntingan kecil",
        "sp-contributions-submit": "Cari",
        "whatlinkshere": "Pranala balik",
        "whatlinkshere-title": "Halaman yang memiliki pranala ke \"$1\"",
        "movelogpagetext": "Di bawah ini adalah log pemindahan halaman.",
        "movesubpage": "{{PLURAL:$1|Subhalaman|Subhalaman}}",
        "movesubpagetext": "Halaman ini memiliki $1 {{PLURAL:$1|subhalaman|subhalaman}} seperti ditampilkan berikut.",
+       "movesubpagetalktext": "Halaman pembicaraan terkait mempunyai $1 {{PLURAL:$1|subhalaman|subhalaman}} yang tampil di bawah ini.",
        "movenosubpage": "Halaman ini tak memiliki subhalaman.",
        "movereason": "Alasan:",
        "revertmove": "batalkan",
        "pageinfo-article-id": "ID Halaman",
        "pageinfo-language": "Bahasa isi halaman",
        "pageinfo-content-model": "Model isi halaman",
+       "pageinfo-content-model-change": "ubah",
        "pageinfo-robot-policy": "Pengindeksan oleh robot",
        "pageinfo-robot-index": "Diperbolehkan",
        "pageinfo-robot-noindex": "Tidak diperbolehkan",
        "pageinfo-category-pages": "Jumlah halaman",
        "pageinfo-category-subcats": "Jumlah subkategori",
        "pageinfo-category-files": "Jumlah berkas",
+       "pageinfo-user-id": "ID pengguna",
        "markaspatrolleddiff": "Tandai telah dipatroli",
        "markaspatrolledtext": "Tandai halaman ini telah dipatroli",
        "markaspatrolledtext-file": "Tandai versi berkas sebagai terpatroli",
        "patrol-log-header": "Ini adalah log revisi terpatroli.",
        "log-show-hide-patrol": "$1 log patroli",
        "log-show-hide-tag": "log tag $1",
+       "confirm-markpatrolled-button": "OK",
+       "confirm-markpatrolled-top": "Tandai revisi $3 dari $2 sebagai terperiksa?",
        "deletedrevision": "Revisi lama yang dihapus $1",
        "filedeleteerror-short": "Kesalahan waktu menghapus berkas: $1",
        "filedeleteerror-long": "Terjadi kesalahan sewaktu menghapus berkas:\n\n$1",
        "tags-actions-header": "Tindakan",
        "tags-active-yes": "Ya",
        "tags-active-no": "Tidak",
-       "tags-source-extension": "Ditetapkan oleh suatu ekstensi",
+       "tags-source-extension": "Ditetapkan oleh perangkat lunak",
        "tags-source-manual": "Digunakan secara manual oleh pengguna dan bot",
        "tags-source-none": "Tidak digunakan lagi",
        "tags-edit": "sunting",
        "tags-deactivate": "nonaktifkan",
        "tags-hitcount": "$1 {{PLURAL:$1|perubahan}}",
        "tags-manage-no-permission": "Anda tak memiliki hak akses untuk mengatur perubahan tag.",
-       "tags-manage-blocked": "Anda tidak dapat mengganti tag ketika sedang diblokir.",
+       "tags-manage-blocked": "Anda tidak dapat mengatur perubahan tag ketika {{GENDER:$1|Anda}} diblokir.",
        "tags-create-heading": "Buat sebuah tag baru",
        "tags-create-explanation": "Secara baku, tag yang baru dibuat akan tersedia untuk digunakan oleh pengguna dan bot.",
        "tags-create-tag-name": "Nama tag:",
        "tags-create-warnings-below": "Apakah Anda ingin melanjutkan pembuatan tanda ini?",
        "tags-delete-title": "Hapus tag",
        "tags-delete-explanation-initial": "Anda akan menghapus tag \"$1\" dari basisdata.",
+       "tags-delete-explanation-warning": "Tindakan ini <strong>tidak bisa dikembalikan</strong> dan <strong>tidak bisa dibatalkan</strong> oleh siapa pun termasuk pengurus basis data. Pastikan sebaik-baiknya bahwa inilah tag yang ingin Anda hapus.",
        "tags-delete-reason": "Alasan:",
+       "tags-delete-submit": "Hapus tag ini juga",
+       "tags-delete-not-allowed": "Tag yang diberikan oleh ekstensi tidak dapat dihapus kecuali ekstensi tersebut mengizinkan.",
+       "tags-delete-not-found": "Tag \"$1\" tidak ada.",
+       "tags-delete-too-many-uses": "Tag \"$1\" diterapkan ke $2 atau lebih {{PLURAL:$2|revisi|revisi}} yang artinya tag tersebut tidak dapat dihapus.",
+       "tags-delete-warnings-after-delete": "Tag \"$1\" dihapus, namun {{PLURAL:$2|peringatan|peringatan}} berikut menemukan:",
+       "tags-delete-no-permission": "Anda tak memiliki hak akses untuk menghapus perubahan tag.",
+       "tags-activate-title": "Aktifkan tag",
+       "tags-activate-question": "Anda akan mengaktifkan tag \"$1\".",
        "tags-activate-reason": "Alasan:",
+       "tags-activate-not-allowed": "Tag \"$1\" tidak mungkin dapat diaktifkan.",
+       "tags-activate-not-found": "Tag \"$1\" tidak ada.",
        "tags-activate-submit": "Aktifkan",
+       "tags-deactivate-title": "Nonaktifkan tag",
+       "tags-deactivate-question": "Anda akan menonaktifkan tag \"$1\".",
        "tags-deactivate-reason": "Alasan:",
+       "tags-deactivate-not-allowed": "Tag \"$1\" tidak mungkin dapat dinonaktifkan.",
        "tags-deactivate-submit": "Matikan",
-       "tags-apply-blocked": "Anda tidak dapat menerapkan perubahan tag dan perubahan lainnya ketika sedang diblokir.",
-       "tags-update-blocked": "Anda tidak dapat menambah atau menghapus tag ketika sedang diblokir.",
+       "tags-apply-no-permission": "Anda tidak memiliki izin untuk menerapkan perubahan tag bersama-sama dengan perubahan Anda.",
+       "tags-apply-blocked": "Anda tidak dapat menerapkan perubahan tag dengan perubahan Anda ketika {{GENDER:$1|Anda}} sedang diblokir.",
+       "tags-apply-not-allowed-one": "Tag \"$1\" tidak diizinkan untuk diterapkan secara manual.",
+       "tags-apply-not-allowed-multi": "{{PLURAL:$2|Tag|Tag}} berikut tidak diizinkan untuk diterapkan secara manual: $1",
+       "tags-update-no-permission": "Anda tidak memiliki izin untuk menambah atau menghapus perubahan tag dari revisi atau entri log individu.",
+       "tags-update-blocked": "Anda tidak dapat menambahkan atau menghapus perubahan tag ketika {{GENDER:$1|Anda}} sedang diblokir.",
+       "tags-edit-title": "Sunting tag",
+       "tags-edit-manage-link": "Kelola tag",
+       "tags-edit-revision-selected": "{{PLURAL:$1|Revisi terpilih|Revisi terpilih}} dari [[:$2]]:",
+       "tags-edit-logentry-selected": "{{PLURAL:$1|Log peristiwa terpilih|Log peristiwa terpilih}}:",
+       "tags-edit-revision-legend": "Tambah atau hapus tag dari {{PLURAL:$1|revisi ini|semua revisi $1}}",
+       "tags-edit-logentry-legend": "Tambah atau hapus tag dari {{PLURAL:$1|entri log ini|semua entri log $1}}",
        "tags-edit-existing-tags": "Tag yang ada:",
        "tags-edit-existing-tags-none": "<em>Tidak ada</em>",
        "tags-edit-new-tags": "Tag baru:",
        "htmlform-cloner-create": "Tambahkan lebih banyak",
        "htmlform-cloner-delete": "Hapus",
        "htmlform-cloner-required": "Paling sedikit satu nilai diperlukan.",
+       "htmlform-date-placeholder": "TTTT-BB-HH",
+       "htmlform-time-placeholder": "JJ:MM:DD",
+       "htmlform-datetime-placeholder": "TTTT-BB-HH JJ:MM:DD",
+       "htmlform-date-invalid": "Nilai yang diberikan tidak dikenali sebagai tanggal. Coba lagi menggunakan format TTTT-BB-HH.",
        "htmlform-title-badnamespace": "[[:$1]] tidak berada dalam ruang nama \"{{ns:$2}}\".",
        "htmlform-title-not-creatable": "\"$1\" bukan merupakan judul halaman yang dapat dibuat",
        "htmlform-title-not-exists": "$1 tidak ada.",
        "htmlform-user-not-exists": "<strong>$1</strong> tidak ada.",
        "htmlform-user-not-valid": "<strong>$1</strong> bukan merupakan nama pengguna sah.",
        "logentry-delete-delete": "$1 {{GENDER:$2|menghapus}} halaman $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|menghapus}} pengalihan $3 dengan penimpaan",
        "logentry-delete-restore": "$1 {{GENDER:$2|mengembalikan}} halaman $3",
        "logentry-delete-event": "$1 {{GENDER:$2|mengubah}} tampilan {{PLURAL:$5|$5 log peristiwa}} di $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|mengubah}} tampilan {{PLURAL:$5|$5  revisi}} di halaman $3: $4",
        "feedback-thanks": "Terima kasih! Umpan balik Anda telah dikirimkan ke halaman \"[$2 $1]\".",
        "feedback-thanks-title": "Terima kasih!",
        "feedback-useragent": "Agen pengguna:",
-       "searchsuggest-search": "Cari",
+       "searchsuggest-search": "Cari {{SITENAME}}",
        "searchsuggest-containing": "berisi...",
        "api-error-autoblocked": "Alamat IP Anda telah diblokir secara otomatis, karena sebelumnya digunakan oleh pengguna yang diblokir.",
        "api-error-badaccess-groups": "Anda tidak diizinkan mengunggah berkas ke wiki ini.",
        "mw-widgets-dateinput-no-date": "Tanggal tidak ada yang terpilih",
        "mw-widgets-dateinput-placeholder-day": "TTTT-BB-HH",
        "mw-widgets-dateinput-placeholder-month": "TTTT-BB",
+       "mw-widgets-mediasearch-input-placeholder": "Cari media",
+       "mw-widgets-mediasearch-noresults": "Tidak ada hasil ditemukan.",
        "mw-widgets-titleinput-description-new-page": "halaman belum ada",
        "mw-widgets-titleinput-description-redirect": "mengalihkan ke $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Tambah sebuah kategori...",
        "sessionmanager-tie": "Tidak dapat menggabungkan banyak jenis otentikasi permintaan: $1.",
        "sessionprovider-generic": "sesi $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sesi berdasarkan kuki",
        "log-action-filter-newusers": "Jenis pembuatan akun:",
        "log-action-filter-patrol": "Jenis patroli:",
        "log-action-filter-protect": "Jenis perlindungan:",
-       "log-action-filter-rights": "Jenis penggantian hak",
-       "log-action-filter-suppress": "Jenis penyembunyian",
+       "log-action-filter-rights": "Jenis penggantian hak akses:",
+       "log-action-filter-suppress": "Jenis penyembunyian:",
        "log-action-filter-upload": "Jenis pengunggahan:",
        "log-action-filter-all": "Semua",
        "log-action-filter-block-block": "Blokir",
        "log-action-filter-contentmodel-change": "Ubah Modelkonten",
        "log-action-filter-contentmodel-new": "Pembuatan halaman dengan Modelkonten yang tak baku",
        "log-action-filter-delete-delete": "Penghapusan halaman",
+       "log-action-filter-delete-delete_redir": "Mengalihkan pengalihan",
        "log-action-filter-delete-restore": "Pembatalan penghapusan halaman",
        "log-action-filter-delete-event": "Log penghapusan",
        "log-action-filter-delete-revision": "Penghapusan revisi",
        "authmanager-authn-autocreate-failed": "Pembuatan otomatis dari akun lokal gagal: $1",
        "authmanager-change-not-supported": "Kredensial yang diberikan tidak dapat diganti, karena tidak ada yang akan menggunakannya.",
        "authmanager-create-disabled": "Pembuatan akun dimatikan.",
-       "authmanager-create-from-login": "Untuk membuat akun Anda, silakan isi kolom di bawah.",
+       "authmanager-create-from-login": "Untuk membuat akun, silakan isi kolom di bawah.",
        "authmanager-create-not-in-progress": "Pembuatan akun tidak dilanjutkan atau data sesi telah hilang. Ulang kembali dari awal.",
        "authmanager-create-no-primary": "Kredensial yang diberikan tidak dapat digunakan untuk pembuatan akun.",
        "authmanager-link-no-primary": "Kredensial yang diberikan tidak dapat digunakan untuk menautkan akun.",
        "linkaccounts-success-text": "Akun telah ditautkan.",
        "linkaccounts-submit": "Tautkan akun",
        "unlinkaccounts": "Lepastautkan akun",
-       "unlinkaccounts-success": "Akun berikut telah dilepastautkan."
+       "unlinkaccounts-success": "Akun berikut telah dilepastautkan.",
+       "restrictionsfield-badip": "Alamat IP atau rentang IP tidak sah: $1",
+       "restrictionsfield-label": "Rentang IP yang diizinkan:",
+       "restrictionsfield-help": "Satu alamat IP atau rentang CIDR per baris. Untuk mengaktifkan semuanya, gunakan <br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "pageid": "ID halaman $1"
 }
index 53a910d..62abac0 100644 (file)
        "yourname": "Nómine de usator:",
        "yourpassword": "Parol-clave:",
        "yourpasswordagain": "Parol-clave denov:",
-       "remembermypassword": "Memorar mi parol-clave in ti navigator (por un maxim de $1 {{PLURAL:$1|die|dies}})",
        "yourdomainname": "Tui dominia:",
        "login": "Aperter session",
        "nav-login-createaccount": "Crear un conto o intrar",
index f379ef2..81b98c5 100644 (file)
        "yourname": "Áhà ọ'bànifé:",
        "yourpassword": "Okwúngáfè:",
        "yourpasswordagain": "Detuari mkpurụ okwu ejị a gafẹ:",
-       "remembermypassword": "Chetá edemede éjim a banyé na orunótuá (nke ukwu nke rürü {{PLURAL:$1|chi|chi}} $1)",
        "yourdomainname": "Obí gi:",
        "login": "Banyé",
        "nav-login-createaccount": "Banyé / ké buwá",
        "content-model-wikitext": "wikitext",
        "parser-template-loop-warning": "Etemete àtụ dị: [[$1]]",
        "undo-summary": "Emekwàlà orübà $1 shí [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]])",
-       "cantcreateaccounttitle": "Enwéghịkị ke buwá",
        "viewpagelogs": "Zi ndetu ncheta màkà ihü a",
        "nohistory": "Ákíkó mbu màkà orü àdíghị màkà ihüá.",
        "currentrev": "Kuwaria nke ubüwạ",
        "listusers-submit": "Zi",
        "listusers-noresult": "Ọ hügị ọ'bànifé.",
        "listusers-blocked": "(kwàchịrị)",
-       "activeusers-hidebots": "Zonari bot",
-       "activeusers-hidesysops": "Zonari ndi íshí",
        "activeusers-noresult": "Ọ hügị ọ'bànifé.",
        "listgrouprights-group": "Ọtú",
        "listgrouprights-rights": "Nkwènyé",
index 46a2e24..904956e 100644 (file)
        "botpasswords-label-resetpassword": "Isaad manen ti kontrasenias",
        "botpasswords-label-grants": "Dagiti sagut a maipakat:",
        "botpasswords-help-grants": "Ti tunggal maysa a sagut ket mangited iti panagserrek kadagiti nailista a karbengan nga addan iti pakabilangan ti agar-aramat. Kitaen ti [[Special:ListGrants|tabla dagiti sagut]] para iti adu pay a pakaammo.",
-       "botpasswords-label-restrictions": "Dagiti panangigawid iti panagusar:",
        "botpasswords-label-grants-column": "Naisaguten",
        "botpasswords-bad-appid": "Saan nga umisu ti nagan ti bot iti \"$1\".",
        "botpasswords-insert-failed": "Napaay iti pananginayon ti nagan ti bot iti \"$1\". Nainayon kadi idin?",
        "passwordreset-nocaller": "Nasken a maited ti maysa nga agtawtawag",
        "passwordreset-nosuchcaller": "Awan ti agtawtawag: $1",
        "passwordreset-ignored": "Saan a natengngel ti panangisaad manen ti kontrasenias. Mabalin a saan a nakompigura ti mangited?",
-       "passwordreset-invalideamil": "Imbalido nga adres ti esurat",
+       "passwordreset-invalidemail": "Imbalido nga adres ti esurat",
        "passwordreset-nodata": "Saan a naited ti nagan ti agar-aramat wenno maysa nga adres ti esurat",
        "changeemail": "Sukatan wenno ikkaten ti adres ti esurat",
        "changeemail-header": "Kompletuen daytoy a porma tapno masukatan ti adres ti esuratmo. No kayatmo a maikkat ti pannakainaig iti ania man nga adres ti esurat manipud iti pakabilangam, ibati a blanko ti baro nga adres ti esurat no ited ti porma.",
        "activeusers-intro": "Daytoy ti listaan dagiti agar-aramat nga adda inar-aramid iti kaunegan dagiti napalabas a $1 {{PLURAL:$1|nga aldaw|nga al-aldaw}}.",
        "activeusers-count": "$1 a {{PLURAL:$1|tignay|tigtignay}} iti napalabas {{PLURAL:$3|nga aldaw|a $3 nga al-aldaw}}",
        "activeusers-from": "Iparang dagiti agar-aramat a mangrugi iti:",
-       "activeusers-hidebots": "Ilemmeng dagiti bot",
-       "activeusers-hidesysops": "Ilemmeng dagiti administrador",
        "activeusers-noresult": "Awan ti nasarakan nga agar-aramat.",
        "activeusers-submit": "Ipakita dagiti aktibo nga agar-aramat",
        "listgrouprights": "Dagiti karbengan ti grupo ti agar-aramat",
        "feedback-bugornote": "No sisasagakan nga agibaga ti teknikal a pakirut a naisalaysay pangngaasi nga [$1 ireporta ti parikut].\nNupay kasta, mausarmo ti nalaka a porma dita baba. Ti komentario nga itedmo ket mainayon iti panid \"[$3 $2], a mairaman ti naganmo nga agar-aramat ken no ania ti pagbasabasa nga us-sarem.",
        "feedback-cancel": "Ukasen",
        "feedback-close": "Nalpasen",
-       "feedback-error-title": "Biddut",
        "feedback-error1": "Biddut: Saan a malasin dagiti nagbanagan manipud ti API",
        "feedback-error2": "Biddut: Napaay ti panagurnos",
        "feedback-error3": "Biddut: Awan ti sungbat manipud ti API",
index d735991..4184353 100644 (file)
        "yourpasswordagain": "Юхаязде къайладIоагIа:",
        "createacct-yourpasswordagain": "Бакъйе пароль",
        "createacct-yourpasswordagain-ph": "Кхы цхьаькхаза Iочуязъе пароль",
-       "remembermypassword": "ДагайоагIаш хилийта са дагара йоазув укх компьютер тӀа (цхьан $1 {{PLURAL:$1|дийнахь}})",
        "userlogin-remembermypassword": "Система чу виса",
        "yourdomainname": "Хьа нана-цIа:",
        "login": "Чувала/яла",
index 02312cc..a6344cc 100644 (file)
        "activeusers-intro": "Þetta er listi yfir notendur sem hafa verið virkir {{PLURAL:$1|síðasta|síðustu}} $1 {{PLURAL:$1|dag|daga}}.",
        "activeusers-count": "$1 {{PLURAL:$1|aðgerð|aðgerðir}} á {{PLURAL:$3|síðasta $3 degi|síðustu $3 dögum}}",
        "activeusers-from": "Sýna notendur sem byrja á:",
-       "activeusers-hidebots": "Fela vélmenni",
-       "activeusers-hidesysops": "Fela möppudýr",
        "activeusers-noresult": "Enginn notandi fannst.",
        "activeusers-submit": "Sýna virka notendur",
        "listgrouprights": "Notandahópréttindi",
index e3e042c..82783c1 100644 (file)
        "views": "Visite",
        "toolbox": "Strumenti",
        "tool-link-userrights": "Modifica gruppi {{GENDER:$1|utente}}",
+       "tool-link-userrights-readonly": "Visualizza gruppi {{GENDER:$1|utente}}",
        "tool-link-emailuser": "Invia una email a questo {{GENDER:$1|utente}}",
        "userpage": "Visualizza la pagina utente",
        "projectpage": "Visualizza la pagina di servizio",
        "passwordreset-emaildisabled": "Le funzionalità di posta elettronica sono state disabilitate su questa wiki.",
        "passwordreset-username": "Nome utente:",
        "passwordreset-domain": "Dominio:",
-       "passwordreset-capture": "Visualizzare il contenuto del messaggio e-mail?",
-       "passwordreset-capture-help": "Se si seleziona questa casella, l'indirizzo e-mail (con la password temporanea), verrà mostrato a voi, oltre ad essere inviato all'utente.",
        "passwordreset-email": "Indirizzo email:",
        "passwordreset-emailtitle": "Dettagli dell'utente su {{SITENAME}}",
        "passwordreset-emailtext-ip": "Qualcuno (probabilmente tu, con indirizzo IP $1) ha richiesto l'invio di una nuova password per l'accesso a {{SITENAME}} ($4). {{PLURAL:$3|L'utente associato|Gli utenti associati}} a questo indirizzo email sono:\n\n$2\n\n{{PLURAL:$3|Questa password temporanea scadrà|Queste password temporanee scadranno}} dopo {{PLURAL:$5|un giorno|$5 giorni}}.\nDovresti accedere e scegliere una nuova password ora. \n\nSe non sei stato tu a fare la richiesta, o se ti sei ricordato la password originale e non vuoi più cambiarla, puoi ignorare questo messaggio e continuare ad utilizzare la tua vecchia password.",
        "passwordreset-emailelement": "Nome utente: \n$1\n\nPassword temporanea: \n$2",
        "passwordreset-emailsentemail": "Se questo indirizzo di posta elettronica è associato con la tua utenza, allora verrà inviata una email per reimpostare la password.",
        "passwordreset-emailsentusername": "Se c'è un indirizzo di posta elettronica associato con questo nome utente, allora verrà inviata una email per reimpostare la password.",
-       "passwordreset-emailsent-capture2": "L'email di reimpostazione della password {{PLURAL:$1|è stata inviata|sono state inviate}}. {{PLURAL:$1|Il nome|L'elenco di nomi}} utente e password è mostrato qui.",
-       "passwordreset-emailerror-capture2": "Invio di email {{GENDER:$2|all'utente}} non riuscito: $1. {{PLURAL:$3|Il nome|L'elenco di nomi}} utente e password è mostrato qui.",
        "passwordreset-nocaller": "Un chiamante deve essere fornito",
        "passwordreset-nosuchcaller": "Chiamante non esiste: $1",
        "passwordreset-ignored": "La reimpostazione della password non è stata gestita. Forse nessun provider è configurato?",
-       "passwordreset-invalideamil": "Indirizzo di posta elettronica non valido",
+       "passwordreset-invalidemail": "Indirizzo di posta elettronica non valido",
        "passwordreset-nodata": "Non è stato fornito né un nome utente né un indirizzo di posta elettronica",
        "changeemail": "Modifica o rimuovi indirizzo di posta elettronica",
        "changeemail-header": "Completa questo modulo per cambiare il tuo indirizzo email. Se vuoi rimuovere l'associazione di qualsiasi indirizzo email dalla tua utenza, lascia il nuovo indirizzo email vuoto quando invii il modulo.",
        "prefs-help-recentchangescount": "Comprende ultime modifiche, cronologie e registri.",
        "prefs-help-watchlist-token2": "Questa è la chiave segreta per il feed web dei tuoi osservati speciali.\nChiunque la conosce sarà in grado di leggere i tuoi osservati speciali, per cui non condividerla. [[Special:ResetTokens|Clicca qui se hai bisogno di reimpostarla]].",
        "savedprefs": "Le preferenze sono state salvate.",
-       "savedrights": "I diritti utente di {{GENDER:$1|$1}} sono stati salvati.",
+       "savedrights": "I gruppi utente di {{GENDER:$1|$1}} sono stati salvati.",
        "timezonelegend": "Fuso orario:",
        "localtime": "Ora locale:",
        "timezoneuseserverdefault": "Usa ora predefinita del wiki ($1)",
        "prefswarning-warning": "Hai fatto modifiche alle tue preferenze che non sono state ancora salvate.\nSe esci da questa pagina senza cliccare \"$1\" le preferenze non verranno aggiornate.",
        "prefs-tabs-navigation-hint": "Suggerimento: è possibile utilizzare i tasti freccia sinistra e destra per spostarsi tra le schede nell'elenco delle schede.",
        "userrights": "Gestione dei permessi degli utenti",
-       "userrights-lookup-user": "Gestione dei gruppi utente",
+       "userrights-lookup-user": "Seleziona un utente",
        "userrights-user-editname": "Inserire il nome utente:",
-       "editusergroup": "Modifica gruppi {{GENDER:$1|utente}}",
+       "editusergroup": "Modifica gruppi utente",
        "editinguser": "Modifica in corso dei diritti dell'{{GENDER:$1|utente}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modifica gruppi utente",
+       "userrights-viewusergroup": "Visualizza gruppi utente",
        "saveusergroups": "Salva gruppi {{GENDER:$1|utente}}",
        "userrights-groupsmember": "Appartiene {{PLURAL:$1|al gruppo|ai gruppi}}:",
        "userrights-groupsmember-auto": "Membro implicito di:",
        "userrights-reason": "Motivo:",
        "userrights-no-interwiki": "Non si dispone dei permessi necessari per modificare i diritti degli utenti su altri siti.",
        "userrights-nodatabase": "Il database $1 non esiste o non è un database locale.",
-       "userrights-nologin": "Per assegnare diritti agli utenti è necessario [[Special:UserLogin|effettuare l'accesso]] come amministratore.",
-       "userrights-notallowed": "Non disponi dell'autorizzazione per aggiungere o rimuovere i permessi utente.",
        "userrights-changeable-col": "Gruppi modificabili",
        "userrights-unchangeable-col": "Gruppi non modificabili",
        "userrights-conflict": "Conflitto di modifica dei diritti utente! Controlla e conferma le tue modifiche.",
-       "userrights-removed-self": "Hai rimosso i tuoi diritti. E quindi, non sarai più in grado di accedere a questa pagina.",
        "group": "Gruppo:",
        "group-user": "Utenti",
        "group-autoconfirmed": "Utenti autoconvalidati",
        "right-siteadmin": "Blocca e sblocca il database",
        "right-override-export-depth": "Esporta le pagine includendo le pagine collegate fino ad una profondità di 5",
        "right-sendemail": "Invia email ad altri utenti",
-       "right-passwordreset": "Vede i messaggi di reimpostazione della password",
        "right-managechangetags": "Crea e attiva/disattiva le [[Special:Tags|etichette]]",
        "right-applychangetags": "Applica delle [[Special:Tags|etichette]] alle proprie modifiche",
        "right-changetags": "Aggiunge e rimuove specifiche [[Special:Tags|etichette]] su singole versioni o voci di registro",
        "action-userrights": "modificare tutti i diritti degli utenti",
        "action-userrights-interwiki": "modificare i diritti degli utenti su altre wiki",
        "action-siteadmin": "bloccare e sbloccare il database",
-       "action-sendemail": "inviare e-mail",
+       "action-sendemail": "inviare email",
        "action-editmywatchlist": "modificare i propri osservati speciali",
        "action-viewmywatchlist": "vedere i propri osservati speciali",
        "action-viewmyprivateinfo": "vedere i propri dati personali",
        "apisandbox-alert-field": "Il valore di questo campo non è valido.",
        "apisandbox-continue": "Continua",
        "apisandbox-continue-clear": "Pulisci",
+       "apisandbox-param-limit": "Inserisci <kbd>max</kbd> per utilizzare il limite massimo.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Tutti i namespace)",
+       "apisandbox-multivalue-all-values": "$1 (Tutti i valori)",
        "booksources": "Fonti librarie",
        "booksources-search-legend": "Ricerca di fonti librarie",
        "booksources-isbn": "Codice ISBN:",
        "activeusers-count": "$1 {{PLURAL:$1|azione|azioni}} {{PLURAL:$3|nell'ultimo giorno|negli ultimi $3 giorni}}",
        "activeusers-from": "Mostra gli utenti a partire da:",
        "activeusers-groups": "Visualizza gli utenti appartenenti ai gruppi:",
+       "activeusers-excludegroups": "Escludi gli utenti appartenenti ai gruppi:",
        "activeusers-noresult": "Nessun utente risponde ai criteri impostati.",
        "activeusers-submit": "Mostra utenti attivi",
        "listgrouprights": "Diritti del gruppo utente",
        "emailccsubject": "Copia del messaggio inviato a $1: $2",
        "emailsent": "Messaggio inviato",
        "emailsenttext": "Il messaggio e-mail è stato inviato.",
-       "emailuserfooter": "Questa email è stata {{GENDER:$1|inviata}} da $1 a {{GENDER:$2|$2}} attraverso la funzione \"{{int:emailuser}}\" su {{SITENAME}}.",
+       "emailuserfooter": "Questa email è stata {{GENDER:$1|inviata}} da $1 a {{GENDER:$2|$2}} attraverso la funzione \"{{int:emailuser}}\" su {{SITENAME}}. La {{GENDER:$2|tua}} eventuale email di risposta sarà inviata direttamente al {{GENDER:$1|mittente originale}}, rivelando il  {{GENDER:$2|tuo}} indirizzo di posta elettronica a {{GENDER:$1|lui|lei}}.",
        "usermessage-summary": "Messaggio di sistema",
        "usermessage-editor": "Messaggero di sistema",
        "usermessage-template": "MediaWiki:MessaggioUtente",
        "tags-deactivate": "disattiva",
        "tags-hitcount": "$1 {{PLURAL:$1|modifica|modifiche}}",
        "tags-manage-no-permission": "Non si dispone dei permessi necessari per gestire le etichette di modifica.",
-       "tags-manage-blocked": "Non puoi gestire le etichette alle modifiche mentre sei bloccato.",
+       "tags-manage-blocked": "Non puoi gestire le etichette alle modifiche mentre sei {{GENDER:$1|bloccato|bloccata}}.",
        "tags-create-heading": "Crea un nuovo tag",
        "tags-create-explanation": "Per impostazione predefinita, i tag appena creati saranno disponibili per l'utilizzo di utenti e bot.",
        "tags-create-tag-name": "Nome del tag:",
        "tags-deactivate-not-allowed": "Non è possibile disattivare il tag \"$1\".",
        "tags-deactivate-submit": "Disattiva",
        "tags-apply-no-permission": "Non disponi dell'autorizzazione per applicare la modifica di tag insieme con le tue modifiche.",
-       "tags-apply-blocked": "Non puoi applicare le etichette alle modifiche mentre sei bloccato.",
+       "tags-apply-blocked": "Non puoi applicare le etichette alle modifiche mentre sei {{GENDER:$1|bloccato|bloccata}}.",
        "tags-apply-not-allowed-one": "L'etichetta \"$1\" non può essere applicata manualmente.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|La seguente etichetta non può essere applicata|Le seguenti etichette non possono essere applicate}}  manualmente: $1",
        "tags-update-no-permission": "Non si dispone dei permessi necessari per aggiungere o rimuovere le etichette di modifica dalle singole versioni o voci di registro.",
-       "tags-update-blocked": "Non puoi aggiungere o rimuovere le etichette alle modifiche mentre sei bloccato.",
+       "tags-update-blocked": "Non puoi aggiungere o rimuovere le etichette alle modifiche mentre sei {{GENDER:$1|bloccato|bloccata}}.",
        "tags-update-add-not-allowed-one": "Il tag \"$1\" non può essere aggiunto manualmente.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Il seguente tag non può essere aggiunto|I seguenti tag non possono essere aggiunti}} manualmente: $1",
        "tags-update-remove-not-allowed-one": "Il tag \"$1\" non può essere rimosso.",
        "mw-widgets-dateinput-no-date": "Nessuna data selezionata",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-GG",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Ricerca file multimediali",
+       "mw-widgets-mediasearch-noresults": "Nessun risultato trovato.",
        "mw-widgets-titleinput-description-new-page": "questa pagina non esiste ancora",
        "mw-widgets-titleinput-description-redirect": "reindirizzamento a $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Aggiungi una categoria...",
        "sessionmanager-tie": "Non è possibile combinare più tipi di richieste di autenticazione: $1.",
        "sessionprovider-generic": "sessioni $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessioni basate su cookie",
        "usercssispublic": "Ricorda: le sottopagine CSS non devono contenere dati riservati poichè sono visualizzabili da altri utenti.",
        "restrictionsfield-badip": "Indirizzo IP o intervallo non valido: $1",
        "restrictionsfield-label": "Intervalli IP consentiti:",
-       "restrictionsfield-help": "Un indirizzo IP o intervallo CIDR per linea. Per consentire tutto, utilizza<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Errore: $1",
-       "edit-error-long": "Errori:\n\n$1"
+       "restrictionsfield-help": "Un indirizzo IP o intervallo CIDR per linea. Per consentire tutto, utilizza<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 27fe191..d07c6a6 100644 (file)
                        "Waiesu",
                        "Matma Rex",
                        "組曲師",
-                       "Foresttttttt"
+                       "Foresttttttt",
+                       "ネイ",
+                       "Mirinano",
+                       "Suchichi02"
                ]
        },
        "tog-underline": "リンクの下線:",
        "botpasswords-label-delete": "削除",
        "botpasswords-label-resetpassword": "パスワードをリセット",
        "botpasswords-label-grants": "該当する権限群",
-       "botpasswords-help-grants": "各権限群は、一覧にある利用者権限で現在の利用者アカウントが既に有している権限を付与します。詳細については、[[Special:ListGrants|権限群の表]]をご覧ください。",
+       "botpasswords-help-grants": "権限群は、現在の利用者アカウントが既に有している権限を付与します。ここで権限群を付与しても、あなたの利用者アカウントが有していない権限を付与しません。詳しくは[[Special:ListGrants|権限群の表]]をご覧ください。",
        "botpasswords-label-grants-column": "付与",
        "botpasswords-bad-appid": "ボット「$1」は有効ではありません。",
        "botpasswords-insert-failed": "ボット「$1」の追加に失敗しました。既に追加されていないか確認してください。",
        "botpasswords-updated-body": "利用者「$2」のボット名「$1」のためのパスワードが更新されました。",
        "botpasswords-deleted-title": "ボット用パスワードが削除されました",
        "botpasswords-deleted-body": "利用者「$2」のボット名「$1」のためのパスワードが削除されました。",
-       "botpasswords-newpassword": "<strong>$1</strong> 用の新しいパスワードは <strong>$2</strong> です。 <em>後で参照するために、この情報を控えておいてください</em>",
+       "botpasswords-newpassword": "<strong>$1</strong>用の新しいパスワードは<strong>$2</strong>です。<em>後で参照するために、この情報を控えておいてください。</em><br />(古いボットの制約などでログイン名と利用者名が同じでなければならない場合は、<strong>$3</strong>を利用者名とし、<strong>$4</strong>をパスワードとしてください。)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider が有効ではありません。",
        "botpasswords-invalid-name": "指定された利用者名には、ボット用パスワードの区切りである「$1」 が含まれていません。",
        "botpasswords-not-exist": "利用者「$1」はボット「$2」のパスワードを所持していません。",
        "passwordreset-emaildisabled": "メール機能は、このウィキでは無効化されています。",
        "passwordreset-username": "利用者名:",
        "passwordreset-domain": "ドメイン:",
-       "passwordreset-capture": "お送りするメールの内容を表示しますか?",
-       "passwordreset-capture-help": "このボックスにチェックを入れると、利用者に送信されるメールの内容 (仮パスワードを含む) をあなたも閲覧できます。",
        "passwordreset-email": "メールアドレス:",
        "passwordreset-emailtitle": "{{SITENAME}}上のアカウントの詳細",
        "passwordreset-emailtext-ip": "誰か (おそらくあなた、IP アドレス $1) が {{SITENAME}} ($4)\nでのパスワードを再設定するよう申請しました。\n以下の利用者{{PLURAL:$3|アカウント|アカウント群}}がこのメールアドレスと紐付けられています。\n\n$2\n\n{{PLURAL:$3|この仮パスワード|これらの仮パスワード}}は {{PLURAL:$5|$5 日|$5 日間}}で有効期限が切れます。\nあなたはすぐにログインして新しいパスワードを設定する必要があります。\nこれが他の誰かによる申請である場合、あるいはあなたが自分の元のパスワードを\n覚えていてそれを変更したくない場合には、このメッセージを無視して以前のパスワードを\n使用し続けることができます。",
        "passwordreset-emailelement": "利用者名: \n$1\n\n仮パスワード: \n$2",
        "passwordreset-emailsentemail": "このメールアドレスがあなたのアカウントに関連付けられている場合は、パスワードリセットのメールが送信されます。",
        "passwordreset-emailsentusername": "この利用者名に関連付けられたメールアドレスがある場合は、パスワードリセットのメールが送信されます。",
-       "passwordreset-emailsent-capture2": "パスワードリセットの{{PLURAL:$1|メール}}が送信されました。{{PLURAL:$1|利用者名とパスワード|利用者名とパスワードの一覧}}は以下のとおりです。",
-       "passwordreset-emailerror-capture2": "{{GENDER:$2|利用者}}へのメール送信に失敗しました: $1{{PLURAL:$3|利用者名とパスワード|利用者名とパスワードの一覧}}は以下のとおりです。",
        "passwordreset-ignored": "パスワードのリセットが処理されませんでした。プロバイダーが設定されていない可能性があります。",
-       "passwordreset-invalideamil": "無効なメールアドレスです",
+       "passwordreset-invalidemail": "無効なメールアドレスです",
        "changeemail": "メールアドレスの変更または除去",
        "changeemail-header": "あなたのメールアドレスを変更するには、このフォームを完成させます。もし、あなたのアカウントから任意のメールアドレスの関連付けを削除したい場合は、フォームの送信時に、新しいメールアドレスを空白のままにします。",
        "changeemail-no-info": "このページに直接アクセスするためにはログインしている必要があります。",
        "contentmodelediterror": "コンテンツモデルが <code>$1</code> であるため、この版を編集することができません。ページの現在のコンテンツモデルは <code>$2</code> です。",
        "recreate-moveddeleted-warn": "<strong>警告: 以前削除されたページを再作成しようとしています。</strong>\n\nこのページの編集を続行するのが適切かどうかご確認ください。\n参考までに、このページの削除と移動の記録を以下に示します:",
        "moveddeleted-notice": "このページは削除されています。\n参考のため、このページの削除と移動の記録を以下に表示します。",
-       "moveddeleted-notice-recent": "ごめんなさい、このページは最近に削除されました (過去24時間以内)。このページについての削除と移動の記録が、参考のため、以下にて提供されています。",
+       "moveddeleted-notice-recent": "申し訳ありません。このページは最近(24時間以内)に削除されました。参考のため、このページの削除と移動の記録を以下に表示します。",
        "log-fulllog": "完全な記録を閲覧",
        "edit-hook-aborted": "フックによって編集が破棄されました。\n理由は不明です。",
        "edit-gone-missing": "ページを更新できませんでした。\n既に削除されているようです。",
        "prefs-help-recentchangescount": "この設定は最近の更新、ページの履歴、および記録に適用されます。",
        "prefs-help-watchlist-token2": "これはあなたのウォッチリスト フィードの秘密のコードです。\nこのトークンを知っている人は誰でもあなたのウォッチリストを読めてしまうため、他の人に教えないでください。\n[[Special:ResetTokens|トークンを再設定する必要がある場合はここをクリックしてください]]。",
        "savedprefs": "個人設定を保存しました。",
-       "savedrights": "{{GENDER:$1|$1}}の利用者権限が保存されました。",
+       "savedrights": "{{GENDER:$1|$1}}の利用者グループが保存されました。",
        "timezonelegend": "タイムゾーン:",
        "localtime": "地域の時刻:",
        "timezoneuseserverdefault": "ウィキの既定を使用 ($1)",
        "prefswarning-warning": "個人設定にまだ保存されていない変更があります。\n「$1」をクリックせずに離れた場合、個人設定は更新されません。",
        "prefs-tabs-navigation-hint": "ヒント: ← キーと → キーで、タブ一覧内のタブ間を移動できます。",
        "userrights": "利用者権限を管理",
-       "userrights-lookup-user": "å\88©ç\94¨è\80\85ã\82°ã\83«ã\83¼ã\83\97ã\82\92管ç\90\86",
+       "userrights-lookup-user": "å\88©ç\94¨è\80\85ã\82\92é\81¸æ\8a\9e",
        "userrights-user-editname": "利用者名を入力:",
-       "editusergroup": "{{GENDER:$1|利用者}}グループを編集",
+       "editusergroup": "利用者グループをロード",
        "editinguser": "利用者<strong> [[User:$1|$1]]</strong> $2 の権限を変更",
        "userrights-editusergroup": "利用者グループを編集",
        "saveusergroups": "{{GENDER:$1|利用者}}グループを保存",
        "userrights-reason": "理由:",
        "userrights-no-interwiki": "他ウィキ上における利用者権限の編集権限は、ありません。",
        "userrights-nodatabase": "データベース$1は存在しないか、ローカル上にありません。",
-       "userrights-nologin": "利用者権限を付与するには、管理者アカウントで[[Special:UserLogin|ログイン]]する必要があります。",
-       "userrights-notallowed": "あなたには利用者権限を追加/除去する権限がありません。",
        "userrights-changeable-col": "変更できるグループ",
        "userrights-unchangeable-col": "変更できないグループ",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "利用者権限の変更が競合しています! 変更内容を確認してください。",
-       "userrights-removed-self": "あなた自身の権限を除去しました。そのため、このページにはもうアクセスできません。",
        "group": "グループ:",
        "group-user": "登録利用者",
        "group-autoconfirmed": "自動承認された利用者",
        "right-siteadmin": "データベースをロックおよびロック解除",
        "right-override-export-depth": "リンク先ページを5階層まで含めて書き出す",
        "right-sendemail": "他の利用者にメールを送信",
-       "right-passwordreset": "パスワード再設定メールを閲覧",
        "right-managechangetags": "[[Special:Tags|タグ]]の作成、有効化および無効化",
        "right-applychangetags": "自分の編集に[[Special:Tags|タグ]]を適用する",
        "right-changetags": "個々の版と記録項目の任意の[[Special:Tags|タグ]]の追加と削除",
        "right-deletechangetags": "データベースから[[Special:Tags|タグ]]を削除します",
        "grant-group-email": "メールの送信",
        "grant-group-customization": "カスタマイズと個人設定",
-       "grant-group-private-information": "君の個人情報にアクセスする。",
+       "grant-group-private-information": "あなたの個人情報にアクセスする",
        "grant-group-other": "その他の活動",
        "grant-blockusers": "利用者をブロックおよびブロック解除",
        "grant-createaccount": "アカウントを作成",
        "action-upload_by_url": "URL からのこのファイルのアップロード",
        "action-writeapi": "書き込みAPIの使用",
        "action-delete": "このページの削除",
-       "action-deleterevision": "この版の削除",
-       "action-deletedhistory": "このページの削除履歴の閲覧",
+       "action-deleterevision": "版の削除",
+       "action-deletelogentry": "記録項目の削除",
+       "action-deletedhistory": "ページの削除履歴の閲覧",
        "action-browsearchive": "削除されたページの検索",
-       "action-undelete": "ã\81\93ã\81®ã\83\9aã\83¼ã\82¸ã\81®å¾©å\85\83",
+       "action-undelete": "ページの復元",
        "action-suppressrevision": "隠された版の確認と復元",
        "action-suppressionlog": "非公開記録の閲覧",
        "action-block": "この利用者の編集ブロック",
        "patrol-log-header": "以下は巡回された版の記録です。",
        "log-show-hide-patrol": "巡回記録を$1",
        "log-show-hide-tag": "タグ記録を$1",
+       "confirm-markpatrolled-button": "OK",
+       "confirm-markpatrolled-top": "ページ$2の$3の版を巡回済みにマークしますか?",
        "deletedrevision": "古い版 $1 を削除しました",
        "filedeleteerror-short": "ファイルの削除エラー: $1",
        "filedeleteerror-long": "ファイルの削除中にエラーが発生しました:\n\n$1",
        "exif-compression-6": "JPEG (旧式)",
        "exif-copyrighted-true": "著作権あり",
        "exif-copyrighted-false": "著作権情報未設定",
-       "exif-photometricinterpretation-0": "黒と白 (白が0)",
+       "exif-photometricinterpretation-0": "黒と白(白が0です)",
        "exif-photometricinterpretation-1": "黒と白(黒が0)",
        "exif-photometricinterpretation-9": "CIE L*a*b* (ICC エンコード)",
        "exif-photometricinterpretation-10": "CIE L*a*b* (ITU エンコード)",
        "tags-deactivate": "無効化",
        "tags-hitcount": "$1 {{PLURAL:$1|回の変更}}",
        "tags-manage-no-permission": "変更タグを管理する権限がありません。",
-       "tags-manage-blocked": "ブロックされているため、変更タグを管理できません",
+       "tags-manage-blocked": "{{GENDER:$1|あなた}}はブロックされているため、変更タグを管理できません。",
        "tags-create-heading": "新しいタグを作成",
        "tags-create-explanation": "既定では、新しく作られたタグは利用者とボットによる使用が可能となります。",
        "tags-create-tag-name": "タグ名:",
        "tags-deactivate-not-allowed": "タグ「$1」は無効化できません。",
        "tags-deactivate-submit": "無効化",
        "tags-apply-no-permission": "あなたには変更と同時に変更タグを適応する権限がありません。",
-       "tags-apply-blocked": "ブロックされているため、変更タグの変更を適用できません。",
+       "tags-apply-blocked": "{{GENDER:$1|あなた}}はブロックされているため、変更タグを適用できません。",
        "tags-apply-not-allowed-one": "タグ \"$1\" の手動適用は認められていません。",
        "tags-apply-not-allowed-multi": "以下の {{PLURAL:$2|タグ}} は手動適用が認められていません: $1",
        "tags-update-no-permission": "あなたには個々の版または記録項目のタグの追加または除去を行う権限がありません。",
-       "tags-update-blocked": "ブロックされているため、変更タグを追加または除去できません。",
+       "tags-update-blocked": "{{GENDER:$1|あなた}}はブロックされているため、変更タグの追加と除去ができません。",
        "tags-update-add-not-allowed-one": "タグ \"$1\" の手動追加は認められていません。",
        "tags-update-add-not-allowed-multi": "以下の {{PLURAL:$2|タグ}} は手動追加が認められていません: $1",
        "tags-update-remove-not-allowed-one": "タグ \"$1\" の除去は認められていません。",
        "htmlform-date-placeholder": "YYYY-MM-DD",
        "htmlform-time-placeholder": "HH:MM:SS",
        "htmlform-datetime-placeholder": "YYYY-MM-DD HH:MM:SS",
-       "htmlform-date-invalid": "君が入力した値は識別できない日付です。YYYY-MM-DD形式で試してください。",
+       "htmlform-date-invalid": "あなたが入力した日付を識別できませんでした。YYYY-MM-DD形式で試してください。",
        "htmlform-title-badnamespace": "[[:$1]]は、\"{{ns:$2}}\"名前空間にありません。",
        "htmlform-title-not-creatable": "\"$1\" は、作成可能なページ名では、ありません。",
        "htmlform-title-not-exists": "$1 は存在しません。",
        "htmlform-user-not-exists": "<strong>$1</strong>は存在しません。",
        "htmlform-user-not-valid": "<strong>$1</strong>は有効な利用者名ではありません。",
        "logentry-delete-delete": "$1 がページ「$3」を{{GENDER:$2|削除しました}}",
+       "logentry-delete-delete_redir": "$1 がリダイレクト「$3」を上書きで{{GENDER:$2|削除しました}}",
        "logentry-delete-restore": "$1 がページ「$3」を{{GENDER:$2|復元しました}}",
        "logentry-delete-event": "$1 が $3 の{{PLURAL:$5|記録項目|記録項目$5件}}の閲覧レベルを{{GENDER:$2|変更しました}}: $4",
        "logentry-delete-revision": "$1 がページ「$3」の{{PLURAL:$5|版|$5件の版}}の閲覧レベルを{{GENDER:$2|変更しました}}: $4",
        "special-characters-title-emdash": "em ダッシュ",
        "special-characters-title-minus": "マイナス記号",
        "mw-widgets-dateinput-no-date": "選択されたデータ無し",
+       "mw-widgets-mediasearch-noresults": "見つかりませんでした。",
        "mw-widgets-titleinput-description-new-page": "ページは存在しません",
        "mw-widgets-titleinput-description-redirect": "$1 へのリダイレクト",
+       "mw-widgets-categoryselector-add-category-placeholder": "カテゴリを追加...",
        "sessionmanager-tie": "複数の要求の認証方法を組み合わせることはできません: $1。",
        "sessionprovider-generic": "$1 セッション",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "クッキーベースのセッション",
        "authmanager-authn-autocreate-failed": "ローカルアカウントの自動作成が失敗しました: $1",
        "authmanager-change-not-supported": "一切利用されないであろう情報のため、指定された証明情報を変更することはできません。",
        "authmanager-create-disabled": "アカウントの作成は禁止されています。",
-       "authmanager-create-from-login": "アカウントを作成するには、以下の入力欄に記入してください。",
+       "authmanager-create-from-login": "アカウントを作成するには、入力欄に記入してください。",
        "authmanager-create-not-in-progress": "アカウントの作成が行われていない、またはセッションデータが失われました。最初からやり直してください。",
        "authmanager-create-no-primary": "指定された証明情報は、アカウントの作成に使用できませんでした。",
        "authmanager-link-no-primary": "指定された証明情報は、アカウントの関連付けに使用できませんでした。",
        "usercssispublic": "注意: CSS のサブページは第三者が閲覧可能なため、機微な情報を含めないでください。",
        "restrictionsfield-badip": "無効な IP アドレス、またはその範囲: $1",
        "restrictionsfield-label": "許可する IP の範囲:",
-       "restrictionsfield-help": "一行につき、単一の IP アドレス、もしくは CIDR による範囲。全帯域からの接続を許可する場合は<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "エラー: $1",
-       "edit-error-long": "エラー:\n\n\n\n$1"
+       "restrictionsfield-help": "一行につき、単一の IP アドレス、もしくは CIDR による範囲。全帯域からの接続を許可する場合は<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 38a261f..2b14bfc 100644 (file)
        "yourpasswordagain": "Ritaip paaswod:",
        "createacct-yourpasswordagain": "Kanfoerm paaswod",
        "createacct-yourpasswordagain-ph": "Enta paaswod agen",
-       "remembermypassword": "Memba mi lagiin pan dis brouza (fi a maximom a $1 {{PLURAL:$1|die|die}})",
        "userlogin-remembermypassword": "Kip mi lagiin‎",
        "yourdomainname": "Yu domien:",
        "externaldberror": "Aida aatentikieshan dietabies era okor ar yu no lou fi opdiet yu extoernal akount.",
        "permissionserrorstext-withaction": "Yu no ab no poermishan fi $2, fi di falarin {{PLURAL:$1|riizn|riizndem}}:",
        "moveddeleted-notice": "Dis piej eh diliit.\nDi diliishan ah muuv lag fi di piej provaid biluo fi refrans.‎",
        "edit-conflict": "Hedit kanflik: $1",
-       "cantcreateaccounttitle": "Cyannat mek di hakkount",
        "viewpagelogs": "Vyuu lagdem fi dis piej",
        "currentrev-asof": "Lietis rivijan az av $1",
        "revisionasof": "Rivijan az av $1",
index 57d4099..48cf4aa 100644 (file)
        "yourpasswordagain": "Djentast adgångskode:",
        "createacct-yourpasswordagain": "Bekräft adgångskode",
        "createacct-yourpasswordagain-ph": "Intast adgångskode idjen",
-       "remembermypassword": "Husk min brugenaun i denn browser (hyest $1 {{PLURAL:$1|daw}})",
        "userlogin-remembermypassword": "Husk mej",
        "userlogin-signwithsecure": "Brug siker forbinjels",
        "yourdomainname": "Det domænnaun:",
index f4e4631..25c1aab 100644 (file)
        "passwordreset-emaildisabled": "Fitur layang elektronik wis dipateni ing wiki iki.",
        "passwordreset-username": "Jeneng panganggo:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "Delok layang èlèktronik sing diasilaké?",
-       "passwordreset-capture-help": "Yèn Sampéyan nyentang kothak iki, layang èlèktronik (mawa tembung sandhi sawetara) bakal ditampilaké nèng Sampéyan lan uga dikirim nèng panganggo.",
        "passwordreset-email": "Alamat layang èlèktronik:",
        "passwordreset-emailtitle": "Rincian akun nèng {{SITENAME}}",
        "passwordreset-emailtext-ip": "Ana uwong (mbok menawa Sampéyan, mawa angka IP $1) njaluk ganti tembung sandhiné Sampéyan ana ing {{SITENAME}} ($4). {{PLURAL:$3|Rèkèning|Rèkèning-rèkèning}} ngisor iki magepokan karo padunungané layang èlèktronik iki:\n\n$2\n\n{{PLURAL:$3|Tembung sandhi sawetara iki}} bakal kedaluwarsa ing {{PLURAL:$5|sak dina|$5 dina}}.\nSampéyan kudu mlebu log lan milih siji tembung sandhi anyar saiki. Yèn wong liya sing njaluk iki, utawa yèn Sampéyan jebul wis kèlingan tembung sandhiné sing lawas saéngga ora ana niyat kanggo ngganti, Sampéyan bisa ngejaraké wara-wara iki lan bacutaké nganggo tembung sandhiné lawas Sampéyan.",
        "preview": "Pratuduh",
        "showpreview": "Deleng pratuduh",
        "showdiff": "Tuduhaké owahan",
-       "anoneditwarning": "<strong>Penget:</strong> Panjenengan boten mlebet log. Alamat IP Panjenengan badhe katingal dening publik manawi Panjenengan ngayahi ewah-ewahan. Manawi Panjenengan  <strong>[$1 mlebet log]</strong> utawai <strong>[$2 damel akun]</strong>, suntingan Panjenengan badhe kaatribusekaken dhumateng  nama pangangge Panjenengan, lan rupi-rupi  kauntungan sanesipun.",
+       "anoneditwarning": "<strong>Pènget:</strong> Panjenengan durung mlebu log. Alamat IP-né panjenengan bakal katon marang wong akèh manawa panjenengan mbesut. Manawa panjenengan <strong>[$1 mlebu log]</strong> utawa <strong>[$2 nggawé akun]</strong>, besutané panjenengan bakal dadi darbéné naragunané panjenengan lan uga ana kauntungan liya.",
        "anonpreviewwarning": "''Sampéyan durung mlebu log. Nyimpen bakal nyathet alamat IP Sampéyan nèng riwayat sunting kaca iki.''",
        "missingsummary": "'''Pènget:''' Panjenengan ora nglebokaké ringkesan panyuntingan. Menawa panjenengan mencèt tombol Simpen manèh, suntingan panjenengan bakal kasimpen tanpa ringkesan panyuntingan.",
        "selfredirect": "<strong>Pélik:</strong> Sampéyan ngalih kaca iki iya nyang kaca iki dhéwé.\nSampéyan mungkin salah wènèh tujuan kanggo alihan utawa salah mbesut kaca.\nYèn sampéyan ngeklik \"{{int:savearticle}}\" manèh, kaca alihan bakal digawé.",
        "showhideselectedversions": "Tampilaké/dhelikaké révisi kapilih",
        "editundo": "wurung",
        "diff-empty": "(Ora ana bedane)",
-       "diff-multi-sameuser": "({{PLURAL:$1|Saowahan madya|$1 owahan madya}} déning panganggo sing padha ora dituduhaké)",
+       "diff-multi-sameuser": "({{PLURAL:$1|$1 owahan antara}} déning naraguna sing padha ora katuduhaké)",
        "diff-multi-manyusers": "({{PLURAL:$1Siji rèvisi sedhengan|$1 rèvisi sedhengan}} déning luwih saka $2 {{PLURAL:$2|panganggo|panganggo}} ora dituduhaké)",
        "difference-missing-revision": "{{PLURAL:$2|Sak pambenahan|$2 pambenahan}} saka prabédan iki ($1) {{PLURAL:$2|ora ditemokaké|ora ditemokaké}}.\n\nIki biasané kasebab pranala prabedan sing wis ora kanggo saka kaca isi wis dibusak.\nRinciané bisa ditemokaké nèng [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log busak].",
        "searchresults": "Kasiling golèk",
        "userrights-reason": "Alesan:",
        "userrights-no-interwiki": "Panjenengan ora ana hak kanggo ngowahi hak panganggo ing wiki liyané.",
        "userrights-nodatabase": "Basis data $1 ora ana utawa ora lokal.",
-       "userrights-nologin": "Panjenengan kudu [[Special:UserLogin|mlebu log]] mawa nganggo akun utawa rékening pangurus supaya bisa ngowahi hak panganggo.",
-       "userrights-notallowed": "Sampéyan ora nduwé idin kanggo nambah utawa nyuda hak-hak panganggo.",
        "userrights-changeable-col": "Grup sing bisa panjenengan owahi",
        "userrights-unchangeable-col": "Grup sing ora bisa diowahi panjenengan",
        "userrights-conflict": "Konflik pangowahan hak-hak panganggo! Tulung ditinjau maneh lan konfirmasi Pangowahan sampeyan.",
-       "userrights-removed-self": "Sampeyan wis berhasil ngilangake hak-hak sampeyan. Nuli, sampeyan ora isa ngakses kaca niki malih.",
        "group": "Golongan:",
        "group-user": "Para panganggo",
        "group-autoconfirmed": "Panganggo sing otomatis didhedhes (dikonfirmasi)",
        "right-siteadmin": "Kunci lan buka kunci basis data",
        "right-override-export-depth": "Èkspor kaca klebu kaca kagandhèng nganti tataran/''depth'' 5",
        "right-sendemail": "Ngirim layang listrik (e-mail) menyang panganggo liya",
-       "right-passwordreset": "Delok layang èlèktronik panyetèlulangan tembung sandhi",
        "grant-group-email": "Kirim layang élèktronik",
        "grant-createaccount": "Gawé akun",
        "grant-createeditmovepage": "Gawé, besut, lan lih kaca",
        "activeusers-intro": "Iki daptar panganggo sing katon lakuné ing $1 {{PLURAL:$1|dina|dina}} kapungkur.",
        "activeusers-count": "$1 {{PLURAL:$1|suntingan|suntingan}} ing {{PLURAL:$3|dina|$3 dina}} pungkasan",
        "activeusers-from": "Tampilna panganggo wiwit saka:",
-       "activeusers-hidebots": "Delikna bot",
-       "activeusers-hidesysops": "Delikna pangurus",
        "activeusers-noresult": "Naraguna ora ana.",
        "listgrouprights": "Hak-hak grup panganggo",
        "listgrouprights-summary": "Ing ngisor iki kapacak dhaftar grup panganggo sing didéfinisi ing wiki iki, kanthi hak-hak aksès gandhèngané.\nInformasi tambahan perkara hak-hak individual bisa ditemokaké ing [[{{MediaWiki:Listgrouprights-helppage}}|kéné]].",
        "movepage-moved": "<strong>\"$1\" wis dilih nyang \"$2\"</strong>",
        "movepage-moved-redirect": "Kaca pengalihan wis kacipta.",
        "movepage-moved-noredirect": "Kanggo gawé pengalihan wis ditahan.",
-       "articleexists": "Satunggalipun kaca kanthi asma punika sampun wonten, utawi asma ingkang panjenengan pendhet mboten leres. Sumangga nyobi asma sanèsipun.",
+       "articleexists": "Kaca mawa jeneng mangkono wis ana utawa jeneng sing kokpilih ora valid.\nMangga pilih jeneng liya.",
        "cantmove-titleprotected": "Panjenengan ora bisa mindhahaké kaca iki menyang lokasi iki, amerga irah-irahan tujuan lagi direksa; ora olèh digawé",
        "movetalk": "Lih kaca parembugan sing magepokan",
        "move-subpages": "Lih anak kaca (tekan $1)",
index 38d9bdb..a2fd8c9 100644 (file)
        "passwordreset-nocaller": "გამომძახებელი უნდა იყოს მიწოდებული",
        "passwordreset-nosuchcaller": "გამომძახებელი არ არსებობს: $1",
        "passwordreset-ignored": "პაროლის გაუქმება არ იქნა შესრულებული. შეიძლება კონფიგურაციაში პროვაიდერი არ იყო გათვალისწინებული?",
-       "passwordreset-invalideamil": "ელ-ფოსტის არასწორი მისამართი",
+       "passwordreset-invalidemail": "ელ-ფოსტის არასწორი მისამართი",
        "passwordreset-nodata": "არც მომხმარებლის სახელი და არც ელ-ფოსტის მისამართი არ იყო მოწოდებული",
        "changeemail": "ელ-ფოსტის მისამართის შეცვლა ან წაშლა",
        "changeemail-header": "შეავსეთ ეს ფორმა მეილის შესაცვლელად. თუ გსურთ თქვენი ანგარიში არ იყოს დაკავშირებული არცერთ მეილთან, ახალი მეილის მისამართის ველი დატოვეთ ცარიელი.",
        "activeusers-intro": "ეს არის მომხმარებელთა სია, რომელთაც აქვს წვლილი უკანასკნელი $1 {{PLURAL:$1|დღის|დღის}} განმავლობაში.",
        "activeusers-count": "$1 {{PLURAL:$1|მოქმედება|მოქმედება}} {{PLURAL:$3|დღის|$3 დღის}} განმავლობაში.",
        "activeusers-from": "მომხმარებელთა ჩვენება, დაწყებული:",
-       "activeusers-hidebots": "რობოტების დამალვა",
-       "activeusers-hidesysops": "ადმინისტრატორების დამალვა",
        "activeusers-noresult": "მომხმარებლები არ არიან ნაპოვნი.",
        "activeusers-submit": "აქტიური მომხმარებლების ჩვენება",
        "listgrouprights": "მომხმარებელთა ჯგუფების უფლებები",
index 0dba198..3397906 100644 (file)
        "yourname": "Paydalanıwshı atı:",
        "yourpassword": "Parol:",
        "yourpasswordagain": "Paroldi qayta kiritin':",
-       "remembermypassword": "Menin' kirgenimdi usı kompyuterde saqlap qal (en' ko'bi menen $1 {{PLURAL:$1|ku'nge|ku'nge}} shekem)",
        "yourdomainname": "Sizin' domen:",
        "login": "Kiriw",
        "nav-login-createaccount": "Kiriw / akkaunt jaratıw",
        "moveddeleted-notice": "Bul bet o'shirilgen.\nTo'mende mag'lıwmat ushın bettin' o'shiriw ha'm ko'shiriw jurnalı ko'rsetilgen.",
        "edit-conflict": "O'zgerislerdegi konflikt.",
        "parser-template-loop-warning": "Shablonlarda qaytalanıw tabıldı: [[$1]]",
-       "cantcreateaccounttitle": "Akkaunt jaratılmadı",
        "cantcreateaccount-text": "[[User:$3|$3]] usı IP adresten ('''$1''') akkaunt jaratıwın blokladı.\n\n$3 keltirilgen sebebi: ''$2''",
        "viewpagelogs": "Usı bettin' jurnalın ko'riw",
        "nohistory": "Bul bettin' o'zgertiw tariyxı joq.",
index cd5ff53..3faa3a8 100644 (file)
        "yourpasswordagain": "Ɛiwed ssekcem awal n tbaḍnit",
        "createacct-yourpasswordagain": "Sergeg awal n uɛeddi",
        "createacct-yourpasswordagain-ph": "Sekcem awal n uɛeddi tikelt nniḍen",
-       "remembermypassword": "Cfu ɣef wawal n tbaḍnit inu di uselkim-agi (i afellay n $1 {{PLURAL:$1|ass|ussan}})",
        "userlogin-remembermypassword": "Eǧǧ taɣimit inu turmidt",
        "userlogin-signwithsecure": "Seqdec tuqqna yettwaḥerzen",
        "yourdomainname": "Taɣult inek",
        "passwordreset-emailtext-user": "Aseqdac $1 ɣef {{SITENAME}} yessutered awennez n awal n uɛaddi i {{SITENAME}} ($4). {{PLURAL:$3|Amiḍan n useqdac agi yeqqen|imiḍanen n iseqdacen agi qqenen}} s tansa e-mail agi :\n\n$2\n\n{{PLURAL:$3|Awal n uɛaddi uɛḍil agi ad i aff tasewti-s|Awalen n uɛaddi uɛḍilen agi ad affen taseweti nsen}} deg {{PLURAL:$5|yiwen ass|$5 ussan}}. Ilaq tura ad qqeneḍ dɣa ad freneḍ awal n uɛaddi amaynut. Lukan mačči d kečč/kem i xedmen asuter agi, naɣ tecfiḍ tura i awal n uɛaddi inek/inem, tzemreḍ ad eǧǧeḍ izen agi.",
        "passwordreset-emailelement": "Isem n useqdac : \n$1\n\nAwal n uɛddi akudan : \n$2",
        "passwordreset-emailsentemail": "Tirawt n uwennez n awal n uɛaddi tetwaceggaɛ.",
-       "passwordreset-emailsent-capture": "Tirawt n uwennez n awal n uɛaddi tetwaceggaɛ, ẓeṛ-itt ddaw agi.",
-       "passwordreset-emailerror-capture": "Tirawt n uwennez n awal n uɛaddi t-arewed, ẓeṛ-itt ddaw agi, lamaɛna aceggaɛ i {{GENDER:$2|umseqdac}} yefkad anezri : $1",
        "changeemail": "Beddel tansa n e-mail",
        "changeemail-header": "Beddel tansa n e-mail n umiḍan",
        "changeemail-no-info": "Ilaq ad qqeneḍ iwakken ad ẓṛeḍ asebter agi.",
        "undo-norev": "Abeddel ur yezmer ara ad yetwekkes acku ulac-itt naɣ tetwekkes yakan",
        "undo-summary": "Ssefsu tasiwelt $1 sɣur [[Special:Contributions/$2|$2]] ([[User talk:$2|Meslay]])",
        "undo-summary-username-hidden": "Semmewet tacaggart $1 sɣur amseqdac yeffren",
-       "cantcreateaccounttitle": "Ur yezmir ara ad yexleq isem n wemseqdac",
        "cantcreateaccount-text": "Asnulfu n umiḍan seg tansa IP (<b>$1</b>) tekyef sɣur [[User:$3|$3]].\n\nTaɣẓint n $3 : ''$2''",
        "cantcreateaccount-range-text": "Asnulfu n umiḍan seg tansiwin IP deg tagrumma <strong>$1</strong>, i sseddan tansa inek/inem IP (<strong>$4</strong>), twawḥelen sɣur [[User:$3|$3]].\n\nTaɣẓint i-d yefka/tefka $3 : <em>$2</em>",
        "viewpagelogs": "Ẓer aɣmis n usebter-agi",
        "activeusers-intro": "Wagi d umuɣ n iseqdacen yexedmen armud deg {{PLURAL:$1|ass agi aneggaru|$1 ussan agi ineggura}}.",
        "activeusers-count": "$1 {{PLURAL:$1|tigawt|tigawin}} deg {{PLURAL:$3|ass aneggaru|$3 ussan ineggura}}",
        "activeusers-from": "Ssken iseqdacen seg :",
-       "activeusers-hidebots": "Ffer iṛubuten",
-       "activeusers-hidesysops": "Ffer inedbalen",
        "activeusers-noresult": "Ur yufi aseqdac.",
        "listgrouprights": "Izerfan n igrawen n iseqdacen",
        "listgrouprights-summary": "Asebter agi yesɛa yiwen umuɣ n igrawen i sengelen deg wiki agi dɣa izerfan n wadduf i qqenen.\nZemrent ad ilint [[{{MediaWiki:Listgrouprights-helppage}}|tilɣa nniḍen]] ɣef izerfan n yiwen.",
        "htmlform-no": "Ala",
        "htmlform-yes": "Ih",
        "htmlform-chosen-placeholder": "Fren taxtiṛit",
-       "sqlite-has-fts": "$1 s anadi deg uḍris ummid yezmer",
-       "sqlite-no-fts": "$1 war anadi deg uḍris ummid yezmer",
        "logentry-delete-delete": "$1 {{GENDER:$2|yemḥa}} asebtar $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|yerred|terred}} asebtar $3",
        "logentry-delete-event": "$1 {{GENDER:$2|yebeddel|tebeddel}} tabanit {{PLURAL:$5|n tadyant n uɣmis|n $5 tidyanin n uɣmis}} ɣef $3: $4",
index ffff096..9dd1e0d 100644 (file)
        "yourname": "Уи цӀэр:",
        "yourpassword": "Пэролыр:",
        "yourpasswordagain": "Иджыри зэ пэролыр:",
-       "remembermypassword": "Сызэрихьэр компьютерым щыIыгъын (махуэу $1 {{PLURAL:$1|щIимыгъуу|щIимыгъуу}})",
        "yourdomainname": "Уи доменыр:",
        "externaldberror": "Щэуэгъуэ хъуа, аутентификациэ щекӀуэкӀым иэ апхуэдиз пӀалъэ уиӀу щыткъым, уи нэкугъуэ аккаунтыр зэпхъуэкӀын.",
        "login": "Системэм зыкъегъэцIыхуын",
        "undo-failure": "Гъэтэрэзыгъуэр хэхыжа хъунукъым, гъэтэрэзыгъуэхэм я зэпхыгъуэр зэремыкӀуэкӀыфым щхьэкӀэ",
        "undo-norev": "Гъэтэрэзыгъуэр хэхыжа хъунукъым зэрщымыӀэм щхьэкӀэ иэ хэхыжагъыху щытщ.",
        "undo-summary": "Гъэтэрэзыгъуэ хэхыжыныр $1 цӀыхухэт [[Special:Contributions/$2|$2]] ([[User talk:$2|тепсэлъыхьыгъуэ]])",
-       "cantcreateaccounttitle": "Аккаунтыр щӀыфынукъым",
        "cantcreateaccount-text": "Аккаунт щӀыныр мы IP-адресыкӀэ (<b>$1</b>) триубыдауэ щытщ [[User:$3|цӀыхухэт $3]].\n\n$3 ар зтеухуауэ къитхыр: ''$2''",
        "viewpagelogs": "Мы напэкӀуэцIым щхьэкӀэ тхылъыр гъэлъэгъуэн",
        "nohistory": "Мы напэкӀуэцӀым и зэхъуэкӀыгъуэхэм я тхыдэ иӀэкъым.",
index b01984c..5ff8194 100644 (file)
        "yourpasswordagain": "کلمۂ شناخت(پاسورڈو)دوبارہ نیویشے",
        "createacct-yourpasswordagain": "کلمۂ اجازتو تصدیق کورے",
        "createacct-yourpasswordagain-ph": "پاس ورڈو وا داخل کورے",
-       "remembermypassword": "ھیہ براوزیرا مہ داخلِ نوشتگی معلوماتن یاد لاکھے (زیاتاری زیات $1 {{PLURAL:$1|بس|بسان}} بچے)",
        "userlogin-remembermypassword": "مہ داخل بہچاوے",
        "yourdomainname": "تہ ڈومین",
        "password-change-forbidden": "تتے ھیہ ویکیپیڈیا تان پاس روڈو تبدیل کوریکو اختیار نیکی",
        "searchprofile-advanced-tooltip": "کسٹم نیم اسپیسا تلاش کورے",
        "search-result-size": "$1 ({{PLURAL:$2|1 لوظ|$2 الفاظ}})",
        "search-result-category-size": "{{PLURAL:$1|1 رُکن|$1 اراکین}} ({{PLURAL:$2|1 ذیلی زمرہ|$2 ذیلی زمرہ جات}}, {{PLURAL:$3|1 ملف|$3 ملفات}})",
-       "search-redirect": "(رجوع مکرر $1)",
+       "search-redirect": "(Redirect $1)",
        "search-section": "(حصہ $1)",
        "search-suggest": "تہ مطلب ھیہ تھے نو اوشوئے؟: $1",
        "search-interwiki-caption": "ملگیری منصوبہ",
        "listusers-noresult": "ھیہ صارف ملاو نو ہوئے",
        "activeusers": "متحرک صارفینان فہرست",
        "activeusers-from": "مطلوبہ حرفاری شروع باک صفحاتن نمائش:",
-       "activeusers-hidebots": "کھوشت خود کار صارف",
-       "activeusers-hidesysops": "کھوشت منتظمان",
        "activeusers-noresult": "ھیہ صارف ملاو نو ہوئے",
        "listgrouprights-group": "گروہ",
        "listgrouprights-rights": "اختیارات",
        "whatlinkshere-prev": "{{PLURAL:$1|سابقہ|سابقہ $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|پروشٹیو|پروشٹیو$1}}",
        "whatlinkshere-links": "← لنکس",
-       "whatlinkshere-hideredirs": "$1 رجوع مکرر",
+       "whatlinkshere-hideredirs": "$1 Redirects",
        "whatlinkshere-hidetrans": "ٹرانسکلوژن $1",
        "whatlinkshere-hidelinks": "$1 لنکس",
        "whatlinkshere-hideimages": "ھوٹوان لنک $1",
index b2a514f..5f62837 100644 (file)
        "yourname": "قاتىسۋشى اتىڭىز:",
        "yourpassword": "قۇپىييا ٴسوزىڭىز:",
        "yourpasswordagain": "قۇپىييا ٴسوزدى قايتالاڭىز:",
-       "remembermypassword": "مەنىڭ كىرگەنىمدى بۇل كومپيۋتەردە ۇمىتپا (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "جەلى ۇيشىگىڭىز:",
        "externaldberror": "وسى ارادا نە شەتتىك راستاۋ دەرەكقورىندا قاتە بولدى, نەمەسە شەتتىك تىركەلگىڭىزدى جاڭالاۋ رۇقساتى جوق.",
        "login": "كىرۋ",
        "undo-failure": "بۇل وڭدەمە جوققا شىعارىلمايدى, سەبەبى ارادا قاقتىعىستى وڭدەمەلەر بار.",
        "undo-norev": "بۇل وڭدەمە جوققا شىعارىلمايدى, سەبەبى بۇل جوق نەمەسە جويىلعان.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User_talk:$2|تالقىلاۋى]]) ىستەگەن ٴنومىر $1 نۇسقاسىن جوققا شىعاردى",
-       "cantcreateaccounttitle": "جاڭا تىركەلگى جاسالمادى",
        "cantcreateaccount-text": "بۇل IP جايدان ('''$1''') جاڭا تىركەلگى جاساۋىن [[User:$3|$3]] بۇعاتتاعان.\n\n$3 كەلتىرىلگەن سەبەبى: ''$2''",
        "viewpagelogs": "بۇل بەت ٴۇشىن جۋرنال وقىيعالارىن قاراۋ",
        "nohistory": "مىندا بۇل بەتتىنىڭ تۇزەتۋ تارىيحى جوق.",
index 3a152ba..f7ad3d9 100644 (file)
@@ -23,7 +23,7 @@
        "tog-hideminor": "Жуықтағы өзгерістерден шағын өңдемелерді жасыру",
        "tog-hidepatrolled": "Тексерілген өңдеулерді жуықтағы өзгерістер тізімінде көрсетпеу",
        "tog-newpageshidepatrolled": "Тексерілген беттерді жаңа беттер тізімінде жасыру",
-       "tog-hidecategorization": "Беттерді санаттауларды жасыру",
+       "tog-hidecategorization": "Беттедің санатталуын жасыру",
        "tog-extendwatchlist": "Бақылау тізімді ұлғайтып барлық өзгерістерді көрсету, ең соңғыларды ғана емес",
        "tog-usenewrc": "Жуықтағы өзгерістер және бақылау тізімінде беті бойынша өзгерістерді топтау",
        "tog-numberheadings": "Мазмұн тақырыптарын автоматты нөмірлеу",
@@ -54,7 +54,7 @@
        "tog-watchlisthideliu": "Бақылау тізіміндегі кірген қатысушылардың өңдеулерін көрсетпеу",
        "tog-watchlisthideanons": "Бақылау тізіміндегі аноним қатысушылардың өңдеулерін көрсетпеу",
        "tog-watchlisthidepatrolled": "Бақылау тізімінде тексерілген өңдеулерді көрсетпеу",
-       "tog-watchlisthidecategorization": "Беттерді санаттауларды жасыру",
+       "tog-watchlisthidecategorization": "Беттедің санатталуын жасыру",
        "tog-ccmeonemails": "Басқа қатысушыға жіберген хатымның есесін өзіме жөнелту",
        "tog-diffonly": "Нұсқалар айырмашылықтарының астында бет мағлұматын көрсетпеу",
        "tog-showhiddencats": "Жасырын санаттарды көрсету",
        "mypage": "Жеке бет",
        "mytalk": "Талқылау",
        "anontalk": "Талқылау",
-       "navigation": "Ð\91аÒ\93Ñ\8bÑ\82Ñ\82ау",
+       "navigation": "ШаÑ\80лау",
        "and": "&#32;және",
        "qbfind": "Табу",
        "qbbrowse": "Шолу",
        "passwordreset-emaildisabled": "E-mail мүмкіндігі бұл уикиде өшірілген.",
        "passwordreset-username": "Қатысушы аты:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Келген хатты қарау керек пе?",
-       "passwordreset-capture-help": "Егер Сіз берілген белгішені қондырсаңыз, қатысушыға жіберілетін уақытша құпия сөз жазылған хат көрсетіледі.",
        "passwordreset-email": "Е-поштаның мекен-жайы:",
        "passwordreset-emailtitle": "{{SITENAME}} тіркелгісі туралы анықтама",
        "passwordreset-emailtext-ip": "Әлде кім (мүмкін сіз болуыңыз, $1 IP адресінен) {{SITENAME}} сайтында ($4) құпия сөзді өзгертуге өтініш білдірді. Мына қатысушы {{PLURAL:$3|аккаунты|аккаунттары}} осы электронды почта қатысты:\n\n$2\n\n{{PLURAL:$3|Бұл уақытша құпия сөз|Бұл уақытша құпия сөздер}} {{PLURAL:$5|бір күнде|$5 күнде}}уақыты аяқталады.\nСіз кіруіңіз және жаңа құпия сөзді таңдауыңыз керек. Егер бұл өтінішті басқа біреу жасаса, немесе сіз  бұрынғы құпия сөзіңізді еске түсірсеңіз және құпия сөзді ауыстыруды қаламасаңыз, сіз бұл хабарламаны ескермей және бұрынғы құпия сөзді қолдана беруіңізге болады.",
        "passwordreset-emailtext-user": "$1 есімді қатысушы {{SITENAME}} сайтында ($4) құпия сөзді өзгертуге өтініш білдірді. Мына қатысушы {{PLURAL:$3|аккаунт|аккаунттар}} осы електронды почта қатысты:\n\n$2\n\n{{PLURAL:$3|Бұл уақытша құпия сөз|Бұл уақытша құпия сөздер}} {{PLURAL:$5|бір күнде|$5 күнде}}уақыты аяқталады.\nСіз кіруіңіз және жаңа құпия сөзді таңдауыңыз керек. Егер бұл өтінішті басқа біреу жасаса, немесе сіз  бұрынғы құпия сөзіңізді еске түсірсеңіз, және құпия сөзді ауыстыруды қаламасаңыз, сіз бұл хабарламаны ескермей және бұрыңғы құпия сөзді қолдана беруіңізге болады.",
        "passwordreset-emailelement": "Қатысушы есімі: \n$1\n\nУақытша құпия сөз: \n$2",
        "passwordreset-emailsentemail": "Бұл email мекенжайы тіркелгіңізге байланысқан, сол себепті құпия сөзді өзгерту электронды пошта арқылы жөнелтіледі.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|email has|emails have}}үшін құпия сөздің қалпына келтіру хабарламасы жіберілді. {{PLURAL:$1|username and password|list of usernames and passwords}} мында көрсетілген.",
-       "passwordreset-emailerror-capture2": "{{GENDER:$2|user}}-мен электронды поштамен хабарласу нәтижесіз қалды: $1 The {{PLURAL:$3|username and password|list of usernames and passwords}} мында көрсетілген.",
        "changeemail": "Е-пошта мекенжайын өзгерту немесе аластау",
        "changeemail-header": "Е-пошта мекен-жайының өзгертілуі",
        "changeemail-no-info": "Бұл бетке тікелей ену үшін жүйеге кіруіңіз керек.",
        "userrights-reason": "Себебі:",
        "userrights-no-interwiki": "Басқа уикилердегі қатысушы құқықтарын өңдеуге рұқсатыңыз жоқ.",
        "userrights-nodatabase": "$1 дерекқоры жоқ не жергілікті емес.",
-       "userrights-nologin": "Қатысушы құқықтарын тағайындау үшін әкімші тіркелгісімен [[Special:UserLogin|кіруіңіз]] жөн.",
-       "userrights-notallowed": "Сізге қатысушы құқықтарын қосуға немесе алып тастауға рұқсат берілмеген.",
        "userrights-changeable-col": "Өзгерте алатын топтар",
        "userrights-unchangeable-col": "Өзгерте алмайтын топтар",
        "userrights-conflict": "Қатысушы құқықтарының қақтығысы! Өзгертулеріңізді қайта қарап шығыңыз және құптаңыз.",
-       "userrights-removed-self": "Өзіңіздің құқықтарыңызды алып тастадыңыз.  Осылайша бұл бетке бұдан былай қатынай алмайсыз.",
        "group": "Топ:",
        "group-user": "Қатысушылар",
        "group-autoconfirmed": "Өздіктіқұпталған қатысушылар",
        "right-siteadmin": "Дерекқорды құлыптау және құлыптауын өшіру",
        "right-override-export-depth": "Тереңдігі 5-тен жоғары сілтенген бетттерді қамти беттерді экспорттау",
        "right-sendemail": "Басқа қатысушыларға е-пошта жіберу",
-       "right-passwordreset": "Өзгерген құпия сөз арқылы хабарламаларды шолу",
        "right-managechangetags": "[[Special:Tags|Тегтерді]] дерекқордан бастау және жою",
        "right-applychangetags": "[[Special:Tags|Тегтерді]] бір өзгерісімен қолдану",
        "right-changetags": "Кез келген [[Special:Tags|тегті]] жеке нұсқалардан және журнал жазбаларынан аластау және қосу",
        "trackingcategories-msg": "Санатты қадағалау",
        "trackingcategories-name": "Хабарлама атауы",
        "trackingcategories-desc": "Санаттарды қосу шарттары",
-       "restricted-displaytitle-ignored": "Еленбеген көретілетін атауларымен беттер",
+       "restricted-displaytitle-ignored": "Еленбеген көрcетілетін атауларымен беттер",
        "noindex-category-desc": "Бұл бет роботтар арқылы индекстелмеген, себебі онда <code><nowiki>__NOINDEX__</nowiki></code> деген сиқырлы сөзі бар және бұл жалауша рұқсат етілген есім кеңістігінде орналасқан.",
        "index-category-desc": "Бұл бетте <code><nowiki>__INDEX__</nowiki></code> деген код бар (және бұл жалауша рұқсат етілген есім кеңістігінде орналасқан), демек мұнда қалыпты жағдайда роботтар арқылы индекстелмейді.",
        "post-expand-template-inclusion-category-desc": "Беттің мөлшері барлық үлгілерді кеңейткен соң мынадан <code>$wgMaxArticleSize</code> үлкенірек болады, сондықтан біраз үлгілер кеңейтілмейді.",
        "undeleterevisions": "$1 {{PLURAL:$1|нұсқа|нұсқа}} жойылды",
        "undeletehistory": "Егер бетті қалпына келтірсеңіз тарихындағы барлық түзетулер де қалпына келтіріледі. Егер жоюдан соң дәл солай атауымен жаңа бет басталса қалпына келтірілген түзетулер бұрынғы өңделу тарихында көрсетіледі.",
        "undeleterevdel": "Егер бұл үстіңгі бетте аяқталса, не файл түзетуі жарым-жартылай жойылған болса, жою болдырмауы орындалмайды.\nОсындай жағдайларда, ең жаңа жойылған түзетуін алып тастауыңыз не жасыруын болдырмауыңыз жөн.",
-       "undeletehistorynoadmin": "Бұл бет жойылған.\nЖою себебі алдындағы өңдеген қатысушылар егжей-тегжейлерімен бірге төмендегі қысқаша мазмұндамасында көрсетілген.\nМына жойылған түзетулерін көкейкесті мәтіні тек әкімшілерге жетімді.",
+       "undeletehistorynoadmin": "Бұл бет жойылған.\nЖойған себебі жою алдындағы өңдеген қатысушылар егжей-тегжейлерімен бірге төмендегі қысқаша мазмұндамасында көрсетілген. Осы жойылған нұсқалардың мәтіні тек әкімшілерге қатынаулы.",
        "undelete-revision": "$4,  $5  кезіндегі $3 жасаған $1 дегеннің жойылған түзетуі:",
        "undeleterevision-missing": "Жарамсыз не жоғалған түзету.\nСілтемеңіз жарамсыз, не түзету қалпына келтірілген, немесе мұрағаттан аласталған болуы мүмкін.",
        "undelete-nodiff": "Еш алдыңғы түзету табылмады.",
        "feedback-thanks": "Рахмет! Сіздің кері байланысыңыз \"[$2 $1]\" бетіне қойылды.",
        "feedback-thanks-title": "Рақмет!",
        "feedback-useragent": "Қатысушы агент:",
-       "searchsuggest-search": "Іздеу",
+       "searchsuggest-search": "{{SITENAME}} жобасынан іздеу",
        "searchsuggest-containing": "қамтылуда...",
        "api-error-badaccess-groups": "Сізге бұл уикиге файл жүктеуге рұқсат етілмеген.",
        "api-error-badtoken": "Ішкі қате: Жаман байрақша",
index 39773cc..7ea4dfd 100644 (file)
@@ -5,7 +5,8 @@
                        "GaiJin",
                        "Kaztrans",
                        "아라",
-                       "Macofe"
+                       "Macofe",
+                       "Zpizza"
                ]
        },
        "tog-underline": "Siltemeniñ astın sız:",
        "yourname": "Qatıswşı atıñız:",
        "yourpassword": "Qupïya söziñiz:",
        "yourpasswordagain": "Qupïya sözdi qaýtalañız:",
-       "remembermypassword": "Meniñ kirgenimdi bul komp′ywterde umıtpa (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "Jeli üýşigiñiz:",
        "externaldberror": "Osı arada ne şettik rastaw derekqorında qate boldı, nemese şettik tirkelgiñizdi jañalaw ruqsatı joq.",
        "login": "Kirw",
        "undo-failure": "Bul öñdeme joqqa şığarılmaýdı, sebebi arada qaqtığıstı öñdemeler bar.",
        "undo-norev": "Bul öñdeme joqqa şığarılmaýdı, sebebi bul joq nemese joýılğan.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User_talk:$2|talqılawı]]) istegen nömir $1 nusqasın joqqa şığardı",
-       "cantcreateaccounttitle": "Jaña tirkelgi jasalmadı",
        "cantcreateaccount-text": "Bul IP jaýdan ('''$1''') jaña tirkelgi jasawın [[User:$3|$3]] buğattağan.\n\n$3 keltirilgen sebebi: ''$2''",
        "viewpagelogs": "Bul bet üşin jwrnal oqïğaların qaraw",
        "nohistory": "Mında bul bettiniñ tüzetw tarïxı joq.",
        "userrights-reason": "Sebebi:",
        "userrights-no-interwiki": "Basqa wïkïlerdegi paýdalanwşı quqıqtarın öñdewge ruqsatıñız joq.",
        "userrights-nodatabase": "$1 derekqorı joq ne jergilikti emes.",
-       "userrights-nologin": "Qatıswşı quqıqtarın tağaýındaw üşin äkimşi tirkelgisimen [[{{#special:Userlogin}}|kirwiñiz]] jön.",
-       "userrights-notallowed": "Qatıswşı quqıqtarın tağaýındaw üşin tirkelgiñizde ruqsat joq.",
        "userrights-changeable-col": "Özgerte alatın toptar",
        "userrights-unchangeable-col": "Özgerte almaýtın toptar",
        "group": "Top:",
        "listusersfrom": "Mına qatıswşıdan bastap körsetw:",
        "listusers-submit": "Körset",
        "listusers-noresult": "Qatıswşı tabılğan joq.",
+       "activeusers-excludegroups": "Toptarğa jatatın paydalanwşılardı qospaw:",
        "listgrouprights": "Qatıswşı tobı quqıqtarı",
        "listgrouprights-summary": "Kelesi tizimde bul wïkïde tağaýındalğan qatıswşı quqıqtarı (baýlanıstı qatınaw quqıqtarımen birge) körsetiledi.\nJeke quqıqtar twralı köbirek aqparattı [[{{MediaWiki:Listgrouprights-helppage}}|mında]] taba alasız.",
        "listgrouprights-group": "Top",
index 282444d..89564eb 100644 (file)
        "yourpasswordagain": "វាយពាក្យសម្ងាត់ម្តងទៀត៖",
        "createacct-yourpasswordagain": "អះអាង​ពាក្យ​សម្ងាត់",
        "createacct-yourpasswordagain-ph": "បញ្ចូលពាក្យសម្ងាត់ម្ដងទៀត",
-       "remembermypassword": "ចងចាំកំណត់ឈ្មោះចូលរបស់ខ្ញុំក្នុងកុំព្យូទ័រនេះ (សំរាប់រយៈពេលយូរបំផុត $1 {{PLURAL:$1|ថ្ងៃ|ថ្ងៃ}})",
        "userlogin-remembermypassword": "រក្សាស្ថានភាពកត់ឈ្មោះចូលរបស់ខ្ញុំ",
        "userlogin-signwithsecure": "ប្រើការតភ្ជាប់មានសុវត្ថិភាព",
        "yourdomainname": "ដូម៉ែនរបស់អ្នក៖",
        "activeusers-intro": "នេះជាបញ្ជីរាយនាមអ្នកប្រើប្រាស់ដែលមានសកម្មភាពក្នុងរូបភាពណាមួយក្នុងរយៈពេល $1 {{PLURAL:$1|ថ្ងៃ|ថ្ងៃ}}ចុងក្រោយ។",
        "activeusers-count": "{{PLURAL:$1|សកម្មភាព|សកម្មភាព}}ចំនួន$1 ក្នុងរយៈពេល{{PLURAL:$3|១ថ្ងៃ|$3 ថ្ងៃ}}ចុងក្រោយ",
        "activeusers-from": "បង្ហាញអត្តនាមផ្ដើមដោយ៖",
-       "activeusers-hidebots": "លាក់រូបយន្ត",
-       "activeusers-hidesysops": "លាក់អភិបាល",
        "activeusers-noresult": "អ្នកប្រើប្រាស់​រកមិនឃើញ​។​",
        "listgrouprights": "សិទ្ធិនិងក្រុមអ្នកប្រើប្រាស់",
        "listgrouprights-summary": "ខាងក្រោមនេះជាបញ្ជីរាយឈ្មោះក្រុមអ្នកប្រើប្រាស់ដែលបានកំណត់ជាមួយនឹងសិទ្ធិរបស់គេនៅលើវិគីនេះ។ មាន[[{{MediaWiki:Listgrouprights-helppage}}|ព័ត៌មានបន្ថែម]] អំពីសិទ្ធិផ្ទាល់ខ្លួន។",
index 7d90f87..d0b2f85 100644 (file)
@@ -63,7 +63,8 @@
                        "HDNua",
                        "Ykhwong",
                        "Matma Rex",
-                       "Tursetic"
+                       "Tursetic",
+                       "Jerrykim306"
                ]
        },
        "tog-underline": "링크에 밑줄:",
        "tog-diffonly": "편집 차이를 비교할 때 문서 내용을 보지 않기",
        "tog-showhiddencats": "숨은 분류 보이기",
        "tog-norollbackdiff": "되돌리기 후 차이를 보지 않기",
-       "tog-useeditwarning": "바꾼 내용을 저장하지 않고 편집 페이지를 벗어날 때 내게 경고하기",
+       "tog-useeditwarning": "바꾼 내용을 저장하지 않고 편집 페이지를 벗어날 때 내게 알리기",
        "tog-prefershttps": "로그인하는 동안 항상 보안 연결 사용",
        "underline-always": "항상",
        "underline-never": "항상 치지 않기",
        "views": "보기",
        "toolbox": "도구",
        "tool-link-userrights": "{{GENDER:$1|사용자}} 그룹 변경",
+       "tool-link-userrights-readonly": "{{GENDER:$1|사용자}} 그룹을 보기",
        "tool-link-emailuser": "이 {{GENDER:$1|사용자}}에게 이메일 보내기",
        "userpage": "사용자 문서 보기",
        "projectpage": "프로젝트 문서 보기",
        "passwordreset-emaildisabled": "이 위키에서 이메일 기능이 비활성화되어 있습니다.",
        "passwordreset-username": "사용자 이름:",
        "passwordreset-domain": "도메인:",
-       "passwordreset-capture": "발송 결과 이메일을 보시겠습니까?",
-       "passwordreset-capture-help": "이 상자에 체크하면 이메일이 발송된 즉시 임시 비밀번호가 담긴 이메일을 볼 수 있습니다.",
        "passwordreset-email": "이메일 주소:",
        "passwordreset-emailtitle": "{{SITENAME}} 계정에 대한 자세한 정보",
        "passwordreset-emailtext-ip": "당신일 수도 있는 $1 IP 주소를 사용하는 사용자가 {{SITENAME}} ($4)의 비밀번호 재설정을 요청하였습니다.\n이 이메일 주소와 연관된 사용자 {{PLURAL:$3|계정}}의 목록입니다:\n\n$2\n\n{{PLURAL:$3|이 임시 비밀번호}}는 {{PLURAL:$5|1일|$5일}} 후에 만료됩니다.\n이 비밀번호로 로그인한 후 비밀번호를 바꾸십시오. 만약 당신이 아닌 다른 사람이 요청하였거나,\n원래의 비밀번호를 기억해냈다면, 이 메시지를 무시하고\n이전의 비밀번호를 계속 사용할 수 있습니다.",
        "passwordreset-emailelement": "사용자 이름: \n$1\n\n임시 비밀번호: \n$2",
        "passwordreset-emailsentemail": "당신의 계정과 연결된 이메일 주소가 있다면, 비밀번호 재설정 메일이 전해질 것입니다.",
        "passwordreset-emailsentusername": "이 사용자 이름과 연결된 이메일 주소가 있다면 비밀번호 초기화 이메일이 전송됩니다.",
-       "passwordreset-emailsent-capture2": "비밀번호 재설정 이메일을 보냈습니다. {{PLURAL:$1|사용자 이름과 비밀번호는|사용자 이름과 비밀번호의 목록은}} 아래에 나타납니다.",
-       "passwordreset-emailerror-capture2": "{{GENDER:$2|사용자}} 이메일 보내기 실패: $1 {{PLURAL:$3|사용자 이름과 비밀번호가|사용자 이름과 비밀번호의 목록이}} 아래에 나타납니다.",
        "passwordreset-nocaller": "호출자를 지정해야 합니다",
        "passwordreset-nosuchcaller": "호출자가 존재하지 않습니다: $1",
        "passwordreset-ignored": "비밀번호 재설정을 처리하지 못했습니다. 제공자가 구성되지 않았기 때문일 수 있습니다.",
-       "passwordreset-invalideamil": "잘못된 이메일 주소",
+       "passwordreset-invalidemail": "잘못된 이메일 주소",
        "passwordreset-nodata": "사용자 이름이나 이메일 주소가 지정되지 않았습니다",
        "changeemail": "이메일 주소를 바꾸거나 제거하기",
        "changeemail-header": "이메일 주소를 바꾸려면 이 양식을 채우세요. 계정에서 이메일 연동을 취소하고 싶다면 양식을 제출할 때 새 이메일 주소를 공란으로 두세요.",
        "minoredit": "사소한 편집입니다",
        "watchthis": "이 문서 주시하기",
        "savearticle": "문서 저장",
-       "savechanges": "변경 사항 저장",
+       "savechanges": "변경사항 저장",
        "publishpage": "문서 게시",
-       "publishchanges": "변경 사항 게시",
+       "publishchanges": "변경사항 게시",
        "preview": "미리 보기",
        "showpreview": "미리 보기",
        "showdiff": "차이 보기",
        "search-external": "바깥 검색",
        "searchdisabled": "{{SITENAME}} 검색이 비활성화되어 있습니다.\n검색이 작동하지 않는 동안 Google을 통해 검색할 수 있습니다.\n검색 엔진의 내용은 최신이 아닐 수 있다는 점을 참고하세요.",
        "search-error": "검색하는 동안 오류가 발생했습니다: $1",
+       "search-warning": "검색하는 동안 경고가 발생했습니다: $1",
        "preferences": "환경 설정",
        "mypreferences": "환경 설정",
        "prefs-edits": "편집 수:",
        "prefs-help-recentchangescount": "이 설정은 최근 바뀜, 문서 역사와 기록에 적용됩니다.",
        "prefs-help-watchlist-token2": "내 주시문서 목록의 웹 피드의 비밀 키입니다.\n이 키를 알고 있는 사람은 내 주시문서 목록을 읽을 수 있으니 이 키를 공유하지 마세요.\n필요하다면 [[Special:ResetTokens|이 키를 재설정할 수 있습니다]].",
        "savedprefs": "설정을 저장했습니다.",
-       "savedrights": "$1의 사용자 권한이 저장되었습니다.",
+       "savedrights": "{{GENDER:$1|$1}}의 사용자 그룹이 저장되었습니다.",
        "timezonelegend": "시간대:",
        "localtime": "현지 시각:",
        "timezoneuseserverdefault": "위키 기본값 사용 ($1)",
        "prefswarning-warning": "사용자 환경 설정에서 바뀐 것이 아직 저장되어 있지 않습니다.\n사용자 환경 설정에서 \"$1\"을 클릭하지 않고 이 페이지를 떠나면 바뀌지 않습니다.",
        "prefs-tabs-navigation-hint": "팁: 탭 목록에서 탭 사이를 둘러보려면 왼쪽과 오른쪽 화살표 키를 사용할 수 있습니다.",
        "userrights": "사용자 권한 관리",
-       "userrights-lookup-user": "사용자 권한 관리",
+       "userrights-lookup-user": "사용자 선택",
        "userrights-user-editname": "사용자 이름 입력:",
-       "editusergroup": "{{GENDER:$1|사용자}} 그룹 편집",
+       "editusergroup": "사용자 그룹 불러오기",
        "editinguser": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|사용자}}의 권한 바꾸기",
        "userrights-editusergroup": "사용자 그룹 편집",
+       "userrights-viewusergroup": "사용자 그룹 보기",
        "saveusergroups": "{{GENDER:$1|사용자}} 권한 저장",
        "userrights-groupsmember": "현재 권한:",
        "userrights-groupsmember-auto": "자동으로 부여된 권한:",
        "userrights-reason": "이유:",
        "userrights-no-interwiki": "다른 위키의 사용자 권한을 바꿀 권한이 없습니다.",
        "userrights-nodatabase": "데이터베이스 $1이 존재하지 않거나 로컬에 있지 않습니다.",
-       "userrights-nologin": "사용자의 권한을 바꾸기 위해서는 반드시 관리자 계정으로 [[Special:UserLogin|로그인]]해야 합니다.",
-       "userrights-notallowed": "다른 사용자의 권한을 추가하거나 제거할 권한이 없습니다.",
        "userrights-changeable-col": "바꿀 수 있는 권한",
        "userrights-unchangeable-col": "바꿀 수 없는 권한",
        "userrights-conflict": "사용자 권한 바꾸기가 충돌합니다! 바뀜을 검토하고 확인하세요.",
-       "userrights-removed-self": "자신의 권한을 제거했습니다. 따라서 더 이상 이 문서에 접근할 수 없습니다.",
        "group": "그룹:",
        "group-user": "사용자",
        "group-autoconfirmed": "자동 인증된 사용자",
        "right-autoconfirmed": "IP 기반의 속도 제한에 영향을 받지 않음",
        "right-bot": "봇의 편집으로 취급",
        "right-nominornewtalk": "토론 문서에서 사소한 편집으로 새 메시지 알림을 보내지 않기",
-       "right-apihighlimits": "API ì\83\81í\95\9c ì\83\81ì\8a¹",
+       "right-apihighlimits": "API ì¿¼ë¦¬ì\97\90ì\84\9c ë\8d\94 ë\86\92ì\9d\80 ì \9cí\95\9c ì\82¬ì\9a©",
        "right-writeapi": "쓰기 API 사용",
        "right-delete": "문서 삭제",
        "right-bigdelete": "문서 역사가 긴 문서를 삭제",
        "right-siteadmin": "데이터베이스를 잠그거나 잠금 해제",
        "right-override-export-depth": "5단계로 링크된 문서를 포함하여 문서를 내보내기",
        "right-sendemail": "다른 사용자에게 이메일 보내기",
-       "right-passwordreset": "비밀번호 재설정 이메일을 보기",
        "right-managechangetags": "데이터베이스에서 [[Special:Tags|태그]]를 만들거나 지우기",
        "right-applychangetags": "자신이 편집할 때 [[Special:Tags|태그]]를 적용하기",
        "right-changetags": "문서의 특정 판과 특정 기록 항목에 임의의 [[Special:Tags|태그]]를 추가하거나 제거하기",
        "grant-editprotected": "보호된 문서 편집하기",
        "grant-highvolume": "대용량 편집",
        "grant-oversight": "사용자 숨기기와 판 억제",
-       "grant-patrol": "페이지 변경 사항 점검",
+       "grant-patrol": "문서의 변경사항 점검",
        "grant-privateinfo": "개인 정보 접근",
        "grant-protect": "문서 보호 및 보호 해제",
        "grant-rollback": "문서의 바뀜을 되돌리기",
        "action-upload_by_url": "URL 주소를 통해 이 파일을 올리기",
        "action-writeapi": "API를 작성할",
        "action-delete": "이 문서 삭제하기",
-       "action-deleterevision": "이 판을 삭제",
+       "action-deleterevision": "판을 삭제",
        "action-deletedhistory": "이 문서의 삭제된 기여의 역사 보기",
        "action-browsearchive": "삭제된 문서 검색",
        "action-undelete": "이 문서 되살리기",
        "apisandbox-alert-field": "이 필드의 값이 유효하지 않습니다.",
        "apisandbox-continue": "계속",
        "apisandbox-continue-clear": "지우기",
+       "apisandbox-param-limit": "최대 한계치를 사용하려면 <kbd>max</kbd>를 입력하십시오.",
+       "apisandbox-multivalue-all-namespaces": "$1 (모든 이름공간)",
+       "apisandbox-multivalue-all-values": "$1 (모든 값)",
        "booksources": "책 찾기",
        "booksources-search-legend": "책 원본 검색",
        "booksources-isbn": "ISBN:",
        "booksources-search": "검색",
        "booksources-text": "아래의 목록은 새 책이나 중고 책을 판매하는 바깥 사이트로, 원하는 책의 정보를 얻을 수 있습니다.",
        "booksources-invalid-isbn": "입력한 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 매직 링크를 사용하는 문서",
+       "magiclink-tracking-pmid-desc": "이 문서는 PMID 매직 링크를 사용합니다. 이관 방법을 보려면 [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org]를 참조하십시오.",
+       "magiclink-tracking-isbn": "ISBN 매직 링크를 사용하는 문서",
+       "magiclink-tracking-isbn-desc": "이 문서는 ISBN 매직 링크를 사용합니다. 이관 방법을 보려면 [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org]를 참조하십시오.",
        "specialloguserlabel": "작업 수행자:",
        "speciallogtitlelabel": "대상 (사용자계정에 대한 제목 또는 {{ns:user}}:사용자이름):",
        "log": "기록 목록",
        "activeusers-count": "마지막 {{PLURAL:$3|$3일}} 사이의 {{PLURAL:$1|활동}} $1회",
        "activeusers-from": "다음으로 시작하는 사용자를 보기:",
        "activeusers-groups": "그룹에 속한 사용자 표시:",
+       "activeusers-excludegroups": "그룹에 속한 사용자 제외:",
        "activeusers-noresult": "사용자를 찾을 수 없습니다.",
        "activeusers-submit": "활동하고 있는 사용자 보이기",
        "listgrouprights": "사용자 권한 목록",
        "modifiedarticleprotection": "님이 \"[[$1]]\" 문서의 보호 설정을 바꿨습니다",
        "unprotectedarticle": "\"[[$1]]\" 문서를 보호 해제했습니다",
        "movedarticleprotection": "님이 문서의 보호 설정을 \"[[$2]]\"에서 \"[[$1]]\"(으)로 이동했습니다",
+       "protectedarticle-comment": "\"[[$1]]\" 문서를 {{GENDER:$2|보호했습니다}}",
+       "modifiedarticleprotection-comment": "\"[[$1]]\" 문서의 {{GENDER:$2|보호 수준을 변경했습니다}}",
+       "unprotectedarticle-comment": "\"[[$1]]\" 문서의 {{GENDER:$2|보호를 해제했습니다}}",
        "protect-title": "\"$1\" 보호하기",
        "protect-title-notallowed": "\"$1\" 문서의 보호 수준 보기",
        "prot_1movedto2": "[[$1]] 문서를 [[$2]] 문서로 이동함",
        "log-show-hide-patrol": "점검 기록을 $1",
        "log-show-hide-tag": "태그 기록을 $1",
        "confirm-markpatrolled-button": "확인",
+       "confirm-markpatrolled-top": "$2의 $3 판을 점검한 것으로 표시하시겠습니까?",
        "deletedrevision": "예전 $1 판이 삭제되었습니다.",
        "filedeleteerror-short": "파일 삭제 오류: $1",
        "filedeleteerror-long": "파일을 삭제하는 도중 오류가 발생했습니다:\n\n$1",
        "tags-deactivate": "비활성화",
        "tags-hitcount": "$1개 {{PLURAL:$1|바뀜}}",
        "tags-manage-no-permission": "태그를 변경할 권한이 없습니다.",
-       "tags-manage-blocked": "차단된 상태에서는 변경 태그를 관리할 수 없습니다.",
+       "tags-manage-blocked": "{{GENDER:$1|당신이}} 차단된 상태에서는 변경 태그를 관리할 수 없습니다.",
        "tags-create-heading": "태그 생성",
        "tags-create-explanation": "기본적으로 새로 생성된 태그는 사용자와 봇이 사용할 수 있습니다.",
        "tags-create-tag-name": "태그 이름:",
        "tags-deactivate-not-allowed": "\"$1\" 태그를 비활성화할 수 없습니다.",
        "tags-deactivate-submit": "비활성화",
        "tags-apply-no-permission": "사용자의 변경 사항과 변경 태그를 적용할 권한이 없습니다.",
-       "tags-apply-blocked": "차단된 상태에서는 사용자의 변경 사항과 변경 태그를 적용할 수 없습니다.",
+       "tags-apply-blocked": "{{GENDER:$1|당신이}} 차단된 상태에서는 사용자의 변경 사항과 변경 태그를 적용할 수 없습니다.",
        "tags-apply-not-allowed-one": "\"$1\" 태그를 수동으로 추가하는 것은 허용되지 않습니다.",
        "tags-apply-not-allowed-multi": "다음 {{PLURAL:$2|태그를}} 수동으로 추가하는 것은 허용되지 않습니다: $1",
        "tags-update-no-permission": "태그를 문서 판이나 로그 기록에서 추가하거나 삭제할 권한이 없습니다.",
-       "tags-update-blocked": "차단된 상태에서는 변경 태그를 추가하거나 제거할 수 없습니다.",
+       "tags-update-blocked": "{{GENDER:$1|당신이}} 차단된 상태에서는 변경 태그를 추가하거나 제거할 수 없습니다.",
        "tags-update-add-not-allowed-one": "\"$1\" 태그를 수동으로 추가하는 것은 허용되지 않습니다.",
        "tags-update-add-not-allowed-multi": "다음 {{PLURAL:$2|태그는}} 수동으로 추가하는 것이 허용되지 않습니다: $1",
        "tags-update-remove-not-allowed-one": "\"$1\" 태그를 제거하는 것은 허용되지 않습니다.",
        "htmlform-user-not-exists": "<strong>$1</strong> 문서는 존재하지 않습니다.",
        "htmlform-user-not-valid": "<strong>$1</strong>은 올바른 사용자 이름이 아닙니다.",
        "logentry-delete-delete": "$1님이 $3 문서를 {{GENDER:$2|삭제했습니다}}",
+       "logentry-delete-delete_redir": "$1님이 덮어쓰기를 통해 $3 문서를 {{GENDER:$2|삭제했습니다}}",
        "logentry-delete-restore": "$1님이 $3 문서를 {{GENDER:$2|되살렸습니다}}",
        "logentry-delete-event": "$1님이 $3의 {{PLURAL:$1|기록 $5개}}에 대해 보이기 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
        "logentry-delete-revision": "$1님이 $3 문서의 {{PLURAL:$5|$5개 편집}}의 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
        "special-characters-title-emdash": "em 대시",
        "special-characters-title-minus": "빼기 기호",
        "mw-widgets-dateinput-no-date": "선택된 날짜 없음",
+       "mw-widgets-mediasearch-input-placeholder": "미디어 검색",
+       "mw-widgets-mediasearch-noresults": "결과가 없습니다.",
        "mw-widgets-titleinput-description-new-page": "문서가 존재하지 않습니다",
        "mw-widgets-titleinput-description-redirect": "$1 문서로 넘겨주기",
+       "mw-widgets-categoryselector-add-category-placeholder": "분류 추가...",
        "sessionmanager-tie": "여러 요청 인증 유형 결합할 수 없습니다: $1.",
        "sessionprovider-generic": "$1 세션",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "쿠키 기반 세션",
        "restrictionsfield-badip": "유효하지 않은 IP 주소나 대역: $1",
        "restrictionsfield-label": "허용된 IP 대역:",
        "restrictionsfield-help": "줄 단위의 하나의 IP 주소 또는 CIDR 대역입니다. 모든 곳에 적용하려면, 다음을 사용하세요<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "오류: $1",
-       "edit-error-long": "오류:\n\n$1"
+       "pageid": "페이지 ID $1"
 }
index 18976ba..557bc61 100644 (file)
        "yourpasswordagain": "Паролну джангыдан джаз:",
        "createacct-yourpasswordagain": "Паролну бегит",
        "createacct-yourpasswordagain-ph": "Паролну энтда бир кере джаз",
-       "remembermypassword": "Бу компьютерде мени тергеў джазыўуму сакълаб тур (эм кёб: $1 {{PLURAL:$1|бир кюн|кюн}})",
        "userlogin-remembermypassword": "Системада туруу",
        "userlogin-signwithsecure": "Джакъланнган байлам",
        "yourdomainname": "Сизни доменигиз:",
        "passwordreset-emailtitle": "{{SITENAME}} сайтдагъы тергеу джазыуну юсюнден билгиле",
        "passwordreset-emailelement": "Къошулуучуну аты: \n$1\n\nБолджаллы пароль: \n$2",
        "passwordreset-emailsentemail": "Пароль бла e-mail ийилди.",
-       "passwordreset-emailsent-capture": "Ийилген пароль эсгертиу e-mail тюбюрекде берилибди.",
-       "passwordreset-emailerror-capture": "Пароль эсгертиу e-mail генерация этилди (тюбюрекде берилибди), аны {{GENDER:$2|къошулуучугъа}} ашырыу джетишимсиз болду, чурум: $1",
        "changeemail": "Электрон почтаны адресин ауушдур",
        "changeemail-header": "Электрон почтаны адресин ауушдуруу",
        "changeemail-no-info": "Бу бетни кёрюр ючюн сиз системагъа тергеу джазыуугъуз (аккаунтугъуз) бла кирирге керексиз.",
        "undo-failure": "Бир-бирине келишмегени себебли, тюрлениу ызына алынамады.",
        "undo-norev": "Болмагъаны неда кетерилгени ючюн, тюрлениу ызына алыналлыкъ тюлдю.",
        "undo-summary": "$1 тюрлениу [[Special:Contributions/$2|$2]] ([[User talk:$2|сюзюу]]) ызына алынды.",
-       "cantcreateaccounttitle": "Акууант къурар мадар джокъду",
        "cantcreateaccount-text": "Бу IP-адресден ('''$1''') хайырланыучу къошулуу, [[User:$3|$3]] джанындан тыйылгъанды.\n\n\n$3 джанындан берилген сылтау: ''$2''",
        "viewpagelogs": "Бу бетни журналларына къара",
        "nohistory": "Бу бетни тюрлениулерини тарихи джокъду.",
        "activeusers-intro": "Бу, ахыр $1 {{PLURAL:$1|1=кюнде|кюнде}} къаллайда болсун ишлетме кёргюзген къошлуучуланы тизмесиди.",
        "activeusers-count": "Ахыр {{PLURAL:$3|1=кюнде|$3 кюнде}} $1 {{PLURAL:$1|1=тюрлендириу|тюрлендириу}}",
        "activeusers-from": "Бу бла башланнган къошлуучуланы кёргюз:",
-       "activeusers-hidebots": "Ботланы джашыр",
-       "activeusers-hidesysops": "Администраторланы джашыр",
        "activeusers-noresult": "Къошлуучу табылмады.",
        "listgrouprights": "Къошулуучуланы къауумуну хакълары",
        "listgrouprights-summary": "Тюбюндеги бу викиде танылгъан къошулуучу къауумланы эмда аланы хакъларыны тизмеси.\nЭнчи хакъла бла байламлы [[{{MediaWiki:Listgrouprights-helppage}}|асламыракъ билги]] болургъа болур.",
        "htmlform-chosen-placeholder": "Вариантны сайлагъыз",
        "htmlform-cloner-create": "Энтда къош",
        "htmlform-cloner-delete": "Кетер",
-       "sqlite-has-fts": "$1 толу текст излеуню хайырландыргъан",
-       "sqlite-no-fts": "$1 толу текст излеуню хайырландыра билмеген",
        "logentry-delete-delete": "$3 бетни $1 {{GENDER:$2|кетерди}}",
        "logentry-delete-restore": "$3 бетни $1 {{GENDER:$2|ызына салды}}",
        "revdelete-content-hid": "ичиндегиси джашырылыбды",
index ede9c55..df813b8 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "Jose77",
                        "Meno25",
-                       "Protostar"
+                       "Protostar",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Link ùndarlaintin",
        "versionrequired": "Yu nid MediaWiki Version $1",
        "versionrequiredtext": "Yu nid MediaWiki Versiòn $1 fòyuz dhis pej.\nLuk [[Special:Version|version page]].",
        "ok": "OK",
-       "pagetitle-view-mainpage": " \n{{SAITNEM}}",
+       "pagetitle-view-mainpage": "{{SITENAME}}",
        "retrievedfrom": "Dèn dòn ritriv am na\"$1\"",
        "youhavenewmessages": "{{PLURAL:$3|Yu gèt}} $1 ($2).",
        "editsection": "èdit",
index 3586530..7d67c36 100644 (file)
        "yourpasswordagain": "Noch ens dat Passwood",
        "createacct-yourpasswordagain": "Noch ens dat Paßwoot",
        "createacct-yourpasswordagain-ph": "Jivv_et Paßwoot norrens en!",
-       "remembermypassword": "Op Duur aanmelde (hält {{PLURAL:$1|för eine Daach|bes op $1 Dääsch|bloß för hück}})",
        "userlogin-remembermypassword": "Op Duur enlogge",
        "userlogin-signwithsecure": "Verschlößeld enlogge",
        "cannotloginnow-title": "Ennlogge jeiht jrahd nit",
        "botpasswords-label-resetpassword": "Paßwoot neu säze",
        "botpasswords-label-grants": "Aanwändba Rääschte:",
        "botpasswords-help-grants": "Jehde Ennwellejong deihjd e Räsch wigger jävve, wad enem Metmaacher övver singe Zohjang alld zohschteihjt.\nLoor op de Sigg met de [[Special:ListGrants|Tabäll met de Rääschde un Enwellejonge]], wann De mih weße wells.",
-       "botpasswords-label-restrictions": "Beschränkonge:",
        "botpasswords-label-grants-column": "Zohjelohße",
        "botpasswords-bad-appid": "„$1“ es keine jölltejje Nahme för ene Bot.",
        "botpasswords-insert-failed": "Kunnt keine Bot mem Nahme „$1“ derbei donn. Wohr velleijsch ald doh.",
        "passwordreset-emailerror-capture2": "{{GENDER:$2|Däm|Däm|Däm Metmaacher|Dä|Däm}} $1 en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> ze scheke hät nit jeflupp: {{PLURAL:$3|Dä Nahme vum Metmaacher un dat Paßwood|Di Leß met dä Nahme un Paßwööter|Nix weed}} heh noh aanjezeijsch.",
        "passwordreset-nocaller": "Entärne Fähler: Ene Oprohfer moß aanjejovve sin.",
        "passwordreset-nosuchcaller": "Entärne Fähler: Dä Oprohfer „$1“ känne mer nit.",
-       "passwordreset-invalideamil": "Dat es en onjöltejje Addräß fö de <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i>",
+       "passwordreset-invalidemail": "Dat es en onjöltejje Addräß fö de <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i>",
        "passwordreset-nodata": "Keine Metmaacher_Nahme un kein Adräß för de <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> es aanjejovve woode.",
        "changeemail": "Donn en Adräß för de <i lang=\"en\">e-mail</i> ändere udder fott schmiiße",
        "changeemail-header": "Donn heh dat Fommulaa ußfölle, öm Ding Adräß för de <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> ze ändere. Wann De en Adräß loß wähde wells, maach dat Fäld läddesch, ih dat De dat Fommolaa loß scheks.",
        "activeusers-intro": "Dat heh es en Leß met dä Metmaacher, di {{PLURAL:$1|zick jäßtere|en de läzde $1 Dääsch|hück}} ööhnsjät jemaat han.",
        "activeusers-count": "{{PLURAL:$1|ein Änderong|$1 Änderonge|kein Änderonge}} {{PLURAL:$3|aam lezde Daach|en de lezte $3 Dääsch|hück}}",
        "activeusers-from": "Donn de Metmaacher zeije aff:",
-       "activeusers-hidebots": "De Bots fott lohße",
-       "activeusers-hidesysops": "De Wiki_Köbesse fott lohße",
        "activeusers-noresult": "Kein Metmaacher jefonge.",
        "activeusers-submit": "Lohß jonn!",
        "listgrouprights": "Metmaacher_Jroppe-Rääschte",
        "htmlform-title-not-exists": "$1 jidd_et nit.",
        "htmlform-user-not-exists": "<strong>$1</strong> jidd_et nit.",
        "htmlform-user-not-valid": "<strong>$1</strong> es keine jöltejje Nahme för ene Metmaacher.",
-       "sqlite-has-fts": "Version $1 (un kann en janze Täxte söhke)",
-       "sqlite-no-fts": "Version $1 (kann ävver nit en janze Täxte söhke)",
        "logentry-delete-delete": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät di Sigg „$3“ fottjeschmeße.",
        "logentry-delete-restore": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät di vörmohls fottjeschmeße Sigg „$3“ wider zeröck jehollt.",
        "logentry-delete-event": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät för {{PLURAL:$5|eine Logboochendraach|$5 Logboochendrääsh|keine Logboochendraach}} vun dä Sigg „$3“ $4.",
        "feedback-external-bug-report-button": "Donne ene Fähler mällde, ene Wonsch för en Verbäßerong ennreische, udder anndere täschneche Idee opbränge.",
        "feedback-dialog-title": "En Rökmäldong jävve",
        "feedback-dialog-intro": "Dat Fommolaa kam_mer för en Rökmäldong bruche. Di kütt zesamme met Dingem Metmaacher_Nahme op di Sigg „$1“.",
-       "feedback-error-title": "Fähler",
        "feedback-error1": "Fähler: dat <i lang=\"en\">API</i> säät jät, wat mer nit kenne",
        "feedback-error2": "Fähler: de Sigg ze ändere es donävve jejange",
        "feedback-error3": "Fähler: dat <i lang=\"en\">API</i> joov kein Antwoot",
index 574b828..dcc8529 100644 (file)
@@ -37,6 +37,7 @@
        "tog-watchdefault": "Rûpelên min guhertin û dosyeyên min barkirin, têxe nav lîsteya min a şopandinê",
        "tog-watchmoves": "Rûpel û dosyeyên ku ez navên wan diguherînim, têxe nav lîsteya min a şopandinê",
        "tog-watchdeletion": "Rûpel û dosyeyên min jêbirin, têxe nav lîsteya min a şopandinê",
+       "tog-watchuploads": "Dosyeyên ku ez bar dikim tevlî lîsteya min a şopandinê bike",
        "tog-minordefault": "Her guhertinekê weke guhertineke biçûk nîşan bide",
        "tog-previewontop": "Pêşdîtina gotarê li jorî cihê guherandinê nîşan bide",
        "tog-previewonfirst": "Li cem guherandinê hertim yekemîn pêşdîtinê nîşan bide",
        "newwindow": "(di pencereyeke din de wê were nîşandan)",
        "cancel": "Betal bike",
        "moredotdotdot": "Bêhtir...",
-       "morenotlisted": "Ev lîste nehatiye temamkirin.",
+       "morenotlisted": "Dibe ku ev lîste neqediyaye.",
        "mypage": "Rûpela min",
        "mytalk": "Gotûbêja min",
        "anontalk": "Gotûbêj",
        "nocookiesnew": "Hesabê bikarhêner hatibû çêkirin, lê te xwe qeyd nekiriye. {{SITENAME}} ji bo qeydkirina bikarhêneran cookie'yan bikartîne. Te bikaranîna cookie'yan girtiye. Xêra xwe cookie'yan qebûl bike, piştre bi navê bikarhêner û şîfreya xwe têkeve.",
        "nocookieslogin": "Ji bo qeydkirina bikarhêneran {{SITENAME}} \"cookies\" bikartîne. Te fonksîyona \"cookies\" girtîye. Xêra xwe kerema xwe \"cookies\" gengaz bike û careke din biceribîne.",
        "noname": "Navê ku te nivîsand ne derbasdar e.",
-       "loginsuccesstitle": "Têketin serkevtî bû!",
+       "loginsuccesstitle": "Tu têketî",
        "loginsuccess": "Tu niha di {{SITENAME}} de tomarkirî yî wek \"$1\".",
        "nosuchuser": "Bikarhênerê bi navê \"$1\" tune. Navê rast binivîse an bi vê formê <b>hesabekî nû çêke</b>. (Ji bo hevalên nû \"Têkeve\" çênabe!)",
        "nosuchusershort": "Li vê derê ne bikarhênerek bi navî \"$1\" heye. Li nivîsandinê xwe seke.",
        "retypenew": "Şîfreya nû careke din binîvîse",
        "resetpass_submit": "Şîfreyê pêkbîne û têkeve",
        "changepassword-success": "Şîfreya te hate guhertandin!",
+       "botpasswords": "Şîfreyên bot",
        "botpasswords-label-appid": "Navê bot:",
        "botpasswords-label-create": "Çêke",
        "botpasswords-label-update": "Rojane bike",
        "passwordreset-emailtitle": "Hûragahiyên hesab li ser {{SITENAME}}",
        "passwordreset-emailelement": "Navê bikarhêner:\n$1\n\nŞîfreya niha:\n$2",
        "passwordreset-emailsentemail": "E-nameyeke bibîrxistinê hate şandin.",
-       "passwordreset-invalideamil": "Navnîşana enameyê ya nederbasdar",
+       "passwordreset-invalidemail": "Navnîşana enameyê ya nederbasdar",
        "changeemail": "Navnîşana enameya xwe biguherîne an rabike",
        "changeemail-oldemail": "Navnîşana e-nameya niha:",
        "changeemail-newemail": "Navnîşana e-nameya nû:",
        "searchprofile-images-tooltip": "Li pelan bigere",
        "searchprofile-everything-tooltip": "Di hemû naverokada bigere (tevî gotûbêja)",
        "search-result-size": "$1 ({{PLURAL:$2|peyvek|$2 peyv}})",
-       "search-redirect": "(beralîkirin $1)",
+       "search-redirect": "(beralîkirina ji $1)",
        "search-section": "(beş $1)",
        "search-category": "(kategorî $1)",
        "search-file-match": "(bi naveroka dosye re lê te)",
        "userrights-reason": "Sedem:",
        "userrights-no-interwiki": "Mafê te ji bo guherandina mafên bikarhênerên di Wîkiyên din de nîne.",
        "userrights-nodatabase": "Danegeh $1 nîne an ne ya vir e.",
-       "userrights-nologin": "Ji bo guherandina mafên bikarhêneran, divê tu bi hesabê rêveber [[Special:UserLogin|têkevî]].",
-       "userrights-notallowed": "Account'a te mafê xwe tune ye ji bo guherandina mafên bikarhêneran.",
        "userrights-changeable-col": "Komên ku tu dikarî biguherînî",
        "userrights-unchangeable-col": "Komên ku tu nikarî biguherînî",
        "group": "Kom:",
        "statistics-pages": "Rûpel",
        "statistics-pages-desc": "Hemû rûpelên di vê wîkiyê de, bi hemû rûpelên gotûbêj, beralîkirin, hwd.",
        "statistics-files": "Wêneyên barkirî",
+       "statistics-edits": "Hejmara guherandinên rûpelan ji avabûna {{SITENAME}} heta niha",
        "statistics-users": "[[Special:ListUsers|Bikarhênerên tomarkirî]]",
        "statistics-users-active": "Bikarhênerên çalak",
        "pageswithprop-submit": "Biçe",
        "protectedtitles-submit": "Sernavan nîşan bide",
        "listusers": "Lîsteya bikarhêneran",
        "listusers-editsonly": "Tenê bikarhênerên bi guherrandinan nîşan bide",
+       "listusers-creationsort": "Li gorî dema çêkirina hesab parzûn bike",
        "usercreated": "di $1 de, li $2 hate çêkirin",
        "newpages": "Rûpelên nû",
        "newpages-submit": "Nîşan bide",
        "wlshowlast": "Guhertinên berî $1 saetan, $2 rojan, ya  nîşan bide",
        "watchlist-hide": "Veşêre",
        "watchlist-submit": "Nîşan bide",
+       "wlshowhideminor": "guherandinên biçûk",
        "wlshowhidebots": "bot",
        "wlshowhideliu": "bikarhênerên tomarkirî",
        "wlshowhideanons": "bikarhênerên bênav",
        "sp-contributions-userrights": "birêvebirina mafên bikarhêneran",
        "sp-contributions-search": "Li beşdariyan bigere",
        "sp-contributions-username": "Navnîşana IP'yê an jî navê bikarhêner:",
+       "sp-contributions-newonly": "Tenê rûpelên hatine çêkirin nîşan bide",
+       "sp-contributions-hideminor": "Guherandinên biçûk veşêre",
        "sp-contributions-submit": "Lêgerîn",
        "whatlinkshere": "Girêdanên li ser vê rûpelê",
        "whatlinkshere-title": "Rûpelan, yê berve $1 tên",
        "pageinfo-header-properties": "Taybetmendiyên rûpelê",
        "pageinfo-display-title": "Sernavê nîşan bide",
        "pageinfo-language": "Zimanê naveroka rûpelê",
-       "pageinfo-watchers": "Hejmara kesên dişopînin",
+       "pageinfo-watchers": "Hejmara şopînerên rûpelê",
        "pageinfo-redirects-name": "Hejmara beralîkirinên ber bi vê rûpelê ve",
        "pageinfo-subpages-name": "Binrûpelên vê rûpelê",
        "pageinfo-firsttime": "Dema çêkirina rûpelê",
        "imagelisttext": "Jêr lîsteyek ji $1 file'an heye, duxrekirin $2.",
        "newimages-summary": "Ev rûpela taybet dosyeyên ku herî dawî hatine barkirin, nîşan dide.",
        "newimages-legend": "Parzûn",
+       "newimages-showbots": "Barkirinên ji aliyê botan nîşan bide",
        "noimages": "Ne tiştek tê dîtin.",
        "ilsubmit": "Lêgerîn",
        "bydate": "li gor dîrokê",
index 6b316da..e4f1e44 100644 (file)
        "yourpasswordagain": "Jynnskrifewgh agas ger tremena arta:",
        "createacct-yourpasswordagain": "Afydhyewgh an ger tremena",
        "createacct-yourpasswordagain-ph": "Entrewgh an ger tremena arta",
-       "remembermypassword": "Perthi kov a'm omgelmi war an jynn amontya-ma (rag $1 {{PLURAL:$1|dydh}} dhe'n moyha)",
        "userlogin-remembermypassword": "Perthi kov a'm omgelmi",
        "userlogin-signwithsecure": "Devnydhya junyans diogel",
        "yourdomainname": "Agas tiredh:",
        "passwordreset-email": "Trigva ebost:",
        "passwordreset-emailtitle": "Manylyon agas akont war {{SITENAME}}",
        "passwordreset-emailsentemail": "Ebost dassettya ger tremena re beu danvenys.",
-       "passwordreset-emailsent-capture": "Ebost dassettya ger tremena re beu danvenys, hag y hyllir y weles a-woles.",
        "changeemail": "Chanjya trigva ebost",
        "changeemail-header": "Chanjya trigva ebost an akont",
        "changeemail-oldemail": "Agas trigva ebost a-lemmyn:",
        "editwarning-warning": "Mar kesowgh an folen ma, hwi a allsa kelli chanjyow gwrys genowgh.\nMars owgh hwi omgelmys, hwi a yll diallosegi an gwarnyans ma yn tregh \"{{int:prefs-editing}}\" agas dewisyow.",
        "undo-success": "Y hyllir diswul an chanj-ma.\nCheckyewgh mar pleg an kehevelyans a-woles rag gwirya bos hemma an pyth a vynnowgh, hag ena gwithewgh an chanjyow a-woles rag gorfenna diswul an chanj.",
        "undo-summary": "Amendyans $1 gans [[Special:Contributions/$2|$2]] ([[User talk:$2|keskows]]) diswrys",
-       "cantcreateaccounttitle": "Ny yllir gwruthyl an akont",
        "viewpagelogs": "Gweles kovnotennow an folen ma",
        "currentrev": "Amendyans diwettha",
        "currentrev-asof": "An amendyans diwettha a-dhia $1",
        "activeusers": "Rol a dhevnydhyoryon vyw",
        "activeusers-intro": "Hemm yw rol a dhevnydhyoryon re wrug gwrians war an wiki-ma y'n $1 {{PLURAL:$1|jydh|dydh}} diwettha.",
        "activeusers-count": "$1 {{PLURAL:$1|wrians|gwrians}} y'n {{PLURAL:$3|jydh|$3 dydh}} diwettha",
-       "activeusers-hidebots": "Kudha botow",
-       "activeusers-hidesysops": "Kudha menystroryon",
        "listgrouprights-members": "(rol eseli)",
        "emailuser": "Ebostya an devnydhyer-ma",
        "defemailsubject": "Ebost danvenys dre {{SITENAME}} gans an devnydhyer \"$1\"",
index ee793ef..171a911 100644 (file)
        "listusers-blocked": "(obstructus)",
        "activeusers": "Index usorum activorum",
        "activeusers-count": "{{PLURAL:$1|una recensio {{PLURAL:$3|hodie|his $3 diebus}} facta|$1 recensiones {{PLURAL:$3|hodie|his $3 diebus}} factae}}",
-       "activeusers-hidebots": "Celare automata",
-       "activeusers-hidesysops": "Celare magistratus",
        "activeusers-noresult": "Nullus usor inventus.",
        "listgrouprights": "Gregum usorum potestates",
        "listgrouprights-group": "Grex",
index 4f3f53a..db6cd9f 100644 (file)
        "yourpasswordagain": "Entra de muevo el kóddiche:",
        "createacct-yourpasswordagain": "Konfirme contrasenya",
        "createacct-yourpasswordagain-ph": "Eskrive la kontrasenya de muevo",
-       "remembermypassword": "Acódrate de mi entrada de kullaneador en este navigador (por un maksimum de {{PLURAL:$1|día|días}})",
        "yourdomainname": "Tu dominyo:",
        "password-change-forbidden": "No se puede kambiar contrasenyas en este viki.",
        "login": "Entrar",
        "post-expand-template-inclusion-category": "Hojas con sovrecarga de şablones",
        "post-expand-template-argument-warning": "'''Aviso:''' Esta oja tiene kuanto menos un kampo enel xablon muy lungo.\nEste o estos kampos no van ser amostrados",
        "post-expand-template-argument-category": "Ojas ke tienen xablones kon parametros no uzados",
-       "cantcreateaccounttitle": "No se puede krear el kuento",
        "viewpagelogs": "Ver los registros de esta hoja",
        "currentrev": "Enderechamiento d'al cavo",
        "currentrev-asof": "Enderechamiento dalcavo de $2 a las $3 la ora",
        "linksearch-line": "Atamiento para $1 en la hoja $2",
        "listusers-submit": "Amostrar",
        "listusers-noresult": "No se topo usuario",
-       "activeusers-hidebots": "Eskonder bots",
        "activeusers-noresult": "No se toparon usuario.",
        "listgrouprights": "Derechos del grupo de usuario",
        "listgrouprights-group": "Grupo",
index 8d6158f..1fd8000 100644 (file)
        "views": "Affichagen",
        "toolbox": "Geschirkëscht",
        "tool-link-userrights": "{{GENDER:$1|Benotzer}}gruppen änneren",
+       "tool-link-userrights-readonly": "{{GENDER:$1|Benotzer}}gruppe weisen",
        "tool-link-emailuser": "{{GENDER:$1|Dëser Benotzerin|Dësem Benotzer}} eng Mail schécken",
        "userpage": "Benotzersäit",
        "projectpage": "Meta-Text",
        "passwordreset-emaildisabled": "D'E-Mail-Funktioune goufen op dëser Wiki ausgeschalt.",
        "passwordreset-username": "Benotzernumm:",
        "passwordreset-domain": "Domaine:",
-       "passwordreset-capture": "D'Mail kucken?",
-       "passwordreset-capture-help": "Wann Dir dës Këscht ukräizt, gëtt de Mail (mam temporäre Passwuert) Iech gewisen an dem Benotzer geschéckt.",
        "passwordreset-email": "E-Mail-Adress:",
        "passwordreset-emailtitle": "Detailer vum Benotzerkont op{{SITENAME}}",
        "passwordreset-emailtext-ip": "Iergendee mat der IP-Adress $1, wahrscheinlech Dir selwer, huet d'Zrécksetze vun Ärem Passwuert op {{SITENAME}} gefrot ($4). {{PLURAL:$3|De Benotzerkont ass|D'Benutzerkonte si}} mat dëser E-Mail-Adress verbonn:\n\n$2\n\n{{PLURAL:$3|Dëst temporärt Passwuert leeft|Dës temporär Passwierder lafe}} bannent {{PLURAL:$5|engem Dag|$5 Deeg}} of.\nDir sollt Iech aloggen an een neit Passwuert festleeën. Wann een Aneren déi Ufro gemaach huet oder Dir Iech erëm un Äert Passwuert erënnere kënnt an et net ännere wëllt, kënnt Dir dës Noriicht ignoréieren an Äert aalt Passwuert weider benotzen.",
        "passwordreset-emailelement": "Benotzernumm: \n$1\n\nTemporärt Passwuert: \n$2",
        "passwordreset-emailsentemail": "Wann dës E-Mailadress mat Ärem Benotzerkont assoziéiert ass, da gëtt Eng E-Mail fir d'Passwuert zréckzesetze geschéckt.",
        "passwordreset-emailsentusername": "Wann eng E-Mailadress mat dësem Benotzernumm associéiert ass, da gëtt Eng E-Mail fir d'Passwuert zeréckzesetze geschéckt.",
-       "passwordreset-invalideamil": "Net-valabel E-Mail-Adress",
+       "passwordreset-invalidemail": "Net-valabel E-Mail-Adress",
        "passwordreset-nodata": "Et gouf weder e Benotzernumm nach e Passwuert uginn",
        "changeemail": "E-Mail-Adress änneren oder ewechhuelen",
        "changeemail-header": "Fëllt dëse Formulaire aus fir Är E-Mailadress z'änneren.  Wann Dir d'Verbindung tëscht Ärer E-Mailadress an Ärem Benotzerkont ewechhuele wëllt, da loosst d'Feld e-Mailadress eidel wann Dir de Formulaire späichert.",
        "prefs-help-recentchangescount": "Inklusiv Rezent Ännerungen, Versiounshistoriquen a Logbicher.",
        "prefs-help-watchlist-token2": "Dëst ass de geheime Schlëssel fir de Webfeed vun Ärer Iwwerwaachungslëscht. Jiddwereen deen e kennt kann Är Iwwerwaachungslëscht liesen, dofir sollt Dir en net weider ginn. [[Special:ResetTokens|Klickt hei wann Dir en zrécksetze musst]].",
        "savedprefs": "Är Astellunge goufe gespäichert.",
-       "savedrights": "D'Benotzerrechter vum {{GENDER:$1|$1}} goufe gespäichert.",
+       "savedrights": "D'Benotzergruppe vum {{GENDER:$1|$1}} goufe gespäichert.",
        "timezonelegend": "Zäitzon:",
        "localtime": "Lokalzäit:",
        "timezoneuseserverdefault": "De Standardwäert vun der Wiki ($1) benotzen",
        "prefswarning-warning": "Dir hutt Ännerunge vun Ären Astellunge gemaach, déi nach net gespäichert goufen.\n\nWann Dir vun dëser Säit erof gitt ouni op \"$1\" ze klicken, da ginn Är Astellungen net aktualiséiert.",
        "prefs-tabs-navigation-hint": "Tipp: Dir kënnt d'Feiler no lénks an no riets benotze fir tëscht den Tabs an der Lëscht vun den Tabs ze navigéieren.",
        "userrights": "Benotzerrechterverwaltung",
-       "userrights-lookup-user": "Benotzergruppe verwalten",
+       "userrights-lookup-user": "E Benotzer eraussichen",
        "userrights-user-editname": "Benotzernumm uginn:",
-       "editusergroup": "{{GENDER:$1|Benotzer}}gruppen änneren",
+       "editusergroup": "Benotzergruppe lueden",
        "editinguser": "Ännere vun de Rechter vum  {{GENDER:$1|Benotzer}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Benotzergruppen änneren",
        "saveusergroups": "{{GENDER:$1|Benotzer}}gruppe späicheren",
        "userrights-reason": "Grond:",
        "userrights-no-interwiki": "Dir hutt net déi néideg Rechter, fir d'Rechter vu Benoutzer op anere Wikien z'änneren.",
        "userrights-nodatabase": "D'Datebank $1 gëtt et net oder se ass net lokal.",
-       "userrights-nologin": "Dir musst mat engem Administrateurs-Benotzerkont [[Special:UserLogin|ageloggt sinn]], fir Benotzerrechter änneren ze kënnen.",
-       "userrights-notallowed": "Dir hutt net déi néideg Rechter fir Rechter vun anere Benotzer derbäizesetzen oder ewechzehuelen.",
        "userrights-changeable-col": "Gruppen déi Dir ännere kënnt",
        "userrights-unchangeable-col": "Gruppen déi Dir net ännere kënnt",
        "userrights-conflict": "Konflikt bei de Benotzerrechter! Kuckt Är Ännerunge w.e.g. no a maacht se w.e.g. nach eng Kéier.",
-       "userrights-removed-self": "Dir hutt Är eege Rechter ewechgeholl. Dofir kënnt Dir net méi op dës Säit zougräifen.",
        "group": "Grupp:",
        "group-user": "Benotzer",
        "group-autoconfirmed": "Registréiert Benotzer",
        "right-siteadmin": "Datebank spären an d'Spär ophiewen",
        "right-override-export-depth": "Säiten exportéieren inklusiv de verlinkte Säite bis zu enger Déift vu 5",
        "right-sendemail": "Anere Benotzer E-Maile schécken",
-       "right-passwordreset": "Maile vum Zrécksetze vum Passwuert weisen",
        "grant-group-page-interaction": "Mat Säiten interagéieren",
        "grant-group-watchlist-interaction": "Mat Ärer Iwwerwaachungslëscht interagéieren",
        "grant-group-email": "E-Mail schécken",
        "action-upload_by_url": "Fichiere vun enger Internetadress (URL) eropzelueden",
        "action-writeapi": "d'API mat Schreifzougrëff ze benotzen",
        "action-delete": "dës Säit ze läschen",
-       "action-deleterevision": "dës Versioun ze läschen",
-       "action-deletedhistory": "d'Lëscht vun de geläschte Versiounen gesinn",
+       "action-deleterevision": "Versioune läschen",
+       "action-deletedhistory": "déi geläscht Versiounen vun enger Säit weisen",
        "action-browsearchive": "no geläschte Säiten ze sichen",
-       "action-undelete": "dës Säit ze restauréieren",
-       "action-suppressrevision": "déi verstoppt Versioun kucken a restauréieren",
+       "action-undelete": "Säite restauréieren",
+       "action-suppressrevision": "verstoppt Versiounen nokucken a restauréieren",
        "action-suppressionlog": "dës privat Lëscht ze kucken",
        "action-block": "dëse Benotzer fir Ännerungen ze spären",
        "action-protect": "de Protektiounsstatus vun dëser Säit änneren",
        "action-userrights-interwiki": "d'Rechter vu Benotzer vun anere Wikien z'änneren",
        "action-siteadmin": "d'Datebank ze spären oder d'Spär opzehiewen",
        "action-sendemail": "Maile schécken",
+       "action-editmyoptions": "ännert Är Astellungen",
        "action-editmywatchlist": "ännert Är Iwwerwaachungslëscht",
        "action-viewmywatchlist": "kuckt Är Iwwerwaachungslëscht",
        "action-viewmyprivateinfo": "Är privat Informatioune kucken",
        "apisandbox-alert-field": "De wäert vun dësem Feld ass net valabel.",
        "apisandbox-continue": "Virufueren",
        "apisandbox-continue-clear": "Eidel maachen",
+       "apisandbox-param-limit": "Gitt <kbd>max</kbd> fir déi maximal Limite ze benotzen.",
+       "apisandbox-multivalue-all-namespaces": "$1 (All Nummräim)",
+       "apisandbox-multivalue-all-values": "$1 (All Wäerter)",
        "booksources": "Bicherreferenzen",
        "booksources-search-legend": "No Bicherreferenze sichen",
        "booksources-search": "Sichen",
        "activeusers-count": "$1 {{PLURAL:$1|Aktioun|Aktiounen}} {{PLURAL:$3|gëschter|an de leschten $3 Deeg}}",
        "activeusers-from": "Benotzer weisen, ugefaange bei:",
        "activeusers-groups": "Benotzer weisen déi zu de Gruppe gehéieren:",
+       "activeusers-excludegroups": "Benotzer ausschléissen déi zu de Gruppe gehéieren:",
        "activeusers-noresult": "Keng Benotzer fonnt.",
        "activeusers-submit": "Aktiv Benotzer weisen",
        "listgrouprights": "Rechter vun de Benotzergruppen",
        "emailccsubject": "Kopie vun denger Noriicht un $1: $2",
        "emailsent": "E-Mail geschéckt",
        "emailsenttext": "Är E-Mail gouf fortgeschéckt.",
-       "emailuserfooter": "Dës E-Mail gouf  {{GENDER:$1|vum}} $1  {{GENDER:$2|dem}} $2 geschéckt dobäi gouf d'Funktioun \"{{int:emailuser}}\" op {{SITENAME}} benotzt.",
+       "emailuserfooter": "Dës E-Mail gouf {{GENDER:$1|vum}} $1  {{GENDER:$2|dem}} $2 geschéckt dobäi gouf d'Funktioun \"{{int:emailuser}}\" op {{SITENAME}} benotzt. {{GENDER:$2|Är}} E-Mail gëtt direkt un den {{GENDER:$1|originalen Absender}} geschéckt do bäi gesäit  {{GENDER:$1|deen}} {{GENDER:$2|Är}} E-Mail-Adress.",
        "usermessage-summary": "Benoriichtegung hannerloossen.",
        "usermessage-editor": "Benoriichtegungs-System",
        "watchlist": "Iwwerwaachungslëscht",
        "addedwatchtext-short": "D'Säit \"$1\" gouf op Är Iwwerwaachungslëscht derbäigesat.",
        "removewatch": "Vun der Iwwerwaachungslëscht erofhuelen",
        "removedwatchtext": "\"[[:$1]]\" a seng Diskussiounssäit goufe vun Ärer [[Special:Watchlist|Iwwerwaachungslëscht]] erofgeholl.",
+       "removedwatchtext-talk": "\"[[:$1]]\" a seng associéiert Säit goufe vun Ärer [[Special:Watchlist|Iwwerwaachungslëscht]] erofgeholl.",
        "removedwatchtext-short": "D'Säit \"$1\" gouf vun Ärer Iwwerwaachungslëscht erofgeholl.",
        "watch": "Iwwerwaachen",
        "watchthispage": "Dës Säit iwwerwaachen",
        "changecontentmodel-cannot-convert": "Den Inhalt vu(n) [[:$1]] kann net op den Typ $2 ëmgewandelt ginn.",
        "changecontentmodel-nodirectediting": "Den Inhaltsmodell $1 ënnerstëtzt keng direkt Ännerungen",
        "changecontentmodel-emptymodels-title": "Keng Modeller fir Inhalter disponibel",
+       "changecontentmodel-emptymodels-text": "Den Inhalt vu(n) [[:$1]] kann net op een aneren Typ ëmgewandelt ginn.",
+       "log-description-contentmodel": "Evenementer a Relatioun mat den Inhaltsmodeller vun enger Säit",
        "logentry-contentmodel-change-revertlink": "zrécksetzen",
        "logentry-contentmodel-change-revert": "zrécksetzen",
        "protectlogpage": "Protektiounslogbuch",
        "unprotectedarticle": "huet d'Spär vu(n) \"[[$1]]\" opgehuewen",
        "movedarticleprotection": "huet de Säiteschutz vun \"[[$2]]\" op \"[[$1]]\" geännert",
        "protectedarticle-comment": "huet \"[[$1]]\" {{GENDER:$2|gespaart}}",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Huet}} den Niveau vun der Spär vu(n) \"[[$1]]\" geännert",
+       "unprotectedarticle-comment": "{{GENDER:$2|huet}} d'Spär vu(n) \"[[$1]]\" ewechgeholl",
        "protect-title": "Ännerung vun der Protektioun vu(n) „$1“",
        "protect-title-notallowed": "Den Niveau vun der Protektioun vu(n) \"$1\" weisen",
        "prot_1movedto2": "[[$1]] gouf op [[$2]] geréckelt",
        "undeletehistorynoadmin": "Dës Säit gouf geläscht. De Grond fir d'Läsche gesitt der ënnen, zesumme mat der Iwwersiicht vun den eenzele Versioune vun der Säit an hiren Auteuren. Déi verschidden Textversioune kënnen awer just vun Administrateure gekuckt a restauréiert ginn.",
        "undelete-revision": "Geläscht Versioun vu(n) $1 (Versioun vum $4 um $5 Auer) vum $3:",
        "undeleterevision-missing": "Ongëlteg oder Versioun déi feelt. Entweder ass de Link falsch oder d'Versioun gouf aus dem Archiv restauréiert oder geläscht.",
+       "undeleterevision-duplicate-revid": "{{PLURAL:$1|Eng Versioun konnt|$1 Versioune konnten}} net restauréiert ginn, well hir <code>rev_id</code> scho benotzt {{PLURAL:$1|gëtt|ginn}}.",
        "undelete-nodiff": "Et si keng méi al Versiounen do.",
        "undeletebtn": "Restauréieren",
        "undeletelink": "weisen/restauréieren",
        "pageinfo-robot-index": "Erlaabt",
        "pageinfo-robot-noindex": "Net erlaabt",
        "pageinfo-watchers": "Zuel vun de Benotzer déi d'Säit iwwerwaachen",
+       "pageinfo-visiting-watchers": "Zuel vun de Benotzer déi iwwerwaachen déi déi rezent Ännerunge besicht hunn",
        "pageinfo-few-watchers": "Manner wéi $1 {{PLURAL:$1|Benotzer deen iwwerwaacht|Benotzer déi iwwerwaachen}}",
        "pageinfo-redirects-name": "Zuel vun de Viruleedungen op dës Säit",
        "pageinfo-subpages-name": "Ënnersäite vun dëser Säit",
        "newimages-legend": "Filter",
        "newimages-label": "Numm vum Fichier (oder en Deel dovun):",
        "newimages-showbots": "Vu Botten eropgeluede Fichiere weisen",
+       "newimages-hidepatrolled": "Nogekuckt Fichiere verstoppen",
        "noimages": "Keng Biller fonnt.",
        "ilsubmit": "Sichen",
        "bydate": "no Datum",
        "tags-edit-add": "Dës Markéierungen (tags) dobäisetzen:",
        "tags-edit-remove": "Dës Markéierungen (tags) ewechhuelen:",
        "tags-edit-remove-all-tags": "(all Markéierungen ewechhuelen)",
+       "tags-edit-chosen-placeholder": "E puer Markéierungen (tags) eraussichen",
        "tags-edit-chosen-no-results": "Keng Markéierunge fonnt déi passen",
        "tags-edit-reason": "Grond:",
        "tags-edit-revision-submit": "Ännerungen op {{PLURAL:$1|dës Versioun|$1 Versiounen}} uwennen",
        "htmlform-date-toohigh": "De wäert deen Dir aginn hutt ass nom leschten erlaabten Datum vum $1.",
        "htmlform-time-toolow": "De Wäert deen Dir aginn hutt ass virun der éischter erlaabter Zäit vu(n) $1.",
        "htmlform-time-toohigh": "De Wäert deen Dir aginn hutt ass no der leschter erlaabter Zäit vu(n) $1.",
+       "htmlform-datetime-toolow": "De Wäert deen Dir uginn hutt ass virum éischten erlaabten Datum an der Zäit vu(n) $1.",
        "htmlform-datetime-toohigh": "De Wäert deen Dir uginn hutt ass nom leschten erlaabten Datum an der Zäit vu(n) $1.",
        "htmlform-title-badnamespace": "[[:$1]] ass net am Nummraum \"{{ns:$2}}\".",
        "htmlform-title-not-creatable": "\"$1\" ass kee Säitentitel deen ugeluecht ka ginn",
        "logentry-block-unblock": "$1 {{GENDER:$2|huet}} d'Spär vum {{GENDER:$4|$3}} opgehuewen",
        "logentry-import-upload": "$1 {{GENDER:$2|huet}} $3 duerch Eropluede vun engem Fichier importéiert",
        "logentry-import-interwiki": "$1 huet $3 vun enger anerer Wiki {{GENDER:$2|importéiert}}",
+       "logentry-import-interwiki-details": "$1 {{GENDER:$2|huet}} $3 vu(n) $5 importéiert ({{PLURAL:$4|Eng Versioun|$4 Versiounen}})",
        "logentry-move-move": "$1 huet d'Säit $3 op $4 {{GENDER:$2|geréckelt}}",
        "logentry-move-move-noredirect": "$1 huet d'Säit $3 op $4 {{GENDER:$2|geréckelt}} ouni eng Viruleedung unzeleeën",
        "logentry-move-move_redir": "$1 huet d'Säit $3 op $4 {{GENDER:$2|geréckelt}} an derbäi gouf eng Viruleedung iwwerschriwwen",
        "mediastatistics-summary": "Statistike vun den Type vun den eropgeluedene Fichieren. Dobäi gëtt nëmmen déi lescht Versioun vun engem Fichier gezielt, al oder geläscht Versioune vu Fichiere sinn ausgeschloss.",
        "mediastatistics-nbytes": "{{PLURAL:$1|$1 Byte|$1 Byten}} ($2; $3%)",
        "mediastatistics-bytespertype": "Gesamtgréisst vun de Fichiere vun dësem Abschnitt:  {{PLURAL:$1|$1 Byte|$1 Bytes}} ($2; $3%).",
+       "mediastatistics-allbytes": "Gesamtgréisst vun alle Fichieren: {{PLURAL:$1|$1 Byte|$1 Bytes}} ($2).",
        "mediastatistics-table-mimetype": "MIME-Typ",
        "mediastatistics-table-extensions": "Méiglech Erweiderungen",
        "mediastatistics-table-count": "Zuel vun de Fichieren",
        "special-characters-group-thai": "Thai",
        "special-characters-group-lao": "Lao",
        "special-characters-group-khmer": "Khmer",
+       "special-characters-title-endash": "en dash",
+       "special-characters-title-emdash": "em dash",
        "special-characters-title-minus": "Minus-Zeechen",
        "mw-widgets-dateinput-no-date": "Keen Datum erausgesicht",
        "mw-widgets-dateinput-placeholder-day": "JJJJ-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "JJJJ-MM",
+       "mw-widgets-mediasearch-input-placeholder": "No Medie sichen",
+       "mw-widgets-mediasearch-noresults": "Näischt fonnt.",
        "mw-widgets-titleinput-description-new-page": "Säit gëtt et nach net",
        "mw-widgets-titleinput-description-redirect": "viruleeden op $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Eng Kategorie derbäisetzen...",
        "sessionprovider-generic": "$1-Sessiounen",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "cookie-baséiert Sessiounen",
        "sessionprovider-nocookies": "Cookië sinn eventuell desaktivéiert. Vergewëssert Iech datt Dir d'Cookien aktivéiert hutt a probéiert nach eng Kéier.",
        "log-action-filter-import": "Importtyp:",
        "log-action-filter-move": "Réckeltyp:",
        "log-action-filter-protect": "Typ vu Spär",
+       "log-action-filter-rights": "Typ vun Ännerung vu Rechter:",
        "log-action-filter-upload": "Eropluedtyp:",
        "log-action-filter-all": "All",
        "log-action-filter-block-block": "Spären",
        "log-action-filter-block-reblock": "Ännere vun enger Spär",
        "log-action-filter-block-unblock": "Spär ophiewen",
        "log-action-filter-delete-delete": "Säite läschen",
+       "log-action-filter-delete-delete_redir": "Viruleedung iwwerschreiwen",
        "log-action-filter-delete-restore": "Säiterestauratioun",
        "log-action-filter-delete-event": "Logbuch-Läschung",
        "log-action-filter-delete-revision": "Läsche vun enger Versioun",
        "linkaccounts": "Benotzerkonte verbannen",
        "linkaccounts-success-text": "De Benotzerkont gouf verlinkt.",
        "linkaccounts-submit": "Benotzerkonte verbannen",
+       "unlinkaccounts": "Benotzerkonten trennen",
+       "unlinkaccounts-success": "De Benotzerkont gouf getrennt.",
        "userjsispublic": "DEnkt drun: Op JavaScript-Ënnersäite solle keng vertraulech Informatioune stoe well se vun anere Benotzer kënne gesi ginn.",
        "restrictionsfield-badip": "Net valabel IP-Adress oder Beräich: $1",
        "restrictionsfield-label": "Zougeloossen IP-Beräicher:",
-       "edit-error-short": "Feeler: $1",
-       "edit-error-long": "Feeler:\n\n$1"
+       "revid": "r$1"
 }
index dd1e9d4..3a8e61b 100644 (file)
        "yourname": "Nom de usor:",
        "yourpassword": "Sinia de entra:",
        "yourpasswordagain": "Retape la sinia:",
-       "remembermypassword": "Memora me sinia de entra a esta computador (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "Tu domina:",
        "login": "Identifia",
        "nav-login-createaccount": "Sinia per entra",
index af7f9be..7afd6f8 100644 (file)
        "yourname": "Ery'obwa memba",
        "yourpassword": "Ekigambo ekikuumi",
        "yourpasswordagain": "Ddamu ekigambo ekikuumi",
-       "remembermypassword": "Tereka ekigambo kyange ekikuumi ku kompyuta eno (okumala {{PLURAL:$1|olunaku|ennaku ezitasukka mu}} $1)",
        "yourdomainname": "Linnya lya twale lya kayungirizi lyo:",
        "externaldberror": "Waliwo kiremya mu ggwanika lya data ekozesebwa okukakasa bamemba oba tokkirizibwa okukyusa ku akawunti yo ey'awalala.",
        "login": "Yingira",
index 8cc7e7d..a82bd16 100644 (file)
        "activeusers-intro": "Dit is 'n lies mit gebroekers die aktief zeen gewaes in de aafgeloupe {{PLURAL:$1|daag|$1 daag}}.",
        "activeusers-count": "$1 {{PLURAL:$1|bewèrking|bewèrkinger}} inne {{PLURAL:$3|lèsten daag|lès $3 daag}}",
        "activeusers-from": "Tuin gebroekers vanaaf:",
-       "activeusers-hidebots": "Verberg bots",
-       "activeusers-hidesysops": "Verberg admins",
        "activeusers-noresult": "Gein gebroekers gevónje.",
        "listgrouprights": "Rechte van gebroekersgróppe",
        "listgrouprights-summary": "Op dees pazjena sjtaon de gebroekersgróppe in deze wiki besjreve, mit zien biebehurende rechte.\nInfermasie daoreuver èn de individueel rechter vinjs te [[{{MediaWiki:Listgrouprights-helppage}}|hie]].",
index dd2620b..6c2409b 100644 (file)
        "views": "Vìxite",
        "toolbox": "Arneixi",
        "tool-link-userrights": "Modiffica groppi {{GENDER:$1|utente}}",
+       "tool-link-userrights-readonly": "Vixualizza groppi {{GENDER:$1|utente}}",
        "tool-link-emailuser": "Manda un'e-mail a questo {{GENDER:$1|utente}}",
        "userpage": "Veddi a paggina utente",
        "projectpage": "Amia a paggina de serviççio",
        "templatepage": "Vizualizza o modello",
        "viewhelppage": "Vizualizza a paggina d'agiutto",
        "categorypage": "Veddi a paggina da categoria",
-       "viewtalkpage": "Veddi o ciæto",
+       "viewtalkpage": "Amia a paggina de discuscion",
        "otherlanguages": "In âtre lengoe",
        "redirectedfrom": "(Rendirissou da $1)",
        "redirectpagesub": "Paggina de rindirissamento",
        "nstab-category": "Categorîa",
        "mainpage-nstab": "Paggina prinçipâ",
        "nosuchaction": "No se poeu",
-       "nosuchactiontext": "L'açion specificâ inta URL a no l'è vallida.\nO che t'hæ scrito mâ, o che donque l'ea sbaliou o colegamento.\nO magara gh'è 'na cammoa into software doeuviou da {{SITENAME}}.",
+       "nosuchactiontext": "L'açion specificâ inta URL a no l'è vallida.\nÒ che t'hæ scrito mâ, ò che donque l'ea sbaliou l'ingancio.\nÒ magara gh'è 'na cammoa into software dœuviou da {{SITENAME}}.",
        "nosuchspecialpage": "Sta paggina speciale a no gh'è",
        "nospecialpagetext": "<strong>A paggina speciale domandâ a no l'è stæta riconosciua.</strong>\n\nA lista de paggine speciale vallide a se treuva in [[Special:SpecialPages|Lista de paggine speciale]].",
        "error": "Errô",
        "yourpasswordagain": "Riscrivi a pòula segrétta:",
        "createacct-yourpasswordagain": "Conferma a password",
        "createacct-yourpasswordagain-ph": "Conferma a password un'atra votta",
-       "userlogin-remembermypassword": "Mantegnime collegou",
+       "userlogin-remembermypassword": "Mantegnime conligou",
        "userlogin-signwithsecure": "Adoeuvia una conescion segua",
        "cannotlogin-title": "Imposcibbile intrâ",
        "cannotlogin-text": "L'accesso o no l'è poscibbile.",
        "cannotloginnow-text": "Quande s'adoeuvia $1 no se poeu intrâ.",
        "cannotcreateaccount-title": "Imposcibbile creâ di utençe",
        "cannotcreateaccount-text": "A creaçion diretta de l'utença a no l'è attivâ insce questo wiki.",
-       "yourdomainname": "Indirisso do scito:",
+       "yourdomainname": "Adresso do scito:",
        "password-change-forbidden": "No ti peu cangiâ poula segretta in questa wiki.",
        "externaldberror": "Gh'è stæto un aro co-o server de aotenticaçion esterno, oppû no ti g'hæ i aotorizzaçioin pe aggiornâ o to accesso esterno.",
        "login": "Intra",
        "botpasswords-label-delete": "Scassa",
        "botpasswords-label-resetpassword": "Reimposta a poula segretta",
        "botpasswords-label-grants": "Assegnaçioin applicabile:",
-       "botpasswords-help-grants": "Ogni assegnaçion a dà accesso a-i driti utente elencæ che un'utença a g'ha zà. Amia a [[Special:ListGrants|tabella d'e assegnaçioin]] pe de ulteioî informaçioin.",
+       "botpasswords-help-grants": "I assegnaçioin consentan l'accesso a di driti che a to utença a possede zà. Attivâ un'assegnaçion chì no fornisce l'accesso a arcun drito che a to utença atrimenti a no gh'aviæ. Amia a [[Special:ListGrants|tabella di assegnaçioin]] pe ciu informaçioin.",
        "botpasswords-label-grants-column": "Assegnaçioin",
        "botpasswords-bad-appid": "O nomme bot \"$1\" o no l'è vallido.",
        "botpasswords-insert-failed": "Imposcibile azonze o nomme bot \"$1\". O l'è za stæto azonto?",
        "passwordreset-emaildisabled": "E funçionalitæ de posta elettronnica son stæte disabilitæ in sce sta wiki.",
        "passwordreset-username": "Nomme utente",
        "passwordreset-domain": "Dominnio:",
-       "passwordreset-capture": "Visualizzâ o contegnuo do messaggio e-mail?",
-       "passwordreset-capture-help": "Se ti seleçion-i sta casella, l'e-mail (co-a poula segretta temporannia), o saiâ mostròu a ti, oltre ch'a ese inviòu a l'utente.",
        "passwordreset-email": "Addresso e-mail:",
        "passwordreset-emailtitle": "Dettaggi account sciu {{SITENAME}}",
        "passwordreset-emailtext-ip": "Quarcun (probabilmente ti, con adresso IP $1) o l'ha domandòu l'invio de 'na neuva poula segretta per l'accesso a {{SITENAME}} ($4). {{PLURAL:$3|L'utente associòu|I utenti associæ}} a sto addresso e-mail son:\n\n$2\n\n{{PLURAL:$3|Questa poula segretta temporannia a descazziâ|Queste poule segrette temporannie descazzian}} doppo {{PLURAL:$5|un giorno|$5 giorni}}.\nTi doviesci accede e çerne una neuva poula segretta oua. \n\nSe no t'ê stæto ti a fâ a domanda, ò se ti t'hæ aregordòu a poula segretta originale e no ti veu ciù cangiâla, ti peu ignorâ sto messaggio e continuâ a deuviâ a teu vegia poula segretta.",
        "passwordreset-emailelement": "Nomme utente: \n$1\n\nPoula segretta temporannia: \n$2",
        "passwordreset-emailsentemail": "Se questo addresso de posta elettronnica o l'è associou a-a teu utença, alloa saiâ inviou un'e-mail pe rempostâ a poula segretta.",
        "passwordreset-emailsentusername": "Se gh'è un adreçço de posta elettronica associou con questo nomme utente, alloa saiâ inviou una email pe rempostâ a password.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|L'|E }}e-mail de rempostaçion da password {{PLURAL:$1|a l'è stæta inviâ|son stæte inviæ}}. {{PLURAL:$1|O nomme|L'elenco di nommi}} utente e password o l'è mostrou chì.",
-       "passwordreset-emailerror-capture2": "Invio d'e-mail {{GENDER:$2|a l'utente}} non ariescio: $1. {{PLURAL:$3|O nomme|L'elenco di nommi}} utente e password o l'è mostrou chì de sotta.",
        "passwordreset-nocaller": "Un chi ciamma ti g'hæ da dâlo",
        "passwordreset-nosuchcaller": "O ciamante o no l'existe: $1",
        "passwordreset-ignored": "A reimpostaçion da password a no l'è stæta gestia. Foscia n'è stæto configuou nisciun provider ?",
-       "passwordreset-invalideamil": "Addresso e-mail non vallido",
+       "passwordreset-invalidemail": "Addresso e-mail non vallido",
        "passwordreset-nodata": "No è stæto fornio ni un nomme utente ni un adreçço de posta elettronica",
        "changeemail": "Cangia o elimmina l'adresso e-mail",
        "changeemail-header": "Completa sto formulaio pe cangiâ o to adresso e-mail. Se ti veu rimeuve l'associaçion de quasesegge addresso e-mail da-a teu utensa, lascia io neuvo addresso e-mail veuo quande ti invii o formulaio.",
        "image_sample": "Exempio.jpg",
        "image_tip": "Incorpora file",
        "media_sample": "Exempio.ogg",
-       "media_tip": "Colegaménto a file moltimediâ",
+       "media_tip": "Ingancio a file moltimediâ",
        "sig_tip": "Firma con dæta e ôa",
        "hr_tip": "Linnia orizontâ",
        "summary": "Oggetto:",
        "previewnote": "'''Questa chì a l'è solo 'n'anteprimma; i cangiamenti no son ancon stæti sarvæ!'''",
        "continue-editing": "Vanni a l'area de modiffica",
        "previewconflict": "L'anteprimma a mostra o scrito presente inta casella de modiffica de d'ato coscì comme o l'apaiâ se ti çerni de sarvalo òua.",
-       "session_fail_preview": "Spiaxenti. No è stæto poscibile elaboâ a modifica perché son andæti persci i dæti relativi a-a sescion.\n\nFoscia t'ê stæto disconnesso. <strong>Verifica d'ese ancon collegou e riproeuva</strong>.\nSe o problema o persciste, ti poeu provâ a [[Special:UserLogout|scollegate]] e effettuâ un nuoeuvo accesso, controllando che o to browser o l'açette i cookie da questo scito.",
+       "session_fail_preview": "Spiaxenti. No l'è stæto poscibile elaboâ a modiffica pe via da pèrdia di dæti relativi a-a sescion.\n\nFoscia t'ê stæto disconesso. <strong>Veifica d'ese ancon conligou e prœuva torna</strong>.\nSe o problema o persciste, ti pœu provâ a [[Special:UserLogout|scollegate]] e effetoâ un nœuvo accesso, controlando che o to navegatô o l'açette i cookie da questo scito.",
        "session_fail_preview_html": "Spiaxenti. No è stæto poscibbile elaboâ a modifica perché son anæti persci i dæti relativi a-a sescion.\n\n<em>Scicomme {{SITENAME}} o g'ha de l'HTML sgroeuzzo attivou e gh'è stæto una perdia di dæti da sescion, l'anteprimma a l'è ascosa comme precaoçion contra i attacchi JavaScript.</em>\n\n<strong>Se se tratta de un normale tentativo d'anteprimma, riproeuva.</strong> \nSe o problema o persciste, ti poeu provâ a [[Special:UserLogout|scollegati]] e effettuâ un noeuvo accesso, controllando che o to browser o l'açette i cookie da questo scito.",
        "token_suffix_mismatch": "'''A modiffica a no l'è stæta sarvâ perché o to client o l'ha mostrou de gestî in moddo errou i carattei de puntezatua into token associou a-a mæxima. Pe evitâ una poscibile corruçion do testo da pagina, l'è stæto refuou l'intrega modiffica. Questa scituaçion a poeu veificase, de votte, quande s'adoeuvia di serviççi de proxy anonnimi via web che presentan di bug.'''",
        "edit_form_incomplete": "'''De parte do formulaio de modiffica n'han razonto o server; controlla che e modiffiche seggian intatte e ripreuva.'''",
        "search-external": "Riçerca esterna",
        "searchdisabled": "A riçerca de {{SITENAME}} a no l'è attiva. Into fratempo ti peu çercâ in sce Google. \nNotta che i so indexi di contegnui de {{SITENAME}} porrieivan no ese aggiornæ.",
        "search-error": "S'è verificou 'n errô durante a riçerca: $1",
+       "search-warning": "Gh'è stæto in alerta durante a çerchia: $1",
        "preferences": "Preferençe",
        "mypreferences": "Preferençe",
        "prefs-edits": "Modiffiche effettuæ:",
        "prefs-help-recentchangescount": "Comprende i urtime modiffiche, paggine de stoie e registri.",
        "prefs-help-watchlist-token2": "Questa a l'è a ciave segretta pe-o feed web di to oservæ.\nChiunque a conosce saiâ in graddo de leze i to oservæ, quindi no stanni a condividdila. [[Special:ResetTokens|Clicca chi se ti g'hæ de besoeugno de rempostâla]].",
        "savedprefs": "E teu preferençe son stæte sarvæ.",
-       "savedrights": "I driti utente de {{GENDER:$1|$1}} son stæti sarvæ.",
+       "savedrights": "I groppi utente de {{GENDER:$1|$1}} son stæti sarvæ.",
        "timezonelegend": "Fuso oraio:",
        "localtime": "Oa locale:",
        "timezoneuseserverdefault": "Adeuvia l'oa predefinia do wiki ($1)",
        "prefswarning-warning": "T'hæ fæto de modiffiche a-e teu preferense che no son ancon stæte sarvæ.\nSe ti sciorti da sta paggina sensa sciaccâ \"$1\" e preferense no saian agiornæ.",
        "prefs-tabs-navigation-hint": "Suggeimento: ti peu deuviâ i pomelli co-a freccia scinistra e drita pe navegâ tra e schede inta lista de schede.",
        "userrights": "Manezzo di driti di utenti",
-       "userrights-lookup-user": "Gestisci i gruppi di utenti",
+       "userrights-lookup-user": "Seleçion-a un utente",
        "userrights-user-editname": "Scrivi o teu nomme utente:",
-       "editusergroup": "Modiffica groppi {{GENDER:$1|utente}}",
+       "editusergroup": "Carrega groppi utente",
        "editinguser": "Apreuvo a cangiâ i driti de l'{{GENDER:$1|utente}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modiffica i gruppi di utenti",
        "saveusergroups": "Sarva groppi {{GENDER:$1|utente}}",
        "userrights-reason": "Raxon:",
        "userrights-no-interwiki": "No ti g'hæ i permissi pe modificâ i driti di utenti insce di atre wiki.",
        "userrights-nodatabase": "O database $1 o no l'esiste ò o no l'è un database locale.",
-       "userrights-nologin": "Pe assegnâ di driti a-i utenti ti g'hæ da [[Special:UserLogin|intrâ]] comme amministratô.",
-       "userrights-notallowed": "No ti g'hæ o permisso de azonze ò rimeuve i driti di utenti.",
        "userrights-changeable-col": "Gruppi che ti peu modificâ",
        "userrights-unchangeable-col": "Gruppi che no ti peu modificâ",
        "userrights-conflict": "Conflito de modiffica di driti utente! Pe piaxei controlla e conferma e teu modiffiche.",
-       "userrights-removed-self": "T'hæ rimosso i teu driti. E quindi, no ti saiæ ciù in grou de accede a questa paggina.",
        "group": "Gruppo:",
        "group-user": "Ûtenti",
        "group-autoconfirmed": "Utenti aotoconfermæ",
        "right-siteadmin": "Abbrocca e sbrocca o database",
        "right-override-export-depth": "Esporta e paggine includendo e pagine collegæ scin a 'na profonditæ de 5",
        "right-sendemail": "Manda de email a di atri utenti",
-       "right-passwordreset": "Vedde i messaggi de rempostaçion da password",
        "right-managechangetags": "Crea e attiva/disattiva i [[Special:Tags|etichette]]",
        "right-applychangetags": "Apprica di [[Special:Tags|etichette]] a-e proppie modiffiche",
        "right-changetags": "Azonze e leva de specifiche [[Special:Tags|etichette]] insce scingole verscioin o voxe de registro",
        "grant-generic": "Pacchetto diritti \"$1\"",
        "grant-group-page-interaction": "Interagisce co-e paggine",
        "grant-group-file-interaction": "Interagisce co-i file murtimediali",
-       "grant-group-watchlist-interaction": "Interagisce con i to oservæ speçiali",
+       "grant-group-watchlist-interaction": "A l'interagisce co-i to oservæ speciali",
        "grant-group-email": "Invia email",
        "grant-group-high-volume": "Esegue açioin mascive",
        "grant-group-customization": "Personalizzaçion e preferençe",
        "grant-basic": "Driti de base",
        "grant-viewdeleted": "Vedde i file e e pagine scassæ",
        "grant-viewmywatchlist": "Vedde i to öservæ speçiali",
+       "grant-viewrestrictedlogs": "Amia i valoî privæ do registro",
        "newuserlogpage": "Nêuvi utenti",
        "newuserlogpagetext": "Questo o l'è un registro de creaçioin di utençe.",
        "rightslog": "Diritti d'ûtente",
        "recentchangeslinked-feed": "Cangiamenti correlæ",
        "recentchangeslinked-toolbox": "Cangiaménti corelæ",
        "recentchangeslinked-title": "Modiffiche correlæ a \"$1\"",
-       "recentchangeslinked-summary": "Sta pàgina a fa védde i cangiaménti ciù reçenti a-e pàgine colegæ a questa.\nE pàgine che t'æ in oservaçion inti [[Special:Watchlist|oservæ speciâli]] son in '''grascetto'''.",
+       "recentchangeslinked-summary": "Sta paggina a fa védde i cangiaménti ciù reçenti a-e pàggine conligæ a questa.\nE pàggine che t'hæ in oservaçion inti [[Special:Watchlist|oservæ speciâli]] son in '''grascetto'''.",
        "recentchangeslinked-page": "Nómme da pàgina:",
-       "recentchangeslinked-to": "Fanni védde sôlo i cangiaménti a-e pàgine colegæ a-a pàgina specificâ",
+       "recentchangeslinked-to": "Fanni védde sôlo i cangiaménti a-e pàggine conligæ a-a pàggina specificâ",
        "recentchanges-page-added-to-category": "[[:$1]] azonto a-a categoria",
        "recentchanges-page-added-to-category-bundled": "[[:$1]] azonta a-a categoria, [[Special:WhatLinksHere/$1|questa pagina a l'è inclusa a l'interno di atre pagine]]",
        "recentchanges-page-removed-from-category": "[[:$1]] rimosso da-a categoria",
        "uploaded-script-svg": "Trovou elemento de script \"$1\" into file caregou in formato SVG.",
        "uploaded-hostile-svg": "Trovou CSS no seguo inte l'elemento de stile do file in formato SVG caregou.",
        "uploaded-event-handler-on-svg": "Impostâ i attributi de gestion di eventi <code>$1=\"$2\"</code> no l'è consentio inti file SGV",
-       "uploaded-href-attribute-svg": "i attributi href inti file SVG poeuan collegâse solo verso e destinaçioin http:// o https://, trovou <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploaded-href-attribute-svg": "i attributi href inti file SVG pœuan ese inganciæ solo ch'a-e destinaçioin http:// o https://, trovou <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "uploaded-href-unsafe-target-svg": "Trovou href a dæti non segui: destinaçion URI <code>&lt;$1 $2=\"$3\"&gt;</code> caregou into file SVG",
        "uploaded-animate-svg": "Trovou o tag \"animate\" ch'o poriæ cangiâ href, doeuviando l'attributo \"from\" <code>&lt;$1 $2=\"$3\"&gt;</code> into file SVG caregou.",
        "uploaded-setting-event-handler-svg": "A configuaçion di attributi pe-o gestô di eventi a l'è bloccâ, trovou <code>&lt;$1 $2=\"$3\"&gt;</code> into file SVG caregou.",
        "imagelinks": "Ûzo do file",
        "linkstoimage": "{{PLURAL:$1|A segoente pàgina a contegne|E segoenti $1 pàgine contegnan}} colegaménti a-o file:",
        "linkstoimage-more": "Ciù de $1 {{PLURAL:$1|pagina aponta|pagine apontan}} a questo file.\nA seguente lista a mostra {{PLURAL:$1|a primma paggina ch'a l'aponta|e primme $1 paggine ch'apontan}} a sto file.\nL'è disponibile un [[Special:WhatLinksHere/$2|elenco completo]].",
-       "nolinkstoimage": "No gh'è nisciûnn-a pàgina collegâ con 'sto file.",
+       "nolinkstoimage": "No gh'è nisciun-a paggina inganciâ a sto file.",
        "morelinkstoimage": "Vixualizza [[Special:WhatLinksHere/$1|di atri inganci]] a questo file.",
        "linkstoimage-redirect": "$1 (rendriççamento file) $2",
        "duplicatesoffile": "{{PLURAL:$1|O seguente file o l'è un dupricou|I seguenti $1 file son di dupricæ}} de questo file ([[Special:FileDuplicateSearch/$2|urteioî detaggi]]):",
        "mimetype": "Tipo MIME:",
        "download": "scarrega",
        "unwatchedpages": "Paggine non öservæ",
-       "listredirects": "Lista de rindirissamenti",
+       "listredirects": "Lista di rendriççi",
        "listduplicatedfiles": "Lista di file doggi",
        "listduplicatedfiles-summary": "Questo o l'è un elenco di file, donde a verscion ciù reçente de 'n file a l'è un dupricou da verscion ciù reçente de 'n atro file. Se piggia in  conscideraçion solo che i file locali.",
        "listduplicatedfiles-entry": "[[:File:$1|$1]] o g'ha [[$3|{{PLURAL:$2|un duplicou|$2 duplicæ}}]].",
        "pageswithprop-submit": "Vanni",
        "pageswithprop-prophidden-long": "valô testoale longo da propietæ ascoso ($1)",
        "pageswithprop-prophidden-binary": "valô binaio da propietæ ascoso ($1)",
-       "doubleredirects": "Rindirissamenti doggi",
+       "doubleredirects": "Rendriççi doggi",
        "doubleredirectstext": "In questa pagina gh'è elencou e paggine che rendiriççan a di atre paggine de redirect.\nOgni riga a conten i collegamenti a-o primmo e a-o segondo redirect, oltre a-a primma riga de testo do segondo redirect che a l'uso o conten a paggina de destinaçion \"corretta\" a-a quæ doviæ puntâ o primmo redirect ascì.\nI redirect <del>scassæ</del> son stæti corretti.",
        "double-redirect-fixed-move": "[[$1]] o l'è stæto mesciou.\nO l'è stato aggiornou aotomaticamente e oua o l'è un redirect a [[$2]].",
        "double-redirect-fixed-maintenance": "Corretto aotomaticamente o redirect doggio da [[$1]] a [[$2]] into travaggio de manutençion.",
        "double-redirect-fixer": "Correttô di redirect",
        "brokenredirects": "Rindirissamenti sballiæ",
-       "brokenredirectstext": "I rendriççi chì de sotta colegan a de paggine inexistente:",
+       "brokenredirectstext": "I rendriççi chì de sotta apontan a de paggine inexistente:",
        "brokenredirects-edit": "cangia",
        "brokenredirects-delete": "scassa",
        "withoutinterwiki": "Paggine sensa interwiki",
        "ntransclusions": "Doeuviou inte $1 {{PLURAL:$1|paggina|paggine}}",
        "specialpage-empty": "Questa paggina speciale a l'è attualmente voeua.",
        "lonelypages": "Paggine orfane",
-       "lonelypagestext": "E seguente paggine no son incluse ni colegæ a di atre paggine de {{SITENAME}}.",
+       "lonelypagestext": "E seguente paggine no son incluse ni conligæ a di atre paggine de {{SITENAME}}.",
        "uncategorizedpages": "Paggine sensa categorîa",
        "uncategorizedcategories": "Categorîe sensa categorîa",
        "uncategorizedimages": "Immaggini sensa categorîa",
        "unusedimages": "File inutilizæ",
        "wantedcategories": "Categorîe domandæ",
        "wantedpages": "Paggine domandæ",
-       "wantedpages-summary": "Lista de paggine inexistente co-o ciu gran nummero de collegamenti a lô, escludendo e pagine ch'han solo che i rendiriççi che-e collegan. Pe 'n elenco de pagine inexistente che g'han di rendriççi che-e collegan, amia [[{{#special:BrokenRedirects}}|a lista di rendriççi erræ]].",
+       "wantedpages-summary": "Lista de paggine inexistente co-o ciu gran nummero d'inganci a lô, escludendo e pagine inganciæ solo che da di rendriççi. Pe 'na lista de pagine inexistente inganciæ da di rendriççi, amia [[{{#special:BrokenRedirects}}|a lista di rendriççi erræ]].",
        "wantedpages-badtitle": "Tittolo invallido into groppo di risultæ: $1",
        "wantedfiles": "File domandæ",
        "wantedfiletext-cat": "I seguenti file son in doeuvia, ma no existan. I file ospitæ inte di repository esterni porieivan esighe elencæ sciben che existan. Questi fasci poxitivi saian <del>barræ</del>. E pagine che incòrpoan i file che no existan son elencæ in [[:$1]].",
        "ancientpages": "Paggine ciû vëgie",
        "move": "Mescia",
        "movethispage": "Mescia 'sta paggina",
-       "unusedimagestext": "I seguenti file existan ma no son doeuviæ inte nisciun-a paggina.\nNotta che di atri sciti web porieivan ese colegæ a 'n file co-in URL diretto, e coscì o poriæ ese inte sta lista sciuben ch'o segge in doeuvia.",
+       "unusedimagestext": "I seguenti file existan ma no son doeuviæ inte nisciun-a paggina.\nNotta che di atri sciti web porieivan ese conligæ a 'n file co-in URL diretto, e coscì o poriæ ese inte sta lista sciuben ch'o segge in doeuvia.",
        "unusedcategoriestext": "E seguente paggine de categoria existan, sciben che nisciun'atra paggina o categoria a-e doeuvie.",
        "notargettitle": "Dæti mancanti",
        "notargettext": "No t'hæ indicou una pagina o un utente con chi eseguî sta fonçion.",
        "apisandbox-alert-field": "O valô de questo campo o no l'è vallido.",
        "apisandbox-continue": "Continnoa",
        "apisandbox-continue-clear": "Nettezza",
+       "apisandbox-param-limit": "Inseisci <kbd>max</kbd> pe doeuviâ o limmite mascimo.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Tutti i namespace)",
+       "apisandbox-multivalue-all-values": "$1 (Tutti i valoî)",
        "booksources": "Fonte libraie",
        "booksources-search-legend": "Çerca e fonti",
        "booksources-isbn": "Codice ISBN:",
        "booksources-search": "Çerca",
        "booksources-text": "De sotta unn-a lista d'inganci a di ätri sciti che vendan libbri neuvi e vegi e che porrieivan avei ciu informaçioin in scî libbri che ti çerchi",
        "booksources-invalid-isbn": "O ISBN inserio pâ no ese vallido; controlla che no ghe segge stæto di ari into copiâlo da-a fonte originale.",
+       "magiclink-tracking-rfc": "Paggine ch'adoeuvian di inganci maggichi RFC",
+       "magiclink-tracking-rfc-desc": "Sta paggina a l'adoeuevia di inganci maggichi RFC. Amia [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] insce comme ezeguî a migraçion.",
+       "magiclink-tracking-pmid": "Paggine ch'adoeuvian di inganci maggichi PMID",
+       "magiclink-tracking-pmid-desc": "Sta paggina a l'adoeuvia dio inganci maggichi PMID. Amia [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sciu comme exeguî a migraçion.",
        "specialloguserlabel": "Açion effettuâ da:",
        "speciallogtitlelabel": "Açion effettuâ sciu (tittolo da paggina ò {{ns:user}}:Nomme utente):",
        "log": "Log",
        "rollbackfailed": "Rollback fallio",
        "rollback-missingparam": "Parammetri obrigatoi mancanti inta recesta.",
        "rollback-missingrevision": "Imposcibile caregâ i dæti da verscion.",
-       "cantrollback": "No se peu tornâ inderê; l'utente ch'o l'ha fæto quelle modiffiche o l'è stæto l'unico contribuente.",
+       "cantrollback": "No se poeu tornâ inderê; l'utente ch'o l'ha fæto quelle modiffiche o l'è stæto l'unico contributô.",
        "alreadyrolled": "No l'è poscibbile annullâ e modiffiche apportæ a-a pagina [[:$1]] da parte de [[User:$2|$2]] ([[User talk:$2|discuscion]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); un atro utente o l'ha zà modificou a pagina oppù o l'ha effettuou o rollback.\n\nA modifica ciù reçente a.a paggina a l'è stæta apportâ da [[User:$3|$3]] ([[User talk:$3|discuscion]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "L'ogetto da modiffica o l'ea: <em>$1</em>.",
        "revertpage": "Annullou e modiffiche de [[Special:Contributions/$2|$2]] ([[User talk:$2|discuscion]]), riportâ a-a verscion precedente de [[User:$1|$1]]",
        "nolinkshere-ns": "Pagine ch'apontan a '''[[:$1]]''' into namespace seleçionou no ghe n'è.",
        "isredirect": "Paggina de rindirissamento",
        "istemplate": "Incluxon",
-       "isimage": "Colegamento a file",
+       "isimage": "Ingancio a-o file",
        "whatlinkshere-prev": "{{PLURAL:$1|precedente|precedenti $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|sûccescivo|sûccescivi $1}}",
        "whatlinkshere-links": "← colegaménti",
        "export-addns": "Azonzi",
        "export-download": "Sarva comme file",
        "export-templates": "Inciodi i template",
-       "export-pagelinks": "Includdi paggine colegæ scin a 'na profonditæ de:",
+       "export-pagelinks": "Includdi paggine conligæ scin a 'na profonditæ de:",
        "export-manual": "Azonzi paggine manoalmente:",
        "allmessages": "Messaggi do scistema",
        "allmessagesname": "Nomme",
        "import-nonewrevisions": "Nisciun-a verscion importâ (ean zà tutte presente, ò satæ pe via di erroî)",
        "xml-error-string": "$1 a-a riga $2, colonna $3 (byte $4): $5",
        "import-upload": "Carrega dæti XML",
-       "import-token-mismatch": "I dæti relativi a-a sescion son anæti persci. Riproeuva.\nFoscia t'ê stæto disconnesso. <strong>Verifica d'ese ancon collegou e riproeuva</strong>.\nSe o problema o persciste, ti poeu provâ a [[Special:UserLogout|scollegate]] e effettuâ un nuoeuvo accesso, controllando che o to browser o l'açette i cookie da questo scito.",
+       "import-token-mismatch": "I dæti relativi a-a sescion son anæti persci. Riprœuva.\nFoscia t'ê stæto disconnesso. <strong>Verifica d'ese ancon conligou e riprœuva</strong>.\nSe o problema o persciste, ti pœu provâ a [[Special:UserLogout|sconligâte]] e effettuâ un nœuvo accesso, controlando che o to navegatô o l'açette i cookie da questo scito.",
        "import-invalid-interwiki": "Imposcibbile importâ da-o progetto wiki indicou.",
        "import-error-edit": "A paggina \"$1\" a no l'è stæta importâ perché no t'ê aotorizzou a modificâla.",
        "import-error-create": "A paggina \"$1\" a no l'è stæta importâ perché no t'ê aotorizzou a creâla.",
        "tooltip-n-recentchanges": "I ùrtimi cangiaménti into scîto",
        "tooltip-n-randompage": "Fanni vedde 'na pagina a brettio.",
        "tooltip-n-help": "Pagine d'agiùtto",
-       "tooltip-t-whatlinkshere": "Lista de tùtte e pagine che son colegæ a sta chì.",
-       "tooltip-t-recentchangeslinked": "Ùrtimi càngi de pàgine colegæ a quésta",
+       "tooltip-t-whatlinkshere": "Lista de tùtte e paggine ch'en conligæ a sta chì.",
+       "tooltip-t-recentchangeslinked": "Ùrtimi càngi de pàggine conligæ a questa",
        "tooltip-feed-rss": "Feed RSS pe questa paggina",
        "tooltip-feed-atom": "Feed Atom pe sta pàgina",
        "tooltip-t-contributions": "Lista de contribûssioin de {{GENDER:$1|questo|questa}} utente",
        "newimages-hidepatrolled": "Ascondi i caregamenti controlæ",
        "noimages": "No gh'è ninte da vedde.",
        "ilsubmit": "Çerca",
-       "bydate": "pe dâta",
+       "bydate": "pe dæta",
        "sp-newimages-showfrom": "Mostra i file ciù reçenti a partî da-e oe $2 do $1",
        "seconds": "{{PLURAL:$1|un segondo|$1 segondi}}",
        "minutes": "{{PLURAL:$1|un menuto|$1 menuti}}",
        "exif-pixelxdimension": "Largheçça immaggine",
        "exif-pixelydimension": "Ateçça immaggine",
        "exif-usercomment": "Notte de l'utente",
-       "exif-relatedsoundfile": "File audio collegou",
+       "exif-relatedsoundfile": "File audio conligou",
        "exif-datetimeoriginal": "Dæta e oa de creassion di dæti",
        "exif-datetimedigitized": "Dæta e oa de digitalizzaçion",
        "exif-subsectime": "Dæta e oa, fraçioin de segondo",
        "exif-originaldocumentid": "ID univvoco do documento origin*a",
        "exif-licenseurl": "URL pe-a liçença do copyright",
        "exif-morepermissionsurl": "Informaçioin insce e liçençe alternative",
-       "exif-attributionurl": "Se quest'oeuvia ti l'adoeuvi torna, pe piaxei coleghite a",
+       "exif-attributionurl": "Se quest'œuvia ti l'adœuvi torna, pe piaxei metti 'n ingancio a",
        "exif-preferredattributionname": "Se quest'oeuvia ti l'adoeuvi torna, pe piaxei attribuiscine a paternitæ a",
        "exif-pngfilecomment": "Commento do file JPEG",
        "exif-disclaimer": "Avertençe",
        "confirmemail_loggedin": "L'adreçço e-mail o l'è stæto confermou.",
        "confirmemail_subject": "{{SITENAME}}: recesta de conferma de l'adreççoo",
        "confirmemail_body": "Quarcun, foscia ti mæximo da l'adreçço IP $1, o l'ha registrou l'utença \"$2\" insce {{SITENAME}} indicando questo adreçço e-mail.\n\nPe confermâ che l'utença a t'apparten da vei e attivâ e fonçioin relative a l'invio di e-mail insce {{SITENAME}}, arvi o collegamento seguente co-o to navegatô:\n\n$3\n\nSe *no* t'ê stæto ti a registrâ l'utença, segui sto colegamento pe annulâ a conferma de l'adreçço e-mail:\n\n$5\n\nQuesto coddiçe de conferma o descaziâ aotomaticamente a $4.",
-       "confirmemail_body_changed": "Quarcun, foscia ti mæximo da l'adreçço IP $1, o l'ha modificou l'adreçço e-mail de l'utença \"$2\" insce {{SITENAME}} indicando questo adreçço e-mail.\n\nPe confermâ che l'utença a t'apparten da vei e riattivâ e fonçioin relative a l'invio di e-mail insce {{SITENAME}}, arvi o collegamento seguente co-o to navegatô:\n\n$3\n\nSe l'utença a *no* t'aparten, segui sto colegamento pe annulâ a conferma de l'adreçço e-mail:",
-       "confirmemail_body_set": "Quarcun, foscia ti mæximo da l'adreçço IP $1, o l'ha impostcou l'adreçço e-mail de l'utença \"$2\" insce {{SITENAME}} indicando questo adreçço e-mail.\n\nPe confermâ che l'utença a t'apparten da vei e attivâ e fonçioin relative a l'invio di e-mail insce {{SITENAME}}, arvi o collegamento seguente co-o to navegatô:\n\n$3\n\nSe l'utença a *no* t'aparten, segui sto colegamento pe annulâ a conferma de l'adreçço e-mail:",
+       "confirmemail_body_changed": "Quarcun, foscia ti mæximo da l'adresso IP $1, o l'ha modificou l'adresso e-mail de l'utença \"$2\" insce {{SITENAME}} indicando questo adresso e-mail.\n\nPe confermâ che l'utença a t'apparten davei e riattivâ e fonçioin relative a l'invio di e-mail insce {{SITENAME}}, arvi l'ingancio seguente co-o to navegatô:\n\n$3\n\nSe l'utença a *no* t'aparten, segui st'ingancio pe annulâ a conferma de l'adresso e-mail:",
+       "confirmemail_body_set": "Quarcun, foscia ti mæximo da l'adresso IP $1, o l'ha impostou l'adresso e-mail de l'utença \"$2\" insce {{SITENAME}} indicando questo adresso e-mail.\n\nPe confermâ che l'utença a t'aparten davei e attivâ e fonçioin relative a l'invio di e-mail insce {{SITENAME}}, arvi l'ingancio seguente co-o to navegatô:\n\n$3\n\nSe l'utença a *no* t'aparten, segui st'ingancio pe annulâ a conferma de l'adresso e-mail:",
        "confirmemail_invalidated": "Recesta de conferma adreçço e-mail annulâ",
        "invalidateemail": "Annulla a recesta de conferma e-mail",
        "notificationemail_subject_changed": "L'adreçço de posta elettronica registrou insce {{SITENAME}} o l'è stæto modificou",
        "json-error-recursion": "Un o ciù rifeimenti ricorscivi into valô da codificâ",
        "json-error-inf-or-nan": "Un ò ciu valoî NAN o INF into valô da codificâ",
        "json-error-unsupported-type": "L'è stæto fornio un valô de un tipo ch'o no poeu ese codificou",
-       "headline-anchor-title": "Colegamento a questa seçion",
+       "headline-anchor-title": "Ingancio a questa seçion",
        "special-characters-group-latin": "Latin",
        "special-characters-group-latinextended": "Latin esteiso",
        "special-characters-group-ipa": "IPA",
        "authmanager-authn-not-in-progress": "L'aotenticaçion a no l'è in corso ò i dæti da sescion son anæti persci. Se prega de recomençâ da cavo.",
        "authmanager-authn-no-primary": "E credençiæ fornie no poeuan ese aotenticæ.",
        "authmanager-authn-no-local-user": "E credençiæ fornie no son associæ a nisciun utente de questo wiki.",
-       "authmanager-authn-no-local-user-link": "E credençiæ fornie son vallide ma no son associæ a nisciun utente de questa wiki. Accedi inte 'n atro moddo ò crea un noeuvo utente, e ti gh'aviæ 'n'opçion pe collegâ e to credençiæ precedente a quell'utença.",
+       "authmanager-authn-no-local-user-link": "E credençiæ fornie son vallide ma no son associæ a nisciun utente de questa wiki. Accedi inte 'n atro moddo ò crea un nœuvo utente, e ti gh'aviæ 'n'opçion pe conligâ e to credençiæ precedente a quell'utença.",
        "authmanager-authn-autocreate-failed": "Creaçion aotomattica de 'n'utença locale fallia: $1",
        "authmanager-change-not-supported": "E credençiæ fornie no poeuan ese modificæ, dæto che no saieivan doeuviæ da ninte.",
        "authmanager-create-disabled": "A creaçion di utençe a l'è disabilitâ.",
        "authmanager-create-from-login": "Pe creâ a to utença, completa i campi chì de sotta.",
        "authmanager-create-not-in-progress": "A creaçion de un'utença a no l'è in corso ò i dæti da sescion son anæti perdui. Se prega de recomençâ da cavo.",
        "authmanager-create-no-primary": "E credençiæ fornie no poeuan ese doeuviæ pe-a creaçion de l'utença.",
-       "authmanager-link-no-primary": "E credençiæ fornie no poeuan ese doeuviæ pe-o colegamento de l'utença.",
-       "authmanager-link-not-in-progress": "O colegamento de l'utença o no procede ò i dæti da sescion so-anæti perdui. Se prega de recomençâ da cavo.",
+       "authmanager-link-no-primary": "E credençiæ fornie no pœuan ese dœuviæ pe conligâ l'utença.",
+       "authmanager-link-not-in-progress": "O conligamento de l'utença o no procede ò i dæti da sescion so-anæti perdui. Se prega de recomençâ da cavo.",
        "authmanager-authplugin-setpass-failed-title": "Modiffica da password fallia",
        "authmanager-authplugin-setpass-failed-message": "O plugin d'aotenticaçion o l'ha impedio a modiffica da password.",
        "authmanager-authplugin-create-fail": "O plugin d'aotenticaçion o l'ha impedio a creaçion de l'utença.",
        "authmanager-provider-temporarypassword": "Password temporannia",
        "authprovider-confirmlink-message": "Basandose insce di reçenti tentativi d'accesso, e seguente utençe poeuan ese collegæ a-o to account wiki. Collegandole ti poeu effettuâ l'accesso con quelle ascì. Se prega de seleçionâ quelle che devan ese collegæ.",
        "authprovider-confirmlink-request-label": "Utençe che dovieivan ese collegæ",
-       "authprovider-confirmlink-success-line": "$1: collegou correttamente.",
+       "authprovider-confirmlink-success-line": "$1: inganciou correttamente.",
        "authprovider-confirmlink-failed": "O collegamento de l'utença o no l'è pin-amente ariescio: $1",
        "authprovider-confirmlink-ok-help": "Continnoa doppo a visualizzaçion di messaggi de errô de collegamento.",
        "authprovider-resetpass-skip-label": "Sata",
        "authprovider-resetpass-skip-help": "Sata a rempostaçion da password.",
-       "authform-nosession-login": "L'aotenticaçion a l'ha avuo successo, ma o to navegatô o no l'è in graddo de \"aregordâ\" che t'ê collegou.\n\n$1",
-       "authform-nosession-signup": "L'utença a l'è stæta creâ, ma o to navegatô o no l'è in graddo de \"aregordâ\" che t'ê collegou.\n$1",
+       "authform-nosession-login": "L'aotenticaçion a l'ha avuo successo, ma o to navegatô o no l'è in graddo de \"aregordâ\" che t'ê conligou.\n\n$1",
+       "authform-nosession-signup": "L'utença a l'è stæta creâ, ma o to navegatô o no l'è in graddo d'\"aregordâ\" che t'ê conligou.\n$1",
        "authform-newtoken": "Token mancante. $1",
        "authform-notoken": "Token mancante",
        "authform-wrongtoken": "Token errou",
        "cannotlink-no-provider-title": "Utençe collegabbile no ghe n'è",
        "cannotlink-no-provider": "Utençe colegabbile no ghe n'è.",
        "linkaccounts": "Collega utençe",
-       "linkaccounts-success-text": "L'utença a l'è stæta colegâ.",
+       "linkaccounts-success-text": "L'utença a l'è stæta inganciâ.",
        "linkaccounts-submit": "Collega utençe",
        "unlinkaccounts": "Scollega utençe",
        "unlinkaccounts-success": "L'utença a l'è stæta scollegâ.",
index 0eec9c6..c906996 100644 (file)
        "yourname": "Kȭlbatijiznim:",
        "yourpassword": "Sallisõnä:",
        "yourpasswordagain": "Kēratigid sallisõnā ūtstõ:",
-       "remembermypassword": " Mǟdlõgid sallisõnā (kuņtš $1 {{PLURAL:$1|päuvõ|päuvõ}})",
        "login": "Log sīezõ",
        "nav-login-createaccount": "Log sīezõ agā registrīer kȭlbatijizõks",
        "userlogin": "Sīezõ loggimi agā kȭlbatijiz-konto lūomi",
index 74b2357..369465c 100644 (file)
        "yourpasswordagain": "تکرار گذرواژه:",
        "createacct-yourpasswordagain": "گذرواژه را دوباره وارد کنید",
        "createacct-yourpasswordagain-ph": "گذرواژه را وارد کنید برای بار دوم",
-       "remembermypassword": "رمزعبورت وة ئئ رایانة ئةویرت/یادت بو(تابیشترإژ$1{{PLURAL:$1|رووژةل|رووژ}})",
        "userlogin-remembermypassword": "مإ وارد  بی بیل",
        "userlogin-signwithsecure": "إژ ورود امن استفاده کةن",
        "cannotloginnow-title": "ایسه نمه‌تونین باینه نوم",
        "passwordreset-emaildisabled": "قابلیت‌های ایمیل در این ویکی غیرفعال شده‌اند.",
        "passwordreset-username": ":نۆم کاربەری",
        "passwordreset-domain": "دامنه:",
-       "passwordreset-capture": "ایمیل نهایی نشان داده شود؟",
-       "passwordreset-capture-help": "اگر این گزینه را علامت بزنید، ایمیل (حاوی گذرواژهٔ موقت) به شما نشان داده خواهد شد و برای کاربر نیز فرستاده خواهد شد.",
        "passwordreset-email": ":نیشانی ایمیل",
        "passwordreset-emailtitle": "جزئیات حساوو أڕ {{SITENAME}}",
        "passwordreset-emailtext-ip": "یک نفر (احتمالاً شما، با نشانی آی‌پی $1) درخواست بازنشانی گذرواژه‌تان در {{SITENAME}} ($4) را کرده‌است. {{PLURAL:$3|حساب|حساب‌های}} کاربری زیر با این آدرس ایمیل مرتبط هستند:\n\n$2\n\n{{PLURAL:$3|این گذرواژهٔ موقت|این گذرواژه‌های موقت}} پس از {{PLURAL:$5|یک روز|$5 روز}} باطل خواهند شد.\nشما باید هم‌اکنون ثبت ورود کنید و گذرواژه‌ای جدید برگزینید. اگر فکر می‌کنید شخص دیگری این درخواست را داده است یا اگر گذرواژهٔ اصلی‌تان را به یاد آوردید و دیگر نمی‌خواهید آن را تغییر دهید، می‌توانید این پیغام را نادیده بگیرید و به استفاده از گذرواژهٔ قبلی‌تان ادامه دهید.",
        "userrights-reason": ":دةلیل",
        "userrights-no-interwiki": "شما اجازهٔ تغییر اختیارات کاربران دیگر ویکی‌ها را ندارید.",
        "userrights-nodatabase": "پایگاه دادهٔ $1 وجود ندارد یا محلی نیست.",
-       "userrights-nologin": "شما باید با یک حساب کاربری مدیر [[Special:UserLogin|به سامانه وارد شوید]] تا بتوانید اختیارات کاربران را تعیین کنید.",
-       "userrights-notallowed": "شما مجوز برای افزودن یا حذف حقوق کاربر را ندارید.",
        "userrights-changeable-col": "گروه‌هایی که می‌توانید تغییر دهید",
        "userrights-unchangeable-col": "گروه‌هایی که نمی‌توانید تغییر دهید",
        "userrights-conflict": "تعارض دسترسی‌های کاربری! لطفاً بررسی کنید و تغییرات را تأیید کنید.",
-       "userrights-removed-self": "شما با موفقیت دسترسی‌های خود را واستاندید. به این ترتیب شما دیگر به این صفحه دسترسی ندارید.",
        "group": "گروه:",
        "group-user": "کاربۀر",
        "group-autoconfirmed": "کاربران تأییدشدهٔ خودکار",
        "right-siteadmin": "قفل‌کردن و بازکردن پایگاه داده‌ها",
        "right-override-export-depth": "برون‌بری صفحه‌ها شامل صفحه‌های پیوند شده تا عمق ۵",
        "right-sendemail": "ارسال ایمیل به دیگر کاربران",
-       "right-passwordreset": "مشاهدهٔ نامه‌های تنظیم مجدد گذرواژه",
        "right-managechangetags": "ایجاد و حذف [[Special:Tags|برچسب‌ها]] از پایگاه داده",
        "right-applychangetags": "تائید [[Special:Tags|برچسب]] بر روی تغییرات یک نفر",
        "right-changetags": "افزودن یا حذف [[Special:Tags|برچسب]] قراردادی بر روی نسخه یا سیاهه ورودی‌ها",
        "activeusers-intro": "در زیر فهرستی از کاربرانی را می‌بینید که در $1 {{PLURAL:$1|روز|روزها}} گذشته فعالیتی داشته‌اند.",
        "activeusers-count": "$1 {{PLURAL:$1|فعالیت|فعالیت ها}} در {{PLURAL:$3|روز|$3 روز}} اخیر",
        "activeusers-from": "نمایش کاربران با آغاز از:",
-       "activeusers-hidebots": "نهفتن ربات‌ها",
-       "activeusers-hidesysops": "نهفتن مدیران",
        "activeusers-noresult": "کاربری پیدا نشد.",
        "activeusers-submit": "نمایش کاربةرةل فعال/کارکةر",
        "listgrouprights": "اختیارات گروه‌های کاربری",
        "importlogpagetext": "درون‌ریزی صفحات به همراه تاریخچهٔ ویرایش آن‌ها از ویکی‌های دیگر.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|نسخه|نسخه ها}} واردشده",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|نسخه|نسخه ها}} واردشده از $2",
-       "javascripttest": "آزمایش جاوا اسکریپت",
+       "javascripttest": "آزمایش جاوااسکریپت",
        "javascripttest-pagetext-unknownaction": "تابع ناشناختهٔ \"$1\".",
        "javascripttest-qunit-intro": "[$1 مستندات آزمایش] را در mediawiki.org ببینید.",
        "tooltip-pt-userpage": "وةڵگة کاربۀری هؤمۀ",
        "htmlform-title-not-exists": "$1 وجود ندارد.",
        "htmlform-user-not-exists": "<strong>$1</strong> وجود ندارد.",
        "htmlform-user-not-valid": "حساوو کاربةری <strong>$1</strong> معتبر نیة.",
-       "sqlite-has-fts": "$1 با پشتیبانی از جستجو در متن کامل",
-       "sqlite-no-fts": "$1 بدون پشتیبانی از جستجو در متن کامل",
        "logentry-delete-delete": "$1 VALGA $3{{GENDER:$2|HAZF Kerdi}}",
        "logentry-delete-restore": "$1 وةڵگة $3 را {{GENDER:$2|احیا کرد}}",
        "logentry-delete-event": "$1 پیدایی {{PLURAL:$5|یک مورد سیاهه|$5 مورد سیاهه}} را در $3 {{GENDER:$2|تغییر داد}}: $4",
        "feedback-external-bug-report-button": "پرونده‌سازی یک عمل فنی",
        "feedback-dialog-title": "ارسال یک بازخورد",
        "feedback-dialog-intro": "شما می توانید از فرم زیر برای بازخورد استفاده کنید. متن شما همراه با نام کاربریتان به وةڵگة \"$1\" افزوده خواهد شد.",
-       "feedback-error-title": "خطا",
        "feedback-error1": "خطا: پاسخ‌های ناشناخته از رابط برنامه‌نویسی نرم‌افزار",
        "feedback-error2": "خطا: شکست در ویرایش",
        "feedback-error3": "خطا: عدم پاسخ از رابط برنامه‌نویسی نرم‌افزار",
index 822718f..0555632 100644 (file)
        "yourpasswordagain": "Tùrna a scrìer la password",
        "createacct-yourpasswordagain": "Conférma la password",
        "createacct-yourpasswordagain-ph": "Tùrna a mèter dét la password",
-       "remembermypassword": "Regordass la mé password (per mìa de piö de {{PLURAL:$1|dé|dé}})",
        "userlogin-remembermypassword": "Tègnem colegàt",
        "userlogin-signwithsecure": "Dòpra 'na conesiù sigüra",
        "yourdomainname": "Specificà 'l domini",
        "passwordreset-emailtitle": "Detài de l'ütènsa sö {{SITENAME}}",
        "passwordreset-emailelement": "Nòm ütènt: \n$1\n\nPassword temporànea: \n$2",
        "passwordreset-emailsentemail": "Gh'è stat mandàt vià 'na e-mail de redefinisiù de la password.",
-       "passwordreset-emailsent-capture": "Gh'è stat mandàt vià chèsta e-mail de redefinisiù de la password:",
        "changeemail": "Càmbia l'indirìs e-mail",
        "changeemail-header": "Càmbia l'indirìs e-mail de l'ütènsa",
        "changeemail-none": "(nisü)",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
        "undo-summary": "Scancelada la mudifega $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Ciciarada]])",
-       "cantcreateaccounttitle": "Impusìbol creà 'n ütènt",
        "cantcreateaccount-text": "La creasiù de ütènse de part de chèsto indirìs IP (<strong>$1</strong>) l'è stàda blocàda de l'ütènt [[User:$3|$3]]. El mutìf specificàt de $3 l'è <em>$2</em>",
        "cantcreateaccount-range-text": "La creasiù de ütènse de part de indirìs IP endèl interval <strong>$1</strong>, del qual el fà part apò a 'l tò (<strong>$4</strong>), l'è stàda blocàda de [[User:$3|$3]].\n\nEl mutìf specificàt de $3 l'è <em>$2</em>.",
        "viewpagelogs": "Varda i register de quela pagina chì",
        "listusers-submit": "Fà ved",
        "activeusers": "Lìsta dei ütèncc atìf",
        "activeusers-from": "Fàm vedè i dupradur a partì da:",
-       "activeusers-hidebots": "Scond i bot",
-       "activeusers-hidesysops": "Scond i aministradur",
        "activeusers-noresult": "Nisü ütènt troàt",
        "listgrouprights": "Diricc del grüp dei ütèncc",
        "listgrouprights-group": "Grüp",
index 690b149..47791ce 100644 (file)
@@ -4,33 +4,39 @@
                        "Passawuth",
                        "Tuinui",
                        "아라",
-                       "Iberia2011"
+                       "Iberia2011",
+                       "Aefgh39622"
                ]
        },
-       "tog-underline": "ຂີດເສັ້ນກ້ອງລິງກ໌:",
-       "tog-hideminor": "ເຊື່ອງການດັດແກ້ເລັກນ້ອຍ ໃນ ການປ່ຽນແປງຫຼ້າສຸດ",
-       "tog-hidepatrolled": "ເຊື່ອງ ການລາດຕະເວນດັດແກ້ ໃນ ການດັດແກ້ຫຼ້າສຸດ",
-       "tog-newpageshidepatrolled": "ເຊື່ອງ ການລາດຕະເວນດັດແກ້ ໃນ ລາຍການໜ້າໃໝ່",
-       "tog-extendwatchlist": "ຂະຫຍາຍ ລາຍການຕິດຕາມ ເພື່ອ ສະແດງທຸກໆການປ່ຽນແປງ",
-       "tog-usenewrc": "ສະແດງ ການປ່ຽນແປງຫຼ້າສຸດ ເປັນສີເຂັ້ມ (JavaScript)",
-       "tog-numberheadings": "ໜາຍເລກຫົວຂໍ້ແບບອັດຕະໂນມັດ",
-       "tog-showtoolbar": "ສະແດງ ທູລບາດັດແກ້ (JavaScript)",
-       "tog-editondblclick": "ໃຫ້ສາມາດດັດແກ້ ໂດຍ ດັບເບິລ໌ ຄລິກ (JavaScript)",
-       "tog-editsectiononrightclick": "ໃຫ້ສາມາດ ດັດແກ້ ໂດຍກົດປຸ່ມຂວາ ຂອງເມົາສ໌ ຢູ່ <br /> ຫົວຂໍ້ຂອງພາກ (JavaScript)",
-       "tog-watchcreations": "ເພີ່ມ ໜ້າທີ່ຂ້ອຍສ້າງ ເຂົ້າໃນ ລາຍການຕິດຕາມ ຂອງ ຂ້ອຍ",
-       "tog-watchdefault": "ເພີ່ມໜ້າ ທີ່ ຂ້ອຍດັດແກ້ ໃສ່ ລາຍຕິດຕາມ ຂອງ ຂ້ອຍ",
-       "tog-watchmoves": "ເພີ່ມ ໜ້າທີ່ຂອ້ຍຍ້າຍ ໃສ່ ລາຍການຕິດຕາມຂອງຂ້ອຍ",
-       "tog-watchdeletion": "ເພີ່ມ ໜ້າ ທີ່ຂ້ອຍລຶບ ໃສ່ ລາຍການຕິດຕາມ ຂອງ ຂ້ອຍ",
-       "tog-minordefault": "ຖ້າບໍ່ມີການຕັ້ງ ກຳໜົດໃຫ້ທຸກໆການດັດແກ້ ເປັນ ການດັດແກ້ເລັກນ້ອຍ",
-       "tog-previewontop": "ສະແດງ ຜົນການດັດແກ້ ເທິງ ຊ່ອງດັດແກ້",
-       "tog-previewonfirst": "ສະແດງ ຜົນການດັດແກ້ ໃນ ເວລາດັດແກ້ເທື່ອທຳອິດ",
-       "tog-enotifwatchlistpages": "ສົ່ງອີເມລມາໃຫ້ຂ້ອຍ ເມື່ອ ໜ້າທີ່ຂ້ອຍຕິດຕາມໄດ້ຖືກປ່ຽນແປງ",
-       "tog-enotifusertalkpages": "ສົ່ງ ອີເມລ ມາໃຫ້ ຂ້ອຍ ເວລາ ໜ້າສົນທະນາຂ້ອຍ ມີການປ່ຽນແປງ",
-       "tog-enotifminoredits": "ສົ່ງ ອີເມລ ໃຫ້ຂ້ອຍ ເວລາມີການດັດແກ້ເລັກນ້ອຍນຳ",
-       "tog-enotifrevealaddr": "ສະແດງ ອີເມລ ຂອງຂ້ອຍ ໃນ ການແຈ້ງວ່າມີຂໍ້ຄວາມອີເມລ",
-       "tog-shownumberswatching": "ສະແດງ ຈຳນວນຜູ້ໃຊ້ ຕິດຕາມໝ້ານີ້",
-       "tog-forceeditsummary": "ເຕື່ອນຂ້ອຍ ຖ້າບໍ່ໄດ້ຂຽນຫຍັງໃສ່ ຊ່ອງ ສະຫຼຸບການດັດແກ້",
-       "tog-watchlisthideown": "ເຊື່ອງ ການດັດແກ້ໂດຍຂ້ອຍ ໃນ ລາຍການຕິດຕາມຂອງຂ້ອຍ",
+       "tog-underline": "ການຂີດເສັ້ນກ້ອງລິງກ໌:",
+       "tog-hideminor": "ເຊື່ອງການດັດແກ້ເລັກນ້ອຍໃນໜ້າປັບປຸງລ້າສຸດ",
+       "tog-hidepatrolled": "ເຊື່ອງການແກ້ໄຂທີ່ກວດສອບແລ້ວໃນໜ້າປັບປຸງລ້າສຸດ",
+       "tog-newpageshidepatrolled": "ເຊື່ອງໜ້າທີ່ກວດສອບແລ້ວໃນລາຍການໜ້າໃໝ່",
+       "tog-hidecategorization": "ເຊື່ອງການຈັດໝວດໝູ່ໜ້າ",
+       "tog-extendwatchlist": "ຂະຫຍາຍລາຍການຕິດຕາມໃຫ້ສະແດງການປ່ຽນແປງທັງໝົດ, ບໍ່ແມ່ນພຽງການປ່ຽນແປງລ້າສຸດ",
+       "tog-usenewrc": "ຈັດກຸ່ມການປ່ຽນແປງແບ່ງຕາມໜ້າຢູ່ໃນລາຍການປັບປຸງລ້າສຸດແລະລາຍການຕິດຕາມ",
+       "tog-numberheadings": "ກຳນົດເລກຫົວເລື່ອງອັດຕະໂນມັດ",
+       "tog-showtoolbar": "ສະແດງແຖບເຄື່ອງມືແກ້ໄຂ",
+       "tog-editondblclick": "ແກ້ໄຂໜ້າເມື່ອຄລິກສອງເທື່ອ",
+       "tog-editsectiononrightclick": "ເປີດໃຊ້ງານການແກ້ໄຂສ່ວນໂດຍຄລິກຂວາຢູ່ເທິງຊື່ເລື່ອງຂອງສ່ວນນັ້ນ",
+       "tog-watchcreations": "ເພີ່ມໜ້າທີ່ຂ້ອຍສ້າງແລະໄຟລ໌ທີ່ຂ້ອຍອັບໂຫຼດເຂົ້າໃນລາຍການຕິດຕາມ",
+       "tog-watchdefault": "ເພີ່ມໜ້າແລະໄຟລ໌ທີ່ຂ້ອຍແກ້ໄຂເຂົ້າໃນລາຍການຕິດຕາມ",
+       "tog-watchmoves": "ເພີ່ມໜ້າແລະໄຟລ໌ທີ່ຂ້ອຍຍ້າຍເຂົ້າໃນລາຍການຕິດຕາມ",
+       "tog-watchdeletion": "ເພີ່ມໜ້າແລະໄຟລ໌ທີ່ຂ້ອຍລຶບເຂົ້າໃນລາຍການຕິດຕາມ",
+       "tog-watchuploads": "ເພີ່ມໄຟລ໌ໃໝ່ທີ່ຂ້ອຍອັບໂຫຼດເຂົ້າໃນລາຍການຕິດຕາມ",
+       "tog-watchrollback": "ເພີ່ມໜ້າທີ່ຂ້ອຍໄດ້ກັບຄືນຢ່າງສຸກເສີນເຂົ້າໃນລາຍການຕິດຕາມ",
+       "tog-minordefault": "ກຳນົດການແກ້ໄຂທຸກຄັ້ງເປັນການແກ້ໄຂເລັກນ້ອຍໂດຍປະລິຍາຍ",
+       "tog-previewontop": "ສະແດງໂຕຢ່າງກ່ອນກ່ອງແກ້ໄຂ",
+       "tog-previewonfirst": "ສະແດງໂຕຢ່າງໃນການແກ້ໄຂຄັ້ງທຳອິດ",
+       "tog-enotifwatchlistpages": "ອີເມລຫາເມື່ອໜ້າຫຼືໄຟລ໌ໃນລາຍການຕິດຕາມປ່ຽນແປງ",
+       "tog-enotifusertalkpages": "ອີເມລຫາເມື່ອມີການປ່ຽນແປງໜ້າສົນທະນາກັບຜູ້ໃຊ້ຂອງຂ້ອຍ",
+       "tog-enotifminoredits": "ອີເມລຫາເຊັ່ນກັນສຳລັບການແກ້ໄຂໜ້າແລະໄຟລ໌ເລັກນ້ອຍ",
+       "tog-enotifrevealaddr": "ເປີດເຜີຍທີ່ຢູ່ອີເມລຂອງຂ້ອຍໃນອີເມລແຈ້ງເຕືອນ",
+       "tog-shownumberswatching": "ສະແດງຈຳນວນຜູ້ໃຊ້ທີ່ຕິດຕາມ",
+       "tog-fancysig": "ຖືລາຍເຊັນເປັນຂໍ້ຄວາມວິກິ (ໂດຍບໍ່ມີລິງຄ໌ອັດຕະໂນມັດ)",
+       "tog-uselivepreview": "ໃຊ້ການສະແດງໂຕຢ່າງແບບສົດ",
+       "tog-forceeditsummary": "ເຕືອນເມື່ອຊ່ອງຄຳອະທິບາຍໂດຍຫຍໍ້ວ່າງເປົ່າ",
+       "tog-watchlisthideown": "ເຊື່ອງການແກ້ໄຂຂອງຂ້ອຍຈາກລາຍການຕິດຕາມ",
        "tog-watchlisthidebots": "ເຊື່ອງ ການດັດແກ້ ໂດຍ ບອທ໌ ໃນລາຍການຕິດຕາມຂອງຂ້ອຍ",
        "tog-watchlisthideminor": "ເຊື່ອງ ການດັດແກ້ເລັກນ້ອຍ ໃນ ລາຍການຕິດຕາມຂອງຂ້ອຍ",
        "tog-watchlisthideliu": "ເຊື່ອງການດັດແກ້ ໂດຍ ຜູ້ໃຊ້ໄດ້ເຊັນເຂົາ ໃນ ລາຍການຕິດຕາມ",
@@ -41,7 +47,7 @@
        "tog-showhiddencats": "ສະແດງໝວດເຊື່ອງ",
        "underline-always": "ທຸກຄັ້ງ",
        "underline-never": "ບໍ່ຂີດ",
-       "underline-default": "àº\84à»\88າàº\95ັà»\89àº\87à»\80àº\94ີມ àº\82ອàº\87 ບຣາວເຊີ",
+       "underline-default": "ສະàº\81ິàº\99ຫຼືàº\84à»\88າàº\97ີà»\88àº\96ືàº\81àº\81ຳàº\99ົàº\94à»\84ວà»\89àº\82ອàº\87ບຣາວເຊີ",
        "sunday": "ວັນອາທິດ",
        "monday": "ວັນຈັນ",
        "tuesday": "ວັນອັງຄານ",
        "subcategories": "ໝວດຍ່ອຍ",
        "category-media-header": "ໜ້າຕ່າງ າ ໃນ \"$1\"",
        "category-empty": "''ບໍ່ມີໜ້າໃດຢູ່ໃນໝວດນີ້''",
-       "hidden-categories": "{{PLURAL:$1|à»\9cວàº\94à»\80àº\8aືà»\88ອàº\87|à»\9cວàº\94ເຊື່ອງ}}",
+       "hidden-categories": "{{PLURAL:$1|à»\9cວàº\94àº\97ີà»\88àº\96ືàº\81à»\80àº\8aືà»\88ອàº\87|à»\9cວàº\94àº\97ີà»\88àº\96ືàº\81ເຊື່ອງ}}",
        "hidden-category-category": "ບັນດາໜວດເຊື່ອງ",
        "category-subcat-count-limited": "ໜວດນີ້ ມີ ໜວດຍ່ອຍ ດັ່ງຕໍ່ໄປນີ້ {{PLURAL:$1|ໜວດຍ່ອຍ|$1 ໜວດຍ່ອຍ}}.",
        "category-article-count": "{{PLURAL:$2|ໝວດນີ້ມີໜ້າຢູ່ພຽງໜ້າດຽວ|ມີ {{PLURAL:$1|ໜ້າດຽວ|$1 ໜ້າ}} ໃນໝວດນີ້ ເຕັມ $2}}",
        "newwindow": "(ເປີດເປັນ ປ່ອງຢ້ຽມ(ວິນໂດ)ໃໝ່ )",
        "cancel": "ລົບລ້າງ",
        "moredotdotdot": "ຕື່ມ...",
-       "mypage": "ໜ້າຂ້ອຍ",
+       "mypage": "ໜ້າ",
        "mytalk": "ສົນທະນາ",
-       "anontalk": "ສົນທະນາ ສຳຫຼັບ IP ນີ້",
+       "anontalk": "ສົນທະນາ",
        "navigation": "ນຳທິດ",
        "and": "&#32;ແລະ",
        "qbfind": "ຊອກຫາ",
        "qbedit": "ດັດແກ້",
        "qbpageoptions": "ໜ້ານີ້",
        "qbmyoptions": "ໝ້າຂ້ອຍ",
+       "navigation-heading": "ເມນູນຳທາງ",
        "errorpagetitle": "ຜິດພາດ",
        "returnto": "ກັບໄປ  $1.",
        "tagline": "ຈາກ {{SITENAME}}",
        "help": "ຊ່ວຍເຫຼືອ",
-       "search": "àº\8aອàº\81ຫາ",
-       "searchbutton": "àº\8aອàº\81ຫາ",
+       "search": "àº\84ົà»\89àº\99ຫາ",
+       "searchbutton": "àº\84ົà»\89àº\99ຫາ",
        "go": "ໄປ",
        "searcharticle": "ໄປ",
        "history": "ປະຫວັດ",
        "history_short": "ປະຫວັດການດັດແກ້",
        "printableversion": "ສະບັບພິມໄດ້",
-       "permalink": "ລິà»\89àº\87àº\84à»\8càº\96າວອàº\99",
+       "permalink": "ລິງຄ໌ຖາວອນ",
        "print": "ພິມ",
-       "edit": "àº\94ັàº\94à»\81àº\81à»\89",
+       "edit": "à»\81àº\81à»\89à»\84àº\82",
        "create": "ສ້າງ",
        "editthispage": "ດັດແກ້ໜ້ານີ້",
        "create-this-page": "ສ້າງໜ້ານີ້",
        "delete": "ລຶບ",
        "deletethispage": "ລຶບໜ້ານີ້",
        "protect": "ປົກປ້ອງ",
-       "protect_change": "àº\9bà»\88ຽàº\99ຮູàº\9aà»\81àº\9aàº\9aàº\81າàº\99àº\9bົàº\81àº\9bà»\89ອງ",
+       "protect_change": "àº\81າàº\99àº\9bà»\88ຽàº\99à»\81àº\9bງ",
        "protectthispage": "ປ້ອງກັນໜ້ານີ້",
-       "unprotect": "à»\80àº\8aົາàº\9bົàº\81àº\9bà»\89ອàº\87",
+       "unprotect": "àº\9bà»\88ຽàº\99à»\81àº\9bàº\87àº\81າàº\99àº\9bà»\89ອàº\87àº\81ັàº\99",
        "newpage": "ໜ້າໃໝ່",
        "talkpage": "ປຶກສາຫາລືໜ້ານີ້",
        "talkpagelinktext": "ສົນທະນາ",
        "specialpage": "ໝ້າພິເສດ",
-       "personaltools": "à»\80àº\84ືà»\88ອàº\87ມືສà»\88ວàº\99àº\95ົວ",
+       "personaltools": "à»\80àº\84ືà»\88ອàº\87ມືສà»\88ວàº\99àº\9aຸàº\81àº\84ົàº\99",
        "articlepage": "ເບິ່ງໜ້າເນື້ອໃນ",
        "talk": "ສົນທະນາ",
        "views": "ເທື່ອເບິ່ງ",
-       "toolbox": "àº\81ັàº\9aອຸàº\9aàº\9bະàº\81ອàº\99",
+       "toolbox": "à»\80àº\84ືà»\88ອàº\87ມື",
        "userpage": "ເບິ່ງໜ້າສົນທະນາຂອງຜູ້ໃຊ້",
        "projectpage": "ເບິ່ງໝ້າໂຄງການ",
        "mediawikipage": "ເບິ່ງ ໝ້າຂໍ້ຄວາມ",
        "viewcount": "ໜ້ານີ້ຖືກເຂົ້າເບິ່ງ {{PLURAL:$1|ເທື່ອໜຶ່ງ|$1 ເທື່ອ}}.",
        "protectedpage": "ໜ້າຖືກປົກປ້ອງ",
        "jumpto": "ໄປຫາ:",
-       "jumptonavigation": "àº\99ຳàº\97ິàº\94",
+       "jumptonavigation": "àº\9bà»\89າàº\8dàº\9aອàº\81àº\97າàº\87",
        "jumptosearch": "ຄົ້ນຫາ",
        "aboutsite": "ກ່ຽວກັບ{{SITENAME}}",
        "aboutpage": "Project:ກ່ຽວກັບ",
-       "copyright": "ເນື້ອໃນ ສະໜອງໃຫ້ ພາຍໃຕ້ $1.",
+       "copyright": "ເນື້ອໃນແມ່ນສາມາດໃຊ້ໄດ້ພາຍໃຕ້ $1 ຖ້າບໍ່ແມ່ນຢ່າງອື່ນໃດທີ່ລະບຸໄວ້.",
        "copyrightpage": "{{ns:project}}:ລິຂະສິດ",
-       "currentevents": "àº\81ິàº\94àº\88ະàº\81ຳàº\9eວມàº\94ຳà»\80àº\99ີນ",
-       "currentevents-url": "Project:àº\81ິàº\94àº\88ະàº\81ຳàº\9eວມàº\94ຳà»\80àº\99ີນ",
+       "currentevents": "à»\80ຫàº\94àº\81າàº\99àº\9bັàº\94àº\88ຸàº\9aັນ",
+       "currentevents-url": "Project:à»\80ຫàº\94àº\81າàº\99àº\9bັàº\94àº\88ຸàº\9aັນ",
        "disclaimers": "ຂໍ້ປະຕິເສດຄວາມຮັບຜິດຊອບ",
        "disclaimerpage": "Project:ຂໍ້ປະຕິເສດຄວາມຮັບຜິດຊອບ",
        "edithelp": "ວິທີດັດແກ້ໜ້າ",
        "badaccess-group0": "ທ່ານ ບໍ່ໄດ້ຮັບອະນຸຍາດ ໃຫ້ປະຕິບັດການ ທີ່ ທ່ານ ສັ່ງ.",
        "versionrequired": "ຕ້ອງການເວີຣ໌ຊັ່ນ $1 ຂອງມີເດຍວິກິ",
        "ok": "ຕົກລົງ",
-       "retrievedfrom": "àº\96ອàº\99ມາຈາກ \"$1\"",
+       "retrievedfrom": "àº\94ຶàº\87àº\82à»\8dà»\89ມູàº\99ຈາກ \"$1\"",
        "youhavenewmessages": "ທ່ານ ມີ $1 ($2).",
        "youhavenewmessagesmulti": "ທ່ານມີຂໍ້ຄວາມໃໝ່ ຢູ່ $1",
-       "editsection": "àº\94ັàº\94à»\81àº\81à»\89",
+       "editsection": "à»\81àº\81à»\89à»\84àº\82",
        "editold": "ດັດແກ້",
        "viewsourceold": "ເບິ່ງ ຊອສ",
        "editlink": "ດັດແກ້",
-       "editsectionhint": "àº\94ັàº\94à»\81àº\81à»\89 ພາກ: $1",
+       "editsectionhint": "à»\81àº\81à»\89à»\84àº\82ພາກ: $1",
        "toc": "ເນື້ອໃນ",
        "showtoc": "ສະແດງ",
        "hidetoc": "ເຊື່ອງ",
        "viewdeleted": "ເບິ່ງ $1 ບໍ?",
        "site-rss-feed": "$1 RSS ຟີດ",
-       "site-atom-feed": "$1 Atom ຟີດ",
+       "site-atom-feed": "ອະຕອມຟີດ $1",
        "page-rss-feed": "\"$1\" RSS ຟີດ",
-       "red-link-title": "$1 (àº\8dັàº\87àº\9aà»\8dà»\88à»\84àº\94à»\89ສà»\89າàº\87)",
-       "nstab-main": "àº\9aົàº\94àº\84ວາມ",
+       "red-link-title": "$1 (àº\9aà»\8dà»\88ມີà»\9cà»\89າàº\99ີà»\89)",
+       "nstab-main": "à»\9cà»\89າ",
        "nstab-user": "ໜ້າຜູ້ໃຊ້",
-       "nstab-special": "ພິເສດ",
+       "nstab-special": "à»\9cà»\89າàº\9eິà»\80ສàº\94",
        "nstab-project": "ໜ້າໂຄງການ",
        "nstab-image": "ໄຟລ໌",
        "nstab-mediawiki": "ຂໍ້ຄວາມ",
        "nstab-template": "ແມ່ແບບ",
        "nstab-help": "ໜ້າຊ່ອຍເຫຼືອ",
        "nstab-category": "ໝວດ",
+       "mainpage-nstab": "ໜ້າຫຼັກ",
        "nosuchspecialpage": "ບໍ່ມີໝ້າພິເສດຊື່ນັ້ນ",
        "databaseerror": "ມີຄວາມຜິດພາດ ດ້ານ ຖານຂໍ້ມູນ",
        "readonly": "ຖານຂໍ້ມູນຖືກລອັກ",
        "missingarticle-diff": "(ສ່ວນຕ່າງ: $1, $2)",
        "internalerror": "ມີຄວາມຜິດພາດພາຍໃນ",
        "filerenameerror": "ບໍ່ສາມາດ ປ່ຽນ ຊື່ໄຟລ໌  \"$1\" ໄປເປັນ  \"$2\" ໄດ້.",
-       "cannotdelete": "ບໍ່ສາມາດລຶບໜ້າ ຫຼື ໄຟລ໌ ໄດ້. (ມັນອາດຈະຖືກລຶບໂດຍໃຜຜູ້ໜຶ່ງແລ້ວ.)",
+       "cannotdelete": "ບໍ່ສາມາດລຶບໜ້າຫຼືໄຟລ໌ \"$1\" ໄດ້.\nມັນອາດຈະຖືກລຶບໂດຍໃຜຜູ້ໜຶ່ງແລ້ວ.",
        "badtitle": "ຫົວຂໍ້ບໍ່ຖືກຕ້ອງ",
        "viewsource": "ເບິ່ງຊອສ໌",
        "namespaceprotected": "ທ່ານບໍ່ໄດ້ຮັບອະນຸຍາດ ໃຫ້ ດັດແກ້ ໜ້າ ໃນ  '''$1'''.",
-       "logouttext": "'''ທ່່ານ ໄດ້ ເຊັນອອກແລ້ວ.'''\n\nທ່ານ ສາມາດສືບຕໍ່ໃຊ້ {{SITENAME}} ແບບບໍ່ສະແດງຊື່, ຫຼື ທ່ານ ສາມາດ ເຊັນເຂົ້າ ອີກ ໂດຍ ຊື່ຜູ້ໃຊ້ ເກົ່າ ຫຼື ໃໝ່ ກໍ່ໄດ້.\nກະລຸນາ ຮັບຊາບວ່າ ບາງໜ້າ ອາດຈະສືບຕໍ່ ສະແດງ ຄືວ່າ ທ່ານ ຍັງເຊັນເຂົ້າຢູ່ ຈົນກວ່າ ທ່ານ ຂໍ້ມູນບັນທຶກຊົ່ວຄາວ ໃນ ໂປຣແກຣມທ່ອງເວັບ ຂອງ ທ່ານ ຈະຖືກລຶບ.",
+       "logouttext": "<strong>ທ່່ານໄດ້ອອກຈາກລະບົບແລ້ວ.<strong>\n\nກະລຸນາຮັບຊາບວ່າບາງໜ້າຈະຍັງຄົງສະແດງຜົນຕໍ່ໄປເຖິງແມ້ວ່າທ່ານຈະເຂົ້າສູ່ລະບົບແລ້ວ, ຈົນກວ່າທ່ານຈະລ້າງແຄຊໃນບຣາວເຊີຂອງທ່ານທັງໝົດ.",
        "yourname": "ຊື່ຜູ້ໃຊ້",
        "yourpassword": "ລະຫັດຜ່ານ",
        "yourpasswordagain": "ພິມລະຫັດຜ່ານອີກ",
-       "remembermypassword": "ຈົດຈໍາການເຊັນເຂົ້າຂອງຂ້ອຍ ຢູ່ ຄອມພິວເຕີໜ່ວຍນີ້ (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "ໂດເມນ ຂອງ ທ່ານ",
        "login": "ເຊັນເຂົ້າ",
        "nav-login-createaccount": "ເຊັນເຂົ້າ / ສ້າງບັນຊີ",
        "userlogin": "ເຊັນເຂົ້າ / ສ້າງບັນຊີ",
        "logout": "ເຊັນອອກ",
        "userlogout": "ເຊັນອອກ",
-       "nologin": "àº\9aà»\8dà»\88ມີàº\9aັàº\99àº\8aີà»\80àº\97ືà»\88ອàº\9aà»\8d? '''$1'''.",
+       "nologin": "àº\8dັàº\87àº\9aà»\8dà»\88ມີàº\9aັàº\99àº\8aີà»\80àº\97ືà»\88ອàº\9aà»\8dà»\88? $1.",
        "nologinlink": "ສ້າງບັນຊີໃໝ່",
        "createaccount": "ສ້າງບັນຊີ",
        "gotaccount": "ມີ ບັນຊີແລ້ວບໍ? '''$1'''.",
        "gotaccountlink": "ເຊັນເຂົ້າ",
-       "createaccountmail": "à»\82àº\94àº\8d àº­àºµà»\80ມລ",
+       "createaccountmail": "à»\83àº\8aà»\89ລະຫັàº\94àº\9cà»\88າàº\99à»\81àº\9aàº\9aສຸà»\88ມàº\8aົà»\88ວàº\84າວà»\81ລະສົà»\88àº\87ມັàº\99à»\84àº\9bà»\83ຫà»\89àº\97ີà»\88ຢູà»\88ອີà»\80ມວàº\97ີà»\88ລະàº\9aຸ",
        "badretype": "ລະຫັດຜ່ານ ທີ່ ທ່ານພິມຄືນ ບໍ່ຖືກກັບ ທີ່ພິມກ່ອນ.",
        "loginerror": "ມີບັນຫາໃນການເຊັນເຂົ້າ",
-       "loginsuccesstitle": "à»\80àº\8aັàº\99à»\80àº\82ົà»\89າສຳà»\80ລັàº\94",
+       "loginsuccesstitle": "à»\80àº\82ົà»\89າສູà»\88ລະàº\9aົàº\9aà»\81ລà»\89ວ",
        "loginsuccess": "'''ທ່ານ ເຊັນເຂົ້າ  {{SITENAME}} ໃນນາມ \"$1\".'''",
        "wrongpassword": "ລະຫັດຜ່ານບໍ່ຖືກ. ກະລຸນາເຮັດຄືນໃໝ່.",
        "wrongpasswordempty": "ບໍ່ມີລະຫັດຜ່ານຖືກພິມເຂົ້າ. ກະລຸນາເຮັດຄືນໃໝ່.",
-       "mailmypassword": "àº\82à»\8dລະຫັàº\94àº\9cà»\88າàº\99àº\97າàº\87ອີà»\80ມລ",
+       "mailmypassword": "àº\95ັà»\89àº\87àº\84à»\88າລະຫັàº\94àº\9cà»\88າàº\99à»\83à»\9dà»\88",
        "acct_creation_throttle_hit": "ຂໍໂທດຫຼາຍໆ, ທ່ານ ໄດ້ສ້າງ $1 ບັນຊີແລ້ວ. ທ່ານ ບໍ່ສາມາດ ສ້ງບັນຊີໄດ້ອີກ.",
-       "emailauthenticated": "ອີເມລ ຂອງ ທ່ານ ຖືກຢືນຢັນ ເມື່ອ $1.",
+       "emailauthenticated": "ອີເມລຂອງທ່ານໄດ້ຖືກຢືນຢັນແລ້ວເມື່ອວັນທີ່ $2 ເວລາ $3.",
        "emailconfirmlink": "ຢືນຢັນ ທີ່ຢູ່ ອີເມລ ຂອງ ທ່ານ",
        "accountcreated": "ບັນຊີ ໄດ້ຖືກສ້າງ ແລ້ວ",
        "accountcreatedtext": "ບັນຊີ ຂອງ  $1 ໄດ້ ຖືກສ້າງແລ້ວ.",
+       "pt-login": "ເຂົ້າສູ່ລະບົບ",
+       "pt-createaccount": "ສ້າງບັນຊີ",
        "changepassword": "ປ່ຽນລະຫັດຜ່ານ",
        "oldpassword": "ລະຫັດຜ່ານເກົ່າ:",
        "newpassword": "ລະຫັດຜ່ານໃໝ່:",
        "retypenew": "ພິມລະຫັດຜ່ານໃໝ່ອີກ:",
        "resetpass_submit": "ຕັ້ງລະຫັດຜ່ານ ແລະ ເຊັນເຂົ້າ",
        "changepassword-success": "ສຳເລັດການປ່ຽນແປງ ລະຫັດຜ່ານຂອງທ່ານແລ້ວ! ດຽວນີ້ ທ່ານ ເຊັ່ນເຂົ້າ ໃນ ...",
+       "passwordreset-invalidemail": "ທີ່ຢູ່ອີເມລບໍ່ຖືກຕ້ອງ",
        "bold_sample": "ໂຕໜັງສືເຂັ້ມ",
        "bold_tip": "ໂຕໜັງສືເຂັ້ມ",
        "italic_sample": "ໂຕເນີ້ງ",
        "template-protected": "(ປົກປ້ອງ)",
        "template-semiprotected": "(ເຄິ່ງປົກປ້ອງ)",
        "nocreatetext": "{{SITENAME}} ໄດ້ຈຳກັດການສ້າງໜ້າໃໝ່.\nທ່ານສາມາດກັບໄປ ດັດແກ້ ໜ້າທີ່ມີແລ້ວ ຫຼື [[Special:UserLogin|ເຊັນເຂົ້າ ຫຼື ສ້າງບັນຊີ]].",
-       "cantcreateaccounttitle": "ບໍ່ສາມາດສ້າງ ບັນຊີ ໄດ້",
        "cantcreateaccount-text": "ການສ້າງບັນຊີ ຈາກ IP ນີ້ (<b>$1</b>) ໄດ້ຖືກຫ້າມ ໂດຍ [[User:$3|$3]].\n\nເຫດຜົນ ໃຫ້ໄວ້ ໂດຍ $3 ແມ່ນ ''$2''",
        "viewpagelogs": "ເບິ່ງບັນທຶກ ຂອງ ໜ້ານີ້",
        "nohistory": "ຍັງບໍ່ມີ ປະຫວັດການດັດແກ້ໜ້ານີ້ເທື່ອ.",
        "currentrev": "ສະບັບປະຈຸບັນ",
-       "revisionasof": "à»\80àº\99ືà»\89ອà»\83àº\99ສະàº\9aັàº\9aເມື່ອ $1",
-       "previousrevision": "â\86\90 àºªàº°àº\9aັàº\9aເກົ່າກວ່າ",
+       "revisionasof": "ລຸà»\89àº\99à»\81àº\81à»\89à»\84àº\82à»\80àº\81ົà»\88າເມື່ອ $1",
+       "previousrevision": "â\86\90 àº¥àº¸à»\89àº\99ເກົ່າກວ່າ",
        "nextrevision": "ສະບັບກ່ອນ",
        "currentrevisionlink": "ສະບັບປະຈຸບັນ",
        "cur": "ດຽວນີ້",
        "show": "ສະແດງ",
        "minoreditletter": "ລ",
        "newpageletter": "ມ",
+       "rc-change-size-new": "$1 {{PLURAL:$1|byte|bytes}} ຫຼັງການປ່ຽນແປງ",
        "recentchangeslinked": "ການດັດແກ້ທີ່ກ່ຽວຂ້ອງ",
        "recentchangeslinked-feed": "ການດັດແກ້ທີ່ກ່ຽວຂ້ອງ",
-       "recentchangeslinked-toolbox": "àº\81າàº\99àº\94ັàº\94à»\81àº\81à»\89ທີ່ກ່ຽວຂ້ອງ",
+       "recentchangeslinked-toolbox": "àº\81າàº\99àº\9bà»\88ຽàº\99à»\81àº\9bàº\87ທີ່ກ່ຽວຂ້ອງ",
        "recentchangeslinked-title": "ການປ່ຽນແປງກ່ຽວຂ້ອງກັບ \"$1\"",
        "upload": "ອັບໂຫຼດໄຟລ໌",
        "filedesc": "ສະຫຼຸບ",
        "sharedupload": "ໄຟລ໌ນີ້ແມ່ນການອັບໂຫຼດຣ່ວມ ແລະ ອາດຖືກໃຊ້ໂດຍໂຄງການອື່ນໆ.",
        "listredirects": "ລາຍການການໂອນໜ້າ",
        "unusedtemplates": "ແມ່ແບບບໍ່ໄດ້ໃຊ້",
-       "randompage": "ໜ້າໃດໜຶ່ງ",
+       "randompage": "ສຸà»\88ມà»\9cà»\89າà»\83àº\94à»\9cຶà»\88àº\87",
        "randomredirect": "ໂອນໄປໜ້າໃດໜຶ່ງ",
        "statistics": "ສະຖິຕິ",
        "doubleredirects": "ໂອນໜ້າ 2 ຄັ້ງ",
        "sp-contributions-search": "ຊອກຫາ ການປະກອບສ່ວນ",
        "sp-contributions-username": "ທີ່ຢູ່ IP ຫຼື ຊື່ຜູ້ໃຊ້:",
        "sp-contributions-submit": "ຊອກຫາ",
-       "whatlinkshere": "ໜ້າທີ່ເຊື່ອມຕໍ່ມາ",
+       "whatlinkshere": "ໜ້າທີ່ເຊື່ອມຕໍ່ມາໜ້ານີ້",
        "whatlinkshere-title": "ໜ້າທີ່ເຊື່ອມຕໍ່ຫາ $1",
        "linkshere": "ບັນດາໜ້າຕໍ່ໄປ ລິ້ງຄ໌ ຫາ ''[[:$1]]''':",
        "nolinkshere": "ບໍ່ມີໜ້າລິ້ງຄ໌ ຫາ '''[[:$1]]'''.",
        "blockipsuccesssub": "ຫ້າມສຳເລັດ",
        "ipblocklist": "ລາຍການ ທີ່ຢູ່ IP ແລະ ຊື່ຜູ້ໃຊ້ ທີ່ຖືກຫ້າມ",
        "blocklink": "ຫ້າມ",
-       "contribslink": "àº\9bະàº\81ອàº\9aສà»\88ວນ",
+       "contribslink": "à»\80ລືà»\88ອàº\87àº\97ີà»\88àº\82ຽນ",
        "autoblocker": "ຫ້າມໂດຍອັດຕາໂນມັດ ຍ້ອນ ທີ່ຢູ່ IP ຂອງທ່ານ ຖືກໃຊ້ໂດຍ \"[[User:$1|$1]]\" ໃນໄລຍະຫຼັງ. ເຫດຜົນໃນການຫ້າມ  $1 ແມ່ນ : \"$2\"",
        "blocklogpage": "ບັນທຶກການຫ້າມ",
        "blocklogentry": "ໄດ້ຫ້າມ \"[[$1]]\" ຈົນຮອດ $2 $3",
        "tooltip-pt-preferences": "ຕັ້ງຄ່າ",
        "tooltip-pt-watchlist": "ລາຍການໜ້າທີ່ທ່ານຕິດຕາມການປ່ຽນແປງ",
        "tooltip-pt-mycontris": "ລາຍການປະກອບສ່ວນຂອງຂ້ອຍ",
-       "tooltip-pt-login": "ມັàº\99àº\9aà»\8dà»\88à»\81ມà»\88àº\99àº\81າàº\99àº\9aັàº\87àº\84ັàº\9a à»\81àº\95à»\88 àº\97à»\88າàº\99àº\84ວàº\99à»\80àº\8aັàº\99à»\80àº\82ົà»\89າ",
+       "tooltip-pt-login": "àº\99ີà»\89àº\9aà»\8dà»\88à»\81ມà»\88àº\99àº\81າàº\99àº\9aັàº\87àº\84ັàº\9a. à»\81àº\95à»\88ຢà»\88າàº\87à»\83àº\94àº\81à»\8dàº\95າມ, àº\97à»\88າàº\99àº\84ວàº\99àº\97ີà»\88àº\88ະà»\80àº\82ົà»\89າສູà»\88ລະàº\9aົàº\9a.",
        "tooltip-pt-logout": "ເຊັນອອກ",
-       "tooltip-ca-talk": "ສົນທະນາ ກ່ຽວກັບ ເນື້ອໃນຂອງໜ້າ",
-       "tooltip-ca-edit": "ທ່ານສາມາດດັດແກ້ໜ້ານີ້ໄດ້. ກະລຸນາໃຊ້ປຸ່ມ ລອງເບິ່ງຜົນ ກ່ອນກົດປຸ່ມບັນທຶກ.",
+       "tooltip-pt-createaccount": "ນີ້ິບໍ່ແມ່ນການບັງຄັບ. ແຕ່ຢ່າງໃດກໍຕາມ, ທ່ານຄວນທີ່ຈະສ້າງບັນຊີແລະເຂົ້າສູ່ລະບົບ.",
+       "tooltip-ca-talk": "ສົນທະນາກ່ຽວກັບເນື້ອໃນຂອງໜ້າ",
+       "tooltip-ca-edit": "ແກ້ໄຂໜ້ານີ້",
        "tooltip-ca-addsection": "ເພີ່ມ ຄຳເຫັນ ໃສ່ ການສົນທະນານີ້.",
        "tooltip-ca-viewsource": "ໜ້ານີ້ຖືກປົກປ້ອງ. ທ່ານສາມາດເບິ່ງຊອສ.",
+       "tooltip-ca-history": "ລຸ້ນແກ້ໄຂເກົ່າຂອງໜ້ານີ້",
        "tooltip-ca-protect": "ປົກປ້ອງໜ້ານີ້",
        "tooltip-ca-delete": "ລຶບໜ້ານີ້",
        "tooltip-ca-move": "ຍ້າຍໜ້ານີ້",
        "tooltip-ca-watch": "ເພີ່ມໜ້ານີ້ໃສ່ລາຍການຕິດຕາມຂອງທ່ານ",
        "tooltip-ca-unwatch": "ເອົາໜ້ານີ້ອອກຈາກລາຍການຕິດຕາມ ຂອງ ທ່ານ",
        "tooltip-search": "ຄົ້ນຫາ {{SITENAME}}",
-       "tooltip-p-logo": "ໜ້າຫຼັກ",
+       "tooltip-search-go": "ໄປຫາໜ້າທີ່ມີຊື່ທີ່ແນ່ນອນນີ້ຖ້າມັນມີຢູ່",
+       "tooltip-search-fulltext": "ຄົ້ນຫາຂໍ້ຄວາມນີ້ໃນໜ້າ",
+       "tooltip-p-logo": "ເຂົ້າສູ່ໜ້າຫຼັກ",
        "tooltip-n-mainpage": "ໄປເບິ່ງໜ້າຫຼັກ",
-       "tooltip-n-portal": "ກ່ຽວກັບໂຄງການ, ທ່ານສາມາດເຮັດຫຍັງ, ແລະ ຈະຊອກຫາຫຍັງໄດ້ຢູ່ໃສ",
-       "tooltip-n-currentevents": "ຊອກຂໍ້ມູນກ່ຽວກັບກິດຈະກຳພວມດຳເນີນ",
-       "tooltip-n-randompage": "ໂຫຼດໜ້າໃດໜຶ່ງ",
-       "tooltip-n-help": "ບ່ອນຊອກ.",
-       "tooltip-t-whatlinkshere": "ລາຍການຂອງທຸກໆໜ້າວິກິ ທີ່ເຊື່ອມຕໍ່ມາ",
+       "tooltip-n-mainpage-description": "ເຂົ້າສູ່ໜ້າຫຼັກ",
+       "tooltip-n-portal": "ກ່ຽວກັບໂຄງການ, ສິ່ງທີ່ທ່ານເຮັດໄດ້, ແລະບ່ອນທີ່ສາມາດຫາສິ່ງຕ່າງໆໄດ້",
+       "tooltip-n-currentevents": "ຄົ້ນຫາມູນກ່ຽວກັບກິດຈະກຳທີ່ກຳລັງດຳເນີນ",
+       "tooltip-n-recentchanges": "ລາຍການການປ່ຽນແປງລ້າສຸດໃນວິກິ",
+       "tooltip-n-randompage": "ສຸ່ມໂຫຼດໜ້າໃດໜຶ່ງ",
+       "tooltip-n-help": "ບ່ອນທີ່ຕ້ອງການຄົ້ນຫາ",
+       "tooltip-t-whatlinkshere": "ລາຍການຂອງທຸກໆໜ້າໃນວິກິທີ່ເຊື່ອມຕໍ່ມາໜ້ານີ້",
+       "tooltip-t-recentchangeslinked": "ການແກ້ໄຂລ້າສຸດໃນໜ້າທີ່ເຊື່ອມຕໍ່ມາຈາກໜ້ານີ້",
        "tooltip-t-contributions": "ເບິ່ງລາຍການປະກອບສ່ວນໂດຍຜູ້ໃຊ້ນີ້",
        "tooltip-t-emailuser": "ສົ່ງອີເມລຫາຜູ້ໃຊ້ນີ້",
        "tooltip-t-upload": "ອັບໂຫຼດໄຟລ໌",
        "tooltip-t-specialpages": "ລາຍການໜ້າພິເສດທັງໝົດ",
+       "tooltip-t-print": "ສະບັບທີ່ພິມໄດ້ຂອງໜ້ານີ້",
+       "tooltip-t-permalink": "ລິງຄ໌ຖາວອນມາລຸ້ນແກ້ໄຂເກົ່າຂອງໜ້ານີ້",
+       "tooltip-ca-nstab-main": "ເບິ່ງໜ້າເນື້ອໃນ",
        "tooltip-ca-nstab-user": "ເບິ່ງໜ້າຜູ້ໃຊ້",
        "tooltip-ca-nstab-project": "ເບິ່ງໜ້າໂຄງການ",
        "tooltip-ca-nstab-image": "ເບິງໜ້າໄຟລ໌",
        "tooltip-compareselectedversions": "ເບິ່ງສ່ວນຕ່າງລະຫວ່າງ ສອງ ສະບັບເລືອກ.",
        "tooltip-watch": "ເພີ່ມໜ້ານີ້ໃສ່ລາຍການຕິດຕາມຂອງທ່ານ",
        "anonymous": "ຜູ້ໃຊ້ ບໍ່ສະແດງຊື່ ຈາກ {{SITENAME}}",
+       "pageinfo-toolboxlink": "ຂໍ້ມູນໜ້າ",
+       "confirm-markpatrolled-button": "ຕົກລົງ",
        "previousdiff": "ສ່ວນຕ່າງກ່ອນ",
        "nextdiff": "ສ່ວນຕ່າງຕໍ່ໄປ →",
        "imagemaxsize": "ກຳນົດຄວາມໃຫຍ່ຂອງ ຮູບ ຫຼື ໜ້າອະທິບາຍຮູບ ບໍ່ໃຫ້ກາຍ:",
        "file-info-size": "$1 × $2  ປິກເຊລ, ຂະໜາດໄຟລ໌: $3, MIME type: $4",
        "file-nohires": "ບໍ່ມີຂະໜາດລະອຽດກວ່າ",
        "show-big-image": "ເຕັມຂະໜາດ",
+       "show-big-image-size": "$1 × $2 ພິກເຊວ",
        "newimages": "ໄຟລ໌ຮູບໃໝ່",
        "newimages-summary": "ໜ້າພິເສດນີ້ສະແດງໄຟລ໌ທີ່ຖຶກອັປໂຫຼດຫຼ້າສຸດ",
        "noimages": "ບໍ່ມີຫຍັງເບິ່ງ.",
        "watchlisttools-edit": "ເບິ່ງ ແລະ ດັດແກ້ ລາຍການຕິດຕາມ",
        "version": "ສະບັບ",
        "specialpages": "ໜ້າພິເສດ",
+       "searchsuggest-search": "ຄົ້ນຫາ {{SITENAME}}",
        "expandtemplates": "ຂະຫຍາຍແມ່ແບບ"
 }
index 4a0cbcc..3b90e11 100644 (file)
        "yourname": "Sebelu:",
        "yourpassword": "Sebu dafi:",
        "yourpasswordagain": "Ritapi sebu dafi:",
-       "remembermypassword": "Askevusize zwa menuhile kwa bye kompyuta (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "Zwa domeni:",
        "login": "Menuhile",
        "nav-login-createaccount": "Menuhile / ipupezi sebelu",
        "template-semiprotected": "(bukelezi di pagafi)",
        "nocreatetext": "{{SITENAME}} sa simplekile petulo.\nA afi e kenki/[[Special:UserLogin|menuhile]].",
        "recreate-moveddeleted-warn": "'''!: A sa hloli petulo dy sa afi kulobala.'''\n\nA sa luku a kenki dyangitubilinisize petulo.\nDesu dafi kulobala di petulo sa gi di informasi:",
-       "cantcreateaccounttitle": "Ni sa hloli di sebelu",
        "viewpagelogs": "Kamukile desu di petulo",
        "currentrev": "Selt nca",
        "revisionasof": "Selt di $1",
index 7aed884..996551b 100644 (file)
        "yourpasswordagain": "یئ گئل هأنی رازینە گوڤاردئن نە بأزە",
        "createacct-yourpasswordagain": "رازینە گوڤاردئن نە پوشت راس کو",
        "createacct-yourpasswordagain-ph": "یئ گئل هأنی رازینە گوڤاردئن نە بأزە",
-       "remembermypassword": "ئوٙمائن ڤامین مئنە د ئی دوڤارتە نیأر د ڤیر داشتوٙ (سی بیشتئروٙنە $1{{PLURAL:$1|روٙز|روٙزیا}})",
        "userlogin-remembermypassword": "مئنە د ساموٙنە ڤادار",
        "userlogin-signwithsecure": "ڤأصل بییئن أمن نە ڤئ کار بئیر",
        "yourdomainname": "پوشگئر شوما:",
        "passwordreset-emailtext-user": "کاریار $1 د {{SITENAME}} د نۊ زئنە کئردئن رازینە گوڤاردئن شومانە د{{SITENAME}} ($4) حاستە. {{PLURAL:$3|حئساڤ|حئساڤیا}} کاریاری کئ هان د هار و ڤا ئی تیرنئشوٙن أنجومانامە هان د ئرتئڤاط:\n\n$2\n\n رازینە گوڤاردئن {{PLURAL:$3|ئی رازینە یا گوڤاردئن موڤأقأتی|ئی رازینە یا گوڤاردئن موڤأقأتی}} شوما د گات {{PLURAL:$5|یئ روٙ|$5 روٙ}} باطئل بوٙە.\nأر کأسی هأنی چئن حاستی داشتە یا یە کئ رازینە گوڤاردئن دئمایی شوما د ڤیرئتوٙ ئوٙما و دە نئمیهایت ڤئنە آلئشت کاری بأکیت، می توٙنیت د ئی پئیغوم تیە پوٙشی بأکیت و هأموٙ رازینە گوڤاردئن دئمایی نە بونیت د کار.",
        "passwordreset-emailelement": "نوم کاریاری: \n$1\n\nرازینە گوڤاردئن موڤأقتی: \n$2",
        "passwordreset-emailsentemail": "یئ گئل رازینە گوڤاردئن هأنی سی أنجومانامە کئل بییە.",
-       "passwordreset-emailsent-capture": "رازینە گوڤاردئن تازە توٙ سی أنجومانامە توٙ کئ ها د هار کئل بییە.",
-       "passwordreset-emailerror-capture": "رازینە گوڤاردئن د أنجومانامە د نۊ زئنە کون کئل بییە،و ڤئ د هار دیاری میکە، ڤألی کئل بییئن ڤئ سی {{GENDER:$2|کاریار}} ناخوش سأرنجوم بییە:$1",
        "changeemail": "أنجومانامە توٙنە آلئشت کاری بأکیت",
        "changeemail-header": "ئی فورمئ نە سی آلئشتکاری أنجومانامە توٙ پور بأکیت. أر میھایت ھأر جوٙر أنجومانامە یی نە د مینجا حئساڤئتوٙ پاکسا بأکیت، جاگە دأئن أنجومانامە نئ د چئنی فورمی حالی بأنیت.",
-       "changeemail-passwordrequired": "شوما سی پوشت راستکاری ئی آلئشت بایأد یئ گئل رازینە گوڤاردئن بأزئنیت.",
        "changeemail-no-info": "شوما سی یە کئ د ئی بألگە دأسرئسی داشتوٙییت باس بیاییت ڤامین.",
        "changeemail-oldemail": "تیرنئشوٙن أنجومانامە ئیسئنی:",
        "changeemail-newemail": "تیرنئشوٙن أنجومانامە تازە:",
        "undo-nochange": "وه نظر میا که ای ویرایشت د ایسنیا خومثی بیه.",
        "undo-summary": "خومثی بیئن وانئری وا $1 [[Special:Contributions/$2|$2]] ([[User talk:$2|چک چنه]])",
        "undo-summary-username-hidden": "خومثی بیئن وانئری $1 وا یه گل کاریار قام بیه",
-       "cantcreateaccounttitle": "نأبوٙە حئساڤ راس بأکیت",
        "cantcreateaccount-text": "حساو دروس بیه و ا ای تیرنشون آی پی(<strong>$1</strong>) وه دس ای [[کاریار:$3|$3]] قلف بیه.\n\n\nدلیل دئه بیه وا $3 ها د<em>$2</em>",
        "cantcreateaccount-range-text": "حساو دروس بیه وا تیرنشون آی پی که د پوشینه <strong>$1</strong> ، که وه ئم مینونه دار تیرنشون آی پی شما ئم هئ(<strong>$4</strong>)، وه دس [[کاریار:$3|$3]]قلف بیه.\n\nدلیل دئه بیه وا $3، \"$2\" ئه.",
        "viewpagelogs": "سئیل پئرئستنوٙمە یا ئی بألگە بأکیت",
        "activeusers-intro": "شما د هار یه گل نومگه د کاریاریایی نه مینیت که د $1 {{PLURAL:$1|رو|رو}} دماتر کنشتگر بینه.",
        "activeusers-count": "$1 {{PLURAL:$1|کنشت|کنشت}} در {{PLURAL:$3|رو|$3 رو}} دماتر",
        "activeusers-from": "کاریاریایی که د شرو بینه نشو بیه:",
-       "activeusers-hidebots": "بوتیا قام کو",
-       "activeusers-hidesysops": "دیوون داریا نه قام کو",
        "activeusers-noresult": "هیچ کاروری پیدا نبی",
        "listgrouprights": "حقوق گرو کاریاری",
        "listgrouprights-summary": "نومگه های گرته د ور گرویا کاریاری تعریف بیه د ای ویکی و اختیارات دئه بیه د ونونه.\nدونسمنیا بیشتر دباره هرکوم د اختیارات نه د   [[{{MediaWiki:Listgrouprights-helppage}}]] پیدا بکیت.",
        "htmlform-cloner-create": "هنی اضاف بکیت",
        "htmlform-cloner-delete": "ؤرداشتن",
        "htmlform-cloner-required": "سی کمترونه یه گل ارزایشت لازمه",
-       "sqlite-has-fts": "$1 وا حامینداری پی جوری تمام نیسسه یی",
-       "sqlite-no-fts": "$1 وا بی حامینداری پی جوری تمام نیسسه یی",
        "logentry-delete-delete": "$1 بلگه {{GENDER:$2|پاکسا بیه}} $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|}} بلگه $3 د نو زنه کرده",
        "logentry-delete-event": "$1 دیاری {{PLURAL:$5|یه گل رخ ون د پهرستنومه|$5 رخ ونیا د پهرستنومه}} نه $3 {{GENDER:$2|آلشتکاری کرد}}: $4",
        "feedback-external-bug-report-button": "جانیا سازی یه گل کنشتیاری کسمدار",
        "feedback-dialog-title": "دیار بیین نهاحردیاری",
        "feedback-dialog-intro": "شما می تونیت نوم بلگه هاری نه سی دماداری هوال حونتو وه کار بئریت.نیسسه شما واگرد نوم کاریاریتو د بلگه \"$1\" اضاف موئه.",
-       "feedback-error-title": "خطا",
        "feedback-error1": "خطا: جواویا نادیار د پیوندکار برنامه نیسی نرم افزار",
        "feedback-error2": "خطا:ویرایشت خو نبی",
        "feedback-error3": "خطا: جواو ندئن د پیوندکار برنامه نیسی نرم افزار",
index 0a995ad..d9b5e3a 100644 (file)
        "talk": "Aptarimas",
        "views": "Peržiūros",
        "toolbox": "Įrankiai",
-       "tool-link-userrights": "Keisti {{GENDER:$1|vartotojo|vartotojos}} grupes",
-       "tool-link-emailuser": "Siusti el. laišką {{GENDER:$1|šiam vartotojui|šiai vartotojai}}",
+       "tool-link-userrights": "Keisti {{GENDER:$1|naudotojo|naudotojos}} grupes",
+       "tool-link-emailuser": "Siųsti {{GENDER:$1|šiam naudotojui|šiai naudotojai}} el. laišką",
        "userpage": "Rodyti naudotojo puslapį",
        "projectpage": "Rodyti projekto puslapį",
        "imagepage": "Žiūrėti failo puslapį",
        "ok": "Gerai",
        "retrievedfrom": "Gauta iš „$1“",
        "youhavenewmessages": "Jūs turite $1 ($2).",
-       "youhavenewmessagesfromusers": "Jūs gavote $1 nuo {{PLURAL:$3|kito vartotojo|$3 vartotojų}} ($2).",
+       "youhavenewmessagesfromusers": "Jūs gavote $1 nuo {{PLURAL:$3|kito naudotojo|$3 naudotojų}} ($2).",
        "youhavenewmessagesmanyusers": "Jūs turite $1 iš daugelio vartotojų ( $2 ) .",
        "newmessageslinkplural": "{{PLURAL:$1|nauja žinutė|999=naujos žinutės}}",
        "newmessagesdifflinkplural": "paskutinis {{PLURAL:$1|pakeitimas|999=pakeitimai}}",
        "passwordreset-emaildisabled": "El. pašto funkcijos uždraustos šiame wiki.",
        "passwordreset-username": "Naudotojo vardas:",
        "passwordreset-domain": "Domenas:",
-       "passwordreset-capture": "Peržiūrėti galutinį e-mail laišką?",
-       "passwordreset-capture-help": "Jei jūs čia pažymėsite, tai e-mail laiškas (su laikinuoju slaptažodžiu) bus parodytas jums prieš išsiunčiant jį naudotojui.",
        "passwordreset-email": "E-pašto adresas:",
        "passwordreset-emailtitle": "Paskyros informacija apie {{sitename}}",
        "passwordreset-emailtext-ip": "Kažkas (tikriausiai jūs, iš IP adreso $1) paprašė priminti jūsų slaptažodį svetainėje {{SITENAME}} ($4). Šio naudotojo {{PLURAL:$3|paskyra|paskyros}} yra susietos su šiuo elektroninio pašto adresu:\n\n$2\n\n{{PLURAL:$3|Šis laikinas slaptažodis|Šie laikini slaptažodžiai}} baigs galiot po {{PLURAL:$5|vienos dienos|$5 dienų}}. \n\nJūs turėtumėte prisijungti ir pasirinkti naują slaptažodį. Jei priminti slaptažodį paprašė kažkas kitas arba jūs prisiminėte savo pirminį slaptažodį ir jums nebereikia jo pakeisti, galite ignoruoti šį pranešimą ir toliau naudotis savo senuoju slaptažodžiu.",
        "passwordreset-emailelement": "Naudotojo vardas: \n$1\n\nLaikinas slaptažodis: \n$2",
        "passwordreset-emailsentemail": "Jeigu šis el. pašto adresas yra susietas su jūsų paskyra, tada slaptažodžio atkūrimo laiškas bus išsiųstas.",
        "passwordreset-emailsentusername": "Jeigu buvo el. paštas susietas su šiuo naudotojo vardu, tai slaptažodžio atkūrimo el. laiškas bus išsiųstas.",
-       "passwordreset-emailsent-capture2": "Slaptažodžio keitimo {{PLURAL:$1|el. laiškas buvo išsiųstas|el. laiškai buvo išsiųsti}}. {{PLURAL:$1|vartotojo vardas ir slaptažodis rodomi|vartotojų vardų ir slaptažodžių sąrašas rodomas}} čia.",
-       "passwordreset-emailerror-capture2": "El. laiško siuntimas {{GENDER:$2|vartotojui}} nepavyko: $1 {{PLURAL:$3|vartotojo vardas ir slaptažodis rodomi|vartotojų vardų ir slaptažodžių sąrašas rodomas}} čia.",
        "passwordreset-nocaller": "Skambinantysis turi būti nurodytas",
        "passwordreset-nosuchcaller": "Skambinantysis neegzistuoja: $1",
-       "passwordreset-invalideamil": "Neteisingas el. pašto adresas",
+       "passwordreset-invalidemail": "Neteisingas el. pašto adresas",
        "passwordreset-nodata": "Vartotojo vardas ir el. paštas buvo nepateikti",
        "changeemail": "Pakeisti ar pašalinti el. pašto adresą",
        "changeemail-header": "Užpildykite šią formą, kad pakeistumėte savo el. pašto adresą. Jeigu norite pašalinti bet kurio el. pašto adreso susiejimą su savo paskyra, palikite naujojo el. pašto adreso lauką tuščią, kai pateiksite formą.",
        "userrights-reason": "Priežastis:",
        "userrights-no-interwiki": "Jūs neturite leidimo keisti naudotojų teises kituose projektuose.",
        "userrights-nodatabase": "Duomenų bazė $1 neegzistuoja arba yra ne vietinė.",
-       "userrights-nologin": "Jūs privalote [[Special:UserLogin|prisijungti]] kaip administratorius, kad galėtumėte priskirti naudotojų teises.",
-       "userrights-notallowed": "Jūs neturite leidimo įtraukti arba pašalinti vartotojo teisių.",
        "userrights-changeable-col": "Grupės, kurias galite keisti",
        "userrights-unchangeable-col": "Grupės, kurių negalite keisti",
        "userrights-conflict": "Naudotojo teisių konfliktas! Prašome dar kartą taikyti savo keitimus.",
-       "userrights-removed-self": "Jūs pašalinote savo paties teises. Taigi, nebegalite pasiekti šio puslapio.",
        "group": "Grupė:",
        "group-user": "Naudotojai",
        "group-autoconfirmed": "Automatiškai patvirtinti naudotojai",
        "right-siteadmin": "Atrakinti ir užrakinti duomenų bazę",
        "right-override-export-depth": "Eksportuoti puslapius įtraukiant susietus puslapius iki 5 lygio gylio",
        "right-sendemail": "Siųsti el. laišką kitiems naudotojams",
-       "right-passwordreset": "Peržiūrėti slaptažodžio pakeitimo e-mail laiškus",
        "right-managechangetags": "Kurti ir (de)aktyvuoti [[Special:Tags|žymes]]",
        "right-applychangetags": "Taikyti [[Special:Tags|žymes]] kartu su pokyčiais",
        "right-changetags": "Pridėti ir ištrinti savavališkus [[Special:Tags|žymes]] individualiuose pakeitimuose ir žurnalo įrašuose",
        "activeusers-count": "$1 {{PLURAL:$1|keitimas|keitimai|keitimų}} per {{PLURAL:$3|paskutinę dieną|$3 paskutines dienas|$3 paskutinių dienų}}",
        "activeusers-from": "Rodyti naudotojus, pradedant:",
        "activeusers-groups": "Rodyti vartotojus, priklausančius grupėms:",
+       "activeusers-excludegroups": "Išskirti vartotojus, priklausančius grupėms:",
        "activeusers-noresult": "Nerasta jokių naudotojų.",
        "activeusers-submit": "Rodyti aktyvius vartotojus",
        "listgrouprights": "Naudotojų grupių teisės",
        "linkaccounts-success-text": "Paskyra buvo susieta.",
        "linkaccounts-submit": "Susieti paskyras",
        "unlinkaccounts": "Atsieti paskyras",
-       "unlinkaccounts-success": "Paskyra buvo atsieta.",
-       "edit-error-short": "Klaida: $1",
-       "edit-error-long": "Klaidos:\n\n$1"
+       "unlinkaccounts-success": "Paskyra buvo atsieta."
 }
index 7f67c7c..78695da 100644 (file)
        "viewsource": "Apsavērt kodu",
        "yourname": "Slāgvuords:",
        "yourpassword": "Paroļs:",
-       "remembermypassword": "Atguoduot muni  iz ituo datora (na vaira kai $1 {{PLURAL:$1|dīnu|dīnom|dīnom}})",
        "login": "Dasaslāgt",
        "nav-login-createaccount": "Dasaslāgt / sataiseit jaunu lītuotuoju",
        "userlogin": "Dasaslāgt / sataiseit jaunu lītuotuoju",
index 2b001c6..d0fc2b3 100644 (file)
        "yourname": "Hmangtuhming:",
        "yourpassword": "Thurûk:",
        "yourpasswordagain": "Thurûk ziak nawn leh rawh le:",
-       "remembermypassword": "He ka rangpuifanna hman mék (browser)-ah hian ka luhna (a rei berah ni {{PLURAL:$1||}}$1) min vawnsak rawh, thurûk ziah nawn ngai lo tùrin.",
        "yourdomainname": "I ram:",
        "password-change-forbidden": "Hë wiki-ah hian thurûk i thlâk thei lo.",
        "externaldberror": "Insawifiahna felfai lo a awm lo a nih loh vëk pawhin i pawnlam siangchan tihdanglam phalsak i ni lo a ni ang.",
        "passwordreset-emailtitle": "{{SITENAME}}-a siangchan chanchin kim",
        "passwordreset-emailelement": "Hmangtuhming: \n$1\n\nThurûk lailâwk: \n$2",
        "passwordreset-emailsentemail": "Hriat nawntirna e-lehkha thawn fel a ni.",
-       "passwordreset-emailsent-capture": "Hriat nawntirna e-lehkha thawn a ni, a hnuaia tarlan ang khuan.",
-       "passwordreset-emailerror-capture": "Hriat nawntirna e-lehkha siam chhuah a ni a, a hnuaia tarlan ang khuan; mahsé thawn hlawhchham a ni: $1",
        "changeemail": "E-chenhmun thlâk rawh",
        "changeemail-header": "Siangchan e-chenhmun thlâk rawh",
        "changeemail-no-info": "He phêk lut mai tùr chuan i inziahluh a ngai.",
        "node-count-exceeded-warning": "Suihbawl theih chin pèl phêkte",
        "expansion-depth-exceeded-category": "Tihchiam theih chin pèl phêkte",
        "expansion-depth-exceeded-warning": "Tihchiam theih chin phêkin a pèl",
-       "cantcreateaccounttitle": "Siangchan siam theih loh",
        "viewpagelogs": "He phêk chanchin hi en rawh",
        "nohistory": "Hë phêk siamṭhatna chanchin ziak a awm lo tlat.",
        "currentrev": "Ennawnna hnuhnung ber",
        "listusers-noresult": "Hmangtu an awm lo.",
        "listusers-blocked": "(danbeh)",
        "activeusers": "Hmangtu hlun tlarna",
-       "activeusers-hidebots": "Khawlmi thupna",
-       "activeusers-hidesysops": "Roreltu thupna",
        "activeusers-noresult": "Hmangtu awm lo.",
        "listgrouprights": "Hmangtu pawl dikna-chanvote",
        "listgrouprights-key": "* <span class=\"listgrouprights-granted\">Dikna-chanvo phalsak</span>\n* <span class=\"listgrouprights-revoked\">Dikna-chanvo hnuhkirsak</span>",
        "special-characters-group-lao": "Lao",
        "special-characters-group-khmer": "Khmer",
        "mw-widgets-dateinput-placeholder-day": "KKKK-TT-NN",
-       "mw-widgets-dateinput-placeholder-month": "KKKK-TT",
-       "api-error-blacklisted": "Hming dang, chiang zâwk deuh thlang hräm rawh le."
+       "mw-widgets-dateinput-placeholder-month": "KKKK-TT"
 }
index fe7a8e3..233b95f 100644 (file)
        "passwordreset-emaildisabled": "Šajā viki ir atspējotas e-pasta iespējas.",
        "passwordreset-username": "Lietotājvārds:",
        "passwordreset-domain": "Domēns:",
-       "passwordreset-capture": "Apskatīt izveidoto e-pastu?",
        "passwordreset-email": "E-pasta adrese:",
        "passwordreset-emailtitle": "Konta informācija {{SITENAME}}",
        "passwordreset-emailelement": "Lietotājvārds: \n$1\n\nPagaidu parole: \n$2",
        "passwordreset-emailsentemail": "Paroles atiestatīšanas e-pasts ir nosūtīts.",
        "passwordreset-nosuchcaller": "Izsaucējs nepastāv: $1",
-       "passwordreset-invalideamil": "Nederīga e-pasta adrese",
+       "passwordreset-invalidemail": "Nederīga e-pasta adrese",
        "changeemail": "Mainīt vai noņemt e-pasta adresi",
        "changeemail-header": "Mainīt konta e-pasta adresi",
        "changeemail-oldemail": "Pašreizējā e-pasta adrese:",
        "userrights-reason": "Iemesls:",
        "userrights-no-interwiki": "Tev nav atļaujas izmainīt dalībnieku tiesības citos wiki.",
        "userrights-nodatabase": "Datubāze $1 neeksistē vai nav lokāla.",
-       "userrights-nologin": "Tev ir [[Special:UserLogin|jāieiet iekšā]] kā adminam, lai varētu izmainīt dalībnieku grupas.",
-       "userrights-notallowed": "Tev nav atļaujas pievienot vai noņemt dalībnieku tiesības.",
        "userrights-changeable-col": "Grupas, kuras tu vari izmainīt",
        "userrights-unchangeable-col": "Grupas, kuras tu nevari izmainīt",
        "group": "Grupa:",
        "right-userrights-interwiki": "Mainīt dalīnieku tiesības citās Vikipēdijās",
        "right-siteadmin": "Bloķēt un atbloķēt datubāzi",
        "right-sendemail": "Sūtīt e-pastu citiem dalībniekiem",
-       "right-passwordreset": "Apskatīt paroles atiestatīšanas e-pasta ziņojumus",
        "grant-group-email": "Sūtīt e-pastu",
        "grant-createaccount": "Izveidot kontu",
        "grant-editmywatchlist": "Labot uzraugāmo rakstu sarakstu",
        "htmlform-cloner-create": "Pievienot vairāk",
        "htmlform-cloner-delete": "Noņemt",
        "logentry-delete-delete": "$1 {{GENDER:$2|izdzēsa}} lapu $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|izdzēsa}} pāradresāciju $3 pārrakstot",
        "logentry-delete-restore": "$1 {{GENDER:$2|atjaunoja}} lapu $3",
        "revdelete-content-hid": "saturs slēpts",
        "revdelete-summary-hid": "labojuma kopsavilkums slēpts",
        "authmanager-realname-label": "Tavs īstais vārds",
        "authmanager-realname-help": "Dalībnieka īstais vārds",
        "authprovider-resetpass-skip-label": "Izlaist",
-       "specialpage-securitylevel-not-allowed-title": "Nav atļauts",
-       "edit-error-short": "Kļūda: $1",
-       "edit-error-long": "Kļūdas:\n\n$1"
+       "specialpage-securitylevel-not-allowed-title": "Nav atļauts"
 }
index 153ab06..81906f6 100644 (file)
        "yourpasswordagain": "復核節",
        "createacct-yourpasswordagain": "訂子符節",
        "createacct-yourpasswordagain-ph": "復告符節",
-       "remembermypassword": "吾之簿通越(達至$1日)",
        "userlogin-remembermypassword": "保我簿登",
        "userlogin-signwithsecure": "以安全伺服登簿",
        "yourdomainname": "汝之網域",
        "undo-failure": "中審之異,此審無返也。",
        "undo-norev": "其審無存或刪,此審無返也。",
        "undo-summary": "返[[Special:Contributions/$2|$2]]([[User talk:$2|書]])之審$1",
-       "cantcreateaccounttitle": "新簿謝焉",
        "cantcreateaccount-text": "[[User:$3|S3]]因''$2''故,封子IP <b>$1</b>。",
        "viewpagelogs": "覽誌",
        "nohistory": "此題無誌",
        "activeusers-intro": "此乃為近$1天內之躍簿也。",
        "activeusers-count": "$3天內之$1易",
        "activeusers-from": "示簿始於:",
-       "activeusers-hidebots": "藏僕",
-       "activeusers-hidesysops": "藏有秩",
        "activeusers-noresult": "無簿矣。",
        "listgrouprights": "權任一覽",
        "listgrouprights-summary": "此所列述,諸職所司也,各有異同。欲知其詳,請閱[[{{MediaWiki:Listgrouprights-helppage}}|此文]]。",
        "htmlform-submit": "呈",
        "htmlform-reset": "復",
        "htmlform-selectorother-other": "他",
-       "sqlite-has-fts": "$1 含全文之尋",
-       "sqlite-no-fts": "$1 不含全文之尋",
        "revdelete-restricted": "應限至有秩",
        "revdelete-unrestricted": "除限自有秩",
        "logentry-newusers-create": "簿$1已{{GENDER:$2|增}}。",
index a5ceb17..c997386 100644 (file)
        "passwordreset-emailtext-user": "प्रयोक्ता $1 {{अन्तर्जाल}} पर अहाँक खाता विवरणक {{SITENAME}} लेल फेरसँ ($4) आग्रह केने छथि। ई प्रयोक्ता {{PLURAL:$3|खाता अछि|खाता सभ अछि}} ऐ ई-पत्र संकेतसँ जुड़ल: $2\n{{PLURAL:$3| ई अस्थायी कूटशब्द|ई सभ अस्थायी कूटशब्द}} खतम भऽ जाएत {{PLURAL:$5|एक दिन|$5 दिन}} मे।\nअहाँ सम्प्रवेश करू आ एकटा नव कूटशब्द आब चुनू। जँ कियो दोसर ई आग्रह केने छथि, वा जँ अहाँकेँ अपन मूल कूटशब्द मोन पड़ि गेल अछि, आ अहाँ आब ओइ कूटशब्दकेँ नै बदलऽ चाहै छी, अहाँ ऐ संदेशकेँ बिसरि सकै छी आ अपन पुरान कूटशब्दक प्रयोग जारी राखि सकै छी।",
        "passwordreset-emailelement": "प्रयोक्ता: \n$1\n\nअस्थायी कूटशब्द: \n$2",
        "passwordreset-emailsentemail": "एकटा ई-पत्र मोन पाड़बा लेल पठाओल गेल अछि।",
-       "passwordreset-invalideamil": "अवैध इमेल ठेगान",
+       "passwordreset-invalidemail": "अवैध इमेल ठेगान",
        "passwordreset-nodata": "प्रयोगकर्ता नाम वा इमेल ठेगान नै देल गेल छल",
        "changeemail": "ई-मेल पता परिवर्तित करी",
        "changeemail-header": "अपन ईमेल पता परिवर्तन हेतु एकरा पुरा करी। यदि अहाँ अपन वर्तमान ईमेल पता हटाबैलेल चाहैत छी, तँ एकरा खाली छोडि दी आ एकरा भेजी।",
index 2cc972a..fe20055 100644 (file)
        "yourpasswordagain": "Balèni tembung sandhi:",
        "createacct-yourpasswordagain": "Konfirmasi tembung sandhi",
        "createacct-yourpasswordagain-ph": "Lebokna tembung sandhi maning",
-       "remembermypassword": "Emutna data login-ne inyong nang peramban kiye (kanggo paling suwe $1 {{PLURAL:$1|dina|dina}})",
        "userlogin-remembermypassword": "Jorna ben Inyong tetep mlebu log",
        "userlogin-signwithsecure": "Gunakna koneksi aman",
        "cannotloginnow-title": "Ora teyeng mlebu siki",
index 31ca464..3a309a5 100644 (file)
        "yourname": "Тиить лемоц:",
        "yourpassword": "Сувама валце:",
        "yourpasswordagain": "Сёрматк сувама валце омбоцекс:",
-       "remembermypassword": "Ванфтомс монь сувама лемозе тя содам машинаса (максимум $1 {{PLURAL:$1|шис|шис}})",
        "yourdomainname": "Тонь доменце:",
        "password-change-forbidden": "Сувама валхне тя викить эса аф полафтовихть",
        "externaldberror": "Лиссь эльбятькс ушеширень датабазонь вельде кемокстакшнембачк эли тондейть аф мярьгови полафнемс тонь ушеширень сёрматфтомацень.",
        "undo-failure": "Тя петнемать аш кода валхтомс ётконь петнематнень карань-каршек арафтомаснон сюнеда.",
        "undo-norev": "Тя петнемать аш кода мърдафтомс сяс мес сонь аш эли сон нардафоль.",
        "undo-summary": "Валхтт петнемась $1 конань тизе [[Special:Contributions/$2|$2]] ([[User talk:$2|Корхнема]])",
-       "cantcreateaccounttitle": "Аш кода сёрматфтомать тиемс",
        "cantcreateaccount-text": "Сёрматфтомась тя IP адреста ('''$1''') пякстазе [[User:$3|$3]].\n\n$3 макссь туфталсь - ''$2''",
        "viewpagelogs": "Няфтемс тя лопать историянц",
        "nohistory": "Тя лопать петнемань историяц аш.",
index 94699ba..74f57ae 100644 (file)
        "yourpasswordagain": "Avereno ampidirina eto ny tenimiafina",
        "createacct-yourpasswordagain": "Hamarino ny tenimiafinao",
        "createacct-yourpasswordagain-ph": "Mbola ampidiro fanindroany ny tenimiafinao",
-       "remembermypassword": "{{PLURAL:}}Tadidio ny tenimiafiko (mandritry ny $1 andro fara-fahabetsany)",
        "userlogin-remembermypassword": "Tadidio aho",
        "userlogin-signwithsecure": "Fidirana amin'ny alalan'ny fanohizana azo antoka",
        "cannotloginnow-title": "Tsy afaka miditra izao",
        "botpasswords-label-delete": "Fafàna",
        "botpasswords-label-resetpassword": "Hamerina ny tenimiafina",
        "botpasswords-label-grants": "Zo mihatra:",
-       "botpasswords-label-restrictions": "Fetran'ny fampiasana:",
        "botpasswords-label-grants-column": "Nomena",
        "botpasswords-bad-appid": "Tsy azo raisina ny anarana rôbô \"$1\".",
        "botpasswords-insert-failed": "Tsy afaka nanampy ny anarana rôbô \"$1\". Tsy efa nampiana ve ilay izy?",
        "activeusers-intro": "Ity ny lisitry ny mpikambana izay nanao zavatra iray nandritry ny andro $1 farany. {{PLURAL:}}",
        "activeusers-count": "Tao $1{{PLURAL:}} tanatin'ny $3 andro",
        "activeusers-from": "Aseho ny mpikambana hatry ny :",
-       "activeusers-hidebots": "Asitriho ny robo",
-       "activeusers-hidesysops": "Asitriho ny mpandrindra",
        "activeusers-noresult": "Tsy nahitana mpikambana.",
        "activeusers-submit": "Hanseho ny mpikambana mavitrika",
        "listgrouprights": "Fahefan'ny vondrom-pikambana",
        "htmlform-title-not-exists": "Tsy misy $1.",
        "htmlform-user-not-exists": "Tsy misy ny <strong>$1</strong>.",
        "htmlform-user-not-valid": "Tsy anaram-pikambana azo raisina <strong>$1</strong>.",
-       "sqlite-has-fts": "$1 misy fikarohan-dahatsoratra tanteraka",
-       "sqlite-no-fts": "$1 tsy misy fikarohan-dahatsoratra tanteraka",
        "logentry-delete-delete": "nofafan'i $1 ny pejy $3",
        "logentry-delete-restore": "Namerina ny pejy $3 i $1{{GENDER:$2|}}",
        "logentry-delete-event": "Nanova ny fahitana {{PLURAL:$5|laogy iray|laogy $5}} tamin'i $3 i $1: $4",
index 868df89..a41205a 100644 (file)
        "yourpasswordagain": "Ulang baliak kato sandi:",
        "createacct-yourpasswordagain": "Konfirmasi kato sandi",
        "createacct-yourpasswordagain-ph": "Masuakan lai kato sandi",
-       "remembermypassword": "Ingek log masuak denai di paramban ko (salamo $1 {{PLURAL:$1|hari}})",
        "userlogin-remembermypassword": "Biakan ambo tetap masuak",
        "userlogin-signwithsecure": "Gunoan server aman",
        "yourdomainname": "Domain Sanak:",
        "listusers-blocked": "(tasakek)",
        "activeusers": "Daftar pangguno aktif",
        "activeusers-from": "Tunjuakan pangguno mulai dari:",
-       "activeusers-hidebots": "Suruakan bot",
-       "activeusers-hidesysops": "Suruakan panguruih",
        "activeusers-noresult": "Pangguno indak basobok",
        "listgrouprights": "Daftar kalompok pangguno",
        "listgrouprights-summary": "Barikuik ko adolah daftar kalompok pangguno nan ado di wiki ko, jo daftar hak aksesnyo masiang-masiang. Informasi labih lanjuik masalah hak masiang-masiang dapek dijumpoi di [[{{MediaWiki:Listgrouprights-helppage}}|laman bantuan hak pangguno]].",
index bfb6fee..831218c 100644 (file)
        "views": "Посети",
        "toolbox": "Алатки",
        "tool-link-userrights": "Смени ги {{GENDER:$1|корисничките}} групи",
+       "tool-link-userrights-readonly": "Погл. {{GENDER:$1|кориснички}} групи",
        "tool-link-emailuser": "Испрати е-пошта на {{GENDER:$1|корисников}}",
        "userpage": "Преглед на корисничката страница",
        "projectpage": "Преглед на проектната страница",
        "passwordreset-emaildisabled": "Можностите за е-пошта се исклучени на ова вики",
        "passwordreset-username": "Корисничко име:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Да ја прикажам пораката?",
-       "passwordreset-capture-help": "Ако го штиклирате кутивчево, ќе ви се прикаже пораката (со привремената лозинка) и истата ќе му биде испратена на корисникот.",
        "passwordreset-email": "Е-пошта:",
        "passwordreset-emailtitle": "Најавни податоци за {{SITENAME}}",
        "passwordreset-emailtext-ip": "Некој (веројатно вие, од IP-адресата $1) побара измена на вашата\nлозинка за {{SITENAME}} ($4). Оваа е-поштенска адреса е наведена во\n{{PLURAL:$3|следнава корисничка сметка|следниве кориснички сметки}}:\n\n$2\n\n{{PLURAL:$3|Оваа привремена лозинка ќе истече|Овие привремени лозинки ќе истечат}} во рок од {{PLURAL:$5|еден ден|$5 дена}}.\nСега треба да се најавите и да внесете нова лозинка. Ако ова барање го\nпоставил некој друг, или пак во меѓувреме сте се сетиле на лозинката, и не сакате\nда ја менувате, тогаш слободно занемарете ја поракава и продолжете да ја користите старата.",
        "passwordreset-emailelement": "Корисничко име: \n$1\n\nПривремена лозинка: \n$2",
        "passwordreset-emailsentemail": "Ако ова е регистрираната е-пошта поврзана со вашата сметка, тогаш ќе ви биде испратено писмо за задавање на нова лозинка.",
        "passwordreset-emailsentusername": "Ако има соодветна регистрирана е-пошта поврзана со ова корисничко име, тогаш ќе ви биде испратена порака за промена на лозинката.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Е-поштата за задавање на нова лозинка|Е-поштата за задавање на нови лозинки}} е испратена. Тука е {{PLURAL:$1|е прикажано корисничкото име и лозинката|прикажан список на кориснички имиња и лозинки}}.",
-       "passwordreset-emailerror-capture2": "Испраќањето е-пошта на {{GENDER:$2|корисникот}} не успеа: $1 Тука е {{PLURAL:$3|прикажано корисничкото име и лозинката|прикажан список на кориснички имиња и лозинки}}.",
        "passwordreset-nocaller": "Мора да се укаже повикувач",
        "passwordreset-nosuchcaller": "Повикувачот не постои: $1",
        "passwordreset-ignored": "Менувањето на лозинката не успеа. Можеби не е поставен услужник?",
-       "passwordreset-invalideamil": "Неважечка е-пошта",
+       "passwordreset-invalidemail": "Неважечка е-пошта",
        "passwordreset-nodata": "Немате укажано ни корисничко име, ни е-пошта.",
        "changeemail": "Смени или отстрани е-пошта",
        "changeemail-header": "Пополнете го образецов за да ја смените е-поштата. Ако сакате да ја отстраните адресата од вашата сметка, оставете го празно полето за нова е-пошта.",
        "search-external": "Надворешно пребарување",
        "searchdisabled": "{{SITENAME}} пребарувањето е оневозможено.\nВо меѓувреме, можете да пребарувате преку Google.\nДа напоменеме дека нивното индексирање на {{SITENAME}} содржините може да биде застарено.",
        "search-error": "Се појави грешка при пребарувањето: $1",
+       "search-warning": "Се појави предупредување при пребарувањето: $1",
        "preferences": "Нагодувања",
        "mypreferences": "нагодувања",
        "prefs-edits": "Број на уредувања:",
        "prefs-help-recentchangescount": "Подразбира скорешни промени, истории на страници и дневници.",
        "prefs-help-watchlist-token2": "Ова е тајна шифра за вашиот канализиран список на набљудувања.\nСекој што ја знае ќе може да ја чита, па затоа ви препорачуваме да не ја кажувате никому.\n[[Special:ResetTokens|Стиснете тука ако треба да зададете нова]].",
        "savedprefs": "Вашите нагодувања се зачувани.",
-       "savedrights": "Ð\9aоÑ\80иÑ\81ниÑ\87киÑ\82е Ð¿Ñ\80ава Ð½Ð° {{GENDER:$1|$1}} Ð½Ðµ се зачувани.",
+       "savedrights": "Ð\9aоÑ\80иÑ\81ниÑ\87киÑ\82е Ð³Ñ\80Ñ\83пи Ð½Ð° {{GENDER:$1|$1}} се зачувани.",
        "timezonelegend": "Часовен појас:",
        "localtime": "Месно време:",
        "timezoneuseserverdefault": "Од викито ($1)",
        "prefswarning-warning": "Направивте промени во нагодувањата, но не ги зачувавте.\nИзмената нема да се изврши ако ја напуштите страницава без да стиснете на „$1“.",
        "prefs-tabs-navigation-hint": "Совет: Можете да ги користите стрелките на тастатурата за да преоѓате од едно на друго јазиче во списокот на јазичиња.",
        "userrights": "Раководење со кориснички права",
-       "userrights-lookup-user": "РаководеÑ\9aе Ñ\81о ÐºÐ¾Ñ\80иÑ\81ниÑ\87ки Ð³Ñ\80Ñ\83пи",
+       "userrights-lookup-user": "Ð\98збеÑ\80еÑ\82е ÐºÐ¾Ñ\80иÑ\81ник",
        "userrights-user-editname": "Внесете корисничко име:",
-       "editusergroup": "УÑ\80еди {{GENDER:$1|коÑ\80иÑ\81ниÑ\87ки}} групи",
+       "editusergroup": "Ð\92Ñ\87иÑ\82аÑ\98 ÐºÐ¾Ñ\80иÑ\81ниÑ\87ки групи",
        "editinguser": "Менување на правата на {{GENDER:$1|корисникот}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Поглед на правата на {{GENDER:$1|корисникот}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Уреди ги корисничките групи",
+       "userrights-viewusergroup": "Преглед на корисничките групи",
        "saveusergroups": "Зачувај ги {{GENDER:$1|корисничките}} групи",
        "userrights-groupsmember": "Член на:",
        "userrights-groupsmember-auto": "Подразбран член на:",
        "userrights-reason": "Причина:",
        "userrights-no-interwiki": "Немате дозвола за уредување на кориснички права на други викија.",
        "userrights-nodatabase": "Базата на податоци $1 не постои или не е месна.",
-       "userrights-nologin": "Мора да сте [[Special:UserLogin|најавени]] со администраторска корисничка сметка за да може да вршите промена на кориснички права.",
-       "userrights-notallowed": "Немате дозвола за додавање и отстранување на кориснички права.",
        "userrights-changeable-col": "Групи кои може да ги промените",
        "userrights-unchangeable-col": "Групи кои не може да ги промените",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Спротиставеност во измените на корисничките права. Прегледајте ги и потврдете ги.",
-       "userrights-removed-self": "Ги отстранивте вашите права. Затоа, повеќе немате пристап на страницава.",
        "group": "Група:",
        "group-user": "Корисници",
        "group-autoconfirmed": "Автопотврдени корисници",
        "right-siteadmin": "Заклучување и отклучување на базата на податоци",
        "right-override-export-depth": "Извезување на страници вклучувајќи поврзани страници со длабочина до 5",
        "right-sendemail": "Испраќање на е-пошта до други корисници",
-       "right-passwordreset": "Преглед на пораки по е-пошта за промена на лозинка",
        "right-managechangetags": "Создавање и (де)активирање на [[Special:Tags|ознаки]]",
        "right-applychangetags": "Задавање на [[Special:Tags|ознаки]] заедно со направените измени",
        "right-changetags": "Додавате и отстранување на произволни [[Special:Tags|ознаки]] во поединечни преработки и дневнички записи",
        "action-upload_by_url": "подигни ја податотекава од URL-адреса",
        "action-writeapi": "употребете запишување во извршникот",
        "action-delete": "избриши ја страницава",
-       "action-deleterevision": "избриши ја ревизијава",
-       "action-deletedhistory": "прегледај ја историјата на бришења за оваа страница",
+       "action-deleterevision": "бришење преработки",
+       "action-deletelogentry": "бришење на дневнички записи",
+       "action-deletedhistory": "преглед на историјата на бришења на оваа страница",
+       "action-deletedtext": "преглед на текст на избришани преработки",
        "action-browsearchive": "барање на избришани страници",
-       "action-undelete": "обнови Ñ\98а Ñ\81Ñ\82Ñ\80аниÑ\86ава",
-       "action-suppressrevision": "прегледај ја и обнови ја оваа скриена преработка",
+       "action-undelete": "обнова Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86и",
+       "action-suppressrevision": "преглед ја и обнова на скриени преработки",
        "action-suppressionlog": "преглед на овој li;en дневник",
        "action-block": "оневозможување на уредувањето на корисников",
        "action-protect": "измени го степенот на заштита на оваа страница",
        "action-userrights-interwiki": "уредување на кориснички права на корисници на други викија",
        "action-siteadmin": "заклучување или отклучување на базата на податоци",
        "action-sendemail": "испраќање на е-пошта",
+       "action-editmyoptions": "уредување на вашите нагодувања",
        "action-editmywatchlist": "уредување на мои набљудувани",
        "action-viewmywatchlist": "преглед на вашиот список на набљудувања",
        "action-viewmyprivateinfo": "преглед на вашите лични податоци",
        "apisandbox-continue": "Продолжи",
        "apisandbox-continue-clear": "Исчисти",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} ќе [https://www.mediawiki.org/wiki/API:Query#Continuing_queries продолжи] со последното барање; „{{int:apisandbox-continue-clear}}“ ќе ги исчисти параметрите поврзани со продолжување.",
+       "apisandbox-param-limit": "Внесете <kbd>max</kbd> за да ја користите најгорната граница.",
+       "apisandbox-multivalue-all-namespaces": "$1 (сите именски простори)",
+       "apisandbox-multivalue-all-values": "$1 (сите вредности)",
        "booksources": "Печатени извори",
        "booksources-search-legend": "Пребарување на извори за книга",
        "booksources-isbn": "ISBN:",
        "activeusers-count": "$1 {{PLURAL:$1|дејство|дејства}} {{PLURAL:$3|денес|во последните $3 дена}}",
        "activeusers-from": "Прикажи корисници почнувајќи од:",
        "activeusers-groups": "Прикажи ги корисниците кои членуваат во групите:",
+       "activeusers-excludegroups": "Изземи ги корисниците што членуваат во групите:",
        "activeusers-noresult": "Не пронајдов ниеден корисник.",
        "activeusers-submit": "Прикажи активни корисници",
        "listgrouprights": "Права на кориснички групи",
        "emailccsubject": "Копија од вашата порака до $1: $2",
        "emailsent": "Писмото е испратено",
        "emailsenttext": "Писмото е испратено.",
-       "emailuserfooter": "$1 го испрати писмово на {{GENDER:$2|$2}} со помош на функцијата „{{int:emailuser}}“ на {{SITENAME}}.",
+       "emailuserfooter": "$1 го испрати писмово на {{GENDER:$2|$2}} со помош на функцијата „{{int:emailuser}}“ на {{SITENAME}}. {{GENDER:$2|Вашата}} е-пошта ќе му биде испратена право на {{GENDER:$1|изворниот испраќач}}, откривајќи {{GENDER:$1|му}} ја {{GENDER:$2|вашата}} адреса.",
        "usermessage-summary": "Оставете системска порака.",
        "usermessage-editor": "Системски гласник",
        "usermessage-template": "MediaWiki:КорисникПорака",
        "tags-deactivate": "деактивирај",
        "tags-hitcount": "$1 {{PLURAL:$1|промена|промени}}",
        "tags-manage-no-permission": "Немате дозвола за раководење со ознаки за промени.",
-       "tags-manage-blocked": "Не можете да раководите со ознаки за промени додека сте блокирани.",
+       "tags-manage-blocked": "Не можете да раководите со ознаки за промени додека {{GENDER:$1|сте}} блокирани.",
        "tags-create-heading": "Создај нова ознака",
        "tags-create-explanation": "Новосоздадните ознаки по основно ќе се стават на располагање за употреба од корисници и ботови.",
        "tags-create-tag-name": "Име на ознаката:",
        "tags-deactivate-not-allowed": "Не можам да ја деактивирам ознаката „$1“.",
        "tags-deactivate-submit": "Декативирај",
        "tags-apply-no-permission": "Немате дозвола да ставате ознаки за промени заедно со измените што ги правите.",
-       "tags-apply-blocked": "Не можете да задавате ознаки за промени додека сте блокирани.",
+       "tags-apply-blocked": "Не можете да задавате ознаки за промени додека {{GENDER:$1|сте}} блокирани.",
        "tags-apply-not-allowed-one": "Не е дозволено ознаката „$1“ да се става рачно.",
        "tags-apply-not-allowed-multi": "Не е дозволено {{PLURAL:$2|следнава ознака да се става рачно|следниве ознаки да се ставаат рачно}}: $1",
        "tags-update-no-permission": "Немате дозвола да додавате или отстранувате ознаки за промена од поединечни преработки или дневнички записи.",
-       "tags-update-blocked": "Не можете да додавате и отстранувате ознаки за промени додека сте блокирани.",
+       "tags-update-blocked": "Не можете да додавате и отстранувате ознаки за промени додека {{GENDER:$1|сте}} блокирани.",
        "tags-update-add-not-allowed-one": "Не е дозволено ознаката „$1“ да се додава рачно.",
        "tags-update-add-not-allowed-multi": "Не е дозволено {{PLURAL:$2|следнава ознака да се додава рачно|следниве ознаки да се додаваат рачно}}: $1",
        "tags-update-remove-not-allowed-one": "Не е дозволено да се отстранува ознаката „$1“.",
        "htmlform-user-not-exists": "<strong>$1</strong> не постои.",
        "htmlform-user-not-valid": "<strong>$1</strong> не претставува важечко корисничко име.",
        "logentry-delete-delete": "$1 {{GENDER:$2|ја избриша}} страницата $3",
+       "logentry-delete-delete_redir": "$1 го {{GENDER:$2|избриша}} пренасочувањето $3 со презапишување",
        "logentry-delete-restore": "$1 {{GENDER:$2|ја возобнови}} страницата $3",
        "logentry-delete-event": "$1 {{GENDER:$2|ја измени}} видливоста на {{PLURAL:$5|настан во дневникот|$5 настани во дневникот}} на $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|ја измени}} видливоста на {{PLURAL:$5|преработка|$5 преработки}} на страницата $3: $4",
        "mw-widgets-dateinput-no-date": "Немате одбрано датум",
        "mw-widgets-dateinput-placeholder-day": "ГГГГ-ММ-ДД",
        "mw-widgets-dateinput-placeholder-month": "ГГГГ-ММ",
+       "mw-widgets-mediasearch-input-placeholder": "Пребарајте слики/снимки",
+       "mw-widgets-mediasearch-noresults": "Не пронајдов ништо.",
        "mw-widgets-titleinput-description-new-page": "страницата сè уште не постои",
        "mw-widgets-titleinput-description-redirect": "пренасочување кон $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Додај категорија...",
        "sessionmanager-tie": "Не можете истовремено да користите повеќе типови барања за заверка: $1.",
        "sessionprovider-generic": "$1 седници",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "седници со колачиња",
        "log-action-filter-contentmodel-change": "Промена на содржински модел",
        "log-action-filter-contentmodel-new": "Создавање страница со нестандарден содржински модел",
        "log-action-filter-delete-delete": "Бришење на страница",
+       "log-action-filter-delete-delete_redir": "Презапишување врз пренасочување",
        "log-action-filter-delete-restore": "Повраток на страница",
        "log-action-filter-delete-event": "Бришење на дневник",
        "log-action-filter-delete-revision": "Бришење на преработка",
        "restrictionsfield-badip": "Неважечки IP-дијапазон на адреси: $1",
        "restrictionsfield-label": "Допуштени IP-опсези:",
        "restrictionsfield-help": "Една IP-адреса или CIDR-опсег по ред. За да овозможите сè, користете<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Грешка: $1",
-       "edit-error-long": "Грешки:\n\n$1"
+       "revid": "п$1",
+       "pageid": "назнака на страницата $1"
 }
index 022f07f..cbb7d06 100644 (file)
        "activeusers-intro": "ഇത് കഴിഞ്ഞ {{PLURAL:$1|ദിവസം|$1 ദിവസങ്ങളിൽ}} ഏതെങ്കിലും വിധത്തിലുള്ള പ്രവർത്തനങ്ങൾ ചെയ്ത ഉപയോക്താക്കളുടെ പട്ടികയാണ്.",
        "activeusers-count": "കഴിഞ്ഞ {{PLURAL:$3|ഒരു ദിവസം|$3 ദിവസങ്ങളിൽ}} {{PLURAL:$1|ഒരു പ്രവൃത്തി|$1 പ്രവൃത്തികൾ}}",
        "activeusers-from": "ഇങ്ങനെ തുടങ്ങുന്ന ഉപയോക്താക്കളെ കാട്ടുക:",
-       "activeusers-hidebots": "യന്ത്രങ്ങളെ മറയ്ക്കുക",
-       "activeusers-hidesysops": "കാര്യനിർവാഹകരെ മറയ്ക്കുക",
        "activeusers-noresult": "ഉപയോക്താക്കളില്ല",
        "activeusers-submit": "സജീവ ഉപയോക്താക്കളെ പ്രദർശിപ്പിക്കുക",
        "listgrouprights": "ഉപയോക്തൃവിഭാഗത്തിന്റെ അവകാശങ്ങൾ",
index 3e85f15..1596eb6 100644 (file)
        "namespaces": "नामविश्वे",
        "variants": "चले(व्हेरियंट्स)",
        "navigation-heading": "दिक्चालन यादी",
-       "errorpagetitle": "à¤\9aà¥\82à¤\95",
+       "errorpagetitle": "तà¥\8dरà¥\81à¤\9fà¥\80",
        "returnto": "$1 कडे परत चला.",
        "tagline": "{{SITENAME}} कडून",
        "help": "साहाय्य",
        "passwordreset-emaildisabled": "या विकिवर विपत्र पाठविणे 'अशक्य' करण्यात आलेले आहे.",
        "passwordreset-username": "सदस्यनाव:",
        "passwordreset-domain": "डोमेन",
-       "passwordreset-capture": "ईमेल कशी असेल ते बघायचेय ?",
-       "passwordreset-capture-help": "या चौकटीत खूण केली तर, ईमेल (तात्पुरत्या परवलीच्या शब्दासह) दाखविण्यात व सदस्यास पाठविण्यात येईल.",
        "passwordreset-email": "विपत्र पत्ता",
        "passwordreset-emailtitle": "{{SITENAME}} वरील खात्याची माहिती",
        "passwordreset-emailtext-ip": "कुणीतरी (कदाचित तुम्ही, अंकपत्ता $1 वरुन) {{SITENAME}}($4) करिता नविन 'परवलीचा शब्द' पुनर्स्थापनेबद्दल विनंती केली आहे.\nखालील{{PLURAL:$3|सदस्यखाते}}या विपत्रपत्त्याशी निगडीत आहे: \n\"$2\"\n{{PLURAL:$3|हा तात्पुरता परवलीचा शब्द|हे तात्पुरते परवलीचे शब्द}}{{PLURAL:$5|एक दिवस|$5 दिवसात}} मुदतबाह्य होतील.आता आपण लॉग-ईन करून  नविन परवलीचा शब्द निवडा.जर ईतर कोणी ही विनंती केली असेल,किंवा जर आपणास परवलीच शब्द आठवला असेल तर,व जर आपण तो बदलु इच्छित नसाल तर आपण हा संदेश टाळा व आपला जुना परवलीचा शब्द वापरणे सुरू ठेवा.",
        "userrights-reason": "कारण:",
        "userrights-no-interwiki": "इतर विकींवरचे सदस्य अधिकार बदलण्याची परवानगी तुम्हाला नाही.",
        "userrights-nodatabase": "विदा $1 अस्तित्वात नाही अथवा स्थानिक नाही.",
-       "userrights-nologin": "सदस्य अधिकार देण्यासाठी तुम्ही प्रबंधक म्हणून [[Special:UserLogin|सनोंद प्रवेशित]] असणे आवश्यक आहे.",
-       "userrights-notallowed": "तुमच्या सदस्य खात्यास, सदस्य अधिकारांची निश्चिती करण्याची परवानगी नाही.",
        "userrights-changeable-col": "गट जे तुम्ही बदलू शकता",
        "userrights-unchangeable-col": "गट जे तुम्ही बदलू शकत नाही",
        "userrights-conflict": "बदलाबाबत सदस्य-हक्क विसंवाद !कृपया आपले बदल पुन्हा पुनरावलोकित व नक्की करा.",
-       "userrights-removed-self": "आपण आपले हक्क यशस्वीरित्या काढलेत.म्हणुन, या पानात आपण दाखल होऊ शकणार नाही.",
        "group": "गट:",
        "group-user": "सदस्य",
        "group-autoconfirmed": "स्वयंशाबीत सदस्य",
        "right-siteadmin": "माहितीसाठ्याला कुलूप लावा अथवा काढा",
        "right-override-export-depth": "जोडलेल्या पानांचा पाचव्या पातळीपर्यंत अंतर्भाव करुन पाने निर्यात करा",
        "right-sendemail": "इतर सदस्यांना विपत्रे पाठवा",
-       "right-passwordreset": "परवलीचा शब्द पुनर्स्थापित केल्याचे विपत्र पहा.",
        "right-managechangetags": "डाटाबेस मधून [[Special:Tags|खूणपताका]] तयार करा किंवा  वगळा",
        "right-applychangetags": "कोणाच्याही बदलास [[Special:Tags|खूणपताका]] जोडा",
        "right-changetags": "वैयक्तिक आवृत्त्यांना व नोंद प्रवेष्ट्यांना, आहेतुक(arbitrary) [[Special:Tags|खूणपताका]] जोडा अथवा हटवा",
        "activeusers-intro": "शेवटच्या $1 {{PLURAL:$1|दिवसात}} काम केलेल्या सदस्यांची यादी येथे मिळेल",
        "activeusers-count": "शेवटच्या {{PLURAL:$3|दिवसात|$3 दिवसांत}} $1 {{PLURAL:$1|क्रिया}}",
        "activeusers-from": "पुढील शब्दापासून सुरू होणारे सदस्य दाखवा:",
-       "activeusers-hidebots": "सांगकामे लपवा",
-       "activeusers-hidesysops": "प्रचालक लपवा",
        "activeusers-noresult": "एकही सदस्य सापडला नाही.",
        "activeusers-submit": "सक्रिय सदस्य दर्शवा",
        "listgrouprights": "सदस्य गट अधिकार",
        "listgrants": "अनुदाने",
        "listgrants-grant": "अनुदान",
        "listgrants-rights": "अधिकार",
-       "trackingcategories": "वरà¥\8dà¤\97 à¤¶à¥\8bधत à¤\86हà¥\8bत",
+       "trackingcategories": "माà¤\97à¥\8bवा à¤\98à¥\87णारà¥\87 à¤µà¤°à¥\8dà¤\97",
        "trackingcategories-summary": "या पानात ते रेखापथनातील वर्ग(tracking categories) आहेत, जे, मिडियाविकि संचेतनाद्वारे स्वयंचलितरित्या वसविण्यात (तयार करण्यात) आले आहेत. त्यांची नावे, {{ns:8}} नामविश्वातील संबंधित प्रणाली संदेशात फेरफार करुन, बदलविता येतात.",
+       "trackingcategories-msg": "मागोवा घेणारा वर्ग",
        "trackingcategories-name": "संदेश नाम",
        "trackingcategories-desc": "वर्ग अंतर्भूत करण्याचे निकष",
        "trackingcategories-nodesc": "वर्णन उपलब्ध नाही.",
        "randomrootpage": "अविशिष्ट मूळ पान",
        "log-action-filter-suppress-block": "रोधामार्फत सदस्य दाबणे",
        "changecredentials": "अधिकारपत्रे (क्रेडेंटियल्स)बदला",
-       "removecredentials": "अधिकारपत्रे (क्रेडेंटियल्स) हटवा",
-       "edit-error-short": "त्रुटी: $1",
-       "edit-error-long": "त्रुटी:$1"
+       "removecredentials": "अधिकारपत्रे (क्रेडेंटियल्स) हटवा"
 }
index 305228d..0a5267d 100644 (file)
        "yourpasswordagain": "Ulangi kata laluan:",
        "createacct-yourpasswordagain": "Sahkan kata laluan",
        "createacct-yourpasswordagain-ph": "Isikan kata laluan semula",
-       "remembermypassword": "Ingat log masuk saya pada pelayar ini (tidak melebihi $1 {{PLURAL:$1|hari|hari}})",
        "userlogin-remembermypassword": "Biar saya kekal log masuk",
        "userlogin-signwithsecure": "Gunakan sambungan terlindung",
        "yourdomainname": "Domain anda:",
        "activeusers-intro": "Yang berikut ialah senarai pengguna yang bergiat sejak {{PLURAL:$1|semalam|$1 hari lalu}}.",
        "activeusers-count": "$1 tindakan sejak {{PLURAL:$3|semalam|$3 hari lalu}}",
        "activeusers-from": "Tunjukkan pengguna bermula pada:",
-       "activeusers-hidebots": "Sorokkan bot",
-       "activeusers-hidesysops": "Sorokkan penyelia",
        "activeusers-noresult": "Tiada pengguna dijumpai.",
        "listgrouprights": "Hak kumpulan pengguna",
        "listgrouprights-summary": "Berikut adalah senarai kumpulan pengguna yang ditubuhkan di wiki ini, dengan hak-hak mereka masing-masing.\nMungkin terdapat [[{{MediaWiki:Listgrouprights-helppage}}|maklumat tambahan]] mengenai setiap hak.",
        "htmlform-cloner-create": "Tambah lebih",
        "htmlform-cloner-delete": "Buang",
        "htmlform-cloner-required": "Sekurang-kurangnya satu nilai diperlukan.",
-       "sqlite-has-fts": "$1 dengan sokongan carian teks penuh",
-       "sqlite-no-fts": "$1 tanpa sokongan carian teks penuh",
        "logentry-delete-delete": "$1 telah {{GENDER:$2|menghapuskan}} laman $3",
        "logentry-delete-restore": "$1 telah {{GENDER:$2|memulihkan}} laman $3",
        "logentry-delete-event": "$1 telah {{GENDER:$2|mengubah}} keterlihatan $5 peristiwa log di $3: $4",
        "feedback-external-bug-report-button": "Failkan tugas teknikal",
        "feedback-dialog-title": "Hantar maklum balas",
        "feedback-dialog-intro": "Anda boleh menggunakan borang yang mudah di bawah untuk menyerahkan maklum balas. Ulasan anda akan disiarkan pada laman \"$1\" di samping nama pengguna anda.",
-       "feedback-error-title": "Ralat",
        "feedback-error1": "Perhatian: Hasil dari API tidak dikenali",
        "feedback-error2": "Perhatian: Penyuntingan gagal",
        "feedback-error3": "Perhatian: Tiada gerak balas dari API",
index 56e90a0..41c6a59 100644 (file)
        "yourname": "Nome de Outelizador",
        "yourpassword": "Palabra chabe",
        "yourpasswordagain": "Repite la tue palabra-chabe",
-       "remembermypassword": "Lhembrar-se de mi neste cumputador (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "L tou domínio",
        "login": "Antrar",
        "nav-login-createaccount": "Antrar / criar cuonta",
index e2b8e1b..f0376cb 100644 (file)
        "activeusers": "တက်ကြွလှုပ်ရှားသည့် အသုံးပြုသူစာရင်း",
        "activeusers-intro": "ဤသည်မှာ နောက်ဆုံး $1 {{PLURAL:$1|ရက်|ရက်}}အတွင်း တက်ကြွလှုပ်ရှားသည့် အသုံးပြုသူများ စာရင်း ဖြစ်သည်။",
        "activeusers-from": "ဤမှစသော အသုံးပြုသူများကို ပြရန် -",
-       "activeusers-hidebots": "ဘော့များကို ဝှက်ရန်",
-       "activeusers-hidesysops": "အက်ဒမင်များကို ဝှက်ရန်",
        "activeusers-noresult": "အသုံးပြုသူ မတွေ့ပါ။",
        "listgrouprights": "အသုံးပြုသူအုပ်စု အခွင့်အရေးများ",
        "listgrouprights-group": "အုပ်စု",
index 7bae28c..2a102ec 100644 (file)
        "listusers-noresult": "Совицязо а муеви",
        "listusers-blocked": "(саймас саезь)",
        "activeusers": "Активной теицятнеде списка",
-       "activeusers-hidebots": "Кекшемс ботатнень",
-       "activeusers-hidesysops": "Кекшемс администратортнэнь",
        "activeusers-noresult": "Якинзэ-пакинзэ арасть",
        "listgrouprights": "Теиця куронть видечинзэ",
        "listgrouprights-group": "Куро",
index dc66e13..a3b7c7e 100644 (file)
        "yourpasswordagain": "پسورد ره دِباره بنویس",
        "createacct-yourpasswordagain": "پسورد ره دِباره باوّین",
        "createacct-yourpasswordagain-ph": "پسورد ره دِباره باوّین",
-       "remembermypassword": "مه رمز ره (تا حداکثر $1 {{PLURAL:$1|روز|روز}}) این مرورگر سر یاد نکان",
        "userlogin-remembermypassword": "مه ره سایت دله دار",
        "yourdomainname": "شمه کاروری نوم",
        "login": "دله بوردن",
        "api-error-unknown-error": "خطای داخلی: زمونی که شما تلاش کاردنی باربی‌یشتن پرونده ره انجوم هادین، اتا چی اشتباه پیش بورده.",
        "api-error-unknown-warning": "اخطار نشناسی‌یه: $1",
        "api-error-uploaddisabled": "باربی‌یشتن این ویکی دله غیرفعاله.",
-       "api-error-verification-error": "ممکن هسته که پرونده رِقِد بورد بائه یا پسوند غلط داره.",
-       "api-error-blacklisted": "اتا عنوان توصیفی دیگه انتخاب هاکنین."
+       "api-error-verification-error": "ممکن هسته که پرونده رِقِد بورد بائه یا پسوند غلط داره."
 }
index e61e6d7..54f3004 100644 (file)
@@ -31,7 +31,7 @@
        "tog-previewontop": "Tiquittāz achtochīhualiztli achtopa tlapatlaliztli caxitl",
        "tog-previewonfirst": "Xiquitta achtochīhualiztli inic cē tlapatlalizpan",
        "tog-enotifwatchlistpages": "Notech moēhualtia cē maltzinteyōtl netitlaniztli ihcuāc mopatla zāzanilli in notlachiyaliz.",
-       "tog-enotifusertalkpages": "Nēchihtoa ihcuāc tlecpatla motēixnāmiquiliz",
+       "tog-enotifusertalkpages": "Ma annechihtoa ica ce tetitlaniliztli ihcuāc mopatla noteixnamiquiliz",
        "tog-enotifminoredits": "Notech moēhualtia cē maltzinteyōtl netitlaniztli nō ihcuāc mopatla tepitōn zāzanilli in notlachiyaliz.",
        "tog-enotifrevealaddr": "Ticnēxtīz mo e-mailcān āxcāncayōtechcopa āmatlacuilizpan",
        "tog-shownumberswatching": "Tiquinttāz tlatequitiltilīlli tlein tlachiyacateh",
@@ -53,7 +53,7 @@
        "editfont-serif": "Serif machiyōtlahtōliztli",
        "sunday": "Īccemilhuitl",
        "monday": "Īcōmilhuitl",
-       "tuesday": "Īcyēyilhuitl",
+       "tuesday": "Icyeyilhuitl",
        "wednesday": "Īcnāhuilhuitl",
        "thursday": "Īcmācuīlilhuitl",
        "friday": "Īcchicuacemilhuitl",
        "sun": "Cemilhui",
        "mon": "Ōmilhui",
        "tue": "Ēyilhui",
-       "wed": "Nāuhilhui",
-       "thu": "Mācuililhui",
+       "wed": "Nahuilhui",
+       "thu": "Macuililhui",
        "fri": "6 ilhui",
        "sat": "7 ilhui",
        "january": "Icce metztli",
        "february": "Icome metztli",
-       "march": "3 Metz",
-       "april": "Ic nāuhtetl mētztli",
-       "may_long": "Ic mācuīlli mētztli",
-       "june": "Ic chicuacē mētztli",
-       "july": "7 Metz",
-       "august": "8 Metz",
-       "september": "9 Metz",
-       "october": "10 Metz",
+       "march": "Ic yetetl metztli",
+       "april": "Ic nauhtetl metztli",
+       "may_long": "Ic macuiltetl metztli",
+       "june": "Ic chicuacentetl metztli",
+       "july": "Ic chicontetl metztli",
+       "august": "Ic chicuetetl metztli",
+       "september": "Ic chiucnahtetl metztli",
+       "october": "Ic mahtlactetl metztli",
        "november": "11 Metz",
        "december": "12 Metz",
        "january-gen": "Ic cē mētztli",
        "november-date": "Īcmahtlactlioncēmētztli $1",
        "december-date": "Īcmahtlactliomōmemētztli $1",
        "pagecategories": "{{PLURAL:$1|Neneuhcayotl|Neneuhcayomeh}}",
-       "category_header": "Tlâkuilòlpiltin ìpan tlaìxmatkàtlàlilòtl \"$1\"",
-       "subcategories": "Tlaìxmatkàtlàlilòpilòmë",
-       "category-media-header": "Media \"$1\" neneuhcāyōc",
-       "category-empty": "''Cah ahtlein inīn neneuhcāyōc.''",
-       "hidden-categories": "{{PLURAL:$1|tlatlàtìlli tlaìxmatkàyòtlàlilòtl|tlatlàtìltìn tlaìxmatkàyòtlàlilòme}}",
+       "category_header": "Tlahcuiloltin ipan neneuhcayotl \"$1\"",
+       "subcategories": "Tlani-neneuhcayotl",
+       "category-media-header": "Media \"$1\" ipan neneuhcayotl",
+       "category-empty": "''Ahtle oncah ipan neneuhcayotl.''",
+       "hidden-categories": "{{PLURAL:$1|tlatlatilli neneuhcayotl|tlatlatiltin neneuhcayomeh}}",
        "hidden-category-category": "Tlatlàtìlkàtlaìxmatkàtlàlilòmë",
-       "category-subcat-count": "{{PLURAL:$2|Inin neneuhcayotl zan quipiya in tetoquilli tlani-neneuhcayotl.|Inn neneuhcayotl {{PLURAL:$1|quipiya intetoquilli tlani-neneuhcayotl|in tetoquiltin $1 tlani-neneuhcayomeh}}, itech tlacecempohualoni $2.}}",
-       "category-subcat-count-limited": "Inīn {{PLURAL:$1|neneuhcāyōtzintli cah|$1 neneuhcāyōtzintli cateh}} inīn neneuhcāyōc.",
+       "category-subcat-count": "{{PLURAL:$2|Inin neneuhcayotl zan quipiya in tetoquilli tlani-neneuhcayotl.|Inin neneuhcayotl {{PLURAL:$1|quipiya in tetoquilli tlani-neneuhcayotl|in tetoquiltin $1 tlani-neneuhcayomeh}}, itech tlacecempohualoni $2.}}",
+       "category-subcat-count-limited": "Inin {{PLURAL:$1|neneuhcayotl quipiya|$1 in tetoquilli tlani-neneuhcayotl|in tetoquiltin tlani-neneuhcayomeh}}.",
        "category-article-count": "{{PLURAL:$2|Inin neneuhcayotl zan quipiya in tetoquilli tlahcuilolli.|{{PLURAL:$1|In tetoquilli tlahcuilolli itech pohui|In tetoquiltin $1 tlahcuiloltin itech pohui}}, inin neneuhcayotl itech tlacecempohualoni ipan $2.}}",
        "category-article-count-limited": "Inīn {{PLURAL:$1|zāzanilli cah|$1 zāzanilli cateh}} inīn neneuhcāyōc.",
        "category-file-count": "{{PLURAL:$2|Inìn tlaìxmatkàyòtlàlilòtl san kipia|Inìn tlaìxmatkàyòtlalilòtl kimpia {{PLURAL:$1|inìn èwalli|inîke $1 èwaltìn}}, ìwikpa $2.}}",
        "category-file-count-limited": "{{PLURAL:$1|Inìn tlâkuilòlèwalli kä|Inîkë $1 tlâkuilòlèwaltìn katêkë}} ìpan inìn tlaìxmatkàtlàlilòtl.",
        "listingcontinuesabbrev": "niman",
        "about": "Ītechcopa",
-       "article": "Tlâkuilòpilli",
-       "newwindow": "(Motlapoāz cē yancuīc tlanexillōtl)",
+       "article": "Tlahcuilolamatl",
+       "newwindow": "(Motlapoaz ce yancuic tlanexillotl)",
        "cancel": "Moxitiniz",
        "moredotdotdot": "Huehca ōmpa...",
        "mypage": "Noāmauh",
        "mytalk": "Teixnamiquiliztli",
-       "anontalk": "Tēixnāmiquiliztli",
-       "navigation": "Nēnemōhualiztli",
+       "anontalk": "Teixnamiquiliztli",
+       "navigation": "Panoliztli",
        "and": "&#32;ihuan",
        "qbfind": "Xicahci",
        "qbbrowse": "Xitlatepotztoca",
        "faqpage": "Project:FAQ",
        "actions": "Āyiliztli",
        "namespaces": "Tocatlacauhtli",
-       "variants": "Nepāpan",
+       "variants": "Nepapan",
        "navigation-heading": "Nemiliztlahtolpohualamatl",
        "errorpagetitle": "Aiuhcāyōtl",
        "returnto": "Ximocuepa īhuīc $1.",
        "searchbutton": "Tlatemoliztli",
        "go": "Xiyauh",
        "searcharticle": "Xiyauh",
-       "history": "Tlaīxtli ītlahtōllo",
+       "history": "Tlahtollotl",
        "history_short": "Tlahtollotl",
        "updatedmarker": "ōmoyancuīx īhuīcpa xōcoyōc notlahpololiz",
        "printableversion": "Tepoztlahcuilolli",
        "protectthispage": "Xicpiya inīn tlaīxtli",
        "unprotect": "Xicpatla in tlapiyaliztli",
        "unprotectthispage": "Xicpatla inīn tlaīxtli ītlapiyaliz",
-       "newpage": "Yancuic tlaīxtli",
+       "newpage": "Yancuic tlahcuilolli",
        "talkpage": "Xictlahto inīn tlaīxtli ītechcopa",
        "talkpagelinktext": "Teixnamiquiliztli",
        "specialpage": "Nònkuâkìskàtlaìxtlapalli",
        "personaltools": "In tlein nitēquitiltilia",
-       "articlepage": "Xiquitta in tlamantlaīxtli",
+       "articlepage": "Xiquitta tlahcuilolamatl",
        "talk": "Teixnamiquiliztli",
        "views": "Tlachiyaliztli",
        "toolbox": "Tequitihualoni",
        "userpage": "Xiquitta tlatequitiltilīlli zāzanilli",
        "projectpage": "Xiquitta tlachīhualiztli zāzanilli",
        "imagepage": "Xiquitta in zāzanilli īāma",
-       "mediawikipage": "Xiquitta tlahcuilōltzin zāzanilli",
-       "templatepage": "Xiquitta neīxcuītīllaīxtli",
+       "mediawikipage": "Xiquitta tetitlaniliztli itlahcuilolamauh",
+       "templatepage": "Xiquitta tlahcuilolamatl ineixcuitil",
        "viewhelppage": "Xiquitta tēpalēhuiliztli zāzanilli",
-       "categorypage": "Mà mỏta in tlaìxmatkàyòtlàlilòtlaìxtlapalli",
+       "categorypage": "Tiquittaz neneuhcayotl itlahcuilolamauh",
        "viewtalkpage": "Xiquitta tēixnāmiquiliztli zāzanilli",
-       "otherlanguages": "Occequīntīn tlahtōlcopa",
+       "otherlanguages": "Occequintin tlahtlahtolcopa",
        "redirectedfrom": "(Ōmotlacuep īhuīcpa $1)",
        "redirectpagesub": "Ōmotlacuep zāzanilli",
        "lastmodifiedat": "Inin tlahcuilolli omopatlac immanin $1, ipan $2.",
        "viewcount": "Inīn zāzanilli quintlapōhua {{PLURAL:$1|cē tlahpololiztli|$1 tlahpololiztli}}.",
        "protectedpage": "Ōmoquīxtix zāzanilli",
        "jumpto": "Īhuīcpa ticholōz:",
-       "jumptonavigation": "nēnemōhualiztli",
+       "jumptonavigation": "amapanoliztli",
        "jumptosearch": "Tlatemoliztli",
        "aboutsite": "Itechcopa {{SITENAME}}",
        "aboutpage": "Project:Itechcopa",
-       "copyright": "In tlahcuilōlli cah tlacēcencāhuani īpan $1 tel ahmo intlā īcuepca motēnēhua.",
+       "copyright": "In tlahcuilolpiyaliztli cah tlani tlacecencahuani $1 tel ahmo icuepca motenehua.",
        "copyrightpage": "{{ns:project}}:Tlachīhualōni ītlapiyaliz",
        "currentevents": "Axcancayotl",
-       "currentevents-url": "Project:Āxcāncāyōtl",
+       "currentevents-url": "Project:Axcancayotl",
        "disclaimers": "tlamamalquixtiliztli",
-       "edithelp": "Tlapatlaliztechcopa tēpalēhuiliztli",
+       "edithelp": "Tepalehuiliztli ica tlapatlaliztli",
        "helppage-top-gethelp": "Tēpalēhuiliztli",
        "mainpage": "Yacatlahcuilolli",
        "mainpage-description": "Yacatlahcuilolli",
        "site-rss-feed": "$1 RSS huelītiliztli",
        "site-atom-feed": "$1 Atom huelītiliztli",
        "page-rss-feed": "\"$1\" RSS huelītiliztli",
-       "page-atom-feed": "\"$1\" RSS huelītiliztli",
-       "red-link-title": "$1 (ahmo oncah tlahcuilolli)",
-       "nstab-main": "Tlahcuilolli-amatl",
-       "nstab-user": "Tlatequitiltilīlli",
+       "page-atom-feed": "\"$1\" RSS huelitiliztli",
+       "red-link-title": "$1 (ahmo oncah tlahcuilolamatl)",
+       "nstab-main": "Tlahcuilolamatl",
+       "nstab-user": "Tequitiuhqui itlahcuilolamauh",
        "nstab-media": "Mēdiatl",
        "nstab-special": "Noncuahquizqui tlahcuilolli",
        "nstab-project": "Ìtlaìxtlapal in tlayẻkàntekitl",
        "filedeleteerror": "Ahmō ōmohuelītic tlapoloa \"$1\".",
        "filenotfound": "Ahmō ōmohuelītic tlanāmiqui \"$1\".",
        "cannotdelete": "Ahmō ōhuelītic mopoloa in zāzanilli \"$1\".\nHueli tlein āquin ōquipolo achtopa.",
-       "badtitle": "Ahcualli tōcāitl",
+       "badtitle": "Ahcualli tocaitl",
        "badtitletext": "Zāzanilli ticnequi in ītōca cah ahcualli, ahtlein quipiya nozo ahcualtzonhuiliztli interwiki tōcāhuicpa.\nHueliz quimpiya tlahtōl tlein ahmo mohuelītih motequitiltia tōcāpan.",
-       "viewsource": "Xiquitta mēyalli",
+       "viewsource": "Tiquittaz itzintiliz",
        "viewsource-title": "Xiquitta in $1 īmēyal",
        "actionthrottled": "Tlachīhualiztli ōmotzacuili",
        "viewsourcetext": "Tihuelīti tiquittaz auh ticcopīnaz inīn zāzanilli īmachiyōnecaquilizmēyal.",
        "virus-unknownscanner": "ahmatic antivirus:",
        "welcomeuser": "Ximopanōlti, $1!",
        "yourname": "Tequihuihcātōcāitl:",
-       "userlogin-yourname": "Tequihuihcātōcāitl",
+       "userlogin-yourname": "Tequitiuhcatocaitl",
        "userlogin-yourname-ph": "Xiquihcuilo motoca iuhqui tequitihuani",
        "yourpassword": "Motlahtōlichtacāyo",
        "userlogin-yourpassword": "Ichtacamachiyotl",
        "yourdomainname": "Moāxcāyō",
        "login": "Xicalaqui",
        "nav-login-createaccount": "Ximocalaqui / ximomachiyōmaca",
-       "userlogin": "Ximomachiyōmaca/Ximocalaqui",
+       "userlogin": "Ximomachiyomaca/Ximocalaqui",
        "userloginnocreate": "Ximocalaqui",
        "logout": "Xiquīza",
        "userlogout": "Xiquīza",
        "notloggedin": "Ahmō ōtimocalac",
-       "userlogin-noaccount": "Cuix ahmō titlapōhualeh?",
+       "userlogin-noaccount": "Cuix ahmo titlapohualeh?",
        "nologin": "Cuix ahmō titlapōhualeh? $1.",
        "nologinlink": "Xicchīhua cē tlapōhualli",
        "createaccount": "Xicchīhua tlapōhualli",
        "gotaccountlink": "Ximocalaqui",
        "createacct-email-ph": "xiquihcuilo mocorreo electrónico",
        "createaccountmail": "Ticnemītīz ahmo cemihcac zāzoichtacātlahtōlli nō in tiquēhualtīz in maltzinteyōtl monetitlanizyeyān",
-       "createaccountreason": "Tleīpampa:",
+       "createaccountreason": "Tleipampa:",
        "createacct-reason": "Tleīpampa",
        "createacct-submit": "Xicchīhua in motlapōhual",
        "badretype": "Ahneneuhqui motlahtōlichtacāyo.",
        "resetpass-submit-loggedin": "Ticpatlāz motlahtōlichtacāyo",
        "resetpass-submit-cancel": "Xiccāhua",
        "passwordreset-username": "Tequihuihcātōcāitl:",
-       "bold_sample": "Tlīltic tlahcuilōlli",
+       "bold_sample": "Tliltic tlahcuilolpiyaliz",
        "bold_tip": "Tlīltic tlahcuilōlli",
        "italic_sample": "Cōliuhqui tlahcuilōliztli",
        "italic_tip": "Cōliuhqui tlahcuilōliztli",
        "hr_tip": "Pāntli",
        "summary": "Mopatlaliz:",
        "subject": "Ītechpa:",
-       "minoredit": "Ca tepitōn inīn tlapatlaliztli",
-       "watchthis": "Xicpiya inīn tlaīxtli",
+       "minoredit": "Ca tepiton inin tlapatlaliztli",
+       "watchthis": "Tictlachiyaz inin tlahcuilolli",
        "savearticle": "Xicpiya tlahcuilolli",
        "preview": "Xiquitta achtochīhualiztli",
-       "showpreview": "Xiquitta achtochīhualiztli",
-       "showdiff": "Xicnēxti tlapatlaliztli",
+       "showpreview": "Xiquitta achtochihualiztli",
+       "showdiff": "Monextiz tlapatlaliztli",
        "missingcommenttext": "Timitztlātlauhtiah xitlanitlahcuiloa.",
        "summary-preview": "Tlahcuilōltōn achtochīhualiztli:",
        "blockedtitle": "Ōmotzacuili tlatequitiltilīlli",
        "accmailtext": "Ōquiyōcox zāzochtacātlahtōlli in [[User talk:$1|$1]] auh ōmoquitītlan īhuīc $2. Tihueliti ticpatlaz īpan ''[[Special:ChangePassword|Ticpatlaz in ]]'' in ōticalaco achtopa.",
        "newarticle": "(Yancuic)",
        "newarticletext": "Ōtictocac cētiliztli cē zāzanilhuīc oc ahmo ia. Intlā quiēlēhuia quichīhua, xitlahcuiloa niman (nō xiquitta [$1 tēpalēhuiliztli zāzanilli] huehca ōmpa tlapatlaliztli). Intlā ahmo, yāuh achtopa zāzanilli.",
-       "noarticletext": "In āxcān, ahmō onca tlahcuilōlli inīn zāzanilpan.\nTihuelīti [[Special:Search/{{PAGENAME}}|tictēmōz inīn zāzanilli ītōca]] occequīntīn zāzanilpan,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} xictēmoa īpan in tlapōhualāmatechpa],\nahnozo [{{fullurl:{{FULLPAGENAME}}|action=edit}} xichīhua inīn zāzanilli]</span>.",
+       "noarticletext": "In axcan, ahmo oncah tlahcuilolli ipan inin amatl.\nTihueliti [[Special:Search/{{PAGENAME}}|tictemoz inin tlahcuilolli itoca]] occequintin tlahcuilolli,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} xictemoa ipan in occe tlahcuilolmachiyotl],\nahnozo [{{fullurl:{{FULLPAGENAME}}|action=edit}} xichihua inin tlahcuilolli]</span>.",
        "userpage-userdoesnotexist": "Ahmo ia cuentah \"<nowiki>$1</nowiki>\" ītōca. Timitztlātlauhtiah xitēchquinōtza intlā ticchīhuāz intlā nozo ticpatlāz inīn zāzanilli.",
        "usercsspreview": "'''Ca inīn moachtochīhualiz ītechcopa moCSS.'''\n'''¡Ahmo ōmochīuh nozan!'''",
        "userjspreview": "'''Ca inīn moachtochīhualiz ītechcopa moJavaScript.'''\n'''¡Ahmo ōmochīuh nozan!'''",
        "editingsection": "Ticpatlacah $1 (tlahtōltzintli)",
        "editingcomment": "Ticpatlacah $1 (tlahtōltzintli)",
        "editconflict": "Tlapatlaliztli yāōyōtōn: $1",
-       "yourtext": "Motlahcuilōl",
+       "yourtext": "Motlahcuilolpiyaliz",
        "yourdiff": "Ahneneuhquiliztli",
-       "copyrightwarning": "<small>Timitztlātlauhtiah xiquitta mochi mopatlaliz cana {{SITENAME}} tlatzayāna īpan $2 (huēhca ōmpa xiquitta $1). Āqueh tlācah quipatlazqueh in motlahcuilōl auh tlatzayāna occeppa; intlā ahmō ticnequi, zātēpan ahmō titlahcuilōz nicān. Nō mitzihtoah in ōtitlahcuiloh ahmō quipiya in copyright nozo in yōllōxoxouhqui tlahcuilōlli. '''¡AHMŌ XITĒQUITILTIA AHYŌLLŌXOXOUHQUI TLAHCUILŌLLI!'''</small>",
+       "copyrightwarning": "<small>Timitztlatlauhtiah ximomati mochi ipatlaliz ihuicpa {{SITENAME}} tiquittah iuhqui tetlanextililiztli tlanipa $2 (xiquitta $1 itech oc tlahtolmelahualiztli). Intlacamo tiquelehuia occequintin tlacah quipatlazqueh motlahcuilol ihuan quipanitlazazqueh, macamo xitlahcuiloz nican. No titechcemihtoa in tlein otiquihcuiloh ahmo quipiya in copyright ihuan itech pohui in yolloxoxouhqui tlahcuilolli. '''¡AHMO XICTEQUITILTIA AHYOLLOXOXOUHQUI TLAHCUILOLLI!'''</small>",
        "copyrightwarning2": "<small>Āqueh tlācah quipatlazqueh in motlahcuilōl auh tlatzayāna occeppa; intlā ahmō ticnequi, zātēpan ahmō titlahcuilōz nicān {{SITENAME}}. Nō mitzihtoah in ōtitlahcuiloh ahmō quipiya in copyright nozo in yōllōxoxouhqui tlahcuilōlli (huēhca ōmpa xiquitta $1). '''¡AHMŌ TIQUINTEQUITILTIA AHYŌLLŌXOXOUHQUI TLAHCUILŌLLI!'''</small>",
        "longpageerror": "'''Aiuhcāyōtl: In tlahcuilōlli tlein ōtiquihuah tlatamachīhua {{PLURAL:$1|cē kilobyte|$1 kilobyte}}, tzonēhua {{PLURAL:$2|cē kilobyte|$2 kilobyte}}. Ahmo mopiyāz.'''",
-       "templatesused": "{{PLURAL:$1|Nemachiòtl tlèn motekìuhtia|Nemachiòmë tlèn mokìntekìuhtiä}} ìpan inìn tlaìxtlapalli:",
+       "templatesused": "{{PLURAL:$1|Nemachiotl tlen motequiuhtia|Nemachiomeh tlen moquintequiuhtiah}} ipan inin tlahcuilolamatl:",
        "templatesusedpreview": "{{PLURAL:$1|Nemachiòtl tlèn motekìuhtia|Nemachiòmë tlèn mokìntekìuhtiä}} ìpan inìn achtochìwalistli:",
        "templatesusedsection": "{{PLURAL:$1|Nemachiòtl tlèn motekìuhtia|Nemachiòmë tlèn mokìntekìuhtiä}} ìpan inìn tlaxélòlistli:",
        "template-protected": "(ōmoquīxti)",
-       "hiddencategories": "Inīn zāzanilli mopiya {{PLURAL:$1|1 neneuhcāyōc ōmotlāti|$1 neneuhcāyōc ōmotlāti}}:",
+       "hiddencategories": "Inin tlahcuilolli pohui {{PLURAL:$1|1 tlatlalilli neneuhcayotl|$1 tlatlaliltin neneuhcayomeh}}:",
        "nocreatetext": "Inīn huiqui ōquitzacuili tlahuelītiliztli ic tlachīhua yancuīc zāzaniltin. Tichuelīti ticcuepa auh ticpatla cē zāzanilli, [[Special:UserLogin|xicalaqui nozo xicchīhua cē cuentah]].",
        "nocreate-loggedin": "Ahmo tihuelīti tiquinchīhua yancuīc zāzaniltin.",
        "permissionserrors": "Tēmācāhualiztli aiuhcāyōtl",
        "permissionserrorstext": "Ahmo tihuelīti quichīhua inōn, inīn {{PLURAL:$1|īxtlamatilizpampa}}:",
        "permissionserrorstext-withaction": "Ahmo tiquihuelīti $2 inīn {{PLURAL:$1|īxtlamatilizpampa}}:",
-       "moveddeleted-notice": "Inīn zāzanilli ōmopolo.\nIn tlapololiztli īhuān in tlazacaliztli tlahcuilōlloh cah tlani.",
+       "moveddeleted-notice": "Inin tlahcuilolamatl omopoloh.\nIn tlapololiztli ihuan in tlazacaliztli tlahcuilolloh cah tlani.",
        "edit-gone-missing": "Ahmo huelīti yancuīya zāzanilli.\nHueliz ōmopolo.",
        "edit-conflict": "Tlapatlaliztli yāōyōtōn",
        "edit-already-exists": "Ahmo mohuelīti mochīhua yancuīc zāzanilli.\nYe ia.",
        "nohistory": "Nicān ahmō oncah tlaīxtlapatlaliztlahtōllōtl.",
        "currentrev": "Āxcān tlapatlaliztli",
        "currentrev-asof": "Āxcān tlachiyaliztli īpan $1",
-       "revisionasof": "Tlachiyaliztli īpan $1",
-       "revision-info": "Tlachiyaliztli īpan $1 īpal {{GENDER:$6|$2}}$7",
-       "previousrevision": "← Huēhueh tlapatlaliztli",
-       "nextrevision": "Yancuīc tlapatlaliztli →",
-       "currentrevisionlink": "Āxcān tlapatlaliztli",
-       "cur": "āxcān",
+       "revisionasof": "Tlachiyaliztli ipan $1",
+       "revision-info": "Tlachicahualiztli ixquichca $1 ihuicpa {{GENDER:$6|$2}}$7",
+       "previousrevision": "← Huehueh tlapatlaliztli",
+       "nextrevision": "Yancuic tlapatlaliztli →",
+       "currentrevisionlink": "Axcan tlapatlaliztli",
+       "cur": "axcan",
        "next": "niman",
-       "last": "xōcoyōc",
+       "last": "xocoyoc",
        "page_first": "achto",
        "page_last": "xōcoyōc",
        "history-fieldset-title": "Xitlatēmo īpan tlahtōllōtl",
        "mergehistory-reason": "Tleīpampa:",
        "revertmerge": "Tiquīxipehuaz",
        "history-title": "«$1» ītlaceppahuiliztlahtōllo",
-       "lineno": "Pāntli $1:",
+       "lineno": "Pantli $1:",
        "editundo": "Ticxitiniz",
        "searchresults": "motlatemoliz itlananquilizhuan",
        "searchresults-title": "«$1» tlatemoliztli imochihualiz",
        "prevn": "{{PLURAL:$1|$1}} achtopa",
        "nextn": "niman {{PLURAL:$1|$1}}",
-       "shown-title": "Quinēxiltīz $1 {{PLURAL:$1|mochīhualiztli}} cece āmac",
+       "shown-title": "Monextiz $1 {{PLURAL:$1|mochihualiztli}} cecen amatl",
        "viewprevnext": "Xiquintta ($1 {{int:pipe-separator}} $2) ($3).",
        "searchmenu-exists": "'''Ye ia zāzanilli ītōca \"[[$1]]\" inīn huiquipan'''",
        "searchmenu-new": "<strong>Ticchīhuāz in zāzanilli «[[:$1]]» inīn huiquipan.</strong> {{PLURAL:$2|0=|Nō xiquitta in tlanāmiquiliztli in mochīhualiztli.}}",
        "searchprofile-everything": "Mochi",
        "searchprofile-advanced": "Huehca ōmpa",
        "searchprofile-articles-tooltip": "Tictēmōz īpan $1",
-       "searchprofile-images-tooltip": "Tiquintēmōz tlahcuilōlli",
+       "searchprofile-images-tooltip": "motemoz tlapiyaliztecpaliztli",
        "searchprofile-everything-tooltip": "Tictēmōz mochi tlapiyalizpan (mopiyah tēixnāmiquiliztli zāzanilli)",
        "search-result-size": "$1 ({{PLURAL:$2|1 tlahtōl|$2 tlahtōltin}})",
        "search-redirect": "(ixquichca ompa mitzhuica $1)",
        "search-section": "(tlahtōltzintli $1)",
-       "search-category": "(tlaìxmatkàyòtlàlilòtl $1)",
+       "search-category": "(neneuhcayotl $1)",
        "search-suggest": "Ahnōceh tiquihtōznequiya: $1",
        "search-interwiki-caption": "Tlachīhualiztli īcnīhuān",
        "search-interwiki-more": "(huehca ōmpa)",
        "powersearch-togglenone": "Ahtlein",
        "search-external": "Tlatēmotiliztli calāmpa",
        "preferences": "Panitlatlālīlli",
-       "mypreferences": "Notlaēlēhuiliz",
+       "mypreferences": "Notlaelehuiliz",
        "prefs-edits": "Tlapatlaliztli tlapōhualli:",
        "prefs-skin": "Ēhuatl",
        "skin-preview": "Xiquitta quemeh yez",
        "prefs-rc": "Yancuic tlapatlaliztli",
        "prefs-watchlist": "Tlachiyaliztli",
        "prefs-watchlist-days": "Tōnaltin tiquinttāz tlachiyalizpan:",
-       "prefs-watchlist-edits": "Tlapatlaliztli tiquintta tlachiyalizpan:",
+       "prefs-watchlist-edits": "Oc cencah tlapohualli itech tlapatlaliztli tlen monextia ipan canahuac tlatecpanaliztli:",
        "prefs-misc": "Zāzo",
        "prefs-resetpass": "Ticpatlāz motlahtōlichtacāyo",
        "saveprefs": "Xicpiya",
        "prefs-editing": "Tlapatlaliztli",
        "rows": "Pāntli:",
-       "searchresultshead": "Tlatēmoliztli",
+       "searchresultshead": "Tlatemoliztli",
        "recentchangesdays": "Tōnaltin tiquinttāz yancuīc tlapatlalizpan:",
        "localtime": "Cāhuitl nicān:",
        "timezoneregion-africa": "Africa",
        "userrights-groupsmember": "Olōlco:",
        "userrights-reason": "Īxtlamatiliztli:",
        "userrights-no-interwiki": "Ahmo tihuelīti ticpatla tlatequitiltilīlli huelītiliztli occequīntīn huiquipan.",
-       "group": "Olōlli:",
+       "group": "Necentlaliliztli:",
        "group-user": "Tequihuihqueh",
        "group-bot": "Tepoztlācah",
        "group-sysop": "Tlahcuilōlpixqueh",
        "enhancedrc-history": "Tlahtollotl",
        "recentchanges": "Yancuic tlapatlaliztli",
        "recentchanges-legend": "Yancuīc tlapatlaliztechcopa tlanequiliztli",
-       "recentchanges-summary": "Xiquinttāz in achi yancuīc ahmo occequīntīn tlapatlaliztli huiquipan inīn zāzanilpan.",
+       "recentchanges-summary": "Tictoquiliz itlapatlaliz oc yancuic inahuac huiqui inin tlahcuilolpan.",
        "recentchanges-label-newpage": "Inīn tlapatlaliztli ōquiyōcox cē yancuīc āmatl",
-       "recentchanges-label-minor": "Ca tepitōn inīn tlapatlaliztli",
-       "rclistfrom": "Xiquinttāz yancuīc tlapatlaliztli īhuīcpa $3 $2",
+       "recentchanges-label-minor": " Inin tepiton tlapatlaliztli",
+       "recentchanges-label-bot": "Inin tlapaltlaliztli oquichiuh ce robot",
+       "rclistfrom": "Xiquittaz yancuic tlapatlaliztli ixquichca $3 ihuicpa $2",
        "rcshowhideminor": "$1 tlapatlalitzintli",
-       "rcshowhideminor-show": "Ticnēxtīz",
-       "rcshowhidebots": "$1 tepoztlācah",
-       "rcshowhidebots-show": "Xicnēxti",
+       "rcshowhideminor-show": "Xicnexti",
+       "rcshowhidebots": "$1 bots",
+       "rcshowhidebots-show": "Xicnexti",
        "rcshowhidebots-hide": "Tiquihyānaz",
        "rcshowhideliu": "$1 tēmachiyōmacalli tlatequitiltilīltin",
-       "rcshowhideanons": "$1 ahtōcā tlatequitiltilīlli",
-       "rcshowhideanons-show": "Xicnēxti",
+       "rcshowhideanons": "$1 ahtocatl tequitiuhqui",
+       "rcshowhideanons-show": "Xicnexti",
        "rcshowhidepatr": "$1 tlapatlaliztli mochiyahua",
-       "rcshowhidemine": "$1 notlahcuilōl",
-       "rcshowhidemine-show": "Xicnēxti",
-       "rclinks": "Xiquintta xōcoyōc $1 tlapatlaliztli xōcoyōc $2 tōnalpan.<br />$3",
+       "rcshowhidemine": "$1 notlahcuilol",
+       "rcshowhidemine-show": "Xicnexti",
+       "rclinks": "Xiquitta yancuic $1 tlapatlaliztli yancuic $2 tonalpan.<br />$3",
        "diff": "ahneneuhqui",
        "hist": "tlahtollotl",
        "hide": "Tiquintlātīz",
        "recentchangeslinked": "Tlapatlaliztli tzonhuilizpan",
        "recentchangeslinked-feed": "Tlapatlaliztli tzonhuilizpan",
        "recentchangeslinked-toolbox": "Itloc itlapatlalizhuan",
-       "recentchangeslinked-title": "Tlapatlaliztli \"$1\" ītechcopa",
-       "recentchangeslinked-page": "Tlaīxtli ītōcā:",
+       "recentchangeslinked-title": "Tlapatlaliztli \"$1\" itechcopa",
+       "recentchangeslinked-page": "Tlahcuilolamatl itoca:",
        "upload": "Tlahcuilolquetzaliztli",
        "uploadbtn": "Tlahcuilōlquetza",
        "uploadnologin": "Ahmo ōtimocalac",
        "watchthisupload": "Tictlachiyāz inīn zāzanilli",
        "upload-form-label-infoform-name": "Tōcāitl",
        "upload-form-label-usage-filename": "Ihcuilōlli ītōcā",
-       "upload_source_file": " (cē tlahcuilōlli mochīuhpōhualhuazco)",
+       "upload_source_file": "(ticpepenaz ce tlahcuilolli mochiuhpohualhuazco)",
        "listfiles_search_for": "Tlatēmōz mēdiatl tōcācopa:",
        "imgfile": "ihcuilōlli",
        "listfiles": "Mochīntīn īxiptli",
        "listfiles_count": "Cuepaliztli",
        "listfiles-latestversion-yes": "Quēmah",
        "listfiles-latestversion-no": "Ahmō",
-       "file-anchor-link": "Ihcuilōlli",
+       "file-anchor-link": "Tlapiyaliztecpanaliztli",
        "filehist": "Ihcuilōlli ītlahtōllo",
        "filehist-deleteall": "tiquimpolōz mochīntīn",
        "filehist-deleteone": "xicpolo",
        "filehist-current": "āxcān",
        "filehist-datetime": "Tlapōhualpan/Cāhuitl",
        "filehist-thumb": "Īxiptlahtōn",
-       "filehist-user": "Tequihuihqui",
-       "filehist-dimensions": "Octacayōtl",
+       "filehist-user": "Tequitiuhqui",
+       "filehist-dimensions": "Octacayotl",
        "filehist-comment": "TlahtoIcaquiliztiloni",
        "imagelinks": "In canin oquitlalihqueh",
        "linkstoimage": "Inīn {{PLURAL:$1|zāzanilli motzonhuilia|$1 zāzanilli motzonhuiliah}} inīn tlahcuilōlhuīc:",
        "listredirects": "Tlacuepaliztli",
        "unusedtemplates": "Nemachiyōtīlli ahmotequitiltiah",
        "unusedtemplateswlh": "occequīntīn tzonhuiliztli",
-       "randompage": "Centlaīxtli",
+       "randompage": "Cecen tlahcuilolli",
        "randompage-nopages": "Ahmo oncah zāzanilli īpan inīn {{PLURAL:$2|tōcāitl}}: $1.",
        "randomincategory-submit": "Yāuh",
        "randomredirect": "Zāzotlacuepaliztli",
        "nbytes": "$1 {{PLURAL:$1|byte}}",
        "ncategories": "$1 {{PLURAL:$1|tlaìxmatkàyòtlàlilòtl|tlaìxmatkàyòtlàlilòme}}",
        "nlinks": "$1 {{PLURAL:$1|tzòwilistli|tzòwilistìn}}",
-       "nmembers": "$1 {{PLURAL:$1|tlâkuilòpilli|tlâkuilòpiltìn}}",
+       "nmembers": "$1 {{PLURAL:$1|tlahcuilolamatl|tlahcuilolamameh}}",
        "nrevisions": "$1 {{PLURAL:$1|tlapiyaliztli}}",
        "nimagelinks": "Motekìuhtia ìpan $1 {{PLURAL:$1|tlaìxtlapalli|tlaìxtlapaltìn}}",
        "ntransclusions": "motekìuhtia ìpan $1 {{PLURAL:$1|tlaìxtlapalli|tlaìxtlapaltìn}}",
        "protectedpages-reason": "Tleīpampa",
        "protectedtitles": "Tōcāitl ōmoquīxtih",
        "listusers": "Tlatequitiltilīlli",
-       "newpages": "Yancuīc zāzaniltin",
+       "newpages": "Yancuic tlahcuiloltin",
        "newpages-username": "Tlatequitiltilīltōcāitl:",
-       "ancientpages": "Huēhuehzāzanilli",
+       "ancientpages": "Huehcauh tlahcuilolamatl",
        "move": "Ticzacāz",
        "movethispage": "Ticzacāz inīn zāzanilli",
-       "pager-newer-n": "{{PLURAL:$1|1 yancuīc|$1 yancuīc}}",
-       "pager-older-n": "{{PLURAL:$1|1 huēhuetl|$1 huēhueh}}",
+       "pager-newer-n": "{{PLURAL:$1|1 yancuic|$1 yancuicqueh}}",
+       "pager-older-n": "{{PLURAL:$1|1 huehcauh|$1 huehcauhqueh}}",
        "booksources": "Āmoxmēyalli",
-       "booksources-search-legend": "Tiquīxtēmōz āmoxmēyalli",
-       "booksources-search": "Tiquīxtēmōz",
+       "booksources-search-legend": "Tiquixtemoz amoxtli itzintiliz",
+       "booksources-search": "Tlatemoliztli",
        "specialloguserlabel": "Tlatequitiltilīlli:",
        "speciallogtitlelabel": "Tōcāitl:",
        "log": "Tlahcuilōlloh",
        "all-logs-page": "Mochīntīn tlācah īntlahcuilōlloh",
-       "allpages": "Mochīntīn zāzanilli",
+       "allpages": "Mochintin tlahcuilolamatl",
        "nextpage": "Niman zāzanilli ($1)",
        "prevpage": "Achto zāzanilli ($1)",
-       "allarticles": "Mochīntīn tlahcuilōlli",
-       "allinnamespace": "Mochīntīn zāzanilli (īpan $1)",
-       "allpagessubmit": "Tiyāz",
-       "categories": "Tlaìxmatkàyòtlàlilòme",
+       "allarticles": "Mochintin tlahcuilolamameh",
+       "allinnamespace": "Mochintin tlahcuilolamameh (tocatlacauhtli $1)",
+       "allpagessubmit": "Tiyaz",
+       "categories": "Neneuhcayotl",
        "categoriespagetext": "{{PLURAL:$1|Inìn tlaìxmatkàyòtlàlilòtl kimpia|Inîke tlaìxmatkàyòtlàlilòme kimpiâke}} tlaìxtlapaltìn noso medios.\nÂmò monèxtiâke nikàn in [[Special:UnusedCategories|tlaìxmatkàyòtlàlilòme tlèn âmò mokìntekitìltia]].\nNò mà mỏta in tlèn [[Special:WantedCategories|ìpan kineki tlaìxmatkàyòtlàlilòtl]].",
        "categoriesfrom": "Mà monèxtìkàn tlaìxmatkàtlàlilòmë tlèn pèwâkë ìka:",
        "linksearch": "Calān tzonhuiliztli tlatemoliztli",
        "watching": "Tlachiyacah...",
        "unwatching": "Ahtlachiyacah...",
        "enotif_impersonal_salutation": "tlatequitiltilīlli īpan {{SITENAME}}",
-       "enotif_anon_editor": "ahtōcātlatequitiltilīlli $1",
+       "enotif_anon_editor": "ahtocatl tequitiuhqui $1",
        "enotif_body": "Māhuiztic $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nTlapatlani ītlahtōlpehuallo:  $PAGESUMMARY $PAGEMINOREDIT\n\nXicnotzāz in tlapatlani:\nīnetitlanizyeyān:$PAGEEDITOR_EMAIL\nīhuiqui:$PAGEEDITOR_WIKI\n\nAhmo occēppa mitztlamachiztīz intlā yancuīc tlapatlaliztli, zā mā tiquittaz inīn āmatl. Tihueliti ticcencahulīz in tēmachiztīlizpāmitl in mochintin motlachixāmatl in motlachiyaliz.\n\nIn {{SITENAME}} icnīuhtīliztica motēmachiztīliztlacentetilīz.\n\nIntlā ticnequi ticpatlaz in maltzinteyōtl monetitlanizyeyān, xiquihitta:\n{{canonicalurl:{{#special:Preferences}}}}\n\n\nIntlā ticnequi ticpatlaz in motlachiyaliz tlaēlēhuiliztli, xiquihitta:\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nIntlā ticnequi ticpolōz in āmatl ītech motlachiyaliz, xiquihitta:\n$UNWATCHURL\n\nMotlahtōlcaquiliztīlōni īhuān ocachi tēpalēhuiliztli, xiquihitta:\n$HELPPAGE",
        "created": "ōmochīuh",
        "changed": "ōmotlacuep",
        "rollback-success": "Ōmotlacuep $1 ītlahcuilōl; āxcān achto $2 ītlahcuilōl.",
        "changecontentmodel-title-label": "Tlaīxtōcāitl",
        "changecontentmodel-reason-label": "Tleīpampa:",
-       "protectlogpage": "Tlapiyaliztlīlmachiyōtīlli",
+       "protectlogpage": "Tlapiyaliztlilmachiyotilli",
        "protectedarticle": "ōmoquīxti \"[[$1]]\"",
        "unprotectedarticle": "ōahmoquīxtih «[[$1]]»",
        "prot_1movedto2": "[[$1]] ōmozacac īhuīc [[$2]]",
        "undelete-search-submit": "Tlatēmōz",
        "undelete-error-short": "Ahcuallōtl ihcuāc momāquīxtiya: $1",
        "undelete-show-file-submit": "Quemah",
-       "namespace": "Tōcātlacāuhtli:",
-       "invert": "Tlacuepāz motlahtōl",
-       "blanknamespace": "(Huēyi)",
+       "namespace": "Tocatlacauhtli:",
+       "invert": "Tlacuepaz motlahtol",
+       "blanknamespace": "(Tlayacatic)",
        "contributions": "In {{GENDER:$1|tlatequitiltilīlli}} ītlahcuilōl",
        "contributions-title": "Tlatequitiltilīlli $1 ītlahcuilōl",
        "mycontris": "Notlahcuilol",
        "sp-contributions-talk": "zānīlli",
        "sp-contributions-search": "Tiquintlatēmōz tlapatlaliztli",
        "sp-contributions-username": "IP nozo tlatequitiltilīlli ītōcā:",
-       "sp-contributions-submit": "Tlatēmōz",
+       "sp-contributions-submit": "Tlatemoliztli",
        "whatlinkshere": "In tlein quitzonhuilia nican",
        "whatlinkshere-title": "Zāzaniltin quitzonhuiliah $1",
-       "whatlinkshere-page": "Zāzanilli:",
+       "whatlinkshere-page": "Tlahcuilolamatl:",
        "linkshere": "Inīn zāzaniltin quitzonhuiliah '''[[:$1]]''' īhuīc:",
        "nolinkshere": "Ahtle quitzonhuilia '''[[:$1]]''' īhuīc.",
        "isredirect": "ōmotlacuep zāzanilli",
        "isimage": "īxiptlahtli tzonhuiliztli",
        "whatlinkshere-prev": "{{PLURAL:$1|achtopa|$1 achtopa}}",
        "whatlinkshere-next": "{{PLURAL:$1|niman|$1 niman}}",
-       "whatlinkshere-links": "← tzòwilistìn",
+       "whatlinkshere-links": "← tzohuiliztin",
        "whatlinkshere-hideredirs": "$1 tlacuepaliztli",
        "whatlinkshere-hidelinks": "$1 tzonhuiliztli",
        "whatlinkshere-hideimages": "$1 tlahcuilōltzonhuīliztli",
        "contribslink": "tlapatlaliztli",
        "blocklogpage": "Tlatequitiltilīlli ōmotzacuili",
        "move-page": "Ticzacāz $1",
-       "move-page-legend": "Ticzacāz zāzanilli",
+       "move-page-legend": "Tictocapatlaliz inin tlahcuilolamatl",
        "movepagetext": "Nicān mohcuiloa quemeh ticzacāz cē zāzanilli auh mochi in ītlahcuillōloh īhuīc occē yancuīc ītōca.\nHuēhuehtōcāitl yez tlacuepaliztli yancuīc tōcāhuīc.\nTzonhuiliztli huēhuehzāzanilhuīc ahmo mopatlāz.\nXiquitta ic māca xicchīhua [[Special:DoubleRedirects|ōntlacuepaliztli]] ahnozo [[Special:BrokenRedirects|tzomoc]].\nTitzonhuilizpiyāz.\n\nXicmati in zāzanilli ahmo mozacāz intlā ye ia cē zāzanilli tōcātica, zan cah iztāc zāzanilli ahnozo tlacuepaliztli īca ahmo tlahcuilōlloh.\nQuihtōznequi tihuelītīz ticuepāz cē zāzanilli īhuīc ītlācatōca intlā ahcuallōtl ticchīhuāz, tēl ahmo tihuelītīz occeppa tihcuilōz īpan zāzanilli tlein ia.\n\n'''¡XICPŌHUA!'''\nHueliz cah inīn huēyi tlapatlaliztli. Timitztlātlauhtia ticmatīz cuallōtl auh ahcuallōtl achtopa ticzacāz.",
        "movenotallowed": "Ahmo tihuelīti tiquinzaca zāzaniltin.",
-       "newtitle": "Yancuīc tōcāhuīc",
-       "move-watch": "Tictlachiyāz inīn zāzanilli",
+       "newtitle": "Yancuic tocaitl",
+       "move-watch": "Tictlachiyaz tlahcuilolamatl itzintiliz ihuan itlatzaccan",
        "movepagebtn": "Ticzacāz zāzanilli",
        "pagemovedsub": "Cualli ōmozacac",
        "movepage-moved": "'''\"$1\" ōmotlacuep īhuīc \"$2\".'''",
-       "movetalk": "Xiczaca yehhuātl īzānīllaīx",
+       "movetalk": "tictocapatlaliz in tlahcuilolamatl iixiptla",
        "movepage-page-moved": "Zāzanilli $1 ōmozacac īhuīc $2.",
        "movepage-page-unmoved": "Ahmo huelīti $1 mozaca īhuīc $2.",
        "movelogpage": "Tlazacaliztli tlahcuilōlloh",
        "immobile-source-namespace": "Ahmo huelīti mozaca zāzanilli tōcātzimpan \"$1\"",
        "immobile-target-namespace": "Ahmo huelīti mozaca zāzanilli tōcātzinhuīc \"$1\"",
        "immobile-source-page": "Ahmo huelīti mozacāz zāzanilli.",
-       "move-leave-redirect": "Ticcāhuāz cē tlacuepaliztli",
+       "move-leave-redirect": "Ma ticcahua ce tlatzonhuiliztli",
        "export": "Tiquinnamacāz zāzaniltin",
        "export-submit": "Ticnamacāz",
        "export-addcattext": "Mà tlatlaìxtlapalwilo ìwikpa tlatlaìxmatkàyòtlàlilòpa:",
        "export-download": "Ticpiyāz quemeh tlahcuilōlli",
        "export-templates": "Tiquimpiyāz nemachiyōtīlli",
        "allmessages": "Mochīntīn Huiquimedia tlahcuilōltzintli",
-       "allmessagesname": "Tōcāitl",
-       "allmessagescurrent": "Āxcān tlahcuilōlli",
+       "allmessagesname": "Tocaitl",
+       "allmessagescurrent": "Tlahcuilolpiyaliztli itech axcan",
        "allmessages-filter-all": "Mochi",
        "allmessages-language": "Tlâtòlli:",
        "allmessages-filter-submit": "Yāuh",
        "tooltip-pt-preferences": "{{GENDER:|Motlaēlēhuiliz}}",
        "tooltip-pt-watchlist": "Zāzaniltin tiquintlachiya ic tlapatlaliztli",
        "tooltip-pt-mycontris": "{{GENDER:|Motlahcuilōl}}",
-       "tooltip-pt-login": "Tihuelīti timocalaqui, tēl ahmo tihuīquilia.",
-       "tooltip-pt-logout": "Tiquīzāz",
+       "tooltip-pt-login": "Tihueliti timocalaqui, tel ahmo tihuiquilia.",
+       "tooltip-pt-logout": "Tiquizaz",
        "tooltip-ca-talk": "Iteixnamiquiliz itechpa inin tlahcuilolli",
        "tooltip-ca-edit": "Ticpatlaz inin tlahcuilolli",
        "tooltip-ca-addsection": "Tictzintīz yancuic xeliuhcāyōtl.",
        "tooltip-ca-protect": "Ticquīxtiāz inīn zāzanilli",
        "tooltip-ca-delete": "Ticpolōz inīn zāzanilli",
        "tooltip-ca-undelete": "Ahticpolōz inīn zāzanilli",
-       "tooltip-ca-move": "Ticzacāz inīn zāzanilli",
+       "tooltip-ca-move": "Ticzacaz inin tlahcuilolamatl",
        "tooltip-ca-watch": "Ticcentiliz inin tlahtolli motecpanaliz",
        "tooltip-ca-unwatch": "Ahtictlachiyāz inīn zāzanilli",
        "tooltip-search": "Tlatemoliztli ipan {{SITENAME}}",
        "tooltip-n-mainpage-description": "Tiquittaz in yacatlahcuilolli",
        "tooltip-n-portal": "Tlachīhualiztechcopa, inōn tihuelīti titlachīhua, tlatēmoyān",
        "tooltip-n-recentchanges": "Yancuic īpan tlapatlaliztli in huiqui",
-       "tooltip-n-randompage": "Tiquittaz centlaīxtli",
+       "tooltip-n-randompage": "Tiquittaz cecen tlahcuilolli",
        "tooltip-n-help": "In tēmachtīlōyān",
-       "tooltip-t-whatlinkshere": "Mochīntīn zāzaniltin huiquipan quitzonhuiliah nicān",
+       "tooltip-t-whatlinkshere": "Mochintin tlahcuiloltin huiquipan quitzonhuiliah nican",
        "tooltip-t-recentchangeslinked": "Yancuic tlapatlaliztli ipan tlahcuiloltin tlein quitzonhuilia nican",
        "tooltip-feed-rss": "RSS tlachicāhualiztli inīn zāzaniltechcopa",
        "tooltip-feed-atom": "Atom tlachicāhualiztli inīn zāzaniltechcopa",
        "tooltip-t-specialpages": "Intlahtoltecpanaliz mochtin in noncuahquizquitlahcuiloltin",
        "tooltip-t-print": "Tepoztlahcuilolli",
        "tooltip-ca-nstab-main": "Tiquittaz tlein quipiya in tlahcuilolli",
-       "tooltip-ca-nstab-user": "Xiquitta tlatequitiltilīlli īzāzanil",
+       "tooltip-ca-nstab-user": "Xiquitta tequitiuhqui itlahcuilolamauh",
        "tooltip-ca-nstab-special": "Inīn nōncuahquīzqui āmatl, auh ahmohuelitizpatla",
        "tooltip-ca-nstab-project": "Xiquitta in tlatequipanōllaīxtli",
        "tooltip-ca-nstab-image": "Xiquittāz īxipzāzanilli",
        "tooltip-compareselectedversions": "Tiquinttāz ahneneuhquiliztli ōme zāzanilli tlapatlaliznepantlah.",
        "tooltip-watch": "Ticcēntilīz inīn zāzanilli motlachiyalizhuīc",
        "tooltip-upload": "Ticpēhua quetzaliztli",
-       "tooltip-summary": "Xicaquilia tepitōn tlahcuilōltōntli",
+       "tooltip-summary": "Xiquihcuilo ce tepiton tlahcuiloltontli",
        "anonymous": "Ahtōcāitl {{PLURAL:$1|tlatequitiltilīlli}} īpan {{SITENAME}}",
        "siteuser": "$1 tlatequitiltilīlli īpan {{SITENAME}}",
        "lastmodifiedatby": "Inīn zāzanilli ōtlapatlac catca īpan $2, $1 īpal $3.",
        "spam_reverting": "Mocuepacah īhuīc xōcoyōc tlapatlaliztli ahmo tzonhuilizca īhuīc $1",
        "spam_blanking": "Mochi tlapatlaliztli quimpiyah tzonhuiliztli īhuīc $1, iztāctiliacah",
        "pageinfo-firstuser": "Tlaīxchīuhqui",
-       "pageinfo-toolboxlink": "Tlaīxtlahtōlmelāhualiztli",
+       "pageinfo-toolboxlink": "Tlahtolamatl itlahtolmelahualiz",
        "pageinfo-contentpage-yes": "Quēmah",
        "pageinfo-protect-cascading-yes": "Quēmah",
        "previousdiff": "← Achtopa",
        "file-info-size": "$1 × $2 pixel; zāzanilli octacayōtl: $3; machiyōtl MIME: $4",
        "file-nohires": "Ahmo ia achi cualli ahmo occē īxiptli.",
        "show-big-image": "Tzintiliztlahcuilolli",
+       "show-big-image-size": "$1 × $2 pixels",
        "newimages": "Yancuīc īxipcān",
        "imagelisttext": "Nicān {{PLURAL:$1|mopiya|mopiyah}} '''$1''' īxiptli $2 iuhcopa.",
        "noimages": "Ahtlein ic tlatta.",
        "exif-gpslatitude-s": "Huiztlān",
        "exif-gpslongitude-e": "Tlāpcopa huehtlatzīncāyōtl",
        "exif-gpslongitude-w": "Cihuātlāmpa huehtlatzīncāyōtl",
-       "namespacesall": "mochīntīn",
+       "namespacesall": "mochintin",
        "monthsall": "(mochīntīn)",
        "confirmemail": "Ticchicāhuāz e-mail",
        "confirmemail_needlogin": "Tihuīquilia $1 ic ticchicāhua mo e-mail.",
        "table_pager_empty": "Ahtlein",
        "autosumm-blank": "Tlaiztāctilīlli zāzanilli",
        "autoredircomment": "Mocuepahua īhuīc [[$1]]",
-       "autosumm-new": "Tlachīhualli zāzanilli īca: \"$1\"",
+       "autosumm-new": "Tlachihuhtli tlahcuilolamatl ica: \"$1\"",
        "size-bytes": "$1 B",
        "size-kilobytes": "$1 KB",
        "size-megabytes": "$1 MB",
index 2b1bc3e..01b9711 100644 (file)
@@ -7,7 +7,8 @@
                        "아라",
                        "唐吉訶德的侍從",
                        "Luuva",
-                       "Macofe"
+                       "Macofe",
+                       "進也"
                ]
        },
        "tog-underline": "Liân-kiat oē té-sûn:",
        "expandtemplates": "Khok-chhiong pang-bô͘",
        "expand_templates_input": "Su-ji̍p bûn-jī:",
        "expand_templates_output": "Kiat-kó:",
-       "expand_templates_remove_comments": "Comments the̍h tiāu"
+       "expand_templates_remove_comments": "Comments the̍h tiāu",
+       "mw-widgets-mediasearch-input-placeholder": "搜揣媒體"
 }
index 6d21b41..5cb16cb 100644 (file)
        "botpasswords-label-resetpassword": "Riabbìa 'a password",
        "botpasswords-label-grants": "Assegnaziune apprecabbele:",
        "botpasswords-help-grants": "Ogne assegnazione dà acciesso a 'e deritte utente elencate ca n'utenza avesse già. Vedite 'a [[Special:ListGrants|tabbella 'e ll'assegnaziune]] pe' ne mòvere cchiù nfurmaziune.",
-       "botpasswords-label-restrictions": "Restriziune d'uso:",
        "botpasswords-label-grants-column": "Assegnaziune date",
        "botpasswords-bad-appid": "'O nomme bot \"$1\" nun è bbuono.",
        "botpasswords-insert-failed": "Nun se pò azzeccà 'o nomme bot \"$1\". Fosse stato già azzeccato?",
        "passwordreset-nocaller": "Nu chiammate s'avess'a dà",
        "passwordreset-nosuchcaller": "'O chiammante nun esiste: $1",
        "passwordreset-ignored": "'A reimpustazione d' 'a password nun s'è gistita. Fosse ca nisciunu fornitore è stato mpustato?",
-       "passwordreset-invalideamil": "Indirizzo 'e posta email nun valido",
+       "passwordreset-invalidemail": "Indirizzo 'e posta email nun valido",
        "passwordreset-nodata": "Nun è stato fornito né nomme utente né indirizzo 'e posta email",
        "changeemail": "Cagna o lèva l'indirizzo e-mail",
        "changeemail-header": "Ghienchete stu modulo pe' puté cagnà 'o indirizzo e-mail d' 'o vuosto. Si vuje vulite luvà e 'o scucchià l'associazione 'e cocche cunto mail d' 'o cunto vuosto, lassate 'o cunto e-mail nuovo abbacante quanno mannarrate stu modulo.",
        "activeusers-intro": "Chest'è n'elenco d'utente c'hanno fatto cierti tipe d'attività nfin'a $1 {{PLURAL:$1|juorno|ghiuorne}} fa.",
        "activeusers-count": "$1 {{PLURAL:$1|cagnamiento|cagnamiente}} int'a l'urdeme {{PLURAL:$3|ghiuorne}}",
        "activeusers-from": "Fà vedè l'utente partenno 'a:",
-       "activeusers-hidebots": "Annascunne 'e bot",
-       "activeusers-hidesysops": "Annascunne l'ammenistrature",
        "activeusers-noresult": "Nisciun'utente truvato.",
        "activeusers-submit": "Mmusta cunte attive",
        "listgrouprights": "Deritte d' 'e gruppe utente",
        "feedback-external-bug-report-button": "Archivia na fatica tecnica",
        "feedback-dialog-title": "Manna 'o feedback",
        "feedback-dialog-intro": "Putite ausà sempricemente 'o modulo ccà abbascio pe' putè mannà 'o feedback vuosto. 'O cummento sarrà azzeccato â paggena \"$1\", nziem' 'o nomme vuosto.",
-       "feedback-error-title": "Errore",
        "feedback-error1": "Errore: Risultato nun aspettato 'a ll'API",
        "feedback-error2": "Errore: Cagnamiento scassato",
        "feedback-error3": "Errore: Ll'API nun risponne",
index 6b2192d..1f70032 100644 (file)
        "views": "Visninger",
        "toolbox": "Verktøy",
        "tool-link-userrights": "Endre {{GENDER:$1|brukergrupper}}",
+       "tool-link-userrights-readonly": "Vis {{GENDER:$1|brukergrupper}}",
        "tool-link-emailuser": "Send {{GENDER:$1|brukeren}} en e-post",
        "userpage": "Vis brukerside",
        "projectpage": "Vis prosjektside",
        "passwordreset-emaildisabled": "E-posttjenester er slått av på denne wikien.",
        "passwordreset-username": "Brukernavn:",
        "passwordreset-domain": "Domene:",
-       "passwordreset-capture": "Vise resulterende e-post?",
-       "passwordreset-capture-help": "Hvis du krysser av her, vil du se e-posten (med foreløpig passord) i tillegg til at den blir sendt til brukeren.",
        "passwordreset-email": "E-postadresse:",
        "passwordreset-emailtitle": "Kontodetaljer på {{SITENAME}}",
        "passwordreset-emailtext-ip": "Noen (sannsynligvis deg fra IP-adressen $1) ba om en tilbakestilling av ditt passord for {{SITENAME}} ($4). {{PLURAL:$3|Den følgende brukerkontoen|De følgende brukerkontoene}} er\ntilknyttet denne e-postadressen:\n\n$2\n\n{{PLURAL:$3|Dette midlertidige passordet|Disse midlertidige passordene}} utløper om {{PLURAL:$5|én dag|$5 dager}}.\nDu bør logge på og velge et nytt passord nå. Dersom noen andre kom med denne\nforespørselen, eller du har kommet på ditt opprinnelige passord, og ikke lenger\nønsker å endre det, kan du ignorere denne meldingen og fortsette å bruke ditt gamle\npassord.",
        "passwordreset-emailelement": "Brukernavn: \n$1\n\nMidlertidig passord: \n$2",
        "passwordreset-emailsentemail": "Hvis denne epostadressen er koblet til din konto, så vil det bli sendt en epost om tilbakestilling av passord.",
        "passwordreset-emailsentusername": "Hvis det finnes en epostadresse knyttet til dette brukernavnet, vil en epost med informasjon om tilbakestilling av passord bli sendt.",
-       "passwordreset-emailsent-capture2": "{{PLURALS:$1|E-posten|E-postene}} om passordtilbakestilling har blitt sendt. {{PLURAL:$1|Brukernavnet og passordet|Listen over brukernavn og passord}} vises under.",
-       "passwordreset-emailerror-capture2": "Kunne ikke sende e-post til {{GENDER:$2|brukeren}}: $1 {{PLURAL:$3|Brukernavnet og passordet|Listen over brukernavn og passord}} vises her.",
        "passwordreset-nocaller": "En bruker må angis",
        "passwordreset-nosuchcaller": "Brukeren finnes ikke: $1",
        "passwordreset-ignored": "Passordtilbakestillingen ble ikke håndtert. Har ingen leverandør blitt konfigurert?",
-       "passwordreset-invalideamil": "Ugyldig e-postadresse",
+       "passwordreset-invalidemail": "Ugyldig e-postadresse",
        "passwordreset-nodata": "Verken et brukernavn eller en e-postadresse ble oppgitt",
        "changeemail": "Endre eller fjerne epostadresse",
        "changeemail-header": "Fyll ut dette skjemaet for å bytte din epost-adresse. Hvis du vil fjerne epostadressen fra din konto, kan du la ny epostadresse-feltet være tomt når.",
        "search-external": "Eksternt søk",
        "searchdisabled": "Søkefunksjonen er slått av. Du kan søke via Google i mellomtiden. Merk at Googles indeksering av {{SITENAME}} muligens er utdatert.",
        "search-error": "En feil oppsto under søk: $1",
+       "search-warning": "En advarsel oppsto under søk: $1",
        "preferences": "Innstillinger",
        "mypreferences": "Innstillinger",
        "prefs-edits": "Antall redigeringer:",
        "prefs-help-recentchangescount": "Dette inkluderer nylige endringer, sidehistorikk og logger.",
        "prefs-help-watchlist-token2": "Dette er den hemmelige nøkkelen til webmatingen for din overvåkningsliste.\nEnhver som kjenner nøkkelen vil kunne lese din overvåkningsliste, så ikke vis den til andre.\n[[Special:ResetTokens|Klikk her om du trenger å nullstille nøkkelen]].",
        "savedprefs": "Innstillingene ble lagret.",
-       "savedrights": "Brukerrettighetene til {{GENDER:$1|$1}} har blitt lagret.",
+       "savedrights": "Brukergruppene til {{GENDER:$1|$1}} har blitt lagret.",
        "timezonelegend": "Tidssone:",
        "localtime": "Lokaltid:",
        "timezoneuseserverdefault": "Bruk wikistandard ($1)",
        "prefswarning-warning": "Du har gjort endringer i dine innstillinger som ikke er lagret ennå.\nDersom du forlater denne siden utenk å klikke på \"$1\" blir ikke innstillingene dine oppdatert.",
        "prefs-tabs-navigation-hint": "Tips: Du kan bruke venstre- og høyrepiltastene for å navigere mellom fanene i fanelisten",
        "userrights": "Bruker&shy;rettighets&shy;kontroll",
-       "userrights-lookup-user": "Ordne brukergrupper",
+       "userrights-lookup-user": "Velg en bruker",
        "userrights-user-editname": "Fyll inn et brukernavn:",
-       "editusergroup": "Endre {{GENDER:$1|brukergrupper}}",
+       "editusergroup": "Last brukergrupper",
        "editinguser": "Endrer brukerrettighetene for {{GENDER:$1|bruker}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Rediger brukergrupper",
        "saveusergroups": "Lagre {{GENDER:$1|brukergrupper}}",
        "userrights-reason": "Årsak:",
        "userrights-no-interwiki": "Du har ikke tillatelse til å endre brukerrettigheter på andre wikier.",
        "userrights-nodatabase": "Databasen $1 finnes ikke, eller er ikke lokal.",
-       "userrights-nologin": "Du må [[Special:UserLogin|logge inn]] med en administratorkonto for å endre brukerrettigheter.",
-       "userrights-notallowed": "Du har ikke tillatelse til å gi eller fjerne brukerrettigheter.",
        "userrights-changeable-col": "Grupper du kan endre",
        "userrights-unchangeable-col": "Grupper du ikke kan endre",
        "userrights-irreversible-marker": "$1 *",
        "userrights-conflict": "En konflikt med endringen av brukerrettigheter! Vær vennlig å sjekke og på nytt bekrefte endringene dine.",
-       "userrights-removed-self": "Du har fjernet dine egne rettigheter. Du har derfor ikke lengre adgang til denne siden.",
        "group": "Gruppe:",
        "group-user": "Brukere",
        "group-autoconfirmed": "Autobekreftede brukere",
        "right-siteadmin": "Låse og låse opp databasen",
        "right-override-export-depth": "Eksporter sider inkludert lenkede sider til en dypde på 5",
        "right-sendemail": "Send e-post til andre brukere",
-       "right-passwordreset": "Vis e-poster over tilbakestilte passord",
        "right-managechangetags": "Opprette og (de)aktivere [[Special:Tags|tagger]]",
        "right-applychangetags": "Legg til [[Special:Tags|merker]] sammen med ens endringer",
        "right-changetags": "Legg til og fjern vilkårlige [[Special:Tags|merker]] på individuelle revisjoner og loggposter",
        "action-upload_by_url": "laste opp denne filen fra en URL",
        "action-writeapi": "bruke skrive-API-en",
        "action-delete": "slette denne siden",
-       "action-deleterevision": "slette denne revisjonen",
+       "action-deleterevision": "slett revisjoner",
        "action-deletedhistory": "se denne sidens slettede historikk",
        "action-browsearchive": "søke i slettede sider",
        "action-undelete": "gjenopprette denne siden",
        "apisandbox-continue": "Fortsett",
        "apisandbox-continue-clear": "Tøm",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} vil [https://www.mediawiki.org/wiki/API:Query#Continuing_queries fortsette] forrige forespørsel; {{int:apisandbox-continue-clear}} vil tømme fortsettelsesrelaterte parametre.",
+       "apisandbox-param-limit": "Skriv <kbd>max</kbd> for å bruke maksgrensa.",
+       "apisandbox-multivalue-all-namespaces": "$1 (alle navnerom)",
+       "apisandbox-multivalue-all-values": "$1 (alle verdier)",
        "booksources": "Bokkilder",
        "booksources-search-legend": "Søk etter bokkilder",
        "booksources-search": "Søk",
        "activeusers-count": "$1 {{PLURAL:$1|endring|endringer}} {{PLURAL:$3|det siste døgnet|de siste $3 dagene}}",
        "activeusers-from": "Vis brukere fra og med:",
        "activeusers-groups": "Vis brukere som tilhører gruppene:",
+       "activeusers-excludegroups": "Ekskluder brukere som hører til gruppene:",
        "activeusers-noresult": "Ingen brukere funnet.",
        "activeusers-submit": "Vis",
        "listgrouprights": "Rettigheter for brukergrupper",
        "emailccsubject": "Kopi av din beskjed til $1: $2",
        "emailsent": "E-post sendt",
        "emailsenttext": "E-postbeskjeden er sendt",
-       "emailuserfooter": "Denne e-posten ble {{GENDER:$1|sendt}} av $1 til {{GENDER:$2|$2}}  via funksjonen «{{int:emailuser}}» på {{SITENAME}}.",
+       "emailuserfooter": "Denne e-posten ble {{GENDER:$1|sendt}} av $1 til {{GENDER:$2|$2}}  via funksjonen «{{int:emailuser}}» på {{SITENAME}}. {{GENDER:$2|Din}} epost vil bli sendt direkte til {{GENDER:$1|opprinnelig avsender}} og avsløre {{GENDER:$2|din}} epost-addresse til {{GENDER:$1|dem}}.",
        "usermessage-summary": "Etterlater en systembeskjed.",
        "usermessage-editor": "Systembudbringer",
        "watchlist": "Overvåkningsliste",
        "tags-deactivate": "deaktiver",
        "tags-hitcount": "{{PLURAL:$1|én endring|$1 endringer}}",
        "tags-manage-no-permission": "Du har ikke tillatelse til å behandle tagger.",
-       "tags-manage-blocked": "Du kan ikke behandle endringstagger mens du er blokkert.",
+       "tags-manage-blocked": "Du kan ikke behandle endringstagger mens {{GENDER:$1|du}} er blokkert.",
        "tags-create-heading": "Opprett ny tagg",
        "tags-create-explanation": "Som standard vil nyopprettede tagger være tilgjengelige for brukere og roboter.",
        "tags-create-tag-name": "Taggnavn:",
        "tags-deactivate-not-allowed": "Det er ikke mulig å deaktivere taggen «$1».",
        "tags-deactivate-submit": "Deaktiver",
        "tags-apply-no-permission": "Du har ikke tilgang til å legge til merker sammen med dine endringer.",
-       "tags-apply-blocked": "Du kan ikke bruke endringstagger med endringene dine mens du er blokkert.",
+       "tags-apply-blocked": "{{GENDER:$1|Du}} kan ikke bruke endringstagger med endringene dine mens du er blokkert.",
        "tags-apply-not-allowed-one": "Merket «$1» kan ikke legges til manuelt.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Det følgende merket|De følgende merkene}} kan ikke legges til manuelt: $1",
        "tags-update-no-permission": "Du har ikke tilgang til å legge til eller fjerne merker fra individuelle revisjoner eller loggposter.",
-       "tags-update-blocked": "Du kan ikke legge til eller fjerne endringstagger mens du er blokkert.",
+       "tags-update-blocked": "{{GENDER:$1|Du}} kan ikke legge til eller fjerne endringstagger mens du er blokkert.",
        "tags-update-add-not-allowed-one": "Merket «$1» kan ikke legges til manuelt.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Det følgende merket|De følgende merkene}} kan ikke legges til manuelt: $1",
        "tags-update-remove-not-allowed-one": "Merket «$1» kan ikke fjernes.",
        "htmlform-user-not-exists": "<strong>$1</strong> eksisterer ikke.",
        "htmlform-user-not-valid": "<strong>$1</strong> er ikke et gyldig brukernavn.",
        "logentry-delete-delete": "$1 {{GENDER:$2|slettet}} siden $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|slettet}} omdirigeringen $3 ved å overskrive",
        "logentry-delete-restore": "$1 {{GENDER:$2|gjenopprettet}} siden $3",
        "logentry-delete-event": "$1 {{GENDER:$2|endret}} synligheten av {{PLURAL:$5|en logghendelse|$5 logghendelser}} på $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|endret}} synligheten av {{PLURAL:$5|en revisjon|$5 revisjoner}} på side $3: $4",
        "mw-widgets-dateinput-no-date": "Ingen dato valgt",
        "mw-widgets-dateinput-placeholder-day": "ÅÅÅÅ-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "ÅÅÅÅ-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Søk etter media",
+       "mw-widgets-mediasearch-noresults": "Ingen resultater funnet.",
        "mw-widgets-titleinput-description-new-page": "siden eksisterer ikke ennå",
        "mw-widgets-titleinput-description-redirect": "omdiriger til $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Legg til en kategori …",
        "sessionmanager-tie": "Kan ikke kombinere flere forespørselsautentiseringstyper: $1",
        "sessionprovider-generic": "$1 sesjoner",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "informasjons&shy;kapsel-baserte sesjoner",
        "log-action-filter-contentmodel-change": "Endring av innholdsmodell",
        "log-action-filter-contentmodel-new": "Oppretting av side med ikke-standard innholdsmodell",
        "log-action-filter-delete-delete": "Sidesletting",
+       "log-action-filter-delete-delete_redir": "Overskriving av omdirigering",
        "log-action-filter-delete-restore": "Sidegjenoppretting",
        "log-action-filter-delete-event": "Loggsletting",
        "log-action-filter-delete-revision": "Revisjonssletting",
        "usercssispublic": "Merk: CSS-undersidene bør ikke inneholde konfidensielle data siden de kan ses av andre brukere.",
        "restrictionsfield-badip": "Ugyldig IP-adresse eller intervall: $1",
        "restrictionsfield-label": "Tillatte IP-intervaller:",
-       "restrictionsfield-help": "Én IP-adresse eller CIDR-intervall per linje. For å slå på alt, bruk <br /><code>0.0.0.0/0</code><br /><code>::/0</code>",
-       "edit-error-short": "Feil: $1",
-       "edit-error-long": "Feil:\n\n$1"
+       "restrictionsfield-help": "Én IP-adresse eller CIDR-intervall per linje. For å slå på alt, bruk <br /><code>0.0.0.0/0</code><br /><code>::/0</code>"
 }
index 7beefc3..14f05dc 100644 (file)
        "yourpasswordagain": "Opniej invoeren",
        "createacct-yourpasswordagain": "Wachtwoord bevestigen",
        "createacct-yourpasswordagain-ph": "Geef t wachtwoord opniej op",
-       "remembermypassword": "Vanzelf anmelden (hooguut $1 {{PLURAL:$1|dag|dagen}})",
        "userlogin-remembermypassword": "Vanzelf anmelden",
        "userlogin-signwithsecure": "Beveiligde verbiending gebruken",
        "yourdomainname": "Joew domein",
        "passwordreset-emailtext-user": "De gebruker $1 van {{SITENAME}} hef n anvraag edaon um joew wachtwoord veur {{SITENAME}} ($4) opniej in te stellen. \nDe volgende {{PLURAL:$3|gebruker is|gebrukers bin}} ekoppeld an dit netpostadres:\n\n$2\n\n{{PLURAL:$3|Dit tiejelike wachtwoord vervölt|Disse tiejelike wachtwoorden vervallen}} over {{PLURAL:$5|één dag|$5 dagen}}.\nMeld je eigen noen an en wiezig t wachtwoord. A'j dit verzeuk niet zelf edaon hebben, of a'j t oorspronkelike wachtwoord nog kennen en t niet wiezigen willen, negeer dit bericht dan en blief joew ouwe wachtwoord gebruken.",
        "passwordreset-emailelement": "Gebrukersnaam: \n$1\n\nTiedelik wachtwoord: \n$2",
        "passwordreset-emailsentemail": "As dit netpostadres an joew gebrukerskonto ekoppeld is, dan wördt der n netbericht estuurd um joew wachtwoord opniej in te stellen.",
-       "passwordreset-emailsent-capture": "Der is n bericht verstuurd um joew wachtwoord opniej in te stellen. Dit ku'j hieronder lezen.",
-       "passwordreset-emailerror-capture": "Der is n bericht veur t opniej opstellen van joew wachwoord an-emaakt, dit ku'j hieronder lezen. t Versturen naor de {{GENDER:$2|gebruker}} is mislokt um de volgende reden: $1",
        "changeemail": "Netpostadres wiezigen of vorthaolen",
        "changeemail-header": "Vul dit formulier in um joew netpostadres te wiezigen. A'j t netpostadres van disse gebrukerskonto ontkoppelen willen, laot t netpostadres dan leeg a'j t formulier opslaon.",
        "changeemail-no-info": "Je mutten an-emeld ween um drekt toegang te hebben tot disse zied.",
        "undo-norev": "De bewarking kon niet weerummedreid wörden, umdat t niet besteet of vortedaon is.",
        "undo-summary": "Versie $1 van [[Special:Contributions/$2|$2]] ([[User talk:$2|overleg]]) weerummedreid",
        "undo-summary-username-hidden": "Versie $1 deur n verbörgen gebruker weerummedreid",
-       "cantcreateaccounttitle": "Anmaken van n gebrukersprofiel is niet meugelik",
        "cantcreateaccount-text": "t Anmaken van gebrukers van dit IP-adres (<b>$1</b>) is eblokkeerd deur [[User:$3|$3]].\n\nDe deur $3 op-egeven reden is ''$2''",
        "viewpagelogs": "Bekiek logboeken veur disse zied",
        "nohistory": "Der bin gien eerdere versies van disse zied.",
        "activeusers-intro": "Dit is n lieste van gebrukers die de aofgeleupen $1 {{PLURAL:$1|dag|dagen}} enigszins aktief ewest hebben.",
        "activeusers-count": "$1 leste {{PLURAL:$1|haandeling|haandelingen}} in de aofeleupen {{PLURAL:$3|dag|$3 dagen}}",
        "activeusers-from": "Laot gebrukers zien vanaof:",
-       "activeusers-hidebots": "Bots verbargen",
-       "activeusers-hidesysops": "Beheerders verbargen",
        "activeusers-noresult": "Gien aktieve gebrukers evunnen.",
        "activeusers-submit": "Bekiek",
        "listgrouprights": "Rechten van gebrukersgroepen",
        "htmlform-no": "Nee",
        "htmlform-yes": "Ja",
        "htmlform-chosen-placeholder": "Kies n opsie",
-       "sqlite-has-fts": "Versie $1 mit ondersteuning veur \"full-text\" zeuken",
-       "sqlite-no-fts": "Versie $1 zonder ondersteuning veur \"full-text\" zeuken",
        "logentry-delete-delete": "$1 hef de zied $3 {{GENDER:$2|vortedaon}}",
        "logentry-delete-restore": "$1 hef de zied $3 {{GENDER:$2|weerummezet}}",
        "logentry-delete-event": "$1 hef de zichtbaorheid van {{PLURAL:$5|n logboekregel|$5 logboekregels}} van $3 {{GENDER:$2|ewiezigd}}: $4",
index 3fc66f5..b99b7eb 100644 (file)
        "userlogin-yourpassword-ph": "Passwoort ingeven",
        "createacct-yourpassword-ph": "Passwoort ingeven",
        "yourpasswordagain": "Passwoort nochmal ingeven",
-       "remembermypassword": "Mit dissen Browser duersam inloggen (för maximal $1 {{PLURAL:$1|Dag|Daag}})",
        "yourdomainname": "Diene Domään:",
        "externaldberror": "Dat geev en Fehler bi de externe Authentifizerungsdatenbank oder du dröffst dien extern Brukerkonto nich ännern.",
        "login": "Anmellen",
        "activeusers-intro": "Dit is en List von Brukers, de {{PLURAL:$1|den verleden Dag|de verleden $1 Daag}} aktiv wesen sünd.",
        "activeusers-count": "$1 {{PLURAL:$1|Ännern|Ännern}} {{PLURAL:$3|den verleden Dag|in de verleden $3 Daag}}",
        "activeusers-from": "Brukers wiesen vanaf:",
-       "activeusers-hidebots": "Bots nich wiesen",
-       "activeusers-hidesysops": "Administraters nich wiesen",
        "activeusers-noresult": "Keen Brukers funnen.",
        "listgrouprights": "Brukergruppen-Rechten",
        "listgrouprights-summary": "Dit is en List vun de Brukergruppen, de in dit Wiki defineert sünd, un de Rechten, de dor mit verbunnen sünd.\nMehr Informatschonen över enkelte Rechten staht ünner [[{{MediaWiki:Listgrouprights-helppage}}]].",
        "htmlform-submit": "Afspiekern",
        "htmlform-reset": "Ännern trüchsetten",
        "htmlform-selectorother-other": "Annere",
-       "sqlite-has-fts": "$1 mit Stöhn för Vulltext-Söök",
-       "sqlite-no-fts": "$1 ahn Stöhn för Vulltext-Söök",
        "logentry-delete-delete": "$1 {{GENDER:$2|wegsmeten}} Siet $3",
        "revdelete-restricted": "Inschränkungen för Administraters instellt",
        "revdelete-unrestricted": "Inschränkungen för Administraters rutnahmen",
index 3babc10..f5f497e 100644 (file)
        "passwordreset-emaildisabled": "इमेल सुविधा यस विकिमा निस्क्रिय बनाइएको छ ।",
        "passwordreset-username": "प्रयोगकर्ता नाम:",
        "passwordreset-domain": "डोमेन",
-       "passwordreset-capture": "निस्कने इमेलको नमुना हेर्ने ?",
-       "passwordreset-capture-help": "यदि तपाईंले यो कोठामा दाग दिनुभयो भनें यो इमेल (अस्थायी पासवर्ड सहित) तपाईंलाई देखा पर्नेछ साथै प्रयोगकर्तालाई पनि पठाइनेछ।",
        "passwordreset-email": "इमेल ठेगाना:",
        "passwordreset-emailtitle": "{{SITENAME}}मा खाता विवरण",
        "passwordreset-emailtext-ip": "कसैले (सायद तपाईंले, $1 आईपि ठेगानाबाट) {{SITENAME}} ($4)मा तपाईंको खाता विवरणको निम्ति एउटा अनुस्मारकको अनुरोध गरेको छ। निम्न प्रयोगकर्ता {{PLURAL:$3|खाता यस इमेल ठेगानासित सम्बन्धित छ|खाताहरू यस इमेल ठेगानासित सम्बन्धित छन्}}:\n\n$2\n\n{{PLURAL:$3|यो अस्थाई पासवर्डको|यी अस्थाई पासवर्डहरुको}} समय {{PLURAL:$5|एक दिन|$5 दिन}}मा सकिनेछ।\nतपाईंले प्रवेश गरेर अहिले नैं नयाँ पासवर्ड छान्नुहोस्। यदि अरु कसैले अनुरोध गरेको भए अथवा यदि तपाईंलाई मूल पासवर्ड याद भए अनि यसलाई परिवर्तन गर्न चाहनुहुन्न भने, तपाईंले यस सन्देशलाई अनदेखा गर्नुहोस् र पुरानै पासवर्डलाई चालू राख्नुहोस्।",
        "saveprefs": "संग्रह",
        "restoreprefs": "सबै पूर्वनिर्धारित स्थिती कायम गर्ने(सबै खण्डहरूमा)",
        "prefs-editing": "सम्पादन",
-       "rows": "हरफहरà¥\81 :",
-       "columns": "सà¥\8dतमà¥\8dभहरà¥\81 :",
+       "rows": "हरफहरà¥\82 :",
+       "columns": "सà¥\8dतमà¥\8dभहरà¥\82 :",
        "searchresultshead": "खोज",
        "stub-threshold": "<a href=\"#\" class=\"stub\">ठूटो</a> को लागि थ्रेसहोल्ड स्वरूपण (बाइट):",
        "stub-threshold-sample-link": "उदाहरण",
        "right-siteadmin": "डेटाबेसको ताल्चामार्ने र ताल्चाखोल्ने",
        "right-override-export-depth": "गहिराइ ५ सम्मको लिंक गरिएका पृष्ठहरू सहित निर्यात गर्ने",
        "right-sendemail": "अन्य प्रयोगकर्ताहरूलाई इमेल पठाउने",
-       "right-passwordreset": "पासवर्ड परिवर्तन गर्ने ईमेलहरु हेर्नुहोस",
        "right-managechangetags": "डाटाबेसबाट [[Special:Tags|tags]] बनाउने र हटाउने",
        "right-applychangetags": "एकको परिवर्तन सहित [[Special:Tags|tags]] लागु गर्ने",
        "right-changetags": "जोड्ने र हटाउने स्वतन्त्र [[Special:Tags|ट्याग]] व्यक्तिगत अवतरणहरू र लग इन्ट्रीहरूमा",
index 0663e7b..52f757a 100644 (file)
@@ -80,7 +80,8 @@
                        "Jdforrester",
                        "Jeleniccz",
                        "MrLeopold",
-                       "Hex"
+                       "Hex",
+                       "Xxmarijnw"
                ]
        },
        "tog-underline": "Koppelingen onderstrepen:",
        "views": "Weergaven",
        "toolbox": "Hulpmiddelen",
        "tool-link-userrights": "{{GENDER:$1|Gebruikersgroepen}} wijzigen",
+       "tool-link-userrights-readonly": "{{GENDER:$1|Gebruikers}}groepen weergeven",
        "tool-link-emailuser": "Deze {{GENDER:$1|gebruiker}} e-mailen",
        "userpage": "Gebruikerspagina bekijken",
        "projectpage": "Projectpagina bekijken",
        "botpasswords-label-delete": "Verwijderen",
        "botpasswords-label-resetpassword": "Het wachtwoord opnieuw instellen",
        "botpasswords-label-grants": "Van toepassing zijnde rechten:",
-       "botpasswords-help-grants": "Iedere toestemming geeft toegang tot de opgegeven gebruikersrechten die de gebruiker al heeft. Zie [[Special:ListGrants|overzicht van rechten]] voor meer informatie.",
+       "botpasswords-help-grants": "Toestemmingen geven toegang tot gebruikersrechten die u al heeft. Het geven van een toestemming op deze plek geeft u geen toegang tot gebruikersrechten die u anders niet zou hebben. Zie het [[Special:ListGrants|overzicht van toestemmingen]] voor meer informatie.",
        "botpasswords-label-grants-column": "Toegewezen",
        "botpasswords-bad-appid": "De botnaam \"$1\" is niet geldig.",
        "botpasswords-insert-failed": "Toevoegen van botnaam \"$1\" mislukt. Is deze misschien al toegevoegd?",
        "passwordreset-emaildisabled": "E-mailmogelijkheden zijn uitgeschakeld op deze wiki.",
        "passwordreset-username": "Gebruikersnaam:",
        "passwordreset-domain": "Domein:",
-       "passwordreset-capture": "De resulterende e-mail bekijken?",
-       "passwordreset-capture-help": "Als u dit vakje aanvinkt, wordt de e-mail (met het tijdelijke wachtwoord) naar de gebruiker verzonden en ook aan u weergegeven.",
        "passwordreset-email": "E-mailadres:",
        "passwordreset-emailtitle": "Accountgegevens op {{SITENAME}}",
        "passwordreset-emailtext-ip": "Iemand, waarschijnlijk u, heeft vanaf het IP-adres $1 een aanvraag gedaan om uw wachtwoord voor {{SITENAME}} ($4) opnieuw in te stellen. De volgende {{PLURAL:$3|gebruiker is|gebruikers zijn}} gekoppeld aan dit e-mailadres:\n\n$2\n\n{{PLURAL:$3|Dit tijdelijke wachtwoord vervalt|Deze tijdelijke wachtwoorden vervallen}} over {{PLURAL:$5|een dag|$5 dagen}}. Meld u aan en wijzig het wachtwoord nu. Als u dit verzoek niet zelf heeft gedaan, of als u het oorspronkelijke wachtwoord nog kent en het niet wilt wijzigen, negeer dit bericht dan en blijf uw oude wachtwoord gebruiken.",
        "passwordreset-emailelement": "Gebruikersnaam: \n$1\n\nTijdelijk wachtwoord: \n$2",
        "passwordreset-emailsentemail": "Als dit e-mailadres aan uw account gekoppeld is, dan wordt er een e-mail verzonden om uw wachtwoord opnieuw in te stellen.",
        "passwordreset-emailsentusername": "Als er een e-mailadres geregistreerd is voor die gebruikersnaam, dan wordt er een e-mail verzonden om uw wachtwoord opnieuw in te stellen.",
-       "passwordreset-emailsent-capture2": "De wachtwoordherstel-{{PLURAL:$1|e-mail is|e-mails zijn}} verzonden. {{PLURAL:$1|De gebruikersnaam en het wachtwoord worden|De lijst van gebruikersnamen en wachtwoorden wordt}} hier weergegeven.",
-       "passwordreset-emailerror-capture2": "Het e-mailen naar de {{GENDER:$2|gebruiker}} is mislukt: $1 {{PLURAL:$3|De gebruikersnaam en het wachtwoord|De lijst met gebruikersnamen en wachtwoorden}} wordt hieronder weergegeven.",
        "passwordreset-nocaller": "Een aanroeper moet worden opgegeven",
        "passwordreset-nosuchcaller": "Aanroeper bestaat niet: $1",
        "passwordreset-ignored": "Opnieuw instellen van het wachtwoord niet is afgehandeld. Misschien is er geen provider geconfigureerd?",
-       "passwordreset-invalideamil": "Ongeldig e-mailadres",
+       "passwordreset-invalidemail": "Ongeldig e-mailadres",
        "passwordreset-nodata": "Er is geen gebruikersnaam of e-mailadres opgegeven",
        "changeemail": "E-mailadres wijzigen of verwijderen",
        "changeemail-header": "Vul dit formulier in om uw e-mailadres te wijzigen. Als u het e-mailadres wilt ontkoppelen van uw account, laat het e-mailadres dan leeg als u het formulier opslaat.",
        "prefs-help-email": "E-mailadres is optioneel, maar maakt het mogelijk om u uw wachtwoord te e-mailen als u het bent vergeten.",
        "prefs-help-email-others": "U kunt ook anderen in staat stellen per e-mail contact met u op te nemen via een koppeling op uw gebruikers- en overlegpagina zonder dat u uw identiteit prijsgeeft.",
        "prefs-help-email-required": "Hiervoor is een e-mailadres nodig.",
-       "prefs-info": "Basisinformatie",
+       "prefs-info": "Basisgegevens",
        "prefs-i18n": "Taalinstellingen",
        "prefs-signature": "Ondertekening",
        "prefs-dateformat": "Datumopmaak",
        "prefswarning-warning": "U heeft deze wijzigingen gemaakt in uw voorkeuren die nog niet opgeslagen zijn. Wanneer u de pagina verlaat zonder op \"$1\" te klikken worden uw voorkeuren niet bijgewerkt.",
        "prefs-tabs-navigation-hint": "Tip: u kunt de pijltjestoetsen naar links en naar rechts gebruiken om te navigeren tussen de tabbladen in de lijst.",
        "userrights": "Gebruikersrechtenbeheer",
-       "userrights-lookup-user": "Gebruikersgroepen beheren",
+       "userrights-lookup-user": "Een gebruiker selecteren",
        "userrights-user-editname": "Voer een gebruikersnaam in:",
        "editusergroup": "{{GENDER:$1|Gebruikersgroepen}} wijzigen",
        "editinguser": "Bezig met wijzigen van de gebruikersrechten van gebruiker '''[[User:$1|$1]]''' $2",
        "userrights-reason": "Reden:",
        "userrights-no-interwiki": "U hebt geen rechten om gebruikersrechten op andere wiki's te wijzigen.",
        "userrights-nodatabase": "De database $1 bestaat niet of is geen lokale database.",
-       "userrights-nologin": "U moet [[Special:UserLogin|aangemeld]] zijn met een gebruiker met de juiste rechten om gebruikersrechten toe te wijzen.",
-       "userrights-notallowed": "U bent niet gemachtigd om gebruikersrechten toe te voegen of te verwijderen.",
        "userrights-changeable-col": "Groepen die u kunt beheren",
        "userrights-unchangeable-col": "Groepen die u niet kunt beheren",
        "userrights-conflict": "Er is een probleem opgetreden tijdens het instellen van de gebruikersrechten! Controleer en bevestig uw wijzigingen.",
-       "userrights-removed-self": "U hebt uw eigen bevoegdheden ingetrokken. U kunt deze pagina niet langer raadplegen.",
        "group": "Groep:",
        "group-user": "gebruikers",
        "group-autoconfirmed": "autobevestigde gebruikers",
        "right-siteadmin": "De database blokkeren en weer vrijgeven",
        "right-override-export-depth": "Pagina's exporteren inclusief pagina's waarnaar verwezen wordt tot een diepte van vijf",
        "right-sendemail": "E-mail versturen aan andere gebruikers",
-       "right-passwordreset": "E-mails voor wachtwoord opnieuw instellen bekijken",
        "right-managechangetags": "[[Special:Tags|Labels]] aanmaken en (de)activeren",
        "right-applychangetags": "[[Special:Tags|Labels]] aan bewerkingen toewijzen",
        "right-changetags": "Willekeurige [[Special:Tags|labels]] toevoegen aan en verwijderen van versies en logboekregels",
        "apisandbox-continue": "Doorgaan",
        "apisandbox-continue-clear": "Wissen",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} zal [https://www.mediawiki.org/wiki/API:Query#Continuing_queries doorgaan] met het laatste verzoek; {{int:apisandbox-continue-clear}} zal de voortgangsparameters wissen.",
+       "apisandbox-param-limit": "Gebruik <kbd>max</kbd> voor de maximale limiet.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Alle naamruimtes)",
+       "apisandbox-multivalue-all-values": "$1 (Alle waarden)",
        "booksources": "Boekinformatie",
        "booksources-search-legend": "Bronnen en gegevens over een boek zoeken",
        "booksources-search": "Zoeken",
        "booksources-text": "Hieronder staat een lijst met koppelingen naar andere websites die nieuwe of gebruikte boeken verkopen, en die wellicht meer informatie over het boek dat u zoekt hebben:",
        "booksources-invalid-isbn": "Het opgegeven ISBN lijkt niet geldig te zijn.\nControleer of u wellicht een fout hebt gemaakt bij de invoer.",
-       "magiclink-tracking-isbn": "Pagina's die ISBN magische links gebruiken",
+       "magiclink-tracking-rfc": "Pagina's die RFC magische koppelingen gebruiken",
+       "magiclink-tracking-rfc-desc": "Deze pagina gebruikt RFC magische koppelingen. Zie [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] over hoe te migreren.",
+       "magiclink-tracking-pmid": "Pagina's die PMID magische koppelingen gebruiken",
+       "magiclink-tracking-pmid-desc": "Deze pagina gebruikt PMID magische koppelingen. Zie [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] over hoe te migreren.",
+       "magiclink-tracking-isbn": "Pagina's die ISBN magische koppelingen gebruiken",
+       "magiclink-tracking-isbn-desc": "Deze pagina gebruikt ISBN magische koppelingen. Zie [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] over hoe te migreren.",
        "specialloguserlabel": "Uitvoerende gebruiker:",
        "speciallogtitlelabel": "Doel (paginanaam of {{ns:user}}:gebruikersnaam voor gebruiker):",
        "log": "Logboeken",
        "activeusers-intro": "Dit is een lijst met gebruikers die enige activiteit hebben laten zien in de afgelopen {{PLURAL:$1|dag|$1 dagen}}.",
        "activeusers-count": "$1 recente {{PLURAL:$1|handeling|handelingen}} in de {{PLURAL:$3|afgelopen dag|laatste $3 dagen}}",
        "activeusers-from": "Gebruikers worden weergegeven vanaf:",
+       "activeusers-groups": "Gebruikers weergeven die horen bij de groepen:",
+       "activeusers-excludegroups": "Gebruikers uitsluiten die behoren tot de groepen:",
        "activeusers-noresult": "Geen actieve gebruikers gevonden.",
        "activeusers-submit": "Weergeven",
        "listgrouprights": "Rechten van gebruikersgroepen",
        "rollbacklinkcount-morethan": "Meer dan {{PLURAL:$1|één bewerking|$1 bewerkingen}} terugdraaien",
        "rollbackfailed": "Ongedaan maken van wijzigingen mislukt.",
        "rollback-missingparam": "Er ontbreken benodigde parameters in het verzoek.",
+       "rollback-missingrevision": "Laden van versiegegevens mislukt.",
        "cantrollback": "Ongedaan maken van wijzigingen onmogelijk: deze pagina heeft slechts 1 auteur.",
        "alreadyrolled": "Het is niet mogelijk om de bewerking van de pagina [[:$1]] door [[User:$2|$2]] ([[User talk:$2|overleg]]{{int:pipe-separator}}[[Special:Contributions/$2|bijdragen]]) ongedaan te maken.\nIemand anders heeft deze pagina al bewerkt of hersteld naar een eerdere versie.\n\nDe meest recente bewerking is gemaakt door [[User:$3|$3]] ([[User talk:$3|overleg]]{{int:pipe-separator}}[[Special:Contributions/$3|bijdragen]]).",
        "editcomment": "De bewerkingssamenvatting was: <em>$1</em>.",
        "revertpage": "Wijzigingen door [[Special:Contributions/$2|$2]] ([[User talk:$2|Overleg]]) hersteld tot de laatste versie door [[User:$1|$1]]",
        "revertpage-nouser": "Wijzigingen door een verborgen gebruiker teruggedraaid naar de laatste versie door {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "De wijzigingen door $1 zijn teruggedraaid.\nDe laatste versie van $2 is hersteld.",
+       "rollback-success-notify": "De wijzigingen door $1 zijn teruggedraaid;\nde laatste versie van $2 is hersteld. [$3 Wijzigingen weergeven]",
        "sessionfailure-title": "Sessiefout",
        "sessionfailure": "Er lijkt een probleem te zijn met uw aanmeldsessie.\nUw handeling is gestopt uit voorzorg tegen een beveiligingsrisico (dat bestaat uit mogelijke \"hijacking\" van deze sessie).\nGa een pagina terug, laad die pagina opnieuw en probeer het nog eens.",
        "changecontentmodel": "Inhoudsmodel van pagina bewerken",
        "changecontentmodel-success-text": "Het inhoudstype van [[:$1]] is gewijzigd.",
        "changecontentmodel-cannot-convert": "De inhoud van [[:$1]] kan niet worden omgezet in een type van $2.",
        "changecontentmodel-nodirectediting": "Het inhoudsmodel $1 ondersteunt direct bewerken niet",
+       "changecontentmodel-emptymodels-title": "Geen inhoudsmodellen beschikbaar",
+       "changecontentmodel-emptymodels-text": "De inhoud van [[:$1]] kan niet worden omgezet in een ander type.",
        "log-name-contentmodel": "Wijzigingenlogboek van inhoudsmodel",
        "log-description-contentmodel": "Gebeurtenissen rond het inhoudsmodel van een pagina",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|maakte}} de pagina $3 aan met behulp van een niet-standaard inhoudsmodel \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|heeft}} het inhoudsmodel gewijzigd van pagina $3 van \"$4\" in \"$5\"",
        "logentry-contentmodel-change-revertlink": "terugdraaien",
        "logentry-contentmodel-change-revert": "terugdraaien",
        "modifiedarticleprotection": "heeft het beveiligingsniveau gewijzigd voor \"[[$1]]\"",
        "unprotectedarticle": "heeft de beveiliging van \"[[$1]]\" opgeheven",
        "movedarticleprotection": "heeft beveiligingsinstellingen verplaatst van \"[[$2]]\" naar \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Beveiligde}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Heeft het beveiligingsniveau voor \"[[$1]]\" gewijzigd}}",
+       "unprotectedarticle-comment": "{{GENDER:$2|Heeft de beveiliging van \"[[$1]]\" opgeheven}}",
        "protect-title": "Beveiligingsniveau instellen voor \"$1\"",
        "protect-title-notallowed": "Beveiligingsniveau voor \"$1\" bekijken",
        "prot_1movedto2": "[[$1]] is hernoemd naar [[$2]]",
        "undeletehistorynoadmin": "Deze pagina is verwijderd.\nDe reden hiervoor staat hieronder, samen met de details van de gebruikers die deze pagina hebben bewerkt vóór de verwijdering.\nDe verwijderde inhoud van de pagina is alleen zichtbaar voor beheerders.",
        "undelete-revision": "Dit is de verwijderde versie van $1 van $4 om $5 gemaakt door $3:",
        "undeleterevision-missing": "Ongeldige of missende versie.\nMogelijk hebt u een verkeerde koppeling of is de versie hersteld of verwijderd uit het archief.",
+       "undeleterevision-duplicate-revid": "{{PLURAL:$1|Eén versie kon|$1 versies konden}} niet worden hersteld, omdat {{PLURAL:$1|haar|hun}} <code>rev_id</code> al in gebruik was.",
        "undelete-nodiff": "Geen eerdere versie gevonden.",
        "undeletebtn": "Terugplaatsen",
        "undeletelink": "bekijken/terugplaatsen",
        "sp-contributions-newbies-sub": "Voor nieuwelingen",
        "sp-contributions-newbies-title": "Bijdragen van nieuwe gebruikers",
        "sp-contributions-blocklog": "blokkeerlogboek",
-       "sp-contributions-suppresslog": "onderdrukte gebruikersbijdragen",
+       "sp-contributions-suppresslog": "onderdrukte {{GENDER:$1|gebruikersbijdragen}}",
        "sp-contributions-deleted": "verwijderde {{GENDER:$1|gebruiker}}sbijdragen",
        "sp-contributions-uploads": "uploads",
        "sp-contributions-logs": "logboeken",
        "whatlinkshere-hideredirs": "doorverwijzingen $1",
        "whatlinkshere-hidetrans": "Transclusies $1",
        "whatlinkshere-hidelinks": "koppelingen $1",
-       "whatlinkshere-hideimages": "Bestandskoppelingen $1",
+       "whatlinkshere-hideimages": "$1 bestandskoppelingen",
        "whatlinkshere-filters": "Filters",
        "whatlinkshere-submit": "OK",
        "autoblockid": "Automatische blokkade #$1",
        "lockdbsuccesstext": "De database is afgesloten.<br />\nVergeet niet de [[Special:UnlockDB|database vrij te geven]] zodra u klaar bent met uw onderhoud.",
        "unlockdbsuccesstext": "De database is vrijgegeven.",
        "lockfilenotwritable": "Geen schrijfrechten op het databaselockbestand.\nOm de database te kunnen blokkeren of vrij te geven, dient de webserver schrijfrechten op dit bestand te hebben.",
-       "databasenotlocked": "De database is niet geblokkeerd.",
+       "databaselocked": "De database is al vergrendeld.",
+       "databasenotlocked": "De database is niet vergrendeld.",
        "lockedbyandtime": "(door $1 om $3 op $2)",
        "move-page": "\"$1\" hernoemen",
        "move-page-legend": "Pagina hernoemen",
        "patrol-log-header": "Dit logboek bevat versies die gemarkeerd zijn als gecontroleerd.",
        "log-show-hide-patrol": "markeerlogboek $1",
        "log-show-hide-tag": "labellogboek $1",
+       "confirm-markpatrolled-button": "OK",
+       "confirm-markpatrolled-top": "Wilt u bewerking $3 van $2 als gecontroleerd markeren?",
        "deletedrevision": "De oude versie $1 is verwijderd",
        "filedeleteerror-short": "Fout bij het verwijderen van bestand: $1",
        "filedeleteerror-long": "Er zijn fouten opgetreden bij het verwijderen van het bestand:\n\n$1",
        "confirmemail_body_set": "Iemand, waarschijnlijk u, met het IP-adres $1,\nheeft het e-mailadres voor gebruiker \"$2\" op {{SITENAME}} ingesteld op dit e-mailadres.\n\nOpen de volgende koppeling in uw webbrowser om te bevestigen dat u deze gebruiker bent en om de e-mailmogelijkheden op {{SITENAME}} opnieuw te activeren:\n\n$3\n\nAls deze gebruiker *niet* aan u toebehoort, klik dan op de volgende koppeling om de bevestiging van uw e-mailadres te annuleren:\n\n$5\n\nDe bevestigingscode vervalt op $4.",
        "confirmemail_invalidated": "De e-mailbevestiging is geannuleerd",
        "invalidateemail": "E-mailbevestiging annuleren",
+       "notificationemail_body_removed": "Iemand, waarschijnlijk u, met het IP-adres $1, heeft het e-mailadres geregistreerd voor gebruiker \"$2\" verwijderd op {{SITENAME}}. \n\nAls u dit niet was, neem dan onmiddellijk contact op met een sitebeheerder.",
        "scarytranscludedisabled": "[Interwiki-invoeging van sjablonen is uitgeschakeld]",
        "scarytranscludefailed": "[De sjabloon $1 kon niet opgehaald worden]",
        "scarytranscludefailed-httpstatus": "[De sjabloon $1 kon niet opgehaald worden: HTTP $2]",
        "tags-actions-header": "Acties",
        "tags-active-yes": "Ja",
        "tags-active-no": "Nee",
-       "tags-source-extension": "Door een uitbreiding toegevoegd",
+       "tags-source-extension": "Gedefinieerd door de software",
        "tags-source-manual": "Handmatig toegevoegd door gebruikers en bots",
        "tags-source-none": "Niet meer in gebruik",
        "tags-edit": "bewerken",
        "tags-deactivate": "deactiveren",
        "tags-hitcount": "$1 {{PLURAL:$1|wijziging|wijzigingen}}",
        "tags-manage-no-permission": "U hebt geen rechten om labels te beheren.",
-       "tags-manage-blocked": "U kunt geen labels beheren wanneer u geblokkeerd bent.",
+       "tags-manage-blocked": "U kunt geen labels beheren wanneer {{GENDER:$1|u}} geblokkeerd bent.",
        "tags-create-heading": "Een nieuw label aanmaken",
        "tags-create-explanation": "Standaard worden nieuw aangemaakte labels beschikbaar gesteld voor gebruik door gebruikers en bots.",
        "tags-create-tag-name": "Labelnaam:",
        "tags-deactivate-not-allowed": "Het is niet mogelijk het label \"$1\" te deactiveren.",
        "tags-deactivate-submit": "Deactiveren",
        "tags-apply-no-permission": "U hebt geen rechten om wijzigingslabels toe te voegen aan uw wijzigingen.",
-       "tags-apply-blocked": "U kunt geen wijzigen aanbrengen aan labels wanneer u geblokkeerd bent.",
+       "tags-apply-blocked": "U kunt geen labels toevoegen aan uw wijzigingen wanneer {{GENDER:$1|u}} geblokkeerd bent.",
        "tags-apply-not-allowed-one": "Het label \"$1\" mag niet handmatig toegevoegd worden.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Het volgende label mag|De volgende labels mogen}} niet handmatig toegevoegd worden: $1",
        "tags-update-no-permission": "U hebt geen rechten om wijzigingslabels toe te voegen aan of te verwijderen van versies of logboekregels.",
-       "tags-update-blocked": "U kunt geen labels toevoegen of verwijderen wanneer u geblokkeerd bent.",
+       "tags-update-blocked": "U kunt geen labels toevoegen of verwijderen wanneer {{GENDER:$1|u}} geblokkeerd bent.",
        "tags-update-add-not-allowed-one": "Het label \"$1\" mag niet handmatig toegevoegd worden.",
        "tags-update-add-not-allowed-multi": " {{PLURAL:$2|Het label kan|De labels kunnen}} niet handmatig toegevoegd worden: $1",
        "tags-update-remove-not-allowed-one": "Het label \"$1\" mag niet verwijderd worden.",
        "log-action-filter-patrol": "Soort markering:",
        "log-action-filter-protect": "Soort beveiliging:",
        "log-action-filter-rights": "Soort verandering van rechten:",
+       "log-action-filter-suppress": "Soort verberging:",
        "log-action-filter-upload": "Soort upload:",
        "log-action-filter-all": "Alles",
        "log-action-filter-block-block": "Blokkade",
        "log-action-filter-suppress-event": "Verbergen van logboekregel",
        "log-action-filter-suppress-revision": "Verbergen van versie",
        "log-action-filter-suppress-delete": "Verbergen van pagina",
+       "log-action-filter-suppress-block": "Verbergen van gebruiker tijdens blokkade",
+       "log-action-filter-suppress-reblock": "Verbergen van gebruiker tijdens wijzigen blokkade",
        "log-action-filter-upload-upload": "Nieuwe upload",
        "log-action-filter-upload-overwrite": "Herupload",
        "authmanager-authn-autocreate-failed": "Het automatisch aanmaken van een lokaal account is mislukt: $1",
index 66b151e..4142ed8 100644 (file)
        "views": "Visningar",
        "toolbox": "Verktøy",
        "tool-link-userrights": "Endra {{GENDER:$1|brukargrupper}}",
+       "tool-link-userrights-readonly": "Syn {{GENDER:$1|brukar}}grupper",
        "tool-link-emailuser": "Send e-post til {{GENDER:$1|brukaren}}",
        "userpage": "Vis brukarside",
        "projectpage": "Sjå prosjektsida",
        "actionthrottled": "Handlinga vart stoppa",
        "actionthrottledtext": "For å hindre spamming kan du ikkje utføre denne handlinga for mange gonger på kort tid. Ver venleg og prøv igjen litt seinare.",
        "protectedpagetext": "Sida har vorte verna for å hindra endring eller andre handlingar.",
-       "viewsourcetext": "Du kan sjå og kopiere kjeldekoden til denne sida:",
-       "viewyourtext": "Du kan sjå og kopiera kjelda til '''endringane dine''' på sida:",
+       "viewsourcetext": "Du kan sjå og kopiere kjeldekoden til denne sida.",
+       "viewyourtext": "Du kan sjå og kopiera kjelda til <strong>endringane dine</strong> på sida.",
        "protectedinterface": "Denne sida inneheld tekst nytta av brukargrensesnittet for programvara på wikien, og er låst for å hindra hærverk.\nFor å leggja til eller endra omsetjingar for alle wikiar, gjer vel å nytta [https://translatewiki.net/wiki/Main_Page?setlang=nn translatewiki.net], prosjektet for lokalisering av MediaWiki.",
        "editinginterface": "'''Åtvaring:''' Du endrar på ei side som inneheld tekst nytta av brukargrensesnittet for programvara.\nEndringar på denne sida påverkar utsjånaden til brukargrensesnittet for dei andre brukarane av wikien.\nFor å leggja til eller endra omsetjingar, gjer vel å nytta [https://translatewiki.net/wiki/Main_Page?setlang=nn translatewiki.net], prosjektet for lokalisering av MediaWiki.",
        "cascadeprotected": "Denne sida er verna mot endring fordi ho er inkludert i {{PLURAL:$1|den opplista sida|dei opplista sidene}} som har djupvern slått på:\n$2",
        "passwordreset-emaildisabled": "E-postfunksjonen er slegen av på wikien.",
        "passwordreset-username": "Brukarnamn:",
        "passwordreset-domain": "Domene:",
-       "passwordreset-capture": "Vis resulterande epost",
-       "passwordreset-capture-help": "Huk av her dersom du vil sjå eposten (med førebels passord) i tillegg til at han blir sendt til brukaren.",
        "passwordreset-email": "↓E-postadresse:",
        "passwordreset-emailtitle": "↓Kontodetaljar på {{SITENAME}}",
        "passwordreset-emailtext-ip": "Nokon (sannsynlegvis deg, frå IP-adressa $1) bad om ei påminning for kontodetaljane dine for {{SITENAME}} ($4). {{PLURAL:$3|Den fylgjande brukarkontoen|Dei fylgjande brukarkontoane}} er assosierte med denne e-postadressa:\n\n$2\n\n{{PLURAL:$3|Dette mellombels passordet|Desse mellombels passorda}} vil verta ugilde om {{PLURAL:$5|éin dag|$5 dagar}}.\nDu bør logga inn og velja eit nytt passord no. Om nokon andre enn deg bad om denne påminninga, eller du har kome i hug det opphavlege passordet og ikkje lenger ynskjer å endra det, kan du sjå bort frå denne meldinga og halda fram med å nytta det gamle passordet ditt.",
        "userrights-reason": "Årsak:",
        "userrights-no-interwiki": "Du har ikkje tilgang til å endre brukartilgangar på andre wikiar.",
        "userrights-nodatabase": "Databasen $1 finst ikkje eller er ikkje lokal.",
-       "userrights-nologin": "Du må [[Special:UserLogin|logge inn]] med ein administrator- og/eller byråkratkonto for å endre brukartilgangar.",
-       "userrights-notallowed": "Du har ikkje løyve til å leggja til eller fjerna brukarrettar.",
        "userrights-changeable-col": "Grupper du kan endre",
        "userrights-unchangeable-col": "Grupper du ikkje kan endre",
        "group": "Gruppe:",
        "right-siteadmin": "Låse og låse opp databasen",
        "right-override-export-depth": "Eksporter sider inkludert lenkte sider til ei djupn på 5",
        "right-sendemail": "Senda e-post til andre brukarar",
-       "right-passwordreset": "Sjå e-postar for passord som er stilte attende",
        "newuserlogpage": "Brukaropprettingslogg",
        "newuserlogpagetext": "Dette er ein logg over oppretta brukarkontoar.",
        "rightslog": "Brukartilgangslogg",
index 3493eb7..eb65fbf 100644 (file)
        "views": "Afichatges",
        "toolbox": "Aisinas",
        "tool-link-userrights": "Modificar los gropes de {{GENDER:$1|l’utilizaire|l’utilizaira}}",
+       "tool-link-userrights-readonly": "Veire los {{GENDER:$1|gropes utilizaire}}",
        "tool-link-emailuser": "Mandar un corrièr electronic a {{GENDER:$1|l’utilizaire|l’utilizaira}}",
        "userpage": "Pagina d'utilizaire",
        "projectpage": "Pagina meta",
        "passwordreset-emaildisabled": "Las foncionalitats e-mail son estadas desactivadas sus aqueste wiki.",
        "passwordreset-username": "Nom d'utilizaire :",
        "passwordreset-domain": "Domeni:",
-       "passwordreset-capture": "Veire lo corrièl resultant ?",
-       "passwordreset-capture-help": "Se marcatz aquesta casa, lo corrièr electronic (amb lo senhal temporari) vos serà afichat al meteis temps que serà mandat a l'utilizaire.",
        "passwordreset-email": "Adreça de corrièr electronic :",
        "passwordreset-emailtitle": "Detailhs d'un compte per {{SITENAME}}",
        "passwordreset-emailtext-ip": "Qualqu'un (probablament vos, dempuèi l'adreça IP $1) a demandat una reïnicializacion de vòstre senhal per {{SITENAME}} ($4). {{PLURAL:$3|Lo compte d'utilizaire seguent es associat|Los comptes d'utilizaires seguents son associats}} a aquesta adreça de corrièr electronic :\n\n$2\n\n{{PLURAL:$3|Aqueste senhal temporari expirarà|Aquestes senhals temporaris expiraràn}} dins {{PLURAL:$5|un jorn|$5 jorns}}. Ara, vos cal vos connectar e causir un senhal novèl. Se aquesta demanda proven pas de vos, o que vos sètz remembrat de vòstre senhal inicial, e que volètz pas mai lo modificar, podètz ignorar aqueste messatge e contunhar d'utilizar vòstre ancian senhal.",
        "columns": "Colomnas :",
        "searchresultshead": "Recèrca",
        "stub-threshold": "Limit pel formatatge dels ligams d’esbòs ($1) :",
+       "stub-threshold-sample-link": "exemple",
        "stub-threshold-disabled": "Desactivat",
        "recentchangesdays": "Nombre de jorns d'afichar dins los darrièrs cambiaments :",
        "recentchangesdays-max": "(maximum $1 {{PLURAL:$1|jorn|jorns}})",
        "prefs-help-recentchangescount": "Aquò inclutz las modificacions recentas, las paginas d’istorics e los jornals.",
        "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.\n[[Special:ResetTokens|Clicatz aicí se la vos cal reïnicializar]].",
        "savedprefs": "Las preferéncias son estadas salvadas.",
+       "savedrights": "Los dreits d'utilizaire de {{GENDER:$1|$1}} son estats enregistrats.",
        "timezonelegend": "Fus orari :",
        "localtime": "Ora locala :",
        "timezoneuseserverdefault": "Utilizar la valor del servidor ($1)",
        "badsig": "Signatura bruta incorrècta, verificatz vòstras balisas HTML.",
        "badsiglength": "Vòstra signatura es tròp longa.\nDeu aver, al maximum $1 caractèr{{PLURAL:$1||s}}.",
        "yourgender": "Cossí vos agrada mai d'èsser descrit ?",
-       "gender-unknown": "M'agrada mai sens detalh",
+       "gender-unknown": "Quand farà mencion de vos, lo logicial utilizarà de mots de genre neutre, quand serà possible",
        "gender-male": "Modifica de pagina del wiki",
        "gender-female": "Modifica de paginas del wiki",
        "prefs-help-gender": "Definir aquesta preferéncia es facultatiu.\nAqueste logicial utiliza sa valor per s’adreçar a vos e vos mencionar als autres en utilizant lo bon genre gramatical.\nAquesta informacion serà publica.",
        "prefs-help-prefershttps": "Aquesta preferéncia serà efectiva al moment de vòstra connexion que ven.",
        "prefs-tabs-navigation-hint": "Astúcia : Podètz utilizar las sagetas d'esquèrra e de dreita per navigar entre los onglets.",
        "userrights": "Gestion dels dreits d'utilizaire",
-       "userrights-lookup-user": "Gestion dels dreits d'utilizaire",
+       "userrights-lookup-user": "Seleccionar un utilizaire",
        "userrights-user-editname": "Entrar un nom d’utilizaire :",
-       "editusergroup": "Modificacion dels gropes d’{{GENDER:$1|utilizaires}}",
+       "editusergroup": "Cargar de gropes d’utilizaires",
        "editinguser": "Modificacion dels dreits de l’{{GENDER:$1|utilizaire|utilizaira}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modificar los gropes de l’utilizaire",
        "saveusergroups": "Enregistrar los gropes de l’{{GENDER:$1|utilizaire|utilizaira}}",
        "userrights-reason": "Motiu :",
        "userrights-no-interwiki": "Sètz pas abilitat per modificar los dreits dels utilizaires sus d'autres wikis.",
        "userrights-nodatabase": "La basa de donadas « $1 » existís pas o es pas en local.",
-       "userrights-nologin": "Vos cal [[Special:UserLogin|vos connectar]] amb un compte d'administrator per balhar los dreits d'utilizaire.",
-       "userrights-notallowed": "Avètz pas la permission d'apondre o suprimir de dreits d'utilizaire.",
        "userrights-changeable-col": "Los gropes que podètz cambiar",
        "userrights-unchangeable-col": "Los gropes que podètz pas cambiar",
        "userrights-conflict": "Conflicte de modificacion de dreits d'utilizaire ! Relegissètz e confirmatz vòstras modificacions.",
-       "userrights-removed-self": "Avètz suprimit vòstres pròpris dreits. Del còp, podètz pas mai accedir a aquesta pagina.",
        "group": "Grop :",
        "group-user": "Utilizaires",
        "group-autoconfirmed": "Utilizaires enregistrats",
        "right-siteadmin": "Verrolhar e desverrolhar la basa de donadas",
        "right-override-export-depth": "Exportar las paginas en incluent las paginas ligadas fins a una prigondor de 5 nivèls",
        "right-sendemail": "Mandar un corrièl als autres utilizaires",
-       "right-passwordreset": "Veire los corrièrs electronics de reïnicializacion dels senhals",
        "right-applychangetags": "Aplicar [[Special:Tags|las balisas]] amb sas pròprias modificacions",
        "grant-generic": "ensemble de dreits « $1 »",
+       "grant-group-email": "Mandar un corrièr electronic",
        "grant-blockusers": "Blocar e desblocar d'utilizaires",
+       "grant-createaccount": "Crear de comptes",
+       "grant-createeditmovepage": "Crear, modificar e desplaçar de paginas",
        "grant-patrol": "Verificar las modificacions de paginas",
+       "grant-basic": "Dreits de basa",
        "newuserlogpage": "Istoric de las creacions de comptes",
        "newuserlogpagetext": "Jornal de las creacions de comptes d'utilizaires.",
        "rightslog": "Istoric de las modificacions d'estatut",
        "recentchanges-label-plusminus": "La talha de la pagina a cambiat d'aqueste nombre d’octets.",
        "recentchanges-legend-heading": "<strong>Legenda :</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (veire tanben la [[Special:NewPages|lista de las paginas novèlas]]).",
+       "recentchanges-submit": "Afichar",
        "rcnotefrom": "Çaijós {{PLURAL:$5|la modificacion efectuada|las modificacions efectuadas}} dempuèi lo <strong>$3, $4</strong> (afichadas fins a <strong>$1</strong>).",
        "rclistfrom": "Afichar las modificacions novèlas dempuèi lo $3 $2",
        "rcshowhideminor": "$1 los cambiaments menors",
        "rcshowhidemine": "$1 mas modificacions",
        "rcshowhidemine-show": "Afichar",
        "rcshowhidemine-hide": "Amagar",
+       "rcshowhidecategorization": "$1 la categorizacion de las paginas",
+       "rcshowhidecategorization-show": "Afichar",
+       "rcshowhidecategorization-hide": "Amagar",
        "rclinks": "Afichar los $1 darrièrs cambiaments efectuats al cors dels $2 darrièrs jorns<br />$3.",
        "diff": "dif",
        "hist": "ist",
        "recentchangeslinked-summary": "Aquesta pagina especiala fa veire los darrièrs cambiaments sus las paginas que son ligadas. Las paginas de [[Special:Watchlist|vòstra lista de seguimznt]] son '''en gras'''.",
        "recentchangeslinked-page": "Nom de la pagina :",
        "recentchangeslinked-to": "Afichar los cambiaments cap a las paginas ligadas al luòc de la pagina donada",
+       "recentchanges-page-added-to-category": "[[:$1]] apondut a la categoria",
        "upload": "Importar un fichièr",
        "uploadbtn": "Importar un fichièr",
        "reuploaddesc": "Anullar lo cargament e tornar al formulari.",
        "upload-too-many-redirects": "L'URL conten tròp de redireccions",
        "upload-http-error": "Una error HTTP es intervenguda : $1",
        "upload-copy-upload-invalid-domain": "La còpia dels telecargaments es pas disponibla dempuèi aqueste domeni.",
+       "upload-dialog-title": "Mandar un fichièr",
+       "upload-dialog-button-cancel": "Anullar",
+       "upload-dialog-button-back": "Retorn",
+       "upload-dialog-button-done": "Acabat",
+       "upload-dialog-button-save": "Enregistrar",
+       "upload-dialog-button-upload": "Mandar",
+       "upload-form-label-infoform-title": "Detalhs",
+       "upload-form-label-infoform-name": "Nom",
+       "upload-form-label-infoform-description": "Descripcion",
+       "upload-form-label-usage-title": "Utilizacion",
+       "upload-form-label-usage-filename": "Nom del fichièr",
+       "upload-form-label-own-work": "Soi l'autor d'aquesta òbra",
+       "upload-form-label-infoform-categories": "Categorias",
+       "upload-form-label-infoform-date": "Data",
        "backend-fail-stream": "Impossible de legir lo fichièr $1.",
        "backend-fail-backup": "Impossible de salvar lo fichièr $1.",
        "backend-fail-notexists": "Lo fichièr $1 existís pas.",
        "uploadstash-nofiles": "Avètz pas de fichièrs en cache d'impòrt.",
        "uploadstash-errclear": "La supression dels fichièrs a fracassat.",
        "uploadstash-refresh": "Actualizar la lista dels fichièrs",
+       "uploadstash-thumbnail": "afichar una miniatura",
        "invalid-chunk-offset": "Offset de segment invalid",
        "img-auth-accessdenied": "Accès refusat",
        "img-auth-nopathinfo": "PATH_INFO mancant. Vòstre servidor es pas parametrat per passar aquesta informacion.\nBenlèu que fonciona en CGI e supòrta pas img_atuh. Consultatz https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "mostrevisions": "Articles mai modificats",
        "prefixindex": "Totas las paginas que començan per…",
        "prefixindex-namespace": "Totas las paginas amb prefix (espaci de noms $1)",
+       "prefixindex-submit": "Afichar",
        "prefixindex-strip": "Levar lo prefix dins la lista",
        "shortpages": "Paginas brèvas",
        "longpages": "Paginas longas",
        "protectedpages-performer": "Proteccion de l’utilizaire",
        "protectedpages-params": "Paramètres de proteccion",
        "protectedpages-reason": "Motiu",
+       "protectedpages-submit": "Afichar las paginas",
        "protectedpages-unknown-timestamp": "Desconegut",
        "protectedpages-unknown-performer": "Utilizaire desconegut",
        "protectedtitles": "Títols protegits",
        "protectedtitlesempty": "Cap de títol es pas actualament protegit amb aquestes paramètres.",
+       "protectedtitles-submit": "Afichar los títols",
        "listusers": "Lista dels participants",
        "listusers-editsonly": "Far veire sonque los utilizaires qu'an al mens una contribucion",
        "listusers-creationsort": "Triar per data de creacion",
        "usereditcount": "$1 {{PLURAL:$1|cambiament|cambiaments}}",
        "usercreated": "{{GENDER:$3|Creat}} lo $1 a $2",
        "newpages": "Paginas novèlas",
+       "newpages-submit": "Afichar",
        "newpages-username": "Nom d'utilizaire :",
        "ancientpages": "Articles mai ancians",
        "move": "Renomenar",
        "apihelp-no-such-module": "Lo modul « $1 » es introbable.",
        "apisandbox": "Nauc de sabla API",
        "apisandbox-api-disabled": "API es desactivat sus aqueste site.",
+       "apisandbox-fullscreen": "Espandir lo panèl",
+       "apisandbox-unfullscreen": "Afichar la pagina",
        "apisandbox-submit": "Far la demanda",
        "apisandbox-reset": "Escafar",
+       "apisandbox-retry": "Ensajar tornarmai",
+       "apisandbox-helpurls": "Ligams d'ajuda",
        "apisandbox-examples": "Exemples",
+       "apisandbox-dynamic-parameters": "Paramètres suplementaris",
+       "apisandbox-dynamic-parameters-add-label": "Apondon del paramètre",
+       "apisandbox-dynamic-parameters-add-placeholder": "Nom del paramètre",
+       "apisandbox-deprecated-parameters": "Paramètres obsolèts",
        "apisandbox-results": "Resultats",
        "apisandbox-request-url-label": "Requèsta URL :",
        "apisandbox-request-time": "Durada de la demanda : {{PLURAL:$1|$1 ms}}",
+       "apisandbox-continue": "Contunhar",
+       "apisandbox-continue-clear": "Escafar",
        "booksources": "Obratges de referéncia",
        "booksources-search-legend": "Recercar demest d'obratges de referéncia",
        "booksources-isbn": "ISBN :",
        "specialloguserlabel": "Autor :",
        "speciallogtitlelabel": "Cibla (títol o {{ns:user}}:nom d'utilizaire) :",
        "log": "Jornals",
+       "logeventslist-submit": "Afichar",
        "all-logs-page": "Totas las operacions publicas",
        "alllogstext": "Afichatge combinat de totes los jornals de {{SITENAME}}.\nPodètz restrénher la vista en seleccionant un tipe de jornal, un nom d’utilizaire (cassa sensibla) o una pagina ciblada (idem).",
        "logempty": "I a pas res dins l’istoric per aquesta pagina.",
        "log-title-wildcard": "Recercar de títols que començan per aqueste tèxte",
        "showhideselectedlogentries": "Afichar/amagar las entradas de jornal seleccionadas",
+       "checkbox-select": "Seleccionar : $1",
+       "checkbox-all": "Tot",
+       "checkbox-none": "Pas cap",
+       "checkbox-invert": "Inversar",
        "allpages": "Totas las paginas",
        "nextpage": "Pagina seguenta ($1)",
        "prevpage": "Pagina precedenta ($1)",
        "cachedspecial-viewing-cached-ttl": "Visualizatz una version d'aquesta pagina mesa en cache, que pòt èsser datada d’al mai $1.",
        "cachedspecial-refresh-now": "Veire lo mai recent.",
        "categories": "Categorias",
+       "categories-submit": "Afichar",
        "categoriespagetext": "{{PLURAL:$1|La categoria seguenta es utilizada|Las categorias seguentas son utilizadas}} per de paginas o de fichièrs.\n[[Special:UnusedCategories|Las categorias inutilizadas]] son pas afichadas aicí.\nVejatz tanben [[Special:WantedCategories|las categorias demandadas]].",
        "categoriesfrom": "Afichar las categorias que començan a :",
        "deletedcontributions": "Contribucions suprimidas d’un utilizaire",
        "listgrouprights-namespaceprotection-header": "Restriccions d'espaci de noms",
        "listgrouprights-namespaceprotection-namespace": "Espaci de noms",
        "listgrouprights-namespaceprotection-restrictedto": "Dreit(s) que permet(on) a l'utilizaire de modificar",
+       "listgrants": "Autorizacions",
+       "listgrants-grant": "Acordar",
+       "listgrants-rights": "Dreits",
        "trackingcategories": "Categorias de seguiment",
        "trackingcategories-msg": "Categoria de seguiment",
        "trackingcategories-name": "Nom del messatge",
        "wlheader-showupdated": "Las paginas que son estadas modificadas dempuèi vòstra darrièra visita son afichadas en '''gras'''.",
        "wlnote": "Çaijós {{PLURAL:$1|figura la darrièra modificacion efectuada|figuran las <strong>$1</strong> darrièras modificacions efectuadas}} pendent {{PLURAL:$2|la darrièra ora|las <strong>$2</strong> darrièras oras}}, dempuèi $3, $4.",
        "wlshowlast": "Far veire las darrièras $1 oras, los darrièrs $2 jorns",
+       "watchlist-hide": "Amagar",
+       "watchlist-submit": "Afichar",
        "wlshowhideminor": "cambiaments menors",
+       "wlshowhidebots": "Robòts",
+       "wlshowhideliu": "utilizaires enregistrats",
+       "wlshowhideanons": "utilizaires anonims",
+       "wlshowhidepatr": "modificacions repassadas",
+       "wlshowhidemine": "mas modificacions",
        "watchlist-options": "Opcions de la lista de seguiment",
        "watching": "Seguit...",
        "unwatching": "Fin del seguit...",
        "delete-confirm": "Escafar «$1»",
        "delete-legend": "Escafar",
        "historywarning": "<strong>Atencion :</strong> la pagina que sètz a mand de suprimir a un istoric amb $1 {{PLURAL:$1|version|versions}} :",
+       "historyaction-submit": "Afichar",
        "confirmdeletetext": "Sètz a mand de suprimir una pagina o un fichièr, e mai totas sas versions anterioras istorizadas.\nConfirmatz qu'es plan çò que volètz far, que ne comprenètz las consequéncias e que fasètz aquò en acòrdi amb las [[{{MediaWiki:Policy-url}}|règlas intèrnas]].",
        "actioncomplete": "Accion efectuada",
        "actionfailed": "L’accion a fracassat",
        "changecontentmodel-title-label": "Títol de la pagina",
        "changecontentmodel-model-label": "Novèl modèl de contengut",
        "changecontentmodel-reason-label": "Motiu :",
+       "changecontentmodel-submit": "Modificar",
        "logentry-contentmodel-change-revertlink": "restablir",
        "logentry-contentmodel-change-revert": "restablir",
        "protectlogpage": "Istoric de las proteccions",
        "ipb-unblock": "Desblocar un compte d'utilizaire o una adreça IP",
        "ipb-blocklist": "Vejatz los blocatges existents",
        "ipb-blocklist-contribs": "Contribucions per {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "$1 restant",
        "unblockip": "Desblocar un utilizaire o una adreça IP",
        "unblockiptext": "Utilizatz lo formulari çaijós per restablir l'accès en escritura\na partir d'una adreça IP precedentament blocada.",
        "ipusubmit": "Suprimir aqueste blocatge",
        "pageinfo-article-id": "Numèro de la pagina",
        "pageinfo-language": "Lenga del contengut de la pagina",
        "pageinfo-content-model": "Modèl de contengut de la pagina",
+       "pageinfo-content-model-change": "modificar",
        "pageinfo-robot-policy": "Indexacion per robòts",
        "pageinfo-robot-index": "Autorizada",
        "pageinfo-robot-noindex": "Interdicha",
        "pageinfo-category-pages": "Nombre de paginas",
        "pageinfo-category-subcats": "Nombre de soscategorias",
        "pageinfo-category-files": "Nombre de fichièrs",
+       "pageinfo-user-id": "ID de l'utilizaire",
        "markaspatrolleddiff": "Marcar coma essent pas un vandalisme",
        "markaspatrolledtext": "Marcar aqueste article coma pas vandalizat",
        "markedaspatrolled": "Marcat coma pas vandalizat",
        "patrol-log-header": "Vaquí un jornal de las versions patrolhadas.",
        "log-show-hide-patrol": "$1 l'istoric de las relecturas",
        "log-show-hide-tag": "$1 lo jornal de las balisas",
+       "confirm-markpatrolled-button": "D'acòrdi",
        "deletedrevision": "La version anciana $1 es estada suprimida.",
        "filedeleteerror-short": "Error al moment de la supression del fichièr : $1",
        "filedeleteerror-long": "D'errors son estadas rencontradas al moment de la supression del fichièr :\n\n$1",
        "confirm-watch-top": "Apondre aquesta pagina a vòstra lista de seguiment ?",
        "confirm-unwatch-button": "D'acòrdi",
        "confirm-unwatch-top": "Levar aquesta pagina de vòstra lista de seguiment ?",
+       "confirm-rollback-button": "D'acòrdi",
        "colon-separator": "&nbsp;:&#32;",
        "quotation-marks": "« $1 »",
        "imgmultipageprev": "← pagina precedenta",
        "watchlisttools-edit": "Veire e modificar la lista de seguiment",
        "watchlisttools-raw": "Modificar la lista (mòde brut)",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussion]])",
+       "timezone-local": "Local",
        "duplicate-defaultsort": "Atencion : La clau de triada per defaut « $2 » espotís la mai recenta « $1 ».",
        "duplicate-displaytitle": "<strong>Atencion :</strong> Lo títol d'afichatge «$2» remplaça l'ancian títol d'afichatge «$1».",
        "version": "Version",
        "redirect-page": "ID de pagina",
        "redirect-revision": "Revision de la pagina",
        "redirect-file": "Nom del fichièr",
+       "redirect-logid": "ID de jornal",
        "redirect-not-exists": "Valor pas trobada",
        "fileduplicatesearch": "Recèrca dels fichièrs en doble",
        "fileduplicatesearch-summary": "Recèrca de las còpias de fichièrs identics d'aprèp lor emprenta de hachatge.",
        "tags-actions-header": "Accions",
        "tags-active-yes": "Òc",
        "tags-active-no": "Non",
-       "tags-source-extension": "Definida per una extension",
+       "tags-source-extension": "Definit pel logicial",
        "tags-source-manual": "Aplicada manualament pels utilizaires e los bòts",
        "tags-source-none": "Obsolèt",
        "tags-edit": "modificar",
        "htmlform-cloner-create": "Apondre encara",
        "htmlform-cloner-delete": "Suprimir",
        "htmlform-cloner-required": "Una valor al mens es obligatòria.",
+       "htmlform-date-placeholder": "AAAA-MM-JJ",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "AAAA-MM-JJ HH:MM:SS",
        "logentry-delete-delete": "$1 {{GENDER:$2|a suprimit}} la pagina $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|a restablit}} la pagina $3",
        "logentry-delete-event": "$1 {{GENDER:$2|a modificat}} la visibilitat {{PLURAL:$5|d'un eveniment del jornal|de $5 eveniments del jornal}} sus $3 : $4",
        "mediastatistics-header-text": "Textual",
        "mediastatistics-header-executable": "Executables",
        "mediastatistics-header-archive": "Formats compressats",
+       "mediastatistics-header-total": "Totes los fichièrs",
        "json-error-state-mismatch": "JSON invalid o mal format",
        "json-error-syntax": "Error de sintaxi",
        "headline-anchor-title": "Ligam cap a aquesta seccion",
        "randomrootpage": "Pagina raiç aleatòria",
        "log-action-filter-rights": "Tipe de cambiament de dreits :",
        "log-action-filter-suppress": "Tipe de supression :",
+       "log-action-filter-all": "Tot",
+       "log-action-filter-block-block": "Blocatge",
+       "log-action-filter-block-unblock": "Desblocar",
+       "authmanager-email-label": "Corrièr electronic",
+       "authmanager-email-help": "Adreça de corrièr electronic",
+       "authmanager-realname-label": "Nom vertadièr",
+       "authmanager-realname-help": "Nom real de l'utilizaire",
+       "authprovider-resetpass-skip-label": "Sautar",
        "changecredentials": "Modificar las informacions d’identificacion"
 }
index 8c42878..bdc8b77 100644 (file)
        "yourpasswordagain": "Пароль ногæй бафысс:",
        "createacct-yourpasswordagain": "Сбæлвырд кæн пароль",
        "createacct-yourpasswordagain-ph": "Пароль ногæй бафысс",
-       "remembermypassword": "Бахъуыды мæ кæнæд ацы браузеры (максимум $1 {{PLURAL:$1|бонмæ}})",
        "userlogin-remembermypassword": "Системæйы мæ дар",
        "userlogin-signwithsecure": "Æдас бастдзинадæй",
        "yourdomainname": "Дæ домен:",
        "passwordreset-emailtext-user": "{{grammar:genitive|{{SITENAME}}}} архайæг $1 æрдомдта дæ {{grammar:genitive|{{SITENAME}}}} ($4) аккаунты пароль ногæй сæвæрын. Ацы архайæджы {{PLURAL:$3|аккаунт баст у|аккаунттæ баст сты}} ацы электрон посты адрисимæ:\n\n$2\n\n{{PLURAL:$3|Ацы рæстæгмæ пароль|Ацы рæстæгмæ паролтæ}} кусдзысты {{PLURAL:$5|иу бон|$5 боны}}.\nНыр ды хъуамæ бахизай системæмæ æмæ равзарай ног пароль. Кæд ай æндæр чидæр æрдомдта, кæнæ кæд дæ пароль æрхъуыды кодтай æмæ дæ нал фæды фæивай йæ, уæд дæ бон у мацæмæ дарай ацы фыстæг æмæ дарддæр архайай дæ зæронд паролæй.",
        "passwordreset-emailelement": "Фæсномыг: \n$1\n\nРæстæгмæ пароль: \n$2",
        "passwordreset-emailsentemail": "Ног пароль сæвæрыны фыстæг æрвыст æрцыд.",
-       "passwordreset-emailsent-capture": "Ног пароль сæвæрыны фыстæг æрвыст æрцыд æмæ бындæр æвдыст у.",
-       "passwordreset-emailerror-capture": "Ног пароль сæвæрыны фыстæг арæзт æрцыд æмæ бындæр æвдыст у. Фæлæ йæ {{grammar:allative|{{GENDER:$2|user}}}} арвитын нæ бантыстис: $1",
        "changeemail": "E-mail адрис фæивын",
        "changeemail-header": "Аккаунты e-mail адрис фæивын",
        "changeemail-no-info": "Ды хъуамæ системæмæ хызт уай, цæмæй ацы фарсмæ комкоммæ бавналай.",
        "post-expand-template-argument-warning": "'''Сындæг:''' Ацы фарсы ис уæддæр иу хуызæджы аргумент, кæй райтынг у æгæр стыр.\nУыцы аргументтæ уагъд æрцыдысты.",
        "post-expand-template-argument-category": "Фæрстæ, кæдоны ис хуызæджы уагъд аргумент",
        "parser-template-loop-warning": "Хуызæгты цасм ссардæуыд: [[$1]]",
-       "cantcreateaccounttitle": "Аккаунт саразæн нæй",
        "viewpagelogs": "Ацы фарсæн йæ логтæ равдисын",
        "nohistory": "Ацы фарсæн ивдтыты истори нæй.",
        "currentrev": "Фæстаг фæлтæр",
        "listusers-noresult": "Иу архайæг дæр не ссардæуыд.",
        "listusers-blocked": "(хъодыгонд)",
        "activeusers": "Активон архайджыты номхыгъд",
-       "activeusers-hidebots": "Боттæ бамбæхс",
-       "activeusers-hidesysops": "Радгæсты бамбæхс",
        "activeusers-noresult": "Иу архайæг дæр не ссардæуыд.",
        "listgrouprights": "Къордты архайджыты бартæ",
        "listgrouprights-group": "Къорд",
        "feedback-back": "Фæстæмæ",
        "feedback-cancel": "Ныууадзын",
        "feedback-close": "Æххæст",
-       "feedback-error-title": "Рæдыд",
        "feedback-error1": "Рæдыд: Æнæзонгæ фæстиуæг API-йæ",
        "feedback-error2": "Рæдыд: Ивд нæ фæрæстмæ",
        "feedback-error3": "Рæдыд: API дзуапп нæ дæтты",
index 829bb0e..0156bdb 100644 (file)
        "yourpasswordagain": "ਪਾਸਵਰਡ ਮੁੜ ਲਿਖੋ:",
        "createacct-yourpasswordagain": "ਪਾਸਵਰਡ ਪੁਸ਼ਟੀ",
        "createacct-yourpasswordagain-ph": "ਪਾਸਵਰਡ ਫੇਰ ਦਿਉ",
-       "remembermypassword": "ਇਸ ਕੰਪਿਊਟਰ ’ਤੇ ਮੇਰਾ ਦਾਖ਼ਲਾ ਯਾਦ ਰੱਖੋ (ਵੱਧ ਤੋਂ ਵੱਧ $1 {{PLURAL:$1|ਦਿਨ|ਦਿਨਾਂ}} ਲਈ)",
        "userlogin-remembermypassword": "ਮੈਨੂੰ ਲਾਗਇਨ ਰੱਖੋ",
        "userlogin-signwithsecure": "ਸੁਰੱਖਿਅਤ ਕੁਨੈਕਸ਼ਨ ਰੱਖੋ",
        "yourdomainname": "ਤੁਹਾਡਾ ਡੋਮੇਨ:",
        "passwordreset-emailtext-user": "{{SITENAME}} 'ਤੇ User $1 ਨੇ ਤੁਹਾਡੇ {{SITENAME}} ($4) ਉਤਲੇ ਪਛਾਣ-ਸ਼ਬਦ ਨੂੰ ਮੁੜ-ਬਣਾਉਣ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਇਸ ਈਮੇਲ ਪਤੇ ਨਾਲ਼ ਹੇਠ ਲਿਖੇ {{PLURAL:$3|ਖਾਤੇ|ਖਾਤਿਆਂ}} ਦਾ ਵਾਸਤਾ ਹੈ:\n\n$2\n\n{{PLURAL:$3|ਇਸ ਆਰਜ਼ੀ ਪਛਾਣ-ਸ਼ਬਦ|ਇਹਨਾਂ ਆਰਜ਼ੀ ਪਛਾਣ-ਸ਼ਬਦਾਂ}} ਦੀ ਮਿਆਦ {{PLURAL:$5|ਇੱਕ ਦਿਨ|$5 ਦਿਨਾਂ}} 'ਚ ਮੁੱਕ ਜਾਵੇਗੀ।\nਤੁਹਾਨੂੰ ਹੁਣੇ ਦਾਖ਼ਲ ਹੋ ਕੇ ਕੋਈ ਨਵਾਂ ਪਛਾਣ-ਸ਼ਬਦ ਬਣਾ ਲੈਣਾ ਚਾਹੀਦਾ ਹੈ। ਜੇਕਰ ਕਿਸੇ ਹੋਰ ਨੇ ਇਹ ਬੇਨਤੀ ਕੀਤੀ ਹੈ ਜਾਂ ਤੁਹਾਨੂੰ ਆਪਣਾ ਪਹਿਲਾ ਪਛਾਣ-ਸ਼ਬਦ ਯਾਦ ਆ ਗਿਆ ਹੈ ਅਤੇ ਹੁਣ ਤੁਸੀਂ ਉਹਨੂੰ ਬਦਲ਼ਨਾ ਨਹੀਂ ਲੋਚਦੇ ਤਾਂ ਤੁਸੀਂ ਇਸ ਸੁਨੇਹੇ ਨੂੰ ਅਣਡਿੱਠਾ ਕਰ ਕੇ ਆਪਣਾ ਪੁਰਾਣਾ ਪਛਾਣ-ਸ਼ਬਦ ਵਰਤਦੇ ਰਹਿ ਸਕਦੇ ਹੋ।",
        "passwordreset-emailelement": "ਯੂਜ਼ਰ-ਨਾਂ: \n$1\n\nਆਰਜ਼ੀ ਪਾਸਵਰਡ: \n$2",
        "passwordreset-emailsentemail": "ਇੱਕ ਪਾਸਵਰਡ ਮੁੜ-ਸੈੱਟ ਈ-ਮੇਲ ਭੇਜੀ ਜਾ ਚੁੱਕੀ ਹੈ।",
-       "passwordreset-invalideamil": "ਗ਼ਲਤ ਈਮੇਲ ਪਤਾ",
+       "passwordreset-invalidemail": "ਗ਼ਲਤ ਈਮੇਲ ਪਤਾ",
        "changeemail": "ਈ-ਮੇਲ ਸਿਰਨਾਵਾਂ ਬਦਲੋ ਜਾੰ ਹਟਾਓ",
        "changeemail-header": "ਖਾਤੇ ਵਾਲਾ ਈ-ਮੇਲ ਸਿਰਨਾਵਾਂ ਬਦਲੋ",
        "changeemail-no-info": "ਇਸ ਸਫ਼ੇ ਨੂੰ ਸਿੱਧੇ ਹੀ ਵੇਖਣ ਲਈ ਤੁਹਾਨੂੰ ਲਾਗਇਨ ਕਰਨਾ ਪਵੇਗਾ।",
        "activeusers-intro": "ਇਹ ਓਹਨਾਂ ਮੈਂਬਰਾਂ ਦੀ ਲਿਸਟ ਹੈ ਜਿੰਨ੍ਹਾਂ ਨੇ ਆਖ਼ਰੀ $1 {{PLURAL:$1|ਦਿਨ|ਦਿਨਾਂ}} ਵਿਚ ਕਿਸੇ ਤਰ੍ਹਾਂ ਦਾ ਕੋਈ ਕੰਮ ਕੀਤਾ ਹੈ।",
        "activeusers-count": "ਆਖ਼ਰੀ {{PLURAL:$3|ਦਿਨ|$3 ਦਿਨਾਂ}} ਵਿਚ $1 {{PLURAL:$1|ਸੋਧ|ਸੋਧਾਂ}}",
        "activeusers-from": "ਇਸਤੋਂ ਸ਼ੁਰੂ ਹੋਣ ਵਾਲ਼ੇ ਮੈਂਬਰ ਵਖਾਓ:",
-       "activeusers-hidebots": "ਬੌਟਾਂ ਨੂੰ ਲੁਕਾਓ",
-       "activeusers-hidesysops": "ਪ੍ਰਸ਼ਾਸਕ ਲੁਕਾਓ",
        "activeusers-noresult": "ਕੋਈ ਵਰਤੋਂਕਾਰ ਨਹੀਂ ਲੱਭਾ।",
        "activeusers-submit": "ਚਾਲੂ ਵਰਤੋਂਕਾਰ ਦਿਖਾਓ",
        "listgrouprights": "ਵਰਤੋਂਕਾਰ ਸਮੂਹਾਂ ਦੇ ਹੱਕ",
        "feedback-bugnew": "ਮੈਂ ਚੈੱਕ ਕੀਤਾ। ਇੱਕ ਨਵੇਂ ਦੋਸ਼ ਦੀ ਰਿਪੋਰਟ ਕਰੋ",
        "feedback-cancel": "ਰੱਦ ਕਰੋ",
        "feedback-close": "ਹੋ ਗਿਆ",
-       "feedback-error-title": "ਗ਼ਲਤੀ",
        "feedback-error2": "ਦੋਸ਼:ਸੋਧ ਫੇਲ੍ਹ ਹੋਈ",
        "feedback-error3": "ਦੋਸ਼:API ਵੱਲੋਂ ਕੋਈ ਜੁਆਬ ਨਹੀਂ",
        "feedback-message": "ਸੁਨੇਹਾ:",
index a2de392..95af027 100644 (file)
        "yourname": "Lagyung talagamit (Username):",
        "yourpassword": "Kekang password:",
        "yourpasswordagain": "Pakisulat meng pasibayu ing password:",
-       "remembermypassword": "Tandanan me ing login ku king computer a ini (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "Ing kekang karinan (domain):",
        "externaldberror": "Mapalyaring mika pamagkamali king external authentication (pamagpatutung panlual) ning database, o ala kang paintulut a i-update ya ing kekang account a panlual (external account).",
        "login": "Mag log in",
        "undo-failure": "E maliaring iurung ing edit a ini uling e la mipapareu deng minunang me-edit.",
        "undo-norev": "E maliaring iurung ing edit a ini uling ala yu o mebura ya.",
        "undo-summary": "Iurung ya ing miyalilan $1 nang [[Special:Contributions/$2|$2]] ([[User talk:$2|Talk]])",
-       "cantcreateaccounttitle": "E makalalang account",
        "cantcreateaccount-text": "Sebat neng [[User:$3|$3]] ing pamaglalang account manibat kaniting IP address ('''$1''').\n\nIni ing sangkan a binie nang $3: ''$2''",
        "viewpagelogs": "Lon la reng log para king bulung a ini",
        "nohistory": "Alang amlat ning pamag-edit (edit history) para king bulung a ini.",
        "rightsnone": "(ala)",
        "revdelete-summary": "sampulung da reng mibayu (edit summary)",
        "feedback-back": "Mibalik",
-       "feedback-error-title": "Mali",
        "feedback-submit": "I-sumiti",
        "feedback-thanks-title": "Salamat pu!",
        "headline-anchor-title": "Ing suglung king seksyun a ini",
index 4a376c8..d96cf90 100644 (file)
        "yourname": "nom d'uzeu:",
        "yourpassword": "Mot d'passe:",
        "yourpasswordagain": "Intrer à nouvieu ch'mot d'passe:",
-       "remembermypassword": "Intrer oùtonmatiquemint l'prochaine fouos (pour un maximum éd $1 {{PLURAL:$1|jour|jours}})",
        "yourdomainname": "Vote donmène:",
        "login": "Intrer",
        "nav-login-createaccount": "Intrer / créer vote conpte",
index 608b0d1..74d9bb6 100644 (file)
        "linksearch-ok": "Uffgucke",
        "listusers-submit": "Zeig",
        "listusers-noresult": "Ken Yuuser gfunne.",
-       "activeusers-hidebots": "Waddefresser verschwinne losse",
-       "activeusers-hidesysops": "Verwalter verschwinne losse",
        "listgrouprights": "Rechte vun Yuuser-Druppe",
        "listgrouprights-group": "Druppe",
        "listgrouprights-rights": "Rechte",
index 5c0ab95..8722398 100644 (file)
        "yourpasswordagain": "Kennword nomol oigewe:",
        "createacct-yourpasswordagain": "Password bschdedische",
        "createacct-yourpasswordagain-ph": "Bschdedisch doi Password",
-       "remembermypassword": "Moi Kennword uffm Brausa merge (hegschdns fa $1 {{PLURAL:$1|Daach|Daach}})",
        "userlogin-remembermypassword": "Oagmeld blaiwe",
        "login": "Oamelde",
        "nav-login-createaccount": "Oamelde / Kondo oaleesche",
        "post-expand-template-argument-warning": "'''Baßma uff:''' Die Said hodd wenigschdns ä Vorlach midä Kenngreeß, wu groß werre dud. Die Kenngreeß wead do nedd õgeguggd.",
        "post-expand-template-argument-category": "Saide, wu wegfallene Vorlachewead hawen.",
        "undo-nochange": "Die Ännarung isch schunmol rigg'gängisch g'machd worre.",
-       "cantcreateaccounttitle": "Konn kä Kondo mache",
        "viewpagelogs": "Lochbischa fa die Said oagugge",
        "nohistory": "Vunde Said hodds kä Gschischd.",
        "currentrev": "Ledschdi Änarung",
index 75d2b95..4197703 100644 (file)
        "views": "Widok",
        "toolbox": "Narzędzia",
        "tool-link-userrights": "Zmiana grup {{GENDER:$1|użytkownika|użytkowniczki}}",
+       "tool-link-userrights-readonly": "Zobacz grupy {{GENDER:$1|użytkownika|użytkowniczki}}",
        "tool-link-emailuser": "Wyślij e-mail do {{GENDER:$1|tego użytkownika|tej użytkowniczki}}",
        "userpage": "Pokaż stronę użytkownika",
        "projectpage": "Pokaż stronę projektu",
        "passwordreset-emaildisabled": "Wysyłanie emaili zostało wyłączone na tej wiki",
        "passwordreset-username": "Nazwa użytkownika:",
        "passwordreset-domain": "Domena:",
-       "passwordreset-capture": "Czy pokazywać treść wiadomości e‐mail?",
-       "passwordreset-capture-help": "Jeśli zaznaczysz to pole, zobaczysz treść wiadomości e‐mail z tymczasowym hasłem, w tej samej formie w jakiej jest wysyłana do użytkownika.",
        "passwordreset-email": "Adres e‐mail:",
        "passwordreset-emailtitle": "Dane konta w {{GRAMMAR:MS.lp|{{SITENAME}}}}",
        "passwordreset-emailtext-ip": "Ktoś (prawdopodobnie Ty, spod adresu IP $1) poprosił o zresetowanie twojego hasła w {{GRAMMAR:MS.lp{{SITENAME}}}} ($4). Z tym adresem e‐mailowym powiązane {{PLURAL:$3|jest konto użytkownika|są następujące konta użytkowników:}}\n\n$2\n\n{{PLURAL:$3|Tymczasowego hasła|Tymczasowych haseł}} można użyć w ciągu {{PLURAL:$5|jednego dnia|$5 dni}}.\nPowinieneś zalogować się i zmienić hasło na nowe. Jeśli to ktoś inny poprosił o wysłanie przypomnienia lub jeśli pamiętasz aktualne hasło i nie chcesz go zmieniać wystarczy, że zignorujesz tę wiadomość i będziesz nadal korzystać ze swojego starego hasła.",
        "passwordreset-emailelement": "Nazwa użytkownika: \n$1\n\nTymczasowe hasło: \n$2",
        "passwordreset-emailsentemail": "Jeśli ten adres e‐mail jest przypisany do Twojego konta, zostanie na niego wysłany e-mail do odzyskiwania hasła.",
        "passwordreset-emailsentusername": "Jeśli z tym kontem powiązany jest adres e‐mail, zostanie na niego wysłany e-mail do odzyskiwania hasła.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Został wysłany e-mail|Zostały wysłane e-maile}} z informacjami o resetowaniu hasła. {{PLURAL:$1|Użytkownik i hasło jest pokazany|Lista użytkowników i haseł jest pokazana}} tutaj.",
-       "passwordreset-emailerror-capture2": "Wysyłanie e-maila do {{GENDER:$2|użytkownika|użytkowniczki}} nie powiodło się: $1 {{PLURAL:$3|Użytkownik i hasło jest pokazany|Lista użytkowników i haseł jest pokazana}} tutaj.",
        "passwordreset-nocaller": "Musi być podany wywołujący",
        "passwordreset-nosuchcaller": "Wywołujący nie istnieje: $1",
-       "passwordreset-invalideamil": "Nieprawidłowy adres e-mail",
+       "passwordreset-invalidemail": "Nieprawidłowy adres e-mail",
        "passwordreset-nodata": "Nie podano ani nazwy użytkownika, ani adresu e-mail",
        "changeemail": "Zmiana lub usunięcie adresu e‐mail",
        "changeemail-header": "Wypełnij ten formularz, aby zmienić swój adres e-mail. Jeśli chcesz usunąć swój adres e-mail, to przy wypełnianiu formularza pozostaw puste pole nowego adresu e-mail.",
        "search-external": "Wyszukiwanie zewnętrzne",
        "searchdisabled": "Wyszukiwanie w {{GRAMMAR:MS.lp|{{SITENAME}}}} zostało wyłączone.\nW międzyczasie możesz skorzystać z wyszukiwania Google.\nJednak informacje o treści {{GRAMMAR:D.lp|{{SITENAME}}}} mogą być w Google nieaktualne.",
        "search-error": "Wystąpił błąd podczas wyszukiwania: $1",
+       "search-warning": "Podczas wyszukiwania wystąpił błąd: $1",
        "preferences": "Preferencje",
        "mypreferences": "Preferencje",
        "prefs-edits": "Liczba edycji:",
        "prefs-help-recentchangescount": "Uwzględnia ostatnie zmiany, historię stron i rejestry.",
        "prefs-help-watchlist-token2": "To jest tajny klucz umożliwiający dostęp do kanału internetowego zmian w obserwowanych przez ciebie stronach.\nKażdy, kto go zna, będzie mógł je zobaczyć, więc zachowaj go dla siebie.\n[[Special:ResetTokens|Kliknij tu, jeśli chcesz go zresetować]].",
        "savedprefs": "Twoje preferencje zostały zapisane.",
-       "savedrights": "Zapisano uprawnienia {{GENDER:$1|użytkownika $1|użytkowniczki $1}}.",
+       "savedrights": "Zapisano grupy {{GENDER:$1|użytkownika $1|użytkowniczki $1}}.",
        "timezonelegend": "Strefa czasowa:",
        "localtime": "Czas lokalny:",
        "timezoneuseserverdefault": "Użyj domyślnej dla tej wiki ($1)",
        "prefswarning-warning": "Niektóre z dokonanych zmian w preferencjach nie zostały jeszcze zapisane. Jeśli wyjdziesz bez wciśnięcia „$1”, Twoje zmiany zostaną utracone.",
        "prefs-tabs-navigation-hint": "Wskazówka: do poruszania się między zakładkami możesz użyć klawiszy strzałek w lewo i w prawo",
        "userrights": "Zarządzanie uprawnieniami użytkowników",
-       "userrights-lookup-user": "Zarządzaj grupami użytkownika",
+       "userrights-lookup-user": "Wybierz użytkownika",
        "userrights-user-editname": "Wprowadź nazwę użytkownika:",
-       "editusergroup": "Edytuj grupy {{GENDER:$1|użytkownika|użytkowniczki}}",
+       "editusergroup": "Wczytaj grupy użytkownika",
        "editinguser": "Zmiana uprawnień {{GENDER:$1|użytkownika|użytkowniczki}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Edytuj grupy użytkownika",
        "saveusergroups": "Zapisz grupy {{GENDER:$1|użytkownika|użytkowniczki}}",
        "userrights-reason": "Powód:",
        "userrights-no-interwiki": "Nie masz dostępu do edycji uprawnień na innych wiki.",
        "userrights-nodatabase": "Baza danych $1 nie istnieje lub nie jest lokalna.",
-       "userrights-nologin": "Musisz [[Special:UserLogin|zalogować się]] na konto administratora, by nadawać uprawnienia użytkownikom.",
-       "userrights-notallowed": "Nie jesteś upoważniony do nadawania i odbierania uprawnień użytkownikom.",
        "userrights-changeable-col": "Grupy, które możesz wybrać",
        "userrights-unchangeable-col": "Grupy, których nie możesz wybrać",
        "userrights-conflict": "Konflikt zmiany uprawnień użytkownika! Proszę sprawdzić i potwierdzić swoje zmiany.",
-       "userrights-removed-self": "Odebrałeś sobie uprawnienia. W związku z tym nie masz już dostępu do tej strony.",
        "group": "Grupa:",
        "group-user": "Użytkownicy",
        "group-autoconfirmed": "Automatycznie zatwierdzeni użytkownicy",
        "right-siteadmin": "Blokowanie i odblokowywanie bazy danych",
        "right-override-export-depth": "Eksport stron wraz z linkowanymi do głębokości 5 linków",
        "right-sendemail": "Wysyłanie e‐maili do innych użytkowników",
-       "right-passwordreset": "Sprawdzanie treści e‐maila o resetowaniu hasła",
        "right-managechangetags": "Tworzenie i (dez)aktywowanie [[Special:Tags|znaczników]]",
        "right-applychangetags": "Wprowadzanie [[Special:Tags|znaczników]] wraz z własnymi zmianami",
        "right-changetags": "Dodawanie i usuwanie dowolnych [[Special:Tags|znaczników]] z poszczególnych wersji i wpisów w rejestrze",
        "action-userrights-interwiki": "edytowania uprawnień użytkowników na innych witrynach wiki",
        "action-siteadmin": "blokowania i odblokowywania bazy danych",
        "action-sendemail": "wysyłania e-maili",
+       "action-editmyoptions": "edycja swoich preferencji",
        "action-editmywatchlist": "edycji swojej listy obserwowanych stron",
        "action-viewmywatchlist": "zobaczenia swojej listy obserwowanych stron",
        "action-viewmyprivateinfo": "zobaczenia swoich prywatnych danych",
        "apisandbox-alert-field": "Wartość tego pola jest nieprawidłowa.",
        "apisandbox-continue": "Kontynuuj",
        "apisandbox-continue-clear": "Wyczyść",
+       "apisandbox-param-limit": "Wpisz <kbd>max</kbd>, aby wykorzystać maksymalny limit.",
+       "apisandbox-multivalue-all-namespaces": "$1 (wszystkie przestrzenie nazw)",
+       "apisandbox-multivalue-all-values": "$1 (wszystkie wartości)",
        "booksources": "Książki",
        "booksources-search-legend": "Szukaj informacji o książkach",
        "booksources-search": "Szukaj",
        "activeusers": "Lista aktywnych użytkowników",
        "activeusers-intro": "Poniżej znajduje się lista użytkowników, którzy byli aktywni w ciągu {{PLURAL:$1|ostatniego dnia|ostatnich $1 dni}}.",
        "activeusers-count": "w ciągu {{PLURAL:$3|ostatniego dnia|ostatnich $3 dni}} {{GENDER:$2|wykonał|wykonała|wykonał}} $1 {{PLURAL:$1|operację|operacje|operacji}}",
-       "activeusers-from": "Pokaż użytkowników zaczynając od:",
+       "activeusers-from": "Wyświetl użytkowników, zaczynając od:",
        "activeusers-groups": "Wyświetl użytkowników należących do grup:",
+       "activeusers-excludegroups": "Wyklucz użytkowników należących do grup:",
        "activeusers-noresult": "Nie odnaleziono żadnego użytkownika.",
        "activeusers-submit": "Wyświetl aktywnych użytkowników",
        "listgrouprights": "Uprawnienia grup użytkowników",
        "rollbacklinkcount-morethan": "cofnij więcej niż $1 {{PLURAL:$1|edycję|edycje|edycji}}",
        "rollbackfailed": "Nie udało się cofnąć zmiany",
        "rollback-missingparam": "W żądaniu nie podano wymaganych parametrów.",
+       "rollback-missingrevision": "Nie udało się załadować informacji o wersji.",
        "cantrollback": "Nie można cofnąć edycji tego autora, ponieważ jest jedynym autorem tej strony.",
        "alreadyrolled": "Nie można dla strony [[:$1|$1]] cofnąć ostatniej zmiany, którą wykonał [[User:$2|$2]] ([[User talk:$2|dyskusja]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]).\nKtoś inny zdążył już to zrobić lub wprowadził własne poprawki do treści strony.\n\nAutorem ostatniej zmiany jest teraz [[User:$3|$3]] ([[User talk:$3|dyskusja]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Edycję opisał: <em>$1</em>.",
        "changecontentmodel-emptymodels-text": "Zawartość [[:$1]] nie może być przekształcona do żadnego typu.",
        "log-name-contentmodel": "Rejestr zmian modelu zawartości",
        "log-description-contentmodel": "Wydarzenia związane z modelami zawartości stron",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|utworzył|utworzyła}} stronę $3 o niebędącym domyślnym modelu zawartości \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|zmienił|zmieniła|zmienił(a)}} model zawartości strony $3 z „$4” na „$5”",
        "logentry-contentmodel-change-revertlink": "Przywróć",
        "logentry-contentmodel-change-revert": "Przywróć",
        "undeletehistorynoadmin": "Ta strona została usunięta.\nPrzyczyna usunięcia podana jest w podsumowaniu poniżej, razem z danymi użytkownika, który edytował stronę przed usunięciem.\nSama treść usuniętych wersji jest dostępna jedynie dla administratorów.",
        "undelete-revision": "Usunięto wersję $1 (z $5 $4) autorstwa $3:",
        "undeleterevision-missing": "Nieprawidłowa lub brakująca wersja.\nMożesz mieć zły link lub wersja mogła zostać odtworzona lub usunięta z archiwum.",
+       "undeleterevision-duplicate-revid": "{{PLURAL:$1|Jedna wersja|$1 wersji}} nie może zostać przywróconych, ponieważ {{PLURAL:$1|jej|ich}} <code>rev_id</code> jest już w użyciu.",
        "undelete-nodiff": "Nie znaleziono poprzednich wersji.",
        "undeletebtn": "Odtwórz",
        "undeletelink": "pokaż lub odtwórz",
        "movelogpagetext": "Lista stron, które ostatnio zostały przeniesione.",
        "movesubpage": "{{PLURAL:$1|Podstrona|Podstrony}}",
        "movesubpagetext": "Ta strona posiada $1 {{PLURAL:$1|podstronę|podstrony|podstron}}:",
+       "movesubpagetalktext": "Odpowiadająca strona dyskusji ma $1 {{PLURAL:$1|podstronę|podstron}} pokazanych poniżej.",
        "movenosubpage": "Ta strona nie posiada podstron.",
        "movereason": "Powód:",
        "revertmove": "cofnij",
        "allmessages-filter-translate": "Przetłumacz",
        "thumbnail-more": "Powiększ",
        "filemissing": "Brak pliku",
-       "thumbnail_error": "Błąd przy generowaniu miniatury $1",
+       "thumbnail_error": "Błąd przy generowaniu miniatury: $1",
        "thumbnail_error_remote": "Komunikat o błędzie z {{grammar:2sg|$1}}:\n$2",
        "djvu_page_error": "Strona DjVu poza zakresem",
        "djvu_no_xml": "Nie można pobrać danych w formacie XML dla pliku DjVu",
        "pageinfo-watchers": "Liczba obserwujących",
        "pageinfo-visiting-watchers": "Liczba obserwujących stronę, którzy ostatnio ją odwiedzili",
        "pageinfo-few-watchers": "Mniej niż $1 {{PLURAL:$1|obserwujący|obserwujących}}",
+       "pageinfo-few-visiting-watchers": "Może być lub nie użytkownik, który odwiedza ostatnie edycje",
        "pageinfo-redirects-name": "Liczba przekierowań do tej strony",
        "pageinfo-subpages-name": "Liczba podstron tej strony",
        "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|przekierowanie|przekierowania|przekierowań}}; $3 {{PLURAL:$3|bez przekierowania|bez przekierowań|bez przekierowań}})",
        "confirmemail_body_set": "Ktoś łącząc się z komputera o adresie IP $1\nustawił w {{GRAMMAR:MS.lp|{{SITENAME}}}} dla konta „$2” adres e‐mail na ten właśnie.\n\nAby potwierdzić, że to Ty {{GENDER:|ustawiłeś|ustawiłaś}} adres otwórz w swojej\nprzeglądarce ten link:\n\n$3\n\nJeśli *nie* jest to Twoje konto, otwórz w swojej przeglądarce\nponiższy link, aby anulować potwierdzenie adresu e‐mail:\n\n$5\n\nKod zawarty w linku straci ważność $4.",
        "confirmemail_invalidated": "Potwierdzenie adresu e‐mail zostało anulowane",
        "invalidateemail": "Anulowanie potwierdzenia adresu e‐mail",
+       "notificationemail_subject_changed": "Został zmieniony zarejestrowany adres e-mail na {{SITENAME}}",
        "scarytranscludedisabled": "[Transkluzja przez interwiki jest wyłączona]",
        "scarytranscludefailed": "[Pobranie szablonu dla $1 nie powiodło się]",
        "scarytranscludefailed-httpstatus": "[Pobranie szablonu dla $1 nie powiodło się: HTTP $2]",
        "tags-deactivate": "dezaktywuj",
        "tags-hitcount": "$1 {{PLURAL:$1|zmiana|zmiany|zmian}}",
        "tags-manage-no-permission": "Nie masz uprawnień do zarządzania znacznikami.",
-       "tags-manage-blocked": "Nie możesz zarządzać znacznikami zmian, kiedy jesteś zablokowany.",
+       "tags-manage-blocked": "Nie możesz zarządzać znacznikami zmian, gdy jesteś {{GENDER:$1|zablokowany|zablokowana}}.",
        "tags-create-heading": "Utwórz nowy znacznik",
        "tags-create-explanation": "Nowe znaczniki będą dostępne domyślnie dla użytkowników i botów.",
        "tags-create-tag-name": "Nazwa znacznika:",
        "tags-deactivate-not-allowed": "Nie można dezaktywować znacznika „$1”.",
        "tags-deactivate-submit": "Dezaktywuj",
        "tags-apply-no-permission": "Nie masz uprawnień do wprowadzania znaczników wraz z własnymi zmianami.",
-       "tags-apply-blocked": "Nie możesz stosować znaczników do swoich zmian, gdy jesteś zablokowany.",
+       "tags-apply-blocked": "Nie możesz stosować znaczników do swoich zmian, gdy jesteś {{GENDER:$1|zablokowany|zablokowana}}.",
        "tags-apply-not-allowed-one": "Znacznik „$1” nie może zostać wprowadzony ręcznie.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Następujący znacznik nie może zostać wprowadzony ręcznie|Następujące znaczniki nie mogą zostać wprowadzone ręcznie}}: $1",
        "tags-update-no-permission": "Nie masz uprawnień do dodawania lub usuwania znaczników z poszczególnych wersji lub wpisów w rejestrze.",
-       "tags-update-blocked": "Nie możesz dodawać i usuwać znaczników zmian, kiedy jesteś zablokowany.",
+       "tags-update-blocked": "Nie możesz dodawać i usuwać znaczników zmian, gdy jesteś {{GENDER:$1|zablokowany|zablokowana}}.",
        "tags-update-add-not-allowed-one": "Znacznik „$1” nie może zostać dodany ręcznie.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Następujący znacznik nie może zostać dodany ręcznie|Następujące znaczniki nie mogą zostać dodane ręcznie}}: $1",
        "tags-update-remove-not-allowed-one": "Znacznika „$1” nie można usunąć.",
        "htmlform-user-not-exists": "<strong>$1</strong> nie istnieje.",
        "htmlform-user-not-valid": "<strong>$1</strong> nie jest prawidłową nazwą użytkownika.",
        "logentry-delete-delete": "$1 {{GENDER:$2|usunął|usunęła}} stronę $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|usunął|usunęła}} przekierowanie $3 poprzez nadpisanie",
        "logentry-delete-restore": "$1 {{GENDER:$2|odtworzył|odtworzyła}} stronę $3",
        "logentry-delete-event": "$1 {{GENDER:$2|zmienił|zmieniła}} widoczność {{PLURAL:$5|zdarzenia|$5 zdarzeń}} w rejestrze $3, wykonano następujące operacje: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|zmienił|zmieniła}} widoczność {{PLURAL:$5|wersji|$5 wersji}} strony $3, wykonano następujące operacje: $4",
        "mw-widgets-dateinput-no-date": "Nie wybrano daty",
        "mw-widgets-dateinput-placeholder-day": "RRRR-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "RRRR-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Szukaj multimediów",
+       "mw-widgets-mediasearch-noresults": "Nie znaleziono wyników.",
        "mw-widgets-titleinput-description-new-page": "strona jeszcze nie istnieje",
        "mw-widgets-titleinput-description-redirect": "przekierowanie do $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Dodaj kategorię...",
        "sessionmanager-tie": "Nie można łączyć kilku rodzajów uwierzytelniania dla zapytania: $1.",
        "sessionprovider-generic": "sesje $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sesje na podstawie cookie",
        "usercssispublic": "Uwaga: Podstrony z kodem CSS są widoczne publicznie i nie powinny zawierać poufnych danych.",
        "restrictionsfield-badip": "Nieprawidłowy adres IP lub zakres adresów: $1",
        "restrictionsfield-label": "Dozwolone zakresy adresów IP:",
-       "restrictionsfield-help": "Jeden adres IP lub zakres CIDR w wierszu. Aby zaznaczyć wszystkie, użyj<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Błąd: $1",
-       "edit-error-long": "Błędy:\n\n$1"
+       "restrictionsfield-help": "Jeden adres IP lub zakres CIDR w wierszu. Aby zaznaczyć wszystkie, użyj<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index e0b4667..fe7db17 100644 (file)
        "yourpasswordagain": "Che a bata torna soa ciav:",
        "createacct-yourpasswordagain": "Ch'a confirma la ciav",
        "createacct-yourpasswordagain-ph": "Ch'a buta torna la ciav",
-       "remembermypassword": "Visesse ëd mia ciav ansima a 's navigador (për al pi $1 {{PLURAL:$1|di}})",
        "userlogin-remembermypassword": "Ten-me andrinta al sistema",
        "userlogin-signwithsecure": "Dovré na conession sigura",
        "yourdomainname": "Sò domini:",
        "activeusers-intro": "Costa a l'é na lista d'utent ch'a l'han avù n'atività qualsëssìa ant j'ùltim $1 {{PLURAL:$1|di|di}}.",
        "activeusers-count": "$1 {{PLURAL:$1|assion}} ant {{PLURAL:$3|l'ùltim di|j'ùltim $3 di}}",
        "activeusers-from": "Smon-me j'utent a parte da:",
-       "activeusers-hidebots": "Stërmé ij trigomiro",
-       "activeusers-hidesysops": "Stërmé j'aministrator",
        "activeusers-noresult": "Pa gnun utent trovà.",
        "listgrouprights": "Drit dël grup d'utent",
        "listgrouprights-summary": "Ambelessì a-i é na lista dle partìe d'utent definìe ansima a costa wiki, con ij sò drit d'acess associà.\nA peulo ess-ie d'[[{{MediaWiki:Listgrouprights-helppage}}|anformassion adissionaj]] ansima a dij drit individuaj.",
        "htmlform-cloner-create": "Gionté 'd pi",
        "htmlform-cloner-delete": "Gavé",
        "htmlform-cloner-required": "A-i é damanca d'almanch un valor.",
-       "sqlite-has-fts": "$1 con arserca an test pien mantnùa",
-       "sqlite-no-fts": "$1 sensa arserca an test pien mantnùa",
        "logentry-delete-delete": "$1 a l'ha {{GENDER:$2|scancelà}} la pàgina $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|a l'ha ripristinà}} la pàgina $3",
        "logentry-delete-event": "$1 {{GENDER:$2|a l'ha modificà}} la visibilità ëd {{PLURAL:$5|n'event dël registr|$5 event dël registr}} dzora $3: $4",
        "feedback-external-bug-report-button": "Presenta un travaj tècnich",
        "feedback-dialog-title": "Spedì ij coment",
        "feedback-dialog-intro": "A peul dovré ël formolari sempi sì-sota për spedì ij sò coment. Ij sò coment a saran giontà a la pàgina «$1», ansema a sò stranòm.",
-       "feedback-error-title": "Eror",
        "feedback-error1": "Eror: Arzultà ëd l'API nen arconossù",
        "feedback-error2": "Eror: Modìfica falìa",
        "feedback-error3": "Eror: gnun-e rispòste da l'API",
index 15b5bee..33d0afe 100644 (file)
        "activeusers-intro": "اے اوناں ورتن والیاں دی لسٹ اے جنان پچھلے $1 {{PLURAL:$1|دن|دناں}} چ کم کیتا اے۔",
        "activeusers-count": "$1 {{PLURAL:$1|تبدیلی|تبدیلیاں}} پچھلے{{PLURAL:$3|دن|$3 دن}} چ",
        "activeusers-from": "ورتن والے ایس توں شروع ہون والے دسو:",
-       "activeusers-hidebots": "بوٹ چھپاؤ",
-       "activeusers-hidesysops": "مکھۓ لکاؤ",
        "activeusers-noresult": "کوئی ورتن والا نئیں لبیا۔",
        "listgrouprights": "ورتن ٹرلی حق",
        "listgrouprights-summary": "تھلے اک لسٹ اے ورتن ٹولیاں دی ای وکی تے، اپنے رلدے حقاں نال۔ \n\nہربندے دے ح‍ق‍اں [[{{MediaWiki:Listgrouprights-helppage}}|ہور جانکاری]]",
index 16f214a..fbb364b 100644 (file)
        "yourname": "Όνεμαν χρήστε:",
        "yourpassword": "Σημάδι:",
        "yourpasswordagain": "Ξαν' γράψτεν το σημάδι:",
-       "remembermypassword": "Αποθήκεμαν τη σημαδίμ σ' αβούτον τον υπολογιστήν (για μέγιστον $1 {{PLURAL:$1|ημέραν|ημέρας}})",
        "yourdomainname": "Το domain εσούν:",
        "login": "Εμπάτε",
        "nav-login-createaccount": "Εμπάτεν / ποισέστεν λογαρίαν",
        "permissionserrorstext-withaction": "'Κ έχετε την άδειαν για $2, για {{PLURAL:$1|τ'αφκά το λόγον|τ'αφκά τοι λόγους}}:",
        "recreate-moveddeleted-warn": "'''Ωρία: Εφτάτε αξάν μίαν σελίδαν ντ' ενεσβύεν οψεκές.'''\n\nΊσως εν καλλίον να μην εφτάτε τη σελίδαν.\nΤερέστεν για βοήθειαν σ' αρχείον σβησεματίων και ετεροχλαεματίων για την αιτίαν για το σβήσιμον:",
        "moveddeleted-notice": "Αούτο η σελίδαν εβζινέθεν.\nΑφκά ευρίεται έναν γράψιμον ασο αρχείον σβησεματίων και ετεροχλαεματίων τη σελίδας.",
-       "cantcreateaccounttitle": "Το ποίσιμον τη λογαρίας 'κ έντον",
        "viewpagelogs": "Τέρεν αρχεία γι' αβούτεν τη σελίδαν",
        "nohistory": "Αούτο η σελίδαν αλλαγάς 'κ εςς.",
        "currentrev": "Ατωριζνόν μορφήν",
index f4424e0..010c8f6 100644 (file)
        "yourname": "Twajā tērpautajas pabilisnā:",
        "yourpassword": "Twājs kliptaswīrds:",
        "yourpasswordagain": "Āntrinais kliptaswīrdan",
-       "remembermypassword": "Pamēnais majjans enēisnas infōrmaciōnins en šismu kōmputerin (per maksimum of $1 {{PLURAL:$1|deinā|dēinans}})",
        "yourdomainname": "Twajā dōmeni:",
        "externaldberror": "Tikka izwinaīnas autentikāntin dātanbazin blānda, anga ni assei enwarīntan kāi etnaunīnlai twajjan izwinaīnan rekkenan.",
        "login": "Enjaīs",
        "undo-failure": "Ni mazīngi etwārtai wartīntun redigīsenin, kōnfliktas sen persirzdausnas wersiōnins paggan.",
        "undo-norev": "Redigīsenis ni mazzi būtwei etwārtai wartīntan, beggi ni ekzistijja anga pastāi āupausintan.",
        "undo-summary": "Etwārtai wartīnsna stēisan wersiōnin $1 teīktan pra [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusiōni]])",
-       "cantcreateaccounttitle": "Ni mazīngi teīktun rekkenan",
        "cantcreateaccount-text": "Rekkenas teīksenis iz šan IP adressin (\"$1\") pastāi drēuditan pra [[User:$3|$3]].\n\nBrewīnsli dātan pra $3 ast \"$2\"",
        "viewpagelogs": "Wīdais šisse pāusas regīsterins",
        "nohistory": "Ni ast redigīsnas istōrija per šin pāusan.",
        "activeusers": "Aktīwan tērpautajan listi",
        "activeusers-count": "$1 {{PLURAL:$1|redigīsenis|redigīsenei}} en {{PLURAL:$3|panzdauman dēinan|$3 panzdaumans dēinans}}",
        "activeusers-from": "Waidinnais tērpautajans pagaūnintins sen:",
-       "activeusers-hidebots": "Kliptinais bōtans",
-       "activeusers-hidesysops": "Kliptinais perwaldītajans",
        "activeusers-noresult": "Ni aupalā di tērpautajans",
        "listgrouprights": "Tērpautajan gruppin enwarīnsenei",
        "listgrouprights-summary": "Zemmais ast listi stēisan tērpautajan gruppin definītan en šissei wiki sen enwarīnsenins preipeisātan tenēimans.\nIzbandais pāausan sen [[{{MediaWiki:Listgrouprights-helppage}}|papilniminans infōrmaciōnins]] ezze enwarīnsenins.",
index c7c6ac6..c23e1c5 100644 (file)
        "passwordreset-emailtitle": "د {{SITENAME}} د گڼون څرگندنې",
        "passwordreset-emailelement": "کارن-نوم: \n$1\n\nلنډمهاله پټنوم: \n$2",
        "passwordreset-emailsentemail": "د پټنوم بيا پرځای کېدنې لپاره برېښليک درولېږل شو.",
-       "passwordreset-invalideamil": "ناسمه برېښليک پته",
+       "passwordreset-invalidemail": "ناسمه برېښليک پته",
        "changeemail": "برېښليک پته بدلول يا ليرې کول",
        "changeemail-header": "د گڼون برېښليک پته بدلول",
        "changeemail-no-info": "دې مخ ته د لاسرسي لپاره بايد غونډال کې ورننوځۍ.",
        "activeusers-intro": "دا د هغو کارنانو لړليک دی چې په {{PLURAL:$1|تېرې|تېرو}} $1 {{PLURAL:$1|ورځ|ورځو}} کې يې ونډې ترسره کړي.",
        "activeusers-count": "په {{PLURAL:$3|تېرې ورځ|تېرو $3 ورځو}} کې $1 {{PLURAL:$1|سمون|سمونونه}}",
        "activeusers-from": "هغه کارنان کتل چې نومونه يې پېلېږي په:",
-       "activeusers-hidebots": "روباټونه پټول",
-       "activeusers-hidesysops": "پازوالان پټول",
        "activeusers-noresult": "کارن و نه موندل شو.",
        "activeusers-submit": "فعاله کارنان ښکاره کول",
        "listgrouprights": "د کارن ډلو رښتې",
        "feedback-cancel": "ناگارل",
        "feedback-close": "ترسره شو",
        "feedback-external-bug-report-button": "د يوې تخنيکي دندې دوتنه جوړونه",
-       "feedback-error-title": "تېروتنه",
        "feedback-message": "پيغام:",
        "feedback-subject": "سکالو:",
        "feedback-submit": "سپارل",
index 92033df..368907c 100644 (file)
                        "Cristofer Alves",
                        "Tark",
                        "O Andarilho",
-                       "Bruno.S.Alves 270"
+                       "Bruno.S.Alves 270",
+                       "!Silent"
                ]
        },
        "tog-underline": "Sublinhar links:",
        "passwordreset-emaildisabled": "Os recursos de e-mail foram desativados nesta wiki.",
        "passwordreset-username": "Nome de usuário:",
        "passwordreset-domain": "Domínio:",
-       "passwordreset-capture": "Ver o e-mail resultante?",
-       "passwordreset-capture-help": "Se marcar esta caixa, o e-mail (com a senha temporária) será-lhe mostrado, além de ser enviado para o usuário.",
        "passwordreset-email": "Endereço de e-mail:",
        "passwordreset-emailtitle": "Detalhes da conta em {{SITENAME}}",
        "passwordreset-emailtext-ip": "Alguém (provavelmente você, a partir do endereço IP $1)\nsolicitou um lembrete dos seus detalhes de conta para {{SITENAME}} ($4).\n{{PLURAL:$3|A seguinte conta está associada|As seguintes contas estão associadas}} a este e-mail:\n\n$2\n\n{{PLURAL:$3|Esta senha temporária vai|Essas senhas temporárias vão}} expirar em {{PLURAL:$5|um dia|$5 dias}}.\nVocê deve efetuar login e escolher uma nova senha agora.\nSe você conseguir lembrar da senha, ignore este e-mail e continue\nusando sua senha anterior. Caso contrário, prossiga com as instruções\ndisponíveis no link.",
        "passwordreset-emailelement": "Usuário: \n$1\n\nSenha temporária: \n$2",
        "passwordreset-emailsentemail": "Se este é um endereço de e-mail registrado para a sua conta, em seguida, um e-mail de redefinição de senha será enviada.",
        "passwordreset-emailsentusername": "Se houver um endereço de email associado a esta conta, ser-lhe-á enviada uma mensagem para redefinir a sua senha.",
-       "passwordreset-emailsent-capture2": "A redefinição da senha {{PLURAL:$1|do e-mail|dos e-mails}} foi enviada. {{PLURAL:$1|O nome de usuário e senha|A lista de nomes de usuário e senhas}} encontram-se a seguir.",
-       "passwordreset-emailerror-capture2": "O envio do e-mail {{GENDER:$2|usuário}} falhou: $1 Os {{PLURAL:$3|nome de usuário e senha|lista de nomes de usuários e senhas}} são mostrados abaixo.",
        "passwordreset-nocaller": "Um interlocutor deve ser fornecido",
        "passwordreset-nosuchcaller": "O interlocutor não existe: $1",
        "passwordreset-ignored": "A redefinição da senha não foi realizada. Talvez o provedor não tenha sido configurado?",
-       "passwordreset-invalideamil": "Endereço de e-mail inválido",
+       "passwordreset-invalidemail": "Endereço de e-mail inválido",
        "passwordreset-nodata": "Não foram fornecidos nome de usuário nem endereço de e-mail",
        "changeemail": "Alterar ou remover endereço de email",
        "changeemail-header": "Preencha este formulário para alterar seu endereço de e-mail. Se você gostaria de remover a associação de qualquer endereço de e-mail da sua conta, deixe o novo endereço de email em branco quando enviar o formulário.",
        "userrights-reason": "Motivo:",
        "userrights-no-interwiki": "Você não tem permissão para alterar privilégios de usuários em outros wikis.",
        "userrights-nodatabase": "O banco de dados $1 não existe ou não é um banco de dados local.",
-       "userrights-nologin": "Você precisa [[Special:UserLogin|autenticar-se]] como um administrador para especificar os privilégios de usuário.",
-       "userrights-notallowed": "Você não tem permissão para adicionar ou remover privilégios a usuários.",
        "userrights-changeable-col": "Grupos que pode alterar",
        "userrights-unchangeable-col": "Grupos que não pode alterar",
        "userrights-conflict": "Há um comflito de permissões de usuário! Por favor, revise e confirme as alterações novamente.",
-       "userrights-removed-self": "Você removeu seus privilégios. Portanto, você agora não pode mais acessar esta página.",
        "group": "Grupo:",
        "group-user": "Usuários",
        "group-autoconfirmed": "Usuários autoconfirmados",
        "right-siteadmin": "Bloquear e desbloquear o banco de dados",
        "right-override-export-depth": "Exportar páginas incluindo páginas ligadas até uma profundidade de 5",
        "right-sendemail": "Enviar email a outros usuários",
-       "right-passwordreset": "Ver todos os e-mails de reposição de senhas",
        "right-managechangetags": "Criar e (des)ativar [[Special:Tags|tags]]",
        "right-applychangetags": "Aplicar [[Special:Tags|etiquetas]] juntamente com as alterações de alguém",
        "right-changetags": "Adicionar e remover [[Special:Tags|etiquetas]] arbitrárias em revisões e ''logs'' individuais",
        "feedback-thanks": "Obrigado! O seu comentário foi adicionado à página \"[$2 $1]\".",
        "feedback-thanks-title": "Obrigado!",
        "feedback-useragent": "Agente de usuário:",
-       "searchsuggest-search": "Pesquisa",
+       "searchsuggest-search": "Pesquisar em {{SITENAME}}",
        "searchsuggest-containing": "páginas contendo…",
        "api-error-badaccess-groups": "Você não tem permissão para enviar arquivos para este wiki.",
        "api-error-badtoken": "Erro interno: token inválido.",
index 276d93e..72d119e 100644 (file)
@@ -72,7 +72,8 @@
                        "Luan",
                        "Gato Preto",
                        "Jdforrester",
-                       "Mansil"
+                       "Mansil",
+                       "Ngl2016"
                ]
        },
        "tog-underline": "Sublinhar ligações:",
        "navigation-heading": "Menu de navegação",
        "errorpagetitle": "Erro",
        "returnto": "Voltar para $1.",
-       "tagline": "De {{SITENAME}}",
+       "tagline": "Da wiki {{SITENAME}}",
        "help": "Ajuda",
        "search": "Pesquisa",
        "search-ignored-headings": " #<!-- deixe esta linha exatamente como ela está --> <pre>\n# Títulos de página que serão ignorados pela pesquisa.\n# Mudanças a esta lista terão efeito quando a página com o título referido for indexada.\n# Pode forçar a indexação de uma página realizando uma edição nula nessa página.\n# A sintaxe é a seguinte:\n#  * Tudo desde um símbolo de cardinal (#) até ao fim da linha é um comentário\n#  * Cada linha não vazia é o título exato a ignorar, respeitando o uso de maiúsculas\nReferências\nLinks externos\nVer também\n #</pre> <!-- deixe esta linha exatamente como ela está -->",
        "views": "Vistas",
        "toolbox": "Ferramentas",
        "tool-link-userrights": "Alterar grupos {{GENDER:$1|do utilizador|da utilizadora}}",
+       "tool-link-userrights-readonly": "Ver grupos {{GENDER:$1|do utilizador|da utilizadora}}",
        "tool-link-emailuser": "Enviar correio eletrónico a {{GENDER:$1|este utilizador|esta utilizadora|este(a) utilizador(a)}}",
        "userpage": "Ver página de utilizador",
        "projectpage": "Ver página de projeto",
        "pool-errorunknown": "Erro desconhecido",
        "pool-servererror": "O serviço ''pool counter'' não está disponível ($1).",
        "poolcounter-usage-error": "Erro de uso: $1",
-       "aboutsite": "Sobre a {{SITENAME}}",
+       "aboutsite": "Sobre a wiki {{SITENAME}}",
        "aboutpage": "Project:Sobre",
        "copyright": "Conteúdo disponibilizado nos termos da $1, salvo indicação em contrário.",
        "copyrightpage": "{{ns:project}}:Direitos_de_autor",
        "nstab-category": "Categoria",
        "mainpage-nstab": "Página principal",
        "nosuchaction": "Operação não existe",
-       "nosuchactiontext": "A operação especificada pelo URL é inválida.\nÉ possível que tenha escrito mal o URL ou seguido uma ligação incorreta.\nIsto pode também indicar um defeito no software da {{SITENAME}}.",
+       "nosuchactiontext": "A operação especificada pelo URL é inválida.\nÉ possível que tenha escrito mal o URL ou seguido uma ligação incorreta.\nIsto pode também indicar um defeito no software da wiki {{SITENAME}}.",
        "nosuchspecialpage": "Esta página especial não existe",
        "nospecialpagetext": "<strong>Solicitou uma página especial inválida.</strong>\n\nEncontra uma lista das páginas especiais válidas em [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Erro",
        "invalidtitle-unknownnamespace": "Título inválido com número de domínio $1 desconhecido e texto \"$2\"",
        "exception-nologin": "Não está autenticado",
        "exception-nologin-text": "Por favor, inicie sessão para poder aceder a esta página ou ação.",
-       "exception-nologin-text-manual": "Por favor $1, para poder aceder a esta página ou acção.",
+       "exception-nologin-text-manual": "Por favor $1, para poder aceder a esta página ou ação.",
        "virus-badscanner": "Má configuração: antivírus desconhecido: ''$1''",
        "virus-scanfailed": "a verificação falhou (código $1)",
        "virus-unknownscanner": "antivírus desconhecido:",
        "cannotlogoutnow-title": "Não é possível encerrar a sessão agora",
        "cannotlogoutnow-text": "Não pode encerrar a sessão quando utilizar $1.",
        "welcomeuser": "Bem-vindo, $1!",
-       "welcomecreation-msg": "A sua conta foi criada.\nNão se esqueça de personalizar as suas [[Special:Preferences|preferências]].",
+       "welcomecreation-msg": "A sua conta foi criada.\nNão se esqueça de personalizar as suas [[Special:Preferences|preferências]] na wiki {{SITENAME}}.",
        "yourname": "Nome de utilizador(a):",
        "userlogin-yourname": "Nome de utilizador(a)",
        "userlogin-yourname-ph": "Digite o seu nome de utilizador(a)",
        "createacct-another-submit": "Criar conta",
        "createacct-continue-submit": "Continuar criação de conta",
        "createacct-another-continue-submit": "Continuar criação de conta",
-       "createacct-benefit-heading": "{{SITENAME}} é feito por pessoas como você.",
+       "createacct-benefit-heading": "A wiki {{SITENAME}} é feita por pessoas como você.",
        "createacct-benefit-body1": "{{PLURAL:$1|edição|edições}}",
        "createacct-benefit-body2": "{{PLURAL:$1|página|páginas}}",
        "createacct-benefit-body3": "{{PLURAL:$1|contribuidor|contribuidores}} recentes",
        "loginerror": "Erro ao iniciar sessão",
        "createacct-error": "Erro na criação da conta",
        "createaccounterror": "Não foi possível criar a conta: $1",
-       "nocookiesnew": "A conta de utilizador foi criada, mas neste momento não tem sessão iniciada.\nA {{SITENAME}} utiliza ''cookies'' para autenticar os utilizadores.\nOs ''cookies'' estão desativados no seu navegador.\nAtive-os e inicie sessão com o seu nome de utilizador e a sua palavra-passe, por favor.",
-       "nocookieslogin": "A {{SITENAME}} utiliza ''cookies'' para autenticar os utilizadores.\nOs ''cookies'' estão desativados no seu navegador.\nAtive-os e tente novamente, por favor.",
+       "nocookiesnew": "A conta de utilizador foi criada, mas neste momento não tem sessão iniciada.\nA wiki {{SITENAME}} utiliza ''cookies'' para autenticar os utilizadores.\nOs ''cookies'' estão desativados no seu navegador.\nAtive-os e inicie sessão com o seu nome de utilizador e a sua palavra-passe, por favor.",
+       "nocookieslogin": "A wiki {{SITENAME}} utiliza ''cookies'' para autenticar os utilizadores.\nOs ''cookies'' estão desativados no seu navegador.\nAtive-os e tente novamente, por favor.",
        "nocookiesfornew": "A conta de utilizador não foi criada, porque não foi possível confirmar a sua origem.\nCertifique-se de que tem os ''cookies'' ativados, recarregue esta página e tente novamente.",
        "createacct-loginerror": "A conta foi criada, mas não foi possível iniciar a sessão automaticamente. Por favor, [[Special:UserLogin|inície a sessão manualmente]].",
        "noname": "Não especificou um nome de utilizador válido.",
        "loginsuccesstitle": "Autenticação bem sucedida",
-       "loginsuccess": "'''Encontra-se agora ligado à {{SITENAME}} como \"$1\"'''.",
+       "loginsuccess": "<strong>Encontra-se agora ligado à wiki {{SITENAME}} como \"$1\".</strong>",
        "nosuchuser": "Não existe nenhum utilizador com o nome \"$1\".\nOs nomes de utilizador são sensíveis às letras maiúsculas e minúsculas.\nVerifique a ortografia, ou [[Special:CreateAccount|crie uma nova conta]].",
        "nosuchusershort": "Não existe um utilizador com o nome \"$1\". Verifique o nome que introduziu.",
        "nouserspecified": "Precisa de especificar um nome de utilizador.",
        "password-name-match": "A sua palavra-passe tem de ser diferente do seu nome de utilizador.",
        "password-login-forbidden": "Foi proibido o uso deste nome de utilizador e palavra-passe.",
        "mailmypassword": "Reiniciar a palavra-passe",
-       "passwordremindertitle": "Nova palavra-passe temporária na {{SITENAME}}",
-       "passwordremindertext": "Alguém (provavelmente você, a partir do endereço IP $1) solicitou uma palavra-passe nova para a sua conta na {{SITENAME}} ($4).\nFoi criada a palavra-passe temporária \"$3\" para o utilizador \"$2\".\nSe o pedido foi feito por si, entre agora na sua conta e escolha uma palavra-passe nova.\nA palavra-passe temporária expira após {{PLURAL:$5|um dia|$5 dias}}.\n\nCaso outra pessoa tenha feito o pedido, ou se entretanto se recordou da sua palavra-passe e já não deseja alterá-la, ignore esta mensagem e continue a utilizar a palavra-passe antiga.",
+       "passwordremindertitle": "Nova palavra-passe temporária na wiki {{SITENAME}}",
+       "passwordremindertext": "Alguém (provavelmente você, a partir do endereço IP $1) solicitou uma palavra-passe nova para a sua conta na wiki {{SITENAME}} ($4).\nFoi criada a palavra-passe temporária \"$3\" para o utilizador \"$2\".\nSe o pedido foi feito por si, entre agora na sua conta e escolha uma palavra-passe nova.\nA palavra-passe temporária expira após {{PLURAL:$5|um dia|$5 dias}}.\n\nCaso outra pessoa tenha feito o pedido, ou se entretanto se recordou da sua palavra-passe e já não deseja alterá-la, ignore esta mensagem e continue a utilizar a palavra-passe antiga.",
        "noemail": "Não foi registado um endereço de correio eletrónico para o utilizador \"$1\".",
        "noemailcreate": "Tem de fornecer um endereço de correio eletrónico válido.",
        "passwordsent": "Foi enviada uma palavra-passe nova para o endereço de correio eletrónico do utilizador \"$1\".\nVolte a iniciar sessão após recebê-la, por favor.",
        "emaildisabled": "Este sítio não consegue enviar mensagens de correio eletrónico.",
        "accountcreated": "Conta criada",
        "accountcreatedtext": "A conta de utilizador para [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) foi criada.",
-       "createaccount-title": "Criação de conta na {{SITENAME}}",
+       "createaccount-title": "Criação de conta na wiki {{SITENAME}}",
        "createaccount-text": "Alguém criou uma conta com o nome $2 para o seu endereço de correio eletrónico, na wiki {{SITENAME}} ($4), com a palavra-passe \"$3\".\nDeve agora iniciar sessão e alterar a sua palavra-passe.\n\nSe a conta foi criada por engano, pode ignorar esta mensagem.",
        "login-throttled": "Realizou demasiadas tentativas de início de sessão com esta conta.\nAguarde $1 antes de tentar novamente, por favor.",
        "login-abort-generic": "O início de sessão falhou - Cancelado",
        "changepassword-throttled": "Realizou demasiadas tentativas de início de sessão com esta conta.\nAguarde $1 antes de tentar novamente, por favor.",
        "botpasswords": "Palavras-passe de robô",
        "botpasswords-summary": "As <em>palavras-passe de robô</em> permitem o acesso a uma conta de utilizador através da API, sem utilizar as credenciais principais de autenticação dessa conta. Os direitos de um utilizador, ao iniciar uma sessão com a palavra-passe de robô, podem estar limitados.\n\nSe não sabe para que necessita desta palavra-passe provavelmente não deveria criá-la. Nunca lhe deve ser solicitado que gere e entregue uma destas palavras-passe.",
-       "botpasswords-disabled": "As palavras-passe de robô estão desactivadas.",
+       "botpasswords-disabled": "As palavras-passe de robô estão desativadas.",
        "botpasswords-no-central-id": "Para utilizar palavras-passe de robô, deve iniciar sessão com uma conta centralizada.",
        "botpasswords-existing": "Palavras-passe de robô existentes",
        "botpasswords-createnew": "Criar uma nova palavra-passe para robô",
        "botpasswords-insert-failed": "Falhou ao adicionar o nome do robô \"$1\". Já foi adicionado?",
        "botpasswords-update-failed": "Falha ao atualizar o nome do robô \"$1\". Será que foi eliminado?",
        "botpasswords-created-title": "Criada palavra-passe para o robô",
-       "botpasswords-created-body": "A palavra-passe de robô para o robô \"$1\" do utilizador \"$2\" foi criada.",
+       "botpasswords-created-body": "A palavra-passe de robô, para o nome de robô \"$1\" do utilizador \"$2\" foi criada.",
        "botpasswords-updated-title": "A palavra-passe de robô foi atualizada.",
-       "botpasswords-updated-body": "O robô palavra-passe para o nome do robô \"$1\" do utilizador \"$2\" foi atualizado.",
+       "botpasswords-updated-body": "A palavra-passe de robô, para o nome de robô \"$1\" do utilizador \"$2\" foi atualizada.",
        "botpasswords-deleted-title": "Palavra-passe de robô eliminada",
-       "botpasswords-deleted-body": "O robô palavra-passe para o nome do robô \"$1\"do utilizador \"$2\" foi eliminado.",
+       "botpasswords-deleted-body": "A palavra-passe de robô, para o nome de robô \"$1\" do utilizador \"$2\" foi eliminada.",
        "botpasswords-newpassword": "A nova palavra-passe para iniciar sessão com <strong>$1</strong> é <strong>$2</strong>. <em>Anote-a para referência futura, por favor.</em> <br> (Para robôs antigos cujo nome de acesso tenha de ser igual ao eventual nome de utilizador, também pode usar o nome de utilizador <strong>$3</strong> e a palavra-passe <strong>$4</strong>.)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider não está disponível.",
        "botpasswords-restriction-failed": "Restrições de palavra-passe de robô evitam esta autenticação.",
        "passwordreset-emaildisabled": "A funcionalidade de correio eletrónico foi desativada nesta wiki.",
        "passwordreset-username": "Nome de utilizador(a):",
        "passwordreset-domain": "Domínio:",
-       "passwordreset-capture": "Ver a mensagem resultante?",
-       "passwordreset-capture-help": "Se marcar esta caixa, a mensagem (com a palavra-passe temporária) ser-lhe-á mostrada e enviada ao utilizador.",
        "passwordreset-email": "Correio eletrónico:",
-       "passwordreset-emailtitle": "Detalhes da conta na {{SITENAME}}",
-       "passwordreset-emailtext-ip": "Alguém (provavelmente você, a partir do endereço IP $1) pediu a recuperação da palavra-passe no projeto {{SITENAME}} ($4). {{PLURAL:$3|A seguinte conta de utilizador está associada|As seguintes contas de utilizador estão associadas}} a este correio eletrónico:\n\n$2\n\n{{PLURAL:$3|Esta palavra-passe temporária irá|Estas palavras-passes temporárias irão}} expirar dentro de {{PLURAL:$5|um dia|$5 dias}}.\nDeve autenticar-se e escolher uma palavra-passe nova agora. Se outra pessoa fez este pedido, ou se entretanto se recordou da sua palavra-passe original e já não deseja alterá-la, pode ignorar esta mensagem e continuar a usar a palavra-passe antiga.",
-       "passwordreset-emailtext-user": "O utilizador $1 do projeto {{SITENAME}} pediu a recuperação da sua palavra-passe no projeto {{SITENAME}} ($4). {{PLURAL:$3|A seguinte conta de utilizador está associada|As seguintes contas de utilizador estão associadas}} a este endereço de correio eletrónico:\n\n$2\n\n{{PLURAL:$3|Esta palavra-passe temporária irá|Estas palavras-passes temporárias irão}} expirar dentro de {{PLURAL:$5|um dia|$5 dias}}.\nDeve autenticar-se e escolher uma palavra-passe nova agora. Se outra pessoa fez este pedido, ou se entretanto se recordou da sua palavra-passe original e já não deseja alterá-la, pode ignorar esta mensagem e continuar a usar a palavra-passe antiga.",
+       "passwordreset-emailtitle": "Detalhes da conta na wiki {{SITENAME}}",
+       "passwordreset-emailtext-ip": "Alguém (provavelmente você, a partir do endereço IP $1) pediu a recuperação da palavra-passe na wiki {{SITENAME}} ($4). {{PLURAL:$3|A seguinte conta de utilizador está associada|As seguintes contas de utilizador estão associadas}} a este correio eletrónico:\n\n$2\n\n{{PLURAL:$3|Esta palavra-passe temporária irá|Estas palavras-passes temporárias irão}} expirar dentro de {{PLURAL:$5|um dia|$5 dias}}.\nDeve autenticar-se e escolher uma palavra-passe nova agora. Se outra pessoa fez este pedido, ou se entretanto se recordou da sua palavra-passe original e já não deseja alterá-la, pode ignorar esta mensagem e continuar a usar a palavra-passe antiga.",
+       "passwordreset-emailtext-user": "O utilizador $1 da wiki {{SITENAME}} pediu a recuperação da sua palavra-passe ($4). {{PLURAL:$3|A seguinte conta de utilizador está associada|As seguintes contas de utilizador estão associadas}} a este endereço de correio eletrónico:\n\n$2\n\n{{PLURAL:$3|Esta palavra-passe temporária irá|Estas palavras-passes temporárias irão}} expirar dentro de {{PLURAL:$5|um dia|$5 dias}}.\nDeve autenticar-se e escolher uma palavra-passe nova agora. Se outra pessoa fez este pedido, ou se entretanto se recordou da sua palavra-passe original e já não deseja alterá-la, pode ignorar esta mensagem e continuar a usar a palavra-passe antiga.",
        "passwordreset-emailelement": "{{GENDER:$1|Utilizador|Utilizadora}}: \n$1\n\nPalavra-passe temporária: \n$2",
        "passwordreset-emailsentemail": "Se este é o endereço de correio eletrónico associado a esta conta, ser-lhe-á enviada uma palavra-passe de reposição.",
        "passwordreset-emailsentusername": "Se houver um endereço de correio eletrónico associado a esta conta, ser-lhe-á enviada uma mensagem para redefinir a sua palavra-passe.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|A mensagem|As mensagens}} de redefinição da palavra-passe {{PLURAL:$1|foi enviada|foram enviadas}} para o seu correio eletrónico. {{PLURAL:$1|O nome de utilizador e palavra-passe encontram-se|A lista de nomes de utilizador e palavras-passe encontra-se}} a seguir.",
-       "passwordreset-emailerror-capture2": "O envio do correio {{GENDER:$2|ao utilizador|à utilizadora|a(o) utilizador(a)}} falhou: $1 {{PLURAL:$3|O nome de utilizador e palavra-passe são mostrados aqui|A lista de nomes de utilizador e palavras-passe é mostrada aqui}}.",
        "passwordreset-nocaller": "Um interlocutor deve ser fornecido",
        "passwordreset-nosuchcaller": "A pessoa que chama não existe: $1",
        "passwordreset-ignored": "A reposição de palavra-passe não foi realizada. Talvez o fornecedor não tenha sido configurado?",
-       "passwordreset-invalideamil": "Correio eletrónico inválido",
+       "passwordreset-invalidemail": "Correio eletrónico inválido",
        "passwordreset-nodata": "Não foram fornecidos nome de utilizador(a) nem endereço de correio eletrónico",
        "changeemail": "Alterar ou remover o endereço de correio eletrónico",
        "changeemail-header": "Complete este formulário para alterar o seu endereço de correio eletrónico. Se quer eliminar a associação de qualquer endereço de correio eletrónico com a sua conta, deixe em branco o novo endereço de correio eletrónico ao submeter o formulário.",
        "changeemail-newemail": "Novo endereço de correio eletrónico:",
        "changeemail-newemail-help": "Este campo deve ser deixado em branco caso pretenda remover o seu endereço de correio eletrónico.\nNão será capaz de redefinir a sua palavra-passe nem receber mensagens eletrónicas desta wiki se efetuar esta operação.",
        "changeemail-none": "(nenhum)",
-       "changeemail-password": "A sua palavra-passe em {{SITENAME}}:",
+       "changeemail-password": "A sua palavra-passe na wiki {{SITENAME}}:",
        "changeemail-submit": "Alterar correio eletrónico",
        "changeemail-throttled": "Realizou demasiadas tentativas de início de sessão.\nAguarde $1 antes de tentar novamente, por favor.",
        "changeemail-nochange": "Por favor insira um novo endereço de e-mail.",
        "nonunicodebrowser": "<strong>Aviso: O seu navegador não é compatível com as especificações Unicode.</strong>\nFoi ativado um sistema de edição alternativo que lhe permite editar as páginas com segurança: os caracteres não-ASCII aparecerão na caixa de edição no formato de códigos hexadecimais.",
        "editingold": "'''Aviso: Está a editar uma revisão desatualizada desta página.'''\nSe gravar, todas as mudanças feitas a partir desta revisão serão perdidas.",
        "yourdiff": "Diferenças",
-       "copyrightwarning": "Note, por favor, que todas as suas contribuições na {{SITENAME}} são consideradas publicadas nos termos da licença $2 (consulte $1 para mais detalhes).\nSe não deseja que o seu texto possa ser inexoravelmente editado e redistribuído, não o envie.\nGarante-nos também que isto é algo escrito por si, ou copiado do domínio público ou de outra fonte de teor livre.<br />\n'''Não envie conteúdos cujos direitos de autor estão protegidos, sem ter a devida permissão!'''",
-       "copyrightwarning2": "Note, por favor, que todas as suas contribuições na {{SITENAME}} podem ser editadas, alteradas ou removidas por outros utilizadores.\nSe não deseja que o seu texto seja inexoravelmente editado, não o envie.<br />\nGarante-nos também que isto é algo escrito por si, ou copiado do domínio público ou de outra fonte de teor livre (consulte $1 para mais detalhes).<br />\n'''Não envie conteúdos cujos direitos de autor estão protegidos, sem ter a devida permissão!'''",
+       "copyrightwarning": "Note, por favor, que todas as suas contribuições na wiki {{SITENAME}} são consideradas publicadas nos termos da licença $2 (consulte $1 para mais detalhes).\nSe não deseja que o seu texto possa ser inexoravelmente editado e redistribuído, não o envie.\nGarante-nos também que isto é algo escrito por si, ou copiado do domínio público ou de outra fonte de teor livre.<br />\n<strong>Não envie conteúdos cujos direitos de autor estão protegidos, sem ter a devida permissão!</strong>",
+       "copyrightwarning2": "Note, por favor, que todas as suas contribuições na wiki {{SITENAME}} podem ser editadas, alteradas ou removidas por outros utilizadores.\nSe não deseja que o seu texto seja inexoravelmente editado, não o envie.<br />\nGarante-nos também que isto é algo escrito por si, ou copiado do domínio público ou de outra fonte de teor livre (consulte $1 para mais detalhes).<br />\n<strong>Não envie conteúdos cujos direitos de autor estão protegidos, sem ter a devida permissão!</strong>",
        "editpage-cannot-use-custom-model": "O modelo de conteúdo desta página não pode ser alterado.",
        "longpageerror": "'''Erro: O texto que submeteu ocupa {{PLURAL:$1|um kilobyte|$1 kilobytes}}, que excede o máximo de {{PLURAL:$2|um kilobyte|$2 kilobytes}}.'''\nA página não pode ser gravada.",
        "readonlywarning": "<strong>Atenção: A base de dados foi bloqueada para manutenção, pelo que não poderá gravar as suas edições neste momento.</strong>\nPode, contudo, copiar e colar o seu texto num ficheiro de texto e guardá-lo para mais tarde.\n\nO administrador do sistema que a bloqueou forneceu a seguinte explicação: $1",
        "template-semiprotected": "(semi-protegida)",
        "hiddencategories": "Esta página pertence a {{PLURAL:$1|uma categoria oculta|$1 categorias ocultas}}:",
        "edittools": "<!-- O texto colocado aqui será mostrado abaixo dos formulários de edição e de envio de ficheiros. -->",
-       "nocreatetext": "A {{SITENAME}} restringe a criação de páginas novas por utilizadores anónimos.\nPode voltar atrás e editar uma página já existente, ou [[Special:UserLogin|inicie sessão ou criar uma conta]].",
+       "nocreatetext": "A wiki {{SITENAME}} restringe a criação de páginas novas por utilizadores anónimos.\nPode voltar atrás e editar uma página já existente, ou [[Special:UserLogin|iniciar uma sessão ou criar uma conta]].",
        "nocreate-loggedin": "Não possui permissão para criar novas páginas.",
        "sectioneditnotsupported-title": "Edição de secções não suportada",
        "sectioneditnotsupported-text": "A edição de secções não é suportada nesta página de edição.",
        "permissionserrorstext": "Não possui permissão para fazer isso, {{PLURAL:$1|pelo seguinte motivo|pelos seguintes motivos}}:",
        "permissionserrorstext-withaction": "Não possui permissão para $2, {{PLURAL:$1|pelo seguinte motivo|pelos seguintes motivos}}:",
        "contentmodelediterror": "Não pode editar esta revisão pois seu modelo de conteúdo é <code>$1</code>, que é diferente do modelo atual da página <code>$2</code>.",
-       "recreate-moveddeleted-warn": "'''Aviso: Está a recriar uma página anteriormente eliminada.'''\n\nVerifique se é apropriado continuar a editar esta página.\nPara sua conveniência, é apresentado de seguida o registo de eliminação e de movimento da página:",
-       "moveddeleted-notice": "Esta página foi eliminada.\nPara referência, é apresentado de seguida o registo de eliminações e de movimento da página.",
+       "recreate-moveddeleted-warn": "<strong>Aviso: Está a recriar uma página anteriormente eliminada.</strong>\n\nVerifique se é apropriado continuar a editar esta página.\nPara sua conveniência, é apresentado abaixo o registo de eliminação e movimentação da página:",
+       "moveddeleted-notice": "Esta página foi eliminada.\nPara sua referência, é apresentado abaixo o registo de eliminação e movimentação da página.",
        "moveddeleted-notice-recent": "Desculpe, esta página foi eliminada recentemente (nas últimas 24 horas).\nA exclusão e registo de movimentação para a página são fornecidos abaixo para referência.",
        "log-fulllog": "Ver registo detalhado",
        "edit-hook-aborted": "A edição foi abortada por um hook.\nNão foi dada nenhuma explicação.",
        "powersearch-togglenone": "Nenhum",
        "powersearch-remember": "Lembrar seleção para pesquisas futuras",
        "search-external": "Pesquisa externa",
-       "searchdisabled": "Foi impossibilitada a realização de pesquisas na {{SITENAME}}.\nEntretanto, pode realizar pesquisas através do Google.\nNote, no entanto, que a indexação da {{SITENAME}} neste motor de busca pode estar desatualizada.",
+       "searchdisabled": "Foi impossibilitada a realização de pesquisas na wiki {{SITENAME}}.\nEntretanto, pode realizar pesquisas através do Google.\nNote, no entanto, que a indexação da wiki {{SITENAME}} neste motor de busca pode estar desatualizada.",
        "search-error": "Um erro ocorreu enquanto se efectuava a pesquisa: $1",
+       "search-warning": "Ocorreu um aviso ao pesquisar: $1",
        "preferences": "Preferências",
        "mypreferences": "Preferências",
        "prefs-edits": "Número de edições:",
        "prefs-help-recentchangescount": "Inclui mudanças recentes, histórico de páginas e registos.",
        "prefs-help-watchlist-token2": "Esta é a chave secreta para o ''feed'' RSS da sua lista de páginas vigiadas.\nQualquer pessoa que conheça a chave será capaz de ler a sua lista de páginas vigiadas, por isso não a divulgue.\n[[Special:ResetTokens|Clique aqui para redefini-la]].",
        "savedprefs": "As suas preferências foram gravadas.",
-       "savedrights": "Os privilégios de utilizador para {{GENDER:$1|$1}} foram gravados.",
+       "savedrights": "Os grupos {{GENDER:$1|do utilizador|da utilizadora}} $1 foram gravados.",
        "timezonelegend": "Fuso horário:",
        "localtime": "Hora local:",
        "timezoneuseserverdefault": "Usar padrão da wiki ($1)",
        "prefswarning-warning": "Fez alterações às suas preferências que não foram gravadas ainda.\nSe abandonar esta página sem clicar em \"$1\", as suas preferências não serão atualizadas.",
        "prefs-tabs-navigation-hint": "Dica: Pode usar as setas direita e esquerda do teclado para navegar entre os separadores.",
        "userrights": "Gestão de privilégios {{GENDER:{{BASEPAGENAME}}|do utilizador|da utilizadora|de utilizador(a)}}",
-       "userrights-lookup-user": "Gerir grupos de utilizadores",
+       "userrights-lookup-user": "Selecionar um utilizador",
        "userrights-user-editname": "Introduza um nome de utilizador(a):",
-       "editusergroup": "Editar grupos {{GENDER:$1|do utilizador|da utilizadora|do(a) utilizador(a)}}",
+       "editusergroup": "Carregar grupos do utilizador",
        "editinguser": "A modificar os privilégios {{GENDER:$1|do utilizador|da utilizadora|do(a) utilizador(a)}}  <strong>[[User:$1|$1]]</strong> $2",
-       "userrights-editusergroup": "Editar grupos {{GENDER:$1|do utilizador|da utilizadora|do(a) utilizador(a)}}",
+       "viewinguserrights": "A ver os privilégios {{GENDER:$1|do utilizador|da utilizadora}} <strong>[[User:$1|$1]]</strong> $2",
+       "userrights-editusergroup": "Editar grupos {{GENDER:$1|do utilizador|da utilizadora}}",
+       "userrights-viewusergroup": "Ver grupos do utilizador",
        "saveusergroups": "Gravar grupos {{GENDER:$1|do utilizador|da utilizadora|do(a) utilizador(a)}}",
        "userrights-groupsmember": "Membro de:",
        "userrights-groupsmember-auto": "Membro implícito de:",
        "userrights-reason": "Motivo:",
        "userrights-no-interwiki": "Não tem permissões para alterar os privilégios de utilizadores noutras wikis.",
        "userrights-nodatabase": "A base de dados $1 não existe ou não é uma base de dados local.",
-       "userrights-nologin": "Precisa de [[Special:UserLogin|iniciar sessão]] com uma conta de administrador para atribuir privilégios aos utilizadores.",
-       "userrights-notallowed": "A sua conta não tem permissão para adicionar ou remover privilégios a utilizadores.",
        "userrights-changeable-col": "Grupos que pode alterar",
        "userrights-unchangeable-col": "Grupos que não pode alterar",
        "userrights-conflict": "Conflito entre alterações de privilégios de utilizador! Por favor, reveja e confirme as suas mudanças.",
-       "userrights-removed-self": "Removeu os seus privilégios. Como resultado disto, já não consegue aceder a esta página.",
        "group": "Grupo:",
        "group-user": "Utilizadores",
        "group-autoconfirmed": "Utilizadores autoconfirmados",
        "right-reupload-shared": "Sobrescrever localmente ficheiros no repositório partilhado de imagens",
        "right-upload_by_url": "Carregar um ficheiro de um endereço URL",
        "right-purge": "Limpar a ''cache'' de uma página no servidor sem confirmação",
-       "right-autoconfirmed": "Não ser afetado pelos limites de frequência baseados no número de IP",
+       "right-autoconfirmed": "Não ser afetado pelos limites de frequência de edição baseados em endereços IP",
        "right-bot": "Ser tratado como um processo automatizado",
        "right-nominornewtalk": "Não desencadear o aviso de mensagens novas ao fazer edições menores a páginas de discussão",
        "right-apihighlimits": "Usar limites superiores nas consultas ''(queries)'' via API",
        "right-blockemail": "Impedir um utilizador de enviar correio eletrónico",
        "right-hideuser": "Bloquear um nome de utilizador, escondendo-o do público",
        "right-ipblock-exempt": "Contornar bloqueios de IP, bloqueios automáticos e bloqueios de gamas de IP",
-       "right-unblockself": "Desbloquearem-se a si próprios",
+       "right-unblockself": "Desbloquear-se a si próprio",
        "right-protect": "Mudar níveis de proteção e editar páginas protegidas em cascata",
        "right-editprotected": "Editar páginas protegidas com \"{{int:protect-level-sysop}}\"",
        "right-editsemiprotected": "Editar páginas protegidas com \"{{int:protect-level-autoconfirmed}}\"",
        "right-editmyoptions": "Editar as suas próprias preferências",
        "right-rollback": "Reverter rapidamente as edições do último utilizador que editou uma página em particular",
        "right-markbotedits": "Marcar edições revertidas como edições de robô",
-       "right-noratelimit": "Não ser afetado pelos limites de velocidade de operação",
+       "right-noratelimit": "Não ser afetado pelos limites de frequência de edição",
        "right-import": "Importar páginas de outras wikis",
        "right-importupload": "Importar páginas de um ficheiro xml",
        "right-patrol": "Marcar edições de outros utilizadores como patrulhadas",
        "right-siteadmin": "Bloquear e desbloquear a base de dados",
        "right-override-export-depth": "Exportar páginas incluindo páginas ligadas até uma profundidade de 5",
        "right-sendemail": "Enviar correio eletrónico a outros utilizadores",
-       "right-passwordreset": "Ver mensagens de redefinição da palavra-passe",
        "right-managechangetags": "Criar e (des)ativar [[Special:Tags|etiquetas]]",
        "right-applychangetags": "Aplicar [[Special:Tags|etiquetas]] juntamente com as alterações",
        "right-changetags": "Adicionar ou remover [[Special:Tags|etiquetas]] arbitrárias em revisões e entradas de registo individuais",
        "action-history": "ver histórico desta página",
        "action-minoredit": "marcar esta edição como uma edição menor",
        "action-move": "mover esta página",
-       "action-move-subpages": "mover esta página e as respectivas subpáginas",
+       "action-move-subpages": "mover esta página e as respetivas subpáginas",
        "action-move-rootuserpages": "mover páginas raiz de utilizadores",
        "action-move-categorypages": "mover categorias",
        "action-movefile": "mover este ficheiro",
        "action-upload_by_url": "enviar este ficheiro através de um URL",
        "action-writeapi": "utilizar o modo de escrita da API",
        "action-delete": "eliminar esta página",
-       "action-deleterevision": "eliminar esta edição",
-       "action-deletedhistory": "ver o histórico de edições eliminadas desta página",
+       "action-deleterevision": "eliminar revisões",
+       "action-deletelogentry": "eliminar entradas de registo",
+       "action-deletedhistory": "ver o histórico de edições eliminadas de uma página",
+       "action-deletedtext": "ver o texto de uma revisão eliminada",
        "action-browsearchive": "pesquisar páginas eliminadas",
-       "action-undelete": "restaurar esta página",
-       "action-suppressrevision": "rever e restaurar esta edição oculta",
+       "action-undelete": "restaurar páginas",
+       "action-suppressrevision": "rever e restaurar edições ocultas",
        "action-suppressionlog": "ver este registo privado",
        "action-block": "impedir este utilizador de editar",
        "action-protect": "alterar os níveis de proteção desta página",
        "action-userrights-interwiki": "editar privilégios de utilizadores de outras wikis",
        "action-siteadmin": "bloquear ou desbloquear a base de dados",
        "action-sendemail": "enviar correio eletrónico",
+       "action-editmyoptions": "editar as suas preferências",
        "action-editmywatchlist": "editar a sua lista de páginas vigiadas",
        "action-viewmywatchlist": "ver a sua lista de páginas vigiadas",
        "action-viewmyprivateinfo": "ver a sua informação privada",
        "recentchanges": "Mudanças recentes",
        "recentchanges-legend": "Opções das mudanças recentes",
        "recentchanges-summary": "Acompanhe nesta página as mudanças mais recentes da wiki.",
-       "recentchanges-noresult": "Nenhuma alteração correspondente a esses critérios foi realizada durante o período selecionado.",
+       "recentchanges-noresult": "Não foi realizada nenhuma alteração correspondente a esses critérios durante o período selecionado.",
        "recentchanges-feed-description": "Acompanhe neste ''feed'' as mudanças mais recentes da wiki.",
        "recentchanges-label-newpage": "Esta edição criou uma nova página",
        "recentchanges-label-minor": "Esta é uma edição menor",
        "upload_directory_missing": "O diretório de carregamento de ficheiros ($1) não existe e o servidor de Internet não conseguiu criá-lo.",
        "upload_directory_read_only": "O servidor de Internet não possui permissão de escrita no diretório de carregamento de ficheiros ($1).",
        "uploaderror": "Erro ao carregar",
-       "upload-recreate-warning": "'''Aviso: Um ficheiro com esse nome foi eliminado ou movido.'''\n\nPara sua conveniência, é apresentado de seguida o registo de eliminação e de movimento da página:",
+       "upload-recreate-warning": "<strong>Aviso: Um ficheiro com esse nome foi eliminado ou movido.</strong>\n\nPara sua conveniência, é apresentado abaixo o registo de eliminação e movimentação da página:",
        "uploadtext": "Utilize o formulário abaixo para fazer o carregamento de novos ficheiros.\nPara ver ou pesquisar ficheiros anteriormente enviados, consulte a [[Special:FileList|lista de ficheiros]].\nOs reenvios de um ficheiro são também registados no [[Special:Log/upload|registo de carregamentos]] e as eliminações no [[Special:Log/delete|registo de eliminações]].\n\nPara utilizar um ficheiro numa página, depois de ter feito o carregamento, insira uma ligação com um dos seguintes formatos:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:ficheiro.jpg]]</nowiki></code>''' para mostrar uma imagem nas suas dimensões originais;\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:ficheiro.png|200px|thumb|left|texto]]</nowiki></code>''' para mostrar uma imagem com a dimensão horizontal de 200 píxeis, dentro de uma caixa, na margem esquerda, contendo 'texto' como descrição (pode usar subconjuntos destas características);\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:ficheiro.ogg]]</nowiki></code>''' para apresentar uma ligação direta para o ficheiro em vez de mostrá-lo, quer este tenha por conteúdo uma imagem ou outros dados.",
        "upload-permitted": "{{PLURAL:$2|Tipo|Tipos}} de ficheiro {{PLURAL:$2|permitido|permitidos}}: $1.",
        "upload-preferred": "{{PLURAL:$2|Tipo|Tipos}} de ficheiro {{PLURAL:$2|preferido|preferidos}}: $1.",
        "upload-prohibited": "{{PLURAL:$2|Tipo|Tipos}} de ficheiro {{PLURAL:$2|proibido|proibidos}}: $1.",
-       "uploadlogpage": "Registo de carregamento",
+       "uploadlogpage": "Registo de carregamentos",
        "uploadlogpagetext": "Segue-se uma lista dos carregamentos mais recentes.\nConsulte a [[Special:NewFiles|galeria de novos ficheiros]] para visioná-los.",
        "filename": "Nome do ficheiro",
        "filedesc": "Descrição do ficheiro",
        "upload-form-label-own-work": "Este é minha obra própria",
        "upload-form-label-infoform-categories": "Categorias",
        "upload-form-label-infoform-date": "Data",
-       "upload-form-label-own-work-message-generic-local": "Confirmo que estou a carregar este ficheiro segundo as condições de serviço e política de licenças de {{SITENAME}}.",
-       "upload-form-label-not-own-work-message-generic-local": "Se não é capaz de carregar este ficheiro sob as políticas de {{SITENAME}}, por favor feche esta janela e tente outro método.",
+       "upload-form-label-own-work-message-generic-local": "Confirmo que estou a carregar este ficheiro segundo as condições de serviço e política de licenças da wiki {{SITENAME}}.",
+       "upload-form-label-not-own-work-message-generic-local": "Se não pode carregar este ficheiro de acordo com as normas da wiki {{SITENAME}}, por favor feche esta janela e tente outro método.",
        "upload-form-label-not-own-work-local-generic-local": "Poderá querer experimentar [[Special:Upload|a página padrão de carregamento]].",
        "upload-form-label-own-work-message-generic-foreign": "Entendo que estou a carregar este ficheiro em um repositório partilhado. Confirmo que estou a fazê-lo cumprindo com os termos de serviço e com as políticas de licenciamento.",
        "upload-form-label-not-own-work-message-generic-foreign": "Se não é capaz de carregar este ficheiro sob as políticas do repositório partilhado, por favor feche esta janela e tente outro método.",
-       "upload-form-label-not-own-work-local-generic-foreign": "Pode querer tentar utilizar [[Special:Upload|a página de carregamento em {{SITENAME}}]], se este ficheiro puder ser carregado de acordo com suas as políticas.",
+       "upload-form-label-not-own-work-local-generic-foreign": "Pode querer tentar utilizar [[Special:Upload|a página de carregamento na wiki {{SITENAME}}]], se este ficheiro puder ser carregado de acordo com as normas da wiki.",
        "backend-fail-stream": "Não foi possível transmitir o ficheiro \"$1\".",
        "backend-fail-backup": "Não foi possível fazer cópia de segurança do ficheiro \"$1\".",
        "backend-fail-notexists": "O ficheiro $1 não existe.",
        "listfiles-latestversion-no": "Não",
        "file-anchor-link": "Ficheiro",
        "filehist": "Histórico do ficheiro",
-       "filehist-help": "Clique numa data/hora para ver o ficheiro tal como se encontrava nesse momento.",
+       "filehist-help": "Clique uma data e hora para ver o ficheiro tal como ele se encontrava nessa altura.",
        "filehist-deleteall": "eliminar todas",
        "filehist-deleteone": "eliminar",
        "filehist-revert": "restaurar",
        "imagelinks": "Uso do ficheiro",
        "linkstoimage": "{{PLURAL:$1|A seguinte página contém ligação|As seguintes $1 páginas contêm ligações}} para este ficheiro:",
        "linkstoimage-more": "Mais de {{PLURAL:$1|uma página contém ligação|$1 páginas contêm ligações}} para este ficheiro.\nA lista abaixo apresenta apenas {{PLURAL:$1|a primeira página|as primeiras $1 páginas}}.\nEncontra-se disponível uma [[Special:WhatLinksHere/$2|lista completa]].",
-       "nolinkstoimage": "Nenhuma página contém ligação para este ficheiro.",
+       "nolinkstoimage": "Não há nenhuma página que contenha ''links'' para este ficheiro.",
        "morelinkstoimage": "Ver a [[Special:WhatLinksHere/$1|lista completa]] de páginas que contêm ligações para este ficheiro.",
        "linkstoimage-redirect": "$1 (redirecionamento de ficheiro) $2",
        "duplicatesoffile": "{{PLURAL:$1|O seguinte ficheiro é duplicado|Os seguintes $1 ficheiros são duplicados}} deste ficheiro ([[Special:FileDuplicateSearch/$2|mais detalhes]]):",
        "statistics-pages": "Páginas",
        "statistics-pages-desc": "Todas as páginas da wiki, incluindo páginas de discussão, redirecionamentos, etc.",
        "statistics-files": "Ficheiros carregados",
-       "statistics-edits": "Edições de páginas desde que a {{SITENAME}} foi instalada",
+       "statistics-edits": "Edições de páginas desde que a wiki {{SITENAME}} foi instalada",
        "statistics-edits-average": "Média de edições por página",
        "statistics-users": "[[Special:ListUsers|Utilizadores]] registados",
        "statistics-users-active": "Utilizadores ativos",
        "ntransclusions": "usada {{PLURAL:$1|numa página|em $1 páginas}}",
        "specialpage-empty": "Não existem dados para apresentar.",
        "lonelypages": "Páginas órfãs",
-       "lonelypagestext": "As seguintes páginas não são destino de ligação nem são transcluídas a partir de outras páginas na {{SITENAME}}.",
+       "lonelypagestext": "As seguintes páginas não são destino de links nem são transcluídas a partir de outras páginas na wiki {{SITENAME}}.",
        "uncategorizedpages": "Páginas não categorizadas",
        "uncategorizedcategories": "Categorias não categorizadas",
        "uncategorizedimages": "Ficheiros não categorizados",
        "shortpages": "Páginas curtas",
        "longpages": "Páginas longas",
        "deadendpages": "Páginas sem saída",
-       "deadendpagestext": "As seguintes páginas não contêm ligações para outras páginas em {{SITENAME}}.",
+       "deadendpagestext": "As seguintes páginas não contêm links para outras páginas na wiki {{SITENAME}}.",
        "protectedpages": "Páginas protegidas",
        "protectedpages-indef": "Apenas proteções indefinidas",
        "protectedpages-summary": "Esta página lista páginas existentes que estão protegidas. Para ver os títulos cuja criação está impossibilitada, consulte [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "apisandbox-continue": "Continuar",
        "apisandbox-continue-clear": "Limpar",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries continuará] o último pedido; {{int:apisandbox-continue-clear}} limpará os parâmetros relativos à continuação.",
+       "apisandbox-param-limit": "Introduza <kbd>max</kbd> para usar o limite máximo.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Todos os espaços nominais)",
+       "apisandbox-multivalue-all-values": "$1 (Todos os valores)",
        "booksources": "Fontes bibliográficas",
        "booksources-search-legend": "Pesquisar referências bibliográficas",
        "booksources-search": "Pesquisar",
        "logeventslist-submit": "Mostrar",
        "all-logs-page": "Todos os registos públicos",
        "alllogstext": "Apresentação combinada de todos os registos disponíveis na wiki {{SITENAME}}.\nPode reduzir a lista escolhendo um tipo de registo, um nome de utilizador ou um título de página. Respeite maiúsculas e minúsculas.",
-       "logempty": "Nenhum item correspondente no registo.",
+       "logempty": "Não existe nenhuma entrada correspondente no registo.",
        "log-title-wildcard": "Procurar títulos iniciados por este texto",
        "showhideselectedlogentries": "Mostrar ou ocultar as entradas selecionadas",
        "log-edit-tags": "Editar etiquetas das entradas de registo selecionadas",
        "allpagessubmit": "Ver",
        "allpagesprefix": "Apresentar páginas iniciadas por:",
        "allpagesbadtitle": "O título de página fornecido era inválido ou tinha um prefixo interlínguas ou interwikis.\nTalvez contenha um ou mais caracteres que não podem ser usados nos títulos.",
-       "allpages-bad-ns": "{{SITENAME}} não possui o domínio \"$1\".",
+       "allpages-bad-ns": "A wiki {{SITENAME}} não possui o espaço nominal \"$1\".",
        "allpages-hide-redirects": "Ocultar redirecionamentos",
        "cachedspecial-viewing-cached-ttl": "Está a ver uma versão desta página guardada na cache há pelo menos $1.",
        "cachedspecial-viewing-cached-ts": "Está a ver uma versão da página guardada na cache, que pode estar desatualizada.",
        "activeusers-count": "$1 {{PLURAL:$1|ação|ações}} {{PLURAL:$3|no último dia|nos últimos $3 dias}}",
        "activeusers-from": "Mostrar utilizadores começados por:",
        "activeusers-groups": "Apresentar os utilizadores que pertencem aos grupos:",
-       "activeusers-noresult": "Nenhum utilizador encontrado.",
+       "activeusers-excludegroups": "Excluir os utilizadores que pertencem aos grupos:",
+       "activeusers-noresult": "Não foram encontrados utilizadores.",
        "activeusers-submit": "Mostrar utilizadores ativos",
        "listgrouprights": "Privilégios dos grupos de utilizadores",
-       "listgrouprights-summary": "A seguinte lista contém os grupos de utilizadores definidos nesta wiki, com os respectivos privilégios de acesso.\nEncontram-se disponíveis [[{{MediaWiki:Listgrouprights-helppage}}|informações adicionais]] sobre privilégios individuais.",
+       "listgrouprights-summary": "A seguinte lista contém os grupos de utilizadores definidos nesta wiki, com os respetivos privilégios de acesso.\nEncontram-se disponíveis [[{{MediaWiki:Listgrouprights-helppage}}|informações adicionais]] sobre privilégios individuais.",
        "listgrouprights-key": "Legenda:\n* <span class=\"listgrouprights-granted\">Privilégio concedido</span>\n* <span class=\"listgrouprights-revoked\">Privilégio revogado</span>",
        "listgrouprights-group": "Grupo",
        "listgrouprights-rights": "Privilégios",
        "expensive-parserfunction-category-desc": "A página tem demasiadas funções do analisador custosas (como <code>#ifexist</code>) incluídas. Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
        "broken-file-category-desc": "A página contém uma ligação quebrada para um ficheiro (uma ligação para incorporar um ficheiro que não existe).",
        "hidden-category-category-desc": "Esta é uma categoria com a marca <code><nowiki>__HIDDENCAT__</nowiki></code>, que faz com que ela não apareça na caixa de ligações de categoria nas páginas, por omissão.",
-       "trackingcategories-nodesc": "Nenhuma descrição disponível.",
+       "trackingcategories-nodesc": "Sem descrição disponível.",
        "trackingcategories-disabled": "A categoria está desativada.",
        "mailnologin": "Não existe endereço de envio",
        "mailnologintext": "Precisa de estar [[Special:UserLogin|autenticado]] e ter um endereço de correio válido nas suas [[Special:Preferences|preferências]], para poder enviar correio eletrónico a outros utilizadores.",
        "emailuser-title-target": "Enviar correio eletrónico a {{GENDER:$1|este utilizador|esta utilizadora|este(a) utilizador(a)}}",
        "emailuser-title-notarget": "Enviar correio eletrónico ao utilizador",
        "emailpagetext": "Pode usar o formulário abaixo para enviar uma mensagem por correio eletrónico para {{GENDER:$1|este utilizador|esta utilizadora}}.\nO endereço de correio que introduziu nas [[Special:Preferences|suas preferências]] irá aparecer no campo do remetente da mensagem \"De:\", para que o destinatário lhe possa responder diretamente.",
-       "defemailsubject": "Correio eletrónico da {{SITENAME}}, {{GENDER:$1|do utilizador|da utilizadora|do(a) utilizador(a)}} \"$1\"",
+       "defemailsubject": "Correio eletrónico {{GENDER:$1|do utilizador|da utilizadora}} \"$1\" da wiki {{SITENAME}}",
        "usermaildisabled": "O correio eletrónico do utilizador foi desativado",
        "usermaildisabledtext": "Não pode enviar correio eletrónico a outros utilizadores desta wiki",
        "noemailtitle": "Sem endereço de correio eletrónico",
        "emailtarget": "Introduza o nome do(a) destinatário(a)",
        "emailusername": "Utilizador(a):",
        "emailusernamesubmit": "Enviar",
-       "email-legend": "Enviar uma mensagem a outro utilizador da {{SITENAME}}",
+       "email-legend": "Enviar uma mensagem a outro utilizador da wiki {{SITENAME}}",
        "emailfrom": "De:",
        "emailto": "Para:",
        "emailsubject": "Assunto:",
        "emailccsubject": "Cópia da sua mensagem para $1: $2",
        "emailsent": "Mensagem enviada",
        "emailsenttext": "A sua mensagem foi enviada.",
-       "emailuserfooter": "Esta mensagem foi {{GENDER:$1|enviada}} por $1 para {{GENDER:$2|$2}} através da opção \"{{int:emailuser}}\" em {{SITENAME}}.",
+       "emailuserfooter": "Esta mensagem foi enviada {{GENDER:$1|pelo utilizador|pela utilizadora}} $1 para {{GENDER:$2|$2}} através da opção \"{{int:emailuser}}\" da wiki {{SITENAME}}. {{GENDER:$2|A sua}} resposta será enviada diretamente para {{GENDER:$1|o|a}} remetente original, e irá revelar-lhe {{GENDER:$2|o seu}} endereço de correio eletrónico.",
        "usermessage-summary": "Deixar mensagem de sistema.",
        "usermessage-editor": "Editor de mensagens de sistema",
        "watchlist": "Páginas vigiadas",
        "wlshowhideliu": "utilizadores registados",
        "wlshowhideanons": "utilizadores anónimos",
        "wlshowhidepatr": "edições patrulhadas",
-       "wlshowhidemine": "minhas edições",
+       "wlshowhidemine": "edições minhas",
        "wlshowhidecategorization": "categorização de páginas",
        "watchlist-options": "Opções da lista de páginas vigiadas",
        "watching": "A vigiar...",
        "unwatching": "A deixar de vigiar...",
        "watcherrortext": "Ocorreu um erro ao alterar a configuração da sua lista de páginas vigiadas para \"$1\".",
        "enotif_reset": "Marcar todas as páginas como visitadas",
-       "enotif_impersonal_salutation": "Utilizador de {{SITENAME}}",
-       "enotif_subject_deleted": "A página  $1 de {{SITENAME}} foi {{GENDER:$2|eliminada}} por $2",
-       "enotif_subject_created": "A página $1 de {{SITENAME}} foi {{GENDER:$2|criada}} por $2",
-       "enotif_subject_moved": "A página $1 de {{SITENAME}} foi {{GENDER:$2|movida}} por $2",
-       "enotif_subject_restored": "A página $1 de {{SITENAME}} foi {{GENDER:$2|restaurada}} por $2",
-       "enotif_subject_changed": "A página $1 de {{SITENAME}} foi {{GENDER:$2|alterada}} por $2",
-       "enotif_body_intro_deleted": "A página $1 de {{SITENAME}} foi {{GENDER:$2|eliminada}} em $PAGEEDITDATE por $2, ver $3.",
-       "enotif_body_intro_created": "A página $1 em {{SITENAME}} foi {{GENDER:$2| criada}} em $PAGEEDITDATE por $2, ver $3 para a versão atual.",
-       "enotif_body_intro_moved": "A página $1 em {{SITENAME}} foi {{GENDER:$2|movida}} em $PAGEEDITDATE por $2, ver $3 para a versão atual.",
-       "enotif_body_intro_restored": "A página $1 em {{SITENAME}} foi {{GENDER:$2|restaurada}} em $PAGEEDITDATE por $2, ver $3 para a versão atual.",
-       "enotif_body_intro_changed": "A página $1 em {{SITENAME}} foi {{GENDER:$2|alterada}} em $PAGEEDITDATE por $2, ver $3 para a versão atual.",
+       "enotif_impersonal_salutation": "Utilizador da wiki {{SITENAME}}",
+       "enotif_subject_deleted": "A página $1 da wiki {{SITENAME}} foi eliminada {{GENDER:$2|pelo utilizador|pela utilizadora}} $2",
+       "enotif_subject_created": "A página $1 da wiki {{SITENAME}} foi criada {{GENDER:$2|pelo utilizador|pela utilizadora}} $2",
+       "enotif_subject_moved": "A página $1 da wiki {{SITENAME}} foi movida {{GENDER:$2|pelo utilizador|pela utilizadora}} $2",
+       "enotif_subject_restored": "A página $1 da wiki {{SITENAME}} foi restaurada {{GENDER:$2|pelo utilizador|pela utilizadora}} $2",
+       "enotif_subject_changed": "A página $1 da wiki {{SITENAME}} foi alterada {{GENDER:$2|pelo utilizador|pela utilizadora}} $2",
+       "enotif_body_intro_deleted": "A página $1 da wiki {{SITENAME}} foi eliminada a $PAGEEDITDATE {{GENDER:$2|pelo utilizador|pela utilizadora}} $2. Veja $3.",
+       "enotif_body_intro_created": "A página $1 da wiki {{SITENAME}} foi criada a $PAGEEDITDATE {{GENDER:$2|pelo utilizador|pela utilizadora}} $2. Veja a revisão atual em $3.",
+       "enotif_body_intro_moved": "A página $1 da wiki {{SITENAME}} foi movida a $PAGEEDITDATE {{GENDER:$2|pelo utilizador|pela utilizadora}} $2. Veja a revisão atual em $3.",
+       "enotif_body_intro_restored": "A página $1 da wiki {{SITENAME}} foi restaurada a $PAGEEDITDATE {{GENDER:$2|pelo utilizador|pela utilizadora}} $2. Veja a revisão atual em $3.",
+       "enotif_body_intro_changed": "A página $1 da wiki {{SITENAME}} foi alterada a  $PAGEEDITDATE {{GENDER:$2|pelo utilizador|pela utilizadora}} $2. Veja a revisão atual em $3.",
        "enotif_lastvisited": "Consulte $1 para todas as alterações efetuadas desde a sua última visita.",
        "enotif_lastdiff": "Consulte $1 para ver esta alteração.",
        "enotif_anon_editor": "utilizador anónimo $1",
-       "enotif_body": "{{GENDER:$WATCHINGUSERNAME|Caro|Cara|Caro(a)}} $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nResumo da edição: $PAGESUMMARY $PAGEMINOREDIT\n\nContacte o editor:\ncorreio eletrónico: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nAté se autenticar e visitar novamente esta página, não receberá mais notificações das alterações futuras. Também pode reativar as notificações para todas páginas na sua lista de páginas vigiadas.\n\nO seu sistema de notificação amigável da {{SITENAME}}\n\n--\nPara alterar as suas preferências de notificação por correio eletrónico, visite\n{{canonicalurl:{{#special:Preferences}}}}\n\nPara alterar as suas preferências das páginas vigiadas, visite\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPara retirar a página da lista de páginas vigiadas, visite\n$UNWATCHURL\n\nPara comentários e pedidos de ajuda:\n$HELPPAGE",
+       "enotif_body": "{{GENDER:$WATCHINGUSERNAME|Caro|Cara|Caro(a)}} $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nResumo da edição: $PAGESUMMARY $PAGEMINOREDIT\n\nContacte o editor:\ncorreio eletrónico: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nAté se autenticar e visitar novamente esta página, não receberá mais notificações das alterações futuras. Também pode reativar as notificações para todas páginas na sua lista de páginas vigiadas.\n\nO seu sistema de notificação amigável da wiki {{SITENAME}}\n\n--\nPara alterar as suas preferências de notificação por correio eletrónico, visite\n{{canonicalurl:{{#special:Preferences}}}}\n\nPara alterar as suas preferências das páginas vigiadas, visite\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPara retirar a página da lista de páginas vigiadas, visite\n$UNWATCHURL\n\nPara comentários e pedidos de ajuda:\n$HELPPAGE",
        "created": "criada",
        "changed": "alterada",
        "deletepage": "Eliminar página",
        "deletereasonotherlist": "Outro motivo",
        "deletereason-dropdown": "* Motivos de eliminação comuns\n** Spam\n** Vandalismo\n** Violação de direitos de autor\n** Pedido do autor\n** Redirecionamento quebrado",
        "delete-edit-reasonlist": "Editar motivos de eliminação",
-       "delete-toobig": "Esta página tem um histórico longo, com mais de $1 {{PLURAL:$1|edição|edições}}.\nA eliminação de páginas como esta foi restringida na {{SITENAME}}, para evitar problemas acidentais.",
-       "delete-warning-toobig": "Esta página tem um histórico de edições longo, com mais de $1 {{PLURAL:$1|edição|edições}}.\nEliminá-la poderá causar problemas na base de dados da {{SITENAME}};\nprossiga com precaução.",
+       "delete-toobig": "Esta página tem um histórico longo, com mais de $1 {{PLURAL:$1|edição|edições}}.\nA eliminação de páginas como esta foi restringida na wiki {{SITENAME}}, para evitar problemas acidentais.",
+       "delete-warning-toobig": "Esta página tem um histórico de edições longo, com mais de $1 {{PLURAL:$1|edição|edições}}.\nEliminá-la poderá causar problemas na base de dados da wiki {{SITENAME}};\nprossiga com precaução.",
        "deleteprotected": "Não é possível eliminar esta página porque foi protegida.",
        "deleting-backlinks-warning": "<strong>Aviso:</strong> Existem [[Special:WhatLinksHere/{{FULLPAGENAME}}|páginas]] que contêm ligações para a página que está prestes a eliminar ou que a transcluem.",
        "rollback": "Reverter edições",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|alterou}} o modelo de conteúdo da página $3 de \"$4\" para \"$5\"",
        "logentry-contentmodel-change-revertlink": "reverter",
        "logentry-contentmodel-change-revert": "reverter",
-       "protectlogpage": "Registo de proteção",
+       "protectlogpage": "Registo de proteções",
        "protectlogtext": "Encontra abaixo o registo de proteção e desproteção de páginas.\nConsulte a [[Special:ProtectedPages|lista de páginas protegidas]] para ver as páginas que se encontram protegidas neste momento.",
        "protectedarticle": "protegeu \"[[$1]]\"",
        "modifiedarticleprotection": "alterou o nível de proteção para \"[[$1]]\"",
        "sp-contributions-blocked-notice": "Este utilizador está bloqueado neste momento.\nPara referência é apresentado abaixo o último registo de bloqueio:",
        "sp-contributions-blocked-notice-anon": "Este endereço IP está bloqueado neste momento.\nPara referência é apresentado abaixo o último registo de bloqueio:",
        "sp-contributions-search": "Pesquisar contribuições",
-       "sp-contributions-username": "Endereço de IP ou utilizador(a):",
+       "sp-contributions-username": "Endereço IP ou nome de utilizador:",
        "sp-contributions-toponly": "Mostrar apenas as edições mais recentes",
        "sp-contributions-newonly": "Mostrar só edições que são criações de páginas",
        "sp-contributions-hideminor": "Ocultar edições menores",
        "whatlinkshere-hideimages": "$1 ligações para ficheiros",
        "whatlinkshere-filters": "Filtros",
        "whatlinkshere-submit": "Continuar",
-       "autoblockid": "Bloqueio automático nº$1",
+       "autoblockid": "Bloqueio automático nº $1",
        "block": "Bloquear utilizador(a)",
        "unblock": "Desbloquear utilizador",
        "blockip": "Bloquear {{GENDER:$1|utilizador|utilizadora|utilizador(a)}}",
        "blockip-legend": "Bloquear utilizador(a)",
        "blockiptext": "Utilize o formulário abaixo para bloquear o acesso de escrita a um endereço IP específico ou a um nome de utilizador(a).\nIsto só deve ser feito para prevenir vandalismo e de acordo com a [[{{MediaWiki:Policy-url}}|política]]. Indique a seguir um motivo de bloqueio específico (por exemplo, indicando as páginas que foram alvo de vandalismo).\nPode bloquear intervalos de endereços IP com a sintaxe [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR]; o maior intervalo permitido é /$1 para IPv4 e /$2 para IPv6.",
-       "ipaddressorusername": "Endereço de IP ou utilizador(a):",
+       "ipaddressorusername": "Endereço IP ou nome de utilizador:",
        "ipbexpiry": "Expiração:",
        "ipbreason": "Motivo:",
        "ipbreason-dropdown": "*Razões comuns para um bloqueio\n** Inserção de informações falsas\n** Remoção de conteúdos de páginas\n** Inserção de \"spam\" para sítios externos\n** Inserção de conteúdo sem sentido/incompreensível nas páginas\n** Comportamento intimidador/inoportuno\n** Uso abusivo de contas múltiplas\n** Nome de utilizador inaceitável",
        "blocklist-userblocks": "Ocultar bloqueios de contas",
        "blocklist-tempblocks": "Ocultar bloqueios temporários",
        "blocklist-addressblocks": "Ocultar bloqueios de IP único",
-       "blocklist-rangeblocks": "Ocultar bloqueios de faixas",
+       "blocklist-rangeblocks": "Ocultar bloqueios de gamas",
        "blocklist-timestamp": "Data e hora",
        "blocklist-target": "Destinatário",
        "blocklist-expiry": "Expira",
        "contribslink": "contribs",
        "emaillink": "enviar correio eletrónico",
        "autoblocker": "Foi automaticamente bloqueado, porque o seu endereço IP foi recentemente usado por \"[[User:$1|$1]]\". \nO motivo apresentado para o bloqueio de $1 é: \"$2\".",
-       "blocklogpage": "Registo de bloqueio",
+       "blocklogpage": "Registo de bloqueios",
        "blocklog-showlog": "Este utilizador foi já bloqueado anteriormente.\nO registo de bloqueios é fornecido abaixo para referência:",
        "blocklog-showsuppresslog": "Este utilizador foi bloqueado e ocultado anteriomente.\nO registo de supressão é fornecido abaixo para referência:",
        "blocklogentry": "bloqueou \"[[$1]]\" por $2. $3",
        "unblock-hideuser": "Não pode desbloquear o utilizador, porque o nome deste utilizador foi oculto.",
        "ipb_cant_unblock": "Erro: O bloqueio com ID $1 não foi encontrado. Pode já ter sido desbloqueado.",
        "ipb_blocked_as_range": "Erro: O IP $1 não se encontra bloqueado de forma direta e não pode ser desbloqueado deste modo. No entanto, está bloqueado como parte da gama $2, a qual pode ser desbloqueada.",
-       "ip_range_invalid": "Gama de IP inválida.",
+       "ip_range_invalid": "Gama de endereços IP inválida.",
        "ip_range_toolarge": "Não são permitidas gamas de IP maiores do que /$1.",
        "proxyblocker": "Bloqueador de proxies",
        "proxyblockreason": "O seu endereço IP foi bloqueado por ser um ''proxy'' público.\nContacte o seu fornecedor de internet ou o serviço de apoio técnico e informe-os deste grave problema de segurança, por favor.",
-       "sorbsreason": "O seu endereço IP encontra-se listado como ''proxy'' aberto na DNSBL utilizada pela {{SITENAME}}.",
-       "sorbs_create_account_reason": "O seu endereço IP encontra-se listado como ''proxy'' aberto na DNSBL utilizada pela {{SITENAME}}. Não pode criar uma conta",
+       "sorbsreason": "O seu endereço IP encontra-se listado como ''proxy'' aberto na DNSBL utilizada pela wiki {{SITENAME}}.",
+       "sorbs_create_account_reason": "O seu endereço IP encontra-se listado como ''proxy'' aberto na DNSBL utilizada pela wiki {{SITENAME}}. Não pode criar uma conta.",
        "xffblockreason": "Um endereço IP presente no cabeçalho X-Forwarded-For, seja seu ou de um servidor de proxy que estiver a usar, foi bloqueado. A razão do bloqueio original foi: $1",
        "cant-see-hidden-user": "O utilizador que está a tentar bloquear já está bloqueado e oculto.\nComo não tem o privilégio para ocultar utilizadores ''(hideuser)'', não pode ver ou editar o bloqueio deste utilizador.",
        "ipbblocked": "Não pode bloquear ou desbloquear outros, porque está bloqueado",
        "locknoconfirm": "Não marcou a caixa de confirmação.",
        "lockdbsuccesssub": "Base de dados foi bloqueada",
        "unlockdbsuccesssub": "Base de dados foi desbloqueada",
-       "lockdbsuccesstext": "A base de dados da {{SITENAME}} foi bloqueada.<br />\nLembre-se de [[Special:UnlockDB|remover o bloqueio]] após a manutenção.",
+       "lockdbsuccesstext": "A base de dados da wiki {{SITENAME}} foi bloqueada.<br />\nLembre-se de [[Special:UnlockDB|remover o bloqueio]] após a manutenção.",
        "unlockdbsuccesstext": "A base de dados foi desbloqueada.",
        "lockfilenotwritable": "O ficheiro de bloqueio da base de dados não pode ser escrito.\nPara bloquear ou desbloquear a base de dados, este precisa de poder ser escrito pelo servidor de internet.",
        "databaselocked": "A base de dados já está bloqueada.",
        "importbadinterwiki": "Ligação interlíngua incorreta",
        "importsuccess": "Importação completa!",
        "importnosources": "Não foram definidas as wikis das quais importar e o carregamento direto de históricos encontra-se desativado.",
-       "importnofile": "Nenhum ficheiro de importação foi carregado.",
+       "importnofile": "Não foi carregado nenhum ficheiro de importação.",
        "importuploaderrorsize": "O carregamento do ficheiro importado falhou.\nO ficheiro é maior do que o tamanho máximo permitido.",
        "importuploaderrorpartial": "O carregamento do ficheiro importado falhou.\nO ficheiro foi recebido parcialmente.",
        "importuploaderrortemp": "O carregamento do ficheiro importado falhou.\nNão há um diretório temporário.",
        "import-parse-failure": "Falha ao importar dados XML",
        "import-noarticle": "Sem páginas para importar!",
-       "import-nonewrevisions": "Nenhuma revisão foi importada (já estavam todas presentes ou foram ignoradas devido a erros).",
+       "import-nonewrevisions": "Não foi importada nenhuma revisão (já estavam todas presentes ou foram ignoradas devido a erros).",
        "xml-error-string": "$1 na linha $2, coluna $3 (byte $4): $5",
        "import-upload": "Enviar dados em XML",
        "import-token-mismatch": "Perda de dados da sessão.\n\nA sua sessão poderá ter sido encerrada. <strong>Por favor, verifique se ainda está autenticado e tente novamente</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite a utilização de ''cookies'' deste sítio.",
        "import-error-interwiki": "A página \"$1\" não pode ser importada pois o seu nome está reservado para um ligação externa (interlíngua).",
        "import-error-special": "A página \"$1\" não pode ser importada porque pertence a um domínio especial que não permite páginas.",
        "import-error-invalid": "A página \"$1\" não pode ser importada porque o seu nome é inválido nesta wiki.",
-       "import-error-unserialize": "Revisão $2 da página \"$1\" não pode ser desserializada. Foi relatado que a revisão usava o modelo de conteúdo $3 serializado como $4.",
+       "import-error-unserialize": "Não foi possível anular a seriação da revisão $2 da página \"$1\". Foi reportado que a revisão usava o modelo de conteúdo $3, seriado como $4.",
        "import-error-bad-location": "A revisão $2, que usa o modelo de conteúdo $3, não pode ser gravada em \"$1\" nesta wiki, porque o modelo não é suportado nessa página.",
        "import-options-wrong": "{{PLURAL:$2|Opção errada|Opções erradas}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "A raiz da página dada é um título inválido.",
        "tooltip-pt-preferences": "As {{GENDER:|suas}} preferências",
        "tooltip-pt-watchlist": "Lista de mudanças nas páginas que está a vigiar",
        "tooltip-pt-mycontris": "Lista das {{GENDER:|suas}} contribuições",
-       "tooltip-pt-anoncontribs": "Uma lista de edições feitas a partir deste endereço de IP",
+       "tooltip-pt-anoncontribs": "Uma lista de edições feitas a partir deste endereço IP",
        "tooltip-pt-login": "É encorajado que inicie sessão, apesar de não ser obrigatório.",
        "tooltip-pt-logout": "Sair da conta",
        "tooltip-pt-createaccount": "É encorajado a criar uma conta e iniciar sessão; no entanto, não é obrigatório",
        "tooltip-ca-move": "Mover esta página",
        "tooltip-ca-watch": "Adicionar esta página à lista de páginas vigiadas",
        "tooltip-ca-unwatch": "Remover esta página da lista de páginas vigiadas",
-       "tooltip-search": "Pesquisar em {{SITENAME}}",
+       "tooltip-search": "Pesquisar na wiki {{SITENAME}}",
        "tooltip-search-go": "Ir para uma página com este nome exacto, caso exista",
        "tooltip-search-fulltext": "Procurar páginas que contêm este texto",
        "tooltip-p-logo": "Visitar a página principal",
        "print.css": "/* Código CSS colocado aqui afectará as impressões */",
        "noscript.css": "/* Os estilos CSS colocados aqui afetarão os utilizadores que tenham o JavaScript desativado em seus navegadores */",
        "common.js": "/* Código Javascript colocado aqui será carregado para todos os utilizadores em cada carregamento de página */",
-       "anonymous": "{{PLURAL:$1|Utilizador anónimo|Utilizadores anónimos}} da {{SITENAME}}",
-       "siteuser": "$1 da {{SITENAME}}",
-       "anonuser": "utilizador anónimo $1 da {{SITENAME}}",
+       "anonymous": "{{PLURAL:$1|Utilizador anónimo|Utilizadores anónimos}} da wiki {{SITENAME}}",
+       "siteuser": "$1 da wiki {{SITENAME}}",
+       "anonuser": "utilizador anónimo $1 da wiki {{SITENAME}}",
        "lastmodifiedatby": "Esta página foi modificada pela última vez à(s) $2 de $1 por $3.",
        "othercontribs": "Baseado no trabalho de $1.",
        "others": "outros",
-       "siteusers": "{{PLURAL:$2|um utilizador|$2 utilizadores}} da {{SITENAME}} ($1)",
-       "anonusers": "{{PLURAL:$2|utilizador anónimo|utilizadores anónimos}} da {{SITENAME}} ($1)",
+       "siteusers": "{{PLURAL:$2|um utilizador|$2 utilizadores}} da wiki {{SITENAME}} ($1)",
+       "anonusers": "{{PLURAL:$2|utilizador anónimo|utilizadores anónimos}} da wiki {{SITENAME}} ($1)",
        "creditspage": "Créditos da página",
        "nocredits": "Não há informação disponível sobre os créditos desta página.",
        "spamprotectiontitle": "Filtro de proteção contra spam",
        "pageinfo-robot-noindex": "Não permitida",
        "pageinfo-watchers": "Número de vigilantes da página",
        "pageinfo-visiting-watchers": "Número de vigilantes que consultaram as edições recentes da página",
-       "pageinfo-few-watchers": "Menos do que $1 {{PLURAL:$1|vigilante|vigilantes}}",
+       "pageinfo-few-watchers": "Menos de $1 {{PLURAL:$1|vigilante|vigilantes}}",
        "pageinfo-few-visiting-watchers": "Pode ou não pode haver editores a vigiar as edições recentes",
        "pageinfo-redirects-name": "Número de redirecionamentos para esta página",
        "pageinfo-subpages-name": "Subpáginas desta página",
        "monthsall": "todos",
        "confirmemail": "Confirmar endereço de correio eletrónico",
        "confirmemail_noemail": "Não tem um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências de utilizador]].",
-       "confirmemail_text": "{{SITENAME}} requer que valide o seu endereço de correio eletrónico antes de usar as funcionalidades de correio.\nClique o botão abaixo para enviar uma mensagem de confirmação para o seu endereço.\nA mensagem incluirá um URL que contém um código;\ninsira o URL no seu navegador para confirmar que o seu endereço de correio eletrónico é válido.",
+       "confirmemail_text": "A wiki {{SITENAME}} requer que valide o seu endereço de correio eletrónico antes de usar as funcionalidades de correio.\nClique o botão abaixo para enviar uma mensagem de confirmação para o seu endereço.\nA mensagem incluirá um URL que contém um código;\ninsira o URL no seu navegador para confirmar que o seu endereço de correio eletrónico é válido.",
        "confirmemail_pending": "Um código de confirmação já lhe foi enviado;\ncaso tenha criado a conta recentemente, é recomendado que aguarde alguns minutos até o receber antes de tentar pedir um novo código.",
        "confirmemail_send": "Enviar código de confirmação",
        "confirmemail_sent": "Correio de confirmação enviado.",
        "confirmemail_oncreate": "Foi enviado um código de confirmação para o seu endereço de correio eletrónico.\nEste código não é necessário para se autenticar no sistema, mas será necessário para ativar qualquer funcionalidade baseada no uso de correio na wiki.",
-       "confirmemail_sendfailed": "A {{SITENAME}} não conseguiu enviar a mensagem de confirmação.\nVerifique se o seu endereço de correio eletrónico tem caracteres inválidos.\n\nO sistema de correio devolveu o erro: $1",
+       "confirmemail_sendfailed": "A wiki {{SITENAME}} não conseguiu enviar a mensagem de confirmação.\nVerifique se o seu endereço de correio eletrónico tem caracteres inválidos.\n\nO sistema de correio devolveu o erro: $1",
        "confirmemail_invalid": "Código de confirmação inválido. O código pode ter expirado.",
        "confirmemail_needlogin": "Precisa de $1 para confirmar o seu endereço de correio eletrónico.",
        "confirmemail_success": "O seu endereço de correio eletrónico foi confirmado.\nPode agora [[Special:UserLogin|autenticar-se]] e desfrutar da wiki.",
        "confirmemail_loggedin": "O seu endereço de correio eletrónico foi confirmado.",
-       "confirmemail_subject": "Confirmação de endereço de correio eletrónico da {{SITENAME}}",
-       "confirmemail_body": "Alguém, provavelmente você a partir do endereço IP $1,\nregistou uma conta \"$2\" com este endereço de correio eletrónico em {{SITENAME}}.\n\nPara confirmar que esta conta é realmente sua e ativar\nas funcionalidades de correio eletrónico em {{SITENAME}}, abra a seguinte ligação no seu navegador:\n\n$3\n\nSe a conta *não* é sua, abra a seguinte ligação para cancelar a confirmação do endereço de correio eletrónico:\n\n$5\n\nEste código de confirmação expira a $4.",
-       "confirmemail_body_changed": "Alguém, provavelmente você a partir do endereço IP $1,\nalterou o endereço de correio eletrónico da conta \"$2\" para este em {{SITENAME}}.\n\nPara confirmar que esta conta é realmente sua e reativar\nas funcionalidades de correio eletrónico em {{SITENAME}},\nabra o seguinte ligação no seu navegador:\n\n$3\n\nCaso a conta *não* lhe pertença, abra a seguinte ligação\npara cancelar a confirmação do endereço de correio eletrónico:\n\n$5\n\nEste código de confirmação expira a $4.",
-       "confirmemail_body_set": "Alguém, provavelmente você a partir do endereço IP $1,\ndefiniu o seu endereço de correio eletrónico como correio da conta \"$2\" em {{SITENAME}}.\n\nPara confirmar que esta conta é realmente sua e reativar\nas funcionalidades de correio eletrónico em {{SITENAME}},\nabra a seguinte ligação no seu navegador:\n\n$3\n\nCaso a conta *não* lhe pertença, abra a seguinte ligação\npara cancelar a confirmação do endereço de correio eletrónico:\n\n$5\n\nEste código de confirmação expira a $4.",
+       "confirmemail_subject": "Confirmação de endereço de correio eletrónico da wiki {{SITENAME}}",
+       "confirmemail_body": "Alguém, provavelmente você a partir do endereço IP $1,\nregistou uma conta \"$2\" com este endereço de correio eletrónico na wiki {{SITENAME}}.\n\nPara confirmar que esta conta é realmente sua e ativar\nas funcionalidades de correio eletrónico na wiki {{SITENAME}}, abra a seguinte ligação no seu navegador:\n\n$3\n\nSe a conta *não* é sua, abra a seguinte ligação para cancelar a confirmação do endereço de correio eletrónico:\n\n$5\n\nEste código de confirmação expira a $4.",
+       "confirmemail_body_changed": "Alguém, provavelmente você a partir do endereço IP $1,\nalterou o endereço de correio eletrónico da conta \"$2\" para este endereço, na wiki{{SITENAME}}.\n\nPara confirmar que esta conta é realmente sua e reativar\nas funcionalidades de correio eletrónico na wiki {{SITENAME}},\nabra a seguinte ligação no seu navegador:\n\n$3\n\nCaso a conta *não* lhe pertença, abra a seguinte ligação\npara cancelar a confirmação do endereço de correio eletrónico:\n\n$5\n\nEste código de confirmação expira a $4.",
+       "confirmemail_body_set": "Alguém, provavelmente você a partir do endereço IP $1,\ndefiniu o seu endereço de correio eletrónico como correio da conta \"$2\" na wiki {{SITENAME}}.\n\nPara confirmar que esta conta é realmente sua e reativar\nas funcionalidades de correio eletrónico na wiki {{SITENAME}},\nabra a seguinte ligação no seu navegador:\n\n$3\n\nCaso a conta *não* lhe pertença, abra a seguinte ligação\npara cancelar a confirmação do endereço de correio eletrónico:\n\n$5\n\nEste código de confirmação expira a $4.",
        "confirmemail_invalidated": "Confirmação de endereço de correio eletrónico cancelada",
        "invalidateemail": "Cancelar confirmação do correio eletrónico",
-       "notificationemail_subject_changed": "O endereço de correio eletrónico registado em {{SITENAME}} foi alterado",
-       "notificationemail_subject_removed": "O endereço de correio eletrónico registado em {{SITENAME}} foi removido",
-       "notificationemail_body_changed": "Alguém, provavelmente você, a partir do endereço IP $1, alterou o endereço de correio eletrónico da conta \"$2\" para \"$3\" em {{SITENAME}}.\n\nCaso não tenha alterado, contacte imediatamente um administrador do sítio.",
-       "notificationemail_body_removed": "Alguém, provavelmente você, a partir do endereço IP $1, eliminou o endereço de correio eletrónico da conta \"$2\" em {{SITENAME}}.\n\nCaso não tenha alterado, contacte imediatamente um administrador do sítio.",
+       "notificationemail_subject_changed": "O endereço de correio eletrónico registado na wiki {{SITENAME}} foi alterado",
+       "notificationemail_subject_removed": "O endereço de correio eletrónico registado na wiki {{SITENAME}} foi removido",
+       "notificationemail_body_changed": "Alguém, provavelmente você, a partir do endereço IP $1, alterou o endereço de correio eletrónico da conta \"$2\" para \"$3\" na wiki {{SITENAME}}.\n\nCaso não o tenha alterado, contacte imediatamente um administrador do sítio.",
+       "notificationemail_body_removed": "Alguém, provavelmente você, a partir do endereço IP $1, eliminou o endereço de correio eletrónico da conta \"$2\" na wiki {{SITENAME}}.\n\nCaso não o tenha eliminado, contacte imediatamente um administrador do sítio.",
        "scarytranscludedisabled": "[Transclusão interwikis foi impossibilitada]",
        "scarytranscludefailed": "[Não foi possível obter a predefinição a partir de $1]",
        "scarytranscludefailed-httpstatus": "[Não foi possível obter a predefinição a partir de $1: HTTP $2]",
        "specialpages-group-users": "Utilizadores e privilégios",
        "specialpages-group-highuse": "Páginas muito usadas",
        "specialpages-group-pages": "Listas de páginas",
-       "specialpages-group-pagetools": "Ferramentas de páginas",
+       "specialpages-group-pagetools": "Ferramentas de página",
        "specialpages-group-wiki": "Dados e ferramentas",
-       "specialpages-group-redirects": "Redirecionar páginas especiais",
+       "specialpages-group-redirects": "Páginas especiais de redirecionamento",
        "specialpages-group-spam": "Ferramentas anti-spam",
        "specialpages-group-developer": "Ferramentas de desenvolvimento",
        "blankpage": "Página em branco",
        "tags-deactivate": "desativar",
        "tags-hitcount": "$1 {{PLURAL:$1|modificação|modificações}}",
        "tags-manage-no-permission": "Não possui permissão para gerir alterações de etiquetas.",
-       "tags-manage-blocked": "Não pode gerir etiquetas de modificação enquanto estiver bloqueado.",
+       "tags-manage-blocked": "Não pode gerir etiquetas de modificação enquanto estiver {{GENDER:$1|bloqueado|bloqueada}}.",
        "tags-create-heading": "Criar nova etiqueta",
        "tags-create-explanation": "Por definição, etiquetas recém-criadas estarão disponíveis para utilização por utilizadores e robôs.",
        "tags-create-tag-name": "Nome da etiqueta:",
        "tags-deactivate-not-allowed": "Não é possível desativar a etiqueta \"$1\".",
        "tags-deactivate-submit": "Desativar",
        "tags-apply-no-permission": "Não possui privilégios para aplicar alterações a etiquetas em conjunto com as suas modificações.",
-       "tags-apply-blocked": "Não pode aplicar etiquetas de modificação nas suas alterações enquanto estiver bloqueado.",
+       "tags-apply-blocked": "Não pode aplicar etiquetas de modificação nas suas alterações enquanto estiver {{GENDER:$1|bloqueado|bloqueada}}.",
        "tags-apply-not-allowed-one": "A etiqueta \"$1\" não pode ser aplicada manualmente.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|A seguinte etiqueta não pode ser aplicada|As seguintes etiquetas não podem ser aplicadas}} manualmente: $1",
        "tags-update-no-permission": "Não possui privilégios para adicionar ou remover etiquetas de revisões individuais ou entradas de registo.",
-       "tags-update-blocked": "Não pode adicionar ou remover etiquetas de modificação enquanto estiver bloqueado.",
+       "tags-update-blocked": "Não pode adicionar ou remover etiquetas de modificação enquanto estiver {{GENDER:$1|bloqueado|bloqueada}}.",
        "tags-update-add-not-allowed-one": "A etiqueta \"$1\" não pode ser adicionada manualmente.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|A seguinte etiqueta não pode ser adicionada|As seguintes etiquetas não podem ser adicionadas}} manualmente: $1",
        "tags-update-remove-not-allowed-one": "A remoção da etiqueta \"$1\" não é permitida.",
        "htmlform-user-not-exists": "<strong>$1</strong> não existe.",
        "htmlform-user-not-valid": "<strong>$1</strong> não é um nome de utilizador válido.",
        "logentry-delete-delete": "$1 apagou a página $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|eliminou}} o redirecionamento $3, sobrescrevendo-o",
        "logentry-delete-restore": "$1 restaurou a página $3",
        "logentry-delete-event": "$1 alterou a visibilidade de {{PLURAL:$5|uma entrada|$5 entradas}} em $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|alterou}} a visibilidade de {{PLURAL:$5|uma revisão|$5 revisões}} em $3: $4",
        "feedback-thanks": "Obrigado! O seu comentário foi adicionado à página \"[$2 $1]\".",
        "feedback-thanks-title": "Obrigado!",
        "feedback-useragent": "Agente de utilizador:",
-       "searchsuggest-search": "Pesquisar em {{SITENAME}}",
+       "searchsuggest-search": "Pesquisar na wiki {{SITENAME}}",
        "searchsuggest-containing": "contendo...",
-       "api-error-autoblocked": "O seu endereço de IP foi bloqueado automaticamente, pois foi utilizado por um utilizador bloqueado.",
+       "api-error-autoblocked": "O seu endereço IP foi bloqueado automaticamente, pois foi utilizado por um utilizador bloqueado.",
        "api-error-badaccess-groups": "Não tem permissão para enviar ficheiros para esta wiki.",
        "api-error-badtoken": "Erro interno: Chave incorrecta.",
        "api-error-blocked": "Foi bloqueado de editar.",
        "duration-centuries": "$1 {{PLURAL:$1|século|séculos}}",
        "duration-millennia": "$1 {{PLURAL:$1|milénio|milénios}}",
        "rotate-comment": "Imagem rodada em $1 {{PLURAL:$1|grau|graus}} no sentido dos ponteiros do relógio",
-       "limitreport-title": "Dados de perfis do analisador:",
+       "limitreport-title": "Dados de caracterização do analisador sintático:",
        "limitreport-cputime": "Tempo de utilização da CPU",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|segundo|segundos}}",
        "limitreport-walltime": "Tempo real de utilização",
        "limitreport-templateargumentsize": "Tamanho dos argumentos da predefinição",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|byte|bytes}}",
        "limitreport-expansiondepth": "Profundidade máxima de expansão",
-       "limitreport-expensivefunctioncount": "Número de funções do analisador custosas",
+       "limitreport-expensivefunctioncount": "Número de funções exigentes do analisador sintático",
        "expandtemplates": "Expandir predefinições",
        "expand_templates_intro": "Esta página especial recebe um texto e expande recursivamente todas as predefinições nele existentes.\nTambém expande funções do analisador sintático ''(parser)'', tais como\n<nowiki>{{</nowiki>#language:...}}, e variáveis, como\n<nowiki>{{</nowiki>CURRENTDAY}}.\nNa verdade, expande tudo o que estiver entre chavetas duplas.",
        "expand_templates_title": "Título de contexto para {{FULLPAGENAME}} etc.:",
        "expand_templates_generate_xml": "Mostrar a árvore de análise sintáctica do XML",
        "expand_templates_generate_rawhtml": "Mostrar o HTML puro",
        "expand_templates_preview": "Antevisão do resultado",
-       "expand_templates_preview_fail_html": "<em>Devido ao fato de {{SITENAME}} possuir código HTML puro ativado e de ter havido perda de dados da sessão, a pré-visualização ficará oculta como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma legítima tentativa de visualização, por favor tente novamente.</strong>\nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite a utilização de ''cookies'' deste sítio.",
-       "expand_templates_preview_fail_html_anon": "<em>Devido ao fato de {{SITENAME}} possuir código HTML puro ativado e de não ter sessão iniciada, a pré-visualização ficará oculta como precaução contra ataques do JavaScript.</em>\n\n<strong>Se esta é uma legítima tentativa de visualização, por favor [[Especial:UserLogin|inicie sessão]] e tente novamente.</strong>",
+       "expand_templates_preview_fail_html": "<em>Porque a wiki {{SITENAME}} permite código HTML puro e ocorreu uma perda de dados da sessão, a antevisão ficará ocultada como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de visionamento, por favor tente novamente.</strong>\nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite que este site crie ''cookies''.",
+       "expand_templates_preview_fail_html_anon": "<em>Porque a wiki {{SITENAME}} permite código HTML puro e não iniciou uma sessão, a antevisão ficará ocultada como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de visionamento, por favor [[Special:UserLogin|inicie uma sessão]] e tente novamente.</strong>",
        "expand_templates_input_missing": "Necessita de fornecer pelo menos algum texto de entrada.",
        "pagelanguage": "Alterar idioma da página",
        "pagelang-name": "Página",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (ativado)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>desativado</strong>)",
        "mediastatistics": "Estatísticas multimédia",
-       "mediastatistics-summary": "Estatísticas sobre os tipos de ficheiros carregados. Inclui apenas a versão mais recente do ficheiro. Versões antigas ou eliminadas são excluídas.",
+       "mediastatistics-summary": "Estatísticas sobre os tipos de ficheiro carregados. Inclui apenas a versão mais recente de cada ficheiro. Versões antigas ou eliminadas não estão incluídas.",
        "mediastatistics-nbytes": "{{PLURAL:$1|$1 byte|$1 bytes}} ($2; $3%)",
-       "mediastatistics-bytespertype": "Tamanho total dos ficheiros para esta secção: {{PLURAL:$1|$1 byte|$1 bytes}} ($2; $3%).",
+       "mediastatistics-bytespertype": "Tamanho total dos ficheiros desta secção: {{PLURAL:$1|$1 byte|$1 bytes}} ($2; $3%).",
        "mediastatistics-allbytes": "Tamanho total de todos os ficheiros: {{PLURAL:$1|$1 byte|$1 bytes}} ($2).",
        "mediastatistics-table-mimetype": "Tipo MIME",
        "mediastatistics-table-extensions": "Extensões possíveis",
        "mediastatistics-header-total": "Todos os ficheiros",
        "json-warn-trailing-comma": "$1 {{PLURAL:$1|vírgula desnecessária foi removida|vírgulas desnecessárias foram removidas}} do código JSON",
        "json-error-unknown": "Houve um problema com o JSON. Erro: $1",
-       "json-error-depth": "A profundidade máxima da pilha foi excedida",
+       "json-error-depth": "A profundidade máxima do ''stack'' foi excedida",
        "json-error-state-mismatch": "Código JSON inválido ou mal formatado",
        "json-error-ctrl-char": "Erro de carácter de controlo, possivelmente codificado incorretamente",
        "json-error-syntax": "Erro de sintaxe",
        "special-characters-title-endash": "hífen",
        "special-characters-title-emdash": "travessão",
        "special-characters-title-minus": "sinal de subtração",
-       "mw-widgets-dateinput-no-date": "Nenhuma data selecionada",
+       "mw-widgets-dateinput-no-date": "Não foi selecionada nenhuma data",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Procurar ficheiros multimédia",
+       "mw-widgets-mediasearch-noresults": "Não foram encontrados resultados.",
        "mw-widgets-titleinput-description-new-page": "a página ainda não existe.",
        "mw-widgets-titleinput-description-redirect": "redirecionar para $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Adicionar uma categoria...",
        "sessionmanager-tie": "Não se pode combinar múltiplas solicitações de tipos de autenticação: $1.",
        "sessionprovider-generic": "Sessões $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessões baseadas em cookie",
        "log-action-filter-delete": "Tipo de eliminação:",
        "log-action-filter-import": "Tipo de importação:",
        "log-action-filter-managetags": "Tipo de ação de gestão de etiqueta:",
-       "log-action-filter-move": "Tipo do movimento:",
+       "log-action-filter-move": "Tipo de movimentação:",
        "log-action-filter-newusers": "Tipo de criação de conta:",
        "log-action-filter-patrol": "Tipo de patrulha:",
        "log-action-filter-protect": "Tipo de proteção:",
        "log-action-filter-suppress": "Tipo de supressão:",
        "log-action-filter-upload": "Tipo de carregamento:",
        "log-action-filter-all": "Todas",
-       "log-action-filter-block-block": "Bloquear",
+       "log-action-filter-block-block": "Bloqueio",
        "log-action-filter-block-reblock": "Alteração de bloqueio",
-       "log-action-filter-block-unblock": "Desbloquear",
-       "log-action-filter-contentmodel-change": "Edição de modelo de conteúdo",
-       "log-action-filter-contentmodel-new": "Criação de página com modelo de conteúdo desconhecido",
+       "log-action-filter-block-unblock": "Desbloqueio",
+       "log-action-filter-contentmodel-change": "Alteração de modelo de conteúdo",
+       "log-action-filter-contentmodel-new": "Criação de página com modelo de conteúdo não padronizado",
        "log-action-filter-delete-delete": "Eliminação de página",
+       "log-action-filter-delete-delete_redir": "Sobrescrição de redirecionamento",
        "log-action-filter-delete-restore": "Restauro de página",
        "log-action-filter-delete-event": "Eliminação de registo",
        "log-action-filter-delete-revision": "Eliminação de revisão",
-       "log-action-filter-import-interwiki": "Importação de transwiki",
+       "log-action-filter-import-interwiki": "Importação transwikis",
        "log-action-filter-import-upload": "Importação por carregamento XML",
        "log-action-filter-managetags-create": "Criação de etiqueta",
        "log-action-filter-managetags-delete": "Eliminação de etiqueta",
        "log-action-filter-managetags-activate": "Ativação de etiqueta",
        "log-action-filter-managetags-deactivate": "Desativação de etiqueta",
-       "log-action-filter-move-move": "Mover sem a substituição de páginas de redirecionamento",
-       "log-action-filter-move-move_redir": "Mover com a substituição de páginas de redirecionamento",
+       "log-action-filter-move-move": "Movimentação sem sobrescrever páginas de redirecionamento",
+       "log-action-filter-move-move_redir": "Movimentação sobrescrevendo páginas de redirecionamento",
        "log-action-filter-newusers-create": "Criação por utilizador anónimo",
        "log-action-filter-newusers-create2": "Criação por utilizador registado",
        "log-action-filter-newusers-autocreate": "Criação automática",
        "log-action-filter-protect-protect": "Proteção",
        "log-action-filter-protect-modify": "Alteração da proteção",
        "log-action-filter-protect-unprotect": "Desproteção",
-       "log-action-filter-protect-move_prot": "Proteção de movimentos",
+       "log-action-filter-protect-move_prot": "Proteção de movimentações",
        "log-action-filter-rights-rights": "Alteração manual",
        "log-action-filter-rights-autopromote": "Alteração automática",
        "log-action-filter-suppress-event": "Supressão de registo",
        "log-action-filter-suppress-block": "Supressão de utilizadores por bloqueio",
        "log-action-filter-suppress-reblock": "Supressão de utilizador por rebloqueio",
        "log-action-filter-upload-upload": "Novo carregamento",
-       "log-action-filter-upload-overwrite": "Recarregar",
+       "log-action-filter-upload-overwrite": "Recarregamento",
        "authmanager-authn-not-in-progress": "A autenticação não está em curso ou os dados da sessão foram perdidos. Comece novamente desde o princípio, por favor.",
        "authmanager-authn-no-primary": "As informações de identificação fornecidas não podem ser autenticadas.",
        "authmanager-authn-no-local-user": "As credenciais fornecidas não estão associadas a nenhum utilizador nesta wiki.",
        "restrictionsfield-badip": "Endereço IP (ou gama de endereços IP) inválido: $1",
        "restrictionsfield-label": "Gamas de endereços IP permitidas:",
        "restrictionsfield-help": "Um endereço IP ou uma gama CIDR por linha. Para ativar todos,\nuse<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Erro: $1",
-       "edit-error-long": "Erros:\n\n$1"
+       "pageid": "identificador de página $1"
 }
index e5df378..6fb46dd 100644 (file)
        "october-gen": "{{doc-months|10|genitive}}\n{{Identical|October}}",
        "november-gen": "{{doc-months|11|genitive}}\n{{Identical|November}}",
        "december-gen": "{{doc-months|12|genitive}}\n{{Identical|December}}",
-       "jan": "{{doc-months|1|short}}",
-       "feb": "{{doc-months|2|short}}",
-       "mar": "{{doc-months|3|short}}",
-       "apr": "{{doc-months|4|short}}",
-       "may": "{{doc-months|5|short}}",
-       "jun": "{{doc-months|6|short}}",
-       "jul": "{{doc-months|7|short}}",
-       "aug": "{{doc-months|8|short}}",
-       "sep": "{{doc-months|9|short}}",
-       "oct": "{{doc-months|10|short}}",
+       "jan": "{{doc-months|1|short}}\n{{Identical|January}}",
+       "feb": "{{doc-months|2|short}}\n{{Identical|February}}",
+       "mar": "{{doc-months|3|short}}\n{{Identical|March}}",
+       "apr": "{{doc-months|4|short}}\n{{Identical|April}}",
+       "may": "{{doc-months|5|short}}\n{{Identical|May}}",
+       "jun": "{{doc-months|6|short}}\n{{Identical|June}}",
+       "jul": "{{doc-months|7|short}}\n{{Identical|July}}",
+       "aug": "{{doc-months|8|short}}\n{{Identical|August}}",
+       "sep": "{{doc-months|9|short}}\n{{Identical|September}}",
+       "oct": "{{doc-months|10|short}}\n{{Identical|October}}",
        "nov": "{{doc-months|11|short}}",
        "dec": "{{doc-months|12|short}}",
        "january-date": "A date in the Gregorian month of January. $1 is the numerical date, for example \"23\".\n{{Identical|January}}",
        "february-date": "A date in the Gregorian month of February. $1 is the numerical date, for example \"23\".\n{{Identical|February}}",
        "march-date": "A date in the Gregorian month of March. $1 is the numerical date, for example \"23\".\n{{Identical|March}}",
-       "april-date": "A date in the Gregorian month of April. $1 is the numerical date, for example \"23\".",
+       "april-date": "A date in the Gregorian month of April. $1 is the numerical date, for example \"23\".\n{{Identical|April}}",
        "may-date": "A date in the Gregorian month of May. $1 is the numerical date, for example \"23\". The month name is not abbreviated.\n{{Identical|May}}",
-       "june-date": "A date in the Gregorian month of June. $1 is the numerical date, for example \"23\".",
-       "july-date": "A date in the Gregorian month of July. $1 is the numerical date, for example \"23\".",
-       "august-date": "A date in the Gregorian month of August. $1 is the numerical date, for example \"23\".",
-       "september-date": "A date in the Gregorian month of September. $1 is the numerical date, for example \"23\".",
-       "october-date": "A date in the Gregorian month of October. $1 is the numerical date, for example \"23\".",
+       "june-date": "A date in the Gregorian month of June. $1 is the numerical date, for example \"23\".\n{{Identical|June}}",
+       "july-date": "A date in the Gregorian month of July. $1 is the numerical date, for example \"23\".\n{{Identical|July}}",
+       "august-date": "A date in the Gregorian month of August. $1 is the numerical date, for example \"23\".\n{{Identical|August}}",
+       "september-date": "A date in the Gregorian month of September. $1 is the numerical date, for example \"23\".\n{{Identical|September}}",
+       "october-date": "A date in the Gregorian month of October. $1 is the numerical date, for example \"23\".\n{{Identical|October}}",
        "november-date": "A date in the Gregorian month of November. $1 is the numerical date, for example \"23\".\n{{Identical|November}}",
        "december-date": "A date in the Gregorian month of December. $1 is the numerical date, for example \"23\".",
        "period-am": "Text indicating the first period of the day when using a 12-hour calendar.",
        "talk": "Used as display name for the tab to all {{msg-mw|Talk}} pages. These pages accompany all content pages and can be used for discussing the content page. Example: [[Talk:Example]].\n\nSee also:\n* {{msg-mw|Talk}}\n* {{msg-mw|Accesskey-ca-talk}}\n* {{msg-mw|Tooltip-ca-talk}}\n{{Identical|Discussion}}",
        "views": "Subtitle for the list of available views, for the current page. In \"monobook\" skin the list of views are shown as tabs, so this sub-title is not shown. For an example, see [{{canonicalurl:Main_Page|useskin=simple}} Main Page using simple skin].\n\n'''Note:''' This is \"views\" as in \"appearances\"/\"representations\", '''not''' as in \"visits\"/\"accesses\".\n{{Identical|View}}",
        "toolbox": "The title of the toolbox below the search menu.\n{{Identical|Tool}}",
-       "tool-link-userrights": "Link to [[Special:UserRights]] (user rights management) in the sidebar toolbox.\n\nParameters:\n* $1 - Name of user for the user group management (usable for GENDER)",
+       "tool-link-userrights": "Link to [[Special:UserRights]] (user rights management) in the sidebar toolbox, shown if the current user is allowed to change given user's groups.\n\nParameters:\n* $1 - Name of user for the user group management (usable for GENDER)",
+       "tool-link-userrights-readonly": "Link to [[Special:UserRights]] (user rights management) in the sidebar toolbox, shown if the current user is '''not''' allowed to change given user's groups.\n\nParameters:\n* $1 - Name of user for the user group management (usable for GENDER)",
        "tool-link-emailuser": "Link to [[Special:EmailUser]] (email user tool) in the sidebar toolbox.\n\nParameters:\n* $1 - Name of user who would receive the email\n\nSee also:\n* {{msg-mw|Emailuser-title-target}}",
        "userpage": "Used in user talk pages as the text of the link to the user page, with the Cologne Blue skin.",
        "projectpage": "Used as link text in Talk page of project page with the Cologne Blue skin.",
        "passwordreset-emaildisabled": "Used as error message in changing password when site's email feature is disabled.",
        "passwordreset-username": "{{Identical|Username}}",
        "passwordreset-domain": "A domain like used in Domain Name System (DNS) or more specifically like a domain component in the Lightweight Directory Access Protocol (LDAP).\n{{Identical|Domain}}",
-       "passwordreset-capture": "Label for checkbox asking the user whether they want to see the contents of the password reset email (only shown if they have the <code>passwordreset</code> permission).",
-       "passwordreset-capture-help": "Longer explanatory message for the capture checkbox label.",
        "passwordreset-email": "{{Identical|E-mail address}}",
        "passwordreset-emailtitle": "Used as subject (title) of email.",
        "passwordreset-emailtext-ip": "Be consistent with {{msg-mw|Passwordreset-emailtext-user}}.\n\nParameters:\n* $1 - an IP address\n* $2 - message {{msg-mw|Passwordreset-emailelement}} repeated $3 times\n* $3 - the number of repetitions in $2\n* $4 - base URL of the wiki\n* $5 - number of days",
        "passwordreset-emailelement": "This is a body of a password reset email to allow them into the system with a new password. Parameters:\n* $1 - the user's login name. This parameter can be used for GENDER.\n* $2 - the temporary password given by the system",
        "passwordreset-emailsentemail": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
        "passwordreset-emailsentusername": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
-       "passwordreset-emailsent-capture2": "Used in [[Special:PasswordReset]].\n\nParameters:\n* $1 - number of accounts notified\n\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
-       "passwordreset-emailerror-capture2": "Error message displayed in [[Special:PasswordReset]] when sending an email fails. Parameters:\n* $1 - error message\n* $2 - username, used for GENDER\n* $3 - number of accounts notified\n\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
        "passwordreset-nocaller": "Shown when a password reset was requested but the process failed due to an internal error related to missing details about the origin (caller) of the password reset request.",
        "passwordreset-nosuchcaller": "Shown when a password reset was requested but the username of the caller could not be resolved to a user. This is an internal error.\n\nParameters:\n* $1 - username of the caller",
        "passwordreset-ignored": "Shown when password reset was unsuccessful due to configuration problems.",
-       "passwordreset-invalideamil": "Returned when the email address is syntatically invalid.",
+       "passwordreset-invalidemail": "Returned when the email address is syntatically invalid.",
        "passwordreset-nodata": "Returned when no data was provided.",
        "changeemail": "Title of [[Special:ChangeEmail|special page]]. This page also allows removing the user's email address.",
        "changeemail-summary": "{{ignored}}",
        "searchdisabled": "{{doc-singularthey}}\nIn this sentence, \"their indexes\" refers to \"Google's indexes\".\n\nShown on [[Special:Search]] when the internal search is disabled.",
        "googlesearch": "{{notranslate}}\nShown when [[mw:Manual:$wgDisableTextSearch|$wgDisableTextSearch]] is set to true and no [[mw:Manual:$wgSearchForwardUrl|$wgSearchForwardUrl]] is set.\n\nParameters:\n* $1 - the search term\n* $2 - \"UTF-8\" (hard-coded)\n* $3 - the message {{msg-mw|Searchbutton}}",
        "search-error": "Shown when an error has occurred when performing a search. Parameters:\n* $1 - the localized error that was returned",
+       "search-warning": "Shown when a warning has occured when performing a search. Parameters:\n* $1 - the localized warning that was returned.",
        "opensearch-desc": "{{ignored}}Link description of the [www.opensearch.org/ OpenSearch] link in the HTML head of pages.",
        "preferences": "Title of the [[Special:Preferences]] page.\n{{Identical|Preferences}}",
        "preferences-summary": "{{doc-specialpagesummary|preferences}}",
        "prefs-help-recentchangescount": "Used in [[Special:Preferences]], tab \"Recent changes\".",
        "prefs-help-watchlist-token2": "Used in [[Special:Preferences]], tab Watchlist. (Formerly in {{msg-mw|prefs-help-watchlist-token}}.)",
        "savedprefs": "This message appears after saving changes to your user preferences.",
-       "savedrights": "This message appears after saving the user rights on [[Special:UserRights]].\n* $1 - The user name of the user which rights was saved.",
+       "savedrights": "This message appears after saving the user groups on [[Special:UserRights]].\n* $1 - The user name of the user which groups was saved.",
        "timezonelegend": "{{Identical|Time zone}}",
        "localtime": "Used as label in [[Special:Preferences#mw-prefsection-datetime|preferences]].",
        "timezoneuseserverdefault": "[[Special:Preferences]] > Date and time > Time zone\n\nThis option lets your time zone setting use the one that is used on the wiki (often UTC).\n\nParameters:\n* $1 - timezone name, or timezone offset (in \"%+03d:%02d\" format)",
        "userrights-summary": "{{doc-specialpagesummary|userrights}}",
        "userrights-lookup-user": "Label text when managing user rights ([[Special:UserRights]])",
        "userrights-user-editname": "Displayed on [[Special:UserRights]].",
-       "editusergroup": "Button name, in page [[Special:Userrights]] (only available to administrators), in the section named {{MediaWiki:userrights-lookup-user}}.\n\n{{Identical|Edit user groups}}.\nParameters:\n* $1 - username, for GENDER support",
-       "editinguser": "Appears on [[Special:UserRights]]. Parameters:\n* $1 - a plaintext username\n* $2 - user tool links. e.g. \"(Talk | contribs | block | send email)\"",
-       "userrights-editusergroup": "Parameter:\n* $1 - (Optional) a username, can be used for GENDER\n{{Identical|Edit user groups}}",
+       "editusergroup": "Button name, in page [[Special:Userrights]], in the section named {{MediaWiki:userrights-lookup-user}}. The username or gender of the user is not known when this message is displayed.",
+       "editinguser": "Appears on [[Special:UserRights]]. Parameters:\n* $1 - a plaintext username\n* $2 - user tool links. e.g. \"(Talk | contribs | block | send email)\"\n\nRelated messages:\n* {{msg-mw|viewinguserrights}}",
+       "viewinguserrights": "Appears on [[Special:UserRights]]. Parameters:\n* $1 - a plaintext username\n* $2 - user tool links. e.g. \"(Talk | contribs | block | send email)\"\n\nRelated messages:\n* {{msg-mw|editinguser}}",
+       "userrights-editusergroup": "Parameter:\n* $1 - (Optional) a username, can be used for GENDER\n\nRelated messages:\n* {{msg-mw|userrights-viewusergroup}}",
+       "userrights-viewusergroup": "Parameter:\n* $1 - (Optional) a username, can be used for GENDER\n\nRelated messages:\n* {{msg-mw|userrights-editusergroup}}",
        "saveusergroups": "Button text when editing user groups.\nParameters:\n* $1 - username, for GENDER support",
        "userrights-groupsmember": "Used when editing user groups in [[Special:Userrights]].\n\nThe message is followed by a list of group names.\n\nParameters:\n* $1 - (Optional) the number of items in the list following the message, for PLURAL\n* $2 - (Optional) the user name, for GENDER",
        "userrights-groupsmember-auto": "Used when editing user groups in [[Special:Userrights]]. The message is followed by a list of group names.\n\n\"Implicit\" is for groups that the user was automatically added to (such as \"autoconfirmed\"); cf. {{msg-mw|userrights-groupsmember}}\n\nParameters:\n* $1 - (Optional) the number of items in the list following the message, for PLURAL\n* $2 - (Optional) the user name, for GENDER",
        "userrights-reason": "Text beside log field when editing user groups\n\n{{Identical|Reason}}",
        "userrights-no-interwiki": "Error message when editing user groups",
        "userrights-nodatabase": "Error message when editing user groups.\n\n\"Local\" means databases/wikis of the same farm/cluster; that is, meta, enwiki, dewiki, commons, etc are all local databases of the Wikimedia Foundation.\n\nSee [{{canonicalurl:meta:Special:Log|type=rights}} meta:Special:Log?type=rights] for a usage of local databases: username@barwiki\n\nParameters:\n* $1 - database name",
-       "userrights-nologin": "Error displayed on [[Special:UserRights]] when you aren't logged in.\n\nIf you are logged in, but don't have the correct permission, you see {{msg-mw|Userrights-notallowed}}.",
-       "userrights-notallowed": "Error displayed on [[Special:UserRights]] when you don't have the permission.",
        "userrights-changeable-col": "Used when editing user groups in [[Special:Userrights]].\n\nThe message is the head of a column of group assignments.\n\nParameters:\n* $1 - (Optional) for PLURAL use, the number of items in the column following the message. Avoid PLURAL, if your language can do without.",
        "userrights-unchangeable-col": "Used when editing user groups in [[Special:Userrights]]. The message is the head of a column of group assignments.\n\nParameters:\n* $1 - (Optional) for PLURAL use, the number of items in the column following the message. Avoid PLURAL, if your language allows that.",
        "userrights-irreversible-marker": "{{optional}}\nParameters:\n* $1 - group member",
        "userrights-conflict": "Shown on [[Special:UserRights]] if the target's rights have been changed since the form was loaded.",
-       "userrights-removed-self": "Shown on [[Special:UserRights]] in a green box after the user removed its own rights to access that page.",
        "group": "{{Identical|Group}}",
        "group-user": "{{doc-group|user}}\n{{Identical|User}}",
        "group-autoconfirmed": "{{doc-group|autoconfirmed}}\nOn Wikimedia sites autoconfirmed users are users which are older than 4 days. After those 4 days, they have more rights.",
        "right-siteadmin": "{{doc-right|siteadmin}}",
        "right-override-export-depth": "{{doc-right|override-export-depth}}",
        "right-sendemail": "{{doc-right|sendemail}}",
-       "right-passwordreset": "{{doc-right|passwordreset}}",
        "right-managechangetags": "{{doc-right|managechangetags}}",
        "right-applychangetags": "{{doc-right|applychangetags}}",
        "right-changetags": "{{doc-right|changetags}}",
        "action-writeapi": "{{Doc-action|writeapi}}\n\nAPI is an abbreviation for [[w:API|application programming interface]].",
        "action-delete": "{{Doc-action|delete}}",
        "action-deleterevision": "{{Doc-action|deleterevision}}",
+       "action-deletelogentry": "{{Doc-action|deletelogentry}}",
        "action-deletedhistory": "{{Doc-action|deletedhistory}}",
+       "action-deletedtext": "{{Doc-action|deletedtext}}",
        "action-browsearchive": "{{Doc-action|browsearchive}}",
        "action-undelete": "{{Doc-action|undelete}}",
        "action-suppressrevision": "{{Doc-action|suppressrevision}}",
        "action-userrights-interwiki": "{{Doc-action|userrights-interwiki}}",
        "action-siteadmin": "{{Doc-action|siteadmin}}",
        "action-sendemail": "{{doc-action|sendemail}}\n{{Identical|E-mail}}",
+       "action-editmyoptions": "{{Doc-action|editmyoptions}}",
        "action-editmywatchlist": "{{doc-action|editmywatchlist}}\n{{Identical|Edit your watchlist}}",
        "action-viewmywatchlist": "{{doc-action|viewmywatchlist}}\n{{Identical|View your watchlist}}",
        "action-viewmyprivateinfo": "{{doc-action|viewmyprivateinfo}}",
        "apisandbox-continue": "Button text for sending another request using query continuation.\n{{Identical|Continue}}",
        "apisandbox-continue-clear": "Button text for clearing query continuation parameters.\n{{Identical|Clear}}",
        "apisandbox-continue-help": "Help text for the continue and clear buttons.",
+       "apisandbox-param-limit": "Additional documentation text for 'limit'-type parameters.",
+       "apisandbox-multivalue-all-namespaces": "Used as an entry in a multiple-namespace widget to select all available namespaces. Parameters:\n* $1 - API input value meaning \"all namespaces\".",
+       "apisandbox-multivalue-all-values": "Used as an entry in a multiple-value widget to select all available values. Parameters:\n* $1 - API input value meaning \"all values\".",
        "booksources": "{{doc-special|BookSources}}\n\n'''This message shouldn't be changed unless it has serious mistakes.'''\n\nIt's used as the page name of the configuration page of [[Special:BookSources]]. Changing it breaks existing sites using the default version of this message.\n\nSee also:\n* {{msg-mw|Booksources|title}}\n* {{msg-mw|Booksources-text|text}}",
        "booksources-summary": "{{doc-specialpagesummary|booksources}}",
        "booksources-search-legend": "Box heading on [[Special:BookSources|book sources]] special page. The box is for searching for places where a particular book can be bought or viewed.",
        "activeusers-count": "Used in [[Special:ActiveUsers]] to show the active user's recent action count in brackets ([]).\n* $1 is the number of recent actions\n* $2 is the user's name for use with GENDER (optional)\n* $3 is the maximum number of days of the RecentChangesList",
        "activeusers-from": "Used as label for checkbox in the form on [[Special:ActiveUsers]].\n\nidentical with {{msg-mw|listusersfrom}}\n\nSee also:\n* {{msg-mw|activeusers|legend for the form}}",
        "activeusers-groups": "Used as label on [[Special:ActiveUsers]].",
+       "activeusers-excludegroups": "Used as an option on [[Special:ActiveUsers]].",
        "activeusers-noresult": "identical with {{msg-mw|listusers-noresult}}",
        "activeusers-submit": "Used as label for button in the form on [[Special:ActiveUsers]]",
        "listgrouprights": "The name of the special page [[Special:ListGroupRights]].",
        "listgrants-summary": "Explanatory text shown at the top of the grant/rights mapping table.\n\nRefers to {{msg-mw|Listgrouprights-helppage}}.",
        "listgrants-grant": "Used as table header for the grant/rights mapping table.\n{{Identical|Grant}}",
        "listgrants-rights": "Used as table header for the grant/rights mapping table.\n{{Identical|Right}}",
+       "listgrants-grant-display": "{{optional}}\nUsed to display the code name of a grant next to the grant. Parameters:\n* $1 - the text from the \"grant-...\" messages, i.e. {{msg-mw|Grant-highvolume}}\n* $2 - the codename of this grant",
        "trackingcategories": "[[Special:TrackingCategories]] page implementing list of Tracking categories [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]].\n{{Identical|Tracking category}}",
        "trackingcategories-summary": "Description for [[Special:TrackingCategories]] page [[mw:Help:Tracking categories|tracking category]]",
        "trackingcategories-msg": "Header for the message column of the table on [[Special:TrackingCategories]]. This column lists the mediawiki message that controls the tracking category in question.\n{{Identical|Tracking category}}",
        "tags-deactivate": "Used on [[Special:Tags]]. Verb. Used as display text on a link to deactivate a tag.\n{{Identical|Delete}}",
        "tags-hitcount": "Shown in the \"{{msg-mw|Tags-hitcount-header}}\" column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].\n\nParameters:\n* $1 - the number of changes marked with the tag",
        "tags-manage-no-permission": "Error message on [[Special:Tags]]",
-       "tags-manage-blocked": "Error message on [[Special:Tags]]",
+       "tags-manage-blocked": "Error message on [[Special:Tags]]\n\nParameters:\n* $1 - user name for gender",
        "tags-create-heading": "The title of a fieldset, beneath which lies a form used to create a tag. For more information on tags see [[mw:Manual:Tags|MediaWiki]].",
        "tags-create-explanation": "The first paragraph of an explanation to tell users what they are about to do.",
        "tags-create-tag-name": "Form field label for the name of the tag to be created.",
        "tags-deactivate-not-allowed": "Error message on [[Special:Tags]]",
        "tags-deactivate-submit": "The label of the form \"submit\" button when the user is about to deactivate a tag.\n{{Identical|Deactivate}}",
        "tags-apply-no-permission": "Error message seen via the API when a user lacks the permission to apply change tags.",
-       "tags-apply-blocked": "Error message seen via the API when a user is blocked and attempted to apply change tags.",
+       "tags-apply-blocked": "Error message seen via the API when a user is blocked and attempted to apply change tags.\n\nParameters:\n* $1 - user name for gender",
        "tags-apply-not-allowed-one": "Error message seen via the API when a user tries to apply a single tag that is not properly defined. This message is only ever used in the case of 1 tag.\n\nParameters:\n* $1 - tag name",
        "tags-apply-not-allowed-multi": "Error message seen via the API when a user tries to apply more than one tag that is not properly defined.\n\nParameters:\n* $1 - comma-separated list of tag names\n* $2 - number of tags",
        "tags-update-no-permission": "Error message seen via the API when a user lacks the permission to add or remove change tags after the fact.",
-       "tags-update-blocked": "Error message seen via the API when a user is blocked and attempted to add or remove change tags after the fact.",
+       "tags-update-blocked": "Error message seen via the API when a user is blocked and attempted to add or remove change tags after the fact.\n\nParameters:\n* $1 - user name for gender",
        "tags-update-add-not-allowed-one": "Error message seen via the API when a user tries to add a single tag that is not properly defined. This message is only ever used in the case of 1 tag.\n\nParameters:\n* $1 - tag name",
        "tags-update-add-not-allowed-multi": "Error message seen via the API when a user tries to add more than one tag that is not properly defined.\n\nParameters:\n* $1 - comma-separated list of tag names\n* $2 - number of tags",
        "tags-update-remove-not-allowed-one": "Error message seen via the API when a user tries to remove a single tag that is not properly defined. This message is only ever used in the case of 1 tag.\n\nParameters:\n* $1 - tag name",
        "htmlform-user-not-valid": "Error message shown if the name provided by the user isn't a valid username. $1 is the username.",
        "rawmessage": "{{notranslate}} Used to pass arbitrary text as a message specifier array",
        "logentry-delete-delete": "{{Logentry|[[Special:Log/delete]]}}",
+       "logentry-delete-delete_redir": "{{Logentry|[[Special:Log/delete]]}}",
        "logentry-delete-restore": "{{Logentry|[[Special:Log/delete]]}}",
        "logentry-delete-event": "{{Logentry|[[Special:Log/delete]]}}\n{{Logentryparam}}\n* $5 - count of affected log events",
        "logentry-delete-revision": "{{Logentry|[[Special:Log/delete]]}}\n{{Logentryparam}}\n* $5 - the number of affected revisions of the page $3",
        "mediastatistics-header-audio": "Header on [[Special:MediaStatistics]] for file types that are in the audio category\n{{Identical|Audio}}",
        "mediastatistics-header-video": "Header on [[Special:MediaStatistics]] for file types that are in the video category\n{{Identical|Video}}",
        "mediastatistics-header-multimedia": "Header on [[Special:MediaStatistics]] for file types that are in the multimedia category. This does not include plain audio or video files, but more complex multimedia such as flash or vrml. This especially includes scripted multimedia. Ogg files in which MediaWiki cannot determine if it is an audio or video file (or something else) are included here.",
-       "mediastatistics-header-office": "Header on [[Special:MediaStatistics]] for file types that are in the Office category. This includes PDFs, OpenDocument files, Microsoft Word files, etc.",
+       "mediastatistics-header-office": "Header on [[Special:MediaStatistics]] for file types that are in the Office category. This includes PDFs, OpenDocument files, Microsoft Word files, etc.\n{{Identical|Office}}",
        "mediastatistics-header-text": "Header on [[Special:MediaStatistics]] for file types that are in the text category. This includes simple text formats, including plain text formats, json, csv, and xml. Source code of compiled programming languages may be included here in the future, but isn't currently.",
        "mediastatistics-header-executable": "Header on [[Special:MediaStatistics]] for file types that are in the executable category. This includes things like source files for interpreted programming language (Shell scripts, javascript, etc).",
        "mediastatistics-header-archive": "Header on [[Special:MediaStatistics]] for file types that are in the archive category. Includes things like tar, zip, gzip etc.",
        "mw-widgets-dateinput-no-date": "Label of a date input field when no date has been selected.",
        "mw-widgets-dateinput-placeholder-day": "[[File:DateInputWidget active, empty.png|frame|Screenshot]]\nPlaceholder displayed in a date input field when it's empty, representing a date format with 4 digits for year, 2 digits for month, and 2 digits for day, separated with hyphens. This should be uppercase, if possible, and must not include any additional explanations. If there is no good way to translate it, make this message blank.",
        "mw-widgets-dateinput-placeholder-month": "Placeholder displayed in a date input field when it's empty, representing a date format with 4 digits for year and 2 digits for month, separated with hyphens (without a day). This should be uppercase, if possible, and must not include any additional explanations. If there is no good way to translate it, make this message blank.",
+       "mw-widgets-mediasearch-input-placeholder": "Place holder text for media search input",
+       "mw-widgets-mediasearch-noresults": "Label notifying the user no results were found for the media search.",
        "mw-widgets-titleinput-description-new-page": "Description label for a new page in the title input widget.",
        "mw-widgets-titleinput-description-redirect": "Description label for a redirect in the title input widget.",
+       "mw-widgets-categoryselector-add-category-placeholder": "Placeholder displayed in the category selector widget after the capsules of already added categories.",
        "sessionmanager-tie": "Used as an error message when multiple session sources are tied in priority.\n\nParameters:\n* $1 - List of dession type descriptions, from messages like {{msg-mw|sessionprovider-mediawiki-session-cookiesessionprovider}}.",
        "sessionprovider-generic": "Used to create a generic session type description when one isn't provided via the proper message. Should be phrased to make sense when added to a message such as {{msg-mw|cannotloginnow-text}}.\n\nParameters:\n* $1 - PHP classname.",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "Description of the sessions provided by the CookieSessionProvider class, which use HTTP cookies. Should be phrased to make sense when added to a message such as {{msg-mw|cannotloginnow-text}}.",
        "sessionprovider-nocookies": "Used to inform the user that sessions may be missing due to lack of cookies.",
        "randomrootpage": "{{doc-special|RandomRootPage}}",
-       "log-action-filter-block": "{{doc-log-action-filter-type|block}}",
-       "log-action-filter-contentmodel": "{{doc-log-action-filter-type|contentmodel}}",
-       "log-action-filter-delete": "{{doc-log-action-filter-type|delete}}",
-       "log-action-filter-import": "{{doc-log-action-filter-type|import}}",
-       "log-action-filter-managetags": "{{doc-log-action-filter-type|managetags}}",
-       "log-action-filter-move": "{{doc-log-action-filter-type|move}}",
-       "log-action-filter-newusers": "{{doc-log-action-filter-type|newusers}}",
-       "log-action-filter-patrol": "{{doc-log-action-filter-type|patrol}}",
-       "log-action-filter-protect": "{{doc-log-action-filter-type|protect}}",
-       "log-action-filter-rights": "{{doc-log-action-filter-type|rights}}",
-       "log-action-filter-suppress": "{{doc-log-action-filter-type|suppress}}",
-       "log-action-filter-upload": "{{doc-log-action-filter-type|upload}}",
-       "log-action-filter-all": "{{doc-log-action-filter-type|all}}\n{{Identical|All}}",
+       "log-action-filter-block": "{{doc-log-action-filter-type|block}}\n{{related|Log-action-filter}}",
+       "log-action-filter-contentmodel": "{{doc-log-action-filter-type|contentmodel}}\n{{related|Log-action-filter}}",
+       "log-action-filter-delete": "{{doc-log-action-filter-type|delete}}\n{{related|Log-action-filter}}",
+       "log-action-filter-import": "{{doc-log-action-filter-type|import}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-managetags": "{{doc-log-action-filter-type|managetags}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-move": "{{doc-log-action-filter-type|move}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-newusers": "{{doc-log-action-filter-type|newusers}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-patrol": "{{doc-log-action-filter-type|patrol}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-protect": "{{doc-log-action-filter-type|protect}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-rights": "{{doc-log-action-filter-type|rights}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-suppress": "{{doc-log-action-filter-type|suppress}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-upload": "{{doc-log-action-filter-type|upload}}\n{{Related|Log-action-filter}}",
+       "log-action-filter-all": "{{doc-log-action-filter-type|all}}\n{{related|Log-action-filter}}\n{{Identical|All}}",
        "log-action-filter-block-block": "{{doc-log-action-filter-action|block|block}}\n{{Identical|Block}}",
        "log-action-filter-block-reblock": "{{doc-log-action-filter-action|block|reblock}}",
        "log-action-filter-block-unblock": "{{doc-log-action-filter-action|block|unblock}}\n{{Identical|Unblock}}",
        "log-action-filter-contentmodel-change": "{{doc-log-action-filter-action|contentmodel|change}}",
        "log-action-filter-contentmodel-new": "{{doc-log-action-filter-action|contentmodel|new}}",
        "log-action-filter-delete-delete": "{{doc-log-action-filter-action|delete|delete}}",
+       "log-action-filter-delete-delete_redir": "{{doc-log-action-filter-action|delete|delete_redir}}",
        "log-action-filter-delete-restore": "{{doc-log-action-filter-action|delete|restore}}",
        "log-action-filter-delete-event": "{{doc-log-action-filter-action|delete|event}}",
        "log-action-filter-delete-revision": "{{doc-log-action-filter-action|delete|revision}}",
        "restrictionsfield-badip": "An error message shown when one entered an invalid IP address or range in a restrictions field (such as Special:BotPassword). $1 is the IP address.",
        "restrictionsfield-label": "Field label shown for restriction fields (e.g. on Special:BotPassword).",
        "restrictionsfield-help": "Placeholder text displayed in restriction fields (e.g. on Special:BotPassword).",
-       "edit-error-short": "Error message. Parameters:\n* $1 - the error details\nSee also:\n* {{msg-mw|edit-error-long}}\n{{Identical|Error}}",
-       "edit-error-long": "Error message. Parameters:\n* $1 - the error details\nSee also:\n* {{msg-mw|edit-error-short}}\n{{Identical|Error}}"
+       "revid": "Used to format a revision ID number in text. Parameters:\n* $1 - Revision ID number.",
+       "pageid": "Used to format a page ID number in text. Parameters:\n* $1 - Page ID number."
 }
index 6de7ea2..e1c2830 100644 (file)
        "yourname": "Rurak shuti:",
        "yourpassword": "Yaykunkapak rimay:",
        "yourpasswordagain": "Yaykunapak rimayta kutin killkapay:",
-       "remembermypassword": "Kay Internet-wampunapi {{PLURAL:$1|shuk punchata|$1 punchakunata}} ñuka rurak shutiwan yaykushkami katichiwapay.",
        "login": "Yaykuna",
        "nav-login-createaccount": "Yaykuna",
        "userlogin": "Yaykuna",
index 52111d3..6e54be3 100644 (file)
        "activeusers-intro": "Quai è ina glista dals utilisaders che han gì activitads {{PLURAL:$1|l'ultim di|en ils ultims $1 dis}}.",
        "activeusers-count": "$1 {{PLURAL:$1|acziun|acziuns}} {{PLURAL:$3|l'ultim di|ils ultims $3 dis}}",
        "activeusers-from": "Mussar utilisaders davent da:",
-       "activeusers-hidebots": "Zuppentar bots",
-       "activeusers-hidesysops": "Zuppentar administraturs",
        "activeusers-noresult": "Chattà nagins utilisaders.",
        "listgrouprights": "Dretgs da las gruppas d'utilisaders",
        "listgrouprights-summary": "Sutvart vegn mussada ina glista da las gruppas d'utilisaders sin questa wiki cun ils dretgs d'access associads.\nInfurmaziuns supplementaras davart ils singuls dretgs chattas [[{{MediaWiki:Listgrouprights-helppage}}|sin questa pagina]].",
index d113101..f6a017d 100644 (file)
        "passwordreset-emaildisabled": "Funcțiile de e-mail au fost dezactivate de pe acest wiki.",
        "passwordreset-username": "Nume de utilizator:",
        "passwordreset-domain": "Domeniu:",
-       "passwordreset-capture": "Vizualizați e-mailul rezultat?",
-       "passwordreset-capture-help": "Dacă bifați această căsuță, e-mailul (conținând parola temperară) vă va fi afișat, dar va fi trimis și utilizatorului.",
        "passwordreset-email": "Adresă de e-mail:",
        "passwordreset-emailtitle": "Detalii despre cont pe {{SITENAME}}",
        "passwordreset-emailtext-ip": "Cineva (probabil dumneavoastră, de la adresa IP $1) a solicitat resetarea parolei \npentru {{SITENAME}} ($4). {{PLURAL:$3|Următorul cont este asociat|Următoarele conturi sunt asociate}}\ncu această adresă de e-mail:\n\n$2\n\n{{PLURAL:$3|Această parolă temporară va|Aceste parole temporare vor}} expira {{PLURAL:$5|într-o zi|în $5 zile}}.\nAr trebui să vă autentificați și să schimbați parola acum. Dacă altcineva a făcut această cerere \nsau dacă v-ați reamintit parola inițială și nu mai doriți să o schimbați,\nputeți ignora acest mesaj, continuând să utilizați vechea parolă.",
        "passwordreset-emailelement": "Nume de utilizator: \n$1\n\nParolă temporară: \n$2",
        "passwordreset-emailsentemail": "Dacă această adresă de e-mail este asociată contului dumneavoastră, atunci se va trimite un e-mail de resetare a parolei.",
        "passwordreset-emailsentusername": "Dacă există o adresă de e-mail asociată acestui nume de utilizator, atunci se va trimite un e-mail de resetare a parolei.",
-       "passwordreset-invalideamil": "Adresă de e-mail nevalidă",
+       "passwordreset-invalidemail": "Adresă de e-mail nevalidă",
        "passwordreset-nodata": "Nu au fost furnizate un nume de utilizator sau o adresă de e-mail",
        "changeemail": "Modificare sau înlăturare adresă de e-mail",
        "changeemail-header": "Completați acest formular pentru a vă schimba adresa de e-mail. Dacă doriți să înlăturați orice asociere a unei adrese de e-mail cu contul dumneavoastră, lăsați necompletat câmpul pentru introducerea unei noi adrese de e-mail atunci când trimiteți formularul.",
        "userrights-reason": "Motiv:",
        "userrights-no-interwiki": "Nu aveți permisiunea de a modifica permisiunile utilizatorilor pe alte wiki.",
        "userrights-nodatabase": "Baza de date $1 nu există sau nu este locală.",
-       "userrights-nologin": "Trebuie să te [[Special:UserLogin|autentifici]] cu un cont de administrator pentru a atribui permisiuni utilizatorilor.",
-       "userrights-notallowed": "Nu aveți permisiunea de a acorda sau elimina drepturi utilizatorilor.",
        "userrights-changeable-col": "Grupuri pe care le puteți schimba",
        "userrights-unchangeable-col": "Grupuri pe care nu le puteți schimba",
        "userrights-conflict": "Conflict al schimbării drepturilor de utilizator! Reverificați și confirmați-vă modificările.",
-       "userrights-removed-self": "V-ați eliminat propriile drepturi. Ca urmare, nu mai puteți accesa această pagină.",
        "group": "Grup:",
        "group-user": "Utilizatori",
        "group-autoconfirmed": "Utilizatori autoconfirmați",
        "right-siteadmin": "Blochează și deblochează baza de date",
        "right-override-export-depth": "Exportă inclusiv paginile legate până la o adâncime de 5",
        "right-sendemail": "Trimite e-mail altor utilizatori",
-       "right-passwordreset": "Vizualizează e-mailurile de reinițializare a parolelor",
        "right-managechangetags": "Creează și (dez)activează [[Special:Tags|etichete]]",
        "right-applychangetags": "Aplică [[Special:Tags|etichete]] asociate modificărilor unui utilizator",
        "right-changetags": "Adaugă și înlătură [[Special:Tags|etichete]] arbitrare din versiuni și intrări de jurnal individuale",
        "grant-oversight": "Ascunde utilizatori și suprimă versiuni",
        "grant-patrol": "Patrulează schimbările paginilor",
        "grant-basic": "Drepturi de bază",
+       "grant-viewmywatchlist": "Vezi lista de pagini urmărite",
        "newuserlogpage": "Jurnal utilizatori noi",
        "newuserlogpagetext": "Acesta este jurnalul creărilor conturilor de utilizator.",
        "rightslog": "Jurnal permisiuni de utilizator",
        "activeusers-intro": "Aceasta este o listă cu utilizatorii care au avut orice fel de activitate în {{PLURAL:$1|ultima zi|ultimele $1 zile}}.",
        "activeusers-count": "{{PLURAL:$1|o acțiune|$1 acțiuni|$1 de acțiuni}} în {{PLURAL:$3|ultima zi|ultimele $3 zile|ultimele $3 de zile}}",
        "activeusers-from": "Afișează utilizatori începând cu:",
-       "activeusers-hidebots": "Ascunde roboții",
-       "activeusers-hidesysops": "Ascunde administratorii",
        "activeusers-noresult": "Niciun utilizator găsit.",
        "activeusers-submit": "Afișează utilizatorii activi",
        "listgrouprights": "Permisiuni grupuri de utilizatori",
index ad4e913..026e178 100644 (file)
@@ -15,6 +15,7 @@
        "tog-hideminor": "Scunne le cangiaminde stuédeche jndr'à le cangiaminde recende",
        "tog-hidepatrolled": "Scunne le cangiaminde condrollate jndr'à le cangiaminde recende",
        "tog-newpageshidepatrolled": "Scunne le pàggene tenute sotte condrolle da l'elenghe de le pàggene nuève",
+       "tog-hidecategorization": "Scunne le categorije d'a vôsce",
        "tog-extendwatchlist": "Spanne l'elenghe de le pàggene condrollate pe fa vedè tutte le cangiaminde fatte, none sulamende l'urteme",
        "tog-usenewrc": "Cangiaminde d'u gruppe pe pàgene jndr'à le urteme cangiaminde e elenghe de le pàggene condrollate",
        "tog-numberheadings": "Testate auto-numerate",
@@ -25,6 +26,7 @@
        "tog-watchdefault": "Mitte le pàggene ca je agghie cangiate jndr'à le pàggene condrollate",
        "tog-watchmoves": "Mitte le pàggene ca je agghie spustate jndr'à le pàggene condrollate",
        "tog-watchdeletion": "Mitte le pàggene ca je agghie scangellate jndr'à le pàggene condrollate",
+       "tog-watchuploads": "Aggiunge file nuéve a l'elenghe de le pàggene condrollate",
        "tog-watchrollback": "Aggiunge le pàggene addò agghie fatte 'n'annullamende jndr'à l'elenghe de le pàggene condrollate",
        "tog-minordefault": "Pe convenzione signe tutte le cangiaminde cumme stuédeche",
        "tog-previewontop": "Fa vedè l'andeprime apprime d'a caselle de le cangiaminde",
        "tog-watchlisthidebots": "Scunne le cangiaminde de le bot da l'elenghe de le pàggene condrollate",
        "tog-watchlisthideminor": "Scunne le cangiaminde stuèdeche da l'elenghe de le pàggene condrollate",
        "tog-watchlisthideliu": "Scunne le cangiaminde de l'utinde canusciute da l'elenghe de le pàggene condrollate",
+       "tog-watchlistreloadautomatically": "Recareche automaticamende l'eleghe de le pàggene condrollate quanne cange 'nu filtre (richieste Javascript)",
        "tog-watchlisthideanons": "Scunne le cangiaminde de l'utinde scanusciute da l'elenghe de le pàggene condrollate",
        "tog-watchlisthidepatrolled": "Scunne le cangiaminde condrollate jndr'à l'elenghe de le pàggene condrollate",
+       "tog-watchlisthidecategorization": "Scunne 'a categorizzazzione d'a vôsce",
        "tog-ccmeonemails": "Manneme 'na copie de le mail ca je manne a l'ôtre utinde",
        "tog-diffonly": "No fà vedè le pàggene cu le condenute sotte a le differenze",
        "tog-showhiddencats": "Fa vedè le categorije scunnute",
        "october-date": "Ottommre $1",
        "november-date": "Novemmre $1",
        "december-date": "Decemmre $1",
+       "period-am": "AM",
+       "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Categorije|Categorije}}",
        "category_header": "Pàggene jndr'à categorie \"$1\"",
        "subcategories": "Sotte Categorije",
        "morenotlisted": "Ste elenghe non g'è comblete.",
        "mypage": "'A pàgena meje",
        "mytalk": "'Ngazzaminde mie",
-       "anontalk": "'Ngazzaminde pe quiste IP",
+       "anontalk": "'Ngazzaminde",
        "navigation": "Naveghesce",
        "and": "&#32;e",
        "qbfind": "Cirche",
        "talk": "'Ngazzaminde",
        "views": "Visite",
        "toolbox": "Struminde",
+       "tool-link-userrights": "Cange le gruppe {{GENDER:$1|utinde}}",
+       "tool-link-userrights-readonly": "'Ndruche le gruppe {{GENDER:$1|utinde}}",
+       "tool-link-emailuser": "Manne 'na mail a stu {{GENDER:$1|utende}}",
        "userpage": "Vide a pàgene de l'utende",
        "projectpage": "Vide a pàgene de le pruggette",
        "imagepage": "Vide a pàgene de le file",
        "laggedslavemode": "Attenzione: 'A pàgene no ge tène cangiaminde recente.",
        "readonly": "Archivie blocchete",
        "enterlockreason": "Mitte 'na raggione p'u blocche, 'ncludenne 'na stime de quanne 'u blocche avène luate.",
-       "readonlytext": "'U database jndr'à stu mumende jè blocchete pe nueve 'nzereminde e otre cangiaminde, pò essere 'nu blocche pe 'na manutenziona de ''routine'', apprisse 'a quale torne tutte a poste.\n\nLe amministrature ca onne mise 'u blocche onne date sta motivazione: $1",
+       "readonlytext": "'U database jndr'à stu mumende ète bloccate pe 'nzereminde nuéve e otre cangiaminde, pò essere 'nu blocche pe 'na manutenziona de ''routine'', apprisse 'a quale torne tutte a poste.\n\nLe amministrature ca onne mise 'u blocche onne date sta mutivazione: $1",
        "missing-article": "'U database non ge iacchije 'u teste de 'na pàgene ca avesse acchià, nnomenete \"$1\" $2.\n\nStu fatte pò succedere quanne le collegaminde 'mbrà le differenze o le cunde non ge sonde aggiornete sus a 'na pàgene ca ha state scangellete.\n\nCe quiste non g'è 'u case, tu pò essere ca è 'cchiate 'nu bochere jndr'à 'u software.\nPe piacere manne 'na comunicazzione a 'n'[[Special:ListUsers/sysop|amministratore]], mettène jndr'à note pure l'URL.",
        "missingarticle-rev": "(versione#: $1)",
        "missingarticle-diff": "(Diff: $1, $2)",
        "mypreferencesprotected": "Non ge tìne le permesse pe cangià le preferenze tune.",
        "ns-specialprotected": "Le pàgene speciale no ponne essere cangete.",
        "titleprotected": "Stu titele ha state prutette da 'a ccreazione da [[User:$1|$1]].\n'U mutive jè <em>$2</em>.",
-       "filereadonlyerror": "Non ge pozze cangià 'u file \"$1\" purcé l'archivije de le file \"$2\" ste in mode sola letture.\n\nL'amministratore ca l'ha bloccate dèje sta spiegazione: \"$3\".",
+       "filereadonlyerror": "Non ge pozze cangià 'u file \"$1\" purcé l'archivije de le file \"$2\" ste in sola letture.\n\nL'amministratore d'u sisteme ca l'ave bloccate dèje sta spiegazione: \"$3\".",
        "invalidtitle-knownnamespace": "Titole invalide cu 'u namespace \"$2\" e teste \"$3\"",
        "invalidtitle-unknownnamespace": "Titele invalide cu numere de namespace scanusciute $1 e teste \"$2\"",
        "exception-nologin": "Non ge sì collegate",
        "userlogin-remembermypassword": "Arrecuèrdeme",
        "userlogin-signwithsecure": "Ause 'na connessione secure",
        "cannotlogin-title": "Non ge puè trasé",
+       "cannotcreateaccount-title": "Non ge pué ccrejà le cunde utinde",
        "yourdomainname": "'U nome d'u dominie tue:",
        "password-change-forbidden": "Non ge puè cangià le passuord sus a sta uicchi.",
        "externaldberror": "Vide bbuene, o stè 'n'errore de autendicazione a 'u database oppure tu non ge puè aggiorna 'u cunde tue esterne.",
        "noname": "Non gìè specifichete 'nu nome utende valide.",
        "loginsuccesstitle": "Tutte a poste, è trasute!",
        "loginsuccess": "'''Mò tu si colleghete jndr'à {{SITENAME}} cumme \"$1\".'''",
-       "nosuchuser": "Non g'esiste n'utende cu 'u nome \"$1\".\nFà attenzione ca le nome de l'utinde so senzibbele a le lettere granne e piccenne.\nVide bbuene a cumme l'è scritte, o [[Special:CreateAccount|ccreje n'utende nuève]].",
+       "nosuchuser": "Non g'esiste n'utende cu 'u nome \"$1\".\nLe nome de l'utinde so senzibbele a le lettere granne e piccenne.\nVide bbuene a cumme l'è scritte, o [[Special:CreateAccount|ccreje n'utende nuève]].",
        "nosuchusershort": "Non ge ste nisciune utende cu 'u nome \"$1\".\nCondrolle accume l'è scritte.",
        "nouserspecified": "A scrivere pe forze 'u nome de l'utende.",
        "login-userblocked": "Stu utende jè bloccate. Non ge puè trasè.",
        "noemail": "Non ge stonne email reggistrete pe l'utende \"$1\".",
        "noemailcreate": "Tu ha mèttere 'n'indirizze e-mail valide",
        "passwordsent": "'Na nova passuord ha state mannete a l'indirizze e-mail reggistrete pe \"$1\".\nPe piacere, colleghete n'otra vota quanne l'è ricevute.",
-       "blocked-mailpassword": "L'indirizze IP tue jè blocchete pe le cangiaminde e accussì tu non ge puè ausà 'a funzione de recupere d'a password pe prevenìe l'abbuse.",
+       "blocked-mailpassword": "L'indirizze IP tune jè bloccate pe le cangiaminde. Tu non ge puè ausà 'a funzione de recupere d'a password pe prevenìe l'abbuse.",
        "eauthentsent": "'N'e-mail de conferme ha state mannate a l'indirizze ca tu è ditte.\nApprime ca otre e-mail avènene mannate a 'u cunde tune, tu ha seguì le 'struzione ca stonne jndr'à l'e-mail, pe confermà ca 'u cunde jè une de le tune.",
        "throttled-mailpassword": "'Nu arrecordatore de passuord ha stete già mannate jndr'à {{PLURAL:$1|l'urtema ore|l'urteme $1 ore}}.\nPe prevenì l'abbuse, sulamende 'nu arrecordatore de passuord avene mannate ogne {{PLURAL:$1|ore|$1 ore}}.",
        "mailerror": "Errore mannanne 'a mail: $1",
-       "acct_creation_throttle_hit": "Le visitature de sta Uicchi ca stonne ausene stu indirizze IP onne ccrejete {{PLURAL:$1|'nu cunde utende|$1 cunde utinde}} jndr'à l'urteme giurne, e onne raggiunde 'u numere massime ca se pò fà jndr'à stu periode.\n'U resultete jè ca le visitature ca stonne ausene stu indirizze IP non ge ponne ccrejà otre cunde utinde nuève jndr'à stu mumende.",
+       "acct_creation_throttle_hit": "Le visitature de sta Uicchi ca stonne ausene stu indirizze IP onne ccrejate {{PLURAL:$1|'nu cunde utende|$1 cunde utinde}} jndr'à l'urteme $2, e onne raggiunde 'u numere massime ca se pò fà jndr'à stu periode.\n'U resultate éte ca le visitature ca stonne ausene stu indirizze IP non ge ponne ccrejà otre cunde utinde nuève jndr'à stu mumende.",
        "emailauthenticated": "L'indirizze e-mail ca ne date ha state confermate 'u sciurne $2 a le $3.",
        "emailnotauthenticated": "L'indirizze e-mail tune non g'a state angore confermate.\nNisciuna mail t'avène mannate pe tutte le seguende dettaglie.",
        "noemailprefs": "Specifiche 'n'indirizze e-mail pe ste dettaglie ca onne essere fatiete.",
        "createacct-another-realname-tip": "'U nome vere jè facoltative.\nCe tu scacchie de metterle, quiste avène ausate pe dà 'u giuste merite a 'a fatìe de l'utende.",
        "pt-login": "Tràse",
        "pt-login-button": "Tràse",
+       "pt-login-continue-button": "Condinue a trasé",
        "pt-createaccount": "Ccreje 'nu cunde utende",
        "pt-userlogout": "Isse",
        "php-mail-error-unknown": "Errore scanusciute jndr'à funzione PHP mail()",
        "resetpass_submit": "'Mboste 'a passuord e colleghete",
        "changepassword-success": "'A password toje ha state cangiate!",
        "changepassword-throttled": "Tu è pruvate 'nu sacche de vote a trasè.\nPe piacere aspitte $1 apprime de pruvà arrete.",
+       "botpasswords": "Password d'u bot",
+       "botpasswords-label-appid": "Nome d'u bot:",
+       "botpasswords-label-create": "Ccreje",
+       "botpasswords-label-update": "Aggiorne",
+       "botpasswords-label-cancel": "Annulle",
+       "botpasswords-label-delete": "Scangìlle",
+       "botpasswords-label-resetpassword": "Azzere 'a passuord",
        "resetpass_forbidden": "Le Password non ge ponne cangià",
        "resetpass-no-info": "Tu a essere colleghete pe accedere a sta pàgene direttamende.",
        "resetpass-submit-loggedin": "Cange 'a password",
        "resetpass-submit-cancel": "Annulle",
-       "resetpass-wrong-oldpass": "'A password temboranea o quedda corrende jè invalide.\nPò essere ca tu è già cangete 'a password toje o è richieste una temboranea nove.",
+       "resetpass-wrong-oldpass": "'A password temboranée o quedda corrende non g'è valide.\nPò essere ca tu è già cangiate 'a password toje o n'è cercate una nove temboranée.",
        "resetpass-recycled": "Pe piacere azzere 'a password toje cu 'n'otra password deverse da quedde de mò.",
        "resetpass-temp-emailed": "Tu è trasute cu 'nu codece email tembaranèe.\nPe spiccià de trasè, tu ha 'mbostà 'na password nove aqquà:",
        "resetpass-temp-password": "Password temboranea:",
        "passwordreset-emaildisabled": "Le funziune de l'email onne state disabbilitate sus a sta uicchi.",
        "passwordreset-username": "Nome utende:",
        "passwordreset-domain": "Dominie:",
-       "passwordreset-capture": "Vide 'a mail resultande?",
-       "passwordreset-capture-help": "Ce tu signe sta sckatele, 'a mail (cu 'a passuord temboranèe) t'avène fatte vedè cumme adda essere mannate a l'utende.",
        "passwordreset-email": "Indirizze e-mail:",
        "passwordreset-emailtitle": "Dettaglie d'u cunde utende sus a {{SITENAME}}",
        "passwordreset-emailtext-ip": "Quacchedune (pò essere tu, da 'u 'ndirizze IP $1) ha richieste 'na mail pe arrecurdarse de le dettaglie d'u cunde sue pe {{SITENAME}} ($4). {{PLURAL:$3|'U cunde utende seguende jè|le cunde utinde seguende sonde}} associate cu st'indirizze e-mail:\n\n$2\n\n{{PLURAL:$3|Sta passuord temboranèe scade|Ste passuord temboranèe scadene}} 'mbrà {{PLURAL:$5|'nu sciurne|$5 sciurne}}.\nTu avissa trasè e scacchià 'na passuord nova. Ce quacchedun'otre ha fatte sta richieste, o ce tu t'è arrecurdate 'a passuord origgenale toje, e non g'a vuè ccu cange cchiù, tu puè ignorà stu messagge e condinuà ausanne 'a passuord vecchie.",
        "passwordreset-emailtext-user": "L'utende $1 sus a {{SITENAME}} ave richieste 'na mail pe arrecurdarse le dettaglie d'u cunde sue pe {{SITENAME}}\n($4). {{PLURAL:$3|'U cunde utende seguende jè|le cunde utinde seguende sonde}} associate cu st'indirizze e-mail:\n\n$2\n\n{{PLURAL:$3|Sta passuord temboranèe scade|Ste passuord temboranèe scadene}}  'mbrà {{PLURAL:$5|'nu sciurne|$5 sciurne}}.\nTu avissa trasè e scacchià 'na passuord nova. Ce quacchedun'otre ha fatte sta richieste, o ce tu t'è arrecurdate 'a passuord origgenale toje, e non g'a vuè ccu cange cchiù, tu puè ignorà stu messagge e condinuà ausanne 'a passuord vecchie.",
        "passwordreset-emailelement": "Nome utende: \n$1\n\nPassuord temboranèe: \n$2",
-       "passwordreset-emailsentemail": "Ce quiste jè 'n'e-mail pu cunde tune, allore 'na password azzerate ha state mannate addà.",
+       "passwordreset-emailsentemail": "Ce queste éte 'n'e-mail pu cunde tune, allore 'na password azzerate ha state mannate addà.",
        "changeemail": "Cange o live 'u 'ndirizze e-mail",
        "changeemail-header": "Comblete stu module pe cangià 'u 'ndirizze email. Ce tu vuè ccu live l'associazione cu ogne indirizze email da 'u cunde tune, lasse 'u 'ndirizze email vacande quanne conferme 'u module.",
        "changeemail-no-info": "Tu a essere collegate pe accedere a sta pàgene direttamende.",
        "accmailtext": "'A passuord ccrejate a uecchije pe [[User talk:$1|$1]] ha state mannate sus a $2.\n\n'A passuord pe stu cunde utende pò essere cangiate sus a pàgene ''[[Special:ChangePassword|cange passuord]]'' 'na vote ca è trasute.",
        "newarticle": "(Nuève)",
        "newarticletext": "Tu ste segue 'nu collegamende a pàgene ca angore non g'esiste.\nPe ccrejà 'a pàgene, accuminze a scrivere jndr'à 'u scatole de sotte (vide 'a [$1 pàggene d'ajute] pe avè cchiù 'mbormaziune).\nCe tu te iacche aqquà e manghe tu 'u se purcè, allore cazze 'u buttone '''back''' d'u brauser.",
-       "anontalkpagetext": "----''Queste jè 'na pàgene de 'ngazzaminde pe 'n'utende anonime, ca non ge vò ccu ccreje angore 'nu cunde utende, o de ce non g'u use.\nNuje auseme 'n'indirizze IP (ca jè numereche) pe identificarle.\nE' normale ca essende 'n'indirizze IP pò essere ausete pure da otre utinde ca 'u pigghiene.\nCe tu non ge si 'n'utende anonime e pinze ca le commende ca so revolte a te sonde studecarije, pe piacere [[Special:CreateAccount|ccreje 'nu cunde utende]] o [[Special:UserLogin|tràse]] pe no fà confusione jndr'à 'u future cu otre utinde anoneme.''",
+       "anontalkpagetext": "----\n<em>Queste jè 'na pàgene de 'ngazzaminde pe 'n'utende anonime, ca non ge vò ccu ccreje angore 'nu cunde utende, o de ce non g'u use.</em>\nNuje ausame 'n'indirizze IP (ca éte numereche) pe identificarle.\nE' normale ca pu fatte ca 'n'indirizze IP pò essere ausate pure da otre utinde ca 'u pigghiane.\nCe tu non ge si 'n'utende anonime e pinze ca le commende ca te arrivane sonde studecarije, pe piacere [[Special:CreateAccount|ccreje 'nu cunde utende]] o [[Special:UserLogin|tràse]] pe no fà confusione jndr'à 'u future cu otre utinde anoneme.",
        "noarticletext": "Non ge stè scritte ninde jndr'à sta pàgene.\nTu puè [[Special:Search/{{PAGENAME}}|cercà pe quiste titole]] jndr'à otre pàggene, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cirche l'archivije sue] o [{{fullurl:{{FULLPAGENAME}}|action=edit}} ccreje sta pàgene]</span>.",
        "noarticletext-nopermission": "Pe mò non ge stè teste jndr'à sta pàgene.\nTu puè [[Special:Search/{{PAGENAME}}|cercà pe stu titole]] jndr'à otre pàggene,\no <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cirche jndr'à l'archivije cullegate]</span>, ma non ge tìne le permesse pe ccrejà sta pàgene.",
        "missing-revision": "'A revisione #$1 d'a pàgene chiamate \"{{FULLPAGENAME}}\" non g'esiste.\n\nQuiste succede normalmende purcé 'u cunde jè collegate a 'na pàgene ca ha state scangellate.\nLe dettaglie le puè acchià jndr'à l'[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} archivije de le scangellaziune].",
        "userpage-userdoesnotexist": "'U cunde utende \"<nowiki>$1</nowiki>\" non g'è reggistrete.\nPe piacere, condrolle ce tu vuè cu ccreje/cange sta pàgene.",
        "userpage-userdoesnotexist-view": "'U cunde utende \"$1\" non g'è reggistrate.",
        "blocked-notice-logextract": "Stu utende jè correndemende bloccate.<br />\nL'urteme archivije de le bloccaminde se iacche aqquà sotte pe referimende:",
-       "clearyourcache": "'''Vide Bbuene''' - Apprisse 'a reggistrazione, tu puè zumbà 'a cache d'u browser tune pe vedè le cangiaminde.\n*'''Firefox / Safari:''' cazze 'u ''Shift'' e condemboraneamende cazze 'u buttone ''Aggiorna'', o cazze 'nzieme ''Ctrl-F5'' o ''Ctrl-R'' (''⌘-R'' sus a 'nu Mac);\n*'''Google Chrome:''' cazze ''Ctrl-Shift-R'' (''⌘-Shift-R'' sus a 'nu Mac)\n*'''Internet Explorer:''' cazze ''Ctrl'' e condemboraneamende cazze ''Aggiorna,'' o cazze ''Ctrl-F5''.\n*'''Opera:''' pulizze 'a cache da ''Tools → Preferences'' (in inglese) (Struminde - Preferenze in tarandine);",
+       "clearyourcache": "<strong>Vide Bbuene</strong> - Apprisse 'a reggistrazione, tu puè zumbà 'a cache d'u browser tune pe vedè le cangiaminde.\n*<strong>Firefox / Safari:</strong> cazze 'u <em>Shift</em> e condemboraneamende cazze 'u buttone <em>Aggiorne</em>, o cazze 'nzieme <em>Ctrl-F5</em> o <em>Ctrl-R</em> (<em>⌘-R</em> sus a 'nu Mac);\n*<strong>Google Chrome:</strong> cazze <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> sus a 'nu Mac)\n*<strong>Internet Explorer:</strong> cazze ''Ctrl'' e condemboraneamende cazze <em>Aggiorne</em> o cazze <em>Ctrl-F5</em>.\n*<strong>Opera:</strong> pulizze 'a cache da <em>Tools → Preferences</em> (in inglese) (Struminde - Preferenze in tarandine);",
        "usercssyoucanpreview": "'''Conziglie:''' Ause 'u buttone \"{{int:showpreview}}\" pe condrollà 'u CSS nuève apprime de reggistrà.",
        "userjsyoucanpreview": "'''Conziglie:''' Ause 'u buttone \"{{int:showpreview}}\" pe condrollà 'u JavaScript nuève apprime de reggistrà.",
        "usercsspreview": "'''Arrecuerdete ca tu ste vide sulamende in andeprime 'u CSS tue.'''\n'''Non g'à state angore reggistrete ninde!'''",
        "editusergroup": "Cange le gruppe utinde",
        "editinguser": "Stè cange le deritte de {{GENDER:$1|l'utende}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Cange le gruppe d'utinde",
+       "userrights-viewusergroup": "'Ndruche le gruppe d'utinde",
        "saveusergroups": "Reggistre le gruppe d'utinde",
        "userrights-groupsmember": "Membre de:",
        "userrights-groupsmember-auto": "Membre imblicite de:",
        "userrights-reason": "Mutive:",
        "userrights-no-interwiki": "Tu non ge tìne le permesse pe cangià le deritte utende sus a l'otre uicchi.",
        "userrights-nodatabase": "'U Database $1 non g'esiste o non g'è lochele.",
-       "userrights-nologin": "Tu à essere [[Special:UserLogin|colleghete]] cu 'nu cunde utende d'amministratore pe assignà le deritte utende.",
-       "userrights-notallowed": "Non ge tìne le permesse pe aggiungere o luà le deritte a le utinde.",
        "userrights-changeable-col": "Gruppe ca tu puè cangià",
        "userrights-unchangeable-col": "Gruppe ca tu non ge puè cangià",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Conflitte sus a le cangiaminde de le deritte utende! Pe piacere revide e conferme le cangiaminde tune.",
-       "userrights-removed-self": "T'è luate le deritte tune. Mò non ge puè cchiù trasè jndr'à sta pàgene.",
        "group": "Gruppe:",
        "group-user": "Utinde",
        "group-autoconfirmed": "Utinde auto confermatarije",
        "right-siteadmin": "Blocche e sblocche 'u database",
        "right-override-export-depth": "L'esportazione de pàggene inglude pàggene collegate 'mbonde a 'na profonnetà de 5",
        "right-sendemail": "Manne 'a mail a otre utinde",
-       "right-passwordreset": "Vide l'e-mail de azzeramende d'a passuord",
        "right-managechangetags": "CCreje e scangìlle [[Special:Tags|tag]] da 'u database",
        "right-applychangetags": "Appleche [[Special:Tags|tag]] sus a 'u de le cangiaminde tune",
        "right-changetags": "Aggiunge e live arbitrariamende [[Special:Tags|tag]] sus a le revisiune individuale e vôsce de l'archivije",
        "apisandbox-examples": "Esembie",
        "apisandbox-results": "Resultate",
        "apisandbox-request-url-label": "URL richieste:",
-       "apisandbox-request-time": "Tiembe cercate: $1",
+       "apisandbox-request-time": "Tiembe cercate: {{PLURAL:$1|$1 ms}}",
        "booksources": "Sorgende de le libbre",
        "booksources-search-legend": "Cirche pe le fonde de le libbre",
        "booksources-isbn": "ISBN:",
        "tags-actions-header": "Aziune",
        "tags-active-yes": "Sìne",
        "tags-active-no": "None",
-       "tags-source-extension": "Definite da 'n'estenzione",
+       "tags-source-extension": "Definite da 'u softuer",
        "tags-source-manual": "Applicate a màne da l'utinde e da le bot",
        "tags-source-none": "No cchiù ausate",
        "tags-edit": "cange",
        "tags-delete-not-allowed": "Tag definite da 'n'estenzione non ge ponne essere scangellate senze ca l'estenzione specifiche 'u permette.",
        "tags-delete-not-found": "'U tag \"$1\" non g'esiste.",
        "tags-delete-too-many-uses": "'U tag \"$1\" jè applecate a cchiù de $2 {{PLURAL:$2|revisione|revisiune}}, ca signifeche ca non ge pò essere scangellate.",
-       "tags-delete-warnings-after-delete": "'U tag \"$1\" ha state scangellate, ma  {{PLURAL:$2|ha assute 'u seguende avvise|onne assute le seguende avvise}}:",
+       "tags-delete-warnings-after-delete": "'U tag \"$1\" ha state scangellate, ma {{PLURAL:$2|ha assute 'u seguende avvise|onne assute le seguende avvise}}:",
        "tags-activate-title": "Attive 'u tag",
        "tags-activate-question": "Tu ste attive 'u tag \"$1\".",
        "tags-activate-reason": "Mutive:",
        "tags-edit-revision-legend": "Aggiunge o live le tag da {{PLURAL:$1|sta revisione|tutte le $1 revisiune}}",
        "tags-edit-logentry-legend": "Aggiunge o live le tag da {{PLURAL:$1|sta vôsce de l'archivije|tutte le $1 vôsce de l'archivije}}",
        "tags-edit-existing-tags": "Tag esistende:",
-       "tags-edit-existing-tags-none": "\"Nisciune\"",
+       "tags-edit-existing-tags-none": "<em>isciune</em>",
        "tags-edit-new-tags": "Tag nuève:",
        "tags-edit-add": "Agigunge ste tag:",
        "tags-edit-remove": "Live ste tag:",
index c3df1fa..1cacac4 100644 (file)
        "tog-hidepatrolled": "Скрывать патрулированные правки в списке свежих правок",
        "tog-newpageshidepatrolled": "Скрывать отпатрулированные страницы в списке новых страниц",
        "tog-hidecategorization": "Скрывать категоризацию страниц",
-       "tog-extendwatchlist": "Расширенный список наблюдения, включающий все изменения, а не только последние",
+       "tog-extendwatchlist": "Расширенный список наблюдения, включающий все изменения, а не только последние <small>(они могут быть сгруппированы настройкой на вкладке «[[Служебная:Настройки#mw-prefsection-rc|Свежие правки]]»)</small>",
        "tog-usenewrc": "Группировать изменения в свежих правках и списке наблюдения",
        "tog-numberheadings": "Автоматически нумеровать заголовки",
        "tog-showtoolbar": "Показывать панель инструментов при редактировании",
        "views": "Просмотры",
        "toolbox": "Инструменты",
        "tool-link-userrights": "Изменить группы {{GENDER:$1|участника|участницы}}",
+       "tool-link-userrights-readonly": "Смотреть группы {{GENDER:$1|участника|участницы}}",
        "tool-link-emailuser": "Написать письмо {{GENDER:$1|участнику|участнице}}",
        "userpage": "Просмотреть страницу участника",
        "projectpage": "Просмотреть страницу проекта",
        "passwordreset-emaildisabled": "Функции электронной почты отключены в этой вики.",
        "passwordreset-username": "Имя участника:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Просмотреть получившееся письмо?",
-       "passwordreset-capture-help": "Если вы установите данную отметку, то вам будет показано письмо с временным паролем, отправляемое участнику.",
        "passwordreset-email": "Адрес электронной почты:",
        "passwordreset-emailtitle": "Сведения об учётной записи {{SITENAME}}",
        "passwordreset-emailtext-ip": "Кто-то (возможно, вы, с IP-адреса $1) запросил сброс пароля к вашей учётной записи в проекте {{SITENAME}} ($4).\nС этим адресом электронной почты {{PLURAL:$3|1=связана следующая учётная запись|связаны следующие учётные записи}}:\n\n$2\n\n{{PLURAL:$3|1=Этот временный пароль будет|Эти временные пароли будут}} действовать {{PLURAL:$5|$5 день|$5 дня|$5 дней|1=один день}}.\nВы должны представиться системе и выбрать новый пароль. \nЕсли вы не делали этого запроса, или вспомнили свой исходный пароль и не желаете его менять, \nто можете проигнорировать это сообщение и продолжить использовать свой старый пароль.",
        "passwordreset-emailelement": "Имя участника: \n$1\n\nВременный пароль: \n$2",
        "passwordreset-emailsentemail": "Если это адрес электронной почты связан с вашей учётной записью, вам будет отправлено письмо для сброса пароля.",
        "passwordreset-emailsentusername": "Если есть адрес электронной почты, связанный с этим именем участника, то будет отправлено письмо для восстановления пароля.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Письмо|Письма}} для сброса пароля {{PLURAL:$1|было отправлено|были отправлены}}. {{PLURAL:$1|Логин и пароль показаны|Список логинов и паролей показан}} здесь.",
-       "passwordreset-emailerror-capture2": "Отправка {{GENDER:$2|участнику|участнице}} письма по электронной почте не удалась: $1\n{{PLURAL:$3|Логин и пароль показаны|Список логинов и паролей показан}} здесь.",
        "passwordreset-nocaller": "Должен быть предоставлен источник вызова",
        "passwordreset-nosuchcaller": "Источник вызова не существует: $1",
        "passwordreset-ignored": "Сброс пароля не был обработан. Может быть, не был настроен ни один провайдер?",
-       "passwordreset-invalideamil": "Недопустимый адрес электронной почты",
+       "passwordreset-invalidemail": "Недопустимый адрес электронной почты",
        "passwordreset-nodata": "Ни имя участника, ни адрес электронной почты не были предоставлены",
        "changeemail": "Изменить или удалить адрес электронной почты",
        "changeemail-header": "Заполните эту форму, чтобы изменить свой адрес электронной почты. Если вы хотите отвязать свой адрес электронной почты от учётной записи, то при заполнении формы оставьте пустым поле нового адреса электронной почты.",
        "undo-failure": "Правка не может быть отменена из-за несовместимости промежуточных изменений.",
        "undo-norev": "Правка не может быть отменена, так как её не существует или она была удалена.",
        "undo-nochange": "Правка, похоже, уже была отменена.",
-       "undo-summary": "Отмена правки $1, сделанной {{GENDER:$2|участником|участницей}} [[Special:Contributions/$2|$2]] ([[User talk:$2|обс.]])",
+       "undo-summary": "Отмена правки $1, сделанной [[Special:Contributions/$2|$2]] ([[User talk:$2|обсуждение]])",
        "undo-summary-username-hidden": "Отмена правки $1, сделанной участником, чьё имя скрыто",
        "cantcreateaccount-text": "Создание учётных записей с этого IP-адреса ('''$1''') было заблокировано {{GENDER:$3|участником|участницей|}} [[User:$3|$3]].\n\n$3 {{GENDER:$3|указал|указала}} следующую причину: ''$2''.",
        "cantcreateaccount-range-text": "{{GENDER:$3|Участник|Участница}} [[User:$3|$3]] {{GENDER:$3|установил|установила}} запрет на создание учётных записей из диапазона IP-адресов <strong>$1</strong>, включающего ваш IP-адрес (<strong>$4</strong>). \n\nБыла указана следующая причина: $2.",
        "search-external": "Внешний поиск",
        "searchdisabled": "Извините, но встроенный полнотекстовый поиск выключен. Вы можете воспользоваться поиском по сайту через поисковые системы общего назначения, однако имейте в виду, что копия сайта в их кэше может быть несколько устаревшей.",
        "search-error": "Произошла ошибка при поиске: $1",
+       "search-warning": "Во время поиска выдано предупреждение: $1",
        "preferences": "Настройки",
        "mypreferences": "Настройки",
        "prefs-edits": "Количество правок:",
        "prefs-help-recentchangescount": "Включает свежие правки, истории страниц, журналы.",
        "prefs-help-watchlist-token2": "Это секретный ключ для веб-канала вашего списка наблюдений.\nЛюбой, кто знает его, сможет читать ваш список наблюдения, поэтому не сообщайте его другим. [[Special:ResetTokens|Нажмите здесь, если вам нужно сбросить его]].",
        "savedprefs": "Ваши настройки сохранены.",
-       "savedrights": "Ð\9fÑ\80ава пользователя {{GENDER:$1|$1}} были сохранены.",
+       "savedrights": "Ð\93Ñ\80Ñ\83ппÑ\8b пользователя {{GENDER:$1|$1}} были сохранены.",
        "timezonelegend": "Часовой пояс:",
        "localtime": "Местное время:",
        "timezoneuseserverdefault": "Использовать настройки сервера ($1)",
        "prefswarning-warning": "Вы внесли в свои настройки изменения, которые ещё не были сохранены.\nЕсли вы покинете эту страницу, не нажав «$1», настройки не будут обновлены.",
        "prefs-tabs-navigation-hint": "Совет: Вы можете использовать клавиши стрелок влево и вправо для перехода между вкладками в списке вкладок.",
        "userrights": "Управление правами участника",
-       "userrights-lookup-user": "УпÑ\80авление Ð³Ñ\80Ñ\83ппами Ñ\83Ñ\87аÑ\81Ñ\82ников",
+       "userrights-lookup-user": "Ð\92Ñ\8bбоÑ\80 Ñ\83Ñ\87аÑ\81Ñ\82ника",
        "userrights-user-editname": "Введите имя учётной записи:",
-       "editusergroup": "Ð\98змениÑ\82Ñ\8c Ð³Ñ\80Ñ\83ппÑ\8b {{GENDER:$1|Ñ\83Ñ\87аÑ\81Ñ\82ника|Ñ\83Ñ\87аÑ\81Ñ\82ниÑ\86Ñ\8b}}",
+       "editusergroup": "Ð\97агÑ\80Ñ\83зка Ð³Ñ\80Ñ\83пп Ñ\83Ñ\87аÑ\81Ñ\82ников",
        "editinguser": "Изменение прав {{GENDER:$1|участника|участницы}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Просмотр прав {{GENDER:$1|участника|участницы}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Изменение членства в группах",
+       "userrights-viewusergroup": "Просмотр групп участника",
        "saveusergroups": "Сохранить группы {{GENDER:$1|участника|участницы}}",
        "userrights-groupsmember": "Состоит в группах:",
        "userrights-groupsmember-auto": "Неявно состоит в группах:",
        "userrights-reason": "Причина:",
        "userrights-no-interwiki": "У вас нет разрешения изменять права участников в других вики.",
        "userrights-nodatabase": "База данных $1 не существует или расположена не локально.",
-       "userrights-nologin": "Вы должны [[Special:UserLogin|представиться системе]] с учётной записи администратора, чтобы присваивать права участникам.",
-       "userrights-notallowed": "У вас нет разрешения добавлять и удалять права участников.",
        "userrights-changeable-col": "Группы, которые вы можете изменять",
        "userrights-unchangeable-col": "Группы, которые вы не можете изменять",
        "userrights-conflict": "Конфликт изменения прав участника! Пожалуйста, проверьте и примените изменения заново.",
-       "userrights-removed-self": "Вы удалили собственные права. Таким образом, вы больше не сможете получить доступ к этой странице.",
        "group": "Группа:",
        "group-user": "Участники",
        "group-autoconfirmed": "Автоподтверждённые участники",
        "right-siteadmin": "блокировка и разблокировка базы данных",
        "right-override-export-depth": "экспортирование страниц, включая связанные страницы с глубиной до 5",
        "right-sendemail": "отправка электронной почты другим участникам",
-       "right-passwordreset": "просмотр электронных писем с изменением пароля",
        "right-managechangetags": "создание и (де)активация [[Special:Tags|меток]]",
        "right-applychangetags": "применение [[Special:Tags|меток]] вместе со своими правками",
        "right-changetags": "добавление и удаление произвольных [[Special:Tags|меток]] на отдельных правках и записях в журнале",
        "action-upload_by_url": "загрузку этого файла с адреса URL",
        "action-writeapi": "использование API для правок",
        "action-delete": "удаление этой страницы",
-       "action-deleterevision": "удаление этой версии страницы",
-       "action-deletedhistory": "просмотр удалённой истории этой страницы",
+       "action-deleterevision": "удаление версий страниц",
+       "action-deletelogentry": "удаление записей журнала",
+       "action-deletedhistory": "просмотр удалённой истории страницы",
+       "action-deletedtext": "просмотр текста удалённой версии",
        "action-browsearchive": "поиск удалённых страниц",
-       "action-undelete": "воÑ\81Ñ\81Ñ\82ановление Ñ\8dÑ\82ой Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\8b",
-       "action-suppressrevision": "пÑ\80оÑ\81моÑ\82Ñ\80 Ð¸ Ð²Ð¾Ñ\81Ñ\81Ñ\82ановление Ñ\8dÑ\82ой Ñ\81кÑ\80Ñ\8bÑ\82ой Ð²ÐµÑ\80Ñ\81ии Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\8b",
+       "action-undelete": "воÑ\81Ñ\81Ñ\82ановление Ñ\81Ñ\82Ñ\80аниÑ\86",
+       "action-suppressrevision": "пÑ\80оÑ\81моÑ\82Ñ\80 Ð¸ Ð²Ð¾Ñ\81Ñ\81Ñ\82ановление Ñ\81кÑ\80Ñ\8bÑ\82Ñ\8bÑ\85 Ð²ÐµÑ\80Ñ\81ий Ñ\81Ñ\82Ñ\80аниÑ\86",
        "action-suppressionlog": "просмотр этого частного журнала",
        "action-block": "ограничивать возможность редактирования для этого участника",
        "action-protect": "изменение уровня защиты этой страницы",
        "action-userrights-interwiki": "изменение прав участников в других вики",
        "action-siteadmin": "блокировка и разблокировка базы данных",
        "action-sendemail": "отправка электронных писем",
+       "action-editmyoptions": "редактирование своих настроек",
        "action-editmywatchlist": "редактирование вашего списка наблюдения",
        "action-viewmywatchlist": "просмотр вашего списка наблюдения",
        "action-viewmyprivateinfo": "просмотр вашей частной информации",
        "apisandbox-continue": "Продолжить",
        "apisandbox-continue-clear": "Очистить",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries продолжит] последний запрос; {{int:apisandbox-continue-clear}} очистит связанные с продолжением параметры.",
+       "apisandbox-param-limit": "Введите <kbd>максимальное</kbd> использование максимального предела.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Все пространства имён)",
+       "apisandbox-multivalue-all-values": "$1 (Все значения)",
        "booksources": "Источники книг",
        "booksources-search-legend": "Поиск информации о книге",
        "booksources-isbn": "ISBN:",
        "activeusers-intro": "Это список участников, совершавших какие-либо действия за {{PLURAL:$1|последний $1 день|последние $1 дня|последние $1 дней|1=последний день}}.",
        "activeusers-count": "$1 {{PLURAL:$1|правка|правки|правок}} за {{PLURAL:$3|$3 последний день|последние $3 дня|последние $3 дней|1=последний день}}",
        "activeusers-from": "Показать участников, начиная с:",
-       "activeusers-groups": "Отображать пользователей, принадлежащих к группам:",
+       "activeusers-groups": "Отображать участников, принадлежащих к группам:",
+       "activeusers-excludegroups": "Исключать участников, принадлежащих к группам:",
        "activeusers-noresult": "Не найдено участников.",
        "activeusers-submit": "Показать активных участников",
        "listgrouprights": "Права групп участников",
        "emailccsubject": "Копия вашего сообщения для $1: $2",
        "emailsent": "Письмо отправлено",
        "emailsenttext": "Ваше электронное сообщение отправлено.",
-       "emailuserfooter": "Это письмо было отправлено {{GENDER:$2|участнику|участнице}} $2 от {{GENDER:$1|участника|участницы}} $1 с помощью функции «{{int:emailuser}}» проекта {{SITENAME}}.",
+       "emailuserfooter": "Это письмо было отправлено {{GENDER:$2|участнику|участнице}} $2 от {{GENDER:$1|участника|участницы}} $1 с помощью функции «{{int:emailuser}}» проекта {{SITENAME}}.\n{{GENDER:$2|Письмо}} будет отослано напрямую {{GENDER:$1|отправителю}}, так что {{GENDER:$2|ваш}} адрес электронной почты станет известен {{GENDER:$1|ему|ей}}.",
        "usermessage-summary": "Оставить системное сообщение.",
        "usermessage-editor": "Системная доставка",
        "watchlist": "Список наблюдения",
        "tags-deactivate": "отключить",
        "tags-hitcount": "$1 {{PLURAL:$1|изменение|изменения|изменений}}",
        "tags-manage-no-permission": "У вас нет прав на управление изменениями меток.",
-       "tags-manage-blocked": "Ð\9dелÑ\8cзÑ\8f Ñ\83пÑ\80авлÑ\8fÑ\82Ñ\8c Ñ\82еги Ð¼ÐµÐ½Ñ\8fеÑ\82Ñ\81Ñ\8f, Ð° Ð²Ñ\8b заблокированы.",
+       "tags-manage-blocked": "Ð\92Ñ\8b Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82е Ñ\83пÑ\80авлÑ\8fÑ\82Ñ\8c Ð¼ÐµÑ\82ками Ð¿Ñ\80авок, Ð¿Ð¾ÐºÐ° {{GENDER:$1|вÑ\8b}} заблокированы.",
        "tags-create-heading": "Создать новую метку",
        "tags-create-explanation": "Вновь созданные метки по умолчанию будут созданы доступными для использования участниками и ботами.",
        "tags-create-tag-name": "Название метки:",
        "tags-deactivate-not-allowed": "Невозможно отключить метку «$1».",
        "tags-deactivate-submit": "Отключить",
        "tags-apply-no-permission": "У вас нет права применять метки изменения к своими изменениям.",
-       "tags-apply-blocked": "Вы не можете применять метки правок к своим правкам, пока вы заблокированы.",
+       "tags-apply-blocked": "Вы не можете применять метки правок к своим правкам, пока {{GENDER:$1|вы}} заблокированы.",
        "tags-apply-not-allowed-one": "Метка «$1» не может быть применена вручную.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Следующая метка не может быть применена|Следующие метки не могут быть применены}} вручную: $1",
        "tags-update-no-permission": "У вас нет права на добавление или изменение меток изменения из отдельных версий или записей журналов.",
-       "tags-update-blocked": "Ð\92Ñ\8b Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ\82Ñ\8c Ð¸Ð»Ð¸ Ñ\83далиÑ\82Ñ\8c Ñ\82еги Ð¼ÐµÐ½Ñ\8fеÑ\82Ñ\81Ñ\8f, Ð° Ð²Ñ\8b заблокированы.",
+       "tags-update-blocked": "Ð\92Ñ\8b Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð¾Ð±Ð°Ð²Ð»Ñ\8fÑ\82Ñ\8c Ð¸Ð»Ð¸ Ñ\83далÑ\8fÑ\82Ñ\8c Ð¼ÐµÑ\82ки Ð¿Ñ\80авок, Ð¿Ð¾ÐºÐ° {{GENDER:$1|вÑ\8b}} заблокированы.",
        "tags-update-add-not-allowed-one": "Тег \"$1\" не может быть добавлен вручную.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Следующий тег|Следующие теги}} нельзя добавлять вручную: $1",
        "tags-update-remove-not-allowed-one": "Метка «$1» не может быть удалена.",
        "htmlform-user-not-exists": "<strong>$1</strong> не существует.",
        "htmlform-user-not-valid": "<strong>$1</strong> — недопустимое имя учётной записи.",
        "logentry-delete-delete": "$1 {{GENDER:$2|удалил|удалила}} страницу $3",
+       "logentry-delete-delete_redir": "$1 удалил{{GENDER:$2||а}} перенаправление $3 с помощью перезаписи",
        "logentry-delete-restore": "$1 {{GENDER:$2|восстановил|восстановила}} страницу $3",
        "logentry-delete-event": "$1 {{GENDER:$2|изменил|изменила}} видимость {{PLURAL:$5|$5 записи|$5 записей|1=записи}} журнала для $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|изменил|изменила}} видимость {{PLURAL:$5|$5 версии|$5 версий|1=версии}} страницы $3: $4",
        "mw-widgets-dateinput-no-date": "Дата не выбрана",
        "mw-widgets-dateinput-placeholder-day": "ГГГГ-ММ-ДД",
        "mw-widgets-dateinput-placeholder-month": "ГГГГ-ММ",
+       "mw-widgets-mediasearch-input-placeholder": "Поиск мультимедиа",
+       "mw-widgets-mediasearch-noresults": "Ничего не найдено.",
        "mw-widgets-titleinput-description-new-page": "страница ещё не существует",
        "mw-widgets-titleinput-description-redirect": "перенаправление на $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Добавить категорию…",
        "sessionmanager-tie": "Невозможно использовать одновременно несколько типов проверки подлинности запроса: $1.",
        "sessionprovider-generic": "$1 сессий",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "сессий на основе куки",
        "log-action-filter-contentmodel-change": "Изменение модели содержимого",
        "log-action-filter-contentmodel-new": "Создание страницы с нестандартной моделью Contentmodel",
        "log-action-filter-delete-delete": "Удаления страницы",
+       "log-action-filter-delete-delete_redir": "Перезапись перенаправления",
        "log-action-filter-delete-restore": "Восстановление страницы",
        "log-action-filter-delete-event": "Удаление журнала",
        "log-action-filter-delete-revision": "Удаление версии",
        "restrictionsfield-badip": "Недопустимый IP-адрес или диапазон адресов: $1",
        "restrictionsfield-label": "Разрешённые диапазоны IP-адресов:",
        "restrictionsfield-help": "По одному IP-адресу или CIDR-диапазону в строке. Чтобы разрешить всё, используйте <br /><code>0.0.0.0/0</code><br /><code>::/0</code>",
-       "edit-error-short": "Ошибка: $1",
-       "edit-error-long": "Ошибки: $1"
+       "pageid": "ID страницы $1"
 }
index 1259b35..dbc7b57 100644 (file)
        "yourpasswordagain": "Повторяйте гесло:",
        "createacct-yourpasswordagain": "Потвердьте гесло",
        "createacct-yourpasswordagain-ph": "Уведьте гесло знову",
-       "remembermypassword": "Запамнятати моє приголошіня на тім компютерї (максімално $1 {{PLURAL:$1|день|днів}})",
        "userlogin-remembermypassword": "Приголосити ня на довго",
        "userlogin-signwithsecure": "Хосновати забеспечене споїня",
        "yourdomainname": "Ваша домена:",
        "passwordreset-emailtext-user": "{{gender:$1|Хоснователь|Хоснователька|Хоснователь}} $1 {{grammar:2sg|{{SITENAME}}}} {{gender:$1|попросив|попросила|попросив}} о наставлїня нового гесла до вашого\nконта на {{grammar:6sg|{{SITENAME}}}} ($4). З тов адресов {{PLURAL:$3|є повязане наступне конто|суть повязаны наступны конта}}:\n\n$2\n\n{{PLURAL:$3|Тото дочасне гесло кінчить|Тоты дочасны гесла кінчать}} {{PLURAL:$5|о єден день|о $5 днї|о $5 днїв}}.\nТеперь бы сьте ся мали приголосити і зволити собі нове гесло. Кідь тоту пожадавку \nпослав дахто другый або сьте собі на своє старе гесло спомянули і не хочете го\nзмінити, можете тото повідомлїня іґноровати і надале хосновати старе гесло.",
        "passwordreset-emailelement": "Імя хоснователя: \n$1\n\nДочасне гесло: \n$2",
        "passwordreset-emailsentemail": "Імейл з геслом быв посланый.",
-       "passwordreset-emailsent-capture": "Быв выґенерованый імейл з геслом, што є вказаный ниже.",
-       "passwordreset-emailerror-capture": "Быв выґенерованый імейл з геслом, котрый є указаный ниже, але ся го не вдало загнати {{GENDER:$2|хоснователёви|хосновательцї}}: $1",
        "changeemail": "Зміна імейловой адресы",
        "changeemail-header": "Зміна імейловой адресу ку конту",
        "changeemail-no-info": "Ку тій сторінцї мають прямый приступ лем приголошены хоснователї.",
        "undo-norev": "Тото едітованя не можете вернути назад, бо не екзістує або было змазане.",
        "undo-summary": "Зрушена верзія $1 од хоснователя [[Special:Contributions/$2|$2]] ([[User talk:$2|діскузія]])",
        "undo-summary-username-hidden": "Зрушыти ревізію $1 скрытого хоснователя",
-       "cantcreateaccounttitle": "Не є можне вытворити конто",
        "cantcreateaccount-text": "Створёваня новых конт з той IP адресы ('''$1''') было заблоковане хоснователём [[User:$3|$3]].\n\n$3 зазначів тоту причіну: ''$2''",
        "viewpagelogs": "Вказати лоґы про тоту сторінку",
        "nohistory": "Про тоту статю не екзістує історія едітовань.",
        "activeusers-intro": "Тото є список хоснователїв, котры были даяк актівны за {{plural:$1|остатнїй день|остатных $1 днїв}}.",
        "activeusers-count": "$1 {{PLURAL:$1|дїя|дїї|дїй}} через {{PLURAL:$3|остатнёго дня|остатнїх  $3 днїв}}",
        "activeusers-from": "Вказати хоснователїв, што ся зачінають на:",
-       "activeusers-hidebots": "Сховати ботів",
-       "activeusers-hidesysops": "Сховати адміністраторів",
        "activeusers-noresult": "Ненайдженый жаден хоснователь.",
        "listgrouprights": "Права ґруп хоснователїв",
        "listgrouprights-summary": "Тото є список ґруп хоснователїв дефінованых на тій вікіi і&nbsp;їх приступовых прав.\n\n[[{{MediaWiki:Listgrouprights-helppage}}|Детайлны інформації о&nbsp;єднотливых правах]]",
        "htmlform-no": "Нє",
        "htmlform-yes": "Гей",
        "htmlform-chosen-placeholder": "Звольте параметер",
-       "sqlite-has-fts": "$1 з підпоров повнотекстового гляданя",
-       "sqlite-no-fts": "$1 без підпоры повнотекстового гляданя",
        "logentry-delete-delete": "$1 {{GENDER:$2|змазав|змазала}} сторінку $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|обновив|обновила}} сторінку $3",
        "logentry-delete-event": "$1 {{GENDER:$2|змінив|змінила}}  відимость {{PLURAL:$5|протоколового запису|$5 протоколовых записів}} к сторінцї $3: $4",
        "special-characters-group-lao": "Лаоськы",
        "special-characters-group-khmer": "Кгмерськы",
        "mw-widgets-dateinput-placeholder-day": "РРРР-ММ-ДД",
-       "mw-widgets-dateinput-placeholder-month": "РРРР-ММ",
-       "api-error-blacklisted": "Звольте іншу, пописну назву."
+       "mw-widgets-dateinput-placeholder-month": "РРРР-ММ"
 }
index 9591937..d96819c 100644 (file)
        "activeusers-intro": "एषा तु गतेषु $1 {{PLURAL:$1|दिनेषु}} कृतकार्याणां योजकाना आवली ।",
        "activeusers-count": "$1 {{PLURAL:$1|कार्यं|कार्याणि}} गतेषु $3 {{PLURAL:$3|दिनेषु}} कृतानि  ।",
        "activeusers-from": "एतस्मात् आरभमाणान् योजकान् दर्शयतु ।",
-       "activeusers-hidebots": "स्वयं चालकान् गोपयतु ।",
-       "activeusers-hidesysops": "प्रशासकान् गोपयतु ।",
        "activeusers-noresult": "सदस्यः न प्राप्तः ।",
        "listgrouprights": "योजकसमूहाधिकाराः ।",
        "listgrouprights-summary": "अधोदत्ता विकिपरिभाषितस्य सङ्गताभिगम्यताधिकारैः सहिता योजकसमूहस्य आवली । [[{{MediaWiki:Listgrouprights-helppage}}|additional information]]",
        "feedback-external-bug-report-button": "यान्त्रककार्यम् अङ्क्यताम्",
        "feedback-dialog-title": "स्वप्रतिक्रियां लिखतु",
        "feedback-dialog-intro": "स्वप्रतिक्रियां लेखितुं निम्नं सरलपत्रम् उपयोक्तुं शक्नोति   ।\nभवतः/भवत्याः योजकनामोल्लेखन सह $1 इत्यस्मिन् पृष्ठे भवतः/भवत्याः प्रतिक्रियां योजयिष्यामः ।",
-       "feedback-error-title": "दोषः",
        "feedback-error1": "API इत्यस्मात् दोषः : अज्ञातः परिणामः ।",
        "feedback-error2": "दोषः : सम्पादनं निष्फलं जातम्",
        "feedback-error3": "दोषः : ए पि ऐ तः प्रतिस्पन्दः न प्राप्तः",
index 232e75e..ede9988 100644 (file)
        "tagline": "{{SITENAME}} диэн сиртэн ылыллыбыт",
        "help": "Көмө",
        "search": "Көрдөөһүн",
+       "search-ignored-headings": " #<!-- бу устуруоканы уларытыма --> <pre>\n# Көрдүүр тиһиктэр көрбөтөҕө буолуохтаах ааттара.\n# Уларыйыы көрдүүр тиһик (поисковик) сирэйи болҕомтоҕо ылбытын кэннэ олоххо киирэр.\n# Болҕомтоҕо ылыыны түргэтэтэр туһугар кураанах (ньуул) уларытыы оҥоруохха сөп.\n# Синтэксииһэ маннык көстөр:\n#   * Маннык бэлиэттэн саҕаланар устуруока «#» ырытыы быһыытынан ааҕыллар.\n#   * Кураанаҕа суох устуруока барыта — көрүллүбэт аат чопчу көрүҥэ, эрэгиистирин эҥин учуоттаан туран.\nБыһаарыылар\nСигэлэр\nЭбии көр\n #</pre> <!-- бу устуруоканы уларытыма -->",
        "searchbutton": "Бул",
        "go": "Бар",
        "searcharticle": "Көрдөр",
        "talk": "Ырытыы",
        "views": "Көрүү",
        "toolbox": "Сэп-сэбиргэл",
+       "tool-link-userrights": "{{GENDER:$1|Кыттааччы}} бөлөҕүн уларыт",
+       "tool-link-userrights-readonly": "{{GENDER:$1|Кыттааччы}} бөлөхтөрүн көр",
+       "tool-link-emailuser": "{{GENDER:$1|Кыттааччыга}} сурук суруйуу",
        "userpage": "Кыттааччы туһунан сирэй",
        "projectpage": "Бырайыак сирэйэ",
        "imagepage": "Билэ сирэйин көрүү",
        "versionrequiredtext": "Бу сирэйи туттарга MediaWiki $1 -с барыла наада. [[Special:Version|Барыллар тустарынан сирэйи]] көр.",
        "ok": "Сөп",
        "retrievedfrom": "Төрдө — «$1»",
-       "youhavenewmessages": "$1 ($2) кэллэ.",
+       "youhavenewmessages": "$1 ($2) {{PLURAL:$3|кэллэ}}.",
        "youhavenewmessagesfromusers": "Маны $1 {{PLURAL:$3|соҕотох кыттааччыттан|$3 кыттааччыттан}} туппуккун ($2).",
        "youhavenewmessagesmanyusers": "Маны $1 элбэх кыттааччыттан туппуккун ($2).",
        "newmessageslinkplural": "{{PLURAL:$1|саҥа этии|999=саҥа этии}}",
        "createacct-yourpasswordagain-ph": "Киирии тылгын хатылаа",
        "userlogin-remembermypassword": "Тиһиликтэн тахсыма",
        "userlogin-signwithsecure": "Бигэ холбонуу",
+       "cannotlogin-title": "Киирэр сатаммат",
+       "cannotlogin-text": "Тиһиккэ киирэр табыллыбат.",
        "cannotloginnow-title": "Сип-билигин киирэр кыах суох",
        "cannotloginnow-text": "Маны $1 туһанар кэмҥэ киирэр кыах суох.",
+       "cannotcreateaccount-title": "Бэлиэтэнэр табыллыбат",
+       "cannotcreateaccount-text": "Быһа бэлиэтэнии бу биикигэ сатаммат эбит.",
        "yourdomainname": "Эн дөмүөнүҥ:",
        "password-change-forbidden": "Бу биикигэ киирии тылы уоарытар табыллыбат.",
        "externaldberror": "Тас киирии билиитин олоҕун сыыһата буолла, эбэтэр тас киирии билииҥ олоҕун саҥардар кыаҕыҥ суох.",
        "login": "Киир",
+       "login-security": "Ким буоларгын бигэргэт",
        "nav-login-createaccount": "Киир / бэлиэтэн",
        "userlogin": "Киир / бэлиэтэн",
        "userloginnocreate": "Киир",
        "userlogin-resetpassword-link": "Киирии тылгын санаттараҕын дуо?",
        "userlogin-helplink2": "Киирэргэ көмө",
        "userlogin-loggedin": "Маннык аатынан киирбиккин {{GENDER:$1|$1}}.\nАтын аатынан киирэргэ аллара көстөр форманы туһан.",
+       "userlogin-reauth": "Тиһиккэ хат киирэн {{GENDER:$1|$1}} буоларгын бигэргэтиэхтээххин.",
        "userlogin-createanother": "Атын аатынан бэлиэтэн",
        "createacct-emailrequired": "Email аадырыс",
        "createacct-emailoptional": "Email аадырыс (булгуччута суох)",
        "createacct-email-ph": "Эл аадырыскын суруй",
        "createacct-another-email-ph": "Эл. почтаҕын киллэр",
        "createaccountmail": "Быстах киирии тылы туһаныы уонна ону ыйыллыбыт аадырыска ыытыы",
+       "createaccountmail-help": "Атын киһиэхэ аһарыгын билбэккэ эрэ бэлиэ-ааты оҥорон биэрэргэ туттуллуон сөп.",
        "createacct-realname": "Дьиҥнээх аатыҥ (булгуччута суох)",
        "createaccountreason": "Төрүөтэ:",
        "createacct-reason": "Төрүөтэ",
        "createacct-reason-ph": "Саҥа аатынан тоҕо киирэҕиний",
+       "createacct-reason-help": "Саҥаны суруйуу сурунаалыгар тахсар сурук",
        "createacct-submit": "Бэлиэтэнии",
        "createacct-another-submit": "Бэлиэтэн",
+       "createacct-continue-submit": "Бэлиэ-ааты салгыы оҥоруу",
+       "createacct-another-continue-submit": "Салгыы бэлиэтэнии",
        "createacct-benefit-heading": "{{SITENAME}} ситим-сири эн курдук дьон оҥороллор.",
        "createacct-benefit-body1": "{{PLURAL:$1|уларытыы|уларытыы}}",
        "createacct-benefit-body2": "{{PLURAL:$1|сирэй|сирэй}}",
        "nocookiesnew": "Маннык ааттаах кыттааччы баар буолла гынан баран, систиэмэҕэ киирэ илик. {{SITENAME}} «cookies» туттар, оттон эн көмпүүтэргэр ону туһанар бобуллубут. Бука диэн «cookies» холбоо, онтон өссө киирэн көр.",
        "nocookieslogin": "{{SITENAME}} дьону билэргэ «cookies» туттар. Эн көмпүүтэргэр «cookies» бобуллубут. Ону холбоон баран өссө киирэн көр.",
        "nocookiesfornew": "Аат кыайан бэлиэтэниллибэтэ. Төрүөтүнэн атын саайка сибидиэнньэ биэрии (CSRF) бобуллубута буолуон сөп. \nКуукилар холбоно сылдьалларын көрөн баран өссө биирдэ боруобалаа.",
+       "createacct-loginerror": "Бэлиэтэнниҥ гынан баран бэлиэ-ааккынан киирэ иликкин. Бука диэн, [[Special:UserLogin|киир дуу]].",
        "noname": "Эн тиһилик билэр аатын киллэрбэтэххин.",
        "loginsuccesstitle": "Киирдиҥ",
        "loginsuccess": "'''Билигин бу аатынан үлэлиигин: \"$1\".'''",
-       "nosuchuser": "Маннык - \"$1\" - ааттаах кыттааччы суох.\nУлахан кыра буукубалар атыннаахтар.\nАатыҥ сөпкө суруллубутун көр эбэтэр [[Special:CreateAccount|саҥаттан бэлиэтэн]].",
+       "nosuchuser": "Маннык - \"$1\" - ааттаах кыттааччы суох эбит.\nУлахан кыра буукубалар атыннаахтарын умнума.\nАатыҥ сөпкө суруллубутун көр эбэтэр [[Special:CreateAccount|саҥаттан бэлиэтэн]].",
        "nosuchusershort": "Маннык - \"$1\" - ааттаах кыттааччы суох. Аатыҥ сөпкө суруллубутун көр.",
        "nouserspecified": "Кыттааччы аатын киллэриэхтээххин.",
        "login-userblocked": "Бу кыттааччы бобуллубут. Тиһиккэ киирии көҥүллэммэт.",
        "noemail": "\"$1\" ааттаах киһиэхэ эл. почтата ыйыллыбатах.",
        "noemailcreate": "Электроннай почтаҥ сөптөөх аадырыһын суруйуохтааххын",
        "passwordsent": "Саҥа аһарык тыл \"$1\" эл. почтатыгар ыытылынна.\nТиһиккэ киирэргэ саҥа аһарыгы туһан.",
-       "blocked-mailpassword": "Эн IP аадырыскыттан манна тугу эмэ уларытар бобуллубут,\nонон киирии тылы өйдөтөр кыах эмиэ суох.",
+       "blocked-mailpassword": "Ð\9eмÑ\81олооÑ\85 Ð´Ñ\8cайÑ\8bÑ\8b Ð¾Ò¥Ð¾Ò»Ñ\83ллÑ\83баÑ\82Ñ\8bн Ñ\82Ñ\83Ò»Ñ\83гаÑ\80 Ð­Ð½ IP Ð°Ð°Ð´Ñ\8bÑ\80Ñ\8bÑ\81кÑ\8bÑ\82Ñ\82ан Ð¼Ð°Ð½Ð½Ð° Ñ\82Ñ\83гÑ\83 Ñ\8dмÑ\8d Ñ\83лаÑ\80Ñ\8bÑ\82аÑ\80 Ð±Ð¾Ð±Ñ\83ллÑ\83бÑ\83Ñ\82,\nонон ÐºÐ¸Ð¸Ñ\80ии Ñ\82Ñ\8bлÑ\8b Ó©Ð¹Ð´Ó©Ñ\82Ó©Ñ\80 ÐºÑ\8bаÑ\85 Ñ\8dмиÑ\8d Ñ\81Ñ\83оÑ\85.",
        "eauthentsent": "Эл. почтаҕар сурук ыытылынна.\nБу аадырыс эйиэнэ буоларын бигэргэтэргэ өссө тугу гыныахтааҕыҥ туһунан сурукка кэпсэниллэр.",
        "throttled-mailpassword": "Киирии тылы өйдөтөр тэрил бүтэһик {{PLURAL:$1|чаас|$1 чаас}} иһигэр туттулла сылдьыбыт.\nКөмүскэнэр соруктан сылтаан киирии тылы {{PLURAL:$1|чааска|$1 чааска}} биирдэ эрэ ыйытыахха сөп.",
        "mailerror": "Сурук ыытарга алҕас таҕыста: $1",
-       "acct_creation_throttle_hit": "Эн IP-гыттан бүгүн {{PLURAL:$1|1 аат оҥоһуллубут|$1 аат бэлиэтэммит}} буолан бүгүҥҥү күннээҕи нуорма туолбут.\nБу IP-тан киирэр дьон саҥа ааты билигин бэлиэтиир кыахтара суох.",
+       "acct_creation_throttle_hit": "Эн IP-гыттан тиһэх $2 болдьоххо {{PLURAL:$1|1 аат оҥоһуллубут|$1 аат бэлиэтэммит}} буолан саҥа аат оҥоһуллар нуормата туолан хаалбыт.\nОнон бу IP-тан киирэн саҥа ааты билигин бэлиэтиир кыах суох.",
        "emailauthenticated": "Эн почтаҥ аадырыһа бигэргэтиллибит кэмэ: $2, $3.",
        "emailnotauthenticated": "Эл. почтаҥ аадырыһа бигэргэтиллэ илик эбит.\nОнон сурук манна ааттаммыт түгэннэргэ ыытыллыа суоҕа.",
        "noemailprefs": "Эл. почтаҥ ыйыллыбатах, онон вики-движок аадырыскын туһанар кыаҕа суох.",
        "createaccount-title": "{{SITENAME}} бырайыакка саҥа аат оҥоруу",
        "createaccount-text": "Ким эрэ {{SITENAME}} бырайыакка ($4) саҥа $2 ааты бэлиэтээбит. \"$2\" киирии тыла \"$3\". Билигин киирэн киирии тылгын уларытыаххын наада.\n\nСаҥа аат сыыһа оҥоһуллубут буоллаҕына тугу да гыныа суоххун сөп.",
        "login-throttled": "Ааккын аһара элбэхтик билиһиннэрэ сатаатыҥ.\nБука диэн $1 буолан баран өссө киирэн көрөөр.",
-       "login-abort-generic": "Бу аатынан сатаан киирбэтиҥ - быстан хаалла",
+       "login-abort-generic": "Бу аатынан сатаан киирбэтиҥ - быһынна",
        "login-migrated-generic": "Эн бэлиэ-аатыҥ көһөрүллүбүт, онон урукку аатыҥ бу биикигэ суох буолбут эбит.",
        "loginlanguagelabel": "Омугун тыла: $1",
        "suspicious-userlogout": "Сеансы түмүктүүр ыйытыгыҥ ылыныллыбата, тоҕо диэтэххэ браузер эбэтэр кээштыыр прокси алҕас ыыппыт ыйытыктарыгар майгынныыр.",
        "createacct-another-realname-tip": "Дьиҥнээх аатыҥ булгуччута суох.\nЫйдаххына уларыппыт сирэйиҥ устуоруйатыгар көстөр буолуоҕа.",
        "pt-login": "Киир",
        "pt-login-button": "Киир",
+       "pt-login-continue-button": "Киириини салҕаа",
        "pt-createaccount": "Бэлиэтэнии",
        "pt-userlogout": "Тахсыы",
        "php-mail-error-unknown": "mail() PHP-функциятыгар туох эрэ алҕас тахсыбыт",
        "newpassword": "Саҥа аһарык:",
        "retypenew": "Саҥа киирии тылы хатылаа:",
        "resetpass_submit": "Киирии тылы уларыт уонна киир",
-       "changepassword-success": "Ð\9aииÑ\80ии Ñ\82Ñ\8bлÑ\8bÒ¥ Ñ\8dÑ\82Ñ\8dÒ¥Ò¥Ñ\8d уларыйда!",
+       "changepassword-success": "Ð\90һаÑ\80Ñ\8bгÑ\8bÒ¥ уларыйда!",
        "changepassword-throttled": "Ааккын аһара элбэхтик билиһиннэрэ сатаатыҥ.\nБука диэн $1 буолан баран өссө киирэн көрөөр.",
        "botpasswords": "Оруобаттар аһарыктара",
        "botpasswords-summary": "<em>Хатыыр тыллара</em> туттааччы учуоттуур сурутуутугар API-нан   логины уонна хатыыр тылы туттубакка эрэ киирэр кыах биэрэр. Кыттааччы  бота хатыыр тыллаах киириитигэр бырааба хааччахтаныан сөп.\nЭн  ити тоҕо наадатын билбэт буоллаххына, бука, итини гымматыҥ ордук.Ким даҕаны эйигиттэн хаһан даҕаны эн оҥорбутуҥ уонна биллэрбитиҥ диэн ыйытыа суохтаах.",
        "botpasswords-label-delete": "Сот",
        "botpasswords-label-resetpassword": "Аһарыгы саҥаттан",
        "botpasswords-label-grants": "Туттуллар көҥүллэр:",
-       "botpasswords-help-grants": " Кыттааччы учуоттуур суруйуутугар баар ыйыллыбыт кыттааччы быраабыгар киирэргэ кыах биэрэр. к. [[Special:ListGrants|көҥүллэр табылыыссаларын]] эбии информацияны ылар туһугар.",
+       "botpasswords-help-grants": "Хас биирдии көҥүл урукку кыахтарга эбиллэн биэрэр. Сиһилии аналлаах [[Special:ListGrants|табылыыссаланы]] көр.",
        "botpasswords-label-grants-column": "Көҥүллэннэ",
        "botpasswords-bad-appid": "Маннык аат «$1» сатаммат.",
        "botpasswords-insert-failed": "«$1» диэн ааттаах оруобаты эбэр табыллыбата. Баҕар хайыы-үйэ эбиллибитэ буолаарай?",
        "botpasswords-update-failed": "\"$1\" диэн ааттаах ботаны кыайан саҥардыбатыбыт. Баҕар, сотторуллубута буолуо?",
        "botpasswords-created-title": "Оруобат аһарыга оҥоһулунна",
-       "botpasswords-created-body": "«$1» оруобат аһарыга бигэргэтилиннэ.",
+       "botpasswords-created-body": "«$2» кыттааччы «$1» оруобатын аһарыга оҥоһулунна.",
        "botpasswords-updated-title": "Оруобат аһарыга саҥардылынна",
-       "botpasswords-updated-body": "«$1» оруобат аһарыга уларытылынна.",
+       "botpasswords-updated-body": "«$2» кыттааччы «$1» оруобатын аһарыга уларытылынна.",
        "botpasswords-deleted-title": "Оруобат аһарыга сотулунна",
-       "botpasswords-deleted-body": "«$1» оруобат аһарыга сотулунна.",
-       "botpasswords-newpassword": "\nСаҥа хатыыр тыл <strong>$1</strong> — <strong>$2</strong> аннынан киириигэ. <em> суруй аныгыскыга туттарга.</em>",
+       "botpasswords-deleted-body": "«$2» кыттааччы «$1» оруобатын аһарыга сотулунна.",
+       "botpasswords-newpassword": "<strong>$1</strong> — <strong>$2</strong> аатынан киирэргэ саҥа аһарык. <em>Кэлин туттарга сурунан кэбис.</em> <br /> (Эргэ оруобаттар кыттааччы аата уонна саҥа киирэр киһи аата сөп түбэллэрин ирдиир буоллахтарына, <strong>$3</strong> кыттааччы аатын уонна маны <strong>$4</strong> аһарык курдук туттуохха сөп.)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider кыаллыбат.",
        "botpasswords-restriction-failed": "Буот аһарыгын кытта сыһыаннаах хааччахтан киирии сатаммата.",
        "botpasswords-invalid-name": "Кыттааччы аатыгар буот аһарыгын араарааччыта суох эбит (\"$1\").",
        "botpasswords-not-exist": "«$1» кыттааччыга «$2» диэн ааттаммыт оруобакка аналлаах аһарыга суох эбит.",
        "resetpass_forbidden": "Киирии тылы уларытар сатаммат",
+       "resetpass_forbidden-reason": "Аһарыгы уларытар сатаммат: $1",
        "resetpass-no-info": "Ааккын билиһиннэрдэххинэ эрэ бу сирэйгэ быһа тиийиэххин сөп.",
        "resetpass-submit-loggedin": "Киирии тылы уларытыы",
        "resetpass-submit-cancel": "Салҕаама",
        "passwordreset-emaildisabled": "Бу биикигэ эл. почтаны туттуу араарыллыбыт",
        "passwordreset-username": "Кыттааччы:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Суруллубут суругу көрөҕүн дуо?",
-       "passwordreset-capture-help": "Бу бэлиэни туруордаххына кыттааччыга ыытыллар сурук (быстах кэмҥэ туһаныллар киирии тыллаах) көстүө.",
        "passwordreset-email": "Электроннай почтата:",
        "passwordreset-emailtitle": "{{SITENAME}} бырайыакка аатын туһунан",
        "passwordreset-emailtext-ip": "Ким эрэ (баҕар эн буолуо, бу IP-ттан $1)  {{SITENAME}} ($4) бырайыакка киирии тылы уларытар туһунан ыйытык биэрбит.\nБу электрон аадырыһы кытта бу {{PLURAL:$3|аат ситимнээх|ааттар ситимнээхтэр}}:\n\n$2\n\nБу быстах кэмҥэ аналлаах {{PLURAL:$3|киирии тыл|кирии тыллар}} {{PLURAL:$5|биир күн үлэлиэҕэ|$5 күн үлэлиэхтэрэ}}.\nЭн тиһиликкэ ааккын этэн саҥа киирии тылы киллэриэхтээххин.\nӨскө бу ыйытыгы ыыппатах буоллаххына, эбэтэр урукку киирии тылгын өйдөөн кэлбит буоллаххына \nбу биллэриини ааххайыа суоххун сөп.\nОччоҕо урукку киирии тылыҥ оннунан хаалыа.",
        "passwordreset-emailelement": "Кыттааччы: \n$1\n\nБыстах аһарык тыл: \n$2",
        "passwordreset-emailsentemail": "Өскө бу Эн ааккар баайыллыбыт аадырыс буоллаҕына, аһарык тылы уларытар туһунан сурук барыа.",
        "passwordreset-emailsentusername": "Өскө бу аакка баайыллыбыт аадырыс баар буоллаҕына, аһарык тылы уларытар туһунан сурук онно барыа.",
+       "passwordreset-nocaller": "Ыҥырааччы көстүөхтээх",
+       "passwordreset-nosuchcaller": "Ыҥырааччы суох: $1",
+       "passwordreset-ignored": "Аһарыгы быраҕар сатаммата. Баҕар биир да провайдер холбоммокко сылдьара буолаарай?",
+       "passwordreset-invalidemail": "Аадырыс алҕастаах",
+       "passwordreset-nodata": "Кыттааччы аата да, аадырыһа да ыйыллыбатахтар",
        "changeemail": "Аадырыһы уларытыы уонна сотуу",
        "changeemail-header": "Бу форманы толорон аадырыскын уларыт. Уларытыыны бигэргэтэргэ аһарыккын киллэриэхтээххин. Почтаҥ аадырыһыттан бэлиэ-ааккыттан араарыаххын баҕарар буоллаххына аадырыһы сотон баран бигэргэтэн кэбиһээр.",
        "changeemail-no-info": "Бу сирэйгэ чопчу тиийэргэ, тиһиликкэ бэлиэтэммит ааккын этиэхтиэххин.",
        "minoredit": "Бу суолтата суох уларытыы",
        "watchthis": "Бу сирэйи кэтээн көрөргө",
        "savearticle": "Уларытыыны бигэргэтии",
+       "savechanges": "Уларытыылары бигэргэтии",
+       "publishpage": "Оҥор",
+       "publishchanges": "Бигэргэт",
        "preview": "Холоон көрүү",
        "showpreview": "Уларытыах иннинэ көрүү",
        "showdiff": "Уларытыылар",
        "accmailtext": "[[User talk:$1|$1]] кыттааччыга түбэспиччэ бэлиэлэртэн оҥоһуллубут аһарык тыл бу аадырыска $2 ыытылынна.\nТиһиккэ бэлиэтэнэн баран аһарыккын ''[[Special:ChangePassword|уларытыаххын]]'' сөп.",
        "newarticle": "(Саҥа ыстатыйа)",
        "newarticletext": "Эн суох сирэйгэ киирэ сатаатыҥ.\nМаннык ааттаах саҥа ыстатыйаны оҥорор буоллаххына, аллара баар түннүккэ суруй\n(сиһ. [$1 көмөнү] көрүөххүн сөп).\nӨскө манна сыыһа киирбит буоллаххына интэриниэтиҥ бырагыраамматын \"төнүн\" диэххин сөп.",
-       "anontalkpagetext": "----''Бу аатын эппэтэх кыттааччы ырытар сирэйэ.\nIP-аадырыһа эрэ көстөр.\nБиир IP-аадырыс хас да киһиэхэ бэриллиэн сөп. Өскө атын киһиэхэ суруллубут суругу алҕас туппут буоллаххына, бэйэҥ [[Special:CreateAccount|ааккын билиһиннэр]] эбэтэр [[Special:UserLogin|киир]], оччоҕо кэлин да булкуур тахсыа суоҕа.''",
+       "anontalkpagetext": "----\n<em>Бу аатын эппэтэх, бэлиэтэнэ илик эбэтэр бэлиэтэниэн баҕарбат кыттааччы сирэйэ.</em>\nОл иһин кинини чопчулаары IP-аадырыһын туттабыт.\nБу аадырыһы атын кыттааччылар эмиэ туһаныахтарын сөп.\nӨскөтө Эн ааккын эппэтэх кыттааччы Эйиэхэ туһуламматах суругу туттум дии саныыр буоллаххына, бука диэн, [[Special:CreateAccount|бэлиэтэн]] биитэр [[Special:UserLogin|урут бэлиэтэммит ааккынан киир]]. Оччоҕо булкуур тахсыа суоҕа.",
        "noarticletext": "Билигин бу сирэй кураанах.\nБу аат атын ыстатыйаларга туттулларын [[Special:Search/{{PAGENAME}}|булуоххун сөп]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} сурунаалларга көрдүөххүн сөп],\nэбэтэр [{{fullurl:{{FULLPAGENAME}}|action=edit}} маннык ааттаах саҥа ыстатыйаны суруйуоххун сөп]</span>.",
        "noarticletext-nopermission": "Билигин бу сирэй кураанах.\nБу [[Special:Search/{{PAGENAME}}|ааты атын сирэйдэргэ көрдөөн көрүөххүн]] сөп,\nэбэтэр <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} сурунаалларга манна сыһыаннаах суруктары булуоххун сөп].</span> Бу сирэйи айар кыаҕыҥ суох.",
        "missing-revision": "«{{FULLPAGENAME}}» сирэй $1 барыла суох.\n\nМаннык үксүн хайыы-үйэ сотуллубут билэҕэ эргэрбит сигэнэн бардахха буолааччы.\nСиһилии баҕар [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} сотуу сурунаалыгар] баара буолуо.",
        "userpage-userdoesnotexist": "\"<nowiki>$1</nowiki>\" аат бэлиэтэммэтэх. Бу сирэйи оҥорор/уларытар баҕалааххын дуо?",
        "userpage-userdoesnotexist-view": "\"$1\" кыттааччы аата бэлиэтэниллибэтэх.",
        "blocked-notice-logextract": "Бу кыттааччы билигин бобуллубут.\nМанна бобуу сурунаалын бүтэһик суруга көстөр:",
-       "clearyourcache": "'''Болҕой:''' Уларыппыт сирэйгин сөпкө көрөргө браузер кээһин ыраастыаххын наада буолуо.\n*'''Firefox / Safari.''' ''Shift'' кунуопканы тутан туран ''Reload'' баттаа, эбэтэр ''Ctrl-F5'', ''Ctrl-R'' дуу (Mac-ка ''⌘-R'') баттаа;\n*'''Google Chrome:''' ''Ctrl-Shift-R'' баттаа (Mac-ка ''⌘-Shift-R'')\n*'''Internet Explorer:''' ''Ctrl'' тутан туран ''Refresh'' баттаа, эбэтэр ''Ctrl-F5'' баттаа.\n*'''Opera:''' Манна ''Tools → Preferences'' киирэн кээһин ыраастаа",
+       "clearyourcache": "<strong>Болҕой:</strong> Уларыппыт сирэйгин сөпкө көрөргө браузер кээһин ыраастыаххын наада буолуо.\n*<strong>Firefox / Safari.</strong> <em>Shift</em> кунуопканы тутан туран <em>Саҥардыы</em> баттаа, эбэтэр <em>Ctrl-F5</em>, <em>Ctrl-R</em> дуу (Mac-ка <em>⌘-R</em>) баттаа;\n*<strong>Google Chrome:</strong> <em>Ctrl-Shift-R</em> баттаа (Mac-ка <em>⌘-Shift-R</em>)\n*<strong>Internet Explorer:</strong> <em>Ctrl</em> тутан туран <em>Саҥардыы</em> баттаа, эбэтэр <em>Ctrl-F5</em> баттаа.\n*<strong>Opera:</strong> Манна <em>Tools → Preferences</em> киирэн кээһин ыраастаа",
        "usercssyoucanpreview": "'''Көмө.''' CSS-билэ саҥа барылын бигэргэтиэҥ иннинэ бу тимэҕи «{{int:showpreview}}»  баттаан тургутан көр.",
        "userjsyoucanpreview": "'''Көмө.''' JS-билэ саҥа барылын бигэргэтиэҥ иннинэ бу тимэҕи «{{int:showpreview}}»  баттаан тургутан көр.",
        "usercsspreview": "'''Умнума: бу CSS тургутуута эрэ.\nБилигин оҥорбутуҥ бигэргэтиллэ илик!'''",
        "continue-editing": "Уларытар сиргэ",
        "previewconflict": "Этот предварительный просмотр отражает текст в верхнем окне редактирования так, как он будет выглядеть, если вы решите записать его.",
        "session_fail_preview": "'''Сиэрбэр сессия идентификаторын сүтэрэн кэбиһэн эн уларытыыгын кыайан киллэрбэтэ.\nБаҕар, үлэ сеансын бүтэрбитиҥ буолуо. <strong>Баһаалыста, көҥүлү ааспыккын бил уонна өссө холонон көр.\n<strong>\nОлох сатамматаҕына биикиттэн [[Special:UserLogout|тахсан]] баран өссө киирэн көрөөр, ону сэргэ браузерыҥ бу саайтан cookies диэни ыларга көҥүллүүрүн бэрэбиэркэлээҥ.'''",
-       "session_fail_preview_html": "'''Сессия дааннайдарын сүтэрэн кэбиһэн сиэрбэр эн уларытыыгын киллэрбэтэ.'''\n\n''{{SITENAME}} ыраас HTML тылы көҥүллүүр буолан JavaScript туһананнар куһаҕаны оҥоруохтарын сөп, онон эрдэ көрдөрүү араарыллыбыт.''\n\n'''Өскө бу уларытыы туох да куһаҕаны аҕалыа диэбэт буоллаххына хатылаа. Ол сатамматаҕына [[Special:UserLogout|тахсан баран]] өссө киирэн көрөөр.'''",
+       "session_fail_preview_html": "Сиэссийэ дааннайдарын сүтэрэн кэбиһэн сиэрбэр эн уларытыыгын киллэрбэтэ.\n\n<em>{{SITENAME}} ыраас HTML тылы туттары көҥүллүүр буолан, JavaScript көмөтүнэн куһаҕаны оҥоруохтарын сөп, онон эрдэ көрдөрүү араарыллыбыт.</em>\n\n<strong>Өскө бу уларытыы туох да куһаҕаны аҕалыа диэбэт буоллаххына хатылаа.</strong> \nОл сатамматаҕына [[Special:UserLogout|тахсан баран]] өссө киирэн көрөөр, ону таһынан браузерыҥ cookies көҥүллүүрүн тургутуоххун сөп.",
        "token_suffix_mismatch": "'''Эн уларытыыҥ киирбэтэ, тоҕо диэтэххэ эн бырагырааммаҥ сорох сурук бэлиэлэрин сыыһа көрөр эбит.\nЫстатыйаны буорту гынымаары уларытыыҥ ылыныллыбата.\nИтинник сыыһалар үксүн прокси-сиэрбэрдэри туһаннахха тахсааччылар.'''",
        "edit_form_incomplete": "'''Уларытыы сорҕото сиэрбэргэ тиийбэтэ. Үчүгэйдик сыныйан көр, Эн уларытыыларыҥ туох да омсото суохтар дуо. Онтон өссө боруобалаа.'''",
        "editing": "Уларытыы $1",
        "invalid-content-data": "Алҕастаах дааннайдар",
        "content-not-allowed-here": "[[$2]] сирэйгэ \"$1\" туттуллуо суохтаах",
        "editwarning-warning": "Атын сирэйгэ көстөххүнэ билигин оҥорбут уларытыыҥ барыта сүтэн хаалыаҕа.\nБэлиэтэммит буоллаххына, бу сэрэтиини туруорууларыҥ \"{{int:prefs-editing}}\" салаатыгар араарар кыахтааххын.",
+       "editpage-invalidcontentmodel-title": "Иһинээҕитин мадьыала өйөммөт эбит",
+       "editpage-invalidcontentmodel-text": "«$1» иһинээҕитин мадьыала өйөммөт эбит.",
        "editpage-notsupportedcontentformat-title": "Иһинээҕитин формаата өйөммөт эбит",
        "editpage-notsupportedcontentformat-text": "$2 иһинээҕитин модела $1 иһинээҕитин формаатын өйөөбөт эбит.",
        "content-model-wikitext": "биики-тиэкис",
        "content-model-css": "CSS",
        "content-json-empty-object": "Кураанах эбийиэк",
        "content-json-empty-array": "Кураанах массив",
+       "deprecated-self-close-category": "Манна көҥүллэммэт бэйэтэ сабыллар HTML-тиэктэри туттар сирэйдэр",
+       "deprecated-self-close-category-desc": "Манна көҥүллэммэт бэйэтэ сабыллар HTML-тиэктэр бааллар, холобур <code>&lt;b/></code> биитэр <code>&lt;span/></code>. Сотору кэминэн HTML5 ирдэбилигэр сөп түбэһиннэрэ, дьайыылара уларыйыа. Онон маннык эргэрбит тиэктэри туттубакка буола сатаа.",
        "duplicate-args-warning": "<strong>Болҕой:</strong> «$3» параметр бииртэн ордук эрэ буоллаҕына [[:$1]] маны [[:$2]] холбуур. Кэлиҥҥи эрэ сыыппара туһаныллыа.",
        "duplicate-args-category": "Халыыптары ыҥырарга хатыланар аргуменнардаах сирэйдэр",
        "duplicate-args-category-desc": "Халыыптары ыҥырарга хатыланар аргуменнардаах сирэйдэр, холобур маннык <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> or <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "revdelete-unsuppress": "Төннөрүллүбүт торумнартан хааччахтааһыны ылан кэбиһэргэ",
        "revdelete-log": "Төрүөтэ:",
        "revdelete-submit": "Маны талбыт {{PLURAL:$1|барылбар|барылларбар}} тутун",
-       "revdelete-success": "'''Барыл көстүүтэ сөпкө уларыйда.'''",
+       "revdelete-success": "Торум көстүүтэ саҥардылынна.",
        "revdelete-failure": "'''Барыл хайдах көстөрө кыайан уларытыллыбат:'''\n$1",
-       "logdelete-success": "'''Дьайыы көстүүтэ сөпкө уларыйда.'''",
+       "logdelete-success": "Дьайыы көстүүтэ уларыйда.",
        "logdelete-failure": "'''Сурунаал дөбөҥө быһаарыллыбата:'''\n$1",
        "revdel-restore": "Көстүүтүн уларытыы",
        "pagehist": "Устуоруйатын сирэйэ",
        "mergehistory-fail-no-change": "Устуоруйа холбоһуутугар ханнык да биэрсийэ холбоһуута буолбата. Баһаалыста сирэйи уонна быстах кэмнээх кэмнэбили өссө төгүл бэрэбиэркэлээ.",
        "mergehistory-fail-permission": "Устуоруйаны холбуурга быраап тиийбэт",
        "mergehistory-fail-self-merge": "Саҕалыыр уонна түмүктүүр сирэйдэриҥ атын буолуохтаахтар",
+       "mergehistory-fail-timestamps-overlap": "Төрүт торумнар биитэр сабырыйаллар, биитэр атын торумнар кэнниттэн кэлэллэр.",
        "mergehistory-fail-toobig": "Устуоруйаны холбуур табыллыбата, тоҕо диэтэххэ $1  барылга көҥүллэнэр лимииттэн элбэҕи көһөрөр наада эбит.",
        "mergehistory-no-source": "Бастакы $1 сирэй суох.",
        "mergehistory-no-destination": "Баар буолуохтаах $1 сирэй суох.",
        "search-external": "Тастан көрдөөһүн",
        "searchdisabled": "{{SITENAME}} көрдүүр тэрилэ араарыллыбыт. Атын көрдүүр системаларынан наадыйар сирэйдэргитин көрдөтүөххүтүн сөп. Ол гынан баран поисковик кээһигэр баар торум эргэрбит буолуон сөп.",
        "search-error": "Көрдүүр кэмҥэ алҕас таҕыста: $1",
+       "search-warning": "Көрдүүр кэмҥэ сэрэтии таҕыста: $1",
        "preferences": "Уларытыылар",
        "mypreferences": "Туруоруулар",
        "prefs-edits": "Көннөрүү ахсаана:",
        "prefs-help-recentchangescount": "Бу саҥа көннөрүүлэри, сирэй устуоруйаларын уонна сурунааллары көрдөрөр.",
        "prefs-help-watchlist-token2": "Бу кэтиир тиһигиҥ ситим-ханаалын кистэлэҥ күлүүһэ.\nБу күлүүһүнэн ким баҕарар эн кэтиир тиһиккин көрүөн сөп, онон кимиэхэ да биэримэ. [[Special:ResetTokens|Маны баттаан уларытыаххын сөп]].",
        "savedprefs": "Эн туруорууларыҥ олохтоннулар.",
-       "savedrights": "{{GENDER:$1|$1}} кыттааччы бырааба бигэргэннэ.",
+       "savedrights": "{{GENDER:$1|$1}} кыттааччы бөлөҕө бигэргэннэ.",
        "timezonelegend": "Олохтоох кэм:",
        "localtime": "Олохтоох кэмим:",
        "timezoneuseserverdefault": "Сиэрбэр туруоруутунан ($1)",
        "prefswarning-warning": "Туруорууларгын уларыппыккын ол эрэн бигэргэппэтэххин.\nБу сирэйтэн «$1» баттамы баттаабакка таҕытаххына, барыта уруккутунан хаалыа.",
        "prefs-tabs-navigation-hint": "Сүбэ: Көмпүүтэриҥ клаватууратын стрелкаларын туһанан кыбытыктан кыбытыкка көһүөххүн сөп.",
        "userrights": "Кыттааччылар бырааптарын салайыы",
-       "userrights-lookup-user": "Ð\9aÑ\8bÑ\82Ñ\82ааÑ\87Ñ\8bлаÑ\80 Ð±Ó©Ð»Ó©Ñ\85Ñ\82Ó©Ñ\80үн Ñ\81алайыы",
+       "userrights-lookup-user": "Ð\9aÑ\8bÑ\82Ñ\82ааÑ\87Ñ\87Ñ\8bнÑ\8b Ñ\82алыы",
        "userrights-user-editname": "Кыттааччы аата:",
-       "editusergroup": "{{GENDER:$1|Кыттааччы}} бөлөхтөрүн уларытарга",
+       "editusergroup": "Кыттааччы бөлөхтөрүн көрдөрүү",
        "editinguser": "<strong>[[User:$1|$1]]</strong> кыттааччы $2 быраабын уларытыы",
        "userrights-editusergroup": "Кыттааччы бөлөхтөрүн уларытарга",
        "saveusergroups": "{{GENDER:$1|Кыттааччы}} бөлөхтөрүн бигэргэт",
        "userrights-reason": "Төрүөтэ:",
        "userrights-no-interwiki": "Атын биикилэргэ кыттааччылар бырааптарын уларытар быраабыҥ суох.",
        "userrights-nodatabase": "$1 билэ тиһигэ (олоҕо, база данных) суох эбэтэр локальнай буолбатах.",
-       "userrights-nologin": "Эн дьон бырааптарын уларытаргар администратор быһыытынан [[Special:UserLogin|бэлиэтэниэхтээххин]].",
-       "userrights-notallowed": "Атын кыттааччы быраабын эбэр уонна уларытар кыаҕыҥ суох эбит.",
        "userrights-changeable-col": "Эн уларытар кыахтаах бөлөхтөрүҥ",
        "userrights-unchangeable-col": "Бу бөлөхтөрү уларытар кыаҕыҥ суох",
        "userrights-conflict": "Кыттааччы быраабын быһаарарга алҕас таҕыста! Хатылаан көр.",
-       "userrights-removed-self": "Бэйэҥ кыаххын сарбынныҥ. Онон бу сирэйгэ киирэр кыаҕыҥ суох буолла.",
        "group": "Бөлөх:",
        "group-user": "Кыттааччылар",
        "group-autoconfirmed": "Аптамаатынан бигэргэтиллибит кыттааччылар",
        "right-siteadmin": "Билэ олоҕор (database) киирэри бобуу уонна көҥүллээһин",
        "right-override-export-depth": "сирэйдэри таһаарааһын (экспортааһын), ситимнээх сирэйдэри 5-с таһымҥа дылы холбоон туран",
        "right-sendemail": "Атын кыттааччыларга эл. почтаны ыытарга",
-       "right-passwordreset": "Киирии тылы почта нөҥүө уларытыыны көрүү",
-       "right-managechangetags": "[[Special:Tags|Бэлиэлэри]] билии олоҕуттан ылыы уонна сотуу",
+       "right-managechangetags": "[[Special:Tags|Тиэктэри]] оҥоруу уонна холбооһун/араарааһын",
        "right-applychangetags": "Улартыыларгын кытта [[Special:Tags|тиэктэри]] тутун",
        "right-changetags": "Ханнык баҕарар [[Special:Tags|тиэктэри]] биирдиилээн уларытыыларга уонна сурунаал суруйууларыгар эбэри уонна сотору көҥүллээ",
+       "right-deletechangetags": "[[Special:Tags|тиэктэри]] билии олоҕуттан сотуу",
        "grant-generic": "Быраап «$1» нобуора",
        "grant-group-page-interaction": "Сирэйдиин алтыһыы",
        "grant-group-file-interaction": "Миэдьийэлиин алтыһыы",
        "grant-group-high-volume": "Кылгас кэм иһигэр элбэҕи оҥоруу",
        "grant-group-customization": "Нарылааһын уонна туруоруулар",
        "grant-group-administration": "Дьаһайыы",
+       "grant-group-private-information": "Эн тускунан билиини көҥүллээһин",
        "grant-group-other": "Эгэлгэ тэрээһиннэр",
        "grant-blockusers": "Бэлиэ ааттары хааччахтааһын ууонна хааччаҕын устуу",
        "grant-createaccount": "Бэлиэтэнии",
        "grant-highvolume": "Түргэнник элбэҕи уларытыы",
        "grant-oversight": "Кыттааччылар уларытыыларын уонна сирэйдэр барылларын кистээһин",
        "grant-patrol": "Сирэй уларыйыытын ботурууллааһын",
+       "grant-privateinfo": "Киһи туһунан сиһилии билиигэ көҥүл",
        "grant-protect": "Көмүскээһин уонна көмүскэли суох гыныы",
        "grant-rollback": "Сирэй уларыйыытын төннөрүү",
        "grant-sendemail": "Атын кыттааччыларга эл. суругу ыытыы",
        "grant-basic": "Сүрүн быраап",
        "grant-viewdeleted": "Сотуллубут билэлэри уонна сирэйдэри көрүү",
        "grant-viewmywatchlist": "Кэтиир тиһиликкин көрүү",
+       "grant-viewrestrictedlogs": "Хааччахтаах сурунаалы көрүү",
        "newuserlogpage": "Кыттааччылары бэлиэтиир сурунаал",
        "newuserlogpagetext": "Соторутааҕыта бэлиэтэммит кыттааччылар.",
        "rightslog": "Кыттаачы бырааптарын сурунаала",
        "rightslogtext": "Бу кыттааччы бырааптарын уларыйыытын көрдөрөр сурунаал.",
        "action-read": "бу сирэйи ааҕыы",
        "action-edit": "бу сирэйи көннөрүү",
-       "action-createpage": "сирэйдэри оҥоруу",
-       "action-createtalk": "Ñ\8bÑ\80Ñ\8bÑ\82Ñ\8bÑ\8b Ñ\81иÑ\80Ñ\8dйдÑ\8dÑ\80ин Ð¾Ò¥Ð¾Ñ\80Ñ\83Ñ\83",
+       "action-createpage": "бу сирэйи оҥоруу",
+       "action-createtalk": "ырытыы сирэйин оҥоруу",
        "action-createaccount": "кыттааччы бу бэлиэтэнэр аатын оҥоруу",
        "action-autocreateaccount": "тас бэлиэ-аатынан аптамаатынан киирии",
        "action-history": "сирэй устуоруйатын көрүү",
        "action-viewmyprivateinfo": "бэйэҥ тускунан көрүү",
        "action-editmyprivateinfo": "бэйэҥ тускунан суруллубуту уларыт",
        "action-editcontentmodel": "сирэй ис тутулун уларытыы",
-       "action-managechangetags": "билии олоҕор бэлиэлэри оҥоруу уонна сотуу",
+       "action-managechangetags": "тиэктэри оҥоруу уонна холбооһун/араарыы",
        "action-applychangetags": "тиэктэри Эн уларытыыларгын кытта туһанары көҥүллээ",
        "action-changetags": "ханнык баҕарар тиэктэри сурунаал биирдиилээн уларытыыларыгар уонна суруктарыгар эбэри уонна сотору көҥүллээ",
+       "action-deletechangetags": "тиэктэри билии олоҕуттан сотуу",
+       "action-purge": "сирэй кээһин ыраастааһын",
        "nchanges": "$1 {{PLURAL:$1|уларытыы|уларытыылар}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|тиһэх сылдьыыгыттан}}",
        "enhancedrc-history": "устуоруйата",
        "recentchangeslinked-page": "Сирэй аата:",
        "recentchangeslinked-to": "Төттөрүтүн, ыйыллыбыт сирэйгэ сигэнэр сирэйдэри көрдөр",
        "recentchanges-page-added-to-category": "[[:$1]] категорияҕа эбилиннэ",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] уонна [[Special:WhatLinksHere/$1|{{PLURAL:$2|биир сирэй|$2 сирэй}}]] категорияҕа эбилиннэ",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] категорияҕа эбилиннэ, [[Special:WhatLinksHere/$1|бу сирэй атын сирэйдэргэ киириитэ]]",
        "recentchanges-page-removed-from-category": "[[:$1]] категорияттан сотулунна",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] уонна {{PLURAL:$2|биир сирэй|$2 сирэй}} категорияттан сотулунна",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] категорияттан сотулунна, [[Special:WhatLinksHere/$1|бу сирэй атын сирэйдэргэ киириитэ]]",
        "autochange-username": "MediaWiki аптамаатынан уларыйыыта",
        "upload": "Билэни угуу",
        "uploadbtn": "Билэни киллэрии",
        "file-thumbnail-no": "Билэ аата мантан саҕаланар <strong>$1</strong>.\nАрааһа ойуу кыра куоппуйата быһыылаах ''(миниатюра)''.\nБу ойуу толору барыйаана баар буоллаҕына ону манна суруй, эбэтэр аатын уларыт.",
        "fileexists-forbidden": "Маннык ааттаах билэ баар, хат суруллар кыаҕа суох.\n\nСин биир бу билэни киллэриэххин баҕарар буоллаххына төннөн атыннык ааттаа. [[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "Маннык ааттаах ойуу уопсай ыскылаакка баар эбит.\nОл да буоллар билэни киллэриэххин баҕарар буоллаххына төннөн атыннык ааттаа. [[File:$1|thumb|center|$1]]",
+       "fileexists-no-change": "Киллэриллэр билэ баар билэни кытта үүт-үкчү <strong>[[:$1]]</strong>.",
+       "fileexists-duplicate-version": "Киллэриллэр билэ баар билэ {{PLURAL:$2|урукку барылын|урукку барылларын}} кытта үүт-үкчү <strong>[[:$1]]</strong>.",
        "file-exists-duplicate": "Бу билэ атын {{PLURAL:$1|билэ дубликаата|билэлэр дубликааттара}} буолар:",
        "file-deleted-duplicate": "Маннык билэ ([[:$1]]) урут сотуллубут эбит. Суруттарыаҥ иннинэ бастаан тоҕо сотуллубутун көр.",
        "file-deleted-duplicate-notitle": "Маннык билэ урут сотуллубут эбит, аата бобуллубут.\nБилэни саҥаттан киллэриэҥ иннинэ бобуллубут билэлэри көрөр кыахтаах киһиэхэ тахсан тоҕо бобуллубутун быһаарыс.",
        "uploaded-script-svg": "Хачайдаммыт SVG-билэҕэ сценарийы өйүүр куттааллаах «$1» элэмиэн көһүннэ.",
        "uploaded-hostile-svg": "Хачайдаммыт SVG-билэ истиилин элэмиэнигэр кутталлаах CSS-куод көһүннэ.",
        "uploaded-event-handler-on-svg": "SVG-билэлэргэ <code>$1=\"$2\"</code> сабыытыйаны таҥастааччы атрибууттарын туруоруу көҥүллэммэт.",
+       "uploaded-href-attribute-svg": "Манна көстүбүт <code><$1 $2=\"$3\"></code> SVG-билэ сигэҕэ аналлаах href-атрибуттарыгар, маннык эрэ көүллэнэр: http:// биитэр https://.",
        "uploaded-href-unsafe-target-svg": "Хачайдаммыт SVG-билэҕэ кутталлаах сигэ көһүннэ <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "uploaded-animate-svg": "«Animate» тиэк көһүннэ, кини «from»-атрибут көмөтүнэн  <code>&lt;$1 $2=\"$3\"&gt;</code> хачайдаммыт SVG-билэҕэ сигэни уларытыан сөп.",
        "uploaded-setting-event-handler-svg": "Дьайыы таҥастыыр тэрил атрибуутун уларытар бобуллубут, киллэриллибит SVG-билэҕэ <code>&lt;$1 $2=\"$3\"&gt;</code> куод көстүбүт.",
        "upload-http-error": "HTTP алҕаһа таҕыста: $1",
        "upload-copy-upload-invalid-domain": "Бу домеҥҥа хачайдааһыны хатылыыр табыллыбат.",
        "upload-foreign-cant-upload": "Бу биики ыйыллыбыт репозиторийга хачайдыырга туруоруллубатах",
+       "upload-foreign-cant-load-config": "Билэ тас ыскылаатыгар хачайдааһын конфигурациятын ылар сатаммата.",
+       "upload-dialog-disabled": "Бу тэрил көмөтүнэн бу биикигэ хачайдыыры сабан кэбиспиттэр.",
        "upload-dialog-title": "Билэни угуу",
        "upload-dialog-button-cancel": "Салҕаама",
+       "upload-dialog-button-back": "Төнүн",
        "upload-dialog-button-done": "Оҥоһулунна",
        "upload-dialog-button-save": "Бигэргэт",
        "upload-dialog-button-upload": "Киллэрии",
        "upload-form-label-infoform-title": "Сиһилии",
        "upload-form-label-infoform-name": "Аата",
+       "upload-form-label-infoform-name-tooltip": "Билэ баһа кини аатын курдук бигэргэниэ. Ханнык баҕарар тылы уонна тыллар ыккардыларыгар арыты туһаныахха сөп. Кэтирээһинин ыйыма.",
        "upload-form-label-infoform-description": "Быһаарыыта",
        "upload-form-label-infoform-description-tooltip": "Кылгастык бу айымньы туһунан сүрүннээн этиҥ. Хаартыскаҕа сүнньүнэн туох ойууламмытый, ханна түһэриллибитий.",
        "upload-form-label-usage-title": "Туһаныы",
        "backend-fail-read": "$1 билэни ааҕар табыллыбата.",
        "backend-fail-create": "$1 билэни суруттарар табыллыбата.",
        "backend-fail-maxsize": "$1 билэни суруттарар табыллыбата, тоҕо диэтэххэ кини кээмэйэ $2 баайты куоһарар.",
-       "backend-fail-readonly": "«$1» сиэрбэр «ааҕыы эрэ» эрэсиимҥэ турар. Төрүөтэ: «$2»",
+       "backend-fail-readonly": "«$1» сиэрбэр «ааҕыы эрэ» диэн эрэсиимҥэ турар. Төрүөтэ: <em>$2</em>",
        "backend-fail-synced": "«$1» билэ сөпсөһүллүбэтэх туруктаах эбит",
        "backend-fail-connect": "Маны кытта «$1» холбонор табыллыбата.",
        "backend-fail-internal": "Манна «$1» биллибэт алҕас таҕыста.",
        "uploadstash-summary": "Бу сирэй биикигэ киллэриллибит (эбэтэр киллэриллэ турар) ол гынан баран аһаҕас көрүүгэ тахса илик билэлэри көрөргө аналлаах. Бу билэлэр ааптартан ураты кимиэхэ да көстүбэттэр.",
        "uploadstash-clear": "Кистэммит билэлэри суох оҥорорго",
        "uploadstash-nofiles": "Кистэммит билэлэриҥ суохтар.",
-       "uploadstash-badtoken": "ЫйбÑ\8bÑ\82 Ð´Ñ\8cайÑ\8bÑ\8bгÑ\8bн Ð¾Ò¥Ð¾Ñ\80оÑ\80 Ñ\82абÑ\8bллÑ\8bбаÑ\82а. Ð\90Ñ\80ааһа Ð±Ð¾Ð»Ð´Ñ\8cоÒ\95о Ð±Ò¯Ð¿Ð¿Ò¯Ñ\82 Ð±Ñ\8bÒ»Ñ\8bÑ\8bлааÑ\85. Ó¨Ñ\81Ñ\81Ó© Ð±Ð¾Ñ\80Ñ\83обалаа.",
+       "uploadstash-badtoken": "ЫйбÑ\8bÑ\82 Ð´Ñ\8cайÑ\8bÑ\8bгÑ\8bн Ð¾Ò¥Ð¾Ñ\80оÑ\80 Ñ\82абÑ\8bллÑ\8bбаÑ\82а. Ð\90Ñ\80ааһа ÐºÐ¸Ð¸Ñ\80биÑ\82 Ð°Ð°Ñ\82Ñ\8bÒ¥ Ð±Ð¾Ð»Ð´Ñ\8cоÒ\95о Ð±Ò¯Ð¿Ð¿Ò¯Ñ\82 Ð±Ñ\8bÒ»Ñ\8bÑ\8bлааÑ\85. Ð¥Ð°Ñ\82Ñ\8bлаан ÐºÓ©Ñ\80.",
        "uploadstash-errclear": "Билэлэри сотор табыллыбата.",
        "uploadstash-refresh": "Билэлэр тиһиктэрин саҥардан биэр",
+       "uploadstash-thumbnail": "ойуучааны көрдөр",
+       "uploadstash-exception": "Суруттараргын быстах уурар сиргэ харайар сатаммата ($1): \"$2\".",
        "invalid-chunk-offset": "Бобуллубут сыҕарыйыы",
        "img-auth-accessdenied": "Киирии бобуллубут",
        "img-auth-nopathinfo": "PATH_INFO суох.\nЭн сиэрбэриҥ маннык сибидиэнньэни ыытарга туруоруллубатах эбит.\nБаҕар кини CGI олоҕурара буолуо ол иһин img_auth өйөөбөтө буолуо.\nМаны https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization көр.",
        "filerevert-submit": "Төннөрүү",
        "filerevert-success": "'''[[Media:$1|$1]]''' бу торумҥа төннөрүлүннэ [$4 торум Filetype-missingот $3, $2].",
        "filerevert-badversion": "Бу билэ этиллибит күҥҥэ-ыйга/кэмҥэ оҥоһуллубут урукку торума суох.",
+       "filerevert-identical": "Талбыт торумуҥ билиҥҥи торуму кытта үүт үкчүлэр.",
        "filedelete": "Сот: $1",
        "filedelete-legend": "Билэни сот",
        "filedelete-intro": "Бу билэни '''[[Media:$1|$1]]''' туох баар суруллубут историятын кытта сотон эрэҕин.",
        "apisandbox": "API песочница",
        "apisandbox-jsonly": "API-песочницаны туһанарга JavaScript ирдэнэр.",
        "apisandbox-api-disabled": "Бу сайтка API араарыллыбыт.",
+       "apisandbox-intro": "Бу сирэйи <strong>MediaWiki API</strong> тургутан көрөргө туһан.\nAPI-ни туттар туһунан сиһилии манна ааҕыахха сөп [[mw:API:Main page|API туһунан]]. Холобура, [https://www.mediawiki.org/wiki/API#A_simple_example Сүрүн сирэй иһинээҕитин хайдах ылар туһунан]. Атын холобурдары көрөргө сигэни баттаа.\nБолҕой: бу тургутар сирэй эрээри, манна суруйбутуҥ биикигэ уларытыыны оҥоруон сөп.",
        "apisandbox-fullscreen": "Паныалы арыйыы.",
        "apisandbox-fullscreen-tooltip": "Браузеры толорорго песочница паныалын арыйыы.",
        "apisandbox-unfullscreen": "Сирэйи көрдөрүү",
        "apisandbox-submit": "Ыйытык оҥоруу",
        "apisandbox-reset": "Сот",
        "apisandbox-retry": "Хатылаа",
+       "apisandbox-loading": "«$1» API-модульга аналлаах хачайдана турар…",
+       "apisandbox-load-error": "«$1» API-модулга аналлаах хачайданарыгар алҕас таҕыста: $2",
+       "apisandbox-no-parameters": "Бу API-модулга туруоруута (параметра) суох.",
        "apisandbox-helpurls": "Көмө сигэлэр",
        "apisandbox-examples": "Холобурдар",
        "apisandbox-dynamic-parameters": "Дьайыы кээмэйдэрэ.",
        "apisandbox-results": "Түмүк",
        "apisandbox-sending-request": "API-көрдөбүлү ыытыы…",
        "apisandbox-loading-results": "API-түмүгүн ылыы…",
+       "apisandbox-results-error": "Көрдөбүлгэ API-хоруйу киллэрии  кэмигэр алҕас таҕыста: $1.",
+       "apisandbox-request-url-label": "Көрдөбүл URL-аадырыһа:",
+       "apisandbox-request-time": "Көрдөбүл болдьоҕо: {{PLURAL:$1|$1 мс}}",
        "apisandbox-results-fixtoken": "Токены көннөрөн баран саҥаттан ыыт.",
+       "apisandbox-results-fixtoken-fail": "«$1» токены ыҥырар табыллыбата.",
+       "apisandbox-alert-page": "Бу сирэй хонуулара алҕастаах.",
+       "apisandbox-alert-field": "Хонуу суолтата алҕастаах.",
+       "apisandbox-continue": "Салгыы",
+       "apisandbox-continue-clear": "Сот",
+       "apisandbox-continue-help": "{{int:apisandbox-continue}} бүтэһик көрдөбүлү [https://www.mediawiki.org/wiki/API:Query#Continuing_queries салгыаҕа]; {{int:apisandbox-continue-clear}} салҕааһыны кытта ситимнээх туруоруулары ырастыа.",
+       "apisandbox-param-limit": "Муҥутуур болдьох <kbd>муҥутуурдук</kbd> туттулларын туоруор.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Аат даллара барыта)",
+       "apisandbox-multivalue-all-values": "$1 (Бары суолталара)",
        "booksources": "Кинигэлэр источниктара",
        "booksources-search-legend": "Кинигэ туһунан көрдөө",
        "booksources-search": "Бул",
        "booksources-text": "Манна кинигэ туһунан атын саайтарга ыйынньыктар хомулуннулар, онно баҕар эбии информация көстүөҕэ.",
        "booksources-invalid-isbn": "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 сигэлээх сирэйдэр",
+       "magiclink-tracking-pmid-desc": "Бу сирэйгэ PMID сигэ туттуллар. Сиһилии [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
+       "magiclink-tracking-isbn": "ISBN сигэлээх сирэйдэр",
+       "magiclink-tracking-isbn-desc": "Бу сирэйгэ ISBN сигэ туттуллар. Сиһилии [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
        "specialloguserlabel": "Толорооччу:",
        "speciallogtitlelabel": "Сыал (тиэкис эбэтэр {{ns:user}}:кыттааччы аата):",
        "log": "Сурунааллар",
        "activeusers-intro": "Бу кэлиҥҥи $1 {{PLURAL:$1|күҥҥэ|күннэргэ}} тугу эмэ гыммыт кыттааччылар тиһиктэрэ.",
        "activeusers-count": "Кэнники $3 күҥҥэ саҥа $1 көннөрүү киирбит",
        "activeusers-from": "Мантан саҕалаан кыттааччылары көрүү:",
+       "activeusers-groups": "Маннык бөлөххө киирэр кыттааччылары көрдөр:",
+       "activeusers-excludegroups": "Маннык бөлөххө киирэр кыттааччылары көрдөрүмэ:",
        "activeusers-noresult": "Кыттааччылар көстүбэтилэр.",
        "activeusers-submit": "Көхтөөх кыттааччылары көрдөр",
        "listgrouprights": "Кыттааччылар бөлөхтөрүн бырааптара",
        "listgrouprights-namespaceprotection-namespace": "Аат дала",
        "listgrouprights-namespaceprotection-restrictedto": "Кыттааччы көннөрөр бырааба",
        "listgrants": "Көҥүл",
+       "listgrants-summary": "Манна кыахтар тиһиликтэрэ, туох быраабы биэрэллэрэ көстөр. Кыттааччы ханнык эмит бырагыраамаҕа бэйэтин аатыттан тугу эрэ гынары көҥүллүөн сөп, ол эрээри онто быраабын таһымынан хааччахтанар. Бырагыраама кыттааччы аатыттан тугу эрэ гынар түгэнигэр ол аакка иҥэриллибит бырааптан уратыны оҥорор кыаҕа суох. \nБыраап туһунан [[{{MediaWiki:Listgrouprights-helppage}}|сиһилии манна ааҕыахха сөп]].",
        "listgrants-grant": "Көҥүл",
        "listgrants-rights": "Быраап",
        "trackingcategories": "Кэтиир категориялар",
        "trackingcategories-msg": "Кэтиир категория",
        "trackingcategories-name": "Этии аата",
        "trackingcategories-desc": "Категорияҕа киирии киритиэрийэ",
+       "restricted-displaytitle-ignored": "Болҕомтоҕо ылыллыбат ааттаах сирэйдэр",
+       "restricted-displaytitle-ignored-desc": "Сирэй болҕомтоҕо ылыллыбат, дьиҥнээх аатын кытта сөп түбэспэт <code><nowiki>{{DISPLAYTITLE}}</nowiki></code> диэн ааттаах эбит.",
        "noindex-category-desc": "Бу сирэйи көрдүүр роботтар болҕомотоҕо ылбаттар, тоҕо диэтэххэ <code><nowiki>__NOINDEX__</nowiki></code> диэн «аптаах тыл» туттуллубут. Сирэй инньэ гынарга көҥүллэммит аат далыгар баар эбит.",
        "index-category-desc": "Сирэйгэ <nowiki>__INDEX__</nowiki> диэн «аптаах тыл» баар эбит (сирэй ону көҥүллүүр аат далыгар баар эбит), онон көрдүүр роботтар кинини болҕомтоҕо ылыа да суох түгэннэргэ көрөллөр эбит.",
        "post-expand-template-inclusion-category-desc": "Халыыптары барытын көрдөрдөххө сирэй ыйааһына маны <code>$wgMaxArticleSize</code> куоһарыан сөп, онон сорҕото эрэ көрдөрүлүннэ.",
        "emailccsubject": "Эн суругуҥ куоппуйата $1: $2",
        "emailsent": "Сурук барда",
        "emailsenttext": "Эн суругуҥ ыытылынна.",
-       "emailuserfooter": "Бу сурук $2 кыттааччыга $1 кыттааччыттан «Сурукта ыыт» диэн тэрил көмөтүнэн {{SITENAME}} ситим-сиртэн ыытыллыбыт.",
+       "emailuserfooter": "Бу сурук {{GENDER:$2|$2}} кыттааччыга {{GENDER:$1|$1}} кыттааччыттан «Сурукта ыыт» (\"{{int:emailuser}}\") диэн тэрил көмөтүнэн {{SITENAME}} ситим-сиртэн ыытыллыбыт. {{GENDER:$2|Эн}} электрон аадырыһыҥ ыыппыт {{GENDER:$1|киһигэр}} көстүөҕэ.",
        "usermessage-summary": "Тиһилик биллэриитин хааллар.",
        "usermessage-editor": "Тиһилик биллэрээччитэ",
        "watchlist": "Кэтэбилим тиһигэ",
        "watchnologin": "Бэйэҕин билиһиннэр",
        "addwatch": "Кэтэбил тиһигэр киллэр",
        "addedwatchtext": "«[[:$1]]» сирэй уонна кинини кытта ситимнээх ырытыы сирэйэ [[Special:Watchlist|кэтэбилиҥ тиһигэр]] киирдэ.",
+       "addedwatchtext-talk": "«[[:$1]]» уонна кинини кытта ситимнээх сирэй [[Special:Watchlist|кэтэбилиҥ тиһигэр]] киирдэ.",
        "addedwatchtext-short": "\"$1\" диэн сирэй кэтэбилиҥ тиһигэр эбилиннэ.",
        "removewatch": "Кэтэбил тиһигиттэн сот",
        "removedwatchtext": "[[:$1]]\" сирэй уонна кини ырытыытын сирэйэ [[Special:Watchlist|кэтэбилиҥ тиһигиттэн]] сотулунна.",
+       "removedwatchtext-talk": "[[:$1]]\" уонна кинини кытта ситимнээх сирэй [[Special:Watchlist|кэтэбилиҥ тиһигиттэн]] сотулуннулар.",
        "removedwatchtext-short": "\"$1\" диэн сирэй кэтэбилиҥ тиһигиттэн сотулунна.",
        "watch": "Кэтээ",
        "watchthispage": "Бу сирэйи кэтээ",
        "delete-toobig": "Бу сирэй уларытыыларын историята уһун, хас да ($1) {{PLURAL:$1|хат көрүүлээх|хат көрүүлэрдээх}}. Маннык сирэйдэри сотор хааччахтанар, тоҕо диэххэ алҕас {{SITENAME}} алдьаныан сөп.",
        "delete-warning-toobig": "Бу сирэй уларыылара уһун историялаах, хас да ($1) {{PLURAL:$1|хат көрүүлээх|хат көрүүлэрдээх}}. Маны соттоххуна, {{SITENAME}} билэтин тиһигин алдьатыан сөп; салгыыр буоллаххына сэрэнэн үлэлээ.",
        "deleteprotected": "Бу сирэйи, көмүскэллээх буолан, сотор кыаҕыҥ суох эбит.",
-       "deleting-backlinks-warning": "'''Сэрэтии.''' Сотоору гынар сирэйгэр [[Special:WhatLinksHere/{{FULLPAGENAME}}|атын сирэйдэр]] сигэнэллэр эбит.",
+       "deleting-backlinks-warning": "<strong>Сэрэтии.</strong>\nСотоору гынар сирэйгэр [[Special:WhatLinksHere/{{FULLPAGENAME}}|атын сирэйдэр]] сигэнэллэр эбит.",
        "rollback": "Уруккутугар төннөр",
        "rollbacklink": "төннөр",
        "rollbacklinkcount": "$1 көннөрүүнү суох гын",
        "rollbacklinkcount-morethan": "$1 элбэх көннөрүүнү суох гын",
        "rollbackfailed": "Төннөрөргө моһуок үөскээтэ",
+       "rollback-missingparam": "Көрдөбүлгэ баар буолуохтаах булгуччулаах туруоруулар суохтар эбит.",
+       "rollback-missingrevision": "Торум туһунан хачайдаан ылар сатаммата.",
        "cantrollback": "Төннөрөр кыах суох; бүтэһик көннөрүүнү оҥорбут киһи бу сирэй соҕотох ааптара буолар.",
        "alreadyrolled": "Бүтэһик [[User:$2|$2]] ([[User talk:$2|Ырытыы]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) оҥорбут [[:$1]] уларытыыларын төннөрөр кыах суох;\nким эрэ атын номнуо бу сирэйи уларыппыт эбэтэр уруккутун төннөрбүт.\n\nКэнники уларытыыны [[User:$3|$3]] ([[User talk:$3|Ырытыы]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) оҥорбут.",
        "editcomment": "Уларытыыны маннык быһаарбыттар: <em>$1</em>.",
        "revertpage": "([[User talk:$2|Ырытыы]]) көннөрүүлэрэ: [[Special:Contributions/$2|$2]] бу торумҥа: [[User:$1|$1]] төннөрүлүннүлэр",
        "revertpage-nouser": "Аата кистэммит киһи уларытыылара суох оҥоһуллан, ыстатыйа бу киһи барылыгар төннөрүлүннэ: {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "$1 көннөрүүлэр бу торумҥа төннөрүлүннүлэр: $2.",
+       "rollback-success-notify": "$1 уларытыылара сотулуннулар; \n$2 тиһэх торумугар төннөрүлүннэ. [$3 Уларытыыны көрдөр]",
        "sessionfailure-title": "Сиэссийэ алҕаһа",
        "sessionfailure": "Арааһа туох эрэ сатаммата, дьайыыҥ оҥоһуллубата. Браузергар \"Төнүн\" тимэҕи баттаа уонна бу иннинээҕи сирэйгин иккистээн киллэрэн көр.",
        "changecontentmodel": "Сирэй ис тутулун киэбин уларытыы",
        "changecontentmodel-title-label": "Сирэй баһа",
        "changecontentmodel-model-label": "Иһинээҕитин саҥа киэбэ",
        "changecontentmodel-reason-label": "Төрүөтэ:",
+       "changecontentmodel-submit": "Уларыйыы",
        "changecontentmodel-success-title": "Иһинээҕитин киэбэ уларыйда",
        "changecontentmodel-success-text": "[[:$1]] иһинээҕитин киэбэ уларыйда.",
        "changecontentmodel-cannot-convert": "[[:$1]] иһинээҕитэ $2 көрүҥҥэ уларыйар кыаҕа суох эбит.",
        "changecontentmodel-nodirectediting": "$1 иһинээҕитин киэбин быһа уларытар сатаммат эбит",
+       "changecontentmodel-emptymodels-title": "Ис хоһоононун холобура суох",
+       "changecontentmodel-emptymodels-text": "[[:$1]] иһинээҕитэ ханнык да атын көрүҥҥэ уларыйар кыаҕа суох эбит.",
        "log-name-contentmodel": "Иһинээҕитин киэбин уларытыы сурунаала",
        "log-description-contentmodel": "Сирэй иһинээҕитин киэбин кытта ситимнээх",
        "logentry-contentmodel-change": "$1 кыттааччы $3 сирэй иһинээҕитин мадьыалын мантан «$4» манна «$5» {{GENDER:$2|уларыппыт}}",
index 7b57f55..f711abd 100644 (file)
        "yourpasswordagain": "Arhõ oku namber olme",
        "createacct-yourpasswordagain": "Uku nambar sãyãḱme",
        "createacct-yourpasswordagain-ph": "Uku nambar arhõ emme",
-       "remembermypassword": "Mitṭen khon bạṛti khata reaḱ cạbi disạ dohoḱma (Jạsti $1 {{PLURAL:$1 din reaḱ din reaḱ}} lạgit)",
        "userlogin-remembermypassword": "Bolo thirege dohokạńme",
        "yourdomainname": "Amaḱ ḍomen:",
        "externaldberror": "Hoe daṛeyaḱa jahan bahre reaḱ jacaeaḱ ḍaṭabes vul hoeakana se amaḱ bahre reaḱ ekaunṭ do nahaḱ halot aguire ạidạri bạnuḱa.",
        "passwordreset-emailtitle": "{{SITENAME}} sayeṭre beoharićaḱ purạo thutiko",
        "passwordreset-emailelement": "Beoharićaḱ ńutum: \n$1\n\nMit́ ghạṛi lạgit uku nambar: \n$2",
        "passwordreset-emailsentemail": "Mitṭen disạ ruaṛ e-mail do kulena.",
-       "passwordreset-emailsent-capture": "Mit́ṭen disạ ruaṛaḱ e-mail dokulena, oka do latarre ńeloḱ kana.",
-       "passwordreset-emailerror-capture": "Disạ ruạṛ oco lạgit́te mit́ṭen e-mail tear hoelena, oka do latarre udugoḱkana, menkhan $1 beoharić ṭhen  ṭhen baṅ kul hoe akana.",
        "changeemail": "E-mail ṭhikạna do bodolme",
        "changeemail-header": "Ekaunṭ e-mail ṭhikạna do bodolme",
        "changeemail-no-info": "Noa sakam sojhete laṛcaṛ lạgit́te am do bhitri boloḱ hoyoḱtama.",
        "post-expand-template-inclusion-category": "Sakamko oka borḍre noa tahẽna ona doe paromkeda",
        "post-expand-template-argument-warning": "'''Sontoroḱmẽ:''' Noa sakamre komse kom mitṭen forma joṛao menaḱa ạḍi lạṭute pasnao akana.\nOnate noa ạrgumenṭkodo bạgi giḍi hoena.",
        "post-expand-template-argument-category": "Bagi forma ạrgumenṭ sapdoho sakam",
-       "cantcreateaccounttitle": "Ekaunṭ do baṅ tearlena",
        "viewpagelogs": "Noa sakam reaḱ cạbi udukme",
        "nohistory": "Noa sakam re do jahan sompadon reaḱ jạṛ bạnuḱa.",
        "currentrev": "Mucạt nãwã aroe",
index 6dc082e..2bdc449 100644 (file)
        "yourpasswordagain": "Repite sa password:",
        "createacct-yourpasswordagain": "Cunfirma sa password",
        "createacct-yourpasswordagain-ph": "Inserta sa password torra",
-       "remembermypassword": "Ammenta sa password in custu navigadore (pro unu màssimu de $1 {{PLURAL:$1|die|dies}})",
        "userlogin-remembermypassword": "Mantènnemi cullegadu",
        "userlogin-signwithsecure": "Imprea una cunnessione segura",
        "yourdomainname": "Ispetzìfica su domìniu",
        "content-model-css": "CSS",
        "post-expand-template-inclusion-category": "Pàginas in is cale sa dimensione templates inclùdidos propassat su lìmite cunsentidu",
        "post-expand-template-argument-category": "Pàginas cuntenentes templates cun argumentos fartados",
-       "cantcreateaccounttitle": "Non si podet creare unu contu",
        "viewpagelogs": "Càstia is registros de custa pàgina",
        "nohistory": "Non b'est sa stòria de is acontzos pro custa pàgina.",
        "currentrev": "Revisione currente",
        "linksearch-line": "$1 est ligadu in sa pàgina $2",
        "listusers-submit": "Ammustra",
        "listusers-blocked": "(blocadu)",
-       "activeusers-hidebots": "Cua bots",
-       "activeusers-hidesysops": "Cua amministradores",
        "listgrouprights-group": "Grupu",
        "listgrouprights-rights": "Deretos",
        "listgrouprights-members": "(lista de is cumponentes)",
index 152a08a..a94b562 100644 (file)
        "yourpasswordagain": "Retype passwaird:",
        "createacct-yourpasswordagain": "Confirm passwaird.",
        "createacct-yourpasswordagain-ph": "Enter passwaird again.",
-       "remembermypassword": "Mynd ma login oan this brouser (fer $1 {{PLURAL:$1|day|days}} at the maist)",
        "userlogin-remembermypassword": "Keep me loggit in",
        "userlogin-signwithsecure": "Uise secure connection",
        "cannotloginnow-title": "Canna log in nou",
        "activeusers-intro": "This is ae leet o uisers that had some kynd o acteevitie wiin the last $1 {{PLURAL:$1|day|days}}.",
        "activeusers-count": "$1 {{PLURAL:$1|action|actions}} in the laist {{PLURAL:$3|day|$3 days}}",
        "activeusers-from": "Displey uisers stairtin at:",
-       "activeusers-hidebots": "Skauk bots",
-       "activeusers-hidesysops": "Skauk admeenistraters",
        "activeusers-noresult": "Naw uisers foond.",
        "listgrouprights": "Uiser groop richts",
        "listgrouprights-summary": "The follaein is ae leet o uiser groops defined oan this wiki, wi thair associatit access richts.\nThaur micht be [[{{MediaWiki:Listgrouprights-helppage}}|addeetional information]] aneat indiveedual richts.",
        "htmlform-cloner-create": "Eik mair",
        "htmlform-cloner-delete": "Remuiv",
        "htmlform-cloner-required": "At least the ae value is needit.",
-       "sqlite-has-fts": "$1 wi ful-tex rake support",
-       "sqlite-no-fts": "$1 wioot ful-tex rake support",
        "logentry-delete-delete": "$1 {{GENDER:$2|delytit}} page $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|restored}} page $3",
        "logentry-delete-event": "$1 {{GENDER:$2|chynged}} veesibeelitie o {{PLURAL:$5|ae log event|$5 log events}} oan $3: $4",
index f3d70fb..68cbdcc 100644 (file)
        "createacct-benefit-heading": "{{SITENAME}} توهان جهڙن سڄڻن ٺاهيو آهي.",
        "createacct-benefit-body1": "{{PLURAL:$1|ترميم|ترميمون}}",
        "createacct-benefit-body2": "{{PLURAL:$1|صفحو|صفحا}}",
-       "createacct-benefit-body3": "حاليه {{PLURAL:$1|ڀاڱيدار}}",
+       "createacct-benefit-body3": "ھاڻوڪا {{PLURAL:$1|ڀاڱيدار}}",
        "badretype": "توهان جو ڄاڻايل ڳجھولفظ درست نہ آهي.",
        "usernameinprogress": "ان يُوزرنانءُ لاءِ کاتو اڳ ۾ ئي تياريءَ هيٺ آهي. مهرباني ڪري انتظار فرمايو.",
        "userexists": "ڄاڻايل يوزرنانءُ اڳ ۾ ئي استعمال هيٺ آهي. مهرباني ڪري ڪو ٻيو يُوزرنانءُ چونڊيو.",
        "noemailcreate": "توهان کي قابل ڪار برق ٽپال پتو مهيا ڪرڻو پوندو.",
        "passwordsent": "يوزر \"$1\" لاءِ هڪ نئون ڳجھو لفظ برق ٽپال ذريعي اماڻيو ويو آهي.  مهرباني ڪري اهو حاصل ڪرڻ بعد لاگ اِن ٿيندا.",
        "mailerror": "ٽپال اماڻڻ ۾ چُڪَ: $1",
-       "acct_creation_throttle_hit": "توهان جي آءِ پي پتي تان هن وڪيءَ تي پوئين ڏينهن {{PLURAL:$1|1 کاتو|$1 کاتا}} کلي چڪا آهن، جيڪو وڌ ۾ وڌ اجازت ڏنل وقت آهي. \nنتيجتاً ساڳي آءِ پي پتي تان في‌الوقت وڌيڪ کاتا کولي نٿا سگھجن.",
+       "acct_creation_throttle_hit": "توهان جي آءِپي پتي تان هن وڪيءَ تي پوئين $2، کان {{PLURAL:$1|1 کاتو|$1 کاتا}} کلي چڪا آهن، جيڪو وڌ ۾ وڌ اجازت ڏنل وقت آهي. \nنتيجتاً ساڳي آءِپي پتي تان في‌الوقت وڌيڪ کاتا کولي نٿا سگھجن.",
        "emailauthenticated": "توهان جي برق ٽپال پتي جي تصديق $2 تي $3 بجي ڪئي وئي.",
        "emailnotauthenticated": "توهان جو برق ٽپال پتي جي تصديق اڃا ٿي نہ سگھي آهي.",
        "noemailprefs": "انهن فيچرس کي فعال بڻائڻ لاءِ پنهنجي ترجيحات ۾ برق ٽپال پتو ڄاڻايو.",
        "passwordreset-emaildisabled": "هن وڪيءَ تي برق‌ٽپال واريون خصوصيتون غير فعال بڻايون ويون آهن.",
        "passwordreset-username": "يُوزرنانءُ:",
        "passwordreset-domain": "ميدان:",
-       "passwordreset-capture": "برق ٽپال ڏسڻ چاهيندا؟",
        "passwordreset-email": "برق ٽپال پتو:",
        "passwordreset-emailtitle": "{{SITENAME}} واري کاتي جا تفصيل",
        "passwordreset-emailelement": "يُوزر نانءُ: \n$1\n\nعارضي ڳجھو لفظ:\n$2",
-       "passwordreset-invalideamil": "ناقابل ڪار برق ٽپال پتو",
+       "passwordreset-invalidemail": "ناقابل ڪار برق ٽپال پتو",
        "changeemail": "برق ٽپال پتو مِٽايو يا بدلايو",
        "changeemail-oldemail": "هاڻوڪو برق ٽپال پتو:",
        "changeemail-newemail": "نئون برق ٽپال پتو:",
        "preview": "پيش نگاھ",
        "showpreview": "پيش نگاھ",
        "showdiff": "تبديليون ڏيکاريو",
-       "anoneditwarning": "<strong>خبردار:</strong> توهان داخل ٿيل نہ آهيو. جيڪڏهن توهان ڪي ترميمون ڪيون تہ هن صفحي جي سوانح ۾ توهان جو آءِ پي پتو درج ڪيو ويندو. جي توهان <strong>[$1 داخل]</strong> ٿيو ٿا < يا strong>[$2 کاتو کوليو] </strong> ٿا، تہ توهان جو ترميمون توهان جي يوزرنانءُ سن منسوب ڪيون وينديون، جنهن جا ٻيا بہ فائدا ٿي سگھن ٿا.",
+       "anoneditwarning": "<strong>خبردار:</strong> توهان داخل ٿيل نہ آهيو. جيڪڏهن توهان ڪي ترميمون ڪيون تہ هن صفحي جي سوانح ۾ توهان جو آءِ پي پتو درج ڪيو ويندو. جي توهان <strong>[$1 داخل]</strong> ٿيو ٿا < يا strong>[$2 کاتو کوليو] </strong> ٿا، تہ توهان جو ترميمون توهان جي يوزرنانءُ سان منسوب ڪيون وينديون، جنهن جا ٻيا بہ فائدا ٿي سگھن ٿا.",
        "anonpreviewwarning": "توهان داخل ٿيل نہ آهيو. جيڪڏهن توهان صفحي ۾ تبديليون سانڍيون تہ اهڙين تبديلين ساڻ توهان جو آءِپي پتو درج ڪيو ويندو.",
        "missingcommenttext": "براءِ مهرباني هيٺ پنهنجا تاثرات درج ڪندا.",
        "summary-preview": "تت تي پيش نگاھ:",
        "templatesusedpreview": "هن پيش نگاھ ۾ استعمال ٿيل {{PLURAL:$1|سانچو|سانچا}}:",
        "templatesusedsection": "هن سيڪشن ۾ استعمال ٿيل {{PLURAL:$1|سانچو|سانچا}}:",
        "template-protected": "(تحفظيل)",
-       "template-semiprotected": "(نيم تحفظيل)",
+       "template-semiprotected": "(نيم-تحفظيل)",
        "hiddencategories": "هيءُ صفحو  {{PLURAL:$1|1 لڪل زمري|$1 لڪل زمرن}}: جو رڪن آهي:",
        "nocreatetext": "{{SITENAME}} نوان صفحا سرجڻ جي روڪَ ڪئي آهي.\nتوهان اڳي ئي موجود صفحن کي سنواري سگھو ٿا، يا [[Special:UserLogin|لاگ اِن ٿي يا نئون کاتو کولي سگھو ٿا]].",
        "nocreate-loggedin": "توهان کي نوان صفحا سرجڻ جي اجازت حاصل ڪانهي.",
        "search-redirect": "($1 کان چوريو)",
        "search-section": "(سيڪشن $1)",
        "search-category": "(ذمرو $1)",
-       "search-suggest": "ڇا توهان جو مطلب $1 آهي؟",
+       "search-suggest": "ڇا توهان جو مطلب ھيو: $1",
        "search-interwiki-caption": "برادر رٿائون",
        "search-interwiki-default": "$1 مان نتيجا",
        "search-interwiki-more": "(وڌيڪ)",
        "recentchangescount": "عدم پيروي جي صورت ۾ ڏيکارڻ جي لاءِ ترميمون:",
        "prefs-help-recentchangescount": "ان ۾ تازيون تبديليون، صفحن جي سوانح، ۽ لاگ شامل آهن.",
        "savedprefs": "توهان جون ترجيحات سانڍجي چڪيون آهن.",
-       "savedrights": "{{GENDER:$1|$1}} نالي يوزر جا حق سانڇجي چڪا آهن.",
+       "savedrights": "{{GENDER:$1|$1}} جا يوزر گروھ سانڍجي چڪا آھن.",
        "timezonelegend": "اوقاتي زون:",
        "localtime": "مقامي وقت:",
        "timezoneuseserverdefault": "وڪي عدم پيروي استعمال ڪريو ($1)",
        "prefs-diffs": "تفاوت",
        "prefs-help-prefershttps": "هيءَ ترجيح توهان جي ايند داخل ٿيڻ تي عمل ۾ ايندي.",
        "userrights": "يُوزر حقن جو بندوبست",
-       "userrights-lookup-user": "يوزر گروپَ سنڀاليو",
+       "userrights-lookup-user": "ڪو يوزر چونڊيو",
        "userrights-user-editname": "يُوزرنانءُ ڄاڻايو:",
-       "editusergroup": "{{GENDER:$1|يوزر}} گروھ ترميميو",
+       "editusergroup": "يوزر گروھ اتاريو",
        "userrights-editusergroup": "يوزر گروپَ سنواريو",
        "saveusergroups": "{{GENDER:$1|يوزر}} گروھ سانڍيو",
        "userrights-groupsmember": "برڪن:",
        "userrights-reason": "سبب:",
        "userrights-no-interwiki": "توهان کي ٻين وڪيز تي يُوزر حقن ۾ ترميم ڪرڻ جو حق حاصل نہ آهي.",
        "userrights-nodatabase": "اعداخانو $1 يا تہ وجود نہ ٿو رکي يا تہ اهو مقامي اعدادخانو نہ آهي.",
-       "userrights-notallowed": "توهان کي يوزر جا حق شامل يا هٽائڻ جي اجازت نه آهي.",
        "userrights-changeable-col": "گروپَ جيڪي توهان تبديل ڪري سگھو ٿا",
        "userrights-unchangeable-col": "گروپَ جيڪي توهان تبديل نٿا ڪري سگھو",
        "group": "گروپ:",
        "right-upload": "فائيل چاڙهيو",
        "right-reupload": "موجوده فائيلن مٿان",
        "right-upload_by_url": "ڪنهن يُوآرايل تان فائيل چاڙهيو",
-       "right-writeapi": "اي پر آءِ لکڻ جو استعمال",
+       "right-writeapi": "ايپيآءِ لکڻ جو استعمال",
        "right-delete": "صفحا ڊاهيو",
        "right-bigdelete": "ڊگھيون سوانح رکندڙ صفحا ڊاهيو",
        "right-browsearchive": "ڊاٺل صفحا ڳوليو",
        "right-siteadmin": "اعدادخانو بنديو ۽ کوليو",
        "right-override-export-depth": "5ئين اونهائيءَ تائين ڳنڍيل صفحن سميت صفحا برآمديو",
        "right-sendemail": "ٻين يوزرس ڏانهن ايميل موڪليو",
-       "right-passwordreset": "ڳجھو لفظ مقرري برق ٽپالون ڏسو",
        "right-managechangetags": "[[Special:Tags|ٽيگس]] سرجيو ۽ ڊاهيو.",
        "grant-group-email": "برق ٽپال اماڻيو",
        "grant-blockusers": "يُوزرس کي بندشيو ۽ اڻبندشيو",
        "uploaded-script-svg": "اسڪرپٽ جوڳو ايليمينٽ ”$1” مليو آهي، اپلوڊ ٿيل ايس وي جي فائيل ۾.",
        "uploaded-hostile-svg": "اپلوڊ ٿيل ايس وي جي فائيل جو غير محفوظ سي ايس ايس ۾ اسٽائيل ايلمينٽ مليو",
        "uploaded-event-handler-on-svg": "ايس وي جي فائيل ۾ ايوينٽ هينڊلر خصوصيتون <code>$1=\"$2\"</code> مقرر ڪرڻ جي اجازت نہ آهي.",
-       "uploaded-href-unsafe-target-svg": "href جو غير محفوظ نشانو مليو آهي <code>&lt;$1 $2=\"$3\"&gt;</code> اپلوڊ ٿيل ايس وي جي فائيل ۾",
+       "uploaded-href-unsafe-target-svg": "href جو غير محفوظ ڊيٽا: يوآرآءِ نشانو مليو آهي <code>&lt;$1 $2=\"$3\"&gt;</code> چاڙھيل اَيسوِيجِي فائيل ۾",
        "uploaded-animate-svg": "”اينيميٽ“ ٽيگ ڳوليو  جيڪا ٿي سگهي ٿو href کي تبديل ڪري رهي هجي. \"form\" وصف استعمال ڪندي <code>&lt;$1 $2=\"$3\"&gt;</code> اپلوڊ ٿيل ايس وي جي فائيل ۾",
        "uploaded-setting-event-handler-svg": "واقعي کي هينڊل ڪندڙ جي سيٽنگ جون وصفون بلاڪ ٿيل آهن. \n<code>&lt;$1 $2=\"$3\"&gt;</code> اپلوڊ ٿيل ايس وي جي فائيل ۾ مليو",
        "uploaded-setting-href-svg": "\"set\"  ٽيگ کي \"href\" وصف استعمال ڪندي بنيادي عنصر کي بلاڪ ڪيو ويو آهي",
        "prevpage": "پويون صفحو ($1)",
        "allpagesfrom": "ھتان شروع ٿيندڙ صفحا نمايو",
        "allpagesto": "ان تي ختم ٿيندڙ صفحا نُمايو:",
-       "allarticles": "سمورا مضمون",
+       "allarticles": "سڀ صفحا",
        "allinnamespace": "سمورا صفحا ($1 نانءُپولار)",
        "allpagessubmit": "ھلو",
        "allpagesprefix": "صفحا نمايو بمع اڳياڙي:",
        "whatlinkshere": "هتان ڇا ڳنڍيل آهي",
        "whatlinkshere-title": "$1 سان ڳنڍيل صفحا",
        "whatlinkshere-page": "صفحو:",
-       "linkshere": "هيٺيان صفحا '''[[:$1]]''' سان ڳنڍيل آهن:",
+       "linkshere": "هيٺيان صفحا <strong>[[:$1]]</strong> سان ڳنڍيل آهن:",
        "nolinkshere": "'''[[:$1]]''' سان ڪو بہ صفحو ڳنڍيل ناهي.",
        "isredirect": "چورڻو صفحو",
        "istemplate": "شموليت",
        "tooltip-ca-talk": "موادي صفحي تي بحث",
        "tooltip-ca-edit": "هيءُ صفحو سنواريو",
        "tooltip-ca-addsection": "نئون سيڪشن شروع ڪريو",
-       "tooltip-ca-viewsource": "هيءُ صفحو تحفظيل آهي. توهان ان جو ذريعو ڏسي سگھو ٿا.",
+       "tooltip-ca-viewsource": "هيءُ صفحو تحفظيل آهي.\nتوهان ان جو ذريعو ڏسي سگھو ٿا",
        "tooltip-ca-history": "هن صفحي جا اڳوڻا ڀيرا",
        "tooltip-ca-protect": "هيءُ صفحو تحفظيو",
        "tooltip-ca-delete": "هيءُ صفحو ڊاهيو",
        "tooltip-n-portal": "ھن رٿا بابت، توھان ڇا ٿا ڪري سگھو، شيون ڪٿي ڳولھجن",
        "tooltip-n-currentevents": "تازن واقعن تي تفصيلي ڄاڻ لھو",
        "tooltip-n-recentchanges": "ھن وڪيءَ ۾ تازين تبديلين جي فھرست",
-       "tooltip-n-randompage": "ڪو بہ بلاترتيب صفحو اتاريو",
+       "tooltip-n-randompage": "ڪو بلاترتيب صفحو اتاريو",
        "tooltip-n-help": "ڳولي لھڻ جي جاءِ",
        "tooltip-t-whatlinkshere": "ھتان ڳنڍيل سمورن وڪي صفحن جي فھرست",
        "tooltip-t-recentchangeslinked": "ويجھڙائيءَ ۾ صفحن ۾ ٿيل تبديليون هن صفحي سان ڳنڍيل آهن",
index bfd5492..faafcb4 100644 (file)
        "yourname": "Innòmu utenti",
        "yourpassword": "Paràura d'órdhini",
        "yourpasswordagain": "Ripeti la paràura d'órdhini",
-       "remembermypassword": "Ammenta la me' paràura d'órdhini in chisthu nabiggadori (par un màssimu di $1 {{PLURAL:$1|dì|dì}})",
        "yourdomainname": "Ippizzificà lu dumìniu",
        "externaldberror": "S'è verifiggaddu un errori cu lu server di autentificazioni esthernu, oppuru nò si diponi di l'autorizazioni nezzessàri pa aggiornà la propria registhrazioni estherna.",
        "login": "Intra",
        "undo-success": "Chistha mudìfigga pò assé annulladda. Verifiggà lu sighenti cuntrasthu prisintaddu pa s'azzirthà chi lu cuntinuddu curripundi a cantu disizaddu e dunca saivvà li mudìfigghi pa cumprità la procedura di annullamentu.",
        "undo-failure": "Impussìbiri annullà la mudìfigga a càusa d'un cuntrasthu cun mudìfigghi intermédi.",
        "undo-summary": "Annulladda la mudìfigga $1 di [[Special:Contributions/$2|$2]] ([[User talk:$2|Dischussioni]])",
-       "cantcreateaccounttitle": "Impussìbiri registhrà un utenti",
        "cantcreateaccount-text": "Criazioni di registhrazioni da chistu indirizzu IP ('''$1''') è isthadda broccadda da [[User:$3|$3]].\n\nLa rasgioni frunidda da $3 è ''$2''",
        "viewpagelogs": "Visuarizza li rigisthri reratibi a chistha pàgina.",
        "nohistory": "Cronologia di li versioni di chistha pàgina nò riperìbiri.",
index 5d38477..86d1f66 100644 (file)
        "userlogin-yourpassword-ph": "تێپەڕوشەگەت بنۊس",
        "createacct-yourpassword-ph": "تێپەڕوشەێگ بنۊس",
        "yourpasswordagain": "دیسان تێپەڕوشەگە بنۊسەو:",
-       "remembermypassword": "تێپەروشەگەم لەسەر ئەی کامپیوترە پاشدەس بکە (ئەو پەڕی $1 {{PLURAL:$1|ڕووژ}}ە)",
        "login": "بچووە ناو",
        "nav-login-createaccount": "بچووە ناو / ھەژمار درس بکە",
        "userlogin": "بچووە ناو / ھەژمار درس بکە",
index 79eccff..0b2b10c 100644 (file)
        "yourname": "Geavaheaddjidovddaldat",
        "yourpassword": "Suollemassátni:",
        "yourpasswordagain": "Čále suollemassáni ođđasit:",
-       "remembermypassword": "Muite mu (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "Fierbmenamma",
        "login": "Čálligoađe sisa",
        "nav-login-createaccount": "Daga ođđa geavaheaddjidovddaldaga dahje čálligoađe sisa",
        "template-protected": "(suodjáluvvon)",
        "template-semiprotected": "(suodjáluvvon anonyma ja ođđa geavaheddjiin)",
        "edittools": "<!-- Teaksta mii lea dás, čájehuvvo rievdadanskovi vuolábealde. -->",
-       "cantcreateaccounttitle": "Dovddaldaga ráhkadeapmi ii lihkosmuvvan",
        "viewpagelogs": "Čájet dán siiddu loggaid",
        "nohistory": "Dán siiddus ii leat rievdadanhistorjá.",
        "currentrev": "Dálá veršuvdna",
        "activeusers-intro": "Dát lea listu geavaheddjiin, mat leat bargan juoidá maŋimus $1 {{PLURAL:$1|beaivvi|beaivvi}} siste.",
        "activeusers-count": "$1 {{PLURAL:$1|rievdadus|rievdadusa}} maŋimus $3 beaivvi siste",
        "activeusers-from": "Čájet geavaheddjiid dán rájes:",
-       "activeusers-hidebots": "Čiega bohtaid",
-       "activeusers-hidesysops": "Čiega administráhtoriid",
        "listgrouprights-members": "(listu miellahtuin)",
        "mailnologin": "Sáddejeaddji čujuhus váilo",
        "mailnologintext": "Don fertet leat [[Special:UserLogin|čálligoahtán sisa]] ja du [[Special:Preferences|ásahusain]] ferte leat gelbbolaš ja <strong>sihkarastojuvvon</strong> e-poastačujuhus, ovdalgo sáhtat sáddet e-poasta eará geavaheddjiide.",
index f031e4e..62ecd78 100644 (file)
        "yourname": "Caitom ID:",
        "yourpassword": "Quimx canj:",
        "yourpasswordagain": "Vanquimx canj:",
-       "remembermypassword": "Qualtiinii he quimx canj jan ordinator iti (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "Hedomino:",
        "externaldberror": "Pos-römjde authenticacionde database extername jöx me necoccebj permiccionde updatan mecaitom externom.",
        "login": "Caápo",
        "undo-success": "Ticpatlöx zo pos-coccebj iixponintöx. Controlar comparicion zo !-cmaade verifiatom jan coccebj yazuáxiim ö xuniim quiíx zo !-cmaade fini iixponintöx ticpatlöx zo.",
        "undo-failure": "Ticpatlöx zo necoccebj ticpatlöxde ticpatlöxám iti-am conflictom.",
        "undo-summary": "Iixponintöx revicion $1 'de [[Special:Contributions/$2|$2]] ([[User talk:$2|Czaxö]])",
-       "cantcreateaccounttitle": "Nexuatláminop",
        "cantcreateaccount-text": "Creacionde caitomde jan adressade IP ('''$1''') coccebj blockom [[User:$3|$3]] mii.\n\nRae' zo xuniim $3 mii coccebj ''$2''",
        "viewpagelogs": "Cohuatlöx logámde jan páhina",
        "nohistory": "Jan páhina necoccebj históriade ticpatlöx.",
index caddb8a..c3817d5 100644 (file)
        "yourpasswordagain": "Šennikufal hantum taaga:",
        "createacct-yourpasswordagain": "Šennikufal tabatandi",
        "createacct-yourpasswordagain-ph": "Šennikufal dam taaga",
-       "remembermypassword": "Hong'ay huruyan tammaasa ceecikaa woo ga (a ma ši bisa {PLURAL:$1|jirbi|jirbi}}) $1",
        "userlogin-remembermypassword": "Ay goywaatoo ma gaabandi ka feera",
        "userlogin-signwithsecure": "Ciya nda saajaw",
        "yourdomainname": "Ni zunbu dogoo:",
        "passwordreset-emailtext-user": "Goykaw $1 {{SITENAME}} wiri ka war sennikufaloo yeeti {{SITENAME}} se\n($4). Goykaa woo {{PLURAL:$3|kontoo ga|kontey ga}} marga nda nda bataga aderesoo woo:\n\n$2\n\n {{PLURAL:$3|Šiiyan šennikufaloo woo|Šiiyan šennikufaley wey}} ga buu {{PLURAL:$5|jirbi foo|jirbi $5}} ra.\nWar ga hima ka huru  nda šennikufal taaga suuba sohõ. Nda boro waani ka ceeci\n ka woo tee wala war ga honga wara šennikufal žeenaa nda war ši boona koyne\n k'a barma, war ga hin ka šaawaroo woo muray nda gaabandi ka goy nda war\n šennikufal žeenaa.",
        "passwordreset-emailelement": "Goykaw maa: \n$1\n\nŠiiyan šennikufal: \n$2",
        "passwordreset-emailsentemail": "Šennikufal yeetiyan bataga n' ka sanbandi war se.",
-       "passwordreset-emailsent-capture": "Šennikulal yeetiyan bataga n' ka sanbandi war se, kaŋ ga cebandi ne ganda.",
-       "passwordreset-emailerror-capture": "Šennikufal yeetiyan bataga n' ka teendi, kaŋ ga cebandi ne ganda, amm'a mana hin ka sanbandi {{GENDER:$2|goykaw}} do: $1",
        "changeemail": "Bataga aderesu barmay",
        "changeemail-header": "Takaddaa woo toonandi ka war bataga aderesoo barmay. War ka hima ka war šennikufaloo dam ka barmayyanoo tabatandi.",
        "changeemail-no-info": "War ga hima ka huru ka hin duu moɲoo woo.",
        "undo-nochange": "A ga hima kaŋ barmaa n' ka taafeeri ka ben.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|deede]]) na $1 fillaa taafeeri",
        "undo-summary-username-hidden": "Goykaw tugante na $1 fillaa taafeeri",
-       "cantcreateaccounttitle": "Ši hin ha kontu tee",
        "cantcreateaccount-text": "[User:$3|$3]] ganji kontu ma tee IP aderesu (<strong>$1</strong>) ga.\n\nDaliloo kaŋ $3 n'a noo ti <em>$2</em>",
        "cantcreateaccount-range-text": "[[User:$3|$3]] ganji kaŋ kontu ma tee IP aderesey kaŋyaŋ goo <strong>$1</strong> laamaa ra ga, sanda war IP aderesoo (<strong>$4</strong>).\n\nDaliloo kaŋ $3 n'a noo ti <em>$2</em>",
        "viewpagelogs": "Hantum taarikey guna moɲoo woo se",
        "activeusers-intro": "Wey ti goykey kaŋ cindi goymee tana ra {{PLURAL:$1|jirbi}} $1 kaŋ kokor ra.",
        "activeusers-count": "{{PLURAL:$1|teera}} $1 {{PLURAL:$3|jirbi|$3}} kaŋ kokor ra.",
        "activeusers-from": "Goykey cebe kaŋ ga šintin ne:",
-       "activeusers-hidebots": "Maršin berekey tugu",
-       "activeusers-hidesysops": "Juwalkey tugu",
        "activeusers-noresult": "Goykaw kul mana duwandi.",
        "listgrouprights": "Goykaw kuray alhakey",
        "listgrouprights-summary": "The following is a list of user groups defined on this wiki, with their associated access rights.\nA ga hin ka tee [[{{MediaWiki:Listgrouprights-helppage}}|alhabar tontoni]] ga bara boro alhakey ga.",
        "htmlform-cloner-create": "Tonton koyne",
        "htmlform-cloner-delete": "Kaa",
        "htmlform-cloner-required": "Nd'ajaase hinna foo ga waažibandi.",
-       "sqlite-has-fts": "$1 nda hantum-timmante ceeci gaakašinay",
-       "sqlite-no-fts": "$1 bila nda hantum-timmante  ceeci gaakašinay",
        "logentry-delete-delete": "$1  {{GENDER:$2|na}} moo $3 tuusu",
        "logentry-delete-restore": "$1 {{GENDER:$2|na}} moo yeeti $3",
        "logentry-delete-event": "$1 {{GENDER:$2|na}} diira sahã barmay {{PLURAL:$5|taariki teera $5}} se $3 ga: $4",
index 5bd2832..0da808b 100644 (file)
@@ -23,6 +23,7 @@
        "tog-watchdefault": "Pridietė poslapius, katrūs keito, keravuojamu sārošap",
        "tog-watchmoves": "Pridietė poslapius, katrūs parvadėno, keravuojamu sārošap",
        "tog-watchdeletion": "Pridietė poslapius, katrūs ėštrėno, keravuojamu sārošap",
+       "tog-watchuploads": "I keravuojamu sāraša pridietė mona ožkrautus abruozdielius",
        "tog-watchrollback": "Pridietė poslapius, katrūs keitėmus grōžėno atgal, keravuojamu sārošap",
        "tog-minordefault": "Kāp prėgol pažīmietė pakeitėmus mažās",
        "tog-previewontop": "Ruodītė parvaiza vėrš taisīmu lauka",
@@ -40,6 +41,7 @@
        "tog-watchlisthidebots": "Kavuotė robotu pakeitėmos keravuojamu sārošė",
        "tog-watchlisthideminor": "Kavuotė mažus pakeitėmus keravuojamu sārošė",
        "tog-watchlisthideliu": "Kavuotė prėsėjongosiu nauduotuoju keitėmus keravuojamu sārošė",
+       "tog-watchlistreloadautomatically": "Parkrautė keravuojamu poslapiu sāraša kap tik kuoštovis būn pakeists (rēk JavaScript)",
        "tog-watchlisthideanons": "Kavuotė anonimėniu nauduotuoju keitėmus keravuojamu sārošė",
        "tog-watchlisthidepatrolled": "Kavuotė sodabuotus pakeitėmus keravuojamu sārošė",
        "tog-watchlisthidecategorization": "Kavuotė poslapiu kateguorėzacėjė",
        "actions": "Vēksmā",
        "namespaces": "Vardū srėtis",
        "variants": "Atmainā",
-       "navigation-heading": "Naršīma pasėrinkėmā",
+       "navigation-heading": "Naršīma pasirinkėmā",
        "errorpagetitle": "Klaida",
        "returnto": "Grīžtė i $1.",
        "tagline": "Straipsnis ėš {{SITENAME}}.",
        "edit-local": "Taisītė vėitėni aprašīma",
        "create": "Padėrbtė",
        "create-local": "Prėkergtė vėitėni aprašīma",
-       "editthispage": "Taisītė ton poslapė",
+       "editthispage": "Taisītė ton poslapi",
        "create-this-page": "Dėrbtė ton poslapi",
        "delete": "Trintė",
-       "deletethispage": "Trintė ton poslapė",
+       "deletethispage": "Trintė ton poslapi",
        "undeletethispage": "Ton poslapi padėrbtė apent",
        "undelete_short": "Dėrbtė apent $1 {{PLURAL:$1:pakeitėma|pakeitėmus|pakeitėmu}}",
        "viewdeleted_short": "Veizietė $1 {{PLURAL:$1|ėštrinta keitėma|ėštrintus keitėmus|ėštrintū keitėmu}}",
        "talk": "Aptarėms",
        "views": "Parveizė̄jėmā",
        "toolbox": "Rakondā",
+       "tool-link-userrights": "Mainītė {{GENDER:$1|nauduotuoja|nauduotuojės}} gropės",
+       "tool-link-emailuser": "Rašītė gromata {{GENDER:$1|tamou nauduotuojou}}",
        "userpage": "Ruodītė nauduotuojė poslapi",
        "projectpage": "Ruodītė pruojekta poslapi",
        "imagepage": "Veizietė abruozdielė poslapi",
        "jumptonavigation": "naršīms",
        "jumptosearch": "paėiška",
        "view-pool-error": "Atsėprašuom, bat serverē daba īr parkrautė.\nNuognē pardaug nauduotoju skait ton poslapi.\nPrašuom palaukat ė mieginkat i ton poslapi patekt apent.\n\n$1",
+       "generic-pool-error": "Atsėprašuom, ale serverē daba īr parkrautė.\nNuognē pardaug nauduotoju skaita ton poslapi.\nPrašuom palaukat ė mieginkat i ton poslapi patekt apent.\n\n$1",
        "pool-errorunknown": "Nežėnuoma klaida",
        "poolcounter-usage-error": "Naudojėma soklīdėms: $1",
        "aboutsite": "Aple {{SITENAME}}",
        "yourpasswordagain": "Pakartuoket slaptažuodė:",
        "createacct-yourpasswordagain": "Čīstā tuokis slaptažuodis?",
        "createacct-yourpasswordagain-ph": "Apent ožrašīkat slaptažuodi",
-       "userlogin-remembermypassword": "Ka liktō prisėjongis",
+       "userlogin-remembermypassword": "Ka liktō prisijongė̄s",
        "userlogin-signwithsecure": "Apsauguots rīšīs",
+       "cannotlogin-title": "Nēn prisijongtė",
+       "cannotlogin-text": "Nie galam prisijongtė.",
        "cannotloginnow-title": "Nēn prėsijongtė",
        "yourdomainname": "Tamstas domens:",
        "password-change-forbidden": "Negalat tuo wiki keistė slaptažuodiu.",
        "nav-login-createaccount": "Prėsėjongtė / padėrbtė paskīra",
        "userlogin": "Prėsėjongtė / padėrbtė paskīra",
        "userloginnocreate": "Prėsėjongtė",
-       "logout": "Atsėjongtė",
-       "userlogout": "Atsėjongtė",
+       "logout": "Atsijongtė",
+       "userlogout": "Atsijongtė",
        "notloggedin": "Neprėsėjongis",
        "userlogin-noaccount": "Netorat paskīruos?",
        "userlogin-joinproject": "Jonkėtėis prī {{SITENAME}}",
        "userlogin-resetpassword-link": "Ožmiršat sava slaptažuodi?",
        "userlogin-helplink2": "Prėsėjongėma pagelba",
        "userlogin-loggedin": "Tamsta jau īr prėsijongė̄s kāp {{GENDER:$1|$1}}.\nJēb nuorat prisėjongtė kāp kėts žmuogos, nauduokat skvarma apatiuo.",
+       "userlogin-reauth": "Tamsta torat prisijongtė apent, ka būtom aiško, ka esat {{GENDER:$1|$1}}.",
        "userlogin-createanother": "Padėrbtė kėta paskīra",
        "createacct-emailrequired": "El. pašta adresos",
        "createacct-emailoptional": "El. paštos (nie būtėns)",
        "createacct-reason-ph": "Kūdie dėrbat kėta nauduotojė poslapi",
        "createacct-submit": "Padėrbkat savėi paskīra",
        "createacct-another-submit": "Padėrbtė paskīra",
+       "createacct-continue-submit": "Tuoliaus dėrbtė nauduotuoja paskīra",
+       "createacct-another-continue-submit": "Tuoliaus dėrbtė nauduotuoja paskīra",
        "createacct-benefit-heading": "{{SITENAME}} īr sokorta prietėliu, tuokiu, kāp Tamsta.",
        "createacct-benefit-body1": "{{PLURAL:$1|pataisīms|pataisīmā|pataisīmu}}",
        "createacct-benefit-body2": "{{PLURAL:$1|poslapis|poslapē|poslapiu}}",
        "createaccounterror": "Nė̄šiejė padėrbtė paskīruos: $1",
        "nocookiesnew": "Nauduotuojė paskīra bova sokurta, bat Tamsta nēsot prėsėjongis. {{SITENAME}} nauduo pakavukus (''cookies''), ka prėkergtom nauduotuojus. Tamsta esot ėšjongis anūs. Prašuom ijongtė pakavukus, tumet prisėjonkat so sava naujo nauduotuojė vardo ė slaptažuodio.",
        "nocookieslogin": "{{SITENAME}} nauduo pakavukus (''cookies''), ka prėkergtom nauduotuojus. Tamsta esat ėšjongis anūs. Prašuom ijongtė pakavukus ė pamiegītė apent.",
+       "noname": "Naožrašėt tinkama nauduotuoja varda!",
        "loginsuccesstitle": "Prisijongiet gerā",
        "loginsuccess": "'''Dabā Tamsta esat prėsėjongis prī {{SITENAME}} kāp „$1“.'''",
        "nosuchuser": "Nier anėjuokė nauduotuojė, katrou vards būtom „$1“ (dėdliuosės rādės svarbo ī).\nPatikrinkėt rašība aba [[Special:CreateAccount|padėrbkėt naujė paskīra]].",
        "eauthentsent": "Patvėrtėnėma gruomata bova nusiōsta i paskėrta el. pašta adresa.\nPrīš ėšsiontiant kėta gruomata i Tamstas diežote, Tamsta torėt vīkdītė nuruodīmus gruomatuo, kū patvėrtėntomiet, kū diežotė tėkrā īr Tamstas.",
        "throttled-mailpassword": "Slaptažuodžė priminims jau bova ėšsiōsts, par paskotėnės {{PLURAL:$1|adīna|$1 adīnas}}. Nuorint apsėsauguotė nū pėktnaudēvėma, slaptažuodė priminėms gal būt ėšsiōsts tėk kas {{PLURAL:$1|adīna|$1 adīnas}}.",
        "mailerror": "Bieda siontiont gromata: $1",
-       "acct_creation_throttle_hit": "Ton pruojekta lankītuojē, katrėi nauduo Tamstas IP adresa, padėrba {{PLURAL:$1|$1 paskīra|$1 paskīras|$1 paskīrū}} par paskotėnta dėina, a tas īr dėdliausis leidams skaitlios par ta čiesa.\nTudie šėton čieso lankītuojē, katrėi nauduo tou IP adresa, daugiau paskīrū dėrbtė nagal.",
+       "acct_creation_throttle_hit": "Ton pruojekta lankītuojē, katrėi nauduo Tamstas IP adresa, padėrba {{PLURAL:$1|$1 paskīra|$1 paskīras|$1 paskīrū}} par paskotėnta $2, a tas īr dėdliausis leidams skaitlios par ta čiesa.\nTudie šėton čieso lankītuojē, katrėi nauduo tou IP adresa, daugiau paskīrū dėrbtė nagal.",
        "emailauthenticated": "Tamstas el. pašta adresos bova ožtvirtėnts $2 d. $3.",
        "emailnotauthenticated": "Tamstas el. pašta adresos da nier patvėrtėnts. Anėjuokės gruomatas\nnebus siontamas ni vėinam žemiau ėšvardėntam puoslaugiō.",
        "noemailprefs": "Nuruodėkīt el. pašta adresa, kū vėiktu šėtos funkcėjės.",
        "pt-login-button": "Prėsėjongtė",
        "pt-login-continue-button": "Tuoliau prisijongėnietė",
        "pt-createaccount": "Pasėdėrbtė paskīra",
-       "pt-userlogout": "Atsėjongtė",
+       "pt-userlogout": "Atsijongtė",
        "changepassword": "Pakeistė slaptažuodė",
        "resetpass_announce": "Ka ožbengtomiet jongtėis, torėt sokortė naujė slaptažuodi.",
        "resetpass_header": "Keistė paskīruos slaptažuodi",
        "resetpass_submit": "Nostatītė slaptažuodi ė prėsėjongtė",
        "changepassword-success": "Tamstas slaptažuodis pamainīts gerā!",
        "changepassword-throttled": "Baisē daug čiesu mieginot prisėjongtė.\nDaba palaukėt $1 prīš mieginant vie.",
+       "resetpass-no-info": "Ka ētomiet tėisē ont tou poslapė, Tamstā rēk prisijongtė.",
        "resetpass-submit-loggedin": "Keistė slaptažuodi",
        "resetpass-submit-cancel": "Pabengtė",
+       "resetpass-wrong-oldpass": "Bluogs laikėns aba esams slaptažuodis.\nTamsta, rasietās, anou pamainėt aba ožprašiet naujė laikėna slaptažuodi.",
+       "resetpass-recycled": "Pamainīkat sava slaptažuodi i kėtuoki, nego daba ī.",
+       "resetpass-temp-emailed": "Tamsta prisijongėt so laikėno kuodo, ėš al. gruomatas.\nKa ožbengtomėt prisijongėma, Tamstā rēk ožrašītė nauja slaptažuodi.",
        "resetpass-temp-password": "Laikėns slaptažuodis:",
        "resetpass-expired": "Tamstas slaptažuodis bengė vēktė. Padirbkėt nauja slaptažuodi, ka prisijongtomiet.",
        "passwordreset": "Apent padėrbtė slaptažuodi",
        "passwordreset-username": "Nauduotuojė vards:",
        "passwordreset-domain": "Domens:",
        "passwordreset-email": "El. pašta adresos:",
+       "passwordreset-emailtitle": "{{SITENAME}} paskīruos aprašīms",
        "passwordreset-emailtext-ip": "Kažėkas (mosietās Tamsta, ėš IP adresa $1) ožprašė pamainītė slaptažuodi tinklapie {{SITENAME}} ($4). Tou nauduotuojė {{PLURAL:$3|poslapis|poslapio|poslapē|poslapiu}}\nsorištė so tou al. pašta adreso ī:\n\n$2\n\n{{PLURAL:$3|Tas čiesėškos slaptažuodis|čiesėški slaptažuodē}} bengs vēktė pu {{PLURAL:$5|dėinuos|$5 dėinū}}.\nTamsta prisijonkėt ė pamainīkėt sava slaptažuodi. Jēb kas tā kėts padirba tou prašīma, aba jēb atminiet sava sena slaptažuodi, ta galėt nakrēptė atėdies i tou gromata ė jongtėis so sava seno slaptažuodio.",
+       "passwordreset-emailtext-user": "Nauduotuos $1 ėš {{SITENAME}} ožprašė, ka būtom atgrōžints Tamstas {{SITENAME}} slaptažuodis ($4). Ton nauduotuoja {{PLURAL:$3|paskīra|paskīras}} prigol prī ton al. pašta adresa:\n\n$2\n\n{{PLURAL:$3|Tas laikėns slaptažuodis|Tėi laikėni slaptažuodē}} bengs vēktė ož {{PLURAL:$5|vėinuos dėinuos|$5 dėinū}}.\n\nTamsta galat prisijongtė ė pasirinktė nauja slaptažuodi. Jēb kon tās kėts ožprašė šėton, aba jēb atmėniet sava slaptažuodi ė nabnuorat anou mainītė, ta galat nakrēptė diemesė i šėton gruomata ė pu senuobie nauduotė sava slaptažuodi.",
        "passwordreset-emailelement": "Nauduotuos:\n$1\n\nČiesėšks slaptažuodis:\n$2",
+       "passwordreset-invalidemail": "Bluogs alektruonėnė pašta adresos",
        "changeemail": "Keistė aba trintė el. pašta adresa",
+       "changeemail-no-info": "Ka ētomiet tėisē ont tou poslapė, Tamstā rēk prisijongtė.",
        "changeemail-oldemail": "Vielībs el. pašta adresosː",
        "changeemail-newemail": "Naus el. pašta adresosː",
        "changeemail-none": "(nie)",
        "changeemail-password": "Tamstas {{SITENAME}} slaptažuodis:",
        "changeemail-submit": "Keistė el. pašta",
        "changeemail-throttled": "Tamsta nuognē daug sīkiu miegėnat prėsėjongtė.\nPalaukat $1 prīš miegėnont apent.",
+       "changeemail-nochange": "Irašīkat kėtuoki nauja al. pašta adresa.",
        "bold_sample": "Pastuorints raštos",
        "bold_tip": "Pastuorints raštos",
        "italic_sample": "Pasviris raštos",
        "summary": "Keitėma paāškėnėms:",
        "subject": "Tema/ontraštė:",
        "minoredit": "Mažos pakeitėms",
-       "watchthis": "Keravuotė ton poslapė",
+       "watchthis": "Keravuotė ton poslapi",
        "savearticle": "Ėšsauguotė poslapi",
+       "savechanges": "Ėšsauguotė pakeitėmus",
        "publishpage": "Padėrbtė ton poslapi",
        "publishchanges": "Ožrašītė poslapė pamainīmus",
        "preview": "Parveiza",
        "missingsummary": "'''Priminėms:''' Tamsta nenuruodiet pakeitėma kuomentara. Jēgo viel paspausėt ''Ėšsauguotė'', Tamstas pakeitėms bus ėšsauguots ba anuo.",
        "selfredirect": "<strong>Atėdės:</strong> Tamsta dėrbat poslapė nosokėma savėsp.\nParašīkat tėkslē, kor ons poslapis tor soktė.\nJēgo apent mīgsat \"{{int:savearticle}}\", ta ons poslapis vės vėin bos padėrbts.",
        "missingcommenttext": "Duokat pāiškėnėma apatiuo.",
+       "missingcommentheader": "'''Primėnėms:''' Tamsta nadaviet pakeitėma paaiškėnėma. Jēgo apent paspausat \"{{int:savearticle}}\", Tamstas pakeitėms būs ėšsauguots ba anuo.",
        "summary-preview": "Pāiškėnėma parvaiza:",
        "subject-preview": "Skėrsnelė/ontraštės parvaiza:",
+       "previewerrortext": "Miegėnant parveizietė pakeitėmus nūtėka klaida.",
        "blockedtitle": "Nauduotuos īr ožgints",
        "blockedtext": "'''Tamstas nauduotuojė vards aba IP adresos ožgints īr.'''\n\nOžgīnė nauduotuos $1.\nDingstės ''$2''.\n\n* Ožgīnėms prasėdė̄jė: $8\n* Ožgīnėms pasėbengs: $6\n* Kas tor būtė ožgints: $7\n\nTamsta galat parašītė $1 aba kėtėim\n[[{{MediaWiki:Grouppage-sysop}}|admėnėstratuorėm]], jēgo mīslėjat, ka Tamstā ožgīnė ba grieka.\nTamsta negalat „rašītė gromata ton nauduotuojō“, jēgo nasat davis tėkra sava el. pašta adresa sava [[Special:Preferences|paskīruos nustatīmūs]] ė nasat ožgints nu anuos nauduojėma.\nTamstas dabartėnis IP adresos īr $3, vuo ožgīnėma ID īr #$5. Prašuom nuruodītė ton, kumet prašīsėt atgėnoms.",
        "autoblockedtext": "Tamstas IP adresos bova liuosā ožgints, tudie, ka ana nauduojė kėts nauduotuos, katra ožgīnė $1.\nDouta dingstės īr tuokė:\n\n:''$2''\n\n* Ožgīnėms prasėdė̄jė: $8\n* Ožgīnėms pasėbengs: $6\n* Kas tor būtė ožgints: $7\n\nTamsta galėt sosėsėiktė so $1 aba kėtu [[{{MediaWiki:Grouppage-sysop}}|adminėstratuoriom]], kū aprokoutomėt biedas diel bluokavėma.\n\nTamsta galat parašītė $1 aba kėtėim\n[[{{MediaWiki:Grouppage-sysop}}|admėnėstratuorėm]], jēgo mīslėjat, ka Tamstā ožgīnė ba grieka.\nTamsta negalat „rašītė gromata ton nauduotuojō“, jēgo nasat davis tėkra sava el. pašta adresa sava [[Special:Preferences|paskīruos nustatīmūs]] ė nasat ožgints nu anuos nauduojėma.\nTamstas dabartėnis IP adresos īr $3, vuo ožgīnėma ID īr #$5. Prašuom nuruodītė ton, kumet prašīsėt atgėnoms.",
        "blockednoreason": "dingstėis nie douta",
        "whitelistedittext": "Tamstā rēk $1, ka dėrbtomiet poslapius.",
        "nosuchsectiontitle": "Nier tuokė skėrsnė",
+       "nosuchsectiontext": "Tamsta miegėnuot keistė skėrsni, katruo daba jau nabie.\nRasietās, kas tā par ton čiesa anou ėštrīnė aba parvadėna.",
        "loginreqtitle": "Rēk prėsėjongtė",
        "loginreqlink": "prėsėjongtė",
        "loginreqpagetext": "Rēk $1, paveiziejėmō kėtū poslapiu.",
        "postedit-confirmation-saved": "Tamstas padėrbts pakeitėms ėšsauguots īr.",
        "edit-already-exists": "Nie galam padėrbtė poslapė. Ons jau īr.",
        "defaultmessagetext": "Tekstos kāp prėklaus",
+       "content-model-wikitext": "viki tekstos",
+       "content-model-text": "paprasts tekstos",
+       "content-model-javascript": "JavaScript",
+       "content-json-empty-object": "Dīks dākts",
        "post-expand-template-inclusion-warning": "Perspiejėms: Šabluonu īterpėma dėdoms īr par dėdelis.\nKāp katrėi šabluonā nebus ītrauktė.",
        "post-expand-template-inclusion-category": "Poslapē, kur šabluonu īterpėma dėdoms viršėjams",
        "post-expand-template-argument-warning": "Perspiejėms: Tas poslapis tor nuors vėina šabluona argomenta, katros tor per dėdli ėšplietėma dėdoma.\nTė argomentā bova praleistė.",
        "history-feed-title": "Versėju istuorėjė",
        "history-feed-item-nocomment": "$1 $2",
        "history-feed-empty": "Prašuoms poslapis nēgzėstuo.\nAns galiejė būtė ėštrėnts ėš pruojekta, aba parvardėnts.\nPamiegīkėt [[Special:Search|ėiškoutė pruojektė]] sosėjosiu naujū poslapiu.",
+       "rev-deleted-comment": "(keitėma aprašīms ėštrints)",
+       "rev-deleted-user": "(nauduotuoja vards ėštrints)",
        "rev-delundel": "ruodītė/kavuotė",
        "rev-showdeleted": "ruodītė",
        "revisiondelete": "Trintė/atkortė versėjės",
+       "revdelete-show-file-confirm": "A ėš tėkrā nuorat parveizietė ėštrinta abruozdielė „<nowiki>$1</nowiki>“ $2 $3 atmaina?",
        "revdelete-show-file-submit": "Tēp",
+       "revdelete-selected-text": "[[:$2]] {{PLURAL:$1|pasirinkts atmains|pasirinkti atmainā}}:",
        "logdelete-selected": "{{PLURAL:$2|Pasėrinkts|Pasėrinktė|Pasėrinktė}} $1 istuorėjės {{PLURAL:$2|atėtėkims|atsėtėkimā|atsėtėkimā}}:",
+       "revdelete-legend": "Nūstatītė veizėmoma aprėbuojėmus",
+       "revdelete-hide-text": "Atmaina tekstos",
+       "revdelete-hide-image": "Kavuotė abruozdielė torėni",
+       "revdelete-hide-name": "Kavuotė tiksla ė doumenis",
        "revdelete-hide-comment": "Keitėma pāiškėnėms",
        "revdelete-hide-user": "Nauduotojė vardos/IP adresos",
+       "revdelete-radio-same": "(namainītė)",
+       "revdelete-radio-set": "Pakavuots",
+       "revdelete-radio-unset": "Veizėms",
        "revdelete-unsuppress": "Šalėntė apribuojėmos atkortuos versėjės",
+       "revdelete-log": "Dingstės:",
        "revdel-restore": "Keistė veizėmuma",
        "pagehist": "Poslapė istuorėjė",
        "deletedhist": "Ėštrinta istuorėjė",
        "mergehistory-from": "Kėlėma poslapisː",
        "mergehistory-into": "Tiksla poslapisː",
        "mergehistory-done": "$3 $1 versėju siekmėngā sojongta so [[:$2]].",
+       "mergehistory-autocomment": "[[:$1]] parnešts ont [[:$2]]",
+       "mergehistory-comment": "[[:$1]] parnešts ont [[:$2]]: $3",
+       "mergehistory-reason": "Dingstės:",
        "revertmerge": "Atskėrtė",
        "history-title": "Poslapė „$1“ istuorėjė",
        "difference-title": "$1 – skėrtoms terp pakeitėmu.",
        "searchprofile-advanced-tooltip": "Ėiškoutė skėrtingūs vardū sėtīs",
        "search-result-size": "$1 ({{PLURAL:$2|1 žuodis|$2 žuodē|$2 žuodiu}})",
        "search-result-category-size": "{{PLURAL:$1|1 narīs|$1 nariū}} ({{PLURAL:$2|1 subkateguorėjuo|$2 subkateguorėju}}, {{PLURAL:$3|1 fails|$3 failu}})",
-       "search-redirect": "(nosokėms $1)",
+       "search-redirect": "(nūsokėms ėš $1)",
        "search-section": "(skėrsnis $1)",
        "search-category": "(kateguorėjė $1)",
        "search-file-match": "(atėtėnk abruozdielė torėni)",
        "prefs-rc": "Vielībė̅jė pakeitėmā",
        "prefs-watchlist": "Keravuojamu sārašos",
        "prefs-editwatchlist": "Keistė keravuojamu sāroša",
+       "prefs-editwatchlist-label": "Mainītė keravuojamu poslapiu īrašėmus:",
        "prefs-editwatchlist-clear": "Ėštrintė keravuojamu sāroša",
        "prefs-watchlist-days": "Kėik dėinū ruodītė keravuojamu sārošė:",
        "prefs-watchlist-days-max": "(daugiausē $1 {{PLURAL:$1|dėina|dėinas|dėinū}})",
        "prefs-watchlist-edits-max": "Dėdliausis skaitlios: 1000",
        "prefs-misc": "Ivairė nustatīmā",
        "prefs-resetpass": "Keistė slaptažuodi",
-       "prefs-changeemail": "Keistė el. pašta adresa",
+       "prefs-changeemail": "Mainītė aba ėšimtė al. pašta adresa",
        "prefs-setemail": "El. pašta adresa parkeitėms",
        "prefs-email": "El. pašta nustatīmā",
        "prefs-rendering": "Ėšruoda",
        "columns": "Štolpalē:",
        "searchresultshead": "Paėiškuos nustatīmā",
        "stub-threshold": "Minimums <a href=\"#\" class=\"stub\">nabėngta poslapė</a> fuormatavėmō:",
+       "stub-threshold-sample-link": "pavīzdīs",
        "stub-threshold-disabled": "Ėšjongta īr",
        "recentchangesdays": "Ruodomas dėinas vielībūju pakeitėmu sārošė:",
        "recentchangesdays-max": "(daugiausē $1 {{PLURAL:$1|dėina|dėinū|dėinas}})",
        "prefs-files": "Abruozdielē",
        "prefs-custom-css": "Asabėšks CSS",
        "prefs-custom-js": "Asabėšks JavaScript",
+       "prefs-common-css-js": "Bendros CSS/JavaScript vėsuom aplinkuom:",
+       "prefs-reset-intro": "Čiuonās galat grōžintė vėsus sava nūstatīmus ont pradėniu (kap būn tiktās prisijongus).\nTas dalīks nab'atšaukiams.",
        "prefs-emailconfirm-label": "Tėkrā tuokis el. paštos?",
        "youremail": "El. paštos:",
        "username": "{{GENDER:$1|Nauduotuojė vards}}:",
        "yourlanguage": "Aplėnkuos kalba:",
        "yourvariant": "Torėnė kalba:",
        "yournick": "Pasėrinkts slapīvardis:",
+       "prefs-help-signature": "Kap rašuot kon tās i aptarėmu poslapius, pasirašīkat tap: \"<nowiki>~~~~</nowiki>\". Tas dākts atvirs i Tamstas paraša ė parašīma čiesa znuoka.",
        "badsig": "Neteisings parašas; patėkrinkėt HTML žīmės.",
        "badsiglength": "Tamstas parašos īr par ėlgs.\nAna gal sodarītė ne daugiau kāp $1 {{PLURAL:$1|sėmbuolis|sėmbuolē|sėmbuoliu}}.",
        "yourgender": "Lītės:",
-       "gender-unknown": "Nier nuruodīta",
+       "gender-unknown": "Nier nūruodīta",
        "gender-male": "Vīrs",
        "gender-female": "Muoterėška",
+       "prefs-help-gender": "Gėmėnies pasirinkėms nie būtėns.\nJēb ana nūruodīsat, svetainės aplinka kreipsis i Tamsta palē Tamstas gėmėnė. \nTas būs vėsiem žėnuoma.",
        "email": "El. paštos:",
-       "prefs-help-realname": "Tėkrs vards nier privaluoms, vuo jēgo Tamsta ana ivesėt, ons bus nauduojams Tamstas darba pažīmiejėmō.",
+       "prefs-help-realname": "Tėkros vards nier privaluoms, ale jēgo Tamsta ana ivesėt, ons bus nauduojams Tamstas darba pažīmiejėmou.",
        "prefs-help-email": "El. pašta adresos nier būtėns, bat ons leid Tamstā gautė naujė slaptažuodi, jēgo pamėršuot kuoks ons bova, ė tēpuogi Tamsta galėt leistė kėtėims pasėiktė Tamsta par Tamstas nauduotuojė aba nauduotuojė aptarėma poslapi tāp, ka anėi nežėnuotom Tamstas el. pašta adresa.",
        "prefs-help-email-required": "Rēk el. pašta adresa",
        "prefs-info": "Pagrindėnės žėnės",
        "prefs-displayrc": "Ruodītė nustatīmus",
        "prefs-displaywatchlist": "Ruodītė nustatīmus",
        "prefs-diffs": "Skėrtomā",
+       "prefswarning-warning": "Tamsta pamainėt sava nūstatīmus, ale anūm da naėšsauguojėt.\nJēb paliksat poslapi napaspaudus ont $1, Tamstas nūstatīmā napasikeis.",
        "userrights": "Nauduotuoju teisiu valdīms",
        "userrights-lookup-user": "Tvarkītė nauduotuojė gropės",
        "userrights-user-editname": "Iveskėt nauduotuojė varda:",
-       "editusergroup": "Redagoutė nauduotuojė gropes",
+       "editusergroup": "Mainītė nauduotuoja gropės",
        "editinguser": "Teisiu keitėms {{GENDER:$1|Nauduotuojō}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Keistė nauduotuoju gropes",
-       "saveusergroups": "Sauguotė nauduotuoju gropes",
+       "saveusergroups": "Sauguotė nauduotuoja gropės",
        "userrights-groupsmember": "Narīs:",
        "userrights-reason": "Dingstės:",
        "group": "Gropė:",
        "grouppage-bureaucrat": "{{ns:project}}:Biorokratā",
        "right-read": "Skaitītė poslapius",
        "right-edit": "Keistė poslapius",
+       "right-minoredit": "Žīmietė ketėmus kap mažus",
+       "right-move": "Parvadintė poslapius",
+       "right-move-subpages": "Parvadinė poslapius ėr anūm pūposlapius",
+       "right-move-categorypages": "Parvadintė kateguorėjės",
+       "right-movefile": "Parvadintė abruozdielius",
        "right-upload": "Ikeltė failus",
        "right-writeapi": "Nauduotė API rašīmō",
        "right-delete": "Trintė poslapius",
        "right-browsearchive": "Ėiškuotė ėštrintū poslapiu",
        "right-undelete": "Tou poslapi padėrbtė apent",
+       "grant-createeditmovepage": "Dėrbtė, keistė ė parvadintė poslapius",
        "newuserlogpage": "Nauduotuojė kūrėma sārašos",
        "rightslog": "Nauduotuoju teisiu istuorėjė",
        "rightslogtext": "Pateikiams nauduotuoju teisiu pakeitėmu sārašos.",
        "action-move-categorypages": "parvadintė kateguorėjes",
        "action-movefile": "parvadintė šėta faila",
        "action-upload": "ikeltė šėta faila",
-       "action-delete": "trintė ton poslapė",
+       "action-delete": "trintė ton poslapi",
        "action-undelete": "atkortė ta poslapi",
        "action-patrol": "pažīmietė kėtū keitėmus kāp patikrėntus",
        "action-userrights": "keistė vėsū nauduotuoju teises",
+       "action-purge": "atšvėižintė poslapi",
        "nchanges": "$1 {{PLURAL:$1|pakeitėms|pakeitėmā|pakeitėmu}}",
+       "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|nug paskotėnė apsilonkėma}}",
        "enhancedrc-history": "istuorėjė",
        "recentchanges": "Vielībė̄jė pakeitėmā",
-       "recentchanges-legend": "Vielībūju pakeitėmu pasėrinkėmā",
+       "recentchanges-legend": "Vielībūju pakeitėmu pasirinkėmā",
        "recentchanges-summary": "Keravuokat patius vielībuosius wiki pakeitėmus tamė poslapie.",
+       "recentchanges-noresult": "Par nūruodīta čiesa napradėrbts anēvėins Tamstas nuorams pakeitėms.",
        "recentchanges-feed-description": "Keravuokėt patius vielībiausius pakeitėmus pruojektō tamė šaltėnī.",
        "recentchanges-label-newpage": "Šėtuo keitėmuo padėrbts naus poslapis",
        "recentchanges-label-minor": "Tas īr mažos pataisīms",
        "recentchanges-label-plusminus": "Anuo baitu skaitliom pakeists straipsnė apmiers",
        "recentchanges-legend-heading": "<strong>Pāiškėnėmā:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (dā veiziekat [[Special:NewPages|vielībūju straipsniu sāroša]])",
+       "recentchanges-submit": "Ruodītė",
        "rcnotefrom": "Apatiuo {{PLURAL:$5|ruodoms pakeitėms|ruodomė pakeitėmā}} nug <strong>$3, $4</strong> (ne daugiau kāp <strong>$1</strong> ruodoma īr).",
        "rclistfrom": "Ruodītė vielībus pakeitėmus pradedont nug $3 $2",
        "rcshowhideminor": "$1 mažus pakeitėmus",
        "rcshowhidebots": "$1 robuotus",
        "rcshowhidebots-show": "Ruodītė",
        "rcshowhidebots-hide": "Kavuotė",
-       "rcshowhideliu": "$1 prėsėjongusiūm nauduotuojūm pakeitėmus",
+       "rcshowhideliu": "$1 prisijongusiu nauduotuoju pakeitėmus",
        "rcshowhideliu-show": "Ruodītė",
        "rcshowhideliu-hide": "Kavuotė",
        "rcshowhideanons": "$1 nažėnomus nauduotuojus",
        "rcshowhidemine-show": "Ruodītė",
        "rcshowhidemine-hide": "Kavuotė",
        "rcshowhidecategorization": "$1, kap poslapiam doud kateguorėjės",
+       "rcshowhidecategorization-show": "Ruodītė",
+       "rcshowhidecategorization-hide": "Kavuotė",
        "rclinks": "Ruodītė vielībus $1 pakeitėmu par paskuojės $2 dėinas<br />$3",
        "diff": "skėrt",
        "hist": "ist",
        "recentchangeslinked-summary": "Tamė specēliam poslapi sogol vielībė̄jė pakeitėmā poslapiūs, i katrūs īr nuruodoma. Poslapē ėš Tamstas [[Special:Watchlist|keravuojamu sāroša]] ėšruod '''stuorā'''.",
        "recentchangeslinked-page": "Poslapė pavadėnėms:",
        "recentchangeslinked-to": "Ruodītė anūs poslapiu pakeitėmus, katrėi prėgol prī douta poslapė",
+       "recentchanges-page-added-to-category": "[[:$1]] pridieta i kateguorėjė",
        "upload": "Ožkrautė abruozdieli",
        "uploadbtn": "Ikeltė faila",
        "reuploaddesc": "Sogrīžtė i ikielima fuorma.",
        "upload-file-error-text": "Ivīka vėdėnė klaida bandont sokortė laikinaji faila serverī. Prašuom sosėsėiktė so sistemuos admėnėstratuoriom.",
        "upload-misc-error": "Nažėnuoma ikielėma klaida",
        "upload-misc-error-text": "Ivīka nežėnuoma klaida vīkstont ikielėmō. Prašuom patėkrėnt, kū URL teisėngs teipuogi pasėikiams ėr pamiegīkit viel. Jē bieda ėšlėik, sosėsėikėt so sistemuos admėnėstratuoriom.",
+       "upload-http-error": "Nūtėka HTTP klaida: $1",
        "upload-dialog-title": "Ožkrautė abruozdieli",
        "upload-dialog-button-cancel": "Pabengtė",
+       "upload-dialog-button-back": "Atgaliuos",
        "upload-dialog-button-done": "Padėrbt",
        "upload-dialog-button-save": "Ėšsauguotė",
        "upload-dialog-button-upload": "Ožkrautė",
        "upload-form-label-infoform-description": "Aprašīms",
        "upload-form-label-usage-title": "Nauduojėms",
        "upload-form-label-usage-filename": "Abruozdielė pavadėnėms",
+       "upload-form-label-own-work": "Tas muona darbs ī",
+       "upload-form-label-infoform-categories": "Kateguorėjės",
+       "upload-form-label-infoform-date": "Čiesos",
+       "upload-form-label-own-work-message-generic-local": "Sotinko, ka ikeldams ton abruozdieli darou ton palē {{SITENAME}} taisīklės.",
        "backend-fail-notexists": "Abruozdielė „$1“ nie.",
        "backend-fail-alreadyexists": "Abruozdielis „$1“ jau īr.",
+       "uploadstash-thumbnail": "veizietė somažinta",
        "img-auth-accessdenied": "Ožgint prė̄tė",
        "upload-curl-error6": "Napavīkst pasėiktė URL",
        "upload-curl-error6-text": "Pataikts URL nagal būt pasėikts. Prašuom patėkrėntė, kū URL īr teisings ėr svetainė veik.",
        "upload_source_file": " (fails Tamstas kompioterī)",
        "listfiles-delete": "trintė",
        "listfiles-summary": "Tas specēlus poslapis ruod vėsus ikeltus failus.\nPalē numatīma paskiausē ikeltė failā īr ruoduomė sāroša vėršou.\nPaspaude ont štolpelė ontraštės pakeisėt ėšruokavėma.",
+       "listfiles-userdoesnotexist": "Nie tuokė nauduotuoja varda kap „$1“",
        "imgfile": "abruozdielis",
        "listfiles": "Failu sārašos",
        "listfiles_thumb": "Somažints",
        "linkstoimage": "{{PLURAL:$1|Ons poslapis|Anėi poslapē}} ruod ton abruozdielin:",
        "nolinkstoimage": "Abruozdielėp neruod anėjuoks poslapis.",
        "morelinkstoimage": "Veizietė [[Special:WhatLinksHere/$1|daugiau nūruodu]] ton abruozdielėn.",
+       "linkstoimage-redirect": "$1 (abruozdielė nūsokėms) $2",
        "sharedupload": "Tas fails īr ėš $1 ė gal būtė nauduojams kėtūs pruojektūs.",
        "sharedupload-desc-here": "Tas abruozdielis īr nug $1 ė gal būtė nauduojams kėtūs poslapiūs.\nŽinės nug [$2 abruozdielė aprašīma poslapė] prėgol apatiuo.",
        "sharedupload-desc-create": "Šėts abruozdielis īr ėš $1 ė gal būtė nauduonams kėtūs pruojektūs. \nMaž nuorat pamainītė anuo aprašīma [$2 anuo poslapie]?",
        "download": "parsėsiūstė",
        "unwatchedpages": "Nekeravuojėmė poslapē",
        "listredirects": "Paradresavėmu sārašos",
+       "listduplicatedfiles": "Abruozdieliu so doblėkatās sārašos",
        "unusedtemplates": "Nenauduojamė šabluonā",
        "unusedtemplatestext": "Tas poslapis ruod sāraša poslapiu, esontiu vardū srėtie „{{ns:template}}“, katrėi nie iterptė i juoki kėta poslapi. Nepamėrškat patikrėntė kėtū nūruodu prīš anas ėštrėnont.",
        "unusedtemplateswlh": "kėtas nūruodas",
        "randompage": "Bikuoks poslapis",
        "randompage-nopages": "Šėtuo vardū srėti nier anėjuokiu poslapiu.",
        "randomincategory": "Bikuoks poslapis kateguorėjuo",
+       "randomincategory-invalidcategory": "\"$1\" nie gers kateguorėjės pavadėnėms.",
+       "randomincategory-nopages": "[[:Category:$1|$1]] kateguoriejuo poslapiu nie.",
        "randomincategory-category": "Kateguorėjė:",
        "randomincategory-legend": "Bikuoks poslapis kateguorėjuo",
        "randomincategory-submit": "Ēk",
        "randomredirect": "Bikuoks nusokims",
-       "randomredirect-nopages": "Šėtuo vardū srėtie nie anėjuokiu nusokėmu.",
+       "randomredirect-nopages": "Šėtuo vardū srėtie $1 nie anėjuokiu nūsokėmu.",
        "statistics": "Skaitlē",
        "statistics-header-pages": "Poslapiu sklaitlē",
        "statistics-header-edits": "Keitėmu skaitlē",
        "specialloguserlabel": "Nauduotuos:",
        "speciallogtitlelabel": "Pavadėnims:",
        "log": "Specēliūju vīksmū istuorėjė",
-       "all-logs-page": "Vėsos istuorėjės",
+       "all-logs-page": "Vėsas istuorėjės",
        "alllogstext": "Bėndra idietu failu, ėštrīnėmu, ožrakėnėmu, bluokavėmu ė prėvėlėju soteikėmu istuorėjė.\nĪr galėmībė somažintė rezoltatu skaitliu patėkslėnont vēksma tėpa, nauduotuojė a sosėjosė poslapė.",
        "logempty": "Istuorėjuo nier anėjuokiū atitinkontiu atsėtėkimu.",
        "log-title-wildcard": "Ėiškuotė pavadinėmu, katrė prasėded šėtuo teksto",
        "showhideselectedlogentries": "Ruodītė/kavuotė sāraša ponktus, katrūs pasėrėnkot",
        "checkbox-select": "Rinktėis: $1",
        "checkbox-all": "Viskos",
+       "checkbox-none": "Nieka",
+       "checkbox-invert": "Apverstė",
        "allpages": "Vėsė straipsnē",
        "nextpage": "Kėts poslapis ($1)",
        "prevpage": "Onkstesnis poslapis ($1)",
        "categoriesfrom": "Ruodītė kateguorėjės pradedont nu:",
        "deletedcontributions": "Ėštrints nauduotuojė duovis",
        "deletedcontributions-title": "Ėštrints nauduotuojė duovis",
-       "linksearch": "Ėšuorėnės nūruodas",
+       "sp-deletedcontributions-contribs": "duovē",
+       "linksearch": "Ėšuorėniu nūruodu ėiškuojėms",
        "linksearch-ns": "Vardū srėtės:",
        "linksearch-ok": "Ėiškuotė",
        "linksearch-line": "$1 īr sosėits ėš $2",
        "listusers-noresult": "Nerast anėjuokiū nauduotuoju.",
        "listusers-blocked": "(ožgints)",
        "activeusers": "Vēkōs nauduotuojē",
+       "activeusers-count": "$1 {{PLURAL:$1|darbs|darbū}} par {{PLURAL:$3|paskotėnė dėina|$3 paskotėnės dėinas|$3 paskotėniu dėinū}}",
+       "activeusers-from": "Ruodītė nauduotuojus pradedont nug:",
        "activeusers-noresult": "Nerast anėjuokiu nauduotuoju.",
+       "activeusers-submit": "Ruodītė darbštius nauduotuojus",
        "listgrouprights": "Nauduotuoju gropiu teisės",
        "listgrouprights-group": "Gropė",
        "listgrouprights-rights": "Teisės",
        "listgrouprights-members": "(nariū sārašos)",
+       "listgrouprights-namespaceprotection-namespace": "Vardū srėtės",
+       "listgrants-grant": "Leidėms",
+       "listgrants-rights": "Teisės",
        "trackingcategories": "Pruogramėnės keravuojėma kateguorėjės",
        "mailnologin": "Nier adresa",
        "mailnologintext": "Tamstā reik būtė [[Special:UserLogin|prisėjongosiam]]\nė tor būtė ivests teisings el. pašta adresos Tamstas [[Special:Preferences|nustatīmuos]],\nkū siōstomiet el. gruomatas kėtėm nauduotuojam.",
        "wlheader-enotif": "El. pašta primėnėmā ijongtė īr.",
        "wlheader-showupdated": "Poslapē, katrėi pakeistė nu Tamstas paskotėnė apsėlonkėma čiesa anūs, īr pažīmietė '''pastuorintā'''",
        "wlnote": "Ruoduoma '''$1''' paskotėniu pakeitėmu, atlėktū par '''$2''' paskotėniu adīnu.",
-       "wlshowlast": "Ruodītė paskotėniu $1 adīnu, $2 dėinū a  pakeitėmus",
-       "watchlist-options": "Keravuojamu sāroša pasėrinkėmā",
+       "wlshowlast": "Ruodītė paskotėniu $1 adīnu, $2 dėinū pakeitėmus",
+       "watchlist-hide": "Kavuotė",
+       "watchlist-submit": "Ruodītė",
+       "wlshowhideminor": "maži pakeitėmā",
+       "wlshowhidebots": "buotā",
+       "wlshowhideliu": "prisijongė̄ nauduotuojē",
+       "wlshowhideanons": "naprisijongė̄ nauduotuojē",
+       "wlshowhidemine": "mona keitėmā",
+       "watchlist-options": "Keravuojamu sāraša pasirinkėmā",
        "watching": "Kergiama keravuojamu sārošon...",
        "unwatching": "Šalėnama ėš keravuojamu sāraša...",
        "enotif_reset": "Pažīmietė vėsus poslapius kāp aplonkītus",
        "enotif_impersonal_salutation": "{{SITENAME}} nauduotuos",
+       "enotif_subject_deleted": "{{SITENAME}} poslapis $1 bova ėštrints $2",
+       "enotif_subject_created": "{{SITENAME}} poslapis $1 bova padėrbts $2",
+       "enotif_subject_moved": "{{SITENAME}} poslapis $1 bova parvadints $2",
+       "enotif_subject_restored": "{{SITENAME}} poslapis $1 bova grōžints $2",
+       "enotif_subject_changed": "{{SITENAME}} poslapis $1 bova paminīts $2",
+       "enotif_body_intro_deleted": "{{SITENAME}} poslapi $1 $PAGEEDITDATE ėštrīnė $2, veiziekėt $3.",
+       "enotif_body_intro_created": "{{SITENAME}} poslapi $1 $PAGEEDITDATE padėrba $2, veiziekėt vielībiausia atmaina $3.",
+       "enotif_body_intro_moved": "{{SITENAME}} poslapi $1 $PAGEEDITDATE parvadėna $2, veiziekėt vielībiausia atmaina $3.",
+       "enotif_body_intro_restored": "{{SITENAME}} poslapi $1 $PAGEEDITDATE grōžėna $2, veiziekėt vielībiausia atmaina $3.",
+       "enotif_body_intro_changed": "{{SITENAME}} poslapi $1 $PAGEEDITDATE pamainė $2, veiziekėt vielībiausia atmaina $3.",
+       "enotif_lastvisited": "Veiziekėt $1, ka žėnuotomėt vėsus pakeitėmus nug Tamstas paskotėnė apsilonkīma.",
+       "enotif_lastdiff": "Veiziekėt $1, ka paveizietomėt ton pakeitėma.",
        "enotif_anon_editor": "anuonėminis nauduotuos $1",
        "created": "sokūrė",
        "changed": "pakeitė",
        "deletepage": "Trintė poslapi",
        "confirm": "Tėkrā tāp",
        "excontent": "bovis torėnīs: „$1“",
-       "excontentauthor": "bovis torėnīs: „$1“ (dėrba tėktās „[[Special:Contributions/$2|$2]]“)",
+       "excontentauthor": "bovė̄s torėnīs: „$1“ (dėrba tėktās „[[Special:Contributions/$2|$2]] [[User talk:$2|aptarėms]]“)",
        "exbeforeblank": "prīš ėštrinont torėnīs bova: „$1“",
        "delete-confirm": "Trintė „$1“",
        "delete-legend": "Trīnėms",
        "historywarning": "<strong>Atėdės:</strong> Poslapis, katron nuorat ėštrintė, bova pakeists $1 {{PLURAL:$1|sīki|sīkius|sīkiu}}:",
+       "historyaction-submit": "Ruodītė",
        "confirmdeletetext": "Tamsta pasėrėnkuot ėštrėntė poslapi a abruozdieli draugum so vėsa anuo istuorėjė.\nPrašuom patvėrtėntė, kū Tamsta tėkrā nuorėt šėtu padarītė, žėnuot aple galėmus padarėnius, ė kū Tamsta šėtā daruot atsėžvelgdamė i [[{{MediaWiki:Policy-url}}|puolitėka]].",
        "actioncomplete": "Vēksmos padėrbts īr",
        "actionfailed": "Vēksmos atšaukts īr",
        "deletereasonotherlist": "Kėta dingstės",
        "deletereason-dropdown": "* Tonkiausės ėštrėnėma dingstisː\n** Šiokšlėnėms\n** Zaunū/bikuo rašīms\n** Pažeistas dėrbieju teisės\n** Patėis nauduotuojė prašīms\n** Bluogs poslapė nusokėms",
        "delete-edit-reasonlist": "Mainītė trīnėma dingstis",
+       "deleteprotected": "Tamsta nagalėt ėštrintė ton poslapė, ba ons apsergiets ī.",
+       "deleting-backlinks-warning": "<strong>Atėduos:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|Kėti poslapē]] tora nūruodas aba apjėm ton poslapi, katra nuorėt trintė.",
        "rollback": "Atmestė pakeitėmus",
        "rollbacklink": "atmestė",
        "rollbacklinkcount": "sogrōžintė $1 {{PLURAL:$1|pakeitėma|pakeitėmo|pakeitėmus|pakeitėmu}}",
        "editcomment": "Padėrbėma paāškėnėms bova: <em>$1</em>.",
        "revertpage": "Atmests [[Special:Contributions/$2|$2]] ([[User talk:$2|aptarėms]]) pakeitėms; sogrōžints atmains, katron padėrba nauduotuos [[User:$1|$1]]",
        "rollback-success": "Atmestė $1 padėrbtė keitėmā; grōžints $2 padėrbts atmains.",
+       "rollback-success-notify": "Atmestė $1 padėrbtė keitėmā; grōžints $2 padėrbts atmains. [$3 ruodītė keitėmus]",
+       "sessionfailure-title": "Sesėjės klaida",
        "sessionfailure": "Atruod ka īr biedū so Tamstas prėsėjongėmo; tas vēksmos bova grōžints kāp atsargoma prėimonė nu sesėjės vuogėma.\nPrašoum mīgtė „atgal“ ėr parkrautė poslapi ėš katruo atiejėt, ė pamieginkėt apent.",
        "changecontentmodel-title-label": "Poslapė pavadėnėms",
        "changecontentmodel-reason-label": "Dingstės:",
        "modifiedarticleprotection": "pamainīts „[[$1]]“ apserguos miers",
        "unprotectedarticle": "nujėmė apserga nug „[[$1]]“",
        "movedarticleprotection": "apsergiejėma nustatīma parkeltė nug \"[[$2]]\" i \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Apsergiejė}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Pamainė}} \"[[$1]]\" apserga",
+       "unprotectedarticle-comment": "{{GENDER:$2|Bengė}} \"[[$1]]\" apserga",
        "protect-title": "Nustatuoms apsauguojėma līgis poslapiō „$1“",
+       "protect-title-notallowed": "Veizietė \"$1\" apserga",
        "prot_1movedto2": "Straipsnis [[$1]] parvadints i [[$2]]",
        "protect-legend": "Tėkrā tuokis apsergiejėms?",
        "protectcomment": "Dingstės:",
        "sp-contributions-username": "IP adresos a nauduotuojė vards:",
        "sp-contributions-toponly": "Ruodītė tėktās paskiausius keitėmus",
        "sp-contributions-newonly": "Ruodītė tėktās tūs keitėmus, katrās padėrbtė straipsnē",
+       "sp-contributions-hideminor": "Kavuotė mažus pakeitėmus",
        "sp-contributions-submit": "Ėiškuotė",
        "whatlinkshere": "Sosėjė̄ straipsnē",
        "whatlinkshere-title": "Poslapē, katrėi ruod i \"$1\"",
        "whatlinkshere-hidelinks": "$1 nūruodas",
        "whatlinkshere-hideimages": "$1 abruozdieliu nūruodas",
        "whatlinkshere-filters": "Kuošeklē",
+       "whatlinkshere-submit": "Ēk",
        "block": "Ožgintė nauduotuoji",
        "unblock": "Nauduotuojė ožgīnėma bengtė",
        "blockip": "Ožgintė {{GENDER:$1|nauduotoji}}",
        "blockip-legend": "Ožgintė nauduotuoji",
-       "blockiptext": "Nauduokėt šėta fuorma noriedamė oždraustė redagavėma teises nuruodīto IP adreso a nauduotuojo. Tas torietu būt atlėikama tam, kū sostabdītomiet vandalėzma, ė vagol [[{{ns:project}}:Puolitėka|puolitėka]].\nŽemiau nuruodīkėt tėkslē prižastė.",
+       "blockiptext": "Nauduokėt šėta skvarma kap nuorėt ožgintė redagavėma teisės nūruodītou IP adresou a nauduotuojou. Tas torietom būtė dėrbama, ka apsergietomėt poslapius nug gadėnėma, ė palē [[{{MediaWiki:Policy-url}}|sotarėma]].\n\nKap ožgėnat, nūruodīkėt tikslē, ož kon.",
        "ipaddressorusername": "IP adresos a nauduotuojė vards",
        "ipbexpiry": "Vēkėma čiesos",
        "ipbreason": "Dingstės:",
        "ipbreason-dropdown": "*Tonkiausės ožgīnėma dingstisː\n** Neteisībės rašīms\n** Torėnė trīnims ėš poslapiu\n** Šiokšlėnėms\n** Zaunu/bikuo rašīms i poslapius\n** Gondėnėmā/Pėktžuodiavėmā\n** Nauduojėms daugiaus kāp vėinuos paskīruos\n** Natinkams nauduotuojė vards",
+       "ipb-hardblock": "Nalaistė prisijongosėm nauduotuojėm dėrbtė pakeitėmu ėš ton IP adresa",
        "ipbcreateaccount": "Nelaistė dėrbtė paskīrū",
        "ipbemailban": "Nelaistė nauduotuojō siōstė el. gromatas",
        "ipbenableautoblock": "Autuomatėškā blokoutė tuo nauduotuojė paskiausē nauduota IP adresa, ė bikuokius paskesnius IP adresus, ėš katrū ons miegin redagoutė",
        "ipbsubmit": "Ožgintė ton nauduotuoji",
        "ipbother": "Kėtuoks čiesos",
        "ipboptions": "2 adīnė:2 hours,1 dėina:1 day,3 dėinas:3 days,1 nedielė:1 week,2 nedielė:2 weeks,1 mienou:1 month,3 mienesē:3 months,6 mienesē:6 months,1 metā:1 year,omžėms:infinite",
+       "ipbhidename": "Kavuotė nauduotuoja varda pakeitėmūs ė sārašūs",
        "ipbwatchuser": "Keravuotė tuo nauduotuojė poslapi ėr anuo aptarėma poslapi",
+       "ipb-disableusertalk": "Nalaistė nauduotuojou rašītė i sava aptarėmu poslapi kap ons ožgints ī",
        "ipb-change-block": "Parblokoutė ta nauduotuoja so šėtās nustatīmās",
        "ipb-confirm": "Tėkrā ožgintė?",
        "badipaddress": "Nelaistėns IP adresos",
        "blockipsuccesssub": "Nauduotuos bova ožgints",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] bova ožgints.\n<br />Aplonkīkat [[Special:BlockList|IP ožginėmu istuorėjė]], jēgo nuorat anou parveizietė.",
+       "ipb-blockingself": "Tamsta tūjaus ožginsėt savėi pati! A tėkrā tap nuorėt?",
        "ipb-edit-dropdown": "Mainītė ožgīnėma dingstis",
        "ipb-unblock-addr": "Nug $1 nujėmtė ožgīnėma",
        "ipb-unblock": "Nug nauduotuojė varda a IP adresa nujėmtė ožgīnėma",
        "ipb-blocklist": "Ruodītė vielībousius ožgīnėmus",
        "ipb-blocklist-contribs": "$1 duovis",
+       "ipb-blocklist-duration-left": "palėka $1",
        "unblockip": "Nauduotuojė ožgīnėma bengtė",
        "unblockiptext": "Nauduokėt šėta fuorma, kū atkortomiet rašīma teises\nonkstiau ožbluokoutam IP adresō a nauduotuojō.",
        "ipusubmit": "Ton ožgīnėma nojėmtė",
        "block-log-flags-angry-autoblock": "vēk prapliests ožgīnėms",
        "block-log-flags-hiddenname": "nauduotuojė vards pakavuots īr",
        "ipb_expiry_invalid": "Galiuojėma čiesos nelaistėns.",
+       "ipb_expiry_old": "Galiuojėma čiesos īr praeitie.",
        "ipb_already_blocked": "„$1“ jau ožgints",
        "ipb-needreblock": "$1 jau īr ožblokouts. A nuorėt pakeistė nustatīmus?",
        "ipb-otherblocks-header": "{{PLURAL:$1|Kėts ožgīnėms|Kėtė ožgīnėmā}}",
        "move-page": "Parvadintė $1",
        "move-page-legend": "Poslapė parvadėnėms",
        "movepagetext": "Nauduojont ta skvarma, katra apatiuo īr, parvadinsat poslapi ėr ėšlaikīsat anuo istuorėjė.\nOnkstesnis pavadėnėms palėks nosokėmo - ons ruodīs poslapin naujė varda.\nTamsta esat atsakėngs, ka nūruodas ruodītom tenā, kor ė rēk.\n\nAtminkat, ka poslapis '''nabus''' parvadints, jēgo jau īr poslapis naujo pavadinėmo, tėktās jēgo ons īr dīks aba netor keitėmu istuorėjės.\nTumet, Tamsta galat parvadintė poslapi seniou nauduoto vardo, jēgo priš šėta ons bova par klaida parvadints, ar esontiu poslapiu sogadintė negalat.\n\n'''ATĖDĖS!'''\nJēgo parvadinat tonkē nauduojama poslapi, ta galat prėdėrbtė ėškadas. Tudie kervauokat, ka dėrbat.",
+       "movepagetext-noredirectfixer": "So ton skvarma apatiuo Tamsta parvadinsat poslapi ė parkelsat vėsa anou istuorėjė.\nSens poslapis paliks nūsokėmo i nauja straipsnė varda.\nSotikrinkėt, ka napalėikat [[Special:DoubleRedirects|dvėgobu]] aba [[Special:BrokenRedirects|navēkontiu nūsokėmu]].\nTamsta pasilėikat atsakings, ka nūruodas ė tuoliaus ruodītom tenās, kor ė rēk.\n\nToriekat uomenie, ka poslapis '''nabūs''' parvadins, jēb jau poslapis so tuokio vardo ī (nabentās, ons būtom tėktās nūsokėms ba istuorėjės).\nTas rēšk, ka Tamsta galiesat sogrōžintė poslapi ont sena anou varda, jēb padarīsat klaida.\n\n'''ATĖDĖS:'''\nJēb parvadinat gausē nauduojama poslapi, ta galat prīdėrbtė ėškadas;\nTudie kervauokat, ka dėrbat!",
        "movepagetalktext": "Sosėits aptarėma poslapis bus autuomatėškā parkelts draugom so ano, '''ėšskīrus:''':\n*Poslapis nauju pavadinėmo tor netoštė aptarėma poslapi, a\n*Paliksėt žemiau asontė varnale nepažīmieta.\nŠėtās atviejās Tamsta sava nužiūra torėt parkeltė a apjongtė aptarėma poslapi.",
        "moveuserpage-warning": "<strong>Atėdės:</strong> Tamsta parvadėnsat nauduotuojė poslapi. Žėnuokat, ka tėktās poslapis bat <em>ne patsā nauduotuos</em> bos parvadints.",
        "movecategorypage-warning": "<strong>Atėdės:</strong> Tamsta parvadinsat kateguorėjės poslapi. Žėnuokat, ka tėktas poslapis bos parvadints, bat <em>poslapē, katrėi anon prėgol,</em> tor būtė sokergtė apent.",
        "tooltip-pt-watchlist": "Poslapiu, katrūs Tamsta pasirinkuot keravuotė, sārašos.",
        "tooltip-pt-mycontris": "Tamstas dėrbtū keitėmu sārašos",
        "tooltip-pt-login": "Kvėitam prėsėjongtė, nuors tas ė nie būtėna.",
-       "tooltip-pt-logout": "Atsėjongtė",
+       "tooltip-pt-logout": "Atsijongtė",
        "tooltip-pt-createaccount": "Tamstā kvėitam padėrbtė paskīra ė prėsėjongtė; bat tas nie būtėina",
        "tooltip-ca-talk": "Poslapė torėnė aptarėms",
-       "tooltip-ca-edit": "Taisītė ton poslapė",
+       "tooltip-ca-edit": "Taisītė ton poslapi",
        "tooltip-ca-addsection": "Pradietė naujė skėrsneli",
        "tooltip-ca-viewsource": "Ons poslapis apsergiets īr. Galat tėktās parveiziet kas anamė ožrašīta.",
        "tooltip-ca-history": "Onkstesnė ton poslapė atmainā.",
index 09392ad..6e3d91c 100644 (file)
        "yourpasswordagain": "Ponovo upišite šifru / Поново упишите шифру",
        "createacct-yourpasswordagain": "Potvrdite lozinku/zaporku",
        "createacct-yourpasswordagain-ph": "Unesite lozinku/zaporku ponovno",
-       "remembermypassword": "Upamti moju lozinku na ovom kompjuteru (za maksimum od $1 {{PLURAL:$1|dan|dana}})",
        "userlogin-remembermypassword": "Zapamti prijavu",
        "userlogin-signwithsecure": "Koristite sigurnu vezu",
        "yourdomainname": "Vaš domen:",
        "activeusers-intro": "Ovo je spisak korisnika koji su napravili neku aktivnost u {{PLURAL:$1|zadnji $1 dan|zadnja $1 dana|zadnjih $1 dana}}.",
        "activeusers-count": "{{PLURAL:$1|$1 izmjena|$1 izmjene|$1 izmjena}} u {{PLURAL:$3|posljednji $3 dan|posljednja $3 dana|posljednjih $3 dana}}",
        "activeusers-from": "Prikaži korisnike koji počinju sa:",
-       "activeusers-hidebots": "Sakrij botove",
-       "activeusers-hidesysops": "Sakrij administratore",
        "activeusers-noresult": "Nije pronađen korisnik.",
        "listgrouprights": "Prava korisničkih grupa",
        "listgrouprights-summary": "Slijedi spisak korisničkih grupa na ovoj wiki, s njihovim pravima pristupa.\nO svakoj od njih postoje i [[{{MediaWiki:Listgrouprights-helppage}}|dodatne informacije]].",
        "htmlform-no": "Ne",
        "htmlform-yes": "Da",
        "htmlform-chosen-placeholder": "Odaberi opciju",
-       "sqlite-has-fts": "$1 sa podrškom pretrage cijelog teksta",
-       "sqlite-no-fts": "$1 bez podrške pretrage cijelog teksta",
        "logentry-delete-delete": "$1 je {{GENDER:$2|obrisao|obrisala}} stranicu $3",
        "logentry-delete-restore": "$1 je {{GENDER:$2|vratio|vratila}} stranicu $3",
        "logentry-delete-event": "$1 je {{GENDER:$2|promijenio|promijenila}} vidljivost {{PLURAL:$5|događaja|$5 događaja}} u evidenciji na $3: $4",
index 71a8157..f84e6e2 100644 (file)
        "yourname": "smiyt o-msxdam:",
        "yourpassword": "awal iḥdan:",
        "yourpasswordagain": "Зawd ara awal iḥdan:",
-       "remembermypassword": "Askti nu ukcum ɣ Urdinaturad (Iɣ kullu tggut $1 {{PLURAL:$1|Ass|Ass}})",
        "yourdomainname": "Taɣult nek",
        "externaldberror": "Imma tlla ɣin kra lafut ɣu ukcumnk ulla urak ittuyskar at tsbddelt lkontnk nbrra.",
        "login": "Kcm ɣid",
index 5105d79..eafaea6 100644 (file)
        "passwordreset-emailelement": "ၸိုဝ်ႈၽူႈၸႂ်ႉတိုဝ်း:\n$1\n\nၶေႃႈလပ်ႉ ၸူဝ်ႈၵႅပ်ႉ:\n$2",
        "passwordreset-emailsentemail": "ႁဵင်းလိၵ်ႈ ဢီးမေးလ်ဢၼ်ၼႆႉၼႆႉ မၼ်းၵပ်းၵၢႆႇၵၼ်တင်း ဢၶွင်ႉၸဝ်ႈၵဝ်ႇ၊ ဢၼ်ပဵၼ် ဢီးမေးလ် တႃႇတင်ႈၶိုၼ်းမၢႆလပ်ႉၼၼ်ႉ တေထုၵ်ႇသူင်ႇၸူးယူႇ.",
        "passwordreset-emailsentusername": "ႁဵင်းလိၵ်ႈ ဢီးမေးလ်ဢၼ်ၼႆႉၼႆႉ မၼ်းၵပ်းၵၢႆႇၵၼ်တင်း ၸိုဝ်ႈၽူႈၸႂ်ႉတိုဝ်း ဢၼ်ၼႆႉ၊ ဢၼ်ပဵၼ် ဢီးမေးလ် တႃႇတင်ႈၶိုၼ်းမၢႆလပ်ႉၼၼ်ႉ တေထုၵ်ႇသူင်ႇၸူးယူႇ.",
-       "passwordreset-invalideamil": "ႁဵင်းလိၵ်ႈ ဢီႈမေးလ် ၽိတ်းဝႆႉ။",
+       "passwordreset-invalidemail": "ႁဵင်းလိၵ်ႈ ဢီႈမေးလ် ၽိတ်းဝႆႉ။",
        "passwordreset-nodata": "ၸိုဝ်ႈၽူႈၸႂ်ႉတိုဝ်းလႄႈ ႁဵင်းလိၵ်ႈဢီးမေးလ် ဢမ်ႇလႆႈၵမ်ႉထႅမ်ဝႆႉ သေဢၼ်။",
        "changeemail": "လႅၵ်ႈလၢႆႈ ဢမ်ႇၼၼ် ထွၼ်ပႅတ်ႈ ႁဵင်းလိၵ်ႈ ဢီးမေးလ်",
        "changeemail-no-info": "တႃႇၸဝ်ႈၵဝ်ႇ တေၸၢင်ႈၸႂ်ႉလႆႈ ၼႃႈလိၵ်ႈၼႆႉ ၵမ်းသိုဝ်ၼၼ်ႉၼႆ ၸဝ်ႈၵဝ်ႇ တေလႆႈ ၶဝ်ႈလွၵ်ႉဢိၼ်ႇဝႆႉဢေႃႈ။",
index cb5735d..59a3ba6 100644 (file)
        "yourpasswordagain": "මුරපදය යළි ඇතුළු කරන්න:",
        "createacct-yourpasswordagain": "මුරපදය සනාථ කරන්න",
        "createacct-yourpasswordagain-ph": "මුරපදය යළි ඇතුළු කරන්න",
-       "remembermypassword": "මාගේ පිවිසීම මෙම ගවේෂක මතකයෙහි (උපරිම ලෙස {{PLURAL:$1|දින|දින}}) $1 ක් මතක තබාගන්න",
        "userlogin-remembermypassword": "මා ප්‍රවිසීම් තත්වයේම තබන්න",
        "userlogin-signwithsecure": "ආරක්‍ෂිත සබඳතාව භාවිතා කරන්න",
        "cannotloginnow-title": "දැන් පිවිසීමට නොහැකිය",
        "passwordreset-emailtext-user": "{{SITENAME}} හි පරිශීලක $1,{{SITENAME}}($4)සඳහා මුරපදය යලි පිහිටුවීමට ඉල්ලා ඇත.\n\n$2\n\n{{PLURAL:$3|මෙම මුරපදය|මෙම මුරපද}}{{PLURAL:$5|එක් දිනකින්|දවස්$5කින්}}කල් ඉකුත් වනු ඇත.\nඔබ දැන් ඇතුළු වී නව මුරපදයක් තේරිය යුතුය.මෙම ඉල්ලීම වෙන කෙනෙකු විසින් හෝ ඔබට ඔබගේ මුල් මුරපදය මතක නම් හෝ ඔබ තව දුරටත් එය වෙනස් කිරීමට අදහස් නොකරයි නම් හෝ ඔබ මෙම පනිවිඩය නොසලකාහැර ඔබගේ පැරණි මුරපදය භාවිතා කරන්න.",
        "passwordreset-emailelement": "පරිශීලක නාමය: \n$1\n\nතාවකාලික මුරපදය: \n$2",
        "passwordreset-emailsentemail": "මුර-පදය නැවත සකස් කිරීම පිළිබඳව විද්‍යුත් තැපෑලක් යවන ලදී.",
-       "passwordreset-invalideamil": "වලංගු නැති ඊමේල් ලිපිනය",
+       "passwordreset-invalidemail": "වලංගු නැති ඊමේල් ලිපිනය",
        "changeemail": "විද්‍යුත් තැපෑල වෙනස් කරන්න හෝ ඉවත් කරන්න",
        "changeemail-header": "ගිණුම් විද්‍යුත් තැපැල් ලිපිනය වෙනස් කරන්න",
        "changeemail-no-info": "මෙම පිටුව සෘජු ලෙස සම්ප්‍රවේශය කෙරුමට පළමුව ඔබ ප්‍රවිෂ්ටව සිටිය යුතුය.",
        "activeusers-intro": "මෙය පසුගිය $1 {{PLURAL:$1|දිනය|දින}}තුළ යම් ක්‍රියාකාරකමක් කළ පරිශීලකයන්ගේ ලැයිස්තුවකි.",
        "activeusers-count": "{{PLURAL:$1|එක් පියවරක්|පියවර $1 ක්}} අවසන් {{PLURAL:$3|දිනය|දින $3}} තුළ",
        "activeusers-from": "මෙයින් ඇරඹෙන පරිශීලකයන් පෙන්වන්න:",
-       "activeusers-hidebots": " bots සඟවන්න",
-       "activeusers-hidesysops": "පරිපාලකයින් සඟවන්න",
        "activeusers-noresult": "කිසිදු පරිශීලකයෙකු හමුනොවිණි.",
        "activeusers-submit": "ක්‍රියාකාරී පරිශීලකයන් පෙන්වන්න",
        "listgrouprights": "පරිශීලක කාණ්ඩ හිමිකම්",
        "htmlform-cloner-create": "තව එක් කරන්න",
        "htmlform-cloner-delete": "ඉවත් කරන්න",
        "htmlform-cloner-required": "අවම වශයෙන් එක් වටිනාකම අවශ්ය වේ.",
-       "sqlite-has-fts": "$1 සම්පූර්ණ-පෙළ සෙවුම් සහය සමග",
-       "sqlite-no-fts": "$1 සම්පූර්ණ-පෙළ සෙවුම් සහය රහිතව",
        "logentry-delete-delete": "$1 විසින් $3 පිටුව {{GENDER:$2|මකා දමන ලදී}}",
        "logentry-delete-restore": "$1 {{GENDER:$2|නැවත පිහිටුවන ලදී}} පිටු $3",
        "logentry-delete-event-legacy": "$1 විසින් $3 හී ලඝු සිදුවීම් වල දෘශ්‍යතාවය වෙනස් කරන ලදී",
index 86ecc66..8e8c7fb 100644 (file)
        "passwordreset-emaildisabled": "E-mailové funkcie boli na tejto wiki vypnuté.",
        "passwordreset-username": "Používateľské meno:",
        "passwordreset-domain": "Doména:",
-       "passwordreset-capture": "Zobraziť výsledný e-mail?",
-       "passwordreset-capture-help": "Ak označíte toto políčko, bude e-mail (s dočasným heslom) okrem zaslania používateľovi zobrazený aj vám.",
        "passwordreset-email": "Emailová adresa:",
        "passwordreset-emailtitle": "Podrobnosti o účte na {{GRAMMAR:lokál|{{SITENAME}}}}",
        "passwordreset-emailtext-ip": "Niekto (pravdepodobne vy z IP adresy $1) požiadal o obnovenie vášho hesla na {{GRAMMAR:genitív|{{SITENAME}}}} ($4). {{PLURAL:$3|Nasledujúci používateľský účet je spojený|Nasledujúce používateľské účty sú spojené}}\ns touto emailovou adresou:\n\n$2\n\n{{PLURAL:$3|Platnosť tohto dočasného hesla vyprší|Platnosť týchto dočasných hesiel vyprší}} o {{PLURAL:$5|jeden deň|$5 dni|$5 dní}}.\nMali by ste sa prihlásiť teraz a zvoliť nové heslo. Ak túto žiadosť podal niekto iný alebo\nak ste si spomenuli svoje pôvodné heslo a už ho chcete zmeniť, môžete túto správu\nignorovať a ďalej používať vaše staré heslo.",
        "passwordreset-emailelement": "Používateľské meno: \n$1\n\nDočasné heslo:\n$2",
        "passwordreset-emailsentemail": "Pokiaľ je toto e-mailová adresa zaregistrovaná k vášmu účtu, bude na ňu zaslaný e-mail pre získanie nového hesla.",
        "passwordreset-emailsentusername": "Pokiaľ je príslušná mailová adresa zaregistrovaná, bude na ňu zaslaný e-mail s novým heslom.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Email|Emaily}} na obnovenie hesla {{PLURAL:$1|bol odoslaný|boli odoslané}}. {{PLURAL:$1|Používateľské meno a heslo|Zoznam používateľských mien a hesiel}} je uvedený nižšie.",
        "changeemail": "Zmeniť alebo odstrániť e-mailovú adresu",
        "changeemail-header": "Vyplňte tento formulár, ak chcete zmeniť svoju emailovú adresu. Ak chcete odstrániť priradenie akejkoľvek emailovej adresy k vášmu účtu, nechajte pri odosielaní formulára emailovú adresu nevyplnenú",
        "changeemail-no-info": "Na prístup k tejto stránke musíte byť prihlásený.",
        "userrights-reason": "Dôvod:",
        "userrights-no-interwiki": "Nemáte oprávnenie upravovať práva používateľov na iných wiki.",
        "userrights-nodatabase": "Databáza $1 neexistuje alebo nie je lokálna.",
-       "userrights-nologin": "Aby ste mohli prideľovať používateľom oprávnenia, musíte sa [[Special:UserLogin|prihlásiť]] s účtom správcu.",
-       "userrights-notallowed": "Nemáte oprávnenie prideľovať alebo odoberať používateľom oprávnenia.",
        "userrights-changeable-col": "Skupiny, ktoré môžete zmeniť",
        "userrights-unchangeable-col": "Skupiny, ktoré nemôžete zmeniť",
        "userrights-conflict": "Konflikt zmien práv používateľov! Prosím, skontrolujte ho a potvrďte svoje zmeny.",
-       "userrights-removed-self": "Úspešne ste odstránili svoje vlastné práva. Z toho dôvodu už nebudete mať prístup k tejto stránke.",
        "group": "Skupina:",
        "group-user": "Používatelia",
        "group-autoconfirmed": "zaregistrovaní používatelia",
        "right-siteadmin": "Zamykať a odomykať databázu",
        "right-override-export-depth": "Exportovať stránky vrátane okdazovaných stránok do hĺbky 5 odkazov",
        "right-sendemail": "Posielať e-mail ostatným používateľom",
-       "right-passwordreset": "Prezeranie e-mailov pre znovunastavovanie hesla",
        "right-managechangetags": "Vytvárenie a (de)aktivácia [[Special:Tags|značiek]]",
        "right-applychangetags": "Pridávanie [[Special:Tags|značiek]] k vlastným úpravám",
        "right-changetags": "Pridávanie ľubovoľných [[Special:Tags|značiek]] na jednotlivé revízie a záznamy a ich odoberanie",
        "booksources-search": "Hľadať",
        "booksources-text": "Nižšie je zoznam odkazov na iné stránky, ktoré predávajú nové a použité knihy a tiež môžu obsahovať ďalšie informácie o knihách, ktoré hľadáte:",
        "booksources-invalid-isbn": "Zdá sa, že dané ISBN nie je platné. Skontrolujte, či ste neurobili chybu pri kopírovaní z pôvodného zdroja.",
-       "magiclink-tracking-rfc": "Stránky s RFC odkazmi",
-       "magiclink-tracking-pmid": "Stránky s PMID odkazmi",
-       "magiclink-tracking-isbn": "Stránky s ISBN odkazmi",
+       "magiclink-tracking-rfc": "Stránky s magickými odkazmi RFC",
+       "magiclink-tracking-pmid": "Stránky s magickými odkazmi PMID",
+       "magiclink-tracking-isbn": "Stránky s magickými odkazmi ISBN",
        "specialloguserlabel": "Pôvodca:",
        "speciallogtitlelabel": "Cieľ (názov alebo {{ns:user}}:Používateľské meno):",
        "log": "Záznamy",
index 63ad3c7..eed382e 100644 (file)
        "views": "Pogled",
        "toolbox": "Orodja",
        "tool-link-userrights": "Spremeni {{GENDER:$1|uporabnikove|uporabničine}} skupine",
+       "tool-link-userrights-readonly": "Ogled {{GENDER:$1|uporabnikovih|uporabničinih}} skupin",
        "tool-link-emailuser": "Pošlji e-pošto {{GENDER:$1|uporabniku|uporabnici}}",
        "userpage": "Prikaži uporabnikovo stran",
        "projectpage": "Prikaži projektno stran",
        "passwordreset-emaildisabled": "Na tem wikiju so možnosti e-pošte onemogočene.",
        "passwordreset-username": "Uporabniško ime:",
        "passwordreset-domain": "Domena:",
-       "passwordreset-capture": "Ogled nastale e-pošte?",
-       "passwordreset-capture-help": "Če potrdite to polje, vam bodo e-pošte (z začasnim geslom) pokazane in poslane uporabniku.",
        "passwordreset-email": "E-poštni naslov:",
        "passwordreset-emailtitle": "Podrobnosti računa na {{SITENAME}}",
        "passwordreset-emailtext-ip": "Nekdo (verjetno vi, z IP-naslova $1) je zahteval ponastavitev vašega\ngesla na {{SITENAME}} ($4). S tem e-poštnim naslovom\n{{PLURAL:$3|je povezan naslednji uporabniški račun|sta povezana naslednja uporabniška računa|so povezani naslednji uporabniški računi}}:\n\n$2\n\n{{PLURAL:$3|Začasno geslo bo poteklo|Začasni gesli bosta potekli|Začasna gesla bodo potekla}} v {{PLURAL:$5|enem dnevu|$5 dneh}}.\nPrijavite se in izberite novo geslo. Če je zahtevo podal\nnekdo drug ali pa ste se spomnili svojega prvotnega gesla in ga več\nne želite spremeniti, lahko to sporočilo prezrete in nadaljujete z uporabo\nsvojega starega gesla.",
        "passwordreset-emailelement": "Uporabniško ime: \n$1\n\nZačasno geslo: \n$2",
        "passwordreset-emailsentemail": "Če je e-poštni naslov povezan z vašim računom, vam bomo poslali e-pošto za postavitev gesla.",
        "passwordreset-emailsentusername": "Če obstaja e-poštni naslov, povezan s tem uporabniškim imenom, vam bomo poslali e-pošto za postavitev gesla.",
-       "passwordreset-emailsent-capture2": "Poslali smo {{PLURAL:$1|e-pošto|e-pošti|e-pošte}} za ponastavitev gesla. {{PLURAL:$1|Uporabniško ime in geslo sta navedena tukaj.|Seznam uporabniških imen in gesel je naveden tukaj.}}",
-       "passwordreset-emailerror-capture2": "Pošiljanje e-pošte {{GENDER:$2|uporabniku|uporabnici}} je spodletelo: $1 {{PLURAL:$3|Uporabniško ime in geslo sta navedena tukaj.|Seznam uporabniških imen in gesel je naveden tukaj.}}",
        "passwordreset-nocaller": "Podati morate klicatelja",
        "passwordreset-nosuchcaller": "Klicatelj ne obstaja: $1",
        "passwordreset-ignored": "Ponastavitve gesla nismo izvedli. Morda ni nastavljen noben ponudnik?",
-       "passwordreset-invalideamil": "Neveljavni e-poštni naslov",
+       "passwordreset-invalidemail": "Neveljavni e-poštni naslov",
        "passwordreset-nodata": "Navedli niste ne uporabniškega imena ne e-poštnega naslova",
        "changeemail": "Sprememba ali odstranitev e-poštnega naslova",
        "changeemail-header": "Izpolnite obrazec za spremembo vašega e-poštnega naslova. Če želite s svojega računa odstraniti povezavo s katerim koli e-poštnim naslovom, pustite polje za nov e-poštni naslov med potrjevanje obrazca prazno.",
        "search-external": "Zunanji iskalnik",
        "searchdisabled": "Iskanje po {{GRAMMAR:dajalnik|{{SITENAME}}}} je onemogoočeno.\nMedtem lahko iščete preko Googla.\nUpoštevajte, da so njihovi podatki vsebine {{GRAMMAR:rodilnik|{{SITENAME}}}} morda zastareli.",
        "search-error": "Med iskanjem je prišlo do napake: $1",
+       "search-warning": "Med iskanjem je prišlo do napake: $1",
        "preferences": "Nastavitve",
        "mypreferences": "Nastavitve",
        "prefs-edits": "Število urejanj:",
        "prefs-help-recentchangescount": "Vključuje zadnje spremembe, zgodovine strani in dnevniške zapise.",
        "prefs-help-watchlist-token2": "To je skrivni ključ do spletnega vira vašega spiska nadzorov. Kdor ve zanj, lahko bere vaš spisek nadzorov, zato ključa ne delite. [[Special:ResetTokens|Kliknite tukaj, če ga želite ponastaviti]].",
        "savedprefs": "Spremembe smo uspešno shranili.",
-       "savedrights": "Uporabniške pravice {{GENDER:$1|$1}} smo shranili.",
+       "savedrights": "Uporabniške skupine {{GENDER:$1|$1}} smo shranili.",
        "timezonelegend": "Časovni pas",
        "localtime": "Krajevni čas:",
        "timezoneuseserverdefault": "Uporabi privzeti wiki čas ($1)",
        "prefswarning-warning": "V svojih nastavitvah ste naredili spremembe, ki jih še niste shranili. Če odidete s strani brez da bi kliknili »$1«, vaših nastavitev ne bomo posodobili.",
        "prefs-tabs-navigation-hint": "Namig: Za krmarjenje med zavihki na seznamu zavihkov lahko uporabite levo in desno smerno tipko.",
        "userrights": "Upravljanje s pravicami uporabnikov",
-       "userrights-lookup-user": "Upravljanje z uporabniškimi skupinami",
+       "userrights-lookup-user": "Izberite uporabnika",
        "userrights-user-editname": "Vpišite uporabniško ime:",
-       "editusergroup": "Uredi {{GENDER:$1|uporabnikove|uporabničine}} skupine",
+       "editusergroup": "Naloži uporabniške skupine",
        "editinguser": "Urejanje pravic {{GENDER:$1|uporabnika|uporabnice}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Ogledovanje uporabniških pravic {{GENDER:$1|uporabnika|uporabnice}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Urejanje uporabniških skupin",
+       "userrights-viewusergroup": "Ogled skupin uporabnikov",
        "saveusergroups": "Shrani {{GENDER:$1|uporabnikove|uporabničine}} skupine",
        "userrights-groupsmember": "Član skupine:",
        "userrights-groupsmember-auto": "Posreden član:",
        "userrights-reason": "Razlog:",
        "userrights-no-interwiki": "Za urejanje pravic uporabnikov na drugih wikijih nimate dovoljenja.",
        "userrights-nodatabase": "Podatkovna baza $1 ne obstaja ali ni lokalna.",
-       "userrights-nologin": "Za dodeljevanje uporabniških pravic se morate [[Special:UserLogin|prijaviti]] s skrbniškim računom.",
-       "userrights-notallowed": "Za dodajanje ali odstranjevanje uporabniških pravic nimate dovoljenja.",
        "userrights-changeable-col": "Skupine, ki jih lahko spremenite",
        "userrights-unchangeable-col": "Skupine, ki jih ne morete spremeniti",
        "userrights-conflict": "Spor sprememb uporabniških pravic! Prosimo, da pregledate in potrdite svoje spremembe.",
-       "userrights-removed-self": "Odstranili ste svoje pravice. Tako sedaj ne morete več dostopati do te strani.",
        "group": "Skupina:",
        "group-user": "Uporabniki",
        "group-autoconfirmed": "Samodejno potrjeni uporabniki",
        "right-siteadmin": "Zaklepanje in odklepanje baze podatkov",
        "right-override-export-depth": "Izvoz strani, vključno s povezaimi straneh do globine 5",
        "right-sendemail": "Pošiljanje e-pošte drugim uporabnikom",
-       "right-passwordreset": "Ogled e-pošt ponastavitve gesel",
        "right-managechangetags": "Ustvarjanje in (dez)aktivacijo [[Special:Tags|oznak]]",
        "right-applychangetags": "Uveljavitev [[Special:Tags|oznak]] skupaj s spremembami",
        "right-changetags": "Dodajanje in odstranjevanje poljubnih [[Special:Tags|oznak]] na posameznih redakcijah in dnevniških vnosih",
        "action-upload_by_url": "nalaganje te datoteke iz URL-naslova",
        "action-writeapi": "uporabo API-ja za pisanje",
        "action-delete": "brisanje te strani",
-       "action-deleterevision": "brisanje te redakcije",
-       "action-deletedhistory": "pregled zgodovine izbrisanih redakcij te strani",
+       "action-deleterevision": "brisanje redakcij",
+       "action-deletelogentry": "brisanje dnevniških vnosov",
+       "action-deletedhistory": "ogled zgodovine izbrisanih redakcij strani",
+       "action-deletedtext": "ogled besedila izbrisanih redakcij",
        "action-browsearchive": "iskanje izbrisanih strani",
-       "action-undelete": "obnavljanje te strani",
-       "action-suppressrevision": "vpogled in obnavljanje te skrite redakcije",
+       "action-undelete": "obnavljanje strani",
+       "action-suppressrevision": "vpogled in obnavljanje skritih redakcij",
        "action-suppressionlog": "vpogled tega zasebnega dnevnika",
        "action-block": "blokiranje urejanja s tega uporabniškega računa",
        "action-protect": "spremembo stopnje zaščite te strani",
        "action-userrights-interwiki": "upravljanje uporabniških pravic za uporabnike drugih wikijev",
        "action-siteadmin": "zaklenitev ali odklepanje podatkovne baze",
        "action-sendemail": "pošiljanje e-sporočil",
+       "action-editmyoptions": "urejanje svojih nastavitev",
        "action-editmywatchlist": "urejanje svojega spiska nadzorov",
        "action-viewmywatchlist": "ogleda svojega spiska nadzorov",
        "action-viewmyprivateinfo": "ogled svojih zasebnih informacij",
        "apisandbox-continue": "Nadaljuj",
        "apisandbox-continue-clear": "Počisti",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} bo [https://www.mediawiki.org/wiki/API:Query#Continuing_queries nadaljevalo] zadnjo zahtevo; {{int:apisandbox-continue-clear}} bo počistilo parametre, povezane z nadaljevanjem.",
+       "apisandbox-param-limit": "Vnesite <kbd>max</kbd>, da uporabite največjo omejitev.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Vsi imenski prostori)",
+       "apisandbox-multivalue-all-values": "$1 (Vse vrednosti)",
        "booksources": "Viri knjig",
        "booksources-search-legend": "Išči knjižne vire",
        "booksources-search": "Išči",
        "activeusers-count": "$1 {{PLURAL:$1|dejanje|dejanji|dejanja|dejanj}} v {{PLURAL:$3|preteklem dnevu|preteklih $3 dneh}}",
        "activeusers-from": "Prikaži uporabnike začenši z:",
        "activeusers-groups": "Prikaži uporabnike, ki pripadajo skupinam:",
+       "activeusers-excludegroups": "Izključi uporabnike, ki pripadajo skupinam:",
        "activeusers-noresult": "Noben uporabnik ni bil najden.",
        "activeusers-submit": "Prikaži dejavne uporabnike",
        "listgrouprights": "Pravice uporabniških skupin",
        "emailccsubject": "Kopija tvojega sporočila iz $1: $2",
        "emailsent": "E-pismo je poslano!",
        "emailsenttext": "E-pismo je poslano.",
-       "emailuserfooter": "To e-poštno sporočilo je {{GENDER:$1|poslal|poslala|poslal(-a)}} $1 uporabniku {{GENDER:$2|$2}} s funkcijo »{{int:emailuser}}« na {{GRAMMAR:dative|{{SITENAME}}}}.",
+       "emailuserfooter": "To e-poštno sporočilo je {{GENDER:$1|poslal|poslala|poslal(-a)}} $1 uporabniku {{GENDER:$2|$2}} s funkcijo »{{int:emailuser}}« na {{GRAMMAR:dative|{{SITENAME}}}}. {{GENDER:$2|Vaše}} e-poštno sporočilo bo poslano neposredno {{GENDER:$1|izvornemu pošiljatelju|izvorni pošiljateljici}}, kar {{GENDER:$1|mu|ji}} bo razkrilo {{GENDER:$2|vaš}} e-poštni naslov.",
        "usermessage-summary": "Pusti sistemsko sporočilo.",
        "usermessage-editor": "Sistemski sporočevalec",
        "watchlist": "Spisek nadzorov",
        "javascripttest": "Preizkušanje JavaScripta",
        "javascripttest-pagetext-unknownaction": "Neznano dejanje »$1«.",
        "javascripttest-qunit-intro": "Oglejte si [$1 dokumentacijo o preizkušanju] na mediawiki.org.",
-       "tooltip-pt-userpage": "{{GENDER:|Vaša}} uporabniška stran",
+       "tooltip-pt-userpage": "{{GENDER:|Tvoja}} uporabniška stran",
        "tooltip-pt-anonuserpage": "Uporabniška stran IP-naslova, ki ga uporabljate",
-       "tooltip-pt-mytalk": "{{GENDER:|Vaša}} pogovorna stran",
+       "tooltip-pt-mytalk": "{{GENDER:|Tvoja}} pogovorna stran",
        "tooltip-pt-anontalk": "Pogovor o urejanjih s tega IP-naslova",
-       "tooltip-pt-preferences": "{{GENDER:|Vaše}} nastavitve",
-       "tooltip-pt-watchlist": "Seznam strani, katerih spremembe spremljate",
-       "tooltip-pt-mycontris": "Seznam {{GENDER:|vaših}} prispevkov",
+       "tooltip-pt-preferences": "{{GENDER:|Tvoje}} nastavitve",
+       "tooltip-pt-watchlist": "Seznam strani, katerih spremembe spremljaš",
+       "tooltip-pt-mycontris": "Seznam {{GENDER:|tvojih}} prispevkov",
        "tooltip-pt-anoncontribs": "Seznam urejanj s tega IP-naslova",
        "tooltip-pt-login": "Prijava ni obvezna, vendar je zaželena",
-       "tooltip-pt-logout": "Odjavite se",
+       "tooltip-pt-logout": "Odjavi se",
        "tooltip-pt-createaccount": "Predlagamo vam, da ustvarite račun in se prijavite, vendar pa to ni obvezno.",
        "tooltip-ca-talk": "Pogovor o strani",
        "tooltip-ca-edit": "Uredi stran",
        "tags-deactivate": "dezaktiviraj",
        "tags-hitcount": "$1 {{PLURAL:$1|sprememba|spremembi|spremembe|sprememb|sprememb}}",
        "tags-manage-no-permission": "Nimate dovoljenja za upravljanje z oznakami sprememb.",
-       "tags-manage-blocked": "Med blokado ne morete upravljati oznak sprememb.",
+       "tags-manage-blocked": "Med blokado {{GENDER:$1|ne morete}} upravljati oznak sprememb.",
        "tags-create-heading": "Ustvari novo oznako",
        "tags-create-explanation": "Privzeto bodo novo ustvarjene oznake na voljo uporabnikom in botom.",
        "tags-create-tag-name": "Ime oznake:",
        "tags-deactivate-not-allowed": "Oznake »$1« ni možno dezaktivirati.",
        "tags-deactivate-submit": "Dezaktiviraj",
        "tags-apply-no-permission": "Nimate dovoljenja za uveljavljanje sprememb oznak skupaj z vašimi spremembami.",
-       "tags-apply-blocked": "Med blokado ne morete uveljaviti oznak sprememb skupaj s svojimi spremembami.",
+       "tags-apply-blocked": "Med blokado {{GENDER:$1|ne morete}} uveljaviti oznak sprememb skupaj s svojimi spremembami.",
        "tags-apply-not-allowed-one": "Oznake »$1« ni mogoče uveljaviti ročno.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Naslednje oznake|Naslednji oznaki|Naslednjih oznak}} ni mogoče ročno uveljaviti: $1",
        "tags-update-no-permission": "Nimate dovoljenja za dodajanje ali odstranjevanje oznak na posameznih redakcijah ali dnevniških vnosih.",
-       "tags-update-blocked": "Med blokado ne morete dodati ali odstraniti oznak sprememb.",
+       "tags-update-blocked": "Med blokado {{GENDER:$1|ne morete}} dodati ali odstraniti oznak sprememb.",
        "tags-update-add-not-allowed-one": "Oznake »$1« ni mogoče dodati ročno.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Naslednje oznake|Naslednji oznaki|Naslednjih oznak}} ni mogoče dodati ročno: $1",
        "tags-update-remove-not-allowed-one": "Oznake »$1« ni mogoče odstraniti.",
        "htmlform-float-invalid": "Vrednost, ki ste jo vnesli, ni število.",
        "htmlform-int-toolow": "Vrednost, ki ste jo vnesli, je manjša od najmanjše dovoljene vrednosti $1",
        "htmlform-int-toohigh": "Vrednost, ki ste jo vnesli, je večja od največje dovoljene vrednosti $1",
-       "htmlform-required": "Ta vrednost je zahtevana",
+       "htmlform-required": "To je zahtevana vrednost.",
        "htmlform-submit": "Pošlji",
        "htmlform-reset": "Razveljavi spremembe",
        "htmlform-selectorother-other": "Drugo",
        "htmlform-user-not-exists": "<strong>$1</strong> ne obstaja.",
        "htmlform-user-not-valid": "<strong>$1</strong> ni veljavno uporabniško ime.",
        "logentry-delete-delete": "$1 je {{GENDER:$2|izbrisal|izbrisala|izbrisal(-a)}} stran $3",
+       "logentry-delete-delete_redir": "$1 je {{GENDER:$2|izbrisal|izbrisala|izbrisal(-a)}} preusmeritev $3 s prepisom",
        "logentry-delete-restore": "$1 je {{GENDER:$2|obnovil|obnovila|obnovil(-a)}} stran $3",
        "logentry-delete-event": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} vidljivost $5 {{PLURAL:$5|dnevniškega dogodka|dnevniških dogodkov}} na $3: $4",
        "logentry-delete-revision": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} vidljivost $5 {{PLURAL:$5|redakcije|redakcij}} na strani $3: $4",
        "mw-widgets-dateinput-no-date": "Datum ni izbran",
        "mw-widgets-dateinput-placeholder-day": "LLLL-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "LLLL-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Iskanje predstavnosti",
+       "mw-widgets-mediasearch-noresults": "Ni zadetkov.",
        "mw-widgets-titleinput-description-new-page": "stran še ne obstaja",
        "mw-widgets-titleinput-description-redirect": "preusmeritev na $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Dodaj kategorijo ...",
        "sessionmanager-tie": "Ne morem združiti več vrst overitvenih zahtev: $1.",
        "sessionprovider-generic": "sej $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sej, ki temeljijo na piškotkih",
        "log-action-filter-contentmodel-change": "Sprememba Modelastrani",
        "log-action-filter-contentmodel-new": "Ustvarjanje strani z nestandardnim Modelomstrani",
        "log-action-filter-delete-delete": "Izbris strani",
+       "log-action-filter-delete-delete_redir": "Prepis preusmeritve",
        "log-action-filter-delete-restore": "Obnovitev strani",
        "log-action-filter-delete-event": "Dnevnik brisanja",
        "log-action-filter-delete-revision": "Izbris redakcije",
        "restrictionsfield-badip": "Neveljaven IP-naslov ali obseg: $1",
        "restrictionsfield-label": "Dovoljeni IP-obsegi:",
        "restrictionsfield-help": "En IP-naslov ali CIDR-območje na vrstico. Da omogočite vse, uporabite<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Napaka: $1",
-       "edit-error-long": "Napake:\n\n$1"
+       "pageid": "ID strani $1"
 }
index cd2f351..5e04c16 100644 (file)
        "yourname": "Benutzernoame:",
        "yourpassword": "Passwort:",
        "yourpasswordagain": "Passwort wiederhola:",
-       "remembermypassword": "Mit diesem Browser dauerhaft angemeldet bleiben (maximal $1 {{PLURAL:$1|Tag|Tage}})",
        "yourdomainname": "Denne Domain:",
        "externaldberror": "Entweder is leit a Fahler bei der externa Authentifizierung vur, oder du darfst dei externes Benutzerkonto ne aktualisiera.",
        "login": "Oanmelda",
        "undo-failure": "De Änderung konnte ne rickgängig gemacht waan, do dar betroffene Obschnitt zwischazeitlich verändert wurde.",
        "undo-norev": "De Beoarbeetung konnte ne rickgängig gemacht waan, do se ne vorhanden ies oder geläscht wurde.",
        "undo-summary": "Änderung $1 vu [[Special:Contributions/$2|$2]] ([[User talk:$2|Dischkur]]) wurde rickgängig gemacht.",
-       "cantcreateaccounttitle": "Nutzerkonto koan ne erstallt waan",
        "cantcreateaccount-text": "De Erstellung annes Nutzerkontos vu dar IP-Atresse '''($1)''' aus wurde durch [[User:$3|$3]] gesperrt.\n\nGrund dar Sperre: ''$2''",
        "viewpagelogs": "Logbicher fier diese Seite oazeega",
        "nohistory": "'S gitt kenne Versionsgeschichte fier diese Seite.",
index 2697621..3f3c720 100644 (file)
        "passwordreset-emaildisabled": "Karakteristikat e  Email janë të paaftë në këtë wiki.",
        "passwordreset-username": "Nofka:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "Dëshiron të shikosh e-mail-in që rezulton?",
-       "passwordreset-capture-help": "Nëse shënoni këtë kuti, e-mail-i (dhe fjalekalimi i përkohshëm) që do t'i dërgohen përdoruesit, do të të tregohen edhe ty.",
        "passwordreset-email": "Posta elektronike",
        "passwordreset-emailtitle": "Detajet e llogarisë në {{SITENAME}}",
        "passwordreset-emailtext-ip": "Dikush (ndoshta ju, nga IP adresa $1) kërkoi një kujtesë për \ndetajet e llogarisë suaj {{SITENAME}} ($4).Përdoruesi në vijim {{PLURAL:$3|llogari është|llogaritë janë}} të lidhur me këtë postë elektronike:\n\n$2\n\n{{PLURAL:$3|Ky fjalëkalim i përkohshëm|Këto fjalëkalime të përkohshme}} do të përfundojë për {{PLURAL:$5|një ditë|$5 ditë}}.\n\nJu duhet të kyçeni dhe të zgjidhni një fjalëkalim të ri tani. Nëse dikush tjetër e ka bërë këtë kërkesës, ose në qoftë se ju mbani mend fjalëkalimin tuaj origjinal, dhe ju nuk dëshirojni të ndryshoni atë, ju mund të injoroni këtë mesazh dhe do të vazhdoni përdorimin e fjalëkalimit tuaj të vjetër.",
        "blockedtitle": "Përdoruesi është bllokuar",
        "blockedtext": "'''Llogaria juaj ose adresa e IP është bllokuar'''\n\nBllokimi u bë nga $1 dhe arsyeja e dhënë ishte '''$2'''.\n\n*Fillimi i bllokimit: $8\n*Skadimi i bllokimit: $6\n*I bllokuari i shënjestruar: $7\n\nMund të kontaktoni $1 ose një nga [[{{MediaWiki:Grouppage-sysop}}|administruesit]] e tjerë për të diskutuar bllokimin.\n\nVini re se nuk mund t'i dërgoni email përdoruesit nëse nuk keni një adresë të saktë të dhënë tek [[Special:Preferences|parapëlqimet e përdoruesit]] ose nëse kjo është një nga mundësitë që ju është bllokuar.\n\nAdresa e IP-së që keni është $3 dhe numri i identifikimit të bllokimit është #$5. Përfshini këto dy të dhëna në çdo ankesë.",
        "autoblockedtext": "IP adresa juaj është bllokuar automatikisht sepse ishte përdorur nga një përdorues tjetër i cili ishte bllokuar nga $1.\nArsyeja e dhënë për këtë është:\n\n:''$2''\n\n* Fillimi i bllokimit: $8\n* Kalimi i kohës së bllokimit: $6\n* Zgjatja e bllokimit: $7\n\nJu mund të kontaktoni $1 ose një tjetër [[{{MediaWiki:Grouppage-sysop}}|administrues]] për ta diskutuar bllokimin.\n\nVini re : që nuk mund ta përdorni mundësinë \"dërgo porosi elektronike\" përveç nëse keni një postë elektronike të vlefshme të regjistruar në [[Special:Preferences|preferencat tuaja]] dhe nuk jeni bllokuar nga përdorimi i saj.\n\nIP adresa juaj e tanishme është $3 dhe ID e bllokimit është #$5.\nJu lutemi përfshini këto detaje në të gjitha kërkesat që i bëni.",
-       "blockednoreason": "nuk është dhënë ësnje arsye",
+       "blockednoreason": "nuk është dhënë asnjë arsye",
        "whitelistedittext": "Ju duhet të $1 për të redaktuar faqet.",
        "confirmedittext": "Ju duhet së pari ta vërtetoni e-mail adresen para se të redaktoni. Ju lutem plotësoni dhe vërtetoni e-mailin tuaj  te [[Special:Preferences|parapëlqimet]] e juaja.",
        "nosuchsectiontitle": "Paragrafi nuk mund të gjendet",
        "userrights-reason": "Arsyeja:",
        "userrights-no-interwiki": "Nuk keni leje për të ndryshuar privilegjet e përdoruesve në wiki të tjera.",
        "userrights-nodatabase": "Regjistri $1 nuk ekziston ose nuk është vendor.",
-       "userrights-nologin": "Duhet të [[Special:UserLogin|hyni brenda]] me një llogari administrative për të ndryshuar privilegjet e përdoruesve.",
-       "userrights-notallowed": "Ju nuk keni leje për të shtuar ose hequr privilegjet e përdoruesve.",
        "userrights-changeable-col": "Grupe që mund të ndryshoni",
        "userrights-unchangeable-col": "Grupe që s'mund të ndryshoni",
        "userrights-conflict": "Konflikt në ndryshimin e të drejtave të përdoruesit! Të lutem të rishiko dhe konfirmo ndryshimet e tua.",
        "right-siteadmin": "Mbyll ose hap bazën e të dhënave",
        "right-override-export-depth": "Eksoprto faqet duke përfshirë e lidhura deri në një thellësi prej 5",
        "right-sendemail": "Dërgo e-mail tek përdoruesit e tjerë",
-       "right-passwordreset": "Shiko e-mail-et e rivendosjes së fjalëkalimit",
        "right-managechangetags": "Krijoni dhe fshini [[Special:Tags|tags]] nga baza e të dhënave",
        "right-applychangetags": "Aplikoni [[Special:Tags|tags]] së bashku me ndryshimet",
        "right-changetags": "Shtoni dhe të largoni në mënyrë arbitrare [[Special:Tags|tags]] në rishikimet individuale dhe regjistrimet e historikut",
        "activeusers-intro": "Kjo është një listë e përdoruesve që kanë qenë aktivë për $1 {{PLURAL:$1|ditë|ditë}}.",
        "activeusers-count": "$1 {{PLURAL:$1|redaktim|redaktime}} në {{PLURAL:$3|ditën|$3 ditët}} e fundit",
        "activeusers-from": "Trego përdoruesit duke filluar prej te:",
-       "activeusers-hidebots": "Fshih robotët",
-       "activeusers-hidesysops": "Fshih administratorët",
        "activeusers-noresult": "Asnjë përdorues nuk u gjet.",
        "listgrouprights": "Grupime përdoruesish me privilegje",
        "listgrouprights-summary": "Më poshtë jepet grupimi i përdoruesve sipas privilegjeve që ju janë dhënë në këtë wiki. Më shumë informacion rreth privilegjeve në veçanti mund të gjendet [[{{MediaWiki:Listgrouprights-helppage}}|këtu]].",
index 2cd4d4c..77dce6f 100644 (file)
        "password-change-forbidden": "Не можете да промените лозинку на овом викију.",
        "externaldberror": "Дошло је до грешке при препознавању базе података или немате овлашћења да ажурирате свој спољни налог.",
        "login": "Пријави ме",
+       "login-security": "Ваерификација вашег индентитета",
        "nav-login-createaccount": "Пријава/регистрација",
        "userlogin": "Пријава/регистрација",
        "userloginnocreate": "Пријава",
        "userlogin-resetpassword-link": "Заборавили сте лозинку?",
        "userlogin-helplink2": "Помоћ при пријављивању",
        "userlogin-loggedin": "Већ сте пријављени као {{GENDER:$1|$1}}.\nКористите доњи образац да бисте се пријавили као други корисник.",
+       "userlogin-reauth": "Морате се поново пријавити да би верификовали да сте {{GENDER:$1|$1}}.",
        "userlogin-createanother": "Отвори још један налог",
        "createacct-emailrequired": "Имејл адреса",
        "createacct-emailoptional": "Имејл адреса (опционо)",
        "passwordreset-emaildisabled": "Имејл је онемогућен на овом викију.",
        "passwordreset-username": "Корисничко име:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Погледати крајњи имејл?",
-       "passwordreset-capture-help": "Ако означите ову кућицу, имејл (с привременом лозинком) ће бити приказан и послат кориснику.",
        "passwordreset-email": "Имејл адреса:",
        "passwordreset-emailtitle": "Детаљи налога на викију {{SITENAME}}",
        "passwordreset-emailtext-ip": "Неко (вероватно Ви, са ИП адресе $1) је затражио нову лозинку на викију {{SITENAME}} ($4).\nСледећи {{PLURAL:$3|кориснички налог је повезан|кориснички налози су повезани}} с овом имејл адресом:\n\n$2\n\n{{PLURAL:$3|Привремена лозинка истиче|Привремене лозинке истичу}} за {{PLURAL:$5|један дан|$5 дана}}.\nПријавите се и изаберите нову лозинку. Ако је неко други захтевао ову радњу или сте се сетили лозинке и не желите да је мењате, занемарите ову поруку и наставите користити стару лозинку.",
        "userrights-reason": "Разлог:",
        "userrights-no-interwiki": "Немате овлашћења да мењате корисничка права на другим викијима.",
        "userrights-nodatabase": "База података $1 не постоји или није локална.",
-       "userrights-nologin": "Морате се [[Special:UserLogin|пријавити]] с администраторским налогом да бисте мењали корисничка права.",
-       "userrights-notallowed": "Немате овлашћења да додајете или уклањате корисничка права.",
        "userrights-changeable-col": "Групе које можете да промените",
        "userrights-unchangeable-col": "Групе које не можете да промените",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Сукоб промена корисничких права! Молимо проверите ваше измене.",
-       "userrights-removed-self": "Скинули сте себи права. Због тога Вам није дозвољен приступ овој страници.",
        "group": "Група:",
        "group-user": "Корисници",
        "group-autoconfirmed": "Аутоматски потврђени корисници",
        "right-siteadmin": "закључавање и откључавање базе података",
        "right-override-export-depth": "извоз страница укључујући и повазене странице до дубине од пет веза",
        "right-sendemail": "Пошаљи имејл другим корисницима",
-       "right-passwordreset": "прегледање порука за обнављање лозинке",
        "right-managechangetags": "прављење и (де)активирање [[Special:Tags|ознака]]",
        "right-applychangetags": "примењивање [[Special:Tags|ознака]] на нечије измене",
        "right-changetags": "додавање и уклањање разних [[Special:Tags|ознака]] на појединачним изменама и уносима у дневницима",
+       "right-deletechangetags": "брисање [[Special:Tags|ознака]] из базе података",
        "grant-group-page-interaction": "Уређивање страница",
        "grant-group-file-interaction": "Уређивање датотека",
        "grant-group-watchlist-interaction": "Уређивање вашег списка надгледања",
        "grant-editmywatchlist": "Уређивање вашег списка надгледања",
        "grant-editpage": "Уређивање постојећих страница",
        "grant-editprotected": "Уређивање заштићених страница",
+       "grant-highvolume": "Масовно уређивање",
        "grant-patrol": "Патролирање измена",
        "grant-protect": "Закључавање и откључавање страница",
        "grant-rollback": "Враћање измена",
        "confirmemail_invalidated": "Потврда имејл адресе је отказана",
        "invalidateemail": "Отказивање потврде имејла",
        "notificationemail_body_changed": "Неко, вероватно Ви је променио имејл адресу налога из $2“ у „$3“ са IP адресе $1 на сајту {{SITENAME}}.\n\nАко ово нисте били Ви, одмах обавестите администраторе сајта.",
+       "notificationemail_body_removed": "Неко, вероватно Ви са ИП адресе $1 је уклонио имејл адресу за налог „$2“ на {{SITENAME}}.\n\n\nАко ово нисте били Ви, одмах обавестите администраторе сајта.",
        "scarytranscludedisabled": "[Међувики укључивање шаблона је онемогућено]",
        "scarytranscludefailed": "[Добављање шаблона за $1 није успело]",
        "scarytranscludefailed-httpstatus": "[Не могу да преузмем шаблон $1: HTTP $2]",
        "confirm-watch-top": "Додати ову страницу у списак надгледања?",
        "confirm-unwatch-button": "У реду",
        "confirm-unwatch-top": "Уклонити ову страницу са списка надгледања?",
+       "confirm-rollback-button": "У реду",
        "semicolon-separator": ";&#32;",
        "comma-separator": ",&#32;",
        "colon-separator": ":&#32;",
        "htmlform-user-not-exists": "<strong>$1</strong> не постоји.",
        "htmlform-user-not-valid": "<strong>$1</strong> није исправно корисничко име.",
        "logentry-delete-delete": "$1 је {{GENDER:$2|обрисао|обрисала}} страницу $3",
+       "logentry-delete-delete_redir": "$1 је {{GENDER:$2|обрисао|обрисала}} преусмерење $3 преснимавањем",
        "logentry-delete-restore": "$1 је {{GENDER:$2|вратио|вратила}} страницу $3",
        "logentry-delete-event": "$1 је {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|1=догађаја|$5 догађаја}} у дневнику $3: $4",
        "logentry-delete-revision": "$1 је {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|1=једне измене|$5 измене|$5 измена}} на страници $3: $4",
        "mw-widgets-dateinput-no-date": "Датум није изабран",
        "mw-widgets-dateinput-placeholder-day": "ГГГГ-ММ-ДД",
        "mw-widgets-dateinput-placeholder-month": "ГГГГ-ММ",
+       "mw-widgets-mediasearch-noresults": "Нема резултата.",
        "mw-widgets-titleinput-description-new-page": "страница још увек не постоји",
        "mw-widgets-titleinput-description-redirect": "преусмерава на $1",
        "randomrootpage": "Случајна коренска страница",
        "log-action-filter-block-reblock": "измена блокирања",
        "log-action-filter-block-unblock": "деблокирање",
        "log-action-filter-delete-delete": "брисање странице",
+       "log-action-filter-delete-delete_redir": "преснимавање преусмерења",
        "log-action-filter-delete-restore": "враћање странице",
        "log-action-filter-delete-event": "брисање уноса у дневницима",
        "log-action-filter-delete-revision": "брисање измене",
index 6bdd3b5..3fad564 100644 (file)
        "passwordreset-emaildisabled": "Imejl je onemogućen na ovom vikiju.",
        "passwordreset-username": "Korisničko ime:",
        "passwordreset-domain": "Domen:",
-       "passwordreset-capture": "Pogledati krajnji imejl?",
-       "passwordreset-capture-help": "Ako označite ovo polje, imejl (s privremenom lozinkom) će biti prikazana i poslata korisniku.",
        "passwordreset-email": "Imejl adresa:",
        "passwordreset-emailtitle": "Detalji naloga na vikiju {{SITENAME}}",
        "passwordreset-emailtext-ip": "Neko (verovatno Vi, sa IP adrese $1) je zatražio novu lozinku na vikiju {{SITENAME}} ($4).\nSledeći {{PLURAL:$3|korisnički nalog je povezan|korisnički nalozi su povezani}} s ovom imejl adresom:\n\n$2\n\n{{PLURAL:$3|Privremena lozinka ističe|Privremene lozinke ističu}} za {{PLURAL:$5|jedan dan|$5 dana}}.\nPrijavite se i izaberite novu lozinku. Ako je neko drugi zahtevao ovu radnju ili ste se setili lozinke i ne želite da je menjate, zanemarite ovu poruku i nastavite koristiti staru lozinku.",
        "userrights-reason": "Razlog:",
        "userrights-no-interwiki": "Nemate ovlašćenja da menjate korisnička prava na drugim vikijima.",
        "userrights-nodatabase": "Baza podataka $1 ne postoji ili nije lokalna.",
-       "userrights-nologin": "Morate se [[Special:UserLogin|prijaviti]] s administratorskim nalogom da biste menjali korisnička prava.",
-       "userrights-notallowed": "Nemate ovlašćenja da dodajete ili uklanjate korisnička prava.",
        "userrights-changeable-col": "Grupe koje možete da promenite",
        "userrights-unchangeable-col": "Grupe koje ne možete da promenite",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Sukob promena korisničkih prava! Molimo proverite vaše izmene.",
-       "userrights-removed-self": "Uspešno ste sebi skinuli prava. Zbog toga nije vam dozvoljen pristup ovoj stranici.",
        "group": "Grupa:",
        "group-user": "Korisnici",
        "group-autoconfirmed": "Automatski potvrđeni korisnici",
        "right-siteadmin": "zaključavanje i otključavanje baze podataka",
        "right-override-export-depth": "izvoz stranica uključujući i povazene stranice do dubine od pet veza",
        "right-sendemail": "Pošalji imejl drugim korisnicima",
-       "right-passwordreset": "pregledanje poruka za obnavljanje lozinke",
        "right-managechangetags": "pravljenje i (de)aktiviranje [[Special:Tags|oznaka]]",
        "grant-group-page-interaction": "Uređivanje stranica",
        "grant-group-file-interaction": "Uređivanje datoteka",
index 499ddeb..6b3bcec 100644 (file)
        "yourname": "Kebroikiman nen:",
        "yourpassword": "Psa wortu:",
        "yourpasswordagain": "Psa wortu ete wan leysi:",
-       "remembermypassword": "Tan memre mi kebroikiman nen nanga psa wortu (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "Yu domein:",
        "login": "Psa kon",
        "nav-login-createaccount": "Psa kon / meki wan account",
        "template-semiprotected": "(sroto wan pisi)",
        "nocreatetext": "{{SITENAME}} puru den primisi fu meki nyun papira.\nYu kan go baka fu kenki papira di de kba, noso yu kan [[Special:UserLogin|psa kon noso meki wan account]].",
        "recreate-moveddeleted-warn": "'''Warskow: yu e meki wan papira, di ben puru fu dyaso kaba, baka.'''\n\nDenki fosi efu na wan bun sani fu meki a papira disi baka. A log buku fu puru sori dyaso gi yepi:",
-       "cantcreateaccounttitle": "Kan masyin ni skopu.",
        "viewpagelogs": "Luku a log buku fu a papira disi",
        "currentrev": "A versi disi",
        "revisionasof": "Versi tapu $1",
index 3853940..68b29f0 100644 (file)
        "yourname": "Benutsernoome:",
        "yourpassword": "Paaswoud:",
        "yourpasswordagain": "Paaswoud wierhoalje:",
-       "remembermypassword": "Ap dissen Computer duurhaft ounmälded blieuwe (Maximoal foar $1 {{PLURAL:$1|Dai|Deege}})",
        "yourdomainname": "Dien Domain:",
        "externaldberror": "Äntweeder deer lait n Failer bie ju externe Authentifizierenge foar, of du duurst din extern Benutzerkonto nit aktualisierje.",
        "login": "Anmäldje",
        "undo-failure": "Ju Annerenge kuud nit tourääch annerd wäide, deer ju betroffene Oudeelenge intwisken ferannerd wuude.",
        "undo-norev": "Ju Beoarbaidenge kuud nit räägels troald wäide, deer ju nit foarhounden is of läsked wuude.",
        "undo-summary": "Annerenge $1 fon [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussion]]) wuude tourääch annerd.",
-       "cantcreateaccounttitle": "Benutserkonto kon nit moaked wäide",
        "cantcreateaccount-text": "Dät Moakjen fon n Benutserkonto fon ju IP-Adresse '''$1''' uut wuude fon [[User:$3|$3]] speerd.\n\nGruund fon ju Speere: ''$2''",
        "viewpagelogs": "Logbouke foar disse Siede anwiese",
        "nohistory": "Dät rakt neen fröiere Versione fon dissen Artikkel.",
        "activeusers-intro": "Dit is ne Lieste fon Benutsere, do binne {{PLURAL:$1|dän lääste Dai|do lääste $1 Deege}} Aktivitäte apwiese.",
        "activeusers-count": "$1 {{PLURAL:$1|Beoarbaidenge|Beoarbaidengen}} in do {{PLURAL:$3|lääste 24 Uuren|fergeene $3 Deege}}",
        "activeusers-from": "Wies Benutsere ounfangend mäd:",
-       "activeusers-hidebots": "Bots fersteete",
-       "activeusers-hidesysops": "Administratore fersteete",
        "activeusers-noresult": "Neen Benutsere fuunen.",
        "listgrouprights": "Benutsergruppen-Gjuchte",
        "listgrouprights-summary": "Dit is ne Lieste fon do in dissen Wiki definierde Benutsergruppen un do deermäd ferbuundene Gjuchte.\nInformatione uurhäär uur eenpelde Gjuchte konnen [[{{MediaWiki:Listgrouprights-helppage}}|hier]] fuunen wäide.",
        "htmlform-submit": "Uurdreege",
        "htmlform-reset": "Annerengen touräächtraale",
        "htmlform-selectorother-other": "Uur",
-       "sqlite-has-fts": "Version $1 mäd Unnerstutsenge foar ju Fultäkstsäike",
-       "sqlite-no-fts": "Version $1 sunner Unnerstutsenge foaar ju Fultäkstsäike",
        "revdelete-restricted": "Einskränkengen jäilde uk foar Administratore",
        "revdelete-unrestricted": "Ienskränkengen foar Administratore wächhoald",
        "rightsnone": "(-)",
index ed76949..f191865 100644 (file)
        "yourpasswordagain": "Ketik deui sandi anjeun",
        "createacct-yourpasswordagain": "Konfirmasi kecap sandi",
        "createacct-yourpasswordagain-ph": "Asupkeun deui kecap sandi",
-       "remembermypassword": "Apalkeun login kuring dina ieu komputer (pikeun paling lila $1 {{PLURAL:$1|poé|poé}})",
        "userlogin-remembermypassword": "Jaga ngarah angger asup log",
        "userlogin-signwithsecure": "Paké sambungan aman",
        "yourdomainname": "Domain anjeun",
        "passwordreset-emailtext-user": "Pamaké $1 di {{SITENAME}} ménta nyetél ulang sandi anjeun di {{SITENAME}} ($4). {{PLURAL:$3|Akun}} di handap tumali jeung alamat surélék ieu:\n\n$2\n\n{{PLURAL:$3|Ieu sandi saheulaanan}} bakal kadaluwarsa dina témpo {{PLURAL:$5|sapoé|$5 poé}}.\nAnjeun kudu asup sarta milih sandi anyar ayeuna. Lamun henteu rumasa nyieun ieu pamundut atawa lamun geus inget sandi asli sarta moal ngarobah deui, ieu talatah teu kudu dipaliré.",
        "passwordreset-emailelement": "Sandiasma: \n$1\n\nSandi saheulaanan: \n$2",
        "passwordreset-emailsentemail": "Surélék pikeun nyetél ulang kecap sandi geus dikirim.",
-       "passwordreset-emailsent-capture": "Surélék pikeun nyetél ulang kecap sandi geus dikirim, sakumaha ditémbongkeun di handap.",
-       "passwordreset-emailerror-capture": "Surélék pikeun nyetél ulang kecap sandi geus dijieun, sakumaha ditémbongkeun di handap, tapi gagal ngirim ka {{GENDER:$2|pamaké}}: $1",
        "changeemail": "Ganti alamat surélék",
        "changeemail-header": "Ganti alamat surélék akun",
        "changeemail-no-info": "Anjeun kudu asup log pikeun bisa muka ieu kaca sacara langsung.",
        "undo-norev": "Éditan ieu henteu bisa bolaykeun alatan kaca henteu kapanggih atawa geus dihapus.",
        "undo-summary": "←Ngabolaykeun révisi $1 ku [[Special:Contributions/$2|$2]] ([[User talk:$2|Obrolan]])",
        "undo-summary-username-hidden": "Bolaykeun révisi $1 ku pamaké nyumput",
-       "cantcreateaccounttitle": "Rekening teu bisa dijieun",
        "cantcreateaccount-text": "Nyieun rekening ti ieu alamat IP ('''$1''') dipeungpeuk ku [[User:$3|$3]].\n\nAlesanana $3 cenah ''$2''.",
        "cantcreateaccount-range-text": "Nyieun akun ti alamat IP dina rentang <strong>$1</strong>, kaasup alamat IP anjeun (<strong>$4</strong>), dipeungpeuk ku [[User:$3|$3]].\n\nAlesan $3 nyaéta <em>$2</em>",
        "viewpagelogs": "Tempo log kaca ieu",
        "activeusers-intro": "Ieu béréndélan kontributor anu geus ngoprék $1 {{PLURAL:$1|poé|poé}} panungtung.",
        "activeusers-count": "$1 {{PLURAL:$1|édit|édit}}an salila {{PLURAL:$3|poé|$3 poé}} panungtung",
        "activeusers-from": "Témbongkeun kontributor dimimitian ku:",
-       "activeusers-hidebots": "Sumputkeun bot",
-       "activeusers-hidesysops": "Sumputkeun kuncén",
        "activeusers-noresult": "Teu kapendak.",
        "listgrouprights": "Hak-hak grup pamaké",
        "listgrouprights-summary": "Ieu mangrupa daptar jumplukan pamaké anu aya di wiki ieu, kalawan daptar hak aksés maranéhanana.\nÉmbaran leuwih luyu ngeunaan hak pamaké bisa ditingali di [[{{MediaWiki:Listgrouprights-helppage}}|dieu]].",
index 333ab9f..d4f9cbb 100644 (file)
        "views": "Visningar",
        "toolbox": "Verktyg",
        "tool-link-userrights": "Ändra {{GENDER:$1|användargrupper}}",
+       "tool-link-userrights-readonly": "Visa {{GENDER:$1|användargrupper}}",
        "tool-link-emailuser": "Skicka e-post till denna {{GENDER:$1|användare}}",
        "userpage": "Visa användarsida",
        "projectpage": "Visa projektsida",
        "botpasswords-label-delete": "Radera",
        "botpasswords-label-resetpassword": "Återställ lösenordet",
        "botpasswords-label-grants": "Tillgängliga beviljanden:",
-       "botpasswords-help-grants": "Varje beviljande ger åtkomst till listade användarrättigheter som ett användarkonto redan har. Se [[Special:ListGrants|tabellen över beviljanden]] för mer information.",
+       "botpasswords-help-grants": "Beviljande ger åtkomst till användarrättigheter som ditt användarkonto redan har. När ett beviljande aktiveras här ger det inte åtkomst till de användarrättigheter som ditt användarkonto inte annars skulle ha. Se [[Special:ListGrants|tabellen över beviljanden]] för mer information.",
        "botpasswords-label-grants-column": "Beviljas",
        "botpasswords-bad-appid": "Botnamnet \"$1\" är inte giltigt.",
        "botpasswords-insert-failed": "Kunde inte lägga till botnamnet \"$1\". Har det redan lagts till?",
        "passwordreset-emaildisabled": "E-postfunktioner har inaktiverats på denna wiki.",
        "passwordreset-username": "Användarnamn:",
        "passwordreset-domain": "Domän:",
-       "passwordreset-capture": "Visa resulterande e-post?",
-       "passwordreset-capture-help": "Om du markerar den här rutan kommer e-postmeddelandet (med det tillfälliga lösenordet) visas för dig och skickas till användaren.",
        "passwordreset-email": "E-postadress:",
        "passwordreset-emailtitle": "Kontouppgifter på {{SITENAME}}",
        "passwordreset-emailtext-ip": "Någon (förmodligen du, från IP-adressen $1) begärde en återställning av ditt lösenord för {{SITENAME}} ($4). Följande användar{{PLURAL:$3|konto är förknippad|konton är förknippade}} med denna e-postadress:\n\n$2\n\n{{PLURAL:$3|Detta|Dessa}} tillfälliga lösenord kommer att gå ut om {{PLURAL:$5|en dag|$5 dagar}}.\nDu bör logga in och välja ett nytt lösenord nu. Om någon annan gjorde denna begäran, eller om du kommer ihåg ditt ursprungliga lösenord, och inte längre önskar ändra det, kan du ignorera detta meddelande och fortsätta använda ditt gamla lösenord.",
        "passwordreset-emailelement": "Användarnamn: \n$1\n\nTillfälligt lösenord: \n$2",
        "passwordreset-emailsentemail": "Om denna e-postadress är associerad med ditt konto kommer en lösenordsåterställning skickas via e-post.",
        "passwordreset-emailsentusername": "Om det finns en e-postadress som associeras med detta användarnamn kommer en lösenordsåterställning skickas via e-post.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|E-postmeddelande|E-postmeddelanden}} för återställning av lösenord har skickats. {{PLURAL:$1|Användarnamnet och lösenordet|Listan över användarnamn och lösenord}} visas här.",
-       "passwordreset-emailerror-capture2": "Kunde inte skicka e-post till {{GENDER:$2|användaren}}: $1 {{PLURAL:$3|Användarnamnet och lösenordet|Listan över användarnamn och lösenord}} listas här.",
        "passwordreset-nocaller": "En användare måste anges",
        "passwordreset-nosuchcaller": "Användare finns inte: $1",
        "passwordreset-ignored": "Lösenordsåterställningen hanterades inte. Kanske ingen leverantör har konfigurerats?",
-       "passwordreset-invalideamil": "Ogiltig e-postadress",
+       "passwordreset-invalidemail": "Ogiltig e-postadress",
        "passwordreset-nodata": "Varken ett användarnamn eller en e-postadress angavs",
        "changeemail": "Ändra eller ta bort e-postadress",
        "changeemail-header": "Fyll i detta formulär för att ändra din e-postadress. Om du vill ta bort en associerad e-postadress från ditt konto lämnar du fältet för ny e-postadress tomt när formuläret skickas in.",
        "search-external": "Extern sökning",
        "searchdisabled": "Sökfunktionen på {{SITENAME}} är avstängd.\nDu kan istället göra sökningar med hjälp av Google.\nNotera dock att deras indexering av {{SITENAME}} kan vara något föråldrad.",
        "search-error": "Ett fel uppstod under sökningen: $1",
+       "search-warning": "En varning uppstod under sökning: $1",
        "preferences": "Inställningar",
        "mypreferences": "Inställningar",
        "prefs-edits": "Antal redigeringar:",
        "prefs-help-recentchangescount": "Detta inkluderar senaste ändringarna, sidhistorik och loggar.",
        "prefs-help-watchlist-token2": "Detta är den hemliga nyckeln till webbflödet i din bevakningslista.\nNågon som vet den kommer att kunna läsa din bevakningslista, så dela inte ut den.\n[[Special:ResetTokens|Klicka här om du behöver återställa den]].",
        "savedprefs": "Dina inställningar har sparats",
-       "savedrights": "Användarrättigheterna för {{GENDER:$1|$1}} har sparats.",
+       "savedrights": "Användargrupperna för {{GENDER:$1|$1}} har sparats.",
        "timezonelegend": "Tidszon:",
        "localtime": "Lokal tid:",
        "timezoneuseserverdefault": "Använd wikins standard ($1)",
        "prefswarning-warning": "Du har gjort ändringar i dina inställningarna som inte har sparats ännu.\nOm du lämnar denna sida utan att klicka på \"$1\" kommer dina inställningar inte att uppdateras.",
        "prefs-tabs-navigation-hint": "Tips: Du kan använda vänster och höger piltangenterna för att navigera mellan flikarna i listan flikar.",
        "userrights": "Hantering av användarrättigheter",
-       "userrights-lookup-user": "Hantera användargrupper",
+       "userrights-lookup-user": "Välj en användare",
        "userrights-user-editname": "Skriv in ett användarnamn:",
-       "editusergroup": "Ändra {{GENDER:$1|användargrupper}}",
+       "editusergroup": "Läs in användargrupper",
        "editinguser": "Ändrar rättigheter för {{GENDER:$1|användaren}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Visar rättigheter för {{GENDER:$1|användaren}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Ändra användargrupper",
+       "userrights-viewusergroup": "Visa användargrupper",
        "saveusergroups": "Spara {{GENDER:$1|användargrupper}}",
        "userrights-groupsmember": "Medlem i:",
        "userrights-groupsmember-auto": "Implicit medlem av:",
        "userrights-reason": "Anledning:",
        "userrights-no-interwiki": "Du har inte behörighet att ändra användarrättigheter på andra wikis.",
        "userrights-nodatabase": "Databasen $1 finns inte eller så är den inte lokal.",
-       "userrights-nologin": "Du måste [[Special:UserLogin|logga in]] med ett administratörskonto för att ändra användarrättigheter.",
-       "userrights-notallowed": "Du har inte behörighet till att lägga till eller ta bort användarrättigheter.",
        "userrights-changeable-col": "Grupper du kan ändra",
        "userrights-unchangeable-col": "Grupper du inte kan ändra",
        "userrights-conflict": "Konflikt vid ändringar av användarrättigheter! Var god granska och bekräfta dina ändringar.",
-       "userrights-removed-self": "Du tog bort dina egna rättigheter. Du kan därför inte längre komma åt denna sida.",
        "group": "Grupp:",
        "group-user": "Användare",
        "group-autoconfirmed": "Automatiskt bekräftade användare",
        "right-siteadmin": "Lås och öppna databasen",
        "right-override-export-depth": "Exportera sidor inklusive länkade sidor till ett djup på 5",
        "right-sendemail": "Skicka e-post till andra användare",
-       "right-passwordreset": "Visa e-postmeddelanden med lösenordsåterställning",
        "right-managechangetags": "Skapa och (in)aktivera [[Special:Tags|märken]]",
        "right-applychangetags": "Tillämpa [[Special:Tags|märken]] tillsammans med ens ändringar",
        "right-changetags": "Lägg till och ta bort godtyckliga [[Special:Tags|märken]] på individuella sidversioner och loggposter.",
        "action-upload_by_url": "ladda upp denna fil från en URL-adress",
        "action-writeapi": "använda skriv-API:t",
        "action-delete": "radera denna sida",
-       "action-deleterevision": "radera denna version",
-       "action-deletedhistory": "se denna sidas raderade historik",
+       "action-deleterevision": "radera sidversioner",
+       "action-deletelogentry": "radera loggposter",
+       "action-deletedhistory": "se en sidas raderade historik",
+       "action-deletedtext": "visa raderad sidversionstext",
        "action-browsearchive": "söka raderade sidor",
-       "action-undelete": "avradera denna sida",
-       "action-suppressrevision": "granska och återställa denna dolda version",
+       "action-undelete": "återställ sidor",
+       "action-suppressrevision": "granska och återställ dolda sidversioner",
        "action-suppressionlog": "se denna privata logg",
        "action-block": "blockera denna användare från redigering",
        "action-protect": "ändra skyddsnivå för denna sida",
        "action-userrights-interwiki": "ändra rättigheter för användare på andra wikier",
        "action-siteadmin": "låsa eller låsa upp databasen",
        "action-sendemail": "skicka e-post",
+       "action-editmyoptions": "redigera dina inställningar",
        "action-editmywatchlist": "redigera din bevakningslista",
        "action-viewmywatchlist": "visa din bevakningslista",
        "action-viewmyprivateinfo": "visa din privata information",
        "apisandbox-continue": "Fortsätt",
        "apisandbox-continue-clear": "Rensa",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} kommer att [https://www.mediawiki.org/wiki/API:Query#Continuing_queries fortsätta] den sista begäran; {{int:apisandbox-continue-clear}} kommer att rensa fortsättningsrelaterade parametrar.",
+       "apisandbox-param-limit": "Ange <kbd>max</kbd> för att använda den maximala gränsen.",
+       "apisandbox-multivalue-all-namespaces": "$1 (alla namnrymder)",
+       "apisandbox-multivalue-all-values": "$1 (alla värden)",
        "booksources": "Bokkällor",
        "booksources-search-legend": "Sök efter bokkällor",
        "booksources-search": "Sök",
        "activeusers-count": "$1 {{PLURAL:$1|handling|handlingar}} {{PLURAL:$3|det senaste dygnet|de senaste $3 dygnen}}",
        "activeusers-from": "Visa användare från och med:",
        "activeusers-groups": "Visa användare som tillhör grupper:",
+       "activeusers-excludegroups": "Exkludera användare som tillhör grupper:",
        "activeusers-noresult": "Inga användare funna.",
        "activeusers-submit": "Visa aktiva användare",
        "listgrouprights": "Behörigheter för användargrupper",
        "emailccsubject": "Kopia av ditt meddelande till $1: $2",
        "emailsent": "E-post har nu skickats",
        "emailsenttext": "Ditt e-postmeddelande har skickats",
-       "emailuserfooter": "Detta e-postmeddelande {{GENDER:$1|skickades}} av $1 till {{GENDER:$2|$2}} med funktionen \"{{int:emailuser}}\" på {{SITENAME}}.",
+       "emailuserfooter": "Detta e-postmeddelande {{GENDER:$1|skickades}} av $1 till {{GENDER:$2|$2}} med funktionen \"{{int:emailuser}}\" på {{SITENAME}}. {{GENDER:$2|Ditt}} e-postmeddelande kommer att skickas direkt till {{GENDER:$1|den ursprungliga avsändaren}}, vilket kommer avslöja {{GENDER:$2|din}} e-postadress för {{GENDER:$1|dem}}.",
        "usermessage-summary": "Lämnar systemmeddelande.",
        "usermessage-editor": "Systemmeddelare",
        "watchlist": "Bevakningslista",
        "patrol-log-header": "Detta är en logg över patrullerade sidversioner.",
        "log-show-hide-patrol": "$1 patrulleringslogg",
        "log-show-hide-tag": "$1 märkeslogg",
+       "confirm-markpatrolled-button": "OK",
+       "confirm-markpatrolled-top": "Markera sidversionen $3 av $2 som patrullerad?",
        "deletedrevision": "Raderade gammal sidversion $1",
        "filedeleteerror-short": "Fel vid radering av fil: $1",
        "filedeleteerror-long": "Fel inträffade vid raderingen av filen:\n\n$1",
        "tags-deactivate": "inaktivera",
        "tags-hitcount": "$1 {{PLURAL:$1|ändring|ändringar}}",
        "tags-manage-no-permission": "Du har inte behörighet att hantera förändringsmärken.",
-       "tags-manage-blocked": "Du kan inte hantera förändringsmärken när du är blockerad.",
+       "tags-manage-blocked": "Du kan inte hantera förändringsmärken när {{GENDER:$1|du}} är blockerad.",
        "tags-create-heading": "Skapa ett nytt märke",
        "tags-create-explanation": "Som standard, kommer nyskapade märken att bli tillgängliga för användning av användare och botar.",
        "tags-create-tag-name": "Märkesnamn:",
        "tags-deactivate-not-allowed": "Det är inte möjligt att inaktivera märket \"$1\".",
        "tags-deactivate-submit": "Inaktivera",
        "tags-apply-no-permission": "Du har inte behörighet att tillämpa ändringsmärken på dina ändringar.",
-       "tags-apply-blocked": "Du kan inte ange ändringsmärken med dina ändringar medans du är blockerad.",
+       "tags-apply-blocked": "Du kan inte ange ändringsmärken med dina ändringar när {{GENDER:$1|du}} är blockerad.",
        "tags-apply-not-allowed-one": "Märket \"$1\" kan inte läggas till manuellt.",
        "tags-apply-not-allowed-multi": "Följande {{PLURAL:$2|märke|märken}} kan inte läggas till manuellt: $1",
        "tags-update-no-permission": "Du har inte behörighet att lägga till eller ta bort märken från individuella sidversioner eller loggposter.",
-       "tags-update-blocked": "Du kan inte lägga till eller ta bort ändringsmärken när du är blockerad.",
+       "tags-update-blocked": "Du kan inte lägga till eller ta bort ändringsmärken när {{GENDER:$1|du}} är blockerad.",
        "tags-update-add-not-allowed-one": "Märket \"$1\" kan inte läggas till manuellt.",
        "tags-update-add-not-allowed-multi": "Följande {{PLURAL:$2|märke|märken}} kan inte läggas till manuellt: $1",
        "tags-update-remove-not-allowed-one": "Märket \"$1\" får inte tas bort.",
        "htmlform-user-not-exists": "<strong>$1</strong> finns inte.",
        "htmlform-user-not-valid": "<strong>$1</strong> är inte ett giltigt användarnamn.",
        "logentry-delete-delete": "$1 {{GENDER:$2|raderade}} sidan $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|raderade}} omdirigeringen $3 genom att skriva över den",
        "logentry-delete-restore": "$1 {{GENDER:$2|återställde}} sidan $3",
        "logentry-delete-event": "$1 {{GENDER:$2|ändrade}} synligheten för {{PLURAL:$5|en logghändelse|$5 logghändelser}} på $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|ändrade}} synligheten för {{PLURAL:$5|en version|$5 versioner}} på sidan $3: $4",
        "mw-widgets-dateinput-no-date": "Inget valt datum",
        "mw-widgets-dateinput-placeholder-day": "ÅÅÅÅ-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "ÅÅÅÅ-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Sök efter media",
+       "mw-widgets-mediasearch-noresults": "Inga resultat hittades.",
        "mw-widgets-titleinput-description-new-page": "sidan existerar inte ännu",
        "mw-widgets-titleinput-description-redirect": "omdirigerar till $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Lägg till en kategori...",
        "sessionmanager-tie": "Kan inte kombinera flera begäransautentiseringstyper: $1.",
        "sessionprovider-generic": "$1-sessioner",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "cookiebaserade sessioner",
        "log-action-filter-contentmodel-change": "Ändring av innehållsmodell",
        "log-action-filter-contentmodel-new": "Skapande av sida med icke-standardiserad innehållsmodell",
        "log-action-filter-delete-delete": "Radering av sida",
+       "log-action-filter-delete-delete_redir": "Överskrivning av omdirigering",
        "log-action-filter-delete-restore": "Återställning av sida",
        "log-action-filter-delete-event": "Radering av logg",
        "log-action-filter-delete-revision": "Radering av sidversion",
        "authmanager-authn-autocreate-failed": "Kunde inte skapa ett lokalt konto automatiskt: $1",
        "authmanager-change-not-supported": "De angivna inloggningsuppgifterna kan inte ändras, då ingenting kan använda dem.",
        "authmanager-create-disabled": "Kontoregistrering är inaktiverat.",
-       "authmanager-create-from-login": "Fyll i fälten nedan för att skapa ditt konto.",
+       "authmanager-create-from-login": "Fyll i fälten för att skapa ditt konto.",
        "authmanager-create-not-in-progress": "Skapande av konto pågår inte eller så har sessionsdata förlorats. Var god börja om från början igen.",
        "authmanager-create-no-primary": "De angivna inloggningsuppgifterna kunde inte användas för att skapa ett konto.",
        "authmanager-link-no-primary": "De angivna inloggningsuppgifterna kunde inte användas för att länka ett konto.",
        "restrictionsfield-badip": "Ogiltig IP-adress eller intervall: $1",
        "restrictionsfield-label": "Tillåtna IP-intervall:",
        "restrictionsfield-help": "En IP-adress eller CIDR-intervall per rad. För att aktivera allting, använd<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Fel: $1",
-       "edit-error-long": "Fel:\n\n$1"
+       "pageid": "sid-ID $1"
 }
index 6ab227a..44b15e8 100644 (file)
@@ -17,7 +17,8 @@
                        "Rich Farmbrough",
                        "Kipala",
                        "Kwisha",
-                       "Macofe"
+                       "Macofe",
+                       "Muddyb"
                ]
        },
        "tog-underline": "Wekea mstari viungo:",
        "yourpasswordagain": "Andika tena neno la siri",
        "createacct-yourpasswordagain": "Thibitisha neno la siri",
        "createacct-yourpasswordagain-ph": "Weka neno la siri tena",
-       "remembermypassword": "Kumbuka kuingia kwangu katika kivinjari hiki (kwa muda usiozidi {{PLURAL:$1|siku}} $1)",
        "userlogin-remembermypassword": "Niweke kama nimeingia",
        "userlogin-signwithsecure": "Tumia muunganisho salama",
        "yourdomainname": "Tovuti yako:",
        "passwordreset-emailtext-user": "Mtumiaji $1 kwenye {{SITENAME}} ameomba neno la siri la akaunti yako liwekwe upya katika {{SITENAME}} ($4). {{PLURAL:$3|Akaunti inayofuata imeunganishwa|Akaunti zinazofuata zimeunganishwa}} na anwani ya barua pepe hii:\n\n$2\n\n{{PLURAL:$3|Neno la siri hili litakwisha|Maneno ya siri haya yatakwisha}} baada ya siku {{PLURAL:$5|one day|$5 siku}}.\nTafadhali ingia sasa na uchague neno jipya la siri. Kama mtu mwingine ameomba hili, au ikiwa umekumbuka neno lako la siri na hutaki kulibadilisha tena, basi usijali ujumbe huu, na uendelee kutumia neno la siri lako la zamani.",
        "passwordreset-emailelement": "Jina la mtumiaji: \n$1\n\nNeno la siri la muda: \n$2",
        "passwordreset-emailsentemail": "Barua pepe ya ukumbusho wa neno la siri imetumwa.",
-       "passwordreset-emailsent-capture": "Barua pepe ya ukukumbusho wa neno la siri imetumwa, ambayo inaonekana hapo chini.",
-       "passwordreset-emailerror-capture": "Barua pepe ya ukukumbusho wa neno la siri imetengenezwa, ambayo inaonekana hapo chini, lakini kuituma kwa mtumiaji {{GENDER:$2|user}} kumeshindikana: $1",
        "changeemail": "Badilisha anwani ya barua pepe",
        "changeemail-header": "Badilisha anwani ya barua pepe ya akaunti yako",
        "changeemail-no-info": "Lazima uwe umeingia ili kuweza kutumia kurasa hii moja kwa moja.",
        "undo-nochange": "Hariri inaonekana kuwa tayari imerudishwa tena.",
        "undo-summary": "Tengua pitio $1 lililoandikwa na [[Special:Contributions/$2|$2]] ([[User talk:$2|Majadiliano]])",
        "undo-summary-username-hidden": "Tednua toleo $1 na mtumiaji aliyejificha",
-       "cantcreateaccounttitle": "Kushindwa kusajili akaunti",
        "cantcreateaccount-text": "Kusajili akaunti kwa kutumia anwani ya IP hii ('''$1''') imezuiwa na [[User:$3|$3]].\n\nSababu iliyotolewa na $3 ni ''$2''",
        "viewpagelogs": "Tazama kumbukumbu kwa ukurasa huu",
        "nohistory": "Hakuna historia ya kuhariri kwa ajili ya ukurasa huu.",
        "activeusers-intro": "Hii ni orodha ya watumiaji walioshughulika jambo fulani ndani ya siku $1 {{PLURAL:$1|iliyopita|zilizopita}}.",
        "activeusers-count": "{{PLURAL:$1|haririo|maharirio}} $1 katika siku $3 {{PLURAL:$3|iliyopita|zilizopita}}",
        "activeusers-from": "Onyesha watumiaji kuanzia:",
-       "activeusers-hidebots": "Ficha boti",
-       "activeusers-hidesysops": "Ficha wakabidhi",
        "activeusers-noresult": "Watumiaji hawakupatikana.",
        "listgrouprights": "Wezo za kundi za watumiaji",
        "listgrouprights-summary": "Inafuata orodha ya kundi za watumiaji wa wiki hii, pamoja na maelezo ya wezo zao za kushughulika mambo.\nLabda patakuwa na [[{{MediaWiki:Listgrouprights-helppage}}|maelezo mengine]] kuhusu wezo zingine.",
        "feedback-back": "Rudi",
        "feedback-cancel": "Batilisha",
        "feedback-close": "Tayari",
-       "feedback-error-title": "Kosa",
        "feedback-error1": "Hitilafu: Hatokeo ya API hayafahamiki",
        "feedback-error2": "Hitilafu: Hariri haikufaulu",
        "feedback-error3": "Hitilafu: API ya wiki haitoi majibu",
index c065fce..7fd903d 100644 (file)
        "botpasswords-label-resetpassword": "கடவுச்சொலை மீளமை",
        "botpasswords-label-grants": "பொருந்தும் மானியங்கள்:",
        "botpasswords-help-grants": "ஒவ்வொரு மானியம் ஏற்கனவே உள்ள பயனர் கணக்குக்கு வரையறுக்கப்பட்ட பயனர் உரிமைகள் அணுக கொடுக்கிறது. மேலதிக விபரங்ளுக்கு [[சிறப்பு:ListGrants|மானியங்களின் அட்டவணையை]] பார்க்க.",
-       "botpasswords-label-restrictions": "பயன்பாட்டு வரையறைகள்:",
        "botpasswords-label-grants-column": "வழங்கப்பட்டது",
        "botpasswords-bad-appid": "\"$1\" என்ற தானியங்கி பெயர் பயன்படாதது.",
        "botpasswords-insert-failed": "\"$1\" என்ற தானியங்கி பெயரை இணைக்க முடியவில்லை. ஏற்கனவே இருக்குமோ?",
        "activeusers-intro": "கடைசி $1 {{PLURAL:$1|நாள்|நாட்கள்}} ஏதேனும் செயலை செய்த பயனர்களின் பட்டியல் இது.",
        "activeusers-count": "$1 {{PLURAL:$1|திருத்தம்|திருத்தங்கள்}} கடைசி {{PLURAL:$3|நாள்|$3 நாட்கள்}}",
        "activeusers-from": "பின்வரும் எழுத்துடன் தொடங்கும் பயனர்களைக் காட்டு:",
-       "activeusers-hidebots": "தானியங்கிகளை மறை",
-       "activeusers-hidesysops": "நிர்வாகிகளை மறை",
        "activeusers-noresult": "எந்தவொரு பயனர்களும் காணப்படவில்லை.",
        "activeusers-submit": "தொடர் பங்களிப்பாளர்களை காட்டு",
        "listgrouprights": "பயனர் குழு உரிமைகள்",
        "feedback-close": "முடிந்தது",
        "feedback-external-bug-report-button": "ஒரு தொழில்நுட்ப பணியைச் சமர்ப்பி",
        "feedback-dialog-title": "பின்னூட்டத்தை சமர்ப்பி",
-       "feedback-error-title": "பிழை",
        "feedback-error1": "பிழை: API லிருந்து அங்கீகரிக்கப்படாத முடிவு.",
        "feedback-error2": "பிழை: திருத்தல்  தோல்வியடைந்தது",
        "feedback-error3": "பிழை: API லிருந்து பதிற்குறிப்பு எதுவும் இல்லை.",
index 315a732..9277032 100644 (file)
        "passwordreset-username": "ಸದಸ್ಯೆರ್ನ ಪುದರ್:",
        "passwordreset-domain": "ಕ್ಷೇತ್ರೊ:",
        "passwordreset-email": "ಇ-ಅಂಚೆ ವಿಳಾಸೊ",
-       "passwordreset-invalideamil": "ಇಮೇಲ್ ಸರಿ ಇಜ್ಜಿ",
+       "passwordreset-invalidemail": "ಇಮೇಲ್ ಸರಿ ಇಜ್ಜಿ",
        "changeemail-oldemail": "ಇತ್ತೆತಾ ಈಮೇಲ್ ವಿಳಾಸೊ:",
        "changeemail-newemail": "ಪೊಸ ಇ-ಅಂಚೆ ವಿಳಾಸೊ:",
        "changeemail-none": "ಒವ್ವುಲಾ ಇಜ್ಜಿ",
        "searchprofile-everything-tooltip": "ಮಾತ ಮಾಹಿತಿಲೆನ್ ನಾಡ್‍ಲೆ (ಪಾತೆರದ ಪುಟೊಲ ಸೇರ್ದ್)",
        "searchprofile-advanced-tooltip": "ಬಳಕೆದ ನಾಮೊವರ್ಗೊಡು ನಾಡ್‍ಲೆ",
        "search-result-size": "$1 ({{PLURAL:$2|೧ ಪದೊ|$2 ಪದೊಕುಲು}})",
-       "search-redirect": "(ಪಿರ ನಿರ್ದೇಶನೊ $1)",
+       "search-redirect": "($1 ಡ್ದ್ ಪಿರ ನಿರ್ದೇಸನೊದ)",
        "search-section": "(ವಿಬಾಗೊ $1)",
        "search-suggest": "ಇಂದೆನ್ ನಾಡೊಂದುಲ್ಲರೆ: $1",
        "search-interwiki-caption": "ಬಳಗದ ಇತರ ಯೋಜನೆಲು",
        "logentry-move-move": "$1 {{GENDER:$2|ಜಾರಲೆ}} ಪುಟೊ $3 ಡ್ದ್ $4",
        "logentry-newusers-create": "ಬಳಕೆದಾರೆರೆ ಕಾತೆ $1 ನ್ನು {{GENDER:$2|ಸ್ರಿಸ್ಟಿ ಮಲ್ತಾಂಡ್}}",
        "logentry-upload-upload": "$1 {{GENDER:$2|ಅಪ್ಲೋಡ್ ಮಲ್ತ್‌ದೆರ್}} $3",
-       "searchsuggest-search": "ನಾಡ್‍ಲೆ"
+       "searchsuggest-search": "{{SITENAME}}ನ್ ನಾಡ್‍ಲೆ"
 }
index 3ec4110..f45a897 100644 (file)
        "views": "చూపులు",
        "toolbox": "పనిముట్లు",
        "tool-link-userrights": "{{GENDER:$1|వాడుకరి}} గుంపులను మార్చు",
+       "tool-link-userrights-readonly": "{{GENDER:$1|వాడుకరి}} గుంపులను చూడండి",
        "tool-link-emailuser": "ఈ {{GENDER:$1|వాడుకరికి}} ఈమెయిలు పంపు",
        "userpage": "వాడుకరి పేజీని చూడండి",
        "projectpage": "ప్రాజెక్టు పేజీని చూడు",
        "passwordreset-emaildisabled": "ఈ వికీలో ఈమెయిలు విశేషాలను అశక్తం చేసాం.",
        "passwordreset-username": "వాడుకరి పేరు:",
        "passwordreset-domain": "డొమైన్:",
-       "passwordreset-capture": "ఈమెయిలు ఎలా ఉంటుందో చూస్తారా?",
-       "passwordreset-capture-help": "ఈ పెట్టెను చెక్ చేస్తే, ఈమెయిలును (తాత్కాలిక సంకేతపదంతో) వాడుకరికి పంపిస్తూనే, మీకూ చూపిస్తాం.",
        "passwordreset-email": "ఈ-మెయిలు చిరునామా:",
        "passwordreset-emailtitle": "{{SITENAME}}లో ఖాతా వివరాలు",
        "passwordreset-emailtext-ip": "ఎవరో (బహుశా మీరే, ఐపీ అడ్రసు $1 నుంచి)  {{SITENAME}} ($4) లో మీ సంకేతపదాన్ని మార్చమంటూ అడిగారు. కింది వాడుకరి {{PLURAL:$3|ఖాతా|ఖాతాలు}}\nఈ ఈమెయిలు చిరునామాతో అనుసంధింపబడి ఉన్నాయి:\n\n$2\n\n{{PLURAL:$3|ఈ సంకేతపదానికి|ఈ సంకేతపదాలకు}} {{PLURAL:$5|ఒక్కరోజులో|$5 రోజుల్లో}} కాలం చెల్లుతుంది.\nఇప్పుడు మీరు లాగినై కొత్త సంకేతపదాన్ని ఎంచుకోవాల్సి ఉంటుంది. ఈ అభ్యర్ధన చేసింది మరెవరైనా అయినా, లేక మీ అసలు సంకేతపదం మీకు గుర్తొచ్చి దాన్ని మార్చాల్సిన అవసరం లేదని అనుకున్నా, మీరీ సందేశాన్ని పట్టించుకోనక్కర్లేదు. పాత సంకేతపదాన్నే వాడుకోవచ్చు.",
        "passwordreset-emailelement": "వాడుకరిపేరు: \n$1\n\nతాత్కాలిక సంకేతపదం: \n$2",
        "passwordreset-emailsentemail": "ఈ ఈమెయిలు చిరునామా మీ ఖాతాకు అనుసంధించి ఉంటే, సంకేతపదం మార్పు ఈమెయిలు పంపించబడుతుంది.",
        "passwordreset-emailsentusername": "ఈ వాడుకరిపేరుకు ఏదైనా ఈమెయిలు చిరునామా అనుసంధించి ఉంటే, సంకేతపదం మార్పు ఈమెయిలు పంపించబడుతుంది.",
-       "passwordreset-emailsent-capture2": "సంకేతపదం మార్పు {{PLURAL:$1|ఈమెయిలును|ఈమెయిళ్ళను}} పంపించాం. {{PLURAL:$1|వాడుకరిపేరు, సంకేతపదాన్ని|వాడుకరిపేర్లు, సంకేతపదాల జాబితాను}} ఇక్కడ చూపించాం.",
-       "passwordreset-emailerror-capture2": "{{GENDER:$2|వాడుకరికి}} ఈమెయిలు పంపడం విఫలమైంది: $1 {{PLURAL:$3|వాడుకరిపేరు, సంకేతపదాన్ని|వాడుకరిపేర్లు, సంకేతపదాల జాబితాను}} ఇక్కడ చూపించాం.",
-       "passwordreset-invalideamil": "తప్పు ఈ-మెయిలు చిరునామా",
+       "passwordreset-invalidemail": "తప్పు ఈ-మెయిలు చిరునామా",
        "passwordreset-nodata": "వాడుకరిపేరుగానీ, ఈ-మెయిలు చిరునామా గానీ ఇవ్వలేదు",
        "changeemail": "ఈ-మెయిలు చిరునామా మార్పు లేదా తొలగింపు",
        "changeemail-header": "మీ ఈ-మెయిల్ చిరునామాను మార్చుకునేందుకు ఈ ఫారమును నింపండి. అసలు మీ ఖాతాకు ఈ-మెయిలు చిరునామా దేన్నీ జోడించ వద్దనుకుంటే, కొత్త ఈ-మెయిలు చిరునామాను ఖాళీగా ఉంచి, ఫారాన్ని సమర్పించండి.",
        "bold_tip": "బొద్దు అక్షరాలు",
        "italic_sample": "వాలు పాఠ్యం",
        "italic_tip": "వాలు పాఠ్యం",
-       "link_sample": "లిà°\82à°\95à±\81 పేరు",
-       "link_tip": "à°\85à°\82తరà±\8dà°\97à°¤ à°²à°¿à°\82à°\95à±\81",
+       "link_sample": "à°²à°\82à°\95à±\86 పేరు",
+       "link_tip": "à°\85à°\82తరà±\8dà°\97à°¤ à°²à°\82à°\95à±\86",
        "extlink_sample": "http://www.example.com లింకు పేరు",
        "extlink_tip": "బయటి లింకు (దీనికి ముందు http:// ఇవ్వటం మరువకండి)",
        "headline_sample": "శీర్షిక పాఠ్యం",
        "prefs-help-recentchangescount": "ఇది ఇటీవలి మార్పులు, పేజీ చరిత్రలు, మరియు చిట్టాలకు వర్తిస్తుంది.",
        "prefs-help-watchlist-token2": "మీ వీక్షణజాబితా యొక్క జాలవడ్డింపుకు చెందిన రహస్య తాళమిది.\nఈ తాళం తెలిసిన ఎవరైనా మీ వీక్షణజాబితాను చదవగలుగుతారు. అందుచేత దీన్ని ఎవరికీ ఇవ్వకండి.\n[[Special:ResetTokens|దాన్ని మార్చాలంటే ఇక్కడ నొక్కండి]].",
        "savedprefs": "మీ అభిరుచులను భద్రపరిచాం.",
-       "savedrights": "{{GENDER:$1|$1}} à°µà°¾à°¡à±\81à°\95à°°à°¿ à°¹à°\95à±\8dà°\95à±\81లనà±\81 à°­à°¦à±\8dరపరà°\9aà°¾à°\82.",
+       "savedrights": "{{GENDER:$1|$1}} à°µà°¾à°¡à±\81à°\95à°°à°¿ à°\97à±\81à°\82à°ªà±\81à°²à±\81 à°­à°¦à±\8dరమయà±\8dయాయి.",
        "timezonelegend": "కాల మండలం:",
        "localtime": "స్థానిక సమయం:",
        "timezoneuseserverdefault": "వికీ అప్రమేయాన్ని ఉపయోగించు ($1)",
        "prefswarning-warning": "మీ అభిరుచులలో మీరు చేసిన మార్పులను ఇంకా భద్రపరచలేదు. మీరు \"$1\" ను నొక్కకుండా ఈ పేజీని వదలి వెళ్తే, మీ అభిరుచులు భద్రం కావు.",
        "prefs-tabs-navigation-hint": "చిట్కా: ట్యాబుల జాబితాలో ఓ ట్యాబు నుండి మరోదానికి వెళ్ళేందుకు కుడి ఎడమ బాణాల కీలను వాడవచ్చు.",
        "userrights": "వాడుకరి హక్కుల నిర్వహణ",
-       "userrights-lookup-user": "వాడుకరి సమూహాలను నిర్వహించండి",
+       "userrights-lookup-user": "వాడుకరిని ఎంచుకోండి",
        "userrights-user-editname": "వాడుకరిపేరును ఇవ్వండి:",
-       "editusergroup": "{{GENDER:$1|వాడుకరి}} గుంపులను మార్చు",
-       "editinguser": "{{GENDER:$1|వాడుకరి}} <strong>[[వాడుకరి:$1|$1]]</strong> $2 యొక్క వాడుకరి హక్కులను మారుస్తున్నారు",
+       "editusergroup": "వాడుకరి గుంపులను చూపించు",
+       "editinguser": "{{GENDER:$1|user}} వాడుకరి హక్కులను మారుస్తున్నారు <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "వాడుకరి సమూహాలను మార్చండి",
        "saveusergroups": "{{GENDER:$1|వాడుకరి}} గుంపులను భద్రపరచు",
        "userrights-groupsmember": "సభ్యులు:",
        "userrights-reason": "కారణం:",
        "userrights-no-interwiki": "ఇతర వికీలలో వాడుకరి హక్కులను మార్చడానికి మీకు అనుమతి లేదు.",
        "userrights-nodatabase": "$1 అనే డేటాబేసు లేదు లేదా అది స్థానికం కాదు.",
-       "userrights-nologin": "వాడుకరి హక్కులను ఇవ్వడానికి మీరు తప్పనిసరిగా ఓ నిర్వాహక ఖాతాతో [[Special:UserLogin|లాగినవ్వాలి]].",
-       "userrights-notallowed": "వాడుకరి హక్కులను చేర్చే మరియు తొలగించే అనుమతి మీకు లేదు.",
        "userrights-changeable-col": "మీరు మార్చదగిన గుంపులు",
        "userrights-unchangeable-col": "మీరు మార్చలేని గుంపులు",
        "userrights-conflict": "వాడుకరి హక్కుల మార్పులలో ఘర్షణ! మీ మార్పులను సమీక్షించి, నిర్ధారించండి.",
-       "userrights-removed-self": "మీ హక్కులను మీరు తొలగించుకున్నారు. ఇక, మీరీ పేజీని చూడలేరు.",
        "group": "గుంపు:",
        "group-user": "వాడుకరులు",
        "group-autoconfirmed": "ఆటోమాటిగ్గా నిర్ధారించబడిన వాడుకరులు",
        "right-siteadmin": "డేటాబేసును లాక్, అన్‌లాక్ చెయ్యి",
        "right-override-export-depth": "5 లింకుల లోతు వరకు ఉన్న పేజీలతో సహా, పేజీలను ఎగుమతి చెయ్యి",
        "right-sendemail": "ఇతర వాడుకరులకు ఈ-మెయిలు పంపించడం",
-       "right-passwordreset": "సంకేతపదం మార్పు ఈమెయిళ్ళను చూడడం",
        "right-managechangetags": "డేటాబేసులో [[Special:Tags|ట్యాగుల]]ను సృష్టించడం, తొలగించడం",
        "right-applychangetags": "తన మార్పులతో [[Special:Tags|ట్యాగుల]]ను ఆపాదించడం",
        "right-changetags": "విడి కూర్పులకు, చిట్టా పద్దులకు ఏవైనా [[Special:Tags|ట్యాగుల]]ను చేర్చడం, తొలగించడం",
        "upload-http-error": "ఒక HTTP పొరపాటు జరిగింది: $1",
        "upload-copy-upload-invalid-domain": "ఈ డొమెయిన్ నుంచి కాపీ ఎక్కింపులు కుదరదు.",
        "upload-dialog-button-cancel": "రద్దుచేయి",
+       "upload-dialog-button-back": "వెనుకకు",
        "upload-dialog-button-done": "పూర్తయ్యింది",
        "upload-dialog-button-save": "భద్రపరచు",
        "upload-dialog-button-upload": "ఎక్కించు",
        "apisandbox-results": "ఫలితాలు",
        "apisandbox-request-url-label": "అభ్యర్థన URL:",
        "apisandbox-request-time": "అభ్యర్ధన సమయం: $1",
+       "apisandbox-continue": "కొనసాగించు",
+       "apisandbox-continue-clear": "తుడిచివేయి",
+       "apisandbox-multivalue-all-namespaces": "$1 (అన్ని పేరుబరులు)",
+       "apisandbox-multivalue-all-values": "$1 (అన్ని విలువలు)",
        "booksources": "పుస్తక మూలాలు",
        "booksources-search-legend": "పుస్తక మూలాల కోసం వెతుకు",
        "booksources-search": "వెతుకు",
        "contributions": "{{GENDER:$1|వాడుకరి}} రచనలు",
        "contributions-title": "$1 యొక్క మార్పులు-చేర్పులు",
        "mycontris": "నా మార్పులు",
-       "anoncontribs": "à°¯à±\8bà°\97దానములు",
+       "anoncontribs": "మారà±\8dà°ªà±\81à°\9aà±\87à°°à±\8dà°ªులు",
        "contribsub2": "{{GENDER:$3|$1}} ($2) కొరకు",
        "contributions-userdoesnotexist": "వాడుకరి ఖాతా \"$1\" నమోదుకాలేదు.",
        "nocontribs": "ఈ విధమైన మార్పులేమీ దొరకలేదు.",
        "whatlinkshere-hideredirs": "$1 దారిమార్పులు",
        "whatlinkshere-hidetrans": "$1 ట్రాన్స్‌క్లూజన్లు",
        "whatlinkshere-hidelinks": "$1 లింకులు",
-       "whatlinkshere-hideimages": "$1 à°¦à°¸à±\8dà°¤à±\8dరాల లంకెలు",
+       "whatlinkshere-hideimages": "$1 à°¦à°¸à±\8dà°¤à±\8dà°°à°ªà±\81 లంకెలు",
        "whatlinkshere-filters": "వడపోతలు",
        "whatlinkshere-submit": "వెళ్ళు",
        "autoblockid": "tanaDDu #$1",
        "patrol-log-header": "ఇది పర్యవేక్షించిన కూర్పుల చిట్టా.",
        "log-show-hide-patrol": "$1 పర్యవేక్షణ చిట్టా",
        "log-show-hide-tag": "ట్యాగుల చిట్టాను $1",
+       "confirm-markpatrolled-button": "సరే",
        "deletedrevision": "పాత సంచిక $1 తొలగించబడినది.",
        "filedeleteerror-short": "ఫైలు తొలగించడంలో పొరపాటు: $1",
        "filedeleteerror-long": "ఫైలుని తొలగించడంలో పొరపాట్లు జరిగాయి:\n\n$1",
        "watchlistedit-raw-done": "మీ వీక్షణ జాబితాను తాజాకరించాం.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 శీర్షికను|$1 శీర్షికలను}} చేర్చాం:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 శీర్షికను|$1 శీర్షికలను}} తీసివేశాం:",
-       "watchlistedit-clear-title": "à°µà±\80à°\95à±\8dà°·à°£à°\9cాబితా à°\9aà±\86రిపివà±\87యబడిà°\82ది",
+       "watchlistedit-clear-title": "వీక్షణజాబితా చెరిపివేయి",
        "watchlistedit-clear-legend": "వీక్షణజాబితా చెరిపివేయి",
        "watchlistedit-clear-titles": "శీర్షికలు:",
        "watchlistedit-clear-submit": "వీక్షణ జాబితా శుభ్రం చేయి (ఇది శాశ్వతం!)",
        "tags-edit-add": "ఈ ట్యాగులను చేర్చు:",
        "tags-edit-remove": "ఈ ట్యాగులను తొలగించు:",
        "tags-edit-reason": "కారణం:",
-       "tags-edit-success": "మారà±\8dà°ªà±\81à°²à±\81 à°µà°¿à°\9cయవà°\82à°¤à°\82à°\97à°¾ à°\86పాదిà°\82à°\9aబడà±\8dడాయి.",
+       "tags-edit-success": "మార్పులు ఆపాదించబడ్డాయి.",
        "comparepages": "పుటల పోలిక",
        "compare-page1": "పుట 1",
        "compare-page2": "పుట 2",
        "htmlform-cloner-create": "ఇంకా చేర్చు",
        "htmlform-cloner-delete": "తొలగించు",
        "htmlform-cloner-required": "కనీసం ఒక విలువు అయినా ఇవ్వాలి.",
+       "htmlform-date-placeholder": "YYYY-MM-DD",
+       "htmlform-time-placeholder": "HH:MM:SS",
+       "htmlform-datetime-placeholder": "YYYY-MM-DD HH:MM:SS",
        "logentry-delete-delete": "$1 $3 పేజీని {{GENDER:$2|తొలగించారు}}",
        "logentry-delete-restore": "పేజీ $3 ని $1 {{GENDER:$2|పునస్థాపించారు}}",
        "logentry-delete-event": "$3 లో {{PLURAL:$5|ఒక లాగ్ ఘటన|$5 లాగ్ ఘటనల}} యొక్క కన్పట్టటాన్ని (విజిబిలిటీ) $1 {{GENDER:$2|మార్చారు}}: $4",
        "expand_templates_generate_xml": "XML పార్స్ ట్రీని చూపించు",
        "expand_templates_generate_rawhtml": "ముడి HTML ను చూపించు",
        "expand_templates_preview": "మునుజూపు",
-       "pagelanguage": "పేజీ భాష ఎంపిక",
+       "pagelanguage": "పేజీ భాషను మార్చు",
        "pagelang-name": "పేజీ",
        "pagelang-language": "భాష",
        "pagelang-use-default": "అప్రమేయ భాషను వాడు",
        "action-pagelang": "పేజీ భాషను మార్చే",
        "log-name-pagelang": "భాష మార్పుల చిట్టా",
        "log-description-pagelang": "ఇది పేజీ భాష మార్పుల చిట్టా.",
-       "logentry-pagelang-pagelang": "$3 à°ªà±\87à°\9cà±\80 à°­à°¾à°·à°¨à±\81 $4 à°¨à±\81à°\82à°¡à°¿ $5 à°\95à°¿ $1 {{GENDER:$2|మారà±\8dà°\9aారà±\81}}.",
+       "logentry-pagelang-pagelang": "$3 భాషను $4 నుండి $5 కి $1 {{GENDER:$2|మార్చారు}}.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (చేతనం)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>అచేతనం</strong>)",
        "mediastatistics": "మాధ్యమ గణాంకాలు",
        "mw-widgets-dateinput-no-date": "ఏ తేదీనీ ఎంచుకోలేదు",
        "mw-widgets-titleinput-description-new-page": "పేజీ ఇంకా లేదు",
        "log-action-filter-all": "అన్నీ",
+       "authmanager-email-label": "ఈమెయిలు",
+       "authmanager-email-help": "ఈమెయిలు చిరునామా",
        "authmanager-realname-label": "అసలు పేరు",
        "authmanager-realname-help": "వాడుకరి అసలు పేరు",
        "authmanager-provider-temporarypassword": "తాత్కాలిక సంకేతపదం",
index a224d42..15341c8 100644 (file)
        "nocreate-loggedin": "Ó la bele kria pájina foun.",
        "permissionserrorstext": "Ó la bele halo ne'e; {{PLURAL:$1|motivu|motivu sira}}:",
        "permissionserrorstext-withaction": "Ita la bele $2. {{PLURAL:$1|Razaun|Razaun sira}}:",
-       "cantcreateaccounttitle": "La bele registrar uza-na'in",
        "currentrev": "Versaun atuál",
        "revisionasof": "Versaun $1 nian",
        "revision-info": "Revisaun loron $4, tempu $5, husi $2",
        "linksearch-ns": "Espasu pájina nian:",
        "linksearch-ok": "Buka",
        "listusers-submit": "Hatudu",
-       "activeusers-hidebots": "Subar bot sira",
-       "activeusers-hidesysops": "Subar administradór sira",
        "listgrouprights-group": "Grupu",
        "listgrouprights-rights": "Priviléjiu",
        "listgrouprights-members": "(lista membru nian)",
index f7826ab..77ac744 100644 (file)
        "yourpasswordagain": "Калимаи убурро боз нависед",
        "createacct-yourpasswordagain": "Тасдиқи гузарвожа",
        "createacct-yourpasswordagain-ph": "Гузарвожаро бори дигар ворид кунед",
-       "remembermypassword": "Вуруди манро дар ин мурургар дар хотир нигоҳ дор (то ҳадди аксар $1 {{PLURAL:$1|рӯз|рӯз}})",
        "userlogin-remembermypassword": "Вурудшуда манро нигоҳ дор",
        "userlogin-signwithsecure": "Истифодаи пайвастшавии амн",
        "yourdomainname": "Домейни Шумо",
        "undo-success": "Ин вироиш метавонад ботил шавад. Лутфан муқоисаи зеринро барои таъйид кардани амалӣ худ, баррасӣ кунед, ва баъдан барои анҷом додани ботилкунии вироиш тағйироти зеринро захира кунед.",
        "undo-failure": "Ба иллати бархӯрдани вироишҳои дар миён омада, ин вироишро ботил наметавон кард.",
        "undo-summary": "Ботили нусхаи $1 аз тарафи [[Special:Contributions/$2|$2]] ([[User talk:$2|Баҳс]])",
-       "cantcreateaccounttitle": "Ҳисобе сохта наметавонам",
        "cantcreateaccount-text": "Имкони сохтани ҳисоби корбарӣ аз ин нишонаи IP ('''$1''') аз тарафи [[User:$3|$3]] баста шудааст.\n\nДалели $3 чунин аст ''$2''",
        "viewpagelogs": "Намоиши гузоришҳои марбута ба ин саҳифа",
        "nohistory": "Таърихи вироиш барои ин саҳифа вуҷуд надорад.",
index 6340644..a577ebe 100644 (file)
        "yourname": "Nomi korbar",
        "yourpassword": "Kalimai ubur\\parolь",
        "yourpasswordagain": "Kalimai uburro boz navised",
-       "remembermypassword": "Vurudi manro dar in mururgar dar xotir nigoh dor (to haddi aksar $1 {{PLURAL:$1|rūz|rūz}})",
        "yourdomainname": "Domejni Şumo",
        "externaldberror": "Xatoe dar irtibot bo pojgohi doda rux doda ast jo in ki şumo içozat ba rūzrasoniji hisobi beruniji xudro nadored.",
        "login": "Vurud",
        "undo-success": "In viroiş metavonad botil şavad. Lutfan muqoisai zerinro baroi ta'jid kardani amalī xud, barrasī kuned, va ba'dan baroi ançom dodani botilkuniji viroiş taƣjiroti zerinro zaxira kuned.",
        "undo-failure": "Ba illati barxūrdani viroişhoi dar mijon omada, in viroişro botil nametavon kard.",
        "undo-summary": "Botili nusxai $1 az tarafi [[Special:Contributions/$2|$2]] ([[User talk:$2|Bahs]])",
-       "cantcreateaccounttitle": "Hisobe soxta nametavonam",
        "cantcreateaccount-text": "Imkoni soxtani hisobi korbarī az in nişonai IP ('''$1''') az tarafi [[User:$3|$3]] basta şudaast.\n\nDaleli $3 cunin ast ''$2''",
        "viewpagelogs": "Namoişi guzorişhoi marbuta ba in sahifa",
        "nohistory": "Ta'rixi viroiş baroi in sahifa vuçud nadorad.",
index 656ea39..bf81066 100644 (file)
@@ -26,7 +26,8 @@
                        "Pilarbini",
                        "Matma Rex",
                        "B20180",
-                       "Pon44695"
+                       "Pon44695",
+                       "Aefgh39622"
                ]
        },
        "tog-underline": "การขีดเส้นใต้ลิงก์:",
@@ -54,7 +55,7 @@
        "tog-enotifminoredits": "อีเมลหาเช่นกันสำหรับการแก้ไขหน้าและไฟล์เล็กน้อย",
        "tog-enotifrevealaddr": "เปิดเผยที่อยู่อีเมลของฉันในอีเมลแจ้งเตือน",
        "tog-shownumberswatching": "แสดงจำนวนผู้ใช้ที่เฝ้าดู",
-       "tog-oldsig": "ลายà¹\80à¸\8bà¹\87à¸\99à¸\97ีà¹\88à¹\83à¸\8aà¹\89อยู่:",
+       "tog-oldsig": "ลายà¹\80à¸\8bà¹\87à¸\99à¸\97ีà¹\88à¸\84ุà¸\93มีอยู่:",
        "tog-fancysig": "ถือลายเซ็นเป็นข้อความวิกิ (โดยไม่มีลิงก์อัตโนมัติ)",
        "tog-uselivepreview": "ใช้การแสดงตัวอย่างแบบสด",
        "tog-forceeditsummary": "เตือนเมื่อช่องคำอธิบายอย่างย่อว่าง",
@@ -71,7 +72,7 @@
        "tog-showhiddencats": "แสดงหมวดหมู่ที่ซ่อนอยู่",
        "tog-norollbackdiff": "ไม่แสดงผลต่างหลังดำเนินการย้อนกลับฉุกเฉิน",
        "tog-useeditwarning": "เตือนฉันเมื่อออกหน้าแก้ไขโดยมีการเปลี่ยนแปลงที่ยังไม่บันทึก",
-       "tog-prefershttps": "à¹\83à¸\8aà¹\89à¸\81ารà¹\80à¸\8aืà¹\88อมà¸\95à¹\88อà¸\9bลอà¸\94ภัยà¸\97ุà¸\81à¸\84รัà¹\89à¸\87à¹\80มืà¹\88อลà¹\87อà¸\81อิà¸\99",
+       "tog-prefershttps": "à¹\83à¸\8aà¹\89à¸\81ารà¹\80à¸\8aืà¹\88อมà¸\95à¹\88อà¸\9bลอà¸\94ภัยà¸\97ุà¸\81à¸\84รัà¹\89à¸\87à¹\80มืà¹\88อà¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9aà¹\81ลà¹\89ว",
        "underline-always": "ทุกครั้ง",
        "underline-never": "ไม่",
        "underline-default": "ค่าโดยปริยายของหน้าตาหรือเบราว์เซอร์",
        "october-date": "$1 ตุลาคม",
        "november-date": "$1 พฤศจิกายน",
        "december-date": "$1 ธันวาคม",
+       "period-am": "ก่อนเที่ยง",
+       "period-pm": "หลังเที่ยง",
        "pagecategories": "{{PLURAL:$1|หมวดหมู่|หมวดหมู่}}",
        "category_header": "หน้าในหมวดหมู่ \"$1\"",
        "subcategories": "หมวดหมู่ย่อย",
        "newwindow": "(เปิดหน้าต่างใหม่)",
        "cancel": "ยกเลิก",
        "moredotdotdot": "ดูเพิ่ม...",
-       "morenotlisted": "รายการนี้ไม่สมบูรณ์",
+       "morenotlisted": "รายà¸\81ารà¸\99ีà¹\89อาà¸\88à¹\84มà¹\88สมà¸\9aูรà¸\93à¹\8c",
        "mypage": "หน้า",
        "mytalk": "พูดคุย",
        "anontalk": "พูดคุย",
        "talk": "อภิปราย",
        "views": "ดู",
        "toolbox": "เครื่องมือ",
+       "tool-link-userrights": "เปลี่ยนกลุ่ม{{GENDER:$1|ผู้ใช้}}",
+       "tool-link-userrights-readonly": "ดูกลุ่ม{{GENDER:$1|ผู้ใช้}}",
+       "tool-link-emailuser": "ส่งอีเมลหา{{GENDER:$1|ผู้ใช้}}นี้",
        "userpage": "ดูหน้าผู้ใช้",
        "projectpage": "ดูหน้าโครงการ",
        "imagepage": "ดูหน้าไฟล์",
        "pool-timeout": "หมดเวลารอกำลังรอล็อก",
        "pool-queuefull": "พื้นที่รองรับคิวเต็ม",
        "pool-errorunknown": "เกิดข้อผิดพลาดไม่ทราบสาเหตุ",
+       "pool-servererror": "บริการพูลเคาน์เตอร์ไม่พร้อมใช้งาน ($1)",
+       "poolcounter-usage-error": "เกิดข้อผิดพลาดในการใช้งาน: $1",
        "aboutsite": "เกี่ยวกับ{{SITENAME}}",
        "aboutpage": "Project:เกี่ยวกับ",
        "copyright": "เนื้อหาอนุญาตให้เผยแพร่ภายใต้ $1 เว้นแต่ระบุไว้เป็นอย่างอื่น",
        "readonly_lag": "ฐานข้อมูลถูกล็อกอัตโนมัติขณะที่เซิร์ฟเวอร์ฐานข้อมูลรองกำลังปรับปรุงตามฐานข้อมูลหลัก",
        "internalerror": "ข้อผิดพลาดภายใน",
        "internalerror_info": "เกิดข้อผิดพลาดภายใน: $1",
-       "filecopyerror": "ไม่สามารถคัดลอกไฟล์ \"$1\" ไป \"$2\"",
+       "internalerror-fatal-exception": "การยกเว้นข้อผิดพลาดร้ายแรงของประเภท \"$1\"",
+       "filecopyerror": "ไม่สามารถคัดลอกไฟล์ \"$1\" ไปยัง \"$2\" ได้",
        "filerenameerror": "ไม่สามารถเปลี่ยนชื่อไฟล์ \"$1\" เป็น \"$2\"",
        "filedeleteerror": "ไม่สามารถลบไฟล์ \"$1\"",
        "directorycreateerror": "ไม่สามารถสร้างสารบบ \"$1\"",
+       "directoryreadonlyerror": "ไดเรกทอรี \"$1\" อ่านได้อย่างเดียว",
+       "directorynotreadableerror": "ไดเรกทอรี \"$1\" ไม่สามารถอ่านได้",
        "filenotfound": "ไม่พบไฟล์ \"$1\"",
        "unexpected": "ค่าไม่คาดหมาย: \"$1\"=\"$2\"",
        "formerror": "มีข้อผิดพลาด: ส่งแบบไม่ได้",
        "yourpasswordagain": "พิมพ์รหัสผ่านอีกครั้ง:",
        "createacct-yourpasswordagain": "ยืนยันรหัสผ่าน",
        "createacct-yourpasswordagain-ph": "กรอกรหัสผ่านอีกครั้ง",
-       "remembermypassword": "จำการล็อกอินของฉันบนเบราเซอร์นี้ (นานสุด $1 วัน)",
        "userlogin-remembermypassword": "ให้ฉันอยู่ในระบบต่อ",
        "userlogin-signwithsecure": "ใช้การเชื่อมต่อที่ปลอดภัย",
+       "cannotlogin-title": "ไม่สามารถเข้าสู่ระบบได้",
+       "cannotlogin-text": "ไม่สามารถเข้าสู่ระบบได้",
        "cannotloginnow-title": "ไม่สามารถล็อกเอาต์ได้ขณะนี้",
        "cannotloginnow-text": "ไม่สามารถล็อกเอาต์ได้เมื่อกำลังใช้ $1",
+       "cannotcreateaccount-title": "ไม่สามารถสร้างบัญชีได้",
+       "cannotcreateaccount-text": "การสร้างบัญชีโดยตรงไม่ได้เปิดใช้งานบนวิกินี้",
        "yourdomainname": "โดเมนของคุณ:",
        "password-change-forbidden": "คุณไม่สามารถเปลี่ยนรหัสผ่านบนวิกินี้",
        "externaldberror": "มีข้อผิดพลาดของฐานข้อมูลการพิสูจน์ตัวจริง หรือคุณไม่ได้รับอนุญาตให้ปรับบัญชีภายนอกของคุณ",
        "eauthentsent": "อีเมลยืนยันถูกส่งไปยังที่อยู่อีเมลที่ระบุไว้แล้ว \nก่อนที่อีเมลอื่นจะถูกส่งไปยังบัญชีนั้น คุณต้องปฏิบัติตามคำสั่งในอีเมลเพื่อยืนยันว่าบัญชีนั้นเป็นของคุณจริง ๆ",
        "throttled-mailpassword": "อีเมลตั้งรหัสผ่านใหม่ถูกส่งไปแล้วใน $1 ชั่วโมงที่ผ่านมา \nอีเมลตั้งรหัสผ่านใหม่จะส่งไปหนึ่งครั้งต่อ $1 ชั่วโมงเท่านั้น เพื่อป้องกันการกระทำผิด",
        "mailerror": "ข้อผิดพลาดในการส่งเมล: $1",
-       "acct_creation_throttle_hit": "ผู้เข้าชมวิกินี้ที่ใช้เลขที่อยู่ไอพีของคุณ ได้สร้าง $1 บัญชีแล้วในวันที่ผ่านมา ซึ่งเป็นจำนวนสูงสุดที่อนุญาตในช่วงเวลาดังกล่าว\nจึงส่งผลให้ผู้เข้าชมที่ใช้เลขที่อยู่ไอพีนี้ ไม่สามารถสร้างบัญชีได้อีกในขณะนี้",
+       "acct_creation_throttle_hit": "ผู้เข้าชมวิกินี้ที่ใช้เลขที่อยู่ไอพีของคุณ ได้สร้าง {{PLURAL:$1|1 บัญชี|$1 บัญชี}}แล้วเมื่อ $2 ผ่านมา ซึ่งเป็นจำนวนสูงสุดที่อนุญาตในช่วงเวลาดังกล่าว\nจึงส่งผลให้ผู้เข้าชมที่ใช้เลขที่อยู่ไอพีนี้ ไม่สามารถสร้างบัญชีได้อีกในขณะนี้",
        "emailauthenticated": "ยืนยันที่อยู่อีเมลของคุณเมื่อวันที่ $2 เวลา $3",
        "emailnotauthenticated": "ที่อยู่อีเมลของคุณยังไม่ได้รับการยืนยัน \nจะไม่มีการส่งอีเมลสำหรับคุณลักษณะใด ๆ ต่อไปนี้",
        "noemailprefs": "ระบุที่อยู่อีเมลในการตั้งค่าของคุณเพื่อให้คุณลักษณะเหล่านี้ทำงานได้",
        "passwordreset-emaildisabled": "วิกินี้ปิดใช้งานคุณลักษณะอีเมล",
        "passwordreset-username": "ชื่อผู้ใช้:",
        "passwordreset-domain": "โดเมน:",
-       "passwordreset-capture": "ดูอีเมลที่ได้หรือไม่",
-       "passwordreset-capture-help": "หากคุณเลือกกล่องนี้ จะแสดงอีเมลดังกล่าว (พร้อมรหัสผ่านชั่วคราว) แก่คุณ เช่นเดียวกับส่งไปยังผู้ใช้",
        "passwordreset-email": "ที่อยู่อีเมล:",
        "passwordreset-emailtitle": "รายละเอียดบัญชีบน {{SITENAME}}",
        "passwordreset-emailtext-ip": "บางคน (ซึ่งอาจเป็นคุณ จากเลขที่อยู่ไอพี $1) ขอตั้งรหัสผ่านของคุณใหม่บน{{SITENAME}} ($4) บัญชีผู้ใช้ดังกล่าวเกี่ยวข้องกับที่อยู่อีเมลนี้:\n\n$2\n\n{{PLURAL:$3|รหัสผ่านชั่วคราวนี้|รหัสผ่านชั่วคราวเหล่านี้}}จะหมดอายุใน $5 วัน\nตอนนี้คุณควรล็อกอินและเลือกรหัสผ่านใหม่ หากบุคคลอื่นขอตั้งรหัสผ่านใหม่นี้ หรือคุณจำรหัสผ่านเดิมของคุณได้แล้ว และคุณไม่ต้องการเปลี่ยนรหัสผ่านอีก คุณอาจละเลยข้อความนี้และใช้รหัสผ่านเดิมของคุณต่อไป",
        "minoredit": "เป็นการแก้ไขเล็กน้อย",
        "watchthis": "เฝ้าดูหน้านี้",
        "savearticle": "บันทึกหน้า",
+       "savechanges": "บันทึกการเปลี่ยนแปลง",
        "publishpage": "เผยแพร่หน้า",
        "preview": "ตัวอย่าง",
        "showpreview": "แสดงตัวอย่าง",
        "searchprofile-advanced-tooltip": "ค้นหาในเนมสเปซที่เลือกเอง",
        "search-result-size": "$1 ($2 คำ)",
        "search-result-category-size": "$1 สมาชิก ($2 หมวดหมู่ย่อย, $3 ไฟล์)",
-       "search-redirect": "(เปลี่ยนทาง $1)",
+       "search-redirect": "(เปลี่ยนทางจาก $1)",
        "search-section": "(ส่วน $1)",
        "search-category": "(หมวดหมู่ $1)",
        "search-file-match": "(เนื้อหาไฟล์ตรง)",
        "prefs-help-recentchangescount": "นี่รวมถึงการปรับปรุงล่าสุด ประวิติหน้า และปูม",
        "prefs-help-watchlist-token2": "นี่คือแป้นลับสำหรับเข้าการป้อนเว็บรายการเฝ้าดูของคุณ\nใครก็ตามที่ทราบจะสามารถอ่านรายการเฝ้าดูของคุณได้ ฉะนั้นอย่าบอกผู้อื่น\n[[Special:ResetTokens|คลิกที่นี่หากคุณต้องการตั้งใหม่]]",
        "savedprefs": "บันทึกการตั้งค่าของคุณแล้ว",
-       "savedrights": "à¸\9aัà¸\99à¸\97ึà¸\81สิà¸\97à¸\98ิผู้ใช้ของ {{GENDER:$1|$1}} แล้ว",
+       "savedrights": "à¸\9aัà¸\99à¸\97ึà¸\81à¸\81ลุà¹\88มผู้ใช้ของ {{GENDER:$1|$1}} แล้ว",
        "timezonelegend": "เขตเวลา:",
        "localtime": "เวลาท้องถิ่น:",
        "timezoneuseserverdefault": "ใช้ค่าโดยปริยายของวิกิ ($1)",
        "userrights-reason": "เหตุผล:",
        "userrights-no-interwiki": "คุณไม่มีสิทธิแก้ไขสิทธิผู้ใช้บนวิกิอื่น",
        "userrights-nodatabase": "ไม่มีฐานข้อมูล $1 หรือฐานข้อมูลอยู่บนเครื่องอื่น",
-       "userrights-nologin": "คุณต้อง[[Special:UserLogin|ล็อกอิน]]ด้วยบัญชีผู้ดูแลระบบก่อน จึงจะกำหนดสิทธิผู้ใช้ได้",
-       "userrights-notallowed": "บัญชีของคุณไม่มีสิทธิเพิ่มหรือเพิกถอนสิทธิผู้ใช้",
        "userrights-changeable-col": "กลุ่มที่คุณสามารถเปลี่ยนได้",
        "userrights-unchangeable-col": "กลุ่มที่คุณไม่สามารถเปลี่ยนได้",
        "userrights-conflict": "พบการเปลี่ยนแปลงสิทธิผู้ใช้ขัดกัน! โปรดทบทวนและยืนยันการเปลี่ยนแปลงของคุณ",
-       "userrights-removed-self": "คุณเพิกถอนสิทธิของคุณสำเร็จแล้ว ฉะนั้น คุณจึงไม่สามารถเข้าถึงหน้านี้ได้อีก",
        "group": "กลุ่ม:",
        "group-user": "ผู้ใช้",
        "group-autoconfirmed": "ผู้ใช้ทั่วไป",
        "right-siteadmin": "ล็อกและปลดล็อกฐานข้อมูล",
        "right-override-export-depth": "ส่งออกหน้า รวมหน้าที่เชื่อมโยงกับหน้านี้สูงสุด 5 ลำดับชั้น",
        "right-sendemail": "ส่งอีเมลหาผู้ใช้อื่น",
-       "right-passwordreset": "ดูอีเมลตั้งรหัสผ่านใหม่",
        "grant-group-email": "ส่งอีเมล",
        "grant-createaccount": "สร้างบัญชี",
        "grant-createeditmovepage": "สร้าง แก้ไข และย้ายหน้า",
        "activeusers-intro": "นี่คือรายการผู้ใช้ที่มีกิจกรรมใด ๆ ในช่วง $1 วันหลังสุด",
        "activeusers-count": "$1 ปฏิบัติการ{{PLURAL:$1|}} ในช่วง $3 วันหลังสุด",
        "activeusers-from": "แสดงผู้ใช้เริ่มจาก:",
-       "activeusers-hidebots": "ซ่อนบอต",
-       "activeusers-hidesysops": "ซ่อนผู้ดูแลระบบ",
        "activeusers-noresult": "ไม่พบผู้ใช้",
        "activeusers-submit": "แสดงผู้ใช้ที่ยังมีกิจกรรม",
        "listgrouprights": "สิทธิกลุ่มผู้ใช้",
        "thumbnail_error": "มีข้อผิดพลาดในการสร้างรูปย่อ: $1",
        "djvu_page_error": "หน้าเดจาวู (DjVu) เกินขนาด",
        "djvu_no_xml": "ไม่สามารถส่งเอกซ์เอ็มแอล (XML) สำหรับไฟล์เดจาวู (DjVu)",
+       "thumbnail-dest-create": "ไม่สามารถบันทึกรูปย่อลงในปลายทางได้",
        "thumbnail_invalid_params": "พารามิเตอร์รูปย่อไม่ถูกต้อง",
        "thumbnail_dest_directory": "ไม่สามารถสร้างสารบบปลายทาง",
        "thumbnail_image-type": "ไม่รองรับรูปแบบของไฟล์รูปภาพนี้",
        "htmlform-no": "ไม่",
        "htmlform-yes": "ใช่",
        "htmlform-chosen-placeholder": "เลือกตัวเลือก",
+       "htmlform-cloner-create": "เพิ่มอีก",
        "htmlform-cloner-required": "ต้องการอย่างน้อยหนึ่งค่า",
        "htmlform-title-badnamespace": "[[:$1]] ไม่อยู่ในเนมสเปซ \"{{ns:$2}}\"",
        "htmlform-title-not-creatable": "\"$1\" มิใช่ชื่อเรื่องหน้าที่สร้างได้",
        "htmlform-title-not-exists": "ไม่มี $1",
        "htmlform-user-not-exists": "ไม่มี <strong>$1</strong>",
        "htmlform-user-not-valid": "<strong>$1</strong> มิใช่ชื่อผู้ใช้ที่สมเหตุสมผล",
-       "sqlite-has-fts": "รุ่น $1 พร้อมการสนับสนุนการค้นหาข้อความแบบเต็ม",
-       "sqlite-no-fts": "รุ่น $1 โดยไม่มีการสนับสนุนการค้นหาข้อความแบบเต็ม",
        "logentry-delete-delete": "$1 ลบหน้า $3",
        "logentry-delete-restore": "$1 กู้คืนหน้า $3",
        "logentry-delete-event": "$1 เปลี่ยนทัศนวิสัยของ $5 รายการปูมใน $3: $4",
        "feedback-subject": "เรื่อง:",
        "feedback-submit": "ตกลง",
        "feedback-thanks": "ขอบคุณ! ผลป้อนกลับของคุณถูกโพสต์ไปยังหน้า \"[$2 $1]\" แล้ว",
-       "searchsuggest-search": "ค้นหา",
+       "searchsuggest-search": "ค้นหา {{SITENAME}}",
        "searchsuggest-containing": "มี...",
        "api-error-badaccess-groups": "คุณไม่ได้รับอนุญาตให้อัปโหลดไฟล์มายังวิกินี้",
        "api-error-empty-file": "ไฟล์ที่คุณส่งมานั้นว่าง",
        "api-error-filename-tooshort": "ชื่อไฟล์สั้นเกินไป",
        "api-error-filetype-banned": "ไฟล์ประเภทนี้ถูกห้าม",
        "api-error-mustbeloggedin": "กรุณาลงชื่อเข้าใช้เพื่ออัปโหลดไฟล์",
+       "api-error-ratelimited": "คุณกำลังพยายามอัปโหลดไฟล์ภายในระยะห่างเวลาที่สั้นเกินกว่าที่วิกินี้อนุญาต\nโปรดรอสักครู่แล้วลองใหม่อีกครั้ง",
        "api-error-uploaddisabled": "การอัปโหลดถูกปิดใช้งานบนวิกินี้",
        "duration-seconds": "$1 วินาที",
        "duration-minutes": "$1 นาที",
index 7ec316c..5d6b0b2 100644 (file)
        "yourname": "Ulanyjy adyňyz:",
        "yourpassword": "Parolyňyz:",
        "yourpasswordagain": "Paroly gaýtadan ýaz:",
-       "remembermypassword": "Sessiýamy şu kompýuterde ýatda sakla  (iň köp $1 {{PLURAL:$1|günläp|günläp}})",
        "yourdomainname": "Siziň domeniňiz:",
        "externaldberror": "Ýa tassyklama maglumat bazasynyň säwligi bar ýa-da öz ulanyjy hasabyňyzy täzelemegiňize rugsat berilmeýär.",
        "login": "Hasaba gir",
        "undo-failure": "Gapma-garşylykly aralyk özgerdişler zerarly bu özgerdişi yzyna alyp bolmaýar.",
        "undo-norev": "Özgerdişi yzyna alyp bolmaýar, sebäbi ol ýok ýa-da öçürilipdir.",
        "undo-summary": "$1 wersiýasy [[Special:Contributions/$2|$2]] ([[User talk:$2|Çekişme]]) tarapyndan yzyna alyndy.",
-       "cantcreateaccounttitle": "Hasap döredip bolmaýar",
        "cantcreateaccount-text": "Bu IP adresinden ('''$1''') ulanyjy hasaby döretmeklik [[User:$3|$3]] tarapyndan blokirlenipdir.\n\n$3 tarapyndan görkezilen sebäp: ''$2''",
        "viewpagelogs": "Bu sahypanyň gündeliklerini görkez",
        "nohistory": "Bu sahypanyň özgerdişler geçmişi ýok.",
        "activeusers-intro": "Bu sanawda soňky $1 {{PLURAL:$1|günüň|günüň}} dowamynda nähilidir bir iş geçiren ulanyjylar görkezilýär.",
        "activeusers-count": "Soňky {{PLURAL:$3|günde|$3 günde}} $1 sany {{PLURAL:$1|özgerdiş|özgerdiş}}",
        "activeusers-from": "Şunuň bilen başlaýan ulanyjylary görkez:",
-       "activeusers-hidebots": "Botlary gizle",
-       "activeusers-hidesysops": "Administratorlary gizle",
        "activeusers-noresult": "Ulanyjy tapylmady.",
        "listgrouprights": "Ulanyjy topary hukuklary",
        "listgrouprights-summary": "Aşakda şu wikide kesgitlenen ulanyjy toparlarynyň hem-de olaryň degişli ulanmak hukuklarynyň sanawy berilýär.\nŞahsy hukuklar barada [[{{MediaWiki:Listgrouprights-helppage}}|goşmaça maglumat]] bar bolup biler.",
        "htmlform-submit": "Tabşyr",
        "htmlform-reset": "Üýtgeşmeleri yzyna al",
        "htmlform-selectorother-other": "Başga",
-       "sqlite-has-fts": "$1 (doly tekstli gözleg goldawly)",
-       "sqlite-no-fts": "$1 (doly tekstli gözleg goldawsyz)",
        "revdelete-restricted": "administratorlara goýlan çäklendirmeler",
        "revdelete-unrestricted": "administratorlardan aýyrylan çäklendirmeler",
        "rightsnone": "(hiç biri)",
index d8af709..405d823 100644 (file)
        "tags-create-submit": "Lumikha/Lumalang",
        "tags-activate-reason": "Dahilan:",
        "tags-deactivate-reason": "Dahilan:",
+       "tags-apply-blocked": "Hindi pwedeng i-apply ang mga tarheta (kasama ng pagbago) habang ikaw ay sinupalpal.",
        "comparepages": "Paghambingin ang mga pahina",
        "compare-page1": "Pahina 1",
        "compare-page2": "Pahina 2",
index 6a78e81..b9f1bc2 100644 (file)
        "yourname": "Иштирокәкә ном:",
        "yourpassword": "Парол:",
        "yourpasswordagain": "Пароли сәнибәтон гырдә карде:",
-       "remembermypassword": "Мыни ым компутерәдә јодәдә огәт (максимум $1 {{PLURAL:$1|руж|руж}})",
        "login": "Ыштәни едаштеј",
        "nav-login-createaccount": "Ыштәни едаштеј / ыштәни ғејд кардовнијеј",
        "userlogin": "Ыштәни едаштеј / ыштәни ғејд кардовнијеј",
index dd64e03..812e34d 100644 (file)
        "yourname": "Hingoa ʻetita",
        "yourpassword": "Leatapu",
        "yourpasswordagain": "Toe ʻai leatapu",
-       "remembermypassword": "Manatuʻi au (for a maximum of $1 {{PLURAL:$1|day|days}})",
        "yourdomainname": "ho ngāueʻanga",
        "login": "Kau ki ai",
        "nav-login-createaccount": "Kau ki ai",
        "templatesusedpreview": "Ngaahi sīpinga ʻoku ngāueʻaki he vakaí ni:",
        "templatesusedsection": "Ngaahi sīpinga ʻoku ngāueʻaki he kongá ni:",
        "nocreatetext": "Naʻe fakangatangata ʻe he tuʻuʻangá ni ʻa e lava ke fakatupu ha peesi foʻou. ʻOku ke lava ke foki pea fatu ha peesi tuʻu, pe [[Special:UserLogin|kau-ki-ai, pe fakatupu ha tohi-kau-ki-ai]].",
-       "cantcreateaccounttitle": "ʻOku ʻikai lava fakatupu e tohi kau-ki-ai",
        "viewpagelogs": "Vakai ki he ngaahi tohinoa ʻo e pēsí ni",
        "nohistory": "ʻOku ʻikai ʻi ai ha hisitōlia fatu maʻa e kupú ni.",
        "currentrev": "Paaki taka",
index 0e572ce..abde066 100644 (file)
        "viewsource": "Lukim as tok",
        "yourname": "Yusanem:",
        "yourpassword": "Paswot:",
-       "remembermypassword": "Holim yusanem bilong mi long dispela komputa (holim pas longpela taim $1 {{PLURAL:$1|de|de}})",
        "login": "Log in",
        "userloginnocreate": "Log in",
        "logout": "Logaut",
index 735038a..a37a699 100644 (file)
@@ -88,7 +88,8 @@
                        "Kumkumuk",
                        "Basak",
                        "Ece Alpdeniz",
-                       "Superyetkin"
+                       "Superyetkin",
+                       "Alikaan"
                ]
        },
        "tog-underline": "Bağlantıların altını çiz:",
        "passwordreset-emaildisabled": "Bu wiki'deki e-posta özellikleri devre dışı bırakıldı.",
        "passwordreset-username": "Kullanıcı adı:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "Sonuç e-postasını görüntüle?",
-       "passwordreset-capture-help": "Bu kutuyu işaretlerseniz, e-posta (geçici şifre ile) size ve yanı sıra kullanıcıya gönderiliyor.",
        "passwordreset-email": "E-posta adresi:",
        "passwordreset-emailtitle": "{{SITENAME}} hesap detayları",
        "passwordreset-emailtext-ip": "Birisi, (muhtemelen siz, $1 IP adresinden) {{SITENAME}} ($4) için hesap bilgilerinizin \nhatırlatılmasını istedi. Aşağıdaki kullanıcı {{PLURAL:$3|hesabı|hesapları}} bu e-posta adresiyle ilişkili:\n\n$2\n\n{{PLURAL:$3|Bu geçici şifre|Bu geçici şifreler}} {{PLURAL:$5|bir gün|$5  gün}} geçerlidir.\nBu geçici parola ile giriş yapın ve yeni bir şifre seçin. Şifre değişimini siz istemediyseniz veya şifrenizi hatırladıysanız ve artık şifrenizi değiştirmek istemiyorsanız; bu iletiyi önemsemeyerek eski şifrenizi kullanmaya devam edebilirsiniz.",
        "passwordreset-emailelement": "Kullanıcı adı: \n$1\n\nGeçici şifre: \n$2",
        "passwordreset-emailsentemail": "Eğer bu e-posta adresi hesabınızın bağlı olduğu adres ise, bir parola sıfırlama e-postası gönderilecektir.",
        "passwordreset-emailsentusername": "Eğer bu e-posta adresi hesabınızın bağlı olduğu adres ise, bir parola sıfırlama e-postası gönderilecektir.",
-       "passwordreset-invalideamil": "Geçersiz e-posta adresi",
+       "passwordreset-invalidemail": "Geçersiz e-posta adresi",
        "passwordreset-nodata": "Ne bir kullanıcı adı ne de bir e-posta adresi verildi.",
        "changeemail": "E-posta adresini değiştir veya çıkar",
        "changeemail-header": "E-posta adresinizi değiştirmek için bu formu doldurun. Eğer e-posta adresini hesabınızdan kaldırmak istiyorsanız formu gönderirken e-posta adresi bölümünü boş bırakın.",
        "search-external": "Dış arama",
        "searchdisabled": "{{SITENAME}} sitesinde arama yapma geçici olarak durdurulmuştur. Bu arada Google kullanarak {{SITENAME}} içinde arama yapabilirsiniz. Arama sitelerinde dizinlerin biraz eski kalmış olabileceğini göz önünde bulundurunuz.",
        "search-error": "Arama yapılırken bir hata oluştu: $1",
+       "search-warning": "Arama yapılırken bir hata oluştu: $1",
        "preferences": "Tercihler",
        "mypreferences": "Tercihler",
        "prefs-edits": "Değişiklik sayısı:",
        "userrights-reason": "Neden:",
        "userrights-no-interwiki": "Diğer vikilerdeki kullanıcıların izinlerini değiştirmeye yetkiniz yok.",
        "userrights-nodatabase": "$1 veritabanı mevcut veya bölgesel değil",
-       "userrights-nologin": "Kullanıcı haklarını atamak için hizmetli hesabı ile [[Special:UserLogin|giriş yapmanız gerekir]].",
-       "userrights-notallowed": "Kullanıcı hakları eklemek veya kaldırmak için izniniz yok.",
        "userrights-changeable-col": "Değiştirebildiğiniz gruplar",
        "userrights-unchangeable-col": "Değiştirebilmediğiniz gruplar",
        "userrights-conflict": "Kullanıcı hakları değişikliklerinde çakışma! Lütfen değişikliklerinizi gözden geçirin ve onaylayın.",
-       "userrights-removed-self": "Kendi haklarınız başarıyla kaldırıldı. Bu nedenle, artık bu sayfaya erişemeyeceksiniz.",
        "group": "Grup:",
        "group-user": "Kullanıcılar",
        "group-autoconfirmed": "Otomatik onaylanmış kullanıcılar",
        "right-siteadmin": "Veritabanını kilitle ve kilidi aç",
        "right-override-export-depth": "Sayfaları, derinlik 5'e kadar bağlantılı sayfalarla beraber, dışa aktar",
        "right-sendemail": "Diğer kullanıcılara e-posta gönder",
-       "right-passwordreset": "Parola sıfırlama e-postalarını görür",
        "right-managechangetags": "Veritabanında [[Special:Tags|etiket]] oluşturma veya silme",
        "right-applychangetags": "Değişiklikleriyle beraber [[Special:Tags|etiketleri]] uygula",
        "right-changetags": "Tekil sürümler ve günlük kayıtlarına rastgele [[Special:Tags|etiket]] ekleme veya çıkarma",
        "booksources-search": "Ara",
        "booksources-text": "Aşağıdaki, yeni ve kullanılmış kitap satan diğer sitelere bağlantıların listesidir, ve aradığınız kitaplar hakkında daha fazla bilgiye sahip olabilirler:",
        "booksources-invalid-isbn": "Verilen ISBN geçersiz gibi görünüyor; orijinal kaynaktan kopyalama hataları için kontrol edin.",
+       "magiclink-tracking-rfc": "RFC sihirli bağlantısını kullanan sayfalar",
+       "magiclink-tracking-pmid": "PMID sihirli bağlantısını kullanan sayfalar",
+       "magiclink-tracking-isbn": "ISBN sihirli bağlantısını kullanan sayfalar",
        "specialloguserlabel": "Kullanıcı:",
        "speciallogtitlelabel": "Hedef (başlık ya da kullanıcı):",
        "log": "Kayıtlar",
        "special-characters-title-emdash": "uzun çizgi",
        "special-characters-title-minus": "Eksi işareti",
        "mw-widgets-dateinput-no-date": "Hiçbir tarih seçilmedi",
+       "mw-widgets-mediasearch-input-placeholder": "Medya ara",
+       "mw-widgets-mediasearch-noresults": "Sonuç bulunamadı.",
        "mw-widgets-titleinput-description-new-page": "sayfa henüz mevcut değil",
        "mw-widgets-titleinput-description-redirect": "$1'e yönlendirildi",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "çerez tabanlı oturumlar",
index 702c294..a32a979 100644 (file)
        "yourname": "Işme duHadomo:",
        "yourpassword": "Qliḍo:",
        "yourpasswordagain": "Naqla ḥreto kṭaw uQliḍo:",
-       "remembermypassword": "Dxar uQliḍayḍi buBrowser (buSowudo $1 {{PLURAL:$1|Yawmo|Yawme}})",
        "login": "3bar",
        "nav-login-createaccount": "3bar / Hway Hadomo",
        "userlogin": "3bar / Hway Hadomo",
index d41c469..6d971d5 100644 (file)
        "yourname": "Vito ra vutirhisi",
        "yourpassword": "Vito-mpfungulo:",
        "yourpasswordagain": "Thlela u hoxa ritompfungulo ra wena:",
-       "remembermypassword": "Tsundzuka ku nghena eka Khompuyuta leyi (kufikela eka $1 {{PLURAL:$1|siku|masiku}})",
        "login": "Pfula u nghena",
        "nav-login-createaccount": "Pfula unghena / Tumbuluxa akhawunti",
        "userlogin": "Pfula unghena / Tumbuluxa akhawunti",
index 5ea66b8..205bf3c 100644 (file)
        "passwordreset-disabled": "Бу викида серсүз бетереп булмый",
        "passwordreset-username": "Кулланучы исеме:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Килеп чыккан хатны күрсәтелсенме?",
-       "passwordreset-capture-help": "Әгәр сез бу тамганы куйсагыз, сезгә кулланучыга вакытлы серсүз белән җибәреләчәк хат күрсәтеләчәк.",
        "passwordreset-email": "E-mail адресы:",
        "passwordreset-emailtitle": "{{SITENAME}} хисап язмасы турында мәгълүматлар",
        "passwordreset-emailtext-ip": "Кемдер (бәлки, сездер, $1 IP-адресыннан) {{SITENAME}} ($4) проектында сезнең серсүзне искә төшерүне сорады.\n{{PLURAL:$3|1=Түбәндәге хисап язмасы|Түбәндәге хисап язмалары}} бу электрон әрҗә адресы белән бәйле:\n\n$2\n\n{{PLURAL:$3|1=Бу вакытлы серсүз|Бу вакытлы серсүзләр}} {{PLURAL:$5|$5 көн}} дәвамында эшлиячәкләр.\nСез системага керергә һәм яңа серсүз сайларга тиешсез.\nӘгәр сез серсүз сорамаган булсагыз яки элеккеге серсүзегезне искә төшерсәгез \nһәм аны үзгәртергә теләмәсәгез, бу хатка җавап бирмәгез\nһәм элеккеге серсүзегезне кулланыгыз.",
        "shown-title": "Сәхифәдә $1 {{PLURAL:$1|язма}} күрсәтелсен",
        "viewprevnext": "Күрсәтелүе: ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "<strong>Бу вики-проектта «[[:$1]]» исемле бит бар инде</strong>{{PLURAL:$2|0=|Башка эзләү нәтиҗәләрен дә карап ал.}}",
-       "searchmenu-new": "<strong>«Әлеге [[:$1]]» вики-проектта бит ясарга!</strong>\n{{PLURAL:$2|0=|Шулай ук, эзләү ярдәмендә табылган битне карагыз.|Шулай ук, эзләү ярдәмендә табылган битләрне карагыз.}}",
+       "searchmenu-new": "<strong>Әлеге вики-проектта «[[:$1]]» исемле бит ясарга!</strong>\n{{PLURAL:$2|0=|Шулай ук, эзләү ярдәмендә табылган битне карагыз.|Шулай ук, эзләү ярдәмендә табылган битләрне карагыз.}}",
        "searchprofile-articles": "Төп битләр",
        "searchprofile-images": "Мультимедиа",
        "searchprofile-everything": "Һәркайда",
        "userrights-reason": "Сәбәп:",
        "userrights-no-interwiki": "Сезнең башка викиларда кулланучыларның хокукларын үзгәртергә хокукларыгыз юк.",
        "userrights-nodatabase": "Бирелгән $1 базасы юк яисә  локаль булып тормый.",
-       "userrights-nologin": "Кулланучыларга вәкаләтләр билгеләү өчен идарәче хисап язмасы белән [[Special:UserLogin|керергә кирәк]]",
-       "userrights-notallowed": "Сезнең кулланучыларга вәкаләтләр тапшырырга яки кире алырга хокукы юк.",
        "userrights-changeable-col": "Сезнең тарафтан үзгәртелми торган төркемнәр",
        "userrights-unchangeable-col": "Сезнең тарафтан үзгәртелми торган төркемнәр",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Кулланучы хокукларын үзгәртү конфликты! Төзәтмәләрегезне тикшерегез, аннары кабатлагыз.",
-       "userrights-removed-self": "Сез үзегезне хокукларыгыздан мәхрүм иттегез. Шул сәбәпле сез бу сәхифәгә башка керә алмыйсыз.",
        "group": "Төркем:",
        "group-user": "Кулланучылар",
        "group-autoconfirmed": "Авторасланган кулланучы",
index 3b5ff02..8e77204 100644 (file)
        "yourpasswordagain": "Sersüzne qabat kertü:",
        "createacct-yourpasswordagain": "Sersüzegezne raslağız",
        "createacct-yourpasswordagain-ph": "Sersüzne yañadan kertegez",
-       "remembermypassword": "Xisap yazmamnı bu brauzerda saqlansın (iñ küp $1 {{PLURAL:$1|kön|kön|kön}}gä qädär)",
        "yourdomainname": "Sezneñ domenığız:",
        "externaldberror": "Tışqı mäğlümat bazası yärdämendä awtentifikatsiä ütkändä xata çıqtı, yäisä tışqı xisap yazmağızğa üzgäreşlär kertü xoquqığız yuq.",
        "login": "Kerü",
        "undo-failure": "Aralıqtağı üzgärtülär turı kilmäw säbäple, üzgärtüdän baş tartıp bulmıy.",
        "undo-norev": "Üzgärtü yuq yäisä ul beterelgän, şuña annan baş tartıp bulmıy.",
        "undo-summary": "[[Special:Contributions/$2|$2]] qullanuçısınıñ ([[User talk:$2|bäxäs]]) $1 üzgärtüennän baş tartu",
-       "cantcreateaccounttitle": "Xisap yazmasın tözep bulmıy",
        "cantcreateaccount-text": "Bu IP adresınnan (<b>$1</b>) xisap yazmaları tözü tıyıla. Tıyuçı: [[User:$3|$3]].\n\n$3 kürsätkän säbäp: ''$2''",
        "viewpagelogs": "Bu bitneñ köndäleklären qaraw",
        "nohistory": "Bu bitneñ üzgärtülär tarixı yuq.",
        "listusers-noresult": "Qullanuçılarnı tabılmadı.",
        "listusers-blocked": "(tıyılğan)",
        "activeusers": "Aktiv qullanuçılar isemlege",
-       "activeusers-hidebots": "Botlarnı yäşer",
-       "activeusers-hidesysops": "İdaräçelärne yäşer",
        "activeusers-noresult": "Qullanuçılar tabılmadı.",
        "listgrouprights": "Qullanuçı törkemnäreneñ xoquqları",
        "listgrouprights-group": "Törkem",
        "feedback-back": "Kire qaytu",
        "feedback-cancel": "Baş tartu",
        "feedback-close": "Yasaldı",
-       "feedback-error-title": "Xata",
        "feedback-message": "Xäbär:",
        "feedback-subject": "Tema:",
        "feedback-submit": "Cibärü",
index 5fff7f1..bac27db 100644 (file)
        "linksearch-ok": "Дилээри",
        "linksearch-line": "$2-де бижиттинген $1 деп тускай айтыг",
        "listusers-submit": "Көргүзери",
-       "activeusers-hidebots": "Роботтарны чажырары",
-       "activeusers-hidesysops": "Эргелекчыларны чажырары",
        "listgrouprights-group": "Бөлүк",
        "listgrouprights-members": "(кежигүннүң даңзызы)",
        "emailuser": "Бо ажыглакчыга э-чагааны чорудаары",
index 5ced470..9e0799e 100644 (file)
@@ -10,7 +10,9 @@
                        "AlnashPiyash2",
                        "Irus",
                        "Shklyaev",
-                       "Wadorgurt"
+                       "Wadorgurt",
+                       "Zpizza",
+                       "Mouse21"
                ]
        },
        "tog-underline": "Чӧлсконъёсыз ултӥз гожен сызоно",
        "noindex-category": "Индексировать каронтэм бамъёс",
        "about": "Та сярысь",
        "article": "Статья",
+       "newwindow": "(усьтӥськоз выль укноын)",
        "cancel": "Берытсконо",
        "mypage": "Бам",
        "mytalk": "Викиавтор сярысь вераськон",
        "view-foreign": "$1 сайтын учконы",
        "edit": "тупатыны",
        "create": "Кылдытоно",
+       "create-local": "Интыысь описаниез ватсаны",
        "editthispage": "Та бамез тупатыны",
        "create-this-page": "Та бамез кылдытыны",
        "delete": "Быдтыны",
        "unprotectthispage": "Та бамлэсь утемзэ воштыны",
        "newpage": "Выль бам",
        "talkpage": "Та бам сярысь вераськыны",
-       "talkpagelinktext": "Ð\92ераськон",
+       "talkpagelinktext": "вераськон",
        "specialpage": "Ваньмыз панель",
        "personaltools": "Нимаз тӥрлыке",
        "articlepage": "Статьяез учкыны",
        "viewtalkpage": "Вераськонэз учкыны",
        "otherlanguages": "Мукет кылъёсын",
        "redirectedfrom": "(Перенаправлять $1)",
-       "redirectpagesub": "Ð\92Ñ\8bжÑ\8bÑ\82он бам",
+       "redirectpagesub": "ЫÑ\81Ñ\82Ó¥Ñ\81Ñ\8c бам",
        "redirectto": "Выжытон:",
        "lastmodifiedat": "Та бамлэн берпуметӥ воштонэз: $2, $1.",
        "protectedpage": "Утем бам",
        "currentevents-url": "Project:Выль иворъёс",
        "disclaimers": "Кыл кутыны пумит луон",
        "disclaimerpage": "Project:Кыл кутыны пумит луон",
+       "edithelp": "Тупатонъя юрттэт",
        "helppage-top-gethelp": "Юрттэт",
        "mainpage": "Кутскон бам",
        "mainpage-description": "Кутскон бам",
        "databaseerror-query": "Курон: $1",
        "databaseerror-function": "Функция: $1",
        "databaseerror-error": "Янгыш: $1",
+       "badtitle": "Умойтэм ним",
+       "badtitletext": "Курем бам ним луэ мыдлань, буш либо кылъёс куспын яке викиос куспын нимыз умойтэм герӟамын.\nНимын, вылды, ярантэм символъёс вань.",
        "viewsource": "Кодзэ учкыны",
        "viewsource-title": "Кодзэ учкыны бам $1",
        "actionthrottled": "Кекатыны ужъёс",
        "welcomecreation-msg": "Тӥляд гожъямъёсты учётной кылдытэмын вал.\nТӥ быгатӥськоды воштэ {{SITENAME}} [[Special:Preferences|параметръёсты]] ке потэ тӥледлы.",
        "yourname": "Пырон ним:",
        "userlogin-yourname": "Пырон ним:",
+       "userlogin-yourname-ph": "Гожтэ учётной записьтылэсь нимзэ",
        "createacct-another-username-ph": "Учётной книга нимъёс пыртэмын",
        "yourpassword": "Лушкемкыл:",
        "userlogin-yourpassword": "Лушкемкыл",
+       "userlogin-yourpassword-ph": "Гожтэ асьтэлэсь парольдэс",
+       "createacct-yourpassword-ph": "Гожтэ паролез",
        "createacct-yourpasswordagain": "Пароль юнматэ",
+       "createacct-yourpasswordagain-ph": "Гожтэ паролез эшшо одӥг пол",
        "userlogin-remembermypassword": "Кылем сӧзнэтэз",
        "cannotcreateaccount-title": "Уг быгатиськы гожъян кылдӥз учётной",
        "yourdomainname": "Тӥ доменэн:",
        "logout": "Кошкыны",
        "userlogout": "Потыны",
        "notloggedin": "Тон эн тусбуяськыны сӧзнэтэз",
+       "userlogin-noaccount": "Ас учётной записьты ӧвӧл?",
+       "userlogin-joinproject": "Проектэ пыриськоно",
        "nologin": "Учётной книга ӧвӧл-а? $1.",
        "nologinlink": "Выль вики-авторлэн регистрациез",
        "createaccount": "выль вики-авторлэн регистрациез",
        "userlogin-helplink2": "Пыронъя юрттэт",
        "createacct-emailrequired": "Электронной почталэн адресэз",
        "createacct-emailoptional": "Электронной почтаезлэн адресэз (необязательное)",
+       "createacct-email-ph": "Гожтэ асьтэлэн электрон почтадылэсь адрессэ",
        "createaccountmail": "Адрес электронной почта огдырлы кутӥ вылын возьматэм образъёсыныз но соослэн случайной сгенерировать пароль ыстыны",
        "createacct-submit": "Выль вики-авторлэн регистрациез",
        "createacct-another-submit": "Выль вики-авторлэн регистрациез",
+       "createacct-benefit-heading": "{{SITENAME}} — тӥ выллем адямиослэн валче ужамзы.",
+       "createacct-benefit-body1": "{{PLURAL:$1|тупатон}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|бам}}",
+       "createacct-benefit-body3": "{{PLURAL:$1|викиавтор}} берло дыре",
        "loginerror": "Янгышъёс пырон",
        "createacct-error": "Янгышъёс бордын учётной книга кылдытыны",
        "createaccounterror": "Уг быгатиськы гожъян учётной кылдоз: $1",
        "pt-userlogout": "Потыны",
        "oldpassword": "Вуж лушкемкыл:",
        "newpassword": "Выль лушкемкыл:",
+       "passwordreset": "Пароль куштыны",
        "passwordreset-username": "Пырон ним:",
+       "italic_sample": "Бекырес текст",
+       "italic_tip": "Бекырес текст",
+       "link_sample": "Чӧлсконлэн йыръянэз",
+       "link_tip": "Пуш чӧлскон",
+       "extlink_sample": "http://www.example.com чӧлсконлэн йыръянэз",
+       "extlink_tip": "Педпала чӧлскон (http:// префиксэз эн вунэтэ)",
+       "headline_sample": "Йыръян текст",
+       "headline_tip": "2-тӥ уровеньем йыръян",
+       "nowiki_sample": "Вики-пусъёсыз санэ басьтытэк кельтоно текстэз пуктэ татчы",
+       "nowiki_tip": "Вики-пусъёсыз лыдэ басьтоно ӧвӧл",
+       "image_tip": "Пыӵатэм файл",
+       "media_tip": "Файл чӧлскон",
+       "sig_tip": "Тӥляд гожтӥськонды но дыр пусъён",
+       "hr_tip": "Горизонтальной гож (эн пыртэ ӵем)",
        "summary": "Мар но малы тупатэмын? (вакчияк):",
        "minoredit": "Ичи воштон",
        "watchthis": "Та бамез чаклан списоке пыртыны",
        "preview": "Бамез эскерон",
        "showpreview": "Бамез эскерон",
        "showdiff": "Пыртэм воштонъёс",
+       "anoneditwarning": "<strong>Сак луэ!</strong> Тӥ сайтэ ӧд пырелэ. Тӥ котькыӵе тупатонъёсыз лэсьтоды бере, тӥляд IP-адресты ваньмызлы адӟытӥськоз. Тӥ <strong>[$1 пыроды]</strong> яке <strong>[$2 учётной записез кылдытоды]</strong> бере, тӥляд тупатонъёсты герӟаськозы нимдылы, мукет пайдаосын ӵош.",
        "blockedtitle": "Заблокировать пыриськисьёс",
-       "blockedtext": "<strong>Ð\9aнигае Ñ\8fке Ñ\83Ñ\87Ñ\91Ñ\82ной IP-адÑ\80еÑ\81 Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ\80ован.</strong>\n\nÐ\91локиÑ\80овка Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñ\81Ñ\82Ñ\80аÑ\82оÑ\80 Ð¿Ð¾Ñ\82ӥз $1.\nÐ\92озÑ\8cмалÑ\8d Ð²Ñ\83оно Ð¼Ñ\83гез: \"\"$2\"\".\n\n* Ð\9aÑ\83Ñ\82Ñ\81кон Ð±Ð»Ð¾ÐºÐ¸Ñ\80овка: $8\n* Ð\91локиÑ\80овка Ð¾Ñ\80Ñ\82Ñ\87из: $6\n* Ð\91локиÑ\80овка Ð¼ÐµÑ\80еÑ\82Ñ\8aÑ\91Ñ\81Ñ\8bз: $7\n\nÐ\91Ñ\8bгаÑ\82Ó¥Ñ\81Ñ\8cкод-а Ñ\82он Ð³ÐµÑ\80Ó\9fаÑ\81Ñ\8cкемÑ\8bн $1 Ñ\8fке Ð¼Ñ\83кеÑ\82 ÐºÐ¾Ñ\82Ñ\8cкÑ\83дӥнÑ\8bз [[{{MediaWiki:Grouppage-sysop}}|админиÑ\81Ñ\82Ñ\80аÑ\82оÑ\80Ñ\8aÑ\91Ñ\81]], Ð±Ð»Ð¾ÐºÐ¸Ñ\80овка Ð¼ÐµÐ´ Ñ\8dÑ\81кеÑ\80озÑ\8b.\nУÑ\87ком, Ð¼Ð°Ñ\80 ÐºÑ\83Ñ\82Ñ\8bнÑ\8b Ñ\83г Ð±Ñ\8bгаÑ\82о Ñ\84Ñ\83нкÑ\86изÑ\8dÑ\81 \"гожÑ\82Ñ\8dÑ\82\", Ð°Ñ\81 ÐºÐµ [[Special:Preferences|наÑ\81Ñ\82Ñ\80ойка Ð¿ÐµÑ\80Ñ\81оналÑ\8cной]] Ð·Ñ\83Ñ\80каÑ\82Ó¥Ñ\81Ñ\8c Ñ\8fке Ñ\8dлекÑ\82Ñ\80онной Ð¿Ð¾Ñ\87Ñ\82аезлÑ\8dн Ð°Ð´Ñ\80еÑ\81Ñ\8dз Ñ\8dн Ñ\87Ñ\83Ñ\80Ñ\82на Ñ\83г ÐºÐ¾Ñ\80Ñ\80екÑ\82нÑ\8bй, Ñ\8fке Ð³Ð¾Ð¶Ñ\82Ó¥Ñ\81Ñ\8cкод ÐºÐµ, Ð³Ð¾Ð¶Ñ\82Ñ\8dÑ\82 Ñ\8bÑ\81Ñ\82он Ñ\83кÑ\88аÑ\81Ñ\8c Ð±Ð»Ð¾ÐºÐ¸Ñ\80овка Ð°Ð»Ð¾Ð½.\nТон IP-адÑ\80еÑ\81 â\80\94 $3, Ð±Ð»Ð¾ÐºÐ¸Ñ\80овка Ð¸Ð´ÐµÐ½Ñ\82иÑ\84икаÑ\82оÑ\80лÑ\8dн â\80\94 $5.\nÐ\9fожалÑ\83йÑ\81Ñ\82а, Ð°Ñ\81лÑ\8dÑ\81Ñ\8cÑ\82Ñ\8bм Ñ\82одон-Ñ\82а Ð²Ð°Ð·Ð¸Ñ\81Ñ\8cконÑ\8dз ÐºÐ¾Ñ\82Ñ\8cкÑ\83 Ð²Ð¾Ð·Ñ\8cмано.",
-       "autoblockedtext": "Тон IP-адрес, герӟет автоматически заблокирован а со, мар солэн кутыны луоно азьвыл кин ке но пырисьёс пӧлысь, заблокирован {{GENDER:$4|участник|куакеч}} $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": "<strong>ТӥлÑ\8fд Ñ\83Ñ\87Ñ\91Ñ\82ной Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8cÑ\82Ñ\8b Ñ\8fке IP-адÑ\80еÑ\81Ñ\82Ñ\8b Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ\80оваÑ\82Ñ\8c ÐºÐ°Ñ\80емÑ\8bн Ð²Ð°Ð».</strong>\n\nÐ\91локиÑ\80овкаез Ð»Ñ\8dÑ\81Ñ\8cÑ\82ӥз $1.\nÐ\9fÑ\83Ñ\81Ñ\8aем Ð¼Ñ\83гез: <em>$2</em>.\n\n* Ð\91локиÑ\80овка ÐºÑ\83Ñ\82Ñ\81киз: $8\n* Ð\91локиÑ\80овка Ð¹Ñ\8bлпÑ\83мÑ\8aÑ\8fÑ\81Ñ\8cкоз: $6\n* Ð\91локиÑ\80овкалÑ\8dн Ñ\83жпÑ\83мез: $7\n\nТӥ Ð±Ð»Ð¾ÐºÐ¸Ñ\80овка Ñ\81Ñ\8fÑ\80Ñ\8bÑ\81Ñ\8c Ð²ÐµÑ\80аÑ\81Ñ\8cкÑ\8bнÑ\8b Ð±Ñ\8bгаÑ\82Ó¥Ñ\81Ñ\8cкодÑ\8b $1 Ñ\8fке ÐºÐ¾Ñ\82Ñ\8cкин Ð¼Ñ\83кеÑ\82 [[{{MediaWiki:Grouppage-sysop}}|админиÑ\81Ñ\82Ñ\80аÑ\82оÑ\80]] Ð´Ð¾Ñ\80Ñ\8b Ð³ÐµÑ\80Ó\9fаÑ\81Ñ\8cкÑ\8bÑ\81а.\n[[Special:Preferences|Ð\9dаÑ\81Ñ\82Ñ\80ойкаоÑ\81адÑ\8b]] Ñ\8dлекÑ\82Ñ\80он Ð¿Ð¾Ñ\87Ñ\82алÑ\8dн Ñ\83жаÑ\81Ñ\8c Ð°Ð´Ñ\80еÑ\81Ñ\8dз Ó§Ð²Ó§Ð» Ð´Ñ\8bÑ\80Ñ\8aÑ\8f, Ñ\82Ó¥ Â«Ð\92икиавÑ\82оÑ\80лÑ\8b Ð³Ð¾Ð¶Ñ\82Ñ\8dÑ\82» Ñ\84Ñ\83нкÑ\86иез Ñ\83же ÐºÑ\83Ñ\82Ñ\8bнÑ\8b Ñ\83д Ð±Ñ\8bгаÑ\82Ó¥Ñ\81Ñ\8cке, Ñ\81ое Ñ\82ӥленÑ\8bдÑ\8b Ñ\83же ÐºÑ\83Ñ\82он Ð´Ñ\83гдÑ\8bÑ\82Ñ\8dмÑ\8bн Ó§Ð²Ó§Ð» ÐºÐµ.\nТӥлÑ\8fд Ð°Ð»Ð¸ IP-адÑ\80еÑ\81Ñ\82Ñ\8b Ð»Ñ\83Ñ\8d $3, Ð½Ð¾ Ð±Ð»Ð¾ÐºÐ¸Ñ\80овка Ð¸Ð´ÐµÐ½Ñ\82иÑ\84икаÑ\82оÑ\80 â\80\94 #$5.\nТаÑ\83на Ð¿Ñ\8bÑ\80Ñ\82Ñ\8d Ð²Ð°Ð½Ñ\8c Ñ\82а Ð¿Ñ\8bÑ\80-поÑ\87 Ñ\81ведениоÑ\81Ñ\8bз Ð°Ñ\81Ñ\8cÑ\82Ñ\8dлÑ\8dн ÐºÑ\83Ñ\80онÑ\8aÑ\91Ñ\81адÑ\8b.",
+       "autoblockedtext": "Тӥляд IP-адресты автоматически заблокировать каремын вал, малы ке шуоно со кутӥськиз вал мукет викиавторен, кинзэ $1 заблокировать кариз.\nБлокировкалэн пусъем мугез:\n\n:<em>$2</em>\n\n* Блокировка кутскиз: $8\n* Блокировка йылпумъяськоз: $6\n* Блокировкалэн ужпумез: $7\n\nТӥ блокировка сярысь вераськыны быгатӥськоды $1 яке мукет [[{{MediaWiki:Grouppage-sysop}}|администраторъёс]] пӧлысь огез доры герӟаськыса.\n\nСак луэ, тӥ «Викиавторлы гожтэт» функциез уже кутыны уд быгатӥське [[Special:Preferences|асьтэлэн настройкаосады]] электрон почталэсь шонер адрессэ гожтытозь яке юнматытозь, либо блокировкады сыӵе амалэн гожтэтъёсыз ыстыны уг лэзьы ке.\n\nТӥляд али IP-адресты луэ $3, но блокировка идентификатор — #$5.\nТауна пыртэ вань та пыр-поч сведениосыз асьтэлэн куронъёсады.",
        "blockednoreason": "мугезлы эн возьмалэ",
        "whitelistedittext": "Тон кулэ $1 бам воштон понна.",
        "loginreqtitle": "Авторизация кулэ",
        "blocked-notice-logextract": "Пользователь заблокирован сётӥз та учырлы.\nСправка понна радъяськылӥсь журнал блокировка лапег берпуметӥ гожтэт:",
        "continue-editing": "Тупатъянэз азьланьтоно",
        "editing": "Тупатон: $1",
+       "creating": "«$1» бамез кылдытон",
        "editingsection": "Тупатон: $1 (люкет)",
+       "templatesused": "Та бам пушкы пыртэм {{PLURAL:$1|шаблон|шаблонъёс}}:",
        "template-protected": "(утемын)",
-       "template-semiprotected": "(полузащищенный)",
+       "template-semiprotected": "(полуутемын)",
+       "hiddencategories": "Та бам пыре {{PLURAL:$1|$1 ватэм категорие}}:",
        "nocreatetext": "Та сайтлэн бамаз выль сюбегатэм луонлыкъёсын кылдытон.\nТон улыса, берлань вуэ быгатэ бам отредактировать, [[Special:UserLogin|тусбуяськыны книгае яке выль система кылдыто учётной]].",
        "nocreate-loggedin": "Тон доразы юаськыны кылдӥз выль бам ӧвӧл.",
        "permissionserrors": "Янгышъёс юаське",
        "cantcreateaccount-text": "Та книгаез кылдытонлы учётной IP-адрес (<strong>$1</strong>) заблокировать луизы [[User:$3|$3]].\n\nМугез, вайиз $3 возьматэ <em>$2</em>",
        "cantcreateaccount-range-text": "Учётной кылдытон - гожъян IP-адрес диапазонын <strong>$1</strong>, Тон пыриське со IP-адрес (<strong>$4</strong>), заблокировать луизы [[User:$3|$3]].\n\nМугез, вайиз $3 возьматэ <em>$2</em>",
        "viewpagelogs": "Та бамлы журналъёсыз возьматыны",
+       "currentrev-asof": "Алиез версия $1",
        "revisionasof": "Версия $1",
+       "revision-info": "Версия $1; {{GENDER:$6|$2}}$7",
        "previousrevision": "← Вужгем",
+       "nextrevision": "Выльгем →",
+       "currentrevisionlink": "Алиез версия",
        "cur": "али",
        "last": "азьв.",
        "history-show-deleted": "Ӵушылэмъёссэ гинэ",
+       "rev-delundel": "возьматыны/ватыны",
        "rev-showdeleted": "возьматоно",
        "revdelete-show-file-submit": "да",
        "revdelete-radio-set": "Ватэм",
        "revdelete-radio-unset": "Адӟымон",
        "revdelete-reason-dropdown": "*Вӧлскем палэнскон мугъёсты\n** Авторской правоосты тӥян\n** Яке кулэтэм информациез личной комментарий\n** Логин несоответствовать\n** Курла информациез Потенциально",
        "history-title": "$1 — воштонъёслэн историзы",
+       "difference-title": "$1 — версиосыз куспын пӧртэмлык",
        "lineno": "$1-тӥ чур:",
        "compareselectedversions": "Быръем версиосыз ӵошатыны",
        "showhideselectedversions": "Возьматыны/ватыны быръем версиосыз",
        "searchresults-title": "утчан \"$1\"",
        "prevn": "{{PLURAL:$1|$1-лы}} берлань",
        "nextn": "{{PLURAL:$1|$1-лы}} азьлань",
+       "nextn-title": "$1 {{PLURAL:$1|шедьтэмлы}} азьлань",
        "shown-title": "Адӟытылоно $1 {{PLURAL:$1|шедьтэмез}} бамлы быдэ",
        "viewprevnext": "Учкыны ($1 {{int:pipe-separator}} $2) ($3)",
+       "searchmenu-new": "<strong>Кылдытыны «[[:$1]]» бамез та вики-проектын!</strong> {{PLURAL:$2|0=|Со сяна утчанэныды шедьтэм бамез учке.|Со сяна шедьтэм бамъёсты учке.}}",
        "searchprofile-articles": "Валтӥсь бамъёс",
        "searchprofile-images": "Мультимедиа",
        "searchprofile-everything": "Котькытын",
        "searchprofile-everything-tooltip": "Вань бамъёсэтӥ утчан (вераськон бамъёсты пыртыса)",
        "search-result-size": "$1 ({{PLURAL:$2|$2 кыл}})",
        "search-redirect": "($1 бамысь ыстон)",
+       "search-section": "(«$1» люкет)",
+       "search-suggest": "Тӥ, вылды, утчаллямды «$1».",
        "search-interwiki-more": "(эшшо)",
        "searchall": "Ваньзэ",
+       "search-showingresults": "{{PLURAL:$4|<strong>$3</strong> пӧлысь <strong>$1-тӥ</strong> шедьтэм|<strong>$3</strong> пӧлысь <strong>$1—$2</strong> шедьтэмъёс}}",
        "search-nonefound": "Запрослы кельшись шедьтэмъёс ӧвӧл.",
        "powersearch-toggleall": "Ваньзэ",
        "powersearch-togglenone": "Номыре",
        "prefs-editing": "Тупатон",
        "yourlanguage": "Интерфейслэн кылыз:",
        "prefs-preview": "Бамез эскерон",
-       "editusergroup": "Ð\93Ñ\80Ñ\83ппае {{GENDER:$1|пÑ\8bÑ\80иÑ\81Ñ\8c}} Ð¼Ñ\83кеÑ\82",
+       "editusergroup": "Ð\92икиавÑ\82оÑ\80лÑ\8dÑ\81Ñ\8c Ð³Ñ\80Ñ\83ппаоÑ\81Ñ\81Ñ\8d Ð²Ð¾Ð·Ñ\8cмаÑ\82Ñ\8bнÑ\8b",
        "group-autoconfirmed": "Автоподтвержденный пыриськисьёс",
        "group-bot": "Боты",
        "group-sysop": "Администраторъёс",
        "group-all": "(ваньзэ)",
+       "grouppage-sysop": "{{ns:project}}:Администраторъёс",
        "right-read": "лыдӟыны бам",
        "right-edit": "правка бам",
        "right-createpage": "бам кылдытон-а, уг-возьматэмзэ эскерон",
        "enhancedrc-history": "история",
        "recentchanges": "Выль тупатонъёс",
        "recentchanges-legend": "Выль тупатонъёслы настройкаос",
+       "recentchanges-summary": "Та бамын викилэн дыръя радъям выль воштонъёсыз возьматэмын.",
        "recentchanges-label-newpage": "Та тупатонэн выль бам кылдӥз",
-       "recentchanges-label-minor": "Ð\9fичи воштон",
-       "recentchanges-label-bot": "Та Ñ\82Ñ\83паÑ\82онÑ\8dз ÐºÐ°Ñ\80из Ð±Ð¾Ñ\82",
+       "recentchanges-label-minor": "Та Ñ\82Ñ\83паÑ\82он Ð»Ñ\83Ñ\8d Ð¿ичи воштон",
+       "recentchanges-label-bot": "Та Ñ\82Ñ\83паÑ\82онÑ\8dз Ð±Ð¾Ñ\82 ÐºÐ°Ñ\80из",
        "recentchanges-label-unpatrolled": "Та тупатонэз нокин но ӧз эскеры на",
        "recentchanges-label-plusminus": "Бамлэн быдӟалаез сомында байтъёслы воштӥськиз",
        "recentchanges-legend-heading": "<strong>Легенда:</strong>",
        "rcshowhideminor-hide": "Ватыны",
        "rcshowhidebots": "$1 ботъёсыз",
        "rcshowhidebots-show": "Возьматыны",
+       "rcshowhidebots-hide": "Ватыны",
        "rcshowhideliu": "$1 пырем викиавторъёсыз",
        "rcshowhideliu-show": "Возьматыны",
        "rcshowhideliu-hide": "Ватыны",
        "recentchangeslinked": "Герӟаськем тупатонъёс",
        "recentchangeslinked-feed": "Герӟаськем тупатонъёс",
        "recentchangeslinked-toolbox": "Герӟаськем тупатонъёс",
+       "recentchangeslinked-title": "«$1» ласянь герӟаськем тупатонъёс",
        "recentchangeslinked-summary": "Татын алигес воштэм бамъёс адӟытэмын, кудъёссэ пусъем бам чӧлске (яке кудъёсыз пусъем категорие пыро).\n[[Special:Watchlist|Чаклан списокысьтыды]] бамъёс <strong>адӟиськытэмын</strong>.",
+       "recentchangeslinked-page": "Бамлэн нимыз:",
+       "recentchangeslinked-to": "Мыддоринтыны: та бамез чӧлскись бамъёсыз воштонъёсыз возьматыны",
        "upload": "Файл поныны",
        "uploadnologin": "Тон эн тусбуяськыны сӧзнэтэз",
        "uploadnologintext": "Тон кулэ $1, медаз загрузка файл сервер.",
+       "filedesc": "Вакчияк описаниез",
        "uploaddisabled": "Загрузка алӥзы",
        "copyuploaddisabled": "Загрузка URL disconnect.",
        "uploaddisabledtext": "Загрузка файл disconnect.",
        "upload-dialog-button-cancel": "Берытсконо",
+       "license-header": "Лицензия",
        "nolicense": "Ӧвӧл",
+       "imgfile": "файл",
        "file-anchor-link": "Файл",
        "filehist": "Файллэн историез",
        "filehist-help": "Зӥбе дата/дыр шоры, кызьы файл со дырын адӟиськемез учкыны вылысь.",
        "filehist-comment": "Валэктон",
        "imagelinks": "Файлэз уже кутон",
        "linkstoimage": "{{PLURAL:$1|$1 бам}} та файлэз чӧлске:",
+       "nolinkstoimage": "Та файл вылэ чӧлскись бамъёс ӧвӧл.",
        "sharedupload": "Та файл — $1-ысь, сое мукет проектъёсын но уже кутыны луэ.",
        "sharedupload-desc-here": "Та файл — $1-ысь, сое мукет проектъёсын но уже кутыны луэ.\n[$2 Файл гожъясь бамысьтыз] информация адӟытэмын улын.",
+       "upload-disallowed-here": "Тӥ та файлэз выльысь гожтыны уд быгатӥське.",
        "randompage": "Олокыӵе статья",
        "withoutinterwiki-submit": "Возьматыны",
        "nbytes": "{{PLURAL:$1|$1 байт}}",
+       "nmembers": "$1 {{PLURAL:$1|объект}}",
        "prefixindex-submit": "Возьматыны",
        "newpages": "Выль бамъёс",
        "newpages-submit": "Возьматыны",
        "move": "Нимзэ воштыны",
+       "pager-older-n": "{{PLURAL:$1|вужгес $1}}",
+       "booksources": "Книгаосын источникъёс",
+       "booksources-search-legend": "Книга сярысь информациез утчан",
+       "booksources-search": "Утчаны",
        "log": "Журналъёс",
        "logeventslist-submit": "Возьматыны",
        "showhideselectedlogentries": "Возьматыны/ватыны быръем журналъёсысь гожъямъёсыз",
        "checkbox-all": "Ваньзэ",
        "checkbox-none": "Номыре",
        "checkbox-invert": "Воштыны интыен",
+       "allarticles": "Ваньмыз бамъёс",
        "allpagessubmit": "Быдэстоно",
+       "categories": "Категориос",
        "categories-submit": "Возьматыны",
        "sp-deletedcontributions-contribs": "тупатонъёсыз",
        "listusers-submit": "Возьматыны",
        "listusers-blocked": "(заблокировать{{GENDER:$1||а}})",
        "listgrouprights": "Право группае пыриськисьёс",
-       "listgrouprights-summary": "Та группае пырисьёс возьматыны кулэ вики список улӥзы, право соответствующийгес солы возьматоно кариськиз. Оло, ас кожазы ватсаса ивортодэт улыны эрикрадэз сярысь.",
+       "listgrouprights-summary": "Та группае пырисьёс возьматыны кулэ вики список улӥзы, право соответствующийгес солы возьматоно кариськиз. Оло, ас [[{{MediaWiki:Listgrouprights-helppage}}|кожазы ватсаса ивортодэт]] улыны эрикрадэз сярысь.",
        "listgrouprights-members": "(список пыриськисьёс)",
        "emailuser": "Викиавторлы гожтэт",
        "emailmessage": "Ивортон:",
        "watchlist-options": "Чаклан списокез тупатыны",
        "enotif_reset": "Вань бамъёсыз лыдӟем пусйыны",
        "historyaction-submit": "Возьматыны",
+       "dellogpage": "Быдтонъёсын журнал",
        "deletionlog": "палэнэ журнал",
        "rollbacklink": "ӝог берыктыны",
+       "rollbacklinkcount": "$1 {{PLURAL:$1|тупатонэз}} ӝог берыктыны",
        "revertpage": "Откат шонертон [[Special:Contributions/$2|$2]] ([[User talk:$2|обсуждение]]) доры версия [[User:$1|$1]]",
        "revertpage-nouser": "Откат шонертон (пыриськисьёс ватэм нимъёссы) доры версия {{GENDER:$1|[[User:$1|$1]]}}",
+       "protectlogpage": "Утёнъёсын журнал",
        "restriction-edit": "Тупатон",
        "undeletehistory": "Выльысь ке тон бамъёстэ, выльысь историяз луэм воштӥськонъёс вань.\nБӧрысь кылдӥзы выль бамъёс палэнэ кошконо луэ ке, сыӵе ик нимыз, историяз вошъяськонъёс предшествующий выльысь кылдозы.",
        "undeletehistorynoadmin": "Статьяос палэнтэмын вал. Мугез но палэнэ список пыриды, со статьяе редактировать-озь палэнэгес, зӧк возьматэ. Текст статьяез удаленный администраторъёс гинэ учкыны быгатод.",
        "contributions": "{{GENDER:$1|Викиавтор}} гожтэмъёсы",
        "contributions-title": "$1 викиавтор гожтэмъёсы",
        "mycontris": "Гожтэмъёс",
+       "anoncontribs": "Гожтэмъёс",
        "nocontribs": "Критерии нокыӵе воштӥськонъёс та соответствующий шедьтыны уг луы.",
+       "month": "Толэзьысен (вазен но):",
+       "year": "Арысен (вазен но):",
        "sp-contributions-blocklog": "блокировка",
        "sp-contributions-deleted": "шонертон палэнтыны {{GENDER:$1|участник|куакеч}}",
        "sp-contributions-blocked-notice": "Пользователь заблокирован сётӥз та учырлы. Справка понна радъяськылӥсь журнал блокировка лапег берпуметӥ гожтэт:",
        "sp-contributions-blocked-notice-anon": "Со ip-адрес вие заблокировать сётӥзы. Блокировка журналъёсты вайытэк улӥзы берпуметӥ книгаысь:",
        "whatlinkshere": "Татчы чӧлсконъёс",
+       "whatlinkshere-title": "«$1» вылэ чӧлскись бамъёс",
+       "whatlinkshere-page": "Бам:",
+       "linkshere": "Та бамъёс <strong>[[:$1]]</strong> вылэ чӧлско:",
+       "isredirect": "ыстӥсь бам",
+       "istemplate": "пыртон",
+       "whatlinkshere-prev": "{{PLURAL:$1|берлань|$1-лы берлань}}",
+       "whatlinkshere-next": "{{PLURAL:$1|азьлань|$1-лы азьлань}}",
+       "whatlinkshere-links": "← чӧлсконъёс",
+       "whatlinkshere-hideredirs": "$1 ыстӥсь бамъёсты",
+       "whatlinkshere-hidetrans": "$1 пыртонъёсты",
+       "whatlinkshere-hidelinks": "$1 чӧлсконъёсты",
+       "whatlinkshere-filters": "Фильтръёс",
        "block": "Блокировка пыриськисьёс",
-       "blockip": "Заблокировать пыриськисьёс",
+       "blockip": "Заблокировать {{GENDER:$1|пыриськисьёс}}",
        "ipbreason-dropdown": "* Блокировка мугез кабес\n** Полы информациез оскизы\n** Вордскем палэнэ бам\n** Спам-сайтъя педпал чӧлскон\n** Текстлэсь визьем ватсан/жуг-жаг\n** Кышкытлыклэсь, пыриськыны уйиськон\n** Злоупотребление кӧня ке книга учётной\n** Пыриськисьёслэн нимъёссы пыриськисьёс",
-       "ipboptions": "2 Ñ\87аÑ\81:2 hours,1 Ð½Ñ\83наллÑ\8b:1 day,3 Ð½Ñ\83наллÑ\8b:3 days,1 Ð°Ñ\80нÑ\8fезлÑ\8b:1 week,2 Ð°Ñ\80нÑ\8fÑ\8fз:2 weeks,1 Ñ\82олÑ\8dзÑ\8c:1 month,3 Ñ\82олÑ\8dзÑ\8c:3 months,6 Ñ\82олÑ\8dзÑ\8c:6 months,1 Ð°Ñ\80лÑ\8dн:1 year,беÑ\81Ñ\81Ñ\80оÑ\87но:infinite",
-       "unblocked": "$1 разблокировать",
+       "ipboptions": "2 Ñ\87аÑ\81:2 hours,1 Ð½Ñ\83наллÑ\8b:1 day,3 Ð½Ñ\83наллÑ\8b:3 days,1 Ð°Ñ\80нÑ\8fезлÑ\8b:1 week,2 Ð°Ñ\80нÑ\8fÑ\8fз:2 weeks,1 Ñ\82олÑ\8dзÑ\8c:1 month,3 Ñ\82олÑ\8dзÑ\8c:3 months,6 Ñ\82олÑ\8dзÑ\8c:6 months,1 Ð°Ñ\80лÑ\8dн:1 year,нокÑ\83:infinite",
+       "unblocked": "[[User:$1|$1]] разблокировать",
        "unblocked-id": "Блокировка $1 басьтоно луиз",
        "blocklist-target": "Ужпумъёс",
        "blocklist-reason": "Мугез",
-       "infiniteblock": "беÑ\81Ñ\81Ñ\80оÑ\87но",
+       "infiniteblock": "нокÑ\83",
        "expiringblock": "йылпумъяськиз $1-ысь $2",
        "anononlyblock": "аноним гинэ",
        "noautoblockblock": "disconnect автоблокировка",
        "unblocklink": "разблокировать",
        "change-blocklink": "блокировка воштыны",
        "contribslink": "тупатонъёсыз",
-       "autoblocker": "Автоблокировка-со понна, мае тӥ IP-адрес кутыны али \"[[User:$1|$1]]\". \nБлокировка мугез $1: \"$2\"",
+       "autoblocker": "Автоблокировка, малы ке шуоно «[[User:$1|$1]]» тӥлесьтыд IP-адрестэс алигес уже кутӥз.\n$1 блокировкалэн мугез: «$2»",
        "blocklogentry": "заблокировать [[$1]] дыр $2 $3",
        "reblock-logentry": "блокировка воштӥз [[$1]] дыр $2 $3",
        "blocklogtext": "Блокировка но та журналлэн ужезлы разблокирование пользователь.\nЗаблокировать Автоматически IP-адрес уг возьма.\nПроизведениосыз печатласько эстониын [[Special:BlockList|сьӧд списокын]], бан список блокъёс лэсьтыны.",
        "block-log-flags-nousertalk": "тупатъяны ачиз уггес быгаты бамлэн обсуждениосаз",
        "range_block_disabled": "Администратор диапазонэз блокировать али.",
        "move-watch": "Чаклан списоке пыртоно инъет но валтӥсь бамъёсыз",
+       "movelogpage": "Нимъёсты воштонъёсын журнал",
+       "export": "Бамъёсты поттон",
        "allmessagesname": "Ивортон",
        "allmessages-filter-all": "Ваньзэ",
        "thumbnail-more": "Будэтоно",
+       "tooltip-pt-userpage": "{{GENDER:|Тӥляд}} асьтэлэн бамды",
+       "tooltip-pt-mytalk": "{{GENDER:|Тӥляд}} вераськон бамды",
+       "tooltip-pt-preferences": "{{GENDER:|Тӥляд}} настройкаосты",
+       "tooltip-pt-watchlist": "Бамъёслы список, кудъёссэ воштонъёсты тӥ эскерылӥськоды",
+       "tooltip-pt-mycontris": "{{GENDER:|Тӥляд}} тупатонъёстылы список",
        "tooltip-pt-login": "Татын системае пырыны луоно, нош одно ик ӧвӧл",
+       "tooltip-pt-logout": "Йылпумъяны али ортчись ужанэз",
        "tooltip-pt-createaccount": "Татын учётной записез лэсьтыны но системае пырыны луоно, нош одно ик ӧвӧл",
        "tooltip-ca-talk": "Бамлэн контентэз сярысь вераськон",
        "tooltip-ca-edit": "Та бамез тупатъяно",
        "tooltip-ca-addsection": "Выль люкет кылдытоно",
        "tooltip-ca-viewsource": "Та бам воштонъёслэсь утемын.\nТӥ быгатӥськоды инъет текстсэ учкыны но кӧчырыны",
        "tooltip-ca-history": "Бамлэн воштонъёсыныз журнал",
+       "tooltip-ca-move": "Та бамлэсь нимзэ воштыны",
        "tooltip-ca-watch": "Та бамез чаклан списокады пыртоно",
        "tooltip-search": "Утчано {{SITENAME}}",
        "tooltip-search-go": "Выжоно сыӵе ик нимын баме",
        "tooltip-ca-nstab-main": "Валтӥсь бамез учконо",
        "tooltip-ca-nstab-user": "Викиавторлэн бамез",
        "tooltip-ca-nstab-special": "Та бам нимысьтыз, сое тупатон луонтэм",
+       "tooltip-ca-nstab-project": "Проектлэн бамез",
        "tooltip-ca-nstab-image": "Файллэн бамез",
+       "tooltip-ca-nstab-template": "Шаблонлэн бамез",
        "tooltip-ca-nstab-category": "Категорилэн бамез",
+       "tooltip-save": "Возьыны воштонъёстэс",
+       "tooltip-preview": "Воштонъёстэс эскерон. Тауна, бамез гожтонлэсь азьло учкелэ соосыз.",
+       "tooltip-diff": "Возьматыны воштонъёсыз, кудъёссэ тӥ текстэ пыртӥды.",
        "tooltip-rollback": "Берло викиавторен лэсьтэм воштонъёсыз одӥг зӥбонэн палэнтыны",
+       "tooltip-undo": "Палэнтыны та тупатонэз но возьматыны воштон эскерымон бамез, кытын палэнтонлэсь мугзэ гожтыны луоз.",
+       "tooltip-summary": "Воштонъёсты сярысь вакчияк гожтэлэ",
+       "simpleantispam-label": "Анти-спам эскерон.\n<strong>Эн</strong> гожтэ татчы!",
        "pageinfo-header-edits": "Воштонъёслэн историзы",
        "pageinfo-toolboxlink": "Бам сярысь тодэтъёс",
+       "previousdiff": "← Вужгес тупатон",
+       "nextdiff": "Выльгес тупатон →",
        "file-info-size": "$1 × $2 пиксель, файллэн быдӟалаез: $3, MIME-тип: $4",
+       "file-nohires": "Бадӟымгес быдӟалаен суред ӧвӧл.",
+       "svg-long-desc": "SVG файл, номинально $1 × $2 пиксель, файллэн быдӟалаез: $3",
        "show-big-image": "Инъет файл",
        "show-big-image-preview": "Быдӟалаез та бамын: $1.",
        "show-big-image-other": "Мукет {{PLURAL:$2|быдӟалаез|быдӟалаосыз}}: $1.",
        "metadata": "Метаданнойёс",
        "metadata-help": "Файл пушкын информация вань на, кудзэ лыдпусо камераос яке сканеръёс файлэз кылдытыку огшоры ватсалляло.\nКылдытон бере файл воштӥськиз ке, куд-огез параметръёс воштэм суредлы ярантэм луыны быгато.",
        "metadata-fields": "Суредысь метаданнойёслэн та списоке пыртэм полеоссы адӟытӥськозы суред бам вылын, метаданнойёслэн таблицазы бинемын дыръя.\nМукет полеоссы ватскозы.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
+       "exif-xresolution": "Горизонтальной разрешение",
+       "exif-yresolution": "Вертикальной разрешение",
+       "exif-datetime": "Файлэз воштонлэн датаез но дырыз",
+       "exif-model": "Камералэн моделез",
+       "exif-software": "Компьютер программаос",
+       "exif-exifversion": "Exif версия",
+       "exif-colorspace": "Буёлъёслэн пространствозы",
        "exif-disclaimer": "Кыл кутыны пумит луон",
        "namespacesall": "ваньзэ",
        "monthsall": "ваньзэ",
        "confirmrecreate-noreason": "{{GENDER:$1|Участник|Куакеч|}}&nbsp;[[User:$1|$1]] ([[User talk:$1|обс]]) {{GENDER:$1|палэнтыны|палэнтыны}} таиз бере бам, кызьы тон сое редактировать карыны кутскиз. Пожалуйста, подтвердите, мар тон малпаськод та бамез зэм но выльысь кылдозы.",
        "confirm-watch-top": "Та бамез чаклан списокады пыртоно?",
        "autosumm-new": "Выль бам: «$1»",
+       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|вераськон]])",
        "version": "Версия",
        "specialpages": "Ваньмыз панельёс",
        "specialpages-group-login": "Тусбуяськыны / Гожтӥськоно",
        "tags-title": "Меткаос",
        "logentry-delete-delete": "$1 {{GENDER:$2|палэнтыны|палэнтыны}} бам $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|выльысь}} бам $3",
+       "logentry-move-move": "$1 $3 бамлы $4 выль ним {{GENDER:$2|сётӥз}}",
        "logentry-newusers-create": "$1 нимо учётной запись {{GENDER:$2|кылдытэмын}} вал",
+       "logentry-upload-upload": "$1 {{GENDER:$2|понӥз}} $3",
        "searchsuggest-search": "Утчано {{SITENAME}}",
        "searchsuggest-containing": "кудъёсаз вань...",
        "api-error-autoblocked": "Тон IP-адрес заблокировать эрказ луи, малы ке шуоно со заблокировать пользователь кутыны луоз.",
index f6381c2..edd0508 100644 (file)
        "yourpasswordagain": "پارولنى قايتا كىرگۈزۈڭ:",
        "createacct-yourpasswordagain": "پارولنى مۇقىملاشتۇرۇڭ",
        "createacct-yourpasswordagain-ph": "پارولنى قايتا كىرگۈزۈڭ",
-       "remembermypassword": "بۇ كومپيۇتېردا كىرگىنىمنى ئەستە ساقلا(ئەڭ ئۇزۇن بولغاندا $1 {{PLURAL:$1|كۈن|كۈن}})",
        "userlogin-remembermypassword": "مېنى ئەستە ساقلا",
        "userlogin-signwithsecure": "بىخەتەر ئۇلىنىشنى ئىشلەت",
        "yourdomainname": "دائىرە نامىڭىز:",
        "passwordreset-emailtext-user": "{{SITENAME}} دىكى ئىشلەتكۈچى $1 بېكەت {{SITENAME}} ($4) دىكى پارولىڭىزنى قايتا بېكىتىشنى ئىلتىماس قىلدى .\nتۆۋەندىكى ئىشلەتكۈچىنىڭ {{PLURAL:$3|ھېسابات|ھېسابات}}($4)ى مۇشۇ ئېلخەتكە باغلانغان:\n\n$2\n\n{{PLURAL:$3|بۇ ۋاقىتلىق پارول|بۇ ۋاقىتلىق پارول}} {{PLURAL:$5|بىر كۈن|$5 كۈن}}دە ۋاقتى ئۆتىدۇ. ئەگەر بۇ مەشغۇلاتنى سىز ئىلتىماس قىلغان بولسىڭىز، دەرھال تىزىمغا كىرىپ يېڭى پارولدىن بىرنى تاللاڭ.\nسىز بەلگىلىگەن يېڭى پارول {{PLURAL:$5|كۈن|$5 كۈن}}دە ۋاقتى توشىدۇ. ئەگەر باشقىلار ئىلتىماس قىلغان بولسا ياكى ئۆزىڭىز بەلگىلىگەن پارول ئېسىڭىزگە كېلىپ ئۇنى ئۆزگەرتمىسىڭىز، \nبۇ ئۇچۇرغا پەرۋا قىلماي ئۆزىڭىزنىڭ كونا پارولىنى ئىشلىتىۋېرىڭ.",
        "passwordreset-emailelement": "ئىشلەتكۈچى نامى: \n$1\n\nۋاقىتلىق پارول: \n$2",
        "passwordreset-emailsentemail": "پارولنى قايتا بېكىتىش ئېلخېتى يوللاندى.",
-       "passwordreset-emailsent-capture": "پارولنى قايتا بېكىتىش ئېلخېتى يوللاندى، تۆۋەندە كۆرسىتىلىدۇ.",
-       "passwordreset-emailerror-capture": "ھاسىل قىلىنغان پارولنى قايتا بېكىتىش ئېلخېتى تۆۋەندە كۆرسىتىلگەندەك ئەمما ئۇنى {{GENDER:$2|ئىشلەتكۈچى}}گە يوللىيالمىدى: $1",
        "changeemail": "ئېلخەت ئادرېس ئۆزگەرت",
        "changeemail-header": "ھېساباتنىڭ ئېلخەت ئادرېسىنى ئۆزگەرت",
        "changeemail-no-info": "سىز تىزىمغا كىرگەندىن كېيىن بىۋاسىتە بۇ بەتكە كىرىشىڭىز لازىم.",
        "undo-nochange": "بۇ قېتىملىق تەھرىرلەش ۋاز كېچىلدى.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|مۇنازىرە]]) ئېلىپ بارغان تۈزىتىش $1",
        "undo-summary-username-hidden": "بىر يوشۇرۇن ئىشلەتكۈچى تەرىپىدىن يېنىۋېلىندى $1.",
-       "cantcreateaccounttitle": "ھېسابات قۇرالمىدى",
        "cantcreateaccount-text": "بۇ IP ئادرېستىن قۇرۇلغان ('''$1''')  ھېسابات [[User:$3|$3]] تەرىپىدىن چەكلەنگەن.\n\n$3 تەمىنلىگەن چەكلەش سەۋەبى ''$2''",
        "viewpagelogs": "بۇ بەتنىڭ خاتىرىسىنى كۆرسەت",
        "nohistory": "بۇ بەتنىڭ تەھرىرلەش خاتىرىسى يوق.",
        "activeusers-intro": "بۇ يېقىنقى $1 {{PLURAL:$1| كۈن|كۈن}}دىكى مەشغۇلات قىلغان ئىشلەتكۈچىلەر تىزىملىكى.",
        "activeusers-count": "يېقىنقى {{PLURAL:$3|كۈن|$3 كۈن}}دىكى {{PLURAL:$1|مەشغۇلات}} قېتىم سانى $1",
        "activeusers-from": "باشلانغان ئىشلەتكۈچىنى كۆرسەت:",
-       "activeusers-hidebots": "ماشىنا ئادەمنى يوشۇر",
-       "activeusers-hidesysops": "باشقۇرغۇچىنى يوشۇر",
        "activeusers-noresult": "ئىشلەتكۈچى تېپىلمىدى.",
        "listgrouprights": "ئىشلەتكۈچى گۇرۇپپا ھوقۇقى",
        "listgrouprights-summary": "تۆۋەندىكىسى بۇ wiki دا ئېنىقلىما بېرىلگەن ئىشلەتكۈچى ھوقۇق چېكى تىزىملىكى ۋە ئۇلارنىڭ زىيارەت ھوقۇق چېكى.\nتېخىمۇ كۆپ قىسمەن ھوقۇقنىڭ تەپسىلاتىنى [[{{MediaWiki:Listgrouprights-helppage}}|بۇ جاي]] دىن تاپالايسىز.",
        "htmlform-no": "ياق",
        "htmlform-yes": "ھەئە",
        "htmlform-chosen-placeholder": "بىرنى تاللاڭ",
-       "sqlite-has-fts": "$1 پۈتۈن تېكست ئىزدەشنى قوللايدۇ",
-       "sqlite-no-fts": "$1 پۈتۈن تېكست ئىزدەشنى قوللىمايدۇ",
        "logentry-delete-delete": "$1 $3 بەتنى {{GENDER:$2|ئۆچۈرىۋەتتى}}",
        "logentry-delete-restore": "$1 $3 بەتنى {{GENDER:$2|ئەسلىگە قايتۇردى}}",
        "logentry-delete-event": "$1 ئىشلەتكۈچى $3 دىكى {{PLURAL:$5|خاتىرە ھادىسە}}سىنىڭ كۆۈنۈشچانلىقىنى ئۆزگەرتتى: $4",
index 7240ace..18d73a6 100644 (file)
        "views": "Перегляди",
        "toolbox": "Інструменти",
        "tool-link-userrights": "Змінити групи {{GENDER:$1|користувачів}}",
+       "tool-link-userrights-readonly": "Перегляд груп {{GENDER:$1|користувача|користувачки}}",
        "tool-link-emailuser": "Надіслати електронного листа {{GENDER:$1|цьому користувачеві|цій користувачці}}",
        "userpage": "Переглянути сторінку користувача",
        "projectpage": "Переглянути сторінку проекту",
        "botpasswords-label-delete": "Видалити",
        "botpasswords-label-resetpassword": "Скинути пароль",
        "botpasswords-label-grants": "Придатні дозволи:",
-       "botpasswords-help-grants": "Ð\9aожен Ð´Ð¾Ð·Ð²Ñ\96л Ð´Ð°Ñ\94 Ð´Ð¾Ñ\81Ñ\82Ñ\83п Ð´Ð¾ Ð¿ÐµÑ\80елÑ\96Ñ\87ениÑ\85 Ð¿Ñ\80ав ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87а, Ñ\8fкÑ\96 Ð²Ð¶Ðµ Ñ\94 Ñ\83 Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83 ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87а. Див. [[Special:ListGrants|таблицю дозволів]] для отримання додаткової інформації.",
+       "botpasswords-help-grants": "Ð\94озволи Ð´Ð°Ñ\8eÑ\82Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83п Ð´Ð¾ Ð¿Ñ\80ав, Ñ\8fкÑ\96 Ð²Ð¶Ðµ Ñ\94 Ñ\83 Ð\92аÑ\88ого Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83. Ð£Ð²Ñ\96мкненнÑ\8f Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ\83 Ñ\82Ñ\83Ñ\82 Ð½Ðµ Ð½Ð°Ð´Ð°Ñ\81Ñ\82Ñ\8c Ð\92ам Ð´Ð¾Ñ\81Ñ\82Ñ\83пÑ\83 Ð´Ð¾ Ð±Ñ\83дÑ\8c\8fкиÑ\85 Ð¿Ñ\80ав, Ñ\8fкиÑ\85 Ð² Ñ\96нÑ\88омÑ\83 Ð²Ð¸Ð¿Ð°Ð´ÐºÑ\83 Ð½Ðµ Ð±Ñ\83ло Ð± Ñ\83 Ð\92аÑ\88ого Ð¾Ð±Ð»Ñ\96кового Ð·Ð°Ð¿Ð¸Ñ\81Ñ\83. Див. [[Special:ListGrants|таблицю дозволів]] для отримання додаткової інформації.",
        "botpasswords-label-grants-column": "Дозволено",
        "botpasswords-bad-appid": "Ім'я бота «$1» є недопустимим.",
        "botpasswords-insert-failed": "Не вдалось додати бота з іменем «$1». Можливо, він вже був доданий?",
        "passwordreset-emaildisabled": "В цій вікі вимкнуто Функції електронної пошти.",
        "passwordreset-username": "Ім'я користувача:",
        "passwordreset-domain": "Домен:",
-       "passwordreset-capture": "Продивитись результуючий електронний лист?",
-       "passwordreset-capture-help": "Якщо ви зробите помітку у віконці, вам буде показаний електронний лист (із тимчасовим паролем), який також буде надісланий користувачеві.",
        "passwordreset-email": "Адреса електронної пошти:",
        "passwordreset-emailtitle": "Деталі облікового запису на {{SITENAME}}",
        "passwordreset-emailtext-ip": "Хтось (імовірно ви, з IP-адреси $1) попросив нагадати деталі вашого облікового запису для {{SITENAME}} ($4). З вашою електронною скринькою пов'язан{{PLURAL:$3|1=ий такий запис|і такі записи}}:\n\n$2\n\n{{PLURAL:$3|1=Цей тимчасовий пароль стане недійсним|Ці тимчасові паролі стануть недійсними}} через $5 {{PLURAL:$5|день|дні|днів}}.\nВи маєте ввійти в систему і вибрати новий пароль. Якщо ж цей запит зробив хтось інший або ви згадали свій старий пароль і не бажаєте його змінювати, можете ігнорувати це повідомлення та продовжувати використовувати старий пароль.",
        "passwordreset-emailelement": "Ім'я користувача: \n$1\n\nТимчасовий пароль: \n$2",
        "passwordreset-emailsentemail": "Якщо ця електронна адреса асоційована з вашим обліковим записом, то лист для відновлення пароля буде відправлено на неї.",
        "passwordreset-emailsentusername": "Якщо існує електронна адреса, яка асоційована з цим обліковим записом, на неї буде надіслано лист для відновлення пароля.",
-       "passwordreset-emailsent-capture2": "{{PLURAL:$1|Електронний лист|Електронні листи}} скидання паролю було надіслано. {{PLURAL:$1|Ім'я користувача і пароль|Список імен користувачів і паролів}} показано тут.",
-       "passwordreset-emailerror-capture2": "Не вдалося надіслати листа {{GENDER:$2|користувачу|користувачці}}: $1 {{PLURAL:$3|Ім'я користувача і пароль|список імен користувачів і паролів}} показано тут.",
        "passwordreset-nocaller": "Має бути надане джерело виклику",
        "passwordreset-nosuchcaller": "Джерело виклику не існує: $1",
        "passwordreset-ignored": "Скидання пароля не відбулося. Можливо, не було налашатовано надавача?",
-       "passwordreset-invalideamil": "Недійсна адреса електронної пошти",
+       "passwordreset-invalidemail": "Недійсна адреса електронної пошти",
        "passwordreset-nodata": "Не надано ні імені користувача, ні електронної адреси",
        "changeemail": "Змінити або вилучити адресу електронної пошти",
        "changeemail-header": "Заповніть цю форму, щоб змінити адресу електронної пошти. Якщо Ви хочете взагалі прибрати зв'язок свого облікового запису з адресою електронної пошти, при надсиланні форми залиште поле нової електронної адреси порожнім.",
        "search-external": "Зовнішній пошук",
        "searchdisabled": "<p>Вибачте, повнотекстовий пошук тимчасово недоступний через перевантаження сервера; передбачається, що ця функція буде знову включена після установки нового обладнання. Поки що ми пропонуємо вам скористатися Google чи Yahoo!:</p>",
        "search-error": "Сталася помилка під час пошуку:$1",
+       "search-warning": "Попередження виникло під час пошуку: $1",
        "preferences": "Налаштування",
        "mypreferences": "Налаштування",
        "prefs-edits": "Кількість редагувань:",
        "prefs-help-recentchangescount": "Це стосується нових редагувань, історій сторінок і журналів.",
        "prefs-help-watchlist-token2": "Це секретний ключ до веб-каналу вашого списку спостереження.\nБудь-хто, хто його знає, матиме можливість читати ваш список спостереження, тому не поширюйте його.\n[[Special:ResetTokens|Натисніть тут, якщо вам потрібно скинути його]].",
        "savedprefs": "Ваші налаштування збережено.",
-       "savedrights": "Ð\9fÑ\80ава ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87а {{GENDER:$1|$1}} Ð±Ñ\83ли Ð·Ð±ÐµÑ\80еженÑ\96.",
+       "savedrights": "Ð\93Ñ\80Ñ\83пи {{GENDER:$1|коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87а $1|коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87ки $1}} Ð±Ñ\83ло Ð·Ð±ÐµÑ\80ежено.",
        "timezonelegend": "Часовий пояс:",
        "localtime": "Місцевий час:",
        "timezoneuseserverdefault": "Використовувати стандартне налаштування вікі ($1)",
        "prefswarning-warning": "Ви внесли в свої налаштування зміни, які ще не були збережені.\nЯкщо ви залишите цю сторінку, не натиснувши \"$1\", налаштування не будуть оновлені.",
        "prefs-tabs-navigation-hint": "Порада: Ви можете використовувати клавіші стрілок вліво і вправо для переходу між вкладками в списку вкладок.",
        "userrights": "Керування правами користувачів",
-       "userrights-lookup-user": "Ð\9aеÑ\80Ñ\83ваннÑ\8f Ð³Ñ\80Ñ\83пами користувача",
+       "userrights-lookup-user": "Ð\92ибеÑ\80Ñ\96Ñ\82Ñ\8c користувача",
        "userrights-user-editname": "Введіть ім'я користувача:",
-       "editusergroup": "РедагÑ\83ваÑ\82и Ð³Ñ\80Ñ\83пи {{GENDER:$1|коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87Ñ\96в}}",
+       "editusergroup": "Ð\97аванÑ\82ажиÑ\82и Ð³Ñ\80Ñ\83пи ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87Ñ\96в",
        "editinguser": "Зміна прав {{GENDER:$1|користувача}} <strong>[[User:$1|$1]]</strong> $2",
-       "userrights-editusergroup": "Змінити групи користувачів",
+       "userrights-editusergroup": "Змінити групи {{GENDER:$1|користувача|користувачки}}",
        "saveusergroups": "Зберегти групи {{GENDER:$1|користувачів}}",
        "userrights-groupsmember": "Член груп:",
        "userrights-groupsmember-auto": "Неявний член:",
        "userrights-reason": "Причина:",
        "userrights-no-interwiki": "У вас нема дозволу змінювати права користувачів на інших вікі.",
        "userrights-nodatabase": "База даних $1 не існує або не є локальною.",
-       "userrights-nologin": "Ви повинні [[Special:UserLogin|ввійти до системи]] з обліковим записом адміністратора, щоб призначати права користувачам.",
-       "userrights-notallowed": "У вас не має дозволів на додавання або зміну прав користувачів.",
        "userrights-changeable-col": "Групи, які ви можете змінити",
        "userrights-unchangeable-col": "Групи, які ви не можете змінити",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Конфлікт зміни прав користувача! Будь ласка, перевірте та  підтвердіть зміни знову.",
-       "userrights-removed-self": "Ви позбавили себе власних прав. Через це Ви більше не маєте доступу до цієї сторінки.",
        "group": "Група:",
        "group-user": "Користувачі",
        "group-autoconfirmed": "Автопідтверджені користувачі",
        "right-siteadmin": "Блокування і розблокування бази даних",
        "right-override-export-depth": "експорт сторінок, включаючи пов'язані сторінки з глибиною до 5",
        "right-sendemail": "надсилання електронної пошти іншим користувачам",
-       "right-passwordreset": "Перегляд повідомлень електронної пошти для зміни паролю",
        "right-managechangetags": "створення та (де)активування [[Special:Tags|міток]]",
        "right-applychangetags": "додавання [[Special:Tags|міток]] разом зі змінами",
        "right-changetags": "додавання або вилучення будь-яких [[Special:Tags|міток]] для певних версій сторінок або записів журналів",
        "apisandbox-continue": "Продовжити",
        "apisandbox-continue-clear": "Очистити",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries продовжить] останній запит; {{int:apisandbox-continue-clear}} очистить параметри, пов'язані з продовженням.",
+       "apisandbox-param-limit": "Введіть <kbd>max</kbd>, щоб використати максимальний ліміт.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Усі простори назв)",
+       "apisandbox-multivalue-all-values": "$1 (Усі значення)",
        "booksources": "Джерела книг",
        "booksources-search-legend": "Пошук інформації про книгу",
        "booksources-isbn": "ISBN:",
        "activeusers-count": "$1 {{PLURAL:$1|дія|дії|дій}} за {{PLURAL:$3|останній $3 день|останні $3 дні|останні $3 днів}}",
        "activeusers-from": "Показувати користувачів, починаючи з:",
        "activeusers-groups": "Показувати користувачів, належних до груп:",
+       "activeusers-excludegroups": "Виключити користувачів, що належать до груп:",
        "activeusers-noresult": "Не знайдено користувачів.",
        "activeusers-submit": "Показати активних користувачів",
        "listgrouprights": "Права груп користувачів",
        "tags-deactivate": "вимкнути",
        "tags-hitcount": "$1 {{PLURAL:$1|зміна|зміни|змін}}",
        "tags-manage-no-permission": "У Вас нема дозволу керувати мітками змін.",
-       "tags-manage-blocked": "Не можна змінювати мітки під час блокування.",
+       "tags-manage-blocked": "Не можна змінювати теги, поки {{GENDER:$1|Вас}} заблоковано.",
        "tags-create-heading": "Створити нову мітку",
        "tags-create-explanation": "За замовчуванням, новостворені мітки будуть доступні для використання користувачами і ботами.",
        "tags-create-tag-name": "Назва мітки:",
        "tags-deactivate-not-allowed": "Неможливо вимкнути мітку «$1».",
        "tags-deactivate-submit": "Вимкнути",
        "tags-apply-no-permission": "Ви не маєте права міняти мітки вашого редагування.",
-       "tags-apply-blocked": "Ви не можете змінювати мітки редагувань, будучи заблокованим.",
+       "tags-apply-blocked": "Ви не можете змінювати теги редагувань, поки {{GENDER:$1|Вас}}  заблоковано.",
        "tags-apply-not-allowed-one": "Мітку «$1» не можна додавати вручну.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Таку мітку|Такі мітки}} не можна додавати вручну: $1",
        "tags-update-no-permission": "Ви не маєте права додавати або вилучати мітки окремих версій чи журнальних записів.",
-       "tags-update-blocked": "Ви не можете додати чи видалити мітки редагувань, будучи заблокованим.",
+       "tags-update-blocked": "Ви не можете додавати чи вилучати теги редагувань, поки {{GENDER:$1|Вас}} заблоковано.",
        "tags-update-add-not-allowed-one": "Мітку \"$1\" не можна додавати вручну.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Таку мітку|Такі мітки}} не можна додавати вручну: $1",
        "tags-update-remove-not-allowed-one": "Мітку «$1» не дозволено вилучати.",
        "htmlform-user-not-exists": "<strong>$1</strong> не існує.",
        "htmlform-user-not-valid": "<strong>$1</strong> не є дійсним іменем користувача.",
        "logentry-delete-delete": "$1 {{GENDER:$2|вилучив|вилучила}} сторінку $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|вилучив|вилучила}} перенаправлення $3 шляхом перезапису",
        "logentry-delete-restore": "$1 {{GENDER:$2|відновив|відновила}} сторінку $3",
        "logentry-delete-event": "$1 {{GENDER:$2|змінив|змінила}} видимість {{PLURAL:$5 запису журналу|$5 записів журналу}} на $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|змінив|змінила}} видимість {{PLURAL:$5|$5 версії|$5 версій}} на сторінці $3: $4",
        "mw-widgets-dateinput-no-date": "Дати не вибрано",
        "mw-widgets-dateinput-placeholder-day": "РРРР-ММ-ДД",
        "mw-widgets-dateinput-placeholder-month": "РРРР-ММ",
+       "mw-widgets-mediasearch-input-placeholder": "Пошук мультимедіа",
+       "mw-widgets-mediasearch-noresults": "Нічого не знайдено.",
        "mw-widgets-titleinput-description-new-page": "сторінка ще не існує",
        "mw-widgets-titleinput-description-redirect": "перенаправлення на $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Додати категорію...",
        "sessionmanager-tie": "Не можна поєднувати кілька типів автентифікації запиту: $1.",
        "sessionprovider-generic": "сесій $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "сесій на основі кук",
        "log-action-filter-contentmodel-change": "Зміна Contentmodel",
        "log-action-filter-contentmodel-new": "Створення сторінки з нестандартною моделлю Contentmodel",
        "log-action-filter-delete-delete": "Видалення сторінки",
+       "log-action-filter-delete-delete_redir": "Перезапис перенаправлення",
        "log-action-filter-delete-restore": "Відновлення сторінки",
        "log-action-filter-delete-event": "Вилучення журналу",
        "log-action-filter-delete-revision": "Вилучення версії",
        "authmanager-authn-autocreate-failed": "Автоматичне створення локального облікового запису не вдалося: $1",
        "authmanager-change-not-supported": "Надані облікові дані не можуть бути змінені, оскільки їх нічого не буде використовувати.",
        "authmanager-create-disabled": "Створення облікових записів вимкнене.",
-       "authmanager-create-from-login": "Щоб Ñ\81Ñ\82воÑ\80иÑ\82и Ð¾Ð±Ð»Ñ\96ковий Ð·Ð°Ð¿Ð¸Ñ\81, Ð±Ñ\83дÑ\8c Ð»Ð°Ñ\81ка, Ð·Ð°Ð¿Ð¾Ð²Ð½Ñ\96Ñ\82Ñ\8c Ð¿Ð¾Ð»Ñ\8f Ð½Ð¸Ð¶Ñ\87е.",
+       "authmanager-create-from-login": "Щоб Ñ\81Ñ\82воÑ\80иÑ\82и Ð¾Ð±Ð»Ñ\96ковий Ð·Ð°Ð¿Ð¸Ñ\81, Ð±Ñ\83дÑ\8c Ð»Ð°Ñ\81ка, Ð·Ð°Ð¿Ð¾Ð²Ð½Ñ\96Ñ\82Ñ\8c Ð¿Ð¾Ð´Ð°Ð½Ñ\96 Ð¿Ð¾Ð»Ñ\8f.",
        "authmanager-create-not-in-progress": "Створення облікового запису не виконується або втрачено дані сесії. Будь ласка, почніть знову з самого початку.",
        "authmanager-create-no-primary": "Надані облікові дані не можуть бути використані для створення облікового запису.",
        "authmanager-link-no-primary": "Надані облікові дані не можуть бути використані для прив'язки облікового запису.",
        "usercssispublic": "Будь ласка, зверніть увагу: підсторінки CSS не повинні містити конфіденційних даних, бо їх можуть бачити інші користувачі.",
        "restrictionsfield-badip": "Недійсна IP-адреса або діапазон: $1",
        "restrictionsfield-label": "Дозволені діапазони IP-адрес:",
-       "restrictionsfield-help": "Одна IP-адреса або CIDR-діапазон на рядок. Щоб увімкнути все, використайте<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "Помилка: $1",
-       "edit-error-long": "Помилки:\n\n$1"
+       "restrictionsfield-help": "Одна IP-адреса або CIDR-діапазон на рядок. Щоб увімкнути все, використайте<br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 1fcff99..de2ee22 100644 (file)
        "passwordreset-nocaller": "کالر کا فراہم کیا جانا لازمی ہے",
        "passwordreset-nosuchcaller": "کالر موجود نہیں: $1",
        "passwordreset-ignored": "پاس ورڈ کی ترتیب نو مکمل نہیں ہو سکی۔ شاید کوئی پرووائڈر فراہم نہیں کیا گیا؟",
-       "passwordreset-invalideamil": "نادرست برقی ڈاک پتا",
+       "passwordreset-invalidemail": "نادرست برقی ڈاک پتا",
        "passwordreset-nodata": "کوئی صارف نام اور نہ کوئی برقی ڈاک پتا فراہم کیا گیا",
        "changeemail": "برقی ڈاک پتے میں تبدیلی یا حذف شدگی",
        "changeemail-header": "اپنے برقی ڈاک پتے کو تبدیل کرنے کے لیے اس فارم کو پُر کریں۔ اگر آپ اپنے کھاتے سے منسلک کسی برقی ڈاک پتے کو ختم کرنا چاہتے ہیں تو فارم پُر کرنے کے دوران میں نئے برقی ڈاک پتے کا خانہ خالی چھوڑ دیں۔",
index 25b3d3d..99ab540 100644 (file)
        "listusers-blocked": "(chetlashtirilgan)",
        "activeusers": "Faol foydalanuvchilar roʻyxati",
        "activeusers-from": "Quyidagidan boshlanuvchi foydalanuvchilarni koʻrsatish:",
-       "activeusers-hidebots": "Botlarni yashirish",
-       "activeusers-hidesysops": "Maʼmurlarni yashirish",
        "activeusers-noresult": "Foydalanuvchilar topilmadi.",
        "listgrouprights": "Foydalanuvchilar guruhlari roʻyxati",
        "listgrouprights-summary": "Har bir viki-loyihada boʻlgani kabi, Oʻzbekcha Vikipediyada ham foydalanuvchilar bir nechta guruhlarga boʻlingan boʻlib, quyida ularning roʻyxati va tegishli huquqlari keltirilgan. Alohida huquqlar haqida [[{{MediaWiki:Listgrouprights-helppage}}|qoʻshimcha maʼlumotlar]] boʻlishi mumkin.",
index 0fdce19..f22471c 100644 (file)
        "yourpasswordagain": "Kirjutagat peitsana udes:",
        "createacct-yourpasswordagain": "Peitsanan vahvištoituz",
        "createacct-yourpasswordagain-ph": "Kirjutagat peitsana toškerdan",
-       "remembermypassword": "Panda muštho minun tulendandmused neciš kompjuteras (enintään $1 {{PLURAL:$1|päivä|päivää}})",
        "userlogin-remembermypassword": "Jäda sistemha",
        "yourdomainname": "Teiden domen:",
        "password-change-forbidden": "Teile ei sa vajehtada peitsanad neciš vikiš.",
        "undo-failure": "Ei voi tühjištada redakcijad, sikš miše läbiredakcijad konfliktuidas.",
        "undo-norev": "Ei voi endištada lehtpol't, sikš miše mugošt lehtpol't ei ole vai se om jo čutud.",
        "undo-summary": "Tühjitadud toižetuz $1, kudamban tegi $2 (arutelu)",
-       "cantcreateaccounttitle": "Ei voi säta registracijad",
        "viewpagelogs": "Ozutada aigkirjad necen lehtpolen täht",
        "nohistory": "Necen lehtpolen täht ei ole toižetusiden aigkirjad.",
        "currentrev": "Nügüdläine versii",
        "listusers-blocked": "(blokiruidud)",
        "activeusers": "Aktivižiden kävutajiden nimikirjutez",
        "activeusers-from": "Oyutada kävutajid, augotaden necišpäi:",
-       "activeusers-hidebots": "Peitta botid",
-       "activeusers-hidesysops": "Peitta administratorid",
        "activeusers-noresult": "Kävutajad ei olgoi löutud.",
        "listgrouprights": "Kävutajiden gruppiden oiktused",
        "listgrouprights-group": "Grupp",
        "htmlform-reset": "Tühjitada toižetused",
        "htmlform-selectorother-other": "Toine",
        "htmlform-yes": "Ka",
-       "sqlite-has-fts": " $1 täuz'tekstaižen ecindan tügedamiženke",
-       "sqlite-no-fts": " $1 täuz'tekstaižen ecindan tügedamižeta",
        "revdelete-restricted": "kaidendused administratoriden täht",
        "revdelete-unrestricted": "kaidendused heittud administratoriden täht",
        "logentry-newusers-create": "{{GENDER:$2|tegihe}} $1-kävutajaks",
index ccc7825..d4ff264 100644 (file)
        "views": "Các hiển thị",
        "toolbox": "Công cụ",
        "tool-link-userrights": "Thay đổi nhóm {{GENDER:$1}}người dùng",
+       "tool-link-userrights-readonly": "Xem {{GENDER:$1}}nhóm người dùng",
        "tool-link-emailuser": "Gửi thư cho {{GENDER:$1}}người dùng này",
        "userpage": "Xem trang thành viên",
        "projectpage": "Xem trang dự án",
        "botpasswords-label-delete": "Xoá",
        "botpasswords-label-resetpassword": "Đặt lại mật khẩu",
        "botpasswords-label-grants": "Các quyền có liên quan:",
-       "botpasswords-help-grants": "Các lượt cấp phép cho phép truy cập các quyền người dùng mà một tài khoản đã có sẵn. Xem thêm thông tin trong [[Special:ListGrants|bảng cấp phép]].",
+       "botpasswords-help-grants": "Các lượt cấp phép cho phép truy cập các quyền lợi mà tài khoản của bạn đã có. Việc cấp phép tại đây không có cho phép truy cập quyền nào mà tài khoản của bạn thường không có. Xem thêm thông tin trong [[Special:ListGrants|bảng cấp phép]].",
        "botpasswords-label-grants-column": "Cấp quyền",
        "botpasswords-bad-appid": "Bot có tên \"$1\" không hợp lệ.",
        "botpasswords-insert-failed": "Không thể thêm tên bot \"$1\". Nó đã được thêm vào chưa?",
        "passwordreset-emaildisabled": "Tính năng gửi thư điện tử không được kích hoạt trên wiki này.",
        "passwordreset-username": "Tên người dùng:",
        "passwordreset-domain": "Tên miền:",
-       "passwordreset-capture": "Xem thư điện tử có mật khẩu tạm",
-       "passwordreset-capture-help": "Nếu bạn kiểm hộp này, bạn sẽ xem thư điện tử có mật khẩu tạm lúc khi nó được gửi cho người dùng.",
        "passwordreset-email": "Địa chỉ thư điện tử:",
        "passwordreset-emailtitle": "Thông tin tài khoản tại {{SITENAME}}",
        "passwordreset-emailtext-ip": "Ai đó (có thể là bạn, từ địa chỉ IP $1) đã yêu cầu tái tạo mật khẩu của bạn \ntại {{SITENAME}} ($4). {{PLURAL:$3|Tài khoản|Các tài khoản}} dưới đây gắn liền \nvới địa chỉ thư điện tử này:\n\n$2\n\n{{PLURAL:$3|Mật khẩu|Các mật khẩu}} tạm này sẽ hết hạn trong vòng {{PLURAL:$5|một ngày|$5 ngày}}. Bạn nên đăng nhập\nngay bây giờ để chọn mật khẩu mới. Nếu bạn không phải là người yêu cầu\nhoặc đã nhớ lại mật khẩu hiện hành, và bạn không còn\nmuốn thay đổi nó, xin vui lòng bỏ qua thông điệp này và tiếp tục sử dụng\nmật khẩu cũ.",
        "passwordreset-emailelement": "Tên người dùng: \n$1\n\nMật khẩu tạm: \n$2",
        "passwordreset-emailsentemail": "Nếu đây là đúng địa chỉ thư điện tử của tài khoản của bạn, một thư điện tử dùng để tái tạo mật khẩu sẽ được gửi cho bạn.",
        "passwordreset-emailsentusername": "Nếu một địa chỉ thư điện tử đã gắn với tên người dùng này thì một thư điện tử để đặt lại mật khẩu sẽ được gửi đến.",
-       "passwordreset-emailsent-capture2": "Đã gửi {{PLURAL:$1|thư điện tử|các thư điện tử}} để đặt lại mật khẩu. {{PLURAL:$1|Tên người dùng và mật khẩu|Các tên người dùng và mật khẩu}} được liệt kê dưới đây.",
-       "passwordreset-emailerror-capture2": "Không gửi được thư điện tử đến {{GENDER:$2}}người dùng: $1 {{PLURAL:$3|Tên người dùng và mật khẩu|Các tên người dùng và mật khẩu}} được liệt kê dưới đây.",
        "passwordreset-nocaller": "Yêu cầu hàm gọi",
        "passwordreset-nosuchcaller": "Hàm gọi không tồn tại: $1",
        "passwordreset-ignored": "Tác vụ đặt lại mật khẩu không được xử lý. Có lẽ trình cung cấp chưa được cấu hình?",
-       "passwordreset-invalideamil": "Địa chỉ thư điện tử không hợp lệ",
+       "passwordreset-invalidemail": "Địa chỉ thư điện tử không hợp lệ",
        "passwordreset-nodata": "Cả tên người dùng và địa chỉ thư điện tử bị thiếu",
        "changeemail": "Đổi hoặc gỡ địa chỉ thư điện tử",
        "changeemail-header": "Điền biểu mẫu này để đổi địa chỉ thư điện tử của bạn. Nếu bạn muốn gỡ địa chỉ thư điện tử nào khỏi tài khoản của bạn, để trống hộp địa chỉ thư điện tử mới và lưu biểu mẫu.",
        "search-external": "Tìm kiếm từ bên ngoài",
        "searchdisabled": "Chức năng tìm kiếm tại {{SITENAME}} đã bị tắt. Bạn có tìm kiếm bằng Google trong thời gian này. Chú ý rằng các chỉ mục từ {{SITENAME}} của chúng có thể đã lỗi thời.",
        "search-error": "Đã xuất hiện lỗi khi tìm kiếm: $1",
+       "search-warning": "Đã xuất hiện lỗi khi tìm kiếm: $1",
        "preferences": "Tùy chọn",
        "mypreferences": "Tùy chọn",
        "prefs-edits": "Số lần sửa đổi:",
        "prefs-help-recentchangescount": "Số này bao gồm các thay đổi gần đây, lịch sử trang, và nhật trình.",
        "prefs-help-watchlist-token2": "Đây là chìa khóa bí mật cho nguồn cấp dữ liệu danh sách theo dõi của bạn.\nBất cứ ai biết nó sẽ có thể để đọc danh sách theo dõi của bạn, vì vậy đừng chia sẻ nó.\n[[Special:ResetTokens|Nhấn chuột vào đây nếu bạn cần phải thiết lập lại nó]].",
        "savedprefs": "Đã lưu các tùy chọn cá nhân.",
-       "savedrights": "Đã lưu các quyền hạn của người dùng {{GENDER:$1}}$1.",
+       "savedrights": "Đã lưu các nhóm người dùng của {{GENDER:$1}}$1.",
        "timezonelegend": "Múi giờ:",
        "localtime": "Giờ hiện tại:",
        "timezoneuseserverdefault": "Sử dụng giờ mặc định của wiki ($1)",
        "prefswarning-warning": "Bạn chưa lưu những thay đổi tùy chọn đã thực hiện.\nNếu bạn rời khỏi trang này mà không bấm “$1”, các tùy chọn của bạn sẽ không được cập nhật.",
        "prefs-tabs-navigation-hint": "Mẹo: Bạn có thể bấm các phím mũi tên trái phải để luân chuyển qua các thẻ trong danh sách thẻ.",
        "userrights": "Quản lý quyền thành viên",
-       "userrights-lookup-user": "Quản lý nhóm thành viên",
+       "userrights-lookup-user": "Chọn thành viên",
        "userrights-user-editname": "Nhập tên thành viên:",
-       "editusergroup": "Sửa nhóm {{GENDER:$1}}người dùng",
+       "editusergroup": "Tải nhóm người dùng",
        "editinguser": "Thay đổi quyền hạn của người dùng <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Sửa nhóm thành viên",
        "saveusergroups": "Lưu nhóm {{GENDER:$1}}người dùng",
        "userrights-reason": "Lý do:",
        "userrights-no-interwiki": "Bạn không có quyền thay đổi quyền hạn của thành viên tại các wiki khác.",
        "userrights-nodatabase": "Cơ sở dữ liệu $1 không tồn tại hoặc nằm ở bên ngoài.",
-       "userrights-nologin": "Bạn phải [[Special:UserLogin|đăng nhập]] vào một tài khoản có quyền quản lý để gán quyền cho thành viên.",
-       "userrights-notallowed": "Bạn không có quyền gán hoặc bãi miễn quyền cho thành viên.",
        "userrights-changeable-col": "Những nhóm bạn có thể thay đổi",
        "userrights-unchangeable-col": "Những nhóm bạn không thể thay đổi",
        "userrights-conflict": "Mâu thuẫn thay đổi sửa nhóm thành viên! Xin vui lòng xem lại và xác nhận các thay đổi của bạn.",
-       "userrights-removed-self": "Bạn đã loại bỏ quyền của chính mình nên không còn truy cập được trang này.",
        "group": "Nhóm:",
        "group-user": "Thành viên thông thường",
        "group-autoconfirmed": "Thành viên tự xác nhận",
        "right-siteadmin": "Khóa và mở khóa cơ sở dữ liệu",
        "right-override-export-depth": "Xuất trang kèm theo các trang được liên kết đến với độ sâu tối đa là 5",
        "right-sendemail": "Gửi thư điện tử cho thành viên khác",
-       "right-passwordreset": "Xem các thư điện tử đặt lại mật khẩu",
        "right-managechangetags": "Tạo và bật/tắt [[Special:Tags|thẻ]]",
        "right-applychangetags": "Áp dụng [[Special:Tags|thẻ]], cùng với những thay đổi của một người",
        "right-changetags": "Thêm và loại bỏ tùy ý các [[Special:Tags|thẻ]] vào các phiên bản riêng và các mục nhật trình",
        "grant-basic": "Quyền cơ bản",
        "grant-viewdeleted": "Xem các trang và tập tin đã xóa",
        "grant-viewmywatchlist": "Xem danh sách theo dõi của bạn",
+       "grant-viewrestrictedlogs": "Xem mục nhật trình hạn chế",
        "newuserlogpage": "Nhật trình mở tài khoản",
        "newuserlogpagetext": "Đây là danh sách những tài khoản thành viên mở lên gần đây.",
        "rightslog": "Nhật trình cấp quyền thành viên",
        "apisandbox-continue": "Tiếp tục",
        "apisandbox-continue-clear": "Đặt lại",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} sẽ [https://www.mediawiki.org/wiki/API:Query#Continuing_queries tiếp tục] lời yêu cầu cuối cùng; {{int:apisandbox-continue-clear}} sẽ đặt lại các tham số có liên quan đến chức năng tiếp tục yêu cầu.",
+       "apisandbox-param-limit": "Nhập <kbd>max</kbd> để sử dụng hạn chế tối đa.",
+       "apisandbox-multivalue-all-namespaces": "$1 (Tất cả các không gian tên)",
+       "apisandbox-multivalue-all-values": "$1 (Tất cả các giá trị)",
        "booksources": "Nguồn sách",
        "booksources-search-legend": "Tìm kiếm nguồn sách",
        "booksources-search": "Tìm kiếm",
        "booksources-text": "Dưới đây là danh sách những trang bán sách mới và cũ, đồng thời có thể có thêm thông tin về những cuốn sách bạn đang tìm:",
        "booksources-invalid-isbn": "ISBN mà bạn cung cấp dường như không đúng; xin hãy kiểm tra lại xem có lỗi gì khi sao chép từ nội dung gốc hay không.",
+       "magiclink-tracking-rfc": "Trang sử dụng liên kết tự động RFC",
+       "magiclink-tracking-rfc-desc": "Trang sử dụng liên kết tự động RFC. Xem thông tin về cách chuyển đổi tại [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
+       "magiclink-tracking-pmid": "Trang sử dụng liên kết tự động PMID",
+       "magiclink-tracking-pmid-desc": "Trang sử dụng liên kết tự động PMID. Xem thông tin về cách chuyển đổi tại [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
+       "magiclink-tracking-isbn": "Trang sử dụng liên kết tự động ISBN",
+       "magiclink-tracking-isbn-desc": "Trang sử dụng liên kết tự động ISBN. Xem thông tin về cách chuyển đổi tại [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org].",
        "specialloguserlabel": "Người thực hiện:",
        "speciallogtitlelabel": "Mục tiêu (tiêu đề hoặc {{ns:user}}:Tên-người-dùng đối với người dùng):",
        "log": "Nhật trình",
        "activeusers-intro": "Dánh sách này liệt kê các thành viên đã hoạt động cách nào đó trong $1 ngày qua.",
        "activeusers-count": "$1 tác vụ trong {{PLURAL:$3|ngày|$3 ngày}} qua",
        "activeusers-from": "Hiển thị thành viên bắt đầu từ:",
-       "activeusers-hidebots": "Ẩn robot",
-       "activeusers-hidesysops": "Ẩn bảo quản viên",
+       "activeusers-groups": "Xem những người dùng theo nhóm:",
+       "activeusers-excludegroups": "Trừ những người dùng thuộc các nhóm:",
        "activeusers-noresult": "Không thấy thành viên.",
        "activeusers-submit": "Xem người dùng tích cực",
        "listgrouprights": "Nhóm thành viên",
        "modifiedarticleprotection": "đã đổi mức khóa cho “[[$1]]”",
        "unprotectedarticle": "đã mở khóa cho “[[$1]]”",
        "movedarticleprotection": "đã di chuyển thiết lập khóa trang từ “[[$2]]” đến “[[$1]]”",
+       "protectedarticle-comment": "{{GENDER:$2}}Đã khóa “[[$1]]”",
+       "modifiedarticleprotection-comment": "Đã {{GENDER:$2|thay đổi mức khóa}} của “[[$1]]”",
+       "unprotectedarticle-comment": "{{GENDER:$2}}Đã mở khóa “[[$1]]”",
        "protect-title": "Thiết lập mức khóa cho “$1”",
        "protect-title-notallowed": "Xem mức khóa cho “$1”",
        "prot_1movedto2": "[[$1]] đổi thành [[$2]]",
        "movelogpagetext": "Dưới đây là danh sách các trang đã được di chuyển.",
        "movesubpage": "{{PLURAL:$1|Trang con|Các trang con}}",
        "movesubpagetext": "Trang này có $1 trang con như hiển thị dưới đây.",
+       "movesubpagetalktext": "Trang thảo luận tương ứng có $1 trang con như hiển thị dưới đây.",
        "movenosubpage": "Trang này không có trang con.",
        "movereason": "Lý do:",
        "revertmove": "lùi lại",
        "pageinfo-category-pages": "Số trang",
        "pageinfo-category-subcats": "Số thể loại con",
        "pageinfo-category-files": "Số tập tin",
+       "pageinfo-user-id": "ID người dùng",
        "markaspatrolleddiff": "Đánh dấu tuần tra",
        "markaspatrolledtext": "Đánh dấu tuần tra trang này",
        "markaspatrolledtext-file": "Đánh dấu đã tuần tra phiên bản file này",
        "patrol-log-header": "Đây là nhật trình tuần tra phiên bản.",
        "log-show-hide-patrol": "$1 nhật trình tuần tra",
        "log-show-hide-tag": "Nhật trình đánh dấu $1",
+       "confirm-markpatrolled-button": "OK",
+       "confirm-markpatrolled-top": "Đánh dấu tuần tra phiên bản $3 của $2?",
        "deletedrevision": "Đã xóa phiên bản cũ $1",
        "filedeleteerror-short": "Lỗi xóa tập tin: $1",
        "filedeleteerror-long": "Có lỗi khi xóa tập tin:\n\n$1",
        "newimages-showbots": "Xem các tập tin do bot tải lên",
        "newimages-hidepatrolled": "Ẩn tập tin tải lên đã tuần tra",
        "noimages": "Chưa có hình.",
+       "gallery-slideshow-toggle": "Bật/tắt hình nhỏ",
        "ilsubmit": "Tìm kiếm",
        "bydate": "theo ngày",
        "sp-newimages-showfrom": "Trưng bày các tập tin từ $2 $1 trở về sau",
        "tags-deactivate": "vô hiệu",
        "tags-hitcount": "$1 thay đổi",
        "tags-manage-no-permission": "Bạn không có quyền hạn để quản lý các thẻ thay đổi.",
-       "tags-manage-blocked": "Bạn không thể quản lý thẻ đánh dấu trong lúc bị cấm.",
+       "tags-manage-blocked": "{{GENDER:$1}}Bạn không thể quản lý thẻ đánh dấu trong lúc bị cấm.",
        "tags-create-heading": "Tạo một thẻ mới",
        "tags-create-explanation": "Theo mặc định, các thẻ mới được tạo ra sẽ được hợp lệ hóa để người dùng và các bot sử dụng.",
        "tags-create-tag-name": "Tên thẻ:",
        "tags-deactivate-not-allowed": "Không thể vô hiệu hóa thẻ “$1”.",
        "tags-deactivate-submit": "Vô hiệu",
        "tags-apply-no-permission": "Bạn không có quyền áp dụng các thẻ thay đổi cùng các thay đổi của bạn.",
-       "tags-apply-blocked": "Bạn không thể thay đổi các thẻ đánh dấu cùng với các thay đổi của bạn trong lúc bị cấm.",
+       "tags-apply-blocked": "{{GENDER:$1}}Bạn không thể thay đổi các thẻ đánh dấu cùng với các thay đổi của bạn trong lúc bị cấm.",
        "tags-apply-not-allowed-one": "Thẻ “$1” không được phép được áp dụng thủ công.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|Thẻ|Các thẻ}} sau không được phép áp dụng thủ công: $1",
        "tags-update-no-permission": "Bạn không có quyền thêm hoặc loại bỏ các thẻ thay đổi từ phiên bản riêng hoặc mục nhật trình.",
-       "tags-update-blocked": "Bạn không thể gắn hoặc gỡ thẻ đánh dấu trong lúc bị cấm.",
+       "tags-update-blocked": "{{GENDER:$1}}Bạn không thể gắn hoặc gỡ thẻ đánh dấu trong lúc bị cấm.",
        "tags-update-add-not-allowed-one": "Thẻ “$1” không được phép thêm vào thủ công.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|Thẻ|Các thẻ}} sau không được phép thêm thủ công: $1",
        "tags-update-remove-not-allowed-one": "Thẻ đánh dấu “$1” không được phép loại bỏ.",
        "htmlform-user-not-exists": "<strong>$1</strong> không tồn tại.",
        "htmlform-user-not-valid": "<strong>$1</strong> không phải là tên người dùng.",
        "logentry-delete-delete": "$1 {{GENDER:$2}}đã xóa trang “$3”",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2}}đã xóa trang đổi hướng $3 bằng cách ghi đè",
        "logentry-delete-restore": "$1 {{GENDER:$2}}đã phục hồi trang “$3”",
        "logentry-delete-event": "$1 {{GENDER:$2}}đã thay đổi mức hiển thị của {{PLURAL:$5|một mục nhật trình|$5 mục nhật trình}} về $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2}}đã thay đổi mức hiển thị của {{PLURAL:$5|một phiên bản|$5 phiên bản}} trang $3: $4",
        "feedback-thanks": "Cảm ơn! Phản hồi của bạn đã được đăng lên trang “[$2 $1]”.",
        "feedback-thanks-title": "Cảm ơn!",
        "feedback-useragent": "Tác nhân người dùng:",
-       "searchsuggest-search": "Tìm kiếm",
+       "searchsuggest-search": "Tìm kiếm {{SITENAME}}",
        "searchsuggest-containing": "có chứa…",
        "api-error-autoblocked": "Địa chỉ IP của bạn bị cấm tự động vì nó đã được sử dụng bởi một người dùng bị cấm.",
        "api-error-badaccess-groups": "Bạn không được phép tải tập tin lên wiki này.",
        "mw-widgets-dateinput-no-date": "Không chọn ngày tháng",
        "mw-widgets-dateinput-placeholder-day": "YYYY-MM-DD (năm-tháng-ngày)",
        "mw-widgets-dateinput-placeholder-month": "YYYY-MM (năm-tháng)",
+       "mw-widgets-mediasearch-input-placeholder": "Tìm phương tiện",
+       "mw-widgets-mediasearch-noresults": "Không tìm thấy kết quả.",
        "mw-widgets-titleinput-description-new-page": "trang này chưa tồn tại",
        "mw-widgets-titleinput-description-redirect": "đổi hướng đến $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Thêm thể loại…",
        "sessionmanager-tie": "Không thể kết hợp nhiều yêu cầu xác thực loại: $1.",
        "sessionprovider-generic": "phiên $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "phiên dựa trên cookie",
        "log-action-filter-contentmodel-change": "Thay đổi kiểu nội dung",
        "log-action-filter-contentmodel-new": "Tạo trang có kiểu nội dung không chuẩn",
        "log-action-filter-delete-delete": "Xóa trang",
+       "log-action-filter-delete-delete_redir": "Ghi đè trang đổi hướng",
        "log-action-filter-delete-restore": "Phục hồi trang",
        "log-action-filter-delete-event": "Xóa nhật trình",
        "log-action-filter-delete-revision": "Xóa phiên bản",
        "authmanager-authn-autocreate-failed": "Thất bại khi tự động tạo tài khoản địa phương: $1",
        "authmanager-change-not-supported": "Không thể thay đổi định danh được cung cấp, vì sẽ không có gì sử dụng nó.",
        "authmanager-create-disabled": "Chứng năng tạo tài khoản được tắt.",
-       "authmanager-create-from-login": "Để tạo tài khoản của mình, xin hãy điền vào các thông tin bên dưới.",
+       "authmanager-create-from-login": "Để tạo tài khoản của mình, xin hãy điền vào các thông tin.",
        "authmanager-create-not-in-progress": "Không phải đang tạo tài khoản, hoặc dữ liệu phiên làm việc bị mất. Xin hãy thử lại từ đầu.",
        "authmanager-create-no-primary": "Không thể sử dụng định danh được cung cấp để tạo tài khoản.",
        "authmanager-link-no-primary": "Không thể sử dụng định danh được cung cấp để liên kết tài khoản.",
index 0f2b80e..c4d76c3 100644 (file)
        "yourname": "Benudsârnôômâ",
        "yourpassword": "Bhaswôrd:",
        "yourpasswordagain": "Bassworrd widderhulln:",
-       "remembermypassword": "Miid den Brauser dauerhafd ogmeld bleim (maximal $1 {{PLURAL:$1|Dooch|Dooch}})",
        "login": "Ôômeldn",
        "nav-login-createaccount": "Oomeldn / Ghondoo ooleeng",
        "userlogin": "Ôômeldn / Als Bajdräächâr ajschrajm",
index 71f37b9..52d2d5b 100644 (file)
        "listusers-noresult": "Geban nonik petuvon.",
        "listusers-blocked": "(pebloköl)",
        "activeusers-count": "{{PLURAL:$1|dunot|dunots}} $1 ün {{PLURAL:$3|del lätik|dels lätik $3}}",
-       "activeusers-hidebots": "Klänedolöd elis bot",
-       "activeusers-hidesysops": "Klänedolöd guvanis",
        "activeusers-noresult": "Geban nonik petuvon.",
        "listgrouprights": "Gitäts gebanagrupa",
        "listgrouprights-summary": "Is palisedons gebanagrups in vük at dabinöls, sa gitäts tefik onsik.\nBa dabinons [[{{MediaWiki:Listgrouprights-helppage}}|nüns pluik]] tefü gebanagitäts patik.",
        "logentry-newusers-create": "Gebanakal: $1 pejafon",
        "rightsnone": "(nonik)",
        "revdelete-summary": "plän redakama",
-       "feedback-error-title": "Pöl",
        "feedback-subject": "Yegäd:",
        "searchsuggest-search": "Suk",
        "searchsuggest-containing": "ninädöl...",
index ef9200d..d1460b8 100644 (file)
        "yourname": "Cäüttijänimi:",
        "yourpassword": "Salasõna",
        "yourpasswordagain": "Tõissaga salain-sõna:",
-       "remembermypassword": "Mäleht minuu (enintään $1 {{PLURAL:$1|päivä|päivää}})",
        "login": "Cirjut süäme",
        "nav-login-createaccount": "Cirjut süäme vai registriiroit cäüttijässi",
        "userlogin": "Cirjut süäme",
index 9937693..de1dd5f 100644 (file)
        "booksources": "Sourdants po les lives",
        "booksources-search-legend": "Cweri des sourdants po des lives",
        "booksources-search": "Cweri",
+       "booksources-invalid-isbn": "L'ISBN ki vos avoz scrît n' est nén bon; sayîz del raveuri, s' i vs plait",
+       "magiclink-tracking-pmid": "Pådje avou des hårdêyes otomatikes PMID",
+       "magiclink-tracking-isbn": "Pådjes avou des hårdêyes otomatikes ISBN",
+       "magiclink-tracking-isbn-desc": "So cisse pådje cial, gn a ene hårdêye otomatike ISBN. Loukîz so [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] po vey kimint aler dsu",
        "specialloguserlabel": "Fwait pa:",
        "speciallogtitlelabel": "Såme (tite ou uzeu):",
        "log": "Djournås",
        "listusers-submit": "Vey",
        "listusers-noresult": "Nol uzeu di trové.",
        "listusers-blocked": "({{GENDER:$1|bloké|blokêye}})",
-       "activeusers-hidebots": "Catchî les robots",
        "listgrouprights-members": "(djivêye des mimbes)",
        "mailnologin": "Nole adresse d' evoyeu",
        "mailnologintext": "Po-z evoyî èn emile a èn ôte uzeu i vs fåt esse [[Special:UserLogin|elodjî]] eyet aveur ene adresse emile d' evoyeu ki soeye valide dins vos [[Special:Preferences|preferinces]].",
index 9f36244..9a4f66e 100644 (file)
        "yourpasswordagain": "Utroha pagbutang an tigaman-han-pagsakob:",
        "createacct-yourpasswordagain": "Igkompirma an tigaman-pagsakob",
        "createacct-yourpasswordagain-ph": "Igbutang an tigaman-pagsakob utro",
-       "remembermypassword": "Hinumdumi an akon pan-sakob dinhi nga panngaykay ''(browser)'' (para ha pinakamaiha $1 {{PLURAL:$1|ka adlaw|ka mga adlaw}})",
        "userlogin-remembermypassword": "I-log-in la ako",
        "userlogin-signwithsecure": "Gamit hin koneksyon nga nakakasegurado",
        "cannotloginnow-title": "Diri nakakalog-in yana",
        "botpasswords-label-delete": "Paraa",
        "botpasswords-label-resetpassword": "Igreset an password",
        "botpasswords-label-grants": "Mga applicable grant",
-       "botpasswords-label-restrictions": "Mga gindidiri ha paggamit:",
        "botpasswords-label-grants-column": "Ginhatag",
        "botpasswords-bad-appid": "An ngaran han bot nga \"$1\" in diri puydi gamiton.",
        "botpasswords-insert-failed": "Pakyas han pagdugang han ngaran han bot nga \"$1\". Naidugang na ini?",
        "passwordreset-emailtext-ip": "Mayda gumaramit (bangin hi ikaw, tikang han IP adres nga $1) nga naghangyo hin reset han imo tigaman-pansulod han {{SITENAME}} ($4). An nasunod nga gumaramit {{PLURAL:$3|nga akawnt|nga mga akawnt}} nahanungod hini nga email nga adres: \n\n$2\n\n{{PLURAL:$3|Iní nga temporaryo nga tigaman-pansulod|Iní nga mga temporaryo nga tigaman-pansulod}} ma-waray bali hin {{PLURAL:$5|usa ka adlaw|$5 nga mga adlaw}}.\nAngay ka sumakob ngan pumílì hin bag-o nga tigaman-pansulod ha yanâ.  Kun mayda lain nga naghatag hini nga hangyo, o kun nahinumdoman mo an imo orihinal nga tigaman-pansulod, ngan nadírì ka na pagbalyo hiní, puyde mo pasagdan ini nga sumat ngan magpadayon hin paggamit han imo daan nga tigaman-pansulod.",
        "passwordreset-emailelement": "Agnay han gumaramit: \n$1\n\nTemporaryo nga tigaman han pagsakob: \n$2",
        "passwordreset-emailsentemail": "Kun inin nga email address in may pagkahisumpay ha imo account, papadangaton ka hin usa nga password reset email.",
-       "passwordreset-emailsent-capture": "Ginpadangat an password reset email, nga ginpakita ha ubos.",
-       "passwordreset-emailerror-capture": "Ginhimo an password reset email, kun diin nakikita ha ubos, pero pakyas an pagpadara ha  {{GENDER:$2|gumaramit}}: $1",
        "changeemail": "Igliwat o igtanggal an e-mail address",
        "changeemail-header": "Kompletoha ini nga form para masalyuan an imo email address. Kun karuyag nimo tanggalun an may pagkahisumpay han bisan ano nga email address tikang ha imo account, blankoha la an bag-o nga email address kun magsusumiti ka han form.",
-       "changeemail-passwordrequired": "Kinahanglan nim igbutang an imo password para igkompirma inin nga pagbag-o.",
        "changeemail-no-info": "Kinahanglanon mo mag-log-in para ka direkta makasakob hini nga pakli.",
        "changeemail-oldemail": "Yana nga e-mail address:",
        "changeemail-newemail": "Bag-o nga e-mail address:",
        "undo-norev": "An pagliwat in diri mapapawaray-buhat tungod waray ito dida o napara na.",
        "undo-summary": "Ginpawara-buhat an rebisyon nga $1 ni [[Special:Contributions/$2|$2]] ([[User talk:$2|himangrawi]])",
        "undo-summary-username-hidden": "Igpawara-an-ginbuhat nga rebisyon $1 han uska tago nga gumaramit",
-       "cantcreateaccounttitle": "Diri makakahimo hin akawnt",
        "cantcreateaccount-text": "An paghimo hin akawnt hini nga IP address  ('''$1''') in ginpugngan ni [[User:$3|$3]]. An rason nga ginhatag ni $3 in ''$2''",
        "viewpagelogs": "Kitaa an mga log para hini nga pakli",
        "nohistory": "Waray kaagi hin pagliwat hin nga pakli.",
        "listusers-blocked": "(ginpugngan)",
        "activeusers": "Taramdan hin mga gumaramit nga nanggigios",
        "activeusers-from": "Igpakita an mga gumaramit tikang ha:",
-       "activeusers-hidebots": "Igtago an mga bot",
-       "activeusers-hidesysops": "Igtago an mga magdudumara",
        "activeusers-noresult": "Waray gumaramit nga nahiagian.",
        "activeusers-submit": "Igpakita an mga gumaramit nga nangigios",
        "listgrouprights": "Mga katungod han grupo hin gumaramit",
        "feedback-back": "Balik",
        "feedback-cancel": "Pasagdi",
        "feedback-close": "Human na.",
-       "feedback-error-title": "Sayop",
        "feedback-error2": "Sayop: Pakyas an pagliwat",
        "feedback-message": "Mensahe:",
        "feedback-subject": "Himangrawon:",
index e9877a5..5197c00 100644 (file)
        "yourpasswordagain": "密码再打一遍:",
        "createacct-yourpasswordagain": "确认密码",
        "createacct-yourpasswordagain-ph": "再打一遍密码",
-       "remembermypassword": "来箇只浏览器上记牢我个登录状态(顶长$1天)",
        "userlogin-remembermypassword": "记牢我个登录状态",
        "userlogin-signwithsecure": "用保险链接",
        "yourdomainname": "侬个域名:",
index 7dae096..c27fc60 100644 (file)
        "yourname": "Демнәчнә нерн:",
        "yourpassword": "Нууц үг:",
        "yourpasswordagain": "Нууц үг давтн:",
-       "remembermypassword": "Намаг эн тоолдврд тодлх ($1 {{PLURAL:$1|1=өдрт|өдрмүдт}} икәр биш)",
        "yourdomainname": "Тана домен:",
        "login": "Орлһн",
        "nav-login-createaccount": "Орх/бүрткгдх",
index d67a289..51150e4 100644 (file)
        "yourpasswordagain": "კჷნე გეკორობით პაროლი:",
        "createacct-yourpasswordagain": "დადასურით პაროლი",
        "createacct-yourpasswordagain-ph": "ხოლო ართშა გენშიონით პაროლი",
-       "remembermypassword": "ქჷგიშინი ჩქიმი მიშულა თე ბრაუზერს (მაქსიმუმ $1 დღას)",
        "userlogin-remembermypassword": "ქუდომტე მიშულირო",
        "userlogin-signwithsecure": "უსაფრთხო კავშირის გამოყენება",
        "yourdomainname": "თქვან დომენ",
        "passwordreset-emailtext-user": "მომხმარებელმა $1 პროექტიდან {{SITENAME}} მოითხოვა თქვენი \nპაროლის თავიდან დაყენება საიტისათვის {{SITENAME}} ($4).\n{{PLURAL:$3|შემდეგი ანგარიში მიბმულია|შემდეგი ანგარიშები მიბმულია}} ამ ელ.ფოსტის მისამართზე:\n\n$2\n\n{{PLURAL:$3|ეს დროებითი პაროლი|ეს დროებითი პაროლები}} იმოქმედებს {{PLURAL:$5|ერთი დღე|$5 დღე}}.\nთქვენ უნდა შეხვიდეთ სისტემაში და აირჩიოთ ახალი პაროლი.\nთუ თქვენ არ გაგიკეთებიათ აღნიშნული მოთხოვნა, ან გაიხსენეთ თქვენი პაროლი\nდა აღარ გსურთ მისი შეცვლა, მაშინ შეგიძლიათ იგნორირება გაუკეთოთ ამ შეტყობინებას\nდა გააგრძელოთ თქვენი ძველი პაროლის გამოყენება.",
        "passwordreset-emailelement": "მომხმარებლის სახელი: \n$1\n\nდროებითი პაროლი: \n$2",
        "passwordreset-emailsentemail": "პაროლის თავიდან დასაყენებელი ელ.ფოსტა გაიგზავნა.",
-       "passwordreset-emailsent-capture": "ქვემოთ ნაჩვენები პაროლის თავიდან დასაყენებელი წერილი გაიგზავნა.",
-       "passwordreset-emailerror-capture": "ქვემოთ მოცემულია შექმნილი პაროლის დასაყენებელი წერილი, რომლის გაგზავნაც {{GENDER:$2|მომხმარებელთან}} ვერ მოხერხდა: $1 გამო",
        "changeemail": "გენშიონით თქვანი ელ. ფოსტაშ ოწურაფუ",
        "changeemail-header": "შეავსეთ ეს ფორმა თქვენი ელ-ფოსტის მისამართის შესაცვლელად. თქვენი პაროლის შეყვანა დაგჭირდებათ ამ ცვლილების დასადასტურებლად.",
        "changeemail-no-info": "კონკრეტულად ამ გვერდთან სამუშაოდ თქვენ უნდა წარადგინოთ თავი სისტემისადმი.",
        "undo-norev": "რედაქტირება ვერ გაუქმდება რადგანაც არ არსებობს ან წაშლილი იქნა.",
        "undo-nochange": "როგორც ჩანს, რედაქტირება უკვე გაუქმდა.",
        "undo-summary": "[[Special:Contributions/$2|$2-ის]]([[User talk:$2|განხილვა]]) ცვლილებების გაუქმება (№$1)",
-       "cantcreateaccounttitle": "ანგარიშის შექმნა ვერ ხერხდება",
        "cantcreateaccount-text": "ამ IP-მისამართიდან აიკრძალა (<strong>$1</strong>) მომხმარებელ [[User:$3|$3]]-ის მიერ.\n\n$3-მა მიუთითა შემდეგი მიზეზი: <em>$2</em>",
        "viewpagelogs": "თე ხასჷლაშო ორეგისტრაციე ჟურნალეფიშ ძირაფა",
        "nohistory": "ამ გვერდს განხილვის გვერდი ცარიელი აქვს.",
        "feedback-external-bug-report-button": "ტექნიკური დავალების გაგზავნა",
        "feedback-dialog-title": "გამოხმაურების გაგზავნა",
        "feedback-dialog-intro": "თქვენ შეგიძლიათ ისარგებლოთ ქვემოთ არსებული მარტივი ფორმით, რათა დატოვოთ თქვენი გამოძახილი. კომენტარები თქვენ მომხმარებლის სახელთან ერთად დამატებული იქნება \"$1\" გვერდზე",
-       "feedback-error-title": "ჩილათა",
        "feedback-error1": "შეცდომა. API-ს მოულოდნელი რეზულტატი",
        "feedback-error2": "შეცდომა: რედაქტირება ვერ განხორციელდა",
        "feedback-error3": "შეცდომა. არ არის API-ს პასუხი",
index d2f0247..8a9f6f1 100644 (file)
        "passwordreset-emailsentusername": "טאמער איז פאראן אן ע־פאסט אדרעס פארקניפט מיט דעם באניצער־נאמען, וועט מען שיקן א פאסווארט צוריקשטעלן ע-פּאָסט.",
        "passwordreset-nocaller": "מען דארף פֿארזארגן א רופֿער",
        "passwordreset-nosuchcaller": "רופֿער איז נישט פֿאראן: $1",
-       "passwordreset-invalideamil": "אומגילטיקער ע־פאסט אדרעס",
+       "passwordreset-invalidemail": "אומגילטיקער ע־פאסט אדרעס",
        "changeemail": "ענדערן אדער אראפנעמען ע-פּאָסט אַדרעס",
        "changeemail-header": "דערגאַנצט די פֿאָרעם צו ענדערן אייער ע-פּאָסט אַדרעס .\nטאמער ווילט איר אראפנעמען די צוארדנונג פון איינעם פון אייערע ע־פאסט אדרעסן פו אייער קאנטע, לאזט ליידיג דעם נייעם ע־פאסט אדרעס ווען איר גיט איין די פֿארעם.",
        "changeemail-no-info": "איר דאַרפֿט זיין אַרײַנלאגירט צוצוקומען גלײַך צו דעם דאָזיגן בלאַט.",
        "activeusers-intro": "דאָס איז א ליסטע פֿון באַניצער וואָס זענען געווען אַקטיוו אינערהאָלב  $1 {{PLURAL:$1|דעם לעצטן טאָג|די לעצטע $1 טעג}}.",
        "activeusers-count": "$1 {{PLURAL:$1|פעולה|פעולות}} אין  {{PLURAL:$3|דעם לעצטן טאָג|די לעצטע $3 טעג}}",
        "activeusers-from": "ווײַזן באַניצער אָנהייבנדיג פון:",
-       "activeusers-hidebots": "באַהאַלטן באטן",
-       "activeusers-hidesysops": "באַהאַלטן סיסאפן",
        "activeusers-noresult": "קיין באניצער נישט געטראפֿן.",
        "activeusers-submit": "ווייזן טעטיגע באניצער",
        "listgrouprights": "באַניצער גרופע רעכטן",
index 1c41e4a..bd8577c 100644 (file)
@@ -15,6 +15,7 @@
        "tog-hideminor": "Ìbòmọ́lẹ̀ àwọn àtúnṣe kékeré nínú àwọn àtúnse tuntun",
        "tog-hidepatrolled": "Ìbòmọ́lẹ̀ àwọn àtúnṣe oníìṣọ́ nínú àwọn àtúnṣe tuntun",
        "tog-newpageshidepatrolled": "Ìbòmọ́lẹ̀ àwọn ojúewé oníìṣọ́ lọ́dọ̀ àtòjọ ojúewé tuntun",
+       "tog-hidecategorization": "Ìbòmọ́lẹ̀ ìṣeẹ̀ka àwọn ojúewé",
        "tog-extendwatchlist": "Ìfẹ̀ àmójútó láti ṣ'àfihàn gbogbo àtúnṣe, kìí ṣe tuntun nìkan",
        "tog-usenewrc": "Ìtò àwọn àtúnṣe gẹ́gẹ́bí ojúewé nínú àwọn àtúnṣe tuntun àti ìmújútó",
        "tog-numberheadings": "Àwọn àkọlé nọmba-araẹni",
@@ -25,6 +26,7 @@
        "tog-watchdefault": "Ṣ'àfikún àwọn ojúewé àti fáìlì tí mo ṣ'àtúnse mọ́ ìmójútó mi",
        "tog-watchmoves": "Ṣ'àfikún àwọn ojúewé ati fáìlì tí mo yípò mọ́ ìmójútó mi",
        "tog-watchdeletion": "Ṣ'àfikún àwọn ojúewé àti fáìlì tí mo parẹ́ mọ́ ìmójútó mi",
+       "tog-watchuploads": "Ìdàpọ̀ àwọn fáìlì tuntun sí ìmójútó mi",
        "tog-minordefault": "Se àmì sí gbogbo àtúnse gẹ́gẹ́ bi kékeré lát'ìbẹ̀rẹ̀.",
        "tog-previewontop": "Se àyẹ̀wò kí ẹ tó s'àtúnṣe",
        "tog-previewonfirst": "S'àfihàn àgbéwò fún àtúnse àkọ́kọ́",
@@ -33,7 +35,7 @@
        "tog-enotifminoredits": "Fi e-mail ránṣẹ́ sí mi bákannà fún àtúnṣe kékékèé sí àwọn ojúewé àti fáìlì",
        "tog-enotifrevealaddr": "Ṣ'àfihàn àdírẹ́ẹ̀sì e-mail mi nínú àwọn ìránṣẹ́ e-mail",
        "tog-shownumberswatching": "S'àfihàn iye àwọn oníṣe tí wọn tẹjú mọ́ọ",
-       "tog-oldsig": "Ìtọwọ́bọ̀wé tówà:",
+       "tog-oldsig": "Ìtọwọ́bọ̀wé yín tówà lọ́wọ́:",
        "tog-fancysig": "Ṣe ìtọwọ́bọ̀wé bíi ìkọ wiki (láìní ìjápọ̀ fúnrararẹ̀)",
        "tog-uselivepreview": "Ìlo àkọ́kọ́yẹ̀wò lẹ́ṣẹ̀kẹṣẹ̀ (àdánwò)",
        "tog-forceeditsummary": "Kìlọ̀ fún mi tí àkótán àtúnṣe bá jẹ́ òfo",
        "passwordreset-emaildisabled": "Ìdálẹ́kun lílo email lórí wiki yìí.",
        "passwordreset-username": "Orúkọ oníṣe:",
        "passwordreset-domain": "Àbùgbé:",
-       "passwordreset-capture": "Wo e-mail tí yíò jáde?",
-       "passwordreset-capture-help": "Tí ẹ bá fagi sínú àpótí yìí, e-mail náà (pẹ̀lú ọ̀rọ̀ìpamọ́ onígbàdíẹ̀) yíò hàn si yín bákannáà yíò jẹ́ fífiránṣẹ́ sí oníṣe náà.",
        "passwordreset-email": "Àdírẹ̀sì e-mail:",
        "passwordreset-emailtitle": "Àwọn ẹ̀kúnrẹ́rẹ́ àpamọ́ lórí {{SITENAME}}",
        "passwordreset-emailtext-ip": "Ẹnìkan (bóyá ẹ̀yin ni, láti àdírẹ̀sì IP $1) tọrọ àtúntò ọ̀rọ̀ìpamọ́ yín fún {{SITENAME}} ($4). {{PLURAL:$3|Àkópamọ́|Àwọn àkópamọ́}} oníṣe ìsàlẹ̀ yìí ní ìbáṣe pọ̀ mọ́ àdírẹ̀sì e-mail yìí:\n\n$2\n\n{{PLURAL:$3|Ọ̀rọ̀ìpamọ́ onígbàdíẹ̀ yìí|Àwọn ọ̀rọ̀ìpamọ́ onígbàdíẹ̀ wọ̀nyí}} yíò dópin lẹ́yìn {{PLURAL:$5|ọjọ́ kan|ọjọ́ $5}}.\nẸ gbọ́dọ̀ lọ yan ọ̀rọ̀ìpamọ́ tuntun báyìí. Tóbá jẹ́ pé ẹ̀lòmíràn ló ṣe ìtọrọ yìí, tàbí tọ́bá jẹ́ pé ẹ ti rántí ọ̀rọ̀ìpamọ́ àtètèkọ́ṣe yín, tí ẹ kọ̀ sí fẹ́ yíipadà mọ́, ẹ lé ṣàìkàsí ìránṣẹ́ yìí, kí ẹ sì tẹ̀síwájú ní lo ọ̀rọ̀ìpamọ́ àtijọ́ yín.",
        "search-section": "(abala $1)",
        "search-suggest": "Ṣé ẹ fẹ́: $1",
        "search-interwiki-caption": "Àwọn iṣẹ́-ọwọ́ mìràn",
-       "search-interwiki-default": "èsì $1",
+       "search-interwiki-default": "Ã\81wá»\8dn Ã¨sì láti $1:",
        "search-interwiki-more": "(tókù)",
        "search-relatedarticle": "Tóbáramu",
        "searchrelated": "tóbáramu",
        "userrights-reason": "Ìdíẹ̀:",
        "userrights-no-interwiki": "Ẹ kò ní ìyọ̀nda láti ṣàtúnṣe àwọn ẹ̀tọ́ oníṣe lórí àwọn wiki míràn.",
        "userrights-nodatabase": "Ibùdó dátà $1 kò sí tàbí kò sí lábẹ́lé.",
-       "userrights-nologin": "Ẹ gbọ́dọ̀ [[Special:UserLogin|wọlé]] pẹ̀lú àpamọ́ alámòójútó láti pín àwọn ẹ̀tọ́ oníṣe.",
-       "userrights-notallowed": "Àpamọ́ yín kò ní ìyọ̀nda láti ṣàfikún tàbí ṣàyọkúrò àwọn ẹ̀tọ́ oníṣe.",
        "userrights-changeable-col": "Àwọn ẹgbẹ́ tí ẹ le túnṣe",
        "userrights-unchangeable-col": "Àwọn ẹgbẹ́ tí ẹ kò le túnṣe",
        "group": "Ìdìpọ̀:",
        "right-siteadmin": "Ìtìpa àti ìṣí ibùdó dátà",
        "right-override-export-depth": "Ìkójáde àwọn ojúewé lámùúpọ̀ mọ́ àwọn ojúewé jíjápọ̀ títí dé ìbú 5",
        "right-sendemail": "Fi e-mail ránṣẹ́ sí àwọn oníṣe míràn",
-       "right-passwordreset": "Ìwo àwọn e-mail fún ìtúntò ọ̀rọ̀ìpamọ́",
        "newuserlogpage": "Àkọsílẹ̀ ìdá oníṣe",
        "newuserlogpagetext": "Àkọọ́lẹ̀ àwọn ìdá oníṣe nì yí.",
        "rightslog": "Àwọn ẹ̀tọ́ oníṣe",
        "action-read": "wo ojúewé yìí",
        "action-edit": "ṣàtúnṣe ojúewé yìí",
        "action-createpage": "dá ojúewé yìí",
-       "action-createtalk": "dá ojúewé ìfọ̀rọ̀wérọ̀",
+       "action-createtalk": "dá ojúewé ìfọ̀rọ̀wérọ̀ yìí",
        "action-createaccount": "dá àpamọ́ oníṣe yìí",
        "action-minoredit": "fagisí àtúnṣe yìí gẹ́gẹ́ bíi kékeré",
        "action-move": "yípò ojúewé yìí",
        "upload-too-many-redirects": "URL náà ní àwọn àtúnjúwe pípọ̀jùlọ",
        "upload-http-error": "Àṣìṣe HTTP ti ṣẹlẹ̀: $1",
        "upload-copy-upload-invalid-domain": "Àwòkọ àwọn ìrùsókè kò sí láti apá yìí.",
+       "upload-dialog-title": "Ìrùsókè fáìlì",
+       "upload-dialog-button-cancel": "Fagilé",
+       "upload-dialog-button-back": "Ẹ̀yìn",
+       "upload-dialog-button-save": "Ìmúpamọ́",
+       "upload-dialog-button-upload": "Ìrùsókè",
+       "upload-form-label-infoform-title": "Àwọn ẹ̀kúnrẹ́rẹ́",
+       "upload-form-label-infoform-name": "Orúkọ",
+       "upload-form-label-infoform-description": "Ìjúwe",
+       "upload-form-label-usage-title": "Ìlò",
+       "upload-form-label-usage-filename": "Ọrúkọ fáìlì",
+       "upload-form-label-own-work": "Iṣẹ́-ọwọ́ mi ló jẹ́",
+       "upload-form-label-infoform-categories": "Àwọn ẹ̀ka",
+       "upload-form-label-infoform-date": "Ọjọ́ọdún",
        "backend-fail-stream": "Kò le ṣe ìgbéhànjáde fáìlì \"$1\".",
        "backend-fail-backup": "Kò le ṣe àwòkọpamọ́ fáìlì \"$1\".",
        "backend-fail-notexists": "Fáìlì $1 kò sí.",
        "license-nopreview": "(Àkọ́yẹ̀wò kò sí)",
        "upload_source_url": " (URL oníìbámu kan tó ṣe é bọ́sí látigboro)",
        "upload_source_file": "(fáìlì lórí kọ̀mpútà yín)",
-       "listfiles-summary": "Ojúewé pàtàkì yìí ṣe àfihàn gbogbo àwọn fáìlì àrùsókè.\nTó bá jẹ́ jíjọ̀ gẹ́gẹ́bí oníṣe, àwọn fáìlì tí oníṣe náà tí ru àtúnyẹ̀wò tuntun sòkè sí nìkan ni yíò hàn.",
+       "listfiles-delete": "ìparẹ́",
+       "listfiles-summary": "Ojúewé pàtàkì yìí ṣe àfihàn gbogbo àwọn fáìlì tí a rùsókè.",
        "listfiles_search_for": "Ṣàwàrí fún orúkọ amóhùnmáwòrán:",
        "imgfile": "fáìlì",
        "listfiles": "Àkójọ \tfáìlì",
        "mostrevisions": "Àwọn ojúewé pẹ̀lu àwọn àtúnyẹ̀wò tópọ̀jùlọ",
        "prefixindex": "Gbogbo ojúewé tó ní ìtọ́ka ìpele",
        "prefixindex-namespace": "Gbogbo ojúewé pẹ̀lú àlẹ̀mọ́wájú (orúkọàyè $1)",
+       "prefixindex-submit": "Ìfihàn",
        "shortpages": "Àwọn ojúewé kúkúrú",
        "longpages": "Ojúewé gúngùn",
        "deadendpages": "Àwọn ojúewé aláìníjàápọ́",
        "protectedpages-indef": "Àwọn àbò aláìlópin",
        "protectedpages-cascade": "Àwọn àbò atẹ̀léra nìkan",
        "protectedpagesempty": "Kò sí àwọn ojúewé kankan tó ní àbò pẹ̀lú àwọn pàrámítà wọ̀nyí.",
+       "protectedpages-page": "Ojúewé",
+       "protectedpages-expiry": "Ìparí",
        "protectedtitles": "Àwọn àkọlé ajẹ́dídáàbòbò",
        "protectedtitlesempty": "Kò sí àwọn àkolé kankan tó ní àbò pẹ̀lú àwọn pàrámítà wọ̀nyí.",
        "listusers": "Àkójọ àwọn oníṣe",
        "activeusers-intro": "Èyí ni àtòjọ àwọn oníṣe tí wọ́n ní irú àgbéṣe kan láàrin {{PLURAL:$1|ọjọ́|ọjọ́}} $1 sẹ́yìn.",
        "activeusers-count": "{{PLURAL:$1|Àtúnṣe|Àwọn àtúnṣe}} $1 ní {{PLURAL:$3|ọjọ́|ọjọ́}} $3 sẹ́yìn",
        "activeusers-from": "Ìfihàn àwọn oníṣe nípa bíbẹ̀rẹ̀ láti:",
-       "activeusers-hidebots": "Ìbòmọ́lẹ̀ àwọn bọt",
-       "activeusers-hidesysops": "Ìbòmọ́lẹ̀ àwọn olùmójútó",
        "activeusers-noresult": "Kò rí oníṣe kankan.",
        "listgrouprights": "Àwọn ẹ̀tọ́ ẹgbẹ́ oníṣe",
        "listgrouprights-summary": "Nísàlẹ̀ ni àtòjọ àwọn ẹgbẹ́ oníṣe tó nítumọ̀ lórí wiki yìí, pẹ̀lú àwọn ẹ̀tọ́ lílò wọn.\nÓ ṣe é ṣe kí [[{{MediaWiki:Listgrouprights-helppage}}|ẹ̀kúnrẹ́rẹ́]] ó wà nípa ẹ̀tọ́ kọ̀ọ̀kan.",
        "wlheader-showupdated": "Àwọn ojúewé tí wọn ti yípadà látìgbà tí ẹ ṣàbẹ̀wò wọn gbẹ̀yìn jẹ́ fífihàn ní ''kedere'''",
        "wlnote": "Lábẹ́ {{PLURAL:$1|ni àtúnṣe tó gbẹ̀yìn|ni àwọn àtúnṣe '''$1''' tí wọn gbẹ̀yìn}} ní {{PLURAL:$2|wákàtí kan|wákàtí '''$2'''}} sẹ́yìn, títí dí ọjọ́ $3, $4.",
        "wlshowlast": "Ìfihàn wákàtí $1 sẹ́yìn ọjọ́ $2 sẹ́yìn",
+       "watchlist-hide": "Ìbòmọ́lẹ̀",
+       "watchlist-submit": "Ìfihàn",
+       "wlshowhideminor": "àwọn àtúnṣe kékéèké",
+       "wlshowhidebots": "àwọn bot",
        "watchlist-options": "Àṣàyàn ìmójútọ́",
        "watching": "Ó ún mójútó...",
        "unwatching": "Jíjáwọ́ ìmójútó...",
        "rollback-success": "Ìdápadà àwọn àtúnṣe ti $1;\njẹ́ yíyípadà sí àtúnyẹ̀wò tógbẹ̀yìn látọwọ́ $2.",
        "sessionfailure-title": "Ìkùnà ètò iṣẹ́",
        "sessionfailure": "Ó dà wípé ìsòro wà pẹ̀lú ìwọlé yín;\na ti fagilé gbogbo ohun tí ẹ ti ṣe nísìnsinyì kí ẹlòmíràn ó mọ́ baà ji mú.\nẸ padà sí ojúewé tó kọjá, ẹ tún ojúewé náà gbéjáde, kí ẹ tó tún tó dán wó.",
+       "changecontentmodel-title-label": "Àkọlé ojúewé",
+       "changecontentmodel-reason-label": "Ìdíẹ̀:",
        "protectlogpage": "Àkọsílẹ̀ àbò",
        "protectlogtext": "Nísàlẹ̀ ni àtòjọ àwọn àtúnṣe sí àwọn àbò ojúewé.\nẸ wo [[Special:ProtectedPages|àtòjọ àwọn ojúewé aláàbò]] fún àtòjọ àwọn àbò ojúewé ìgbàyí.",
        "protectedarticle": "ti dá àbò bo \"[[$1]]\"",
        "whatlinkshere-hidelinks": "Ìjápọ̀ $1",
        "whatlinkshere-hideimages": "$1 àwọn ìjápọ̀ fáìlì",
        "whatlinkshere-filters": "Ajọ̀",
+       "whatlinkshere-submit": "Rìnsó",
        "autoblockid": "Ìdínàaláraẹni #$1",
        "block": "Dínà oníṣe",
        "unblock": "Ìmúkúrò ìdínà oníṣe",
        "movenotallowedfile": "Ẹ kò ní ìyọ̀nda láti yípò fáìlì.",
        "cant-move-user-page": "Ẹ kò ní ìyọ̀nda láti yípò àwọn ojúewé oníṣe (àyàfi láti ọ̀dọ̀ àwọn abẹ́ojúewé).",
        "cant-move-to-user-page": "Ẹ kò ní ìyọ̀nda láti yípò àwọn ojúewé sí ojúewé oníṣe (àyàfi sí abẹ́ojúewé oníṣe).",
-       "newtitle": "Sí àkọlé tuntun:",
+       "newtitle": "Àkọlé tuntun:",
        "move-watch": "Mójútó ojúewé yìí",
        "movepagebtn": "Yípò ojúewé",
        "pagemovedsub": "Ìyípò ti já sí rere",
        "movenosubpage": "Ojúewé yìí kò ní àwọn abẹ́ojúewé.",
        "movereason": "Ìdíẹ̀:",
        "revertmove": "dápadà",
-       "delete_and_move_text": "== Ìparẹ́ pọndandan ==\nOjúewé àdésí \"[[:$1]]\" wà tẹ́lẹ̀tẹ́lẹ̀.\nṢé ẹ fẹ́ paárẹ́ láti sínà fún ìyípò?",
+       "delete_and_move_text": "Ojúewé àdésí \"[[:$1]]\" wà tẹ́lẹ̀.\nṢé ẹ fẹ́ paárẹ́ láti sínà fún ìyípò?",
        "delete_and_move_confirm": "Bẹ́ẹ̀ni, pa ojúewé náà rẹ́",
        "delete_and_move_reason": "Jẹ́ píparẹ́ láti baà fi ayè lẹ̀ fún ìyípòdà láti \"[[$1]]\"",
        "selfmove": "Àwọn àkọlé orísun àti ibiàyè jẹ́ ọ̀kannáà;\nkò le yípò ojúewé padà sí ara rẹ̀.",
        "move-leave-redirect": "Ẹ fún ní àtúnjúwe",
        "protectedpagemovewarning": "'''Àkíyèsí:''' Ojúewé yìí ti jẹ́ dídáàbòbò nítoríẹ̀ àwọn olùmójútó tí wọ́n ní ẹ̀tọ́ nìkan ni wọ́n le yínípòpadà.\nÀkọọ́lẹ̀ àìpẹ́ nìyí nísàlẹ̀ fún ìtọ́kasí:",
        "semiprotectedpagemovewarning": "'''Àkíyèsí:''' Ojúewé yìí ti jẹ́ dídáàbòbò nítoríẹ̀ àwọn oníṣe tí wọ́n ti forúkọsílẹ̀ nìkan ni wọ́n le yínípòpadà.\nÀkọọ́lẹ̀ àìpẹ́ nìyí nísàlẹ̀ fún ìtọ́kasí:",
-       "move-over-sharedrepo": "==Fáìlì wà ==\n[[:$1]] wà lórí ibi-àkójọ àjọpín kan. Ìyípò fáìlì kan padà sí àkọlé yìí yíò gun fáìlì àjọpin náà lórí.",
+       "move-over-sharedrepo": "[[:$1]] wà lórí ibi-àkójọ àjọpín kan. Ìyípò fáìlì kan padà sí àkọlé yìí yíò gun fáìlì àjọpin náà lórí.",
        "file-exists-sharedrepo": "Orúkọ fáìlì tí ẹ yàn pilẹ̀ tí únjẹ́ lílò lórí ibi-àkójọ àjọpín kan.\nẸ jọ̀wọ́ ẹ yan orúkọ míràn.",
        "export": "Ìkójáde àwọn ojúewé",
        "exporttext": "Ẹ le ṣàkójáde ìkọ̀rọ̀ àti ìtàn àtúnṣe ojúewé pàtó kan tàbí àpapọ̀ àwọn ojúewé tí a fi XML yí.\nÈyí ṣe é kówọlé sínú wiki míràn pẹ̀lú MediaWiki láti orí [[Special:Import|ìkówọlé ojúewé]].\n\nLáti ṣàkójáde àwọn ojúewé, ẹ tẹ àkọlé wọn sínú àpótí ọ̀rọ̀ ìsàlẹ̀, àkọlé kan lórí ìlà kan, kí ẹ sì sọ bóyá ẹ fẹ́ àtúnyẹ̀wò ìwòyí àti àwọn àtúnyẹ̀wò tó ti pẹ́, pẹ̀lú ìlà ìtàn ojúewé, tàbí àtúnyẹ̀wò ìwòyí pẹ̀lú ẹ̀kúnrẹ́rẹ́ ọ̀rọ̀ nípa àtúnṣe tó gbẹ̀yìn.\n\nẸ tún le lo àjápọ̀, fún àpẹrẹ  [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] fún ojúewé \"[[{{MediaWiki:Mainpage}}]]\".",
        "allmessages-prefix": "Ajọ̀ pẹ̀lú àlẹ̀mọ́wájú:",
        "allmessages-language": "Èdè:",
        "allmessages-filter-submit": "Lọ",
+       "allmessages-filter-translate": "Y'édèpadà",
        "thumbnail-more": "Ìmútóbi",
        "filemissing": "Fáìlì kò sí",
        "thumbnail_error": "Asìṣẹ ìdá àwòrán kékeré: $1",
        "patrol-log-page": "Àkọọ́lẹ̀ ìsọ́",
        "patrol-log-header": "Àkọọ́lẹ̀ àwọn àtúnyẹ̀wò sísọ́ nì yí.",
        "log-show-hide-patrol": "$1 àkọọ́lẹ̀ ìsọ́",
+       "confirm-markpatrolled-button": "OK",
        "deletedrevision": "Àtúnyẹ̀wò àtijọ́ píparẹ́ $1",
        "filedeleteerror-short": "Àsìṣe ìparẹ́ fáílì: $1",
        "filedeleteerror-long": "Àwọn àsìṣe ṣẹlẹ̀ nígbà ìṣeìparẹ́ fáìlì náà:\n\n$1",
        "minutes": "{{PLURAL:$1|ìṣẹ́jú $1}}",
        "hours": "{{PLURAL:$1|wákàtí $1}}",
        "days": "{{PLURAL:$1|ọjọ́ $1}}",
+       "weeks": "{{PLURAL:$1|ọ̀sẹ̀ $1|ọ̀sẹ̀ $1}}",
        "months": "{{PLURAL:$1|oṣù $1|oṣù $1}}",
        "years": "{{PLURAL:$1|ọdún $1|ọdún $1}}",
        "ago": "$1 sẹ́yìn",
        "just-now": "nísinsìnyí",
+       "hours-ago": "{{PLURAL:$1|wákàtí|wákàtí}} $1 ṣẹ́yìn",
+       "minutes-ago": "{{PLURAL:$1|ìṣẹ́jú|ìṣẹ́jú}} $1 ṣẹ́yìn",
+       "seconds-ago": "{{PLURAL:$1|ìṣẹ́júàáyá|ìṣẹ́júàáyá}} $1 ṣẹ́yìn",
        "monday-at": "Ọjọ́ajé ní ago $1",
        "tuesday-at": "Ọjọ́ìṣẹ́gun ní ago $1",
        "wednesday-at": "Ọjọ́rú ní ago $1",
        "confirm-watch-top": "Ṣe ìfikún ojúewé yìí mọ́ ìmójútó yín?",
        "confirm-unwatch-button": "OK",
        "confirm-unwatch-top": "Yọ ojúewé yìí kúrò nínú ìmójútó yín?",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← ojúewé tókọjá",
        "imgmultipagenext": "ojúewé tóúnbọ̀ →",
        "imgmultigo": "Lọ!",
        "special-characters-group-gujarati": "Gujarati",
        "special-characters-group-thai": "Thai",
        "special-characters-group-lao": "Lao",
-       "special-characters-group-khmer": "Khmer",
-       "edit-error-short": "Àṣìṣe: $1",
-       "edit-error-long": "Àwọn àsìṣe:\n\n\n$1"
+       "special-characters-group-khmer": "Khmer"
 }
index b3838a7..9a3a44f 100644 (file)
        "yourpassword": "Wachtwoôrd",
        "userlogin-yourpassword": "Wachtwoôrd",
        "yourpasswordagain": "Heef je wachtwoôrd opnieuw in:",
-       "remembermypassword": "Anmeldhehevens ontouwen (maximaal $1 {{PLURAL:$1|dag|daege}})",
        "yourdomainname": "Je domein:",
        "externaldberror": "Der is een fout opetreeën bie 't anmelden bie de database of je ei hin toestemmieng jen externe gebruker bie te werken.",
        "login": "Anmelden",
        "undo-success": "Ieronder sti de tekst wirin a de wiezigieng onedaene is emikt. Controleer voe 't opslaene of a 't resultaot ewenst is.",
        "undo-failure": "De wiezigieng kan nie onhedaen emikt worn vanwehe aore striedihe wiezigiengen.",
        "undo-summary": "Versie $1 van [[Special:Contributions/$2|$2]] ([[User talk:$2|overleg]]) onedaen emikt.",
-       "cantcreateaccounttitle": "Anmaeken gebruker mislukt.",
        "cantcreateaccount-text": "'t Anmaeken van gebrukers van dit IP-adres (<b>$1</b>) is eblokkeerd deur [[User:$3|$3]].\n\nDe deur $3 opeheven reeën is ''$2''",
        "viewpagelogs": "Bekiek de logboeken vò deêze bladzie",
        "nohistory": "Deêze pagina is nie bewerkt.",
index b6061ed..09b96e6 100644 (file)
        "views": "视图",
        "toolbox": "工具",
        "tool-link-userrights": "更改{{GENDER:$1|用户}}组",
+       "tool-link-userrights-readonly": "查看{{GENDER:$1|用户}}组",
        "tool-link-emailuser": "电邮联系该{{GENDER:$1|用户}}",
        "userpage": "查看用户页面",
        "projectpage": "查看项目页面",
        "passwordreset-emaildisabled": "此Wiki上无法使用邮件功能。",
        "passwordreset-username": "用户名:",
        "passwordreset-domain": "域:",
-       "passwordreset-capture": "查看生成的电子邮件吗?",
-       "passwordreset-capture-help": "如果您选中此框,电子邮件(包括临时密码)将显示,并发送给用户。",
        "passwordreset-email": "电子邮件地址:",
        "passwordreset-emailtitle": "在 {{SITENAME}} 的帐户详细信息",
        "passwordreset-emailtext-ip": "有人(可能是您,来自IP地址$1)请求重设{{SITENAME}}($4)上相关账户的密码。以下$3个账户与该电子邮件地址关联:\n\n$2\n\n这个临时密码将会在{{PLURAL:$5|一天|$5天}}后过期。请立即登录并设置新的密码。如果请求是其他人发出的,或者您已回忆起您的旧密码并不再需要更改,您可以忽略本条消息并继续使用原密码。",
        "passwordreset-emailelement": "用户名:\n$1\n\n临时密码:\n$2",
        "passwordreset-emailsentemail": "如果此邮件地址与您的账户相关联的话,将发送一封密码重置邮件。",
        "passwordreset-emailsentusername": "如果有邮件地址与此用户名相关联的话,将发送一封密码重置邮件。",
-       "passwordreset-emailsent-capture2": "密码重置{{PLURAL:$1|邮件}}已发送。{{PLURAL:$1|用户名和密码|用户名和密码列表}}在此显示。",
-       "passwordreset-emailerror-capture2": "向{{GENDER:$2|用户}}发送电子邮件失败:$1 {{PLURAL:$3|用户名和密码|用户名和密码列表}}在此显示。",
        "passwordreset-nocaller": "必须提供一个调用方",
        "passwordreset-nosuchcaller": "调用方不存在:$1",
        "passwordreset-ignored": "密码重置没有处理。也许没有配置提供者?",
-       "passwordreset-invalideamil": "无效的电子邮件地址",
+       "passwordreset-invalidemail": "无效的电子邮件地址",
        "passwordreset-nodata": "用户名和电子邮件地址均未提供",
        "changeemail": "更改或移除电子邮件地址",
        "changeemail-header": "完成此表格以更改您的电子邮件地址。如果您希望从您的账户中移除任何关联的电子邮件地址,请在提交表格时将新电子邮件地址留空。",
        "suppressionlogtext": "该列表列出了管理人员隐藏的删除与封禁。另参见[[Special:BlockList|封禁列表]]查询当前的封禁列表。",
        "mergehistory": "合并页面历史",
        "mergehistory-header": "此页面让您将来源页面的版本合并到新页面中去。请确保此次更改能继续保持历史页面的连续性。",
-       "mergehistory-box": "合并两个页面的版本历史:",
+       "mergehistory-box": "合并两个页面的修订版本:",
        "mergehistory-from": "来源页面:",
        "mergehistory-into": "目的页面:",
        "mergehistory-list": "可以合并的编辑历史",
        "search-external": "外部搜索",
        "searchdisabled": "{{SITENAME}}的搜索已被禁用。您可以暂时使用搜索引擎进行搜索,须注意其索引的{{SITENAME}}内容可能不是最新的。",
        "search-error": "搜索时发生错误:$1",
+       "search-warning": "搜索时发生警告:$1",
        "preferences": "设置",
        "mypreferences": "参数设置",
        "prefs-edits": "编辑数:",
        "prefs-help-recentchangescount": "这包括最近更改、页面历史和日志。",
        "prefs-help-watchlist-token2": "这是您的监视列表的网络feed密钥。\n任何拥有者均可以浏览您的监视列表,因此不要公开该密钥。\n如果有需要,[[Special:ResetTokens|您可以重置密钥]]。",
        "savedprefs": "您的系统设置已保存。",
-       "savedrights": "{{GENDER:$1|$1}}的用户权限已被保存。",
+       "savedrights": "{{GENDER:$1|$1}}的用户已被保存。",
        "timezonelegend": "时区:",
        "localtime": "当地时间:",
        "timezoneuseserverdefault": "使用wiki默认值($1)",
        "prefswarning-warning": "您对您的参数设置的更改尚未保存。如果您不点击“$1”就离开,您的设置就不会更新。",
        "prefs-tabs-navigation-hint": "提示:您可以通过左、右箭头键在选项卡之间切换。",
        "userrights": "用户权限管理",
-       "userrights-lookup-user": "管理用户组",
+       "userrights-lookup-user": "选择用户",
        "userrights-user-editname": "输入用户名:",
-       "editusergroup": "编辑{{GENDER:$1|用户}}组",
+       "editusergroup": "加载用户组",
        "editinguser": "更改{{GENDER:$1|用户}}<strong>[[User:$1|$1]]</strong>的用户权限$2",
+       "viewinguserrights": "查看{{GENDER:$1|用户}}<strong>[[User:$1|$1]]</strong>的用户权限$2",
        "userrights-editusergroup": "编辑用户组",
+       "userrights-viewusergroup": "查看用户组",
        "saveusergroups": "保存{{GENDER:$1|用户}}组",
        "userrights-groupsmember": "用户组:",
        "userrights-groupsmember-auto": "自动用户组:",
        "userrights-reason": "原因:",
        "userrights-no-interwiki": "您并没有权限去编辑在其它wiki上的用户权限。",
        "userrights-nodatabase": "数据库$1不存在或并非为本地的。",
-       "userrights-nologin": "您必须要以管理员帐户[[Special:UserLogin|登录]]之后才可以指定用户权限。",
-       "userrights-notallowed": "您没有权限添加或移除用户权限。",
        "userrights-changeable-col": "您可以更改的用户组",
        "userrights-unchangeable-col": "您不能更改的用户组",
        "userrights-conflict": "用户权限的更改存在冲突!请检查并确认您的更改。",
-       "userrights-removed-self": "您已删除您自己的权利。因此,您不再能够访问此页。",
        "group": "用户组:",
        "group-user": "用户",
        "group-autoconfirmed": "自动确认用户",
        "right-siteadmin": "锁定和解锁数据库",
        "right-override-export-depth": "导出页面,包括最多5层链接",
        "right-sendemail": "发送电子邮件给其他用户",
-       "right-passwordreset": "查看密码重置电子邮件",
        "right-managechangetags": "创建和(取消)激活[[Special:Tags|标签]]",
        "right-applychangetags": "连同某人的更改一起应用[[Special:Tags|标签]]",
        "right-changetags": "在个别修订和日志记录中添加和移除任意[[Special:Tags|标签]]",
        "action-upload_by_url": "从URL上传本文件",
        "action-writeapi": "使用写入API",
        "action-delete": "删除本页",
-       "action-deleterevision": "删除本版本",
-       "action-deletedhistory": "查看本页面被删除的历史",
+       "action-deleterevision": "删除修订",
+       "action-deletelogentry": "删除日志记录",
+       "action-deletedhistory": "查看页面被删除的历史",
+       "action-deletedtext": "查看已删除的修订版本文字",
        "action-browsearchive": "搜索已被删除的页面",
-       "action-undelete": "还原本页",
-       "action-suppressrevision": "复核并还原该隐藏版本",
+       "action-undelete": "还原页面",
+       "action-suppressrevision": "复核并还原隐藏修订版本",
        "action-suppressionlog": "查看本非公开日志",
        "action-block": "阻止该用户编辑",
        "action-protect": "更改本页面的保护级别",
        "action-userrights-interwiki": "编辑其他wiki用户的用户权限",
        "action-siteadmin": "锁定或解锁数据库",
        "action-sendemail": "发送电子邮件",
+       "action-editmyoptions": "编辑您的参数设置",
        "action-editmywatchlist": "编辑您的监视列表",
        "action-viewmywatchlist": "查看您的监视列表",
        "action-viewmyprivateinfo": "查看您的私人信息",
        "nrevisions": "$1个版本",
        "nimagelinks": "用于$1个页面中",
        "ntransclusions": "用于$1个页面中",
-       "specialpage-empty": "æ­¤æ\8a¥å\91\8aæ\97 结果。",
+       "specialpage-empty": "没æ\9c\89ç\94¨äº\8eæ­¤æ\8a¥å\91\8aç\9a\84结果。",
        "lonelypages": "孤立页面",
        "lonelypagestext": "以下页面没有被{{SITENAME}}的其它页面链接或包含。",
        "uncategorizedpages": "未归类页面",
        "mostimages": "最多链接文件",
        "mostinterwikis": "有最多跨wiki的页面",
        "mostrevisions": "有最多版本的页面",
-       "prefixindex": "所有前缀的页面",
-       "prefixindex-namespace": "所有前缀的页面($1名字空间)",
+       "prefixindex": "所有前缀的页面",
+       "prefixindex-namespace": "所有前缀的页面($1名字空间)",
        "prefixindex-submit": "显示",
        "prefixindex-strip": "在列表中除去前缀",
        "shortpages": "短页面",
        "apisandbox-continue": "继续",
        "apisandbox-continue-clear": "清除",
        "apisandbox-continue-help": "{{int:apisandbox-continue}}将[https://www.mediawiki.org/wiki/API:Query#Continuing_queries 继续]上次请求;{{int:apisandbox-continue-clear}}将清除继续相关的参数。",
+       "apisandbox-param-limit": "输入<kbd>max</kbd>以使用最大限制。",
+       "apisandbox-multivalue-all-namespaces": "$1(所有名字空间)",
+       "apisandbox-multivalue-all-values": "$1(所有值)",
        "booksources": "网络书源",
        "booksources-search-legend": "搜索图书来源",
        "booksources-isbn": "ISBN:",
        "allarticles": "所有页面",
        "allinnamespace": "所有页面($1名字空间)",
        "allpagessubmit": "提交",
-       "allpagesprefix": "显示有该前缀的页面:",
+       "allpagesprefix": "显示前缀的页面:",
        "allpagesbadtitle": "给定的页面标题是非法的,或者具有一个内部语言或内部 wiki 的前缀。它可能包含一个或更多的不能用于标题的字符。",
        "allpages-bad-ns": "在{{SITENAME}}中没有一个叫做\"$1\"的名字空间。",
        "allpages-hide-redirects": "隐藏重定向",
        "activeusers-count": "过去$3天有$1次操作",
        "activeusers-from": "显示用户开始于:",
        "activeusers-groups": "显示属于用户组的用户:",
+       "activeusers-excludegroups": "排除属于用户组的用户:",
        "activeusers-noresult": "找不到用户。",
        "activeusers-submit": "显示活跃用户",
        "listgrouprights": "用户组权限",
        "emailccsubject": "您发送给$1的消息的副本:$2",
        "emailsent": "电子邮件已发送",
        "emailsenttext": "您的电子邮件已经发出。",
-       "emailuserfooter": "本电子邮件是通过{{SITENAME}}的“{{int:emailuser}}”功能被$1{{GENDER:$1|发送}}至{{GENDER:$2|$2}}的。",
+       "emailuserfooter": "本电子邮件是通过{{SITENAME}}的“{{int:emailuser}}”功能被$1{{GENDER:$1|发送}}至{{GENDER:$2|$2}}的。{{GENDER:$2|您}}的电子邮件将直接发送至{{GENDER:$1|原始发送者}},并向{{GENDER:$1|其}}显示{{GENDER:$2|您}}的电子邮件地址。",
        "usermessage-summary": "留下系统消息。",
        "usermessage-editor": "系统信息编辑器",
        "watchlist": "监视列表",
        "confirmrecreate-noreason": "用户 [[User:$1|$1]]([[User talk:$1|talk]]) 在您开始编辑之后{{GENDER:$1|删除}}此页面。请确认您确实要重新创建此页面。",
        "recreate": "重新创建",
        "confirm_purge_button": "确定",
-       "confirm-purge-top": "要清除此页面的缓存吗?",
+       "confirm-purge-top": "要清除此页面的缓存吗",
        "confirm-purge-bottom": "清除页面数据会清除缓存并强制显示最近的版本。",
        "confirm-watch-button": "确定",
        "confirm-watch-top": "将此页添加到您的监视列表吗?",
        "confirm-rollback-button": "确定",
        "confirm-rollback-top": "回退此页面的编辑么?",
        "semicolon-separator": ";",
-       "comma-separator": "",
+       "comma-separator": "",
        "colon-separator": ":",
        "pipe-separator": "&#32;|&#32;",
        "word-separator": "",
        "tags-deactivate": "取消激活",
        "tags-hitcount": "$1个更改",
        "tags-manage-no-permission": "您没有权限管理更改标签。",
-       "tags-manage-blocked": "不能在被封禁的情况下管理更改标签。",
+       "tags-manage-blocked": "{{GENDER:$1|您}}不能在被封禁的情况下管理更改标签。",
        "tags-create-heading": "创建一个新标签",
        "tags-create-explanation": "默认情况下,新创建的标签将可供用户和机器人使用。",
        "tags-create-tag-name": "标签名称:",
        "tags-deactivate-not-allowed": "无法取消激活标签“$1”。",
        "tags-deactivate-submit": "取消激活",
        "tags-apply-no-permission": "您并无权限连带您的更改一起应用更改标签。",
-       "tags-apply-blocked": "不能在被封禁的情况下应用更改标签到您的更改中。",
+       "tags-apply-blocked": "{{GENDER:$1|您}}不能在被封禁的情况下应用更改标签到您的更改中。",
        "tags-apply-not-allowed-one": "标签“$1”不允许手动应用。",
        "tags-apply-not-allowed-multi": "以下{{PLURAL:$2|标签}}不允许手动应用:$1",
        "tags-update-no-permission": "您并无权限从个别修订或日志记录中添加或移除更改标签。",
-       "tags-update-blocked": "不能在被封禁的情况下添加或移除更改标签。",
+       "tags-update-blocked": "{{GENDER:$1|您}}不能在被封禁的情况下添加或移除更改标签。",
        "tags-update-add-not-allowed-one": "标签“$1”不被允许手动添加。",
        "tags-update-add-not-allowed-multi": "以下{{PLURAL:$2|标签}}不被允许手动添加:$1",
        "tags-update-remove-not-allowed-one": "标签“$1”不被允许移除。",
        "htmlform-user-not-exists": "<strong>$1</strong>不存在。",
        "htmlform-user-not-valid": "<strong>$1</strong>不是一个有效的用户名。",
        "logentry-delete-delete": "$1{{GENDER:$2|删除}}页面$3",
+       "logentry-delete-delete_redir": "$1通过覆盖{{GENDER:$2|删除}}了重定向$3",
        "logentry-delete-restore": "$1{{GENDER:$2|还原}}页面$3",
        "logentry-delete-event": "$1{{GENDER:$2|更改}}$3的{{PLURAL:$5|$5个日志事件}}的可见性:$4",
        "logentry-delete-revision": "$1{{GENDER:$2|更改}}页面$3的{{PLURAL:$5|$5个版本}}的可见性:$4",
        "mediastatistics-header-audio": "音频",
        "mediastatistics-header-video": "视频",
        "mediastatistics-header-multimedia": "富媒体",
-       "mediastatistics-header-office": "办公文件",
+       "mediastatistics-header-office": "文档",
        "mediastatistics-header-text": "文本",
        "mediastatistics-header-executable": "可执行文件",
        "mediastatistics-header-archive": "压缩格式",
        "special-characters-title-emdash": "长划线",
        "special-characters-title-minus": "减号",
        "mw-widgets-dateinput-no-date": "没有选定日期",
+       "mw-widgets-mediasearch-input-placeholder": "搜索媒体",
+       "mw-widgets-mediasearch-noresults": "找不到结果。",
        "mw-widgets-titleinput-description-new-page": "页面不存在",
        "mw-widgets-titleinput-description-redirect": "重定向至$1",
+       "mw-widgets-categoryselector-add-category-placeholder": "添加分类...",
        "sessionmanager-tie": "不能结合多个请求的身份验证类型:$1。",
        "sessionprovider-generic": "$1会话",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "基于cookie的会话",
        "log-action-filter-contentmodel-change": "内容类型的更改",
        "log-action-filter-contentmodel-new": "带有非标准内容模型的页面的更改",
        "log-action-filter-delete-delete": "页面删除",
+       "log-action-filter-delete-delete_redir": "重定向覆盖",
        "log-action-filter-delete-restore": "页面还原",
        "log-action-filter-delete-event": "日志删除",
        "log-action-filter-delete-revision": "修订版本删除",
        "restrictionsfield-badip": "无效的IP地址或段:$1",
        "restrictionsfield-label": "允许的IP段:",
        "restrictionsfield-help": "每行一个IP地址或CIDR段。要启用所有,可使用<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "错误:$1",
-       "edit-error-long": "错误:\n\n$1"
+       "pageid": "页面ID$1"
 }
index fc41120..f702115 100644 (file)
@@ -76,7 +76,8 @@
                        "Cosine02",
                        "一個正常人",
                        "Wehwei",
-                       "1233thehongkonger"
+                       "1233thehongkonger",
+                       "Maskers"
                ]
        },
        "tog-underline": "底線標示連結:",
        "currentevents-url": "Project:Current events",
        "disclaimers": "免責聲明",
        "disclaimerpage": "Project:一般免責聲明",
-       "edithelp": "編輯説明",
-       "helppage-top-gethelp": "説明",
+       "edithelp": "編輯說明",
+       "helppage-top-gethelp": "說明",
        "mainpage": "首頁",
        "mainpage-description": "首頁",
        "policy-url": "Project:Policy",
        "botpasswords-label-delete": "刪除",
        "botpasswords-label-resetpassword": "重設密碼",
        "botpasswords-label-grants": "適用的權限:",
-       "botpasswords-help-grants": "æ¯\8få\80\8bæ\8e\88æ¬\8aæ\9c\83給äº\88æ\93\81æ\9c\89該æ\8e\88æ¬\8aç\9a\84使ç\94¨è\80\85帳è\99\9få\88\97æ\96¼è©²æ\8e\88æ¬\8aæ¸\85å\96®ç\9a\84使ç\94¨è\80\85æ¬\8aé\99\90ã\80\82 請參考 [[Special:ListGrants|授權表]] 取得更多資訊。",
+       "botpasswords-help-grants": "æ\8e\88æ¬\8aå\8f¯ä»¥å\85\81許æ\82¨å­\98å\8f\96æ\82¨ç\9a\84使ç\94¨è\80\85帳è\99\9få·²ç¶\93æ\93\81æ\9c\89ç\9a\84æ¬\8aé\99\90ï¼\8cä½\86å\9c¨æ­¤é\96\8bå\95\9fæ\8e\88æ¬\8a並ä¸\8dæ\9c\83è®\93æ\82¨ç\9a\84使ç\94¨è\80\85帳è\99\9få\8f¯ä»¥å­\98å\8f\96é\82£äº\9bæ\82¨ä¸¦æ\9cªæ\93\81æ\9c\89ç\9a\84æ¬\8aé\99\90ã\80\82請參考 [[Special:ListGrants|授權表]] 取得更多資訊。",
        "botpasswords-label-grants-column": "已授權",
        "botpasswords-bad-appid": "機器人名稱 \"$1\" 無效。",
        "botpasswords-insert-failed": "新增機器人名稱 \"$1\" 失敗,是否已新增過?",
        "botpasswords-update-failed": "更新機器人名稱 \"$1\" 失敗,是否已刪除過?",
        "botpasswords-created-title": "已建立機器人密碼",
-       "botpasswords-created-body": "使用者''$2\"所擁有的機器人\"$1\"之密碼已建立。",
+       "botpasswords-created-body": "給使用者 \"$2\" 的機器人 \"$1\" 的機器人密碼已建立。",
        "botpasswords-updated-title": "已更新機器人密碼",
-       "botpasswords-updated-body": "使用者''$2\"所擁有的機器人\"$1\"之密碼已更新。",
+       "botpasswords-updated-body": "給使用者 \"$2\" 的機器人 \"$1\" 的機器人密碼已更新。",
        "botpasswords-deleted-title": "已刪除機器人密碼",
-       "botpasswords-deleted-body": "使用者''$2\"所擁有的機器人\"$1\"之密碼已刪除。",
+       "botpasswords-deleted-body": "給使用者 \"$2\" 的機器人 \"$1\" 的機器人密碼已刪除。",
        "botpasswords-newpassword": "用來登入 <strong>$1</strong> 的新密碼為 <strong>$2</strong>。 <em>請記錄此密碼以供未來參考使用。</em> <br> (較舊的機器人的登入名稱需與最終使用者名稱相同,您也可使用 <strong>$3</strong> 做為使用者名稱 <strong>$4</strong> 做為密碼。)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider 無法使用。",
        "botpasswords-restriction-failed": "機器人密碼限制已拒絕此次登入。",
        "passwordreset-emaildisabled": "此 Wiki 已停用電子郵件功能。",
        "passwordreset-username": "使用者名稱:",
        "passwordreset-domain": "網域名稱:",
-       "passwordreset-capture": "檢視電子郵件內容?",
-       "passwordreset-capture-help": "若您勾選此核選方塊,電子郵件 (包含臨時密碼) 將直接顯示,並寄給使用者。",
        "passwordreset-email": "電子郵件地址:",
        "passwordreset-emailtitle": "在 {{SITENAME}} 的帳號詳細資料",
        "passwordreset-emailtext-ip": "不明人士 (可能是您自己,來自 IP 位址 $1) 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件地址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略本訊息並且繼續使用您原本的密碼。",
        "passwordreset-emailelement": "使用者名稱:\n$1\n\n臨時密碼:\n$2",
        "passwordreset-emailsentemail": "若此確實為您帳號所登記的電子郵件地址,將會寄出重設密碼的信件給您。",
        "passwordreset-emailsentusername": "若此確實為您使用者名稱所登記的電子郵件地址,將會寄出重設密碼的信件給您。",
-       "passwordreset-emailsent-capture2": "密碼重設{{PLURAL:$1|郵件|郵件}}已寄出,{{PLURAL:$1|使用者名稱與密碼|使用者名稱與密碼清單}}如下顯示。",
-       "passwordreset-emailerror-capture2": "寄發電子郵件給{{GENDER:$2|使用者}}失敗:$1,{{PLURAL:$3|使用者名稱與密碼|使用者名稱與密碼清單}}如下顯示。",
        "passwordreset-nocaller": "必須提供 caller",
        "passwordreset-nosuchcaller": "Caller 不存在:$1",
        "passwordreset-ignored": "未處理密碼重設動作,可能尚未設定提供者?",
-       "passwordreset-invalideamil": "無效的電子郵件地址",
+       "passwordreset-invalidemail": "無效的電子郵件地址",
        "passwordreset-nodata": "未提供使用者名稱或是電子郵件地址",
        "changeemail": "變更或移除電子郵件地址",
        "changeemail-header": "請填寫此表單來變更您的電子郵件地址,若您想要移除您帳號所連結的所有電子郵件地址,請於新電子郵件地址欄位留空。",
        "accmailtitle": "密碼已寄出",
        "accmailtext": "[[User talk:$1|$1]] 的隨機密碼已經寄送至 $2,可登入後至 <em>[[Special:ChangePassword|變更密碼]] 頁面更改</em>。",
        "newarticle": "(新)",
-       "newarticletext": "您正連結至一頁不存在頁面。\n要建立該頁面,請在下方的編輯方塊中輸入內容 (詳情請參考 [$1 明頁面]) 。\n如果您是不小心來到此頁面,請點選瀏覽器的 <strong>返回</strong> 按鈕。",
+       "newarticletext": "您正連結至一頁不存在頁面。\n要建立該頁面,請在下方的編輯方塊中輸入內容 (詳情請參考 [$1 使用說明頁面]) 。\n如果您是不小心來到此頁面,請點選瀏覽器的 <strong>返回</strong> 按鈕。",
        "anontalkpagetext": "----\n<em>此討論頁面是給尚未建立帳號的匿名使用者使用</em>\n因此我們必須使用 IP 位址來辨識身份,但相同的 IP 位址可能由許多不同的使用者所共用。\n如果您是匿名使用者並且覺得評論的內容與您無關,請 [[Special:CreateAccount|建立新帳號]] 或 [[Special:UserLogin|登入]] 避免與其他匿名使用者混淆。",
        "noarticletext": "此頁面目前沒有內容,您可以在其它頁面中[[Special:Search/{{PAGENAME}}|搜尋此頁面標題]]、<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜尋相關日誌]或[{{fullurl:{{FULLPAGENAME}}|action=edit}} 建立此頁]</span>。",
        "noarticletext-nopermission": "此頁面目前沒有內容,\n您可以在其它頁面中 [[Special:Search/{{PAGENAME}}|搜尋此頁面標題]],或 <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜尋相關日誌]</span>,但您沒有權限建立此頁面。",
        "revdelete-unsuppress": "移除已還原修訂上的顯示限制",
        "revdelete-log": "原因:",
        "revdelete-submit": "套用至已選取的{{PLURAL:$1|一筆|多筆}}修訂",
-       "revdelete-success": "å·²æ\88\90å\8a\9fæ\9b´æ\96°æª¢ç¤ºä¿®è¨\82å\85§å®¹ç\9a\84æ¬\8aé\99\90設å®\9a。",
+       "revdelete-success": "å·²æ\9b´æ\96°ä¿®è¨\82ç\9a\84å\8f¯è¦\8bæ\80§。",
        "revdelete-failure": "無法更新修訂的顯示設定:\n$1",
-       "logdelete-success": "已成功更新檢視日誌的權限設定。",
+       "logdelete-success": "已設定日誌的可見性。",
        "logdelete-failure": "無法更新日誌的顯示設定:\n$1",
-       "revdel-restore": "變更能見度",
+       "revdel-restore": "變更可見性",
        "pagehist": "頁面歷史",
        "deletedhist": "已刪除歷史",
        "revdelete-hide-current": "隱藏於 $1 $2 的項目錯誤:此為目前的修訂,不可隱藏。",
        "search-external": "外部搜尋",
        "searchdisabled": "{{SITENAME}} 已停用搜尋功能。\n您可以改透過 Google 搜尋。\n請注意,在 Google 中搜尋到的 {{SITENAME}} 頁面內容可能不是最新的。",
        "search-error": "搜尋時發生錯誤:$1",
+       "search-warning": "搜尋時發生錯誤:$1",
        "preferences": "偏好設定",
        "mypreferences": "偏好設定",
        "prefs-edits": "編輯次數:",
        "saveprefs": "儲存",
        "restoreprefs": "還原所有預設設定 (所有項目)",
        "prefs-editing": "編輯",
-       "rows": "橫行數:",
-       "columns": "直行數:",
+       "rows": "數:",
+       "columns": "數:",
        "searchresultshead": "搜尋",
        "stub-threshold": "短頁面連結格式門檻值 ($1):",
        "stub-threshold-sample-link": "樣本",
        "prefswarning-warning": "您對您的偏好設定所做的變更尚未儲存。\n若您未點選 \"$1\" 離開此頁面,將不會更新您的偏好設定。",
        "prefs-tabs-navigation-hint": "提示:您可使用左、右方向鍵切換頁籤。",
        "userrights": "使用者權限管理",
-       "userrights-lookup-user": "管理使用者群組",
+       "userrights-lookup-user": "選擇用戶",
        "userrights-user-editname": "請輸入使用者名稱:",
-       "editusergroup": "編輯{{GENDER:$1|使用者}}群組",
+       "editusergroup": "加載用戶組",
        "editinguser": "變更{{GENDER:$1|使用者}} <strong>[[User:$1|$1]]</strong> 的使用者權限 $2",
        "userrights-editusergroup": "編輯使用者群組",
        "saveusergroups": "儲存{{GENDER:$1|使用者}}群組",
        "userrights-reason": "原因:",
        "userrights-no-interwiki": "您沒有權限去編輯其他 Wiki 上的使用者權限。",
        "userrights-nodatabase": "資料庫 $1 不存在或不在本地主機的。",
-       "userrights-nologin": "您必須 [[Special:UserLogin|登入]] 管理員帳號以指定使用者權限。",
-       "userrights-notallowed": "您沒有權限加入或刪除使用者權限。",
        "userrights-changeable-col": "您可變更的群組",
        "userrights-unchangeable-col": "您不可變更的群組",
        "userrights-conflict": "使用者權限變更發生衝突!請檢閱並確認你的變更。",
-       "userrights-removed-self": "您已移除自己的權限,故您已無法再次存取此頁面。",
        "group": "群組:",
        "group-user": "使用者",
        "group-autoconfirmed": "自動確認的使用者",
        "right-siteadmin": "鎖定和解除鎖定資料庫",
        "right-override-export-depth": "匯出頁面包含連結內容,深度上限為 5 層",
        "right-sendemail": "傳送電子郵件聯絡其他使用者",
-       "right-passwordreset": "檢視重設密碼電子郵件",
        "right-managechangetags": "建立並自資料庫 (取消) 啟用 [[Special:Tags|標籤]]",
        "right-applychangetags": "連同某個人的變更一起套用[[Special:Tags|標籤]]",
        "right-changetags": "加入與移除任何於各別修訂與日誌項目的[[Special:Tags|標籤]]",
        "action-applychangetags": "連同您的變更一起套用標籤",
        "action-changetags": "加入與移除任何於各別修訂與日誌項目的標籤",
        "action-deletechangetags": "從資料庫刪除標籤",
-       "action-purge": "刷新此頁面",
+       "action-purge": "清除此頁面",
        "nchanges": "$1 次變更",
        "enhancedrc-since-last-visit": "{{PLURAL:$1|自上次拜訪}}已有 $1",
        "enhancedrc-history": "歷史",
        "mostimages": "被連結最多的檔案",
        "mostinterwikis": "最多跨 Wiki 連結的頁面",
        "mostrevisions": "最多修訂的頁面",
-       "prefixindex": "æ\89\80æ\9c\89é \81é\9d¢è\88\87å­\97é¦\96",
-       "prefixindex-namespace": "æ\89\80æ\9c\89å\90«å­\97é¦\96ç\9a\84頁面 ($1 命名空間)",
+       "prefixindex": "æ\8c\89è©\9eé ­æ\9f¥è©¢é \81é\9d¢",
+       "prefixindex-namespace": "æ\8c\89è©\9eé ­æ\9f¥è©¢頁面 ($1 命名空間)",
        "prefixindex-submit": "顯示",
-       "prefixindex-strip": "於清單中省略首",
+       "prefixindex-strip": "於清單中省略首",
        "shortpages": "過短的頁面",
        "longpages": "過長的頁面",
        "deadendpages": "無連結頁面",
        "apisandbox-continue": "繼續",
        "apisandbox-continue-clear": "清除",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} 會 [https://www.mediawiki.org/wiki/API:Query#Continuing_queries 繼續] 最後的請求,{{int:apisandbox-continue-clear}} 則會清除繼續相關的參數。",
+       "apisandbox-param-limit": "輸入 <kbd>max</kbd> 以使用最大限制。",
        "booksources": "圖書資源",
        "booksources-search-legend": "尋找圖書資源",
        "booksources-isbn": "國際標準書號:",
        "booksources-search": "搜尋",
        "booksources-text": "下列清單包含其他銷售新書籍或二手書籍的網站連結,可會有你想尋找書籍的進一部資訊:",
        "booksources-invalid-isbn": "您提供的 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 魔法連結的頁面",
+       "magiclink-tracking-pmid-desc": "此頁面使用 PMID 魔法連結的頁面,請參考 [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] 的如何遷移。",
+       "magiclink-tracking-isbn": "使用 ISBN 魔法連結的頁面",
+       "magiclink-tracking-isbn-desc": "此頁面使用 ISBN 魔法連結的頁面,請參考 [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] 的如何遷移。",
        "specialloguserlabel": "執行者:",
        "speciallogtitlelabel": "目標 (標題或以 {{ns:user}}:使用者 表示使用者):",
        "log": "日誌",
        "allarticles": "所有頁面",
        "allinnamespace": "所有頁面 ($1 命名空間)",
        "allpagessubmit": "執行",
-       "allpagesprefix": "顯示以此為字首頁面:",
+       "allpagesprefix": "根據詞首查詢頁面",
        "allpagesbadtitle": "指定的頁面標題無效、包含內部語言或內部 Wiki 的字首。\n它可能包含一個或多個的不能用於標題的字元。",
        "allpages-bad-ns": "{{SITENAME}} 沒有 \"$1\" 命名空間。",
        "allpages-hide-redirects": "隱藏重新導向頁面",
        "activeusers-count": "最近 $3 天內有 $1 次動作",
        "activeusers-from": "顯示使用者開始自:",
        "activeusers-groups": "顯示屬於以下群組的使用者:",
+       "activeusers-excludegroups": "排除屬於以下群組的使用者:",
        "activeusers-noresult": "查無使用者。",
        "activeusers-submit": "顯示活動中的使用者",
        "listgrouprights": "使用者群組權限",
        "modifiedarticleprotection": "已變更 \"[[$1]]\" 的保護層級",
        "unprotectedarticle": "已解除 \"[[$1]]\" 的保護",
        "movedarticleprotection": "已移動 \"[[$2]]\" 的保護設定至 \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|受保護}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|已更改}} \"[[$1]]\" 的保護層級",
+       "unprotectedarticle-comment": "{{GENDER:$2|已移除}} \"[[$1]]\" 的保護",
        "protect-title": "變更 \"$1\" 的保護層級",
        "protect-title-notallowed": "檢視 \"$1\" 的保護層級",
        "prot_1movedto2": "已移動 [[$1]] 至 [[$2]]",
        "import-mapping-namespace": "匯入至命名空間:",
        "import-mapping-subpage": "匯入做為以下頁面的子頁面:",
        "import-upload-filename": "檔案名稱:",
-       "import-comment": "註解:",
+       "import-comment": "è©\95è«\96:",
        "importtext": "請使用 [[Special:Export|匯出工具]] 從來源 Wiki 匯出檔案,\n儲存至您的電腦後再上傳到這裡。",
        "importstart": "正在匯入頁面...",
        "import-revision-count": "$1 個修訂",
        "log-show-hide-patrol": "$1 巡查日誌",
        "log-show-hide-tag": "$1 標籤日誌",
        "confirm-markpatrolled-button": "確定",
+       "confirm-markpatrolled-top": "標記 $2 的修訂 $3 為已巡查?",
        "deletedrevision": "已刪除舊修訂 $1",
        "filedeleteerror-short": "刪除檔案發生錯誤:$1",
        "filedeleteerror-long": "刪除檔案時發生錯誤:\n\n$1",
        "exif-colorspace": "色彩空間",
        "exif-componentsconfiguration": "每像素內含",
        "exif-compressedbitsperpixel": "影像壓縮模式",
-       "exif-pixelxdimension": "å\9c\96ç\89\87寬度",
-       "exif-pixelydimension": "å\9c\96ç\89\87高度",
+       "exif-pixelxdimension": "å½±å\83\8f寬度",
+       "exif-pixelydimension": "å½±å\83\8f高度",
        "exif-usercomment": "使用者評論",
        "exif-relatedsoundfile": "相關的音效檔案",
        "exif-datetimeoriginal": "資料產生的日期時間",
        "exif-source": "來源",
        "exif-editstatus": "圖片社評狀態",
        "exif-urgency": "緊急性",
-       "exif-fixtureidentifier": "夾具名稱",
+       "exif-fixtureidentifier": "Fixture 名稱",
        "exif-locationdest": "描繪地點",
        "exif-locationdestcode": "位置代碼描述",
        "exif-objectcycle": "媒體發生時間",
        "confirm-rollback-button": "確定",
        "confirm-rollback-top": "還原編輯到此頁面?",
        "semicolon-separator": ";",
-       "comma-separator": "",
+       "comma-separator": "",
        "colon-separator": ":",
        "word-separator": "",
        "parentheses": " ($1)",
        "tags-deactivate": "停用",
        "tags-hitcount": "$1 次變更",
        "tags-manage-no-permission": "您沒有權限管理變更標籤。",
-       "tags-manage-blocked": "您無法在被封鎖的情況下管理變更標籤。",
+       "tags-manage-blocked": "您無法在{{GENDER:$1|您}}被封鎖的情況下管理變更標籤。",
        "tags-create-heading": "建立新標籤",
        "tags-create-explanation": "在預設情況下,新建立的標籤可被使用者及機器人使用。",
        "tags-create-tag-name": "標籤名稱:",
        "tags-deactivate-not-allowed": "無法停用標籤 \"$1\"。",
        "tags-deactivate-submit": "停用",
        "tags-apply-no-permission": "您沒有權限連同您的變更一起套用標籤。",
-       "tags-apply-blocked": "您無法在被封鎖的情況下套用變更標籤為您的變更。",
+       "tags-apply-blocked": "您無法在{{GENDER:$1|您}}被封鎖的情況下套用變更標籤為您的變更。",
        "tags-apply-not-allowed-one": "不允許手動套用標籤 \"$1\"。",
        "tags-apply-not-allowed-multi": "不允許手動套用以下{{PLURAL:$2|標籤|標籤}}:$1",
        "tags-update-no-permission": "您沒有權限加入與移除任何於各別修訂與日誌項目的標籤",
-       "tags-update-blocked": "您無法在被封鎖的情況下移除變更標籤。",
+       "tags-update-blocked": "您無法在{{GENDER:$1|您}}被封鎖的情況下移除變更標籤。",
        "tags-update-add-not-allowed-one": "不允許手動加入標籤 \"$1\"。",
        "tags-update-add-not-allowed-multi": "不允許手動加入以下{{PLURAL:$2|標籤|標籤}}:$1",
        "tags-update-remove-not-allowed-one": "不允許手動移除標籤 \"$1\"。",
        "authmanager-authn-autocreate-failed": "自動建立本地帳號失敗:$1",
        "authmanager-change-not-supported": "提供的憑證無法變更,因為尚無法使用。",
        "authmanager-create-disabled": "已關閉帳號自動建立。",
-       "authmanager-create-from-login": "要建立您的帳號,請先填寫以下欄位。",
+       "authmanager-create-from-login": "要建立您的帳號,請先填寫欄位。",
        "authmanager-create-not-in-progress": "帳號建立尚未進行或連線階段資料已遺失,請重頭再開始。",
        "authmanager-create-no-primary": "提供的憑證無使用在帳號建立。",
        "authmanager-link-no-primary": "提供的憑證無使用在帳號連結。",
        "usercssispublic": "請注意:CSS 子頁面可被其他使用者檢視,不應包含憑証資料。",
        "restrictionsfield-badip": "無效的 IP 位址或範圍:$1",
        "restrictionsfield-label": "允許的 IP 範圍:",
-       "restrictionsfield-help": "一個 IP 位址或 CIDR 範圍一行,要開啟所有範圍可使用 <br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "edit-error-short": "錯誤:$1",
-       "edit-error-long": "錯誤:\n\n$1"
+       "restrictionsfield-help": "一個 IP 位址或 CIDR 範圍一行,要開啟所有範圍可使用 <br><code>0.0.0.0/0</code><br><code>::/0</code>"
 }
index 5bc3590..7dde2b7 100644 (file)
@@ -49,3 +49,263 @@ $digitTransformTable = [
 
 $digitGroupingPattern = "##,##,###";
 
+$specialPageAliases = [
+       'Activeusers'               => [ 'সক্রিয়_ব্যবহারকারী' ],
+       'Allmessages'               => [ 'সব_বার্তা' ],
+       'AllMyUploads'              => [ 'আমার_সব_আপলোড', 'আমার_সব_ফাইল' ],
+       'Allpages'                  => [ 'সব_পাতা', 'সব_পৃষ্ঠা', 'সব_পাতাসমূহ' ],
+       'ApiHelp'                   => [ 'এপিআই_সাহায্য' ],
+       'ApiSandbox'                => [ 'এপিআই_খেলাঘর' ],
+       'Ancientpages'              => [ 'পুরানো_পাতা', 'পুরানো_পৃষ্ঠা' ],
+       'Badtitle'                  => [ 'ত্রুটিযুক্ত_শিরোনাম' ],
+       'Blankpage'                 => [ 'খালি_পাতা', 'খালি_পৃষ্ঠা' ],
+       'Block'                     => [ 'বাধাদান', 'আইপি_বাধাদান', 'ব্যবহারকারী_বাধাদান' ],
+       'Booksources'               => [ 'বইয়ের_উৎস' ],
+       'BotPasswords'              => [ 'বট_পাসওয়ার্ড' ],
+       'BrokenRedirects'           => [ 'ভাঙ্গা_পুনর্নির্দেশ' ],
+       'Categories'                => [ 'বিষয়শ্রেণী' ],
+       'ChangeContentModel'        => [ 'বিষয়বস্তুর_মডেল_পরিবর্তন' ],
+       'ChangeCredentials'         => [ 'পরিচয়পত্র_পরিবর্তন' ],
+       'ChangeEmail'               => [ 'ইমেইল_পরিবর্তন' ],
+       'ChangePassword'            => [ 'পাসওয়ার্ড_পরিবর্তন', 'পাসপরিবর্তন', 'পাসওয়ার্ডপরিবর্তন' ],
+       'ComparePages'              => [ 'পাতার_তুলনা', 'পৃষ্ঠার_তুলনা' ],
+       'Confirmemail'              => [ 'ইমেইল_নিশ্চিতকরণ' ],
+       'Contributions'             => [ 'অবদান', 'অবদানসমূহ' ],
+       'CreateAccount'             => [ 'অ্যাকাউন্ট_তৈরি' ],
+       'Deadendpages'              => [ 'সংযোগহীন_পাতা', 'সংযোগহীন_পৃষ্ঠা' ],
+       'DeletedContributions'      => [ 'অপসারিত_অবদান' ],
+       'Diff'                      => [ 'পার্থক্য' ],
+       'DoubleRedirects'           => [ 'দ্বৈত_পুনর্নির্দেশ', 'দুইবার_করা_পুনর্নির্দেশ' ],
+       'EditTags'                  => [ 'ট্যাগ_সম্পাদনা' ],
+       'EditWatchlist'             => [ 'নজরতালিকা_সম্পাদনা' ],
+       'Emailuser'                 => [ 'ইমেইল_প্রেরণ', 'ইমেইল' ],
+       'ExpandTemplates'           => [ 'টেমপ্লেট_সম্প্রসারণ' ],
+       'Export'                    => [ 'রপ্তানি' ],
+       'Fewestrevisions'           => [ 'কমসংখ্যক_সংশোধন' ],
+       'FileDuplicateSearch'       => [ 'সদৃশ_ফাইল_অনুসন্ধান' ],
+       'Filepath'                  => [ 'ফাইলের_পথ' ],
+       'Import'                    => [ 'আমদানি' ],
+       'Invalidateemail'           => [ 'অবৈধ_ইমেইল' ],
+       'JavaScriptTest'            => [ 'জাভাস্ক্রিপ্ট_পরীক্ষা' ],
+       'BlockList'                 => [ 'বাধার_তালিকা', 'বাধার_তালিকাসমূহ', 'আইপি_বাধার_তালিকা' ],
+       'LinkSearch'                => [ 'সংযোগ_অনুসন্ধান' ],
+       'LinkAccounts'              => [ 'অ্যাকাউন্টের_তালিকা' ],
+       'Listadmins'                => [ 'প্রশাসকের_তালিকা' ],
+       'Listbots'                  => [ 'বটের_তালিকা' ],
+       'Listfiles'                 => [ 'ফাইলের_তালিকা', 'চিত্রের_তালিকা', 'ছবির_তালিকা' ],
+       'Listgrouprights'           => [ 'দলগত_অধিকারের_তালিকা', 'ব্যবহারকারীর_দলগত_অধিকার' ],
+       'Listgrants'                => [ 'অনুদানের_তালিকা', 'গ্র্যান্টের_তালিকা' ],
+       'Listredirects'             => [ 'পুনর্নির্দেশের_তালিকা', 'পুনঃনির্দেশের_তালিকা' ],
+       'ListDuplicatedFiles'       => [ 'সদৃশ_ফাইলের_তালিকা', 'অনুরূপ_ফাইলের_তালিকা' ],
+       'Listusers'                 => [ 'ব্যবহারকারীর_তালিকা', 'ব্যবহারকারী_তালিকা' ],
+       'Lockdb'                    => [ 'ডাটাবেস_অবরোধ', 'লকডিবি' ],
+       'Log'                       => [ 'লগ', 'লগসমূহ' ],
+       'Lonelypages'               => [ 'পিতৃহীন_পাতা', 'পিতৃহীন_পাতাসমূহ' ],
+       'Longpages'                 => [ 'দীর্ঘ_পাতাসমূহ' ],
+       'MediaStatistics'           => [ 'মিডিয়া_পরিসংখ্যান' ],
+       'MergeHistory'              => [ 'ইতিহাস_একত্রীকরণ' ],
+       'MIMEsearch'                => [ 'এমআইএমই_অনুসন্ধান' ],
+       'Mostcategories'            => [ 'সর্বাধিক_বিষয়শ্রেণীসমৃদ্ধ' ],
+       'Mostimages'                => [ 'সর্বাধিক_ফাইল', 'বেশী_ছবি' ],
+       'Mostinterwikis'            => [ 'সর্বাধিক_আন্তঃউইকি' ],
+       'Mostlinked'                => [ 'সর্বাধিক_সংযুক্ত_পাতা' ],
+       'Mostlinkedcategories'      => [ 'সর্বাধিক_সংযুক্ত_বিষয়শ্রেণী', 'সর্বাধিক_ব্যবহৃত_বিষয়শ্রেণী', 'সর্বাধিক_সংযুক্ত_বিষয়শ্রেণীসমূহ' ],
+       'Mostlinkedtemplates'       => [ 'সর্বাধিক_সংযুক্ত_টেমপ্লট', 'সর্বাধিক_সংযুক্ত_টেমপ্লটসমূহ', 'সর্বাধিক_ব্যবহৃত_টেমপ্লেট' ],
+       'Mostrevisions'             => [ 'সর্বাধিক_সংশোধন' ],
+       'Movepage'                  => [ 'পাতা_স্থানান্তর' ],
+       'Mycontributions'           => [ 'আমার_অবদান' ],
+       'MyLanguage'                => [ 'আমার_ভাষা' ],
+       'Mypage'                    => [ 'আমার_পাতা' ],
+       'Mytalk'                    => [ 'আমার_আলাপ' ],
+       'Myuploads'                 => [ 'আমার_আপলোড', 'আমার_ফাইল' ],
+       'Newimages'                 => [ 'নতুন_চিত্রসমূহ', 'নতুন_ছবিসমূহ' ],
+       'Newpages'                  => [ 'নতুন_পাতাসমূহ' ],
+       'PagesWithProp'             => [ 'বৈশিষ্ট্যযুক্ত_পাতা', 'বৈশিষ্ট্যযুক্ত_পৃষ্ঠা' ],
+       'PageLanguage'              => [ 'পাতার_ভাষা' ],
+       'PasswordReset'             => [ 'পাসওয়ার্ড_পুনঃস্থাপন' ],
+       'PermanentLink'             => [ 'স্থায়ী_সংযোগ', 'স্থায়ী_লিঙ্ক' ],
+       'Preferences'               => [ 'পছন্দসমূহ', 'আমার_পছন্দ' ],
+       'Prefixindex'               => [ 'উপসর্গ' ],
+       'Protectedpages'            => [ 'সুরক্ষিত_পাতা' ],
+       'Protectedtitles'           => [ 'সুরক্ষিত_শিরোনাম' ],
+       'Randompage'                => [ 'অজানা_পাতা', 'অজানা_যেকোন_পাতা' ],
+       'RandomInCategory'          => [ 'অজানা_বিষয়শ্রেণী' ],
+       'Randomredirect'            => [ 'অজানা_পুনর্নির্দেশ' ],
+       'Randomrootpage'            => [ 'অজানা_মূল_পাতা' ],
+       'Recentchanges'             => [ 'সাম্প্রতিক_পরিবর্তনসমূহ', 'সাম্প্রতিক_পরিবর্তন' ],
+       'Recentchangeslinked'       => [ 'সংযুক্ত_সাম্প্রতিক_পরিবর্তন', 'সংযুক্ত_সাম্প্রতিক_পরিবর্তনসমূহ', 'সম্পর্কিত_পরিবর্তন' ],
+       'Redirect'                  => [ 'পুনর্নির্দেশ' ],
+       'RemoveCredentials'         => [ 'পরিচয়পত্র_অপসারণ' ],
+       'ResetTokens'               => [ 'টোকেন_পরিবর্তন' ],
+       'Revisiondelete'            => [ 'অপসারিত_ইতিহাস' ],
+       'RunJobs'                   => [ 'রানজব' ],
+       'Search'                    => [ 'অনুসন্ধান' ],
+       'Shortpages'                => [ 'সংক্ষিপ্ত_পাতাসমূহ' ],
+       'Specialpages'              => [ 'বিশেষ_পাতাসমূহ' ],
+       'Statistics'                => [ 'পরিসংখ্যান' ],
+       'Tags'                      => [ 'ট্যাগ' ],
+       'TrackingCategories'        => [ 'বিষয়শ্রেণীসমূহ_অনুসরণ' ],
+       'Unblock'                   => [ 'বাধা_তোলা', 'বাধা_অপসারণ' ],
+       'Uncategorizedcategories'   => [ 'বিষয়শ্রেণীবিহীন_বিষয়শ্রেণী' ],
+       'Uncategorizedimages'       => [ 'বিষয়শ্রেণীবিহীন_চিত্র', 'বিষয়শ্রেণীবিহীন_ছবি' ],
+       'Uncategorizedpages'        => [ 'বিষয়শ্রেণীবিহীন_পাতা' ],
+       'Uncategorizedtemplates'    => [ 'বিষয়শ্রেণীবিহীন_টেমপ্লেট' ],
+       'Undelete'                  => [ 'পুনরুদ্ধার' ],
+       'UnlinkAccounts'            => [ 'অসংযুক্ত_অ্যাকাউন্ট' ],
+       'Unlockdb'                  => [ 'ডাটাবেস_মুক্তি', 'আনলকডিবি' ],
+       'Unusedcategories'          => [ 'অব্যবহৃত_বিষয়শ্রেণী' ],
+       'Unusedimages'              => [ 'অব্যবহৃত_চিত্র', 'অব্যবহৃত_ছবি' ],
+       'Unusedtemplates'           => [ 'অব্যবহৃত_টেমপ্লেট' ],
+       'Unwatchedpages'            => [ 'নজরহীন_পাতা', 'নজরে_না_রাখা_পাতা' ],
+       'Upload'                    => [ 'আপলোড' ],
+       'UploadStash'               => [ 'স্টাশ_আপলোড' ],
+       'Userlogin'                 => [ 'ব্যবহারকারী_প্রবেশ', 'প্রবেশ' ],
+       'Userlogout'                => [ 'ব্যবহারকারী_প্রস্থান', 'প্রস্থান' ],
+       'Userrights'                => [ 'ব্যবহারকারী_অধিকার', 'ব্যবহারকারীর_অধিকার' ],
+       'Version'                   => [ 'সংস্করণ' ],
+       'Wantedcategories'          => [ 'আবশ্যিক_বিষয়শ্রেণীসমূহ' ],
+       'Wantedfiles'               => [ 'আবশ্যিক_ফাইলসমূহ' ],
+       'Wantedpages'               => [ 'আবশ্যিক_পাতাসমূহ', 'ভাঙ্গা_লিংকসমূহ' ],
+       'Wantedtemplates'           => [ 'আবশ্যিক_টেমপ্লেটসমূহ' ],
+       'Watchlist'                 => [ 'নজরতালিকা' ],
+       'Whatlinkshere'             => [ 'সংযোগকারী_পৃষ্ঠাসমূহ' ],
+       'Withoutinterwiki'          => [ 'আন্তঃউইকিহীন' ],
+];
+
+$magicWords = [
+       'redirect'                => [ 0, '#পুনর্নির্দেশ', '#পুনঃর্নির্দেশ', '#পুনঃনির্দেশ', '#পুননির্দেশ', '#REDIRECT' ],
+       'notoc'                   => [ 0, '__কোন_বিষয়বস্তুর_ছক_নয়__', '__কোনবিষয়বস্তুরছকনয়__', '__কোন_বিষয়বস্তুর_টেবিল_নয়__', '__কোনবিষয়বস্তুরটেবিলনয়__', '__NOTOC__' ],
+       'nogallery'               => [ 0, '__কোনগ্যালারিনয়__', '__কোনগ্যালারীনয়__', '__কোন_গ্যালারি_নয়__', '__কোন_গ্যালারী_নয়__', '__NOGALLERY__' ],
+       'toc'                     => [ 0, '__বিষয়বস্তুর_ছক__', '__বিষয়বস্তুরছক__', '__বিষয়বস্তুর_টেবিল__', '__বিষয়বস্তুরটেবিল__', '__TOC__' ],
+       'noeditsection'           => [ 0, '__কোনসম্পাদনাঅনুচ্ছেদনয়__', '__কোন_সম্পাদনা_অনুচ্ছেদ_নয়__', '__NOEDITSECTION__' ],
+       'currentmonth'            => [ 1, 'চলতি_মাস', 'চলতিমাস', 'বর্তমান_মাস', 'বর্তমানমাস', 'বর্তমান_মাস_২', 'বর্তমানমাস২', 'CURRENTMONTH', 'CURRENTMONTH2' ],
+       'currentmonth1'           => [ 1, 'চলতি_মাস_১', 'চলতিমাস১', 'বর্তমান_মাস_১', 'বর্তমানমাস১', 'CURRENTMONTH1' ],
+       'currentmonthname'        => [ 1, 'বর্তমান_মাসের_নাম', 'বর্তমানমাসেরনাম', 'CURRENTMONTHNAME' ],
+       'currentmonthnamegen'     => [ 1, 'বর্তমান_মাসের_নাম_উৎপন্ন', 'বর্তমানমাসেরনামউৎপন্ন', 'CURRENTMONTHNAMEGEN' ],
+       'currentmonthabbrev'      => [ 1, 'বর্তমান_মাস_সংক্ষেপ', 'বর্তমানমাসসংক্ষেপ', 'বর্তমান_মাস_সংক্ষিপ্ত', 'বর্তমানমাসসংক্ষিপ্ত', 'CURRENTMONTHABBREV' ],
+       'currentday'              => [ 1, 'বর্তমান_দিন', 'বর্তমানদিন', 'আজকের_দিন', 'আজকেরদিন', 'CURRENTDAY' ],
+       'currentday2'             => [ 1, 'বর্তমান_দিন_২', 'বর্তমানদিন২', 'আজকের_দিন_২', 'আজকেরদিন২', 'CURRENTDAY2' ],
+       'currentdayname'          => [ 1, 'বর্তমান_দিনের_নাম', 'বর্তমানদিনেরনাম', 'আজকের_দিনের_নাম', 'আজকেরদিনেরনাম', 'CURRENTDAYNAME' ],
+       'currentyear'             => [ 1, 'চলতি_বছর', 'চলতিবছর', 'বর্তমান_বছর', 'বর্তমানবছর', 'CURRENTYEAR' ],
+       'currenttime'             => [ 1, 'বর্তমান_সময়', 'বর্তমানসময়', 'এখনকার_সময়', 'এখনকারসময়', 'এখন_সময়', 'CURRENTTIME' ],
+       'currenthour'             => [ 1, 'বর্তমান_ঘণ্টা', 'বর্তমানঘণ্টা', 'বর্তমান_ঘন্টা', 'বর্তমানঘন্টা', 'এখনকার_ঘণ্টা', 'এখনকারঘণ্টা', 'CURRENTHOUR' ],
+       'localmonth'              => [ 1, 'স্থানীয়_মাস', 'স্থানীয়মাস', 'স্থানীয়_মাস_২', 'স্থানীয়মাস২', 'LOCALMONTH', 'LOCALMONTH2' ],
+       'localmonth1'             => [ 1, 'স্থানীয়_মাস_১', 'স্থানীয়মাস১', 'LOCALMONTH1' ],
+       'localmonthname'          => [ 1, 'স্থানীয়_মাসের_নাম', 'স্থানীয়মাসেরনাম', 'LOCALMONTHNAME' ],
+       'localmonthnamegen'       => [ 1, 'স্থানীয়_মাসের_নাম_উৎপন্ন', 'স্থানীয়মাসেরনামউৎপন্ন', 'LOCALMONTHNAMEGEN' ],
+       'localmonthabbrev'        => [ 1, 'স্থানীয়_মাস_সংক্ষেপ', 'স্থানীয়মাসসংক্ষেপ', 'স্থানীয়_মাস_সংক্ষিপ্ত', 'স্থানীয়মাসসংক্ষিপ্ত', 'সংক্ষেপিত_স্থানীয়_মাস', 'সংক্ষেপিতস্থানীয়মাস', 'LOCALMONTHABBREV' ],
+       'localday'                => [ 1, 'স্থানীয়_দিন', 'স্থানীয়দিন', 'স্থানীয়_বার', 'স্থানীয়বার', 'LOCALDAY' ],
+       'localday2'               => [ 1, 'স্থানীয়_দিন_২', 'স্থানীয়দিন২', 'LOCALDAY2' ],
+       'localdayname'            => [ 1, 'স্থানীয়_দিনের_নাম', 'স্থানীয়দিনেরনাম', 'LOCALDAYNAME' ],
+       'localyear'               => [ 1, 'স্থানীয়_বছর', 'স্থানীয়বছর', 'LOCALYEAR' ],
+       'localtime'               => [ 1, 'স্থানীয়_সময়', 'স্থানীয়সময়', 'LOCALTIME' ],
+       'localhour'               => [ 1, 'স্থানীয়_ঘণ্টা', 'স্থানীয়ঘণ্টা', 'স্থানীয়_ঘন্টা', 'স্থানীয়ঘন্টা', 'LOCALHOUR' ],
+       'numberofpages'           => [ 1, 'পাতার_সংখ্যা', 'পাতারসংখ্যা', 'পৃষ্ঠার_সংখ্যা', 'পৃষ্ঠারসংখ্যা', 'পৃষ্ঠা_সংখ্যা', 'পৃষ্ঠাসংখ্যা', 'NUMBEROFPAGES' ],
+       'numberofarticles'        => [ 1, 'নিবন্ধের_সংখ্যা', 'নিবন্ধেরসংখ্যা', 'নিবন্ধ_সংখ্যা', 'নিবন্ধসংখ্যা', 'NUMBEROFARTICLES' ],
+       'numberoffiles'           => [ 1, 'ফাইলের_সংখ্যা', 'ফাইলেরসংখ্যা', 'ফাইল_সংখ্যা', 'ফাইলসংখ্যা', 'NUMBEROFFILES' ],
+       'numberofusers'           => [ 1, 'ব্যবহারকারীর_সংখ্যা', 'ব্যবহারকারীরসংখ্যা', 'ব্যবহারকারী_সংখ্যা', 'ব্যবহারকারীসংখ্যা', 'NUMBEROFUSERS' ],
+       'numberofactiveusers'     => [ 1, 'সক্রিয়_ব্যবহারকারীর_সংখ্যা', 'সক্রিয়ব্যবহারকারীরসংখ্যা', 'সক্রিয়_ব্যবহারকারী_সংখ্যা', 'সক্রিয়ব্যবহারকারীসংখ্যা', 'NUMBEROFACTIVEUSERS' ],
+       'numberofedits'           => [ 1, 'সম্পাদনার_সংখ্যা', 'সম্পাদনারসংখ্যা', 'সম্পাদনা_সংখ্যা', 'সম্পাদনাসংখ্যা', 'NUMBEROFEDITS' ],
+       'pagename'                => [ 1, 'পাতার_নাম', 'পাতারনাম', 'পৃষ্ঠার_নাম', 'পৃষ্ঠারনাম', 'PAGENAME' ],
+       'pagenamee'               => [ 1, 'পাতার_নামম', 'পাতারনামম', 'পৃষ্ঠার_নামম', 'পৃষ্ঠারনামম', 'PAGENAMEE' ],
+       'namespace'               => [ 1, 'নামস্থান', 'NAMESPACE' ],
+       'namespacee'              => [ 1, 'নামস্থানন', 'NAMESPACEE' ],
+       'namespacenumber'         => [ 1, 'নামস্থানের_সংখ্যা', 'নামস্থানেরসংখ্যা', 'NAMESPACENUMBER' ],
+       'talkspace'               => [ 1, 'আলাপের_স্থান', 'আলোচনার_স্থান', 'আলাপেরস্থান', 'আলোচনারস্থান', 'আলাপের_জায়গা', 'আলাপেরজায়গা', 'TALKSPACE' ],
+       'talkspacee'              => [ 1, 'আলাপের_স্থানন', 'আলোচনার_স্থানন', 'আলাপেরস্থানন', 'আলোচনারস্থানন', 'TALKSPACEE' ],
+       'subjectspace'            => [ 1, 'বিষয়ের_স্থান', 'নিবন্ধের_স্থান', 'বিষয়েরস্থান', 'নিবন্ধেরস্থান', 'SUBJECTSPACE', 'ARTICLESPACE' ],
+       'subjectspacee'           => [ 1, 'বিষয়ের_স্থানন', 'নিবন্ধের_স্থানন', 'বিষয়েরস্থানন', 'নিবন্ধেরস্থানন', 'SUBJECTSPACEE', 'ARTICLESPACEE' ],
+       'fullpagename'            => [ 1, 'পূর্ণ_পাতার_নাম', 'সম্পূর্ণ_পাতার_নাম', 'পূর্ণপাতারনাম', 'সম্পূর্ণপাতারনাম', 'পূর্ণ_পৃষ্ঠার_নাম', 'সম্পূর্ণ_পৃষ্ঠার_নাম', 'পূর্ণপৃষ্ঠারনাম', 'সম্পূর্ণপৃষ্ঠারনাম', 'FULLPAGENAME' ],
+       'fullpagenamee'           => [ 1, 'পূর্ণ_পাতার_নামম', 'সম্পূর্ণ_পাতার_নামম', 'পূর্ণপাতারনামম', 'সম্পূর্ণপাতারনামম', 'পূর্ণ_পৃষ্ঠার_নামম', 'সম্পূর্ণ_পৃষ্ঠার_নামম', 'পূর্ণপৃষ্ঠারনামম', 'সম্পূর্ণপৃষ্ঠারনামম', 'FULLPAGENAMEE' ],
+       'subpagename'             => [ 1, 'উপপাতার_নাম', 'উপপাতারনাম', 'উপপৃষ্ঠার_নাম', 'উপপৃষ্ঠারনাম', 'SUBPAGENAME' ],
+       'subpagenamee'            => [ 1, 'উপপাতার_নামম', 'উপপাতারনামম', 'উপপৃষ্ঠার_নামম', 'উপপৃষ্ঠারনামম', 'SUBPAGENAMEE' ],
+       'rootpagename'            => [ 1, 'মূল_পাতার_নাম', 'মূলপাতারনাম', 'মূল_পৃষ্ঠার_নাম', 'মূল_পৃষ্ঠার_নাম', 'ROOTPAGENAME' ],
+       'rootpagenamee'           => [ 1, 'মূল_পাতার_নামম', 'মূলপাতারনামম', 'মূল_পৃষ্ঠার_নামম', 'মূল_পৃষ্ঠার_নামম', 'ROOTPAGENAMEE' ],
+       'basepagename'            => [ 1, 'ভিত্তি_পাতার_নাম', 'ভিত্তিপাতারনাম', 'ভিত্তি_পৃষ্ঠার_নাম', 'ভিত্তি_পৃষ্ঠার_নাম', 'BASEPAGENAME' ],
+       'basepagenamee'           => [ 1, 'ভিত্তি_পাতার_নামম', 'ভিত্তিপাতারনামম', 'ভিত্তি_পৃষ্ঠার_নামম', 'ভিত্তি_পৃষ্ঠার_নামম', 'BASEPAGENAMEE' ],
+       'talkpagename'            => [ 1, 'আলাপ_পাতার_নাম', 'আলাপপাতারনাম', 'আলাপ_পৃষ্ঠার_নাম', 'আলোচনা_পৃষ্ঠার_নাম', 'আলোচনা_পাতার_নাম', 'আলোচনাপাতারনাম', 'আলোচনা_পৃষ্ঠার_নাম', 'আলোচনা_পৃষ্ঠার_নাম', 'TALKPAGENAME' ],
+       'talkpagenamee'           => [ 1, 'আলাপ_পাতার_নামম', 'আলাপপাতারনামম', 'আলাপ_পৃষ্ঠার_নামম', 'আলোচনা_পৃষ্ঠার_নামম', 'আলোচনা_পাতার_নামম', 'আলোচনাপাতারনামম', 'আলোচনা_পৃষ্ঠার_নামম', 'আলোচনা_পৃষ্ঠার_নামম', 'TALKPAGENAMEE' ],
+       'subjectpagename'         => [ 1, 'বিষয়ের_পাতার_নাম', 'বিষয়েরপাতারনাম', 'বিষয়ের_পৃষ্ঠার_নাম', 'বিষয়েরপৃষ্ঠারনাম', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
+       'subjectpagenamee'        => [ 1, 'বিষয়ের_পাতার_নামম', 'বিষয়েরপাতারনামম', 'বিষয়ের_পৃষ্ঠার_নামম', 'বিষয়েরপৃষ্ঠারনামম', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
+       'img_thumbnail'           => [ 1, 'থাম্ব','থাম্বনেইল', 'thumb', 'thumbnail' ],
+       'img_manualthumb'         => [ 1, 'থাম্ব=$1','থাম্বনেইল=$1', 'thumbnail=$1', 'thumb=$1' ],
+       'img_right'               => [ 1, 'ডান', 'ডানে', 'right' ],
+       'img_left'                => [ 1, 'বাম', 'বামে', 'left' ],
+       'img_none'                => [ 1, 'কিছুই_না', 'কোনটি_না', 'কিছুইনা', 'কোনটিনা', 'none' ],
+       'img_width'               => [ 1, '$1পিক্সেল', '$1পিক্স', '$1px' ],
+       'img_center'              => [ 1, 'কেন্দ্র', 'কেন্দ্রে', 'center', 'centre' ],
+       'img_framed'              => [ 1, 'ফ্রেম', 'ফ্রেমসহ', 'frame', 'framed', 'enframed' ],
+       'img_frameless'           => [ 1, 'ফ্রেমহীন', 'ফ্রেমবিহীন', 'frameless' ],
+       'img_lang'                => [ 1, 'ভাষা=$1', 'lang=$1' ],
+       'img_page'                => [ 1, 'পাতা=$1', 'পাতা $1', 'পৃষ্ঠা=$1', 'পৃষ্ঠা $1', 'page=$1', 'page $1' ],
+       'img_upright'             => [ 1, 'ডানে_উপরে', 'ডানেউপরে=$1', 'ডানদিকে_উপরে', 'ডানদিকে_উপরে $1', 'ডানদিকে_উপরে=$1', 'ডানেউপরে $1', 'upright', 'upright=$1', 'upright $1' ],
+       'img_border'              => [ 1, 'সীমানা', 'সীমান্ত', 'border' ],
+       'img_top'                 => [ 1, 'শীর্ষ', 'উপর', 'শীর্ষে', 'উপরে', 'top' ],
+       'img_text_top'            => [ 1, 'পাঠ্য-উপরে', 'লেখা-উপরে', 'পাঠ্য-উপর', 'লেখা-উপর', 'text-top' ],
+       'img_middle'              => [ 1, 'মধ্য', 'মধ্যে', 'middle' ],
+       'img_bottom'              => [ 1, 'নিচে', 'নিচ', 'নীচ', 'নীচে', 'তলদেশ', 'নিম্নে', 'bottom' ],
+       'img_text_bottom'         => [ 1, 'পাঠ্য-নীচে', 'লেখা-নীচ', 'text-bottom' ],
+       'img_link'                => [ 1, 'সংযোগ=$1', 'লিঙ্ক=$1', 'link=$1' ],
+       'img_class'               => [ 1, 'ক্লাস=$1', 'class=$1' ],
+       'sitename'                => [ 1, 'সাইটের_নাম', 'সাইটেরনাম', 'SITENAME' ],
+       'localurl'                => [ 0, 'স্থানীয়_ইউআরএল:', 'স্থানীয়ইউআরএল:', 'LOCALURL:' ],
+       'articlepath'             => [ 0, 'নিবন্ধের_পথ', 'নিবন্ধেরপথ', 'ARTICLEPATH' ],
+       'pageid'                  => [ 0, 'পাতার_আইডি', 'পাতারআইডি', 'পৃষ্ঠার_আইডি', 'পৃষ্ঠারআইডি', 'PAGEID' ],
+       'server'                  => [ 0, 'সার্ভার', 'SERVER' ],
+       'servername'              => [ 0, 'সার্ভারের_নাম', 'সার্ভারেরনাম', 'SERVERNAME' ],
+       'scriptpath'              => [ 0, 'স্ক্রিপ্টের_পথ', 'স্ক্রিপ্টেরপথ', 'SCRIPTPATH' ],
+       'stylepath'               => [ 0, 'শৈলীর_পথ', 'শৈলীরপথ', 'STYLEPATH' ],
+       'grammar'                 => [ 0, 'ব্যাকরণ:', 'GRAMMAR:' ],
+       'gender'                  => [ 0, 'লিঙ্গ:', 'GENDER:' ],
+       'bidi'                    => [ 0, 'বিআইডিআই:', 'BIDI:' ],
+       'notitleconvert'          => [ 0, '__কোন_শিরোনাম_রূপান্তরকারী_নয়__', '__কোনশিরোনামরূপান্তরকারীনয়__', '__NOTITLECONVERT__', '__NOTC__' ],
+       'nocontentconvert'        => [ 0, '__কোন_বিষয়বস্তু_রূপান্তরকারী_নয়__', '__কোনবিষয়বস্তুরূপান্তরকারীনয়__', '__NOCONTENTCONVERT__', '__NOCC__' ],
+       'currentweek'             => [ 1, 'বর্তমান_সপ্তাহ', 'বর্তমানসপ্তাহ', 'চলতি_সপ্তাহ', 'চলতিসপ্তাহ', 'CURRENTWEEK' ],
+       'currentdow'              => [ 1, 'বর্তমান_সপ্তাহের_দিন', 'বর্তমানসপ্তাহেরদিন', 'CURRENTDOW' ],
+       'localweek'               => [ 1, 'স্থানীয়_সপ্তাহ', 'স্থানীয়সপ্তাহ', 'LOCALWEEK' ],
+       'localdow'                => [ 1, 'স্থানীয়_সপ্তাহের_দিন', 'স্থানীয়সপ্তাহেরদিন', 'LOCALDOW' ],
+       'revisionid'              => [ 1, 'সংশোধনের_আইডি', 'সংশোধনেরআইডি', 'REVISIONID' ],
+       'revisionday'             => [ 1, 'সংশোধনের_দিন', 'সংশোধনেরদিন', 'REVISIONDAY' ],
+       'revisionday2'            => [ 1, 'সংশোধনের_দিন_২', 'সংশোধনেরদিন২', 'REVISIONDAY2' ],
+       'revisionmonth'           => [ 1, 'সংশোধনের_মাস', 'সংশোধনেরমাস', 'REVISIONMONTH' ],
+       'revisionmonth1'          => [ 1, 'সংশোধনের_মাস_১', 'সংশোধনেরমাস১', 'REVISIONMONTH1' ],
+       'revisionyear'            => [ 1, 'সংশোধনের_বছর', 'সংশোধনেরবছর', 'REVISIONYEAR' ],
+       'revisiontimestamp'       => [ 1, 'সংশোধনের_সময়তারিখ', 'সংশোধনেরসময়তারিখ', 'REVISIONTIMESTAMP' ],
+       'revisionuser'            => [ 1, 'সংশোধনের_ব্যবহারকারী', 'সংশোধনেরব্যবহারকারী', 'REVISIONUSER' ],
+       'revisionsize'            => [ 1, 'সংশোধনের_আকার', 'সংশোধনেরআকার', 'REVISIONSIZE' ],
+       'plural'                  => [ 0, 'বহুবচন:', 'PLURAL:' ],
+       'raw'                     => [ 0, 'অবিন্যস্ত:', 'RAW:' ],
+       'displaytitle'            => [ 1, 'প্রদর্শনের_শিরোনাম', 'প্রদর্শনেরশিরোনাম', 'প্রদর্শিত_শিরোনাম', 'প্রদর্শিতশিরোনাম', 'DISPLAYTITLE' ],
+       'newsectionlink'          => [ 1, '__নতুন_অনুচ্ছেদের_সংযোগ__', '__নতুন_অনুচ্ছেদের_লিঙ্ক__', '__নতুনঅনুচ্ছেদেরসংযোগ__', '__নতুনঅনুচ্ছেদেরলিঙ্ক__', '__NEWSECTIONLINK__' ],
+       'nonewsectionlink'        => [ 1, '__কোন_নতুন_অনুচ্ছেদের_সংযোগ_নয়__', '__কোন_নতুন_অনুচ্ছেদের_লিঙ্ক_নয়__', '__কোননতুনঅনুচ্ছেদেরসংযোগনয়__', '__কোননতুনঅনুচ্ছেদেরলিঙ্কনয়__', '__NONEWSECTIONLINK__' ],
+       'currentversion'          => [ 1, 'বর্তমান_সংস্করণ', 'বর্তমানসংস্করণ', 'CURRENTVERSION' ],
+       'currenttimestamp'        => [ 1, 'বর্তমান_সময়তারিখ', 'বর্তমান_সময়তারিখ', 'CURRENTTIMESTAMP' ],
+       'localtimestamp'          => [ 1, 'স্থানীয়_সময়তারিখ', 'স্থানীয়সময়তারিখ', 'LOCALTIMESTAMP' ],
+       'language'                => [ 0, '#ভাষা:', '#LANGUAGE:' ],
+       'contentlanguage'         => [ 1, 'বিষয়বস্তুর_ভাষা', 'বিষয়বস্তুরভাষা', 'CONTENTLANGUAGE', 'CONTENTLANG' ],
+       'pagesinnamespace'        => [ 1, 'নামস্থানে_পাতা', 'নামস্থানে_পৃষ্ঠা', 'নামস্থানেপাতা', 'নামস্থানেপৃষ্ঠা', 'PAGESINNAMESPACE:', 'PAGESINNS:' ],
+       'numberofadmins'          => [ 1, 'প্রশাসকের_সংখ্যা', 'প্রশাসকেরসংখ্যা', 'প্রশাসক_সংখ্যা', 'প্রশাসকসংখ্যা', 'NUMBEROFADMINS' ],
+       'formatnum'               => [ 0, 'নম্বর_বিন্যাস', 'নম্বরবিন্যাস', 'FORMATNUM' ],
+       'special'                 => [ 0, 'বিশেষ', 'special' ],
+       'defaultsort'             => [ 1, 'পূর্বনির্ধারিত_বাছাই', 'পূর্বনির্ধারিতবাছাই', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ],
+       'filepath'                => [ 0, 'ফাইলের_পথ:', 'ফাইলেরপথ:', 'FILEPATH:' ],
+       'tag'                     => [ 0, 'ট্যাগ', 'tag' ],
+       'hiddencat'               => [ 1, '__লুকায়িতবিষয়শ্রেণী__', '__লুক্কায়িতবিষয়শ্রেণী__', '__HIDDENCAT__' ],
+       'pagesincategory'         => [ 1, 'বিষয়শ্রেণীতেপাতা', 'বিষয়শ্রেণীতেপৃষ্ঠা', 'বিষয়শ্রেণীতে_পাতা', 'বিষয়শ্রেণীতে_পৃষ্ঠা', 'PAGESINCATEGORY', 'PAGESINCAT' ],
+       'pagesize'                => [ 1, 'পাতার_আকার', 'পাতারআকার', 'পৃষ্ঠার_আকার', 'পৃষ্ঠারআকার', 'PAGESIZE' ],
+       'index'                   => [ 1, '__নির্ঘণ্ট__', '__INDEX__' ],
+       'noindex'                 => [ 1, '__কোননির্ঘণ্টনয়__', '__কোন_নির্ঘণ্ট_নয়__', '__নির্ঘণ্টনয়__', '__NOINDEX__' ],
+       'numberingroup'           => [ 1, 'দলে_সংখ্যা', 'দলেসংখ্যা', 'NUMBERINGROUP', 'NUMINGROUP' ],
+       'staticredirect'          => [ 1, '__স্থির_পুনর্নির্দেশ__', '__স্থিরপুনর্নির্দেশ__', '__STATICREDIRECT__' ],
+       'protectionlevel'         => [ 1, 'সুরক্ষার_স্তর', 'সুরক্ষারস্তর', 'সুরক্ষা_স্তর', 'সুরক্ষাস্তর', 'PROTECTIONLEVEL' ],
+       'protectionexpiry'        => [ 1, 'সুরক্ষার_মেয়াদোত্তীর্ণ', 'সুরক্ষারমেয়াদোত্তীর্ণ', 'সুরক্ষা_মেয়াদোত্তীর্ণ', 'সুরক্ষামেয়াদোত্তীর্ণ', 'PROTECTIONEXPIRY' ],
+       'formatdate'              => [ 0, 'তারিখ_বিন্যাস', 'তারিখবিন্যাস', 'formatdate', 'dateformat' ],
+       'url_path'                => [ 0, 'পথ', 'PATH' ],
+       'url_wiki'                => [ 0, 'উইকি', 'WIKI' ],
+       'pagesincategory_all'     => [ 0, 'সব', 'সকল', 'all' ],
+       'pagesincategory_pages'   => [ 0, 'পাতাসমূহ', 'পৃষ্ঠাসমূহ', 'pages' ],
+       'pagesincategory_subcats' => [ 0, 'উপবিষয়শ্রেণী', '', 'subcats' ],
+       'pagesincategory_files'   => [ 0, 'ফাইলসমূহ', 'files' ],
+];
+
+$linkTrail = '/^([\x{0980}-\x{09FF}]+)(.*)$/sDu';
diff --git a/languages/messages/MessagesKrl.php b/languages/messages/MessagesKrl.php
new file mode 100644 (file)
index 0000000..b991899
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+/** Karelian (Karlaj)
+ *
+ * To improve a translation please visit https://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ *
+ */
+
+$fallback = 'fi'; // T137415
index 954d911..84b107e 100644 (file)
@@ -13,7 +13,7 @@
  * @author Numulunj pilgae
  */
 
-$fallbak = 'ru';
+$fallback = 'ru';
 
 $namespaceNames = [
        NS_MEDIA            => 'Медиа',
index 14f5b6f..63c1e80 100644 (file)
@@ -8,7 +8,7 @@
  *
  */
 
-$fallback = 'ru';
+$fallback = 'fi'; // T146744#2678472
 
 $namespaceNames = [
        NS_MEDIA            => 'Medii',
index 838ea33..29627a6 100644 (file)
@@ -12,6 +12,8 @@
  * @author Reder
  */
 
+$fallback = 'it';
+
 $specialPageAliases = [
        'Allmessages'               => [ 'TutteLeMessagge' ],
        'Preferences'               => [ 'Preferenze' ],
index 369e0be..0c381e5 100644 (file)
@@ -58,7 +58,6 @@ $separatorTransformTable = [
        '.' => ','
 ];
 
-$fallback = 'ru';
 $fallback8bitEncoding = 'windows-1251';
 $linkPrefixExtension = true;
 
@@ -86,11 +85,23 @@ $namespaceAliases = [
        'Зображення' => NS_FILE,
        'Обговорення_зображення' => NS_FILE_TALK,
        'Обговорення_шаблона' => NS_TEMPLATE_TALK,
+       // Backwards compatibility from Russian
+       'Медиа' => NS_MEDIA,
+       'Служебная' => NS_SPECIAL,
+       'Обсуждение' => NS_TALK,
+       'Участник' => NS_USER,
+       'Обсуждение_участника' => NS_USER_TALK,
+       'Обсуждение_файла' => NS_FILE_TALK,
+       'Обсуждение_MediaWiki' => NS_MEDIAWIKI_TALK,
+       'Обсуждение_шаблона' => NS_TEMPLATE_TALK,
+       'Справка' => NS_HELP,
+       'Обсуждение_справки' => NS_HELP_TALK,
+       'Категория' => NS_CATEGORY,
+       'Обсуждение_категории' => NS_CATEGORY_TALK,
+       'Изображение' => NS_FILE,
+       'Обсуждение_изображения' => NS_FILE_TALK,
 ];
 
-// Remove Russian aliases
-$namespaceGenderAliases = [];
-
 $dateFormats = [
        'mdy time' => 'H:i',
        'mdy date' => 'xg j, Y',
@@ -113,108 +124,109 @@ $bookstoreList = [
        'Amazon.com' => 'http://www.amazon.com/exec/obidos/ISBN=$1'
 ];
 
+// Russian names are kept for backwards compatibility
 $specialPageAliases = [
-       'Activeusers'               => [ 'Активні_дописувачі' ],
-       'Allmessages'               => [ 'Системні_повідомлення' ],
-       'AllMyUploads'              => [ 'Усі_мої_файли' ],
-       'Allpages'                  => [ 'Усі_сторінки' ],
+       'Activeusers'               => [ 'Активні_дописувачі', 'Активные_участники' ],
+       'Allmessages'               => [ 'Системні_повідомлення', 'Системные_сообщения' ],
+       'AllMyUploads'              => [ 'Усі_мої_файли', 'Все_мои_файлы' ],
+       'Allpages'                  => [ 'Усі_сторінки', 'Все_страницы' ],
        'Ancientpages'              => [ 'Давні_сторінки' ],
-       'Badtitle'                  => [ 'Помилковий_заголовок' ],
-       'Blankpage'                 => [ 'Порожня_сторінка' ],
-       'Block'                     => [ 'Заблокувати' ],
-       'Booksources'               => [ 'Джерела_книг' ],
-       'BrokenRedirects'           => [ 'Розірвані_перенаправлення' ],
-       'Categories'                => [ 'Категорії' ],
-       'ChangeEmail'               => [ 'Змінити_e-mail' ],
-       'ChangePassword'            => [ 'Змінити_пароль' ],
-       'ComparePages'              => [ 'Порівняння_сторінок' ],
-       'Confirmemail'              => [ 'Підтвердити_e-mail' ],
-       'Contributions'             => [ 'Внесок' ],
-       'CreateAccount'             => [ 'Створити_обліковий_запис' ],
-       'Deadendpages'              => [ 'Сторінки_без_посилань' ],
-       'DeletedContributions'      => [ 'Вилучений_внесок' ],
-       'DoubleRedirects'           => [ 'Подвійні_перенаправлення' ],
-       'EditWatchlist'             => [ 'Редагувати_список_спостереження' ],
-       'Emailuser'                 => [ 'Лист_користувачеві' ],
-       'ExpandTemplates'           => [ 'Розгортання_шаблонів' ],
-       'Export'                    => [ 'Експорт' ],
-       'Fewestrevisions'           => [ 'Найменшредаговані' ],
-       'FileDuplicateSearch'       => [ 'Пошук_дублікатів_файлів' ],
-       'Filepath'                  => [ 'Шлях_до_файлу' ],
-       'Import'                    => [ 'Імпорт' ],
-       'Invalidateemail'           => [ 'Неперевірена_email-адреса' ],
-       'JavaScriptTest'            => [ 'JavaScript_тест' ],
-       'BlockList'                 => [ 'Список_блокувань', 'Блокування', 'Блокування_IP-адрес' ],
-       'LinkSearch'                => [ 'Пошук_посилань' ],
-       'Listadmins'                => [ 'Список_адміністраторів' ],
-       'Listbots'                  => [ 'Список_ботів' ],
-       'Listfiles'                 => [ 'Список_файлів' ],
-       'Listgrouprights'           => [ 'Список_прав_груп', 'Права_груп_користувачів' ],
-       'Listredirects'             => [ 'Список_перенаправлень' ],
-       'ListDuplicatedFiles'       => [ 'Список_дубльованих_файлів' ],
-       'Listusers'                 => [ 'Список_користувачів' ],
-       'Lockdb'                    => [ 'Заблокувати_базу_даних' ],
-       'Log'                       => [ 'Журнали' ],
-       'Lonelypages'               => [ 'Ізольовані_сторінки' ],
-       'Longpages'                 => [ 'Найдовші_сторінки' ],
-       'MergeHistory'              => [ 'Об\'єднання_історії' ],
-       'MIMEsearch'                => [ 'Пошук_за_MIME' ],
-       'Mostcategories'            => [ 'Найбільш_категоризовані' ],
-       'Mostimages'                => [ 'Найуживаніші_файли' ],
-       'Mostinterwikis'            => [ 'Найбільше_інтервікі' ],
-       'Mostlinked'                => [ 'Найуживаніші_сторінки', 'Найбільше_посилань' ],
-       'Mostlinkedcategories'      => [ 'Найуживаніші_категорії' ],
-       'Mostlinkedtemplates'       => [ 'Найуживаніші_шаблони' ],
-       'Mostrevisions'             => [ 'Найбільш_редаговані' ],
-       'Movepage'                  => [ 'Перейменувати' ],
-       'Mycontributions'           => [ 'Мій_внесок' ],
-       'MyLanguage'                => [ 'Моя_мова' ],
-       'Mypage'                    => [ 'Моя_сторінка' ],
-       'Mytalk'                    => [ 'Моє_обговорення' ],
-       'Myuploads'                 => [ 'Мої_завантаження' ],
-       'Newimages'                 => [ 'Нові_файли' ],
-       'Newpages'                  => [ 'Нові_сторінки' ],
-       'PasswordReset'             => [ 'Скинути_пароль' ],
-       'PermanentLink'             => [ 'Постійне_посилання' ],
-       'Preferences'               => [ 'Налаштування' ],
-       'Prefixindex'               => [ 'Покажчик_за_початком_назви' ],
-       'Protectedpages'            => [ 'Захищені_сторінки' ],
-       'Protectedtitles'           => [ 'Захищені_назви_сторінок' ],
-       'Randompage'                => [ 'Випадкова_сторінка' ],
-       'Randomredirect'            => [ 'Випадкове_перенаправлення' ],
-       'Recentchanges'             => [ 'Нові_редагування' ],
-       'Recentchangeslinked'       => [ 'Пов\'язані_редагування' ],
+       'Badtitle'                  => [ 'Помилковий_заголовок', 'Недопустимое_название' ],
+       'Blankpage'                 => [ 'Порожня_сторінка', 'Пустая_страница' ],
+       'Block'                     => [ 'Заблокувати', 'Заблокировать' ],
+       'Booksources'               => [ 'Джерела_книг', 'Источники_книг' ],
+       'BrokenRedirects'           => [ 'Розірвані_перенаправлення', 'Разорванные_перенаправления' ],
+       'Categories'                => [ 'Категорії', 'Категории' ],
+       'ChangeEmail'               => [ 'Змінити_e-mail', 'Сменить_e-mail', 'Сменить_почту' ],
+       'ChangePassword'            => [ 'Змінити_пароль', 'Сменить_пароль' ],
+       'ComparePages'              => [ 'Порівняння_сторінок', 'Сравнение_страниц' ],
+       'Confirmemail'              => [ 'Підтвердити_e-mail', 'Подтвердить_e-mail', 'Подтвердить_почту' ],
+       'Contributions'             => [ 'Внесок', 'Вклад' ],
+       'CreateAccount'             => [ 'Створити_обліковий_запис', 'Создать_учётную_запись', 'Создать_пользователя', 'Зарегистрироваться' ],
+       'Deadendpages'              => [ 'Сторінки_без_посилань', 'Тупиковые_страницы' ],
+       'DeletedContributions'      => [ 'Вилучений_внесок', 'Удалённый_вклад' ],
+       'DoubleRedirects'           => [ 'Подвійні_перенаправлення', 'Двойные_перенаправления' ],
+       'EditWatchlist'             => [ 'Редагувати_список_спостереження', 'Править_список_наблюдения' ],
+       'Emailuser'                 => [ 'Лист_користувачеві', 'Письмо_участнику', 'Отправить_письмо' ],
+       'ExpandTemplates'           => [ 'Розгортання_шаблонів', 'Развёртка_шаблонов' ],
+       'Export'                    => [ 'Експорт', 'Экспорт', 'Выгрузка' ],
+       'Fewestrevisions'           => [ 'Найменшредаговані', 'Редко_редактируемые' ],
+       'FileDuplicateSearch'       => [ 'Пошук_дублікатів_файлів', 'Поиск_дубликатов_файлов' ],
+       'Filepath'                  => [ 'Шлях_до_файлу', 'Путь_к_файлу' ],
+       'Import'                    => [ 'Імпорт', 'Импорт' ],
+       'Invalidateemail'           => [ 'Неперевірена_email-адреса', 'Отменить_подтверждение_адреса' ],
+       'JavaScriptTest'            => [ 'JavaScript_тест', 'Тестирование_JavaScript' ],
+       'BlockList'                 => [ 'Список_блокувань', 'Блокування', 'Блокування_IP-адрес', 'Список_блокировок', 'Блокировки' ],
+       'LinkSearch'                => [ 'Пошук_посилань', 'Поиск_ссылок' ],
+       'Listadmins'                => [ 'Список_адміністраторів', 'Список_администраторов' ],
+       'Listbots'                  => [ 'Список_ботів', 'Список_ботов' ],
+       'Listfiles'                 => [ 'Список_файлів', 'Список_файлов', 'Список_изображений' ],
+       'Listgrouprights'           => [ 'Список_прав_груп', 'Права_груп_користувачів', 'Права_групп_участников', 'Список_прав_групп' ],
+       'Listredirects'             => [ 'Список_перенаправлень', 'Список_перенаправлений' ],
+       'ListDuplicatedFiles'       => [ 'Список_дубльованих_файлів', 'Список_файлов-дубликатов' ],
+       'Listusers'                 => [ 'Список_користувачів', 'Список_участников' ],
+       'Lockdb'                    => [ 'Заблокувати_базу_даних', 'Заблокировать_БД', 'Заблокировать_базу_данных' ],
+       'Log'                       => [ 'Журнали', 'Журналы', 'Журнал' ],
+       'Lonelypages'               => [ 'Ізольовані_сторінки', 'Изолированные_страницы' ],
+       'Longpages'                 => [ 'Найдовші_сторінки', 'Длинные_страницы' ],
+       'MergeHistory'              => [ 'Об\'єднання_історії', 'Объединение_историй' ],
+       'MIMEsearch'                => [ 'Пошук_за_MIME', 'Поиск_по_MIME' ],
+       'Mostcategories'            => [ 'Найбільш_категоризовані', 'Самые_категоризованные' ],
+       'Mostimages'                => [ 'Найуживаніші_файли', 'Самые_используемые_файлы' ],
+       'Mostinterwikis'            => [ 'Найбільше_інтервікі', 'Наибольшее_количество_интервики-ссылок' ],
+       'Mostlinked'                => [ 'Найуживаніші_сторінки', 'Найбільше_посилань', 'Самые_используемые_страницы' ],
+       'Mostlinkedcategories'      => [ 'Найуживаніші_категорії', 'Самые_используемые_категории' ],
+       'Mostlinkedtemplates'       => [ 'Найуживаніші_шаблони', 'Самые_используемые_шаблоны' ],
+       'Mostrevisions'             => [ 'Найбільш_редаговані', 'Наибольшее_количество_версий' ],
+       'Movepage'                  => [ 'Перейменувати', 'Переименовать_страницу', 'Переименование', 'Переименовать' ],
+       'Mycontributions'           => [ 'Мій_внесок', 'Мой_вклад' ],
+       'MyLanguage'                => [ 'Моя_мова', 'Мой_язык' ],
+       'Mypage'                    => [ 'Моя_сторінка', 'Моя_страница' ],
+       'Mytalk'                    => [ 'Моє_обговорення', 'Моё_обсуждение' ],
+       'Myuploads'                 => [ 'Мої_завантаження', 'Мои_загрузки' ],
+       'Newimages'                 => [ 'Нові_файли', 'Новые_файлы' ],
+       'Newpages'                  => [ 'Нові_сторінки', 'Новые_страницы' ],
+       'PasswordReset'             => [ 'Скинути_пароль', 'Сброс_пароля' ],
+       'PermanentLink'             => [ 'Постійне_посилання', 'Постоянная_ссылка' ],
+       'Preferences'               => [ 'Налаштування', 'Настройки' ],
+       'Prefixindex'               => [ 'Покажчик_за_початком_назви', 'Указатель_по_началу_названия' ],
+       'Protectedpages'            => [ 'Захищені_сторінки', 'Защищённые_страницы' ],
+       'Protectedtitles'           => [ 'Захищені_назви_сторінок', 'Защищённые_названия' ],
+       'Randompage'                => [ 'Випадкова_сторінка', 'Случайная_страница', 'Случайная' ],
+       'Randomredirect'            => [ 'Випадкове_перенаправлення', 'Случайное_перенаправление' ],
+       'Recentchanges'             => [ 'Нові_редагування', 'Свежие_правки' ],
+       'Recentchangeslinked'       => [ 'Пов\'язані_редагування', 'Связанные_правки' ],
        'Redirect'                  => [ 'Перенаправлення' ],
-       'Revisiondelete'            => [ 'Вилучити_редагування' ],
-       'Search'                    => [ 'Пошук' ],
-       'Shortpages'                => [ 'Короткі_сторінки' ],
-       'Specialpages'              => [ 'Спеціальні_сторінки' ],
+       'Revisiondelete'            => [ 'Вилучити_редагування', 'Удаление_правки' ],
+       'Search'                    => [ 'Пошук', 'Поиск' ],
+       'Shortpages'                => [ 'Короткі_сторінки', 'Короткие_страницы' ],
+       'Specialpages'              => [ 'Спеціальні_сторінки', 'Спецстраницы' ],
        'Statistics'                => [ 'Статистика' ],
-       'Tags'                      => [ 'Мітки' ],
-       'Unblock'                   => [ 'Розблокувати' ],
-       'Uncategorizedcategories'   => [ 'Некатегоризовані_категорії' ],
-       'Uncategorizedimages'       => [ 'Некатегоризовані_файли' ],
-       'Uncategorizedpages'        => [ 'Некатегоризовані_сторінки' ],
-       'Uncategorizedtemplates'    => [ 'Некатегоризовані_шаблони' ],
-       'Undelete'                  => [ 'Відновити' ],
-       'Unlockdb'                  => [ 'Розблокувати_базу_даних' ],
-       'Unusedcategories'          => [ 'Порожні_категорії' ],
-       'Unusedimages'              => [ 'Невикористані_файли' ],
-       'Unusedtemplates'           => [ 'Невикористані_шаблони' ],
+       'Tags'                      => [ 'Мітки', 'Метки' ],
+       'Unblock'                   => [ 'Розблокувати', 'Разблокировка' ],
+       'Uncategorizedcategories'   => [ 'Некатегоризовані_категорії', 'Некатегоризованные_категории' ],
+       'Uncategorizedimages'       => [ 'Некатегоризовані_файли', 'Некатегоризованные_файлы' ],
+       'Uncategorizedpages'        => [ 'Некатегоризовані_сторінки', 'Некатегоризованные_страницы' ],
+       'Uncategorizedtemplates'    => [ 'Некатегоризовані_шаблони', 'Некатегоризованные_шаблоны' ],
+       'Undelete'                  => [ 'Відновити', 'Восстановить', 'Восстановление' ],
+       'Unlockdb'                  => [ 'Розблокувати_базу_даних', 'Разблокировка_БД' ],
+       'Unusedcategories'          => [ 'Порожні_категорії', 'Неиспользуемые_категории' ],
+       'Unusedimages'              => [ 'Невикористані_файли', 'Неиспользуемые_файлы' ],
+       'Unusedtemplates'           => [ 'Невикористані_шаблони', 'Неиспользуемые_шаблоны' ],
        'Unwatchedpages'            => [ 'Неспостережувані' ],
-       'Upload'                    => [ 'Завантаження' ],
-       'UploadStash'               => [ 'Приховане_завантаження' ],
-       'Userlogin'                 => [ 'Вхід' ],
-       'Userlogout'                => [ 'Вихід' ],
-       'Userrights'                => [ 'Керування_правами_користувачів' ],
-       'Version'                   => [ 'Версія' ],
-       'Wantedcategories'          => [ 'Потрібні_категорії' ],
-       'Wantedfiles'               => [ 'Потрібні_файли' ],
-       'Wantedpages'               => [ 'Потрібні_сторінки' ],
-       'Wantedtemplates'           => [ 'Потрібні_шаблони' ],
-       'Watchlist'                 => [ 'Список_спостереження' ],
-       'Whatlinkshere'             => [ 'Посилання_сюди' ],
-       'Withoutinterwiki'          => [ 'Без_інтервікі' ],
+       'Upload'                    => [ 'Завантаження', 'Загрузка' ],
+       'UploadStash'               => [ 'Приховане_завантаження', 'Скрытная_загрузка' ],
+       'Userlogin'                 => [ 'Вхід', 'Вход' ],
+       'Userlogout'                => [ 'Вихід', 'Завершение_сеанса', 'Выход' ],
+       'Userrights'                => [ 'Керування_правами_користувачів', 'Управление_правами' ],
+       'Version'                   => [ 'Версія', 'Версия' ],
+       'Wantedcategories'          => [ 'Потрібні_категорії', 'Требуемые_категории' ],
+       'Wantedfiles'               => [ 'Потрібні_файли', 'Требуемые_файлы' ],
+       'Wantedpages'               => [ 'Потрібні_сторінки', 'Требуемые_страницы' ],
+       'Wantedtemplates'           => [ 'Потрібні_шаблони', 'Требуемые_шаблоны' ],
+       'Watchlist'                 => [ 'Список_спостереження', 'Список_наблюдения' ],
+       'Whatlinkshere'             => [ 'Посилання_сюди', 'Ссылки_сюда' ],
+       'Withoutinterwiki'          => [ 'Без_інтервікі', 'Без_интервики' ],
 ];
 
 $magicWords = [
@@ -368,8 +380,8 @@ $magicWords = [
        'pagesincategory_all'       => [ '0', 'усе', 'все', 'all' ],
        'pagesincategory_pages'     => [ '0', 'сторінки', 'страницы', 'pages' ],
        'pagesincategory_subcats'   => [ '0', 'підкатегорії', 'подкатегории', 'subcats' ],
+       'pagesincategory_files'     => [ '0', 'файли', 'файлы', 'files' ],
 ];
 
 $linkTrail = '/^([a-zабвгґдеєжзиіїйклмнопрстуфхцчшщьєюяёъы“»]+)(.*)$/sDu';
 $linkPrefixCharset = '„«';
-
index 552bec0..3925efe 100644 (file)
@@ -498,7 +498,7 @@ abstract class Maintenance {
         */
        public function getConfig() {
                if ( $this->config === null ) {
-                       $this->config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+                       $this->config = MediaWikiServices::getInstance()->getMainConfig();
                }
 
                return $this->config;
index 38daf64..18c7f11 100644 (file)
@@ -60,7 +60,7 @@ class BackupDumper extends Maintenance {
        /**
         * The dependency-injected database to use.
         *
-        * @var DatabaseBase|null
+        * @var IDatabase|null
         *
         * @see self::setDB
         */
@@ -314,7 +314,7 @@ class BackupDumper extends Maintenance {
         * @todo Fixme: the --server parameter is currently not respected, as it
         * doesn't seem terribly easy to ask the load balancer for a particular
         * connection by name.
-        * @return DatabaseBase
+        * @return IDatabase
         */
        function backupDb() {
                if ( $this->forcedDb !== null ) {
@@ -335,7 +335,7 @@ class BackupDumper extends Maintenance {
         * Force the dump to use the provided database connection for database
         * operations, wherever possible.
         *
-        * @param DatabaseBase|null $db (Optional) the database connection to use. If null, resort to
+        * @param IDatabase|null $db (Optional) the database connection to use. If null, resort to
         *   use the globally provided ways to get database connections.
         */
        function setDB( IDatabase $db = null ) {
index 38b8ba1..863d74a 100644 (file)
@@ -22,6 +22,8 @@
  * @author Roan Kattouw
  */
 
+use MediaWiki\MediaWikiServices;
+
 require_once __DIR__ . '/Maintenance.php';
 
 /**
@@ -41,7 +43,7 @@ class CleanupRemovedModules extends Maintenance {
 
        public function execute() {
                $dbw = $this->getDB( DB_MASTER );
-               $rl = new ResourceLoader( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+               $rl = new ResourceLoader( MediaWikiServices::getInstance()->getMainConfig() );
                $moduleNames = $rl->getModuleNames();
                $moduleList = implode( ', ', array_map( [ $dbw, 'addQuotes' ], $moduleNames ) );
                $limit = max( 1, intval( $this->getOption( 'batchsize', 500 ) ) );
index cd7a842..95bbe3d 100644 (file)
@@ -47,7 +47,7 @@ class UploadStashCleanup extends Maintenance {
                $repo = RepoGroup::singleton()->getLocalRepo();
                $tempRepo = $repo->getTempRepo();
 
-               $dbr = $repo->getSlaveDB();
+               $dbr = $repo->getReplicaDB();
 
                // how far back should this look for files to delete?
                $cutoff = time() - $wgUploadStashMaxAge;
index 914336f..a2a06d2 100644 (file)
@@ -1036,7 +1036,6 @@ csrf
 css
 cssclass
 csslinks
-cssprefs
 cta
 ctime
 ctor
index f3561b5..e649c9d 100644 (file)
@@ -98,7 +98,7 @@ $maintenance->finalSetup();
 require_once "$IP/includes/Setup.php";
 
 // Initialize main config instance
-$maintenance->setConfig( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+$maintenance->setConfig( MediaWikiServices::getInstance()->getMainConfig() );
 
 // Sanity-check required extensions are installed
 $maintenance->checkRequiredExtensions();
index c06a72e..7979e7d 100644 (file)
@@ -36,7 +36,7 @@ class FindMissingFiles extends Maintenance {
                $lastName = $this->getOption( 'start', '' );
 
                $repo = RepoGroup::singleton()->getLocalRepo();
-               $dbr = $repo->getSlaveDB();
+               $dbr = $repo->getReplicaDB();
                $be = $repo->getBackend();
 
                $mtime1 = $dbr->timestampOrNull( $this->getOption( 'mtimeafter', null ) );
index abd170b..5980631 100644 (file)
@@ -75,7 +75,7 @@ class FindOrphanedFiles extends Maintenance {
                        return;
                }
 
-               $dbr = $repo->getSlaveDB();
+               $dbr = $repo->getReplicaDB();
 
                $curNames = [];
                $oldNames = [];
index 2894653..816e745 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup Maintenance
  */
 
+use MediaWiki\MediaWikiServices;
+
 require_once __DIR__ . '/Maintenance.php';
 
 /**
@@ -129,7 +131,7 @@ class ImportTextFiles extends Maintenance {
                                }
                        }
 
-                       $rev = new WikiRevision( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+                       $rev = new WikiRevision( MediaWikiServices::getInstance()->getMainConfig() );
                        $rev->setText( rtrim( $text ) );
                        $rev->setTitle( $title );
                        $rev->setUserObj( $user );
index aad85da..9fe5009 100644 (file)
@@ -27,6 +27,7 @@
                                        "mw.notification",
                                        "mw.Notification_",
                                        "mw.storage",
+                                       "mw.storage.session",
                                        "mw.user",
                                        "mw.util",
                                        "mw.plugin.*",
index a650aa0..bb47631 100644 (file)
@@ -36,11 +36,6 @@ $mmfl = false;
  * @ingroup Maintenance
  */
 class MergeMessageFileList extends Maintenance {
-       /**
-        * @var bool
-        */
-       protected $hasError;
-
        function __construct() {
                parent::__construct();
                $this->addOption(
@@ -106,7 +101,6 @@ class MergeMessageFileList extends Maintenance {
                                }
 
                                if ( !$found ) {
-                                       $this->hasError = true;
                                        $this->error( "Extension {$extname} in {$extdir} lacks expected entry point: " .
                                                "extension.json, skin.json, or {$extname}.php." );
                                }
@@ -119,10 +113,6 @@ class MergeMessageFileList extends Maintenance {
                        $mmfl['setupFiles'] = array_merge( $mmfl['setupFiles'], $extensionPaths );
                }
 
-               if ( $this->hasError ) {
-                       $this->error( "Some files are missing (see above). Giving up.", 1 );
-               }
-
                if ( $this->hasOption( 'output' ) ) {
                        $mmfl['output'] = $this->getOption( 'output' );
                }
index c6bd794..b41e0e0 100644 (file)
@@ -28,6 +28,10 @@ require_once __DIR__ . '/Maintenance.php';
  *  populateContentModel.php --ns=1 --table=page
  */
 class PopulateContentModel extends Maintenance {
+       protected $wikiId;
+
+       protected $wanCache;
+
        public function __construct() {
                parent::__construct();
                $this->addDescription( 'Populate the various content_* fields' );
@@ -38,6 +42,11 @@ class PopulateContentModel extends Maintenance {
 
        public function execute() {
                $dbw = $this->getDB( DB_MASTER );
+
+               $this->wikiId = $dbw->getWikiID();
+
+               $this->wanCache = ObjectCache::getMainWANInstance();
+
                $ns = $this->getOption( 'ns' );
                if ( !ctype_digit( $ns ) && $ns !== 'all' ) {
                        $this->error( 'Invalid namespace', 1 );
@@ -57,6 +66,18 @@ class PopulateContentModel extends Maintenance {
                }
        }
 
+       protected function clearCache( $page_id, $rev_id ) {
+               $contentModelKey = $this->wanCache->makeKey( 'page', 'content-model', $rev_id );
+               $revisionKey =
+                       $this->wanCache->makeGlobalKey( 'revision', $this->wikiId, $page_id, $rev_id );
+
+               // WikiPage content model cache
+               $this->wanCache->delete( $contentModelKey );
+
+               // Revision object cache, which contains a content model
+               $this->wanCache->delete( $revisionKey );
+       }
+
        private function updatePageRows( Database $dbw, $pageIds, $model ) {
                $count = count( $pageIds );
                $this->output( "Setting $count rows to $model..." );
@@ -117,6 +138,7 @@ class PopulateContentModel extends Maintenance {
                        [ $key => $ids ],
                        __METHOD__
                );
+
                $this->output( "done.\n" );
        }
 
@@ -130,19 +152,27 @@ class PopulateContentModel extends Maintenance {
                        $fields = [ 'ar_namespace', 'ar_title' ];
                        $join_conds = [];
                        $where = $ns === 'all' ? [] : [ 'ar_namespace' => $ns ];
+                       $page_id_column = 'ar_page_id';
+                       $rev_id_column = 'ar_rev_id';
                } else { // revision
                        $selectTables = [ 'revision', 'page' ];
                        $fields = [ 'page_title', 'page_namespace' ];
                        $join_conds = [ 'page' => [ 'INNER JOIN', 'rev_page=page_id' ] ];
                        $where = $ns === 'all' ? [] : [ 'page_namespace' => $ns ];
+                       $page_id_column = 'rev_page';
+                       $rev_id_column = 'rev_id';
                }
 
                $toSave = [];
+               $idsToClear = [];
                $lastId = 0;
                do {
                        $rows = $dbw->select(
                                $selectTables,
-                               array_merge( $fields, [ $model_column, $format_column, $key ] ),
+                               array_merge(
+                                       $fields,
+                                       [ $model_column, $format_column, $key, $page_id_column, $rev_id_column ]
+                               ),
                                // @todo support populating format if model is already set
                                [
                                        $model_column => null,
@@ -174,9 +204,17 @@ class PopulateContentModel extends Maintenance {
                                if ( $dbModel === null && $dbFormat === null ) {
                                        // Set the defaults
                                        $toSave[$defaultModel][] = $row->{$key};
+                                       $idsToClear[] = [
+                                               'page_id' => $row->{$page_id_column},
+                                               'rev_id' => $row->{$rev_id_column},
+                                       ];
                                } else { // $dbModel === null, $dbFormat set.
                                        if ( $dbFormat === $defaultFormat ) {
                                                $toSave[$defaultModel][] = $row->{$key};
+                                               $idsToClear[] = [
+                                                       'page_id' => $row->{$page_id_column},
+                                                       'rev_id' => $row->{$rev_id_column},
+                                               ];
                                        } else { // non-default format, just update now
                                                $this->output( "Updating model to match format for $table $id of $title... " );
                                                $dbw->update(
@@ -186,6 +224,7 @@ class PopulateContentModel extends Maintenance {
                                                        __METHOD__
                                                );
                                                wfWaitForSlaves();
+                                               $this->clearCache( $row->{$page_id_column}, $row->{$rev_id_column} );
                                                $this->output( "done.\n" );
                                                continue;
                                        }
@@ -200,6 +239,10 @@ class PopulateContentModel extends Maintenance {
                foreach ( $toSave as $model => $ids ) {
                        $this->updateRevisionOrArchiveRows( $dbw, $ids, $model, $table );
                }
+
+               foreach ( $idsToClear as $idPair ) {
+                       $this->clearCache( $idPair['page_id'], $idPair['rev_id'] );
+               }
        }
 }
 
index 31b2101..f6bb253 100644 (file)
@@ -41,8 +41,8 @@ class Protect extends Maintenance {
        }
 
        public function execute() {
-               $userName = $this->getOption( 'u', false );
-               $reason = $this->getOption( 'r', '' );
+               $userName = $this->getOption( 'user', false );
+               $reason = $this->getOption( 'reason', '' );
 
                $cascade = $this->hasOption( 'cascade' );
 
index 615d1fe..3c0fc7e 100644 (file)
@@ -210,7 +210,7 @@ class PurgeChangedFiles extends Maintenance {
        }
 
        protected function purgeFromArchiveTable( LocalRepo $repo, LocalFile $file ) {
-               $dbr = $repo->getSlaveDB();
+               $dbr = $repo->getReplicaDB();
                $res = $dbr->select(
                        'filearchive',
                        [ 'fa_archive_name' ],
index 5d085a8..e00a55d 100644 (file)
@@ -32,6 +32,8 @@ require __DIR__ . '/Maintenance.php';
 class PurgeParserCache extends Maintenance {
        public $lastProgress;
 
+       private $usleep = 0;
+
        function __construct() {
                parent::__construct();
                $this->addDescription( "Remove old objects from the parser cache. " .
@@ -39,36 +41,44 @@ class PurgeParserCache extends Maintenance {
                $this->addOption( 'expiredate', 'Delete objects expiring before this date.', false, true );
                $this->addOption(
                        'age',
-                       'Delete objects created more than this many seconds ago, assuming $wgParserCacheExpireTime ' .
-                               'has been consistent.',
-                       false, true );
+                       'Delete objects created more than this many seconds ago, assuming ' .
+                               '$wgParserCacheExpireTime has remained consistent.',
+                       false,
+                       true );
+               $this->addOption( 'msleep', 'Milliseconds to sleep between purge chunks', false, true );
        }
 
        function execute() {
+               global $wgParserCacheExpireTime;
+
                $inputDate = $this->getOption( 'expiredate' );
                $inputAge = $this->getOption( 'age' );
                if ( $inputDate !== null ) {
                        $date = wfTimestamp( TS_MW, strtotime( $inputDate ) );
                } elseif ( $inputAge !== null ) {
-                       global $wgParserCacheExpireTime;
                        $date = wfTimestamp( TS_MW, time() + $wgParserCacheExpireTime - intval( $inputAge ) );
                } else {
                        $this->error( "Must specify either --expiredate or --age", 1 );
+                       return;
                }
+               $this->usleep = 1e3 * $this->getOption( 'msleep', 0 );
 
                $english = Language::factory( 'en' );
-               $this->output( "Deleting objects expiring before " . $english->timeanddate( $date ) . "\n" );
+               $this->output( "Deleting objects expiring before " .
+                       $english->timeanddate( $date ) . "\n" );
 
                $pc = wfGetParserCacheStorage();
-               $success = $pc->deleteObjectsExpiringBefore( $date, [ $this, 'showProgress' ] );
+               $success = $pc->deleteObjectsExpiringBefore( $date, [ $this, 'showProgressAndWait' ] );
                if ( !$success ) {
                        $this->error( "\nCannot purge this kind of parser cache.", 1 );
                }
-               $this->showProgress( 100 );
+               $this->showProgressAndWait( 100 );
                $this->output( "\nDone\n" );
        }
 
-       function showProgress( $percent ) {
+       public function showProgressAndWait( $percent ) {
+               usleep( $this->usleep ); // avoid lag; T150124
+
                $percentString = sprintf( "%.2f", $percent );
                if ( $percentString === $this->lastProgress ) {
                        return;
index a5e7a2f..f8eedb3 100644 (file)
@@ -34,26 +34,74 @@ class BatchedQueryRunner extends Maintenance {
        public function __construct() {
                parent::__construct();
                $this->addDescription(
-                       "Run a query repeatedly until it affects 0 rows, and wait for replica DBs in between.\n" .
-                               "NOTE: You need to set a LIMIT clause yourself." );
+                       "Run an update query on all rows of a table. " .
+                       "Waits for replicas at appropriate intervals." );
+               $this->addOption( 'table', 'The table name', true, true );
+               $this->addOption( 'set', 'The SET clause', true, true );
+               $this->addOption( 'where', 'The WHERE clause', false, true );
+               $this->addOption( 'key', 'A column name, the values of which are unique', true, true );
+               $this->addOption( 'batch-size', 'The batch size (default 1000)', false, true );
+               $this->addOption( 'db', 'The database name, or omit to use the current wiki.', false, true );
        }
 
        public function execute() {
-               if ( !$this->hasArg() ) {
-                       $this->error( "No query specified. Specify the query as a command line parameter.", true );
+               $table = $this->getOption( 'table' );
+               $key = $this->getOption( 'key' );
+               $set = $this->getOption( 'set' );
+               $where = $this->getOption( 'where', null );
+               $where = $where === null ? [] : [ $where ];
+               $batchSize = $this->getOption( 'batch-size', 1000 );
+
+               $dbName = $this->getOption( 'db', null );
+               if ( $dbName === null ) {
+                       $dbw = $this->getDB( DB_MASTER );
+               } else {
+                       $lbf = MediaWiki\MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+                       $lb = $lbf->getMainLB( $dbName );
+                       $dbw = $lb->getConnection( DB_MASTER, [], $dbName );
                }
 
-               $query = $this->getArg();
+               $selectConds = $where;
+               $prevEnd = false;
+
                $n = 1;
-               $dbw = $this->getDB( DB_MASTER );
                do {
                        $this->output( "Batch $n: " );
                        $n++;
+
+                       // Note that the update conditions do not rely on atomicity of the
+                       // SELECT query in order to guarantee that all rows are updated. The
+                       // results of the SELECT are merely a partitioning hint. Simultaneous
+                       // updates merely result in the wrong number of rows being updated
+                       // in a batch.
+
+                       $res = $dbw->select( $table, $key, $selectConds, __METHOD__,
+                               [ 'ORDER BY' => $key, 'LIMIT' => $batchSize ] );
+                       if ( $res->numRows() ) {
+                               $res->seek( $res->numRows() - 1 );
+                               $row = $res->fetchObject();
+                               $end = $dbw->addQuotes( $row->$key );
+                               $selectConds = array_merge( $where, [ "$key > $end" ] );
+                               $updateConds = array_merge( $where, [ "$key <= $end" ] );
+                       } else {
+                               $updateConds = $where;
+                       }
+                       if ( $prevEnd !== false ) {
+                               $updateConds = array_merge( [ "$key > $prevEnd" ], $updateConds );
+                       }
+
+                       $query = "UPDATE " . $dbw->tableName( $table ) .
+                               " SET " . $set .
+                               " WHERE " . $dbw->makeList( $updateConds, IDatabase::LIST_AND );
+
                        $dbw->query( $query, __METHOD__ );
+
+                       $prevEnd = $end;
+
                        $affected = $dbw->affectedRows();
-                       $this->output( "$affected rows\n" );
+                       $this->output( "$affected rows affected\n" );
                        wfWaitForSlaves();
-               } while ( $affected > 0 );
+               } while ( $res->numRows() );
        }
 
        public function getDbType() {
index bb9f4ea..9045870 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup Maintenance ExternalStorage
  */
 
+use MediaWiki\MediaWikiServices;
+
 if ( !defined( 'MEDIAWIKI' ) ) {
        $optionsWithoutArgs = [ 'fix' ];
        require_once __DIR__ . '/../commandLine.inc';
@@ -470,7 +472,7 @@ class CheckStorage {
                $source = new ImportStreamSource( $file );
                $importer = new WikiImporter(
                        $source,
-                       ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       MediaWikiServices::getInstance()->getMainConfig()
                );
                $importer->setRevisionCallback( [ $this, 'importRevision' ] );
                $importer->doImport();
index a43e0ba..eb717e8 100644 (file)
@@ -26,8 +26,6 @@ if ( PHP_SAPI != 'cli' ) {
        die( "This script can only be run from the command line.\n" );
 }
 
-chdir( dirname( __DIR__ ) );
-
 $CREDITS = 'CREDITS';
 $START_CONTRIBUTORS = '<!-- BEGIN CONTRIBUTOR LIST -->';
 $END_CONTRIBUTORS = '<!-- END CONTRIBUTOR LIST -->';
@@ -38,6 +36,10 @@ $header = [];
 $contributors = [];
 $footer = [];
 
+if ( !file_exists( $CREDITS ) ) {
+       exit( 'No CREDITS file found. Are you running this script in the right directory?' );
+}
+
 $lines = explode( "\n", file_get_contents( $CREDITS ) );
 foreach ( $lines as $line ) {
        if ( $inHeader ) {
index b9baf8c..9906990 100644 (file)
@@ -2,73 +2,22 @@
 
 require_once __DIR__ . '/Maintenance.php';
 
-use Composer\Spdx\SpdxLicenses;
-use JsonSchema\Validator;
-
 class ValidateRegistrationFile extends Maintenance {
        public function __construct() {
                parent::__construct();
                $this->addArg( 'path', 'Path to extension.json/skin.json file.', true );
        }
        public function execute() {
-               if ( !class_exists( Validator::class ) ) {
-                       $this->error( 'The JsonSchema library cannot be found, please install it through composer.', 1 );
-               } elseif ( !class_exists( SpdxLicenses::class ) ) {
-                       $this->error(
-                               'The spdx-licenses library cannot be found, please install it through composer.', 1
-                       );
-               }
-
+               $validator = new ExtensionJsonValidator( function( $msg ) {
+                       $this->error( $msg, 1 );
+               } );
+               $validator->checkDependencies();
                $path = $this->getArg( 0 );
-               $data = json_decode( file_get_contents( $path ) );
-               if ( !is_object( $data ) ) {
-                       $this->error( "$path is not a valid JSON file.", 1 );
-               }
-               if ( !isset( $data->manifest_version ) ) {
-                       $this->output( "Warning: No manifest_version set, assuming 1.\n" );
-                       // For backwards-compatability assume 1
-                       $data->manifest_version = 1;
-               }
-               $version = $data->manifest_version;
-               if ( $version !== ExtensionRegistry::MANIFEST_VERSION ) {
-                       $schemaPath = dirname( __DIR__ ) . "/docs/extension.schema.v$version.json";
-               } else {
-                       $schemaPath = dirname( __DIR__ ) . '/docs/extension.schema.json';
-               }
-
-               if ( $version < ExtensionRegistry::OLDEST_MANIFEST_VERSION
-                       || $version > ExtensionRegistry::MANIFEST_VERSION
-               ) {
-                       $this->error( "Error: $path is using a non-supported schema version, it should use "
-                               . ExtensionRegistry::MANIFEST_VERSION, 1 );
-               } elseif ( $version < ExtensionRegistry::MANIFEST_VERSION ) {
-                       $this->output( "Warning: $path is using a deprecated schema, and should be updated to "
-                               . ExtensionRegistry::MANIFEST_VERSION . "\n" );
-               }
-
-               $licenseError = false;
-               // Check if it's a string, if not, schema validation will display an error
-               if ( isset( $data->{'license-name'} ) && is_string( $data->{'license-name'} ) ) {
-                       $licenses = new SpdxLicenses();
-                       $valid = $licenses->validate( $data->{'license-name'} );
-                       if ( !$valid ) {
-                               $licenseError = '[license-name] Invalid SPDX license identifier, '
-                                       . 'see <https://spdx.org/licenses/>';
-                       }
-               }
-
-               $validator = new Validator;
-               $validator->check( $data, (object)[ '$ref' => 'file://' . $schemaPath ] );
-               if ( $validator->isValid() && !$licenseError ) {
-                       $this->output( "$path validates against the version $version schema!\n" );
-               } else {
-                       foreach ( $validator->getErrors() as $error ) {
-                               $this->output( "[{$error['property']}] {$error['message']}\n" );
-                       }
-                       if ( $licenseError ) {
-                               $this->output( "$licenseError\n" );
-                       }
-                       $this->error( "$path does not validate.", 1 );
+               try {
+                       $validator->validate( $path );
+                       $this->output( "$path validates against the schema!\n" );
+               } catch ( ExtensionJsonValidationError $e ) {
+                       $this->error( $e->getMessage(), 1 );
                }
        }
 }
index 2ce19e5..0a859c0 100644 (file)
@@ -113,6 +113,7 @@ class WrapOldPasswords extends Maintenance {
                        }
 
                        $this->commitTransaction( $dbw, __METHOD__ );
+                       LBFactory::waitForReplication();
 
                        // Clear memcached so old passwords are wiped out
                        foreach ( $updateUsers as $user ) {
index 3b75c3a..99e752c 100644 (file)
@@ -6,13 +6,13 @@
     "postdoc": "grunt copy:jsduck"
   },
   "devDependencies": {
+    "eslint-config-wikimedia": "0.3.0",
     "grunt": "1.0.1",
     "grunt-banana-checker": "0.5.0",
     "grunt-contrib-copy": "1.0.0",
-    "grunt-contrib-jshint": "1.0.0",
     "grunt-contrib-watch": "1.0.0",
-    "grunt-jscs": "2.8.0",
-    "grunt-jsonlint": "1.0.7",
+    "grunt-eslint": "19.0.0",
+    "grunt-jsonlint": "1.1.0",
     "grunt-karma": "2.0.0",
     "grunt-stylelint": "0.6.0",
     "karma": "1.1.0",
index edce2ea..4693b42 100644 (file)
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -31,4 +31,7 @@
        <exclude-pattern type="relative">^extensions/</exclude-pattern>
        <exclude-pattern type="relative">^skins/</exclude-pattern>
        <exclude-pattern>.git</exclude-pattern>
+       <exclude-pattern>AdminSettings.php</exclude-pattern>
+       <exclude-pattern>LocalSettings.php</exclude-pattern>
+       <exclude-pattern>StartProfiler.php</exclude-pattern>
 </ruleset>
index 5c2f12a..a556b60 100644 (file)
@@ -40,7 +40,6 @@ return [
                'group' => 'noscript',
        ],
        'filepage' => [
-               'position' => 'top',
                'class' => 'ResourceLoaderWikiModule',
                'styles' => [ 'MediaWiki:Filepage.css' ],
        ],
@@ -54,9 +53,6 @@ return [
        'user' => [ 'class' => 'ResourceLoaderUserModule' ],
        'user.styles' => [ 'class' => 'ResourceLoaderUserStylesModule' ],
 
-       // Scripts generated based on the current user's preferences
-       'user.cssprefs' => [ 'class' => 'ResourceLoaderUserCSSPrefsModule' ],
-
        // Populate mediawiki.user placeholders with information about the current user
        'user.defaults' => [ 'class' => 'ResourceLoaderUserDefaultsModule' ],
        'user.options' => [ 'class' => 'ResourceLoaderUserOptionsModule' ],
@@ -97,13 +93,11 @@ return [
         * including more than one of them into your skin as this will result in duplicate CSS.
         */
        'mediawiki.skinning.elements' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki.skinning/elements.css' => [ 'media' => 'screen' ],
                ],
        ],
        'mediawiki.skinning.content' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki.skinning/elements.css' => [ 'media' => 'screen' ],
                        'resources/src/mediawiki.skinning/content.css' => [ 'media' => 'screen' ],
@@ -111,7 +105,6 @@ return [
        ],
        // Used in the web installer. Test it after modifying this definition!
        'mediawiki.skinning.interface' => [
-               'position' => 'top',
                'class' => 'ResourceLoaderSkinModule',
                'styles' => [
                        'resources/src/mediawiki.skinning/elements.css' => [ 'media' => 'screen' ],
@@ -121,7 +114,6 @@ return [
        ],
 
        'mediawiki.skinning.content.parsoid' => [
-               'position' => 'top',
                // Style Parsoid HTML+RDFa output consistent with wikitext from PHP parser
                // with the interface.css styles; skinStyles should be used if your
                // skin over-rides common content styling.
@@ -132,7 +124,6 @@ return [
        ],
 
        'mediawiki.skinning.content.externallinks' => [
-               'position' => 'bottom',
                'styles' => [
                        'resources/src/mediawiki.skinning/content.externallinks.css' => [ 'media' => 'screen' ],
                ],
@@ -323,7 +314,6 @@ return [
        'jquery.qunit' => [
                'scripts' => 'resources/lib/qunitjs/qunit.js',
                'styles' => 'resources/lib/qunitjs/qunit.css',
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'jquery.qunit.completenessTest' => [
@@ -341,7 +331,6 @@ return [
                        'message' => 'Please use "mediawiki.storage" instead.',
                ],
                'scripts' => 'resources/lib/jquery/jquery.jStorage.js',
-               'dependencies' => 'json',
        ],
        'jquery.suggestions' => [
                'scripts' => 'resources/src/jquery/jquery.suggestions.js',
@@ -395,7 +384,6 @@ return [
                'group' => 'jquery.ui',
        ],
        'jquery.ui.core.styles' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/lib/jquery.ui/themes/smoothness/jquery.ui.core.css',
@@ -746,10 +734,10 @@ return [
 
        /* json2 */
 
+       // Deprecated since MediaWiki 1.29.0
        'json' => [
-               'scripts' => 'resources/lib/json2/json2.js',
+               'deprecated' => 'Use of the "json" MediaWiki module is deprecated since MediaWiki 1.29.0',
                'targets' => [ 'desktop', 'mobile' ],
-               'skipFunction' => 'resources/src/json-skip.js',
        ],
 
        /* Moment.js */
@@ -869,7 +857,6 @@ return [
        'mediawiki.apihelp' => [
                'styles' => 'resources/src/mediawiki/mediawiki.apihelp.css',
                'targets' => [ 'desktop' ],
-               'position' => 'top',
        ],
        'mediawiki.template' => [
                'scripts' => 'resources/src/mediawiki/mediawiki.template.js',
@@ -891,7 +878,6 @@ return [
        'mediawiki.apipretty' => [
                'styles' => 'resources/src/mediawiki/mediawiki.apipretty.css',
                'targets' => [ 'desktop', 'mobile' ],
-               'position' => 'top',
        ],
        'mediawiki.api' => [
                'scripts' => 'resources/src/mediawiki/api.js',
@@ -936,7 +922,6 @@ return [
                        'dom-level2-shim',
                        'mediawiki.api',
                        'mediawiki.api.edit',
-                       'json',
                ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
@@ -967,7 +952,6 @@ return [
                ],
        ],
        'mediawiki.content.json' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki/mediawiki.content.json.less',
        ],
        'mediawiki.confirmCloseWindow' => [
@@ -986,12 +970,8 @@ return [
                'dependencies' => [
                        'jquery.footHovzer',
                ],
-               // Uses a custom mw.config variable that is set in debughtml,
-               // must be loaded on the bottom
-               'position' => 'bottom',
        ],
        'mediawiki.diff.styles' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki/mediawiki.diff.styles.css',
                        'resources/src/mediawiki/mediawiki.diff.styles.print.css' => [
@@ -1036,7 +1016,6 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.feedlink' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki/mediawiki.feedlink.css',
        ],
        'mediawiki.filewarning' => [
@@ -1061,7 +1040,6 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.helplink' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki/mediawiki.helplink.less',
                ],
@@ -1111,12 +1089,10 @@ return [
        ],
        'mediawiki.htmlform.styles' => [
                'styles' => 'resources/src/mediawiki/htmlform/styles.css',
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.htmlform.ooui.styles' => [
                'styles' => 'resources/src/mediawiki/htmlform/ooui.styles.css',
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.icon' => [
@@ -1128,7 +1104,6 @@ return [
                'dependencies' => [
                        'jquery.byteLength',
                        'mediawiki.RegExp',
-                       'json',
                ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
@@ -1179,7 +1154,6 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.notification.convertmessagebox.styles' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki/mediawiki.notification.convertmessagebox.styles.less',
                ],
@@ -1191,7 +1165,6 @@ return [
        ],
        'mediawiki.pager.tablePager' => [
                'styles' => 'resources/src/mediawiki/mediawiki.pager.tablePager.less',
-               'position' => 'top',
        ],
        'mediawiki.searchSuggest' => [
                'scripts' => 'resources/src/mediawiki/mediawiki.searchSuggest.js',
@@ -1209,7 +1182,6 @@ return [
                ],
        ],
        'mediawiki.sectionAnchor' => [
-               'position' => 'top',
                // Back-compat to hide it on cached pages (T18691; Ie9e334e973; 2015-03-17)
                'styles' => 'resources/src/mediawiki/mediawiki.sectionAnchor.css',
                'targets' => [ 'desktop', 'mobile' ],
@@ -1219,7 +1191,10 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.Title' => [
-               'scripts' => 'resources/src/mediawiki/mediawiki.Title.js',
+               'scripts' => [
+                       'resources/src/mediawiki/mediawiki.Title.js',
+                       'resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js',
+               ],
                'dependencies' => [
                        'jquery.byteLength',
                        'mediawiki.util',
@@ -1406,6 +1381,11 @@ return [
                'dependencies' => 'mediawiki.util',
                'targets' => [ 'desktop', 'mobile' ],
        ],
+       'mediawiki.user.blockcookie' => [
+               'scripts' => 'resources/src/mediawiki/mediawiki.user.blockcookie.js',
+               'dependencies' => [ 'mediawiki.cookie', 'mediawiki.storage' ],
+               'targets' => [ 'desktop', 'mobile' ],
+       ],
        'mediawiki.user' => [
                'scripts' => 'resources/src/mediawiki/mediawiki.user.js',
                'dependencies' => [
@@ -1435,7 +1415,6 @@ return [
        ],
        'mediawiki.viewport' => [
                'scripts' => 'resources/src/mediawiki/mediawiki.viewport.js',
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.checkboxtoggle' => [
@@ -1454,7 +1433,6 @@ return [
                'scripts' => 'resources/src/mediawiki.toolbar/toolbar.js',
                'styles' => 'resources/src/mediawiki.toolbar/toolbar.less',
                'dependencies' => 'jquery.textSelection',
-               'position' => 'top',
        ],
        'mediawiki.experiments' => [
                'scripts' => 'resources/src/mediawiki/mediawiki.experiments.js',
@@ -1475,10 +1453,8 @@ return [
                        'jquery.byteLimit',
                        'mediawiki.api',
                ],
-               'position' => 'top',
        ],
        'mediawiki.action.edit.styles' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.styles.css',
        ],
        'mediawiki.action.edit.collapsibleFooter' => [
@@ -1521,12 +1497,10 @@ return [
                'styles' => 'resources/src/mediawiki.action/mediawiki.action.history.css',
        ],
        'mediawiki.action.history.styles' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.action/mediawiki.action.history.styles.css',
        ],
        // using this module is deprecated, for diff styles use mediawiki.diff.styles instead
        'mediawiki.action.history.diff' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki/mediawiki.diff.styles.css',
                        'resources/src/mediawiki/mediawiki.diff.styles.print.css' => [
@@ -1552,7 +1526,6 @@ return [
                ],
        ],
        'mediawiki.action.view.categoryPage.styles' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.categoryPage.less',
                'targets' => [ 'desktop', 'mobile' ]
        ],
@@ -1575,11 +1548,9 @@ return [
        'mediawiki.action.view.redirect' => [
                'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.redirect.js',
                'dependencies' => 'jquery.client',
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.action.view.redirectPage' => [
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
                'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css',
        ],
@@ -1606,7 +1577,6 @@ return [
                                [ 'media' => 'print' ],
                        'resources/src/mediawiki.action/mediawiki.action.view.filepage.css',
                ],
-               'position' => 'top',
        ],
 
        /* MediaWiki Language */
@@ -1712,12 +1682,10 @@ return [
                        'resources/src/mediawiki/page/gallery.print.css' => [ 'media' => 'print' ],
                        'resources/src/mediawiki/page/gallery.css',
                ],
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.page.gallery.slideshow' => [
                'scripts' => 'resources/src/mediawiki/page/gallery-slideshow.js',
-               'position' => 'top',
                'dependencies' => [
                        'mediawiki.api',
                        'mediawiki.Title',
@@ -1744,7 +1712,6 @@ return [
        'mediawiki.page.startup' => [
                'scripts' => 'resources/src/mediawiki/page/startup.js',
                'dependencies' => 'mediawiki.util',
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.page.patrol.ajax' => [
@@ -1807,7 +1774,6 @@ return [
        /* MediaWiki Special pages */
 
        'mediawiki.special' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.css',
                'targets' => [ 'desktop', 'mobile' ],
        ],
@@ -1867,6 +1833,9 @@ return [
                        'apisandbox-continue',
                        'apisandbox-continue-clear',
                        'apisandbox-continue-help',
+                       'apisandbox-param-limit',
+                       'apisandbox-multivalue-all-namespaces',
+                       'apisandbox-multivalue-all-values',
                        'api-format-prettyprint-status',
                        'blanknamespace',
                ],
@@ -1877,11 +1846,9 @@ return [
                'dependencies' => 'mediawiki.util',
        ],
        'mediawiki.special.changeslist' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.css',
        ],
        'mediawiki.special.changeslist.legend' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css',
        ],
        'mediawiki.special.changeslist.legend.js' => [
@@ -1892,15 +1859,12 @@ return [
                ],
        ],
        'mediawiki.special.changeslist.enhanced' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css',
        ],
        'mediawiki.special.changeslist.visitedstatus' => [
-               'position' => 'top',
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.visitedstatus.js',
        ],
        'mediawiki.special.comparepages.styles' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less',
        ],
        'mediawiki.special.edittags' => [
@@ -1915,7 +1879,6 @@ return [
        ],
        'mediawiki.special.edittags.styles' => [
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.edittags.css',
-               'position' => 'top',
        ],
        'mediawiki.special.import' => [
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.import.js',
@@ -1929,7 +1892,6 @@ return [
        ],
        'mediawiki.special.movePage.styles' => [
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.movePage.css',
-               'position' => 'top',
        ],
        'mediawiki.special.pageLanguage' => [
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.pageLanguage.js',
@@ -1938,12 +1900,10 @@ return [
                ],
        ],
        'mediawiki.special.pagesWithProp' => [
-               'position' => 'top',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css',
        ],
        'mediawiki.special.preferences' => [
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.preferences.js',
-               'position' => 'top',
                'messages' => [
                        'prefs-tabs-navigation-hint',
                        'prefswarning-warning',
@@ -1964,14 +1924,11 @@ return [
        ],
        'mediawiki.special.preferences.styles' => [
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.styles.css',
-               'position' => 'top',
        ],
        'mediawiki.special.recentchanges' => [
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.recentchanges.js',
-               'position' => 'top',
        ],
        'mediawiki.special.search' => [
-               'position' => 'top',
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.js',
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.css',
                'dependencies' => 'mediawiki.widgets.SearchInputWidget',
@@ -2023,16 +1980,13 @@ return [
                'styles' => [
                        'resources/src/mediawiki.special/mediawiki.special.userlogin.common.css',
                ],
-               'position' => 'top',
        ],
        'mediawiki.special.userlogin.signup.styles' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css',
                ],
        ],
        'mediawiki.special.userlogin.login.styles' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki.special/mediawiki.special.userlogin.login.css',
                ],
@@ -2090,7 +2044,6 @@ return [
        /* MediaWiki Legacy */
 
        'mediawiki.legacy.commonPrint' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki.legacy/commonPrint.css' => [ 'media' => 'print' ]
                ],
@@ -2102,13 +2055,11 @@ return [
        ],
        // Used in the web installer. Test it after modifying this definition!
        'mediawiki.legacy.shared' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki.legacy/shared.css' => [ 'media' => 'screen' ]
                ],
        ],
        'mediawiki.legacy.oldshared' => [
-               'position' => 'top',
                'styles' => [
                        'resources/src/mediawiki.legacy/oldshared.css' => [ 'media' => 'screen' ]
                ],
@@ -2116,14 +2067,12 @@ return [
        'mediawiki.legacy.wikibits' => [
                'scripts' => 'resources/src/mediawiki.legacy/wikibits.js',
                'dependencies' => 'mediawiki.util',
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
 
        /* MediaWiki UI */
 
        'mediawiki.ui' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/src/mediawiki.ui/default.less',
@@ -2132,7 +2081,6 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.ui.checkbox' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/src/mediawiki.ui/components/checkbox.less',
@@ -2141,7 +2089,6 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.ui.radio' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/src/mediawiki.ui/components/radio.less',
@@ -2151,7 +2098,6 @@ return [
        ],
        // Lightweight module for anchor styles
        'mediawiki.ui.anchor' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/src/mediawiki.ui/components/anchors.less',
@@ -2161,7 +2107,6 @@ return [
        ],
        // Lightweight module for button styles
        'mediawiki.ui.button' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/src/mediawiki.ui/components/buttons.less',
@@ -2170,7 +2115,6 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.ui.input' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/src/mediawiki.ui/components/inputs.less',
@@ -2179,7 +2123,6 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.ui.icon' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/src/mediawiki.ui/components/icons.less',
@@ -2189,7 +2132,6 @@ return [
        ],
        // Lightweight module for text styles
        'mediawiki.ui.text' => [
-               'position' => 'top',
                'skinStyles' => [
                        'default' => [
                                'resources/src/mediawiki.ui/components/text.less',
@@ -2240,7 +2182,6 @@ return [
                                'resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.base.css',
                        ],
                ],
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.widgets.DateInputWidget' => [
@@ -2341,6 +2282,33 @@ return [
                ],
                'messages' => [
                        'red-link-title',
+                       'mw-widgets-categoryselector-add-category-placeholder'
+               ],
+               'targets' => [ 'desktop', 'mobile' ],
+       ],
+       'mediawiki.widgets.MediaSearch' => [
+               'scripts' => [
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js',
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js',
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js',
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js',
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js',
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js',
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js',
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js',
+               ],
+               'styles' => [
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css',
+                       'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css',
+               ],
+               'dependencies' => [
+                       'oojs-ui-widgets',
+                       'mediawiki.ForeignApi',
+                       'mediawiki.Title',
+               ],
+               'messages' => [
+                       'mw-widgets-mediasearch-noresults',
+                       'mw-widgets-mediasearch-input-placeholder',
                ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
@@ -2369,7 +2337,6 @@ return [
                                'resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css',
                        ],
                ],
-               'position' => 'top',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.widgets.StashedFileWidget' => [
@@ -2412,7 +2379,6 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
                'dependencies' => [
                        'es5-shim',
-                       'json',
                ],
        ],
 
diff --git a/resources/lib/json2/json2.js b/resources/lib/json2/json2.js
deleted file mode 100644 (file)
index 5838457..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
-    json2.js
-    2015-05-03
-
-    Public Domain.
-
-    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
-
-    See http://www.JSON.org/js.html
-
-
-    This code should be minified before deployment.
-    See http://javascript.crockford.com/jsmin.html
-
-    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
-    NOT CONTROL.
-
-
-    This file creates a global JSON object containing two methods: stringify
-    and parse. This file is provides the ES5 JSON capability to ES3 systems.
-    If a project might run on IE8 or earlier, then this file should be included.
-    This file does nothing on ES5 systems.
-
-        JSON.stringify(value, replacer, space)
-            value       any JavaScript value, usually an object or array.
-
-            replacer    an optional parameter that determines how object
-                        values are stringified for objects. It can be a
-                        function or an array of strings.
-
-            space       an optional parameter that specifies the indentation
-                        of nested structures. If it is omitted, the text will
-                        be packed without extra whitespace. If it is a number,
-                        it will specify the number of spaces to indent at each
-                        level. If it is a string (such as '\t' or '&nbsp;'),
-                        it contains the characters used to indent at each level.
-
-            This method produces a JSON text from a JavaScript value.
-
-            When an object value is found, if the object contains a toJSON
-            method, its toJSON method will be called and the result will be
-            stringified. A toJSON method does not serialize: it returns the
-            value represented by the name/value pair that should be serialized,
-            or undefined if nothing should be serialized. The toJSON method
-            will be passed the key associated with the value, and this will be
-            bound to the value
-
-            For example, this would serialize Dates as ISO strings.
-
-                Date.prototype.toJSON = function (key) {
-                    function f(n) {
-                        // Format integers to have at least two digits.
-                        return n < 10 
-                            ? '0' + n 
-                            : n;
-                    }
-
-                    return this.getUTCFullYear()   + '-' +
-                         f(this.getUTCMonth() + 1) + '-' +
-                         f(this.getUTCDate())      + 'T' +
-                         f(this.getUTCHours())     + ':' +
-                         f(this.getUTCMinutes())   + ':' +
-                         f(this.getUTCSeconds())   + 'Z';
-                };
-
-            You can provide an optional replacer method. It will be passed the
-            key and value of each member, with this bound to the containing
-            object. The value that is returned from your method will be
-            serialized. If your method returns undefined, then the member will
-            be excluded from the serialization.
-
-            If the replacer parameter is an array of strings, then it will be
-            used to select the members to be serialized. It filters the results
-            such that only members with keys listed in the replacer array are
-            stringified.
-
-            Values that do not have JSON representations, such as undefined or
-            functions, will not be serialized. Such values in objects will be
-            dropped; in arrays they will be replaced with null. You can use
-            a replacer function to replace those with JSON values.
-            JSON.stringify(undefined) returns undefined.
-
-            The optional space parameter produces a stringification of the
-            value that is filled with line breaks and indentation to make it
-            easier to read.
-
-            If the space parameter is a non-empty string, then that string will
-            be used for indentation. If the space parameter is a number, then
-            the indentation will be that many spaces.
-
-            Example:
-
-            text = JSON.stringify(['e', {pluribus: 'unum'}]);
-            // text is '["e",{"pluribus":"unum"}]'
-
-
-            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
-            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
-
-            text = JSON.stringify([new Date()], function (key, value) {
-                return this[key] instanceof Date 
-                    ? 'Date(' + this[key] + ')' 
-                    : value;
-            });
-            // text is '["Date(---current time---)"]'
-
-
-        JSON.parse(text, reviver)
-            This method parses a JSON text to produce an object or array.
-            It can throw a SyntaxError exception.
-
-            The optional reviver parameter is a function that can filter and
-            transform the results. It receives each of the keys and values,
-            and its return value is used instead of the original value.
-            If it returns what it received, then the structure is not modified.
-            If it returns undefined then the member is deleted.
-
-            Example:
-
-            // Parse the text. Values that look like ISO date strings will
-            // be converted to Date objects.
-
-            myData = JSON.parse(text, function (key, value) {
-                var a;
-                if (typeof value === 'string') {
-                    a =
-/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
-                    if (a) {
-                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
-                            +a[5], +a[6]));
-                    }
-                }
-                return value;
-            });
-
-            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
-                var d;
-                if (typeof value === 'string' &&
-                        value.slice(0, 5) === 'Date(' &&
-                        value.slice(-1) === ')') {
-                    d = new Date(value.slice(5, -1));
-                    if (d) {
-                        return d;
-                    }
-                }
-                return value;
-            });
-
-
-    This is a reference implementation. You are free to copy, modify, or
-    redistribute.
-*/
-
-/*jslint 
-    eval, for, this 
-*/
-
-/*property
-    JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
-    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
-    lastIndex, length, parse, prototype, push, replace, slice, stringify,
-    test, toJSON, toString, valueOf
-*/
-
-
-// Create a JSON object only if one does not already exist. We create the
-// methods in a closure to avoid creating global variables.
-
-if (typeof JSON !== 'object') {
-    JSON = {};
-}
-
-(function () {
-    'use strict';
-    
-    var rx_one = /^[\],:{}\s]*$/,
-        rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
-        rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
-        rx_four = /(?:^|:|,)(?:\s*\[)+/g,
-        rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-        rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
-
-    function f(n) {
-        // Format integers to have at least two digits.
-        return n < 10 
-            ? '0' + n 
-            : n;
-    }
-    
-    function this_value() {
-        return this.valueOf();
-    }
-
-    if (typeof Date.prototype.toJSON !== 'function') {
-
-        Date.prototype.toJSON = function () {
-
-            return isFinite(this.valueOf())
-                ? this.getUTCFullYear() + '-' +
-                        f(this.getUTCMonth() + 1) + '-' +
-                        f(this.getUTCDate()) + 'T' +
-                        f(this.getUTCHours()) + ':' +
-                        f(this.getUTCMinutes()) + ':' +
-                        f(this.getUTCSeconds()) + 'Z'
-                : null;
-        };
-
-        Boolean.prototype.toJSON = this_value;
-        Number.prototype.toJSON = this_value;
-        String.prototype.toJSON = this_value;
-    }
-
-    var gap,
-        indent,
-        meta,
-        rep;
-
-
-    function quote(string) {
-
-// If the string contains no control characters, no quote characters, and no
-// backslash characters, then we can safely slap some quotes around it.
-// Otherwise we must also replace the offending characters with safe escape
-// sequences.
-
-        rx_escapable.lastIndex = 0;
-        return rx_escapable.test(string) 
-            ? '"' + string.replace(rx_escapable, function (a) {
-                var c = meta[a];
-                return typeof c === 'string'
-                    ? c
-                    : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-            }) + '"' 
-            : '"' + string + '"';
-    }
-
-
-    function str(key, holder) {
-
-// Produce a string from holder[key].
-
-        var i,          // The loop counter.
-            k,          // The member key.
-            v,          // The member value.
-            length,
-            mind = gap,
-            partial,
-            value = holder[key];
-
-// If the value has a toJSON method, call it to obtain a replacement value.
-
-        if (value && typeof value === 'object' &&
-                typeof value.toJSON === 'function') {
-            value = value.toJSON(key);
-        }
-
-// If we were called with a replacer function, then call the replacer to
-// obtain a replacement value.
-
-        if (typeof rep === 'function') {
-            value = rep.call(holder, key, value);
-        }
-
-// What happens next depends on the value's type.
-
-        switch (typeof value) {
-        case 'string':
-            return quote(value);
-
-        case 'number':
-
-// JSON numbers must be finite. Encode non-finite numbers as null.
-
-            return isFinite(value) 
-                ? String(value) 
-                : 'null';
-
-        case 'boolean':
-        case 'null':
-
-// If the value is a boolean or null, convert it to a string. Note:
-// typeof null does not produce 'null'. The case is included here in
-// the remote chance that this gets fixed someday.
-
-            return String(value);
-
-// If the type is 'object', we might be dealing with an object or an array or
-// null.
-
-        case 'object':
-
-// Due to a specification blunder in ECMAScript, typeof null is 'object',
-// so watch out for that case.
-
-            if (!value) {
-                return 'null';
-            }
-
-// Make an array to hold the partial results of stringifying this object value.
-
-            gap += indent;
-            partial = [];
-
-// Is the value an array?
-
-            if (Object.prototype.toString.apply(value) === '[object Array]') {
-
-// The value is an array. Stringify every element. Use null as a placeholder
-// for non-JSON values.
-
-                length = value.length;
-                for (i = 0; i < length; i += 1) {
-                    partial[i] = str(i, value) || 'null';
-                }
-
-// Join all of the elements together, separated with commas, and wrap them in
-// brackets.
-
-                v = partial.length === 0
-                    ? '[]'
-                    : gap
-                        ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
-                        : '[' + partial.join(',') + ']';
-                gap = mind;
-                return v;
-            }
-
-// If the replacer is an array, use it to select the members to be stringified.
-
-            if (rep && typeof rep === 'object') {
-                length = rep.length;
-                for (i = 0; i < length; i += 1) {
-                    if (typeof rep[i] === 'string') {
-                        k = rep[i];
-                        v = str(k, value);
-                        if (v) {
-                            partial.push(quote(k) + (
-                                gap 
-                                    ? ': ' 
-                                    : ':'
-                            ) + v);
-                        }
-                    }
-                }
-            } else {
-
-// Otherwise, iterate through all of the keys in the object.
-
-                for (k in value) {
-                    if (Object.prototype.hasOwnProperty.call(value, k)) {
-                        v = str(k, value);
-                        if (v) {
-                            partial.push(quote(k) + (
-                                gap 
-                                    ? ': ' 
-                                    : ':'
-                            ) + v);
-                        }
-                    }
-                }
-            }
-
-// Join all of the member texts together, separated with commas,
-// and wrap them in braces.
-
-            v = partial.length === 0
-                ? '{}'
-                : gap
-                    ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
-                    : '{' + partial.join(',') + '}';
-            gap = mind;
-            return v;
-        }
-    }
-
-// If the JSON object does not yet have a stringify method, give it one.
-
-    if (typeof JSON.stringify !== 'function') {
-        meta = {    // table of character substitutions
-            '\b': '\\b',
-            '\t': '\\t',
-            '\n': '\\n',
-            '\f': '\\f',
-            '\r': '\\r',
-            '"': '\\"',
-            '\\': '\\\\'
-        };
-        JSON.stringify = function (value, replacer, space) {
-
-// The stringify method takes a value and an optional replacer, and an optional
-// space parameter, and returns a JSON text. The replacer can be a function
-// that can replace values, or an array of strings that will select the keys.
-// A default replacer method can be provided. Use of the space parameter can
-// produce text that is more easily readable.
-
-            var i;
-            gap = '';
-            indent = '';
-
-// If the space parameter is a number, make an indent string containing that
-// many spaces.
-
-            if (typeof space === 'number') {
-                for (i = 0; i < space; i += 1) {
-                    indent += ' ';
-                }
-
-// If the space parameter is a string, it will be used as the indent string.
-
-            } else if (typeof space === 'string') {
-                indent = space;
-            }
-
-// If there is a replacer, it must be a function or an array.
-// Otherwise, throw an error.
-
-            rep = replacer;
-            if (replacer && typeof replacer !== 'function' &&
-                    (typeof replacer !== 'object' ||
-                    typeof replacer.length !== 'number')) {
-                throw new Error('JSON.stringify');
-            }
-
-// Make a fake root object containing our value under the key of ''.
-// Return the result of stringifying the value.
-
-            return str('', {'': value});
-        };
-    }
-
-
-// If the JSON object does not yet have a parse method, give it one.
-
-    if (typeof JSON.parse !== 'function') {
-        JSON.parse = function (text, reviver) {
-
-// The parse method takes a text and an optional reviver function, and returns
-// a JavaScript value if the text is a valid JSON text.
-
-            var j;
-
-            function walk(holder, key) {
-
-// The walk method is used to recursively walk the resulting structure so
-// that modifications can be made.
-
-                var k, v, value = holder[key];
-                if (value && typeof value === 'object') {
-                    for (k in value) {
-                        if (Object.prototype.hasOwnProperty.call(value, k)) {
-                            v = walk(value, k);
-                            if (v !== undefined) {
-                                value[k] = v;
-                            } else {
-                                delete value[k];
-                            }
-                        }
-                    }
-                }
-                return reviver.call(holder, key, value);
-            }
-
-
-// Parsing happens in four stages. In the first stage, we replace certain
-// Unicode characters with escape sequences. JavaScript handles many characters
-// incorrectly, either silently deleting them, or treating them as line endings.
-
-            text = String(text);
-            rx_dangerous.lastIndex = 0;
-            if (rx_dangerous.test(text)) {
-                text = text.replace(rx_dangerous, function (a) {
-                    return '\\u' +
-                            ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-                });
-            }
-
-// In the second stage, we run the text against regular expressions that look
-// for non-JSON patterns. We are especially concerned with '()' and 'new'
-// because they can cause invocation, and '=' because it can cause mutation.
-// But just to be safe, we want to reject all unexpected forms.
-
-// We split the second stage into 4 regexp operations in order to work around
-// crippling inefficiencies in IE's and Safari's regexp engines. First we
-// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
-// replace all simple value tokens with ']' characters. Third, we delete all
-// open brackets that follow a colon or comma or that begin the text. Finally,
-// we look to see that the remaining characters are only whitespace or ']' or
-// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
-
-            if (
-                rx_one.test(
-                    text
-                        .replace(rx_two, '@')
-                        .replace(rx_three, ']')
-                        .replace(rx_four, '')
-                )
-            ) {
-
-// In the third stage we use the eval function to compile the text into a
-// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
-// in JavaScript: it can begin a block or an object literal. We wrap the text
-// in parens to eliminate the ambiguity.
-
-                j = eval('(' + text + ')');
-
-// In the optional fourth stage, we recursively walk the new structure, passing
-// each name/value pair to a reviver function for possible transformation.
-
-                return typeof reviver === 'function'
-                    ? walk({'': j}, '')
-                    : j;
-            }
-
-// If the text is not JSON parseable, then a SyntaxError is thrown.
-
-            throw new SyntaxError('JSON.parse');
-        };
-    }
-}());
index 8538417..98835d5 100644 (file)
@@ -24,6 +24,7 @@
        "ooui-dialog-process-dismiss": "Απόρριψη",
        "ooui-dialog-process-retry": "Δοκιμάστε ξανά",
        "ooui-dialog-process-continue": "Συνέχεια",
+       "ooui-selectfile-button-select": "Επιλέξτε ένα αρχείο",
        "ooui-selectfile-not-supported": "Επιλογή αρχείου δεν υποστηρίζεται",
        "ooui-selectfile-placeholder": "Κανένα αρχείο δεν είναι επιλεγμένο",
        "ooui-selectfile-dragdrop-placeholder": "Σύρετε το αρχείο εδώ"
index 542447d..1acedf2 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:37Z
+ * Date: 2016-12-06T23:32:53Z
  */
 ( function ( OO ) {
 
index bcc3778..72df673 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:42Z
+ * Date: 2016-12-06T23:32:57Z
  */
 .oo-ui-element-hidden {
   display: none !important;
@@ -832,10 +832,14 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
   display: none;
 }
 .oo-ui-textInputWidget.oo-ui-iconElement > .oo-ui-iconElement-icon,
-.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator {
+.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
   display: block;
   position: absolute;
   top: 0;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator {
   height: 100%;
   -webkit-touch-callout: none;
   -webkit-user-select: none;
@@ -843,21 +847,24 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
       -ms-user-select: none;
           user-select: none;
 }
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget-labelPosition-before > .oo-ui-labelElement-label {
+  left: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget-labelPosition-after > .oo-ui-labelElement-label {
+  right: 0;
+}
 .oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-iconElement-icon,
-.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-labelElement-label {
   cursor: text;
 }
 .oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-textInputWidget-type-search > .oo-ui-indicatorElement-indicator {
   cursor: pointer;
 }
 .oo-ui-textInputWidget.oo-ui-widget-disabled input,
-.oo-ui-textInputWidget.oo-ui-widget-disabled textarea {
-  -webkit-touch-callout: none;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-}
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
 .oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
   -webkit-touch-callout: none;
   -webkit-user-select: none;
@@ -865,21 +872,6 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
       -ms-user-select: none;
           user-select: none;
 }
-.oo-ui-textInputWidget.oo-ui-labelElement > .oo-ui-labelElement-label {
-  display: block;
-}
-.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
-.oo-ui-textInputWidget-labelPosition-before > .oo-ui-labelElement-label {
-  left: 0;
-}
-.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
-.oo-ui-textInputWidget-labelPosition-after > .oo-ui-labelElement-label {
-  right: 0;
-}
-.oo-ui-textInputWidget > .oo-ui-labelElement-label {
-  position: absolute;
-  top: 0;
-}
 .oo-ui-textInputWidget input,
 .oo-ui-textInputWidget textarea {
   padding: 0.5em;
index e7c2ee0..bab34b8 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:42Z
+ * Date: 2016-12-06T23:32:57Z
  */
 .oo-ui-element-hidden {
   display: none !important;
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > input.oo-ui-buttonElement-button,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button:active {
   color: #000;
+  box-shadow: none;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
   color: #36c;
   color: #447ff5;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:active:focus > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
   color: #2a4b8d;
   box-shadow: none;
   color: #447ff5;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:active:focus > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
   color: #2a4b8d;
   box-shadow: none;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
-  color: #c33;
+  color: #d33;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label {
-  color: #e53939;
+  color: #ff4242;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active:focus > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
-  color: #873636;
+  color: #b32424;
   box-shadow: none;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled[class*='oo-ui-flaggedElement'] > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
   box-shadow: inset 0 0 0 1px #36c;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active:focus,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
-  background-color: #d9d9d9;
+  background-color: #c8ccd1;
   color: #000;
   border-color: #72777d;
+  box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
   background-color: #2a4b8d;
   box-shadow: inset 0 0 0 1px #36c;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
-  color: #c33;
+  color: #d33;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
   background-color: #fff;
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active:focus,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
-  background-color: #fbf4f4;
-  color: #873636;
-  border-color: #873636;
+  background-color: #ffffff;
+  color: #b32424;
+  border-color: #b32424;
   box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
-  border-color: #c33;
-  box-shadow: inset 0 0 0 1px #c33;
+  border-color: #d33;
+  box-shadow: inset 0 0 0 1px #d33;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
   color: #fff;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
   color: #fff;
-  background-color: #c33;
-  border-color: #c33;
+  background-color: #d33;
+  border-color: #d33;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
-  background-color: #e53939;
-  border-color: #e53939;
+  background-color: #ff4242;
+  border-color: #ff4242;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active:focus,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
   color: #fff;
-  background-color: #873636;
-  border-color: #873636;
+  background-color: #b32424;
+  border-color: #b32424;
   box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
-  border-color: #c33;
-  box-shadow: inset 0 0 0 1px #c33, inset 0 0 0 2px #fff;
+  border-color: #d33;
+  box-shadow: inset 0 0 0 1px #d33, inset 0 0 0 2px #fff;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
 }
 .oo-ui-fieldLayout {
   display: block;
-  margin-bottom: 1em;
+  margin-top: 1.640625em;
 }
 .oo-ui-fieldLayout:before,
 .oo-ui-fieldLayout:after {
   padding: 0.5em 0.75em;
   line-height: 1.5;
 }
-.oo-ui-fieldLayout:last-child {
-  margin-bottom: 0;
+.oo-ui-fieldLayout.oo-ui-labelElement,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
+  margin-top: 1.171875em;
 }
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label,
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
-  padding-top: 0.5em;
-  margin-right: 5%;
-  width: 35%;
+.oo-ui-fieldLayout:first-child,
+.oo-ui-fieldLayout.oo-ui-labelElement:first-child,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline:first-child {
+  margin-top: 0;
 }
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field,
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
-  width: 60%;
+.oo-ui-fieldLayout.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+  padding-bottom: 0.3125em;
 }
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
-  margin-bottom: 1.25em;
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+  padding: 0.3125em 0.46875em;
 }
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
-  padding: 0.25em 0.25em 0.25em 0.5em;
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+  width: 35%;
+  margin-right: 5%;
+  padding-top: 0.3125em;
 }
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
-  padding-top: 0.25em;
-  padding-bottom: 0.5em;
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+  width: 60%;
+}
+.oo-ui-fieldLayout-disabled > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+  color: #72777d;
 }
 .oo-ui-fieldLayout > .oo-ui-popupButtonWidget {
   margin-right: 0;
 .oo-ui-fieldLayout > .oo-ui-popupButtonWidget:last-child {
   margin-right: 0;
 }
-.oo-ui-fieldLayout-disabled > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
-  color: #72777d;
-}
 .oo-ui-fieldLayout-messages {
   list-style: none none;
   margin: 0.25em 0 0 0.25em;
 }
 .oo-ui-fieldLayout-messages .oo-ui-iconWidget {
   display: table-cell;
-  border-right: 0.5em solid transparent;
 }
 .oo-ui-fieldLayout-messages .oo-ui-labelWidget {
   display: table-cell;
-  padding: 0.1em 0;
+  padding: 0.1em 0 0.1em 0.3125em;
   line-height: 1.5;
   vertical-align: middle;
 }
@@ -552,7 +559,7 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
   margin-top: 2em;
 }
 .oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-labelElement-label {
-  margin-bottom: 0.5em;
+  margin-bottom: 0.56818em;
   font-size: 1.1em;
   font-weight: bold;
 }
@@ -687,7 +694,7 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
   background-color: transparent;
 }
 .oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
-  padding: 0.25em 0.25em 0.25em 0.5em;
+  padding: 0.25em 0.25em 0.25em 0.46875em;
 }
 .oo-ui-radioOptionWidget .oo-ui-radioInputWidget {
   margin-right: 0;
@@ -881,7 +888,7 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 }
 .oo-ui-checkboxInputWidget {
   position: relative;
-  line-height: 1.6em;
+  line-height: 1.5625em;
   white-space: nowrap;
 }
 .oo-ui-checkboxInputWidget * {
@@ -891,8 +898,8 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 .oo-ui-checkboxInputWidget [type='checkbox'] {
   position: relative;
   max-width: none;
-  width: 1.6em;
-  height: 1.6em;
+  width: 1.5625em;
+  height: 1.5625em;
   margin: 0;
   opacity: 0;
   z-index: 1;
@@ -908,8 +915,8 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
           box-sizing: border-box;
   position: absolute;
   left: 0;
-  width: 1.6em;
-  height: 1.6em;
+  width: 1.5625em;
+  height: 1.5625em;
   border: 1px solid #72777d;
   border-radius: 2px;
 }
@@ -1031,7 +1038,7 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 }
 .oo-ui-radioInputWidget {
   position: relative;
-  line-height: 1.6em;
+  line-height: 1.5625em;
   white-space: nowrap;
 }
 .oo-ui-radioInputWidget * {
@@ -1041,8 +1048,8 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 .oo-ui-radioInputWidget [type='radio'] {
   position: relative;
   max-width: none;
-  width: 1.6em;
-  height: 1.6em;
+  width: 1.5625em;
+  height: 1.5625em;
   margin: 0;
   opacity: 0;
   z-index: 1;
@@ -1054,8 +1061,8 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
   -webkit-box-sizing: border-box;
      -moz-box-sizing: border-box;
           box-sizing: border-box;
-  width: 1.6em;
-  height: 1.6em;
+  width: 1.5625em;
+  height: 1.5625em;
   border: 1px solid #72777d;
   border-radius: 100%;
 }
@@ -1070,11 +1077,11 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
   border-radius: 100%;
 }
 .oo-ui-radioInputWidget [type='radio']:checked + span {
-  border-width: 0.4em;
+  border-width: 0.390625em;
 }
 .oo-ui-radioInputWidget [type='radio']:checked:hover + span,
 .oo-ui-radioInputWidget [type='radio']:checked:focus:hover + span {
-  border-width: 0.4em;
+  border-width: 0.390625em;
 }
 .oo-ui-radioInputWidget [type='radio']:disabled + span {
   background-color: #c8ccd1;
@@ -1182,10 +1189,14 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
   display: none;
 }
 .oo-ui-textInputWidget.oo-ui-iconElement > .oo-ui-iconElement-icon,
-.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator {
+.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
   display: block;
   position: absolute;
   top: 0;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator {
   height: 100%;
   -webkit-touch-callout: none;
   -webkit-user-select: none;
@@ -1193,21 +1204,24 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
       -ms-user-select: none;
           user-select: none;
 }
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget-labelPosition-before > .oo-ui-labelElement-label {
+  left: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget-labelPosition-after > .oo-ui-labelElement-label {
+  right: 0;
+}
 .oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-iconElement-icon,
-.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-labelElement-label {
   cursor: text;
 }
 .oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-textInputWidget-type-search > .oo-ui-indicatorElement-indicator {
   cursor: pointer;
 }
 .oo-ui-textInputWidget.oo-ui-widget-disabled input,
-.oo-ui-textInputWidget.oo-ui-widget-disabled textarea {
-  -webkit-touch-callout: none;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-}
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
 .oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
   -webkit-touch-callout: none;
   -webkit-user-select: none;
@@ -1215,37 +1229,22 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
       -ms-user-select: none;
           user-select: none;
 }
-.oo-ui-textInputWidget.oo-ui-labelElement > .oo-ui-labelElement-label {
-  display: block;
-}
-.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
-.oo-ui-textInputWidget-labelPosition-before > .oo-ui-labelElement-label {
-  left: 0;
-}
-.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
-.oo-ui-textInputWidget-labelPosition-after > .oo-ui-labelElement-label {
-  right: 0;
-}
-.oo-ui-textInputWidget > .oo-ui-labelElement-label {
-  position: absolute;
-  top: 0;
-}
 .oo-ui-textInputWidget input,
 .oo-ui-textInputWidget textarea {
-  margin: 0;
   font-size: inherit;
   font-family: inherit;
   background-color: #fff;
   color: #000;
   border: 1px solid #a2a9b1;
   border-radius: 2px;
-  padding: 0.625em 0.546875em 0.546875em;
 }
 .oo-ui-textInputWidget input {
+  padding: 0.625em 0.546875em 0.546875em;
   line-height: 1.172em;
 }
 .oo-ui-textInputWidget textarea {
-  line-height: 1.275;
+  padding: 0.46875em 0.546875em 0.546875em;
+  line-height: 1.4;
 }
 .oo-ui-textInputWidget .oo-ui-pendingElement-pending {
   background-color: transparent;
@@ -1310,51 +1309,50 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
   border-color: #f00;
   box-shadow: inset 0 0 0 0.1em #f00;
 }
-.oo-ui-textInputWidget.oo-ui-widget-disabled input,
-.oo-ui-textInputWidget.oo-ui-widget-disabled textarea {
-  background-color: #eaecf0;
-  color: #72777d;
-  text-shadow: 0 1px 1px #fff;
-  border-color: #c8ccd1;
-}
-.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
-.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
-  opacity: 0.51;
-}
-.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
-  color: #72777d;
-  text-shadow: 0 1px 1px #fff;
-}
 .oo-ui-textInputWidget.oo-ui-iconElement input,
 .oo-ui-textInputWidget.oo-ui-iconElement textarea {
-  padding-left: 2.875em;
+  padding-left: 2.65625em;
 }
 .oo-ui-textInputWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
-  left: 0;
-  height: 100%;
-  max-height: 2.375em;
-  margin-left: 0.5em;
-  background-position: right center;
+  max-height: 2.5em;
+  left: 0.46875em;
 }
 .oo-ui-textInputWidget.oo-ui-indicatorElement input,
 .oo-ui-textInputWidget.oo-ui-indicatorElement textarea {
   padding-right: 2.4875em;
 }
 .oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
-  height: 100%;
-  max-height: 2.375em;
-  margin: 0 0.775em;
+  max-height: 2.5em;
+  right: 0.625em;
 }
 .oo-ui-textInputWidget > .oo-ui-labelElement-label {
   color: #72777d;
-  padding: 0.4em;
-  line-height: 1.5;
+  right: 0.625em;
+  border: 1px solid transparent;
+  border-width: 1px 0;
+  padding: 0.625em 0 0.546875em;
+  line-height: 1.172em;
 }
 .oo-ui-textInputWidget-labelPosition-after.oo-ui-indicatorElement > .oo-ui-labelElement-label {
-  margin-right: 2.0875em;
+  right: 2.1875em;
 }
 .oo-ui-textInputWidget-labelPosition-before.oo-ui-iconElement > .oo-ui-labelElement-label {
-  margin-left: 2.475em;
+  left: 2.65625em;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea {
+  background-color: #eaecf0;
+  color: #72777d;
+  text-shadow: 0 1px 1px #fff;
+  border-color: #c8ccd1;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+  opacity: 0.51;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
+  color: #72777d;
+  text-shadow: 0 1px 1px #fff;
 }
 .oo-ui-menuSelectWidget {
   position: absolute;
@@ -1469,12 +1467,17 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 }
 .oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:hover {
   background-color: #fff;
+  color: #444;
   border-color: #a2a9b1;
 }
 .oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:hover .oo-ui-iconElement-icon,
 .oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:hover .oo-ui-indicatorElement-indicator {
   opacity: 0.73;
 }
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:active {
+  color: #000;
+  border-color: #72777d;
+}
 .oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:focus {
   border-color: #36c;
   outline: 0;
@@ -1610,7 +1613,7 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
   vertical-align: middle;
 }
 .oo-ui-checkboxMultioptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
-  padding: 0.25em 0.25em 0.25em 0.5em;
+  padding: 0.25em 0.25em 0.25em 0.46875em;
 }
 .oo-ui-checkboxMultioptionWidget .oo-ui-checkboxInputWidget {
   margin-right: 0;
index fd4e033..b92094c 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:37Z
+ * Date: 2016-12-06T23:32:53Z
  */
 ( function ( OO ) {
 
@@ -414,7 +414,7 @@ OO.ui.infuse = function ( idOrNode ) {
                }
                return message;
        };
-} )();
+}() );
 
 /**
  * Package a message and arguments for deferred resolution.
@@ -4308,8 +4308,7 @@ OO.mixinClass( OO.ui.PopupWidget, OO.ui.mixin.ClippableElement );
 OO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {
        if (
                this.isVisible() &&
-               !$.contains( this.$element[ 0 ], e.target ) &&
-               ( !this.$autoCloseIgnore || !this.$autoCloseIgnore.has( e.target ).length )
+               !OO.ui.contains( this.$element.add( this.$autoCloseIgnore ).get(), e.target, true )
        ) {
                this.toggle( false );
        }
@@ -4597,7 +4596,7 @@ OO.ui.mixin.PopupElement = function OoUiMixinPopupElement( config ) {
        this.popup = new OO.ui.PopupWidget( $.extend(
                { autoClose: true },
                config.popup,
-               { $autoCloseIgnore: this.$element }
+               { $autoCloseIgnore: this.$element.add( config.popup && config.popup.$autoCloseIgnore ) }
        ) );
 };
 
@@ -9797,7 +9796,7 @@ OO.ui.ComboBoxInputWidget.prototype.setOptions = function ( options ) {
  * @throws {Error} An error is thrown if no widget is specified
  */
 OO.ui.FieldLayout = function OoUiFieldLayout( fieldWidget, config ) {
-       var hasInputWidget, div;
+       var hasInputWidget, $div;
 
        // Allow passing positional parameters inside the config object
        if ( OO.isPlainObject( fieldWidget ) && config === undefined ) {
@@ -9837,14 +9836,14 @@ OO.ui.FieldLayout = function OoUiFieldLayout( fieldWidget, config ) {
                        icon: 'info'
                } );
 
-               div = $( '<div>' );
+               $div = $( '<div>' );
                if ( config.help instanceof OO.ui.HtmlSnippet ) {
-                       div.html( config.help.toString() );
+                       $div.html( config.help.toString() );
                } else {
-                       div.text( config.help );
+                       $div.text( config.help );
                }
                this.popupButtonWidget.getPopup().$body.append(
-                       div.addClass( 'oo-ui-fieldLayout-help-content' )
+                       $div.addClass( 'oo-ui-fieldLayout-help-content' )
                );
                this.$help = this.popupButtonWidget.$element;
        } else {
@@ -10138,8 +10137,13 @@ OO.inheritClass( OO.ui.ActionFieldLayout, OO.ui.FieldLayout );
  * @constructor
  * @param {Object} [config] Configuration options
  * @cfg {OO.ui.FieldLayout[]} [items] An array of fields to add to the fieldset. See OO.ui.FieldLayout for more information about fields.
+ * @cfg {string|OO.ui.HtmlSnippet} [help] Help text. When help text is specified, a "help" icon will appear
+ *  in the upper-right corner of the rendered field; clicking it will display the text in a popup.
+ *  For important messages, you are advised to use `notices`, as they are always shown.
  */
 OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
+       var $div;
+
        // Configuration initialization
        config = config || {};
 
@@ -10148,7 +10152,7 @@ OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
 
        // Mixin constructors
        OO.ui.mixin.IconElement.call( this, config );
-       OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, { $label: $( '<legend>' ) } ) );
+       OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, { $label: $( '<div>' ) } ) );
        OO.ui.mixin.GroupElement.call( this, config );
 
        if ( config.help ) {
@@ -10158,10 +10162,14 @@ OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
                        icon: 'info'
                } );
 
+               $div = $( '<div>' );
+               if ( config.help instanceof OO.ui.HtmlSnippet ) {
+                       $div.html( config.help.toString() );
+               } else {
+                       $div.text( config.help );
+               }
                this.popupButtonWidget.getPopup().$body.append(
-                       $( '<div>' )
-                               .text( config.help )
-                               .addClass( 'oo-ui-fieldsetLayout-help-content' )
+                       $div.addClass( 'oo-ui-fieldsetLayout-help-content' )
                );
                this.$help = this.popupButtonWidget.$element;
        } else {
index 17bca7e..7dc6bef 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:37Z
+ * Date: 2016-12-06T23:32:53Z
  */
 ( function ( OO ) {
 
index 7fb36c4..baf8833 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:42Z
+ * Date: 2016-12-06T23:32:57Z
  */
 .oo-ui-popupTool .oo-ui-popupWidget-popup,
 .oo-ui-popupTool .oo-ui-popupWidget-anchor {
index cb9660a..99a1f5e 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:42Z
+ * Date: 2016-12-06T23:32:57Z
  */
 .oo-ui-tool.oo-ui-widget-enabled {
   -webkit-transition: background-color 100ms;
index e17f511..e45ca29 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:37Z
+ * Date: 2016-12-06T23:32:53Z
  */
 ( function ( OO ) {
 
index d6ba00b..318bf82 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:42Z
+ * Date: 2016-12-06T23:32:57Z
  */
 .oo-ui-draggableElement-handle,
 .oo-ui-draggableElement-handle.oo-ui-widget {
index bf50532..a4db2a3 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:42Z
+ * Date: 2016-12-06T23:32:57Z
  */
 .oo-ui-draggableElement-handle,
 .oo-ui-draggableElement-handle.oo-ui-widget {
 .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-iconElement-icon {
   position: absolute;
 }
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content :-moz-placeholder {
+  color: #72777d;
+  opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content ::-moz-placeholder {
+  color: #72777d;
+  opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content :-ms-input-placeholder {
+  color: #72777d;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content ::-webkit-input-placeholder {
+  color: #72777d;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content :placeholder-shown {
+  color: #72777d;
+}
 .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input {
   border: 0;
   line-height: 1.675;
index 6962c92..1185fc1 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:37Z
+ * Date: 2016-12-06T23:32:53Z
  */
 ( function ( OO ) {
 
@@ -4074,8 +4074,7 @@ OO.ui.CapsuleMultiselectWidget.prototype.onPopupFocusOut = function () {
        setTimeout( function () {
                if (
                        widget.isVisible() &&
-                       !OO.ui.contains( widget.$element[ 0 ], document.activeElement, true ) &&
-                       ( !widget.$autoCloseIgnore || !widget.$autoCloseIgnore.has( document.activeElement ).length )
+                       !OO.ui.contains( widget.$element.add( widget.$autoCloseIgnore ).get(), document.activeElement, true )
                ) {
                        widget.toggle( false );
                }
index 6258b84..ad0e7ab 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:42Z
+ * Date: 2016-12-06T23:32:57Z
  */
 .oo-ui-actionWidget.oo-ui-pendingElement-pending {
   background-image: /* @embed */ url(themes/apex/images/textures/pending.gif);
index 359c469..ecc0004 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:42Z
+ * Date: 2016-12-06T23:32:57Z
  */
 .oo-ui-window {
   background: transparent;
index 8b614c6..b47b0c8 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.18.0
+ * OOjs UI v0.18.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-11-09T00:52:37Z
+ * Date: 2016-12-06T23:32:53Z
  */
 ( function ( OO ) {
 
@@ -1286,7 +1286,8 @@ OO.ui.WindowManager.prototype.getCurrentWindow = function () {
  *
  * @param {OO.ui.Window|string} win Window object or symbolic name of window to open
  * @param {Object} [data] Window opening data
- * @param {jQuery} [data.$returnFocusTo] Element to which the window will return focus when closed.
+ * @param {jQuery|null} [data.$returnFocusTo] Element to which the window will return focus when closed.
+ *  Defaults the current activeElement. If set to null, focus isn't changed on close.
  * @return {jQuery.Promise} An `opening` promise resolved when the window is done opening.
  *  See {@link #event-opening 'opening' event}  for more information about `opening` promises.
  * @fires opening
@@ -1418,7 +1419,9 @@ OO.ui.WindowManager.prototype.closeWindow = function ( win, data ) {
                                                                manager.toggleGlobalEvents( false );
                                                                manager.toggleAriaIsolation( false );
                                                        }
-                                                       manager.$returnFocusTo[ 0 ].focus();
+                                                       if ( manager.$returnFocusTo && manager.$returnFocusTo.length ) {
+                                                               manager.$returnFocusTo[ 0 ].focus();
+                                                       }
                                                        manager.closing = null;
                                                        manager.currentWindow = null;
                                                        closing.resolve( data );
index f5694a1..e6fa863 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 651cddf..80bbcaf 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 6b9e490..21efb82 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 11fcef7..4515405 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index cd4087e..3edb545 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index d168364..c97d770 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 7efe531..f110a04 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 765b8fe..6ff4a0e 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index c844449..7098f23 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 8c7b845..afdb9e5 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index e98012f..3779ae3 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index c545a49..059073f 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 39fdda5..5a70c5e 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index bac9768..61aec85 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 6a7c565..4666fd1 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 53460be..54b9f62 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.png differ
index abf656f..f01a779 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
 </svg>
index 000e529..f574a39 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.png differ
index b2b0179..3391d4e 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <g id="cancel">
         <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
     </g>
index 0cc9169..305f41d 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.png differ
index 7e3dc53..059f0bd 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
 </svg>
index 42311de..e16f042 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.png differ
index a9900c1..2cfa62e 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <path d="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
 </svg>
index 72d6a7b..29cd2b5 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.png differ
index 2811b25..2daea47 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <path d="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
 </svg>
index 55a68db..441fe2d 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.png differ
index 663913a..548e136 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #fff }</style>
-    <path d="M19 12c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 4c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+    <path d="M19 12c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 3c-1.6 0-3-1.4-3-3s1.4-3 3-3 3 1.4 3 3-1.4 3-3 3z"/>
 </svg>
index c1676e6..2e7107d 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-progressive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-progressive.png differ
index a9631cc..daf032a 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #36c }</style>
-    <path d="M19 12c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 4c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+    <path d="M19 12c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 3c-1.6 0-3-1.4-3-3s1.4-3 3-3 3 1.4 3 3-1.4 3-3 3z"/>
 </svg>
index 536e77c..ddb1c5c 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.png differ
index f1fa246..26fb6b7 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-    <path d="M19 12c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 4c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+    <path d="M19 12c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 3c-1.6 0-3-1.4-3-3s1.4-3 3-3 3 1.4 3 3-1.4 3-3 3z"/>
 </svg>
index 607354c..ee5de90 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.png differ
index 43074af..cfa98d8 100644 (file)
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #fff }</style>
-    <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4z"/>
-    <path d="M18 11h-1V7.1l-.1-.1H13V5.1c-.3-.1-.7-.1-1-.1-3.9 0-7 3.1-7 7 0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7 0-.3 0-.7-.1-1H18zm-6 5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+  <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4V4z"/>
+  <path d="M18.9 11c.1.3.1.7.1 1 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-3.9 3.1-7 7-7 .3 0 .7 0 1 .1V7h3.9l.1.1V11h1.9zM15 12c0-1.6-1.4-3-3-3s-3 1.4-3 3 1.4 3 3 3 3-1.4 3-3z"/>
 </svg>
+
index 2fcf2e1..036a31d 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-progressive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-progressive.png differ
index 7dc09d4..7cf1509 100644 (file)
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #36c }</style>
-    <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4z"/>
-    <path d="M18 11h-1V7.1l-.1-.1H13V5.1c-.3-.1-.7-.1-1-.1-3.9 0-7 3.1-7 7 0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7 0-.3 0-.7-.1-1H18zm-6 5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+  <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4V4z"/>
+  <path d="M18.9 11c.1.3.1.7.1 1 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-3.9 3.1-7 7-7 .3 0 .7 0 1 .1V7h3.9l.1.1V11h1.9zM15 12c0-1.6-1.4-3-3-3s-3 1.4-3 3 1.4 3 3 3 3-1.4 3-3z"/>
 </svg>
+
index 88160bc..d8c1691 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.png differ
index d84970f..9d71335 100644 (file)
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-    <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4z"/>
-    <path d="M18 11h-1V7.1l-.1-.1H13V5.1c-.3-.1-.7-.1-1-.1-3.9 0-7 3.1-7 7 0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7 0-.3 0-.7-.1-1H18zm-6 5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+  <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4V4z"/>
+  <path d="M18.9 11c.1.3.1.7.1 1 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-3.9 3.1-7 7-7 .3 0 .7 0 1 .1V7h3.9l.1.1V11h1.9zM15 12c0-1.6-1.4-3-3-3s-3 1.4-3 3 1.4 3 3 3 3-1.4 3-3z"/>
 </svg>
+
index 6ea8226..934d5cc 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.png differ
index 6a4af93..8b02ddb 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #fff }</style>
-    <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0z"/>
-    <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 5c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4z"/>
+    <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0"/>
+    <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 4c1.65 0 3-1.35 3-3s-1.35-3-3-3-3 1.35-3 3 1.35 3 3 3z"/>
 </svg>
index 56b7924..be7c51e 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-progressive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-progressive.png differ
index 8108685..c920c8d 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #36c }</style>
-    <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0z"/>
-    <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 5c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4z"/>
+    <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0"/>
+    <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 4c1.65 0 3-1.35 3-3s-1.35-3-3-3-3 1.35-3 3 1.35 3 3 3z"/>
 </svg>
index 20aba25..7cc1f74 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.png differ
index 8f35458..03c484a 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-    <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0z"/>
-    <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 5c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4z"/>
+    <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0"/>
+    <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 4c1.65 0 3-1.35 3-3s-1.35-3-3-3-3 1.35-3 3 1.35 3 3 3z"/>
 </svg>
index 55ab6c4..cf85c4d 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.png differ
index 7048a40..0732f2e 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
 </svg>
index c1d2a66..c367e77 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.png differ
index 3ebc63b..59ad3f2 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <path d="M6 8c0-1.1.9-2 2-2h2l1-1h2l1 1h2c1.1 0 2 .9 2 2H6zm1 1h10l-1 11H8z"/>
 </svg>
index 8fb039c..2cb27f1 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.png differ
index 7ee7522..d45ebac 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <path d="M12 9V7s0-5-4.5-5S3 7 3 7h2s0-3 2.5-3S10 7 10 7v2H7v7c0 1.7 1.3 3 3 3h10V9z"/>
 </svg>
index 7c2786d..fac51b9 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.png differ
index a5f2721..5e6d205 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #c33 }</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d33 }</style>
     <path d="M11 9V7s0-5 4.5-5S20 7 20 7h-2s0-3-2.5-3S13 7 13 7v2h3v7c0 1.7-1.3 3-3 3H3V9z"/>
 </svg>
index 349227a..91d0358 100644 (file)
@@ -15,7 +15,7 @@
                        "color": "#36c"
                },
                "destructive": {
-                       "color": "#c33"
+                       "color": "#d33"
                },
                "warning": {
                        "color": "#ff5d00"
index 8c78b67..ae68fc4 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * QUnit 1.22.0
+ * QUnit 1.23.1
  * https://qunitjs.com/
  *
  * Copyright jQuery Foundation and other contributors
  * Released under the MIT license
  * https://jquery.org/license
  *
- * Date: 2016-02-23T15:57Z
+ * Date: 2016-04-12T17:29Z
  */
 
 /** Font Family and Sizes */
index 84873ae..5df0822 100644 (file)
@@ -1,15 +1,15 @@
 /*!
- * QUnit 1.22.0
+ * QUnit 1.23.1
  * https://qunitjs.com/
  *
  * Copyright jQuery Foundation and other contributors
  * Released under the MIT license
  * https://jquery.org/license
  *
- * Date: 2016-02-23T15:57Z
+ * Date: 2016-04-12T17:29Z
  */
 
-(function( global ) {
+( function( global ) {
 
 var QUnit = {};
 
@@ -27,7 +27,7 @@ var window = global.window;
 var defined = {
        document: window && window.document !== undefined,
        setTimeout: setTimeout !== undefined,
-       sessionStorage: (function() {
+       sessionStorage: ( function() {
                var x = "qunit-test-string";
                try {
                        sessionStorage.setItem( x, x );
@@ -46,7 +46,7 @@ var runStarted = false;
 var toString = Object.prototype.toString,
        hasOwn = Object.prototype.hasOwnProperty;
 
-// returns a new Array with the elements that are in a but not in b
+// Returns a new Array with the elements that are in a but not in b
 function diff( a, b ) {
        var i, j,
                result = a.slice();
@@ -63,7 +63,7 @@ function diff( a, b ) {
        return result;
 }
 
-// from jquery.js
+// From jquery.js
 function inArray( elem, array ) {
        if ( array.indexOf ) {
                return array.indexOf( elem );
@@ -157,32 +157,6 @@ function is( type, obj ) {
        return QUnit.objectType( obj ) === type;
 }
 
-var getUrlParams = function() {
-       var i, param, name, value;
-       var urlParams = {};
-       var location = window.location;
-       var params = location.search.slice( 1 ).split( "&" );
-       var length = params.length;
-
-       for ( i = 0; i < length; i++ ) {
-               if ( params[ i ] ) {
-                       param = params[ i ].split( "=" );
-                       name = decodeURIComponent( param[ 0 ] );
-
-                       // allow just a key to turn on a flag, e.g., test.html?noglobals
-                       value = param.length === 1 ||
-                               decodeURIComponent( param.slice( 1 ).join( "=" ) ) ;
-                       if ( urlParams[ name ] ) {
-                               urlParams[ name ] = [].concat( urlParams[ name ], value );
-                       } else {
-                               urlParams[ name ] = value;
-                       }
-               }
-       }
-
-       return urlParams;
-};
-
 // Doesn't support IE6 to IE9, it will return undefined on these browsers
 // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
 function extractStacktrace( e, offset ) {
@@ -212,12 +186,12 @@ function extractStacktrace( e, offset ) {
        // Support: Safari <=6 only
        } else if ( e.sourceURL ) {
 
-               // exclude useless self-reference for generated Error objects
+               // Exclude useless self-reference for generated Error objects
                if ( /qunit.js$/.test( e.sourceURL ) ) {
                        return;
                }
 
-               // for actual exceptions, this is useful
+               // For actual exceptions, this is useful
                return e.sourceURL + ":" + e.line;
        }
 }
@@ -244,53 +218,35 @@ function sourceFromStacktrace( offset ) {
  * `config` initialized at top of scope
  */
 var config = {
+
        // The queue of tests to run
        queue: [],
 
-       // block until document ready
+       // Block until document ready
        blocking: true,
 
-       // by default, run previously failed tests first
+       // By default, run previously failed tests first
        // very useful in combination with "Hide passed tests" checked
        reorder: true,
 
-       // by default, modify document.title when suite is done
+       // By default, modify document.title when suite is done
        altertitle: true,
 
        // HTML Reporter: collapse every test except the first failing test
        // If false, all failing tests will be expanded
        collapse: true,
 
-       // by default, scroll to top of the page when suite is done
+       // By default, scroll to top of the page when suite is done
        scrolltop: true,
 
-       // depth up-to which object will be dumped
+       // Depth up-to which object will be dumped
        maxDepth: 5,
 
-       // when enabled, all tests must call expect()
+       // When enabled, all tests must call expect()
        requireExpects: false,
 
-       // add checkboxes that are persisted in the query-string
-       // when enabled, the id is set to `true` as a `QUnit.config` property
-       urlConfig: [
-               {
-                       id: "hidepassed",
-                       label: "Hide passed tests",
-                       tooltip: "Only show tests and assertions that fail. Stored as query-strings."
-               },
-               {
-                       id: "noglobals",
-                       label: "Check for Globals",
-                       tooltip: "Enabling this will test if any test introduces new properties on the " +
-                               "global object (`window` in Browsers). Stored as query-strings."
-               },
-               {
-                       id: "notrycatch",
-                       label: "No try-catch",
-                       tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " +
-                               "exceptions in IE reasonable. Stored as query-strings."
-               }
-       ],
+       // Placeholder for user-configurable form-exposed URL parameters
+       urlConfig: [],
 
        // Set of all modules.
        modules: [],
@@ -307,27 +263,9 @@ var config = {
        callbacks: {}
 };
 
-var urlParams = defined.document ? getUrlParams() : {};
-
 // Push a loose unnamed module to the modules collection
 config.modules.push( config.currentModule );
 
-if ( urlParams.filter === true ) {
-       delete urlParams.filter;
-}
-
-// String search anywhere in moduleName+testName
-config.filter = urlParams.filter;
-
-config.testId = [];
-if ( urlParams.testId ) {
-       // Ensure that urlParams.testId is an array
-       urlParams.testId = decodeURIComponent( urlParams.testId ).split( "," );
-       for (var i = 0; i < urlParams.testId.length; i++ ) {
-               config.testId.push( urlParams.testId[ i ] );
-       }
-}
-
 var loggingCallbacks = {};
 
 // Register logging callbacks
@@ -431,7 +369,7 @@ function verifyLoggingCallbacks() {
                                }
                                QUnit.pushFailure( error, filePath + ":" + linerNr );
                        } else {
-                               QUnit.test( "global failure", extend(function() {
+                               QUnit.test( "global failure", extend( function() {
                                        QUnit.pushFailure( error, filePath + ":" + linerNr );
                                }, { validTest: true } ) );
                        }
@@ -440,25 +378,23 @@ function verifyLoggingCallbacks() {
 
                return ret;
        };
-} )();
-
-QUnit.urlParams = urlParams;
+}() );
 
 // Figure out if we're running the tests from a server or not
 QUnit.isLocal = !( defined.document && window.location.protocol !== "file:" );
 
 // Expose the current QUnit version
-QUnit.version = "1.22.0";
+QUnit.version = "1.23.1";
 
 extend( QUnit, {
 
-       // call on start of module test to prepend name to all tests
+       // Call on start of module test to prepend name to all tests
        module: function( name, testEnvironment, executeNow ) {
                var module, moduleFns;
                var currentModule = config.currentModule;
 
                if ( arguments.length === 2 ) {
-                       if ( testEnvironment instanceof Function ) {
+                       if ( objectType( testEnvironment ) === "function" ) {
                                executeNow = testEnvironment;
                                testEnvironment = undefined;
                        }
@@ -482,7 +418,7 @@ extend( QUnit, {
                        afterEach: setHook( module, "afterEach" )
                };
 
-               if ( executeNow instanceof Function ) {
+               if ( objectType( executeNow ) === "function" ) {
                        config.moduleStack.push( module );
                        setCurrentModule( module );
                        executeNow.call( module.testEnvironment, moduleFns );
@@ -500,7 +436,8 @@ extend( QUnit, {
                        var module = {
                                name: moduleName,
                                parentModule: parentModule,
-                               tests: []
+                               tests: [],
+                               moduleId: generateHash( moduleName )
                        };
 
                        var env = {};
@@ -573,7 +510,7 @@ extend( QUnit, {
                                return;
                        }
 
-                       // throw an Error if start is called more often than stop
+                       // Throw an Error if start is called more often than stop
                        if ( config.current.semaphore < 0 ) {
                                config.current.semaphore = 0;
 
@@ -634,7 +571,7 @@ extend( QUnit, {
                offset = ( offset || 0 ) + 2;
                return sourceFromStacktrace( offset );
        }
-});
+} );
 
 registerLoggingCallbacks( QUnit );
 
@@ -657,17 +594,17 @@ function begin() {
 
                // Avoid unnecessary information by not logging modules' test environments
                for ( i = 0, l = config.modules.length; i < l; i++ ) {
-                       modulesLog.push({
+                       modulesLog.push( {
                                name: config.modules[ i ].name,
                                tests: config.modules[ i ].tests
-                       });
+                       } );
                }
 
                // The test run is officially beginning now
                runLoggingCallbacks( "begin", {
                        totalTests: Test.count,
                        modules: modulesLog
-               });
+               } );
        }
 
        config.blocking = false;
@@ -706,7 +643,7 @@ function pauseProcessing() {
 
        if ( config.testTimeout && defined.setTimeout ) {
                clearTimeout( config.timeout );
-               config.timeout = setTimeout(function() {
+               config.timeout = setTimeout( function() {
                        if ( config.current ) {
                                config.current.semaphore = 0;
                                QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) );
@@ -723,7 +660,7 @@ function resumeProcessing() {
 
        // A slight delay to allow this iteration of the event loop to finish (more assertions, etc.)
        if ( defined.setTimeout ) {
-               setTimeout(function() {
+               setTimeout( function() {
                        if ( config.current && config.current.semaphore > 0 ) {
                                return;
                        }
@@ -752,7 +689,7 @@ function done() {
                        passed: config.moduleStats.all - config.moduleStats.bad,
                        total: config.moduleStats.all,
                        runtime: now() - config.moduleStats.started
-               });
+               } );
        }
        delete config.previousModule;
 
@@ -764,7 +701,7 @@ function done() {
                passed: passed,
                total: config.stats.all,
                runtime: runtime
-       });
+       } );
 }
 
 function setHook( module, hookName ) {
@@ -779,6 +716,7 @@ function setHook( module, hookName ) {
 
 var focused = false;
 var priorityCount = 0;
+var unitSampler;
 
 function Test( settings ) {
        var i, l;
@@ -801,10 +739,10 @@ function Test( settings ) {
 
        this.testId = generateHash( this.module.name, this.testName );
 
-       this.module.tests.push({
+       this.module.tests.push( {
                name: this.testName,
                testId: this.testId
-       });
+       } );
 
        if ( settings.skip ) {
 
@@ -840,14 +778,14 @@ Test.prototype = {
                                        passed: config.moduleStats.all - config.moduleStats.bad,
                                        total: config.moduleStats.all,
                                        runtime: now() - config.moduleStats.started
-                               });
+                               } );
                        }
                        config.previousModule = this.module;
                        config.moduleStats = { all: 0, bad: 0, started: now() };
                        runLoggingCallbacks( "moduleStart", {
                                name: this.module.name,
                                tests: this.module.tests
-                       });
+                       } );
                }
 
                config.current = this;
@@ -863,7 +801,7 @@ Test.prototype = {
                        name: this.testName,
                        module: this.module.name,
                        testId: this.testId
-               });
+               } );
 
                if ( !config.pollution ) {
                        saveGlobal();
@@ -892,7 +830,7 @@ Test.prototype = {
                        this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " +
                                this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
 
-                       // else next test will carry the responsibility
+                       // Else next test will carry the responsibility
                        saveGlobal();
 
                        // Restart the tests if they're blocking
@@ -1001,7 +939,7 @@ Test.prototype = {
 
                        // DEPRECATED: this property will be removed in 2.0.0, use runtime instead
                        duration: this.runtime
-               });
+               } );
 
                // QUnit.reset() is deprecated and will be replaced for a new
                // fixture reset function on QUnit 2.0/2.1.
@@ -1021,8 +959,8 @@ Test.prototype = {
 
                function run() {
 
-                       // each of these can by async
-                       synchronize([
+                       // Each of these can by async
+                       synchronize( [
                                function() {
                                        test.before();
                                },
@@ -1040,19 +978,19 @@ Test.prototype = {
                                function() {
                                        test.finish();
                                }
-                       ]);
+                       ] );
                }
 
                // Prioritize previously failed tests, detected from sessionStorage
                priority = QUnit.config.reorder && defined.sessionStorage &&
                                +sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName );
 
-               return synchronize( run, priority );
+               return synchronize( run, priority, config.seed );
        },
 
        pushResult: function( resultInfo ) {
 
-               // resultInfo = { result, actual, expected, message, negative }
+               // Destructure of resultInfo = { result, actual, expected, message, negative }
                var source,
                        details = {
                                module: this.module.name,
@@ -1076,10 +1014,10 @@ Test.prototype = {
 
                runLoggingCallbacks( "log", details );
 
-               this.assertions.push({
+               this.assertions.push( {
                        result: !!resultInfo.result,
                        message: resultInfo.message
-               });
+               } );
        },
 
        pushFailure: function( message, source, actual ) {
@@ -1104,10 +1042,10 @@ Test.prototype = {
 
                runLoggingCallbacks( "log", details );
 
-               this.assertions.push({
+               this.assertions.push( {
                        result: false,
                        message: message
-               });
+               } );
        },
 
        resolvePromise: function( promise, phase ) {
@@ -1126,7 +1064,7 @@ Test.prototype = {
                                                        " " + test.testName + ": " + ( error.message || error );
                                                test.pushFailure( message, extractStacktrace( error, 0 ) );
 
-                                               // else next test will carry the responsibility
+                                               // Else next test will carry the responsibility
                                                saveGlobal();
 
                                                // Unblock
@@ -1140,30 +1078,43 @@ Test.prototype = {
        valid: function() {
                var filter = config.filter,
                        regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec( filter ),
-                       module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(),
+                       module = config.module && config.module.toLowerCase(),
                        fullName = ( this.module.name + ": " + this.testName );
 
-               function testInModuleChain( testModule ) {
+               function moduleChainNameMatch( testModule ) {
                        var testModuleName = testModule.name ? testModule.name.toLowerCase() : null;
                        if ( testModuleName === module ) {
                                return true;
                        } else if ( testModule.parentModule ) {
-                               return testInModuleChain( testModule.parentModule );
+                               return moduleChainNameMatch( testModule.parentModule );
                        } else {
                                return false;
                        }
                }
 
+               function moduleChainIdMatch( testModule ) {
+                       return inArray( testModule.moduleId, config.moduleId ) > -1 ||
+                               testModule.parentModule && moduleChainIdMatch( testModule.parentModule );
+               }
+
                // Internally-generated tests are always valid
                if ( this.callback && this.callback.validTest ) {
                        return true;
                }
 
-               if ( config.testId.length > 0 && inArray( this.testId, config.testId ) < 0 ) {
+               if ( config.moduleId && config.moduleId.length > 0 &&
+                       !moduleChainIdMatch( this.module ) ) {
+
+                       return false;
+               }
+
+               if ( config.testId && config.testId.length > 0 &&
+                       inArray( this.testId, config.testId ) < 0 ) {
+
                        return false;
                }
 
-               if ( module && !testInModuleChain( this.module ) ) {
+               if ( module && !moduleChainNameMatch( this.module ) ) {
                        return false;
                }
 
@@ -1172,7 +1123,7 @@ Test.prototype = {
                }
 
                return regexFilter ?
-                       this.regexFilter( !!regexFilter[1], regexFilter[2], regexFilter[3], fullName ) :
+                       this.regexFilter( !!regexFilter[ 1 ], regexFilter[ 2 ], regexFilter[ 3 ], fullName ) :
                        this.stringFilter( filter, fullName );
        },
 
@@ -1260,8 +1211,9 @@ function generateHash( module, testName ) {
        return hex.slice( -8 );
 }
 
-function synchronize( callback, priority ) {
-       var last = !priority;
+function synchronize( callback, priority, seed ) {
+       var last = !priority,
+               index;
 
        if ( QUnit.objectType( callback ) === "array" ) {
                while ( callback.length ) {
@@ -1272,6 +1224,14 @@ function synchronize( callback, priority ) {
 
        if ( priority ) {
                config.queue.splice( priorityCount++, 0, callback );
+       } else if ( seed ) {
+               if ( !unitSampler ) {
+                       unitSampler = unitSamplerGenerator( seed );
+               }
+
+               // Insert into a random position after all priority items
+               index = Math.floor( unitSampler() * ( config.queue.length - priorityCount + 1 ) );
+               config.queue.splice( priorityCount + index, 0, callback );
        } else {
                config.queue.push( callback );
        }
@@ -1281,6 +1241,25 @@ function synchronize( callback, priority ) {
        }
 }
 
+function unitSamplerGenerator( seed ) {
+
+       // 32-bit xorshift, requires only a nonzero seed
+       // http://excamera.com/sphinx/article-xorshift.html
+       var sample = parseInt( generateHash( seed ), 16 ) || -1;
+       return function() {
+               sample ^= sample << 13;
+               sample ^= sample >>> 17;
+               sample ^= sample << 5;
+
+               // ECMAScript has no unsigned number type
+               if ( sample < 0 ) {
+                       sample += 0x100000000;
+               }
+
+               return sample / 0x100000000;
+       };
+}
+
 function saveGlobal() {
        config.pollution = [];
 
@@ -1288,7 +1267,7 @@ function saveGlobal() {
                for ( var key in global ) {
                        if ( hasOwn.call( global, key ) ) {
 
-                               // in Opera sometimes DOM element ids show up here, ignore them
+                               // In Opera sometimes DOM element ids show up here, ignore them
                                if ( /^qunit-test-output/.test( key ) ) {
                                        continue;
                                }
@@ -1337,12 +1316,12 @@ function test( testName, expected, callback, async ) {
                expected = null;
        }
 
-       newTest = new Test({
+       newTest = new Test( {
                testName: testName,
                expected: expected,
                async: async,
                callback: callback
-       });
+       } );
 
        newTest.queue();
 }
@@ -1351,10 +1330,10 @@ function test( testName, expected, callback, async ) {
 function skip( testName ) {
        if ( focused )  { return; }
 
-       var test = new Test({
+       var test = new Test( {
                testName: testName,
                skip: true
-       });
+       } );
 
        test.queue();
 }
@@ -1373,12 +1352,12 @@ function only( testName, expected, callback, async ) {
                expected = null;
        }
 
-       newTest = new Test({
+       newTest = new Test( {
                testName: testName,
                expected: expected,
                async: async,
                callback: callback
-       });
+       } );
 
        newTest.queue();
 }
@@ -1448,7 +1427,7 @@ QUnit.assert = Assert.prototype = {
 
        pushResult: function( resultInfo ) {
 
-               // resultInfo = { result, actual, expected, message, negative }
+               // Destructure of resultInfo = { result, actual, expected, message, negative }
                var assert = this,
                        currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current;
 
@@ -1594,7 +1573,7 @@ QUnit.assert = Assert.prototype = {
                currentTest.ignoreGlobalErrors = true;
                try {
                        block.call( currentTest.testEnvironment );
-               } catch (e) {
+               } catch ( e ) {
                        actual = e;
                }
                currentTest.ignoreGlobalErrors = false;
@@ -1602,30 +1581,30 @@ QUnit.assert = Assert.prototype = {
                if ( actual ) {
                        expectedType = QUnit.objectType( expected );
 
-                       // we don't want to validate thrown error
+                       // We don't want to validate thrown error
                        if ( !expected ) {
                                ok = true;
                                expectedOutput = null;
 
-                       // expected is a regexp
+                       // Expected is a regexp
                        } else if ( expectedType === "regexp" ) {
                                ok = expected.test( errorString( actual ) );
 
-                       // expected is a string
+                       // Expected is a string
                        } else if ( expectedType === "string" ) {
                                ok = expected === errorString( actual );
 
-                       // expected is a constructor, maybe an Error constructor
+                       // Expected is a constructor, maybe an Error constructor
                        } else if ( expectedType === "function" && actual instanceof expected ) {
                                ok = true;
 
-                       // expected is an Error object
+                       // Expected is an Error object
                        } else if ( expectedType === "object" ) {
                                ok = actual instanceof expected.constructor &&
                                        actual.name === expected.name &&
                                        actual.message === expected.message;
 
-                       // expected is a validation function which returns true if validation passed
+                       // Expected is a validation function which returns true if validation passed
                        } else if ( expectedType === "function" && expected.call( {}, actual ) === true ) {
                                expectedOutput = null;
                                ok = true;
@@ -1643,10 +1622,10 @@ QUnit.assert = Assert.prototype = {
 
 // Provide an alternative to assert.throws(), for environments that consider throws a reserved word
 // Known to us are: Closure Compiler, Narwhal
-(function() {
+( function() {
        /*jshint sub:true */
-       Assert.prototype.raises = Assert.prototype[ "throws" ];
-}());
+       Assert.prototype.raises = Assert.prototype [ "throws" ]; //jscs:ignore requireDotNotation
+}() );
 
 function errorString( error ) {
        var name, message,
@@ -1670,7 +1649,7 @@ function errorString( error ) {
 
 // Test for equality any JavaScript type.
 // Author: Philippe Rathé <prathe@gmail.com>
-QUnit.equiv = (function() {
+QUnit.equiv = ( function() {
 
        // Stack to decide between skip/abort functions
        var callers = [];
@@ -1766,7 +1745,8 @@ QUnit.equiv = (function() {
 
                        len = a.length;
                        if ( len !== b.length ) {
-                               // safe and faster
+
+                               // Safe and faster
                                return false;
                        }
 
@@ -1800,33 +1780,53 @@ QUnit.equiv = (function() {
                },
 
                "set": function( b, a ) {
-                       var aArray, bArray;
-
-                       aArray = [];
-                       a.forEach( function( v ) {
-                               aArray.push( v );
-                       });
-                       bArray = [];
-                       b.forEach( function( v ) {
-                               bArray.push( v );
-                       });
-
-                       return innerEquiv( bArray, aArray );
+                       var innerEq,
+                               outerEq = true;
+
+                       if ( a.size !== b.size ) {
+                               return false;
+                       }
+
+                       a.forEach( function( aVal ) {
+                               innerEq = false;
+
+                               b.forEach( function( bVal ) {
+                                       if ( innerEquiv( bVal, aVal ) ) {
+                                               innerEq = true;
+                                       }
+                               } );
+
+                               if ( !innerEq ) {
+                                       outerEq = false;
+                               }
+                       } );
+
+                       return outerEq;
                },
 
                "map": function( b, a ) {
-                       var aArray, bArray;
-
-                       aArray = [];
-                       a.forEach( function( v, k ) {
-                               aArray.push( [ k, v ] );
-                       });
-                       bArray = [];
-                       b.forEach( function( v, k ) {
-                               bArray.push( [ k, v ] );
-                       });
-
-                       return innerEquiv( bArray, aArray );
+                       var innerEq,
+                               outerEq = true;
+
+                       if ( a.size !== b.size ) {
+                               return false;
+                       }
+
+                       a.forEach( function( aVal, aKey ) {
+                               innerEq = false;
+
+                               b.forEach( function( bVal, bKey ) {
+                                       if ( innerEquiv( [ bVal, bKey ], [ aVal, aKey ] ) ) {
+                                               innerEq = true;
+                                       }
+                               } );
+
+                               if ( !innerEq ) {
+                                       outerEq = false;
+                               }
+                       } );
+
+                       return outerEq;
                },
 
                "object": function( b, a ) {
@@ -1908,11 +1908,11 @@ QUnit.equiv = (function() {
        }
 
        return innerEquiv;
-}());
+}() );
 
 // Based on jsDump by Ariel Flesler
 // http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
-QUnit.dump = (function() {
+QUnit.dump = ( function() {
        function quote( str ) {
                return "\"" + str.toString().replace( /\\/g, "\\\\" ).replace( /"/g, "\\\"" ) + "\"";
        }
@@ -1950,7 +1950,7 @@ QUnit.dump = (function() {
        var reName = /^function (\w+)/,
                dump = {
 
-                       // objType is used mostly internally, you can fix a (custom) type in advance
+                       // The objType is used mostly internally, you can fix a (custom) type in advance
                        parse: function( obj, objType, stack ) {
                                stack = stack || [];
                                var res, parser, parserType,
@@ -1994,7 +1994,7 @@ QUnit.dump = (function() {
                                        type = "node";
                                } else if (
 
-                                       // native arrays
+                                       // Native arrays
                                        toString.call( obj ) === "[object Array]" ||
 
                                        // NodeList objects
@@ -2010,10 +2010,12 @@ QUnit.dump = (function() {
                                }
                                return type;
                        },
+
                        separator: function() {
                                return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&#160;" : " ";
                        },
-                       // extra can be a number, shortcut for increasing-calling-decreasing
+
+                       // Extra can be a number, shortcut for increasing-calling-decreasing
                        indent: function( extra ) {
                                if ( !this.multiline ) {
                                        return "";
@@ -2033,11 +2035,11 @@ QUnit.dump = (function() {
                        setParser: function( name, parser ) {
                                this.parsers[ name ] = parser;
                        },
+
                        // The next 3 are exposed so you can use them
                        quote: quote,
                        literal: literal,
                        join: join,
-                       //
                        depth: 1,
                        maxDepth: QUnit.config.maxDepth,
 
@@ -2054,13 +2056,13 @@ QUnit.dump = (function() {
                                "function": function( fn ) {
                                        var ret = "function",
 
-                                               // functions never have name in IE
+                                               // Functions never have name in IE
                                                name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ];
 
                                        if ( name ) {
                                                ret += " " + name;
                                        }
-                                       ret += "( ";
+                                       ret += "(";
 
                                        ret = [ ret, dump.parse( fn, "functionArgs" ), "){" ].join( "" );
                                        return join( ret, dump.parse( fn, "functionCode" ), "}" );
@@ -2131,7 +2133,7 @@ QUnit.dump = (function() {
                                        return ret + open + "/" + tag + close;
                                },
 
-                               // function calls it internally, it's the arguments part of the function
+                               // Function calls it internally, it's the arguments part of the function
                                functionArgs: function( fn ) {
                                        var args,
                                                l = fn.length;
@@ -2148,11 +2150,14 @@ QUnit.dump = (function() {
                                        }
                                        return " " + args.join( ", " ) + " ";
                                },
-                               // object calls it internally, the key part of an item in a map
+
+                               // Object calls it internally, the key part of an item in a map
                                key: quote,
-                               // function calls it internally, it's the content of the function
+
+                               // Function calls it internally, it's the content of the function
                                functionCode: "[code]",
-                               // node calls it internally, it's a html attribute value
+
+                               // Node calls it internally, it's a html attribute value
                                attribute: quote,
                                string: quote,
                                date: quote,
@@ -2160,23 +2165,26 @@ QUnit.dump = (function() {
                                number: literal,
                                "boolean": literal
                        },
-                       // if true, entities are escaped ( <, >, \t, space and \n )
+
+                       // If true, entities are escaped ( <, >, \t, space and \n )
                        HTML: false,
-                       // indentation unit
+
+                       // Indentation unit
                        indentChar: "  ",
-                       // if true, items in a collection, are separated by a \n, else just a space.
+
+                       // If true, items in a collection, are separated by a \n, else just a space.
                        multiline: true
                };
 
        return dump;
-}());
+}() );
 
-// back compat
+// Back compat
 QUnit.jsDump = QUnit.dump;
 
 // Deprecated
 // Extend assert methods to QUnit for Backwards compatibility
-(function() {
+( function() {
        var i,
                assertions = Assert.prototype;
 
@@ -2190,12 +2198,12 @@ QUnit.jsDump = QUnit.dump;
        for ( i in assertions ) {
                QUnit[ i ] = applyCurrent( assertions[ i ] );
        }
-})();
+}() );
 
 // For browser, export only select globals
 if ( defined.document ) {
 
-       (function() {
+       ( function() {
                var i, l,
                        keys = [
                                "test",
@@ -2221,7 +2229,7 @@ if ( defined.document ) {
                for ( i = 0, l = keys.length; i < l; i++ ) {
                        window[ keys[ i ] ] = QUnit[ keys[ i ] ];
                }
-       })();
+       }() );
 
        window.QUnit = QUnit;
 }
@@ -2246,1959 +2254,2081 @@ if ( typeof define === "function" && define.amd ) {
        QUnit.config.autostart = false;
 }
 
-/*
- * This file is a modified version of google-diff-match-patch's JavaScript implementation
- * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
- * modifications are licensed as more fully set forth in LICENSE.txt.
- *
- * The original source of google-diff-match-patch is attributable and licensed as follows:
- *
- * Copyright 2006 Google Inc.
- * https://code.google.com/p/google-diff-match-patch/
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * More Info:
- *  https://code.google.com/p/google-diff-match-patch/
- *
- * Usage: QUnit.diff(expected, actual)
- *
- */
-QUnit.diff = ( function() {
-       function DiffMatchPatch() {
-       }
+// Get a reference to the global object, like window in browsers
+}( ( function() {
+       return this;
+}() ) ) );
 
-       //  DIFF FUNCTIONS
+( function() {
 
-       /**
-        * The data structure representing a diff is an array of tuples:
-        * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
-        * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
-        */
-       var DIFF_DELETE = -1,
-               DIFF_INSERT = 1,
-               DIFF_EQUAL = 0;
+// Only interact with URLs via window.location
+var location = typeof window !== "undefined" && window.location;
+if ( !location ) {
+       return;
+}
 
-       /**
-        * Find the differences between two texts.  Simplifies the problem by stripping
-        * any common prefix or suffix off the texts before diffing.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {boolean=} optChecklines Optional speedup flag. If present and false,
-        *     then don't run a line-level diff first to identify the changed areas.
-        *     Defaults to true, which does a faster, slightly less optimal diff.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        */
-       DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines ) {
-               var deadline, checklines, commonlength,
-                       commonprefix, commonsuffix, diffs;
+var urlParams = getUrlParams();
 
-               // The diff must be complete in up to 1 second.
-               deadline = ( new Date() ).getTime() + 1000;
+QUnit.urlParams = urlParams;
 
-               // Check for null inputs.
-               if ( text1 === null || text2 === null ) {
-                       throw new Error( "Null input. (DiffMain)" );
-               }
+// Match module/test by inclusion in an array
+QUnit.config.moduleId = [].concat( urlParams.moduleId || [] );
+QUnit.config.testId = [].concat( urlParams.testId || [] );
 
-               // Check for equality (speedup).
-               if ( text1 === text2 ) {
-                       if ( text1 ) {
-                               return [
-                                       [ DIFF_EQUAL, text1 ]
-                               ];
-                       }
-                       return [];
-               }
+// Exact case-insensitive match of the module name
+QUnit.config.module = urlParams.module;
 
-               if ( typeof optChecklines === "undefined" ) {
-                       optChecklines = true;
-               }
+// Regular expression or case-insenstive substring match against "moduleName: testName"
+QUnit.config.filter = urlParams.filter;
 
-               checklines = optChecklines;
+// Test order randomization
+if ( urlParams.seed === true ) {
 
-               // Trim off common prefix (speedup).
-               commonlength = this.diffCommonPrefix( text1, text2 );
-               commonprefix = text1.substring( 0, commonlength );
-               text1 = text1.substring( commonlength );
-               text2 = text2.substring( commonlength );
+       // Generate a random seed if the option is specified without a value
+       QUnit.config.seed = Math.random().toString( 36 ).slice( 2 );
+} else if ( urlParams.seed ) {
+       QUnit.config.seed = urlParams.seed;
+}
 
-               // Trim off common suffix (speedup).
-               commonlength = this.diffCommonSuffix( text1, text2 );
-               commonsuffix = text1.substring( text1.length - commonlength );
-               text1 = text1.substring( 0, text1.length - commonlength );
-               text2 = text2.substring( 0, text2.length - commonlength );
+// Add URL-parameter-mapped config values with UI form rendering data
+QUnit.config.urlConfig.push(
+       {
+               id: "hidepassed",
+               label: "Hide passed tests",
+               tooltip: "Only show tests and assertions that fail. Stored as query-strings."
+       },
+       {
+               id: "noglobals",
+               label: "Check for Globals",
+               tooltip: "Enabling this will test if any test introduces new properties on the " +
+                       "global object (`window` in Browsers). Stored as query-strings."
+       },
+       {
+               id: "notrycatch",
+               label: "No try-catch",
+               tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " +
+                       "exceptions in IE reasonable. Stored as query-strings."
+       }
+);
 
-               // Compute the diff on the middle block.
-               diffs = this.diffCompute( text1, text2, checklines, deadline );
+QUnit.begin( function() {
+       var i, option,
+               urlConfig = QUnit.config.urlConfig;
 
-               // Restore the prefix and suffix.
-               if ( commonprefix ) {
-                       diffs.unshift( [ DIFF_EQUAL, commonprefix ] );
-               }
-               if ( commonsuffix ) {
-                       diffs.push( [ DIFF_EQUAL, commonsuffix ] );
-               }
-               this.diffCleanupMerge( diffs );
-               return diffs;
-       };
+       for ( i = 0; i < urlConfig.length; i++ ) {
 
-       /**
-        * Reduce the number of edits by eliminating operationally trivial equalities.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        */
-       DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) {
-               var changes, equalities, equalitiesLength, lastequality,
-                       pointer, preIns, preDel, postIns, postDel;
-               changes = false;
-               equalities = []; // Stack of indices where equalities are found.
-               equalitiesLength = 0; // Keeping our own length var is faster in JS.
-               /** @type {?string} */
-               lastequality = null;
-               // Always equal to diffs[equalities[equalitiesLength - 1]][1]
-               pointer = 0; // Index of current position.
-               // Is there an insertion operation before the last equality.
-               preIns = false;
-               // Is there a deletion operation before the last equality.
-               preDel = false;
-               // Is there an insertion operation after the last equality.
-               postIns = false;
-               // Is there a deletion operation after the last equality.
-               postDel = false;
-               while ( pointer < diffs.length ) {
+               // Options can be either strings or objects with nonempty "id" properties
+               option = QUnit.config.urlConfig[ i ];
+               if ( typeof option !== "string" ) {
+                       option = option.id;
+               }
 
-                       // Equality found.
-                       if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) {
-                               if ( diffs[ pointer ][ 1 ].length < 4 && ( postIns || postDel ) ) {
+               if ( QUnit.config[ option ] === undefined ) {
+                       QUnit.config[ option ] = urlParams[ option ];
+               }
+       }
+} );
 
-                                       // Candidate found.
-                                       equalities[ equalitiesLength++ ] = pointer;
-                                       preIns = postIns;
-                                       preDel = postDel;
-                                       lastequality = diffs[ pointer ][ 1 ];
-                               } else {
+function getUrlParams() {
+       var i, param, name, value;
+       var urlParams = {};
+       var params = location.search.slice( 1 ).split( "&" );
+       var length = params.length;
 
-                                       // Not a candidate, and can never become one.
-                                       equalitiesLength = 0;
-                                       lastequality = null;
-                               }
-                               postIns = postDel = false;
+       for ( i = 0; i < length; i++ ) {
+               if ( params[ i ] ) {
+                       param = params[ i ].split( "=" );
+                       name = decodeURIComponent( param[ 0 ] );
 
-                       // An insertion or deletion.
+                       // Allow just a key to turn on a flag, e.g., test.html?noglobals
+                       value = param.length === 1 ||
+                               decodeURIComponent( param.slice( 1 ).join( "=" ) ) ;
+                       if ( urlParams[ name ] ) {
+                               urlParams[ name ] = [].concat( urlParams[ name ], value );
                        } else {
+                               urlParams[ name ] = value;
+                       }
+               }
+       }
 
-                               if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) {
-                                       postDel = true;
-                               } else {
-                                       postIns = true;
-                               }
+       return urlParams;
+}
 
-                               /*
-                                * Five types to be split:
-                                * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
-                                * <ins>A</ins>X<ins>C</ins><del>D</del>
-                                * <ins>A</ins><del>B</del>X<ins>C</ins>
-                                * <ins>A</del>X<ins>C</ins><del>D</del>
-                                * <ins>A</ins><del>B</del>X<del>C</del>
-                                */
-                               if ( lastequality && ( ( preIns && preDel && postIns && postDel ) ||
-                                               ( ( lastequality.length < 2 ) &&
-                                               ( preIns + preDel + postIns + postDel ) === 3 ) ) ) {
+// Don't load the HTML Reporter on non-browser environments
+if ( typeof window === "undefined" || !window.document ) {
+       return;
+}
 
-                                       // Duplicate record.
-                                       diffs.splice(
-                                               equalities[ equalitiesLength - 1 ],
-                                               0,
-                                               [ DIFF_DELETE, lastequality ]
-                                       );
+// Deprecated QUnit.init - Ref #530
+// Re-initialize the configuration options
+QUnit.init = function() {
+       var config = QUnit.config;
 
-                                       // Change second copy to insert.
-                                       diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
-                                       equalitiesLength--; // Throw away the equality we just deleted;
-                                       lastequality = null;
-                                       if ( preIns && preDel ) {
-                                               // No changes made which could affect previous entry, keep going.
-                                               postIns = postDel = true;
-                                               equalitiesLength = 0;
-                                       } else {
-                                               equalitiesLength--; // Throw away the previous equality.
-                                               pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
-                                               postIns = postDel = false;
-                                       }
-                                       changes = true;
-                               }
-                       }
-                       pointer++;
-               }
+       config.stats = { all: 0, bad: 0 };
+       config.moduleStats = { all: 0, bad: 0 };
+       config.started = 0;
+       config.updateRate = 1000;
+       config.blocking = false;
+       config.autostart = true;
+       config.autorun = false;
+       config.filter = "";
+       config.queue = [];
 
-               if ( changes ) {
-                       this.diffCleanupMerge( diffs );
-               }
-       };
+       appendInterface();
+};
 
-       /**
-        * Convert a diff array into a pretty HTML report.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        * @param {integer} string to be beautified.
-        * @return {string} HTML representation.
-        */
-       DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) {
-               var op, data, x,
-                       html = [];
-               for ( x = 0; x < diffs.length; x++ ) {
-                       op = diffs[ x ][ 0 ]; // Operation (insert, delete, equal)
-                       data = diffs[ x ][ 1 ]; // Text of change.
-                       switch ( op ) {
-                       case DIFF_INSERT:
-                               html[ x ] = "<ins>" + data + "</ins>";
-                               break;
-                       case DIFF_DELETE:
-                               html[ x ] = "<del>" + data + "</del>";
-                               break;
-                       case DIFF_EQUAL:
-                               html[ x ] = "<span>" + data + "</span>";
-                               break;
+var config = QUnit.config,
+       document = window.document,
+       collapseNext = false,
+       hasOwn = Object.prototype.hasOwnProperty,
+       unfilteredUrl = setUrl( { filter: undefined, module: undefined,
+               moduleId: undefined, testId: undefined } ),
+       defined = {
+               sessionStorage: ( function() {
+                       var x = "qunit-test-string";
+                       try {
+                               sessionStorage.setItem( x, x );
+                               sessionStorage.removeItem( x );
+                               return true;
+                       } catch ( e ) {
+                               return false;
                        }
-               }
-               return html.join( "" );
-       };
+               }() )
+       },
+       modulesList = [];
 
-       /**
-        * Determine the common prefix of two strings.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {number} The number of characters common to the start of each
-        *     string.
-        */
-       DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) {
-               var pointermid, pointermax, pointermin, pointerstart;
-               // Quick check for common null cases.
-               if ( !text1 || !text2 || text1.charAt( 0 ) !== text2.charAt( 0 ) ) {
-                       return 0;
-               }
-               // Binary search.
-               // Performance analysis: https://neil.fraser.name/news/2007/10/09/
-               pointermin = 0;
-               pointermax = Math.min( text1.length, text2.length );
-               pointermid = pointermax;
-               pointerstart = 0;
-               while ( pointermin < pointermid ) {
-                       if ( text1.substring( pointerstart, pointermid ) ===
-                                       text2.substring( pointerstart, pointermid ) ) {
-                               pointermin = pointermid;
-                               pointerstart = pointermin;
-                       } else {
-                               pointermax = pointermid;
-                       }
-                       pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
-               }
-               return pointermid;
-       };
+/**
+* Escape text for attribute or text content.
+*/
+function escapeText( s ) {
+       if ( !s ) {
+               return "";
+       }
+       s = s + "";
 
-       /**
-        * Determine the common suffix of two strings.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {number} The number of characters common to the end of each string.
-        */
-       DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) {
-               var pointermid, pointermax, pointermin, pointerend;
-               // Quick check for common null cases.
-               if ( !text1 ||
-                               !text2 ||
-                               text1.charAt( text1.length - 1 ) !== text2.charAt( text2.length - 1 ) ) {
-                       return 0;
-               }
-               // Binary search.
-               // Performance analysis: https://neil.fraser.name/news/2007/10/09/
-               pointermin = 0;
-               pointermax = Math.min( text1.length, text2.length );
-               pointermid = pointermax;
-               pointerend = 0;
-               while ( pointermin < pointermid ) {
-                       if ( text1.substring( text1.length - pointermid, text1.length - pointerend ) ===
-                                       text2.substring( text2.length - pointermid, text2.length - pointerend ) ) {
-                               pointermin = pointermid;
-                               pointerend = pointermin;
-                       } else {
-                               pointermax = pointermid;
-                       }
-                       pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+       // Both single quotes and double quotes (for attributes)
+       return s.replace( /['"<>&]/g, function( s ) {
+               switch ( s ) {
+               case "'":
+                       return "&#039;";
+               case "\"":
+                       return "&quot;";
+               case "<":
+                       return "&lt;";
+               case ">":
+                       return "&gt;";
+               case "&":
+                       return "&amp;";
                }
-               return pointermid;
-       };
-
-       /**
-        * Find the differences between two texts.  Assumes that the texts do not
-        * have any common prefix or suffix.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {boolean} checklines Speedup flag.  If false, then don't run a
-        *     line-level diff first to identify the changed areas.
-        *     If true, then run a faster, slightly less optimal diff.
-        * @param {number} deadline Time when the diff should be complete by.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) {
-               var diffs, longtext, shorttext, i, hm,
-                       text1A, text2A, text1B, text2B,
-                       midCommon, diffsA, diffsB;
+       } );
+}
 
-               if ( !text1 ) {
-                       // Just add some text (speedup).
-                       return [
-                               [ DIFF_INSERT, text2 ]
-                       ];
-               }
+/**
+ * @param {HTMLElement} elem
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvent( elem, type, fn ) {
+       if ( elem.addEventListener ) {
 
-               if ( !text2 ) {
-                       // Just delete some text (speedup).
-                       return [
-                               [ DIFF_DELETE, text1 ]
-                       ];
-               }
+               // Standards-based browsers
+               elem.addEventListener( type, fn, false );
+       } else if ( elem.attachEvent ) {
 
-               longtext = text1.length > text2.length ? text1 : text2;
-               shorttext = text1.length > text2.length ? text2 : text1;
-               i = longtext.indexOf( shorttext );
-               if ( i !== -1 ) {
-                       // Shorter text is inside the longer text (speedup).
-                       diffs = [
-                               [ DIFF_INSERT, longtext.substring( 0, i ) ],
-                               [ DIFF_EQUAL, shorttext ],
-                               [ DIFF_INSERT, longtext.substring( i + shorttext.length ) ]
-                       ];
-                       // Swap insertions for deletions if diff is reversed.
-                       if ( text1.length > text2.length ) {
-                               diffs[ 0 ][ 0 ] = diffs[ 2 ][ 0 ] = DIFF_DELETE;
+               // Support: IE <9
+               elem.attachEvent( "on" + type, function() {
+                       var event = window.event;
+                       if ( !event.target ) {
+                               event.target = event.srcElement || document;
                        }
-                       return diffs;
-               }
 
-               if ( shorttext.length === 1 ) {
-                       // Single character string.
-                       // After the previous speedup, the character can't be an equality.
-                       return [
-                               [ DIFF_DELETE, text1 ],
-                               [ DIFF_INSERT, text2 ]
-                       ];
-               }
+                       fn.call( elem, event );
+               } );
+       }
+}
 
-               // Check to see if the problem can be split in two.
-               hm = this.diffHalfMatch( text1, text2 );
-               if ( hm ) {
-                       // A half-match was found, sort out the return data.
-                       text1A = hm[ 0 ];
-                       text1B = hm[ 1 ];
-                       text2A = hm[ 2 ];
-                       text2B = hm[ 3 ];
-                       midCommon = hm[ 4 ];
-                       // Send both pairs off for separate processing.
-                       diffsA = this.DiffMain( text1A, text2A, checklines, deadline );
-                       diffsB = this.DiffMain( text1B, text2B, checklines, deadline );
-                       // Merge the results.
-                       return diffsA.concat( [
-                               [ DIFF_EQUAL, midCommon ]
-                       ], diffsB );
-               }
+/**
+ * @param {Array|NodeList} elems
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvents( elems, type, fn ) {
+       var i = elems.length;
+       while ( i-- ) {
+               addEvent( elems[ i ], type, fn );
+       }
+}
 
-               if ( checklines && text1.length > 100 && text2.length > 100 ) {
-                       return this.diffLineMode( text1, text2, deadline );
-               }
+function hasClass( elem, name ) {
+       return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0;
+}
 
-               return this.diffBisect( text1, text2, deadline );
-       };
+function addClass( elem, name ) {
+       if ( !hasClass( elem, name ) ) {
+               elem.className += ( elem.className ? " " : "" ) + name;
+       }
+}
 
-       /**
-        * Do the two texts share a substring which is at least half the length of the
-        * longer text?
-        * This speedup can produce non-minimal diffs.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {Array.<string>} Five element Array, containing the prefix of
-        *     text1, the suffix of text1, the prefix of text2, the suffix of
-        *     text2 and the common middle.  Or null if there was no match.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffHalfMatch = function( text1, text2 ) {
-               var longtext, shorttext, dmp,
-                       text1A, text2B, text2A, text1B, midCommon,
-                       hm1, hm2, hm;
+function toggleClass( elem, name, force ) {
+       if ( force || typeof force === "undefined" && !hasClass( elem, name ) ) {
+               addClass( elem, name );
+       } else {
+               removeClass( elem, name );
+       }
+}
 
-               longtext = text1.length > text2.length ? text1 : text2;
-               shorttext = text1.length > text2.length ? text2 : text1;
-               if ( longtext.length < 4 || shorttext.length * 2 < longtext.length ) {
-                       return null; // Pointless.
+function removeClass( elem, name ) {
+       var set = " " + elem.className + " ";
+
+       // Class name may appear multiple times
+       while ( set.indexOf( " " + name + " " ) >= 0 ) {
+               set = set.replace( " " + name + " ", " " );
+       }
+
+       // Trim for prettiness
+       elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" );
+}
+
+function id( name ) {
+       return document.getElementById && document.getElementById( name );
+}
+
+function getUrlConfigHtml() {
+       var i, j, val,
+               escaped, escapedTooltip,
+               selection = false,
+               urlConfig = config.urlConfig,
+               urlConfigHtml = "";
+
+       for ( i = 0; i < urlConfig.length; i++ ) {
+
+               // Options can be either strings or objects with nonempty "id" properties
+               val = config.urlConfig[ i ];
+               if ( typeof val === "string" ) {
+                       val = {
+                               id: val,
+                               label: val
+                       };
                }
-               dmp = this; // 'this' becomes 'window' in a closure.
 
-               /**
-                * Does a substring of shorttext exist within longtext such that the substring
-                * is at least half the length of longtext?
-                * Closure, but does not reference any external variables.
-                * @param {string} longtext Longer string.
-                * @param {string} shorttext Shorter string.
-                * @param {number} i Start index of quarter length substring within longtext.
-                * @return {Array.<string>} Five element Array, containing the prefix of
-                *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
-                *     of shorttext and the common middle.  Or null if there was no match.
-                * @private
-                */
-               function diffHalfMatchI( longtext, shorttext, i ) {
-                       var seed, j, bestCommon, prefixLength, suffixLength,
-                               bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
-                       // Start with a 1/4 length substring at position i as a seed.
-                       seed = longtext.substring( i, i + Math.floor( longtext.length / 4 ) );
-                       j = -1;
-                       bestCommon = "";
-                       while ( ( j = shorttext.indexOf( seed, j + 1 ) ) !== -1 ) {
-                               prefixLength = dmp.diffCommonPrefix( longtext.substring( i ),
-                                       shorttext.substring( j ) );
-                               suffixLength = dmp.diffCommonSuffix( longtext.substring( 0, i ),
-                                       shorttext.substring( 0, j ) );
-                               if ( bestCommon.length < suffixLength + prefixLength ) {
-                                       bestCommon = shorttext.substring( j - suffixLength, j ) +
-                                               shorttext.substring( j, j + prefixLength );
-                                       bestLongtextA = longtext.substring( 0, i - suffixLength );
-                                       bestLongtextB = longtext.substring( i + prefixLength );
-                                       bestShorttextA = shorttext.substring( 0, j - suffixLength );
-                                       bestShorttextB = shorttext.substring( j + prefixLength );
+               escaped = escapeText( val.id );
+               escapedTooltip = escapeText( val.tooltip );
+
+               if ( !val.value || typeof val.value === "string" ) {
+                       urlConfigHtml += "<input id='qunit-urlconfig-" + escaped +
+                               "' name='" + escaped + "' type='checkbox'" +
+                               ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
+                               ( config[ val.id ] ? " checked='checked'" : "" ) +
+                               " title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped +
+                               "' title='" + escapedTooltip + "'>" + val.label + "</label>";
+               } else {
+                       urlConfigHtml += "<label for='qunit-urlconfig-" + escaped +
+                               "' title='" + escapedTooltip + "'>" + val.label +
+                               ": </label><select id='qunit-urlconfig-" + escaped +
+                               "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
+
+                       if ( QUnit.is( "array", val.value ) ) {
+                               for ( j = 0; j < val.value.length; j++ ) {
+                                       escaped = escapeText( val.value[ j ] );
+                                       urlConfigHtml += "<option value='" + escaped + "'" +
+                                               ( config[ val.id ] === val.value[ j ] ?
+                                                       ( selection = true ) && " selected='selected'" : "" ) +
+                                               ">" + escaped + "</option>";
                                }
-                       }
-                       if ( bestCommon.length * 2 >= longtext.length ) {
-                               return [ bestLongtextA, bestLongtextB,
-                                       bestShorttextA, bestShorttextB, bestCommon
-                               ];
                        } else {
-                               return null;
+                               for ( j in val.value ) {
+                                       if ( hasOwn.call( val.value, j ) ) {
+                                               urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
+                                                       ( config[ val.id ] === j ?
+                                                               ( selection = true ) && " selected='selected'" : "" ) +
+                                                       ">" + escapeText( val.value[ j ] ) + "</option>";
+                                       }
+                               }
+                       }
+                       if ( config[ val.id ] && !selection ) {
+                               escaped = escapeText( config[ val.id ] );
+                               urlConfigHtml += "<option value='" + escaped +
+                                       "' selected='selected' disabled='disabled'>" + escaped + "</option>";
                        }
+                       urlConfigHtml += "</select>";
                }
+       }
 
-               // First check if the second quarter is the seed for a half-match.
-               hm1 = diffHalfMatchI( longtext, shorttext,
-                       Math.ceil( longtext.length / 4 ) );
-               // Check again based on the third quarter.
-               hm2 = diffHalfMatchI( longtext, shorttext,
-                       Math.ceil( longtext.length / 2 ) );
-               if ( !hm1 && !hm2 ) {
-                       return null;
-               } else if ( !hm2 ) {
-                       hm = hm1;
-               } else if ( !hm1 ) {
-                       hm = hm2;
-               } else {
-                       // Both matched.  Select the longest.
-                       hm = hm1[ 4 ].length > hm2[ 4 ].length ? hm1 : hm2;
-               }
+       return urlConfigHtml;
+}
 
-               // A half-match was found, sort out the return data.
-               text1A, text1B, text2A, text2B;
-               if ( text1.length > text2.length ) {
-                       text1A = hm[ 0 ];
-                       text1B = hm[ 1 ];
-                       text2A = hm[ 2 ];
-                       text2B = hm[ 3 ];
-               } else {
-                       text2A = hm[ 0 ];
-                       text2B = hm[ 1 ];
-                       text1A = hm[ 2 ];
-                       text1B = hm[ 3 ];
+// Handle "click" events on toolbar checkboxes and "change" for select menus.
+// Updates the URL with the new state of `config.urlConfig` values.
+function toolbarChanged() {
+       var updatedUrl, value, tests,
+               field = this,
+               params = {};
+
+       // Detect if field is a select menu or a checkbox
+       if ( "selectedIndex" in field ) {
+               value = field.options[ field.selectedIndex ].value || undefined;
+       } else {
+               value = field.checked ? ( field.defaultValue || true ) : undefined;
+       }
+
+       params[ field.name ] = value;
+       updatedUrl = setUrl( params );
+
+       // Check if we can apply the change without a page refresh
+       if ( "hidepassed" === field.name && "replaceState" in window.history ) {
+               QUnit.urlParams[ field.name ] = value;
+               config[ field.name ] = value || false;
+               tests = id( "qunit-tests" );
+               if ( tests ) {
+                       toggleClass( tests, "hidepass", value || false );
                }
-               midCommon = hm[ 4 ];
-               return [ text1A, text1B, text2A, text2B, midCommon ];
-       };
+               window.history.replaceState( null, "", updatedUrl );
+       } else {
+               window.location = updatedUrl;
+       }
+}
 
-       /**
-        * Do a quick line-level diff on both strings, then rediff the parts for
-        * greater accuracy.
-        * This speedup can produce non-minimal diffs.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {number} deadline Time when the diff should be complete by.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffLineMode = function( text1, text2, deadline ) {
-               var a, diffs, linearray, pointer, countInsert,
-                       countDelete, textInsert, textDelete, j;
-               // Scan the text on a line-by-line basis first.
-               a = this.diffLinesToChars( text1, text2 );
-               text1 = a.chars1;
-               text2 = a.chars2;
-               linearray = a.lineArray;
+function setUrl( params ) {
+       var key, arrValue, i,
+               querystring = "?",
+               location = window.location;
 
-               diffs = this.DiffMain( text1, text2, false, deadline );
+       params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params );
 
-               // Convert the diff back to original text.
-               this.diffCharsToLines( diffs, linearray );
-               // Eliminate freak matches (e.g. blank lines)
-               this.diffCleanupSemantic( diffs );
+       for ( key in params ) {
 
-               // Rediff any replacement blocks, this time character-by-character.
-               // Add a dummy entry at the end.
-               diffs.push( [ DIFF_EQUAL, "" ] );
-               pointer = 0;
-               countDelete = 0;
-               countInsert = 0;
-               textDelete = "";
-               textInsert = "";
-               while ( pointer < diffs.length ) {
-                       switch ( diffs[ pointer ][ 0 ] ) {
-                       case DIFF_INSERT:
-                               countInsert++;
-                               textInsert += diffs[ pointer ][ 1 ];
-                               break;
-                       case DIFF_DELETE:
-                               countDelete++;
-                               textDelete += diffs[ pointer ][ 1 ];
-                               break;
-                       case DIFF_EQUAL:
-                               // Upon reaching an equality, check for prior redundancies.
-                               if ( countDelete >= 1 && countInsert >= 1 ) {
-                                       // Delete the offending records and add the merged ones.
-                                       diffs.splice( pointer - countDelete - countInsert,
-                                               countDelete + countInsert );
-                                       pointer = pointer - countDelete - countInsert;
-                                       a = this.DiffMain( textDelete, textInsert, false, deadline );
-                                       for ( j = a.length - 1; j >= 0; j-- ) {
-                                               diffs.splice( pointer, 0, a[ j ] );
-                                       }
-                                       pointer = pointer + a.length;
+               // Skip inherited or undefined properties
+               if ( hasOwn.call( params, key ) && params[ key ] !== undefined ) {
+
+                       // Output a parameter for each value of this key (but usually just one)
+                       arrValue = [].concat( params[ key ] );
+                       for ( i = 0; i < arrValue.length; i++ ) {
+                               querystring += encodeURIComponent( key );
+                               if ( arrValue[ i ] !== true ) {
+                                       querystring += "=" + encodeURIComponent( arrValue[ i ] );
                                }
-                               countInsert = 0;
-                               countDelete = 0;
-                               textDelete = "";
-                               textInsert = "";
-                               break;
+                               querystring += "&";
                        }
-                       pointer++;
                }
-               diffs.pop(); // Remove the dummy entry at the end.
+       }
+       return location.protocol + "//" + location.host +
+               location.pathname + querystring.slice( 0, -1 );
+}
 
-               return diffs;
-       };
+function applyUrlParams() {
+       var selectedModule,
+               modulesList = id( "qunit-modulefilter" ),
+               filter = id( "qunit-filter-input" ).value;
 
-       /**
-        * Find the 'middle snake' of a diff, split the problem in two
-        * and return the recursively constructed diff.
-        * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {number} deadline Time at which to bail if not yet complete.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffBisect = function( text1, text2, deadline ) {
-               var text1Length, text2Length, maxD, vOffset, vLength,
-                       v1, v2, x, delta, front, k1start, k1end, k2start,
-                       k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
-               // Cache the text lengths to prevent multiple calls.
-               text1Length = text1.length;
-               text2Length = text2.length;
-               maxD = Math.ceil( ( text1Length + text2Length ) / 2 );
-               vOffset = maxD;
-               vLength = 2 * maxD;
-               v1 = new Array( vLength );
-               v2 = new Array( vLength );
-               // Setting all elements to -1 is faster in Chrome & Firefox than mixing
-               // integers and undefined.
-               for ( x = 0; x < vLength; x++ ) {
-                       v1[ x ] = -1;
-                       v2[ x ] = -1;
+       selectedModule = modulesList ?
+               decodeURIComponent( modulesList.options[ modulesList.selectedIndex ].value ) :
+               undefined;
+
+       window.location = setUrl( {
+               module: ( selectedModule === "" ) ? undefined : selectedModule,
+               filter: ( filter === "" ) ? undefined : filter,
+
+               // Remove moduleId and testId filters
+               moduleId: undefined,
+               testId: undefined
+       } );
+}
+
+function toolbarUrlConfigContainer() {
+       var urlConfigContainer = document.createElement( "span" );
+
+       urlConfigContainer.innerHTML = getUrlConfigHtml();
+       addClass( urlConfigContainer, "qunit-url-config" );
+
+       // For oldIE support:
+       // * Add handlers to the individual elements instead of the container
+       // * Use "click" instead of "change" for checkboxes
+       addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged );
+       addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged );
+
+       return urlConfigContainer;
+}
+
+function toolbarLooseFilter() {
+       var filter = document.createElement( "form" ),
+               label = document.createElement( "label" ),
+               input = document.createElement( "input" ),
+               button = document.createElement( "button" );
+
+       addClass( filter, "qunit-filter" );
+
+       label.innerHTML = "Filter: ";
+
+       input.type = "text";
+       input.value = config.filter || "";
+       input.name = "filter";
+       input.id = "qunit-filter-input";
+
+       button.innerHTML = "Go";
+
+       label.appendChild( input );
+
+       filter.appendChild( label );
+       filter.appendChild( button );
+       addEvent( filter, "submit", function( ev ) {
+               applyUrlParams();
+
+               if ( ev && ev.preventDefault ) {
+                       ev.preventDefault();
                }
-               v1[ vOffset + 1 ] = 0;
-               v2[ vOffset + 1 ] = 0;
-               delta = text1Length - text2Length;
-               // If the total number of characters is odd, then the front path will collide
-               // with the reverse path.
-               front = ( delta % 2 !== 0 );
-               // Offsets for start and end of k loop.
-               // Prevents mapping of space beyond the grid.
-               k1start = 0;
-               k1end = 0;
-               k2start = 0;
-               k2end = 0;
-               for ( d = 0; d < maxD; d++ ) {
-                       // Bail out if deadline is reached.
-                       if ( ( new Date() ).getTime() > deadline ) {
-                               break;
-                       }
 
-                       // Walk the front path one step.
-                       for ( k1 = -d + k1start; k1 <= d - k1end; k1 += 2 ) {
-                               k1Offset = vOffset + k1;
-                               if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) {
-                                       x1 = v1[ k1Offset + 1 ];
-                               } else {
-                                       x1 = v1[ k1Offset - 1 ] + 1;
-                               }
-                               y1 = x1 - k1;
-                               while ( x1 < text1Length && y1 < text2Length &&
-                                       text1.charAt( x1 ) === text2.charAt( y1 ) ) {
-                                       x1++;
-                                       y1++;
-                               }
-                               v1[ k1Offset ] = x1;
-                               if ( x1 > text1Length ) {
-                                       // Ran off the right of the graph.
-                                       k1end += 2;
-                               } else if ( y1 > text2Length ) {
-                                       // Ran off the bottom of the graph.
-                                       k1start += 2;
-                               } else if ( front ) {
-                                       k2Offset = vOffset + delta - k1;
-                                       if ( k2Offset >= 0 && k2Offset < vLength && v2[ k2Offset ] !== -1 ) {
-                                               // Mirror x2 onto top-left coordinate system.
-                                               x2 = text1Length - v2[ k2Offset ];
-                                               if ( x1 >= x2 ) {
-                                                       // Overlap detected.
-                                                       return this.diffBisectSplit( text1, text2, x1, y1, deadline );
-                                               }
-                                       }
-                               }
-                       }
+               return false;
+       } );
+
+       return filter;
+}
+
+function toolbarModuleFilterHtml() {
+       var i,
+               moduleFilterHtml = "";
+
+       if ( !modulesList.length ) {
+               return false;
+       }
+
+       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" +
+               "<select id='qunit-modulefilter' name='modulefilter'><option value='' " +
+               ( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) +
+               ">< All Modules ></option>";
+
+       for ( i = 0; i < modulesList.length; i++ ) {
+               moduleFilterHtml += "<option value='" +
+                       escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " +
+                       ( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) +
+                       ">" + escapeText( modulesList[ i ] ) + "</option>";
+       }
+       moduleFilterHtml += "</select>";
+
+       return moduleFilterHtml;
+}
+
+function toolbarModuleFilter() {
+       var toolbar = id( "qunit-testrunner-toolbar" ),
+               moduleFilter = document.createElement( "span" ),
+               moduleFilterHtml = toolbarModuleFilterHtml();
+
+       if ( !toolbar || !moduleFilterHtml ) {
+               return false;
+       }
+
+       moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
+       moduleFilter.innerHTML = moduleFilterHtml;
+
+       addEvent( moduleFilter.lastChild, "change", applyUrlParams );
+
+       toolbar.appendChild( moduleFilter );
+}
+
+function appendToolbar() {
+       var toolbar = id( "qunit-testrunner-toolbar" );
+
+       if ( toolbar ) {
+               toolbar.appendChild( toolbarUrlConfigContainer() );
+               toolbar.appendChild( toolbarLooseFilter() );
+               toolbarModuleFilter();
+       }
+}
+
+function appendHeader() {
+       var header = id( "qunit-header" );
+
+       if ( header ) {
+               header.innerHTML = "<a href='" + escapeText( unfilteredUrl ) + "'>" + header.innerHTML +
+                       "</a> ";
+       }
+}
+
+function appendBanner() {
+       var banner = id( "qunit-banner" );
+
+       if ( banner ) {
+               banner.className = "";
+       }
+}
+
+function appendTestResults() {
+       var tests = id( "qunit-tests" ),
+               result = id( "qunit-testresult" );
+
+       if ( result ) {
+               result.parentNode.removeChild( result );
+       }
+
+       if ( tests ) {
+               tests.innerHTML = "";
+               result = document.createElement( "p" );
+               result.id = "qunit-testresult";
+               result.className = "result";
+               tests.parentNode.insertBefore( result, tests );
+               result.innerHTML = "Running...<br />&#160;";
+       }
+}
+
+function storeFixture() {
+       var fixture = id( "qunit-fixture" );
+       if ( fixture ) {
+               config.fixture = fixture.innerHTML;
+       }
+}
+
+function appendFilteredTest() {
+       var testId = QUnit.config.testId;
+       if ( !testId || testId.length <= 0 ) {
+               return "";
+       }
+       return "<div id='qunit-filteredTest'>Rerunning selected tests: " +
+               escapeText( testId.join( ", " ) ) +
+               " <a id='qunit-clearFilter' href='" +
+               escapeText( unfilteredUrl ) +
+               "'>Run all tests</a></div>";
+}
+
+function appendUserAgent() {
+       var userAgent = id( "qunit-userAgent" );
+
+       if ( userAgent ) {
+               userAgent.innerHTML = "";
+               userAgent.appendChild(
+                       document.createTextNode(
+                               "QUnit " + QUnit.version + "; " + navigator.userAgent
+                       )
+               );
+       }
+}
 
-                       // Walk the reverse path one step.
-                       for ( k2 = -d + k2start; k2 <= d - k2end; k2 += 2 ) {
-                               k2Offset = vOffset + k2;
-                               if ( k2 === -d || ( k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) {
-                                       x2 = v2[ k2Offset + 1 ];
-                               } else {
-                                       x2 = v2[ k2Offset - 1 ] + 1;
-                               }
-                               y2 = x2 - k2;
-                               while ( x2 < text1Length && y2 < text2Length &&
-                                       text1.charAt( text1Length - x2 - 1 ) ===
-                                       text2.charAt( text2Length - y2 - 1 ) ) {
-                                       x2++;
-                                       y2++;
-                               }
-                               v2[ k2Offset ] = x2;
-                               if ( x2 > text1Length ) {
-                                       // Ran off the left of the graph.
-                                       k2end += 2;
-                               } else if ( y2 > text2Length ) {
-                                       // Ran off the top of the graph.
-                                       k2start += 2;
-                               } else if ( !front ) {
-                                       k1Offset = vOffset + delta - k2;
-                                       if ( k1Offset >= 0 && k1Offset < vLength && v1[ k1Offset ] !== -1 ) {
-                                               x1 = v1[ k1Offset ];
-                                               y1 = vOffset + x1 - k1Offset;
-                                               // Mirror x2 onto top-left coordinate system.
-                                               x2 = text1Length - x2;
-                                               if ( x1 >= x2 ) {
-                                                       // Overlap detected.
-                                                       return this.diffBisectSplit( text1, text2, x1, y1, deadline );
-                                               }
-                                       }
-                               }
-                       }
+function appendInterface() {
+       var qunit = id( "qunit" );
+
+       if ( qunit ) {
+               qunit.innerHTML =
+                       "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+                       "<h2 id='qunit-banner'></h2>" +
+                       "<div id='qunit-testrunner-toolbar'></div>" +
+                       appendFilteredTest() +
+                       "<h2 id='qunit-userAgent'></h2>" +
+                       "<ol id='qunit-tests'></ol>";
+       }
+
+       appendHeader();
+       appendBanner();
+       appendTestResults();
+       appendUserAgent();
+       appendToolbar();
+}
+
+function appendTestsList( modules ) {
+       var i, l, x, z, test, moduleObj;
+
+       for ( i = 0, l = modules.length; i < l; i++ ) {
+               moduleObj = modules[ i ];
+
+               for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) {
+                       test = moduleObj.tests[ x ];
+
+                       appendTest( test.name, test.testId, moduleObj.name );
                }
-               // Diff took too long and hit the deadline or
-               // number of diffs equals number of characters, no commonality at all.
-               return [
-                       [ DIFF_DELETE, text1 ],
-                       [ DIFF_INSERT, text2 ]
-               ];
-       };
+       }
+}
 
-       /**
-        * Given the location of the 'middle snake', split the diff in two parts
-        * and recurse.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {number} x Index of split point in text1.
-        * @param {number} y Index of split point in text2.
-        * @param {number} deadline Time at which to bail if not yet complete.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) {
-               var text1a, text1b, text2a, text2b, diffs, diffsb;
-               text1a = text1.substring( 0, x );
-               text2a = text2.substring( 0, y );
-               text1b = text1.substring( x );
-               text2b = text2.substring( y );
+function appendTest( name, testId, moduleName ) {
+       var title, rerunTrigger, testBlock, assertList,
+               tests = id( "qunit-tests" );
 
-               // Compute both diffs serially.
-               diffs = this.DiffMain( text1a, text2a, false, deadline );
-               diffsb = this.DiffMain( text1b, text2b, false, deadline );
+       if ( !tests ) {
+               return;
+       }
 
-               return diffs.concat( diffsb );
-       };
+       title = document.createElement( "strong" );
+       title.innerHTML = getNameHtml( name, moduleName );
 
-       /**
-        * Reduce the number of edits by eliminating semantically trivial equalities.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        */
-       DiffMatchPatch.prototype.diffCleanupSemantic = function( diffs ) {
-               var changes, equalities, equalitiesLength, lastequality,
-                       pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1,
-                       lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
-               changes = false;
-               equalities = []; // Stack of indices where equalities are found.
-               equalitiesLength = 0; // Keeping our own length var is faster in JS.
-               /** @type {?string} */
-               lastequality = null;
-               // Always equal to diffs[equalities[equalitiesLength - 1]][1]
-               pointer = 0; // Index of current position.
-               // Number of characters that changed prior to the equality.
-               lengthInsertions1 = 0;
-               lengthDeletions1 = 0;
-               // Number of characters that changed after the equality.
-               lengthInsertions2 = 0;
-               lengthDeletions2 = 0;
-               while ( pointer < diffs.length ) {
-                       if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found.
-                               equalities[ equalitiesLength++ ] = pointer;
-                               lengthInsertions1 = lengthInsertions2;
-                               lengthDeletions1 = lengthDeletions2;
-                               lengthInsertions2 = 0;
-                               lengthDeletions2 = 0;
-                               lastequality = diffs[ pointer ][ 1 ];
-                       } else { // An insertion or deletion.
-                               if ( diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
-                                       lengthInsertions2 += diffs[ pointer ][ 1 ].length;
-                               } else {
-                                       lengthDeletions2 += diffs[ pointer ][ 1 ].length;
-                               }
-                               // Eliminate an equality that is smaller or equal to the edits on both
-                               // sides of it.
-                               if ( lastequality && ( lastequality.length <=
-                                               Math.max( lengthInsertions1, lengthDeletions1 ) ) &&
-                                               ( lastequality.length <= Math.max( lengthInsertions2,
-                                                       lengthDeletions2 ) ) ) {
+       rerunTrigger = document.createElement( "a" );
+       rerunTrigger.innerHTML = "Rerun";
+       rerunTrigger.href = setUrl( { testId: testId } );
 
-                                       // Duplicate record.
-                                       diffs.splice(
-                                               equalities[ equalitiesLength - 1 ],
-                                               0,
-                                               [ DIFF_DELETE, lastequality ]
-                                       );
+       testBlock = document.createElement( "li" );
+       testBlock.appendChild( title );
+       testBlock.appendChild( rerunTrigger );
+       testBlock.id = "qunit-test-output-" + testId;
 
-                                       // Change second copy to insert.
-                                       diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
+       assertList = document.createElement( "ol" );
+       assertList.className = "qunit-assert-list";
 
-                                       // Throw away the equality we just deleted.
-                                       equalitiesLength--;
+       testBlock.appendChild( assertList );
 
-                                       // Throw away the previous equality (it needs to be reevaluated).
-                                       equalitiesLength--;
-                                       pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
+       tests.appendChild( testBlock );
+}
 
-                                       // Reset the counters.
-                                       lengthInsertions1 = 0;
-                                       lengthDeletions1 = 0;
-                                       lengthInsertions2 = 0;
-                                       lengthDeletions2 = 0;
-                                       lastequality = null;
-                                       changes = true;
-                               }
-                       }
-                       pointer++;
-               }
+// HTML Reporter initialization and load
+QUnit.begin( function( details ) {
+       var i, moduleObj, tests;
 
-               // Normalize the diff.
-               if ( changes ) {
-                       this.diffCleanupMerge( diffs );
+       // Sort modules by name for the picker
+       for ( i = 0; i < details.modules.length; i++ ) {
+               moduleObj = details.modules[ i ];
+               if ( moduleObj.name ) {
+                       modulesList.push( moduleObj.name );
                }
+       }
+       modulesList.sort( function( a, b ) {
+               return a.localeCompare( b );
+       } );
 
-               // Find any overlaps between deletions and insertions.
-               // e.g: <del>abcxxx</del><ins>xxxdef</ins>
-               //   -> <del>abc</del>xxx<ins>def</ins>
-               // e.g: <del>xxxabc</del><ins>defxxx</ins>
-               //   -> <ins>def</ins>xxx<del>abc</del>
-               // Only extract an overlap if it is as big as the edit ahead or behind it.
-               pointer = 1;
-               while ( pointer < diffs.length ) {
-                       if ( diffs[ pointer - 1 ][ 0 ] === DIFF_DELETE &&
-                                       diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
-                               deletion = diffs[ pointer - 1 ][ 1 ];
-                               insertion = diffs[ pointer ][ 1 ];
-                               overlapLength1 = this.diffCommonOverlap( deletion, insertion );
-                               overlapLength2 = this.diffCommonOverlap( insertion, deletion );
-                               if ( overlapLength1 >= overlapLength2 ) {
-                                       if ( overlapLength1 >= deletion.length / 2 ||
-                                                       overlapLength1 >= insertion.length / 2 ) {
-                                               // Overlap found.  Insert an equality and trim the surrounding edits.
-                                               diffs.splice(
-                                                       pointer,
-                                                       0,
-                                                       [ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ]
-                                               );
-                                               diffs[ pointer - 1 ][ 1 ] =
-                                                       deletion.substring( 0, deletion.length - overlapLength1 );
-                                               diffs[ pointer + 1 ][ 1 ] = insertion.substring( overlapLength1 );
-                                               pointer++;
-                                       }
-                               } else {
-                                       if ( overlapLength2 >= deletion.length / 2 ||
-                                                       overlapLength2 >= insertion.length / 2 ) {
+       // Capture fixture HTML from the page
+       storeFixture();
 
-                                               // Reverse overlap found.
-                                               // Insert an equality and swap and trim the surrounding edits.
-                                               diffs.splice(
-                                                       pointer,
-                                                       0,
-                                                       [ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ]
-                                               );
+       // Initialize QUnit elements
+       appendInterface();
+       appendTestsList( details.modules );
+       tests = id( "qunit-tests" );
+       if ( tests && config.hidepassed ) {
+               addClass( tests, "hidepass" );
+       }
+} );
+
+QUnit.done( function( details ) {
+       var i, key,
+               banner = id( "qunit-banner" ),
+               tests = id( "qunit-tests" ),
+               html = [
+                       "Tests completed in ",
+                       details.runtime,
+                       " milliseconds.<br />",
+                       "<span class='passed'>",
+                       details.passed,
+                       "</span> assertions of <span class='total'>",
+                       details.total,
+                       "</span> passed, <span class='failed'>",
+                       details.failed,
+                       "</span> failed."
+               ].join( "" );
+
+       if ( banner ) {
+               banner.className = details.failed ? "qunit-fail" : "qunit-pass";
+       }
+
+       if ( tests ) {
+               id( "qunit-testresult" ).innerHTML = html;
+       }
+
+       if ( config.altertitle && document.title ) {
 
-                                               diffs[ pointer - 1 ][ 0 ] = DIFF_INSERT;
-                                               diffs[ pointer - 1 ][ 1 ] =
-                                                       insertion.substring( 0, insertion.length - overlapLength2 );
-                                               diffs[ pointer + 1 ][ 0 ] = DIFF_DELETE;
-                                               diffs[ pointer + 1 ][ 1 ] =
-                                                       deletion.substring( overlapLength2 );
-                                               pointer++;
-                                       }
-                               }
-                               pointer++;
+               // Show ✖ for good, ✔ for bad suite result in title
+               // use escape sequences in case file gets loaded with non-utf-8-charset
+               document.title = [
+                       ( details.failed ? "\u2716" : "\u2714" ),
+                       document.title.replace( /^[\u2714\u2716] /i, "" )
+               ].join( " " );
+       }
+
+       // Clear own sessionStorage items if all tests passed
+       if ( config.reorder && defined.sessionStorage && details.failed === 0 ) {
+               for ( i = 0; i < sessionStorage.length; i++ ) {
+                       key = sessionStorage.key( i++ );
+                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
+                               sessionStorage.removeItem( key );
                        }
-                       pointer++;
                }
-       };
+       }
 
-       /**
-        * Determine if the suffix of one string is the prefix of another.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {number} The number of characters common to the end of the first
-        *     string and the start of the second string.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffCommonOverlap = function( text1, text2 ) {
-               var text1Length, text2Length, textLength,
-                       best, length, pattern, found;
-               // Cache the text lengths to prevent multiple calls.
-               text1Length = text1.length;
-               text2Length = text2.length;
-               // Eliminate the null case.
-               if ( text1Length === 0 || text2Length === 0 ) {
-                       return 0;
-               }
-               // Truncate the longer string.
-               if ( text1Length > text2Length ) {
-                       text1 = text1.substring( text1Length - text2Length );
-               } else if ( text1Length < text2Length ) {
-                       text2 = text2.substring( 0, text1Length );
-               }
-               textLength = Math.min( text1Length, text2Length );
-               // Quick check for the worst case.
-               if ( text1 === text2 ) {
-                       return textLength;
-               }
+       // Scroll back to top to show results
+       if ( config.scrolltop && window.scrollTo ) {
+               window.scrollTo( 0, 0 );
+       }
+} );
 
-               // Start by looking for a single character match
-               // and increase length until no match is found.
-               // Performance analysis: https://neil.fraser.name/news/2010/11/04/
-               best = 0;
-               length = 1;
-               while ( true ) {
-                       pattern = text1.substring( textLength - length );
-                       found = text2.indexOf( pattern );
-                       if ( found === -1 ) {
-                               return best;
-                       }
-                       length += found;
-                       if ( found === 0 || text1.substring( textLength - length ) ===
-                                       text2.substring( 0, length ) ) {
-                               best = length;
-                               length++;
-                       }
-               }
-       };
+function getNameHtml( name, module ) {
+       var nameHtml = "";
 
-       /**
-        * Split two texts into an array of strings.  Reduce the texts to a string of
-        * hashes where each Unicode character represents one line.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
-        *     An object containing the encoded text1, the encoded text2 and
-        *     the array of unique strings.
-        *     The zeroth element of the array of unique strings is intentionally blank.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffLinesToChars = function( text1, text2 ) {
-               var lineArray, lineHash, chars1, chars2;
-               lineArray = []; // e.g. lineArray[4] === 'Hello\n'
-               lineHash = {}; // e.g. lineHash['Hello\n'] === 4
+       if ( module ) {
+               nameHtml = "<span class='module-name'>" + escapeText( module ) + "</span>: ";
+       }
 
-               // '\x00' is a valid character, but various debuggers don't like it.
-               // So we'll insert a junk entry to avoid generating a null character.
-               lineArray[ 0 ] = "";
+       nameHtml += "<span class='test-name'>" + escapeText( name ) + "</span>";
 
-               /**
-                * Split a text into an array of strings.  Reduce the texts to a string of
-                * hashes where each Unicode character represents one line.
-                * Modifies linearray and linehash through being a closure.
-                * @param {string} text String to encode.
-                * @return {string} Encoded string.
-                * @private
-                */
-               function diffLinesToCharsMunge( text ) {
-                       var chars, lineStart, lineEnd, lineArrayLength, line;
-                       chars = "";
-                       // Walk the text, pulling out a substring for each line.
-                       // text.split('\n') would would temporarily double our memory footprint.
-                       // Modifying text would create many large strings to garbage collect.
-                       lineStart = 0;
-                       lineEnd = -1;
-                       // Keeping our own length variable is faster than looking it up.
-                       lineArrayLength = lineArray.length;
-                       while ( lineEnd < text.length - 1 ) {
-                               lineEnd = text.indexOf( "\n", lineStart );
-                               if ( lineEnd === -1 ) {
-                                       lineEnd = text.length - 1;
-                               }
-                               line = text.substring( lineStart, lineEnd + 1 );
-                               lineStart = lineEnd + 1;
+       return nameHtml;
+}
 
-                               if ( lineHash.hasOwnProperty ? lineHash.hasOwnProperty( line ) :
-                                                       ( lineHash[ line ] !== undefined ) ) {
-                                       chars += String.fromCharCode( lineHash[ line ] );
-                               } else {
-                                       chars += String.fromCharCode( lineArrayLength );
-                                       lineHash[ line ] = lineArrayLength;
-                                       lineArray[ lineArrayLength++ ] = line;
-                               }
-                       }
-                       return chars;
-               }
+QUnit.testStart( function( details ) {
+       var running, testBlock, bad;
 
-               chars1 = diffLinesToCharsMunge( text1 );
-               chars2 = diffLinesToCharsMunge( text2 );
-               return {
-                       chars1: chars1,
-                       chars2: chars2,
-                       lineArray: lineArray
-               };
-       };
+       testBlock = id( "qunit-test-output-" + details.testId );
+       if ( testBlock ) {
+               testBlock.className = "running";
+       } else {
 
-       /**
-        * Rehydrate the text in a diff from a string of line hashes to real lines of
-        * text.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        * @param {!Array.<string>} lineArray Array of unique strings.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) {
-               var x, chars, text, y;
-               for ( x = 0; x < diffs.length; x++ ) {
-                       chars = diffs[ x ][ 1 ];
-                       text = [];
-                       for ( y = 0; y < chars.length; y++ ) {
-                               text[ y ] = lineArray[ chars.charCodeAt( y ) ];
-                       }
-                       diffs[ x ][ 1 ] = text.join( "" );
-               }
-       };
+               // Report later registered tests
+               appendTest( details.name, details.testId, details.module );
+       }
 
-       /**
-        * Reorder and merge like edit sections.  Merge equalities.
-        * Any edit section can move as long as it doesn't cross an equality.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        */
-       DiffMatchPatch.prototype.diffCleanupMerge = function( diffs ) {
-               var pointer, countDelete, countInsert, textInsert, textDelete,
-                       commonlength, changes, diffPointer, position;
-               diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end.
-               pointer = 0;
-               countDelete = 0;
-               countInsert = 0;
-               textDelete = "";
-               textInsert = "";
-               commonlength;
-               while ( pointer < diffs.length ) {
-                       switch ( diffs[ pointer ][ 0 ] ) {
-                       case DIFF_INSERT:
-                               countInsert++;
-                               textInsert += diffs[ pointer ][ 1 ];
-                               pointer++;
-                               break;
-                       case DIFF_DELETE:
-                               countDelete++;
-                               textDelete += diffs[ pointer ][ 1 ];
-                               pointer++;
-                               break;
-                       case DIFF_EQUAL:
-                               // Upon reaching an equality, check for prior redundancies.
-                               if ( countDelete + countInsert > 1 ) {
-                                       if ( countDelete !== 0 && countInsert !== 0 ) {
-                                               // Factor out any common prefixes.
-                                               commonlength = this.diffCommonPrefix( textInsert, textDelete );
-                                               if ( commonlength !== 0 ) {
-                                                       if ( ( pointer - countDelete - countInsert ) > 0 &&
-                                                                       diffs[ pointer - countDelete - countInsert - 1 ][ 0 ] ===
-                                                                       DIFF_EQUAL ) {
-                                                               diffs[ pointer - countDelete - countInsert - 1 ][ 1 ] +=
-                                                                       textInsert.substring( 0, commonlength );
-                                                       } else {
-                                                               diffs.splice( 0, 0, [ DIFF_EQUAL,
-                                                                       textInsert.substring( 0, commonlength )
-                                                               ] );
-                                                               pointer++;
-                                                       }
-                                                       textInsert = textInsert.substring( commonlength );
-                                                       textDelete = textDelete.substring( commonlength );
-                                               }
-                                               // Factor out any common suffixies.
-                                               commonlength = this.diffCommonSuffix( textInsert, textDelete );
-                                               if ( commonlength !== 0 ) {
-                                                       diffs[ pointer ][ 1 ] = textInsert.substring( textInsert.length -
-                                                                       commonlength ) + diffs[ pointer ][ 1 ];
-                                                       textInsert = textInsert.substring( 0, textInsert.length -
-                                                               commonlength );
-                                                       textDelete = textDelete.substring( 0, textDelete.length -
-                                                               commonlength );
-                                               }
-                                       }
-                                       // Delete the offending records and add the merged ones.
-                                       if ( countDelete === 0 ) {
-                                               diffs.splice( pointer - countInsert,
-                                                       countDelete + countInsert, [ DIFF_INSERT, textInsert ] );
-                                       } else if ( countInsert === 0 ) {
-                                               diffs.splice( pointer - countDelete,
-                                                       countDelete + countInsert, [ DIFF_DELETE, textDelete ] );
-                                       } else {
-                                               diffs.splice(
-                                                       pointer - countDelete - countInsert,
-                                                       countDelete + countInsert,
-                                                       [ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ]
-                                               );
-                                       }
-                                       pointer = pointer - countDelete - countInsert +
-                                               ( countDelete ? 1 : 0 ) + ( countInsert ? 1 : 0 ) + 1;
-                               } else if ( pointer !== 0 && diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL ) {
+       running = id( "qunit-testresult" );
+       if ( running ) {
+               bad = QUnit.config.reorder && defined.sessionStorage &&
+                       +sessionStorage.getItem( "qunit-test-" + details.module + "-" + details.name );
+
+               running.innerHTML = ( bad ?
+                       "Rerunning previously failed test: <br />" :
+                       "Running: <br />" ) +
+                       getNameHtml( details.name, details.module );
+       }
 
-                                       // Merge this equality with the previous one.
-                                       diffs[ pointer - 1 ][ 1 ] += diffs[ pointer ][ 1 ];
-                                       diffs.splice( pointer, 1 );
-                               } else {
-                                       pointer++;
-                               }
-                               countInsert = 0;
-                               countDelete = 0;
-                               textDelete = "";
-                               textInsert = "";
-                               break;
-                       }
-               }
-               if ( diffs[ diffs.length - 1 ][ 1 ] === "" ) {
-                       diffs.pop(); // Remove the dummy entry at the end.
-               }
+} );
 
-               // Second pass: look for single edits surrounded on both sides by equalities
-               // which can be shifted sideways to eliminate an equality.
-               // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
-               changes = false;
-               pointer = 1;
+function stripHtml( string ) {
 
-               // Intentionally ignore the first and last element (don't need checking).
-               while ( pointer < diffs.length - 1 ) {
-                       if ( diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL &&
-                                       diffs[ pointer + 1 ][ 0 ] === DIFF_EQUAL ) {
+       // Strip tags, html entity and whitespaces
+       return string.replace( /<\/?[^>]+(>|$)/g, "" ).replace( /\&quot;/g, "" ).replace( /\s+/g, "" );
+}
 
-                               diffPointer = diffs[ pointer ][ 1 ];
-                               position = diffPointer.substring(
-                                       diffPointer.length - diffs[ pointer - 1 ][ 1 ].length
-                               );
+QUnit.log( function( details ) {
+       var assertList, assertLi,
+               message, expected, actual, diff,
+               showDiff = false,
+               testItem = id( "qunit-test-output-" + details.testId );
 
-                               // This is a single edit surrounded by equalities.
-                               if ( position === diffs[ pointer - 1 ][ 1 ] ) {
+       if ( !testItem ) {
+               return;
+       }
 
-                                       // Shift the edit over the previous equality.
-                                       diffs[ pointer ][ 1 ] = diffs[ pointer - 1 ][ 1 ] +
-                                               diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer ][ 1 ].length -
-                                                       diffs[ pointer - 1 ][ 1 ].length );
-                                       diffs[ pointer + 1 ][ 1 ] =
-                                               diffs[ pointer - 1 ][ 1 ] + diffs[ pointer + 1 ][ 1 ];
-                                       diffs.splice( pointer - 1, 1 );
-                                       changes = true;
-                               } else if ( diffPointer.substring( 0, diffs[ pointer + 1 ][ 1 ].length ) ===
-                                               diffs[ pointer + 1 ][ 1 ] ) {
+       message = escapeText( details.message ) || ( details.result ? "okay" : "failed" );
+       message = "<span class='test-message'>" + message + "</span>";
+       message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
 
-                                       // Shift the edit over the next equality.
-                                       diffs[ pointer - 1 ][ 1 ] += diffs[ pointer + 1 ][ 1 ];
-                                       diffs[ pointer ][ 1 ] =
-                                               diffs[ pointer ][ 1 ].substring( diffs[ pointer + 1 ][ 1 ].length ) +
-                                               diffs[ pointer + 1 ][ 1 ];
-                                       diffs.splice( pointer + 1, 1 );
-                                       changes = true;
-                               }
-                       }
-                       pointer++;
-               }
-               // If shifts were made, the diff needs reordering and another shift sweep.
-               if ( changes ) {
-                       this.diffCleanupMerge( diffs );
+       // The pushFailure doesn't provide details.expected
+       // when it calls, it's implicit to also not show expected and diff stuff
+       // Also, we need to check details.expected existence, as it can exist and be undefined
+       if ( !details.result && hasOwn.call( details, "expected" ) ) {
+               if ( details.negative ) {
+                       expected = "NOT " + QUnit.dump.parse( details.expected );
+               } else {
+                       expected = QUnit.dump.parse( details.expected );
                }
-       };
 
-       return function( o, n ) {
-               var diff, output, text;
-               diff = new DiffMatchPatch();
-               output = diff.DiffMain( o, n );
-               diff.diffCleanupEfficiency( output );
-               text = diff.diffPrettyHtml( output );
+               actual = QUnit.dump.parse( details.actual );
+               message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" +
+                       escapeText( expected ) +
+                       "</pre></td></tr>";
 
-               return text;
-       };
-}() );
+               if ( actual !== expected ) {
 
-// Get a reference to the global object, like window in browsers
-}( (function() {
-       return this;
-})() ));
+                       message += "<tr class='test-actual'><th>Result: </th><td><pre>" +
+                               escapeText( actual ) + "</pre></td></tr>";
 
-(function() {
+                       // Don't show diff if actual or expected are booleans
+                       if ( !( /^(true|false)$/.test( actual ) ) &&
+                                       !( /^(true|false)$/.test( expected ) ) ) {
+                               diff = QUnit.diff( expected, actual );
+                               showDiff = stripHtml( diff ).length !==
+                                       stripHtml( expected ).length +
+                                       stripHtml( actual ).length;
+                       }
 
-// Don't load the HTML Reporter on non-Browser environments
-if ( typeof window === "undefined" || !window.document ) {
-       return;
-}
+                       // Don't show diff if expected and actual are totally different
+                       if ( showDiff ) {
+                               message += "<tr class='test-diff'><th>Diff: </th><td><pre>" +
+                                       diff + "</pre></td></tr>";
+                       }
+               } else if ( expected.indexOf( "[object Array]" ) !== -1 ||
+                               expected.indexOf( "[object Object]" ) !== -1 ) {
+                       message += "<tr class='test-message'><th>Message: </th><td>" +
+                               "Diff suppressed as the depth of object is more than current max depth (" +
+                               QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " +
+                               " run with a higher max depth or <a href='" +
+                               escapeText( setUrl( { maxDepth: -1 } ) ) + "'>" +
+                               "Rerun</a> without max depth.</p></td></tr>";
+               } else {
+                       message += "<tr class='test-message'><th>Message: </th><td>" +
+                               "Diff suppressed as the expected and actual results have an equivalent" +
+                               " serialization</td></tr>";
+               }
 
-// Deprecated QUnit.init - Ref #530
-// Re-initialize the configuration options
-QUnit.init = function() {
-       var tests, banner, result, qunit,
-               config = QUnit.config;
+               if ( details.source ) {
+                       message += "<tr class='test-source'><th>Source: </th><td><pre>" +
+                               escapeText( details.source ) + "</pre></td></tr>";
+               }
 
-       config.stats = { all: 0, bad: 0 };
-       config.moduleStats = { all: 0, bad: 0 };
-       config.started = 0;
-       config.updateRate = 1000;
-       config.blocking = false;
-       config.autostart = true;
-       config.autorun = false;
-       config.filter = "";
-       config.queue = [];
+               message += "</table>";
 
-       // Return on non-browser environments
-       // This is necessary to not break on node tests
-       if ( typeof window === "undefined" ) {
-               return;
+       // This occurs when pushFailure is set and we have an extracted stack trace
+       } else if ( !details.result && details.source ) {
+               message += "<table>" +
+                       "<tr class='test-source'><th>Source: </th><td><pre>" +
+                       escapeText( details.source ) + "</pre></td></tr>" +
+                       "</table>";
        }
 
-       qunit = id( "qunit" );
-       if ( qunit ) {
-               qunit.innerHTML =
-                       "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-                       "<h2 id='qunit-banner'></h2>" +
-                       "<div id='qunit-testrunner-toolbar'></div>" +
-                       "<h2 id='qunit-userAgent'></h2>" +
-                       "<ol id='qunit-tests'></ol>";
-       }
+       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
 
-       tests = id( "qunit-tests" );
-       banner = id( "qunit-banner" );
-       result = id( "qunit-testresult" );
+       assertLi = document.createElement( "li" );
+       assertLi.className = details.result ? "pass" : "fail";
+       assertLi.innerHTML = message;
+       assertList.appendChild( assertLi );
+} );
 
-       if ( tests ) {
-               tests.innerHTML = "";
-       }
+QUnit.testDone( function( details ) {
+       var testTitle, time, testItem, assertList,
+               good, bad, testCounts, skipped, sourceName,
+               tests = id( "qunit-tests" );
 
-       if ( banner ) {
-               banner.className = "";
+       if ( !tests ) {
+               return;
        }
 
-       if ( result ) {
-               result.parentNode.removeChild( result );
-       }
+       testItem = id( "qunit-test-output-" + details.testId );
 
-       if ( tests ) {
-               result = document.createElement( "p" );
-               result.id = "qunit-testresult";
-               result.className = "result";
-               tests.parentNode.insertBefore( result, tests );
-               result.innerHTML = "Running...<br />&#160;";
+       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+
+       good = details.passed;
+       bad = details.failed;
+
+       // Store result when possible
+       if ( config.reorder && defined.sessionStorage ) {
+               if ( bad ) {
+                       sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad );
+               } else {
+                       sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name );
+               }
        }
-};
 
-var config = QUnit.config,
-       collapseNext = false,
-       hasOwn = Object.prototype.hasOwnProperty,
-       defined = {
-               document: window.document !== undefined,
-               sessionStorage: (function() {
-                       var x = "qunit-test-string";
-                       try {
-                               sessionStorage.setItem( x, x );
-                               sessionStorage.removeItem( x );
-                               return true;
-                       } catch ( e ) {
-                               return false;
-                       }
-               }())
-       },
-       modulesList = [];
+       if ( bad === 0 ) {
 
-/**
-* Escape text for attribute or text content.
-*/
-function escapeText( s ) {
-       if ( !s ) {
-               return "";
+               // Collapse the passing tests
+               addClass( assertList, "qunit-collapsed" );
+       } else if ( bad && config.collapse && !collapseNext ) {
+
+               // Skip collapsing the first failing test
+               collapseNext = true;
+       } else {
+
+               // Collapse remaining tests
+               addClass( assertList, "qunit-collapsed" );
        }
-       s = s + "";
 
-       // Both single quotes and double quotes (for attributes)
-       return s.replace( /['"<>&]/g, function( s ) {
-               switch ( s ) {
-               case "'":
-                       return "&#039;";
-               case "\"":
-                       return "&quot;";
-               case "<":
-                       return "&lt;";
-               case ">":
-                       return "&gt;";
-               case "&":
-                       return "&amp;";
-               }
-       });
-}
+       // The testItem.firstChild is the test name
+       testTitle = testItem.firstChild;
 
-/**
- * @param {HTMLElement} elem
- * @param {string} type
- * @param {Function} fn
- */
-function addEvent( elem, type, fn ) {
-       if ( elem.addEventListener ) {
+       testCounts = bad ?
+               "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " :
+               "";
 
-               // Standards-based browsers
-               elem.addEventListener( type, fn, false );
-       } else if ( elem.attachEvent ) {
+       testTitle.innerHTML += " <b class='counts'>(" + testCounts +
+               details.assertions.length + ")</b>";
+
+       if ( details.skipped ) {
+               testItem.className = "skipped";
+               skipped = document.createElement( "em" );
+               skipped.className = "qunit-skipped-label";
+               skipped.innerHTML = "skipped";
+               testItem.insertBefore( skipped, testTitle );
+       } else {
+               addEvent( testTitle, "click", function() {
+                       toggleClass( assertList, "qunit-collapsed" );
+               } );
 
-               // support: IE <9
-               elem.attachEvent( "on" + type, function() {
-                       var event = window.event;
-                       if ( !event.target ) {
-                               event.target = event.srcElement || document;
-                       }
+               testItem.className = bad ? "fail" : "pass";
 
-                       fn.call( elem, event );
-               });
+               time = document.createElement( "span" );
+               time.className = "runtime";
+               time.innerHTML = details.runtime + " ms";
+               testItem.insertBefore( time, assertList );
        }
-}
 
-/**
- * @param {Array|NodeList} elems
- * @param {string} type
- * @param {Function} fn
- */
-function addEvents( elems, type, fn ) {
-       var i = elems.length;
-       while ( i-- ) {
-               addEvent( elems[ i ], type, fn );
+       // Show the source of the test when showing assertions
+       if ( details.source ) {
+               sourceName = document.createElement( "p" );
+               sourceName.innerHTML = "<strong>Source: </strong>" + details.source;
+               addClass( sourceName, "qunit-source" );
+               if ( bad === 0 ) {
+                       addClass( sourceName, "qunit-collapsed" );
+               }
+               addEvent( testTitle, "click", function() {
+                       toggleClass( sourceName, "qunit-collapsed" );
+               } );
+               testItem.appendChild( sourceName );
        }
-}
+} );
 
-function hasClass( elem, name ) {
-       return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0;
-}
+// Avoid readyState issue with phantomjs
+// Ref: #818
+var notPhantom = ( function( p ) {
+       return !( p && p.version && p.version.major > 0 );
+} )( window.phantom );
 
-function addClass( elem, name ) {
-       if ( !hasClass( elem, name ) ) {
-               elem.className += ( elem.className ? " " : "" ) + name;
-       }
+if ( notPhantom && document.readyState === "complete" ) {
+       QUnit.load();
+} else {
+       addEvent( window, "load", QUnit.load );
 }
 
-function toggleClass( elem, name ) {
-       if ( hasClass( elem, name ) ) {
-               removeClass( elem, name );
-       } else {
-               addClass( elem, name );
+/*
+ * This file is a modified version of google-diff-match-patch's JavaScript implementation
+ * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
+ * modifications are licensed as more fully set forth in LICENSE.txt.
+ *
+ * The original source of google-diff-match-patch is attributable and licensed as follows:
+ *
+ * Copyright 2006 Google Inc.
+ * https://code.google.com/p/google-diff-match-patch/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * More Info:
+ *  https://code.google.com/p/google-diff-match-patch/
+ *
+ * Usage: QUnit.diff(expected, actual)
+ *
+ */
+QUnit.diff = ( function() {
+       function DiffMatchPatch() {
        }
-}
 
-function removeClass( elem, name ) {
-       var set = " " + elem.className + " ";
-
-       // Class name may appear multiple times
-       while ( set.indexOf( " " + name + " " ) >= 0 ) {
-               set = set.replace( " " + name + " ", " " );
-       }
+       //  DIFF FUNCTIONS
 
-       // trim for prettiness
-       elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" );
-}
+       /**
+        * The data structure representing a diff is an array of tuples:
+        * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
+        * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
+        */
+       var DIFF_DELETE = -1,
+               DIFF_INSERT = 1,
+               DIFF_EQUAL = 0;
 
-function id( name ) {
-       return defined.document && document.getElementById && document.getElementById( name );
-}
+       /**
+        * Find the differences between two texts.  Simplifies the problem by stripping
+        * any common prefix or suffix off the texts before diffing.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {boolean=} optChecklines Optional speedup flag. If present and false,
+        *     then don't run a line-level diff first to identify the changed areas.
+        *     Defaults to true, which does a faster, slightly less optimal diff.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        */
+       DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines ) {
+               var deadline, checklines, commonlength,
+                       commonprefix, commonsuffix, diffs;
 
-function getUrlConfigHtml() {
-       var i, j, val,
-               escaped, escapedTooltip,
-               selection = false,
-               len = config.urlConfig.length,
-               urlConfigHtml = "";
+               // The diff must be complete in up to 1 second.
+               deadline = ( new Date() ).getTime() + 1000;
 
-       for ( i = 0; i < len; i++ ) {
-               val = config.urlConfig[ i ];
-               if ( typeof val === "string" ) {
-                       val = {
-                               id: val,
-                               label: val
-                       };
+               // Check for null inputs.
+               if ( text1 === null || text2 === null ) {
+                       throw new Error( "Null input. (DiffMain)" );
                }
 
-               escaped = escapeText( val.id );
-               escapedTooltip = escapeText( val.tooltip );
-
-               if ( config[ val.id ] === undefined ) {
-                       config[ val.id ] = QUnit.urlParams[ val.id ];
+               // Check for equality (speedup).
+               if ( text1 === text2 ) {
+                       if ( text1 ) {
+                               return [
+                                       [ DIFF_EQUAL, text1 ]
+                               ];
+                       }
+                       return [];
                }
 
-               if ( !val.value || typeof val.value === "string" ) {
-                       urlConfigHtml += "<input id='qunit-urlconfig-" + escaped +
-                               "' name='" + escaped + "' type='checkbox'" +
-                               ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
-                               ( config[ val.id ] ? " checked='checked'" : "" ) +
-                               " title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped +
-                               "' title='" + escapedTooltip + "'>" + val.label + "</label>";
-               } else {
-                       urlConfigHtml += "<label for='qunit-urlconfig-" + escaped +
-                               "' title='" + escapedTooltip + "'>" + val.label +
-                               ": </label><select id='qunit-urlconfig-" + escaped +
-                               "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
-
-                       if ( QUnit.is( "array", val.value ) ) {
-                               for ( j = 0; j < val.value.length; j++ ) {
-                                       escaped = escapeText( val.value[ j ] );
-                                       urlConfigHtml += "<option value='" + escaped + "'" +
-                                               ( config[ val.id ] === val.value[ j ] ?
-                                                       ( selection = true ) && " selected='selected'" : "" ) +
-                                               ">" + escaped + "</option>";
-                               }
-                       } else {
-                               for ( j in val.value ) {
-                                       if ( hasOwn.call( val.value, j ) ) {
-                                               urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
-                                                       ( config[ val.id ] === j ?
-                                                               ( selection = true ) && " selected='selected'" : "" ) +
-                                                       ">" + escapeText( val.value[ j ] ) + "</option>";
-                                       }
-                               }
-                       }
-                       if ( config[ val.id ] && !selection ) {
-                               escaped = escapeText( config[ val.id ] );
-                               urlConfigHtml += "<option value='" + escaped +
-                                       "' selected='selected' disabled='disabled'>" + escaped + "</option>";
-                       }
-                       urlConfigHtml += "</select>";
+               if ( typeof optChecklines === "undefined" ) {
+                       optChecklines = true;
                }
-       }
 
-       return urlConfigHtml;
-}
+               checklines = optChecklines;
 
-// Handle "click" events on toolbar checkboxes and "change" for select menus.
-// Updates the URL with the new state of `config.urlConfig` values.
-function toolbarChanged() {
-       var updatedUrl, value,
-               field = this,
-               params = {};
+               // Trim off common prefix (speedup).
+               commonlength = this.diffCommonPrefix( text1, text2 );
+               commonprefix = text1.substring( 0, commonlength );
+               text1 = text1.substring( commonlength );
+               text2 = text2.substring( commonlength );
 
-       // Detect if field is a select menu or a checkbox
-       if ( "selectedIndex" in field ) {
-               value = field.options[ field.selectedIndex ].value || undefined;
-       } else {
-               value = field.checked ? ( field.defaultValue || true ) : undefined;
-       }
+               // Trim off common suffix (speedup).
+               commonlength = this.diffCommonSuffix( text1, text2 );
+               commonsuffix = text1.substring( text1.length - commonlength );
+               text1 = text1.substring( 0, text1.length - commonlength );
+               text2 = text2.substring( 0, text2.length - commonlength );
 
-       params[ field.name ] = value;
-       updatedUrl = setUrl( params );
+               // Compute the diff on the middle block.
+               diffs = this.diffCompute( text1, text2, checklines, deadline );
 
-       if ( "hidepassed" === field.name && "replaceState" in window.history ) {
-               config[ field.name ] = value || false;
-               if ( value ) {
-                       addClass( id( "qunit-tests" ), "hidepass" );
-               } else {
-                       removeClass( id( "qunit-tests" ), "hidepass" );
+               // Restore the prefix and suffix.
+               if ( commonprefix ) {
+                       diffs.unshift( [ DIFF_EQUAL, commonprefix ] );
                }
+               if ( commonsuffix ) {
+                       diffs.push( [ DIFF_EQUAL, commonsuffix ] );
+               }
+               this.diffCleanupMerge( diffs );
+               return diffs;
+       };
 
-               // It is not necessary to refresh the whole page
-               window.history.replaceState( null, "", updatedUrl );
-       } else {
-               window.location = updatedUrl;
-       }
-}
-
-function setUrl( params ) {
-       var key,
-               querystring = "?";
+       /**
+        * Reduce the number of edits by eliminating operationally trivial equalities.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        */
+       DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) {
+               var changes, equalities, equalitiesLength, lastequality,
+                       pointer, preIns, preDel, postIns, postDel;
+               changes = false;
+               equalities = []; // Stack of indices where equalities are found.
+               equalitiesLength = 0; // Keeping our own length var is faster in JS.
+               /** @type {?string} */
+               lastequality = null;
 
-       params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params );
+               // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+               pointer = 0; // Index of current position.
 
-       for ( key in params ) {
-               if ( hasOwn.call( params, key ) ) {
-                       if ( params[ key ] === undefined ) {
-                               continue;
-                       }
-                       querystring += encodeURIComponent( key );
-                       if ( params[ key ] !== true ) {
-                               querystring += "=" + encodeURIComponent( params[ key ] );
-                       }
-                       querystring += "&";
-               }
-       }
-       return location.protocol + "//" + location.host +
-               location.pathname + querystring.slice( 0, -1 );
-}
+               // Is there an insertion operation before the last equality.
+               preIns = false;
 
-function applyUrlParams() {
-       var selectedModule,
-               modulesList = id( "qunit-modulefilter" ),
-               filter = id( "qunit-filter-input" ).value;
+               // Is there a deletion operation before the last equality.
+               preDel = false;
 
-       selectedModule = modulesList ?
-               decodeURIComponent( modulesList.options[ modulesList.selectedIndex ].value ) :
-               undefined;
+               // Is there an insertion operation after the last equality.
+               postIns = false;
 
-       window.location = setUrl({
-               module: ( selectedModule === "" ) ? undefined : selectedModule,
-               filter: ( filter === "" ) ? undefined : filter,
+               // Is there a deletion operation after the last equality.
+               postDel = false;
+               while ( pointer < diffs.length ) {
 
-               // Remove testId filter
-               testId: undefined
-       });
-}
+                       // Equality found.
+                       if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) {
+                               if ( diffs[ pointer ][ 1 ].length < 4 && ( postIns || postDel ) ) {
 
-function toolbarUrlConfigContainer() {
-       var urlConfigContainer = document.createElement( "span" );
+                                       // Candidate found.
+                                       equalities[ equalitiesLength++ ] = pointer;
+                                       preIns = postIns;
+                                       preDel = postDel;
+                                       lastequality = diffs[ pointer ][ 1 ];
+                               } else {
 
-       urlConfigContainer.innerHTML = getUrlConfigHtml();
-       addClass( urlConfigContainer, "qunit-url-config" );
+                                       // Not a candidate, and can never become one.
+                                       equalitiesLength = 0;
+                                       lastequality = null;
+                               }
+                               postIns = postDel = false;
 
-       // For oldIE support:
-       // * Add handlers to the individual elements instead of the container
-       // * Use "click" instead of "change" for checkboxes
-       addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged );
-       addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged );
+                       // An insertion or deletion.
+                       } else {
 
-       return urlConfigContainer;
-}
+                               if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) {
+                                       postDel = true;
+                               } else {
+                                       postIns = true;
+                               }
 
-function toolbarLooseFilter() {
-       var filter = document.createElement( "form" ),
-               label = document.createElement( "label" ),
-               input = document.createElement( "input" ),
-               button = document.createElement( "button" );
+                               /*
+                                * Five types to be split:
+                                * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
+                                * <ins>A</ins>X<ins>C</ins><del>D</del>
+                                * <ins>A</ins><del>B</del>X<ins>C</ins>
+                                * <ins>A</del>X<ins>C</ins><del>D</del>
+                                * <ins>A</ins><del>B</del>X<del>C</del>
+                                */
+                               if ( lastequality && ( ( preIns && preDel && postIns && postDel ) ||
+                                               ( ( lastequality.length < 2 ) &&
+                                               ( preIns + preDel + postIns + postDel ) === 3 ) ) ) {
 
-       addClass( filter, "qunit-filter" );
+                                       // Duplicate record.
+                                       diffs.splice(
+                                               equalities[ equalitiesLength - 1 ],
+                                               0,
+                                               [ DIFF_DELETE, lastequality ]
+                                       );
 
-       label.innerHTML = "Filter: ";
+                                       // Change second copy to insert.
+                                       diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
+                                       equalitiesLength--; // Throw away the equality we just deleted;
+                                       lastequality = null;
+                                       if ( preIns && preDel ) {
 
-       input.type = "text";
-       input.value = config.filter || "";
-       input.name = "filter";
-       input.id = "qunit-filter-input";
+                                               // No changes made which could affect previous entry, keep going.
+                                               postIns = postDel = true;
+                                               equalitiesLength = 0;
+                                       } else {
+                                               equalitiesLength--; // Throw away the previous equality.
+                                               pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
+                                               postIns = postDel = false;
+                                       }
+                                       changes = true;
+                               }
+                       }
+                       pointer++;
+               }
 
-       button.innerHTML = "Go";
+               if ( changes ) {
+                       this.diffCleanupMerge( diffs );
+               }
+       };
 
-       label.appendChild( input );
+       /**
+        * Convert a diff array into a pretty HTML report.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        * @param {integer} string to be beautified.
+        * @return {string} HTML representation.
+        */
+       DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) {
+               var op, data, x,
+                       html = [];
+               for ( x = 0; x < diffs.length; x++ ) {
+                       op = diffs[ x ][ 0 ]; // Operation (insert, delete, equal)
+                       data = diffs[ x ][ 1 ]; // Text of change.
+                       switch ( op ) {
+                       case DIFF_INSERT:
+                               html[ x ] = "<ins>" + escapeText( data ) + "</ins>";
+                               break;
+                       case DIFF_DELETE:
+                               html[ x ] = "<del>" + escapeText( data ) + "</del>";
+                               break;
+                       case DIFF_EQUAL:
+                               html[ x ] = "<span>" + escapeText( data ) + "</span>";
+                               break;
+                       }
+               }
+               return html.join( "" );
+       };
 
-       filter.appendChild( label );
-       filter.appendChild( button );
-       addEvent( filter, "submit", function( ev ) {
-               applyUrlParams();
+       /**
+        * Determine the common prefix of two strings.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {number} The number of characters common to the start of each
+        *     string.
+        */
+       DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) {
+               var pointermid, pointermax, pointermin, pointerstart;
 
-               if ( ev && ev.preventDefault ) {
-                       ev.preventDefault();
+               // Quick check for common null cases.
+               if ( !text1 || !text2 || text1.charAt( 0 ) !== text2.charAt( 0 ) ) {
+                       return 0;
                }
 
-               return false;
-       });
+               // Binary search.
+               // Performance analysis: https://neil.fraser.name/news/2007/10/09/
+               pointermin = 0;
+               pointermax = Math.min( text1.length, text2.length );
+               pointermid = pointermax;
+               pointerstart = 0;
+               while ( pointermin < pointermid ) {
+                       if ( text1.substring( pointerstart, pointermid ) ===
+                                       text2.substring( pointerstart, pointermid ) ) {
+                               pointermin = pointermid;
+                               pointerstart = pointermin;
+                       } else {
+                               pointermax = pointermid;
+                       }
+                       pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+               }
+               return pointermid;
+       };
 
-       return filter;
-}
+       /**
+        * Determine the common suffix of two strings.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {number} The number of characters common to the end of each string.
+        */
+       DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) {
+               var pointermid, pointermax, pointermin, pointerend;
 
-function toolbarModuleFilterHtml() {
-       var i,
-               moduleFilterHtml = "";
+               // Quick check for common null cases.
+               if ( !text1 ||
+                               !text2 ||
+                               text1.charAt( text1.length - 1 ) !== text2.charAt( text2.length - 1 ) ) {
+                       return 0;
+               }
 
-       if ( !modulesList.length ) {
-               return false;
-       }
+               // Binary search.
+               // Performance analysis: https://neil.fraser.name/news/2007/10/09/
+               pointermin = 0;
+               pointermax = Math.min( text1.length, text2.length );
+               pointermid = pointermax;
+               pointerend = 0;
+               while ( pointermin < pointermid ) {
+                       if ( text1.substring( text1.length - pointermid, text1.length - pointerend ) ===
+                                       text2.substring( text2.length - pointermid, text2.length - pointerend ) ) {
+                               pointermin = pointermid;
+                               pointerend = pointermin;
+                       } else {
+                               pointermax = pointermid;
+                       }
+                       pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+               }
+               return pointermid;
+       };
 
-       modulesList.sort(function( a, b ) {
-               return a.localeCompare( b );
-       });
+       /**
+        * Find the differences between two texts.  Assumes that the texts do not
+        * have any common prefix or suffix.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {boolean} checklines Speedup flag.  If false, then don't run a
+        *     line-level diff first to identify the changed areas.
+        *     If true, then run a faster, slightly less optimal diff.
+        * @param {number} deadline Time when the diff should be complete by.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) {
+               var diffs, longtext, shorttext, i, hm,
+                       text1A, text2A, text1B, text2B,
+                       midCommon, diffsA, diffsB;
 
-       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" +
-               "<select id='qunit-modulefilter' name='modulefilter'><option value='' " +
-               ( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) +
-               ">< All Modules ></option>";
+               if ( !text1 ) {
 
-       for ( i = 0; i < modulesList.length; i++ ) {
-               moduleFilterHtml += "<option value='" +
-                       escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " +
-                       ( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) +
-                       ">" + escapeText( modulesList[ i ] ) + "</option>";
-       }
-       moduleFilterHtml += "</select>";
+                       // Just add some text (speedup).
+                       return [
+                               [ DIFF_INSERT, text2 ]
+                       ];
+               }
 
-       return moduleFilterHtml;
-}
+               if ( !text2 ) {
 
-function toolbarModuleFilter() {
-       var toolbar = id( "qunit-testrunner-toolbar" ),
-               moduleFilter = document.createElement( "span" ),
-               moduleFilterHtml = toolbarModuleFilterHtml();
+                       // Just delete some text (speedup).
+                       return [
+                               [ DIFF_DELETE, text1 ]
+                       ];
+               }
+
+               longtext = text1.length > text2.length ? text1 : text2;
+               shorttext = text1.length > text2.length ? text2 : text1;
+               i = longtext.indexOf( shorttext );
+               if ( i !== -1 ) {
+
+                       // Shorter text is inside the longer text (speedup).
+                       diffs = [
+                               [ DIFF_INSERT, longtext.substring( 0, i ) ],
+                               [ DIFF_EQUAL, shorttext ],
+                               [ DIFF_INSERT, longtext.substring( i + shorttext.length ) ]
+                       ];
 
-       if ( !toolbar || !moduleFilterHtml ) {
-               return false;
-       }
+                       // Swap insertions for deletions if diff is reversed.
+                       if ( text1.length > text2.length ) {
+                               diffs[ 0 ][ 0 ] = diffs[ 2 ][ 0 ] = DIFF_DELETE;
+                       }
+                       return diffs;
+               }
 
-       moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
-       moduleFilter.innerHTML = moduleFilterHtml;
+               if ( shorttext.length === 1 ) {
 
-       addEvent( moduleFilter.lastChild, "change", applyUrlParams );
+                       // Single character string.
+                       // After the previous speedup, the character can't be an equality.
+                       return [
+                               [ DIFF_DELETE, text1 ],
+                               [ DIFF_INSERT, text2 ]
+                       ];
+               }
 
-       toolbar.appendChild( moduleFilter );
-}
+               // Check to see if the problem can be split in two.
+               hm = this.diffHalfMatch( text1, text2 );
+               if ( hm ) {
 
-function appendToolbar() {
-       var toolbar = id( "qunit-testrunner-toolbar" );
+                       // A half-match was found, sort out the return data.
+                       text1A = hm[ 0 ];
+                       text1B = hm[ 1 ];
+                       text2A = hm[ 2 ];
+                       text2B = hm[ 3 ];
+                       midCommon = hm[ 4 ];
 
-       if ( toolbar ) {
-               toolbar.appendChild( toolbarUrlConfigContainer() );
-               toolbar.appendChild( toolbarLooseFilter() );
-       }
-}
+                       // Send both pairs off for separate processing.
+                       diffsA = this.DiffMain( text1A, text2A, checklines, deadline );
+                       diffsB = this.DiffMain( text1B, text2B, checklines, deadline );
 
-function appendHeader() {
-       var header = id( "qunit-header" );
+                       // Merge the results.
+                       return diffsA.concat( [
+                               [ DIFF_EQUAL, midCommon ]
+                       ], diffsB );
+               }
 
-       if ( header ) {
-               header.innerHTML = "<a href='" +
-                       escapeText( setUrl( { filter: undefined, module: undefined, testId: undefined } ) ) +
-                       "'>" + header.innerHTML + "</a> ";
-       }
-}
+               if ( checklines && text1.length > 100 && text2.length > 100 ) {
+                       return this.diffLineMode( text1, text2, deadline );
+               }
 
-function appendBanner() {
-       var banner = id( "qunit-banner" );
+               return this.diffBisect( text1, text2, deadline );
+       };
 
-       if ( banner ) {
-               banner.className = "";
-       }
-}
+       /**
+        * Do the two texts share a substring which is at least half the length of the
+        * longer text?
+        * This speedup can produce non-minimal diffs.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {Array.<string>} Five element Array, containing the prefix of
+        *     text1, the suffix of text1, the prefix of text2, the suffix of
+        *     text2 and the common middle.  Or null if there was no match.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffHalfMatch = function( text1, text2 ) {
+               var longtext, shorttext, dmp,
+                       text1A, text2B, text2A, text1B, midCommon,
+                       hm1, hm2, hm;
 
-function appendTestResults() {
-       var tests = id( "qunit-tests" ),
-               result = id( "qunit-testresult" );
+               longtext = text1.length > text2.length ? text1 : text2;
+               shorttext = text1.length > text2.length ? text2 : text1;
+               if ( longtext.length < 4 || shorttext.length * 2 < longtext.length ) {
+                       return null; // Pointless.
+               }
+               dmp = this; // 'this' becomes 'window' in a closure.
 
-       if ( result ) {
-               result.parentNode.removeChild( result );
-       }
+               /**
+                * Does a substring of shorttext exist within longtext such that the substring
+                * is at least half the length of longtext?
+                * Closure, but does not reference any external variables.
+                * @param {string} longtext Longer string.
+                * @param {string} shorttext Shorter string.
+                * @param {number} i Start index of quarter length substring within longtext.
+                * @return {Array.<string>} Five element Array, containing the prefix of
+                *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
+                *     of shorttext and the common middle.  Or null if there was no match.
+                * @private
+                */
+               function diffHalfMatchI( longtext, shorttext, i ) {
+                       var seed, j, bestCommon, prefixLength, suffixLength,
+                               bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
 
-       if ( tests ) {
-               tests.innerHTML = "";
-               result = document.createElement( "p" );
-               result.id = "qunit-testresult";
-               result.className = "result";
-               tests.parentNode.insertBefore( result, tests );
-               result.innerHTML = "Running...<br />&#160;";
-       }
-}
+                       // Start with a 1/4 length substring at position i as a seed.
+                       seed = longtext.substring( i, i + Math.floor( longtext.length / 4 ) );
+                       j = -1;
+                       bestCommon = "";
+                       while ( ( j = shorttext.indexOf( seed, j + 1 ) ) !== -1 ) {
+                               prefixLength = dmp.diffCommonPrefix( longtext.substring( i ),
+                                       shorttext.substring( j ) );
+                               suffixLength = dmp.diffCommonSuffix( longtext.substring( 0, i ),
+                                       shorttext.substring( 0, j ) );
+                               if ( bestCommon.length < suffixLength + prefixLength ) {
+                                       bestCommon = shorttext.substring( j - suffixLength, j ) +
+                                               shorttext.substring( j, j + prefixLength );
+                                       bestLongtextA = longtext.substring( 0, i - suffixLength );
+                                       bestLongtextB = longtext.substring( i + prefixLength );
+                                       bestShorttextA = shorttext.substring( 0, j - suffixLength );
+                                       bestShorttextB = shorttext.substring( j + prefixLength );
+                               }
+                       }
+                       if ( bestCommon.length * 2 >= longtext.length ) {
+                               return [ bestLongtextA, bestLongtextB,
+                                       bestShorttextA, bestShorttextB, bestCommon
+                               ];
+                       } else {
+                               return null;
+                       }
+               }
 
-function storeFixture() {
-       var fixture = id( "qunit-fixture" );
-       if ( fixture ) {
-               config.fixture = fixture.innerHTML;
-       }
-}
+               // First check if the second quarter is the seed for a half-match.
+               hm1 = diffHalfMatchI( longtext, shorttext,
+                       Math.ceil( longtext.length / 4 ) );
 
-function appendFilteredTest() {
-       var testId = QUnit.config.testId;
-       if ( !testId || testId.length <= 0 ) {
-               return "";
-       }
-       return "<div id='qunit-filteredTest'>Rerunning selected tests: " +
-               escapeText( testId.join(", ") ) +
-               " <a id='qunit-clearFilter' href='" +
-               escapeText( setUrl( { filter: undefined, module: undefined, testId: undefined } ) ) +
-               "'>" + "Run all tests" + "</a></div>";
-}
+               // Check again based on the third quarter.
+               hm2 = diffHalfMatchI( longtext, shorttext,
+                       Math.ceil( longtext.length / 2 ) );
+               if ( !hm1 && !hm2 ) {
+                       return null;
+               } else if ( !hm2 ) {
+                       hm = hm1;
+               } else if ( !hm1 ) {
+                       hm = hm2;
+               } else {
 
-function appendUserAgent() {
-       var userAgent = id( "qunit-userAgent" );
+                       // Both matched.  Select the longest.
+                       hm = hm1[ 4 ].length > hm2[ 4 ].length ? hm1 : hm2;
+               }
 
-       if ( userAgent ) {
-               userAgent.innerHTML = "";
-               userAgent.appendChild(
-                       document.createTextNode(
-                               "QUnit " + QUnit.version + "; " + navigator.userAgent
-                       )
-               );
-       }
-}
+               // A half-match was found, sort out the return data.
+               text1A, text1B, text2A, text2B;
+               if ( text1.length > text2.length ) {
+                       text1A = hm[ 0 ];
+                       text1B = hm[ 1 ];
+                       text2A = hm[ 2 ];
+                       text2B = hm[ 3 ];
+               } else {
+                       text2A = hm[ 0 ];
+                       text2B = hm[ 1 ];
+                       text1A = hm[ 2 ];
+                       text1B = hm[ 3 ];
+               }
+               midCommon = hm[ 4 ];
+               return [ text1A, text1B, text2A, text2B, midCommon ];
+       };
 
-function appendTestsList( modules ) {
-       var i, l, x, z, test, moduleObj;
+       /**
+        * Do a quick line-level diff on both strings, then rediff the parts for
+        * greater accuracy.
+        * This speedup can produce non-minimal diffs.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {number} deadline Time when the diff should be complete by.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffLineMode = function( text1, text2, deadline ) {
+               var a, diffs, linearray, pointer, countInsert,
+                       countDelete, textInsert, textDelete, j;
 
-       for ( i = 0, l = modules.length; i < l; i++ ) {
-               moduleObj = modules[ i ];
+               // Scan the text on a line-by-line basis first.
+               a = this.diffLinesToChars( text1, text2 );
+               text1 = a.chars1;
+               text2 = a.chars2;
+               linearray = a.lineArray;
 
-               if ( moduleObj.name ) {
-                       modulesList.push( moduleObj.name );
-               }
+               diffs = this.DiffMain( text1, text2, false, deadline );
 
-               for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) {
-                       test = moduleObj.tests[ x ];
+               // Convert the diff back to original text.
+               this.diffCharsToLines( diffs, linearray );
 
-                       appendTest( test.name, test.testId, moduleObj.name );
-               }
-       }
-}
+               // Eliminate freak matches (e.g. blank lines)
+               this.diffCleanupSemantic( diffs );
 
-function appendTest( name, testId, moduleName ) {
-       var title, rerunTrigger, testBlock, assertList,
-               tests = id( "qunit-tests" );
+               // Rediff any replacement blocks, this time character-by-character.
+               // Add a dummy entry at the end.
+               diffs.push( [ DIFF_EQUAL, "" ] );
+               pointer = 0;
+               countDelete = 0;
+               countInsert = 0;
+               textDelete = "";
+               textInsert = "";
+               while ( pointer < diffs.length ) {
+                       switch ( diffs[ pointer ][ 0 ] ) {
+                       case DIFF_INSERT:
+                               countInsert++;
+                               textInsert += diffs[ pointer ][ 1 ];
+                               break;
+                       case DIFF_DELETE:
+                               countDelete++;
+                               textDelete += diffs[ pointer ][ 1 ];
+                               break;
+                       case DIFF_EQUAL:
+
+                               // Upon reaching an equality, check for prior redundancies.
+                               if ( countDelete >= 1 && countInsert >= 1 ) {
 
-       if ( !tests ) {
-               return;
-       }
+                                       // Delete the offending records and add the merged ones.
+                                       diffs.splice( pointer - countDelete - countInsert,
+                                               countDelete + countInsert );
+                                       pointer = pointer - countDelete - countInsert;
+                                       a = this.DiffMain( textDelete, textInsert, false, deadline );
+                                       for ( j = a.length - 1; j >= 0; j-- ) {
+                                               diffs.splice( pointer, 0, a[ j ] );
+                                       }
+                                       pointer = pointer + a.length;
+                               }
+                               countInsert = 0;
+                               countDelete = 0;
+                               textDelete = "";
+                               textInsert = "";
+                               break;
+                       }
+                       pointer++;
+               }
+               diffs.pop(); // Remove the dummy entry at the end.
 
-       title = document.createElement( "strong" );
-       title.innerHTML = getNameHtml( name, moduleName );
+               return diffs;
+       };
 
-       rerunTrigger = document.createElement( "a" );
-       rerunTrigger.innerHTML = "Rerun";
-       rerunTrigger.href = setUrl({ testId: testId });
+       /**
+        * Find the 'middle snake' of a diff, split the problem in two
+        * and return the recursively constructed diff.
+        * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {number} deadline Time at which to bail if not yet complete.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffBisect = function( text1, text2, deadline ) {
+               var text1Length, text2Length, maxD, vOffset, vLength,
+                       v1, v2, x, delta, front, k1start, k1end, k2start,
+                       k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
 
-       testBlock = document.createElement( "li" );
-       testBlock.appendChild( title );
-       testBlock.appendChild( rerunTrigger );
-       testBlock.id = "qunit-test-output-" + testId;
+               // Cache the text lengths to prevent multiple calls.
+               text1Length = text1.length;
+               text2Length = text2.length;
+               maxD = Math.ceil( ( text1Length + text2Length ) / 2 );
+               vOffset = maxD;
+               vLength = 2 * maxD;
+               v1 = new Array( vLength );
+               v2 = new Array( vLength );
 
-       assertList = document.createElement( "ol" );
-       assertList.className = "qunit-assert-list";
+               // Setting all elements to -1 is faster in Chrome & Firefox than mixing
+               // integers and undefined.
+               for ( x = 0; x < vLength; x++ ) {
+                       v1[ x ] = -1;
+                       v2[ x ] = -1;
+               }
+               v1[ vOffset + 1 ] = 0;
+               v2[ vOffset + 1 ] = 0;
+               delta = text1Length - text2Length;
 
-       testBlock.appendChild( assertList );
+               // If the total number of characters is odd, then the front path will collide
+               // with the reverse path.
+               front = ( delta % 2 !== 0 );
 
-       tests.appendChild( testBlock );
-}
+               // Offsets for start and end of k loop.
+               // Prevents mapping of space beyond the grid.
+               k1start = 0;
+               k1end = 0;
+               k2start = 0;
+               k2end = 0;
+               for ( d = 0; d < maxD; d++ ) {
 
-// HTML Reporter initialization and load
-QUnit.begin(function( details ) {
-       var qunit = id( "qunit" );
+                       // Bail out if deadline is reached.
+                       if ( ( new Date() ).getTime() > deadline ) {
+                               break;
+                       }
 
-       // Fixture is the only one necessary to run without the #qunit element
-       storeFixture();
+                       // Walk the front path one step.
+                       for ( k1 = -d + k1start; k1 <= d - k1end; k1 += 2 ) {
+                               k1Offset = vOffset + k1;
+                               if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) {
+                                       x1 = v1[ k1Offset + 1 ];
+                               } else {
+                                       x1 = v1[ k1Offset - 1 ] + 1;
+                               }
+                               y1 = x1 - k1;
+                               while ( x1 < text1Length && y1 < text2Length &&
+                                       text1.charAt( x1 ) === text2.charAt( y1 ) ) {
+                                       x1++;
+                                       y1++;
+                               }
+                               v1[ k1Offset ] = x1;
+                               if ( x1 > text1Length ) {
 
-       if ( qunit ) {
-               qunit.innerHTML =
-                       "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-                       "<h2 id='qunit-banner'></h2>" +
-                       "<div id='qunit-testrunner-toolbar'></div>" +
-                       appendFilteredTest() +
-                       "<h2 id='qunit-userAgent'></h2>" +
-                       "<ol id='qunit-tests'></ol>";
-       }
+                                       // Ran off the right of the graph.
+                                       k1end += 2;
+                               } else if ( y1 > text2Length ) {
 
-       appendHeader();
-       appendBanner();
-       appendTestResults();
-       appendUserAgent();
-       appendToolbar();
-       appendTestsList( details.modules );
-       toolbarModuleFilter();
+                                       // Ran off the bottom of the graph.
+                                       k1start += 2;
+                               } else if ( front ) {
+                                       k2Offset = vOffset + delta - k1;
+                                       if ( k2Offset >= 0 && k2Offset < vLength && v2[ k2Offset ] !== -1 ) {
 
-       if ( qunit && config.hidepassed ) {
-               addClass( qunit.lastChild, "hidepass" );
-       }
-});
+                                               // Mirror x2 onto top-left coordinate system.
+                                               x2 = text1Length - v2[ k2Offset ];
+                                               if ( x1 >= x2 ) {
 
-QUnit.done(function( details ) {
-       var i, key,
-               banner = id( "qunit-banner" ),
-               tests = id( "qunit-tests" ),
-               html = [
-                       "Tests completed in ",
-                       details.runtime,
-                       " milliseconds.<br />",
-                       "<span class='passed'>",
-                       details.passed,
-                       "</span> assertions of <span class='total'>",
-                       details.total,
-                       "</span> passed, <span class='failed'>",
-                       details.failed,
-                       "</span> failed."
-               ].join( "" );
+                                                       // Overlap detected.
+                                                       return this.diffBisectSplit( text1, text2, x1, y1, deadline );
+                                               }
+                                       }
+                               }
+                       }
 
-       if ( banner ) {
-               banner.className = details.failed ? "qunit-fail" : "qunit-pass";
-       }
+                       // Walk the reverse path one step.
+                       for ( k2 = -d + k2start; k2 <= d - k2end; k2 += 2 ) {
+                               k2Offset = vOffset + k2;
+                               if ( k2 === -d || ( k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) {
+                                       x2 = v2[ k2Offset + 1 ];
+                               } else {
+                                       x2 = v2[ k2Offset - 1 ] + 1;
+                               }
+                               y2 = x2 - k2;
+                               while ( x2 < text1Length && y2 < text2Length &&
+                                       text1.charAt( text1Length - x2 - 1 ) ===
+                                       text2.charAt( text2Length - y2 - 1 ) ) {
+                                       x2++;
+                                       y2++;
+                               }
+                               v2[ k2Offset ] = x2;
+                               if ( x2 > text1Length ) {
 
-       if ( tests ) {
-               id( "qunit-testresult" ).innerHTML = html;
-       }
+                                       // Ran off the left of the graph.
+                                       k2end += 2;
+                               } else if ( y2 > text2Length ) {
 
-       if ( config.altertitle && defined.document && document.title ) {
+                                       // Ran off the top of the graph.
+                                       k2start += 2;
+                               } else if ( !front ) {
+                                       k1Offset = vOffset + delta - k2;
+                                       if ( k1Offset >= 0 && k1Offset < vLength && v1[ k1Offset ] !== -1 ) {
+                                               x1 = v1[ k1Offset ];
+                                               y1 = vOffset + x1 - k1Offset;
 
-               // show ✖ for good, ✔ for bad suite result in title
-               // use escape sequences in case file gets loaded with non-utf-8-charset
-               document.title = [
-                       ( details.failed ? "\u2716" : "\u2714" ),
-                       document.title.replace( /^[\u2714\u2716] /i, "" )
-               ].join( " " );
-       }
+                                               // Mirror x2 onto top-left coordinate system.
+                                               x2 = text1Length - x2;
+                                               if ( x1 >= x2 ) {
 
-       // clear own sessionStorage items if all tests passed
-       if ( config.reorder && defined.sessionStorage && details.failed === 0 ) {
-               for ( i = 0; i < sessionStorage.length; i++ ) {
-                       key = sessionStorage.key( i++ );
-                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
-                               sessionStorage.removeItem( key );
+                                                       // Overlap detected.
+                                                       return this.diffBisectSplit( text1, text2, x1, y1, deadline );
+                                               }
+                                       }
+                               }
                        }
                }
-       }
-
-       // scroll back to top to show results
-       if ( config.scrolltop && window.scrollTo ) {
-               window.scrollTo( 0, 0 );
-       }
-});
 
-function getNameHtml( name, module ) {
-       var nameHtml = "";
+               // Diff took too long and hit the deadline or
+               // number of diffs equals number of characters, no commonality at all.
+               return [
+                       [ DIFF_DELETE, text1 ],
+                       [ DIFF_INSERT, text2 ]
+               ];
+       };
 
-       if ( module ) {
-               nameHtml = "<span class='module-name'>" + escapeText( module ) + "</span>: ";
-       }
+       /**
+        * Given the location of the 'middle snake', split the diff in two parts
+        * and recurse.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {number} x Index of split point in text1.
+        * @param {number} y Index of split point in text2.
+        * @param {number} deadline Time at which to bail if not yet complete.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) {
+               var text1a, text1b, text2a, text2b, diffs, diffsb;
+               text1a = text1.substring( 0, x );
+               text2a = text2.substring( 0, y );
+               text1b = text1.substring( x );
+               text2b = text2.substring( y );
 
-       nameHtml += "<span class='test-name'>" + escapeText( name ) + "</span>";
+               // Compute both diffs serially.
+               diffs = this.DiffMain( text1a, text2a, false, deadline );
+               diffsb = this.DiffMain( text1b, text2b, false, deadline );
 
-       return nameHtml;
-}
+               return diffs.concat( diffsb );
+       };
 
-QUnit.testStart(function( details ) {
-       var running, testBlock, bad;
+       /**
+        * Reduce the number of edits by eliminating semantically trivial equalities.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        */
+       DiffMatchPatch.prototype.diffCleanupSemantic = function( diffs ) {
+               var changes, equalities, equalitiesLength, lastequality,
+                       pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1,
+                       lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
+               changes = false;
+               equalities = []; // Stack of indices where equalities are found.
+               equalitiesLength = 0; // Keeping our own length var is faster in JS.
+               /** @type {?string} */
+               lastequality = null;
 
-       testBlock = id( "qunit-test-output-" + details.testId );
-       if ( testBlock ) {
-               testBlock.className = "running";
-       } else {
+               // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+               pointer = 0; // Index of current position.
 
-               // Report later registered tests
-               appendTest( details.name, details.testId, details.module );
-       }
+               // Number of characters that changed prior to the equality.
+               lengthInsertions1 = 0;
+               lengthDeletions1 = 0;
 
-       running = id( "qunit-testresult" );
-       if ( running ) {
-               bad = QUnit.config.reorder && defined.sessionStorage &&
-                       +sessionStorage.getItem( "qunit-test-" + details.module + "-" + details.name );
+               // Number of characters that changed after the equality.
+               lengthInsertions2 = 0;
+               lengthDeletions2 = 0;
+               while ( pointer < diffs.length ) {
+                       if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found.
+                               equalities[ equalitiesLength++ ] = pointer;
+                               lengthInsertions1 = lengthInsertions2;
+                               lengthDeletions1 = lengthDeletions2;
+                               lengthInsertions2 = 0;
+                               lengthDeletions2 = 0;
+                               lastequality = diffs[ pointer ][ 1 ];
+                       } else { // An insertion or deletion.
+                               if ( diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
+                                       lengthInsertions2 += diffs[ pointer ][ 1 ].length;
+                               } else {
+                                       lengthDeletions2 += diffs[ pointer ][ 1 ].length;
+                               }
 
-               running.innerHTML = ( bad ?
-                       "Rerunning previously failed test: <br />" :
-                       "Running: <br />" ) +
-                       getNameHtml( details.name, details.module );
-       }
+                               // Eliminate an equality that is smaller or equal to the edits on both
+                               // sides of it.
+                               if ( lastequality && ( lastequality.length <=
+                                               Math.max( lengthInsertions1, lengthDeletions1 ) ) &&
+                                               ( lastequality.length <= Math.max( lengthInsertions2,
+                                                       lengthDeletions2 ) ) ) {
 
-});
+                                       // Duplicate record.
+                                       diffs.splice(
+                                               equalities[ equalitiesLength - 1 ],
+                                               0,
+                                               [ DIFF_DELETE, lastequality ]
+                                       );
 
-function stripHtml( string ) {
-       // strip tags, html entity and whitespaces
-       return string.replace(/<\/?[^>]+(>|$)/g, "").replace(/\&quot;/g, "").replace(/\s+/g, "");
-}
+                                       // Change second copy to insert.
+                                       diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
 
-QUnit.log(function( details ) {
-       var assertList, assertLi,
-               message, expected, actual, diff,
-               showDiff = false,
-               testItem = id( "qunit-test-output-" + details.testId );
+                                       // Throw away the equality we just deleted.
+                                       equalitiesLength--;
 
-       if ( !testItem ) {
-               return;
-       }
+                                       // Throw away the previous equality (it needs to be reevaluated).
+                                       equalitiesLength--;
+                                       pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
 
-       message = escapeText( details.message ) || ( details.result ? "okay" : "failed" );
-       message = "<span class='test-message'>" + message + "</span>";
-       message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
+                                       // Reset the counters.
+                                       lengthInsertions1 = 0;
+                                       lengthDeletions1 = 0;
+                                       lengthInsertions2 = 0;
+                                       lengthDeletions2 = 0;
+                                       lastequality = null;
+                                       changes = true;
+                               }
+                       }
+                       pointer++;
+               }
 
-       // pushFailure doesn't provide details.expected
-       // when it calls, it's implicit to also not show expected and diff stuff
-       // Also, we need to check details.expected existence, as it can exist and be undefined
-       if ( !details.result && hasOwn.call( details, "expected" ) ) {
-               if ( details.negative ) {
-                       expected = escapeText( "NOT " + QUnit.dump.parse( details.expected ) );
-               } else {
-                       expected = escapeText( QUnit.dump.parse( details.expected ) );
+               // Normalize the diff.
+               if ( changes ) {
+                       this.diffCleanupMerge( diffs );
                }
 
-               actual = escapeText( QUnit.dump.parse( details.actual ) );
-               message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" +
-                       expected +
-                       "</pre></td></tr>";
+               // Find any overlaps between deletions and insertions.
+               // e.g: <del>abcxxx</del><ins>xxxdef</ins>
+               //   -> <del>abc</del>xxx<ins>def</ins>
+               // e.g: <del>xxxabc</del><ins>defxxx</ins>
+               //   -> <ins>def</ins>xxx<del>abc</del>
+               // Only extract an overlap if it is as big as the edit ahead or behind it.
+               pointer = 1;
+               while ( pointer < diffs.length ) {
+                       if ( diffs[ pointer - 1 ][ 0 ] === DIFF_DELETE &&
+                                       diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
+                               deletion = diffs[ pointer - 1 ][ 1 ];
+                               insertion = diffs[ pointer ][ 1 ];
+                               overlapLength1 = this.diffCommonOverlap( deletion, insertion );
+                               overlapLength2 = this.diffCommonOverlap( insertion, deletion );
+                               if ( overlapLength1 >= overlapLength2 ) {
+                                       if ( overlapLength1 >= deletion.length / 2 ||
+                                                       overlapLength1 >= insertion.length / 2 ) {
 
-               if ( actual !== expected ) {
+                                               // Overlap found.  Insert an equality and trim the surrounding edits.
+                                               diffs.splice(
+                                                       pointer,
+                                                       0,
+                                                       [ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ]
+                                               );
+                                               diffs[ pointer - 1 ][ 1 ] =
+                                                       deletion.substring( 0, deletion.length - overlapLength1 );
+                                               diffs[ pointer + 1 ][ 1 ] = insertion.substring( overlapLength1 );
+                                               pointer++;
+                                       }
+                               } else {
+                                       if ( overlapLength2 >= deletion.length / 2 ||
+                                                       overlapLength2 >= insertion.length / 2 ) {
 
-                       message += "<tr class='test-actual'><th>Result: </th><td><pre>" +
-                               actual + "</pre></td></tr>";
+                                               // Reverse overlap found.
+                                               // Insert an equality and swap and trim the surrounding edits.
+                                               diffs.splice(
+                                                       pointer,
+                                                       0,
+                                                       [ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ]
+                                               );
 
-                       // Don't show diff if actual or expected are booleans
-                       if ( !( /^(true|false)$/.test( actual ) ) &&
-                                       !( /^(true|false)$/.test( expected ) ) ) {
-                               diff = QUnit.diff( expected, actual );
-                               showDiff = stripHtml( diff ).length !==
-                                       stripHtml( expected ).length +
-                                       stripHtml( actual ).length;
+                                               diffs[ pointer - 1 ][ 0 ] = DIFF_INSERT;
+                                               diffs[ pointer - 1 ][ 1 ] =
+                                                       insertion.substring( 0, insertion.length - overlapLength2 );
+                                               diffs[ pointer + 1 ][ 0 ] = DIFF_DELETE;
+                                               diffs[ pointer + 1 ][ 1 ] =
+                                                       deletion.substring( overlapLength2 );
+                                               pointer++;
+                                       }
+                               }
+                               pointer++;
                        }
+                       pointer++;
+               }
+       };
 
-                       // Don't show diff if expected and actual are totally different
-                       if ( showDiff ) {
-                               message += "<tr class='test-diff'><th>Diff: </th><td><pre>" +
-                                       diff + "</pre></td></tr>";
-                       }
-               } else if ( expected.indexOf( "[object Array]" ) !== -1 ||
-                               expected.indexOf( "[object Object]" ) !== -1 ) {
-                       message += "<tr class='test-message'><th>Message: </th><td>" +
-                               "Diff suppressed as the depth of object is more than current max depth (" +
-                               QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " +
-                               " run with a higher max depth or <a href='" +
-                               escapeText( setUrl( { maxDepth: -1 } ) ) + "'>" +
-                               "Rerun</a> without max depth.</p></td></tr>";
+       /**
+        * Determine if the suffix of one string is the prefix of another.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {number} The number of characters common to the end of the first
+        *     string and the start of the second string.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffCommonOverlap = function( text1, text2 ) {
+               var text1Length, text2Length, textLength,
+                       best, length, pattern, found;
+
+               // Cache the text lengths to prevent multiple calls.
+               text1Length = text1.length;
+               text2Length = text2.length;
+
+               // Eliminate the null case.
+               if ( text1Length === 0 || text2Length === 0 ) {
+                       return 0;
                }
 
-               if ( details.source ) {
-                       message += "<tr class='test-source'><th>Source: </th><td><pre>" +
-                               escapeText( details.source ) + "</pre></td></tr>";
+               // Truncate the longer string.
+               if ( text1Length > text2Length ) {
+                       text1 = text1.substring( text1Length - text2Length );
+               } else if ( text1Length < text2Length ) {
+                       text2 = text2.substring( 0, text1Length );
                }
+               textLength = Math.min( text1Length, text2Length );
 
-               message += "</table>";
+               // Quick check for the worst case.
+               if ( text1 === text2 ) {
+                       return textLength;
+               }
 
-       // this occurs when pushFailure is set and we have an extracted stack trace
-       } else if ( !details.result && details.source ) {
-               message += "<table>" +
-                       "<tr class='test-source'><th>Source: </th><td><pre>" +
-                       escapeText( details.source ) + "</pre></td></tr>" +
-                       "</table>";
-       }
+               // Start by looking for a single character match
+               // and increase length until no match is found.
+               // Performance analysis: https://neil.fraser.name/news/2010/11/04/
+               best = 0;
+               length = 1;
+               while ( true ) {
+                       pattern = text1.substring( textLength - length );
+                       found = text2.indexOf( pattern );
+                       if ( found === -1 ) {
+                               return best;
+                       }
+                       length += found;
+                       if ( found === 0 || text1.substring( textLength - length ) ===
+                                       text2.substring( 0, length ) ) {
+                               best = length;
+                               length++;
+                       }
+               }
+       };
 
-       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+       /**
+        * Split two texts into an array of strings.  Reduce the texts to a string of
+        * hashes where each Unicode character represents one line.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
+        *     An object containing the encoded text1, the encoded text2 and
+        *     the array of unique strings.
+        *     The zeroth element of the array of unique strings is intentionally blank.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffLinesToChars = function( text1, text2 ) {
+               var lineArray, lineHash, chars1, chars2;
+               lineArray = []; // E.g. lineArray[4] === 'Hello\n'
+               lineHash = {};  // E.g. lineHash['Hello\n'] === 4
 
-       assertLi = document.createElement( "li" );
-       assertLi.className = details.result ? "pass" : "fail";
-       assertLi.innerHTML = message;
-       assertList.appendChild( assertLi );
-});
+               // '\x00' is a valid character, but various debuggers don't like it.
+               // So we'll insert a junk entry to avoid generating a null character.
+               lineArray[ 0 ] = "";
 
-QUnit.testDone(function( details ) {
-       var testTitle, time, testItem, assertList,
-               good, bad, testCounts, skipped, sourceName,
-               tests = id( "qunit-tests" );
+               /**
+                * Split a text into an array of strings.  Reduce the texts to a string of
+                * hashes where each Unicode character represents one line.
+                * Modifies linearray and linehash through being a closure.
+                * @param {string} text String to encode.
+                * @return {string} Encoded string.
+                * @private
+                */
+               function diffLinesToCharsMunge( text ) {
+                       var chars, lineStart, lineEnd, lineArrayLength, line;
+                       chars = "";
 
-       if ( !tests ) {
-               return;
-       }
+                       // Walk the text, pulling out a substring for each line.
+                       // text.split('\n') would would temporarily double our memory footprint.
+                       // Modifying text would create many large strings to garbage collect.
+                       lineStart = 0;
+                       lineEnd = -1;
 
-       testItem = id( "qunit-test-output-" + details.testId );
+                       // Keeping our own length variable is faster than looking it up.
+                       lineArrayLength = lineArray.length;
+                       while ( lineEnd < text.length - 1 ) {
+                               lineEnd = text.indexOf( "\n", lineStart );
+                               if ( lineEnd === -1 ) {
+                                       lineEnd = text.length - 1;
+                               }
+                               line = text.substring( lineStart, lineEnd + 1 );
+                               lineStart = lineEnd + 1;
 
-       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+                               if ( lineHash.hasOwnProperty ? lineHash.hasOwnProperty( line ) :
+                                                       ( lineHash[ line ] !== undefined ) ) {
+                                       chars += String.fromCharCode( lineHash[ line ] );
+                               } else {
+                                       chars += String.fromCharCode( lineArrayLength );
+                                       lineHash[ line ] = lineArrayLength;
+                                       lineArray[ lineArrayLength++ ] = line;
+                               }
+                       }
+                       return chars;
+               }
 
-       good = details.passed;
-       bad = details.failed;
+               chars1 = diffLinesToCharsMunge( text1 );
+               chars2 = diffLinesToCharsMunge( text2 );
+               return {
+                       chars1: chars1,
+                       chars2: chars2,
+                       lineArray: lineArray
+               };
+       };
 
-       // store result when possible
-       if ( config.reorder && defined.sessionStorage ) {
-               if ( bad ) {
-                       sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad );
-               } else {
-                       sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name );
+       /**
+        * Rehydrate the text in a diff from a string of line hashes to real lines of
+        * text.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        * @param {!Array.<string>} lineArray Array of unique strings.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) {
+               var x, chars, text, y;
+               for ( x = 0; x < diffs.length; x++ ) {
+                       chars = diffs[ x ][ 1 ];
+                       text = [];
+                       for ( y = 0; y < chars.length; y++ ) {
+                               text[ y ] = lineArray[ chars.charCodeAt( y ) ];
+                       }
+                       diffs[ x ][ 1 ] = text.join( "" );
                }
-       }
+       };
 
-       if ( bad === 0 ) {
+       /**
+        * Reorder and merge like edit sections.  Merge equalities.
+        * Any edit section can move as long as it doesn't cross an equality.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        */
+       DiffMatchPatch.prototype.diffCleanupMerge = function( diffs ) {
+               var pointer, countDelete, countInsert, textInsert, textDelete,
+                       commonlength, changes, diffPointer, position;
+               diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end.
+               pointer = 0;
+               countDelete = 0;
+               countInsert = 0;
+               textDelete = "";
+               textInsert = "";
+               commonlength;
+               while ( pointer < diffs.length ) {
+                       switch ( diffs[ pointer ][ 0 ] ) {
+                       case DIFF_INSERT:
+                               countInsert++;
+                               textInsert += diffs[ pointer ][ 1 ];
+                               pointer++;
+                               break;
+                       case DIFF_DELETE:
+                               countDelete++;
+                               textDelete += diffs[ pointer ][ 1 ];
+                               pointer++;
+                               break;
+                       case DIFF_EQUAL:
 
-               // Collapse the passing tests
-               addClass( assertList, "qunit-collapsed" );
-       } else if ( bad && config.collapse && !collapseNext ) {
+                               // Upon reaching an equality, check for prior redundancies.
+                               if ( countDelete + countInsert > 1 ) {
+                                       if ( countDelete !== 0 && countInsert !== 0 ) {
 
-               // Skip collapsing the first failing test
-               collapseNext = true;
-       } else {
+                                               // Factor out any common prefixes.
+                                               commonlength = this.diffCommonPrefix( textInsert, textDelete );
+                                               if ( commonlength !== 0 ) {
+                                                       if ( ( pointer - countDelete - countInsert ) > 0 &&
+                                                                       diffs[ pointer - countDelete - countInsert - 1 ][ 0 ] ===
+                                                                       DIFF_EQUAL ) {
+                                                               diffs[ pointer - countDelete - countInsert - 1 ][ 1 ] +=
+                                                                       textInsert.substring( 0, commonlength );
+                                                       } else {
+                                                               diffs.splice( 0, 0, [ DIFF_EQUAL,
+                                                                       textInsert.substring( 0, commonlength )
+                                                               ] );
+                                                               pointer++;
+                                                       }
+                                                       textInsert = textInsert.substring( commonlength );
+                                                       textDelete = textDelete.substring( commonlength );
+                                               }
 
-               // Collapse remaining tests
-               addClass( assertList, "qunit-collapsed" );
-       }
+                                               // Factor out any common suffixies.
+                                               commonlength = this.diffCommonSuffix( textInsert, textDelete );
+                                               if ( commonlength !== 0 ) {
+                                                       diffs[ pointer ][ 1 ] = textInsert.substring( textInsert.length -
+                                                                       commonlength ) + diffs[ pointer ][ 1 ];
+                                                       textInsert = textInsert.substring( 0, textInsert.length -
+                                                               commonlength );
+                                                       textDelete = textDelete.substring( 0, textDelete.length -
+                                                               commonlength );
+                                               }
+                                       }
 
-       // testItem.firstChild is the test name
-       testTitle = testItem.firstChild;
+                                       // Delete the offending records and add the merged ones.
+                                       if ( countDelete === 0 ) {
+                                               diffs.splice( pointer - countInsert,
+                                                       countDelete + countInsert, [ DIFF_INSERT, textInsert ] );
+                                       } else if ( countInsert === 0 ) {
+                                               diffs.splice( pointer - countDelete,
+                                                       countDelete + countInsert, [ DIFF_DELETE, textDelete ] );
+                                       } else {
+                                               diffs.splice(
+                                                       pointer - countDelete - countInsert,
+                                                       countDelete + countInsert,
+                                                       [ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ]
+                                               );
+                                       }
+                                       pointer = pointer - countDelete - countInsert +
+                                               ( countDelete ? 1 : 0 ) + ( countInsert ? 1 : 0 ) + 1;
+                               } else if ( pointer !== 0 && diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL ) {
 
-       testCounts = bad ?
-               "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " :
-               "";
+                                       // Merge this equality with the previous one.
+                                       diffs[ pointer - 1 ][ 1 ] += diffs[ pointer ][ 1 ];
+                                       diffs.splice( pointer, 1 );
+                               } else {
+                                       pointer++;
+                               }
+                               countInsert = 0;
+                               countDelete = 0;
+                               textDelete = "";
+                               textInsert = "";
+                               break;
+                       }
+               }
+               if ( diffs[ diffs.length - 1 ][ 1 ] === "" ) {
+                       diffs.pop(); // Remove the dummy entry at the end.
+               }
 
-       testTitle.innerHTML += " <b class='counts'>(" + testCounts +
-               details.assertions.length + ")</b>";
+               // Second pass: look for single edits surrounded on both sides by equalities
+               // which can be shifted sideways to eliminate an equality.
+               // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
+               changes = false;
+               pointer = 1;
 
-       if ( details.skipped ) {
-               testItem.className = "skipped";
-               skipped = document.createElement( "em" );
-               skipped.className = "qunit-skipped-label";
-               skipped.innerHTML = "skipped";
-               testItem.insertBefore( skipped, testTitle );
-       } else {
-               addEvent( testTitle, "click", function() {
-                       toggleClass( assertList, "qunit-collapsed" );
-               });
+               // Intentionally ignore the first and last element (don't need checking).
+               while ( pointer < diffs.length - 1 ) {
+                       if ( diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL &&
+                                       diffs[ pointer + 1 ][ 0 ] === DIFF_EQUAL ) {
 
-               testItem.className = bad ? "fail" : "pass";
+                               diffPointer = diffs[ pointer ][ 1 ];
+                               position = diffPointer.substring(
+                                       diffPointer.length - diffs[ pointer - 1 ][ 1 ].length
+                               );
 
-               time = document.createElement( "span" );
-               time.className = "runtime";
-               time.innerHTML = details.runtime + " ms";
-               testItem.insertBefore( time, assertList );
-       }
+                               // This is a single edit surrounded by equalities.
+                               if ( position === diffs[ pointer - 1 ][ 1 ] ) {
 
-       // Show the source of the test when showing assertions
-       if ( details.source ) {
-               sourceName = document.createElement( "p" );
-               sourceName.innerHTML = "<strong>Source: </strong>" + details.source;
-               addClass( sourceName, "qunit-source" );
-               if ( bad === 0 ) {
-                       addClass( sourceName, "qunit-collapsed" );
+                                       // Shift the edit over the previous equality.
+                                       diffs[ pointer ][ 1 ] = diffs[ pointer - 1 ][ 1 ] +
+                                               diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer ][ 1 ].length -
+                                                       diffs[ pointer - 1 ][ 1 ].length );
+                                       diffs[ pointer + 1 ][ 1 ] =
+                                               diffs[ pointer - 1 ][ 1 ] + diffs[ pointer + 1 ][ 1 ];
+                                       diffs.splice( pointer - 1, 1 );
+                                       changes = true;
+                               } else if ( diffPointer.substring( 0, diffs[ pointer + 1 ][ 1 ].length ) ===
+                                               diffs[ pointer + 1 ][ 1 ] ) {
+
+                                       // Shift the edit over the next equality.
+                                       diffs[ pointer - 1 ][ 1 ] += diffs[ pointer + 1 ][ 1 ];
+                                       diffs[ pointer ][ 1 ] =
+                                               diffs[ pointer ][ 1 ].substring( diffs[ pointer + 1 ][ 1 ].length ) +
+                                               diffs[ pointer + 1 ][ 1 ];
+                                       diffs.splice( pointer + 1, 1 );
+                                       changes = true;
+                               }
+                       }
+                       pointer++;
                }
-               addEvent( testTitle, "click", function() {
-                       toggleClass( sourceName, "qunit-collapsed" );
-               });
-               testItem.appendChild( sourceName );
-       }
-});
 
-if ( defined.document ) {
+               // If shifts were made, the diff needs reordering and another shift sweep.
+               if ( changes ) {
+                       this.diffCleanupMerge( diffs );
+               }
+       };
 
-       // Avoid readyState issue with phantomjs
-       // Ref: #818
-       var notPhantom = ( function( p ) {
-               return !( p && p.version && p.version.major > 0 );
-       } )( window.phantom );
+       return function( o, n ) {
+               var diff, output, text;
+               diff = new DiffMatchPatch();
+               output = diff.DiffMain( o, n );
+               diff.diffCleanupEfficiency( output );
+               text = diff.diffPrettyHtml( output );
 
-       if ( notPhantom && document.readyState === "complete" ) {
-               QUnit.load();
-       } else {
-               addEvent( window, "load", QUnit.load );
-       }
-} else {
-       config.pageLoaded = true;
-       config.autorun = true;
-}
+               return text;
+       };
+}() );
 
-})();
+}() );
index a6106e4..f25944c 100644 (file)
  */
 ( function ( $, mw ) {
 
-// Cached access key modifiers for used browser
-var cachedAccessKeyModifiers,
-
-       // Whether to use 'test-' instead of correct prefix (used for testing)
-       useTestPrefix = false,
-
-       // tag names which can have a label tag
-       // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Form-associated_content
-       labelable = 'button, input, textarea, keygen, meter, output, progress, select';
-
-/**
- * Find the modifier keys that need to be pressed together with the accesskey to trigger the input.
- *
- * The result is dependant on the ua paramater or the current platform.
- * For browsers that support accessKeyLabel, #getAccessKeyLabel never calls here.
- * Valid key values that are returned can be: ctrl, alt, option, shift, esc
- *
- * @private
- * @param {Object} [ua] An object with a 'userAgent' and 'platform' property.
- * @return {Array} Array with 0 or more of the string values: ctrl, option, alt, shift, esc
- */
-function getAccessKeyModifiers( ua ) {
-       // use cached prefix if possible
-       if ( !ua && cachedAccessKeyModifiers ) {
-               return cachedAccessKeyModifiers;
-       }
+       // Cached access key modifiers for used browser
+       var cachedAccessKeyModifiers,
+
+               // Whether to use 'test-' instead of correct prefix (used for testing)
+               useTestPrefix = false,
+
+               // tag names which can have a label tag
+               // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Form-associated_content
+               labelable = 'button, input, textarea, keygen, meter, output, progress, select';
+
+       /**
+        * Find the modifier keys that need to be pressed together with the accesskey to trigger the input.
+        *
+        * The result is dependant on the ua paramater or the current platform.
+        * For browsers that support accessKeyLabel, #getAccessKeyLabel never calls here.
+        * Valid key values that are returned can be: ctrl, alt, option, shift, esc
+        *
+        * @private
+        * @param {Object} [ua] An object with a 'userAgent' and 'platform' property.
+        * @return {Array} Array with 0 or more of the string values: ctrl, option, alt, shift, esc
+        */
+       function getAccessKeyModifiers( ua ) {
+               var profile, accessKeyModifiers;
+
+               // use cached prefix if possible
+               if ( !ua && cachedAccessKeyModifiers ) {
+                       return cachedAccessKeyModifiers;
+               }
 
-       var profile = $.client.profile( ua ),
+               profile = $.client.profile( ua );
                accessKeyModifiers = [ 'alt' ];
 
-       // Classic Opera on any platform
-       if ( profile.name === 'opera' && profile.versionNumber < 15 ) {
-               accessKeyModifiers = [ 'shift', 'esc' ];
-
-       // Chrome and modern Opera on any platform
-       } else if ( profile.name === 'chrome' || profile.name === 'opera' ) {
-               accessKeyModifiers = (
-                       profile.platform === 'mac'
-                               // Chrome on Mac
-                               ? [ 'ctrl', 'option' ]
-                               // Chrome on Windows or Linux
-                               // (both alt- and alt-shift work, but alt with E, D, F etc does not
-                               // work since they are browser shortcuts)
-                               : [ 'alt', 'shift' ]
-               );
-
-       // Non-Windows Safari with webkit_version > 526
-       } else if ( profile.platform !== 'win'
-               && profile.name === 'safari'
-               && profile.layoutVersion > 526
-       ) {
-               accessKeyModifiers = [ 'ctrl', 'alt' ];
-
-       // Safari/Konqueror on any platform, or any browser on Mac
-       // (but not Safari on Windows)
-       } else if ( !( profile.platform === 'win' && profile.name === 'safari' )
-               && ( profile.name === 'safari'
-               || profile.platform === 'mac'
-               || profile.name === 'konqueror' )
-       ) {
-               accessKeyModifiers = [ 'ctrl' ];
-
-       // Firefox/Iceweasel 2.x and later
-       } else if ( ( profile.name === 'firefox' || profile.name === 'iceweasel' )
-               && profile.versionBase > '1'
-       ) {
-               accessKeyModifiers = [ 'alt', 'shift' ];
-       }
+               // Classic Opera on any platform
+               if ( profile.name === 'opera' && profile.versionNumber < 15 ) {
+                       accessKeyModifiers = [ 'shift', 'esc' ];
+
+               // Chrome and modern Opera on any platform
+               } else if ( profile.name === 'chrome' || profile.name === 'opera' ) {
+                       accessKeyModifiers = (
+                               profile.platform === 'mac' ?
+                                       // Chrome on Mac
+                                       [ 'ctrl', 'option' ] :
+                                       // Chrome on Windows or Linux
+                                       // (both alt- and alt-shift work, but alt with E, D, F etc does not
+                                       // work since they are browser shortcuts)
+                                       [ 'alt', 'shift' ]
+                       );
+
+               // Non-Windows Safari with webkit_version > 526
+               } else if ( profile.platform !== 'win' &&
+                       profile.name === 'safari' &&
+                       profile.layoutVersion > 526
+               ) {
+                       accessKeyModifiers = [ 'ctrl', 'alt' ];
+
+               // Safari/Konqueror on any platform, or any browser on Mac
+               // (but not Safari on Windows)
+               } else if (
+                       !( profile.platform === 'win' && profile.name === 'safari' ) &&
+                       (
+                               profile.name === 'safari' ||
+                               profile.platform === 'mac' ||
+                               profile.name === 'konqueror'
+                       )
+               ) {
+                       accessKeyModifiers = [ 'ctrl' ];
+
+               // Firefox/Iceweasel 2.x and later
+               } else if (
+                       ( profile.name === 'firefox' || profile.name === 'iceweasel' ) &&
+                       profile.versionBase > '1'
+               ) {
+                       accessKeyModifiers = [ 'alt', 'shift' ];
+               }
 
-       // cache modifiers
-       if ( !ua ) {
-               cachedAccessKeyModifiers = accessKeyModifiers;
+               // cache modifiers
+               if ( !ua ) {
+                       cachedAccessKeyModifiers = accessKeyModifiers;
+               }
+               return accessKeyModifiers;
        }
-       return accessKeyModifiers;
-}
 
-/**
- * Get the access key label for an element.
- *
- * Will use native accessKeyLabel if available (currently only in Firefox 8+),
- * falls back to #getAccessKeyModifiers.
- *
- * @private
- * @param {HTMLElement} element Element to get the label for
- * @return {string} Access key label
- */
-function getAccessKeyLabel( element ) {
-       // abort early if no access key
-       if ( !element.accessKey ) {
-               return '';
-       }
-       // use accessKeyLabel if possible
-       // https://html.spec.whatwg.org/multipage/interaction.html#dom-accesskeylabel
-       if ( !useTestPrefix && element.accessKeyLabel ) {
-               return element.accessKeyLabel;
+       /**
+        * Get the access key label for an element.
+        *
+        * Will use native accessKeyLabel if available (currently only in Firefox 8+),
+        * falls back to #getAccessKeyModifiers.
+        *
+        * @private
+        * @param {HTMLElement} element Element to get the label for
+        * @return {string} Access key label
+        */
+       function getAccessKeyLabel( element ) {
+               // abort early if no access key
+               if ( !element.accessKey ) {
+                       return '';
+               }
+               // use accessKeyLabel if possible
+               // https://html.spec.whatwg.org/multipage/interaction.html#dom-accesskeylabel
+               if ( !useTestPrefix && element.accessKeyLabel ) {
+                       return element.accessKeyLabel;
+               }
+               return ( useTestPrefix ? 'test' : getAccessKeyModifiers().join( '-' ) ) + '-' + element.accessKey;
        }
-       return ( useTestPrefix ? 'test' : getAccessKeyModifiers().join( '-' ) ) + '-' + element.accessKey;
-}
-
-/**
- * Update the title for an element (on the element with the access key or it's label) to show
- * the correct access key label.
- *
- * @private
- * @param {HTMLElement} element Element with the accesskey
- * @param {HTMLElement} titleElement Element with the title to update (may be the same as `element`)
- */
-function updateTooltipOnElement( element, titleElement ) {
-       var oldTitle, parts, regexp, newTitle, accessKeyLabel;
 
-       oldTitle = titleElement.title;
-       if ( !oldTitle ) {
-               // don't add a title if the element didn't have one before
-               return;
-       }
+       /**
+        * Update the title for an element (on the element with the access key or it's label) to show
+        * the correct access key label.
+        *
+        * @private
+        * @param {HTMLElement} element Element with the accesskey
+        * @param {HTMLElement} titleElement Element with the title to update (may be the same as `element`)
+        */
+       function updateTooltipOnElement( element, titleElement ) {
+               var oldTitle, parts, regexp, newTitle, accessKeyLabel;
+
+               oldTitle = titleElement.title;
+               if ( !oldTitle ) {
+                       // don't add a title if the element didn't have one before
+                       return;
+               }
 
-       parts = ( mw.msg( 'word-separator' ) + mw.msg( 'brackets' ) ).split( '$1' );
-       regexp = new RegExp( $.map( parts, mw.RegExp.escape ).join( '.*?' ) + '$' );
-       newTitle = oldTitle.replace( regexp, '' );
-       accessKeyLabel = getAccessKeyLabel( element );
+               parts = ( mw.msg( 'word-separator' ) + mw.msg( 'brackets' ) ).split( '$1' );
+               regexp = new RegExp( $.map( parts, mw.RegExp.escape ).join( '.*?' ) + '$' );
+               newTitle = oldTitle.replace( regexp, '' );
+               accessKeyLabel = getAccessKeyLabel( element );
 
-       if ( accessKeyLabel ) {
-               // Should be build the same as in Linker::titleAttrib
-               newTitle += mw.msg( 'word-separator' ) + mw.msg( 'brackets', accessKeyLabel );
-       }
-       if ( oldTitle !== newTitle ) {
-               titleElement.title = newTitle;
+               if ( accessKeyLabel ) {
+                       // Should be build the same as in Linker::titleAttrib
+                       newTitle += mw.msg( 'word-separator' ) + mw.msg( 'brackets', accessKeyLabel );
+               }
+               if ( oldTitle !== newTitle ) {
+                       titleElement.title = newTitle;
+               }
        }
-}
 
-/**
- * Update the title for an element to show the correct access key label.
- *
- * @private
- * @param {HTMLElement} element Element with the accesskey
- */
-function updateTooltip( element ) {
-       var id, $element, $label, $labelParent;
-       updateTooltipOnElement( element, element );
-
-       // update associated label if there is one
-       $element = $( element );
-       if ( $element.is( labelable ) ) {
-               // Search it using 'for' attribute
-               id = element.id.replace( /"/g, '\\"' );
-               if ( id ) {
-                       $label = $( 'label[for="' + id + '"]' );
-                       if ( $label.length === 1 ) {
-                               updateTooltipOnElement( element, $label[ 0 ] );
+       /**
+        * Update the title for an element to show the correct access key label.
+        *
+        * @private
+        * @param {HTMLElement} element Element with the accesskey
+        */
+       function updateTooltip( element ) {
+               var id, $element, $label, $labelParent;
+               updateTooltipOnElement( element, element );
+
+               // update associated label if there is one
+               $element = $( element );
+               if ( $element.is( labelable ) ) {
+                       // Search it using 'for' attribute
+                       id = element.id.replace( /"/g, '\\"' );
+                       if ( id ) {
+                               $label = $( 'label[for="' + id + '"]' );
+                               if ( $label.length === 1 ) {
+                                       updateTooltipOnElement( element, $label[ 0 ] );
+                               }
                        }
-               }
 
-               // Search it as parent, because the form control can also be inside the label element itself
-               $labelParent = $element.parents( 'label' );
-               if ( $labelParent.length === 1 ) {
-                       updateTooltipOnElement( element, $labelParent[ 0 ] );
+                       // Search it as parent, because the form control can also be inside the label element itself
+                       $labelParent = $element.parents( 'label' );
+                       if ( $labelParent.length === 1 ) {
+                               updateTooltipOnElement( element, $labelParent[ 0 ] );
+                       }
                }
        }
-}
-
-/**
- * Update the titles for all elements in a jQuery selection.
- *
- * @return {jQuery}
- * @chainable
- */
-$.fn.updateTooltipAccessKeys = function () {
-       return this.each( function () {
-               updateTooltip( this );
-       } );
-};
 
-/**
- * getAccessKeyModifiers
- *
- * @method updateTooltipAccessKeys_getAccessKeyModifiers
- * @inheritdoc #getAccessKeyModifiers
- */
-$.fn.updateTooltipAccessKeys.getAccessKeyModifiers = getAccessKeyModifiers;
-
-/**
- * getAccessKeyLabel
- *
- * @method updateTooltipAccessKeys_getAccessKeyLabel
- * @inheritdoc #getAccessKeyLabel
- */
-$.fn.updateTooltipAccessKeys.getAccessKeyLabel = getAccessKeyLabel;
-
-/**
- * getAccessKeyPrefix
- *
- * @method updateTooltipAccessKeys_getAccessKeyPrefix
- * @deprecated since 1.27 Use #getAccessKeyModifiers
- */
-$.fn.updateTooltipAccessKeys.getAccessKeyPrefix = function ( ua ) {
-       return getAccessKeyModifiers( ua ).join( '-' ) + '-';
-};
-
-/**
- * Switch test mode on and off.
- *
- * @method updateTooltipAccessKeys_setTestMode
- * @param {boolean} mode New mode
- */
-$.fn.updateTooltipAccessKeys.setTestMode = function ( mode ) {
-       useTestPrefix = mode;
-};
-
-/**
- * @class jQuery
- * @mixins jQuery.plugin.accessKeyLabel
- */
+       /**
+        * Update the titles for all elements in a jQuery selection.
+        *
+        * @return {jQuery}
+        * @chainable
+        */
+       $.fn.updateTooltipAccessKeys = function () {
+               return this.each( function () {
+                       updateTooltip( this );
+               } );
+       };
+
+       /**
+        * getAccessKeyModifiers
+        *
+        * @method updateTooltipAccessKeys_getAccessKeyModifiers
+        * @inheritdoc #getAccessKeyModifiers
+        */
+       $.fn.updateTooltipAccessKeys.getAccessKeyModifiers = getAccessKeyModifiers;
+
+       /**
+        * getAccessKeyLabel
+        *
+        * @method updateTooltipAccessKeys_getAccessKeyLabel
+        * @inheritdoc #getAccessKeyLabel
+        */
+       $.fn.updateTooltipAccessKeys.getAccessKeyLabel = getAccessKeyLabel;
+
+       /**
+        * getAccessKeyPrefix
+        *
+        * @method updateTooltipAccessKeys_getAccessKeyPrefix
+        * @deprecated since 1.27 Use #getAccessKeyModifiers
+        * @param {Object} [ua] An object with a 'userAgent' and 'platform' property.
+        * @return {string}
+        */
+       $.fn.updateTooltipAccessKeys.getAccessKeyPrefix = function ( ua ) {
+               return getAccessKeyModifiers( ua ).join( '-' ) + '-';
+       };
+
+       /**
+        * Switch test mode on and off.
+        *
+        * @method updateTooltipAccessKeys_setTestMode
+        * @param {boolean} mode New mode
+        */
+       $.fn.updateTooltipAccessKeys.setTestMode = function ( mode ) {
+               useTestPrefix = mode;
+       };
+
+       /**
+        * @class jQuery
+        * @mixins jQuery.plugin.accessKeyLabel
+        */
 
 }( jQuery, mediaWiki ) );
index fd7e8d1..8716b69 100644 (file)
  */
 ( function ( $ ) {
 
-var
-       // Cache ellipsed substrings for every string-width-position combination
-       cache = {},
+       var
+               // Cache ellipsed substrings for every string-width-position combination
+               cache = {},
 
-       // Use a separate cache when match highlighting is enabled
-       matchTextCache = {};
+               // Use a separate cache when match highlighting is enabled
+               matchTextCache = {};
 
-// Due to <https://github.com/jscs-dev/jscs-jsdoc/issues/136>
-// jscs:disable jsDoc
-/**
- * Automatically truncate the plain text contents of an element and add an ellipsis
- *
- * @param {Object} options
- * @param {'left'|'center'|'right'} [options.position='center'] Where to remove text.
- * @param {boolean} [options.tooltip=false] Whether to show a tooltip with the remainder
- * of the text.
- * @param {boolean} [options.restoreText=false] Whether to save the text for restoring
- * later.
- * @param {boolean} [options.hasSpan=false] Whether the element is already a container,
- * or if the library should create a new container for it.
- * @param {string|null} [options.matchText=null] Text to highlight, e.g. search terms.
- * @return {jQuery}
- * @chainable
- */
-$.fn.autoEllipsis = function ( options ) {
-       options = $.extend( {
-               position: 'center',
-               tooltip: false,
-               restoreText: false,
-               hasSpan: false,
-               matchText: null
-       }, options );
+       // Due to <https://github.com/jscs-dev/jscs-jsdoc/issues/136>
+       // jscs:disable jsDoc
+       /**
       * Automatically truncate the plain text contents of an element and add an ellipsis
       *
       * @param {Object} options
       * @param {'left'|'center'|'right'} [options.position='center'] Where to remove text.
       * @param {boolean} [options.tooltip=false] Whether to show a tooltip with the remainder
       * of the text.
       * @param {boolean} [options.restoreText=false] Whether to save the text for restoring
       * later.
       * @param {boolean} [options.hasSpan=false] Whether the element is already a container,
       * or if the library should create a new container for it.
       * @param {string|null} [options.matchText=null] Text to highlight, e.g. search terms.
       * @return {jQuery}
       * @chainable
       */
+       $.fn.autoEllipsis = function ( options ) {
+               options = $.extend( {
+                       position: 'center',
+                       tooltip: false,
+                       restoreText: false,
+                       hasSpan: false,
+                       matchText: null
+               }, options );
 
-       return this.each( function () {
-               var $trimmableText,
-                       text, trimmableText, w, pw,
-                       l, r, i, side, m,
-                       // container element - used for measuring against
-                       $container = $( this );
+               return this.each( function () {
+                       var $trimmableText,
+                               text, trimmableText, w, pw,
+                               l, r, i, side, m,
+                               // container element - used for measuring against
+                               $container = $( this );
 
-               if ( options.restoreText ) {
-                       if ( !$container.data( 'autoEllipsis.originalText' ) ) {
-                               $container.data( 'autoEllipsis.originalText', $container.text() );
-                       } else {
-                               $container.text( $container.data( 'autoEllipsis.originalText' ) );
+                       if ( options.restoreText ) {
+                               if ( !$container.data( 'autoEllipsis.originalText' ) ) {
+                                       $container.data( 'autoEllipsis.originalText', $container.text() );
+                               } else {
+                                       $container.text( $container.data( 'autoEllipsis.originalText' ) );
+                               }
                        }
-               }
 
-               // trimmable text element - only the text within this element will be trimmed
-               if ( options.hasSpan ) {
-                       $trimmableText = $container.children( options.selector );
-               } else {
-                       $trimmableText = $( '<span>' )
-                               .css( 'whiteSpace', 'nowrap' )
-                               .text( $container.text() );
-                       $container
-                               .empty()
-                               .append( $trimmableText );
-               }
+                       // trimmable text element - only the text within this element will be trimmed
+                       if ( options.hasSpan ) {
+                               $trimmableText = $container.children( options.selector );
+                       } else {
+                               $trimmableText = $( '<span>' )
+                                       .css( 'whiteSpace', 'nowrap' )
+                                       .text( $container.text() );
+                               $container
+                                       .empty()
+                                       .append( $trimmableText );
+                       }
 
-               text = $container.text();
-               trimmableText = $trimmableText.text();
-               w = $container.width();
-               pw = 0;
+                       text = $container.text();
+                       trimmableText = $trimmableText.text();
+                       w = $container.width();
+                       pw = 0;
 
-               // Try cache
-               if ( options.matchText ) {
-                       if ( !( text in matchTextCache ) ) {
-                               matchTextCache[ text ] = {};
-                       }
-                       if ( !( options.matchText in matchTextCache[ text ] ) ) {
-                               matchTextCache[ text ][ options.matchText ] = {};
-                       }
-                       if ( !( w in matchTextCache[ text ][ options.matchText ] ) ) {
-                               matchTextCache[ text ][ options.matchText ][ w ] = {};
-                       }
-                       if ( options.position in matchTextCache[ text ][ options.matchText ][ w ] ) {
-                               $container.html( matchTextCache[ text ][ options.matchText ][ w ][ options.position ] );
-                               if ( options.tooltip ) {
-                                       $container.attr( 'title', text );
+                       // Try cache
+                       if ( options.matchText ) {
+                               if ( !( text in matchTextCache ) ) {
+                                       matchTextCache[ text ] = {};
                                }
-                               return;
-                       }
-               } else {
-                       if ( !( text in cache ) ) {
-                               cache[ text ] = {};
-                       }
-                       if ( !( w in cache[ text ] ) ) {
-                               cache[ text ][ w ] = {};
-                       }
-                       if ( options.position in cache[ text ][ w ] ) {
-                               $container.html( cache[ text ][ w ][ options.position ] );
-                               if ( options.tooltip ) {
-                                       $container.attr( 'title', text );
+                               if ( !( options.matchText in matchTextCache[ text ] ) ) {
+                                       matchTextCache[ text ][ options.matchText ] = {};
+                               }
+                               if ( !( w in matchTextCache[ text ][ options.matchText ] ) ) {
+                                       matchTextCache[ text ][ options.matchText ][ w ] = {};
+                               }
+                               if ( options.position in matchTextCache[ text ][ options.matchText ][ w ] ) {
+                                       $container.html( matchTextCache[ text ][ options.matchText ][ w ][ options.position ] );
+                                       if ( options.tooltip ) {
+                                               $container.attr( 'title', text );
+                                       }
+                                       return;
+                               }
+                       } else {
+                               if ( !( text in cache ) ) {
+                                       cache[ text ] = {};
+                               }
+                               if ( !( w in cache[ text ] ) ) {
+                                       cache[ text ][ w ] = {};
+                               }
+                               if ( options.position in cache[ text ][ w ] ) {
+                                       $container.html( cache[ text ][ w ][ options.position ] );
+                                       if ( options.tooltip ) {
+                                               $container.attr( 'title', text );
+                                       }
+                                       return;
                                }
-                               return;
                        }
-               }
 
-               if ( $trimmableText.width() + pw > w ) {
-                       switch ( options.position ) {
-                               case 'right':
-                                       // Use binary search-like technique for efficiency
-                                       l = 0;
-                                       r = trimmableText.length;
-                                       do {
-                                               m = Math.ceil( ( l + r ) / 2 );
-                                               $trimmableText.text( trimmableText.slice( 0, m ) + '...' );
-                                               if ( $trimmableText.width() + pw > w ) {
-                                                       // Text is too long
-                                                       r = m - 1;
-                                               } else {
-                                                       l = m;
+                       if ( $trimmableText.width() + pw > w ) {
+                               switch ( options.position ) {
+                                       case 'right':
+                                               // Use binary search-like technique for efficiency
+                                               l = 0;
+                                               r = trimmableText.length;
+                                               do {
+                                                       m = Math.ceil( ( l + r ) / 2 );
+                                                       $trimmableText.text( trimmableText.slice( 0, m ) + '...' );
+                                                       if ( $trimmableText.width() + pw > w ) {
+                                                               // Text is too long
+                                                               r = m - 1;
+                                                       } else {
+                                                               l = m;
+                                                       }
+                                               } while ( l < r );
+                                               $trimmableText.text( trimmableText.slice( 0, l ) + '...' );
+                                               break;
+                                       case 'center':
+                                               // TODO: Use binary search like for 'right'
+                                               i = [ Math.round( trimmableText.length / 2 ), Math.round( trimmableText.length / 2 ) ];
+                                               // Begin with making the end shorter
+                                               side = 1;
+                                               while ( $trimmableText.outerWidth() + pw > w && i[ 0 ] > 0 ) {
+                                                       $trimmableText.text( trimmableText.slice( 0, i[ 0 ] ) + '...' + trimmableText.slice( i[ 1 ] ) );
+                                                       // Alternate between trimming the end and begining
+                                                       if ( side === 0 ) {
+                                                               // Make the begining shorter
+                                                               i[ 0 ]--;
+                                                               side = 1;
+                                                       } else {
+                                                               // Make the end shorter
+                                                               i[ 1 ]++;
+                                                               side = 0;
+                                                       }
                                                }
-                                       } while ( l < r );
-                                       $trimmableText.text( trimmableText.slice( 0, l ) + '...' );
-                                       break;
-                               case 'center':
-                                       // TODO: Use binary search like for 'right'
-                                       i = [ Math.round( trimmableText.length / 2 ), Math.round( trimmableText.length / 2 ) ];
-                                       // Begin with making the end shorter
-                                       side = 1;
-                                       while ( $trimmableText.outerWidth() + pw > w && i[ 0 ] > 0 ) {
-                                               $trimmableText.text( trimmableText.slice( 0, i[ 0 ] ) + '...' + trimmableText.slice( i[ 1 ] ) );
-                                               // Alternate between trimming the end and begining
-                                               if ( side === 0 ) {
-                                                       // Make the begining shorter
-                                                       i[ 0 ]--;
-                                                       side = 1;
-                                               } else {
-                                                       // Make the end shorter
-                                                       i[ 1 ]++;
-                                                       side = 0;
+                                               break;
+                                       case 'left':
+                                               // TODO: Use binary search like for 'right'
+                                               r = 0;
+                                               while ( $trimmableText.outerWidth() + pw > w && r < trimmableText.length ) {
+                                                       $trimmableText.text( '...' + trimmableText.slice( r ) );
+                                                       r++;
                                                }
-                                       }
-                                       break;
-                               case 'left':
-                                       // TODO: Use binary search like for 'right'
-                                       r = 0;
-                                       while ( $trimmableText.outerWidth() + pw > w && r < trimmableText.length ) {
-                                               $trimmableText.text( '...' + trimmableText.slice( r ) );
-                                               r++;
-                                       }
-                                       break;
+                                               break;
+                               }
+                       }
+                       if ( options.tooltip ) {
+                               $container.attr( 'title', text );
+                       }
+                       if ( options.matchText ) {
+                               $container.highlightText( options.matchText );
+                               matchTextCache[ text ][ options.matchText ][ w ][ options.position ] = $container.html();
+                       } else {
+                               cache[ text ][ w ][ options.position ] = $container.html();
                        }
-               }
-               if ( options.tooltip ) {
-                       $container.attr( 'title', text );
-               }
-               if ( options.matchText ) {
-                       $container.highlightText( options.matchText );
-                       matchTextCache[ text ][ options.matchText ][ w ][ options.position ] = $container.html();
-               } else {
-                       cache[ text ][ w ][ options.position ] = $container.html();
-               }
 
-       } );
-};
-// jscs:enable jsDoc
+               } );
+       };
+       // jscs:enable jsDoc
 
-/**
- * @class jQuery
- * @mixins jQuery.plugin.autoEllipsis
- */
+       /**
       * @class jQuery
       * @mixins jQuery.plugin.autoEllipsis
       */
 
 }( jQuery ) );
index b1692bb..567bec8 100644 (file)
@@ -3,6 +3,17 @@
  */
 ( function ( $ ) {
 
+       var eventKeys = [
+               'keyup.byteLimit',
+               'keydown.byteLimit',
+               'change.byteLimit',
+               'mouseup.byteLimit',
+               'cut.byteLimit',
+               'paste.byteLimit',
+               'focus.byteLimit',
+               'blur.byteLimit'
+       ].join( ' ' );
+
        /**
         * Utility function to trim down a string, based on byteLimit
         * and given a safe start position. It supports insertion anywhere
                };
        };
 
-       var eventKeys = [
-               'keyup.byteLimit',
-               'keydown.byteLimit',
-               'change.byteLimit',
-               'mouseup.byteLimit',
-               'cut.byteLimit',
-               'paste.byteLimit',
-               'focus.byteLimit',
-               'blur.byteLimit'
-       ].join( ' ' );
-
        /**
         * Enforces a byte limit on an input field, so that UTF-8 entries are counted as well,
         * when, for example, a database field has a byte limit rather than a character limit.
index a3cc8fc..70dc105 100644 (file)
@@ -10,7 +10,6 @@
 ( function ( $ ) {
 
        function getColor( elem, attr ) {
-               /*jshint boss:true */
                var color;
 
                do {
@@ -22,6 +21,7 @@
                        }
 
                        attr = 'backgroundColor';
+               // eslint-disable-next-line no-cond-assign
                } while ( elem = elem.parentNode );
 
                return $.colorUtil.getRGB( color );
index c14f2c8..c53ec3b 100644 (file)
@@ -23,7 +23,6 @@
                 * @return {Array}
                 */
                getRGB: function ( color ) {
-                       /*jshint boss:true */
                        var result;
 
                        // Check if we're already dealing with an array of colors
@@ -32,6 +31,7 @@
                        }
 
                        // Look for rgb(num,num,num)
+                       // eslint-disable-next-line no-cond-assign
                        if ( result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec( color ) ) {
                                return [
                                        parseInt( result[ 1 ], 10 ),
@@ -41,6 +41,7 @@
                        }
 
                        // Look for rgb(num%,num%,num%)
+                       // eslint-disable-next-line no-cond-assign
                        if ( result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec( color ) ) {
                                return [
                                        parseFloat( result[ 1 ] ) * 2.55,
@@ -50,6 +51,7 @@
                        }
 
                        // Look for #a0b1c2
+                       // eslint-disable-next-line no-cond-assign
                        if ( result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec( color ) ) {
                                return [
                                        parseInt( result[ 1 ], 16 ),
@@ -59,6 +61,7 @@
                        }
 
                        // Look for #fff
+                       // eslint-disable-next-line no-cond-assign
                        if ( result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec( color ) ) {
                                return [
                                        parseInt( result[ 1 ] + result[ 1 ], 16 ),
@@ -68,6 +71,7 @@
                        }
 
                        // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
+                       // eslint-disable-next-line no-cond-assign
                        if ( result = /rgba\(0, 0, 0, 0\)/.exec( color ) ) {
                                return $.colorUtil.colors.transparent;
                        }
                 * @return {number[]} The HSL representation
                 */
                rgbToHsl: function ( r, g, b ) {
+                       var d, h, s, l, min, max;
+
                        r = r / 255;
                        g = g / 255;
                        b = b / 255;
 
-                       var d,
-                               max = Math.max( r, g, b ),
-                               min = Math.min( r, g, b ),
-                               h,
-                               s,
-                               l = ( max + min ) / 2;
+                       max = Math.max( r, g, b );
+                       min = Math.min( r, g, b );
+                       l = ( max + min ) / 2;
 
                        if ( max === min ) {
                                // achromatic
index 1ecce6c..7931c81 100644 (file)
@@ -12,6 +12,7 @@
                return data;
        };
 
+       // eslint-disable-next-line valid-jsdoc
        /**
         * Enable inline confirmation for given clickable element (like `<a />` or `<button />`).
         *
index f9db72f..0bfa8f3 100644 (file)
@@ -19,6 +19,9 @@
        $.expandableField = {
                /**
                 * Expand the field, make the callback
+                *
+                * @param {jQuery.Event} e Event
+                * @param {Object} context
                 */
                expandField: function ( e, context ) {
                        context.config.beforeExpand.call( context.data.$field, context );
@@ -29,6 +32,9 @@
                },
                /**
                 * Condense the field, make the callback
+                *
+                * @param {jQuery.Event} e Event
+                * @param {Object} context
                 */
                condenseField: function ( e, context ) {
                        context.config.beforeCondense.call( context.data.$field, context );
index 7d308f8..7a7109c 100644 (file)
  */
 ( function ( $ ) {
 
-/**
- * Get reported or approximate device pixel ratio.
- *
- * - 1.0 means 1 CSS pixel is 1 hardware pixel
- * - 2.0 means 1 CSS pixel is 2 hardware pixels
- * - etc.
- *
- * Uses `window.devicePixelRatio` if available, or CSS media queries on IE.
- *
- * @static
- * @inheritable
- * @return {number} Device pixel ratio
- */
-$.devicePixelRatio = function () {
-       if ( window.devicePixelRatio !== undefined ) {
-               // Most web browsers:
-               // * WebKit/Blink (Safari, Chrome, Android browser, etc)
-               // * Opera
-               // * Firefox 18+
-               // * Microsoft Edge (Windows 10)
-               return window.devicePixelRatio;
-       } else if ( window.msMatchMedia !== undefined ) {
-               // Windows 8 desktops / tablets, probably Windows Phone 8
-               //
-               // IE 10/11 doesn't report pixel ratio directly, but we can get the
-               // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
-               // simplicity, but you may get different values depending on zoom
-               // factor, size of screen and orientation in Metro IE.
-               if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
+       /**
+        * Get reported or approximate device pixel ratio.
+        *
+        * - 1.0 means 1 CSS pixel is 1 hardware pixel
+        * - 2.0 means 1 CSS pixel is 2 hardware pixels
+        * - etc.
+        *
+        * Uses `window.devicePixelRatio` if available, or CSS media queries on IE.
+        *
+        * @static
+        * @inheritable
+        * @return {number} Device pixel ratio
+        */
+       $.devicePixelRatio = function () {
+               if ( window.devicePixelRatio !== undefined ) {
+                       // Most web browsers:
+                       // * WebKit/Blink (Safari, Chrome, Android browser, etc)
+                       // * Opera
+                       // * Firefox 18+
+                       // * Microsoft Edge (Windows 10)
+                       return window.devicePixelRatio;
+               } else if ( window.msMatchMedia !== undefined ) {
+                       // Windows 8 desktops / tablets, probably Windows Phone 8
+                       //
+                       // IE 10/11 doesn't report pixel ratio directly, but we can get the
+                       // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
+                       // simplicity, but you may get different values depending on zoom
+                       // factor, size of screen and orientation in Metro IE.
+                       if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
+                               return 2;
+                       } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
+                               return 1.5;
+                       } else {
+                               return 1;
+                       }
+               } else {
+                       // Legacy browsers...
+                       // Assume 1 if unknown.
+                       return 1;
+               }
+       };
+
+       /**
+        * Bracket a given device pixel ratio to one of [1, 1.5, 2].
+        *
+        * This is useful for grabbing images on the fly with sizes based on the display
+        * density, without causing slowdown and extra thumbnail renderings on devices
+        * that are slightly different from the most common sizes.
+        *
+        * The bracketed ratios match the default 'srcset' output on MediaWiki thumbnails,
+        * so will be consistent with default renderings.
+        *
+        * @static
+        * @inheritable
+        * @param {number} baseRatio Base ratio
+        * @return {number} Device pixel ratio
+        */
+       $.bracketDevicePixelRatio = function ( baseRatio ) {
+               if ( baseRatio > 1.5 ) {
                        return 2;
-               } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
+               } else if ( baseRatio > 1 ) {
                        return 1.5;
                } else {
                        return 1;
                }
-       } else {
-               // Legacy browsers...
-               // Assume 1 if unknown.
-               return 1;
-       }
-};
-
-/**
- * Bracket a given device pixel ratio to one of [1, 1.5, 2].
- *
- * This is useful for grabbing images on the fly with sizes based on the display
- * density, without causing slowdown and extra thumbnail renderings on devices
- * that are slightly different from the most common sizes.
- *
- * The bracketed ratios match the default 'srcset' output on MediaWiki thumbnails,
- * so will be consistent with default renderings.
- *
- * @static
- * @inheritable
- * @return {number} Device pixel ratio
- */
-$.bracketDevicePixelRatio = function ( baseRatio ) {
-       if ( baseRatio > 1.5 ) {
-               return 2;
-       } else if ( baseRatio > 1 ) {
-               return 1.5;
-       } else {
-               return 1;
-       }
-};
+       };
 
-/**
- * Get reported or approximate device pixel ratio, bracketed to [1, 1.5, 2].
- *
- * This is useful for grabbing images on the fly with sizes based on the display
- * density, without causing slowdown and extra thumbnail renderings on devices
- * that are slightly different from the most common sizes.
- *
- * The bracketed ratios match the default 'srcset' output on MediaWiki thumbnails,
- * so will be consistent with default renderings.
- *
- * - 1.0 means 1 CSS pixel is 1 hardware pixel
- * - 1.5 means 1 CSS pixel is 1.5 hardware pixels
- * - 2.0 means 1 CSS pixel is 2 hardware pixels
- *
- * @static
- * @inheritable
- * @return {number} Device pixel ratio
- */
-$.bracketedDevicePixelRatio = function () {
-       return $.bracketDevicePixelRatio( $.devicePixelRatio() );
-};
+       /**
       * Get reported or approximate device pixel ratio, bracketed to [1, 1.5, 2].
       *
       * This is useful for grabbing images on the fly with sizes based on the display
       * density, without causing slowdown and extra thumbnail renderings on devices
       * that are slightly different from the most common sizes.
       *
       * The bracketed ratios match the default 'srcset' output on MediaWiki thumbnails,
       * so will be consistent with default renderings.
       *
       * - 1.0 means 1 CSS pixel is 1 hardware pixel
       * - 1.5 means 1 CSS pixel is 1.5 hardware pixels
       * - 2.0 means 1 CSS pixel is 2 hardware pixels
       *
       * @static
       * @inheritable
       * @return {number} Device pixel ratio
       */
+       $.bracketedDevicePixelRatio = function () {
+               return $.bracketDevicePixelRatio( $.devicePixelRatio() );
+       };
 
-/**
- * Implement responsive images based on srcset attributes, if browser has no
- * native srcset support.
- *
- * @return {jQuery} This selection
- * @chainable
- */
-$.fn.hidpi = function () {
-       var $target = this,
-               // TODO add support for dpi media query checks on Firefox, IE
-               devicePixelRatio = $.devicePixelRatio(),
-               testImage = new Image();
+       /**
       * Implement responsive images based on srcset attributes, if browser has no
       * native srcset support.
       *
       * @return {jQuery} This selection
       * @chainable
       */
+       $.fn.hidpi = function () {
+               var $target = this,
+                       // TODO add support for dpi media query checks on Firefox, IE
+                       devicePixelRatio = $.devicePixelRatio(),
+                       testImage = new Image();
 
-       if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
-               // No native srcset support.
-               $target.find( 'img' ).each( function () {
-                       var $img = $( this ),
-                               srcset = $img.attr( 'srcset' ),
-                               match;
-                       if ( typeof srcset === 'string' && srcset !== '' ) {
-                               match = $.matchSrcSet( devicePixelRatio, srcset );
-                               if ( match !== null ) {
-                                       $img.attr( 'src', match );
+               if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
+                       // No native srcset support.
+                       $target.find( 'img' ).each( function () {
+                               var $img = $( this ),
+                                       srcset = $img.attr( 'srcset' ),
+                                       match;
+                               if ( typeof srcset === 'string' && srcset !== '' ) {
+                                       match = $.matchSrcSet( devicePixelRatio, srcset );
+                                       if ( match !== null ) {
+                                               $img.attr( 'src', match );
+                                       }
                                }
-                       }
-               } );
-       }
+                       } );
+               }
 
-       return $target;
-};
+               return $target;
+       };
 
-/**
- * Match a srcset entry for the given device pixel ratio
- *
- * Exposed for testing.
- *
- * @private
- * @static
- * @param {number} devicePixelRatio
- * @param {string} srcset
- * @return {Mixed} null or the matching src string
- */
-$.matchSrcSet = function ( devicePixelRatio, srcset ) {
-       var candidates,
-               candidate,
-               bits,
-               src,
-               i,
-               ratioStr,
-               ratio,
-               selectedRatio = 1,
-               selectedSrc = null;
-       candidates = srcset.split( / *, */ );
-       for ( i = 0; i < candidates.length; i++ ) {
-               candidate = candidates[ i ];
-               bits = candidate.split( / +/ );
-               src = bits[ 0 ];
-               if ( bits.length > 1 && bits[ 1 ].charAt( bits[ 1 ].length - 1 ) === 'x' ) {
-                       ratioStr = bits[ 1 ].slice( 0, -1 );
-                       ratio = parseFloat( ratioStr );
-                       if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
-                               selectedRatio = ratio;
-                               selectedSrc = src;
+       /**
+        * Match a srcset entry for the given device pixel ratio
+        *
+        * Exposed for testing.
+        *
+        * @private
+        * @static
+        * @param {number} devicePixelRatio
+        * @param {string} srcset
+        * @return {Mixed} null or the matching src string
+        */
+       $.matchSrcSet = function ( devicePixelRatio, srcset ) {
+               var candidates,
+                       candidate,
+                       bits,
+                       src,
+                       i,
+                       ratioStr,
+                       ratio,
+                       selectedRatio = 1,
+                       selectedSrc = null;
+               candidates = srcset.split( / *, */ );
+               for ( i = 0; i < candidates.length; i++ ) {
+                       candidate = candidates[ i ];
+                       bits = candidate.split( / +/ );
+                       src = bits[ 0 ];
+                       if ( bits.length > 1 && bits[ 1 ].charAt( bits[ 1 ].length - 1 ) === 'x' ) {
+                               ratioStr = bits[ 1 ].slice( 0, -1 );
+                               ratio = parseFloat( ratioStr );
+                               if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
+                                       selectedRatio = ratio;
+                                       selectedSrc = src;
+                               }
                        }
                }
-       }
-       return selectedSrc;
-};
+               return selectedSrc;
+       };
 
-/**
- * @class jQuery
- * @mixins jQuery.plugin.hidpi
- */
+       /**
       * @class jQuery
       * @mixins jQuery.plugin.hidpi
       */
 
 }( jQuery ) );
index e37f19b..3feca81 100644 (file)
                                        // replace the matched node, with our span-wrapped clone of the matched node
                                        middlebit.parentNode.replaceChild( spannode, middlebit );
                                }
-                       } else if ( node.nodeType === Node.ELEMENT_NODE
+                       } else if (
+                               node.nodeType === Node.ELEMENT_NODE &&
                                // element with childnodes, and not a script, style or an element we created
-                               && node.childNodes
-                               && !/(script|style)/i.test( node.tagName )
-                               && !( node.tagName.toLowerCase() === 'span'
-                                       && node.className.match( /\bhighlight/ )
+                               node.childNodes &&
+                               !/(script|style)/i.test( node.tagName ) &&
+                               !(
+                                       node.tagName.toLowerCase() === 'span' &&
+                                       node.className.match( /\bhighlight/ )
                                )
                        ) {
                                for ( i = 0; i < node.childNodes.length; ++i ) {
index f5932b2..05b3891 100644 (file)
  */
 ( function ( $, mw ) {
 
-/**
- * Gets a localized message, using parameters from options if present.
- *
- * @ignore
- * @param {Object} options
- * @param {string} key
- * @return {string} Localized message
- */
-function msg( options, key ) {
-       var args = options.params[ key ] || [];
-       // Format: mw.msg( key [, p1, p2, ...] )
-       args.unshift( options.prefix + ( options.keys[ key ] || key ) );
-       return mw.msg.apply( mw, args );
-}
+       /**
       * Gets a localized message, using parameters from options if present.
       *
       * @ignore
       * @param {Object} options
       * @param {string} key
       * @return {string} Localized message
       */
+       function msg( options, key ) {
+               var args = options.params[ key ] || [];
+               // Format: mw.msg( key [, p1, p2, ...] )
+               args.unshift( options.prefix + ( options.keys[ key ] || key ) );
+               return mw.msg.apply( mw, args );
+       }
 
-/**
- * Localizes a DOM selection by replacing <html:msg /> elements with localized text and adding
- * localized title and alt attributes to elements with title-msg and alt-msg attributes
- * respectively.
- *
- * Call on a selection of HTML which contains `<html:msg key="message-key" />` elements or elements
- * with title-msg="message-key", alt-msg="message-key" or placeholder-msg="message-key" attributes.
- * `<html:msg />` elements will be replaced with localized text, *-msg attributes will be replaced
- * with attributes that do not have the "-msg" suffix and contain a localized message.
- *
- * Example:
- *     // Messages: { 'title': 'Awesome', 'desc': 'Cat doing backflip' 'search' contains 'Search' }
- *     var html = '\
- *         <p>\
- *             <html:msg key="title" />\
- *             <img src="something.jpg" title-msg="title" alt-msg="desc" />\
- *             <input type="text" placeholder-msg="search" />\
- *         </p>';
- *     $( 'body' ).append( $( html ).localize() );
- *
- * Appends something like this to the body...
- *     <p>
- *         Awesome
- *         <img src="something.jpg" title="Awesome" alt="Cat doing backflip" />
- *         <input type="text" placeholder="Search" />
- *     </p>
- *
- * Arguments can be passed into uses of a message using the params property of the options object
- * given to .localize(). Multiple messages can be given parameters, because the params property is
- * an object keyed by the message key to apply the parameters to, each containing an array of
- * parameters to use. The limitation is that you can not use different parameters to individual uses
- * of a message in the same selection being localized - they will all recieve the same parameters.
- *
- * Example:
- *     // Messages: { 'easy-as': 'Easy as $1 $2 $3.' }
- *     var html = '<p><html:msg key="easy-as" /></p>';
- *     $( 'body' ).append( $( html ).localize( { 'params': { 'easy-as': ['a', 'b', 'c'] } } ) );
- *
- * Appends something like this to the body...
- *     <p>Easy as a, b, c</p>
- *
- * Raw HTML content can be used, instead of it being escaped as text. To do this, just use the raw
- * attribute on a msg element.
- *
- * Example:
- *     // Messages: { 'hello': '<b><i>Hello</i> $1!</b>' }
- *     var html = '\
- *         <p>\
- *             <!-- escaped: --><html:msg key="hello" />\
- *             <!-- raw: --><html:msg key="hello" raw />\
- *         </p>';
- *     $( 'body' ).append( $( html ).localize( { 'params': { 'hello': ['world'] } } ) );
- *
- * Appends something like this to the body...
- *     <p>
- *         <!-- escaped: -->&lt;b&gt;&lt;i&gt;Hello&lt;/i&gt; world!&lt;/b&gt;
- *         <!-- raw: --><b><i>Hello</i> world!</b>
- *     </p>
- *
- * Message keys can also be remapped, allowing the same generic template to be used with a variety
- * of messages. This is important for improving re-usability of templates.
- *
- * Example:
- *     // Messages: { 'good-afternoon': 'Good afternoon' }
- *     var html = '<p><html:msg key="greeting" /></p>';
- *     $( 'body' ).append( $( html ).localize( { 'keys': { 'greeting': 'good-afternoon' } } ) );
- *
- * Appends something like this to the body...
- *     <p>Good afternoon</p>
- *
- * Message keys can also be prefixed globally, which is handy when writing extensions, where by
- * convention all messages are prefixed with the extension's name.
- *
- * Example:
- *     // Messages: { 'teleportation-warning': 'You may not get there all in one piece.' }
- *     var html = '<p><html:msg key="warning" /></p>';
- *     $( 'body' ).append( $( html ).localize( { 'prefix': 'teleportation-' } ) );
- *
- * Appends something like this to the body...
- *     <p>You may not get there all in one piece.</p>
- *
- * @param {Object} options Map of options to be used while localizing
- * @param {string} options.prefix String to prepend to all message keys
- * @param {Object} options.keys Message key aliases, used for remapping keys to a template
- * @param {Object} options.params Lists of parameters to use with certain message keys
- * @return {jQuery}
- * @chainable
- */
-$.fn.localize = function ( options ) {
-       var $target = this,
-               attributes = [ 'title', 'alt', 'placeholder' ];
+       /**
       * Localizes a DOM selection by replacing <html:msg /> elements with localized text and adding
       * localized title and alt attributes to elements with title-msg and alt-msg attributes
       * respectively.
       *
       * Call on a selection of HTML which contains `<html:msg key="message-key" />` elements or elements
       * with title-msg="message-key", alt-msg="message-key" or placeholder-msg="message-key" attributes.
       * `<html:msg />` elements will be replaced with localized text, *-msg attributes will be replaced
       * with attributes that do not have the "-msg" suffix and contain a localized message.
       *
       * Example:
       *     // Messages: { 'title': 'Awesome', 'desc': 'Cat doing backflip' 'search' contains 'Search' }
       *     var html = '\
       *         <p>\
       *             <html:msg key="title" />\
       *             <img src="something.jpg" title-msg="title" alt-msg="desc" />\
       *             <input type="text" placeholder-msg="search" />\
       *         </p>';
       *     $( 'body' ).append( $( html ).localize() );
       *
       * Appends something like this to the body...
       *     <p>
       *         Awesome
       *         <img src="something.jpg" title="Awesome" alt="Cat doing backflip" />
       *         <input type="text" placeholder="Search" />
       *     </p>
       *
       * Arguments can be passed into uses of a message using the params property of the options object
       * given to .localize(). Multiple messages can be given parameters, because the params property is
       * an object keyed by the message key to apply the parameters to, each containing an array of
       * parameters to use. The limitation is that you can not use different parameters to individual uses
       * of a message in the same selection being localized - they will all recieve the same parameters.
       *
       * Example:
       *     // Messages: { 'easy-as': 'Easy as $1 $2 $3.' }
       *     var html = '<p><html:msg key="easy-as" /></p>';
       *     $( 'body' ).append( $( html ).localize( { 'params': { 'easy-as': ['a', 'b', 'c'] } } ) );
       *
       * Appends something like this to the body...
       *     <p>Easy as a, b, c</p>
       *
       * Raw HTML content can be used, instead of it being escaped as text. To do this, just use the raw
       * attribute on a msg element.
       *
       * Example:
       *     // Messages: { 'hello': '<b><i>Hello</i> $1!</b>' }
       *     var html = '\
       *         <p>\
       *             <!-- escaped: --><html:msg key="hello" />\
       *             <!-- raw: --><html:msg key="hello" raw />\
       *         </p>';
       *     $( 'body' ).append( $( html ).localize( { 'params': { 'hello': ['world'] } } ) );
       *
       * Appends something like this to the body...
       *     <p>
       *         <!-- escaped: -->&lt;b&gt;&lt;i&gt;Hello&lt;/i&gt; world!&lt;/b&gt;
       *         <!-- raw: --><b><i>Hello</i> world!</b>
       *     </p>
       *
       * Message keys can also be remapped, allowing the same generic template to be used with a variety
       * of messages. This is important for improving re-usability of templates.
       *
       * Example:
       *     // Messages: { 'good-afternoon': 'Good afternoon' }
       *     var html = '<p><html:msg key="greeting" /></p>';
       *     $( 'body' ).append( $( html ).localize( { 'keys': { 'greeting': 'good-afternoon' } } ) );
       *
       * Appends something like this to the body...
       *     <p>Good afternoon</p>
       *
       * Message keys can also be prefixed globally, which is handy when writing extensions, where by
       * convention all messages are prefixed with the extension's name.
       *
       * Example:
       *     // Messages: { 'teleportation-warning': 'You may not get there all in one piece.' }
       *     var html = '<p><html:msg key="warning" /></p>';
       *     $( 'body' ).append( $( html ).localize( { 'prefix': 'teleportation-' } ) );
       *
       * Appends something like this to the body...
       *     <p>You may not get there all in one piece.</p>
       *
       * @param {Object} options Map of options to be used while localizing
       * @param {string} options.prefix String to prepend to all message keys
       * @param {Object} options.keys Message key aliases, used for remapping keys to a template
       * @param {Object} options.params Lists of parameters to use with certain message keys
       * @return {jQuery}
       * @chainable
       */
+       $.fn.localize = function ( options ) {
+               var $target = this,
+                       attributes = [ 'title', 'alt', 'placeholder' ];
 
-       // Extend options
-       options = $.extend( {
-               prefix: '',
-               keys: {},
-               params: {}
-       }, options );
+               // Extend options
+               options = $.extend( {
+                       prefix: '',
+                       keys: {},
+                       params: {}
+               }, options );
 
-       // Elements
-       // Ok, so here's the story on this selector. In IE 6/7, searching for 'msg' turns up the
-       // 'html:msg', but searching for 'html:msg' doesn't. In later IE and other browsers, searching
-       // for 'html:msg' turns up the 'html:msg', but searching for 'msg' doesn't. So searching for
-       // both 'msg' and 'html:msg' seems to get the job done. This feels pretty icky, though.
-       $target.find( 'msg,html\\:msg' ).each( function () {
-               var $el = $( this );
-               // Escape by default
-               if ( $el.attr( 'raw' ) ) {
-                       $el.html( msg( options, $el.attr( 'key' ) ) );
-               } else {
-                       $el.text( msg( options, $el.attr( 'key' ) ) );
-               }
-               // Remove wrapper
-               $el.replaceWith( $el.html() );
-       } );
-
-       // Attributes
-       // Note: there's no way to prevent escaping of values being injected into attributes, this is
-       // on purpose, not a design flaw.
-       $.each( attributes, function ( i, attr ) {
-               var msgAttr = attr + '-msg';
-               $target.find( '[' + msgAttr + ']' ).each( function () {
+               // Elements
+               // Ok, so here's the story on this selector. In IE 6/7, searching for 'msg' turns up the
+               // 'html:msg', but searching for 'html:msg' doesn't. In later IE and other browsers, searching
+               // for 'html:msg' turns up the 'html:msg', but searching for 'msg' doesn't. So searching for
+               // both 'msg' and 'html:msg' seems to get the job done. This feels pretty icky, though.
+               $target.find( 'msg,html\\:msg' ).each( function () {
                        var $el = $( this );
-                       $el.attr( attr, msg( options, $el.attr( msgAttr ) ) ).removeAttr( msgAttr );
+                       // Escape by default
+                       if ( $el.attr( 'raw' ) ) {
+                               $el.html( msg( options, $el.attr( 'key' ) ) );
+                       } else {
+                               $el.text( msg( options, $el.attr( 'key' ) ) );
+                       }
+                       // Remove wrapper
+                       $el.replaceWith( $el.html() );
                } );
-       } );
 
-       // HTML, Text for elements which cannot have children e.g. OPTION
-       $target.find( '[data-msg-text]' ).each( function () {
-               var $el = $( this );
-               $el.text( msg( options, $el.attr( 'data-msg-text' ) ) );
-       } );
+               // Attributes
+               // Note: there's no way to prevent escaping of values being injected into attributes, this is
+               // on purpose, not a design flaw.
+               $.each( attributes, function ( i, attr ) {
+                       var msgAttr = attr + '-msg';
+                       $target.find( '[' + msgAttr + ']' ).each( function () {
+                               var $el = $( this );
+                               $el.attr( attr, msg( options, $el.attr( msgAttr ) ) ).removeAttr( msgAttr );
+                       } );
+               } );
 
-       $target.find( '[data-msg-html]' ).each( function () {
-               var $el = $( this );
-               $el.html( msg( options, $el.attr( 'data-msg-html' ) ) );
-       } );
+               // HTML, Text for elements which cannot have children e.g. OPTION
+               $target.find( '[data-msg-text]' ).each( function () {
+                       var $el = $( this );
+                       $el.text( msg( options, $el.attr( 'data-msg-text' ) ) );
+               } );
+
+               $target.find( '[data-msg-html]' ).each( function () {
+                       var $el = $( this );
+                       $el.html( msg( options, $el.attr( 'data-msg-html' ) ) );
+               } );
 
-       return $target;
-};
+               return $target;
+       };
 
-// Let IE know about the msg tag before it's used...
-document.createElement( 'msg' );
+       // Let IE know about the msg tag before it's used...
+       document.createElement( 'msg' );
 
-/**
- * @class jQuery
- * @mixins jQuery.plugin.localize
- */
+       /**
       * @class jQuery
       * @mixins jQuery.plugin.localize
       */
 
 }( jQuery, mediaWiki ) );
index 27ceb2b..f9675fa 100644 (file)
                        return false;
                },
                compareArray: function ( arrThis, arrAgainst ) {
+                       var i;
                        if ( arrThis.length !== arrAgainst.length ) {
                                return false;
                        }
-                       for ( var i = 0; i < arrThis.length; i++ ) {
+                       for ( i = 0; i < arrThis.length; i++ ) {
                                if ( $.isArray( arrThis[ i ] ) ) {
                                        if ( !$.compareArray( arrThis[ i ], arrAgainst[ i ] ) ) {
                                                return false;
                return str.replace( /([\\{}()|.?*+\-\^$\[\]])/g, '\\$1' );
        }, 'Use mediawiki.RegExp instead.' );
 
-} )( jQuery, mediaWiki );
+}( jQuery, mediaWiki ) );
index c472ac7..12b0404 100644 (file)
@@ -35,7 +35,7 @@
        function args( elem ) {
                // Return an object of element attributes
                var newAttrs = {},
-                               rinlinejQuery = /^jQuery\d+$/;
+                       rinlinejQuery = /^jQuery\d+$/;
                $.each( elem.attributes, function ( i, attr ) {
                        if ( attr.specified && !rinlinejQuery.test( attr.name ) ) {
                                newAttrs[ attr.name ] = attr.value;
@@ -46,7 +46,7 @@
 
        function clearPlaceholder( event, value ) {
                var input = this,
-                               $input = $( input );
+                       $input = $( input );
                if ( input.value === $input.attr( 'placeholder' ) && $input.hasClass( 'placeholder' ) ) {
                        if ( $input.data( 'placeholder-password' ) ) {
                                $input = $input.hide().next().show().attr( 'id', $input.removeAttr( 'id' ).data( 'placeholder-id' ) );
@@ -68,9 +68,9 @@
 
        function setPlaceholder() {
                var $replacement,
-                               input = this,
-                               $input = $( input ),
-                               id = this.id;
+                       input = this,
+                       $input = $( input ),
+                       id = this.id;
                if ( !input.value ) {
                        if ( input.type === 'password' ) {
                                if ( !$input.data( 'placeholder-textinput' ) ) {
@@ -85,7 +85,7 @@
                                                                'placeholder-password': $input,
                                                                'placeholder-id': id
                                                        } )
-                                                       .bind( 'focus.placeholder drop.placeholder', clearPlaceholder );
+                                                       .on( 'focus.placeholder drop.placeholder', clearPlaceholder );
                                        $input
                                                        .data( {
                                                                'placeholder-textinput': $replacement,
 
        function changePlaceholder( text ) {
                var hasArgs = arguments.length,
-                               $input = this;
+                       $input = this;
                if ( hasArgs ) {
                        if ( $input.attr( 'placeholder' ) !== text ) {
                                $input.prop( 'placeholder', text );
                                .filter( function () {
                                        return !$( this ).data( 'placeholder-enabled' );
                                } )
-                               .bind( {
+                               .on( {
                                        'focus.placeholder drop.placeholder': clearPlaceholder,
                                        'blur.placeholder': setPlaceholder
                                } )
                } );
 
                // Clear placeholder values upon page reload
-               $( window ).bind( 'beforeunload.placeholder', function () {
+               $( window ).on( 'beforeunload.placeholder', function () {
                        $( '.placeholder' ).each( function () {
                                this.value = '';
                        } );
index 8d263fb..4353dd7 100644 (file)
@@ -17,9 +17,9 @@
 
        var util,
                hasOwn = Object.prototype.hasOwnProperty,
-               log = ( window.console && window.console.log )
-                       ? function () { return window.console.log.apply( window.console, arguments ); }
-                       function () {};
+               log = ( window.console && window.console.log ) ?
+                       function () { return window.console.log.apply( window.console, arguments ); } :
+                       function () {};
 
        // Simplified version of a few jQuery methods, except that they don't
        // call other jQuery methods. Required to be able to run the CompletenessTest
                } );
 
                QUnit.done( function () {
+                       var toolbar, testResults, cntTotal, cntCalled, cntMissing;
+
                        that.populateMissingTests();
                        log( 'CompletenessTest/populateMissingTests', that );
 
-                       var toolbar, testResults, cntTotal, cntCalled, cntMissing;
-
                        cntTotal = util.keys( that.injectionTracker ).length;
                        cntCalled = util.keys( that.methodCallTracker ).length;
                        cntMissing = util.keys( that.missingTests ).length;
 
                        // Hard ignores
                        if ( this.ignoreFn( currVal, this, currPathArray ) ) {
-                               return null;
+                               return;
                        }
 
                        // Handle the lazy limit
                        this.lazyCounter++;
                        if ( this.lazyCounter > this.lazyLimit ) {
                                log( 'CompletenessTest.fn.walkTheObject> Limit reached: ' + this.lazyCounter, currPathArray );
-                               return null;
+                               return;
                        }
 
                        // Functions
                        // Make the spy inherit from the original so that its static methods are also
                        // visible in the spy (e.g. when we inject a check into mw.log, mw.log.warn
                        // must remain accessible).
-                       // XXX: https://github.com/jshint/jshint/issues/2656
-                       /*jshint ignore:start */
-                       /*jshint proto:true */
                        spy.__proto__ = val;
-                       /*jshint ignore:end */
 
                        // Objects are by reference, members (unless objects) are not.
                        obj[ key ] = spy;
index af5a97d..9079cc0 100644 (file)
@@ -59,6 +59,8 @@
                 * @return {jQuery}
                 */
                createSpinner: function ( opts ) {
+                       var $spinner;
+
                        if ( opts !== undefined && $.type( opts ) !== 'object' ) {
                                opts = {
                                        id: opts
@@ -67,7 +69,7 @@
 
                        opts = $.extend( {}, defaults, opts );
 
-                       var $spinner = $( '<div>' ).addClass( 'mw-spinner' ).attr( 'title', '...' );
+                       $spinner = $( '<div>' ).addClass( 'mw-spinner' ).attr( 'title', '...' );
                        if ( opts.id !== undefined ) {
                                $spinner.attr( 'id', 'mw-spinner-' + opts.id );
                        }
index 884ecb6..f3e4e09 100644 (file)
                                                        $results.empty();
                                                        expWidth = -1;
                                                        for ( i = 0; i < context.config.suggestions.length; i++ ) {
-                                                               /*jshint loopfunc:true */
                                                                text = context.config.suggestions[ i ];
                                                                $result = $( '<div>' )
                                                                        .addClass( 'suggestions-result' )
                                                        46, // delete
                                                        8   // backspace
                                                ];
-                                               if ( context.data.keypressedCount === 0
-                                                       && e.which === context.data.keypressed
-                                                       && $.inArray( e.which, allowed ) !== -1
+                                               if ( context.data.keypressedCount === 0 &&
+                                                       e.which === context.data.keypressed &&
+                                                       $.inArray( e.which, allowed ) !== -1
                                                ) {
                                                        $.suggestions.keypress( e, context, context.data.keypressed );
                                                }
index 62be0d8..4da05e6 100644 (file)
         * in default (ascending) order when their header cell is clicked the next time.
         *
         * @param {jQuery} $headers
-        * @param {number[][]} sortList
-        * @param {number[][]} headerToColumns
+        * @param {Array} sortList 2D number array
+        * @param {Array} headerToColumns 2D number array
         */
        function setHeadersOrder( $headers, sortList, headerToColumns ) {
                // Loop through all headers to retrieve the indices of the columns the header spans across:
        }
 
        function setHeadersCss( table, $headers, list, css, msg, columnToHeader ) {
+               var i, len;
                // Remove all header information and reset titles to default message
                $headers.removeClass( css[ 0 ] ).removeClass( css[ 1 ] ).attr( 'title', msg[ 1 ] );
 
-               for ( var i = 0; i < list.length; i++ ) {
+               for ( i = 0, len = list.length; i < len; i++ ) {
                        $headers
                                .eq( columnToHeader[ list[ i ][ 0 ] ] )
                                .addClass( css[ list[ i ][ 1 ] ] )
        }
 
        function buildCollationTable() {
+               var key, keys = [];
                ts.collationTable = mw.config.get( 'tableSorterCollation' );
                ts.collationRegex = null;
                if ( ts.collationTable ) {
-                       var key,
-                               keys = [];
-
                        // Build array of key names
                        for ( key in ts.collationTable ) {
                                // Check hasOwn to be safe
        /* Public scope */
 
        $.tablesorter = {
-                       defaultOptions: {
-                               cssHeader: 'headerSort',
-                               cssAsc: 'headerSortUp',
-                               cssDesc: 'headerSortDown',
-                               cssChildRow: 'expand-child',
-                               sortMultiSortKey: 'shiftKey',
-                               unsortableClass: 'unsortable',
-                               parsers: [],
-                               cancelSelection: true,
-                               sortList: [],
-                               headerList: [],
-                               headerToColumns: [],
-                               columnToHeader: [],
-                               columns: 0
-                       },
-
-                       dateRegex: [],
-                       monthNames: {},
-
-                       /**
-                        * @param {jQuery} $tables
-                        * @param {Object} [settings]
-                        */
-                       construct: function ( $tables, settings ) {
-                               return $tables.each( function ( i, table ) {
-                                       // Declare and cache.
-                                       var $headers, cache, config, sortCSS, sortMsg,
-                                               $table = $( table ),
-                                               firstTime = true;
-
-                                       // Quit if no tbody
-                                       if ( !table.tBodies ) {
+               defaultOptions: {
+                       cssHeader: 'headerSort',
+                       cssAsc: 'headerSortUp',
+                       cssDesc: 'headerSortDown',
+                       cssChildRow: 'expand-child',
+                       sortMultiSortKey: 'shiftKey',
+                       unsortableClass: 'unsortable',
+                       parsers: [],
+                       cancelSelection: true,
+                       sortList: [],
+                       headerList: [],
+                       headerToColumns: [],
+                       columnToHeader: [],
+                       columns: 0
+               },
+
+               dateRegex: [],
+               monthNames: {},
+
+               /**
+                * @param {jQuery} $tables
+                * @param {Object} [settings]
+                * @return {jQuery}
+                */
+               construct: function ( $tables, settings ) {
+                       return $tables.each( function ( i, table ) {
+                               // Declare and cache.
+                               var $headers, cache, config, sortCSS, sortMsg,
+                                       $table = $( table ),
+                                       firstTime = true;
+
+                               // Quit if no tbody
+                               if ( !table.tBodies ) {
+                                       return;
+                               }
+                               if ( !table.tHead ) {
+                                       // No thead found. Look for rows with <th>s and
+                                       // move them into a <thead> tag or a <tfoot> tag
+                                       emulateTHeadAndFoot( $table );
+
+                                       // Still no thead? Then quit
+                                       if ( !table.tHead ) {
                                                return;
                                        }
-                                       if ( !table.tHead ) {
-                                               // No thead found. Look for rows with <th>s and
-                                               // move them into a <thead> tag or a <tfoot> tag
-                                               emulateTHeadAndFoot( $table );
+                               }
+                               $table.addClass( 'jquery-tablesorter' );
 
-                                               // Still no thead? Then quit
-                                               if ( !table.tHead ) {
-                                                       return;
-                                               }
-                                       }
-                                       $table.addClass( 'jquery-tablesorter' );
-
-                                       // Merge and extend
-                                       config = $.extend( {}, $.tablesorter.defaultOptions, settings );
-
-                                       // Save the settings where they read
-                                       $.data( table, 'tablesorter', { config: config } );
-
-                                       // Get the CSS class names, could be done elsewhere
-                                       sortCSS = [ config.cssAsc, config.cssDesc ];
-                                       // Messages tell the the user what the *next* state will be
-                                       // so are in reverse order to the CSS classes.
-                                       sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ];
-
-                                       // Build headers
-                                       $headers = buildHeaders( table, sortMsg );
-
-                                       // Grab and process locale settings.
-                                       buildTransformTable();
-                                       buildDateTable();
-
-                                       // Precaching regexps can bring 10 fold
-                                       // performance improvements in some browsers.
-                                       cacheRegexs();
-
-                                       function setupForFirstSort() {
-                                               firstTime = false;
-
-                                               // Defer buildCollationTable to first sort. As user and site scripts
-                                               // may customize tableSorterCollation but load after $.ready(), other
-                                               // scripts may call .tablesorter() before they have done the
-                                               // tableSorterCollation customizations.
-                                               buildCollationTable();
-
-                                               // Legacy fix of .sortbottoms
-                                               // Wrap them inside a tfoot (because that's what they actually want to be)
-                                               // and put the <tfoot> at the end of the <table>
-                                               var $tfoot,
-                                                       $sortbottoms = $table.find( '> tbody > tr.sortbottom' );
-                                               if ( $sortbottoms.length ) {
-                                                       $tfoot = $table.children( 'tfoot' );
-                                                       if ( $tfoot.length ) {
-                                                               $tfoot.eq( 0 ).prepend( $sortbottoms );
-                                                       } else {
-                                                               $table.append( $( '<tfoot>' ).append( $sortbottoms ) );
-                                                       }
-                                               }
+                               // Merge and extend
+                               config = $.extend( {}, $.tablesorter.defaultOptions, settings );
 
-                                               explodeRowspans( $table );
-                                               manageColspans( $table );
+                               // Save the settings where they read
+                               $.data( table, 'tablesorter', { config: config } );
 
-                                               // Try to auto detect column type, and store in tables config
-                                               config.parsers = buildParserCache( table, $headers );
-                                       }
+                               // Get the CSS class names, could be done elsewhere
+                               sortCSS = [ config.cssAsc, config.cssDesc ];
+                               // Messages tell the the user what the *next* state will be
+                               // so are in reverse order to the CSS classes.
+                               sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ];
 
-                                       // Apply event handling to headers
-                                       // this is too big, perhaps break it out?
-                                       $headers.on( 'keypress click', function ( e ) {
-                                               var cell, $cell, columns, newSortList, i,
-                                                       totalRows,
-                                                       j, s, o;
-
-                                               if ( e.type === 'click' && e.target.nodeName.toLowerCase() === 'a' ) {
-                                                       // The user clicked on a link inside a table header.
-                                                       // Do nothing and let the default link click action continue.
-                                                       return true;
-                                               }
+                               // Build headers
+                               $headers = buildHeaders( table, sortMsg );
 
-                                               if ( e.type === 'keypress' && e.which !== 13 ) {
-                                                       // Only handle keypresses on the "Enter" key.
-                                                       return true;
-                                               }
+                               // Grab and process locale settings.
+                               buildTransformTable();
+                               buildDateTable();
 
-                                               if ( firstTime ) {
-                                                       setupForFirstSort();
+                               // Precaching regexps can bring 10 fold
+                               // performance improvements in some browsers.
+                               cacheRegexs();
+
+                               function setupForFirstSort() {
+                                       var $tfoot, $sortbottoms;
+
+                                       firstTime = false;
+
+                                       // Defer buildCollationTable to first sort. As user and site scripts
+                                       // may customize tableSorterCollation but load after $.ready(), other
+                                       // scripts may call .tablesorter() before they have done the
+                                       // tableSorterCollation customizations.
+                                       buildCollationTable();
+
+                                       // Legacy fix of .sortbottoms
+                                       // Wrap them inside a tfoot (because that's what they actually want to be)
+                                       // and put the <tfoot> at the end of the <table>
+                                       $sortbottoms = $table.find( '> tbody > tr.sortbottom' );
+                                       if ( $sortbottoms.length ) {
+                                               $tfoot = $table.children( 'tfoot' );
+                                               if ( $tfoot.length ) {
+                                                       $tfoot.eq( 0 ).prepend( $sortbottoms );
+                                               } else {
+                                                       $table.append( $( '<tfoot>' ).append( $sortbottoms ) );
                                                }
+                                       }
 
-                                               // Build the cache for the tbody cells
-                                               // to share between calculations for this sort action.
-                                               // Re-calculated each time a sort action is performed due to possiblity
-                                               // that sort values change. Shouldn't be too expensive, but if it becomes
-                                               // too slow an event based system should be implemented somehow where
-                                               // cells get event .change() and bubbles up to the <table> here
-                                               cache = buildCache( table );
-
-                                               totalRows = ( $table[ 0 ].tBodies[ 0 ] && $table[ 0 ].tBodies[ 0 ].rows.length ) || 0;
-                                               if ( totalRows > 0 ) {
-                                                       cell = this;
-                                                       $cell = $( cell );
-
-                                                       // Get current column sort order
-                                                       $cell.data( {
-                                                               order: $cell.data( 'count' ) % 2,
-                                                               count: $cell.data( 'count' ) + 1
-                                                       } );
+                                       explodeRowspans( $table );
+                                       manageColspans( $table );
 
-                                                       cell = this;
-                                                       // Get current column index
-                                                       columns = config.headerToColumns[ $cell.data( 'headerIndex' ) ];
-                                                       newSortList = $.map( columns, function ( c ) {
-                                                               // jQuery "helpfully" flattens the arrays...
-                                                               return [ [ c, $cell.data( 'order' ) ] ];
-                                                       } );
-                                                       // Index of first column belonging to this header
-                                                       i = columns[ 0 ];
+                                       // Try to auto detect column type, and store in tables config
+                                       config.parsers = buildParserCache( table, $headers );
+                               }
 
-                                                       if ( !e[ config.sortMultiSortKey ] ) {
-                                                               // User only wants to sort on one column set
-                                                               // Flush the sort list and add new columns
-                                                               config.sortList = newSortList;
-                                                       } else {
-                                                               // Multi column sorting
-                                                               // It is not possible for one column to belong to multiple headers,
-                                                               // so this is okay - we don't need to check for every value in the columns array
-                                                               if ( isValueInArray( i, config.sortList ) ) {
-                                                                       // The user has clicked on an already sorted column.
-                                                                       // Reverse the sorting direction for all tables.
-                                                                       for ( j = 0; j < config.sortList.length; j++ ) {
-                                                                               s = config.sortList[ j ];
-                                                                               o = config.headerList[ config.columnToHeader[ s[ 0 ] ] ];
-                                                                               if ( isValueInArray( s[ 0 ], newSortList ) ) {
-                                                                                       $( o ).data( 'count', s[ 1 ] + 1 );
-                                                                                       s[ 1 ] = $( o ).data( 'count' ) % 2;
-                                                                               }
+                               // Apply event handling to headers
+                               // this is too big, perhaps break it out?
+                               $headers.on( 'keypress click', function ( e ) {
+                                       var cell, $cell, columns, newSortList, i,
+                                               totalRows,
+                                               j, s, o;
+
+                                       if ( e.type === 'click' && e.target.nodeName.toLowerCase() === 'a' ) {
+                                               // The user clicked on a link inside a table header.
+                                               // Do nothing and let the default link click action continue.
+                                               return true;
+                                       }
+
+                                       if ( e.type === 'keypress' && e.which !== 13 ) {
+                                               // Only handle keypresses on the "Enter" key.
+                                               return true;
+                                       }
+
+                                       if ( firstTime ) {
+                                               setupForFirstSort();
+                                       }
+
+                                       // Build the cache for the tbody cells
+                                       // to share between calculations for this sort action.
+                                       // Re-calculated each time a sort action is performed due to possiblity
+                                       // that sort values change. Shouldn't be too expensive, but if it becomes
+                                       // too slow an event based system should be implemented somehow where
+                                       // cells get event .change() and bubbles up to the <table> here
+                                       cache = buildCache( table );
+
+                                       totalRows = ( $table[ 0 ].tBodies[ 0 ] && $table[ 0 ].tBodies[ 0 ].rows.length ) || 0;
+                                       if ( totalRows > 0 ) {
+                                               cell = this;
+                                               $cell = $( cell );
+
+                                               // Get current column sort order
+                                               $cell.data( {
+                                                       order: $cell.data( 'count' ) % 2,
+                                                       count: $cell.data( 'count' ) + 1
+                                               } );
+
+                                               cell = this;
+                                               // Get current column index
+                                               columns = config.headerToColumns[ $cell.data( 'headerIndex' ) ];
+                                               newSortList = $.map( columns, function ( c ) {
+                                                       // jQuery "helpfully" flattens the arrays...
+                                                       return [ [ c, $cell.data( 'order' ) ] ];
+                                               } );
+                                               // Index of first column belonging to this header
+                                               i = columns[ 0 ];
+
+                                               if ( !e[ config.sortMultiSortKey ] ) {
+                                                       // User only wants to sort on one column set
+                                                       // Flush the sort list and add new columns
+                                                       config.sortList = newSortList;
+                                               } else {
+                                                       // Multi column sorting
+                                                       // It is not possible for one column to belong to multiple headers,
+                                                       // so this is okay - we don't need to check for every value in the columns array
+                                                       if ( isValueInArray( i, config.sortList ) ) {
+                                                               // The user has clicked on an already sorted column.
+                                                               // Reverse the sorting direction for all tables.
+                                                               for ( j = 0; j < config.sortList.length; j++ ) {
+                                                                       s = config.sortList[ j ];
+                                                                       o = config.headerList[ config.columnToHeader[ s[ 0 ] ] ];
+                                                                       if ( isValueInArray( s[ 0 ], newSortList ) ) {
+                                                                               $( o ).data( 'count', s[ 1 ] + 1 );
+                                                                               s[ 1 ] = $( o ).data( 'count' ) % 2;
                                                                        }
-                                                               } else {
-                                                                       // Add columns to sort list array
-                                                                       config.sortList = config.sortList.concat( newSortList );
                                                                }
+                                                       } else {
+                                                               // Add columns to sort list array
+                                                               config.sortList = config.sortList.concat( newSortList );
                                                        }
+                                               }
 
-                                                       // Reset order/counts of cells not affected by sorting
-                                                       setHeadersOrder( $headers, config.sortList, config.headerToColumns );
+                                               // Reset order/counts of cells not affected by sorting
+                                               setHeadersOrder( $headers, config.sortList, config.headerToColumns );
 
-                                                       // Set CSS for headers
-                                                       setHeadersCss( $table[ 0 ], $headers, config.sortList, sortCSS, sortMsg, config.columnToHeader );
-                                                       appendToTable(
-                                                               $table[ 0 ], multisort( $table[ 0 ], config.sortList, cache )
-                                                       );
+                                               // Set CSS for headers
+                                               setHeadersCss( $table[ 0 ], $headers, config.sortList, sortCSS, sortMsg, config.columnToHeader );
+                                               appendToTable(
+                                                       $table[ 0 ], multisort( $table[ 0 ], config.sortList, cache )
+                                               );
 
-                                                       // Stop normal event by returning false
-                                                       return false;
-                                               }
+                                               // Stop normal event by returning false
+                                               return false;
+                                       }
 
-                                       // Cancel selection
-                                       } ).mousedown( function () {
-                                               if ( config.cancelSelection ) {
-                                                       this.onselectstart = function () {
-                                                               return false;
-                                                       };
+                               // Cancel selection
+                               } ).mousedown( function () {
+                                       if ( config.cancelSelection ) {
+                                               this.onselectstart = function () {
                                                        return false;
-                                               }
-                                       } );
+                                               };
+                                               return false;
+                                       }
+                               } );
 
-                                       /**
-                                        * Sorts the table. If no sorting is specified by passing a list of sort
-                                        * objects, the table is sorted according to the initial sorting order.
-                                        * Passing an empty array will reset sorting (basically just reset the headers
-                                        * making the table appear unsorted).
-                                        *
-                                        * @param {Array} [sortList] List of sort objects.
-                                        */
-                                       $table.data( 'tablesorter' ).sort = function ( sortList ) {
-
-                                               if ( firstTime ) {
-                                                       setupForFirstSort();
-                                               }
+                               /**
+                                * Sorts the table. If no sorting is specified by passing a list of sort
+                                * objects, the table is sorted according to the initial sorting order.
+                                * Passing an empty array will reset sorting (basically just reset the headers
+                                * making the table appear unsorted).
+                                *
+                                * @param {Array} [sortList] List of sort objects.
+                                */
+                               $table.data( 'tablesorter' ).sort = function ( sortList ) {
+
+                                       if ( firstTime ) {
+                                               setupForFirstSort();
+                                       }
 
-                                               if ( sortList === undefined ) {
-                                                       sortList = config.sortList;
-                                               } else if ( sortList.length > 0 ) {
-                                                       sortList = convertSortList( sortList );
-                                               }
+                                       if ( sortList === undefined ) {
+                                               sortList = config.sortList;
+                                       } else if ( sortList.length > 0 ) {
+                                               sortList = convertSortList( sortList );
+                                       }
 
-                                               // Set each column's sort count to be able to determine the correct sort
-                                               // order when clicking on a header cell the next time
-                                               setHeadersOrder( $headers, sortList, config.headerToColumns );
+                                       // Set each column's sort count to be able to determine the correct sort
+                                       // order when clicking on a header cell the next time
+                                       setHeadersOrder( $headers, sortList, config.headerToColumns );
 
-                                               // re-build the cache for the tbody cells
-                                               cache = buildCache( table );
+                                       // re-build the cache for the tbody cells
+                                       cache = buildCache( table );
 
-                                               // set css for headers
-                                               setHeadersCss( table, $headers, sortList, sortCSS, sortMsg, config.columnToHeader );
+                                       // set css for headers
+                                       setHeadersCss( table, $headers, sortList, sortCSS, sortMsg, config.columnToHeader );
 
-                                               // sort the table and append it to the dom
-                                               appendToTable( table, multisort( table, sortList, cache ) );
-                                       };
+                                       // sort the table and append it to the dom
+                                       appendToTable( table, multisort( table, sortList, cache ) );
+                               };
 
-                                       // sort initially
-                                       if ( config.sortList.length > 0 ) {
-                                               config.sortList = convertSortList( config.sortList );
-                                               $table.data( 'tablesorter' ).sort();
-                                       }
+                               // sort initially
+                               if ( config.sortList.length > 0 ) {
+                                       config.sortList = convertSortList( config.sortList );
+                                       $table.data( 'tablesorter' ).sort();
+                               }
 
-                               } );
-                       },
+                       } );
+               },
 
-                       addParser: function ( parser ) {
-                               if ( !getParserById( parser.id ) ) {
-                                       parsers.push( parser );
-                               }
-                       },
-
-                       formatDigit: function ( s ) {
-                               var out, c, p, i;
-                               if ( ts.transformTable !== false ) {
-                                       out = '';
-                                       for ( p = 0; p < s.length; p++ ) {
-                                               c = s.charAt( p );
-                                               if ( c in ts.transformTable ) {
-                                                       out += ts.transformTable[ c ];
-                                               } else {
-                                                       out += c;
-                                               }
+               addParser: function ( parser ) {
+                       if ( !getParserById( parser.id ) ) {
+                               parsers.push( parser );
+                       }
+               },
+
+               formatDigit: function ( s ) {
+                       var out, c, p, i;
+                       if ( ts.transformTable !== false ) {
+                               out = '';
+                               for ( p = 0; p < s.length; p++ ) {
+                                       c = s.charAt( p );
+                                       if ( c in ts.transformTable ) {
+                                               out += ts.transformTable[ c ];
+                                       } else {
+                                               out += c;
                                        }
-                                       s = out;
                                }
-                               i = parseFloat( s.replace( /[, ]/g, '' ).replace( '\u2212', '-' ) );
-                               return isNaN( i ) ? 0 : i;
-                       },
+                               s = out;
+                       }
+                       i = parseFloat( s.replace( /[, ]/g, '' ).replace( '\u2212', '-' ) );
+                       return isNaN( i ) ? 0 : i;
+               },
 
-                       formatFloat: function ( s ) {
-                               var i = parseFloat( s );
-                               return isNaN( i ) ? 0 : i;
-                       },
+               formatFloat: function ( s ) {
+                       var i = parseFloat( s );
+                       return isNaN( i ) ? 0 : i;
+               },
 
-                       formatInt: function ( s ) {
-                               var i = parseInt( s, 10 );
-                               return isNaN( i ) ? 0 : i;
-                       },
+               formatInt: function ( s ) {
+                       var i = parseInt( s, 10 );
+                       return isNaN( i ) ? 0 : i;
+               },
 
-                       clearTableBody: function ( table ) {
-                               $( table.tBodies[ 0 ] ).empty();
-                       },
+               clearTableBody: function ( table ) {
+                       $( table.tBodies[ 0 ] ).empty();
+               },
 
-                       getParser: function ( id ) {
-                               buildTransformTable();
-                               buildDateTable();
-                               cacheRegexs();
-                               buildCollationTable();
+               getParser: function ( id ) {
+                       buildTransformTable();
+                       buildDateTable();
+                       cacheRegexs();
+                       buildCollationTable();
 
-                               return getParserById( id );
-                       },
+                       return getParserById( id );
+               },
 
-                       getParsers: function () {  // for table diagnosis
-                               return parsers;
-                       }
-               };
+               getParsers: function () {  // for table diagnosis
+                       return parsers;
+               }
+       };
 
        // Shortcut
        ts = $.tablesorter;
                        return true;
                },
                format: function ( s ) {
+                       var tsc;
                        s = $.trim( s.toLowerCase() );
                        if ( ts.collationRegex ) {
-                               var tsc = ts.collationTable;
+                               tsc = ts.collationTable;
                                s = s.replace( ts.collationRegex, function ( match ) {
                                        var r = tsc[ match ] ? tsc[ match ] : tsc[ match.toUpperCase() ];
                                        return r.toLowerCase();
                                if ( !matches ) {
                                        return $.tablesorter.formatFloat( 0 );
                                }
-                               isodate = new Date( matches[ 2 ]  + '/' + matches[ 3 ] + '/' + matches[ 1 ] );
+                               isodate = new Date( matches[ 2 ] + '/' + matches[ 3 ] + '/' + matches[ 1 ] );
                        } else {
                                matches = s.match( ts.rgx.isoDate[ 0 ] );
                                if ( !matches ) {
index 5e93ba6..c897302 100644 (file)
 
                /**
                 * Helper function to get an IE TextRange object for an element
+                *
+                * @param {HTMLElement} element
+                * @return {TextRange}
                 */
-               function rangeForElementIE( e ) {
-                       if ( e.nodeName.toLowerCase() === 'input' ) {
-                               return e.createTextRange();
+               function rangeForElementIE( element ) {
+                       var sel;
+                       if ( element.nodeName.toLowerCase() === 'input' ) {
+                               return element.createTextRange();
                        } else {
-                               var sel = document.body.createTextRange();
-                               sel.moveToElementText( e );
+                               sel = document.body.createTextRange();
+                               sel.moveToElementText( element );
                                return sel;
                        }
                }
@@ -47,6 +51,8 @@
                 * Helper function for IE for activating the textarea. Called only in the
                 * IE-specific code paths below; makes use of IE-specific non-standard
                 * function setActive() if possible to avoid screen flicker.
+                *
+                * @param {HTMLElement} element
                 */
                function activateElementOnIE( element ) {
                        if ( element.setActive ) {
                fn = {
                        /**
                         * Get the contents of the textarea
+                        *
+                        * @return {string}
                         */
                        getContents: function () {
                                return this.val();
                        },
                        /**
                         * Set the contents of the textarea, replacing anything that was there before
+                        *
+                        * @param {string} content
                         */
                        setContents: function ( content ) {
                                this.val( content );
@@ -72,6 +82,8 @@
                        /**
                         * Get the currently selected text in this textarea. Will focus the textarea
                         * in some browsers (IE/Opera)
+                        *
+                        * @return {string}
                         */
                        getSelection: function () {
                                var retval, range,
                         * Inserts text at the beginning and end of a text selection, optionally
                         * inserting text at the caret when selection is empty.
                         *
+                        * @param {Object} options Options
                         * FIXME document the options parameters
+                        * @return {jQuery}
                         */
                        encapsulateSelection: function ( options ) {
                                return this.each( function () {
                                         * Do the splitlines stuff.
                                         *
                                         * Wrap each line of the selected text with pre and post
+                                        *
+                                        * @param {string} selText Selected text
+                                        * @param {string} pre Text before
+                                        * @param {string} post Text after
+                                        * @return {string} Wrapped text
                                         */
                                        function doSplitLines( selText, pre, post ) {
                                                var i,
                         *
                         * Will focus the textarea in some browsers (IE/Opera)
                         *
+                        * @param {Object} options Options
                         * FIXME document the options parameters
+                        * @return {number} Position
                         */
                        getCaretPosition: function ( options ) {
                                function getCaret( e ) {
                                        var caretPos = 0,
                                                endPos = 0,
                                                preText, rawPreText, periText,
-                                               rawPeriText, postText, rawPostText,
+                                               rawPeriText, postText,
                                                // IE Support
                                                preFinished,
                                                periFinished,
                                                // Load the text values we need to compare
                                                preText = rawPreText = preRange.text;
                                                periText = rawPeriText = periRange.text;
-                                               postText = rawPostText = postRange.text;
+                                               postText = postRange.text;
 
                                                /*
                                                 * Check each range for trimmed newlines by shrinking the range by 1
                                                                        postFinished = true;
                                                                } else {
                                                                        postRange.moveEnd( 'character', -1 );
-                                                                       if ( postRange.text === postText ) {
-                                                                               rawPostText += '\r\n';
-                                                                       } else {
+                                                                       if ( postRange.text !== postText ) {
                                                                                postFinished = true;
                                                                        }
                                                                }
                                return getCaret( this.get( 0 ) );
                        },
                        /**
+                        * @param {Object} options options
                         * FIXME document the options parameters
+                        * @return {jQuery}
                         */
                        setSelection: function ( options ) {
                                return this.each( function () {
                         * Scroll a textarea to the current cursor position. You can set the cursor
                         * position with setSelection()
                         *
-                        * @param {boolean} options Whether to force a scroll even if the caret position
-                        *  is already visible. Defaults to false
-                        *
-                        * FIXME document the options parameters (function body suggests options.force is a boolean, not options itself)
+                        * @param {Object} options options
+                        * @cfg {boolean} [force=false] Whether to force a scroll even if the caret position
+                        *  is already visible.
+                        * FIXME document the options parameters
+                        * @return {jQuery}
                         */
                        scrollToCaretPosition: function ( options ) {
                                function getLineLength( e ) {
diff --git a/resources/src/json-skip.js b/resources/src/json-skip.js
deleted file mode 100644 (file)
index 0a1e1c2..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/*!
- * Skip function for json2.js.
- */
-return !!( window.JSON && JSON.stringify && JSON.parse );
index 6c63957..c8d3fad 100644 (file)
@@ -1,6 +1,7 @@
 /*!
  * Scripts for pre-emptive edit preparing on action=edit
  */
+/* eslint-disable no-use-before-define */
 ( function ( mw, $ ) {
        if ( !mw.config.get( 'wgAjaxEditStash' ) ) {
                return;
                        if (
                                // Reverts may involve use (undo) links; stash as they review the diff.
                                // Since the form has a pre-filled summary, stash the edit immediately.
-                               mw.util.getParamValue( 'undo' ) !== null
+                               mw.util.getParamValue( 'undo' ) !== null ||
                                // Pressing "show changes" and "preview" also signify that the user will
                                // probably save the page soon
-                               || $.inArray( $form.find( '#mw-edit-mode' ).val(), [ 'preview', 'diff' ] ) > -1
+                               $.inArray( $form.find( '#mw-edit-mode' ).val(), [ 'preview', 'diff' ] ) > -1
                        ) {
                                checkStash();
                        }
index 077d5e3..b3b0af2 100644 (file)
@@ -10,6 +10,7 @@ jQuery( function ( $ ) {
         * @ignore
         * @context {Element} input
         * @param {jQuery.Event} e
+        * @return {boolean} False to cancel the default event
         */
        function updateDiffRadios() {
                var nextState = 'before',
index 5b08f95..cad530b 100644 (file)
@@ -10,8 +10,8 @@
 }
 
 #pagehistory li.selected {
-       background-color: #f9f9f9;
-       border: 1px dashed #aaa;
+       background-color: #f8f9fa;
+       border: 1px dashed #a2a9b1;
 }
 
 .mw-history-revisionactions {
index 2be29f0..7439754 100644 (file)
@@ -4,11 +4,12 @@
 ( function ( mw, $ ) {
        $( function () {
                mw.util.$content.dblclick( function ( e ) {
+                       var $a;
                        // Recheck preference so extensions can do a hack to disable this code.
                        if ( parseInt( mw.user.options.get( 'editondblclick' ), 10 ) ) {
                                e.preventDefault();
                                // Trigger native HTMLElement click instead of opening URL (bug 43052)
-                               var $a = $( '#ca-edit a' );
+                               $a = $( '#ca-edit a' );
                                // Not every page has an edit link (bug 57713)
                                if ( $a.length ) {
                                        $a.get( 0 ).click();
index d5520a1..1f0365e 100644 (file)
@@ -46,8 +46,8 @@
  */
 #filetoc {
        text-align: center;
-       border: 1px solid #aaa;
-       background-color: #f9f9f9;
+       border: 1px solid #a2a9b1;
+       background-color: #f8f9fa;
        padding: 5px;
        font-size: 95%;
        margin-bottom: 0.5em;
 
 .mw_metadata td,
 .mw_metadata th {
-       border: 1px solid #aaa;
+       border: 1px solid #a2a9b1;
        padding-left: 5px;
        padding-right: 5px;
 }
 
 .mw_metadata th {
-       background-color: #f9f9f9;
+       background-color: #f8f9fa;
 }
 
 .mw_metadata td {
index 29a5a79..39a122d 100644 (file)
@@ -28,7 +28,7 @@
                }
 
                // Note that this will update the hash in a modern browser, retaining back behaviour
-               history.replaceState( /*data=*/ history.state, /*title=*/ document.title, /*url=*/ canonical );
+               history.replaceState( /* data= */ history.state, /* title= */ document.title, /* url= */ canonical );
                if ( shouldChangeFragment ) {
                        // Specification for history.replaceState() doesn't require browser to scroll,
                        // so scroll to be sure (see also T110501). Support for IE9 and IE10.
index a4c911a..e136211 100644 (file)
@@ -3,7 +3,6 @@
  */
 
 mediaWiki.language.convertGrammar = function ( word, form ) {
-       /*jshint onecase:true */
        var grammarForms = mediaWiki.language.getData( 'ga', 'grammarForms' );
        if ( grammarForms && grammarForms[ form ] ) {
                return grammarForms[ form ][ word ];
index 945f02f..5bf8c4d 100644 (file)
@@ -21,7 +21,7 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                        }
 
                        // Add a hyphen (maqaf) before numbers and non-Hebrew letters
-                       if ( word.slice( 0, 1 ) < 'א' ||  word.slice( 0, 1 ) > 'ת' ) {
+                       if ( word.slice( 0, 1 ) < 'א' || word.slice( 0, 1 ) > 'ת' ) {
                                word = '־' + word;
                        }
        }
index 935d466..bb6f61d 100644 (file)
@@ -3,7 +3,6 @@
  */
 
 mediaWiki.language.convertGrammar = function ( word, form ) {
-       /*jshint onecase:true */
        var grammarForms = mediaWiki.language.getData( 'hy', 'grammarForms' );
        if ( grammarForms && grammarForms[ form ] ) {
                return grammarForms[ form ][ word ];
index cf3ef79..fc2af3d 100644 (file)
  */
 ( function ( mw, $ ) {
 
-/**
- * @class mw.language
- */
-$.extend( mw.language, {
-
        /**
-        * Process the PLURAL template substitution
-        *
-        * @private
-        * @param {Object} template Template object
-        * @param {string} template.title
-        * @param {Array} template.parameters
-        * @return {string}
+        * @class mw.language
         */
-       procPLURAL: function ( template ) {
-               if ( template.title && template.parameters && mw.language.convertPlural ) {
-                       // Check if we have forms to replace
-                       if ( template.parameters.length === 0 ) {
-                               return '';
+       $.extend( mw.language, {
+
+               /**
+                * Process the PLURAL template substitution
+                *
+                * @private
+                * @param {Object} template Template object
+                * @param {string} template.title
+                * @param {Array} template.parameters
+                * @return {string}
+                */
+               procPLURAL: function ( template ) {
+                       var count;
+                       if ( template.title && template.parameters && mw.language.convertPlural ) {
+                               // Check if we have forms to replace
+                               if ( template.parameters.length === 0 ) {
+                                       return '';
+                               }
+                               // Restore the count into a Number ( if it got converted earlier )
+                               count = mw.language.convertNumber( template.title, true );
+                               // Do convertPlural call
+                               return mw.language.convertPlural( parseInt( count, 10 ), template.parameters );
                        }
-                       // Restore the count into a Number ( if it got converted earlier )
-                       var count = mw.language.convertNumber( template.title, true );
-                       // Do convertPlural call
-                       return mw.language.convertPlural( parseInt( count, 10 ), template.parameters );
-               }
-               // Could not process plural return first form or nothing
-               if ( template.parameters[ 0 ] ) {
-                       return template.parameters[ 0 ];
-               }
-               return '';
-       },
+                       // Could not process plural return first form or nothing
+                       if ( template.parameters[ 0 ] ) {
+                               return template.parameters[ 0 ];
+                       }
+                       return '';
+               },
 
-       /**
-        * Plural form transformations, needed for some languages.
-        *
-        * @param {number} count Non-localized quantifier
-        * @param {Array} forms List of plural forms
-        * @param {Object} [explicitPluralForms] List of explicit plural forms
-        * @return {string} Correct form for quantifier in this language
-        */
-       convertPlural: function ( count, forms, explicitPluralForms ) {
-               var pluralRules,
-                       pluralFormIndex = 0;
+               /**
+                * Plural form transformations, needed for some languages.
+                *
+                * @param {number} count Non-localized quantifier
+                * @param {Array} forms List of plural forms
+                * @param {Object} [explicitPluralForms] List of explicit plural forms
+                * @return {string} Correct form for quantifier in this language
+                */
+               convertPlural: function ( count, forms, explicitPluralForms ) {
+                       var pluralRules,
+                               pluralFormIndex = 0;
 
-               if ( explicitPluralForms && ( explicitPluralForms[ count ] !== undefined ) ) {
-                       return explicitPluralForms[ count ];
-               }
+                       if ( explicitPluralForms && ( explicitPluralForms[ count ] !== undefined ) ) {
+                               return explicitPluralForms[ count ];
+                       }
 
-               if ( !forms || forms.length === 0 ) {
-                       return '';
-               }
+                       if ( !forms || forms.length === 0 ) {
+                               return '';
+                       }
 
-               pluralRules = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'pluralRules' );
-               if ( !pluralRules ) {
-                       // default fallback.
-                       return ( count === 1 ) ? forms[ 0 ] : forms[ 1 ];
-               }
-               pluralFormIndex = mw.cldr.getPluralForm( count, pluralRules );
-               pluralFormIndex = Math.min( pluralFormIndex, forms.length - 1 );
-               return forms[ pluralFormIndex ];
-       },
+                       pluralRules = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'pluralRules' );
+                       if ( !pluralRules ) {
+                               // default fallback.
+                               return ( count === 1 ) ? forms[ 0 ] : forms[ 1 ];
+                       }
+                       pluralFormIndex = mw.cldr.getPluralForm( count, pluralRules );
+                       pluralFormIndex = Math.min( pluralFormIndex, forms.length - 1 );
+                       return forms[ pluralFormIndex ];
+               },
 
-       /**
-        * Pads an array to a specific length by copying the last one element.
-        *
-        * @private
-        * @param {Array} forms Number of forms given to convertPlural
-        * @param {number} count Number of forms required
-        * @return {Array} Padded array of forms
-        */
-       preConvertPlural: function ( forms, count ) {
-               while ( forms.length < count ) {
-                       forms.push( forms[ forms.length - 1 ] );
-               }
-               return forms;
-       },
+               /**
+                * Pads an array to a specific length by copying the last one element.
+                *
+                * @private
+                * @param {Array} forms Number of forms given to convertPlural
+                * @param {number} count Number of forms required
+                * @return {Array} Padded array of forms
+                */
+               preConvertPlural: function ( forms, count ) {
+                       while ( forms.length < count ) {
+                               forms.push( forms[ forms.length - 1 ] );
+                       }
+                       return forms;
+               },
 
-       /**
-        * Provides an alternative text depending on specified gender.
-        *
-        * Usage in message text: `{{gender:[gender|user object]|masculine|feminine|neutral}}`.
-        * If second or third parameter are not specified, masculine is used.
-        *
-        * These details may be overridden per language.
-        *
-        * @param {string} gender 'male', 'female', or anything else for neutral.
-        * @param {Array} forms List of gender forms
-        * @return {string}
-        */
-       gender: function ( gender, forms ) {
-               if ( !forms || forms.length === 0 ) {
-                       return '';
-               }
-               forms = mw.language.preConvertPlural( forms, 2 );
-               if ( gender === 'male' ) {
-                       return forms[ 0 ];
-               }
-               if ( gender === 'female' ) {
-                       return forms[ 1 ];
-               }
-               return ( forms.length === 3 ) ? forms[ 2 ] : forms[ 0 ];
-       },
+               /**
+                * Provides an alternative text depending on specified gender.
+                *
+                * Usage in message text: `{{gender:[gender|user object]|masculine|feminine|neutral}}`.
+                * If second or third parameter are not specified, masculine is used.
+                *
+                * These details may be overridden per language.
+                *
+                * @param {string} gender 'male', 'female', or anything else for neutral.
+                * @param {Array} forms List of gender forms
+                * @return {string}
+                */
+               gender: function ( gender, forms ) {
+                       if ( !forms || forms.length === 0 ) {
+                               return '';
+                       }
+                       forms = mw.language.preConvertPlural( forms, 2 );
+                       if ( gender === 'male' ) {
+                               return forms[ 0 ];
+                       }
+                       if ( gender === 'female' ) {
+                               return forms[ 1 ];
+                       }
+                       return ( forms.length === 3 ) ? forms[ 2 ] : forms[ 0 ];
+               },
 
-       /**
-        * Grammatical transformations, needed for inflected languages.
-        * Invoked by putting `{{grammar:form|word}}` in a message.
-        *
-        * The rules can be defined in $wgGrammarForms global or computed
-        * dynamically by overriding this method per language.
-        *
-        * @param {string} word
-        * @param {string} form
-        * @return {string}
-        */
-       convertGrammar: function ( word, form ) {
-               var grammarForms = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'grammarForms' );
-               if ( grammarForms && grammarForms[ form ] ) {
-                       return grammarForms[ form ][ word ] || word;
-               }
-               return word;
-       },
+               /**
+                * Grammatical transformations, needed for inflected languages.
+                * Invoked by putting `{{grammar:form|word}}` in a message.
+                *
+                * The rules can be defined in $wgGrammarForms global or computed
+                * dynamically by overriding this method per language.
+                *
+                * @param {string} word
+                * @param {string} form
+                * @return {string}
+                */
+               convertGrammar: function ( word, form ) {
+                       var grammarForms = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'grammarForms' );
+                       if ( grammarForms && grammarForms[ form ] ) {
+                               return grammarForms[ form ][ word ] || word;
+                       }
+                       return word;
+               },
 
-       /**
-        * Turn a list of string into a simple list using commas and 'and'.
-        *
-        * See Language::listToText in languages/Language.php
-        *
-        * @param {string[]} list
-        * @return {string}
-        */
-       listToText: function ( list ) {
-               var text = '',
-                       i = 0;
+               /**
+                * Turn a list of string into a simple list using commas and 'and'.
+                *
+                * See Language::listToText in languages/Language.php
+                *
+                * @param {string[]} list
+                * @return {string}
+                */
+               listToText: function ( list ) {
+                       var text = '',
+                               i = 0;
 
-               for ( ; i < list.length; i++ ) {
-                       text += list[ i ];
-                       if ( list.length - 2 === i ) {
-                               text += mw.msg( 'and' ) + mw.msg( 'word-separator' );
-                       } else if ( list.length - 1 !== i ) {
-                               text += mw.msg( 'comma-separator' );
+                       for ( ; i < list.length; i++ ) {
+                               text += list[ i ];
+                               if ( list.length - 2 === i ) {
+                                       text += mw.msg( 'and' ) + mw.msg( 'word-separator' );
+                               } else if ( list.length - 1 !== i ) {
+                                       text += mw.msg( 'comma-separator' );
+                               }
                        }
-               }
-               return text;
-       },
+                       return text;
+               },
 
-       setSpecialCharacters: function ( data ) {
-               this.specialCharacters = data;
-       }
-} );
+               setSpecialCharacters: function ( data ) {
+                       this.specialCharacters = data;
+               }
+       } );
 
 }( mediaWiki, jQuery ) );
index 268985f..10ceecc 100644 (file)
         * @return {string}
         */
        function replicate( str, num ) {
+               var buf = [];
+
                if ( num <= 0 || !str ) {
                        return '';
                }
 
-               var buf = [];
                while ( num-- ) {
                        buf.push( str );
                }
         * @return {string}
         */
        function pad( text, size, ch, end ) {
+               var out, padStr;
+
                if ( !ch ) {
                        ch = '0';
                }
 
-               var out = String( text ),
-                       padStr = replicate( ch, Math.ceil( ( size - out.length ) / ch.length ) );
+               out = String( text );
+               padStr = replicate( ch, Math.ceil( ( size - out.length ) / ch.length ) );
 
                return end ? out + padStr : padStr + out;
        }
         * @return {string}
         */
        function commafyNumber( value, pattern, options ) {
-               options = options || {
-                       group: ',',
-                       decimal: '.'
-               };
-
-               if ( isNaN( value ) ) {
-                       return value;
-               }
-
                var padLength,
                        patternDigits,
                        index,
                        groupSize2 = 0,
                        pieces = [];
 
+               options = options || {
+                       group: ',',
+                       decimal: '.'
+               };
+
+               if ( isNaN( value ) ) {
+                       return value;
+               }
+
                if ( patternParts[ 1 ] ) {
                        // Pad fractional with trailing zeros
                        padLength = ( patternParts[ 1 ] && patternParts[ 1 ].lastIndexOf( '0' ) + 1 );
                return valueParts.join( options.decimal );
        }
 
+       /**
+        * Helper function to flip transformation tables.
+        *
+        * @param {...Object} Transformation tables
+        * @return {Object}
+        */
+       function flipTransform() {
+               var i, key, table, flipped = {};
+
+               // Ensure we strip thousand separators. This might be overwritten.
+               flipped[ ',' ] = '';
+
+               for ( i = 0; i < arguments.length; i++ ) {
+                       table = arguments[ i ];
+                       for ( key in table ) {
+                               if ( table.hasOwnProperty( key ) ) {
+                                       // The thousand separator should be deleted
+                                       flipped[ table[ key ] ] = key === ',' ? '' : key;
+                               }
+                       }
+               }
+
+               return flipped;
+       }
+
        $.extend( mw.language, {
 
                /**
                 * @return {number|string} Formatted number
                 */
                convertNumber: function ( num, integer ) {
-                       var i, tmp, transformTable, numberString, convertedNumber, pattern;
+                       var transformTable, digitTransformTable, separatorTransformTable,
+                               i, numberString, convertedNumber, pattern;
 
-                       pattern = mw.language.getData( mw.config.get( 'wgUserLanguage' ),
-                               'digitGroupingPattern' ) || '#,##0.###';
-
-                       // Set the target transform table:
-                       transformTable = mw.language.getDigitTransformTable();
-
-                       if ( !transformTable ) {
+                       // Quick shortcut for plain numbers
+                       if ( integer && parseInt( num, 10 ) === num ) {
                                return num;
                        }
 
-                       // Check if the 'restore' to Latin number flag is set:
+                       // Load the transformation tables (can be empty)
+                       digitTransformTable = mw.language.getDigitTransformTable();
+                       separatorTransformTable = mw.language.getSeparatorTransformTable();
+
                        if ( integer ) {
-                               if ( parseInt( num, 10 ) === num ) {
-                                       return num;
-                               }
-                               tmp = [];
-                               for ( i in transformTable ) {
-                                       tmp[ transformTable[ i ] ] = i;
-                               }
-                               transformTable = tmp;
+                               // Reverse the digit transformation tables if we are doing unformatting
+                               transformTable = flipTransform( separatorTransformTable, digitTransformTable );
                                numberString = String( num );
                        } else {
-                               // Ignore transform table if wgTranslateNumerals is false
-                               if ( !mw.config.get( 'wgTranslateNumerals' ) ) {
-                                       transformTable = [];
+                               // This check being here means that digits can still be unformatted
+                               // even if we do not produce them. This seems sane behavior.
+                               if ( mw.config.get( 'wgTranslateNumerals' ) ) {
+                                       transformTable = digitTransformTable;
                                }
+
+                               // Commaying is more complex, so we handle it here separately.
+                               // When unformatting, we just use separatorTransformTable.
+                               pattern = mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+                                       'digitGroupingPattern' ) || '#,##0.###';
                                numberString = mw.language.commafy( num, pattern );
                        }
 
                        convertedNumber = '';
                        for ( i = 0; i < numberString.length; i++ ) {
-                               if ( transformTable[ numberString[ i ] ] ) {
+                               if ( transformTable.hasOwnProperty( numberString[ i ] ) ) {
                                        convertedNumber += transformTable[ numberString[ i ] ];
                                } else {
                                        convertedNumber += numberString[ i ];
                                }
                        }
-                       return integer ? parseInt( convertedNumber, 10 ) : convertedNumber;
+
+                       if ( integer ) {
+                               // Parse string to integer. This loses decimals!
+                               convertedNumber = parseInt( convertedNumber, 10 );
+                       }
+
+                       return convertedNumber;
                },
 
                /**
index 6226c90..aa49ae1 100644 (file)
 ( function ( mw, $ ) {
 
-var ProtectionForm = window.ProtectionForm = {
-       /**
-        * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
-        * on the protection form
-        */
-       init: function () {
-               var $cell = $( '<td>' ),
-                       $row = $( '<tr>' ).append( $cell );
-
-               if ( !$( '#mwProtectSet' ).length ) {
-                       return false;
-               }
-
-               if ( mw.config.get( 'wgCascadeableLevels' ) !== undefined ) {
-                       $( 'form#mw-Protect-Form' ).submit( this.toggleUnchainedInputs.bind( ProtectionForm, true ) );
-               }
-               this.getExpirySelectors().each( function () {
-                       $( this ).change( ProtectionForm.updateExpiryList.bind( ProtectionForm, this ) );
-               } );
-               this.getExpiryInputs().each( function () {
-                       $( this ).on( 'keyup change', ProtectionForm.updateExpiry.bind( ProtectionForm, this ) );
-               } );
-               this.getLevelSelectors().each( function () {
-                       $( this ).change( ProtectionForm.updateLevels.bind( ProtectionForm, this ) );
-               } );
-
-               $( '#mwProtectSet > tbody > tr:first' ).after( $row );
-
-               // If there is only one protection type, there is nothing to chain
-               if ( $( '[id ^= mw-protect-table-]' ).length > 1 ) {
-                       $cell.append(
-                               $( '<input>' )
-                                       .attr( { id: 'mwProtectUnchained', type: 'checkbox' } )
-                                       .click( this.onChainClick.bind( this ) )
-                                       .prop( 'checked', !this.areAllTypesMatching() ),
-                               document.createTextNode( ' ' ),
-                               $( '<label>' )
-                                       .attr( 'for', 'mwProtectUnchained' )
-                                       .text( mw.msg( 'protect-unchain-permissions' ) )
-                       );
-
-                       this.toggleUnchainedInputs( !this.areAllTypesMatching() );
-               }
-
-               $( '#mwProtect-reason' ).byteLimit( 180 );
-
-               this.updateCascadeCheckbox();
-       },
-
-       /**
-        * Sets the disabled attribute on the cascade checkbox depending on the current selected levels
-        */
-       updateCascadeCheckbox: function () {
-               this.getLevelSelectors().each( function () {
-                       if ( !ProtectionForm.isCascadeableLevel( $( this ).val() ) ) {
-                               $( '#mwProtect-cascade' ).prop( { checked: false, disabled: true } );
+       var ProtectionForm = window.ProtectionForm = {
+               /**
+                * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
+                * on the protection form
+                *
+                * @return {boolean}
+                */
+               init: function () {
+                       var $cell = $( '<td>' ),
+                               $row = $( '<tr>' ).append( $cell );
+
+                       if ( !$( '#mwProtectSet' ).length ) {
                                return false;
-                       } else {
-                               $( '#mwProtect-cascade' ).prop( 'disabled', false );
                        }
-               } );
-       },
-
-       /**
-        * Checks if a certain protection level is cascadeable.
-        *
-        * @param {string} level
-        * @return {boolean}
-        */
-       isCascadeableLevel: function ( level ) {
-               return $.inArray( level, mw.config.get( 'wgCascadeableLevels' ) ) !== -1;
-       },
-
-       /**
-        * When protection levels are locked together, update the rest
-        * when one action's level changes
-        *
-        * @param {Element} source Level selector that changed
-        */
-       updateLevels: function ( source ) {
-               if ( !this.isUnchained() ) {
-                       this.setAllSelectors( source.selectedIndex );
-               }
-               this.updateCascadeCheckbox();
-       },
-
-       /**
-        * When protection levels are locked together, update the
-        * expiries when one changes
-        *
-        * @param {Element} source expiry input that changed
-        */
-
-       updateExpiry: function ( source ) {
-               if ( !this.isUnchained() ) {
+
+                       if ( mw.config.get( 'wgCascadeableLevels' ) !== undefined ) {
+                               $( 'form#mw-Protect-Form' ).submit( this.toggleUnchainedInputs.bind( ProtectionForm, true ) );
+                       }
+                       this.getExpirySelectors().each( function () {
+                               $( this ).change( ProtectionForm.updateExpiryList.bind( ProtectionForm, this ) );
+                       } );
                        this.getExpiryInputs().each( function () {
-                               this.value = source.value;
+                               $( this ).on( 'keyup change', ProtectionForm.updateExpiry.bind( ProtectionForm, this ) );
                        } );
-               }
-               if ( this.isUnchained() ) {
-                       $( '#' + source.id.replace( /^mwProtect-(\w+)-expires$/, 'mwProtectExpirySelection-$1' ) ).val( 'othertime' );
-               } else {
-                       this.getExpirySelectors().each( function () {
-                               this.value = 'othertime';
+                       this.getLevelSelectors().each( function () {
+                               $( this ).change( ProtectionForm.updateLevels.bind( ProtectionForm, this ) );
                        } );
-               }
-       },
-
-       /**
-        * When protection levels are locked together, update the
-        * expiry lists when one changes and clear the custom inputs
-        *
-        * @param {Element} source Expiry selector that changed
-        */
-       updateExpiryList: function ( source ) {
-               if ( !this.isUnchained() ) {
-                       this.getExpirySelectors().each( function () {
-                               this.value = source.value;
+
+                       $( '#mwProtectSet > tbody > tr:first' ).after( $row );
+
+                       // If there is only one protection type, there is nothing to chain
+                       if ( $( '[id ^= mw-protect-table-]' ).length > 1 ) {
+                               $cell.append(
+                                       $( '<input>' )
+                                               .attr( { id: 'mwProtectUnchained', type: 'checkbox' } )
+                                               .click( this.onChainClick.bind( this ) )
+                                               .prop( 'checked', !this.areAllTypesMatching() ),
+                                       document.createTextNode( ' ' ),
+                                       $( '<label>' )
+                                               .attr( 'for', 'mwProtectUnchained' )
+                                               .text( mw.msg( 'protect-unchain-permissions' ) )
+                               );
+
+                               this.toggleUnchainedInputs( !this.areAllTypesMatching() );
+                       }
+
+                       $( '#mwProtect-reason' ).byteLimit( 180 );
+
+                       this.updateCascadeCheckbox();
+                       return true;
+               },
+
+               /**
+                * Sets the disabled attribute on the cascade checkbox depending on the current selected levels
+                */
+               updateCascadeCheckbox: function () {
+                       this.getLevelSelectors().each( function () {
+                               if ( !ProtectionForm.isCascadeableLevel( $( this ).val() ) ) {
+                                       $( '#mwProtect-cascade' ).prop( { checked: false, disabled: true } );
+                                       return false;
+                               } else {
+                                       $( '#mwProtect-cascade' ).prop( 'disabled', false );
+                               }
                        } );
-                       this.getExpiryInputs().each( function () {
-                               this.value = '';
+               },
+
+               /**
+                * Checks if a certain protection level is cascadeable.
+                *
+                * @param {string} level
+                * @return {boolean}
+                */
+               isCascadeableLevel: function ( level ) {
+                       return $.inArray( level, mw.config.get( 'wgCascadeableLevels' ) ) !== -1;
+               },
+
+               /**
+                * When protection levels are locked together, update the rest
+                * when one action's level changes
+                *
+                * @param {Element} source Level selector that changed
+                */
+               updateLevels: function ( source ) {
+                       if ( !this.isUnchained() ) {
+                               this.setAllSelectors( source.selectedIndex );
+                       }
+                       this.updateCascadeCheckbox();
+               },
+
+               /**
+                * When protection levels are locked together, update the
+                * expiries when one changes
+                *
+                * @param {Element} source expiry input that changed
+                */
+
+               updateExpiry: function ( source ) {
+                       if ( !this.isUnchained() ) {
+                               this.getExpiryInputs().each( function () {
+                                       this.value = source.value;
+                               } );
+                       }
+                       if ( this.isUnchained() ) {
+                               $( '#' + source.id.replace( /^mwProtect-(\w+)-expires$/, 'mwProtectExpirySelection-$1' ) ).val( 'othertime' );
+                       } else {
+                               this.getExpirySelectors().each( function () {
+                                       this.value = 'othertime';
+                               } );
+                       }
+               },
+
+               /**
+                * When protection levels are locked together, update the
+                * expiry lists when one changes and clear the custom inputs
+                *
+                * @param {Element} source Expiry selector that changed
+                */
+               updateExpiryList: function ( source ) {
+                       if ( !this.isUnchained() ) {
+                               this.getExpirySelectors().each( function () {
+                                       this.value = source.value;
+                               } );
+                               this.getExpiryInputs().each( function () {
+                                       this.value = '';
+                               } );
+                       }
+               },
+
+               /**
+                * Update chain status and enable/disable various bits of the UI
+                * when the user changes the "unlock move permissions" checkbox
+                */
+               onChainClick: function () {
+                       this.toggleUnchainedInputs( this.isUnchained() );
+                       if ( !this.isUnchained() ) {
+                               this.setAllSelectors( this.getMaxLevel() );
+                       }
+                       this.updateCascadeCheckbox();
+               },
+
+               /**
+                * Returns true if the named attribute in all objects in the given array are matching
+                *
+                * @param {Object[]} objects
+                * @param {string} attrName
+                * @return {boolean}
+                */
+               matchAttribute: function ( objects, attrName ) {
+                       return $.map( objects, function ( object ) {
+                               return object[ attrName ];
+                       } ).filter( function ( item, index, a ) {
+                               return index === a.indexOf( item );
+                       } ).length === 1;
+               },
+
+               /**
+                * Are all actions protected at the same level, with the same expiry time?
+                *
+                * @return {boolean}
+                */
+               areAllTypesMatching: function () {
+                       return this.matchAttribute( this.getLevelSelectors(), 'selectedIndex' ) &&
+                               this.matchAttribute( this.getExpirySelectors(), 'selectedIndex' ) &&
+                               this.matchAttribute( this.getExpiryInputs(), 'value' );
+               },
+
+               /**
+                * Is protection chaining off?
+                *
+                * @return {boolean}
+                */
+               isUnchained: function () {
+                       var element = document.getElementById( 'mwProtectUnchained' );
+                       return element ?
+                               element.checked :
+                               true; // No control, so we need to let the user set both levels
+               },
+
+               /**
+                * Find the highest protection level in any selector
+                *
+                * @return {number}
+                */
+               getMaxLevel: function () {
+                       return Math.max.apply( Math, this.getLevelSelectors().map( function () {
+                               return this.selectedIndex;
+                       } ) );
+               },
+
+               /**
+                * Protect all actions at the specified level
+                *
+                * @param {number} index Protection level
+                */
+               setAllSelectors: function ( index ) {
+                       this.getLevelSelectors().each( function () {
+                               this.selectedIndex = index;
                        } );
+               },
+
+               /**
+                * Get a list of all protection selectors on the page
+                *
+                * @return {jQuery}
+                */
+               getLevelSelectors: function () {
+                       return $( 'select[id ^= mwProtect-level-]' );
+               },
+
+               /**
+                * Get a list of all expiry inputs on the page
+                *
+                * @return {jQuery}
+                */
+               getExpiryInputs: function () {
+                       return $( 'input[id ^= mwProtect-][id $= -expires]' );
+               },
+
+               /**
+                * Get a list of all expiry selector lists on the page
+                *
+                * @return {jQuery}
+                */
+               getExpirySelectors: function () {
+                       return $( 'select[id ^= mwProtectExpirySelection-]' );
+               },
+
+               /**
+                * Enable/disable protection selectors and expiry inputs
+                *
+                * @param {boolean} val Enable?
+                */
+               toggleUnchainedInputs: function ( val ) {
+                       var setDisabled = function () { this.disabled = !val; };
+                       this.getLevelSelectors().slice( 1 ).each( setDisabled );
+                       this.getExpiryInputs().slice( 1 ).each( setDisabled );
+                       this.getExpirySelectors().slice( 1 ).each( setDisabled );
                }
-       },
-
-       /**
-        * Update chain status and enable/disable various bits of the UI
-        * when the user changes the "unlock move permissions" checkbox
-        */
-       onChainClick: function () {
-               this.toggleUnchainedInputs( this.isUnchained() );
-               if ( !this.isUnchained() ) {
-                       this.setAllSelectors( this.getMaxLevel() );
-               }
-               this.updateCascadeCheckbox();
-       },
-
-       /**
-        * Returns true if the named attribute in all objects in the given array are matching
-        *
-        * @param {Object[]} objects
-        * @param {string} attrName
-        * @return {boolean}
-        */
-       matchAttribute: function ( objects, attrName ) {
-               return $.map( objects, function ( object ) {
-                       return object[ attrName ];
-               } ).filter( function ( item, index, a ) {
-                       return index === a.indexOf( item );
-               } ).length === 1;
-       },
-
-       /**
-        * Are all actions protected at the same level, with the same expiry time?
-        *
-        * @return {boolean}
-        */
-       areAllTypesMatching: function () {
-               return this.matchAttribute( this.getLevelSelectors(), 'selectedIndex' )
-                       && this.matchAttribute( this.getExpirySelectors(), 'selectedIndex' )
-                       && this.matchAttribute( this.getExpiryInputs(), 'value' );
-       },
-
-       /**
-        * Is protection chaining off?
-        *
-        * @return {boolean}
-        */
-       isUnchained: function () {
-               var element = document.getElementById( 'mwProtectUnchained' );
-               return element
-                       ? element.checked
-                       : true; // No control, so we need to let the user set both levels
-       },
-
-       /**
-        * Find the highest protection level in any selector
-        *
-        * @return {number}
-        */
-       getMaxLevel: function () {
-               return Math.max.apply( Math, this.getLevelSelectors().map( function () {
-                       return this.selectedIndex;
-               } ) );
-       },
-
-       /**
-        * Protect all actions at the specified level
-        *
-        * @param {number} index Protection level
-        */
-       setAllSelectors: function ( index ) {
-               this.getLevelSelectors().each( function () {
-                       this.selectedIndex = index;
-               } );
-       },
-
-       /**
-        * Get a list of all protection selectors on the page
-        *
-        * @return {jQuery}
-        */
-       getLevelSelectors: function () {
-               return $( 'select[id ^= mwProtect-level-]' );
-       },
-
-       /**
-        * Get a list of all expiry inputs on the page
-        *
-        * @return {jQuery}
-        */
-       getExpiryInputs: function () {
-               return $( 'input[id ^= mwProtect-][id $= -expires]' );
-       },
-
-       /**
-        * Get a list of all expiry selector lists on the page
-        *
-        * @return {jQuery}
-        */
-       getExpirySelectors: function () {
-               return $( 'select[id ^= mwProtectExpirySelection-]' );
-       },
-
-       /**
-        * Enable/disable protection selectors and expiry inputs
-        *
-        * @param {boolean} val Enable?
-        */
-       toggleUnchainedInputs: function ( val ) {
-               var setDisabled = function () { this.disabled = !val; };
-               this.getLevelSelectors().slice( 1 ).each( setDisabled );
-               this.getExpiryInputs().slice( 1 ).each( setDisabled );
-               this.getExpirySelectors().slice( 1 ).each( setDisabled );
-       }
-};
-
-$( ProtectionForm.init.bind( ProtectionForm ) );
+       };
+
+       $( ProtectionForm.init.bind( ProtectionForm ) );
 
 }( mediaWiki, jQuery ) );
index 1522de1..42392ed 100644 (file)
@@ -124,6 +124,16 @@ span.comment {
        font-family: serif;
 }
 
+/* Underline preference */
+
+.mw-underline-always a {
+       text-decoration: underline;
+}
+
+.mw-underline-never a {
+       text-decoration: none;
+}
+
 /**
  * rev_deleted stuff
  */
@@ -343,8 +353,8 @@ a.new {
  */
 table.wikitable {
        margin: 1em 0;
-       background-color: #f9f9f9;
-       border: 1px solid #aaa;
+       background-color: #f8f9fa;
+       border: 1px solid #a2a9b1;
        border-collapse: collapse;
        color: #000;
 }
@@ -359,7 +369,7 @@ table.wikitable > * > tr > td {
 
 table.wikitable > tr > th,
 table.wikitable > * > tr > th {
-       background-color: #f2f2f2;
+       background-color: #eaecf0;
        text-align: center;
 }
 
index 38271a0..8062849 100644 (file)
 
        /**
         * @deprecated since 1.17 Use mw.loader instead. Warnings added in 1.25.
+        * @param {string} url
+        * @return {HTMLElement} Script tag
         */
        function importScriptURI( url ) {
+               var s;
                if ( loadedScripts[ url ] ) {
                        return null;
                }
                loadedScripts[ url ] = true;
-               var s = document.createElement( 'script' );
+               s = document.createElement( 'script' );
                s.setAttribute( 'src', url );
                document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );
                return s;
 
        /**
         * @deprecated since 1.17 Use mw.loader instead. Warnings added in 1.25.
+        * @param {string} url
+        * @param {string} media
+        * @return {HTMLElement} Link tag
         */
        function importStylesheetURI( url, media ) {
                var l = document.createElement( 'link' );
index 676ecca..9688f1f 100644 (file)
@@ -26,9 +26,9 @@
 // Orange; for contextual use of returning to a past action
 @colorRegressive: #ff5d00;
 // Red; for contextual use of a negative action of high severity
-@colorDestructive: #c33;
-@colorDestructiveHighlight: #e53939;
-@colorDestructiveActive: #873636;
+@colorDestructive: #d33;
+@colorDestructiveHighlight: #ff4242;
+@colorDestructiveActive: #b32424;
 // Orange; for contextual use of a potentially negative action of medium severity
 @colorMediumSevere: #ff5d00;
 // Yellow; for contextual use of a potentially negative action of low severity
index 68fb2aa..558fd4c 100644 (file)
@@ -1,4 +1,3 @@
-/*global OO */
 ( function ( mw, $ ) {
        /**
         * Factory for MessagePoster objects. This provides a pluggable to way to script the action
index d4c93fd..e1df01d 100644 (file)
@@ -10,8 +10,8 @@
 .toc,
 .mw-warning,
 .toccolours {
-       border: 1px solid #aaa;
-       background-color: #f9f9f9;
+       border: 1px solid #a2a9b1;
+       background-color: #f8f9fa;
        padding: 5px;
        font-size: 95%;
 }
@@ -147,9 +147,9 @@ div.thumb {
 }
 
 div.thumbinner {
-       border: 1px solid #ccc;
+       border: 1px solid #c8ccd1;
        padding: 3px;
-       background-color: #f9f9f9;
+       background-color: #f8f9fa;
        font-size: 94%;
        text-align: center;
        /* new block formatting context,
@@ -158,7 +158,7 @@ div.thumbinner {
 }
 
 html .thumbimage {
-       border: 1px solid #ccc;
+       border: 1px solid #c8ccd1;
 }
 
 html .thumbcaption {
@@ -199,7 +199,7 @@ div.magnify a {
 }
 
 img.thumbborder {
-       border: 1px solid #ddd;
+       border: 1px solid #eaecf0;
 }
 
 /* Directionality-specific styles for thumbnails - their positioning depends on content language */
index 9c52b2a..33ceb48 100644 (file)
@@ -204,8 +204,8 @@ pre, code, tt, kbd, samp, .mw-code {
 
 code {
        color: #000;
-       background-color: #f9f9f9;
-       border: 1px solid #ddd;
+       background-color: #f8f9fa;
+       border: 1px solid #eaecf0;
        border-radius: 2px;
        padding: 1px 4px;
 }
@@ -213,8 +213,8 @@ code {
 pre,
 .mw-code {
        color: #000;
-       background-color: #f9f9f9;
-       border: 1px solid #ddd;
+       background-color: #f8f9fa;
+       border: 1px solid #eaecf0;
        padding: 1em;
        /* Wrap lines in overflow. T2260, T103780 */
        white-space: pre-wrap;
index 4ca2096..7dbcd4d 100644 (file)
@@ -8,8 +8,8 @@
 
 /* Categories */
 .catlinks {
-       border: 1px solid #aaa;
-       background-color: #f9f9f9;
+       border: 1px solid #a2a9b1;
+       background-color: #f8f9fa;
        padding: 5px;
        margin-top: 1em;
        clear: both;
index 64cfcf5..60155fd 100644 (file)
@@ -1,4 +1,4 @@
-/*global OO */
+/* eslint-disable no-use-before-define */
 ( function ( $, mw, OO ) {
        'use strict';
        var ApiSandbox, Util, WidgetMethods, Validators,
@@ -51,9 +51,7 @@
                tokenWidget: {
                        alertTokenError: function ( code, error ) {
                                windowManager.openWindow( 'errorAlert', {
-                                       title: mw.message(
-                                               'apisandbox-results-fixtoken-fail', this.paramInfo.tokentype
-                                       ).parse(),
+                                       title: Util.parseMsg( 'apisandbox-results-fixtoken-fail', this.paramInfo.tokentype ),
                                        message: error,
                                        actions: [
                                                {
                                }
                        },
                        apiCheckValid: function () {
-                               var ok = this.getApiValue() !== undefined || suppressErrors;
+                               var ok = true,
+                                       pi = this.paramInfo;
+
+                               if ( !suppressErrors ) {
+                                       ok = this.getApiValue() !== undefined && !(
+                                               pi.allspecifier !== undefined &&
+                                               this.getItemsData().length > 1 &&
+                                               this.getItemsData().indexOf( pi.allspecifier ) !== -1
+                                       );
+                               }
+
                                this.setIcon( ok ? null : 'alert' );
                                this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() );
                                return $.Deferred().resolve( ok ).promise();
        };
 
        /**
-        * @class mw.special.ApiSandbox.Utils
+        * @class mw.special.ApiSandbox.Util
         * @private
         */
        Util = {
                                        break;
 
                                case 'limit':
-                                       widget = new OO.ui.NumberInputWidget( {
-                                               required: Util.apiBool( pi.required ),
-                                               isInteger: true
+                                       widget = new OO.ui.TextInputWidget( {
+                                               required: Util.apiBool( pi.required )
                                        } );
-                                       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.input.setValidation( function ( value ) {
-                                               return value === 'max' || widget.validateNumber( value );
+                                       widget.setValidation( function ( value ) {
+                                               var n, pi = this.paramInfo;
+
+                                               if ( value === 'max' ) {
+                                                       return true;
+                                               } else {
+                                                       n = +value;
+                                                       return !isNaN( n ) && isFinite( n ) &&
+                                                               // eslint-disable-next-line no-bitwise
+                                                               ( n | 0 ) === 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 );
-                                       widget.setRange( pi.min || 0, mw.config.get( 'apihighlimits' ) ? pi.highmax : pi.max );
                                        multiMode = 'enter';
                                        break;
 
                                                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.CapsuleMultiselectWidget( {
                                                        menu: { items: items }
                                                } );
                                                return new OO.ui.MenuOptionWidget( { data: String( v ), label: String( v ) } );
                                        } );
                                        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.CapsuleMultiselectWidget( {
                                                        menu: { items: items }
                                                } );
                },
 
                /**
-                * Parse an HTML string, adding target="_blank" to any links
+                * Parse an HTML string and call Util.fixupHTML()
                 *
                 * @param {string} html HTML to parse
                 * @return {jQuery}
                 */
                parseHTML: function ( html ) {
                        var $ret = $( $.parseHTML( html ) );
-                       $ret.filter( 'a' ).add( $ret.find( 'a' ) )
+                       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 $ret;
+                       return $html;
                }
        };
 
 
                        $content
                                .empty()
-                               .append( $( '<p>' ).append( mw.message( 'apisandbox-intro' ).parse() ) )
+                               .append( $( '<p>' ).append( Util.parseMsg( 'apisandbox-intro' ) ) )
                                .append(
                                        $( '<div>', { id: 'mw-apisandbox-ui' } )
                                                .append( $toolbar )
 
                /**
                 * Update the current query when the page hash changes
+                *
+                * @return {boolean} Successful
                 */
                loadFromHash: function () {
                        var params, m, re,
                        $.when.apply( $, deferreds ).done( function () {
                                if ( $.inArray( false, arguments ) !== -1 ) {
                                        windowManager.openWindow( 'errorAlert', {
-                                               title: mw.message( 'apisandbox-submit-invalid-fields-title' ).parse(),
-                                               message: mw.message( 'apisandbox-submit-invalid-fields-message' ).parse(),
+                                               title: Util.parseMsg( 'apisandbox-submit-invalid-fields-title' ),
+                                               message: Util.parseMsg( 'apisandbox-submit-invalid-fields-message' ),
                                                actions: [
                                                        {
                                                                action: 'accept',
                                                                readOnly: true,
                                                                value: mw.util.wikiScript( 'api' ) + '?' + query
                                                        } ), {
-                                                               label: mw.message( 'apisandbox-request-url-label' ).parse()
+                                                               label: Util.parseMsg( 'apisandbox-request-url-label' )
                                                        }
                                                ).$element,
                                                $result
 
                                                $result.empty();
                                                if ( /^text\/mediawiki-api-prettyprint-wrapped(?:;|$)/.test( ct ) ) {
-                                                       data = $.parseJSON( data );
+                                                       data = JSON.parse( data );
                                                        if ( data.modules.length ) {
                                                                mw.loader.load( data.modules );
                                                        }
                                                        if ( data.status && data.status !== 200 ) {
                                                                $( '<div>' )
                                                                        .addClass( 'api-pretty-header api-pretty-status' )
-                                                                       .append(
-                                                                               mw.message( 'api-format-prettyprint-status', data.status, data.statustext ).parse()
-                                                                       )
+                                                                       .append( Util.parseMsg( 'api-format-prettyprint-status', data.status, data.statustext ) )
                                                                        .appendTo( $result );
                                                        }
                                                        $result.append( Util.parseHTML( data.html ) );
                                                                                framed: false,
                                                                                icon: 'info',
                                                                                popup: {
-                                                                                       $content: $( '<div>' ).append( mw.message( 'apisandbox-continue-help' ).parse() ),
+                                                                                       $content: $( '<div>' ).append( Util.parseMsg( 'apisandbox-continue-help' ) ),
                                                                                        padded: true
                                                                                }
                                                                        } ).$element
 
                                if ( that.widgets[ name ] !== undefined ) {
                                        windowManager.openWindow( 'errorAlert', {
-                                               title: mw.message(
-                                                       'apisandbox-dynamic-error-exists', name
-                                               ).parse(),
+                                               title: Util.parseMsg( 'apisandbox-dynamic-error-exists', name ),
                                                actions: [
                                                        {
                                                                action: 'accept',
                                                                if ( pi.parameters[ i ].highmax !== undefined ) {
                                                                        dl.append( $( '<dd>', {
                                                                                addClass: 'info',
-                                                                               append: Util.parseHTML( mw.message(
-                                                                                       'api-help-param-limit2', pi.parameters[ i ].max, pi.parameters[ i ].highmax
-                                                                               ).parse() )
+                                                                               append: [
+                                                                                       Util.parseMsg(
+                                                                                               'api-help-param-limit2', pi.parameters[ i ].max, pi.parameters[ i ].highmax
+                                                                                       ),
+                                                                                       ' ',
+                                                                                       Util.parseMsg( 'apisandbox-param-limit' )
+                                                                               ]
                                                                        } ) );
                                                                } else {
                                                                        dl.append( $( '<dd>', {
                                                                                addClass: 'info',
-                                                                               append: Util.parseHTML( mw.message(
-                                                                                       'api-help-param-limit', pi.parameters[ i ].max
-                                                                               ).parse() )
+                                                                               append: [
+                                                                                       Util.parseMsg( 'api-help-param-limit', pi.parameters[ i ].max ),
+                                                                                       ' ',
+                                                                                       Util.parseMsg( 'apisandbox-param-limit' )
+                                                                               ]
                                                                        } ) );
                                                                }
                                                                break;
                                                                if ( tmp !== '' ) {
                                                                        dl.append( $( '<dd>', {
                                                                                addClass: 'info',
-                                                                               append: Util.parseHTML( mw.message(
+                                                                               append: Util.parseMsg(
                                                                                        'api-help-param-integer-' + tmp,
                                                                                        Util.apiBool( pi.parameters[ i ].multi ) ? 2 : 1,
                                                                                        pi.parameters[ i ].min, pi.parameters[ i ].max
-                                                                               ).parse() )
+                                                                               )
                                                                        } ) );
                                                                }
                                                                break;
                                        items.push( new OO.ui.FieldLayout(
                                                new OO.ui.Widget( {} ).toggle( false ), {
                                                        align: 'top',
-                                                       label: Util.parseHTML( mw.message( 'apisandbox-no-parameters' ).parse() )
+                                                       label: Util.parseMsg( 'apisandbox-no-parameters' )
                                                }
                                        ) );
                                }
index 69a2a67..3e6e684 100644 (file)
@@ -6,9 +6,10 @@
                var $tagList = $( '#mw-edittags-tag-list' );
                if ( $tagList.length ) {
                        $tagList.chosen( {
-                               /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
+                               /* eslint-disable camelcase */
                                placeholder_text_multiple: mw.msg( 'tags-edit-chosen-placeholder' ),
                                no_results_text: mw.msg( 'tags-edit-chosen-no-results' )
+                               /* eslint-enable camelcase */
                        } );
                }
 
index 5191f92..ebe9ed9 100644 (file)
@@ -53,9 +53,9 @@
        font-size: 97%;
 }
 .mw-search-profile-tabs {
-       background-color: #f3f3f3;
+       background-color: #f8f9fa;
        margin-top: 1em;
-       border: 1px solid #c0c0c0;
+       border: 1px solid #c8ccd1;
 }
 .search-types {
        float: left;
@@ -76,7 +76,7 @@
        padding: 0.5em;
 }
 .search-types .current a {
-       color: #333;
+       color: #222;
        cursor: default;
 }
 .search-types .current a:hover {
@@ -86,7 +86,7 @@
        float: right;
        padding: 0.5em;
        padding-right: 0.75em;
-       color: #666;
+       color: #54595d;
        font-size: 95%;
 }
 #mw-search-top-table div.oo-ui-actionFieldLayout {
@@ -96,8 +96,8 @@
 #mw-searchoptions {
        margin: 0;
        padding: 0.5em 0.75em 0.75em 0.75em;
-       background-color: #f9f9f9;
-       border: 1px solid #c0c0c0;
+       background-color: #f8f9fa;
+       border: 1px solid #c8ccd1;
        border-top-width: 0;
 }
 #mw-searchoptions legend {
 }
 #mw-searchoptions .divider {
        clear: both;
-       border-bottom: 1px solid #ddd;
+       border-bottom: 1px solid #eaecf0;
        padding-top: 0.5em;
        margin-bottom: 0.5em;
 }
 #mw-search-interwiki {
        float: right;
        width: 18em;
-       border: 1px solid #aaa;
+       border: 1px solid #a2a9b1;
        margin-top: 2ex;
 }
 .searchalttitle,
        font-size: 97%;
        text-align: left;
        padding: 0.15em 0.15em 0.2em 0.2em;
-       background-color: #ececec;
-       border-top: 1px solid #bbb;
+       background-color: #eaecf0;
+       border-top: 1px solid #c8ccd1;
 }
 .searchdidyoumean {
        font-size: 127%;
        margin-top: 0.8em;
        /* Note that this color won't affect the link, as desired. */
-       color: #c00;
+       color: #d33;
 }
index dd48367..f818096 100644 (file)
@@ -5,8 +5,11 @@
  * @class mw.special.upload
  * @singleton
  */
+
+/* eslint-disable no-use-before-define */
+/* global Uint8Array */
+
 ( function ( mw, $ ) {
-       /*jshint latedef:false */
        var uploadWarning, uploadLicense,
                ajaxUploadDestCheck = mw.config.get( 'wgAjaxUploadDestCheck' ),
                $license = $( '#wpLicense' );
        $( function () {
                /**
                 * Is the FileAPI available with sufficient functionality?
+                *
+                * @return {boolean}
                 */
                function hasFileAPI() {
                        return window.FileReader !== undefined;
                        }, mw.config.get( 'wgFileCanRotate' ) ? function ( data ) {
                                try {
                                        meta = mw.libs.jpegmeta( data, file.fileName );
-                                       // jscs:disable requireCamelCaseOrUpperCaseIdentifiers, disallowDanglingUnderscores
+                                       // eslint-disable-next-line no-underscore-dangle, camelcase
                                        meta._binary_data = null;
-                                       // jscs:enable
                                } catch ( e ) {
                                        meta = null;
                                }
 
                /**
                 * Check if the file does not exceed the maximum size
+                *
+                * @param {File} file
+                * @return {boolean}
                 */
                function checkMaxUploadSize( file ) {
                        var maxSize, $error;
                if ( hasFileAPI() ) {
                        // Update thumbnail when the file selection control is updated.
                        $( '#wpUploadFile' ).change( function () {
+                               var file;
                                clearPreview();
                                if ( this.files && this.files.length ) {
                                        // Note: would need to be updated to handle multiple files.
-                                       var file = this.files[ 0 ];
+                                       file = this.files[ 0 ];
 
                                        if ( !checkMaxUploadSize( file ) ) {
                                                return;
index bb26c0f..e9fc024 100644 (file)
         *  current cursor position.
         * @param {string} [button.imageId] `id` attribute of the button HTML element. Can be
         *  used to define the image with CSS if it's not provided as `imageFile`.
+        * @param {string} [speedTip]
+        * @param {string} [tagOpen]
+        * @param {string} [tagClose]
+        * @param {string} [sampleText]
+        * @param {string} [imageId]
         */
        function insertButton( button, speedTip, tagOpen, tagClose, sampleText, imageId ) {
                var $button;
index 31b1cd5..54a5a85 100644 (file)
                return this.selected;
        };
 
+       // eslint-disable-next-line valid-jsdoc
        /**
         * Set the selected dates
         *
                return this.focusedDate;
        };
 
+       // eslint-disable-next-line valid-jsdoc
        /**
         * Set the currently-focused date
         *
         *
         * @protected
         * @param {jQuery.Event} e Key down event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.datetime.CalendarWidget.prototype.onKeyDown = function ( e ) {
                var focusedDate = this.getFocusedDate();
index 1c54234..1793849 100644 (file)
         *  Defaults to the current date and time (with 0 milliseconds).
         */
        mw.widgets.datetime.DateTimeFormatter = function MwWidgetsDatetimeDateTimeFormatter( config ) {
-               var statick = this.constructor[ 'static' ];
-
-               statick.setupDefaults();
+               this.constructor.static.setupDefaults();
 
                config = $.extend( {
                        format: '@default',
                        local: false,
-                       fullZones: statick.fullZones,
-                       shortZones: statick.shortZones
+                       fullZones: this.constructor.static.fullZones,
+                       shortZones: this.constructor.static.shortZones
                }, config );
 
                // Mixin constructors
                OO.EventEmitter.call( this );
 
                // Properties
-               if ( statick.formats[ config.format ] ) {
-                       this.format = statick.formats[ config.format ];
+               if ( this.constructor.static.formats[ config.format ] ) {
+                       this.format = this.constructor.static.formats[ config.format ];
                } else {
                        this.format = config.format;
                }
@@ -70,7 +68,7 @@
         * @inheritable
         * @property {Object}
         */
-       mw.widgets.datetime.DateTimeFormatter[ 'static' ].formats = {};
+       mw.widgets.datetime.DateTimeFormatter.static.formats = {};
 
        /**
         * Default time zone indicators
@@ -79,7 +77,7 @@
         * @inheritable
         * @property {string[]}
         */
-       mw.widgets.datetime.DateTimeFormatter[ 'static' ].fullZones = null;
+       mw.widgets.datetime.DateTimeFormatter.static.fullZones = null;
 
        /**
         * Default abbreviated time zone indicators
@@ -88,9 +86,9 @@
         * @inheritable
         * @property {string[]}
         */
-       mw.widgets.datetime.DateTimeFormatter[ 'static' ].shortZones = null;
+       mw.widgets.datetime.DateTimeFormatter.static.shortZones = null;
 
-       mw.widgets.datetime.DateTimeFormatter[ 'static' ].setupDefaults = function () {
+       mw.widgets.datetime.DateTimeFormatter.static.setupDefaults = function () {
                if ( !this.fullZones ) {
                        this.fullZones = [
                                mw.msg( 'timezone-utc' ),
                return this.local;
        };
 
+       // eslint-disable-next-line valid-jsdoc
        /**
         * Toggle whether dates are in local time or UTC
         *
         *  - 'clip': "Jan 32" => "Jan 31", "Feb 32" => "Feb 28" (or 29), "Feb 0" => "Feb 1", etc.
         * @return {Date} Adjusted date
         */
-       mw.widgets.datetime.DateTimeFormatter.prototype.adjustComponent = function ( date /*, component, delta, mode */ ) {
+       mw.widgets.datetime.DateTimeFormatter.prototype.adjustComponent = function ( date /* , component, delta, mode */ ) {
                // Should be overridden by subclass
                return date;
        };
index a3088ec..e9bedf5 100644 (file)
 
        /* Static properties */
 
-       mw.widgets.datetime.DateTimeInputWidget[ 'static' ].supportsSimpleLabel = false;
+       mw.widgets.datetime.DateTimeInputWidget.static.supportsSimpleLabel = false;
 
        /* Events */
 
         * @private
         * @param {jQuery} $field
         * @param {jQuery.Event} e Key down event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldKeyDown = function ( $field, e ) {
                var spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
         * @private
         * @param {jQuery} $field
         * @param {jQuery.Event} e Change event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldWheel = function ( $field, e ) {
                var delta = 0,
index fbf3238..b280ead 100644 (file)
@@ -32,7 +32,7 @@
        /**
         * @inheritdoc
         */
-       mw.widgets.datetime.DiscordianDateTimeFormatter[ 'static' ].formats = {
+       mw.widgets.datetime.DiscordianDateTimeFormatter.static.formats = {
                '@time': '${hour|0}:${minute|0}:${second|0}',
                '@date': '$!{dow|full}${not-intercalary|1|, }${season|full}${not-intercalary|1| }${day|#}, ${year|#}',
                '@datetime': '$!{dow|full}${not-intercalary|1|, }${season|full}${not-intercalary|1| }${day|#}, ${year|#} ${hour|0}:${minute|0}:${second|0} $!{zone|short}',
index f60b34b..9e9b15f 100644 (file)
         * @cfg {number} [weekStartsOn=0] What day the week starts on: 0 is Sunday, 1 is Monday, 6 is Saturday.
         */
        mw.widgets.datetime.ProlepticGregorianDateTimeFormatter = function MwWidgetsDatetimeProlepticGregorianDateTimeFormatter( config ) {
-               var statick = this.constructor[ 'static' ];
-
-               statick.setupDefaults();
+               this.constructor.static.setupDefaults();
 
                config = $.extend( {
                        weekStartsOn: 0,
-                       hour12Periods: statick.hour12Periods
+                       hour12Periods: this.constructor.static.hour12Periods
                }, config );
 
                if ( config.fullMonthNames && !config.shortMonthNames ) {
                        }.bind( this ) );
                }
                config = $.extend( {
-                       fullMonthNames: statick.fullMonthNames,
-                       shortMonthNames: statick.shortMonthNames,
-                       fullDayNames: statick.fullDayNames,
-                       shortDayNames: statick.shortDayNames,
-                       dayLetters: statick.dayLetters
+                       fullMonthNames: this.constructor.static.fullMonthNames,
+                       shortMonthNames: this.constructor.static.shortMonthNames,
+                       fullDayNames: this.constructor.static.fullDayNames,
+                       shortDayNames: this.constructor.static.shortDayNames,
+                       dayLetters: this.constructor.static.dayLetters
                }, config );
 
                // Parent constructor
@@ -89,7 +87,7 @@
        /**
         * @inheritdoc
         */
-       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'static' ].formats = {
+       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.formats = {
                '@time': '${hour|0}:${minute|0}:${second|0}',
                '@date': '$!{dow|short} ${day|#} ${month|short} ${year|#}',
                '@datetime': '$!{dow|short} ${day|#} ${month|short} ${year|#} ${hour|0}:${minute|0}:${second|0} $!{zone|short}',
         * @inheritable
         * @property {Object}
         */
-       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'static' ].fullMonthNames = null;
+       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.fullMonthNames = null;
 
        /**
         * Default abbreviated month names.
         * @inheritable
         * @property {Object}
         */
-       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'static' ].shortMonthNames = null;
+       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.shortMonthNames = null;
 
        /**
         * Default full day of week names.
         * @inheritable
         * @property {Object}
         */
-       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'static' ].fullDayNames = null;
+       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.fullDayNames = null;
 
        /**
         * Default abbreviated day of week names.
         * @inheritable
         * @property {Object}
         */
-       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'static' ].shortDayNames = null;
+       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.shortDayNames = null;
 
        /**
         * Default day letters.
         * @inheritable
         * @property {string[]}
         */
-       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'static' ].dayLetters = null;
+       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.dayLetters = null;
 
        /**
         * Default AM/PM indicators
         * @inheritable
         * @property {string[]}
         */
-       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'static' ].hour12Periods = null;
+       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.hour12Periods = null;
 
-       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'static' ].setupDefaults = function () {
-               mw.widgets.datetime.DateTimeFormatter[ 'static' ].setupDefaults.call( this );
+       mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.setupDefaults = function () {
+               mw.widgets.datetime.DateTimeFormatter.static.setupDefaults.call( this );
 
                if ( this.fullMonthNames && !this.shortMonthNames ) {
                        this.shortMonthNames = {};
diff --git a/resources/src/mediawiki.widgets/MediaSearch/broken-image.png b/resources/src/mediawiki.widgets/MediaSearch/broken-image.png
new file mode 100644 (file)
index 0000000..f5be958
Binary files /dev/null and b/resources/src/mediawiki.widgets/MediaSearch/broken-image.png differ
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js
new file mode 100644 (file)
index 0000000..dd07b92
--- /dev/null
@@ -0,0 +1,229 @@
+/*!
+ * MediaWiki Widgets - APIResultsProvider class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org
+ */
+( function ( $, mw ) {
+
+       /**
+        * API Results Provider object.
+        *
+        * @class
+        * @mixins OO.EventEmitter
+        *
+        * @constructor
+        * @param {string} apiurl The URL to the api
+        * @param {Object} [config] Configuration options
+        * @cfg {number} fetchLimit The default number of results to fetch
+        * @cfg {string} lang The language of the API
+        * @cfg {number} offset Initial offset, if relevant, to call results from
+        * @cfg {Object} ajaxSettings The settings for the ajax call
+        * @cfg {Object} staticParams The data parameters that are static and should
+        *  always be sent to the API request, as opposed to user parameters.
+        * @cfg {Object} userParams Initial user parameters to be sent as data to
+        *  the API request. These can change per request, like the search query term
+        *  or sizing parameters for images, etc.
+        */
+       mw.widgets.APIResultsProvider = function MwWidgetsAPIResultsProvider( apiurl, config ) {
+               config = config || {};
+
+               this.setAPIurl( apiurl );
+               this.setDefaultFetchLimit( config.fetchLimit || 30 );
+               this.setLang( config.lang );
+               this.setOffset( config.offset || 0 );
+               this.setAjaxSettings( config.ajaxSettings || {} );
+
+               this.staticParams = config.staticParams || {};
+               this.userParams = config.userParams || {};
+
+               this.toggleDepleted( false );
+
+               // Mixin constructors
+               OO.EventEmitter.call( this );
+       };
+
+       /* Setup */
+       OO.mixinClass( mw.widgets.APIResultsProvider, OO.EventEmitter );
+
+       /* Methods */
+
+       /**
+        * Get results from the source
+        *
+        * @param {number} howMany Number of results to ask for
+        * @return {jQuery.Promise} Promise that is resolved into an array
+        * of available results, or is rejected if no results are available.
+        */
+       mw.widgets.APIResultsProvider.prototype.getResults = function () {
+               var xhr,
+                       deferred = $.Deferred(),
+                       allParams = $.extend( {}, this.getStaticParams(), this.getUserParams() );
+
+               xhr = $.getJSON( this.getAPIurl(), allParams )
+                       .done( function ( data ) {
+                               if (
+                                       $.type( data ) !== 'array' ||
+                                       (
+                                               $.type( data ) === 'array' &&
+                                               data.length === 0
+                                       )
+                               ) {
+                                       deferred.resolve();
+                               } else {
+                                       deferred.resolve( data );
+                               }
+                       } );
+               return deferred.promise( { abort: xhr.abort } );
+       };
+
+       /**
+        * Set API url
+        *
+        * @param {string} apiurl API url
+        */
+       mw.widgets.APIResultsProvider.prototype.setAPIurl = function ( apiurl ) {
+               this.apiurl = apiurl;
+       };
+
+       /**
+        * Set api url
+        *
+        * @return {string} API url
+        */
+       mw.widgets.APIResultsProvider.prototype.getAPIurl = function () {
+               return this.apiurl;
+       };
+
+       /**
+        * Get the static, non-changing data parameters sent to the API
+        *
+        * @return {Object} Data parameters
+        */
+       mw.widgets.APIResultsProvider.prototype.getStaticParams = function () {
+               return this.staticParams;
+       };
+
+       /**
+        * Get the user-inputted dynamic data parameters sent to the API
+        *
+        * @return {Object} Data parameters
+        */
+       mw.widgets.APIResultsProvider.prototype.getUserParams = function () {
+               return this.userParams;
+       };
+
+       /**
+        * Set the data parameters sent to the API
+        *
+        * @param {Object} params User defined data parameters
+        */
+       mw.widgets.APIResultsProvider.prototype.setUserParams = function ( params ) {
+               // Asymmetrically compare (params is subset of this.userParams)
+               if ( !OO.compare( params, this.userParams, true ) ) {
+                       this.userParams = $.extend( {}, this.userParams, params );
+                       this.reset();
+               }
+       };
+
+       /**
+        * Reset the provider
+        */
+       mw.widgets.APIResultsProvider.prototype.reset = function () {
+               // Reset offset
+               this.setOffset( 0 );
+               // Reset depleted status
+               this.toggleDepleted( false );
+       };
+
+       /**
+        * Get fetch limit or 'page' size. This is the number
+        * of results per request.
+        *
+        * @return {number} limit
+        */
+       mw.widgets.APIResultsProvider.prototype.getDefaultFetchLimit = function () {
+               return this.limit;
+       };
+
+       /**
+        * Set limit
+        *
+        * @param {number} limit Default number of results to fetch from the API
+        */
+       mw.widgets.APIResultsProvider.prototype.setDefaultFetchLimit = function ( limit ) {
+               this.limit = limit;
+       };
+
+       /**
+        * Get provider API language
+        *
+        * @return {string} Provider API language
+        */
+       mw.widgets.APIResultsProvider.prototype.getLang = function () {
+               return this.lang;
+       };
+
+       /**
+        * Set provider API language
+        *
+        * @param {string} lang Provider API language
+        */
+       mw.widgets.APIResultsProvider.prototype.setLang = function ( lang ) {
+               this.lang = lang;
+       };
+
+       /**
+        * Get result offset
+        *
+        * @return {number} Offset Results offset for the upcoming request
+        */
+       mw.widgets.APIResultsProvider.prototype.getOffset = function () {
+               return this.offset;
+       };
+
+       /**
+        * Set result offset
+        *
+        * @param {number} offset Results offset for the upcoming request
+        */
+       mw.widgets.APIResultsProvider.prototype.setOffset = function ( offset ) {
+               this.offset = offset;
+       };
+
+       /**
+        * Check whether the provider is depleted and has no more results
+        * to hand off.
+        *
+        * @return {boolean} The provider is depleted
+        */
+       mw.widgets.APIResultsProvider.prototype.isDepleted = function () {
+               return this.depleted;
+       };
+
+       /**
+        * Toggle depleted state
+        *
+        * @param {boolean} isDepleted The provider is depleted
+        */
+       mw.widgets.APIResultsProvider.prototype.toggleDepleted = function ( isDepleted ) {
+               this.depleted = isDepleted !== undefined ? isDepleted : !this.depleted;
+       };
+
+       /**
+        * Get the default ajax settings
+        *
+        * @return {Object} Ajax settings
+        */
+       mw.widgets.APIResultsProvider.prototype.getAjaxSettings = function () {
+               return this.ajaxSettings;
+       };
+
+       /**
+        * Get the default ajax settings
+        *
+        * @param {Object} settings Ajax settings
+        */
+       mw.widgets.APIResultsProvider.prototype.setAjaxSettings = function ( settings ) {
+               this.ajaxSettings = settings;
+       };
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js
new file mode 100644 (file)
index 0000000..3bc1d51
--- /dev/null
@@ -0,0 +1,224 @@
+/*!
+ * MediaWiki Widgets - APIResultsQueue class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org
+ */
+( function ( $, mw ) {
+
+       /**
+        * API Results Queue object.
+        *
+        * @class
+        * @mixins OO.EventEmitter
+        *
+        * @constructor
+        * @param {Object} [config] Configuration options
+        * @cfg {number} limit The default number of results to fetch
+        * @cfg {number} threshold The default number of extra results
+        *  that the queue should always strive to have on top of the
+        *  individual requests for items.
+        */
+       mw.widgets.APIResultsQueue = function MwWidgetsAPIResultsQueue( config ) {
+               config = config || {};
+
+               this.fileRepoPromise = null;
+               this.providers = [];
+               this.providerPromises = [];
+               this.queue = [];
+
+               this.params = {};
+
+               this.limit = config.limit || 20;
+               this.setThreshold( config.threshold || 10 );
+
+               // Mixin constructors
+               OO.EventEmitter.call( this );
+       };
+
+       /* Setup */
+       OO.mixinClass( mw.widgets.APIResultsQueue, OO.EventEmitter );
+
+       /* Methods */
+
+       /**
+        * Set up the queue and its resources.
+        * This should be overridden if there are any setup steps to perform.
+        *
+        * @return {jQuery.Promise} Promise that resolves when the resources
+        *  are set up. Note: The promise must have an .abort() functionality.
+        */
+       mw.widgets.APIResultsQueue.prototype.setup = function () {
+               return $.Deferred().resolve().promise( { abort: $.noop } );
+       };
+
+       /**
+        * Get items from the queue
+        *
+        * @param {number} [howMany] How many items to retrieve. Defaults to the
+        *  default limit supplied on initialization.
+        * @return {jQuery.Promise} Promise that resolves into an array of items.
+        */
+       mw.widgets.APIResultsQueue.prototype.get = function ( howMany ) {
+               var fetchingPromise = null,
+                       me = this;
+
+               howMany = howMany || this.limit;
+
+               // Check if the queue has enough items
+               if ( this.queue.length < howMany + this.threshold ) {
+                       // Call for more results
+                       fetchingPromise = this.queryProviders( howMany + this.threshold )
+                               .then( function ( items ) {
+                                       // Add to the queue
+                                       me.queue = me.queue.concat.apply( me.queue, items );
+                               } );
+               }
+
+               return $.when( fetchingPromise )
+                       .then( function () {
+                               return me.queue.splice( 0, howMany );
+                       } );
+
+       };
+
+       /**
+        * Get results from all providers
+        *
+        * @param {number} [howMany] How many items to retrieve. Defaults to the
+        *  default limit supplied on initialization.
+        * @return {jQuery.Promise} Promise that is resolved into an array
+        *  of fetched items. Note: The promise must have an .abort() functionality.
+        */
+       mw.widgets.APIResultsQueue.prototype.queryProviders = function ( howMany ) {
+               var i, len,
+                       queue = this;
+
+               // Make sure there are resources set up
+               return this.setup()
+                       .then( function () {
+                               // Abort previous requests
+                               for ( i = 0, len = queue.providerPromises.length; i < len; i++ ) {
+                                       queue.providerPromises[ i ].abort();
+                               }
+                               queue.providerPromises = [];
+                               // Set up the query to all providers
+                               for ( i = 0, len = queue.providers.length; i < len; i++ ) {
+                                       if ( !queue.providers[ i ].isDepleted() ) {
+                                               queue.providerPromises.push(
+                                                       queue.providers[ i ].getResults( howMany )
+                                               );
+                                       }
+                               }
+
+                               return $.when.apply( $, queue.providerPromises )
+                                       .then( Array.prototype.concat.bind( [] ) );
+                       } );
+       };
+
+       /**
+        * Set the search query for all the providers.
+        *
+        * This also makes sure to abort any previous promises.
+        *
+        * @param {Object} params API search parameters
+        */
+       mw.widgets.APIResultsQueue.prototype.setParams = function ( params ) {
+               var i, len;
+               if ( !OO.compare( params, this.params, true ) ) {
+                       this.reset();
+                       this.params = $.extend( this.params, params );
+                       // Reset queue
+                       this.queue = [];
+                       // Reset promises
+                       for ( i = 0, len = this.providerPromises.length; i < len; i++ ) {
+                               this.providerPromises[ i ].abort();
+                       }
+                       // Change queries
+                       for ( i = 0, len = this.providers.length; i < len; i++ ) {
+                               this.providers[ i ].setUserParams( this.params );
+                       }
+               }
+       };
+
+       /**
+        * Reset the queue and all its providers
+        */
+       mw.widgets.APIResultsQueue.prototype.reset = function () {
+               var i, len;
+               // Reset queue
+               this.queue = [];
+               // Reset promises
+               for ( i = 0, len = this.providerPromises.length; i < len; i++ ) {
+                       this.providerPromises[ i ].abort();
+               }
+               // Change queries
+               for ( i = 0, len = this.providers.length; i < len; i++ ) {
+                       this.providers[ i ].reset();
+               }
+       };
+
+       /**
+        * Get the data parameters sent to the API
+        *
+        * @return {Object} params API search parameters
+        */
+       mw.widgets.APIResultsQueue.prototype.getParams = function () {
+               return this.params;
+       };
+
+       /**
+        * Set the providers
+        *
+        * @param {mw.widgets.APIResultsProvider[]} providers An array of providers
+        */
+       mw.widgets.APIResultsQueue.prototype.setProviders = function ( providers ) {
+               this.providers = providers;
+       };
+
+       /**
+        * Add a provider to the group
+        *
+        * @param {mw.widgets.APIResultsProvider} provider A provider object
+        */
+       mw.widgets.APIResultsQueue.prototype.addProvider = function ( provider ) {
+               this.providers.push( provider );
+       };
+
+       /**
+        * Set the providers
+        *
+        * @return {mw.widgets.APIResultsProvider[]} providers An array of providers
+        */
+       mw.widgets.APIResultsQueue.prototype.getProviders = function () {
+               return this.providers;
+       };
+
+       /**
+        * Get the queue size
+        *
+        * @return {number} Queue size
+        */
+       mw.widgets.APIResultsQueue.prototype.getQueueSize = function () {
+               return this.queue.length;
+       };
+
+       /**
+        * Set queue threshold
+        *
+        * @param {number} threshold Queue threshold, below which we will
+        *  request more items
+        */
+       mw.widgets.APIResultsQueue.prototype.setThreshold = function ( threshold ) {
+               this.threshold = threshold;
+       };
+
+       /**
+        * Get queue threshold
+        *
+        * @return {number} threshold Queue threshold, below which we will
+        *  request more items
+        */
+       mw.widgets.APIResultsQueue.prototype.getThreshold = function () {
+               return this.threshold;
+       };
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js
new file mode 100644 (file)
index 0000000..d767109
--- /dev/null
@@ -0,0 +1,322 @@
+/*!
+ * MediaWiki Widgets - MediaResourceProvider class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+       /**
+        * MediaWiki media resource provider.
+        *
+        * @class
+        * @extends mw.widgets.APIResultsProvider
+        *
+        * @constructor
+        * @param {string} apiurl The API url
+        * @param {Object} [config] Configuration options
+        * @cfg {string} [scriptDirUrl] The url of the API script
+        */
+       mw.widgets.MediaResourceProvider = function MwWidgetsMediaResourceProvider( apiurl, config ) {
+               config = config || {};
+
+               // Parent constructor
+               mw.widgets.MediaResourceProvider.super.call( this, apiurl, config );
+
+               // Fetching configuration
+               this.scriptDirUrl = config.scriptDirUrl;
+               this.isLocal = config.local !== undefined;
+
+               if ( this.isLocal ) {
+                       this.setAPIurl( mw.util.wikiScript( 'api' ) );
+               } else {
+                       // If 'apiurl' is set, use that. Otherwise, build the url
+                       // from scriptDirUrl and /api.php suffix
+                       this.setAPIurl( this.getAPIurl() || ( this.scriptDirUrl + '/api.php' ) );
+               }
+
+               this.siteInfoPromise = null;
+               this.thumbSizes = [];
+               this.imageSizes = [];
+       };
+
+       /* Inheritance */
+       OO.inheritClass( mw.widgets.MediaResourceProvider, mw.widgets.APIResultsProvider );
+
+       /* Methods */
+
+       /**
+        * @inheritdoc
+        */
+       mw.widgets.MediaResourceProvider.prototype.getStaticParams = function () {
+               return $.extend(
+                       {},
+                       // Parent method
+                       mw.widgets.MediaResourceProvider.super.prototype.getStaticParams.call( this ),
+                       {
+                               action: 'query',
+                               iiprop: 'dimensions|url|mediatype|extmetadata|timestamp|user',
+                               iiextmetadatalanguage: this.getLang(),
+                               prop: 'imageinfo'
+                       }
+               );
+       };
+
+       /**
+        * Initialize the source and get the site info.
+        *
+        * Connect to the api url and retrieve the siteinfo parameters
+        * that are required for fetching results.
+        *
+        * @return {jQuery.Promise} Promise that resolves when the class
+        * properties are set.
+        */
+       mw.widgets.MediaResourceProvider.prototype.loadSiteInfo = function () {
+               var provider = this;
+
+               if ( !this.siteInfoPromise ) {
+                       this.siteInfoPromise = new mw.Api().get( {
+                               action: 'query',
+                               meta: 'siteinfo'
+                       } )
+                               .then( function ( data ) {
+                                       provider.setImageSizes( data.query.general.imagelimits || [] );
+                                       provider.setThumbSizes( data.query.general.thumblimits || [] );
+                                       provider.setUserParams( {
+                                               // Standard width per resource
+                                               iiurlwidth: provider.getStandardWidth()
+                                       } );
+                               } );
+               }
+               return this.siteInfoPromise;
+       };
+
+       /**
+        * Override parent method and get results from the source
+        *
+        * @param {number} [howMany] The number of items to pull from the API
+        * @return {jQuery.Promise} Promise that is resolved into an array
+        * of available results, or is rejected if no results are available.
+        */
+       mw.widgets.MediaResourceProvider.prototype.getResults = function ( howMany ) {
+               var xhr,
+                       aborted = false,
+                       provider = this;
+
+               return this.loadSiteInfo()
+                       .then( function () {
+                               if ( aborted ) {
+                                       return $.Deferred().reject();
+                               }
+                               xhr = provider.fetchAPIresults( howMany );
+                               return xhr;
+                       } )
+                       .then(
+                               function ( results ) {
+                                       if ( !results || results.length === 0 ) {
+                                               provider.toggleDepleted( true );
+                                               return [];
+                                       }
+                                       return results;
+                               },
+                               // Process failed, return an empty promise
+                               function () {
+                                       provider.toggleDepleted( true );
+                                       return $.Deferred().resolve( [] );
+                               }
+                       )
+                       .promise( { abort: function () {
+                               aborted = true;
+                               if ( xhr ) {
+                                       xhr.abort();
+                               }
+                       } } );
+       };
+
+       /**
+        * Get continuation API data
+        *
+        * @param {number} howMany The number of results to retrieve
+        * @return {Object} API request data
+        */
+       mw.widgets.MediaResourceProvider.prototype.getContinueData = function () {
+               return {};
+       };
+
+       /**
+        * Set continuation data for the next page
+        *
+        * @param {Object} continueData Continuation data
+        */
+       mw.widgets.MediaResourceProvider.prototype.setContinue = function () {
+       };
+
+       /**
+        * Sort the results
+        *
+        * @param {Object[]} results API results
+        * @return {Object[]} Sorted results
+        */
+       mw.widgets.MediaResourceProvider.prototype.sort = function ( results ) {
+               return results;
+       };
+
+       /**
+        * Call the API for search results.
+        *
+        * @param {number} howMany The number of results to retrieve
+        * @return {jQuery.Promise} Promise that resolves with an array of objects that contain
+        *  the fetched data.
+        */
+       mw.widgets.MediaResourceProvider.prototype.fetchAPIresults = function ( howMany ) {
+               var xhr, api,
+                       provider = this;
+
+               if ( !this.isValid() ) {
+                       return $.Deferred().reject().promise( { abort: $.noop } );
+               }
+
+               api = this.isLocal ? new mw.Api() : new mw.ForeignApi( this.getAPIurl(), { anonymous: true } );
+               xhr = api.get( $.extend( {}, this.getStaticParams(), this.getUserParams(), this.getContinueData( howMany ) ) );
+               return xhr
+                       .then( function ( data ) {
+                               var page, newObj, raw,
+                                       results = [];
+
+                               if ( data.error ) {
+                                       provider.toggleDepleted( true );
+                                       return [];
+                               }
+
+                               if ( data.continue ) {
+                                       // Update the offset for next time
+                                       provider.setContinue( data.continue );
+                               } else {
+                                       // This is the last available set of results. Mark as depleted!
+                                       provider.toggleDepleted( true );
+                               }
+
+                               // If the source returned no results, it will not have a
+                               // query property
+                               if ( data.query ) {
+                                       raw = data.query.pages;
+                                       if ( raw ) {
+                                               // Strip away the page ids
+                                               for ( page in raw ) {
+                                                       if ( !raw[ page ].imageinfo ) {
+                                                               // The search may give us pages that belong to the File:
+                                                               // namespace but have no files in them, either because
+                                                               // they were deleted or imported wrongly, or just started
+                                                               // as pages. In that case, the response will not include
+                                                               // imageinfo. Skip those files.
+                                                               continue;
+                                                       }
+                                                       newObj = raw[ page ].imageinfo[ 0 ];
+                                                       newObj.title = raw[ page ].title;
+                                                       newObj.index = raw[ page ].index;
+                                                       results.push( newObj );
+                                               }
+                                       }
+                               }
+                               return provider.sort( results );
+                       } )
+                       .promise( { abort: xhr.abort } );
+       };
+
+       /**
+        * Set name
+        *
+        * @param {string} name
+        */
+       mw.widgets.MediaResourceProvider.prototype.setName = function ( name ) {
+               this.name = name;
+       };
+
+       /**
+        * Get name
+        *
+        * @return {string} name
+        */
+       mw.widgets.MediaResourceProvider.prototype.getName = function () {
+               return this.name;
+       };
+
+       /**
+        * Get standard width, based on the provider source's thumb sizes.
+        *
+        * @return {number|undefined} fetchWidth
+        */
+       mw.widgets.MediaResourceProvider.prototype.getStandardWidth = function () {
+               return ( this.thumbSizes && this.thumbSizes[ this.thumbSizes.length - 1 ] ) ||
+                       ( this.imageSizes && this.imageSizes[ 0 ] ) ||
+                       // Fall back on a number
+                       300;
+       };
+
+       /**
+        * Get prop
+        *
+        * @return {string} prop
+        */
+       mw.widgets.MediaResourceProvider.prototype.getFetchProp = function () {
+               return this.fetchProp;
+       };
+
+       /**
+        * Set prop
+        *
+        * @param {string} prop
+        */
+       mw.widgets.MediaResourceProvider.prototype.setFetchProp = function ( prop ) {
+               this.fetchProp = prop;
+       };
+
+       /**
+        * Set thumb sizes
+        *
+        * @param {number[]} sizes Available thumbnail sizes
+        */
+       mw.widgets.MediaResourceProvider.prototype.setThumbSizes = function ( sizes ) {
+               this.thumbSizes = sizes;
+       };
+
+       /**
+        * Set image sizes
+        *
+        * @param {number[]} sizes Available image sizes
+        */
+       mw.widgets.MediaResourceProvider.prototype.setImageSizes = function ( sizes ) {
+               this.imageSizes = sizes;
+       };
+
+       /**
+        * Get thumb sizes
+        *
+        * @return {number[]} sizes Available thumbnail sizes
+        */
+       mw.widgets.MediaResourceProvider.prototype.getThumbSizes = function () {
+               return this.thumbSizes;
+       };
+
+       /**
+        * Get image sizes
+        *
+        * @return {number[]} sizes Available image sizes
+        */
+       mw.widgets.MediaResourceProvider.prototype.getImageSizes = function () {
+               return this.imageSizes;
+       };
+
+       /**
+        * Check if this source is valid.
+        *
+        * @return {boolean} Source is valid
+        */
+       mw.widgets.MediaResourceProvider.prototype.isValid = function () {
+               return this.isLocal ||
+                       // If we don't have either 'apiurl' or 'scriptDirUrl'
+                       // the source is invalid, and we will skip it
+                       this.apiurl !== undefined ||
+                       this.scriptDirUrl !== undefined;
+       };
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js
new file mode 100644 (file)
index 0000000..34fa44b
--- /dev/null
@@ -0,0 +1,68 @@
+/*!
+ * MediaWiki Widgets - MediaResourceQueue class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+       /**
+        * MediaWiki media resource queue.
+        *
+        * @class
+        * @extends mw.widgets.APIResultsQueue
+        *
+        * @constructor
+        * @param {Object} [config] Configuration options
+        * @cfg {number} maxHeight The maximum height of the media, used in the
+        *  search call to the API.
+        */
+       mw.widgets.MediaResourceQueue = function MwWidgetsMediaResourceQueue( config ) {
+               config = config || {};
+
+               // Parent constructor
+               mw.widgets.MediaResourceQueue.super.call( this, config );
+
+               this.maxHeight = config.maxHeight || 200;
+       };
+
+       /* Inheritance */
+       OO.inheritClass( mw.widgets.MediaResourceQueue, mw.widgets.APIResultsQueue );
+
+       /**
+        * Fetch the file repos.
+        *
+        * @return {jQuery.Promise} Promise that resolves when the resources are set up
+        */
+       mw.widgets.MediaResourceQueue.prototype.getFileRepos = function () {
+               var defaultSource = [ {
+                       url: mw.util.wikiScript( 'api' ),
+                       local: ''
+               } ];
+
+               if ( !this.fileRepoPromise ) {
+                       this.fileRepoPromise = new mw.Api().get( {
+                               action: 'query',
+                               meta: 'filerepoinfo'
+                       } ).then(
+                               function ( resp ) {
+                                       return resp.query && resp.query.repos || defaultSource;
+                               },
+                               function () {
+                                       return $.Deferred().resolve( defaultSource );
+                               }
+                       );
+               }
+
+               return this.fileRepoPromise;
+       };
+
+       /**
+        * Get image maximum height
+        *
+        * @return {string} Image max height
+        */
+       mw.widgets.MediaResourceQueue.prototype.getMaxHeight = function () {
+               return this.maxHeight;
+       };
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css
new file mode 100644 (file)
index 0000000..bc752b5
--- /dev/null
@@ -0,0 +1,89 @@
+/*!
+ * MediaWiki Widgets - MediaResultWidget styles.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.mw-widget-mediaResultWidget {
+       display: inline-block;
+       position: relative;
+       padding: 0;
+       margin: 2px;
+       overflow: hidden;
+       box-sizing: border-box;
+       text-align: center;
+}
+
+.mw-widget-mediaResultWidget-error {
+       background-color: #f3f3f3;
+}
+
+.mw-widget-mediaResultWidget-thumbnail {
+       opacity: 0;
+       display: inline-block;
+       /* stylelint-disable no-unsupported-browser-features */
+       -webkit-transition: opacity 400ms;
+       -moz-transition: opacity 400ms;
+       transition: opacity 400ms;
+       /* stylelint-enable no-unsupported-browser-features */
+}
+
+.mw-widget-mediaResultWidget-done .mw-widget-mediaResultWidget-thumbnail,
+.mw-widget-mediaResultWidget-error .mw-widget-mediaResultWidget-thumbnail {
+       opacity: 1;
+}
+
+.mw-widget-mediaResultWidget-crop {
+       background-size: cover; /* stylelint-disable-line no-unsupported-browser-features */
+       background-position: center center;
+}
+
+.mw-widget-mediaResultWidget-overlay {
+       position: absolute;
+       top: 0;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       box-shadow: inset 0 0 0 1px #ccc;
+}
+
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-highlighted,
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-selected {
+       box-shadow: 0 0 0.3em #a7dcff, 0 0 0 #fff;
+}
+
+.mw-widget-mediaResultWidget-error .mw-widget-mediaResultWidget-thumbnail {
+       /* @embed */
+       background-image: url( broken-image.png );
+       background-size: auto; /* stylelint-disable-line no-unsupported-browser-features */
+       background-position: center center;
+       background-repeat: no-repeat;
+}
+
+.mw-widget-mediaResultWidget .mw-widget-mediaResultWidget-nameLabel {
+       position: absolute;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       overflow: hidden;
+       padding: 0.5em;
+       color: #fff;
+       text-shadow: 1px 1px #000; /* stylelint-disable-line no-unsupported-browser-features */
+       line-height: 1.125em;
+       background-color: rgba( 0, 0, 0, 0.5 );
+       text-overflow: ellipsis;
+       text-align: left;
+}
+
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-highlighted .mw-widget-mediaResultWidget-nameLabel {
+       background-color: rgba( 0, 0, 0, 0.75 );
+}
+
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-selected .mw-widget-mediaResultWidget-nameLabel {
+       background-color: #000;
+}
+
+.mw-widget-mediaSearchWidget-noresults {
+       padding-top: 1em;
+}
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js
new file mode 100644 (file)
index 0000000..7607e84
--- /dev/null
@@ -0,0 +1,274 @@
+/*!
+ * MediaWiki Widgets - MediaResultWidget class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+       /**
+        * Creates an mw.widgets.MediaResultWidget object.
+        *
+        * @class
+        * @extends OO.ui.OptionWidget
+        *
+        * @constructor
+        * @param {Object} [config] Configuration options
+        * @cfg {number} [rowHeight] Height of the row this result is part of
+        * @cfg {number} [maxRowWidth] A limit for the width of the row this
+        *  result is a part of.
+        * @cfg {number} [minWidth] Minimum width for the result
+        * @cfg {number} [maxWidth] Maximum width for the result
+        */
+       mw.widgets.MediaResultWidget = function MwWidgetsMediaResultWidget( config ) {
+               // Configuration initialization
+               config = config || {};
+
+               // Parent constructor
+               mw.widgets.MediaResultWidget.super.call( this, config );
+
+               // Properties
+               this.setRowHeight( config.rowHeight || 150 );
+               this.maxRowWidth = config.maxRowWidth || 500;
+               this.minWidth = config.minWidth || this.maxRowWidth / 5;
+               this.maxWidth = config.maxWidth || this.maxRowWidth * 2 / 3;
+
+               this.imageDimensions = {};
+
+               this.isAudio = this.data.mediatype === 'AUDIO';
+
+               // Store the thumbnail url
+               this.thumbUrl = this.data.thumburl;
+               this.src = null;
+               this.row = null;
+
+               this.$thumb = $( '<img>' )
+                       .addClass( 'mw-widget-mediaResultWidget-thumbnail' )
+                       .on( {
+                               load: this.onThumbnailLoad.bind( this ),
+                               error: this.onThumbnailError.bind( this )
+                       } );
+               this.$overlay = $( '<div>' )
+                       .addClass( 'mw-widget-mediaResultWidget-overlay' );
+
+               this.calculateSizing( this.data );
+
+               // Get wiki default thumbnail size
+               this.defaultThumbSize = mw.config.get( 'wgVisualEditorConfig' )
+                       .defaultUserOptions.defaultthumbsize;
+
+               // Initialization
+               this.setLabel( new mw.Title( this.data.title ).getNameText() );
+               this.$label.addClass( 'mw-widget-mediaResultWidget-nameLabel' );
+
+               this.$element
+                       .addClass( 'mw-widget-mediaResultWidget ve-ui-texture-pending' )
+                       .prepend( this.$thumb, this.$overlay );
+       };
+
+       /* Inheritance */
+
+       OO.inheritClass( mw.widgets.MediaResultWidget, OO.ui.OptionWidget );
+
+       /* Static methods */
+
+       // Copied from ve.dm.MWImageNode
+       mw.widgets.MediaResultWidget.static.resizeToBoundingBox = function ( imageDimensions, boundingBox ) {
+               var newDimensions = OO.copy( imageDimensions ),
+                       scale = Math.min(
+                               boundingBox.height / imageDimensions.height,
+                               boundingBox.width / imageDimensions.width
+                       );
+
+               if ( scale < 1 ) {
+                       // Scale down
+                       newDimensions = {
+                               width: Math.floor( newDimensions.width * scale ),
+                               height: Math.floor( newDimensions.height * scale )
+                       };
+               }
+               return newDimensions;
+       };
+
+       /* Methods */
+       /** */
+       mw.widgets.MediaResultWidget.prototype.onThumbnailLoad = function () {
+               this.$thumb.first().addClass( 've-ui-texture-transparency' );
+               this.$element
+                       .addClass( 'mw-widget-mediaResultWidget-done' )
+                       .removeClass( 've-ui-texture-pending' );
+       };
+
+       /** */
+       mw.widgets.MediaResultWidget.prototype.onThumbnailError = function () {
+               this.$thumb.last()
+                       .css( 'background-image', '' )
+                       .addClass( 've-ui-texture-alert' );
+               this.$element
+                       .addClass( 'mw-widget-mediaResultWidget-error' )
+                       .removeClass( 've-ui-texture-pending' );
+       };
+
+       /**
+        * Resize the thumbnail and wrapper according to row height and bounding boxes, if given.
+        *
+        * @param {Object} originalDimensions Original image dimensions with width and height values
+        * @param {Object} [boundingBox] Specific bounding box, if supplied
+        */
+       mw.widgets.MediaResultWidget.prototype.calculateSizing = function ( originalDimensions, boundingBox ) {
+               var wrapperPadding,
+                       imageDimensions = {};
+
+               boundingBox = boundingBox || {};
+
+               if ( this.isAudio ) {
+                       // HACK: We are getting the wrong information from the
+                       // API about audio files. Set their thumbnail to square 120px
+                       imageDimensions = {
+                               width: 120,
+                               height: 120
+                       };
+               } else {
+                       // Get the image within the bounding box
+                       imageDimensions = this.constructor.static.resizeToBoundingBox(
+                               // Image original dimensions
+                               {
+                                       width: originalDimensions.width || originalDimensions.thumbwidth,
+                                       height: originalDimensions.height || originalDimensions.thumbwidth
+                               },
+                               // Bounding box
+                               {
+                                       width: boundingBox.width || this.getImageMaxWidth(),
+                                       height: boundingBox.height || this.getRowHeight()
+                               }
+                       );
+               }
+               this.imageDimensions = imageDimensions;
+               // Set the thumbnail size
+               this.$thumb.css( this.imageDimensions );
+
+               // Set the box size
+               wrapperPadding = this.calculateWrapperPadding( this.imageDimensions );
+               this.$element.css( wrapperPadding );
+       };
+
+       /**
+        * Replace the empty .src attribute of the image with the
+        * actual src.
+        */
+       mw.widgets.MediaResultWidget.prototype.lazyLoad = function () {
+               if ( !this.hasSrc() ) {
+                       this.src = this.thumbUrl;
+                       this.$thumb.attr( 'src', this.thumbUrl );
+               }
+       };
+
+       /**
+        * Retrieve the store dimensions object
+        *
+        * @return {Object} Thumb dimensions
+        */
+       mw.widgets.MediaResultWidget.prototype.getDimensions = function () {
+               return this.dimensions;
+       };
+
+       /**
+        * Resize thumbnail and element according to the resize factor
+        *
+        * @param {number} resizeFactor The resizing factor for the image
+        */
+       mw.widgets.MediaResultWidget.prototype.resizeThumb = function ( resizeFactor ) {
+               var boundingBox,
+                       imageOriginalWidth = this.imageDimensions.width,
+                       wrapperWidth = this.$element.width();
+               // Set the new row height
+               this.setRowHeight( Math.ceil( this.getRowHeight() * resizeFactor ) );
+
+               boundingBox = {
+                       width: Math.ceil( this.imageDimensions.width * resizeFactor ),
+                       height: this.getRowHeight()
+               };
+
+               this.calculateSizing( this.data, boundingBox );
+
+               // We need to adjust the wrapper this time to fit the "perfect"
+               // dimensions, regardless of how small the image is
+               if ( imageOriginalWidth < wrapperWidth ) {
+                       boundingBox.width = wrapperWidth * resizeFactor;
+               }
+               this.$element.css( this.calculateWrapperPadding( boundingBox ) );
+       };
+
+       /**
+        * Adjust the wrapper padding for small images
+        *
+        * @param {Object} thumbDimensions Thumbnail dimensions
+        * @return {Object} Css styling for the wrapper
+        */
+       mw.widgets.MediaResultWidget.prototype.calculateWrapperPadding = function ( thumbDimensions ) {
+               var css = {
+                       height: this.rowHeight,
+                       width: thumbDimensions.width,
+                       lineHeight: this.getRowHeight() + 'px'
+               };
+
+               // Check if the image is too thin so we can make a bit of space around it
+               if ( thumbDimensions.width < this.minWidth ) {
+                       css.width = this.minWidth;
+               }
+
+               return css;
+       };
+
+       /**
+        * Set the row height for all size calculations
+        *
+        * @return {number} rowHeight Row height
+        */
+       mw.widgets.MediaResultWidget.prototype.getRowHeight = function () {
+               return this.rowHeight;
+       };
+
+       /**
+        * Set the row height for all size calculations
+        *
+        * @param {number} rowHeight Row height
+        */
+       mw.widgets.MediaResultWidget.prototype.setRowHeight = function ( rowHeight ) {
+               this.rowHeight = rowHeight;
+       };
+
+       mw.widgets.MediaResultWidget.prototype.setImageMaxWidth = function ( width ) {
+               this.maxWidth = width;
+       };
+       mw.widgets.MediaResultWidget.prototype.getImageMaxWidth = function () {
+               return this.maxWidth;
+       };
+
+       /**
+        * Set the row this result is in.
+        *
+        * @param {number} row Row number
+        */
+       mw.widgets.MediaResultWidget.prototype.setRow = function ( row ) {
+               this.row = row;
+       };
+
+       /**
+        * Get the row this result is in.
+        *
+        * @return {number} row Row number
+        */
+       mw.widgets.MediaResultWidget.prototype.getRow = function () {
+               return this.row;
+       };
+
+       /**
+        * Check if the image has a src attribute already
+        *
+        * @return {boolean} Thumbnail has its source attribute set
+        */
+       mw.widgets.MediaResultWidget.prototype.hasSrc = function () {
+               return !!this.src;
+       };
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js
new file mode 100644 (file)
index 0000000..a46d911
--- /dev/null
@@ -0,0 +1,69 @@
+/*!
+ * MediaWiki Widgets - MediaSearchProvider class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+       /**
+        * MediaWiki media search provider.
+        *
+        * @class
+        * @extends mw.widgets.MediaResourceProvider
+        *
+        * @constructor
+        * @param {string} apiurl The API url
+        * @param {Object} [config] Configuration options
+        */
+       mw.widgets.MediaSearchProvider = function MwWidgetsMediaSearchProvider( apiurl, config ) {
+               config = config || {};
+
+               config.staticParams = $.extend( {
+                       generator: 'search',
+                       gsrnamespace: mw.config.get( 'wgNamespaceIds' ).file
+               }, config.staticParams );
+
+               // Parent constructor
+               mw.widgets.MediaSearchProvider.super.call( this, apiurl, config );
+       };
+
+       /* Inheritance */
+       OO.inheritClass( mw.widgets.MediaSearchProvider, mw.widgets.MediaResourceProvider );
+
+       /* Methods */
+
+       /**
+        * @inheritdoc
+        */
+       mw.widgets.MediaSearchProvider.prototype.getContinueData = function ( howMany ) {
+               return {
+                       gsroffset: this.getOffset(),
+                       gsrlimit: howMany || this.getDefaultFetchLimit()
+               };
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.widgets.MediaSearchProvider.prototype.setContinue = function ( continueData ) {
+               // Update the offset for next time
+               this.setOffset( continueData.gsroffset );
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.widgets.MediaSearchProvider.prototype.sort = function ( results ) {
+               return results.sort( function ( a, b ) {
+                       return a.index - b.index;
+               } );
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.widgets.MediaSearchProvider.prototype.isValid = function () {
+               return this.getUserParams().gsrsearch && mw.widgets.MediaSearchProvider.super.prototype.isValid.call( this );
+       };
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js
new file mode 100644 (file)
index 0000000..7ee98bb
--- /dev/null
@@ -0,0 +1,82 @@
+/*!
+ * MediaWiki Widgets - MediaSearchQueue class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+       /**
+        * MediaWiki media resource queue.
+        *
+        * @class
+        * @extends mw.widgets.MediaResourceQueue
+        *
+        * @constructor
+        * @param {Object} [config] Configuration options
+        * @cfg {number} maxHeight The maximum height of the media, used in the
+        *  search call to the API.
+        */
+       mw.widgets.MediaSearchQueue = function MwWidgetsMediaSearchQueue( config ) {
+               config = config || {};
+
+               // Parent constructor
+               mw.widgets.MediaSearchQueue.super.call( this, config );
+
+               this.searchQuery = '';
+       };
+
+       /* Inheritance */
+       OO.inheritClass( mw.widgets.MediaSearchQueue, mw.widgets.MediaResourceQueue );
+
+       /**
+        * Override parent method to set up the providers according to
+        * the file repos
+        *
+        * @return {jQuery.Promise} Promise that resolves when the resources are set up
+        */
+       mw.widgets.MediaSearchQueue.prototype.setup = function () {
+               var i, len,
+                       queue = this;
+
+               return this.getFileRepos().then( function ( sources ) {
+                       if ( queue.providers.length === 0 ) {
+                               // Set up the providers
+                               for ( i = 0, len = sources.length; i < len; i++ ) {
+                                       queue.providers.push( new mw.widgets.MediaSearchProvider(
+                                               sources[ i ].apiurl,
+                                               {
+                                                       name: sources[ i ].name,
+                                                       local: sources[ i ].local,
+                                                       scriptDirUrl: sources[ i ].scriptDirUrl,
+                                                       userParams: {
+                                                               gsrsearch: queue.getSearchQuery()
+                                                       },
+                                                       staticParams: {
+                                                               iiurlheight: queue.getMaxHeight()
+                                                       }
+                                               } )
+                                       );
+                               }
+                       }
+               } );
+       };
+
+       /**
+        * Set the search query
+        *
+        * @param {string} searchQuery API search query
+        */
+       mw.widgets.MediaSearchQueue.prototype.setSearchQuery = function ( searchQuery ) {
+               this.setParams( { gsrsearch: searchQuery } );
+       };
+
+       /**
+        * Get the search query
+        *
+        * @return {string} API search query
+        */
+       mw.widgets.MediaSearchQueue.prototype.getSearchQuery = function () {
+               return this.getParams().gsrsearch;
+       };
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css
new file mode 100644 (file)
index 0000000..3d28ef8
--- /dev/null
@@ -0,0 +1,10 @@
+/*!
+ * MediaWiki Widgets - MediaSearchWidget styles.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.mw-widget-mediaSearchWidget .oo-ui-searchWidget-query .oo-ui-inputWidget {
+       max-width: none;
+}
diff --git a/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js b/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js
new file mode 100644 (file)
index 0000000..c6938e8
--- /dev/null
@@ -0,0 +1,462 @@
+/*!
+ * MediaWiki Widgets - MediaSearchWidget class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+       /**
+        * Creates an mw.widgets.MediaSearchWidget object.
+        *
+        * @class
+        * @extends OO.ui.SearchWidget
+        *
+        * @constructor
+        * @param {Object} [config] Configuration options
+        * @param {number} [size] Vertical size of thumbnails
+        */
+       mw.widgets.MediaSearchWidget = function MwWidgetsMediaSearchWidget( config ) {
+               // Configuration initialization
+               config = $.extend( {
+                       placeholder: mw.msg( 'mw-widgets-mediasearch-input-placeholder' )
+               }, config );
+
+               // Parent constructor
+               mw.widgets.MediaSearchWidget.super.call( this, config );
+
+               // Properties
+               this.providers = {};
+               this.lastQueryValue = '';
+               this.searchQueue = new mw.widgets.MediaSearchQueue( {
+                       limit: this.constructor.static.limit,
+                       threshold: this.constructor.static.threshold
+               } );
+
+               this.queryTimeout = null;
+               this.itemCache = {};
+               this.promises = [];
+               this.lang = config.lang || 'en';
+               this.$panels = config.$panels;
+
+               this.externalLinkUrlProtocolsRegExp = new RegExp(
+                       '^(' + mw.config.get( 'wgUrlProtocols' ) + ')',
+                       'i'
+               );
+
+               // Masonry fit properties
+               this.rows = [];
+               this.rowHeight = config.rowHeight || 200;
+               this.layoutQueue = [];
+               this.numItems = 0;
+               this.currentItemCache = [];
+
+               this.resultsSize = {};
+
+               this.selected = null;
+
+               this.noItemsMessage = new OO.ui.LabelWidget( {
+                       label: mw.msg( 'mw-widgets-mediasearch-noresults' ),
+                       classes: [ 'mw-widget-mediaSearchWidget-noresults' ]
+               } );
+               this.noItemsMessage.toggle( false );
+
+               // Events
+               this.$results.on( 'scroll', this.onResultsScroll.bind( this ) );
+               this.$query.append( this.noItemsMessage.$element );
+               this.results.connect( this, {
+                       add: 'onResultsAdd',
+                       remove: 'onResultsRemove'
+               } );
+
+               this.resizeHandler = OO.ui.debounce( this.afterResultsResize.bind( this ), 500 );
+
+               // Initialization
+               this.$element.addClass( 'mw-widget-mediaSearchWidget' );
+       };
+
+       /* Inheritance */
+
+       OO.inheritClass( mw.widgets.MediaSearchWidget, OO.ui.SearchWidget );
+
+       /* Static properties */
+
+       mw.widgets.MediaSearchWidget.static.limit = 10;
+
+       mw.widgets.MediaSearchWidget.static.threshold = 5;
+
+       /* Methods */
+
+       /**
+        * Respond to window resize and check if the result display should
+        * be updated.
+        */
+       mw.widgets.MediaSearchWidget.prototype.afterResultsResize = function () {
+               var items = this.currentItemCache;
+
+               if (
+                       items.length > 0 &&
+                       (
+                               this.resultsSize.width !== this.$results.width() ||
+                               this.resultsSize.height !== this.$results.height()
+                       )
+               ) {
+                       this.resetRows();
+                       this.itemCache = {};
+                       this.processQueueResults( items );
+                       if ( this.results.getItems().length > 0 ) {
+                               this.lazyLoadResults();
+                       }
+
+                       // Cache the size
+                       this.resultsSize = {
+                               width: this.$results.width(),
+                               height: this.$results.height()
+                       };
+               }
+       };
+
+       /**
+        * Teardown the widget; disconnect the window resize event.
+        */
+       mw.widgets.MediaSearchWidget.prototype.teardown = function () {
+               $( window ).off( 'resize', this.resizeHandler );
+       };
+
+       /**
+        * Setup the widget; activate the resize event.
+        */
+       mw.widgets.MediaSearchWidget.prototype.setup = function () {
+               $( window ).on( 'resize', this.resizeHandler );
+       };
+
+       /**
+        * Query all sources for media.
+        *
+        * @method
+        */
+       mw.widgets.MediaSearchWidget.prototype.queryMediaQueue = function () {
+               var search = this,
+                       value = this.getQueryValue();
+
+               if ( value === '' ) {
+                       return;
+               }
+
+               this.query.pushPending();
+               search.noItemsMessage.toggle( false );
+
+               this.searchQueue.setSearchQuery( value );
+               this.searchQueue.get( this.constructor.static.limit )
+                       .then( function ( items ) {
+                               if ( items.length > 0 ) {
+                                       search.processQueueResults( items );
+                                       search.currentItemCache = search.currentItemCache.concat( items );
+                               }
+
+                               search.query.popPending();
+                               search.noItemsMessage.toggle( search.results.getItems().length === 0 );
+                               if ( search.results.getItems().length > 0 ) {
+                                       search.lazyLoadResults();
+                               }
+
+                       } );
+       };
+
+       /**
+        * Process the media queue giving more items
+        *
+        * @method
+        * @param {Object[]} items Given items by the media queue
+        */
+       mw.widgets.MediaSearchWidget.prototype.processQueueResults = function ( items ) {
+               var i, len, title,
+                       resultWidgets = [],
+                       inputSearchQuery = this.getQueryValue(),
+                       queueSearchQuery = this.searchQueue.getSearchQuery();
+
+               if ( inputSearchQuery === '' || queueSearchQuery !== inputSearchQuery ) {
+                       return;
+               }
+
+               for ( i = 0, len = items.length; i < len; i++ ) {
+                       title = new mw.Title( items[ i ].title ).getMainText();
+                       // Do not insert duplicates
+                       if ( !Object.prototype.hasOwnProperty.call( this.itemCache, title ) ) {
+                               this.itemCache[ title ] = true;
+                               resultWidgets.push(
+                                       new mw.widgets.MediaResultWidget( {
+                                               data: items[ i ],
+                                               rowHeight: this.rowHeight,
+                                               maxWidth: this.results.$element.width() / 3,
+                                               minWidth: 30,
+                                               rowWidth: this.results.$element.width()
+                                       } )
+                               );
+                       }
+               }
+               this.results.addItems( resultWidgets );
+
+       };
+
+       /**
+        * Get the sanitized query value from the input
+        *
+        * @return {string} Query value
+        */
+       mw.widgets.MediaSearchWidget.prototype.getQueryValue = function () {
+               var queryValue = this.query.getValue().trim();
+
+               if ( queryValue.match( this.externalLinkUrlProtocolsRegExp ) ) {
+                       queryValue = queryValue.match( /.+\/([^\/]+)/ )[ 1 ];
+               }
+               return queryValue;
+       };
+
+       /**
+        * Handle search value change
+        *
+        * @param {string} value New value
+        */
+       mw.widgets.MediaSearchWidget.prototype.onQueryChange = function () {
+               // Get the sanitized query value
+               var queryValue = this.getQueryValue();
+
+               if ( queryValue === this.lastQueryValue ) {
+                       return;
+               }
+
+               // Parent method
+               mw.widgets.MediaSearchWidget.super.prototype.onQueryChange.apply( this, arguments );
+
+               // Reset
+               this.itemCache = {};
+               this.currentItemCache = [];
+               this.resetRows();
+
+               // Empty the results queue
+               this.layoutQueue = [];
+
+               // Change resource queue query
+               this.searchQueue.setSearchQuery( queryValue );
+               this.lastQueryValue = queryValue;
+
+               // Queue
+               clearTimeout( this.queryTimeout );
+               this.queryTimeout = setTimeout( this.queryMediaQueue.bind( this ), 350 );
+       };
+
+       /**
+        * Handle results scroll events.
+        *
+        * @param {jQuery.Event} e Scroll event
+        */
+       mw.widgets.MediaSearchWidget.prototype.onResultsScroll = function () {
+               var position = this.$results.scrollTop() + this.$results.outerHeight(),
+                       threshold = this.results.$element.outerHeight() - this.rowHeight * 3;
+
+               // Check if we need to ask for more results
+               if ( !this.query.isPending() && position > threshold ) {
+                       this.queryMediaQueue();
+               }
+
+               this.lazyLoadResults();
+       };
+
+       /**
+        * Lazy-load the images that are visible.
+        */
+       mw.widgets.MediaSearchWidget.prototype.lazyLoadResults = function () {
+               var i, elementTop,
+                       items = this.results.getItems(),
+                       resultsScrollTop = this.$results.scrollTop(),
+                       position = resultsScrollTop + this.$results.outerHeight();
+
+               // Lazy-load results
+               for ( i = 0; i < items.length; i++ ) {
+                       elementTop = items[ i ].$element.position().top;
+                       if ( elementTop <= position && !items[ i ].hasSrc() ) {
+                               // Load the image
+                               items[ i ].lazyLoad();
+                       }
+               }
+       };
+
+       /**
+        * Reset all the rows; destroy the jQuery elements and reset
+        * the rows array.
+        */
+       mw.widgets.MediaSearchWidget.prototype.resetRows = function () {
+               var i, len;
+
+               for ( i = 0, len = this.rows.length; i < len; i++ ) {
+                       this.rows[ i ].$element.remove();
+               }
+
+               this.rows = [];
+               this.itemCache = {};
+       };
+
+       /**
+        * Find an available row at the end. Either we will need to create a new
+        * row or use the last available row if it isn't full.
+        *
+        * @return {number} Row index
+        */
+       mw.widgets.MediaSearchWidget.prototype.getAvailableRow = function () {
+               var row;
+
+               if ( this.rows.length === 0 ) {
+                       row = 0;
+               } else {
+                       row = this.rows.length - 1;
+               }
+
+               if ( !this.rows[ row ] ) {
+                       // Create new row
+                       this.rows[ row ] = {
+                               isFull: false,
+                               width: 0,
+                               items: [],
+                               $element: $( '<div>' )
+                                       .addClass( 'mw-widget-mediaResultWidget-row' )
+                                       .css( {
+                                               overflow: 'hidden'
+                                       } )
+                                       .data( 'row', row )
+                                       .attr( 'data-full', false )
+                       };
+                       // Append to results
+                       this.results.$element.append( this.rows[ row ].$element );
+               } else if ( this.rows[ row ].isFull ) {
+                       row++;
+                       // Create new row
+                       this.rows[ row ] = {
+                               isFull: false,
+                               width: 0,
+                               items: [],
+                               $element: $( '<div>' )
+                                       .addClass( 'mw-widget-mediaResultWidget-row' )
+                                       .css( {
+                                               overflow: 'hidden'
+                                       } )
+                                       .data( 'row', row )
+                                       .attr( 'data-full', false )
+                       };
+                       // Append to results
+                       this.results.$element.append( this.rows[ row ].$element );
+               }
+
+               return row;
+       };
+
+       /**
+        * Respond to add results event in the results widget.
+        * Override the way SelectWidget and GroupElement append the items
+        * into the group so we can append them in groups of rows.
+        *
+        * @param {mw.widgets.MediaResultWidget[]} items An array of item elements
+        */
+       mw.widgets.MediaSearchWidget.prototype.onResultsAdd = function ( items ) {
+               var search = this;
+
+               // Add method to a queue; this queue will only run when the widget
+               // is visible
+               this.layoutQueue.push( function () {
+                       var i, j, ilen, jlen, itemWidth, row, effectiveWidth,
+                               resizeFactor,
+                               maxRowWidth = search.results.$element.width() - 15;
+
+                       // Go over the added items
+                       row = search.getAvailableRow();
+                       for ( i = 0, ilen = items.length; i < ilen; i++ ) {
+                               itemWidth = items[ i ].$element.outerWidth( true );
+
+                               // Add items to row until it is full
+                               if ( search.rows[ row ].width + itemWidth >= maxRowWidth ) {
+                                       // Mark this row as full
+                                       search.rows[ row ].isFull = true;
+                                       search.rows[ row ].$element.attr( 'data-full', true );
+
+                                       // Find the resize factor
+                                       effectiveWidth = search.rows[ row ].width;
+                                       resizeFactor = maxRowWidth / effectiveWidth;
+
+                                       search.rows[ row ].$element.attr( 'data-effectiveWidth', effectiveWidth );
+                                       search.rows[ row ].$element.attr( 'data-resizeFactor', resizeFactor );
+                                       search.rows[ row ].$element.attr( 'data-row', row );
+
+                                       // Resize all images in the row to fit the width
+                                       for ( j = 0, jlen = search.rows[ row ].items.length; j < jlen; j++ ) {
+                                               search.rows[ row ].items[ j ].resizeThumb( resizeFactor );
+                                       }
+
+                                       // find another row
+                                       row = search.getAvailableRow();
+                               }
+
+                               // Add the cumulative
+                               search.rows[ row ].width += itemWidth;
+
+                               // Store reference to the item and to the row
+                               search.rows[ row ].items.push( items[ i ] );
+                               items[ i ].setRow( row );
+
+                               // Append the item
+                               search.rows[ row ].$element.append( items[ i ].$element );
+                       }
+
+                       // If we have less than 4 rows, call for more images
+                       if ( search.rows.length < 4 ) {
+                               search.queryMediaQueue();
+                       }
+               } );
+               this.runLayoutQueue();
+       };
+
+       /**
+        * Run layout methods from the queue only if the element is visible.
+        */
+       mw.widgets.MediaSearchWidget.prototype.runLayoutQueue = function () {
+               var i, len;
+
+               if ( this.$element.is( ':visible' ) ) {
+                       for ( i = 0, len = this.layoutQueue.length; i < len; i++ ) {
+                               this.layoutQueue.pop()();
+                       }
+               }
+       };
+
+       /**
+        * Respond to removing results event in the results widget.
+        * Clear the relevant rows.
+        *
+        * @param {OO.ui.OptionWidget[]} items Removed items
+        */
+       mw.widgets.MediaSearchWidget.prototype.onResultsRemove = function ( items ) {
+               if ( items.length > 0 ) {
+                       // In the case of the media search widget, if any items are removed
+                       // all are removed (new search)
+                       this.resetRows();
+                       this.currentItemCache = [];
+               }
+       };
+
+       /**
+        * Set language for the search results.
+        *
+        * @param {string} lang Language
+        */
+       mw.widgets.MediaSearchWidget.prototype.setLang = function ( lang ) {
+               this.lang = lang;
+       };
+
+       /**
+        * Get language for the search results.
+        *
+        * @return {string} lang Language
+        */
+       mw.widgets.MediaSearchWidget.prototype.getLang = function () {
+               return this.lang;
+       };
+}( jQuery, mediaWiki ) );
index 3daa70a..57a3d9c 100644 (file)
@@ -4,7 +4,7 @@
  * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
  */
-/*global moment */
+/* global moment */
 ( function ( $, mw ) {
 
        /**
                selected = moment( this.getDate(), this.getDateFormat() );
 
                switch ( this.displayLayer ) {
-               case 'month':
-                       this.labelButton.setLabel( this.moment.format( 'MMMM YYYY' ) );
-                       this.upButton.toggle( true );
-
-                       // First week displayed is the first week spanned by the month, unless it begins on Monday, in
-                       // which case first week displayed is the previous week. This makes the calendar "balanced"
-                       // and also neatly handles 28-day February sometimes spanning only 4 weeks.
-                       currentDay = moment( this.moment ).startOf( 'month' ).subtract( 1, 'day' ).startOf( 'week' );
-
-                       // Day-of-week labels. Localisation-independent: works with weeks starting on Saturday, Sunday
-                       // or Monday.
-                       for ( i = 0; i < 7; i++ ) {
-                               items.push(
-                                       $( '<div>' )
-                                               .addClass( 'mw-widget-calendarWidget-day-heading' )
-                                               .text( currentDay.format( 'dd' ) )
-                               );
-                               currentDay.add( 1, 'day' );
-                       }
-                       currentDay.subtract( 7, 'days' );
-
-                       // Actual calendar month. Always displays 6 weeks, for consistency (months can span 4 to 6
-                       // weeks).
-                       for ( i = 0; i < 42; i++ ) {
-                               items.push(
-                                       $( '<div>' )
-                                               .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-day' )
-                                               .toggleClass( 'mw-widget-calendarWidget-day-additional', !currentDay.isSame( this.moment, 'month' ) )
-                                               .toggleClass( 'mw-widget-calendarWidget-day-today', currentDay.isSame( today, 'day' ) )
-                                               .toggleClass( 'mw-widget-calendarWidget-item-selected', currentDay.isSame( selected, 'day' ) )
-                                               .text( currentDay.format( 'D' ) )
-                                               .data( 'date', currentDay.date() )
-                                               .data( 'month', currentDay.month() )
-                                               .data( 'year', currentDay.year() )
-                               );
-                               currentDay.add( 1, 'day' );
-                       }
-                       break;
-
-               case 'year':
-                       this.labelButton.setLabel( this.moment.format( 'YYYY' ) );
-                       this.upButton.toggle( true );
-
-                       currentMonth = moment( this.moment ).startOf( 'year' );
-                       for ( i = 0; i < 12; i++ ) {
-                               items.push(
-                                       $( '<div>' )
-                                               .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-month' )
-                                               .toggleClass( 'mw-widget-calendarWidget-item-selected', currentMonth.isSame( selected, 'month' ) )
-                                               .text( currentMonth.format( 'MMMM' ) )
-                                               .data( 'month', currentMonth.month() )
-                               );
-                               currentMonth.add( 1, 'month' );
-                       }
-                       // Shuffle the array to display months in columns rather than rows.
-                       items = [
-                               items[ 0 ], items[ 6 ],      //  | January  | July      |
-                               items[ 1 ], items[ 7 ],      //  | February | August    |
-                               items[ 2 ], items[ 8 ],      //  | March    | September |
-                               items[ 3 ], items[ 9 ],      //  | April    | October   |
-                               items[ 4 ], items[ 10 ],     //  | May      | November  |
-                               items[ 5 ], items[ 11 ]      //  | June     | December  |
-                       ];
-                       break;
-
-               case 'duodecade':
-                       this.labelButton.setLabel( null );
-                       this.upButton.toggle( false );
-
-                       currentYear = moment( { year: Math.floor( this.moment.year() / 20 ) * 20 } );
-                       for ( i = 0; i < 20; i++ ) {
-                               items.push(
-                                       $( '<div>' )
-                                               .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-year' )
-                                               .toggleClass( 'mw-widget-calendarWidget-item-selected', currentYear.isSame( selected, 'year' ) )
-                                               .text( currentYear.format( 'YYYY' ) )
-                                               .data( 'year', currentYear.year() )
-                               );
-                               currentYear.add( 1, 'year' );
-                       }
-                       break;
+                       case 'month':
+                               this.labelButton.setLabel( this.moment.format( 'MMMM YYYY' ) );
+                               this.upButton.toggle( true );
+
+                               // First week displayed is the first week spanned by the month, unless it begins on Monday, in
+                               // which case first week displayed is the previous week. This makes the calendar "balanced"
+                               // and also neatly handles 28-day February sometimes spanning only 4 weeks.
+                               currentDay = moment( this.moment ).startOf( 'month' ).subtract( 1, 'day' ).startOf( 'week' );
+
+                               // Day-of-week labels. Localisation-independent: works with weeks starting on Saturday, Sunday
+                               // or Monday.
+                               for ( i = 0; i < 7; i++ ) {
+                                       items.push(
+                                               $( '<div>' )
+                                                       .addClass( 'mw-widget-calendarWidget-day-heading' )
+                                                       .text( currentDay.format( 'dd' ) )
+                                       );
+                                       currentDay.add( 1, 'day' );
+                               }
+                               currentDay.subtract( 7, 'days' );
+
+                               // Actual calendar month. Always displays 6 weeks, for consistency (months can span 4 to 6
+                               // weeks).
+                               for ( i = 0; i < 42; i++ ) {
+                                       items.push(
+                                               $( '<div>' )
+                                                       .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-day' )
+                                                       .toggleClass( 'mw-widget-calendarWidget-day-additional', !currentDay.isSame( this.moment, 'month' ) )
+                                                       .toggleClass( 'mw-widget-calendarWidget-day-today', currentDay.isSame( today, 'day' ) )
+                                                       .toggleClass( 'mw-widget-calendarWidget-item-selected', currentDay.isSame( selected, 'day' ) )
+                                                       .text( currentDay.format( 'D' ) )
+                                                       .data( 'date', currentDay.date() )
+                                                       .data( 'month', currentDay.month() )
+                                                       .data( 'year', currentDay.year() )
+                                       );
+                                       currentDay.add( 1, 'day' );
+                               }
+                               break;
+
+                       case 'year':
+                               this.labelButton.setLabel( this.moment.format( 'YYYY' ) );
+                               this.upButton.toggle( true );
+
+                               currentMonth = moment( this.moment ).startOf( 'year' );
+                               for ( i = 0; i < 12; i++ ) {
+                                       items.push(
+                                               $( '<div>' )
+                                                       .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-month' )
+                                                       .toggleClass( 'mw-widget-calendarWidget-item-selected', currentMonth.isSame( selected, 'month' ) )
+                                                       .text( currentMonth.format( 'MMMM' ) )
+                                                       .data( 'month', currentMonth.month() )
+                                       );
+                                       currentMonth.add( 1, 'month' );
+                               }
+                               // Shuffle the array to display months in columns rather than rows.
+                               items = [
+                                       items[ 0 ], items[ 6 ],      //  | January  | July      |
+                                       items[ 1 ], items[ 7 ],      //  | February | August    |
+                                       items[ 2 ], items[ 8 ],      //  | March    | September |
+                                       items[ 3 ], items[ 9 ],      //  | April    | October   |
+                                       items[ 4 ], items[ 10 ],     //  | May      | November  |
+                                       items[ 5 ], items[ 11 ]      //  | June     | December  |
+                               ];
+                               break;
+
+                       case 'duodecade':
+                               this.labelButton.setLabel( null );
+                               this.upButton.toggle( false );
+
+                               currentYear = moment( { year: Math.floor( this.moment.year() / 20 ) * 20 } );
+                               for ( i = 0; i < 20; i++ ) {
+                                       items.push(
+                                               $( '<div>' )
+                                                       .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-year' )
+                                                       .toggleClass( 'mw-widget-calendarWidget-item-selected', currentYear.isSame( selected, 'year' ) )
+                                                       .text( currentYear.format( 'YYYY' ) )
+                                                       .data( 'year', currentYear.year() )
+                                       );
+                                       currentYear.add( 1, 'year' );
+                               }
+                               break;
                }
 
                this.$body.append.apply( this.$body, items );
         */
        mw.widgets.CalendarWidget.prototype.onPrevButtonClick = function () {
                switch ( this.displayLayer ) {
-               case 'month':
-                       this.moment.subtract( 1, 'month' );
-                       break;
-               case 'year':
-                       this.moment.subtract( 1, 'year' );
-                       break;
-               case 'duodecade':
-                       this.moment.subtract( 20, 'years' );
-                       break;
+                       case 'month':
+                               this.moment.subtract( 1, 'month' );
+                               break;
+                       case 'year':
+                               this.moment.subtract( 1, 'year' );
+                               break;
+                       case 'duodecade':
+                               this.moment.subtract( 20, 'years' );
+                               break;
                }
                this.updateUI( 'previous' );
        };
         */
        mw.widgets.CalendarWidget.prototype.onNextButtonClick = function () {
                switch ( this.displayLayer ) {
-               case 'month':
-                       this.moment.add( 1, 'month' );
-                       break;
-               case 'year':
-                       this.moment.add( 1, 'year' );
-                       break;
-               case 'duodecade':
-                       this.moment.add( 20, 'years' );
-                       break;
+                       case 'month':
+                               this.moment.add( 1, 'month' );
+                               break;
+                       case 'year':
+                               this.moment.add( 1, 'year' );
+                               break;
+                       case 'duodecade':
+                               this.moment.add( 20, 'years' );
+                               break;
                }
                this.updateUI( 'next' );
        };
         * what gets clicked.
         *
         * @private
+        * @param {jQuery.Event} e Click event
         */
        mw.widgets.CalendarWidget.prototype.onBodyClick = function ( e ) {
                var
         *
         * @private
         * @param {jQuery.Event} e Mouse click event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.CalendarWidget.prototype.onClick = function ( e ) {
                if ( !this.isDisabled() && e.which === 1 ) {
         *
         * @private
         * @param {jQuery.Event} e Key down event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.CalendarWidget.prototype.onKeyDown = function ( e ) {
                var
-                       /*jshint -W024*/
                        dir = OO.ui.Element.static.getDir( this.$element ),
-                       /*jshint +W024*/
                        nextDirectionKey = dir === 'ltr' ? OO.ui.Keys.RIGHT : OO.ui.Keys.LEFT,
                        prevDirectionKey = dir === 'ltr' ? OO.ui.Keys.LEFT : OO.ui.Keys.RIGHT,
                        changed = true;
 
                if ( !this.isDisabled() ) {
                        switch ( e.which ) {
-                       case prevDirectionKey:
-                               this.moment.subtract( 1, this.precision === 'month' ? 'month' : 'day' );
-                               break;
-                       case nextDirectionKey:
-                               this.moment.add( 1, this.precision === 'month' ? 'month' : 'day' );
-                               break;
-                       case OO.ui.Keys.UP:
-                               this.moment.subtract( 1, this.precision === 'month' ? 'month' : 'week' );
-                               break;
-                       case OO.ui.Keys.DOWN:
-                               this.moment.add( 1, this.precision === 'month' ? 'month' : 'week' );
-                               break;
-                       case OO.ui.Keys.PAGEUP:
-                               this.moment.subtract( 1, this.precision === 'month' ? 'year' : 'month' );
-                               break;
-                       case OO.ui.Keys.PAGEDOWN:
-                               this.moment.add( 1, this.precision === 'month' ? 'year' : 'month' );
-                               break;
-                       default:
-                               changed = false;
-                               break;
+                               case prevDirectionKey:
+                                       this.moment.subtract( 1, this.precision === 'month' ? 'month' : 'day' );
+                                       break;
+                               case nextDirectionKey:
+                                       this.moment.add( 1, this.precision === 'month' ? 'month' : 'day' );
+                                       break;
+                               case OO.ui.Keys.UP:
+                                       this.moment.subtract( 1, this.precision === 'month' ? 'month' : 'week' );
+                                       break;
+                               case OO.ui.Keys.DOWN:
+                                       this.moment.add( 1, this.precision === 'month' ? 'month' : 'week' );
+                                       break;
+                               case OO.ui.Keys.PAGEUP:
+                                       this.moment.subtract( 1, this.precision === 'month' ? 'year' : 'month' );
+                                       break;
+                               case OO.ui.Keys.PAGEDOWN:
+                                       this.moment.add( 1, this.precision === 'month' ? 'year' : 'month' );
+                                       break;
+                               default:
+                                       changed = false;
+                                       break;
                        }
 
                        if ( changed ) {
index 4d86cfd..488d9e0 100644 (file)
@@ -94,7 +94,8 @@
         * @extends mw.Title
         *
         * @constructor
-        * @inheritdoc
+        * @param {string} title
+        * @param {number} [namespace]
         */
        function ForeignTitle( title, namespace ) {
                // We only need to handle categories here... but we don't know the target language.
        };
 
        /**
-        * @class mw.widgets.CategoryCapsuleItemWidget
-        *
         * Category selector capsule item widget. Extends OO.ui.CapsuleItemWidget with the ability to link
         * to the given page, and to show its existence status (i.e., whether it is a redlink).
         *
+        * @class mw.widgets.CategoryCapsuleItemWidget
         * @uses mw.Api
         * @extends OO.ui.CapsuleItemWidget
         *
                this.$label.replaceWith( this.$link );
                this.setLabelElement( this.$link );
 
-               /*jshint -W024*/
                if ( !this.constructor.static.pageExistenceCaches[ this.apiUrl ] ) {
                        this.constructor.static.pageExistenceCaches[ this.apiUrl ] =
                                new PageExistenceCache( new mw.ForeignApi( this.apiUrl ) );
                        .done( function ( exists ) {
                                widget.setMissing( !exists );
                        } );
-               /*jshint +W024*/
        };
 
        /* Setup */
 
        /* Static Properties */
 
-       /*jshint -W024*/
        /**
         * Map of API URLs to PageExistenceCache objects.
         *
        mw.widgets.CategoryCapsuleItemWidget.static.pageExistenceCaches = {
                '': new PageExistenceCache()
        };
-       /*jshint +W024*/
 
        /* Methods */
 
index 267eebb..422c048 100644 (file)
@@ -52,6 +52,7 @@
                        menu: {
                                filterFromInput: false
                        },
+                       placeholder: mw.msg( 'mw-widgets-categoryselector-add-category-placeholder' ),
                        // This allows the user to both select non-existent categories, and prevents the selector from
                        // being wiped from #onMenuItemsChange when we change the available options in the dropdown
                        allowArbitrary: true
                                        prop: 'categories',
                                        cllimit: this.limit,
                                        titles: 'Category:' + input
-                               } ).done( function ( res )  {
+                               } ).done( function ( res ) {
                                        var categories = [];
 
                                        $.each( res.query.pages, function ( index, page ) {
index ddae9b1..8f48ec3 100644 (file)
@@ -51,7 +51,6 @@
        OO.inheritClass( mw.widgets.ComplexTitleInputWidget, OO.ui.Widget );
 
        /* Static Methods */
-       /*jshint -W024*/
 
        /**
         * @inheritdoc
@@ -85,8 +84,6 @@
                return state;
        };
 
-       /*jshint +W024*/
-
        /* Methods */
 
        /**
index ed251f2..7f5e608 100644 (file)
@@ -4,7 +4,7 @@
  * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
  */
-/*global moment */
+/* global moment */
 ( function ( $, mw ) {
 
        /**
@@ -87,6 +87,8 @@
         *     calendar uses relative positioning.
         */
        mw.widgets.DateInputWidget = function MWWDateInputWidget( config ) {
+               var placeholderDateFormat, mustBeAfter, mustBeBefore;
+
                // Config initialization
                config = $.extend( {
                        precision: 'day',
                        }
                }
 
-               var placeholderDateFormat, mustBeAfter, mustBeBefore;
                if ( config.placeholderDateFormat ) {
                        placeholderDateFormat = config.placeholderDateFormat;
                } else if ( config.inputFormat ) {
         * @return {string} Format string
         */
        mw.widgets.DateInputWidget.prototype.getDisplayFormat = function () {
+               var localeData, llll, lll, ll, format;
+
                if ( this.displayFormat !== undefined ) {
                        return this.displayFormat;
                }
                        // We try to construct it as 'llll - (lll - ll)' and hope for the best.
                        // This seems to work well for many languages (maybe even all?).
 
-                       var localeData = moment.localeData( moment.locale() ),
-                               llll = localeData.longDateFormat( 'llll' ),
-                               lll = localeData.longDateFormat( 'lll' ),
-                               ll = localeData.longDateFormat( 'll' ),
-                               format = llll.replace( lll.replace( ll, '' ), '' );
+                       localeData = moment.localeData( moment.locale() );
+                       llll = localeData.longDateFormat( 'llll' );
+                       lll = localeData.longDateFormat( 'lll' );
+                       ll = localeData.longDateFormat( 'll' );
+                       format = llll.replace( lll.replace( ll, '' ), '' );
 
                        return format;
                }
         *
         * @private
         * @param {jQuery.Event} e Mouse click event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.DateInputWidget.prototype.onClick = function ( e ) {
                if ( !this.isDisabled() && e.which === 1 ) {
         *
         * @private
         * @param {jQuery.Event} e Key press event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.DateInputWidget.prototype.onKeyPress = function ( e ) {
                if ( !this.isDisabled() &&
         *
         * @private
         * @param {jQuery.Event} e Key press event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.DateInputWidget.prototype.onCalendarKeyPress = function ( e ) {
                if ( !this.isDisabled() && e.which === OO.ui.Keys.ENTER ) {
         *
         * @private
         * @param {jQuery.Event} e Mouse click event
+        * @return {boolean} False to cancel the default event
         */
        mw.widgets.DateInputWidget.prototype.onCalendarClick = function ( e ) {
                if (
index c88395e..aa0c739 100644 (file)
@@ -36,6 +36,8 @@
 
        /**
         * @private
+        * @param {Object} [config] Configuration options
+        * @return {Object[]} Dropdown options
         */
        mw.widgets.NamespaceInputWidget.prototype.getNamespaceDropdownOptions = function ( config ) {
                var options,
index d816335..2ac75c5 100755 (executable)
@@ -13,6 +13,7 @@
         * @extends mw.widgets.TitleInputWidget
         *
         * @constructor
+        * @param {Object} [config] Configuration options
         * @cfg {boolean} [pushPending=true] Visually mark the input field as "pending", while
         *  requesting suggestions.
         * @cfg {boolean} [performSearchOnClick=true] If true, the script will start a search when-
@@ -77,7 +78,7 @@
         * @inheritdoc mw.widgets.TitleWidget
         */
        mw.widgets.SearchInputWidget.prototype.getSuggestionsPromise = function () {
-               var api = new mw.Api(),
+               var api = this.getApi(),
                        promise,
                        self = this;
 
index 101a606..a78ad82 100644 (file)
@@ -15,6 +15,7 @@
         * @mixins OO.ui.mixin.LookupElement
         *
         * @constructor
+        * @param {Object} [config] Configuration options
         * @cfg {boolean} [suggestions=true] Display search suggestions
         * @cfg {RegExp|Function|string} [validate] Perform title validation
         */
index 96f9549..5ba9481 100644 (file)
@@ -15,6 +15,7 @@
         * @mixins mw.widgets.TitleWidget
         *
         * @constructor
+        * @param {Object} [config] Configuration options
         */
        mw.widgets.TitleSearchWidget = function MwWidgetsTitleSearchWidget( config ) {
                config = config || {};
index 7ca19df..0e5e0c5 100644 (file)
@@ -6,16 +6,6 @@
  */
 ( function ( $, mw ) {
 
-       var interwikiPrefixesPromise = new mw.Api().get( {
-                       action: 'query',
-                       meta: 'siteinfo',
-                       siprop: 'interwikimap'
-               } ).then( function ( data ) {
-                       return $.map( data.query.interwikimap, function ( interwiki ) {
-                               return interwiki.prefix;
-                       } );
-               } );
-
        /**
         * Mixin for title widgets
         *
@@ -36,6 +26,7 @@
         * @cfg {boolean} [validateTitle=true] Whether the input must be a valid title (if set to true,
         *  the widget will marks itself red for invalid inputs, including an empty query).
         * @cfg {Object} [cache] Result cache which implements a 'set' method, taking keyed values as an argument
+        * @cfg {mw.Api} [api] API object to use, creates a default mw.Api instance if not specified
         */
        mw.widgets.TitleWidget = function MwWidgetsTitleWidget( config ) {
                // Config initialization
@@ -56,6 +47,7 @@
                this.excludeCurrentPage = !!config.excludeCurrentPage;
                this.validateTitle = config.validateTitle !== undefined ? config.validateTitle : true;
                this.cache = config.cache;
+               this.api = config.api || new mw.Api();
 
                // Initialization
                this.$element.addClass( 'mw-widget-titleWidget' );
 
        OO.initClass( mw.widgets.TitleWidget );
 
+       /* Static properties */
+
+       mw.widgets.TitleWidget.static.interwikiPrefixesPromiseCache = {};
+
        /* Methods */
 
        /**
                this.namespace = namespace;
        };
 
+       mw.widgets.TitleWidget.prototype.getInterwikiPrefixesPromise = function () {
+               var api = this.getApi(),
+                       cache = this.constructor.static.interwikiPrefixesPromiseCache,
+                       key = api.defaults.ajax.url;
+               if ( !cache.hasOwnProperty( key ) ) {
+                       cache[ key ] = api.get( {
+                               action: 'query',
+                               meta: 'siteinfo',
+                               siprop: 'interwikimap'
+                       } ).then( function ( data ) {
+                               return $.map( data.query.interwikimap, function ( interwiki ) {
+                                       return interwiki.prefix;
+                               } );
+                       } );
+               }
+               return cache[ key ];
+       };
+
        /**
         * Get a promise which resolves with an API repsonse for suggested
         * links for the current query.
         */
        mw.widgets.TitleWidget.prototype.getSuggestionsPromise = function () {
                var req,
+                       api = this.getApi(),
                        query = this.getQueryValue(),
                        widget = this,
                        promiseAbortObject = { abort: function () {
                        } };
 
                if ( mw.Title.newFromText( query ) ) {
-                       return interwikiPrefixesPromise.then( function ( interwikiPrefixes ) {
+                       return this.getInterwikiPrefixesPromise().then( function ( interwikiPrefixes ) {
                                var params,
                                        interwiki = query.substring( 0, query.indexOf( ':' ) );
                                if (
                                                params.prop.push( 'pageterms' );
                                                params.wbptterms = 'description';
                                        }
-                                       req = new mw.Api().get( params );
+                                       req = api.get( params );
                                        promiseAbortObject.abort = req.abort.bind( req ); // TODO ew
                                        return req.then( function ( ret ) {
                                                if ( ret.query === undefined ) {
-                                                       ret = new mw.Api().get( { action: 'query', titles: query } );
+                                                       ret = api.get( { action: 'query', titles: query } );
                                                        promiseAbortObject.abort = ret.abort.bind( ret );
                                                }
                                                return ret;
                }
        };
 
+       /**
+        * Get the API object for title requests
+        *
+        * @return {mw.Api} MediaWiki API
+        */
+       mw.widgets.TitleWidget.prototype.getApi = function () {
+               return this.api;
+       };
+
        /**
         * Get option widgets from the server response
         *
                        description = mw.msg( 'mw-widgets-titleinput-description-new-page' );
                }
                return {
-                       data: this.namespace !== null && this.relative
-                               ? mwTitle.getRelativeText( this.namespace )
-                               title,
+                       data: this.namespace !== null && this.relative ?
+                               mwTitle.getRelativeText( this.namespace ) :
+                               title,
                        url: mwTitle.getUrl(),
                        imageUrl: this.showImages ? data.imageUrl : null,
                        description: this.showDescriptions ? description : null,
index 164fd20..2b3a59f 100644 (file)
@@ -90,6 +90,7 @@
         *
         * @method
         * @param {Mixed} response Response from server
+        * @return {Object}
         */
        mw.widgets.UserInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
                return response.query.allusers || {};
index f51403f..1a3cdd5 100644 (file)
                this.apiUrl = String( url );
                this.anonymous = options && options.anonymous;
 
-               options = $.extend( /*deep=*/ true,
+               options = $.extend( /* deep=*/ true,
                        {
                                ajax: {
                                        url: this.apiUrl,
                                        xhrFields: {
-                                               withCredentials: this.anonymous ? false : true
+                                               withCredentials: !this.anonymous
                                        }
                                },
                                parameters: {
index b7579ff..0c08ca4 100644 (file)
                                } )
                                // AJAX success just means "200 OK" response, also check API error codes
                                .done( function ( result, textStatus, jqXHR ) {
+                                       var code;
                                        if ( result === undefined || result === null || result === '' ) {
                                                apiDeferred.reject( 'ok-but-empty',
                                                        'OK response but empty result (check HTTP headers?)',
                                                        jqXHR
                                                );
                                        } else if ( result.error ) {
-                                               var code = result.error.code === undefined ? 'unknown' : result.error.code;
+                                               code = result.error.code === undefined ? 'unknown' : result.error.code;
                                                apiDeferred.reject( code, result, result, jqXHR );
                                        } else {
                                                apiDeferred.resolve( result, jqXHR );
                                                        } );
                                                }
 
-                                               // Different error, pass on to let caller handle the error code
-                                               return this;
+                                               // Let caller handle the error code
+                                               return $.Deferred().rejectWith( this, arguments );
                                        }
                                );
                        } ).promise( { abort: function () {
                 *
                 * @since 1.22
                 * @param {string} type Token type
+                * @param {string} [assert]
                 * @return {jQuery.Promise} Received token.
                 */
                getToken: function ( type, assert ) {
                        promiseGroup = promises[ this.defaults.ajax.url ];
                        d = promiseGroup && promiseGroup[ type + 'Token' ];
 
+                       if ( !promiseGroup ) {
+                               promiseGroup = promises[ this.defaults.ajax.url ] = {};
+                       }
+
                        if ( !d ) {
                                apiPromise = this.get( {
                                        action: 'query',
                                                // Clear promise. Do not cache errors.
                                                delete promiseGroup[ type + 'Token' ];
 
-                                               // Pass on to allow the caller to handle the error
-                                               return this;
+                                               // Let caller handle the error code
+                                               return $.Deferred().rejectWith( this, arguments );
                                        } )
                                        // Attach abort handler
                                        .promise( { abort: apiPromise.abort } );
 
                                // Store deferred now so that we can use it again even if it isn't ready yet
-                               if ( !promiseGroup ) {
-                                       promiseGroup = promises[ this.defaults.ajax.url ] = {};
-                               }
                                promiseGroup[ type + 'Token' ] = d;
                        }
 
index bb3a913..21fad5e 100644 (file)
                        var basetimestamp, curtimestamp,
                                api = this;
                        return api.get( {
-                                       action: 'query',
-                                       prop: 'revisions',
-                                       rvprop: [ 'content', 'timestamp' ],
-                                       titles: String( title ),
-                                       formatversion: '2',
-                                       curtimestamp: true
-                               } )
+                               action: 'query',
+                               prop: 'revisions',
+                               rvprop: [ 'content', 'timestamp' ],
+                               titles: String( title ),
+                               formatversion: '2',
+                               curtimestamp: true
+                       } )
                                .then( function ( data ) {
                                        var page, revision;
                                        if ( !data.query || !data.query.pages ) {
index 418fd23..f38e88b 100644 (file)
                 * @return {string} return.done.data Parsed HTML of `wikitext`.
                 */
                parse: function ( content, additionalParams ) {
-                       var apiPromise, config = $.extend( {
-                               formatversion: 2,
-                               action: 'parse',
-                               contentmodel: 'wikitext'
-                       }, additionalParams );
+                       var apiPromise,
+                               config = $.extend( {
+                                       formatversion: 2,
+                                       action: 'parse',
+                                       contentmodel: 'wikitext'
+                               }, additionalParams );
 
                        if ( mw.Title && content instanceof mw.Title ) {
                                // Parse existing page
index 8169449..351ceb2 100644 (file)
@@ -34,7 +34,8 @@
         * @return {string}
         */
        function getFirstKey( obj ) {
-               for ( var key in obj ) {
+               var key;
+               for ( key in obj ) {
                        if ( obj.hasOwnProperty( key ) ) {
                                return key;
                        }
@@ -45,6 +46,7 @@
         * Get new iframe object for an upload.
         *
         * @private
+        * @param {string} id
         * @return {HTMLIframeElement}
         */
        function getNewIframe( id ) {
@@ -58,6 +60,8 @@
         * Shortcut for getting hidden inputs
         *
         * @private
+        * @param {string} name
+        * @param {string} val
         * @return {jQuery}
         */
        function getHiddenInput( name, val ) {
                 *
                 * @param {string} filekey
                 * @param {Object} data
+                * @return {jQuery.Promise}
                 */
                uploadFromStash: function ( filekey, data ) {
                        data.filekey = filekey;
index a2ff129..687b475 100644 (file)
@@ -12,6 +12,7 @@
         * @param {string|mw.Title|string[]|mw.Title[]} pages Full page name or instance of mw.Title, or an
         *  array thereof. If an array is passed, the return value passed to the promise will also be an
         *  array of appropriate objects.
+        * @param {Object} [addParams]
         * @return {jQuery.Promise}
         * @return {Function} return.done
         * @return {Object|Object[]} return.done.watch Object or list of objects (depends on the `pages`
index 0fbbcbe..5f60097 100644 (file)
@@ -4,8 +4,6 @@
  */
 ( function ( mw, $ ) {
 
-       /*jshint -W024*/
-
        /**
         * Helper function for hide-if to find the nearby form field.
         *
 
        mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
                $root.find( '.mw-htmlform-hide-if' ).each( function () {
-                       var v, i, fields, test, func, spec, self, modules, data,extraModules,
+                       var v, i, fields, test, func, spec, self, modules, data, extraModules,
                                $el = $( this );
 
                        modules = [];
index 37474f6..4f672fc 100644 (file)
@@ -10,6 +10,7 @@
         * Currently only supports passing 'hide-if' data.
         *
         * @ignore
+        * @param {Object} [config] Configuration options
         */
        mw.htmlform.Element = function ( config ) {
                // Configuration initialization
index 9ab2532..37c0554 100644 (file)
@@ -18,8 +18,8 @@
                } );
                $oldContainer.find( 'input' ).each( function () {
                        var $oldInput = $( this ),
-                       checked = $oldInput.prop( 'checked' ),
-                       $option = $( '<option>' );
+                               checked = $oldInput.prop( 'checked' ),
+                               $option = $( '<option>' );
                        $option.prop( 'value', $oldInput.prop( 'value' ) );
                        if ( checked ) {
                                $option.prop( 'selected', true );
@@ -98,7 +98,6 @@
                                                modules.push.apply( modules, extraModules );
                                        }
                                        mw.loader.using( modules, function () {
-                                               /*jshint -W024*/
                                                convertCheckboxesWidgetToCapsules( OO.ui.FieldLayout.static.infuse( $el ) );
                                        } );
                                } else {
index 844d74c..a5cf1d8 100644 (file)
@@ -1,4 +1,4 @@
-/*global moment */
+/* global moment, Uint8Array */
 ( function ( $, mw ) {
 
        /**
@@ -18,6 +18,9 @@
         * @class mw.ForeignStructuredUpload.BookletLayout
         * @uses mw.ForeignStructuredUpload
         * @extends mw.Upload.BookletLayout
+        *
+        * @constructor
+        * @param {Object} config Configuration options
         * @cfg {string} [target] Used to choose the target repository.
         *     If nothing is passed, the {@link mw.ForeignUpload#property-target default} is used.
         */
                                }
 
                                try {
-                                       metadata = mw.libs.jpegmeta( this.result, file.name );
+                                       metadata = mw.libs.jpegmeta( fileStr, file.name );
                                } catch ( e ) {
                                        metadata = null;
                                }
index 3a0a94b..0c572d4 100644 (file)
@@ -1,8 +1,5 @@
 ( function ( mw, $, OO ) {
        /**
-        * @class mw.ForeignStructuredUpload
-        * @extends mw.ForeignUpload
-        *
         * Used to represent an upload in progress on the frontend.
         *
         * This subclass will upload to a wiki using a structured metadata
         * **TODO: This currently only supports uploads under CC-BY-SA 4.0,
         * and should really have support for more licenses.**
         *
-        * @inheritdoc
+        * @class mw.ForeignStructuredUpload
+        * @extends mw.ForeignUpload
+        *
+        * @constructor
+        * @param {string} [target]
+        * @param {Object} [apiconfig]
         */
        function ForeignStructuredUpload( target, apiconfig ) {
                this.date = undefined;
index 781c1df..08fc01d 100644 (file)
@@ -1,8 +1,5 @@
 ( function ( mw, OO, $ ) {
        /**
-        * @class mw.ForeignUpload
-        * @extends mw.Upload
-        *
         * Used to represent an upload in progress on the frontend.
         *
         * Subclassed to upload to a foreign API, with no other goodies. Use
@@ -12,6 +9,9 @@
         * an object, we assume you want the default, and treat it as apiconfig
         * instead.
         *
+        * @class mw.ForeignUpload
+        * @extends mw.Upload
+        *
         * @constructor
         * @param {string} [target] Used to set up the target
         *     wiki. If not remote, this class behaves identically to mw.Upload (unless further subclassed)
 
        /**
         * Override from mw.Upload to make sure the API info is found and allowed
+        *
+        * @inheritdoc
         */
        ForeignUpload.prototype.upload = function () {
                var upload = this;
 
        /**
         * Override from mw.Upload to make sure the API info is found and allowed
+        *
+        * @inheritdoc
         */
        ForeignUpload.prototype.uploadToStash = function () {
                var upload = this;
index e468768..0e2af50 100644 (file)
@@ -3,17 +3,15 @@
  * @author Timo Tijhof, 2011-2013
  * @since 1.18
  */
-( function ( mw, $ ) {
-       /*jshint latedef:false */
 
+/* eslint-disable no-use-before-define */
+
+( function ( mw, $ ) {
        /**
         * Parse titles into an object structure. Note that when using the constructor
         * directly, passing invalid titles will result in an exception. Use #newFromText to use the
         * logic directly and get null for invalid titles which is easier to work with.
         *
-        * @class mw.Title
-        */
-       /**
         * Note that in the constructor and #newFromText method, `namespace` is the **default** namespace
         * only, and can be overridden by a namespace prefix in `title`. If you do not want this behavior,
         * use #makeTitle. Compare:
@@ -30,7 +28,8 @@
         *     mw.Title.newFromText( 'Template:Foo', NS_TEMPLATE ).getPrefixedText(); // => 'Template:Foo'
         *     mw.Title.makeTitle( NS_TEMPLATE, 'Template:Foo' ).getPrefixedText();   // => 'Template:Template:Foo'
         *
-        * @method constructor
+        * @class mw.Title
+        * @constructor
         * @param {string} title Title of the page. If no second argument given,
         *  this will be searched for a namespace
         * @param {number} [namespace=NS_MAIN] If given, will used as default namespace for the given title
                this.title = parsed.title;
                this.ext = parsed.ext;
                this.fragment = parsed.fragment;
-
-               return this;
        }
 
        /* Private members */
 
+       // eslint-disable-next-line vars-on-top
        var
+               namespaceIds = mw.config.get( 'wgNamespaceIds' ),
 
-       namespaceIds = mw.config.get( 'wgNamespaceIds' ),
+               /**
+                * @private
+                * @static
+                * @property NS_MAIN
+                */
+               NS_MAIN = namespaceIds[ '' ],
 
-       /**
-        * @private
-        * @static
-        * @property NS_MAIN
-        */
-       NS_MAIN = namespaceIds[ '' ],
+               /**
+                * @private
+                * @static
+                * @property NS_TALK
+                */
+               NS_TALK = namespaceIds.talk,
 
-       /**
-        * @private
-        * @static
-        * @property NS_TALK
-        */
-       NS_TALK = namespaceIds.talk,
+               /**
+                * @private
+                * @static
+                * @property NS_SPECIAL
+                */
+               NS_SPECIAL = namespaceIds.special,
 
-       /**
-        * @private
-        * @static
-        * @property NS_SPECIAL
-        */
-       NS_SPECIAL = namespaceIds.special,
+               /**
+                * @private
+                * @static
+                * @property NS_MEDIA
+                */
+               NS_MEDIA = namespaceIds.media,
 
-       /**
-        * @private
-        * @static
-        * @property NS_MEDIA
-        */
-       NS_MEDIA = namespaceIds.media,
+               /**
+                * @private
+                * @static
+                * @property NS_FILE
+                */
+               NS_FILE = namespaceIds.file,
 
-       /**
-        * @private
-        * @static
-        * @property NS_FILE
-        */
-       NS_FILE = namespaceIds.file,
+               /**
+                * @private
+                * @static
+                * @property FILENAME_MAX_BYTES
+                */
+               FILENAME_MAX_BYTES = 240,
 
-       /**
-        * @private
-        * @static
-        * @property FILENAME_MAX_BYTES
-        */
-       FILENAME_MAX_BYTES = 240,
+               /**
+                * @private
+                * @static
+                * @property TITLE_MAX_BYTES
+                */
+               TITLE_MAX_BYTES = 255,
 
-       /**
-        * @private
-        * @static
-        * @property TITLE_MAX_BYTES
-        */
-       TITLE_MAX_BYTES = 255,
+               /**
+                * Get the namespace id from a namespace name (either from the localized, canonical or alias
+                * name).
+                *
+                * Example: On a German wiki this would return 6 for any of 'File', 'Datei', 'Image' or
+                * even 'Bild'.
+                *
+                * @private
+                * @static
+                * @method getNsIdByName
+                * @param {string} ns Namespace name (case insensitive, leading/trailing space ignored)
+                * @return {number|boolean} Namespace id or boolean false
+                */
+               getNsIdByName = function ( ns ) {
+                       var id;
+
+                       // Don't cast non-strings to strings, because null or undefined should not result in
+                       // returning the id of a potential namespace called "Null:" (e.g. on null.example.org/wiki)
+                       // Also, toLowerCase throws exception on null/undefined, because it is a String method.
+                       if ( typeof ns !== 'string' ) {
+                               return false;
+                       }
+                       // TODO: Should just use local var namespaceIds here but it
+                       // breaks test which modify the config
+                       id = mw.config.get( 'wgNamespaceIds' )[ ns.toLowerCase() ];
+                       if ( id === undefined ) {
+                               return false;
+                       }
+                       return id;
+               },
 
-       /**
-        * Get the namespace id from a namespace name (either from the localized, canonical or alias
-        * name).
-        *
-        * Example: On a German wiki this would return 6 for any of 'File', 'Datei', 'Image' or
-        * even 'Bild'.
-        *
-        * @private
-        * @static
-        * @method getNsIdByName
-        * @param {string} ns Namespace name (case insensitive, leading/trailing space ignored)
-        * @return {number|boolean} Namespace id or boolean false
-        */
-       getNsIdByName = function ( ns ) {
-               var id;
-
-               // Don't cast non-strings to strings, because null or undefined should not result in
-               // returning the id of a potential namespace called "Null:" (e.g. on null.example.org/wiki)
-               // Also, toLowerCase throws exception on null/undefined, because it is a String method.
-               if ( typeof ns !== 'string' ) {
-                       return false;
-               }
-               // TODO: Should just use local var namespaceIds here but it
-               // breaks test which modify the config
-               id = mw.config.get( 'wgNamespaceIds' )[ ns.toLowerCase() ];
-               if ( id === undefined ) {
-                       return false;
-               }
-               return id;
-       },
+               /**
+                * @private
+                * @method getNamespacePrefix_
+                * @param {number} namespace
+                * @return {string}
+                */
+               getNamespacePrefix = function ( namespace ) {
+                       return namespace === NS_MAIN ?
+                               '' :
+                               ( mw.config.get( 'wgFormattedNamespaces' )[ namespace ].replace( / /g, '_' ) + ':' );
+               },
 
-       /**
-        * @private
-        * @method getNamespacePrefix_
-        * @param {number} namespace
-        * @return {string}
-        */
-       getNamespacePrefix = function ( namespace ) {
-               return namespace === NS_MAIN ?
-                       '' :
-                       ( mw.config.get( 'wgFormattedNamespaces' )[ namespace ].replace( / /g, '_' ) + ':' );
-       },
-
-       rUnderscoreTrim = /^_+|_+$/g,
-
-       rSplit = /^(.+?)_*:_*(.*)$/,
-
-       // See MediaWikiTitleCodec.php#getTitleInvalidRegex
-       rInvalid = new RegExp(
-               '[^' + mw.config.get( 'wgLegalTitleChars' ) + ']' +
-               // URL percent encoding sequences interfere with the ability
-               // to round-trip titles -- you can't link to them consistently.
-               '|%[0-9A-Fa-f]{2}' +
-               // XML/HTML character references produce similar issues.
-               '|&[A-Za-z0-9\u0080-\uFFFF]+;' +
-               '|&#[0-9]+;' +
-               '|&#x[0-9A-Fa-f]+;'
-       ),
-
-       // From MediaWikiTitleCodec::splitTitleString() in PHP
-       // Note that this is not equivalent to /\s/, e.g. underscore is included, tab is not included.
-       rWhitespace = /[ _\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]+/g,
-
-       // From MediaWikiTitleCodec::splitTitleString() in PHP
-       rUnicodeBidi = /[\u200E\u200F\u202A-\u202E]/g,
+               rUnderscoreTrim = /^_+|_+$/g,
 
-       /**
-        * Slightly modified from Flinfo. Credit goes to Lupo and Flominator.
-        * @private
-        * @static
-        * @property sanitationRules
-        */
-       sanitationRules = [
-               // "signature"
-               {
-                       pattern: /~{3}/g,
-                       replace: '',
-                       generalRule: true
-               },
-               // control characters
-               {
-                       pattern: /[\x00-\x1f\x7f]/g,
-                       replace: '',
-                       generalRule: true
-               },
-               // URL encoding (possibly)
-               {
-                       pattern: /%([0-9A-Fa-f]{2})/g,
-                       replace: '% $1',
-                       generalRule: true
-               },
-               // HTML-character-entities
-               {
-                       pattern: /&(([A-Za-z0-9\x80-\xff]+|#[0-9]+|#x[0-9A-Fa-f]+);)/g,
-                       replace: '& $1',
-                       generalRule: true
-               },
-               // slash, colon (not supported by file systems like NTFS/Windows, Mac OS 9 [:], ext4 [/])
-               {
-                       pattern: new RegExp( '[' + mw.config.get( 'wgIllegalFileChars', '' ) + ']', 'g' ),
-                       replace: '-',
-                       fileRule: true
-               },
-               // brackets, greater than
-               {
-                       pattern: /[\]\}>]/g,
-                       replace: ')',
-                       generalRule: true
-               },
-               // brackets, lower than
-               {
-                       pattern: /[\[\{<]/g,
-                       replace: '(',
-                       generalRule: true
-               },
-               // everything that wasn't covered yet
-               {
-                       pattern: new RegExp( rInvalid.source, 'g' ),
-                       replace: '-',
-                       generalRule: true
-               },
-               // directory structures
-               {
-                       pattern: /^(\.|\.\.|\.\/.*|\.\.\/.*|.*\/\.\/.*|.*\/\.\.\/.*|.*\/\.|.*\/\.\.)$/g,
-                       replace: '',
-                       generalRule: true
-               }
-       ],
+               rSplit = /^(.+?)_*:_*(.*)$/,
 
-       /**
-        * Internal helper for #constructor and #newFromText.
-        *
-        * Based on Title.php#secureAndSplit
-        *
-        * @private
-        * @static
-        * @method parse
-        * @param {string} title
-        * @param {number} [defaultNamespace=NS_MAIN]
-        * @return {Object|boolean}
-        */
-       parse = function ( title, defaultNamespace ) {
-               var namespace, m, id, i, fragment, ext;
+               // See MediaWikiTitleCodec.php#getTitleInvalidRegex
+               rInvalid = new RegExp(
+                       '[^' + mw.config.get( 'wgLegalTitleChars' ) + ']' +
+                       // URL percent encoding sequences interfere with the ability
+                       // to round-trip titles -- you can't link to them consistently.
+                       '|%[0-9A-Fa-f]{2}' +
+                       // XML/HTML character references produce similar issues.
+                       '|&[A-Za-z0-9\u0080-\uFFFF]+;' +
+                       '|&#[0-9]+;' +
+                       '|&#x[0-9A-Fa-f]+;'
+               ),
 
-               namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace;
+               // From MediaWikiTitleCodec::splitTitleString() in PHP
+               // Note that this is not equivalent to /\s/, e.g. underscore is included, tab is not included.
+               rWhitespace = /[ _\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]+/g,
 
-               title = title
-                       // Strip Unicode bidi override characters
-                       .replace( rUnicodeBidi, '' )
-                       // Normalise whitespace to underscores and remove duplicates
-                       .replace( rWhitespace, '_' )
-                       // Trim underscores
-                       .replace( rUnderscoreTrim, '' );
+               // From MediaWikiTitleCodec::splitTitleString() in PHP
+               rUnicodeBidi = /[\u200E\u200F\u202A-\u202E]/g,
+
+               /**
+                * Slightly modified from Flinfo. Credit goes to Lupo and Flominator.
+                * @private
+                * @static
+                * @property sanitationRules
+                */
+               sanitationRules = [
+                       // "signature"
+                       {
+                               pattern: /~{3}/g,
+                               replace: '',
+                               generalRule: true
+                       },
+                       // control characters
+                       {
+                               // eslint-disable-next-line no-control-regex
+                               pattern: /[\x00-\x1f\x7f]/g,
+                               replace: '',
+                               generalRule: true
+                       },
+                       // URL encoding (possibly)
+                       {
+                               pattern: /%([0-9A-Fa-f]{2})/g,
+                               replace: '% $1',
+                               generalRule: true
+                       },
+                       // HTML-character-entities
+                       {
+                               pattern: /&(([A-Za-z0-9\x80-\xff]+|#[0-9]+|#x[0-9A-Fa-f]+);)/g,
+                               replace: '& $1',
+                               generalRule: true
+                       },
+                       // slash, colon (not supported by file systems like NTFS/Windows, Mac OS 9 [:], ext4 [/])
+                       {
+                               pattern: new RegExp( '[' + mw.config.get( 'wgIllegalFileChars', '' ) + ']', 'g' ),
+                               replace: '-',
+                               fileRule: true
+                       },
+                       // brackets, greater than
+                       {
+                               pattern: /[\]\}>]/g,
+                               replace: ')',
+                               generalRule: true
+                       },
+                       // brackets, lower than
+                       {
+                               pattern: /[\[\{<]/g,
+                               replace: '(',
+                               generalRule: true
+                       },
+                       // everything that wasn't covered yet
+                       {
+                               pattern: new RegExp( rInvalid.source, 'g' ),
+                               replace: '-',
+                               generalRule: true
+                       },
+                       // directory structures
+                       {
+                               pattern: /^(\.|\.\.|\.\/.*|\.\.\/.*|.*\/\.\/.*|.*\/\.\.\/.*|.*\/\.|.*\/\.\.)$/g,
+                               replace: '',
+                               generalRule: true
+                       }
+               ],
+
+               /**
+                * Internal helper for #constructor and #newFromText.
+                *
+                * Based on Title.php#secureAndSplit
+                *
+                * @private
+                * @static
+                * @method parse
+                * @param {string} title
+                * @param {number} [defaultNamespace=NS_MAIN]
+                * @return {Object|boolean}
+                */
+               parse = function ( title, defaultNamespace ) {
+                       var namespace, m, id, i, fragment, ext;
+
+                       namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace;
 
-               // Process initial colon
-               if ( title !== '' && title[ 0 ] === ':' ) {
-                       // Initial colon means main namespace instead of specified default
-                       namespace = NS_MAIN;
                        title = title
-                               // Strip colon
-                               .slice( 1 )
+                               // Strip Unicode bidi override characters
+                               .replace( rUnicodeBidi, '' )
+                               // Normalise whitespace to underscores and remove duplicates
+                               .replace( rWhitespace, '_' )
                                // Trim underscores
                                .replace( rUnderscoreTrim, '' );
-               }
 
-               if ( title === '' ) {
-                       return false;
-               }
+                       // Process initial colon
+                       if ( title !== '' && title[ 0 ] === ':' ) {
+                               // Initial colon means main namespace instead of specified default
+                               namespace = NS_MAIN;
+                               title = title
+                                       // Strip colon
+                                       .slice( 1 )
+                                       // Trim underscores
+                                       .replace( rUnderscoreTrim, '' );
+                       }
 
-               // Process namespace prefix (if any)
-               m = title.match( rSplit );
-               if ( m ) {
-                       id = getNsIdByName( m[ 1 ] );
-                       if ( id !== false ) {
-                               // Ordinary namespace
-                               namespace = id;
-                               title = m[ 2 ];
+                       if ( title === '' ) {
+                               return false;
+                       }
 
-                               // For Talk:X pages, make sure X has no "namespace" prefix
-                               if ( namespace === NS_TALK && ( m = title.match( rSplit ) ) ) {
-                                       // Disallow titles like Talk:File:x (subject should roundtrip: talk:file:x -> file:x -> file_talk:x)
-                                       if ( getNsIdByName( m[ 1 ] ) !== false ) {
-                                               return false;
+                       // Process namespace prefix (if any)
+                       m = title.match( rSplit );
+                       if ( m ) {
+                               id = getNsIdByName( m[ 1 ] );
+                               if ( id !== false ) {
+                                       // Ordinary namespace
+                                       namespace = id;
+                                       title = m[ 2 ];
+
+                                       // For Talk:X pages, make sure X has no "namespace" prefix
+                                       if ( namespace === NS_TALK && ( m = title.match( rSplit ) ) ) {
+                                               // Disallow titles like Talk:File:x (subject should roundtrip: talk:file:x -> file:x -> file_talk:x)
+                                               if ( getNsIdByName( m[ 1 ] ) !== false ) {
+                                                       return false;
+                                               }
                                        }
                                }
                        }
-               }
 
-               // Process fragment
-               i = title.indexOf( '#' );
-               if ( i === -1 ) {
-                       fragment = null;
-               } else {
-                       fragment = title
-                               // Get segment starting after the hash
-                               .slice( i + 1 )
-                               // Convert to text
-                               // NB: Must not be trimmed ("Example#_foo" is not the same as "Example#foo")
-                               .replace( /_/g, ' ' );
-
-                       title = title
-                               // Strip hash
-                               .slice( 0, i )
-                               // Trim underscores, again (strips "_" from "bar" in "Foo_bar_#quux")
-                               .replace( rUnderscoreTrim, '' );
-               }
+                       // Process fragment
+                       i = title.indexOf( '#' );
+                       if ( i === -1 ) {
+                               fragment = null;
+                       } else {
+                               fragment = title
+                                       // Get segment starting after the hash
+                                       .slice( i + 1 )
+                                       // Convert to text
+                                       // NB: Must not be trimmed ("Example#_foo" is not the same as "Example#foo")
+                                       .replace( /_/g, ' ' );
+
+                               title = title
+                                       // Strip hash
+                                       .slice( 0, i )
+                                       // Trim underscores, again (strips "_" from "bar" in "Foo_bar_#quux")
+                                       .replace( rUnderscoreTrim, '' );
+                       }
 
-               // Reject illegal characters
-               if ( title.match( rInvalid ) ) {
-                       return false;
-               }
+                       // Reject illegal characters
+                       if ( title.match( rInvalid ) ) {
+                               return false;
+                       }
 
-               // Disallow titles that browsers or servers might resolve as directory navigation
-               if (
-                       title.indexOf( '.' ) !== -1 && (
-                               title === '.' || title === '..' ||
-                               title.indexOf( './' ) === 0 ||
-                               title.indexOf( '../' ) === 0 ||
-                               title.indexOf( '/./' ) !== -1 ||
-                               title.indexOf( '/../' ) !== -1 ||
-                               title.slice( -2 ) === '/.' ||
-                               title.slice( -3 ) === '/..'
-                       )
-               ) {
-                       return false;
-               }
+                       // Disallow titles that browsers or servers might resolve as directory navigation
+                       if (
+                               title.indexOf( '.' ) !== -1 && (
+                                       title === '.' || title === '..' ||
+                                       title.indexOf( './' ) === 0 ||
+                                       title.indexOf( '../' ) === 0 ||
+                                       title.indexOf( '/./' ) !== -1 ||
+                                       title.indexOf( '/../' ) !== -1 ||
+                                       title.slice( -2 ) === '/.' ||
+                                       title.slice( -3 ) === '/..'
+                               )
+                       ) {
+                               return false;
+                       }
 
-               // Disallow magic tilde sequence
-               if ( title.indexOf( '~~~' ) !== -1 ) {
-                       return false;
-               }
+                       // Disallow magic tilde sequence
+                       if ( title.indexOf( '~~~' ) !== -1 ) {
+                               return false;
+                       }
 
-               // Disallow titles exceeding the TITLE_MAX_BYTES byte size limit (size of underlying database field)
-               // Except for special pages, e.g. [[Special:Block/Long name]]
-               // Note: The PHP implementation also asserts that even in NS_SPECIAL, the title should
-               // be less than 512 bytes.
-               if ( namespace !== NS_SPECIAL && $.byteLength( title ) > TITLE_MAX_BYTES ) {
-                       return false;
-               }
+                       // Disallow titles exceeding the TITLE_MAX_BYTES byte size limit (size of underlying database field)
+                       // Except for special pages, e.g. [[Special:Block/Long name]]
+                       // Note: The PHP implementation also asserts that even in NS_SPECIAL, the title should
+                       // be less than 512 bytes.
+                       if ( namespace !== NS_SPECIAL && $.byteLength( title ) > TITLE_MAX_BYTES ) {
+                               return false;
+                       }
 
-               // Can't make a link to a namespace alone.
-               if ( title === '' && namespace !== NS_MAIN ) {
-                       return false;
-               }
+                       // Can't make a link to a namespace alone.
+                       if ( title === '' && namespace !== NS_MAIN ) {
+                               return false;
+                       }
 
-               // Any remaining initial :s are illegal.
-               if ( title[ 0 ] === ':' ) {
-                       return false;
-               }
+                       // Any remaining initial :s are illegal.
+                       if ( title[ 0 ] === ':' ) {
+                               return false;
+                       }
 
-               // For backwards-compatibility with old mw.Title, we separate the extension from the
-               // rest of the title.
-               i = title.lastIndexOf( '.' );
-               if ( i === -1 || title.length <= i + 1 ) {
-                       // Extensions are the non-empty segment after the last dot
-                       ext = null;
-               } else {
-                       ext = title.slice( i + 1 );
-                       title = title.slice( 0, i );
-               }
+                       // For backwards-compatibility with old mw.Title, we separate the extension from the
+                       // rest of the title.
+                       i = title.lastIndexOf( '.' );
+                       if ( i === -1 || title.length <= i + 1 ) {
+                               // Extensions are the non-empty segment after the last dot
+                               ext = null;
+                       } else {
+                               ext = title.slice( i + 1 );
+                               title = title.slice( 0, i );
+                       }
 
-               return {
-                       namespace: namespace,
-                       title: title,
-                       ext: ext,
-                       fragment: fragment
-               };
-       },
+                       return {
+                               namespace: namespace,
+                               title: title,
+                               ext: ext,
+                               fragment: fragment
+                       };
+               },
 
-       /**
-        * Convert db-key to readable text.
-        *
-        * @private
-        * @static
-        * @method text
-        * @param {string} s
-        * @return {string}
-        */
-       text = function ( s ) {
-               if ( s !== null && s !== undefined ) {
-                       return s.replace( /_/g, ' ' );
-               } else {
-                       return '';
-               }
-       },
+               /**
+                * Convert db-key to readable text.
+                *
+                * @private
+                * @static
+                * @method text
+                * @param {string} s
+                * @return {string}
+                */
+               text = function ( s ) {
+                       if ( s !== null && s !== undefined ) {
+                               return s.replace( /_/g, ' ' );
+                       } else {
+                               return '';
+                       }
+               },
 
-       /**
-        * Sanitizes a string based on a rule set and a filter
-        *
-        * @private
-        * @static
-        * @method sanitize
-        * @param {string} s
-        * @param {Array} filter
-        * @return {string}
-        */
-       sanitize = function ( s, filter ) {
-               var i, ruleLength, rule, m, filterLength,
-                       rules = sanitationRules;
-
-               for ( i = 0, ruleLength = rules.length; i < ruleLength; ++i ) {
-                       rule = rules[ i ];
-                       for ( m = 0, filterLength = filter.length; m < filterLength; ++m ) {
-                               if ( rule[ filter[ m ] ] ) {
-                                       s = s.replace( rule.pattern, rule.replace );
+               /**
+                * Sanitizes a string based on a rule set and a filter
+                *
+                * @private
+                * @static
+                * @method sanitize
+                * @param {string} s
+                * @param {Array} filter
+                * @return {string}
+                */
+               sanitize = function ( s, filter ) {
+                       var i, ruleLength, rule, m, filterLength,
+                               rules = sanitationRules;
+
+                       for ( i = 0, ruleLength = rules.length; i < ruleLength; ++i ) {
+                               rule = rules[ i ];
+                               for ( m = 0, filterLength = filter.length; m < filterLength; ++m ) {
+                                       if ( rule[ filter[ m ] ] ) {
+                                               s = s.replace( rule.pattern, rule.replace );
+                                       }
                                }
                        }
-               }
-               return s;
-       },
-
-       /**
-        * Cuts a string to a specific byte length, assuming UTF-8
-        * or less, if the last character is a multi-byte one
-        *
-        * @private
-        * @static
-        * @method trimToByteLength
-        * @param {string} s
-        * @param {number} length
-        * @return {string}
-        */
-       trimToByteLength = function ( s, length ) {
-               var byteLength, chopOffChars, chopOffBytes;
-
-               // bytelength is always greater or equal to the length in characters
-               s = s.substr( 0, length );
-               while ( ( byteLength = $.byteLength( s ) ) > length ) {
-                       // Calculate how many characters can be safely removed
-                       // First, we need to know how many bytes the string exceeds the threshold
-                       chopOffBytes = byteLength - length;
-                       // A character in UTF-8 is at most 4 bytes
-                       // One character must be removed in any case because the
-                       // string is too long
-                       chopOffChars = Math.max( 1, Math.floor( chopOffBytes / 4 ) );
-                       s = s.substr( 0, s.length - chopOffChars );
-               }
-               return s;
-       },
+                       return s;
+               },
 
-       /**
-        * Cuts a file name to a specific byte length
-        *
-        * @private
-        * @static
-        * @method trimFileNameToByteLength
-        * @param {string} name without extension
-        * @param {string} extension file extension
-        * @return {string} The full name, including extension
-        */
-       trimFileNameToByteLength = function ( name, extension ) {
-               // There is a special byte limit for file names and ... remember the dot
-               return trimToByteLength( name, FILENAME_MAX_BYTES - extension.length - 1 ) + '.' + extension;
-       },
-
-       // Polyfill for ES5 Object.create
-       createObject = Object.create || ( function () {
-               return function ( o ) {
-                       function Title() {}
-                       if ( o !== Object( o ) ) {
-                               throw new Error( 'Cannot inherit from a non-object' );
+               /**
+                * Cuts a string to a specific byte length, assuming UTF-8
+                * or less, if the last character is a multi-byte one
+                *
+                * @private
+                * @static
+                * @method trimToByteLength
+                * @param {string} s
+                * @param {number} length
+                * @return {string}
+                */
+               trimToByteLength = function ( s, length ) {
+                       var byteLength, chopOffChars, chopOffBytes;
+
+                       // bytelength is always greater or equal to the length in characters
+                       s = s.substr( 0, length );
+                       while ( ( byteLength = $.byteLength( s ) ) > length ) {
+                               // Calculate how many characters can be safely removed
+                               // First, we need to know how many bytes the string exceeds the threshold
+                               chopOffBytes = byteLength - length;
+                               // A character in UTF-8 is at most 4 bytes
+                               // One character must be removed in any case because the
+                               // string is too long
+                               chopOffChars = Math.max( 1, Math.floor( chopOffBytes / 4 ) );
+                               s = s.substr( 0, s.length - chopOffChars );
                        }
-                       Title.prototype = o;
-                       return new Title();
-               };
-       }() );
+                       return s;
+               },
+
+               /**
+                * Cuts a file name to a specific byte length
+                *
+                * @private
+                * @static
+                * @method trimFileNameToByteLength
+                * @param {string} name without extension
+                * @param {string} extension file extension
+                * @return {string} The full name, including extension
+                */
+               trimFileNameToByteLength = function ( name, extension ) {
+                       // There is a special byte limit for file names and ... remember the dot
+                       return trimToByteLength( name, FILENAME_MAX_BYTES - extension.length - 1 ) + '.' + extension;
+               },
+
+               // Polyfill for ES5 Object.create
+               createObject = Object.create || ( function () {
+                       return function ( o ) {
+                               function Title() {}
+                               if ( o !== Object( o ) ) {
+                                       throw new Error( 'Cannot inherit from a non-object' );
+                               }
+                               Title.prototype = o;
+                               return new Title();
+                       };
+               }() );
 
        /* Static members */
 
                        }
                }
 
-               if ( namespace === NS_MEDIA
-                       || ( options.forUploading && ( namespace === NS_FILE ) )
+               if (
+                       namespace === NS_MEDIA ||
+                       ( options.forUploading && ( namespace === NS_FILE ) )
                ) {
 
                        title = sanitize( title, [ 'generalRule', 'fileRule' ] );
                pages: {},
 
                set: function ( titles, state ) {
+                       var i, len,
+                               pages = this.pages;
+
                        titles = $.isArray( titles ) ? titles : [ titles ];
                        state = state === undefined ? true : !!state;
-                       var i,
-                               pages = this.pages,
-                               len = titles.length;
 
-                       for ( i = 0; i < len; i++ ) {
+                       for ( i = 0, len = titles.length; i < len; i++ ) {
                                pages[ titles[ i ] ] = state;
                        }
                        return true;
                        ) {
                                return this.title;
                        }
-                       return this.title[ 0 ].toUpperCase() + this.title.slice( 1 );
+                       // PHP's strtoupper differs from String.toUpperCase in a number of cases
+                       // Bug: T147646
+                       return mw.Title.phpCharToUpper( this.title[ 0 ] ) + this.title.slice( 1 );
                },
 
                /**
diff --git a/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js b/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js
new file mode 100644 (file)
index 0000000..2b39c9a
--- /dev/null
@@ -0,0 +1,255 @@
+// This file can't be parsed by JSDuck due to <https://github.com/tenderlove/rkelly/issues/35>.
+// (It is excluded in jsduck.json.)
+// ESLint suggests unquoting some object keys, which would render the file unparseable by Opera 12.
+/* eslint-disable quote-props */
+( function ( mw ) {
+       var toUpperMapping = {
+               'ß': 'ß',
+               'ʼn': 'ʼn',
+               'Dž': 'Dž',
+               'dž': 'Dž',
+               'Lj': 'Lj',
+               'lj': 'Lj',
+               'Nj': 'Nj',
+               'nj': 'Nj',
+               'ǰ': 'ǰ',
+               'Dz': 'Dz',
+               'dz': 'Dz',
+               'ʝ': 'Ʝ',
+               'ͅ': 'ͅ',
+               'ΐ': 'ΐ',
+               'ΰ': 'ΰ',
+               'և': 'և',
+               'ᏸ': 'Ᏸ',
+               'ᏹ': 'Ᏹ',
+               'ᏺ': 'Ᏺ',
+               'ᏻ': 'Ᏻ',
+               'ᏼ': 'Ᏼ',
+               'ᏽ': 'Ᏽ',
+               'ẖ': 'ẖ',
+               'ẗ': 'ẗ',
+               'ẘ': 'ẘ',
+               'ẙ': 'ẙ',
+               'ẚ': 'ẚ',
+               'ὐ': 'ὐ',
+               'ὒ': 'ὒ',
+               'ὔ': 'ὔ',
+               'ὖ': 'ὖ',
+               'ᾀ': 'ᾈ',
+               'ᾁ': 'ᾉ',
+               'ᾂ': 'ᾊ',
+               'ᾃ': 'ᾋ',
+               'ᾄ': 'ᾌ',
+               'ᾅ': 'ᾍ',
+               'ᾆ': 'ᾎ',
+               'ᾇ': 'ᾏ',
+               'ᾈ': 'ᾈ',
+               'ᾉ': 'ᾉ',
+               'ᾊ': 'ᾊ',
+               'ᾋ': 'ᾋ',
+               'ᾌ': 'ᾌ',
+               'ᾍ': 'ᾍ',
+               'ᾎ': 'ᾎ',
+               'ᾏ': 'ᾏ',
+               'ᾐ': 'ᾘ',
+               'ᾑ': 'ᾙ',
+               'ᾒ': 'ᾚ',
+               'ᾓ': 'ᾛ',
+               'ᾔ': 'ᾜ',
+               'ᾕ': 'ᾝ',
+               'ᾖ': 'ᾞ',
+               'ᾗ': 'ᾟ',
+               'ᾘ': 'ᾘ',
+               'ᾙ': 'ᾙ',
+               'ᾚ': 'ᾚ',
+               'ᾛ': 'ᾛ',
+               'ᾜ': 'ᾜ',
+               'ᾝ': 'ᾝ',
+               'ᾞ': 'ᾞ',
+               'ᾟ': 'ᾟ',
+               'ᾠ': 'ᾨ',
+               'ᾡ': 'ᾩ',
+               'ᾢ': 'ᾪ',
+               'ᾣ': 'ᾫ',
+               'ᾤ': 'ᾬ',
+               'ᾥ': 'ᾭ',
+               'ᾦ': 'ᾮ',
+               'ᾧ': 'ᾯ',
+               'ᾨ': 'ᾨ',
+               'ᾩ': 'ᾩ',
+               'ᾪ': 'ᾪ',
+               'ᾫ': 'ᾫ',
+               'ᾬ': 'ᾬ',
+               'ᾭ': 'ᾭ',
+               'ᾮ': 'ᾮ',
+               'ᾯ': 'ᾯ',
+               'ᾲ': 'ᾲ',
+               'ᾳ': 'ᾼ',
+               'ᾴ': 'ᾴ',
+               'ᾶ': 'ᾶ',
+               'ᾷ': 'ᾷ',
+               'ᾼ': 'ᾼ',
+               'ῂ': 'ῂ',
+               'ῃ': 'ῌ',
+               'ῄ': 'ῄ',
+               'ῆ': 'ῆ',
+               'ῇ': 'ῇ',
+               'ῌ': 'ῌ',
+               'ῒ': 'ῒ',
+               'ΐ': 'ΐ',
+               'ῖ': 'ῖ',
+               'ῗ': 'ῗ',
+               'ῢ': 'ῢ',
+               'ΰ': 'ΰ',
+               'ῤ': 'ῤ',
+               'ῦ': 'ῦ',
+               'ῧ': 'ῧ',
+               'ῲ': 'ῲ',
+               'ῳ': 'ῼ',
+               'ῴ': 'ῴ',
+               'ῶ': 'ῶ',
+               'ῷ': 'ῷ',
+               'ῼ': 'ῼ',
+               'ⅰ': 'ⅰ',
+               'ⅱ': 'ⅱ',
+               'ⅲ': 'ⅲ',
+               'ⅳ': 'ⅳ',
+               'ⅴ': 'ⅴ',
+               'ⅵ': 'ⅵ',
+               'ⅶ': 'ⅶ',
+               'ⅷ': 'ⅷ',
+               'ⅸ': 'ⅸ',
+               'ⅹ': 'ⅹ',
+               'ⅺ': 'ⅺ',
+               'ⅻ': 'ⅻ',
+               'ⅼ': 'ⅼ',
+               'ⅽ': 'ⅽ',
+               'ⅾ': 'ⅾ',
+               'ⅿ': 'ⅿ',
+               'ⓐ': 'ⓐ',
+               'ⓑ': 'ⓑ',
+               'ⓒ': 'ⓒ',
+               'ⓓ': 'ⓓ',
+               'ⓔ': 'ⓔ',
+               'ⓕ': 'ⓕ',
+               'ⓖ': 'ⓖ',
+               'ⓗ': 'ⓗ',
+               'ⓘ': 'ⓘ',
+               'ⓙ': 'ⓙ',
+               'ⓚ': 'ⓚ',
+               'ⓛ': 'ⓛ',
+               'ⓜ': 'ⓜ',
+               'ⓝ': 'ⓝ',
+               'ⓞ': 'ⓞ',
+               'ⓟ': 'ⓟ',
+               'ⓠ': 'ⓠ',
+               'ⓡ': 'ⓡ',
+               'ⓢ': 'ⓢ',
+               'ⓣ': 'ⓣ',
+               'ⓤ': 'ⓤ',
+               'ⓥ': 'ⓥ',
+               'ⓦ': 'ⓦ',
+               'ⓧ': 'ⓧ',
+               'ⓨ': 'ⓨ',
+               'ⓩ': 'ⓩ',
+               'ꞵ': 'Ꞵ',
+               'ꞷ': 'Ꞷ',
+               'ꭓ': 'Ꭓ',
+               'ꭰ': 'Ꭰ',
+               'ꭱ': 'Ꭱ',
+               'ꭲ': 'Ꭲ',
+               'ꭳ': 'Ꭳ',
+               'ꭴ': 'Ꭴ',
+               'ꭵ': 'Ꭵ',
+               'ꭶ': 'Ꭶ',
+               'ꭷ': 'Ꭷ',
+               'ꭸ': 'Ꭸ',
+               'ꭹ': 'Ꭹ',
+               'ꭺ': 'Ꭺ',
+               'ꭻ': 'Ꭻ',
+               'ꭼ': 'Ꭼ',
+               'ꭽ': 'Ꭽ',
+               'ꭾ': 'Ꭾ',
+               'ꭿ': 'Ꭿ',
+               'ꮀ': 'Ꮀ',
+               'ꮁ': 'Ꮁ',
+               'ꮂ': 'Ꮂ',
+               'ꮃ': 'Ꮃ',
+               'ꮄ': 'Ꮄ',
+               'ꮅ': 'Ꮅ',
+               'ꮆ': 'Ꮆ',
+               'ꮇ': 'Ꮇ',
+               'ꮈ': 'Ꮈ',
+               'ꮉ': 'Ꮉ',
+               'ꮊ': 'Ꮊ',
+               'ꮋ': 'Ꮋ',
+               'ꮌ': 'Ꮌ',
+               'ꮍ': 'Ꮍ',
+               'ꮎ': 'Ꮎ',
+               'ꮏ': 'Ꮏ',
+               'ꮐ': 'Ꮐ',
+               'ꮑ': 'Ꮑ',
+               'ꮒ': 'Ꮒ',
+               'ꮓ': 'Ꮓ',
+               'ꮔ': 'Ꮔ',
+               'ꮕ': 'Ꮕ',
+               'ꮖ': 'Ꮖ',
+               'ꮗ': 'Ꮗ',
+               'ꮘ': 'Ꮘ',
+               'ꮙ': 'Ꮙ',
+               'ꮚ': 'Ꮚ',
+               'ꮛ': 'Ꮛ',
+               'ꮜ': 'Ꮜ',
+               'ꮝ': 'Ꮝ',
+               'ꮞ': 'Ꮞ',
+               'ꮟ': 'Ꮟ',
+               'ꮠ': 'Ꮠ',
+               'ꮡ': 'Ꮡ',
+               'ꮢ': 'Ꮢ',
+               'ꮣ': 'Ꮣ',
+               'ꮤ': 'Ꮤ',
+               'ꮥ': 'Ꮥ',
+               'ꮦ': 'Ꮦ',
+               'ꮧ': 'Ꮧ',
+               'ꮨ': 'Ꮨ',
+               'ꮩ': 'Ꮩ',
+               'ꮪ': 'Ꮪ',
+               'ꮫ': 'Ꮫ',
+               'ꮬ': 'Ꮬ',
+               'ꮭ': 'Ꮭ',
+               'ꮮ': 'Ꮮ',
+               'ꮯ': 'Ꮯ',
+               'ꮰ': 'Ꮰ',
+               'ꮱ': 'Ꮱ',
+               'ꮲ': 'Ꮲ',
+               'ꮳ': 'Ꮳ',
+               'ꮴ': 'Ꮴ',
+               'ꮵ': 'Ꮵ',
+               'ꮶ': 'Ꮶ',
+               'ꮷ': 'Ꮷ',
+               'ꮸ': 'Ꮸ',
+               'ꮹ': 'Ꮹ',
+               'ꮺ': 'Ꮺ',
+               'ꮻ': 'Ꮻ',
+               'ꮼ': 'Ꮼ',
+               'ꮽ': 'Ꮽ',
+               'ꮾ': 'Ꮾ',
+               'ꮿ': 'Ꮿ',
+               'ff': 'ff',
+               'fi': 'fi',
+               'fl': 'fl',
+               'ffi': 'ffi',
+               'ffl': 'ffl',
+               'ſt': 'ſt',
+               'st': 'st',
+               'ﬓ': 'ﬓ',
+               'ﬔ': 'ﬔ',
+               'ﬕ': 'ﬕ',
+               'ﬖ': 'ﬖ',
+               'ﬗ': 'ﬗ'
+       };
+       mw.Title.phpCharToUpper = function ( chr ) {
+               var mapped = toUpperMapping[ chr ];
+               return mapped || chr.toUpperCase();
+       };
+}( mediaWiki ) );
index 7c4855f..c7ebfd8 100644 (file)
@@ -1,4 +1,4 @@
-/*global moment*/
+/* global moment*/
 ( function ( $, mw, moment ) {
 
        /**
                                        // If the user can't upload anything, don't give them the option to.
                                        api.getUserInfo().then( function ( userInfo ) {
                                                if ( userInfo.rights.indexOf( 'upload' ) === -1 ) {
-                                                       // TODO Use a better error message when not all logged-in users can upload
-                                                       booklet.getPage( 'upload' ).$element.msg( 'api-error-mustbeloggedin' );
+                                                       if ( mw.user.isAnon() ) {
+                                                               booklet.getPage( 'upload' ).$element.msg( 'api-error-mustbeloggedin' );
+                                                       } else {
+                                                               booklet.getPage( 'upload' ).$element.msg( 'api-error-badaccess-groups' );
+                                                       }
                                                }
                                                return $.Deferred().resolve();
                                        } )
index a719ffe..9d9c0a6 100644 (file)
@@ -29,6 +29,9 @@
         * @uses mw.Upload
         * @uses mw.Upload.BookletLayout
         * @extends OO.ui.ProcessDialog
+        *
+        * @constructor
+        * @param {Object} [config] Configuration options
         * @cfg {Function} [bookletClass=mw.Upload.BookletLayout] Booklet class to be
         *     used for the steps
         * @cfg {Object} [booklet] Booklet constructor configuration
@@ -57,7 +60,6 @@
         * @inheritdoc
         * @property title
         */
-       /*jshint -W024*/
        mw.Upload.Dialog.static.title = mw.msg( 'upload-dialog-title' );
 
        /**
@@ -97,8 +99,6 @@
                }
        ];
 
-       /*jshint +W024*/
-
        /* Methods */
 
        /**
         * @return {mw.Upload.BookletLayout} An upload booklet
         */
        mw.Upload.Dialog.prototype.createUploadBooklet = function () {
+               // eslint-disable-next-line new-cap
                return new this.bookletClass( $.extend( {
                        $overlay: this.$overlay
                }, this.bookletConfig ) );
index 23b0900..02df2a8 100644 (file)
@@ -2,8 +2,6 @@
        var UP;
 
        /**
-        * @class mw.Upload
-        *
         * Used to represent an upload in progress on the frontend.
         * Most of the functionality is implemented in mw.Api.plugin.upload,
         * but this model class will tie it together as well as let you perform
@@ -43,6 +41,8 @@
         *       } );
         *     } );
         *
+        * @class mw.Upload
+        *
         * @constructor
         * @param {Object|mw.Api} [apiconfig] A mw.Api object (or subclass), or configuration
         *     to pass to the constructor of mw.Api.
index 835b423..0c47dbe 100644 (file)
  * @class mw.Uri
  */
 
+/* eslint-disable no-use-before-define */
+
 ( function ( mw, $ ) {
+       var parser, properties;
+
        /**
         * Function that's useful when constructing the URI string -- we frequently encounter the pattern
         * of having to add something to the URI as we go, but only if it's present, and to include a
         * @static
         * @property {Object} parser
         */
-       var parser = {
+       parser = {
                strict: mw.template.get( 'mediawiki.Uri', 'strict.regexp' ).render(),
                loose: mw.template.get( 'mediawiki.Uri', 'loose.regexp' ).render()
-       },
+       };
 
        /**
         * The order here matches the order of captured matches in the `parser` property regexes.
         * @param {string|Function} documentLocation A full url, or function returning one.
         *  If passed a function, the return value may change over time and this will be honoured. (T74334)
         * @member mw
+        * @return {Function} Uri class
         */
        mw.UriRelative = function ( documentLocation ) {
                var getDefaultUri = ( function () {
index 4d0c135..e3a8f7b 100644 (file)
@@ -1,9 +1,5 @@
-/* jshint devel: true */
 ( function ( mw, $ ) {
        /**
-        * @method confirmCloseWindow
-        * @member mw
-        *
         * Prevent the closing of a window with a confirm message (the onbeforeunload event seems to
         * work in most browsers.)
         *
@@ -25,6 +21,8 @@
         *         // do whatever you wanted to do
         *     }
         *
+        * @method confirmCloseWindow
+        * @member mw
         * @param {Object} [options]
         * @param {string} [options.namespace] Namespace for the event registration
         * @param {string} [options.message]
                        }
                };
        };
-} )( mediaWiki, jQuery );
+}( mediaWiki, jQuery ) );
index 26c74a1..3c1a668 100644 (file)
                        }
 
                        bitDiv( 'phpversion' )
-                               .append( $( this.data.phpEngine === 'HHVM'
-                                       ? '<a href="http://hhvm.com/">HHVM</a>'
-                                       '<a href="https://php.net/">PHP</a>'
+                               .append( $( this.data.phpEngine === 'HHVM' ?
+                                       '<a href="http://hhvm.com/">HHVM</a>' :
+                                       '<a href="https://php.net/">PHP</a>'
                                ) )
                                .append( ': ' + this.data.phpVersion );
 
 
                /**
                 * Build the console panel
+                *
+                * @return {jQuery} Console panel
                 */
                buildConsoleTable: function () {
                        var $table, entryTypeText, i, length, entry;
                        $table = $( '<table id="mw-debug-querylist"></table>' );
 
                        $( '<tr>' )
-                               .append( $( '<th>#</th>' ).css( 'width', '4em' )    )
+                               .append( $( '<th>#</th>' ).css( 'width', '4em' ) )
                                .append( $( '<th>SQL</th>' ) )
-                               .append( $( '<th>Time</th>' ).css( 'width', '8em'  ) )
+                               .append( $( '<th>Time</th>' ).css( 'width', '8em' ) )
                                .append( $( '<th>Call</th>' ).css( 'width', '18em' ) )
                        .appendTo( $table );
 
index 46b8479..e86aff6 100644 (file)
                        /**
                         * Dumb window.onerror handler which forwards the errors via mw.track.
                         *
+                        * @param {string} errorMessage
+                        * @param {string} url
+                        * @param {number} lineNumber
+                        * @param {number} [columnNumber]
+                        * @param {Error|Mixed} [errorObject]
+                        * @return {boolean} True to prevent the default action
                         * @fires global_error
                         */
                        window.onerror = function ( errorMessage, url, lineNumber, columnNumber, errorObject ) {
index 49ff411..0c9ea97 100644 (file)
@@ -1,4 +1,3 @@
-/* jshint bitwise:false */
 ( function ( mw, $ ) {
 
        var CONTROL_BUCKET = 'control',
@@ -17,6 +16,7 @@
         * @see https://jsbin.com/kejewi/4/watch?js,console
         */
        function hashString( string ) {
+               /* eslint-disable no-bitwise */
                var hash = 0,
                        i = string.length;
 
@@ -30,6 +30,7 @@
                hash += ( hash << 15 );
 
                return hash >>> 0;
+               /* eslint-enable no-bitwise */
        }
 
        /**
index 0b3ea04..6abdf83 100644 (file)
@@ -6,8 +6,6 @@
  * @author Moriel Schottlender, 2015
  * @since 1.19
  */
-/*jshint esversion:5 */
-/*global OO*/
 ( function ( mw, $ ) {
        /**
         * This is a way of getting simple feedback from users. It's useful
                                this.feedbackSubjectInput.getValue()
                        );
 
-               this.actions.setAbilities( { submit:  isValid } );
+               this.actions.setAbilities( { submit: isValid } );
        };
 
        /**
                                if ( secondaryCode === 'http' ) {
                                        fb.status = 'error3';
                                        // ajax request failed
-                                       mw.log.warn( 'Feedback report failed with HTTP error: ' +  details.textStatus );
+                                       mw.log.warn( 'Feedback report failed with HTTP error: ' + details.textStatus );
                                } else {
                                        fb.status = 'error2';
-                                       mw.log.warn( 'Feedback report failed with API error: ' +  secondaryCode );
+                                       mw.log.warn( 'Feedback report failed with API error: ' + secondaryCode );
                                }
                        } else {
                                fb.status = 'error1';
index 882affe..72bf3d7 100644 (file)
@@ -4,7 +4,6 @@
  * @author Mark Holmquist, 2015
  * @since 1.25
  */
-/*global OO*/
 ( function ( mw, $, oo ) {
        var warningConfig = mw.config.get( 'wgFileWarning' ),
                warningMessages = warningConfig.messages,
index a74aef3..fdaa989 100644 (file)
@@ -4,7 +4,9 @@
  * @author Ori Livneh
  * @since 1.22
  */
-/*jshint devel:true */
+
+/* eslint-disable no-console */
+
 ( function ( mw, $ ) {
 
        var inspect,
        }
 
        function humanSize( bytes ) {
-               if ( !$.isNumeric( bytes ) || bytes === 0 ) { return bytes; }
-               var i = 0,
+               var i,
                        units = [ '', ' KiB', ' MiB', ' GiB', ' TiB', ' PiB' ];
 
-               for ( ; bytes >= 1024; bytes /= 1024 ) { i++; }
+               if ( !$.isNumeric( bytes ) || bytes === 0 ) { return bytes; }
+
+               for ( i = 0; bytes >= 1024; bytes /= 1024 ) { i++; }
                // Maintain one decimal for kB and above, but don't
                // add ".0" for bytes.
                return bytes.toFixed( i > 0 ? 1 : 0 ) + units[ i ];
                        /**
                         * Generate a breakdown of all loaded modules and their size in
                         * kilobytes. Modules are ordered from largest to smallest.
+                        *
+                        * @return {Object[]} Size reports
                         */
                        size: function () {
                                // Map each module to a descriptor object.
                        /**
                         * For each module with styles, count the number of selectors, and
                         * count how many match against some element currently in the DOM.
+                        *
+                        * @return {Object[]} CSS reports
                         */
                        css: function () {
                                var modules = [];
                                                allSelectors: stats.total,
                                                matchedSelectors: stats.matched,
                                                percentMatched: stats.total !== 0 ?
-                                                       ( stats.matched / stats.total * 100 ).toFixed( 2 )  + '%' : null
+                                                       ( stats.matched / stats.total * 100 ).toFixed( 2 ) + '%' : null
                                        } );
                                } );
                                sortByProperty( modules, 'allSelectors', true );
                         * Report stats on mw.loader.store: the number of localStorage
                         * cache hits and misses, the number of items purged from the
                         * cache, and the total size of the module blob in localStorage.
+                        *
+                        * @return {Object[]} Store stats
                         */
                        store: function () {
                                var raw, stats = { enabled: mw.loader.store.enabled };
                                        $.extend( stats, mw.loader.store.stats );
                                        try {
                                                raw = localStorage.getItem( mw.loader.store.getStoreKey() );
-                                               stats.totalSizeInBytes =  $.byteLength( raw );
+                                               stats.totalSizeInBytes = $.byteLength( raw );
                                                stats.totalSize = humanSize( $.byteLength( raw ) );
                                        } catch ( e ) {}
                                }
 
                                // Grep module's CSS
                                if (
-                                       $.isPlainObject( module.style ) && $.isArray( module.style.css )
-                                       && pattern.test( module.style.css.join( '' ) )
+                                       $.isPlainObject( module.style ) && $.isArray( module.style.css ) &&
+                                       pattern.test( module.style.css.join( '' ) )
                                ) {
                                        // Module's CSS source matches
                                        return true;
index 2646cff..c82b9cb 100644 (file)
        function getFailableParserFn( options ) {
                return function ( args ) {
                        var fallback,
+                               // eslint-disable-next-line new-cap
                                parser = new mw.jqueryMsg.parser( options ),
                                key = args[ 0 ],
                                argsArray = $.isArray( args[ 1 ] ) ? args[ 1 ] : slice.call( args, 1 );
                }
 
                return function () {
+                       var failableResult;
                        if ( !failableParserFn ) {
                                failableParserFn = getFailableParserFn( options );
                        }
-                       var failableResult = failableParserFn( arguments );
+                       failableResult = failableParserFn( arguments );
                        if ( format === 'text' || format === 'escaped' ) {
                                return failableResult.text();
                        } else {
                var failableParserFn;
 
                return function () {
+                       var $target;
                        if ( !failableParserFn ) {
                                failableParserFn = getFailableParserFn( options );
                        }
-                       var $target = this.empty();
+                       $target = this.empty();
                        appendWithoutParsing( $target, failableParserFn( arguments ) );
                        return $target;
                };
                this.settings.onlyCurlyBraceTransform = ( this.settings.format === 'text' || this.settings.format === 'escaped' );
                this.astCache = {};
 
+               // eslint-disable-next-line new-cap
                this.emitter = new mw.jqueryMsg.htmlEmitter( this.settings.language, this.settings.magic );
        };
 
 
                /**
                 * Fetch the message string associated with a key, return parsed structure. Memoized.
-                * Note that we pass '[' + key + ']' back for a missing message here.
+                * Note that we pass '⧼' + key + '⧽' back for a missing message here.
                 *
                 * @param {string} key
-                * @return {string|Array} string of '[key]' if message missing, simple string if possible, array of arrays if needs parsing
+                * @return {string|Array} string of '⧼key⧽' if message missing, simple string if possible, array of arrays if needs parsing
                 */
                getAst: function ( key ) {
                        var wikiText;
                        if ( !this.astCache.hasOwnProperty( key ) ) {
                                wikiText = this.settings.messages.get( key );
                                if ( typeof wikiText !== 'string' ) {
-                                       wikiText = '\\[' + key + '\\]';
+                                       wikiText = '⧼' + key + '⧽';
                                }
                                this.astCache[ key ] = this.wikiTextToAst( wikiText );
                        }
                        /**
                         * Starts the parse
                         *
-                        * @param {Function} rootExpression root parse function
+                        * @param {Function} rootExpression Root parse function
+                        * @return {Array|null}
                         */
                        function start( rootExpression ) {
                                var result = nOrMore( 0, rootExpression )();
 
        /**
         * htmlEmitter - object which primarily exists to emit HTML from parser ASTs
+        *
+        * @param {Object} language
+        * @param {Object} magic
         */
        mw.jqueryMsg.htmlEmitter = function ( language, magic ) {
-               this.language = language;
                var jmsg = this;
+               this.language = language;
                $.each( magic, function ( key, val ) {
                        jmsg[ key.toLowerCase() ] = function () {
                                return val;
                 * It may, though, if the wikitext appears in extension-controlled content.
                 *
                 * @param {string[]} nodes
+                * @return {jQuery}
                 */
                wikilink: function ( nodes ) {
                        var page, anchor, url, $el;
                 * @return {number|string} Formatted number
                 */
                formatnum: function ( nodes ) {
-                       var isInteger = ( nodes[ 1 ] && nodes[ 1 ] === 'R' ) ? true : false,
+                       var isInteger = !!nodes[ 1 ] && nodes[ 1 ] === 'R',
                                number = nodes[ 0 ];
 
                        return this.language.convertNumber( number, isInteger );
                return function () {
                        return reusableParent.msg( this.key, this.parameters ).contents().detach();
                };
-       } )();
+       }() );
 
 }( mediaWiki, jQuery ) );
index 9c8fe70..fceeb64 100644 (file)
@@ -7,7 +7,9 @@
  * @alternateClassName mediaWiki
  * @singleton
  */
-/*jshint latedef:false */
+
+/* eslint-disable no-use-before-define */
+
 ( function ( $ ) {
        'use strict';
 
@@ -31,7 +33,7 @@
         * @return {string} hash as an seven-character base 36 string
         */
        function fnv132( str ) {
-               /*jshint bitwise:false */
+               /* eslint-disable no-bitwise */
                var hash = 0x811C9DC5,
                        i;
 
@@ -46,6 +48,7 @@
                }
 
                return hash;
+               /* eslint-enable no-bitwise */
        }
 
        StringSet = window.Set || ( function () {
                        return mw.format.apply( null, [ this.map.get( this.key ) ].concat( this.parameters ) );
                },
 
+               // eslint-disable-next-line valid-jsdoc
                /**
                 * Add (does not replace) parameters for `$N` placeholder values.
                 *
                        var text;
 
                        if ( !this.exists() ) {
-                               // Use <key> as text if key does not exist
-                               if ( this.format === 'escaped' || this.format === 'parse' ) {
-                                       // format 'escaped' and 'parse' need to have the brackets and key html escaped
-                                       return mw.html.escape( '<' + this.key + '>' );
-                               }
-                               return '<' + this.key + '>';
+                               // Use ⧼key⧽ as text if key does not exist
+                               // Err on the side of safety, ensure that the output
+                               // is always html safe in the event the message key is
+                               // missing, since in that case its highly likely the
+                               // message key is user-controlled.
+                               // '⧼' is used instead of '<' to side-step any
+                               // double-escaping issues.
+                               // (Keep synchronised with Message::toString() in PHP.)
+                               return '⧼' + mw.html.escape( this.key ) + '⧽';
                        }
 
                        if ( this.format === 'plain' || this.format === 'text' || this.format === 'parse' ) {
                }
        };
 
+       /* eslint-disable no-console */
        log = ( function () {
                // Also update the restoration of methods in mediawiki.log.js
                // when adding or removing methods here.
                log.deprecate = !Object.defineProperty ? function ( obj, key, val ) {
                        obj[ key ] = val;
                } : function ( obj, key, val, msg, logName ) {
+                       var logged = new StringSet();
                        logName = logName || key;
                        msg = 'Use of "' + logName + '" is deprecated.' + ( msg ? ( ' ' + msg ) : '' );
-                       var logged = new StringSet();
                        function uniqueTrace() {
                                var trace = new Error().stack;
                                if ( logged.has( trace ) ) {
 
                return log;
        }() );
+       /* eslint-enable no-console */
 
        /**
         * @class mw
                                }
 
                                if ( registry[ module ].skip !== null ) {
-                                       /*jshint evil:true */
+                                       // eslint-disable-next-line no-new-func
                                        skip = new Function( registry[ module ].skip );
                                        registry[ module ].skip = null;
                                        if ( skip() ) {
                                                        ) );
                                                }
 
-                                               unresolved.add(  module );
+                                               unresolved.add( module );
                                                sortDependencies( deps[ i ], resolved, unresolved );
                                        }
                                }
                         * @private
                         * @param {string[]} modules Array of string module names
                         * @return {Array} List of dependencies, including 'module'.
+                        * @throws {Error} If an unregistered module or a dependency loop is encountered
                         */
                        function resolve( modules ) {
-                               var resolved = [];
-                               $.each( modules, function ( idx, module ) {
-                                       sortDependencies( module, resolved );
-                               } );
+                               var i, resolved = [];
+                               for ( i = 0; i < modules.length; i++ ) {
+                                       sortDependencies( modules[ i ], resolved );
+                               }
                                return resolved;
                        }
 
                         * Utility function for execute()
                         *
                         * @ignore
+                        * @param {string} [media] Media attribute
+                        * @param {string} url URL
                         */
                        function addLink( media, url ) {
                                var el = document.createElement( 'link' );
                                                } );
                                        };
 
-                                       implicitDependencies = ( $.inArray( module, legacyModules ) !== -1 )
-                                               ? []
-                                               legacyModules;
+                                       implicitDependencies = ( $.inArray( module, legacyModules ) !== -1 ) ?
+                                               [] :
+                                               legacyModules;
 
                                        if ( module === 'user' ) {
                                                // Implicit dependency on the site module. Not real dependency because
                                                implicitDependencies.push( 'site' );
                                        }
 
-                                       legacyWait = implicitDependencies.length
-                                               ? mw.loader.using( implicitDependencies )
-                                               $.Deferred().resolve();
+                                       legacyWait = implicitDependencies.length ?
+                                               mw.loader.using( implicitDependencies ) :
+                                               $.Deferred().resolve();
 
                                        legacyWait.always( function () {
                                                try {
                         * to a query string of the form foo.bar,baz|bar.baz,quux
                         *
                         * @private
+                        * @param {Object} moduleMap Module map
+                        * @return {string} Module query string
                         */
                        function buildModulesString( moduleMap ) {
                                var p, prefix,
                                                        prefix = modules[ i ].substr( 0, lastDotIndex );
                                                        suffix = modules[ i ].slice( lastDotIndex + 1 );
 
-                                                       bytesAdded = hasOwn.call( moduleMap, prefix )
-                                                               ? suffix.length + 3 // '%2C'.length == 3
-                                                               modules[ i ].length + 3; // '%7C'.length == 3
+                                                       bytesAdded = hasOwn.call( moduleMap, prefix ) ?
+                                                               suffix.length + 3 : // '%2C'.length == 3
+                                                               modules[ i ].length + 3; // '%7C'.length == 3
 
                                                        // If the url would become too long, create a new one,
                                                        // but don't create empty requests
                                                        return true;
                                                } );
                                                asyncEval( implementations, function ( err ) {
+                                                       var failed;
                                                        // Not good, the cached mw.loader.implement calls failed! This should
                                                        // never happen, barring ResourceLoader bugs, browser bugs and PEBKACs.
                                                        // Depending on how corrupt the string is, it is likely that some
 
                                                        mw.track( 'resourceloader.exception', { exception: err, source: 'store-eval' } );
                                                        // Re-add the failed ones that are still pending back to the batch
-                                                       var failed = $.grep( sourceModules, function ( module ) {
+                                                       failed = $.grep( sourceModules, function ( module ) {
                                                                return registry[ module ].state === 'loading';
                                                        } );
                                                        batchRequest( failed );
                                                deferred.fail( error );
                                        }
 
-                                       // Resolve entire dependency map
-                                       dependencies = resolve( dependencies );
+                                       try {
+                                               // Resolve entire dependency map
+                                               dependencies = resolve( dependencies );
+                                       } catch ( e ) {
+                                               return deferred.reject( e ).promise();
+                                       }
                                        if ( allReady( dependencies ) ) {
                                                // Run ready immediately
                                                deferred.resolve( mw.loader.require );
                                 *
                                 * @protected
                                 * @since 1.27
+                                * @param {string} moduleName Module name
+                                * @return {Mixed} Exported value
                                 */
                                require: function ( moduleName ) {
                                        var state = mw.loader.getState( moduleName );
                                         *
                                         * @param {string} module Module name
                                         * @param {Object} descriptor The module's descriptor as set in the registry
+                                        * @return {boolean} Module was set
                                         */
                                        set: function ( module, descriptor ) {
                                                var args, key, src;
                                                        // Partial descriptor
                                                        // (e.g. skipped module, or style module with state=ready)
                                                        $.inArray( undefined, [ descriptor.script, descriptor.style,
-                                                                       descriptor.messages, descriptor.templates ] ) !== -1
+                                                               descriptor.messages, descriptor.templates ] ) !== -1
                                                ) {
                                                        // Decline to store
                                                        return false;
                                                        }
                                                } catch ( e ) {
                                                        mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-json' } );
-                                                       return;
+                                                       return false;
                                                }
 
                                                src = 'mw.loader.implement(' + args.join( ',' ) + ');';
                                                }
                                                mw.loader.store.items[ key ] = src;
                                                mw.loader.store.update();
+                                               return true;
                                        },
 
                                        /**
                                         * Iterate through the module store, removing any item that does not correspond
                                         * (in name and version) to an item in the module registry.
+                                        *
+                                        * @return {boolean} Store was pruned
                                         */
                                        prune: function () {
                                                var key, module;
                                                                delete mw.loader.store.items[ key ];
                                                        }
                                                }
+                                               return true;
                                        },
 
                                        /**
                                 * Wrapper object for raw HTML passed to mw.html.element().
                                 *
                                 * @class mw.html.Raw
+                                * @constructor
+                                * @param {string} value
                                 */
                                Raw: function ( value ) {
                                        this.value = value;
                                 * Wrapper object for CDATA element contents passed to mw.html.element()
                                 *
                                 * @class mw.html.Cdata
+                                * @constructor
+                                * @param {string} value
                                 */
                                Cdata: function ( value ) {
                                        this.value = value;
                                         */
                                        remove: list.remove,
 
+                                       // eslint-disable-next-line valid-jsdoc
                                        /**
                                         * Run a hook.
                                         *
         * @param {string} [data.module] Name of module which caused the error
         */
        function logError( topic, data ) {
+               /* eslint-disable no-console */
                var msg,
                        e = data.exception,
                        source = data.source,
                                console.error( String( e ), e );
                        }
                }
+               /* eslint-enable no-console */
        }
 
        // Subscribe to error streams
index c886817..4d23604 100644 (file)
 
                        if ( !$log.length ) {
                                $log = $( '<div id="mw-log-console"></div>' ).css( {
-                                               overflow: 'auto',
-                                               height: '150px',
-                                               backgroundColor: 'white',
-                                               borderTop: 'solid 2px #ADADAD'
-                                       } );
+                                       overflow: 'auto',
+                                       height: '150px',
+                                       backgroundColor: 'white',
+                                       borderTop: 'solid 2px #ADADAD'
+                               } );
                                hovzer = $.getFootHovzer();
                                hovzer.$.append( $log );
                                hovzer.update();
index 36b45f1..e1287db 100644 (file)
         * @alternateClassName mw.Notification
         * @constructor
         * @private
+        * @param {mw.Message|jQuery|HTMLElement|string} message
+        * @param {Object} options
         */
        function Notification( message, options ) {
-               var $notification, $notificationTitle, $notificationContent;
+               var $notification, $notificationContent;
 
                $notification = $( '<div class="mw-notification"></div>' )
                        .data( 'mw.notification', this )
@@ -48,7 +50,7 @@
                }
 
                if ( options.title ) {
-                       $notificationTitle = $( '<div class="mw-notification-title"></div>' )
+                       $( '<div class="mw-notification-title"></div>' )
                                .text( options.title )
                                .appendTo( $notification );
                }
                                        $area.hide();
                                        notif.$notification.remove();
                                } else {
-                                       notif.$notification.slideUp( 'fast',  function () {
+                                       notif.$notification.slideUp( 'fast', function () {
                                                $( this ).remove();
                                        } );
                                }
         * @ignore
         */
        function init() {
-               var offset, $window = $( window );
+               var offset,
+                       isFloating = false;
 
                $area = $( '<div id="mw-notification-area" class="mw-notification-area mw-notification-area-layout"></div>' )
                        // Pause auto-hide timers when the mouse is in the notification area.
                $area.hide();
 
                function updateAreaMode() {
-                       var isFloating = $window.scrollTop() > offset.top;
+                       var shouldFloat = window.pageYOffset > offset.top;
+                       if ( isFloating === shouldFloat ) {
+                               return;
+                       }
+                       isFloating = shouldFloat;
                        $area
                                .toggleClass( 'mw-notification-area-floating', isFloating )
                                .toggleClass( 'mw-notification-area-layout', !isFloating );
                }
 
-               $window.on( 'scroll', updateAreaMode );
+               $( window ).on( 'scroll', updateAreaMode );
 
                // Initial mode
                updateAreaMode();
index 7c7aca3..fa1a78c 100644 (file)
                }
 
                /**
-                * defines the location of autocomplete. Typically either
+                * Defines the location of autocomplete. Typically either
                 * header, which is in the top right of vector (for example)
                 * and content which identifies the main search bar on
-                * Special:Search.  Defaults to header for skins that don't set
+                * Special:Search. Defaults to header for skins that don't set
                 * explicitly.
                 *
                 * @ignore
+                * @param {Object} context
+                * @return {string}
                 */
                function getInputLocation( context ) {
                        return context.config.$region
                 * 'this' is the search input box (jQuery object)
                 *
                 * @ignore
+                * @param {Object} metadata
                 */
                function onAfterUpdate( metadata ) {
                        var context = this.data( 'suggestionsContext' );
                                cache: true,
                                highlightInput: true
                        } )
-                       .bind( 'paste cut drop', function () {
+                       .on( 'paste cut drop', function () {
                                // make sure paste and cut events from the mouse and drag&drop events
                                // trigger the keypress handler and cause the suggestions to update
                                $( this ).trigger( 'keypress' );
index a9d17ff..20f8efb 100644 (file)
@@ -1,65 +1,91 @@
 ( function ( mw ) {
        'use strict';
 
-       /**
-        * Library for storing device specific information. It should be used for storing simple
-        * strings and is not suitable for storing large chunks of data.
-        *
-        * @class mw.storage
-        * @singleton
-        */
-       mw.storage = {
-
-               localStorage: ( function () {
-                       // Catch exceptions to avoid fatal in Chrome's "Block data storage" mode
-                       // which throws when accessing the localStorage property itself, as opposed
-                       // to the standard behaviour of throwing on getItem/setItem. (T148998)
+       // Catch exceptions to avoid fatal in Chrome's "Block data storage" mode
+       // which throws when accessing the localStorage property itself, as opposed
+       // to the standard behaviour of throwing on getItem/setItem. (T148998)
+       var
+               localStorage = ( function () {
                        try {
                                return window.localStorage;
                        } catch ( e ) {}
                }() ),
-
-               /**
-                * Retrieve value from device storage.
-                *
-                * @param {string} key Key of item to retrieve
-                * @return {string|boolean} False when localStorage not available, otherwise string
-                */
-               get: function ( key ) {
+               sessionStorage = ( function () {
                        try {
-                               return mw.storage.localStorage.getItem( key );
+                               return window.sessionStorage;
                        } catch ( e ) {}
-                       return false;
-               },
+               }() );
 
-               /**
-                 * Set a value in device storage.
-                 *
-                 * @param {string} key Key name to store under
-                 * @param {string} value Value to be stored
-                 * @return {boolean} Whether the save succeeded or not
-                 */
-               set: function ( key, value ) {
-                       try {
-                               mw.storage.localStorage.setItem( key, value );
-                               return true;
-                       } catch ( e ) {}
-                       return false;
-               },
+       /**
+        * A wrapper for an HTML5 Storage interface (`localStorage` or `sessionStorage`)
+        * that is safe to call on all browsers.
+        *
+        * @class mw.SafeStorage
+        * @private
+        */
 
-               /**
-                 * Remove a value from device storage.
-                 *
-                 * @param {string} key Key of item to remove
-                 * @return {boolean} Whether the save succeeded or not
-                 */
-               remove: function ( key ) {
-                       try {
-                               mw.storage.localStorage.removeItem( key );
-                               return true;
-                       } catch ( e ) {}
-                       return false;
-               }
+       /**
+        * @ignore
+        * @param {Object|undefined} store The Storage instance to wrap around
+        */
+       function SafeStorage( store ) {
+               this.store = store;
+       }
+
+       /**
+        * Retrieve value from device storage.
+        *
+        * @param {string} key Key of item to retrieve
+        * @return {string|boolean} False when localStorage not available, otherwise string
+        */
+       SafeStorage.prototype.get = function ( key ) {
+               try {
+                       return this.store.getItem( key );
+               } catch ( e ) {}
+               return false;
+       };
+
+       /**
+         * Set a value in device storage.
+         *
+         * @param {string} key Key name to store under
+         * @param {string} value Value to be stored
+         * @return {boolean} Whether the save succeeded or not
+         */
+       SafeStorage.prototype.set = function ( key, value ) {
+               try {
+                       this.store.setItem( key, value );
+                       return true;
+               } catch ( e ) {}
+               return false;
+       };
+
+       /**
+         * Remove a value from device storage.
+         *
+         * @param {string} key Key of item to remove
+         * @return {boolean} Whether the save succeeded or not
+         */
+       SafeStorage.prototype.remove = function ( key ) {
+               try {
+                       this.store.removeItem( key );
+                       return true;
+               } catch ( e ) {}
+               return false;
        };
 
+       /**
+        * @class
+        * @singleton
+        * @extends mw.SafeStorage
+        */
+       mw.storage = new SafeStorage( localStorage );
+
+       /**
+        * @class
+        * @singleton
+        * @extends mw.SafeStorage
+        */
+       mw.storage.session = new SafeStorage( sessionStorage );
+
 }( mediaWiki ) );
index 7f62256..9f5e5c4 100644 (file)
@@ -1,4 +1,4 @@
-/*global Mustache */
+/* global Mustache */
 ( function ( mw, $ ) {
        // Register mustache compiler
        mw.template.registerCompiler( 'mustache', {
@@ -16,6 +16,7 @@
                                 * @param {Object} data Data to render
                                 * @param {Object} partialTemplates Map partial names to Mustache template objects
                                 *  returned by mw.template.get()
+                                * @return {jQuery} Rendered HTML
                                 */
                                render: function ( data, partialTemplates ) {
                                        var partials = {};
diff --git a/resources/src/mediawiki/mediawiki.user.blockcookie.js b/resources/src/mediawiki/mediawiki.user.blockcookie.js
new file mode 100644 (file)
index 0000000..ffff039
--- /dev/null
@@ -0,0 +1,23 @@
+( function ( mw ) {
+
+       // If a user has been autoblocked, a cookie is set.
+       // Its value is replicated here in localStorage to guard against cookie-removal.
+       // This module will only be loaded when $wgCookieSetOnAutoblock is true.
+       // Ref: https://phabricator.wikimedia.org/T5233
+
+       if ( !mw.cookie.get( 'BlockID' ) && mw.storage.get( 'blockID' ) ) {
+               // The block ID exists in storage, but not in the cookie.
+               mw.cookie.set( 'BlockID', mw.storage.get( 'blockID' ) );
+
+       } else if ( parseInt( mw.cookie.get( 'BlockID' ), 10 ) > 0 && !mw.storage.get( 'blockID' ) ) {
+               // The block ID exists in the cookie, but not in storage.
+               // (When a block expires the cookie remains but its value is '', hence the integer check above.)
+               mw.storage.set( 'blockID', mw.cookie.get( 'BlockID' ) );
+
+       } else if ( mw.cookie.get( 'BlockID' ) === '' && mw.storage.get( 'blockID' ) ) {
+               // If only the empty string is in the cookie, remove the storage value. The block is no longer valid.
+               mw.storage.remove( 'blockID' );
+
+       }
+
+}( mediaWiki ) );
index 63e7de8..c4c91f9 100644 (file)
@@ -2,10 +2,9 @@
  * @class mw.user
  * @singleton
  */
+/* global Uint32Array */
 ( function ( mw, $ ) {
-       var i,
-               userInfoPromise,
-               byteToHex = [];
+       var userInfoPromise;
 
        /**
         * Get the current user's groups or rights
                return userInfoPromise;
        }
 
-       // Map from numbers 0-255 to a hex string (with padding)
-       for ( i = 0; i < 256; i++ ) {
-               // Padding: Add a full byte (0x100, 256) and strip the extra character
-               byteToHex[ i ] = ( i + 256 ).toString( 16 ).slice( 1 );
-       }
-
        // mw.user with the properties options and tokens gets defined in mediawiki.js.
        $.extend( mw.user, {
 
                 * @return {string} 64 bit integer in hex format, padded
                 */
                generateRandomSessionId: function () {
-                       /*jshint bitwise:false */
-                       var rnds, i, r,
-                               hexRnds = new Array( 8 ),
+                       var rnds, i,
+                               hexRnds = new Array( 2 ),
                                // Support: IE 11
                                crypto = window.crypto || window.msCrypto;
 
-                       // Based on https://github.com/broofa/node-uuid/blob/bfd9f96127/uuid.js
                        if ( crypto && crypto.getRandomValues ) {
-                               // Fill an array with 8 random values, each of which is 8 bits.
-                               // Note that Uint8Array is array-like but does not implement Array.
-                               rnds = new Uint8Array( 8 );
+                               // Fill an array with 2 random values, each of which is 32 bits.
+                               // Note that Uint32Array is array-like but does not implement Array.
+                               rnds = new Uint32Array( 2 );
                                crypto.getRandomValues( rnds );
                        } else {
-                               rnds = new Array( 8 );
-                               for ( i = 0; i < 8; i++ ) {
-                                       if ( ( i & 3 ) === 0 ) {
-                                               r = Math.random() * 0x100000000;
-                                       }
-                                       rnds[ i ] = r >>> ( ( i & 3 ) << 3 ) & 255;
-                               }
+                               rnds = [
+                                       Math.floor( Math.random() * 0x100000000 ),
+                                       Math.floor( Math.random() * 0x100000000 )
+                               ];
                        }
-                       // Convert from number to hex
-                       for ( i = 0; i < 8; i++ ) {
-                               hexRnds[ i ] = byteToHex[ rnds[ i ] ];
+                       // Convert number to a string with 16 hex characters
+                       for ( i = 0; i < 2; i++ ) {
+                               // Add 0x100000000 before converting to hex and strip the extra character
+                               // after converting to keep the leading zeros.
+                               hexRnds[ i ] = ( rnds[ i ] + 0x100000000 ).toString( 16 ).slice( 1 );
                        }
 
                        // Concatenation of two random integers with entropy n and m
                 *  unavailable, or Date for when the user registered.
                 */
                getRegistration: function () {
+                       var registration;
                        if ( mw.user.isAnon() ) {
                                return false;
                        }
-                       var registration = mw.config.get( 'wgUserRegistration' );
+                       registration = mw.config.get( 'wgUserRegistration' );
                        // Registration may be unavailable if the user signed up before MediaWiki
                        // began tracking this.
                        return !registration ? null : new Date( registration );
index 654f232..a8188db 100644 (file)
@@ -50,6 +50,7 @@
                 * Encode the string like PHP's rawurlencode
                 *
                 * @param {string} str String to be encoded.
+                * @return {string} Encoded string
                 */
                rawurlencode: function ( str ) {
                        str = String( str );
@@ -62,6 +63,7 @@
                 * Encode the string like Sanitizer::escapeId in PHP
                 *
                 * @param {string} str String to be encoded.
+                * @return {string} Encoded string
                 */
                escapeId: function ( str ) {
                        str = String( str );
@@ -80,6 +82,7 @@
                 * of `wfUrlencode` in PHP.
                 *
                 * @param {string} str String to be encoded.
+                * @return {string} Encoded string
                 */
                wikiUrlencode: function ( str ) {
                        return util.rawurlencode( str )
                                query = $.param( params );
                        }
                        if ( query ) {
-                               url = title
-                                       ? util.wikiScript() + '?title=' + util.wikiUrlencode( title ) + '&' + query
-                                       util.wikiScript() + '?' + query;
+                               url = title ?
+                                       util.wikiScript() + '?title=' + util.wikiUrlencode( title ) + '&' + query :
+                                       util.wikiScript() + '?' + query;
                        } else {
                                url = mw.config.get( 'wgArticlePath' )
                                        .replace( '$1', util.wikiUrlencode( title ).replace( /\$/g, '$$$$' ) );
                 * @return {Mixed} Parameter value or null.
                 */
                getParamValue: function ( param, url ) {
-                       if ( url === undefined ) {
-                               url = location.href;
-                       }
                        // Get last match, stop at hash
                        var     re = new RegExp( '^[^#]*[&?]' + mw.RegExp.escape( param ) + '=([^&#]*)' ),
-                               m = re.exec( url );
+                               m = re.exec( url !== undefined ? url : location.href );
+
                        if ( m ) {
                                // Beware that decodeURIComponent is not required to understand '+'
                                // by spec, as encodeURIComponent does not produce it.
 
                        html5EmailRegexp = new RegExp(
                                // start of string
-                               '^'
-                               +
+                               '^' +
                                // User part which is liberal :p
-                               '[' + rfc5322Atext + '\\.]+'
-                               +
+                               '[' + rfc5322Atext + '\\.]+' +
                                // 'at'
-                               '@'
-                               +
+                               '@' +
                                // Domain first part
-                               '[' + rfc1034LdhStr + ']+'
-                               +
+                               '[' + rfc1034LdhStr + ']+' +
                                // Optional second part and following are separated by a dot
-                               '(?:\\.[' + rfc1034LdhStr + ']+)*'
-                               +
+                               '(?:\\.[' + rfc1034LdhStr + ']+)*' +
                                // End of string
                                '$',
                                // RegExp is case insensitive
                 * @return {boolean}
                 */
                isIPv4Address: function ( address, allowBlock ) {
+                       var block, RE_IP_BYTE, RE_IP_ADD;
+
                        if ( typeof address !== 'string' ) {
                                return false;
                        }
 
-                       var     block = allowBlock ? '(?:\\/(?:3[0-2]|[12]?\\d))?' : '',
-                               RE_IP_BYTE = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])',
-                               RE_IP_ADD = '(?:' + RE_IP_BYTE + '\\.){3}' + RE_IP_BYTE;
+                       block = allowBlock ? '(?:\\/(?:3[0-2]|[12]?\\d))?' : '';
+                       RE_IP_BYTE = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])';
+                       RE_IP_ADD = '(?:' + RE_IP_BYTE + '\\.){3}' + RE_IP_BYTE;
 
                        return ( new RegExp( '^' + RE_IP_ADD + block + '$' ).test( address ) );
                },
                 * @return {boolean}
                 */
                isIPv6Address: function ( address, allowBlock ) {
+                       var block, RE_IPV6_ADD;
+
                        if ( typeof address !== 'string' ) {
                                return false;
                        }
 
-                       var     block = allowBlock ? '(?:\\/(?:12[0-8]|1[01][0-9]|[1-9]?\\d))?' : '',
-                               RE_IPV6_ADD =
-                       '(?:' + // starts with "::" (including "::")
-                       ':(?::|(?::' + '[0-9A-Fa-f]{1,4}' + '){1,7})' +
-                       '|' + // ends with "::" (except "::")
-                       '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){0,6}::' +
-                       '|' + // contains no "::"
-                       '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){7}' +
-                       ')';
+                       block = allowBlock ? '(?:\\/(?:12[0-8]|1[01][0-9]|[1-9]?\\d))?' : '';
+                       RE_IPV6_ADD =
+                               '(?:' + // starts with "::" (including "::")
+                               ':(?::|(?::' + '[0-9A-Fa-f]{1,4}' + '){1,7})' +
+                               '|' + // ends with "::" (except "::")
+                               '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){0,6}::' +
+                               '|' + // contains no "::"
+                               '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){7}' +
+                               ')';
 
                        if ( new RegExp( '^' + RE_IPV6_ADD + block + '$' ).test( address ) ) {
                                return true;
                        RE_IPV6_ADD = '[0-9A-Fa-f]{1,4}' + '(?:::?' + '[0-9A-Fa-f]{1,4}' + '){1,6}';
 
                        return (
-                               new RegExp( '^' + RE_IPV6_ADD + block + '$' ).test( address )
-                               && /::/.test( address )
-                               && !/::.*::/.test( address )
+                               new RegExp( '^' + RE_IPV6_ADD + block + '$' ).test( address ) &&
+                               /::/.test( address ) &&
+                               !/::.*::/.test( address )
                        );
                },
 
index 6396331..b453ac8 100644 (file)
@@ -18,6 +18,7 @@
                 *
                 * @ignore
                 * @private
+                * @return {Object} Viewport positions
                 */
                makeViewportFromWindow: function () {
                        var $window = $( window ),
@@ -85,7 +86,7 @@
                 */
                isElementCloseToViewport: function ( el, threshold, rectangle ) {
                        var viewport = rectangle ? $.extend( {}, rectangle ) : this.makeViewportFromWindow();
-                       threshold = threshold || 50 ;
+                       threshold = threshold || 50;
 
                        viewport.top -= threshold;
                        viewport.left -= threshold;
index cf448b0..094c4df 100644 (file)
        /**
         * Gets the height of the interface elements and the
         * gallery's caption.
+        *
+        * @return {number} Height
         */
        mw.GallerySlideshow.prototype.getChromeHeight = function () {
                return this.$interface.outerHeight() + this.$galleryCaption.outerHeight();
                if ( this.imageInfoCache[ imageSrc ] === undefined ) {
                        api = new mw.Api();
                        // TODO: This supports only gallery of images
-                       title = new mw.Title.newFromImg( $img );
+                       title = mw.Title.newFromImg( $img );
                        params = {
                                action: 'query',
                                formatversion: 2,
        };
 
        // Bootstrap all slideshow galleries
-       $( function () {
-               $( '.mw-gallery-slideshow' ).each( function () {
-                       /*jshint -W031 */
+       mw.hook( 'wikipage.content' ).add( function ( $content ) {
+               $content.find( '.mw-gallery-slideshow' ).each( function () {
+                       // eslint-disable-next-line no-new
                        new mw.GallerySlideshow( this );
-                       /*jshint +W031 */
                } );
        } );
 }( mediaWiki, jQuery, OO ) );
index 474d541..b7a9132 100644 (file)
@@ -28,8 +28,8 @@ li.gallerycaption {
 
 li.gallerybox div.thumb {
        text-align: center;
-       border: 1px solid #ccc;
-       background-color: #f9f9f9;
+       border: 1px solid #c8ccd1;
+       background-color: #f8f9fa;
        margin: 2px;
 }
 
index 02bc1de..6038a57 100644 (file)
@@ -1,8 +1,10 @@
 /*!
  * Implement AJAX navigation for multi-page images so the user may browse without a full page reload.
  */
+
+/* eslint-disable no-use-before-define */
+
 ( function ( mw, $ ) {
-       /*jshint latedef:false */
        var jqXhr, $multipageimage, $spinner,
                cache = {},
                cacheOrder = [];
index 89bbbe7..6d6d46d 100644 (file)
                                rcid: rcid
                        } )
                        .done( function ( data ) {
+                               var title;
                                // Remove all patrollinks from the page (including any spinners inside).
                                $patrolLinks.closest( '.patrollink' ).remove();
                                if ( data.patrol !== undefined ) {
                                        // Success
-                                       var title = new mw.Title( data.patrol.title );
+                                       title = new mw.Title( data.patrol.title );
                                        mw.notify( mw.msg( 'markedaspatrollednotify', title.toText() ) );
                                } else {
                                        // This should never happen as errors should trigger fail
index 83d14b3..d94b158 100644 (file)
@@ -30,6 +30,7 @@
                        $spinner = $.createSpinner( { size: 'small', type: 'inline' } );
                        $link.hide().after( $spinner );
 
+                       // @todo: data.messageHtml is no more. Convert to using errorformat=html.
                        api = new mw.Api();
                        api.rollback( page, user )
                                .then( function ( data ) {
@@ -43,9 +44,9 @@
                                        }
                                        $( e.delegateTarget ).remove();
                                }, function ( errorCode, data ) {
-                                       var message = data && data.error && data.error.messageHtml
-                                               ? $.parseHTML( data.error.messageHtml )
-                                               mw.msg( 'rollbackfailed' ),
+                                       var message = data && data.error && data.error.messageHtml ?
+                                               $.parseHTML( data.error.messageHtml ) :
+                                               mw.msg( 'rollbackfailed' ),
                                                type = errorCode === 'alreadyrolled' ? 'warn' : 'error';
 
                                        mw.notify( message, {
index 282799a..076357a 100644 (file)
@@ -3,6 +3,7 @@
        mw.page = {};
 
        $( function () {
+               var $diff;
                mw.util.init();
 
                /**
@@ -23,7 +24,7 @@
                 */
                mw.hook( 'wikipage.content' ).fire( $( '#mw-content-text' ) );
 
-               var $diff = $( 'table.diff[data-mw="interface"]' );
+               $diff = $( 'table.diff[data-mw="interface"]' );
                if ( $diff.length ) {
                        /**
                         * Fired when the diff is added to a page containing a diff
index c67b93e..0abb957 100644 (file)
@@ -1,7 +1,7 @@
 // Use DMY date format for Moment.js, in accordance with MediaWiki's date formatting routines.
 // This affects English only (and languages without localisations, that fall back to English).
 // http://momentjs.com/docs/#/customization/long-date-formats/
-/*global moment */
+/* global moment */
 moment.locale( 'en', {
        longDateFormat: {
                // Unchanged, but have to be repeated here:
index dd33b00..13f26f0 100644 (file)
@@ -1,4 +1,4 @@
-/*global moment, mw */
+/* global moment, mw */
 
 // HACK: Overwrite moment's i18n with MediaWiki's for the current language so that
 // wgTranslateNumerals is respected.
index 5f52d1e..c8acc86 100644 (file)
@@ -4,16 +4,16 @@
  */
 
 window.Node = window.Node || {
-       ELEMENT_NODE:                1,
-       ATTRIBUTE_NODE:              2,
-       TEXT_NODE:                   3,
-       CDATA_SECTION_NODE:          4,
-       ENTITY_REFERENCE_NODE:       5,
-       ENTITY_NODE:                 6,
+       ELEMENT_NODE: 1,
+       ATTRIBUTE_NODE: 2,
+       TEXT_NODE: 3,
+       CDATA_SECTION_NODE: 4,
+       ENTITY_REFERENCE_NODE: 5,
+       ENTITY_NODE: 6,
        PROCESSING_INSTRUCTION_NODE: 7,
-       COMMENT_NODE:                8,
-       DOCUMENT_NODE:               9,
-       DOCUMENT_TYPE_NODE:          10,
-       DOCUMENT_FRAGMENT_NODE:      11,
-       NOTATION_NODE:               12
+       COMMENT_NODE: 8,
+       DOCUMENT_NODE: 9,
+       DOCUMENT_TYPE_NODE: 10,
+       DOCUMENT_FRAGMENT_NODE: 11,
+       NOTATION_NODE: 12
 };
index 5e05590..82a00bc 100644 (file)
@@ -3,11 +3,11 @@
  *
  * This file is where we decide whether to initialise the modern run-time.
  */
-/*jshint unused: false */
-/*globals mw, RLQ: true, NORLQ: true, $VARS, $CODE, performance */
 
-var mediaWikiLoadStart = ( new Date() ).getTime(),
+/* global mw, $VARS, $CODE */
 
+// eslint-disable-next-line no-unused-vars
+var mediaWikiLoadStart = ( new Date() ).getTime(),
        mwPerformance = ( window.performance && performance.mark ) ? performance : {
                mark: function () {}
        };
@@ -21,17 +21,19 @@ mwPerformance.mark( 'mwLoadStart' );
  * - DOM Level 4 & Selectors API Level 1
  * - HTML5 & Web Storage
  * - DOM Level 2 Events
+ * - JSON
  *
  * Browsers we support in our modern run-time (Grade A):
- * - Chrome
+ * - Chrome 4+
  * - IE 9+
  * - Firefox 3.5+
- * - Safari 4+
+ * - Safari 5+
  * - Opera 10.5+
- * - Mobile Safari (iOS 1+)
+ * - Mobile Safari (iOS 4+)
  * - Android 2.0+
  *
  * Browsers we support in our no-javascript run-time (Grade C):
+ * - Chrome 1+
  * - IE 6+
  * - Firefox 3+
  * - Safari 3+
@@ -44,30 +46,37 @@ mwPerformance.mark( 'mwLoadStart' );
  * - Nokia's Ovi Browser
  * - MeeGo's browser
  * - Google Glass
+ * - UC Mini (speed mode on)
  *
  * Other browsers that pass the check are considered Grade X.
+ *
+ * @param {string} [str] User agent, defaults to navigator.userAgent
+ * @return {boolean} User agent is compatible with MediaWiki JS
  */
 function isCompatible( str ) {
        var ua = str || navigator.userAgent;
        return !!(
                // http://caniuse.com/#feat=queryselector
-               'querySelector' in document
+               'querySelector' in document &&
 
                // http://caniuse.com/#feat=namevalue-storage
                // https://developer.blackberry.com/html5/apis/v1_0/localstorage.html
                // https://blog.whatwg.org/this-week-in-html-5-episode-30
-               && 'localStorage' in window
+               'localStorage' in window &&
 
                // http://caniuse.com/#feat=addeventlistener
-               && 'addEventListener' in window
+               'addEventListener' in window &&
+
+               // http://caniuse.com/#feat=json
+               // https://phabricator.wikimedia.org/T141344#2784065
+               ( window.JSON && JSON.stringify && JSON.parse ) &&
 
                // Hardcoded exceptions for browsers that pass the requirement but we don't want to
                // support in the modern run-time.
-               && !(
-                       ua.match( /webOS\/1\.[0-4]|SymbianOS|Series60|NetFront|Opera Mini|S40OviBrowser|MeeGo|Android.+Glass/ ) ||
-                       ua.match( /PlayStation/i ) ||
-                       // UC Mini (speed mode on)
-                       ua.match( /^Mozilla\/5\.0 .+ Gecko\/$/ )
+               // Note: Please extend the regex instead of adding new ones
+               !(
+                       ua.match( /webOS\/1\.[0-4]|SymbianOS|Series60|NetFront|Opera Mini|S40OviBrowser|MeeGo|Android.+Glass|^Mozilla\/5\.0 .+ Gecko\/$/ ) ||
+                       ua.match( /PlayStation/i )
                )
        );
 }
@@ -112,6 +121,7 @@ function isCompatible( str ) {
 
                // Must be after mw.config.set because these callbacks may use mw.loader which
                // needs to have values 'skin', 'debug' etc. from mw.config.
+               // eslint-disable-next-line vars-on-top
                var RLQ = window.RLQ || [];
                while ( RLQ.length ) {
                        RLQ.shift()();
index 0bfa318..b67c9ab 100644 (file)
@@ -29,12 +29,15 @@ $wgAutoloadClasses += [
        # tests/common
        'TestSetup' => "$testDir/common/TestSetup.php",
 
+       # tests/integration
+       'MWHttpRequestTestCase' => "$testDir/integration/includes/http/MWHttpRequestTestCase.php",
+
        # tests/parser
        'DbTestPreviewer' => "$testDir/parser/DbTestPreviewer.php",
        'DbTestRecorder' => "$testDir/parser/DbTestRecorder.php",
        'DjVuSupport' => "$testDir/parser/DjVuSupport.php",
-       'TestRecorder' => "$testDir/parser/TestRecorder.php",
        'MultiTestRecorder' => "$testDir/parser/MultiTestRecorder.php",
+       'ParserTestMockParser' => "$testDir/parser/ParserTestMockParser.php",
        'ParserTestRunner' => "$testDir/parser/ParserTestRunner.php",
        'ParserTestParserHook' => "$testDir/parser/ParserTestParserHook.php",
        'ParserTestPrinter' => "$testDir/parser/ParserTestPrinter.php",
diff --git a/tests/integration/includes/http/CurlHttpRequestTest.php b/tests/integration/includes/http/CurlHttpRequestTest.php
new file mode 100644 (file)
index 0000000..04f80f4
--- /dev/null
@@ -0,0 +1,5 @@
+<?php
+
+class CurlHttpRequestTest extends MWHttpRequestTestCase {
+       protected static $httpEngine = 'curl';
+}
diff --git a/tests/integration/includes/http/MWHttpRequestTestCase.php b/tests/integration/includes/http/MWHttpRequestTestCase.php
new file mode 100644 (file)
index 0000000..4fd1cde
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+
+class MWHttpRequestTestCase extends PHPUnit_Framework_TestCase {
+       protected static $httpEngine;
+       protected $oldHttpEngine;
+
+       public function setUp() {
+               parent::setUp();
+               $this->oldHttpEngine = Http::$httpEngine;
+               Http::$httpEngine = static::$httpEngine;
+
+               try {
+                       $request = MWHttpRequest::factory( 'null:' );
+               } catch ( DomainException $e ) {
+                       $this->markTestSkipped( static::$httpEngine . ' engine not supported' );
+               }
+
+               if ( static::$httpEngine === 'php' ) {
+                       $this->assertInstanceOf( PhpHttpRequest::class, $request );
+               } else {
+                       $this->assertInstanceOf( CurlHttpRequest::class, $request );
+               }
+       }
+
+       public function tearDown() {
+               parent::tearDown();
+               Http::$httpEngine = $this->oldHttpEngine;
+       }
+
+       // --------------------
+
+       public function testIsRedirect() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/get' );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertFalse( $request->isRedirect() );
+
+               $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/1' );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertTrue( $request->isRedirect() );
+       }
+
+       public function testgetFinalUrl() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3' );
+               if ( !$request->canFollowRedirects() ) {
+                       $this->markTestSkipped( 'cannot follow redirects' );
+               }
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertNotSame( 'http://httpbin.org/get', $request->getFinalUrl() );
+
+               $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
+                       => true ] );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertSame( 'http://httpbin.org/get', $request->getFinalUrl() );
+               $this->assertResponseFieldValue( 'url', 'http://httpbin.org/get', $request );
+
+               $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
+               => true ] );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertSame( 'http://httpbin.org/get', $request->getFinalUrl() );
+               $this->assertResponseFieldValue( 'url', 'http://httpbin.org/get', $request );
+
+               if ( static::$httpEngine === 'curl' ) {
+                       $this->markTestIncomplete( 'maxRedirects seems to be ignored by CurlHttpRequest' );
+                       return;
+               }
+
+               $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
+               => true, 'maxRedirects' => 1 ] );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertNotSame( 'http://httpbin.org/get', $request->getFinalUrl() );
+       }
+
+       public function testSetCookie() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/cookies' );
+               $request->setCookie( 'foo', 'bar' );
+               $request->setCookie( 'foo2', 'bar2', [ 'domain' => 'example.com' ] );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertResponseFieldValue( 'cookies', [ 'foo' => 'bar' ], $request );
+       }
+
+       public function testSetCookieJar() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/cookies' );
+               $cookieJar = new CookieJar();
+               $cookieJar->setCookie( 'foo', 'bar', [ 'domain' => 'httpbin.org' ] );
+               $cookieJar->setCookie( 'foo2', 'bar2', [ 'domain' => 'example.com' ] );
+               $request->setCookieJar( $cookieJar );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertResponseFieldValue( 'cookies', [ 'foo' => 'bar' ], $request );
+
+               $request = MWHttpRequest::factory( 'http://httpbin.org/cookies/set?foo=bar' );
+               $cookieJar = new CookieJar();
+               $request->setCookieJar( $cookieJar );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertHasCookie( 'foo', 'bar', $request->getCookieJar() );
+
+               $this->markTestIncomplete( 'CookieJar does not handle deletion' );
+               return;
+
+               $request = MWHttpRequest::factory( 'http://httpbin.org/cookies/delete?foo' );
+               $cookieJar = new CookieJar();
+               $cookieJar->setCookie( 'foo', 'bar', [ 'domain' => 'httpbin.org' ] );
+               $cookieJar->setCookie( 'foo2', 'bar2', [ 'domain' => 'httpbin.org' ] );
+               $request->setCookieJar( $cookieJar );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertNotHasCookie( 'foo', $request->getCookieJar() );
+               $this->assertHasCookie( 'foo2', 'bar2', $request->getCookieJar() );
+       }
+
+       public function testGetResponseHeaders() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/response-headers?Foo=bar' );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $headers = array_change_key_case( $request->getResponseHeaders(), CASE_LOWER );
+               $this->assertArrayHasKey( 'foo', $headers );
+               $this->assertSame( $request->getResponseHeader( 'Foo' ), 'bar' );
+       }
+
+       public function testSetHeader() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/headers' );
+               $request->setHeader( 'Foo', 'bar' );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertResponseFieldValue( [ 'headers', 'Foo' ], 'bar', $request );
+       }
+
+       public function testGetStatus() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/status/418' );
+               $status = $request->execute();
+               $this->assertFalse( $status->isOK() );
+               $this->assertSame( $request->getStatus(), 418 );
+       }
+
+       public function testSetUserAgent() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/user-agent' );
+               $request->setUserAgent( 'foo' );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertResponseFieldValue( 'user-agent', 'foo', $request );
+       }
+
+       public function testSetData() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/post', [ 'method' => 'POST' ] );
+               $request->setData( [ 'foo' => 'bar', 'foo2' => 'bar2' ] );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertResponseFieldValue( 'form', [ 'foo' => 'bar', 'foo2' => 'bar2' ], $request );
+       }
+
+       public function testSetCallback() {
+               if ( static::$httpEngine === 'php' ) {
+                       $this->markTestIncomplete( 'PhpHttpRequest does not use setCallback()' );
+                       return;
+               }
+
+               $request = MWHttpRequest::factory( 'http://httpbin.org/ip' );
+               $data = '';
+               $request->setCallback( function ( $fh, $content ) use ( &$data ) {
+                       $data .= $content;
+                       return strlen( $content );
+               } );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $data = json_decode( $data, true );
+               $this->assertInternalType( 'array', $data );
+               $this->assertArrayHasKey( 'origin', $data );
+       }
+
+       public function testBasicAuthentication() {
+               $request = MWHttpRequest::factory( 'http://httpbin.org/basic-auth/user/pass', [
+                       'username' => 'user',
+                       'password' => 'pass',
+               ] );
+               $status = $request->execute();
+               $this->assertTrue( $status->isGood() );
+               $this->assertResponseFieldValue( 'authenticated', true, $request );
+
+               $request = MWHttpRequest::factory( 'http://httpbin.org/basic-auth/user/pass', [
+                       'username' => 'user',
+                       'password' => 'wrongpass',
+               ] );
+               $status = $request->execute();
+               $this->assertFalse( $status->isOK() );
+               $this->assertSame( 401, $request->getStatus() );
+       }
+
+       // --------------------
+
+       /**
+        * Verifies that the request was successful, returned valid JSON and the given field of that
+        * JSON data is as expected.
+        * @param string|string[] $key Path to the data in the response object
+        * @param mixed $expectedValue
+        * @param MWHttpRequest $response
+        */
+       protected function assertResponseFieldValue( $key, $expectedValue, MWHttpRequest $response ) {
+               $this->assertSame( 200, $response->getStatus(), 'response status is not 200' );
+               $data = json_decode( $response->getContent(), true );
+               $this->assertInternalType( 'array', $data, 'response is not JSON' );
+               $keyPath = '';
+               foreach ( (array)$key as $keySegment ) {
+                       $keyPath .= ( $keyPath ? '.' : '' ) . $keySegment;
+                       $this->assertArrayHasKey( $keySegment, $data, $keyPath . ' not found' );
+                       $data = $data[$keySegment];
+               }
+               $this->assertSame( $expectedValue, $data );
+       }
+
+       /**
+        * Asserts that the cookie jar has the given cookie with the given value.
+        * @param string $expectedName Cookie name
+        * @param string $expectedValue Cookie value
+        * @param CookieJar $cookieJar
+        */
+       protected function assertHasCookie( $expectedName, $expectedValue, CookieJar $cookieJar ) {
+               $cookieJar = TestingAccessWrapper::newFromObject( $cookieJar );
+               $cookies = array_change_key_case( $cookieJar->cookie, CASE_LOWER );
+               $this->assertArrayHasKey( strtolower( $expectedName ), $cookies );
+               $cookie = TestingAccessWrapper::newFromObject(
+                       $cookies[strtolower( $expectedName )] );
+               $this->assertSame( $expectedValue, $cookie->value );
+       }
+
+       /**
+        * Asserts that the cookie jar does not have the given cookie.
+        * @param string $expectedName Cookie name
+        * @param CookieJar $cookieJar
+        */
+       protected function assertNotHasCookie( $name, CookieJar $cookieJar ) {
+               $cookieJar = TestingAccessWrapper::newFromObject( $cookieJar );
+               $this->assertArrayNotHasKey( strtolower( $name ),
+                       array_change_key_case( $cookieJar->cookie, CASE_LOWER ) );
+       }
+}
+
diff --git a/tests/integration/includes/http/PhpHttpRequestTest.php b/tests/integration/includes/http/PhpHttpRequestTest.php
new file mode 100644 (file)
index 0000000..d0222a5
--- /dev/null
@@ -0,0 +1,5 @@
+<?php
+
+class PhpHttpRequestTest extends MWHttpRequestTestCase {
+       protected static $httpEngine = 'php';
+}
diff --git a/tests/parser/ParserTestMockParser.php b/tests/parser/ParserTestMockParser.php
new file mode 100644 (file)
index 0000000..0757b34
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * A parser used during article insertion which does nothing, to avoid
+ * unnecessary log noise and other interference with debugging.
+ */
+class ParserTestMockParser {
+       public function preSaveTransform( $text, Title $title, User $user,
+               ParserOptions $options, $clearState = true
+       ) {
+               return $text;
+       }
+
+       public function parse(
+               $text, Title $title, ParserOptions $options,
+               $linestart = true, $clearState = true, $revid = null
+       ) {
+               return new ParserOutput;
+       }
+}
index e433c2e..281e1df 100644 (file)
@@ -426,7 +426,7 @@ class ParserTestRunner {
         * @param ScopedCallback|null A ScopedCallback to consume
         * @return ScopedCallback
         */
-       protected function createTeardownObject( $teardown, $nextTeardown ) {
+       protected function createTeardownObject( $teardown, $nextTeardown = null ) {
                return new ScopedCallback( function() use ( $teardown, $nextTeardown ) {
                        // Schedule teardown snippets in reverse order
                        $teardown = array_reverse( $teardown );
@@ -1503,7 +1503,18 @@ class ParserTestRunner {
                        throw new MWException( "duplicate article '$name' at $file:$line\n" );
                }
 
-               $status = $page->doEditContent( ContentHandler::makeContent( $text, $title ), '', EDIT_NEW );
+               // Use mock parser, to make debugging of actual parser tests simpler.
+               // But initialise the MessageCache clone first, don't let MessageCache
+               // get a reference to the mock object.
+               MessageCache::singleton()->getParser();
+               $restore = $this->executeSetupSnippets( [ 'wgParser' => new ParserTestMockParser ] );
+               $status = $page->doEditContent(
+                       ContentHandler::makeContent( $text, $title ),
+                       '',
+                       EDIT_NEW | EDIT_INTERNAL
+               );
+               $restore();
+
                if ( !$status->isOK() ) {
                        throw new MWException( $status->getWikiText( false, false, 'en' ) );
                }
index 9fe3029..5b17eac 100644 (file)
@@ -7440,6 +7440,23 @@ Piped link with no link text
 <p>[[Thomas Bek (bishop of St David's)|]]</p>
 !! end
 
+!! test
+Piped link with empty link text
+!! wikitext
+[[Main Page|<nowiki />]] - empty nowiki
+[[Main Page| ]] - empty space
+[[Main Page|&nbsp;]] - empty non breaking space
+!! html/php
+<p><a href="/wiki/Main_Page" title="Main Page"></a> - empty nowiki
+<a href="/wiki/Main_Page" title="Main Page"> </a> - empty space
+<a href="/wiki/Main_Page" title="Main Page">&#160;</a> - empty non breaking space
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page"><meta typeof="mw:Placeholder" data-parsoid='{"src":"&lt;nowiki />"}'/></a> - empty nowiki
+<a rel="mw:WikiLink" href="./Main_Page" title="Main Page"> </a> - empty space
+<a rel="mw:WikiLink" href="./Main_Page" title="Main Page"><span typeof="mw:Entity" data-parsoid='{"src":"&amp;nbsp;","srcContent":" "}'> </span></a> - empty non breaking space</p>
+!! end
+
 !! test
 Broken link
 !! wikitext
index e0f4416..db1df5c 100644 (file)
@@ -81,6 +81,13 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         */
        private $mwGlobals = [];
 
+       /**
+        * Holds list of MediaWiki configuration settings to be unset in tearDown().
+        * See also setMwGlobals().
+        * @var array
+        */
+       private $mwGlobalsToUnset = [];
+
        /**
         * Holds original loggers which have been replaced by setLogger()
         * @var LoggerInterface[]
@@ -535,7 +542,11 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                foreach ( $this->mwGlobals as $key => $value ) {
                        $GLOBALS[$key] = $value;
                }
+               foreach ( $this->mwGlobalsToUnset as $value ) {
+                       unset( $GLOBALS[$value] );
+               }
                $this->mwGlobals = [];
+               $this->mwGlobalsToUnset = [];
                $this->restoreLoggers();
 
                if ( self::$serviceLocator && MediaWikiServices::getInstance() !== self::$serviceLocator ) {
@@ -684,8 +695,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         *
         * @param array|string $globalKeys Key to the global variable, or an array of keys.
         *
-        * @throws Exception When trying to stash an unset global
-        *
         * @note To allow changes to global variables to take effect on global service instances,
         *       call overrideMwServices().
         *
@@ -700,9 +709,13 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        // NOTE: make sure we only save the global once or a second call to
                        // setMwGlobals() on the same global would override the original
                        // value.
-                       if ( !array_key_exists( $globalKey, $this->mwGlobals ) ) {
+                       if (
+                               !array_key_exists( $globalKey, $this->mwGlobals ) &&
+                               !array_key_exists( $globalKey, $this->mwGlobalsToUnset )
+                       ) {
                                if ( !array_key_exists( $globalKey, $GLOBALS ) ) {
-                                       throw new Exception( "Global with key {$globalKey} doesn't exist and cant be stashed" );
+                                       $this->mwGlobalsToUnset[$globalKey] = $globalKey;
+                                       continue;
                                }
                                // NOTE: we serialize then unserialize the value in case it is an object
                                // this stops any objects being passed by reference. We could use clone
index 8eb1fd5..45cfdbf 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
 use Psr\Log\LoggerInterface;
 use Psr\Log\NullLogger;
 
@@ -10,14 +11,23 @@ abstract class ResourceLoaderTestCase extends MediaWikiTestCase {
        const BLANK_VERSION = '09p30q0';
 
        /**
-        * @param string $lang
-        * @param string $dir
+        * @param array|string $options Language code or options array
+        * - string 'lang' Language code
+        * - string 'dir' Language direction (ltr or rtl)
         * @return ResourceLoaderContext
         */
-       protected function getResourceLoaderContext( $lang = 'en', $dir = 'ltr' ) {
+       protected function getResourceLoaderContext( $options = [] ) {
+               if ( is_string( $options ) ) {
+                       // Back-compat for extension tests
+                       $options = [ 'lang' => $options ];
+               }
+               $options += [
+                       'lang' => 'en',
+                       'dir' => 'ltr',
+               ];
                $resourceLoader = new ResourceLoader();
                $request = new FauxRequest( [
-                               'lang' => $lang,
+                               'lang' => $options['lang'],
                                'modules' => 'startup',
                                'only' => 'scripts',
                                'skin' => 'vector',
@@ -27,7 +37,7 @@ abstract class ResourceLoaderTestCase extends MediaWikiTestCase {
                        ->setConstructorArgs( [ $resourceLoader, $request ] )
                        ->setMethods( [ 'getDirection' ] )
                        ->getMock();
-               $ctx->method( 'getDirection' )->willReturn( $dir );
+               $ctx->method( 'getDirection' )->willReturn( $options['dir'] );
                return $ctx;
        }
 
@@ -140,7 +150,7 @@ class EmptyResourceLoader extends ResourceLoader {
        // and default registrations are done from ServiceWiring instead.
        public function __construct( Config $config = null, LoggerInterface $logger = null ) {
                $this->setLogger( $logger ?: new NullLogger() );
-               $this->config = $config ?: ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               $this->config = $config ?: MediaWikiServices::getInstance()->getMainConfig();
                $this->setMessageBlobStore( new MessageBlobStore( $this, $this->getLogger() ) );
        }
 }
diff --git a/tests/phpunit/data/localisationcache/ba.json b/tests/phpunit/data/localisationcache/ba.json
new file mode 100644 (file)
index 0000000..59b8912
--- /dev/null
@@ -0,0 +1,3 @@
+{
+       "present-ba": "ba"
+}
index 27600cd..39cce86 100644 (file)
@@ -1,5 +1,5 @@
 {
-       "present-uk": "en",
+       "present-ba": "en",
        "present-ru": "en",
        "present-en": "en"
 }
index 79e1444..c9f89d3 100644 (file)
@@ -1,4 +1,4 @@
 {
-       "present-uk": "ru",
+       "present-ba": "ru",
        "present-ru": "ru"
 }
diff --git a/tests/phpunit/data/localisationcache/uk.json b/tests/phpunit/data/localisationcache/uk.json
deleted file mode 100644 (file)
index f63ce5d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       "present-uk": "uk"
-}
diff --git a/tests/phpunit/includes/HttpTest.php b/tests/phpunit/includes/HttpTest.php
deleted file mode 100644 (file)
index c3804c6..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-<?php
-
-/**
- * @group Http
- */
-class HttpTest extends MediaWikiTestCase {
-       /**
-        * @dataProvider cookieDomains
-        * @covers Cookie::validateCookieDomain
-        */
-       public function testValidateCookieDomain( $expected, $domain, $origin = null ) {
-               if ( $origin ) {
-                       $ok = Cookie::validateCookieDomain( $domain, $origin );
-                       $msg = "$domain against origin $origin";
-               } else {
-                       $ok = Cookie::validateCookieDomain( $domain );
-                       $msg = "$domain";
-               }
-               $this->assertEquals( $expected, $ok, $msg );
-       }
-
-       public static function cookieDomains() {
-               return [
-                       [ false, "org" ],
-                       [ false, ".org" ],
-                       [ true, "wikipedia.org" ],
-                       [ true, ".wikipedia.org" ],
-                       [ false, "co.uk" ],
-                       [ false, ".co.uk" ],
-                       [ false, "gov.uk" ],
-                       [ false, ".gov.uk" ],
-                       [ true, "supermarket.uk" ],
-                       [ false, "uk" ],
-                       [ false, ".uk" ],
-                       [ false, "127.0.0." ],
-                       [ false, "127." ],
-                       [ false, "127.0.0.1." ],
-                       [ true, "127.0.0.1" ],
-                       [ false, "333.0.0.1" ],
-                       [ true, "example.com" ],
-                       [ false, "example.com." ],
-                       [ true, ".example.com" ],
-
-                       [ true, ".example.com", "www.example.com" ],
-                       [ false, "example.com", "www.example.com" ],
-                       [ true, "127.0.0.1", "127.0.0.1" ],
-                       [ false, "127.0.0.1", "localhost" ],
-               ];
-       }
-
-       /**
-        * Test Http::isValidURI()
-        * @bug 27854 : Http::isValidURI is too lax
-        * @dataProvider provideURI
-        * @covers Http::isValidURI
-        */
-       public function testIsValidUri( $expect, $URI, $message = '' ) {
-               $this->assertEquals(
-                       $expect,
-                       (bool)Http::isValidURI( $URI ),
-                       $message
-               );
-       }
-
-       /**
-        * @covers Http::getProxy
-        */
-       public function testGetProxy() {
-               $this->setMwGlobals( 'wgHTTPProxy', 'proxy.domain.tld' );
-               $this->assertEquals(
-                       'proxy.domain.tld',
-                       Http::getProxy()
-               );
-       }
-
-       /**
-        * Feeds URI to test a long regular expression in Http::isValidURI
-        */
-       public static function provideURI() {
-               /** Format: 'boolean expectation', 'URI to test', 'Optional message' */
-               return [
-                       [ false, '¿non sens before!! http://a', 'Allow anything before URI' ],
-
-                       # (http|https) - only two schemes allowed
-                       [ true, 'http://www.example.org/' ],
-                       [ true, 'https://www.example.org/' ],
-                       [ true, 'http://www.example.org', 'URI without directory' ],
-                       [ true, 'http://a', 'Short name' ],
-                       [ true, 'http://étoile', 'Allow UTF-8 in hostname' ], # 'étoile' is french for 'star'
-                       [ false, '\\host\directory', 'CIFS share' ],
-                       [ false, 'gopher://host/dir', 'Reject gopher scheme' ],
-                       [ false, 'telnet://host', 'Reject telnet scheme' ],
-
-                       # :\/\/ - double slashes
-                       [ false, 'http//example.org', 'Reject missing colon in protocol' ],
-                       [ false, 'http:/example.org', 'Reject missing slash in protocol' ],
-                       [ false, 'http:example.org', 'Must have two slashes' ],
-                       # Following fail since hostname can be made of anything
-                       [ false, 'http:///example.org', 'Must have exactly two slashes, not three' ],
-
-                       # (\w+:{0,1}\w*@)? - optional user:pass
-                       [ true, 'http://user@host', 'Username provided' ],
-                       [ true, 'http://user:@host', 'Username provided, no password' ],
-                       [ true, 'http://user:pass@host', 'Username and password provided' ],
-
-                       # (\S+) - host part is made of anything not whitespaces
-                       // commented these out in order to remove @group Broken
-                       // @todo are these valid tests? if so, fix Http::isValidURI so it can handle them
-                       // [ false, 'http://!"èèè¿¿¿~~\'', 'hostname is made of any non whitespace' ],
-                       // [ false, 'http://exam:ple.org/', 'hostname can not use colons!' ],
-
-                       # (:[0-9]+)? - port number
-                       [ true, 'http://example.org:80/' ],
-                       [ true, 'https://example.org:80/' ],
-                       [ true, 'http://example.org:443/' ],
-                       [ true, 'https://example.org:443/' ],
-
-                       # Part after the hostname is / or / with something else
-                       [ true, 'http://example/#' ],
-                       [ true, 'http://example/!' ],
-                       [ true, 'http://example/:' ],
-                       [ true, 'http://example/.' ],
-                       [ true, 'http://example/?' ],
-                       [ true, 'http://example/+' ],
-                       [ true, 'http://example/=' ],
-                       [ true, 'http://example/&' ],
-                       [ true, 'http://example/%' ],
-                       [ true, 'http://example/@' ],
-                       [ true, 'http://example/-' ],
-                       [ true, 'http://example//' ],
-                       [ true, 'http://example/&' ],
-
-                       # Fragment
-                       [ true, 'http://exam#ple.org', ], # This one is valid, really!
-                       [ true, 'http://example.org:80#anchor' ],
-                       [ true, 'http://example.org/?id#anchor' ],
-                       [ true, 'http://example.org/?#anchor' ],
-
-                       [ false, 'http://a ¿non !!sens after', 'Allow anything after URI' ],
-               ];
-       }
-
-       /**
-        * Warning:
-        *
-        * These tests are for code that makes use of an artifact of how CURL
-        * handles header reporting on redirect pages, and will need to be
-        * rewritten when bug 29232 is taken care of (high-level handling of
-        * HTTP redirects).
-        */
-       public function testRelativeRedirections() {
-               $h = MWHttpRequestTester::factory( 'http://oldsite/file.ext', [], __METHOD__ );
-
-               # Forge a Location header
-               $h->setRespHeaders( 'location', [
-                               'http://newsite/file.ext',
-                               '/newfile.ext',
-                       ]
-               );
-               # Verify we correctly fix the Location
-               $this->assertEquals(
-                       'http://newsite/newfile.ext',
-                       $h->getFinalUrl(),
-                       "Relative file path Location: interpreted as full URL"
-               );
-
-               $h->setRespHeaders( 'location', [
-                               'https://oldsite/file.ext'
-                       ]
-               );
-               $this->assertEquals(
-                       'https://oldsite/file.ext',
-                       $h->getFinalUrl(),
-                       "Location to the HTTPS version of the site"
-               );
-
-               $h->setRespHeaders( 'location', [
-                               '/anotherfile.ext',
-                               'http://anotherfile/hoster.ext',
-                               'https://anotherfile/hoster.ext'
-                       ]
-               );
-               $this->assertEquals(
-                       'https://anotherfile/hoster.ext',
-                       $h->getFinalUrl( "Relative file path Location: should keep the latest host and scheme!" )
-               );
-       }
-
-       /**
-        * Constant values are from PHP 5.3.28 using cURL 7.24.0
-        * @see https://secure.php.net/manual/en/curl.constants.php
-        *
-        * All constant values are present so that developers don’t need to remember
-        * to add them if added at a later date. The commented out constants were
-        * not found anywhere in the MediaWiki core code.
-        *
-        * Commented out constants that were not available in:
-        * HipHop VM 3.3.0 (rel)
-        * Compiler: heads/master-0-g08810d920dfff59e0774cf2d651f92f13a637175
-        * Repo schema: 3214fc2c684a4520485f715ee45f33f2182324b1
-        * Extension API: 20140829
-        *
-        * Commented out constants that were removed in PHP 5.6.0
-        *
-        * @covers CurlHttpRequest::execute
-        */
-       public function provideCurlConstants() {
-               return [
-                       [ 'CURLAUTH_ANY' ],
-                       [ 'CURLAUTH_ANYSAFE' ],
-                       [ 'CURLAUTH_BASIC' ],
-                       [ 'CURLAUTH_DIGEST' ],
-                       [ 'CURLAUTH_GSSNEGOTIATE' ],
-                       [ 'CURLAUTH_NTLM' ],
-                       // [ 'CURLCLOSEPOLICY_CALLBACK' ], // removed in PHP 5.6.0
-                       // [ 'CURLCLOSEPOLICY_LEAST_RECENTLY_USED' ], // removed in PHP 5.6.0
-                       // [ 'CURLCLOSEPOLICY_LEAST_TRAFFIC' ], // removed in PHP 5.6.0
-                       // [ 'CURLCLOSEPOLICY_OLDEST' ], // removed in PHP 5.6.0
-                       // [ 'CURLCLOSEPOLICY_SLOWEST' ], // removed in PHP 5.6.0
-                       [ 'CURLE_ABORTED_BY_CALLBACK' ],
-                       [ 'CURLE_BAD_CALLING_ORDER' ],
-                       [ 'CURLE_BAD_CONTENT_ENCODING' ],
-                       [ 'CURLE_BAD_FUNCTION_ARGUMENT' ],
-                       [ 'CURLE_BAD_PASSWORD_ENTERED' ],
-                       [ 'CURLE_COULDNT_CONNECT' ],
-                       [ 'CURLE_COULDNT_RESOLVE_HOST' ],
-                       [ 'CURLE_COULDNT_RESOLVE_PROXY' ],
-                       [ 'CURLE_FAILED_INIT' ],
-                       [ 'CURLE_FILESIZE_EXCEEDED' ],
-                       [ 'CURLE_FILE_COULDNT_READ_FILE' ],
-                       [ 'CURLE_FTP_ACCESS_DENIED' ],
-                       [ 'CURLE_FTP_BAD_DOWNLOAD_RESUME' ],
-                       [ 'CURLE_FTP_CANT_GET_HOST' ],
-                       [ 'CURLE_FTP_CANT_RECONNECT' ],
-                       [ 'CURLE_FTP_COULDNT_GET_SIZE' ],
-                       [ 'CURLE_FTP_COULDNT_RETR_FILE' ],
-                       [ 'CURLE_FTP_COULDNT_SET_ASCII' ],
-                       [ 'CURLE_FTP_COULDNT_SET_BINARY' ],
-                       [ 'CURLE_FTP_COULDNT_STOR_FILE' ],
-                       [ 'CURLE_FTP_COULDNT_USE_REST' ],
-                       [ 'CURLE_FTP_PORT_FAILED' ],
-                       [ 'CURLE_FTP_QUOTE_ERROR' ],
-                       [ 'CURLE_FTP_SSL_FAILED' ],
-                       [ 'CURLE_FTP_USER_PASSWORD_INCORRECT' ],
-                       [ 'CURLE_FTP_WEIRD_227_FORMAT' ],
-                       [ 'CURLE_FTP_WEIRD_PASS_REPLY' ],
-                       [ 'CURLE_FTP_WEIRD_PASV_REPLY' ],
-                       [ 'CURLE_FTP_WEIRD_SERVER_REPLY' ],
-                       [ 'CURLE_FTP_WEIRD_USER_REPLY' ],
-                       [ 'CURLE_FTP_WRITE_ERROR' ],
-                       [ 'CURLE_FUNCTION_NOT_FOUND' ],
-                       [ 'CURLE_GOT_NOTHING' ],
-                       [ 'CURLE_HTTP_NOT_FOUND' ],
-                       [ 'CURLE_HTTP_PORT_FAILED' ],
-                       [ 'CURLE_HTTP_POST_ERROR' ],
-                       [ 'CURLE_HTTP_RANGE_ERROR' ],
-                       [ 'CURLE_LDAP_CANNOT_BIND' ],
-                       [ 'CURLE_LDAP_INVALID_URL' ],
-                       [ 'CURLE_LDAP_SEARCH_FAILED' ],
-                       [ 'CURLE_LIBRARY_NOT_FOUND' ],
-                       [ 'CURLE_MALFORMAT_USER' ],
-                       [ 'CURLE_OBSOLETE' ],
-                       [ 'CURLE_OK' ],
-                       [ 'CURLE_OPERATION_TIMEOUTED' ],
-                       [ 'CURLE_OUT_OF_MEMORY' ],
-                       [ 'CURLE_PARTIAL_FILE' ],
-                       [ 'CURLE_READ_ERROR' ],
-                       [ 'CURLE_RECV_ERROR' ],
-                       [ 'CURLE_SEND_ERROR' ],
-                       [ 'CURLE_SHARE_IN_USE' ],
-                       // [ 'CURLE_SSH' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLE_SSL_CACERT' ],
-                       [ 'CURLE_SSL_CERTPROBLEM' ],
-                       [ 'CURLE_SSL_CIPHER' ],
-                       [ 'CURLE_SSL_CONNECT_ERROR' ],
-                       [ 'CURLE_SSL_ENGINE_NOTFOUND' ],
-                       [ 'CURLE_SSL_ENGINE_SETFAILED' ],
-                       [ 'CURLE_SSL_PEER_CERTIFICATE' ],
-                       [ 'CURLE_TELNET_OPTION_SYNTAX' ],
-                       [ 'CURLE_TOO_MANY_REDIRECTS' ],
-                       [ 'CURLE_UNKNOWN_TELNET_OPTION' ],
-                       [ 'CURLE_UNSUPPORTED_PROTOCOL' ],
-                       [ 'CURLE_URL_MALFORMAT' ],
-                       [ 'CURLE_URL_MALFORMAT_USER' ],
-                       [ 'CURLE_WRITE_ERROR' ],
-                       [ 'CURLFTPAUTH_DEFAULT' ],
-                       [ 'CURLFTPAUTH_SSL' ],
-                       [ 'CURLFTPAUTH_TLS' ],
-                       // [ 'CURLFTPMETHOD_MULTICWD' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLFTPMETHOD_NOCWD' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLFTPMETHOD_SINGLECWD' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLFTPSSL_ALL' ],
-                       [ 'CURLFTPSSL_CONTROL' ],
-                       [ 'CURLFTPSSL_NONE' ],
-                       [ 'CURLFTPSSL_TRY' ],
-                       // [ 'CURLINFO_CERTINFO' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLINFO_CONNECT_TIME' ],
-                       [ 'CURLINFO_CONTENT_LENGTH_DOWNLOAD' ],
-                       [ 'CURLINFO_CONTENT_LENGTH_UPLOAD' ],
-                       [ 'CURLINFO_CONTENT_TYPE' ],
-                       [ 'CURLINFO_EFFECTIVE_URL' ],
-                       [ 'CURLINFO_FILETIME' ],
-                       [ 'CURLINFO_HEADER_OUT' ],
-                       [ 'CURLINFO_HEADER_SIZE' ],
-                       [ 'CURLINFO_HTTP_CODE' ],
-                       [ 'CURLINFO_NAMELOOKUP_TIME' ],
-                       [ 'CURLINFO_PRETRANSFER_TIME' ],
-                       [ 'CURLINFO_PRIVATE' ],
-                       [ 'CURLINFO_REDIRECT_COUNT' ],
-                       [ 'CURLINFO_REDIRECT_TIME' ],
-                       // [ 'CURLINFO_REDIRECT_URL' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLINFO_REQUEST_SIZE' ],
-                       [ 'CURLINFO_SIZE_DOWNLOAD' ],
-                       [ 'CURLINFO_SIZE_UPLOAD' ],
-                       [ 'CURLINFO_SPEED_DOWNLOAD' ],
-                       [ 'CURLINFO_SPEED_UPLOAD' ],
-                       [ 'CURLINFO_SSL_VERIFYRESULT' ],
-                       [ 'CURLINFO_STARTTRANSFER_TIME' ],
-                       [ 'CURLINFO_TOTAL_TIME' ],
-                       [ 'CURLMSG_DONE' ],
-                       [ 'CURLM_BAD_EASY_HANDLE' ],
-                       [ 'CURLM_BAD_HANDLE' ],
-                       [ 'CURLM_CALL_MULTI_PERFORM' ],
-                       [ 'CURLM_INTERNAL_ERROR' ],
-                       [ 'CURLM_OK' ],
-                       [ 'CURLM_OUT_OF_MEMORY' ],
-                       [ 'CURLOPT_AUTOREFERER' ],
-                       [ 'CURLOPT_BINARYTRANSFER' ],
-                       [ 'CURLOPT_BUFFERSIZE' ],
-                       [ 'CURLOPT_CAINFO' ],
-                       [ 'CURLOPT_CAPATH' ],
-                       // [ 'CURLOPT_CERTINFO' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLOPT_CLOSEPOLICY' ], // removed in PHP 5.6.0
-                       [ 'CURLOPT_CONNECTTIMEOUT' ],
-                       [ 'CURLOPT_CONNECTTIMEOUT_MS' ],
-                       [ 'CURLOPT_COOKIE' ],
-                       [ 'CURLOPT_COOKIEFILE' ],
-                       [ 'CURLOPT_COOKIEJAR' ],
-                       [ 'CURLOPT_COOKIESESSION' ],
-                       [ 'CURLOPT_CRLF' ],
-                       [ 'CURLOPT_CUSTOMREQUEST' ],
-                       [ 'CURLOPT_DNS_CACHE_TIMEOUT' ],
-                       [ 'CURLOPT_DNS_USE_GLOBAL_CACHE' ],
-                       [ 'CURLOPT_EGDSOCKET' ],
-                       [ 'CURLOPT_ENCODING' ],
-                       [ 'CURLOPT_FAILONERROR' ],
-                       [ 'CURLOPT_FILE' ],
-                       [ 'CURLOPT_FILETIME' ],
-                       [ 'CURLOPT_FOLLOWLOCATION' ],
-                       [ 'CURLOPT_FORBID_REUSE' ],
-                       [ 'CURLOPT_FRESH_CONNECT' ],
-                       [ 'CURLOPT_FTPAPPEND' ],
-                       [ 'CURLOPT_FTPLISTONLY' ],
-                       [ 'CURLOPT_FTPPORT' ],
-                       [ 'CURLOPT_FTPSSLAUTH' ],
-                       [ 'CURLOPT_FTP_CREATE_MISSING_DIRS' ],
-                       // [ 'CURLOPT_FTP_FILEMETHOD' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLOPT_FTP_SKIP_PASV_IP' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLOPT_FTP_SSL' ],
-                       [ 'CURLOPT_FTP_USE_EPRT' ],
-                       [ 'CURLOPT_FTP_USE_EPSV' ],
-                       [ 'CURLOPT_HEADER' ],
-                       [ 'CURLOPT_HEADERFUNCTION' ],
-                       [ 'CURLOPT_HTTP200ALIASES' ],
-                       [ 'CURLOPT_HTTPAUTH' ],
-                       [ 'CURLOPT_HTTPGET' ],
-                       [ 'CURLOPT_HTTPHEADER' ],
-                       [ 'CURLOPT_HTTPPROXYTUNNEL' ],
-                       [ 'CURLOPT_HTTP_VERSION' ],
-                       [ 'CURLOPT_INFILE' ],
-                       [ 'CURLOPT_INFILESIZE' ],
-                       [ 'CURLOPT_INTERFACE' ],
-                       [ 'CURLOPT_IPRESOLVE' ],
-                       // [ 'CURLOPT_KEYPASSWD' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLOPT_KRB4LEVEL' ],
-                       [ 'CURLOPT_LOW_SPEED_LIMIT' ],
-                       [ 'CURLOPT_LOW_SPEED_TIME' ],
-                       [ 'CURLOPT_MAXCONNECTS' ],
-                       [ 'CURLOPT_MAXREDIRS' ],
-                       // [ 'CURLOPT_MAX_RECV_SPEED_LARGE' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLOPT_MAX_SEND_SPEED_LARGE' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLOPT_NETRC' ],
-                       [ 'CURLOPT_NOBODY' ],
-                       [ 'CURLOPT_NOPROGRESS' ],
-                       [ 'CURLOPT_NOSIGNAL' ],
-                       [ 'CURLOPT_PORT' ],
-                       [ 'CURLOPT_POST' ],
-                       [ 'CURLOPT_POSTFIELDS' ],
-                       [ 'CURLOPT_POSTQUOTE' ],
-                       [ 'CURLOPT_POSTREDIR' ],
-                       [ 'CURLOPT_PRIVATE' ],
-                       [ 'CURLOPT_PROGRESSFUNCTION' ],
-                       // [ 'CURLOPT_PROTOCOLS' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLOPT_PROXY' ],
-                       [ 'CURLOPT_PROXYAUTH' ],
-                       [ 'CURLOPT_PROXYPORT' ],
-                       [ 'CURLOPT_PROXYTYPE' ],
-                       [ 'CURLOPT_PROXYUSERPWD' ],
-                       [ 'CURLOPT_PUT' ],
-                       [ 'CURLOPT_QUOTE' ],
-                       [ 'CURLOPT_RANDOM_FILE' ],
-                       [ 'CURLOPT_RANGE' ],
-                       [ 'CURLOPT_READDATA' ],
-                       [ 'CURLOPT_READFUNCTION' ],
-                       // [ 'CURLOPT_REDIR_PROTOCOLS' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLOPT_REFERER' ],
-                       [ 'CURLOPT_RESUME_FROM' ],
-                       [ 'CURLOPT_RETURNTRANSFER' ],
-                       // [ 'CURLOPT_SSH_AUTH_TYPES' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLOPT_SSH_HOST_PUBLIC_KEY_MD5' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLOPT_SSH_PRIVATE_KEYFILE' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLOPT_SSH_PUBLIC_KEYFILE' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLOPT_SSLCERT' ],
-                       [ 'CURLOPT_SSLCERTPASSWD' ],
-                       [ 'CURLOPT_SSLCERTTYPE' ],
-                       [ 'CURLOPT_SSLENGINE' ],
-                       [ 'CURLOPT_SSLENGINE_DEFAULT' ],
-                       [ 'CURLOPT_SSLKEY' ],
-                       [ 'CURLOPT_SSLKEYPASSWD' ],
-                       [ 'CURLOPT_SSLKEYTYPE' ],
-                       [ 'CURLOPT_SSLVERSION' ],
-                       [ 'CURLOPT_SSL_CIPHER_LIST' ],
-                       [ 'CURLOPT_SSL_VERIFYHOST' ],
-                       [ 'CURLOPT_SSL_VERIFYPEER' ],
-                       [ 'CURLOPT_STDERR' ],
-                       [ 'CURLOPT_TCP_NODELAY' ],
-                       [ 'CURLOPT_TIMECONDITION' ],
-                       [ 'CURLOPT_TIMEOUT' ],
-                       [ 'CURLOPT_TIMEOUT_MS' ],
-                       [ 'CURLOPT_TIMEVALUE' ],
-                       [ 'CURLOPT_TRANSFERTEXT' ],
-                       [ 'CURLOPT_UNRESTRICTED_AUTH' ],
-                       [ 'CURLOPT_UPLOAD' ],
-                       [ 'CURLOPT_URL' ],
-                       [ 'CURLOPT_USERAGENT' ],
-                       [ 'CURLOPT_USERPWD' ],
-                       [ 'CURLOPT_VERBOSE' ],
-                       [ 'CURLOPT_WRITEFUNCTION' ],
-                       [ 'CURLOPT_WRITEHEADER' ],
-                       // [ 'CURLPROTO_ALL' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_DICT' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_FILE' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_FTP' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_FTPS' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_HTTP' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_HTTPS' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_LDAP' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_LDAPS' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_SCP' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_SFTP' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_TELNET' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLPROTO_TFTP' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLPROXY_HTTP' ],
-                       // [ 'CURLPROXY_SOCKS4' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLPROXY_SOCKS5' ],
-                       // [ 'CURLSSH_AUTH_DEFAULT' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLSSH_AUTH_HOST' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLSSH_AUTH_KEYBOARD' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLSSH_AUTH_NONE' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLSSH_AUTH_PASSWORD' ], // not present in HHVM 3.3.0-dev
-                       // [ 'CURLSSH_AUTH_PUBLICKEY' ], // not present in HHVM 3.3.0-dev
-                       [ 'CURLVERSION_NOW' ],
-                       [ 'CURL_HTTP_VERSION_1_0' ],
-                       [ 'CURL_HTTP_VERSION_1_1' ],
-                       [ 'CURL_HTTP_VERSION_NONE' ],
-                       [ 'CURL_IPRESOLVE_V4' ],
-                       [ 'CURL_IPRESOLVE_V6' ],
-                       [ 'CURL_IPRESOLVE_WHATEVER' ],
-                       [ 'CURL_NETRC_IGNORED' ],
-                       [ 'CURL_NETRC_OPTIONAL' ],
-                       [ 'CURL_NETRC_REQUIRED' ],
-                       [ 'CURL_TIMECOND_IFMODSINCE' ],
-                       [ 'CURL_TIMECOND_IFUNMODSINCE' ],
-                       [ 'CURL_TIMECOND_LASTMOD' ],
-                       [ 'CURL_VERSION_IPV6' ],
-                       [ 'CURL_VERSION_KERBEROS4' ],
-                       [ 'CURL_VERSION_LIBZ' ],
-                       [ 'CURL_VERSION_SSL' ],
-               ];
-       }
-
-       /**
-        * Added this test based on an issue experienced with HHVM 3.3.0-dev
-        * where it did not define a cURL constant.
-        *
-        * @bug 70570
-        * @dataProvider provideCurlConstants
-        */
-       public function testCurlConstants( $value ) {
-               $this->assertTrue( defined( $value ), $value . ' not defined' );
-       }
-}
-
-/**
- * Class to let us overwrite MWHttpRequest respHeaders variable
- */
-class MWHttpRequestTester extends MWHttpRequest {
-       // function derived from the MWHttpRequest factory function but
-       // returns appropriate tester class here
-       public static function factory( $url, $options = null, $caller = __METHOD__ ) {
-               if ( !Http::$httpEngine ) {
-                       Http::$httpEngine = function_exists( 'curl_init' ) ? 'curl' : 'php';
-               } elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) {
-                       throw new MWException( __METHOD__ . ': curl (http://php.net/curl) is not installed, but' .
-                               'Http::$httpEngine is set to "curl"' );
-               }
-
-               switch ( Http::$httpEngine ) {
-                       case 'curl':
-                               return new CurlHttpRequestTester( $url, $options, $caller );
-                       case 'php':
-                               if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
-                                       throw new MWException( __METHOD__ .
-                                               ': allow_url_fopen needs to be enabled for pure PHP HTTP requests to work. '
-                                                       . 'If possible, curl should be used instead. See http://php.net/curl.' );
-                               }
-
-                               return new PhpHttpRequestTester( $url, $options, $caller );
-                       default:
-               }
-       }
-}
-
-class CurlHttpRequestTester extends CurlHttpRequest {
-       function setRespHeaders( $name, $value ) {
-               $this->respHeaders[$name] = $value;
-       }
-}
-
-class PhpHttpRequestTester extends PhpHttpRequest {
-       function setRespHeaders( $name, $value ) {
-               $this->respHeaders[$name] = $value;
-       }
-}
index 8390e1f..4fe806c 100644 (file)
@@ -512,6 +512,136 @@ class MessageTest extends MediaWikiLangTestCase {
                );
        }
 
+       public static function provideListParam() {
+               $lang = Language::factory( 'de' );
+               $msg1 = new Message( 'mainpage', [], $lang );
+               $msg2 = new RawMessage( "''link''", [], $lang );
+
+               return [
+                       'Simple comma list' => [
+                               [ 'a', 'b', 'c' ],
+                               'comma',
+                               'text',
+                               'a, b, c'
+                       ],
+
+                       'Simple semicolon list' => [
+                               [ 'a', 'b', 'c' ],
+                               'semicolon',
+                               'text',
+                               'a; b; c'
+                       ],
+
+                       'Simple pipe list' => [
+                               [ 'a', 'b', 'c' ],
+                               'pipe',
+                               'text',
+                               'a | b | c'
+                       ],
+
+                       'Simple text list' => [
+                               [ 'a', 'b', 'c' ],
+                               'text',
+                               'text',
+                               'a, b and c'
+                       ],
+
+                       'Empty list' => [
+                               [],
+                               'comma',
+                               'text',
+                               ''
+                       ],
+
+                       'List with all "before" params, ->text()' => [
+                               [ "''link''", Message::numParam( 12345678 ) ],
+                               'semicolon',
+                               'text',
+                               '\'\'link\'\'; 12,345,678'
+                       ],
+
+                       'List with all "before" params, ->parse()' => [
+                               [ "''link''", Message::numParam( 12345678 ) ],
+                               'semicolon',
+                               'parse',
+                               '<i>link</i>; 12,345,678'
+                       ],
+
+                       'List with all "after" params, ->text()' => [
+                               [ $msg1, $msg2, Message::rawParam( '[[foo]]' ) ],
+                               'semicolon',
+                               'text',
+                               'Main Page; \'\'link\'\'; [[foo]]'
+                       ],
+
+                       'List with all "after" params, ->parse()' => [
+                               [ $msg1, $msg2, Message::rawParam( '[[foo]]' ) ],
+                               'semicolon',
+                               'parse',
+                               'Main Page; <i>link</i>; [[foo]]'
+                       ],
+
+                       'List with both "before" and "after" params, ->text()' => [
+                               [ $msg1, $msg2, Message::rawParam( '[[foo]]' ), "''link''", Message::numParam( 12345678 ) ],
+                               'semicolon',
+                               'text',
+                               'Main Page; \'\'link\'\'; [[foo]]; \'\'link\'\'; 12,345,678'
+                       ],
+
+                       'List with both "before" and "after" params, ->parse()' => [
+                               [ $msg1, $msg2, Message::rawParam( '[[foo]]' ), "''link''", Message::numParam( 12345678 ) ],
+                               'semicolon',
+                               'parse',
+                               'Main Page; <i>link</i>; [[foo]]; <i>link</i>; 12,345,678'
+                       ],
+               ];
+       }
+
+       /**
+        * @covers Message::listParam
+        * @covers Message::extractParam
+        * @covers Message::formatListParam
+        * @dataProvider provideListParam
+        */
+       public function testListParam( $list, $type, $format, $expect ) {
+               $lang = Language::factory( 'en' );
+
+               $msg = new RawMessage( '$1' );
+               $msg->params( [ Message::listParam( $list, $type ) ] );
+               $this->assertEquals(
+                       $expect,
+                       $msg->inLanguage( $lang )->$format()
+               );
+       }
+
+       /**
+        * @covers Message::extractParam
+        */
+       public function testMessageAsParam() {
+               $this->setMwGlobals( [
+                       'wgScript' => '/wiki/index.php',
+                       'wgArticlePath' => '/wiki/$1',
+               ] );
+
+               $msg = new Message( 'returnto', [
+                       new Message( 'apihelp-link', [
+                               'foo', new Message( 'mainpage', [], Language::factory( 'en' ) )
+                       ], Language::factory( 'de' ) )
+               ], Language::factory( 'es' ) );
+
+               $this->assertEquals(
+                       'Volver a [[Special:ApiHelp/foo|Página principal]].',
+                       $msg->text(),
+                       'Process with ->text()'
+               );
+               $this->assertEquals(
+                       '<p>Volver a <a href="/wiki/Special:ApiHelp/foo" title="Special:ApiHelp/foo">Página '
+                               . "principal</a>.\n</p>",
+                       $msg->parseAsBlock(),
+                       'Process with ->parseAsBlock()'
+               );
+       }
+
        public static function provideParser() {
                return [
                        [
index c637d34..6269872 100644 (file)
@@ -305,6 +305,37 @@ class OutputPageTest extends MediaWikiTestCase {
                $request->setCookie( 'Token', '123' );
                $this->assertTrue( $outputPage->haveCacheVaryCookies() );
        }
+
+       /*
+        * @covers OutputPage::addCategoryLinks
+        * @covers OutputPage::getCategories
+        */
+       function testGetCategories() {
+               $fakeResultWrapper = new FakeResultWrapper( [
+                       (object) [
+                               'pp_value' => 1,
+                               'page_title' => 'Test'
+                       ],
+                       (object) [
+                               'page_title' => 'Test2'
+                       ]
+               ] );
+               $outputPage = $this->getMockBuilder( 'OutputPage' )
+                       ->setConstructorArgs( [ new RequestContext() ] )
+                       ->setMethods( [ 'addCategoryLinksToLBAndGetResult' ] )
+                       ->getMock();
+               $outputPage->expects( $this->any() )
+                       ->method( 'addCategoryLinksToLBAndGetResult' )
+                       ->will( $this->returnValue( $fakeResultWrapper ) );
+
+               $outputPage->addCategoryLinks( [
+                       'Test' => 'Test',
+                       'Test2' => 'Test2',
+               ] );
+               $this->assertEquals( [ 0 => 'Test', '1' => 'Test2' ], $outputPage->getCategories() );
+               $this->assertEquals( [ 0 => 'Test2' ], $outputPage->getCategories( 'normal' ) );
+               $this->assertEquals( [ 0 => 'Test' ], $outputPage->getCategories( 'hidden' ) );
+       }
 }
 
 /**
index bc43709..c5a7e04 100644 (file)
@@ -129,11 +129,11 @@ class PrefixSearchTest extends MediaWikiLangTestCase {
                                'results' => [
                                        'Special:ActiveUsers',
                                        'Special:AllMessages',
-                                       'Special:AllMyFiles',
+                                       'Special:AllMyUploads',
                                ],
                                // Third result when testing offset
                                'offsetresult' => [
-                                       'Special:AllMyUploads',
+                                       'Special:AllPages',
                                ],
                        ] ],
                        [ [
@@ -146,7 +146,7 @@ class PrefixSearchTest extends MediaWikiLangTestCase {
                                ],
                                // Third result when testing offset
                                'offsetresult' => [
-                                       'Special:UncategorizedImages',
+                                       'Special:UncategorizedPages',
                                ],
                        ] ],
                        [ [
index 93687df..bdec0a5 100644 (file)
@@ -1233,7 +1233,7 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
                        ->with( 'watchlisttoken' )
                        ->willReturn( '0123456789abcdef' );
 
-               $this->setExpectedException( UsageException::class, 'Incorrect watchlist token provided' );
+               $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
                $queryService->getWatchedItemsWithRecentChangeInfo(
                        $user,
                        [ 'watchlistOwner' => $otherUser, 'watchlistOwnerToken' => $token ]
index dbd1299..18ff1f4 100644 (file)
@@ -305,17 +305,6 @@ class XmlTest extends MediaWikiTestCase {
                );
        }
 
-       /**
-        * @covers Xml::escapeJsString
-        */
-       public function testEscapeJsStringSpecialChars() {
-               $this->assertEquals(
-                       '\\\\\r\n',
-                       Xml::escapeJsString( "\\\r\n" ),
-                       'escapeJsString() with special characters'
-               );
-       }
-
        /**
         * @covers Xml::encodeJsVar
         */
index 8b75d56..96f3e44 100644 (file)
@@ -20,7 +20,7 @@ class ApiBaseTest extends ApiTestCase {
        }
 
        /**
-        * @expectedException UsageException
+        * @expectedException ApiUsageException
         * @covers ApiBase::requireOnlyOneParameter
         */
        public function testRequireOnlyOneParameterZero() {
@@ -32,7 +32,7 @@ class ApiBaseTest extends ApiTestCase {
        }
 
        /**
-        * @expectedException UsageException
+        * @expectedException ApiUsageException
         * @covers ApiBase::requireOnlyOneParameter
         */
        public function testRequireOnlyOneParameterTrue() {
@@ -58,10 +58,10 @@ class ApiBaseTest extends ApiTestCase {
                $context->setRequest( new FauxRequest( $input !== null ? [ 'foo' => $input ] : [] ) );
                $wrapper->mMainModule = new ApiMain( $context );
 
-               if ( $expected instanceof UsageException ) {
+               if ( $expected instanceof ApiUsageException ) {
                        try {
                                $wrapper->getParameterFromSettings( 'foo', $paramSettings, true );
-                       } catch ( UsageException $ex ) {
+                       } catch ( ApiUsageException $ex ) {
                                $this->assertEquals( $expected, $ex );
                        }
                } else {
@@ -73,9 +73,7 @@ class ApiBaseTest extends ApiTestCase {
 
        public static function provideGetParameterFromSettings() {
                $warnings = [
-                       'The value passed for \'foo\' contains invalid or non-normalized data. Textual data should ' .
-                       'be valid, NFC-normalized Unicode without C0 control characters other than ' .
-                       'HT (\\t), LF (\\n), and CR (\\r).'
+                       [ 'apiwarn-badutf8', 'foo' ],
                ];
 
                $c0 = '';
@@ -96,7 +94,7 @@ class ApiBaseTest extends ApiTestCase {
                        'String param, required, empty' => [
                                '',
                                [ ApiBase::PARAM_DFLT => 'default', ApiBase::PARAM_REQUIRED => true ],
-                               new UsageException( 'The foo parameter must be set', 'nofoo' ),
+                               ApiUsageException::newWithMessage( null, [ 'apierror-missingparam', 'foo' ] ),
                                []
                        ],
                        'Multi-valued parameter' => [
@@ -126,4 +124,48 @@ class ApiBaseTest extends ApiTestCase {
                ];
        }
 
+       public function testErrorArrayToStatus() {
+               $mock = new MockApi();
+
+               // Sanity check empty array
+               $expect = Status::newGood();
+               $this->assertEquals( $expect, $mock->errorArrayToStatus( [] ) );
+
+               // No blocked $user, so no special block handling
+               $expect = Status::newGood();
+               $expect->fatal( 'blockedtext' );
+               $expect->fatal( 'autoblockedtext' );
+               $expect->fatal( 'mainpage' );
+               $expect->fatal( 'parentheses', 'foobar' );
+               $this->assertEquals( $expect, $mock->errorArrayToStatus( [
+                       [ 'blockedtext' ],
+                       [ 'autoblockedtext' ],
+                       'mainpage',
+                       [ 'parentheses', 'foobar' ],
+               ] ) );
+
+               // Has a blocked $user, so special block handling
+               $user = $this->getMutableTestUser()->getUser();
+               $block = new \Block( [
+                       'address' => $user->getName(),
+                       'user' => $user->getID(),
+                       'reason' => __METHOD__,
+                       'expiry' => time() + 100500,
+               ] );
+               $block->insert();
+               $blockinfo = [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $block ) ];
+
+               $expect = Status::newGood();
+               $expect->fatal( ApiMessage::create( 'apierror-blocked', 'blocked', $blockinfo ) );
+               $expect->fatal( ApiMessage::create( 'apierror-autoblocked', 'autoblocked', $blockinfo ) );
+               $expect->fatal( 'mainpage' );
+               $expect->fatal( 'parentheses', 'foobar' );
+               $this->assertEquals( $expect, $mock->errorArrayToStatus( [
+                       [ 'blockedtext' ],
+                       [ 'autoblockedtext' ],
+                       'mainpage',
+                       [ 'parentheses', 'foobar' ],
+               ], $user ) );
+       }
+
 }
index d2dccf9..08fc128 100644 (file)
@@ -65,8 +65,8 @@ class ApiBlockTest extends ApiTestCase {
        }
 
        /**
-        * @expectedException UsageException
-        * @expectedExceptionMessage The token parameter must be set
+        * @expectedException ApiUsageException
+        * @expectedExceptionMessage The "token" parameter must be set
         */
        public function testBlockingActionWithNoToken() {
                $this->doApiRequest(
index 3ad16d1..bb4ea75 100644 (file)
@@ -160,10 +160,8 @@ class ApiContinuationManagerTest extends MediaWikiTestCase {
                try {
                        self::getManager( 'foo', $allModules, [ 'mock1', 'mock2' ] );
                        $this->fail( 'Expected exception not thrown' );
-               } catch ( UsageException $ex ) {
-                       $this->assertSame(
-                               'Invalid continue param. You should pass the original value returned by the previous query',
-                               $ex->getMessage(),
+               } catch ( ApiUsageException $ex ) {
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'badcontinue' ),
                                'Expected exception'
                        );
                }
index 02d0a0d..0ffcbca 100644 (file)
@@ -195,9 +195,9 @@ class ApiEditPageTest extends ApiTestCase {
                                'section' => '9999',
                                'text' => 'text',
                        ] );
-                       $this->fail( "Should have raised a UsageException" );
-               } catch ( UsageException $e ) {
-                       $this->assertEquals( 'nosuchsection', $e->getCodeString() );
+                       $this->fail( "Should have raised an ApiUsageException" );
+               } catch ( ApiUsageException $e ) {
+                       $this->assertTrue( self::apiExceptionHasCode( $e, 'nosuchsection' ) );
                }
        }
 
@@ -333,8 +333,8 @@ class ApiEditPageTest extends ApiTestCase {
                        ], null, self::$users['sysop']->getUser() );
 
                        $this->fail( 'redirect-appendonly error expected' );
-               } catch ( UsageException $ex ) {
-                       $this->assertEquals( 'redirect-appendonly', $ex->getCodeString() );
+               } catch ( ApiUsageException $ex ) {
+                       $this->assertTrue( self::apiExceptionHasCode( $ex, 'redirect-appendonly' ) );
                }
        }
 
@@ -369,8 +369,8 @@ class ApiEditPageTest extends ApiTestCase {
                        ], null, self::$users['sysop']->getUser() );
 
                        $this->fail( 'edit conflict expected' );
-               } catch ( UsageException $ex ) {
-                       $this->assertEquals( 'editconflict', $ex->getCodeString() );
+               } catch ( ApiUsageException $ex ) {
+                       $this->assertTrue( self::apiExceptionHasCode( $ex, 'editconflict' ) );
                }
        }
 
@@ -474,7 +474,7 @@ class ApiEditPageTest extends ApiTestCase {
 
        public function testCheckDirectApiEditingDisallowed_forNonTextContent() {
                $this->setExpectedException(
-                       'UsageException',
+                       'ApiUsageException',
                        'Direct editing via API is not supported for content model ' .
                                'testing used by Dummy:ApiEditPageTest_nonTextPageEdit'
                );
index d13b00b..1b7f6bf 100644 (file)
@@ -5,6 +5,30 @@
  */
 class ApiErrorFormatterTest extends MediaWikiLangTestCase {
 
+       /**
+        * @covers ApiErrorFormatter
+        */
+       public function testErrorFormatterBasics() {
+               $result = new ApiResult( 8388608 );
+               $formatter = new ApiErrorFormatter( $result, Language::factory( 'de' ), 'wikitext', false );
+               $this->assertSame( 'de', $formatter->getLanguage()->getCode() );
+
+               $formatter->addMessagesFromStatus( null, Status::newGood() );
+               $this->assertSame(
+                       [ ApiResult::META_TYPE => 'assoc' ],
+                       $result->getResultData()
+               );
+
+               $this->assertSame( [], $formatter->arrayFromStatus( Status::newGood() ) );
+
+               $wrappedFormatter = TestingAccessWrapper::newFromObject( $formatter );
+               $this->assertSame(
+                       'Blah "kbd" <X> 😊',
+                       $wrappedFormatter->stripMarkup( 'Blah <kbd>kbd</kbd> <b>&lt;X&gt;</b> &#x1f60a;' ),
+                       'stripMarkup'
+               );
+       }
+
        /**
         * @covers ApiErrorFormatter
         * @dataProvider provideErrorFormatter
@@ -22,7 +46,7 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
 
                $formatter->addWarning( 'string', 'mainpage' );
                $formatter->addError( 'err', 'mainpage' );
-               $this->assertSame( $expect1, $result->getResultData(), 'Simple test' );
+               $this->assertEquals( $expect1, $result->getResultData(), 'Simple test' );
 
                $result->reset();
                $formatter->addWarning( 'foo', 'mainpage' );
@@ -35,6 +59,17 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                $formatter->addError( 'errWithData', $msg2 );
                $this->assertSame( $expect2, $result->getResultData(), 'Complex test' );
 
+               $this->assertEquals(
+                       $this->removeModuleTag( $expect2['warnings'][2] ),
+                       $formatter->formatMessage( $msg1 ),
+                       'formatMessage test 1'
+               );
+               $this->assertEquals(
+                       $this->removeModuleTag( $expect2['warnings'][3] ),
+                       $formatter->formatMessage( $msg2 ),
+                       'formatMessage test 2'
+               );
+
                $result->reset();
                $status = Status::newGood();
                $status->warning( 'mainpage' );
@@ -47,245 +82,256 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                $this->assertSame( $expect3, $result->getResultData(), 'Status test' );
 
                $this->assertSame(
-                       $expect3['errors']['status'],
+                       array_map( [ $this, 'removeModuleTag' ], $expect3['errors'] ),
                        $formatter->arrayFromStatus( $status, 'error' ),
                        'arrayFromStatus test for error'
                );
                $this->assertSame(
-                       $expect3['warnings']['status'],
+                       array_map( [ $this, 'removeModuleTag' ], $expect3['warnings'] ),
                        $formatter->arrayFromStatus( $status, 'warning' ),
                        'arrayFromStatus test for warning'
                );
        }
 
+       private function removeModuleTag( $s ) {
+               if ( is_array( $s ) ) {
+                       unset( $s['module'] );
+               }
+               return $s;
+       }
+
        public static function provideErrorFormatter() {
-               $mainpagePlain = wfMessage( 'mainpage' )->useDatabase( false )->plain();
-               $parensPlain = wfMessage( 'parentheses', 'foobar' )->useDatabase( false )->plain();
-               $mainpageText = wfMessage( 'mainpage' )->inLanguage( 'de' )->text();
-               $parensText = wfMessage( 'parentheses', 'foobar' )->inLanguage( 'de' )->text();
+               $mainpageText = wfMessage( 'mainpage' )->inLanguage( 'de' )->useDatabase( false )->text();
+               $parensText = wfMessage( 'parentheses', 'foobar' )->inLanguage( 'de' )
+                       ->useDatabase( false )->text();
+               $mainpageHTML = wfMessage( 'mainpage' )->inLanguage( 'en' )->parse();
+               $parensHTML = wfMessage( 'parentheses', 'foobar' )->inLanguage( 'en' )->parse();
                $C = ApiResult::META_CONTENT;
                $I = ApiResult::META_INDEXED_TAG_NAME;
+               $overriddenData = [ 'overriddenData' => true, ApiResult::META_TYPE => 'assoc' ];
 
                return [
-                       [ 'wikitext', 'de', true,
+                       $tmp = [ 'wikitext', 'de', false,
                                [
                                        'errors' => [
-                                               'err' => [
-                                                       [ 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ],
-                                                       $I => 'error',
-                                               ],
+                                               [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'err', $C => 'text' ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'string' => [
-                                                       [ 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ],
-                                                       $I => 'warning',
-                                               ],
+                                               [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'string', $C => 'text' ],
+                                               $I => 'warning',
                                        ],
                                ],
                                [
                                        'errors' => [
-                                               'errWithData' => [
-                                                       [ 'code' => 'overriddenCode', 'text' => $mainpageText,
-                                                               'overriddenData' => true, $C => 'text' ],
-                                                       $I => 'error',
-                                               ],
+                                               [ 'code' => 'overriddenCode', 'text' => $mainpageText,
+                                                       'data' => $overriddenData, 'module' => 'errWithData', $C => 'text' ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'messageWithData' => [
-                                                       [ 'code' => 'overriddenCode', 'text' => $mainpageText,
-                                                               'overriddenData' => true, $C => 'text' ],
-                                                       $I => 'warning',
-                                               ],
-                                               'message' => [
-                                                       [ 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ],
-                                                       $I => 'warning',
-                                               ],
-                                               'foo' => [
-                                                       [ 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ],
-                                                       [ 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ],
-                                                       $I => 'warning',
-                                               ],
+                                               [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'foo', $C => 'text' ],
+                                               [ 'code' => 'parentheses', 'text' => $parensText, 'module' => 'foo', $C => 'text' ],
+                                               [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'message', $C => 'text' ],
+                                               [ 'code' => 'overriddenCode', 'text' => $mainpageText,
+                                                       'data' => $overriddenData, 'module' => 'messageWithData', $C => 'text' ],
+                                               $I => 'warning',
                                        ],
                                ],
                                [
                                        'errors' => [
-                                               'status' => [
-                                                       [ 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ],
-                                                       [ 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ],
-                                                       $I => 'error',
-                                               ],
+                                               [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'status', $C => 'text' ],
+                                               [ 'code' => 'parentheses', 'text' => $parensText, 'module' => 'status', $C => 'text' ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'status' => [
-                                                       [ 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ],
-                                                       [ 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ],
-                                                       [ 'code' => 'overriddenCode', 'text' => $mainpageText,
-                                                               'overriddenData' => true, $C => 'text' ],
-                                                       $I => 'warning',
-                                               ],
+                                               [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'status', $C => 'text' ],
+                                               [ 'code' => 'parentheses', 'text' => $parensText, 'module' => 'status', $C => 'text' ],
+                                               [ 'code' => 'overriddenCode', 'text' => $mainpageText,
+                                                       'data' => $overriddenData, 'module' => 'status', $C => 'text' ],
+                                               $I => 'warning',
+                                       ],
+                               ],
+                       ],
+                       [ 'plaintext' ] + $tmp, // For these messages, plaintext and wikitext are the same
+                       [ 'html', 'en', true,
+                               [
+                                       'errors' => [
+                                               [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'err', $C => 'html' ],
+                                               $I => 'error',
+                                       ],
+                                       'warnings' => [
+                                               [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'string', $C => 'html' ],
+                                               $I => 'warning',
+                                       ],
+                               ],
+                               [
+                                       'errors' => [
+                                               [ 'code' => 'overriddenCode', 'html' => $mainpageHTML,
+                                                       'data' => $overriddenData, 'module' => 'errWithData', $C => 'html' ],
+                                               $I => 'error',
+                                       ],
+                                       'warnings' => [
+                                               [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'foo', $C => 'html' ],
+                                               [ 'code' => 'parentheses', 'html' => $parensHTML, 'module' => 'foo', $C => 'html' ],
+                                               [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'message', $C => 'html' ],
+                                               [ 'code' => 'overriddenCode', 'html' => $mainpageHTML,
+                                                       'data' => $overriddenData, 'module' => 'messageWithData', $C => 'html' ],
+                                               $I => 'warning',
+                                       ],
+                               ],
+                               [
+                                       'errors' => [
+                                               [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'status', $C => 'html' ],
+                                               [ 'code' => 'parentheses', 'html' => $parensHTML, 'module' => 'status', $C => 'html' ],
+                                               $I => 'error',
+                                       ],
+                                       'warnings' => [
+                                               [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'status', $C => 'html' ],
+                                               [ 'code' => 'parentheses', 'html' => $parensHTML, 'module' => 'status', $C => 'html' ],
+                                               [ 'code' => 'overriddenCode', 'html' => $mainpageHTML,
+                                                       'data' => $overriddenData, 'module' => 'status', $C => 'html' ],
+                                               $I => 'warning',
                                        ],
                                ],
                        ],
                        [ 'raw', 'fr', true,
                                [
                                        'errors' => [
-                                               'err' => [
-                                                       [
-                                                               'code' => 'mainpage',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ]
-                                                       ],
-                                                       $I => 'error',
+                                               [
+                                                       'code' => 'mainpage',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'module' => 'err',
                                                ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'string' => [
-                                                       [
-                                                               'code' => 'mainpage',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ]
-                                                       ],
-                                                       $I => 'warning',
+                                               [
+                                                       'code' => 'mainpage',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'module' => 'string',
                                                ],
+                                               $I => 'warning',
                                        ],
                                ],
                                [
                                        'errors' => [
-                                               'errWithData' => [
-                                                       [
-                                                               'code' => 'overriddenCode',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ],
-                                                               'overriddenData' => true
-                                                       ],
-                                                       $I => 'error',
+                                               [
+                                                       'code' => 'overriddenCode',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'data' => $overriddenData,
+                                                       'module' => 'errWithData',
                                                ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'messageWithData' => [
-                                                       [
-                                                               'code' => 'overriddenCode',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ],
-                                                               'overriddenData' => true
-                                                       ],
-                                                       $I => 'warning',
+                                               [
+                                                       'code' => 'mainpage',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'module' => 'foo',
+                                               ],
+                                               [
+                                                       'code' => 'parentheses',
+                                                       'key' => 'parentheses',
+                                                       'params' => [ 'foobar', $I => 'param' ],
+                                                       'module' => 'foo',
                                                ],
-                                               'message' => [
-                                                       [
-                                                               'code' => 'mainpage',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ]
-                                                       ],
-                                                       $I => 'warning',
+                                               [
+                                                       'code' => 'mainpage',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'module' => 'message',
                                                ],
-                                               'foo' => [
-                                                       [
-                                                               'code' => 'mainpage',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ]
-                                                       ],
-                                                       [
-                                                               'code' => 'parentheses',
-                                                               'key' => 'parentheses',
-                                                               'params' => [ 'foobar', $I => 'param' ]
-                                                       ],
-                                                       $I => 'warning',
+                                               [
+                                                       'code' => 'overriddenCode',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'data' => $overriddenData,
+                                                       'module' => 'messageWithData',
                                                ],
+                                               $I => 'warning',
                                        ],
                                ],
                                [
                                        'errors' => [
-                                               'status' => [
-                                                       [
-                                                               'code' => 'mainpage',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ]
-                                                       ],
-                                                       [
-                                                               'code' => 'parentheses',
-                                                               'key' => 'parentheses',
-                                                               'params' => [ 'foobar', $I => 'param' ]
-                                                       ],
-                                                       $I => 'error',
+                                               [
+                                                       'code' => 'mainpage',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'module' => 'status',
+                                               ],
+                                               [
+                                                       'code' => 'parentheses',
+                                                       'key' => 'parentheses',
+                                                       'params' => [ 'foobar', $I => 'param' ],
+                                                       'module' => 'status',
                                                ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'status' => [
-                                                       [
-                                                               'code' => 'mainpage',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ]
-                                                       ],
-                                                       [
-                                                               'code' => 'parentheses',
-                                                               'key' => 'parentheses',
-                                                               'params' => [ 'foobar', $I => 'param' ]
-                                                       ],
-                                                       [
-                                                               'code' => 'overriddenCode',
-                                                               'key' => 'mainpage',
-                                                               'params' => [ $I => 'param' ],
-                                                               'overriddenData' => true
-                                                       ],
-                                                       $I => 'warning',
+                                               [
+                                                       'code' => 'mainpage',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'module' => 'status',
                                                ],
+                                               [
+                                                       'code' => 'parentheses',
+                                                       'key' => 'parentheses',
+                                                       'params' => [ 'foobar', $I => 'param' ],
+                                                       'module' => 'status',
+                                               ],
+                                               [
+                                                       'code' => 'overriddenCode',
+                                                       'key' => 'mainpage',
+                                                       'params' => [ $I => 'param' ],
+                                                       'data' => $overriddenData,
+                                                       'module' => 'status',
+                                               ],
+                                               $I => 'warning',
                                        ],
                                ],
                        ],
                        [ 'none', 'fr', true,
                                [
                                        'errors' => [
-                                               'err' => [
-                                                       [ 'code' => 'mainpage' ],
-                                                       $I => 'error',
-                                               ],
+                                               [ 'code' => 'mainpage', 'module' => 'err' ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'string' => [
-                                                       [ 'code' => 'mainpage' ],
-                                                       $I => 'warning',
-                                               ],
+                                               [ 'code' => 'mainpage', 'module' => 'string' ],
+                                               $I => 'warning',
                                        ],
                                ],
                                [
                                        'errors' => [
-                                               'errWithData' => [
-                                                       [ 'code' => 'overriddenCode', 'overriddenData' => true ],
-                                                       $I => 'error',
-                                               ],
+                                               [ 'code' => 'overriddenCode', 'data' => $overriddenData,
+                                                       'module' => 'errWithData' ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'messageWithData' => [
-                                                       [ 'code' => 'overriddenCode', 'overriddenData' => true ],
-                                                       $I => 'warning',
-                                               ],
-                                               'message' => [
-                                                       [ 'code' => 'mainpage' ],
-                                                       $I => 'warning',
-                                               ],
-                                               'foo' => [
-                                                       [ 'code' => 'mainpage' ],
-                                                       [ 'code' => 'parentheses' ],
-                                                       $I => 'warning',
-                                               ],
+                                               [ 'code' => 'mainpage', 'module' => 'foo' ],
+                                               [ 'code' => 'parentheses', 'module' => 'foo' ],
+                                               [ 'code' => 'mainpage', 'module' => 'message' ],
+                                               [ 'code' => 'overriddenCode', 'data' => $overriddenData,
+                                                       'module' => 'messageWithData' ],
+                                               $I => 'warning',
                                        ],
                                ],
                                [
                                        'errors' => [
-                                               'status' => [
-                                                       [ 'code' => 'mainpage' ],
-                                                       [ 'code' => 'parentheses' ],
-                                                       $I => 'error',
-                                               ],
+                                               [ 'code' => 'mainpage', 'module' => 'status' ],
+                                               [ 'code' => 'parentheses', 'module' => 'status' ],
+                                               $I => 'error',
                                        ],
                                        'warnings' => [
-                                               'status' => [
-                                                       [ 'code' => 'mainpage' ],
-                                                       [ 'code' => 'parentheses' ],
-                                                       [ 'code' => 'overriddenCode', 'overriddenData' => true ],
-                                                       $I => 'warning',
-                                               ],
+                                               [ 'code' => 'mainpage', 'module' => 'status' ],
+                                               [ 'code' => 'parentheses', 'module' => 'status' ],
+                                               [ 'code' => 'overriddenCode', 'data' => $overriddenData, 'module' => 'status' ],
+                                               $I => 'warning',
                                        ],
                                ],
                        ],
@@ -302,7 +348,14 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                $result = new ApiResult( 8388608 );
                $formatter = new ApiErrorFormatter_BackCompat( $result );
 
+               $this->assertSame( 'en', $formatter->getLanguage()->getCode() );
+
+               $this->assertSame( [], $formatter->arrayFromStatus( Status::newGood() ) );
+
                $formatter->addWarning( 'string', 'mainpage' );
+               $formatter->addWarning( 'raw',
+                       new RawMessage( 'Blah <kbd>kbd</kbd> <b>&lt;X&gt;</b> &#x1f61e;' )
+               );
                $formatter->addError( 'err', 'mainpage' );
                $this->assertSame( [
                        'error' => [
@@ -310,6 +363,10 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                                'info' => $mainpagePlain,
                        ],
                        'warnings' => [
+                               'raw' => [
+                                       'warnings' => 'Blah "kbd" <X> 😞',
+                                       ApiResult::META_CONTENT => 'warnings',
+                               ],
                                'string' => [
                                        'warnings' => $mainpagePlain,
                                        ApiResult::META_CONTENT => 'warnings',
@@ -321,12 +378,13 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                $result->reset();
                $formatter->addWarning( 'foo', 'mainpage' );
                $formatter->addWarning( 'foo', 'mainpage' );
-               $formatter->addWarning( 'foo', [ 'parentheses', 'foobar' ] );
+               $formatter->addWarning( 'xxx+foo', [ 'parentheses', 'foobar' ] );
                $msg1 = wfMessage( 'mainpage' );
                $formatter->addWarning( 'message', $msg1 );
                $msg2 = new ApiMessage( 'mainpage', 'overriddenCode', [ 'overriddenData' => true ] );
                $formatter->addWarning( 'messageWithData', $msg2 );
                $formatter->addError( 'errWithData', $msg2 );
+               $formatter->addWarning( null, 'mainpage' );
                $this->assertSame( [
                        'error' => [
                                'code' => 'overriddenCode',
@@ -334,6 +392,10 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                                'overriddenData' => true,
                        ],
                        'warnings' => [
+                               'unknown' => [
+                                       'warnings' => $mainpagePlain,
+                                       ApiResult::META_CONTENT => 'warnings',
+                               ],
                                'messageWithData' => [
                                        'warnings' => $mainpagePlain,
                                        ApiResult::META_CONTENT => 'warnings',
@@ -350,6 +412,22 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                        ApiResult::META_TYPE => 'assoc',
                ], $result->getResultData(), 'Complex test' );
 
+               $this->assertSame(
+                       [
+                               'code' => 'mainpage',
+                               'info' => 'Main Page',
+                       ],
+                       $formatter->formatMessage( $msg1 )
+               );
+               $this->assertSame(
+                       [
+                               'code' => 'overriddenCode',
+                               'info' => 'Main Page',
+                               'overriddenData' => true,
+                       ],
+                       $formatter->formatMessage( $msg2 )
+               );
+
                $result->reset();
                $status = Status::newGood();
                $status->warning( 'mainpage' );
@@ -377,14 +455,16 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                $this->assertSame(
                        [
                                [
-                                       'type' => 'error',
                                        'message' => 'mainpage',
-                                       'params' => [ $I => 'param' ]
+                                       'params' => [ $I => 'param' ],
+                                       'code' => 'mainpage',
+                                       'type' => 'error',
                                ],
                                [
-                                       'type' => 'error',
                                        'message' => 'parentheses',
-                                       'params' => [ 'foobar', $I => 'param' ]
+                                       'params' => [ 'foobar', $I => 'param' ],
+                                       'code' => 'parentheses',
+                                       'type' => 'error',
                                ],
                                $I => 'error',
                        ],
@@ -394,24 +474,28 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                $this->assertSame(
                        [
                                [
-                                       'type' => 'warning',
                                        'message' => 'mainpage',
-                                       'params' => [ $I => 'param' ]
+                                       'params' => [ $I => 'param' ],
+                                       'code' => 'mainpage',
+                                       'type' => 'warning',
                                ],
                                [
-                                       'type' => 'warning',
                                        'message' => 'parentheses',
-                                       'params' => [ 'foobar', $I => 'param' ]
+                                       'params' => [ 'foobar', $I => 'param' ],
+                                       'code' => 'parentheses',
+                                       'type' => 'warning',
                                ],
                                [
                                        'message' => 'mainpage',
                                        'params' => [ $I => 'param' ],
-                                       'type' => 'warning'
+                                       'code' => 'mainpage',
+                                       'type' => 'warning',
                                ],
                                [
                                        'message' => 'mainpage',
                                        'params' => [ $I => 'param' ],
-                                       'type' => 'warning'
+                                       'code' => 'overriddenCode',
+                                       'type' => 'warning',
                                ],
                                $I => 'warning',
                        ],
index c111949..c9a3428 100644 (file)
@@ -53,8 +53,8 @@ class ApiMainTest extends ApiTestCase {
                                'assert' => $assert,
                        ], null, null, $user );
                        $this->assertFalse( $error ); // That no error was expected
-               } catch ( UsageException $e ) {
-                       $this->assertEquals( $e->getCodeString(), $error );
+               } catch ( ApiUsageException $e ) {
+                       $this->assertTrue( self::apiExceptionHasCode( $e, $error ) );
                }
        }
 
@@ -76,8 +76,8 @@ class ApiMainTest extends ApiTestCase {
                                'assertuser' => $user->getName() . 'X',
                        ], null, null, $user );
                        $this->fail( 'Expected exception not thrown' );
-               } catch ( UsageException $e ) {
-                       $this->assertEquals( $e->getCodeString(), 'assertnameduserfailed' );
+               } catch ( ApiUsageException $e ) {
+                       $this->assertTrue( self::apiExceptionHasCode( $e, 'assertnameduserfailed' ) );
                }
        }
 
@@ -305,4 +305,274 @@ class ApiMainTest extends ApiTestCase {
                $main = new ApiMain( new FauxRequest( [ 'action' => 'query', 'meta' => 'siteinfo' ] ) );
                $this->assertTrue( $main->lacksSameOriginSecurity(), 'Hook, should lack security' );
        }
+
+       /**
+        * Test proper creation of the ApiErrorFormatter
+        * @covers ApiMain::__construct
+        * @dataProvider provideApiErrorFormatterCreation
+        * @param array $request Request parameters
+        * @param array $expect Expected data
+        *  - uselang: ApiMain language
+        *  - class: ApiErrorFormatter class
+        *  - lang: ApiErrorFormatter language
+        *  - format: ApiErrorFormatter format
+        *  - usedb: ApiErrorFormatter use-database flag
+        */
+       public function testApiErrorFormatterCreation( array $request, array $expect ) {
+               $context = new RequestContext();
+               $context->setRequest( new FauxRequest( $request ) );
+               $context->setLanguage( 'ru' );
+
+               $main = new ApiMain( $context );
+               $formatter = $main->getErrorFormatter();
+               $wrappedFormatter = TestingAccessWrapper::newFromObject( $formatter );
+
+               $this->assertSame( $expect['uselang'], $main->getLanguage()->getCode() );
+               $this->assertInstanceOf( $expect['class'], $formatter );
+               $this->assertSame( $expect['lang'], $formatter->getLanguage()->getCode() );
+               $this->assertSame( $expect['format'], $wrappedFormatter->format );
+               $this->assertSame( $expect['usedb'], $wrappedFormatter->useDB );
+       }
+
+       public static function provideApiErrorFormatterCreation() {
+               global $wgContLang;
+
+               return [
+                       'Default (BC)' => [ [], [
+                               'uselang' => 'ru',
+                               'class' => ApiErrorFormatter_BackCompat::class,
+                               'lang' => 'en',
+                               'format' => 'none',
+                               'usedb' => false,
+                       ] ],
+                       'BC ignores fields' => [ [ 'errorlang' => 'de', 'errorsuselocal' => 1 ], [
+                               'uselang' => 'ru',
+                               'class' => ApiErrorFormatter_BackCompat::class,
+                               'lang' => 'en',
+                               'format' => 'none',
+                               'usedb' => false,
+                       ] ],
+                       'Explicit BC' => [ [ 'errorformat' => 'bc' ], [
+                               'uselang' => 'ru',
+                               'class' => ApiErrorFormatter_BackCompat::class,
+                               'lang' => 'en',
+                               'format' => 'none',
+                               'usedb' => false,
+                       ] ],
+                       'Basic' => [ [ 'errorformat' => 'wikitext' ], [
+                               'uselang' => 'ru',
+                               'class' => ApiErrorFormatter::class,
+                               'lang' => 'ru',
+                               'format' => 'wikitext',
+                               'usedb' => false,
+                       ] ],
+                       'Follows uselang' => [ [ 'uselang' => 'fr', 'errorformat' => 'plaintext' ], [
+                               'uselang' => 'fr',
+                               'class' => ApiErrorFormatter::class,
+                               'lang' => 'fr',
+                               'format' => 'plaintext',
+                               'usedb' => false,
+                       ] ],
+                       'Explicitly follows uselang' => [
+                               [ 'uselang' => 'fr', 'errorlang' => 'uselang', 'errorformat' => 'plaintext' ],
+                               [
+                                       'uselang' => 'fr',
+                                       'class' => ApiErrorFormatter::class,
+                                       'lang' => 'fr',
+                                       'format' => 'plaintext',
+                                       'usedb' => false,
+                               ]
+                       ],
+                       'uselang=content' => [
+                               [ 'uselang' => 'content', 'errorformat' => 'plaintext' ],
+                               [
+                                       'uselang' => $wgContLang->getCode(),
+                                       'class' => ApiErrorFormatter::class,
+                                       'lang' => $wgContLang->getCode(),
+                                       'format' => 'plaintext',
+                                       'usedb' => false,
+                               ]
+                       ],
+                       'errorlang=content' => [
+                               [ 'errorlang' => 'content', 'errorformat' => 'plaintext' ],
+                               [
+                                       'uselang' => 'ru',
+                                       'class' => ApiErrorFormatter::class,
+                                       'lang' => $wgContLang->getCode(),
+                                       'format' => 'plaintext',
+                                       'usedb' => false,
+                               ]
+                       ],
+                       'Explicit parameters' => [
+                               [ 'errorlang' => 'de', 'errorformat' => 'html', 'errorsuselocal' => 1 ],
+                               [
+                                       'uselang' => 'ru',
+                                       'class' => ApiErrorFormatter::class,
+                                       'lang' => 'de',
+                                       'format' => 'html',
+                                       'usedb' => true,
+                               ]
+                       ],
+                       'Explicit parameters override uselang' => [
+                               [ 'errorlang' => 'de', 'uselang' => 'fr', 'errorformat' => 'raw' ],
+                               [
+                                       'uselang' => 'fr',
+                                       'class' => ApiErrorFormatter::class,
+                                       'lang' => 'de',
+                                       'format' => 'raw',
+                                       'usedb' => false,
+                               ]
+                       ],
+                       'Bogus language doesn\'t explode' => [
+                               [ 'errorlang' => '<bogus1>', 'uselang' => '<bogus2>', 'errorformat' => 'none' ],
+                               [
+                                       'uselang' => 'en',
+                                       'class' => ApiErrorFormatter::class,
+                                       'lang' => 'en',
+                                       'format' => 'none',
+                                       'usedb' => false,
+                               ]
+                       ],
+                       'Bogus format doesn\'t explode' => [ [ 'errorformat' => 'bogus' ], [
+                               'uselang' => 'ru',
+                               'class' => ApiErrorFormatter_BackCompat::class,
+                               'lang' => 'en',
+                               'format' => 'none',
+                               'usedb' => false,
+                       ] ],
+               ];
+       }
+
+       /**
+        * @covers ApiMain::errorMessagesFromException
+        * @covers ApiMain::substituteResultWithError
+        * @dataProvider provideExceptionErrors
+        * @param Exception $exception
+        * @param array $expectReturn
+        * @param array $expectResult
+        */
+       public function testExceptionErrors( $error, $expectReturn, $expectResult ) {
+               $context = new RequestContext();
+               $context->setRequest( new FauxRequest( [ 'errorformat' => 'plaintext' ] ) );
+               $context->setLanguage( 'en' );
+               $context->setConfig( new MultiConfig( [
+                       new HashConfig( [ 'ShowHostnames' => true, 'ShowSQLErrors' => false ] ),
+                       $context->getConfig()
+               ] ) );
+
+               $main = new ApiMain( $context );
+               $main->addWarning( new RawMessage( 'existing warning' ), 'existing-warning' );
+               $main->addError( new RawMessage( 'existing error' ), 'existing-error' );
+
+               $ret = TestingAccessWrapper::newFromObject( $main )->substituteResultWithError( $error );
+               $this->assertSame( $expectReturn, $ret );
+
+               // PHPUnit sometimes adds some SplObjectStorage garbage to the arrays,
+               // so let's try ->assertEquals().
+               $this->assertEquals(
+                       $expectResult,
+                       $main->getResult()->getResultData( [], [ 'Strip' => 'all' ] )
+               );
+       }
+
+       // Not static so $this->getMock() can be used
+       public function provideExceptionErrors() {
+               $reqId = WebRequest::getRequestId();
+               $doclink = wfExpandUrl( wfScript( 'api' ) );
+
+               $ex = new InvalidArgumentException( 'Random exception' );
+               $trace = wfMessage( 'api-exception-trace',
+                       get_class( $ex ),
+                       $ex->getFile(),
+                       $ex->getLine(),
+                       MWExceptionHandler::getRedactedTraceAsString( $ex )
+               )->inLanguage( 'en' )->useDatabase( false )->text();
+
+               $dbex = new DBQueryError( $this->getMock( 'IDatabase' ), 'error', 1234, 'SELECT 1', __METHOD__ );
+               $dbtrace = wfMessage( 'api-exception-trace',
+                       get_class( $dbex ),
+                       $dbex->getFile(),
+                       $dbex->getLine(),
+                       MWExceptionHandler::getRedactedTraceAsString( $dbex )
+               )->inLanguage( 'en' )->useDatabase( false )->text();
+
+               $apiEx1 = new ApiUsageException( null,
+                       StatusValue::newFatal( new ApiRawMessage( 'An error', 'sv-error1' ) ) );
+               TestingAccessWrapper::newFromObject( $apiEx1 )->modulePath = 'foo+bar';
+               $apiEx1->getStatusValue()->warning( new ApiRawMessage( 'A warning', 'sv-warn1' ) );
+               $apiEx1->getStatusValue()->warning( new ApiRawMessage( 'Another warning', 'sv-warn2' ) );
+               $apiEx1->getStatusValue()->fatal( new ApiRawMessage( 'Another error', 'sv-error2' ) );
+
+               return [
+                       [
+                               $ex,
+                               [ 'existing-error', 'internal_api_error_InvalidArgumentException' ],
+                               [
+                                       'warnings' => [
+                                               [ 'code' => 'existing-warning', 'text' => 'existing warning', 'module' => 'main' ],
+                                       ],
+                                       'errors' => [
+                                               [ 'code' => 'existing-error', 'text' => 'existing error', 'module' => 'main' ],
+                                               [
+                                                       'code' => 'internal_api_error_InvalidArgumentException',
+                                                       'text' => "[$reqId] Exception caught: Random exception",
+                                               ]
+                                       ],
+                                       'trace' => $trace,
+                                       'servedby' => wfHostname(),
+                               ]
+                       ],
+                       [
+                               $dbex,
+                               [ 'existing-error', 'internal_api_error_DBQueryError' ],
+                               [
+                                       'warnings' => [
+                                               [ 'code' => 'existing-warning', 'text' => 'existing warning', 'module' => 'main' ],
+                                       ],
+                                       'errors' => [
+                                               [ 'code' => 'existing-error', 'text' => 'existing error', 'module' => 'main' ],
+                                               [
+                                                       'code' => 'internal_api_error_DBQueryError',
+                                                       'text' => "[$reqId] Database query error.",
+                                               ]
+                                       ],
+                                       'trace' => $dbtrace,
+                                       'servedby' => wfHostname(),
+                               ]
+                       ],
+                       [
+                               new UsageException( 'Usage exception!', 'ue', 0, [ 'foo' => 'bar' ] ),
+                               [ 'existing-error', 'ue' ],
+                               [
+                                       'warnings' => [
+                                               [ 'code' => 'existing-warning', 'text' => 'existing warning', 'module' => 'main' ],
+                                       ],
+                                       'errors' => [
+                                               [ 'code' => 'existing-error', 'text' => 'existing error', 'module' => 'main' ],
+                                               [ 'code' => 'ue', 'text' => "Usage exception!", 'data' => [ 'foo' => 'bar' ] ]
+                                       ],
+                                       'docref' => "See $doclink for API usage.",
+                                       'servedby' => wfHostname(),
+                               ]
+                       ],
+                       [
+                               $apiEx1,
+                               [ 'existing-error', 'sv-error1', 'sv-error2' ],
+                               [
+                                       'warnings' => [
+                                               [ 'code' => 'existing-warning', 'text' => 'existing warning', 'module' => 'main' ],
+                                               [ 'code' => 'sv-warn1', 'text' => 'A warning', 'module' => 'foo+bar' ],
+                                               [ 'code' => 'sv-warn2', 'text' => 'Another warning', 'module' => 'foo+bar' ],
+                                       ],
+                                       'errors' => [
+                                               [ 'code' => 'existing-error', 'text' => 'existing error', 'module' => 'main' ],
+                                               [ 'code' => 'sv-error1', 'text' => 'An error', 'module' => 'foo+bar' ],
+                                               [ 'code' => 'sv-error2', 'text' => 'Another error', 'module' => 'foo+bar' ],
+                                       ],
+                                       'docref' => "See $doclink for API usage.",
+                                       'servedby' => wfHostname(),
+                               ]
+                       ],
+               ];
+       }
 }
index 8764b41..e405b3b 100644 (file)
@@ -23,6 +23,56 @@ class ApiMessageTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers ApiMessageTrait
+        */
+       public function testCodeDefaults() {
+               $msg = new ApiMessage( 'foo' );
+               $this->assertSame( 'foo', $msg->getApiCode() );
+
+               $msg = new ApiMessage( 'apierror-bar' );
+               $this->assertSame( 'bar', $msg->getApiCode() );
+
+               $msg = new ApiMessage( 'apiwarn-baz' );
+               $this->assertSame( 'baz', $msg->getApiCode() );
+
+               // BC case
+               $msg = new ApiMessage( 'actionthrottledtext' );
+               $this->assertSame( 'ratelimited', $msg->getApiCode() );
+
+               $msg = new ApiMessage( [ 'apierror-missingparam', 'param' ] );
+               $this->assertSame( 'noparam', $msg->getApiCode() );
+       }
+
+       /**
+        * @covers ApiMessageTrait
+        * @dataProvider provideInvalidCode
+        * @param mixed $code
+        */
+       public function testInvalidCode( $code ) {
+               $msg = new ApiMessage( 'foo' );
+               try {
+                       $msg->setApiCode( $code );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( InvalidArgumentException $ex ) {
+                       $this->assertTrue( true );
+               }
+
+               try {
+                       new ApiMessage( 'foo', $code );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( InvalidArgumentException $ex ) {
+                       $this->assertTrue( true );
+               }
+       }
+
+       public static function provideInvalidCode() {
+               return [
+                       [ '' ],
+                       [ 42 ],
+               ];
+       }
+
        /**
         * @covers ApiMessage
         * @covers ApiMessageTrait
@@ -105,14 +155,32 @@ class ApiMessageTest extends MediaWikiTestCase {
         * @covers ApiMessage::create
         */
        public function testApiMessageCreate() {
-               $this->assertInstanceOf( 'ApiMessage', ApiMessage::create( new Message( 'mainpage' ) ) );
-               $this->assertInstanceOf( 'ApiRawMessage', ApiMessage::create( new RawMessage( 'mainpage' ) ) );
-               $this->assertInstanceOf( 'ApiMessage', ApiMessage::create( 'mainpage' ) );
+               $this->assertInstanceOf( ApiMessage::class, ApiMessage::create( new Message( 'mainpage' ) ) );
+               $this->assertInstanceOf(
+                       ApiRawMessage::class, ApiMessage::create( new RawMessage( 'mainpage' ) )
+               );
+               $this->assertInstanceOf( ApiMessage::class, ApiMessage::create( 'mainpage' ) );
+
+               $msg = new ApiMessage( [ 'parentheses', 'foobar' ] );
+               $msg2 = new Message( 'parentheses', [ 'foobar' ] );
 
-               $msg = new ApiMessage( 'mainpage' );
                $this->assertSame( $msg, ApiMessage::create( $msg ) );
+               $this->assertEquals( $msg, ApiMessage::create( $msg2 ) );
+               $this->assertEquals( $msg, ApiMessage::create( [ 'parentheses', 'foobar' ] ) );
+               $this->assertEquals( $msg,
+                       ApiMessage::create( [ 'message' => 'parentheses', 'params' => [ 'foobar' ] ] )
+               );
+               $this->assertSame( $msg,
+                       ApiMessage::create( [ 'message' => $msg, 'params' => [ 'xxx' ] ] )
+               );
+               $this->assertEquals( $msg,
+                       ApiMessage::create( [ 'message' => $msg2, 'params' => [ 'xxx' ] ] )
+               );
+               $this->assertSame( $msg,
+                       ApiMessage::create( [ 'message' => $msg ] )
+               );
 
-               $msg = new ApiRawMessage( 'mainpage' );
+               $msg = new ApiRawMessage( [ 'parentheses', 'foobar' ] );
                $this->assertSame( $msg, ApiMessage::create( $msg ) );
        }
 
index 0a577c1..ef70626 100644 (file)
@@ -30,7 +30,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
                $this->mUserMock->expects( $this->any() )
                        ->method( 'getEffectiveGroups' )->will( $this->returnValue( [ '*', 'user' ] ) );
                $this->mUserMock->expects( $this->any() )
-                       ->method( 'isAllowed' )->will( $this->returnValue( true ) );
+                       ->method( 'isAllowedAny' )->will( $this->returnValue( true ) );
 
                // Set up callback for User::getOptionKinds
                $this->mUserMock->expects( $this->any() )
@@ -146,7 +146,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * @expectedException UsageException
+        * @expectedException ApiUsageException
         */
        public function testNoToken() {
                $request = $this->getSampleRequest( [ 'token' => null ] );
@@ -163,13 +163,11 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
                        $request = $this->getSampleRequest();
 
                        $this->executeQuery( $request );
-               } catch ( UsageException $e ) {
-                       $this->assertEquals( 'notloggedin', $e->getCodeString() );
-                       $this->assertEquals( 'Anonymous users cannot change preferences', $e->getMessage() );
-
+               } catch ( ApiUsageException $e ) {
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $e, 'notloggedin' ) );
                        return;
                }
-               $this->fail( "UsageException was not thrown" );
+               $this->fail( "ApiUsageException was not thrown" );
        }
 
        public function testNoOptionname() {
@@ -177,13 +175,11 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
                        $request = $this->getSampleRequest( [ 'optionvalue' => '1' ] );
 
                        $this->executeQuery( $request );
-               } catch ( UsageException $e ) {
-                       $this->assertEquals( 'nooptionname', $e->getCodeString() );
-                       $this->assertEquals( 'The optionname parameter must be set', $e->getMessage() );
-
+               } catch ( ApiUsageException $e ) {
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $e, 'nooptionname' ) );
                        return;
                }
-               $this->fail( "UsageException was not thrown" );
+               $this->fail( "ApiUsageException was not thrown" );
        }
 
        public function testNoChanges() {
@@ -200,13 +196,11 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
                        $request = $this->getSampleRequest();
 
                        $this->executeQuery( $request );
-               } catch ( UsageException $e ) {
-                       $this->assertEquals( 'nochanges', $e->getCodeString() );
-                       $this->assertEquals( 'No changes were requested', $e->getMessage() );
-
+               } catch ( ApiUsageException $e ) {
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $e, 'nochanges' ) );
                        return;
                }
-               $this->fail( "UsageException was not thrown" );
+               $this->fail( "ApiUsageException was not thrown" );
        }
 
        public function testReset() {
@@ -400,7 +394,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
                        'options' => 'success',
                        'warnings' => [
                                'options' => [
-                                       'warnings' => "Validation error for 'special': cannot be set by this module"
+                                       'warnings' => "Validation error for \"special\": cannot be set by this module."
                                ]
                        ]
                ], $response );
@@ -423,7 +417,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
                        'options' => 'success',
                        'warnings' => [
                                'options' => [
-                                       'warnings' => "Validation error for 'unknownOption': not a valid preference"
+                                       'warnings' => "Validation error for \"unknownOption\": not a valid preference."
                                ]
                        ]
                ], $response );
index b72a4f8..f01a670 100644 (file)
@@ -23,12 +23,10 @@ class ApiParseTest extends ApiTestCase {
                                'page' => $somePage ] );
 
                        $this->fail( "API did not return an error when parsing a nonexistent page" );
-               } catch ( UsageException $ex ) {
-                       $this->assertEquals(
-                               'missingtitle',
-                               $ex->getCodeString(),
+               } catch ( ApiUsageException $ex ) {
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'missingtitle' ),
                                "Parse request for nonexistent page must give 'missingtitle' error: "
-                                       . var_export( $ex->getMessageArray(), true )
+                                       . var_export( self::getErrorFormatter()->arrayFromStatus( $ex->getStatusValue() ), true )
                        );
                }
        }
index eaeb3ae..0a2cd83 100644 (file)
@@ -1498,7 +1498,7 @@ class ApiQueryWatchlistIntegrationTest extends ApiTestCase {
                $otherUser->setOption( 'watchlisttoken', '1234567890' );
                $otherUser->saveSettings();
 
-               $this->setExpectedException( UsageException::class, 'Incorrect watchlist token provided' );
+               $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
 
                $this->doListWatchlistRequest( [
                        'wlowner' => $otherUser->getName(),
@@ -1507,7 +1507,7 @@ class ApiQueryWatchlistIntegrationTest extends ApiTestCase {
        }
 
        public function testOwnerAndTokenParams_noWatchlistTokenSet() {
-               $this->setExpectedException( UsageException::class, 'Incorrect watchlist token provided' );
+               $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
 
                $this->doListWatchlistRequest( [
                        'wlowner' => $this->getNonLoggedInTestUser()->getName(),
index d6f315d..0f01664 100644 (file)
@@ -503,7 +503,7 @@ class ApiQueryWatchlistRawIntegrationTest extends ApiTestCase {
                $otherUser->setOption( 'watchlisttoken', '1234567890' );
                $otherUser->saveSettings();
 
-               $this->setExpectedException( UsageException::class, 'Incorrect watchlist token provided' );
+               $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
 
                $this->doListWatchlistRawRequest( [
                        'wrowner' => $otherUser->getName(),
@@ -512,7 +512,7 @@ class ApiQueryWatchlistRawIntegrationTest extends ApiTestCase {
        }
 
        public function testOwnerAndTokenParams_userHasNoWatchlistToken() {
-               $this->setExpectedException( UsageException::class, 'Incorrect watchlist token provided' );
+               $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
 
                $this->doListWatchlistRawRequest( [
                        'wrowner' => $this->getNotLoggedInTestUser()->getName(),
index 7e1f9d8..6b299c9 100644 (file)
@@ -3,6 +3,8 @@
 abstract class ApiTestCase extends MediaWikiLangTestCase {
        protected static $apiUrl;
 
+       protected static $errorFormatter = null;
+
        /**
         * @var ApiTestContext
         */
@@ -196,6 +198,26 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
                return $data[0]['tokens'];
        }
 
+       protected static function getErrorFormatter() {
+               if ( self::$errorFormatter === null ) {
+                       self::$errorFormatter = new ApiErrorFormatter(
+                               new ApiResult( false ),
+                               Language::factory( 'en' ),
+                               'none'
+                       );
+               }
+               return self::$errorFormatter;
+       }
+
+       public static function apiExceptionHasCode( ApiUsageException $ex, $code ) {
+               return (bool)array_filter(
+                       self::getErrorFormatter()->arrayFromStatus( $ex->getStatusValue() ),
+                       function ( $e ) use ( $code ) {
+                               return is_array( $e ) && $e['code'] === $code;
+                       }
+               );
+       }
+
        public function testApiTestGroup() {
                $groups = PHPUnit_Util_Test::getGroups( get_class( $this ) );
                $constraint = PHPUnit_Framework_Assert::logicalOr(
index b63bf2e..971b63c 100644 (file)
@@ -14,7 +14,7 @@ class ApiUnblockTest extends ApiTestCase {
        }
 
        /**
-        * @expectedException UsageException
+        * @expectedException ApiUsageException
         */
        public function testWithNoToken() {
                $this->doApiRequest(
index de2b56b..9b79e6c 100644 (file)
@@ -67,9 +67,9 @@ class ApiUploadTest extends ApiTestCaseUpload {
                        $this->doApiRequest( [
                                'action' => 'upload'
                        ] );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
-                       $this->assertEquals( "The token parameter must be set", $e->getMessage() );
+                       $this->assertEquals( 'The "token" parameter must be set', $e->getMessage() );
                }
                $this->assertTrue( $exception, "Got exception" );
        }
@@ -83,7 +83,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                        $this->doApiRequestWithToken( [
                                'action' => 'upload',
                        ], $session, self::$users['uploader']->getUser() );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                        $this->assertEquals( "One of the parameters filekey, file, url is required",
                                $e->getMessage() );
@@ -129,7 +129,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                try {
                        list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
                                self::$users['uploader']->getUser() );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                }
                $this->assertTrue( isset( $result['upload'] ) );
@@ -168,7 +168,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                $exception = false;
                try {
                        $this->doApiRequestWithToken( $params, $session, self::$users['uploader']->getUser() );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $this->assertContains( 'The file you submitted was empty', $e->getMessage() );
                        $exception = true;
                }
@@ -218,7 +218,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                try {
                        list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
                                self::$users['uploader']->getUser() );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                }
                $this->assertTrue( isset( $result['upload'] ) );
@@ -235,7 +235,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                try {
                        list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
                                self::$users['uploader']->getUser() ); // FIXME: leaks a temporary file
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                }
                $this->assertTrue( isset( $result['upload'] ) );
@@ -289,7 +289,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                try {
                        list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
                                self::$users['uploader']->getUser() );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                }
                $this->assertTrue( isset( $result['upload'] ) );
@@ -314,7 +314,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                try {
                        list( $result ) = $this->doApiRequestWithToken( $params, $session,
                                self::$users['uploader']->getUser() ); // FIXME: leaks a temporary file
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                }
                $this->assertTrue( isset( $result['upload'] ) );
@@ -371,7 +371,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                try {
                        list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
                                self::$users['uploader']->getUser() ); // FIXME: leaks a temporary file
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                }
                $this->assertFalse( $exception );
@@ -400,12 +400,12 @@ class ApiUploadTest extends ApiTestCaseUpload {
                try {
                        list( $result ) = $this->doApiRequestWithToken( $params, $session,
                                self::$users['uploader']->getUser() );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                }
                $this->assertTrue( isset( $result['upload'] ) );
                $this->assertEquals( 'Success', $result['upload']['result'] );
-               $this->assertFalse( $exception, "No UsageException exception." );
+               $this->assertFalse( $exception, "No ApiUsageException exception." );
 
                // clean up
                $this->deleteFileByFileName( $fileName );
@@ -476,7 +476,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                                try {
                                        list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
                                                self::$users['uploader']->getUser() );
-                               } catch ( UsageException $e ) {
+                               } catch ( ApiUsageException $e ) {
                                        $this->markTestIncomplete( $e->getMessage() );
                                }
                                // Make sure we got a valid chunk continue:
@@ -504,7 +504,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                        try {
                                list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
                                        self::$users['uploader']->getUser() );
-                       } catch ( UsageException $e ) {
+                       } catch ( ApiUsageException $e ) {
                                $this->markTestIncomplete( $e->getMessage() );
                        }
                        // Make sure we got a valid chunk continue:
@@ -544,7 +544,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                try {
                        list( $result ) = $this->doApiRequestWithToken( $params, $session,
                                self::$users['uploader']->getUser() );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                }
                $this->assertTrue( isset( $result['upload'] ) );
index 19afc14..0cd2707 100644 (file)
@@ -146,11 +146,11 @@ class ApiWatchTest extends ApiTestCase {
 
                        $this->assertArrayHasKey( 'rollback', $data[0] );
                        $this->assertArrayHasKey( 'title', $data[0]['rollback'] );
-               } catch ( UsageException $ue ) {
-                       if ( $ue->getCodeString() == 'onlyauthor' ) {
+               } catch ( ApiUsageException $ue ) {
+                       if ( self::apiExceptionHasCode( $ue, 'onlyauthor' ) ) {
                                $this->markTestIncomplete( "Only one author to 'Help:UTPage', cannot test rollback" );
                        } else {
-                               $this->fail( "Received error '" . $ue->getCodeString() . "'" );
+                               $this->fail( "Received error '" . $ue->getMessage() . "'" );
                        }
                }
        }
index d7db538..1407c10 100644 (file)
@@ -9,7 +9,11 @@ class MockApi extends ApiBase {
        public function __construct() {
        }
 
-       public function setWarning( $warning ) {
+       public function getModulePath() {
+               return $this->getModuleName();
+       }
+
+       public function addWarning( $warning, $code = null, $data = null ) {
                $this->warnings[] = $warning;
        }
 
index f5b50e5..9915a38 100644 (file)
@@ -12,4 +12,8 @@ class MockApiQueryBase extends ApiQueryBase {
        public function getModuleName() {
                return $this->name;
        }
+
+       public function getModulePath() {
+               return 'query+' . $this->getModuleName();
+       }
 }
index 0028bbb..3aa1db3 100644 (file)
@@ -133,12 +133,10 @@ class ApiFormatPhpTest extends ApiFormatTestBase {
                        $printer->closePrinter();
                        ob_end_clean();
                        $this->fail( 'Expected exception not thrown' );
-               } catch ( UsageException $ex ) {
+               } catch ( ApiUsageException $ex ) {
                        ob_end_clean();
-                       $this->assertSame(
-                               'This response cannot be represented using format=php. ' .
-                                       'See https://phabricator.wikimedia.org/T68776',
-                               $ex->getMessage(),
+                       $this->assertTrue(
+                               $ex->getStatusValue()->hasMessage( 'apierror-formatphp' ),
                                'Expected exception'
                        );
                }
index 3fef0b0..0f8c8ee 100644 (file)
@@ -105,11 +105,11 @@ class ApiFormatXmlTest extends ApiFormatTestBase {
                                [ 'includexmlnamespace' => 1 ] ],
 
                        // xslt param
-                       [ [], '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Invalid or non-existent stylesheet specified</xml></warnings></api>',
+                       [ [], '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Invalid or non-existent stylesheet specified.</xml></warnings></api>',
                                [ 'xslt' => 'DoesNotExist' ] ],
                        [ [], '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should be in the MediaWiki namespace.</xml></warnings></api>',
                                [ 'xslt' => 'ApiFormatXmlTest' ] ],
-                       [ [], '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should have .xsl extension.</xml></warnings></api>',
+                       [ [], '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should have &quot;.xsl&quot; extension.</xml></warnings></api>',
                                [ 'xslt' => 'MediaWiki:ApiFormatXmlTest' ] ],
                        [ [],
                                '<?xml version="1.0"?><?xml-stylesheet href="' .
index 8cb2327..9407edf 100644 (file)
@@ -99,11 +99,11 @@ class ApiQueryTest extends ApiTestCase {
                $exceptionCaught = false;
                try {
                        $this->assertEquals( $expected, $api->titlePartToKey( $titlePart, $namespace ) );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exceptionCaught = true;
                }
                $this->assertEquals( $expectException, $exceptionCaught,
-                       'UsageException thrown by titlePartToKey' );
+                       'ApiUsageException thrown by titlePartToKey' );
        }
 
        function provideTestTitlePartToKey() {
index a1cdf7e..a57682b 100644 (file)
@@ -2,6 +2,8 @@
 
 namespace MediaWiki\Auth;
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * @group AuthManager
  * @covers MediaWiki\Auth\AbstractPasswordPrimaryAuthenticationProvider
@@ -26,7 +28,7 @@ class AbstractPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCa
                $provider = $this->getMockForAbstractClass(
                        AbstractPasswordPrimaryAuthenticationProvider::class
                );
-               $provider->setConfig( \ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+               $provider->setConfig( MediaWikiServices::getInstance()->getMainConfig() );
                $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
 
                $obj = $providerPriv->getPasswordFactory();
@@ -38,7 +40,7 @@ class AbstractPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCa
                $provider = $this->getMockForAbstractClass(
                        AbstractPasswordPrimaryAuthenticationProvider::class
                );
-               $provider->setConfig( \ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+               $provider->setConfig( MediaWikiServices::getInstance()->getMainConfig() );
                $provider->setLogger( new \Psr\Log\NullLogger() );
                $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
 
@@ -56,7 +58,7 @@ class AbstractPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCa
                );
                $provider->setConfig( new \MultiConfig( [
                        $config,
-                       \ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       MediaWikiServices::getInstance()->getMainConfig()
                ] ) );
                $provider->setLogger( new \Psr\Log\NullLogger() );
                $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
@@ -105,7 +107,7 @@ class AbstractPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCa
                $provider = $this->getMockForAbstractClass(
                        AbstractPasswordPrimaryAuthenticationProvider::class
                );
-               $provider->setConfig( \ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+               $provider->setConfig( MediaWikiServices::getInstance()->getMainConfig() );
                $provider->setLogger( new \Psr\Log\NullLogger() );
                $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
 
@@ -121,7 +123,8 @@ class AbstractPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCa
                ] );
 
                $manager = new AuthManager(
-                       new \FauxRequest(), \ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       new \FauxRequest(),
+                       MediaWikiServices::getInstance()->getMainConfig()
                );
 
                $provider = $this->getMockForAbstractClass(
index d482453..b96455e 100644 (file)
@@ -2,6 +2,8 @@
 
 namespace MediaWiki\Auth;
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * @group AuthManager
  * @group Database
@@ -17,7 +19,8 @@ class LegacyHookPreAuthenticationProviderTest extends \MediaWikiTestCase {
                $request->expects( $this->any() )->method( 'getIP' )->will( $this->returnValue( '127.0.0.42' ) );
 
                $manager = new AuthManager(
-                       $request, \ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       $request,
+                       MediaWikiServices::getInstance()->getMainConfig()
                );
 
                $provider = new LegacyHookPreAuthenticationProvider();
index caf1680..72a03c3 100644 (file)
@@ -2,6 +2,8 @@
 
 namespace MediaWiki\Auth;
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * @group AuthManager
  * @group Database
@@ -28,7 +30,7 @@ class LocalPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCase
                }
                $config = new \MultiConfig( [
                        $this->config,
-                       \ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       MediaWikiServices::getInstance()->getMainConfig()
                ] );
 
                if ( !$this->manager ) {
@@ -449,7 +451,7 @@ class LocalPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCase
                $changeReq->password = $newpass;
                $provider->providerChangeAuthenticationData( $changeReq );
 
-               if ( $loginOnly ) {
+               if ( $loginOnly && $changed ) {
                        $old = 'fail';
                        $new = 'fail';
                        $expectExpiry = null;
index d4ebe34..bc7d65e 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace MediaWiki\Auth;
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\ScopedCallback;
 
 /**
@@ -32,7 +33,7 @@ class TemporaryPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestC
                }
                $config = new \MultiConfig( [
                        $this->config,
-                       \ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       MediaWikiServices::getInstance()->getMainConfig()
                ] );
 
                if ( !$this->manager ) {
@@ -520,10 +521,6 @@ class TemporaryPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestC
                $provider = $this->getProvider( [ 'emailEnabled' => false ] );
                $status = $provider->providerAllowsAuthenticationDataChange( $req, true );
                $this->assertEquals( \StatusValue::newFatal( 'passwordreset-emaildisabled' ), $status );
-               $req->hasBackchannel = true;
-               $status = $provider->providerAllowsAuthenticationDataChange( $req, true );
-               $this->assertFalse( $status->hasMessage( 'passwordreset-emaildisabled' ) );
-               $req->hasBackchannel = false;
 
                $provider = $this->getProvider( [ 'passwordReminderResendTime' => 10 ] );
                $status = $provider->providerAllowsAuthenticationDataChange( $req, true );
@@ -686,18 +683,10 @@ class TemporaryPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestC
                $provider = $this->getProvider( [ 'emailEnabled' => false ] );
                $status = $provider->testForAccountCreation( $user, $creator, [ $req ] );
                $this->assertEquals( \StatusValue::newFatal( 'emaildisabled' ), $status );
-               $req->hasBackchannel = true;
-               $status = $provider->testForAccountCreation( $user, $creator, [ $req ] );
-               $this->assertFalse( $status->hasMessage( 'emaildisabled' ) );
-               $req->hasBackchannel = false;
 
                $provider = $this->getProvider( [ 'emailEnabled' => true ] );
                $status = $provider->testForAccountCreation( $user, $creator, [ $req ] );
                $this->assertEquals( \StatusValue::newFatal( 'noemailcreate' ), $status );
-               $req->hasBackchannel = true;
-               $status = $provider->testForAccountCreation( $user, $creator, [ $req ] );
-               $this->assertFalse( $status->hasMessage( 'noemailcreate' ) );
-               $req->hasBackchannel = false;
 
                $user->setEmail( 'test@localhost.localdomain' );
                $status = $provider->testForAccountCreation( $user, $creator, [ $req ] );
index 5806003..c945885 100644 (file)
@@ -196,7 +196,7 @@ class ThrottlerTest extends \MediaWikiTestCase {
                        ->setMethods( [ 'log' ] )
                        ->getMockForAbstractClass();
                $logger->expects( $this->once() )->method( 'log' )->with( $this->anything(), $this->anything(), [
-                       'type' => 'custom',
+                       'throttle' => 'custom',
                        'index' => 0,
                        'ip' => '1.2.3.4',
                        'username' => 'SomeUser',
index 9c723c0..e5bb237 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+use MediaWiki\MediaWikiServices;
 
 /**
  * @group Database
@@ -39,7 +40,7 @@ class GenderCacheTest extends MediaWikiLangTestCase {
         * @covers GenderCache::getGenderOf
         */
        public function testUserName( $userKey, $expectedGender ) {
-               $genderCache = GenderCache::singleton();
+               $genderCache = MediaWikiServices::getInstance()->getGenderCache();
                $username = isset( self::$nameMap[$userKey] ) ? self::$nameMap[$userKey] : $userKey;
                $gender = $genderCache->getGenderOf( $username );
                $this->assertEquals( $gender, $expectedGender, "GenderCache normal" );
@@ -53,7 +54,7 @@ class GenderCacheTest extends MediaWikiLangTestCase {
         */
        public function testUserObjects( $userKey, $expectedGender ) {
                $username = isset( self::$nameMap[$userKey] ) ? self::$nameMap[$userKey] : $userKey;
-               $genderCache = GenderCache::singleton();
+               $genderCache = MediaWikiServices::getInstance()->getGenderCache();
                $gender = $genderCache->getGenderOf( $username );
                $this->assertEquals( $gender, $expectedGender, "GenderCache normal" );
        }
@@ -79,7 +80,7 @@ class GenderCacheTest extends MediaWikiLangTestCase {
         */
        public function testStripSubpages( $userKey, $expectedGender ) {
                $username = isset( self::$nameMap[$userKey] ) ? self::$nameMap[$userKey] : $userKey;
-               $genderCache = GenderCache::singleton();
+               $genderCache = MediaWikiServices::getInstance()->getGenderCache();
                $gender = $genderCache->getGenderOf( "$username/subpage" );
                $this->assertEquals( $gender, $expectedGender, "GenderCache must strip of subpages" );
        }
index 697eb2d..ed82153 100644 (file)
@@ -61,14 +61,14 @@ class LocalisationCacheTest extends MediaWikiTestCase {
 
        public function testRecacheFallbacks() {
                $lc = $this->getMockLocalisationCache();
-               $lc->recache( 'uk' );
+               $lc->recache( 'ba' );
                $this->assertEquals(
                        [
-                               'present-uk' => 'uk',
+                               'present-ba' => 'ba',
                                'present-ru' => 'ru',
                                'present-en' => 'en',
                        ],
-                       $lc->getItem( 'uk', 'messages' ),
+                       $lc->getItem( 'ba', 'messages' ),
                        'Fallbacks are only used to fill missing data'
                );
        }
@@ -84,7 +84,7 @@ class LocalisationCacheTest extends MediaWikiTestCase {
                                        array &$cache
                                ) {
                                        if ( $code === 'ru' ) {
-                                               $cache['messages']['present-uk'] = 'ru-override';
+                                               $cache['messages']['present-ba'] = 'ru-override';
                                                $cache['messages']['present-ru'] = 'ru-override';
                                                $cache['messages']['present-en'] = 'ru-override';
                                        }
@@ -93,14 +93,14 @@ class LocalisationCacheTest extends MediaWikiTestCase {
                ] );
 
                $lc = $this->getMockLocalisationCache();
-               $lc->recache( 'uk' );
+               $lc->recache( 'ba' );
                $this->assertEquals(
                        [
-                               'present-uk' => 'uk',
+                               'present-ba' => 'ba',
                                'present-ru' => 'ru-override',
                                'present-en' => 'ru-override',
                        ],
-                       $lc->getItem( 'uk', 'messages' ),
+                       $lc->getItem( 'ba', 'messages' ),
                        'Updates provided by hooks follow the normal fallback order.'
                );
        }
index f42cb95..8a76618 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
+
 class ConfigFactoryTest extends MediaWikiTestCase {
 
        /**
@@ -140,7 +142,7 @@ class ConfigFactoryTest extends MediaWikiTestCase {
        public function testGetDefaultInstance() {
                // NOTE: the global config factory returned here has been overwritten
                // for operation in test mode. It may not reflect LocalSettings.
-               $factory = ConfigFactory::getDefaultInstance();
+               $factory = MediaWikiServices::getInstance()->getConfigFactory();
                $this->assertInstanceOf( 'Config', $factory->makeConfig( 'main' ) );
        }
 
diff --git a/tests/phpunit/includes/debug/logger/monolog/LogstashFormatterTest.php b/tests/phpunit/includes/debug/logger/monolog/LogstashFormatterTest.php
new file mode 100644 (file)
index 0000000..8086b4b
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+
+namespace MediaWiki\Logger\Monolog;
+
+class LogstashFormatterTest extends \PHPUnit_Framework_TestCase {
+       /**
+        * @dataProvider provideV1
+        * @param array $record The input record.
+        * @param array $expected Associative array of expected keys and their values.
+        * @param array $notExpected List of keys that should not exist.
+        */
+       public function testV1( array $record, array $expected, array $notExpected ) {
+               $formatter = new LogstashFormatter( 'app', 'system', null, null, LogstashFormatter::V1 );
+               $formatted = json_decode( $formatter->format( $record ), true );
+               foreach ( $expected as $key => $value ) {
+                       $this->assertArrayHasKey( $key, $formatted );
+                       $this->assertSame( $value, $formatted[$key] );
+               }
+               foreach ( $notExpected as $key ) {
+                       $this->assertArrayNotHasKey( $key, $formatted );
+               }
+       }
+
+       public function provideV1() {
+               return [
+                       [
+                               [ 'extra' => [ 'foo' => 1 ], 'context' => [ 'bar' => 2 ] ],
+                               [ 'foo' => 1, 'bar' => 2 ],
+                               [ 'logstash_formatter_key_conflict' ],
+                       ],
+                       [
+                               [ 'extra' => [ 'url' => 1 ], 'context' => [ 'url' => 2 ] ],
+                               [ 'url' => 1, 'c_url' => 2, 'logstash_formatter_key_conflict' => [ 'url' ] ],
+                               [],
+                       ],
+                       [
+                               [ 'channel' => 'x', 'context' => [ 'channel' => 'y' ] ],
+                               [ 'channel' => 'x', 'c_channel' => 'y',
+                                       'logstash_formatter_key_conflict' => [ 'channel' ] ],
+                               [],
+                       ],
+               ];
+       }
+
+       public function testV1WithPrefix() {
+               $formatter = new LogstashFormatter( 'app', 'system', null, 'ctx_', LogstashFormatter::V1 );
+               $record = [ 'extra' => [ 'url' => 1 ], 'context' => [ 'url' => 2 ] ];
+               $formatted = json_decode( $formatter->format( $record ), true );
+               $this->assertArrayHasKey( 'url', $formatted );
+               $this->assertSame( 1, $formatted['url'] );
+               $this->assertArrayHasKey( 'ctx_url', $formatted );
+               $this->assertSame( 2, $formatted['ctx_url'] );
+               $this->assertArrayNotHasKey( 'c_url', $formatted );
+       }
+}
index fbabf7f..33e3a25 100644 (file)
@@ -49,9 +49,9 @@ class HtmlAutoCompleteSelectFieldTest extends MediaWikiTestCase {
         */
        function testOptionalSelectElement() {
                $params = [
-                       'fieldname'    => 'Test',
-                       'autocomplete' => $this->options,
-                       'options'      => $this->options,
+                       'fieldname'         => 'Test',
+                       'autocomplete-data' => $this->options,
+                       'options'           => $this->options,
                ];
 
                $field = new HTMLAutoCompleteSelectField( $params );
index dd5b58b..f97716b 100644 (file)
@@ -51,7 +51,7 @@ class HtmlCheckMatrixTest extends MediaWikiTestCase {
 
        public function testValidateAllowsOnlyKnownTags() {
                $field = new HTMLCheckMatrix( self::$defaultOptions );
-               $this->assertInternalType( 'string', $this->validate( $field, [ 'foo' ] ) );
+               $this->assertInstanceOf( Message::class, $this->validate( $field, [ 'foo' ] ) );
        }
 
        public function testValidateAcceptsPartialTagList() {
diff --git a/tests/phpunit/includes/http/HttpTest.php b/tests/phpunit/includes/http/HttpTest.php
new file mode 100644 (file)
index 0000000..7e98d1c
--- /dev/null
@@ -0,0 +1,534 @@
+<?php
+
+/**
+ * @group Http
+ */
+class HttpTest extends MediaWikiTestCase {
+       /**
+        * @dataProvider cookieDomains
+        * @covers Cookie::validateCookieDomain
+        */
+       public function testValidateCookieDomain( $expected, $domain, $origin = null ) {
+               if ( $origin ) {
+                       $ok = Cookie::validateCookieDomain( $domain, $origin );
+                       $msg = "$domain against origin $origin";
+               } else {
+                       $ok = Cookie::validateCookieDomain( $domain );
+                       $msg = "$domain";
+               }
+               $this->assertEquals( $expected, $ok, $msg );
+       }
+
+       public static function cookieDomains() {
+               return [
+                       [ false, "org" ],
+                       [ false, ".org" ],
+                       [ true, "wikipedia.org" ],
+                       [ true, ".wikipedia.org" ],
+                       [ false, "co.uk" ],
+                       [ false, ".co.uk" ],
+                       [ false, "gov.uk" ],
+                       [ false, ".gov.uk" ],
+                       [ true, "supermarket.uk" ],
+                       [ false, "uk" ],
+                       [ false, ".uk" ],
+                       [ false, "127.0.0." ],
+                       [ false, "127." ],
+                       [ false, "127.0.0.1." ],
+                       [ true, "127.0.0.1" ],
+                       [ false, "333.0.0.1" ],
+                       [ true, "example.com" ],
+                       [ false, "example.com." ],
+                       [ true, ".example.com" ],
+
+                       [ true, ".example.com", "www.example.com" ],
+                       [ false, "example.com", "www.example.com" ],
+                       [ true, "127.0.0.1", "127.0.0.1" ],
+                       [ false, "127.0.0.1", "localhost" ],
+               ];
+       }
+
+       /**
+        * Test Http::isValidURI()
+        * @bug 27854 : Http::isValidURI is too lax
+        * @dataProvider provideURI
+        * @covers Http::isValidURI
+        */
+       public function testIsValidUri( $expect, $URI, $message = '' ) {
+               $this->assertEquals(
+                       $expect,
+                       (bool)Http::isValidURI( $URI ),
+                       $message
+               );
+       }
+
+       /**
+        * @covers Http::getProxy
+        */
+       public function testGetProxy() {
+               $this->setMwGlobals( 'wgHTTPProxy', 'proxy.domain.tld' );
+               $this->assertEquals(
+                       'proxy.domain.tld',
+                       Http::getProxy()
+               );
+       }
+
+       /**
+        * Feeds URI to test a long regular expression in Http::isValidURI
+        */
+       public static function provideURI() {
+               /** Format: 'boolean expectation', 'URI to test', 'Optional message' */
+               return [
+                       [ false, '¿non sens before!! http://a', 'Allow anything before URI' ],
+
+                       # (http|https) - only two schemes allowed
+                       [ true, 'http://www.example.org/' ],
+                       [ true, 'https://www.example.org/' ],
+                       [ true, 'http://www.example.org', 'URI without directory' ],
+                       [ true, 'http://a', 'Short name' ],
+                       [ true, 'http://étoile', 'Allow UTF-8 in hostname' ], # 'étoile' is french for 'star'
+                       [ false, '\\host\directory', 'CIFS share' ],
+                       [ false, 'gopher://host/dir', 'Reject gopher scheme' ],
+                       [ false, 'telnet://host', 'Reject telnet scheme' ],
+
+                       # :\/\/ - double slashes
+                       [ false, 'http//example.org', 'Reject missing colon in protocol' ],
+                       [ false, 'http:/example.org', 'Reject missing slash in protocol' ],
+                       [ false, 'http:example.org', 'Must have two slashes' ],
+                       # Following fail since hostname can be made of anything
+                       [ false, 'http:///example.org', 'Must have exactly two slashes, not three' ],
+
+                       # (\w+:{0,1}\w*@)? - optional user:pass
+                       [ true, 'http://user@host', 'Username provided' ],
+                       [ true, 'http://user:@host', 'Username provided, no password' ],
+                       [ true, 'http://user:pass@host', 'Username and password provided' ],
+
+                       # (\S+) - host part is made of anything not whitespaces
+                       // commented these out in order to remove @group Broken
+                       // @todo are these valid tests? if so, fix Http::isValidURI so it can handle them
+                       // [ false, 'http://!"èèè¿¿¿~~\'', 'hostname is made of any non whitespace' ],
+                       // [ false, 'http://exam:ple.org/', 'hostname can not use colons!' ],
+
+                       # (:[0-9]+)? - port number
+                       [ true, 'http://example.org:80/' ],
+                       [ true, 'https://example.org:80/' ],
+                       [ true, 'http://example.org:443/' ],
+                       [ true, 'https://example.org:443/' ],
+
+                       # Part after the hostname is / or / with something else
+                       [ true, 'http://example/#' ],
+                       [ true, 'http://example/!' ],
+                       [ true, 'http://example/:' ],
+                       [ true, 'http://example/.' ],
+                       [ true, 'http://example/?' ],
+                       [ true, 'http://example/+' ],
+                       [ true, 'http://example/=' ],
+                       [ true, 'http://example/&' ],
+                       [ true, 'http://example/%' ],
+                       [ true, 'http://example/@' ],
+                       [ true, 'http://example/-' ],
+                       [ true, 'http://example//' ],
+                       [ true, 'http://example/&' ],
+
+                       # Fragment
+                       [ true, 'http://exam#ple.org', ], # This one is valid, really!
+                       [ true, 'http://example.org:80#anchor' ],
+                       [ true, 'http://example.org/?id#anchor' ],
+                       [ true, 'http://example.org/?#anchor' ],
+
+                       [ false, 'http://a ¿non !!sens after', 'Allow anything after URI' ],
+               ];
+       }
+
+       /**
+        * Warning:
+        *
+        * These tests are for code that makes use of an artifact of how CURL
+        * handles header reporting on redirect pages, and will need to be
+        * rewritten when bug 29232 is taken care of (high-level handling of
+        * HTTP redirects).
+        */
+       public function testRelativeRedirections() {
+               $h = MWHttpRequestTester::factory( 'http://oldsite/file.ext', [], __METHOD__ );
+
+               # Forge a Location header
+               $h->setRespHeaders( 'location', [
+                               'http://newsite/file.ext',
+                               '/newfile.ext',
+                       ]
+               );
+               # Verify we correctly fix the Location
+               $this->assertEquals(
+                       'http://newsite/newfile.ext',
+                       $h->getFinalUrl(),
+                       "Relative file path Location: interpreted as full URL"
+               );
+
+               $h->setRespHeaders( 'location', [
+                               'https://oldsite/file.ext'
+                       ]
+               );
+               $this->assertEquals(
+                       'https://oldsite/file.ext',
+                       $h->getFinalUrl(),
+                       "Location to the HTTPS version of the site"
+               );
+
+               $h->setRespHeaders( 'location', [
+                               '/anotherfile.ext',
+                               'http://anotherfile/hoster.ext',
+                               'https://anotherfile/hoster.ext'
+                       ]
+               );
+               $this->assertEquals(
+                       'https://anotherfile/hoster.ext',
+                       $h->getFinalUrl( "Relative file path Location: should keep the latest host and scheme!" )
+               );
+       }
+
+       /**
+        * Constant values are from PHP 5.3.28 using cURL 7.24.0
+        * @see https://secure.php.net/manual/en/curl.constants.php
+        *
+        * All constant values are present so that developers don’t need to remember
+        * to add them if added at a later date. The commented out constants were
+        * not found anywhere in the MediaWiki core code.
+        *
+        * Commented out constants that were not available in:
+        * HipHop VM 3.3.0 (rel)
+        * Compiler: heads/master-0-g08810d920dfff59e0774cf2d651f92f13a637175
+        * Repo schema: 3214fc2c684a4520485f715ee45f33f2182324b1
+        * Extension API: 20140829
+        *
+        * Commented out constants that were removed in PHP 5.6.0
+        *
+        * @covers CurlHttpRequest::execute
+        */
+       public function provideCurlConstants() {
+               return [
+                       [ 'CURLAUTH_ANY' ],
+                       [ 'CURLAUTH_ANYSAFE' ],
+                       [ 'CURLAUTH_BASIC' ],
+                       [ 'CURLAUTH_DIGEST' ],
+                       [ 'CURLAUTH_GSSNEGOTIATE' ],
+                       [ 'CURLAUTH_NTLM' ],
+                       // [ 'CURLCLOSEPOLICY_CALLBACK' ], // removed in PHP 5.6.0
+                       // [ 'CURLCLOSEPOLICY_LEAST_RECENTLY_USED' ], // removed in PHP 5.6.0
+                       // [ 'CURLCLOSEPOLICY_LEAST_TRAFFIC' ], // removed in PHP 5.6.0
+                       // [ 'CURLCLOSEPOLICY_OLDEST' ], // removed in PHP 5.6.0
+                       // [ 'CURLCLOSEPOLICY_SLOWEST' ], // removed in PHP 5.6.0
+                       [ 'CURLE_ABORTED_BY_CALLBACK' ],
+                       [ 'CURLE_BAD_CALLING_ORDER' ],
+                       [ 'CURLE_BAD_CONTENT_ENCODING' ],
+                       [ 'CURLE_BAD_FUNCTION_ARGUMENT' ],
+                       [ 'CURLE_BAD_PASSWORD_ENTERED' ],
+                       [ 'CURLE_COULDNT_CONNECT' ],
+                       [ 'CURLE_COULDNT_RESOLVE_HOST' ],
+                       [ 'CURLE_COULDNT_RESOLVE_PROXY' ],
+                       [ 'CURLE_FAILED_INIT' ],
+                       [ 'CURLE_FILESIZE_EXCEEDED' ],
+                       [ 'CURLE_FILE_COULDNT_READ_FILE' ],
+                       [ 'CURLE_FTP_ACCESS_DENIED' ],
+                       [ 'CURLE_FTP_BAD_DOWNLOAD_RESUME' ],
+                       [ 'CURLE_FTP_CANT_GET_HOST' ],
+                       [ 'CURLE_FTP_CANT_RECONNECT' ],
+                       [ 'CURLE_FTP_COULDNT_GET_SIZE' ],
+                       [ 'CURLE_FTP_COULDNT_RETR_FILE' ],
+                       [ 'CURLE_FTP_COULDNT_SET_ASCII' ],
+                       [ 'CURLE_FTP_COULDNT_SET_BINARY' ],
+                       [ 'CURLE_FTP_COULDNT_STOR_FILE' ],
+                       [ 'CURLE_FTP_COULDNT_USE_REST' ],
+                       [ 'CURLE_FTP_PORT_FAILED' ],
+                       [ 'CURLE_FTP_QUOTE_ERROR' ],
+                       [ 'CURLE_FTP_SSL_FAILED' ],
+                       [ 'CURLE_FTP_USER_PASSWORD_INCORRECT' ],
+                       [ 'CURLE_FTP_WEIRD_227_FORMAT' ],
+                       [ 'CURLE_FTP_WEIRD_PASS_REPLY' ],
+                       [ 'CURLE_FTP_WEIRD_PASV_REPLY' ],
+                       [ 'CURLE_FTP_WEIRD_SERVER_REPLY' ],
+                       [ 'CURLE_FTP_WEIRD_USER_REPLY' ],
+                       [ 'CURLE_FTP_WRITE_ERROR' ],
+                       [ 'CURLE_FUNCTION_NOT_FOUND' ],
+                       [ 'CURLE_GOT_NOTHING' ],
+                       [ 'CURLE_HTTP_NOT_FOUND' ],
+                       [ 'CURLE_HTTP_PORT_FAILED' ],
+                       [ 'CURLE_HTTP_POST_ERROR' ],
+                       [ 'CURLE_HTTP_RANGE_ERROR' ],
+                       [ 'CURLE_LDAP_CANNOT_BIND' ],
+                       [ 'CURLE_LDAP_INVALID_URL' ],
+                       [ 'CURLE_LDAP_SEARCH_FAILED' ],
+                       [ 'CURLE_LIBRARY_NOT_FOUND' ],
+                       [ 'CURLE_MALFORMAT_USER' ],
+                       [ 'CURLE_OBSOLETE' ],
+                       [ 'CURLE_OK' ],
+                       [ 'CURLE_OPERATION_TIMEOUTED' ],
+                       [ 'CURLE_OUT_OF_MEMORY' ],
+                       [ 'CURLE_PARTIAL_FILE' ],
+                       [ 'CURLE_READ_ERROR' ],
+                       [ 'CURLE_RECV_ERROR' ],
+                       [ 'CURLE_SEND_ERROR' ],
+                       [ 'CURLE_SHARE_IN_USE' ],
+                       // [ 'CURLE_SSH' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLE_SSL_CACERT' ],
+                       [ 'CURLE_SSL_CERTPROBLEM' ],
+                       [ 'CURLE_SSL_CIPHER' ],
+                       [ 'CURLE_SSL_CONNECT_ERROR' ],
+                       [ 'CURLE_SSL_ENGINE_NOTFOUND' ],
+                       [ 'CURLE_SSL_ENGINE_SETFAILED' ],
+                       [ 'CURLE_SSL_PEER_CERTIFICATE' ],
+                       [ 'CURLE_TELNET_OPTION_SYNTAX' ],
+                       [ 'CURLE_TOO_MANY_REDIRECTS' ],
+                       [ 'CURLE_UNKNOWN_TELNET_OPTION' ],
+                       [ 'CURLE_UNSUPPORTED_PROTOCOL' ],
+                       [ 'CURLE_URL_MALFORMAT' ],
+                       [ 'CURLE_URL_MALFORMAT_USER' ],
+                       [ 'CURLE_WRITE_ERROR' ],
+                       [ 'CURLFTPAUTH_DEFAULT' ],
+                       [ 'CURLFTPAUTH_SSL' ],
+                       [ 'CURLFTPAUTH_TLS' ],
+                       // [ 'CURLFTPMETHOD_MULTICWD' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLFTPMETHOD_NOCWD' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLFTPMETHOD_SINGLECWD' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLFTPSSL_ALL' ],
+                       [ 'CURLFTPSSL_CONTROL' ],
+                       [ 'CURLFTPSSL_NONE' ],
+                       [ 'CURLFTPSSL_TRY' ],
+                       // [ 'CURLINFO_CERTINFO' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLINFO_CONNECT_TIME' ],
+                       [ 'CURLINFO_CONTENT_LENGTH_DOWNLOAD' ],
+                       [ 'CURLINFO_CONTENT_LENGTH_UPLOAD' ],
+                       [ 'CURLINFO_CONTENT_TYPE' ],
+                       [ 'CURLINFO_EFFECTIVE_URL' ],
+                       [ 'CURLINFO_FILETIME' ],
+                       [ 'CURLINFO_HEADER_OUT' ],
+                       [ 'CURLINFO_HEADER_SIZE' ],
+                       [ 'CURLINFO_HTTP_CODE' ],
+                       [ 'CURLINFO_NAMELOOKUP_TIME' ],
+                       [ 'CURLINFO_PRETRANSFER_TIME' ],
+                       [ 'CURLINFO_PRIVATE' ],
+                       [ 'CURLINFO_REDIRECT_COUNT' ],
+                       [ 'CURLINFO_REDIRECT_TIME' ],
+                       // [ 'CURLINFO_REDIRECT_URL' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLINFO_REQUEST_SIZE' ],
+                       [ 'CURLINFO_SIZE_DOWNLOAD' ],
+                       [ 'CURLINFO_SIZE_UPLOAD' ],
+                       [ 'CURLINFO_SPEED_DOWNLOAD' ],
+                       [ 'CURLINFO_SPEED_UPLOAD' ],
+                       [ 'CURLINFO_SSL_VERIFYRESULT' ],
+                       [ 'CURLINFO_STARTTRANSFER_TIME' ],
+                       [ 'CURLINFO_TOTAL_TIME' ],
+                       [ 'CURLMSG_DONE' ],
+                       [ 'CURLM_BAD_EASY_HANDLE' ],
+                       [ 'CURLM_BAD_HANDLE' ],
+                       [ 'CURLM_CALL_MULTI_PERFORM' ],
+                       [ 'CURLM_INTERNAL_ERROR' ],
+                       [ 'CURLM_OK' ],
+                       [ 'CURLM_OUT_OF_MEMORY' ],
+                       [ 'CURLOPT_AUTOREFERER' ],
+                       [ 'CURLOPT_BINARYTRANSFER' ],
+                       [ 'CURLOPT_BUFFERSIZE' ],
+                       [ 'CURLOPT_CAINFO' ],
+                       [ 'CURLOPT_CAPATH' ],
+                       // [ 'CURLOPT_CERTINFO' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLOPT_CLOSEPOLICY' ], // removed in PHP 5.6.0
+                       [ 'CURLOPT_CONNECTTIMEOUT' ],
+                       [ 'CURLOPT_CONNECTTIMEOUT_MS' ],
+                       [ 'CURLOPT_COOKIE' ],
+                       [ 'CURLOPT_COOKIEFILE' ],
+                       [ 'CURLOPT_COOKIEJAR' ],
+                       [ 'CURLOPT_COOKIESESSION' ],
+                       [ 'CURLOPT_CRLF' ],
+                       [ 'CURLOPT_CUSTOMREQUEST' ],
+                       [ 'CURLOPT_DNS_CACHE_TIMEOUT' ],
+                       [ 'CURLOPT_DNS_USE_GLOBAL_CACHE' ],
+                       [ 'CURLOPT_EGDSOCKET' ],
+                       [ 'CURLOPT_ENCODING' ],
+                       [ 'CURLOPT_FAILONERROR' ],
+                       [ 'CURLOPT_FILE' ],
+                       [ 'CURLOPT_FILETIME' ],
+                       [ 'CURLOPT_FOLLOWLOCATION' ],
+                       [ 'CURLOPT_FORBID_REUSE' ],
+                       [ 'CURLOPT_FRESH_CONNECT' ],
+                       [ 'CURLOPT_FTPAPPEND' ],
+                       [ 'CURLOPT_FTPLISTONLY' ],
+                       [ 'CURLOPT_FTPPORT' ],
+                       [ 'CURLOPT_FTPSSLAUTH' ],
+                       [ 'CURLOPT_FTP_CREATE_MISSING_DIRS' ],
+                       // [ 'CURLOPT_FTP_FILEMETHOD' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLOPT_FTP_SKIP_PASV_IP' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLOPT_FTP_SSL' ],
+                       [ 'CURLOPT_FTP_USE_EPRT' ],
+                       [ 'CURLOPT_FTP_USE_EPSV' ],
+                       [ 'CURLOPT_HEADER' ],
+                       [ 'CURLOPT_HEADERFUNCTION' ],
+                       [ 'CURLOPT_HTTP200ALIASES' ],
+                       [ 'CURLOPT_HTTPAUTH' ],
+                       [ 'CURLOPT_HTTPGET' ],
+                       [ 'CURLOPT_HTTPHEADER' ],
+                       [ 'CURLOPT_HTTPPROXYTUNNEL' ],
+                       [ 'CURLOPT_HTTP_VERSION' ],
+                       [ 'CURLOPT_INFILE' ],
+                       [ 'CURLOPT_INFILESIZE' ],
+                       [ 'CURLOPT_INTERFACE' ],
+                       [ 'CURLOPT_IPRESOLVE' ],
+                       // [ 'CURLOPT_KEYPASSWD' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLOPT_KRB4LEVEL' ],
+                       [ 'CURLOPT_LOW_SPEED_LIMIT' ],
+                       [ 'CURLOPT_LOW_SPEED_TIME' ],
+                       [ 'CURLOPT_MAXCONNECTS' ],
+                       [ 'CURLOPT_MAXREDIRS' ],
+                       // [ 'CURLOPT_MAX_RECV_SPEED_LARGE' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLOPT_MAX_SEND_SPEED_LARGE' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLOPT_NETRC' ],
+                       [ 'CURLOPT_NOBODY' ],
+                       [ 'CURLOPT_NOPROGRESS' ],
+                       [ 'CURLOPT_NOSIGNAL' ],
+                       [ 'CURLOPT_PORT' ],
+                       [ 'CURLOPT_POST' ],
+                       [ 'CURLOPT_POSTFIELDS' ],
+                       [ 'CURLOPT_POSTQUOTE' ],
+                       [ 'CURLOPT_POSTREDIR' ],
+                       [ 'CURLOPT_PRIVATE' ],
+                       [ 'CURLOPT_PROGRESSFUNCTION' ],
+                       // [ 'CURLOPT_PROTOCOLS' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLOPT_PROXY' ],
+                       [ 'CURLOPT_PROXYAUTH' ],
+                       [ 'CURLOPT_PROXYPORT' ],
+                       [ 'CURLOPT_PROXYTYPE' ],
+                       [ 'CURLOPT_PROXYUSERPWD' ],
+                       [ 'CURLOPT_PUT' ],
+                       [ 'CURLOPT_QUOTE' ],
+                       [ 'CURLOPT_RANDOM_FILE' ],
+                       [ 'CURLOPT_RANGE' ],
+                       [ 'CURLOPT_READDATA' ],
+                       [ 'CURLOPT_READFUNCTION' ],
+                       // [ 'CURLOPT_REDIR_PROTOCOLS' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLOPT_REFERER' ],
+                       [ 'CURLOPT_RESUME_FROM' ],
+                       [ 'CURLOPT_RETURNTRANSFER' ],
+                       // [ 'CURLOPT_SSH_AUTH_TYPES' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLOPT_SSH_HOST_PUBLIC_KEY_MD5' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLOPT_SSH_PRIVATE_KEYFILE' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLOPT_SSH_PUBLIC_KEYFILE' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLOPT_SSLCERT' ],
+                       [ 'CURLOPT_SSLCERTPASSWD' ],
+                       [ 'CURLOPT_SSLCERTTYPE' ],
+                       [ 'CURLOPT_SSLENGINE' ],
+                       [ 'CURLOPT_SSLENGINE_DEFAULT' ],
+                       [ 'CURLOPT_SSLKEY' ],
+                       [ 'CURLOPT_SSLKEYPASSWD' ],
+                       [ 'CURLOPT_SSLKEYTYPE' ],
+                       [ 'CURLOPT_SSLVERSION' ],
+                       [ 'CURLOPT_SSL_CIPHER_LIST' ],
+                       [ 'CURLOPT_SSL_VERIFYHOST' ],
+                       [ 'CURLOPT_SSL_VERIFYPEER' ],
+                       [ 'CURLOPT_STDERR' ],
+                       [ 'CURLOPT_TCP_NODELAY' ],
+                       [ 'CURLOPT_TIMECONDITION' ],
+                       [ 'CURLOPT_TIMEOUT' ],
+                       [ 'CURLOPT_TIMEOUT_MS' ],
+                       [ 'CURLOPT_TIMEVALUE' ],
+                       [ 'CURLOPT_TRANSFERTEXT' ],
+                       [ 'CURLOPT_UNRESTRICTED_AUTH' ],
+                       [ 'CURLOPT_UPLOAD' ],
+                       [ 'CURLOPT_URL' ],
+                       [ 'CURLOPT_USERAGENT' ],
+                       [ 'CURLOPT_USERPWD' ],
+                       [ 'CURLOPT_VERBOSE' ],
+                       [ 'CURLOPT_WRITEFUNCTION' ],
+                       [ 'CURLOPT_WRITEHEADER' ],
+                       // [ 'CURLPROTO_ALL' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_DICT' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_FILE' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_FTP' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_FTPS' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_HTTP' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_HTTPS' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_LDAP' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_LDAPS' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_SCP' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_SFTP' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_TELNET' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLPROTO_TFTP' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLPROXY_HTTP' ],
+                       // [ 'CURLPROXY_SOCKS4' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLPROXY_SOCKS5' ],
+                       // [ 'CURLSSH_AUTH_DEFAULT' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLSSH_AUTH_HOST' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLSSH_AUTH_KEYBOARD' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLSSH_AUTH_NONE' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLSSH_AUTH_PASSWORD' ], // not present in HHVM 3.3.0-dev
+                       // [ 'CURLSSH_AUTH_PUBLICKEY' ], // not present in HHVM 3.3.0-dev
+                       [ 'CURLVERSION_NOW' ],
+                       [ 'CURL_HTTP_VERSION_1_0' ],
+                       [ 'CURL_HTTP_VERSION_1_1' ],
+                       [ 'CURL_HTTP_VERSION_NONE' ],
+                       [ 'CURL_IPRESOLVE_V4' ],
+                       [ 'CURL_IPRESOLVE_V6' ],
+                       [ 'CURL_IPRESOLVE_WHATEVER' ],
+                       [ 'CURL_NETRC_IGNORED' ],
+                       [ 'CURL_NETRC_OPTIONAL' ],
+                       [ 'CURL_NETRC_REQUIRED' ],
+                       [ 'CURL_TIMECOND_IFMODSINCE' ],
+                       [ 'CURL_TIMECOND_IFUNMODSINCE' ],
+                       [ 'CURL_TIMECOND_LASTMOD' ],
+                       [ 'CURL_VERSION_IPV6' ],
+                       [ 'CURL_VERSION_KERBEROS4' ],
+                       [ 'CURL_VERSION_LIBZ' ],
+                       [ 'CURL_VERSION_SSL' ],
+               ];
+       }
+
+       /**
+        * Added this test based on an issue experienced with HHVM 3.3.0-dev
+        * where it did not define a cURL constant.
+        *
+        * @bug 70570
+        * @dataProvider provideCurlConstants
+        */
+       public function testCurlConstants( $value ) {
+               $this->assertTrue( defined( $value ), $value . ' not defined' );
+       }
+}
+
+/**
+ * Class to let us overwrite MWHttpRequest respHeaders variable
+ */
+class MWHttpRequestTester extends MWHttpRequest {
+       // function derived from the MWHttpRequest factory function but
+       // returns appropriate tester class here
+       public static function factory( $url, $options = null, $caller = __METHOD__ ) {
+               if ( !Http::$httpEngine ) {
+                       Http::$httpEngine = function_exists( 'curl_init' ) ? 'curl' : 'php';
+               } elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) {
+                       throw new DomainException( __METHOD__ . ': curl (http://php.net/curl) is not installed, but' .
+                               'Http::$httpEngine is set to "curl"' );
+               }
+
+               switch ( Http::$httpEngine ) {
+                       case 'curl':
+                               return new CurlHttpRequestTester( $url, $options, $caller );
+                       case 'php':
+                               if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
+                                       throw new DomainException( __METHOD__ .
+                                               ': allow_url_fopen needs to be enabled for pure PHP HTTP requests to work. '
+                                                       . 'If possible, curl should be used instead. See http://php.net/curl.' );
+                               }
+
+                               return new PhpHttpRequestTester( $url, $options, $caller );
+                       default:
+               }
+       }
+}
+
+class CurlHttpRequestTester extends CurlHttpRequest {
+       function setRespHeaders( $name, $value ) {
+               $this->respHeaders[$name] = $value;
+       }
+}
+
+class PhpHttpRequestTester extends PhpHttpRequest {
+       function setRespHeaders( $name, $value ) {
+               $this->respHeaders[$name] = $value;
+       }
+}
index 5e3c626..8e06f9e 100644 (file)
@@ -1,4 +1,6 @@
 <?php
+use MediaWiki\MediaWikiServices;
+
 /**
  * Integration test that checks import success and
  * LinkCache integration.
@@ -77,7 +79,7 @@ class ImportLinkCacheIntegrationTest extends MediaWikiTestCase {
 
                $importer = new WikiImporter(
                        $importStreamSource->value,
-                       ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       MediaWikiServices::getInstance()->getMainConfig()
                );
                $importer->setDebug( true );
 
index 9d05d15..53d91c6 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+use MediaWiki\MediaWikiServices;
 
 /**
  * Test class for Import methods.
@@ -25,7 +26,7 @@ class ImportTest extends MediaWikiLangTestCase {
 
                $importer = new WikiImporter(
                        $source,
-                       ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       MediaWikiServices::getInstance()->getMainConfig()
                );
 
                $importer->doImport();
@@ -92,7 +93,7 @@ EOF
 
                $importer = new WikiImporter(
                        $source,
-                       ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       MediaWikiServices::getInstance()->getMainConfig()
                );
                $importer->setPageOutCallback( $callback );
                $importer->doImport();
@@ -175,7 +176,7 @@ EOF
 
                $importer = new WikiImporter(
                        $source,
-                       ConfigFactory::getDefaultInstance()->makeConfig( 'main' )
+                       MediaWikiServices::getInstance()->getMainConfig()
                );
                $importer->setSiteInfoCallback( $callback );
                $importer->doImport();
diff --git a/tests/phpunit/includes/installer/DatabaseUpdaterTest.php b/tests/phpunit/includes/installer/DatabaseUpdaterTest.php
deleted file mode 100644 (file)
index 2a75cf4..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-<?php
-
-class DatabaseUpdaterTest extends MediaWikiTestCase {
-
-       public function testSetAppliedUpdates() {
-               $db = new FakeDatabase();
-               $dbu = new FakeDatabaseUpdater( $db );
-               $dbu->setAppliedUpdates( "test", [] );
-               $expected = "updatelist-test-" . time() . "0";
-               $actual = $db->lastInsertData['ul_key'];
-               $this->assertEquals( $expected, $actual, var_export( $db->lastInsertData, true ) );
-               $dbu->setAppliedUpdates( "test", [] );
-               $expected = "updatelist-test-" . time() . "1";
-               $actual = $db->lastInsertData['ul_key'];
-               $this->assertEquals( $expected, $actual, var_export( $db->lastInsertData, true ) );
-       }
-}
-
-class FakeDatabase extends Database {
-       public $lastInsertTable;
-       public $lastInsertData;
-
-       function __construct() {
-               $this->cliMode = true;
-               $this->connLogger = new \Psr\Log\NullLogger();
-               $this->queryLogger = new \Psr\Log\NullLogger();
-               $this->errorLogger = function ( Exception $e ) {
-                       wfWarn( get_class( $e ) . ": {$e->getMessage()}" );
-               };
-               $this->currentDomain = DatabaseDomain::newUnspecified();
-       }
-
-       function clearFlag( $arg, $remember = self::REMEMBER_NOTHING ) {
-       }
-
-       function setFlag( $arg, $remember = self::REMEMBER_NOTHING ) {
-       }
-
-       public function insert( $table, $a, $fname = __METHOD__, $options = [] ) {
-               $this->lastInsertTable = $table;
-               $this->lastInsertData = $a;
-       }
-
-       /**
-        * Get the type of the DBMS, as it appears in $wgDBtype.
-        *
-        * @return string
-        */
-       function getType() {
-               // TODO: Implement getType() method.
-       }
-
-       /**
-        * Open a connection to the database. Usually aborts on failure
-        *
-        * @param string $server Database server host
-        * @param string $user Database user name
-        * @param string $password Database user password
-        * @param string $dbName Database name
-        * @return bool
-        * @throws DBConnectionError
-        */
-       function open( $server, $user, $password, $dbName ) {
-               // TODO: Implement open() method.
-       }
-
-       /**
-        * Fetch the next row from the given result object, in object form.
-        * Fields can be retrieved with $row->fieldname, with fields acting like
-        * member variables.
-        * If no more rows are available, false is returned.
-        *
-        * @param ResultWrapper|stdClass $res Object as returned from Database::query(), etc.
-        * @return stdClass|bool
-        * @throws DBUnexpectedError Thrown if the database returns an error
-        */
-       function fetchObject( $res ) {
-               // TODO: Implement fetchObject() method.
-       }
-
-       /**
-        * Fetch the next row from the given result object, in associative array
-        * form. Fields are retrieved with $row['fieldname'].
-        * If no more rows are available, false is returned.
-        *
-        * @param ResultWrapper $res Result object as returned from Database::query(), etc.
-        * @return array|bool
-        * @throws DBUnexpectedError Thrown if the database returns an error
-        */
-       function fetchRow( $res ) {
-               // TODO: Implement fetchRow() method.
-       }
-
-       /**
-        * Get the number of rows in a result object
-        *
-        * @param mixed $res A SQL result
-        * @return int
-        */
-       function numRows( $res ) {
-               // TODO: Implement numRows() method.
-       }
-
-       /**
-        * Get the number of fields in a result object
-        * @see https://secure.php.net/mysql_num_fields
-        *
-        * @param mixed $res A SQL result
-        * @return int
-        */
-       function numFields( $res ) {
-               // TODO: Implement numFields() method.
-       }
-
-       /**
-        * Get a field name in a result object
-        * @see https://secure.php.net/mysql_field_name
-        *
-        * @param mixed $res A SQL result
-        * @param int $n
-        * @return string
-        */
-       function fieldName( $res, $n ) {
-               // TODO: Implement fieldName() method.
-       }
-
-       /**
-        * Get the inserted value of an auto-increment row
-        *
-        * The value inserted should be fetched from nextSequenceValue()
-        *
-        * Example:
-        * $id = $dbw->nextSequenceValue( 'page_page_id_seq' );
-        * $dbw->insert( 'page', [ 'page_id' => $id ] );
-        * $id = $dbw->insertId();
-        *
-        * @return int
-        */
-       function insertId() {
-               // TODO: Implement insertId() method.
-       }
-
-       /**
-        * Change the position of the cursor in a result object
-        * @see https://secure.php.net/mysql_data_seek
-        *
-        * @param mixed $res A SQL result
-        * @param int $row
-        */
-       function dataSeek( $res, $row ) {
-               // TODO: Implement dataSeek() method.
-       }
-
-       /**
-        * Get the last error number
-        * @see https://secure.php.net/mysql_errno
-        *
-        * @return int
-        */
-       function lastErrno() {
-               // TODO: Implement lastErrno() method.
-       }
-
-       /**
-        * Get a description of the last error
-        * @see https://secure.php.net/mysql_error
-        *
-        * @return string
-        */
-       function lastError() {
-               // TODO: Implement lastError() method.
-       }
-
-       /**
-        * mysql_fetch_field() wrapper
-        * Returns false if the field doesn't exist
-        *
-        * @param string $table Table name
-        * @param string $field Field name
-        *
-        * @return Field
-        */
-       function fieldInfo( $table, $field ) {
-               // TODO: Implement fieldInfo() method.
-       }
-
-       /**
-        * Get information about an index into an object
-        * @param string $table Table name
-        * @param string $index Index name
-        * @param string $fname Calling function name
-        * @return mixed Database-specific index description class or false if the index does not exist
-        */
-       function indexInfo( $table, $index, $fname = __METHOD__ ) {
-               // TODO: Implement indexInfo() method.
-       }
-
-       /**
-        * Get the number of rows affected by the last write query
-        * @see https://secure.php.net/mysql_affected_rows
-        *
-        * @return int
-        */
-       function affectedRows() {
-               // TODO: Implement affectedRows() method.
-       }
-
-       /**
-        * Wrapper for addslashes()
-        *
-        * @param string $s String to be slashed.
-        * @return string Slashed string.
-        */
-       function strencode( $s ) {
-               // TODO: Implement strencode() method.
-       }
-
-       /**
-        * Returns a wikitext link to the DB's website, e.g.,
-        *   return "[https://www.mysql.com/ MySQL]";
-        * Should at least contain plain text, if for some reason
-        * your database has no website.
-        *
-        * @return string Wikitext of a link to the server software's web site
-        */
-       function getSoftwareLink() {
-               // TODO: Implement getSoftwareLink() method.
-       }
-
-       /**
-        * A string describing the current software version, like from
-        * mysql_get_server_info().
-        *
-        * @return string Version information from the database server.
-        */
-       function getServerVersion() {
-               // TODO: Implement getServerVersion() method.
-       }
-
-       /**
-        * Closes underlying database connection
-        * @since 1.20
-        * @return bool Whether connection was closed successfully
-        */
-       protected function closeConnection() {
-               // TODO: Implement closeConnection() method.
-       }
-
-       /**
-        * The DBMS-dependent part of query()
-        *
-        * @param string $sql SQL query.
-        * @return ResultWrapper|bool Result object to feed to fetchObject,
-        *   fetchRow, ...; or false on failure
-        */
-       protected function doQuery( $sql ) {
-               // TODO: Implement doQuery() method.
-       }
-}
-
-class FakeDatabaseUpdater extends DatabaseUpdater {
-       function __construct( $db ) {
-               $this->db = $db;
-               self::$updateCounter = 0;
-       }
-
-       /**
-        * Get an array of updates to perform on the database. Should return a
-        * multi-dimensional array. The main key is the MediaWiki version (1.12,
-        * 1.13...) with the values being arrays of updates, identical to how
-        * updaters.inc did it (for now)
-        *
-        * @return array
-        */
-       protected function getCoreUpdateList() {
-               return [];
-       }
-
-       public function canUseNewUpdatelog() {
-               return true;
-       }
-
-       public function setAppliedUpdates( $version, $updates = [] ) {
-               parent::setAppliedUpdates( $version, $updates );
-       }
-}
diff --git a/tests/phpunit/includes/libs/rdbms/connectionmanager/ConnectionManagerTest.php b/tests/phpunit/includes/libs/rdbms/connectionmanager/ConnectionManagerTest.php
new file mode 100644 (file)
index 0000000..1677851
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+
+namespace Wikimedia\Tests\Rdbms;
+
+use IDatabase;
+use LoadBalancer;
+use PHPUnit_Framework_MockObject_MockObject;
+use Wikimedia\Rdbms\ConnectionManager;
+
+/**
+ * @covers Wikimedia\Rdbms\ConnectionManager
+ *
+ * @license GPL-2.0+
+ * @author Daniel Kinzler
+ */
+class ConnectionManagerTest extends \PHPUnit_Framework_TestCase {
+
+       /**
+        * @return IDatabase|PHPUnit_Framework_MockObject_MockObject
+        */
+       private function getIDatabaseMock() {
+               return $this->getMock( IDatabase::class );
+       }
+
+       /**
+        * @return LoadBalancer|PHPUnit_Framework_MockObject_MockObject
+        */
+       private function getLoadBalancerMock() {
+               $lb = $this->getMockBuilder( LoadBalancer::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+
+               return $lb;
+       }
+
+       public function testGetReadConnection_nullGroups() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnection' )
+                       ->with( DB_REPLICA, [ 'group1' ], 'someDbName' )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new ConnectionManager( $lb, 'someDbName', [ 'group1' ] );
+               $actual = $manager->getReadConnection();
+
+               $this->assertSame( $database, $actual );
+       }
+
+       public function testGetReadConnection_withGroups() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnection' )
+                       ->with( DB_REPLICA, [ 'group2' ], 'someDbName' )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new ConnectionManager( $lb, 'someDbName', [ 'group1' ] );
+               $actual = $manager->getReadConnection( [ 'group2' ] );
+
+               $this->assertSame( $database, $actual );
+       }
+
+       public function testGetWriteConnection() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnection' )
+                       ->with( DB_MASTER, [ 'group1' ], 'someDbName' )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new ConnectionManager( $lb, 'someDbName', [ 'group1' ] );
+               $actual = $manager->getWriteConnection();
+
+               $this->assertSame( $database, $actual );
+       }
+
+       public function testReleaseConnection() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'reuseConnection' )
+                       ->with( $database )
+                       ->will( $this->returnValue( null ) );
+
+               $manager = new ConnectionManager( $lb );
+               $manager->releaseConnection( $database );
+       }
+
+       public function testGetReadConnectionRef_nullGroups() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnectionRef' )
+                       ->with( DB_REPLICA, [ 'group1' ], 'someDbName' )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new ConnectionManager( $lb, 'someDbName', [ 'group1' ] );
+               $actual = $manager->getReadConnectionRef();
+
+               $this->assertSame( $database, $actual );
+       }
+
+       public function testGetReadConnectionRef_withGroups() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnectionRef' )
+                       ->with( DB_REPLICA, [ 'group2' ], 'someDbName' )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new ConnectionManager( $lb, 'someDbName', [ 'group1' ] );
+               $actual = $manager->getReadConnectionRef( [ 'group2' ] );
+
+               $this->assertSame( $database, $actual );
+       }
+
+       public function testGetWriteConnectionRef() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnectionRef' )
+                       ->with( DB_MASTER, [ 'group1' ], 'someDbName' )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new ConnectionManager( $lb, 'someDbName', [ 'group1' ] );
+               $actual = $manager->getWriteConnectionRef();
+
+               $this->assertSame( $database, $actual );
+       }
+
+}
diff --git a/tests/phpunit/includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManagerTest.php b/tests/phpunit/includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManagerTest.php
new file mode 100644 (file)
index 0000000..0d54659
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+
+namespace Wikimedia\Tests\Rdbms;
+
+use IDatabase;
+use LoadBalancer;
+use PHPUnit_Framework_MockObject_MockObject;
+use Wikimedia\Rdbms\SessionConsistentConnectionManager;
+
+/**
+ * @covers Wikimedia\Rdbms\SessionConsistentConnectionManager
+ *
+ * @license GPL-2.0+
+ * @author Daniel Kinzler
+ */
+class SessionConsistentConnectionManagerTest extends \PHPUnit_Framework_TestCase {
+
+       /**
+        * @return IDatabase|PHPUnit_Framework_MockObject_MockObject
+        */
+       private function getIDatabaseMock() {
+               return $this->getMock( IDatabase::class );
+       }
+
+       /**
+        * @return LoadBalancer|PHPUnit_Framework_MockObject_MockObject
+        */
+       private function getLoadBalancerMock() {
+               $lb = $this->getMockBuilder( LoadBalancer::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+
+               return $lb;
+       }
+
+       public function testGetReadConnection() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnection' )
+                       ->with( DB_REPLICA )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new SessionConsistentConnectionManager( $lb );
+               $actual = $manager->getReadConnection();
+
+               $this->assertSame( $database, $actual );
+       }
+
+       public function testGetReadConnectionReturnsWriteDbOnForceMatser() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnection' )
+                       ->with( DB_MASTER )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new SessionConsistentConnectionManager( $lb );
+               $manager->prepareForUpdates();
+               $actual = $manager->getReadConnection();
+
+               $this->assertSame( $database, $actual );
+       }
+
+       public function testGetWriteConnection() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnection' )
+                       ->with( DB_MASTER )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new SessionConsistentConnectionManager( $lb );
+               $actual = $manager->getWriteConnection();
+
+               $this->assertSame( $database, $actual );
+       }
+
+       public function testForceMaster() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'getConnection' )
+                       ->with( DB_MASTER )
+                       ->will( $this->returnValue( $database ) );
+
+               $manager = new SessionConsistentConnectionManager( $lb );
+               $manager->prepareForUpdates();
+               $manager->getReadConnection();
+       }
+
+       public function testReleaseConnection() {
+               $database = $this->getIDatabaseMock();
+               $lb = $this->getLoadBalancerMock();
+
+               $lb->expects( $this->once() )
+                       ->method( 'reuseConnection' )
+                       ->with( $database )
+                       ->will( $this->returnValue( null ) );
+
+               $manager = new SessionConsistentConnectionManager( $lb );
+               $manager->releaseConnection( $database );
+       }
+}
index a96a296..7d0813d 100644 (file)
@@ -63,13 +63,9 @@ class ArticleTest extends MediaWikiTestCase {
         * @covers Article::onArticleCreate
         * @covers Article::onArticleDelete
         * @covers Article::onArticleEdit
-        * @covers Article::getAutosummary
         */
        public function testStaticFunctions() {
                $this->hideDeprecated( 'Article::selectFields' );
-               $this->hideDeprecated( 'Article::getAutosummary' );
-               $this->hideDeprecated( 'WikiPage::getAutosummary' );
-               $this->hideDeprecated( 'CategoryPage::getAutosummary' ); // Inherited from Article
 
                $this->assertEquals( WikiPage::selectFields(), Article::selectFields(),
                        "Article static functions" );
@@ -79,7 +75,5 @@ class ArticleTest extends MediaWikiTestCase {
                        "Article static functions" );
                $this->assertEquals( true, is_callable( "ImagePage::onArticleEdit" ),
                        "Article static functions" );
-               $this->assertTrue( is_string( CategoryPage::getAutosummary( '', '', 0 ) ),
-                       "Article static functions" );
        }
 }
index 4b7ebd3..49d9fd2 100644 (file)
@@ -1034,63 +1034,6 @@ more stuff
                $this->assertEquals( "one", $page->getContent()->getNativeData() );
        }
 
-       public static function provideGetAutosummary() {
-               return [
-                       [
-                               'Hello there, world!',
-                               '#REDIRECT [[Foo]]',
-                               0,
-                               '/^Redirected page .*Foo/'
-                       ],
-
-                       [
-                               null,
-                               'Hello world!',
-                               EDIT_NEW,
-                               '/^Created page .*Hello/'
-                       ],
-
-                       [
-                               'Hello there, world!',
-                               '',
-                               0,
-                               '/^Blanked/'
-                       ],
-
-                       [
-                               'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
-                               eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
-                               voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
-                               clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
-                               'Hello world!',
-                               0,
-                               '/^Replaced .*Hello/'
-                       ],
-
-                       [
-                               'foo',
-                               'bar',
-                               0,
-                               '/^$/'
-                       ],
-               ];
-       }
-
-       /**
-        * @dataProvider provideGetAutoSummary
-        * @covers WikiPage::getAutosummary
-        */
-       public function testGetAutosummary( $old, $new, $flags, $expected ) {
-               $this->hideDeprecated( "WikiPage::getAutosummary" );
-
-               $page = $this->newPage( "WikiPageTest_testGetAutosummary" );
-
-               $summary = $page->getAutosummary( $old, $new, $flags );
-
-               $this->assertTrue( (bool)preg_match( $expected, $summary ),
-                       "Autosummary didn't match expected pattern $expected: $summary" );
-       }
-
        public static function provideGetAutoDeleteReason() {
                return [
                        [
index 1de4265..9b57e1c 100644 (file)
@@ -259,7 +259,7 @@ class ExtensionRegistryTest extends MediaWikiTestCase {
                                                'JsonZeroConfig' => [
                                                        'namespace' => 480,
                                                        'nsName' => 'Zero',
-                                                       'isLocal' => false,
+                                                       'isLocal' => true,
                                                ],
                                        ],
                                ],
index d2a0724..528c322 100644 (file)
@@ -114,22 +114,22 @@ class ResourceLoaderClientHtmlTest extends PHPUnit_Framework_TestCase {
                                'test.scripts.mixed.user.empty' => 'ready',
                        ],
                        'general' => [
-                               'top' => [ 'test.top' ],
-                               'bottom' => [ 'test' ],
+                               'test',
+                               'test.top',
                        ],
                        'styles' => [
                                'test.styles.mixed',
                                'test.styles.pure',
                        ],
                        'scripts' => [
-                               'top' => [ 'test.scripts.top' ],
-                               'bottom' => [ 'test.scripts' ],
+                               'test.scripts',
+                               'test.scripts.top',
                        ],
                        'embed' => [
                                'styles' => [ 'test.styles.private' ],
                                'general' => [
-                                       'top' => [ 'test.private.top' ],
-                                       'bottom' => [ 'test.private.bottom' ],
+                                       'test.private.bottom',
+                                       'test.private.top',
                                ],
                        ],
                ];
@@ -202,13 +202,7 @@ class ResourceLoaderClientHtmlTest extends PHPUnit_Framework_TestCase {
                        'test.scripts',
                ] );
 
-               // @codingStandardsIgnoreStart Generic.Files.LineLength
-               $expected = '<script>(window.RLQ=window.RLQ||[]).push(function(){'
-                       . 'mw.loader.implement("test.private.bottom@{blankVer}",function($,jQuery,require,module){},{"css":[]});'
-                       . 'mw.loader.load("/w/load.php?debug=false\u0026lang=nl\u0026modules=test.scripts\u0026only=scripts\u0026skin=fallback");'
-                       . 'mw.loader.load(["test"]);'
-                       . '});</script>';
-               // @codingStandardsIgnoreEnd
+               $expected = '';
                $expected = self::expandVariables( $expected );
 
                $this->assertEquals( $expected, $client->getBodyHtml() );
index 1093039..baf0b69 100644 (file)
@@ -104,4 +104,13 @@ class ResourceLoaderContextTest extends PHPUnit_Framework_TestCase {
                $this->assertSame( 'Example', $ctx->getUser() );
                $this->assertEquals( 'Example', $ctx->getUserObj()->getName() );
        }
+
+       public function testMsg() {
+               $ctx = new ResourceLoaderContext( $this->getResourceLoader(), new FauxRequest( [
+                       'lang' => 'en'
+               ] ) );
+               $msg = $ctx->msg( 'mainpage' );
+               $this->assertInstanceOf( Message::class, $msg );
+               $this->assertSame( 'Main Page', $msg->useDatabase( false )->plain() );
+       }
 }
index 8b29983..4a3b90a 100644 (file)
@@ -130,7 +130,7 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                $modules = self::getModules();
                $rl = new ResourceLoaderFileModule( $modules[$name] );
                $rl->setName( $name );
-               $ctx = $this->getResourceLoaderContext( 'en', 'ltr' );
+               $ctx = $this->getResourceLoaderContext();
                $this->assertEquals( $rl->getScript( $ctx ), $expected );
        }
 
@@ -210,8 +210,14 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                ] );
                $expectedModule->setName( 'testing' );
 
-               $contextLtr = $this->getResourceLoaderContext( 'en', 'ltr' );
-               $contextRtl = $this->getResourceLoaderContext( 'he', 'rtl' );
+               $contextLtr = $this->getResourceLoaderContext( [
+                       'lang' => 'en',
+                       'dir' => 'ltr',
+               ] );
+               $contextRtl = $this->getResourceLoaderContext( [
+                       'lang' => 'he',
+                       'dir' => 'rtl',
+               ] );
 
                // Since we want to compare the effect of @noflip+@embed against the effect of just @embed, and
                // the @noflip annotations are always preserved, we need to strip them first.
@@ -282,9 +288,9 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                        'File has leading BOM'
                );
 
-               $contextLtr = $this->getResourceLoaderContext( 'en', 'ltr' );
+               $context = $this->getResourceLoaderContext();
                $this->assertEquals(
-                       $testModule->getStyles( $contextLtr ),
+                       $testModule->getStyles( $context ),
                        [ 'all' => ".efbbbf_bom_char_at_start_of_file {}\n" ],
                        'Leading BOM removed when concatenating files'
                );
index 179a8ed..84b56d4 100644 (file)
@@ -61,7 +61,10 @@ class ResourceLoaderImageTest extends ResourceLoaderTestCase {
                static $contexts = [];
 
                $image = $this->getTestImage( $imageName );
-               $context = $this->getResourceLoaderContext( $languageCode, $dirMap[$languageCode] );
+               $context = $this->getResourceLoaderContext( [
+                       'lang' => $languageCode,
+                       'dir' => $dirMap[$languageCode],
+               ] );
 
                $this->assertEquals( $image->getPath( $context ), $this->imagesPath . '/' . $path );
        }
@@ -87,7 +90,7 @@ class ResourceLoaderImageTest extends ResourceLoaderTestCase {
         * @covers ResourceLoaderImage::massageSvgPathdata
         */
        public function testGetImageData() {
-               $context = $this->getResourceLoaderContext( 'en', 'ltr' );
+               $context = $this->getResourceLoaderContext();
 
                $image = $this->getTestImage( 'remove' );
                $data = file_get_contents( $this->imagesPath . '/remove.svg' );
index c24a321..1ecdf21 100644 (file)
@@ -51,6 +51,16 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
                $this->assertEquals( $module, $resourceLoader->getModule( 'test' ) );
        }
 
+       /**
+        * @covers ResourceLoader::register
+        */
+       public function testRegisterEmptyString() {
+               $module = new ResourceLoaderTestModule();
+               $resourceLoader = new EmptyResourceLoader();
+               $resourceLoader->register( '', $module );
+               $this->assertEquals( $module, $resourceLoader->getModule( '' ) );
+       }
+
        /**
         * @covers ResourceLoader::register
         */
index e0de588..a88264b 100644 (file)
@@ -126,11 +126,11 @@ class SearchEnginePrefixTest extends MediaWikiLangTestCase {
                                'results' => [
                                        'Special:ActiveUsers',
                                        'Special:AllMessages',
-                                       'Special:AllMyFiles',
+                                       'Special:AllMyUploads',
                                ],
                                // Third result when testing offset
                                'offsetresult' => [
-                                       'Special:AllMyUploads',
+                                       'Special:AllPages',
                                ],
                        ] ],
                        [ [
@@ -143,7 +143,7 @@ class SearchEnginePrefixTest extends MediaWikiLangTestCase {
                                ],
                                // Third result when testing offset
                                'offsetresult' => [
-                                       'Special:UncategorizedImages',
+                                       'Special:UncategorizedPages',
                                ],
                        ] ],
                        [ [
index cc16e5f..03e9c8f 100644 (file)
@@ -22,9 +22,17 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
        protected $rc;
 
        /** helper to test SpecialRecentchanges::buildMainQueryConds() */
-       private function assertConditions( $expected, $requestOptions = null, $message = '' ) {
+       private function assertConditions(
+               $expected,
+               $requestOptions = null,
+               $message = '',
+               $user = null
+       ) {
                $context = new RequestContext;
                $context->setRequest( new FauxRequest( $requestOptions ) );
+               if ( $user ) {
+                       $context->setUser( $user );
+               }
 
                # setup the rc object
                $this->rc = new SpecialRecentChanges();
@@ -40,12 +48,22 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
                );
 
                $this->assertEquals(
-                       $expected,
-                       $queryConditions,
+                       self::normalizeCondition( $expected ),
+                       self::normalizeCondition( $queryConditions ),
                        $message
                );
        }
 
+       private static function normalizeCondition( $conds ) {
+               return array_map(
+                       function ( $k, $v ) {
+                               return is_numeric( $k ) ? $v : "$k = $v";
+                       },
+                       array_keys( $conds ),
+                       $conds
+               );
+       }
+
        /** return false if condition begin with 'rc_timestamp ' */
        private static function filterOutRcTimestampCondition( $var ) {
                return ( false === strpos( $var, 'rc_timestamp ' ) );
@@ -55,8 +73,8 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
                $this->assertConditions(
                        [ # expected
                                'rc_bot' => 0,
-                               0 => "rc_type != '6'",
-                               1 => "rc_namespace = '0'",
+                               "rc_type != '6'",
+                               "rc_namespace = '0'",
                        ],
                        [
                                'namespace' => NS_MAIN,
@@ -69,8 +87,8 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
                $this->assertConditions(
                        [ # expected
                                'rc_bot' => 0,
-                               0 => "rc_type != '6'",
-                               1 => sprintf( "rc_namespace != '%s'", NS_MAIN ),
+                               "rc_type != '6'",
+                               "rc_namespace != '0'",
                        ],
                        [
                                'namespace' => NS_MAIN,
@@ -88,8 +106,8 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
                $this->assertConditions(
                        [ # expected
                                'rc_bot' => 0,
-                               0 => "rc_type != '6'",
-                               1 => sprintf( "(rc_namespace = '%s' OR rc_namespace = '%s')", $ns1, $ns2 ),
+                               "rc_type != '6'",
+                               "(rc_namespace = '$ns1' OR rc_namespace = '$ns2')",
                        ],
                        [
                                'namespace' => $ns1,
@@ -107,8 +125,8 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
                $this->assertConditions(
                        [ # expected
                                'rc_bot' => 0,
-                               0 => "rc_type != '6'",
-                               1 => sprintf( "(rc_namespace != '%s' AND rc_namespace != '%s')", $ns1, $ns2 ),
+                               "rc_type != '6'",
+                               "(rc_namespace != '$ns1' AND rc_namespace != '$ns2')",
                        ],
                        [
                                'namespace' => $ns1,
@@ -129,4 +147,220 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
                        [ NS_TALK, NS_MAIN ],
                ];
        }
+
+       public function testRcHidemyselfFilter() {
+               $user = $this->getTestUser()->getUser();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_user != '{$user->getId()}'",
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidemyself' => 1,
+                       ],
+                       "rc conditions: hidemyself=1 (logged in)",
+                       $user
+               );
+
+               $user = User::newFromName( '10.11.12.13', false );
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_user_text != '10.11.12.13'",
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidemyself' => 1,
+                       ],
+                       "rc conditions: hidemyself=1 (anon)",
+                       $user
+               );
+       }
+
+       public function testRcHidebyothersFilter() {
+               $user = $this->getTestUser()->getUser();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_user = '{$user->getId()}'",
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidebyothers' => 1,
+                       ],
+                       "rc conditions: hidebyothers=1 (logged in)",
+                       $user
+               );
+
+               $user = User::newFromName( '10.11.12.13', false );
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_user_text = '10.11.12.13'",
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidebyothers' => 1,
+                       ],
+                       "rc conditions: hidebyothers=1 (anon)",
+                       $user
+               );
+       }
+
+       public function testRcHidemyselfHidebyothersFilter() {
+               $user = $this->getTestUser()->getUser();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_user != '{$user->getId()}'",
+                               "rc_user = '{$user->getId()}'",
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidemyself' => 1,
+                               'hidebyothers' => 1,
+                       ],
+                       "rc conditions: hidemyself=1 hidebyothers=1 (logged in)",
+                       $user
+               );
+       }
+
+       public function testRcHidepageedits() {
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_type != '6'",
+                               "rc_type != '0'",
+                       ],
+                       [
+                               'hidepageedits' => 1,
+                       ],
+                       "rc conditions: hidepageedits=1"
+               );
+       }
+
+       public function testRcHidenewpages() {
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_type != '6'",
+                               "rc_type != '1'",
+                       ],
+                       [
+                               'hidenewpages' => 1,
+                       ],
+                       "rc conditions: hidenewpages=1"
+               );
+       }
+
+       public function testRcHidelog() {
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_type != '6'",
+                               "rc_type != '3'",
+                       ],
+                       [
+                               'hidelog' => 1,
+                       ],
+                       "rc conditions: hidelog=1"
+               );
+       }
+
+       public function testRcHidehumans() {
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 1,
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidebots' => 0,
+                               'hidehumans' => 1,
+                       ],
+                       "rc conditions: hidebots=0 hidehumans=1"
+               );
+       }
+
+       public function testRcHidepatrolledDisabledFilter() {
+               $user = $this->getTestUser()->getUser();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidepatrolled' => 1,
+                       ],
+                       "rc conditions: hidepatrolled=1 (user not allowed)",
+                       $user
+               );
+       }
+
+       public function testRcHideunpatrolledDisabledFilter() {
+               $user = $this->getTestUser()->getUser();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hideunpatrolled' => 1,
+                       ],
+                       "rc conditions: hideunpatrolled=1 (user not allowed)",
+                       $user
+               );
+       }
+       public function testRcHidepatrolledFilter() {
+               $user = $this->getTestSysop()->getUser();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_patrolled = 0",
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidepatrolled' => 1,
+                       ],
+                       "rc conditions: hidepatrolled=1",
+                       $user
+               );
+       }
+
+       public function testRcHideunpatrolledFilter() {
+               $user = $this->getTestSysop()->getUser();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_patrolled = 1",
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hideunpatrolled' => 1,
+                       ],
+                       "rc conditions: hideunpatrolled=1",
+                       $user
+               );
+       }
+
+       // This is probably going to change when we do auto-fix of
+       // filters combinations that don't make sense but for now
+       // it's the behavior therefore it's the test.
+       public function testRcHidepatrolledHideunpatrolledFilter() {
+               $user = $this->getTestSysop()->getUser();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_bot' => 0,
+                               "rc_patrolled = 0",
+                               "rc_patrolled = 1",
+                               "rc_type != '6'",
+                       ],
+                       [
+                               'hidepatrolled' => 1,
+                               'hideunpatrolled' => 1,
+                       ],
+                       "rc conditions: hidepatrolled=1 hideunpatrolled=1",
+                       $user
+               );
+       }
 }
index 6d17a68..62081aa 100644 (file)
@@ -58,7 +58,7 @@ class UploadFromUrlTest extends ApiTestCase {
                        $this->doApiRequest( [
                                'action' => 'upload',
                        ] );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                        $this->assertEquals( "The token parameter must be set", $e->getMessage() );
                }
@@ -70,7 +70,7 @@ class UploadFromUrlTest extends ApiTestCase {
                                'action' => 'upload',
                                'token' => $token,
                        ], $data );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                        $this->assertEquals( "One of the parameters sessionkey, file, url is required",
                                $e->getMessage() );
@@ -84,7 +84,7 @@ class UploadFromUrlTest extends ApiTestCase {
                                'url' => 'http://www.example.com/test.png',
                                'token' => $token,
                        ], $data );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                        $this->assertEquals( "The filename parameter must be set", $e->getMessage() );
                }
@@ -99,7 +99,7 @@ class UploadFromUrlTest extends ApiTestCase {
                                'filename' => 'UploadFromUrlTest.png',
                                'token' => $token,
                        ], $data );
-               } catch ( UsageException $e ) {
+               } catch ( ApiUsageException $e ) {
                        $exception = true;
                        $this->assertEquals( "Permission denied", $e->getMessage() );
                }
index 4db636b..7ff882a 100644 (file)
@@ -11,7 +11,7 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
         */
        public function testIsAllowed( $passwordResetRoutes, $enableEmail,
                $allowsAuthenticationDataChange, $canEditPrivate, $canSeePassword,
-               $userIsBlocked, $isAllowed, $isAllowedToDisplayPassword
+               $userIsBlocked, $isAllowed
        ) {
                $config = new HashConfig( [
                        'PasswordResetRoutes' => $passwordResetRoutes,
@@ -40,8 +40,6 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
                $passwordReset = new PasswordReset( $config, $authManager );
 
                $this->assertSame( $isAllowed, $passwordReset->isAllowed( $user )->isGood() );
-               $this->assertSame( $isAllowedToDisplayPassword,
-                       $passwordReset->isAllowed( $user, true )->isGood() );
        }
 
        public function provideIsAllowed() {
@@ -54,7 +52,6 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
                                'canSeePassword' => true,
                                'userIsBlocked' => false,
                                'isAllowed' => false,
-                               'isAllowedToDisplayPassword' => false,
                        ],
                        [
                                'passwordResetRoutes' => [ 'username' => true ],
@@ -64,7 +61,6 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
                                'canSeePassword' => true,
                                'userIsBlocked' => false,
                                'isAllowed' => false,
-                               'isAllowedToDisplayPassword' => false,
                        ],
                        [
                                'passwordResetRoutes' => [ 'username' => true ],
@@ -74,7 +70,6 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
                                'canSeePassword' => true,
                                'userIsBlocked' => false,
                                'isAllowed' => false,
-                               'isAllowedToDisplayPassword' => false,
                        ],
                        [
                                'passwordResetRoutes' => [ 'username' => true ],
@@ -84,7 +79,6 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
                                'canSeePassword' => true,
                                'userIsBlocked' => false,
                                'isAllowed' => false,
-                               'isAllowedToDisplayPassword' => false,
                        ],
                        [
                                'passwordResetRoutes' => [ 'username' => true ],
@@ -94,7 +88,6 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
                                'canSeePassword' => true,
                                'userIsBlocked' => true,
                                'isAllowed' => false,
-                               'isAllowedToDisplayPassword' => false,
                        ],
                        [
                                'passwordResetRoutes' => [ 'username' => true ],
@@ -104,7 +97,6 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
                                'canSeePassword' => false,
                                'userIsBlocked' => false,
                                'isAllowed' => true,
-                               'isAllowedToDisplayPassword' => false,
                        ],
                        [
                                'passwordResetRoutes' => [ 'username' => true ],
@@ -114,7 +106,6 @@ class PasswordResetTest extends PHPUnit_Framework_TestCase {
                                'canSeePassword' => true,
                                'userIsBlocked' => false,
                                'isAllowed' => true,
-                               'isAllowedToDisplayPassword' => true,
                        ],
                ];
        }
index 199fc8f..0819bf2 100644 (file)
@@ -3,6 +3,8 @@
 define( 'NS_UNITTEST', 5600 );
 define( 'NS_UNITTEST_TALK', 5601 );
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * @group Database
  */
@@ -347,6 +349,12 @@ class UserTest extends MediaWikiTestCase {
                $user->saveSettings();
 
                $user = User::newFromName( $user->getName() );
+               $user->load( User::READ_LATEST );
+               $this->assertEquals( 'test', $user->getOption( 'userjs-someoption' ) );
+               $this->assertEquals( 200, $user->getOption( 'cols' ) );
+
+               $user = User::newFromName( $user->getName() );
+               MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache();
                $this->assertEquals( 'test', $user->getOption( 'userjs-someoption' ) );
                $this->assertEquals( 200, $user->getOption( 'cols' ) );
        }
@@ -578,4 +586,162 @@ class UserTest extends MediaWikiTestCase {
                $users->rewind();
                $this->assertTrue( $user->equals( $users->current() ) );
        }
+
+       /**
+        * When a user is autoblocked a cookie is set with which to track them
+        * in case they log out and change IP addresses.
+        * @link https://phabricator.wikimedia.org/T5233
+        */
+       public function testAutoblockCookies() {
+               // Set up the bits of global configuration that we use.
+               $this->setMwGlobals( [
+                       'wgCookieSetOnAutoblock' => true,
+                       'wgCookiePrefix' => 'wmsitetitle',
+               ] );
+
+               // 1. Log in a test user, and block them.
+               $user1tmp = $this->getTestUser()->getUser();
+               $request1 = new FauxRequest();
+               $request1->getSession()->setUser( $user1tmp );
+               $expiryFiveDays = time() + ( 5 * 24 * 60 * 60 );
+               $block = new Block( [
+                       'enableAutoblock' => true,
+                       'expiry' => wfTimestamp( TS_MW, $expiryFiveDays ),
+               ] );
+               $block->setTarget( $user1tmp );
+               $block->insert();
+               $user1 = User::newFromSession( $request1 );
+               $user1->mBlock = $block;
+               $user1->load();
+
+               // Confirm that the block has been applied as required.
+               $this->assertTrue( $user1->isLoggedIn() );
+               $this->assertTrue( $user1->isBlocked() );
+               $this->assertEquals( Block::TYPE_USER, $block->getType() );
+               $this->assertTrue( $block->isAutoblocking() );
+               $this->assertGreaterThanOrEqual( 1, $block->getId() );
+
+               // Test for the desired cookie name, value, and expiry.
+               $cookies = $request1->response()->getCookies();
+               $this->assertArrayHasKey( 'wmsitetitleBlockID', $cookies );
+               $this->assertEquals( $block->getId(), $cookies['wmsitetitleBlockID']['value'] );
+               $this->assertEquals( $expiryFiveDays, $cookies['wmsitetitleBlockID']['expire'] );
+
+               // 2. Create a new request, set the cookies, and see if the (anon) user is blocked.
+               $request2 = new FauxRequest();
+               $request2->setCookie( 'BlockID', $block->getId() );
+               $user2 = User::newFromSession( $request2 );
+               $user2->load();
+               $this->assertNotEquals( $user1->getId(), $user2->getId() );
+               $this->assertNotEquals( $user1->getToken(), $user2->getToken() );
+               $this->assertTrue( $user2->isAnon() );
+               $this->assertFalse( $user2->isLoggedIn() );
+               $this->assertTrue( $user2->isBlocked() );
+               $this->assertEquals( true, $user2->getBlock()->isAutoblocking() ); // Non-strict type-check.
+               // Can't directly compare the objects becuase of member type differences.
+               // One day this will work: $this->assertEquals( $block, $user2->getBlock() );
+               $this->assertEquals( $block->getId(), $user2->getBlock()->getId() );
+               $this->assertEquals( $block->getExpiry(), $user2->getBlock()->getExpiry() );
+
+               // 3. Finally, set up a request as a new user, and the block should still be applied.
+               $user3tmp = $this->getTestUser()->getUser();
+               $request3 = new FauxRequest();
+               $request3->getSession()->setUser( $user3tmp );
+               $request3->setCookie( 'BlockID', $block->getId() );
+               $user3 = User::newFromSession( $request3 );
+               $user3->load();
+               $this->assertTrue( $user3->isLoggedIn() );
+               $this->assertTrue( $user3->isBlocked() );
+               $this->assertEquals( true, $user3->getBlock()->isAutoblocking() ); // Non-strict type-check.
+
+               // Clean up.
+               $block->delete();
+       }
+
+       /**
+        * Make sure that no cookie is set to track autoblocked users
+        * when $wgCookieSetOnAutoblock is false.
+        */
+       public function testAutoblockCookiesDisabled() {
+               // Set up the bits of global configuration that we use.
+               $this->setMwGlobals( [
+                       'wgCookieSetOnAutoblock' => false,
+                       'wgCookiePrefix' => 'wm_no_cookies',
+               ] );
+
+               // 1. Log in a test user, and block them.
+               $testUser = $this->getTestUser()->getUser();
+               $request1 = new FauxRequest();
+               $request1->getSession()->setUser( $testUser );
+               $block = new Block( [ 'enableAutoblock' => true ] );
+               $block->setTarget( $testUser );
+               $block->insert();
+               $user = User::newFromSession( $request1 );
+               $user->mBlock = $block;
+               $user->load();
+
+               // 2. Test that the cookie IS NOT present.
+               $this->assertTrue( $user->isLoggedIn() );
+               $this->assertTrue( $user->isBlocked() );
+               $this->assertEquals( Block::TYPE_USER, $block->getType() );
+               $this->assertTrue( $block->isAutoblocking() );
+               $this->assertGreaterThanOrEqual( 1, $user->getBlockId() );
+               $this->assertGreaterThanOrEqual( $block->getId(), $user->getBlockId() );
+               $cookies = $request1->response()->getCookies();
+               $this->assertArrayNotHasKey( 'wm_no_cookiesBlockID', $cookies );
+
+               // Clean up.
+               $block->delete();
+       }
+
+       /**
+        * When a user is autoblocked and a cookie is set to track them, the expiry time of the cookie
+        * should match the block's expiry. If the block is infinite, the cookie expiry time should
+        * match $wgCookieExpiration. If the expiry time is changed, the cookie's should change with it.
+        */
+       public function testAutoblockCookieInfiniteExpiry() {
+               $cookieExpiration = 20 * 24 * 60 * 60; // 20 days
+               $this->setMwGlobals( [
+                       'wgCookieSetOnAutoblock' => true,
+                       'wgCookieExpiration' => $cookieExpiration,
+                       'wgCookiePrefix' => 'wm_infinite_block',
+               ] );
+               // 1. Log in a test user, and block them indefinitely.
+               $user1Tmp = $this->getTestUser()->getUser();
+               $request1 = new FauxRequest();
+               $request1->getSession()->setUser( $user1Tmp );
+               $block = new Block( [ 'enableAutoblock' => true, 'expiry' => 'infinity' ] );
+               $block->setTarget( $user1Tmp );
+               $block->insert();
+               $user1 = User::newFromSession( $request1 );
+               $user1->mBlock = $block;
+               $user1->load();
+
+               // 2. Test the cookie's expiry timestamp.
+               $this->assertTrue( $user1->isLoggedIn() );
+               $this->assertTrue( $user1->isBlocked() );
+               $this->assertEquals( Block::TYPE_USER, $block->getType() );
+               $this->assertTrue( $block->isAutoblocking() );
+               $this->assertGreaterThanOrEqual( 1, $user1->getBlockId() );
+               $cookies = $request1->response()->getCookies();
+               // Calculate the expected cookie expiry date.
+               $this->assertArrayHasKey( 'wm_infinite_blockBlockID', $cookies );
+               $this->assertEquals( time() + $cookieExpiration, $cookies['wm_infinite_blockBlockID']['expire'] );
+
+               // 3. Change the block's expiry (to 2 days), and the cookie's should be changed also.
+               $newExpiry = time() + 2 * 24 * 60 * 60;
+               $block->mExpiry = wfTimestamp( TS_MW, $newExpiry );
+               $block->update();
+               $user2tmp = $this->getTestUser()->getUser();
+               $request2 = new FauxRequest();
+               $request2->getSession()->setUser( $user2tmp );
+               $user2 = User::newFromSession( $request2 );
+               $user2->mBlock = $block;
+               $user2->load();
+               $cookies = $request2->response()->getCookies();
+               $this->assertEquals( $newExpiry, $cookies['wm_infinite_blockBlockID']['expire'] );
+
+               // Clean up.
+               $block->delete();
+       }
 }
index bd10856..cbf94d6 100644 (file)
@@ -5,6 +5,7 @@
 // without changing the visibility and without working around hacks in
 // Maintenance.php
 // For the same reason, we cannot just use FakeMaintenance.
+use MediaWiki\MediaWikiServices;
 
 /**
  * makes parts of the API of Maintenance that is hidden by protected visibily
@@ -826,7 +827,7 @@ class MaintenanceTest extends MediaWikiTestCase {
        public function testGetConfig() {
                $this->assertInstanceOf( 'Config', $this->m->getConfig() );
                $this->assertSame(
-                       ConfigFactory::getDefaultInstance()->makeConfig( 'main' ),
+                       MediaWikiServices::getInstance()->getMainConfig(),
                        $this->m->getConfig()
                );
        }
index e11fd8a..8ba2aeb 100644 (file)
@@ -25,14 +25,16 @@ use JsonSchema\Validator;
  */
 class ExtensionJsonValidationTest extends PHPUnit_Framework_TestCase {
 
+       /**
+        * @var ExtensionJsonValidator
+        */
+       protected $validator;
+
        public function setUp() {
                parent::setUp();
-               if ( !class_exists( Validator::class ) ) {
-                       $this->markTestSkipped(
-                               'The JsonSchema library cannot be found,' .
-                               ' please install it through composer to run extension.json validation tests.'
-                       );
-               }
+
+               $this->validator = new ExtensionJsonValidator( [ $this, 'markTestSkipped' ] );
+               $this->validator->checkDependencies();
 
                if ( !ExtensionRegistry::getInstance()->getAllThings() ) {
                        $this->markTestSkipped(
@@ -55,56 +57,12 @@ class ExtensionJsonValidationTest extends PHPUnit_Framework_TestCase {
         * @param string $path Path to thing's json file
         */
        public function testPassesValidation( $path ) {
-               $data = json_decode( file_get_contents( $path ) );
-               $this->assertInstanceOf( 'stdClass', $data, "$path is not valid JSON" );
-
-               $this->assertObjectHasAttribute( 'manifest_version', $data,
-                       "$path does not have manifest_version set." );
-               $version = $data->manifest_version;
-               if ( $version !== ExtensionRegistry::MANIFEST_VERSION ) {
-                       $schemaPath = __DIR__ . "/../../../docs/extension.schema.v$version.json";
-               } else {
-                       $schemaPath = __DIR__ . '/../../../docs/extension.schema.json';
-               }
-
-               // Not too old
-               $this->assertTrue(
-                       $version >= ExtensionRegistry::OLDEST_MANIFEST_VERSION,
-                       "$path is using a non-supported schema version"
-               );
-               // Not too new
-               $this->assertTrue(
-                       $version <= ExtensionRegistry::MANIFEST_VERSION,
-                       "$path is using a non-supported schema version"
-               );
-
-               $licenseError = false;
-               if ( class_exists( SpdxLicenses::class ) && isset( $data->{'license-name'} )
-                       // Check if it's a string, if not, schema validation will display an error
-                       && is_string( $data->{'license-name'} )
-               ) {
-                       $licenses = new SpdxLicenses();
-                       $valid = $licenses->validate( $data->{'license-name'} );
-                       if ( !$valid ) {
-                               $licenseError = '[license-name] Invalid SPDX license identifier, '
-                                       . 'see <https://spdx.org/licenses/>';
-                       }
-               }
-
-               $validator = new Validator;
-               $validator->check( $data, (object)[ '$ref' => 'file://' . $schemaPath ] );
-               if ( $validator->isValid() && !$licenseError ) {
-                       // All good.
+               try {
+                       $this->validator->validate( $path );
+                       // All good
                        $this->assertTrue( true );
-               } else {
-                       $out = "$path did pass validation.\n";
-                       foreach ( $validator->getErrors() as $error ) {
-                               $out .= "[{$error['property']}] {$error['message']}\n";
-                       }
-                       if ( $licenseError ) {
-                               $out .= "$licenseError\n";
-                       }
-                       $this->assertTrue( false, $out );
+               } catch ( ExtensionJsonValidationError $e ) {
+                       $this->assertEquals( false, $e->getMessage() );
                }
        }
 }
index 16299aa..11a25c4 100644 (file)
@@ -43,6 +43,9 @@
                <testsuite name="structure">
                        <directory>structure</directory>
                </testsuite>
+               <testsuite name="tests">
+                       <directory>tests</directory>
+               </testsuite>
                <testsuite name="uploadfromurl">
                        <file>suites/UploadFromUrlTestSuite.php</file>
                </testsuite>
index 5d2f37e..edc81ff 100644 (file)
@@ -9,8 +9,6 @@ use Psr\Log\LoggerInterface;
  */
 class MediaWikiTestCaseTest extends MediaWikiTestCase {
 
-       const GLOBAL_KEY_NONEXISTING = 'MediaWikiTestCaseTestGLOBAL-NONExisting';
-
        private static $startGlobals = [
                'MediaWikiTestCaseTestGLOBAL-ExistingString' => 'foo',
                'MediaWikiTestCaseTestGLOBAL-ExistingStringEmpty' => '',
@@ -90,14 +88,22 @@ class MediaWikiTestCaseTest extends MediaWikiTestCase {
 
        /**
         * @covers MediaWikiTestCase::stashMwGlobals
+        * @covers MediaWikiTestCase::tearDown
         */
-       public function testExceptionThrownWhenStashingNonExistentGlobals() {
-               $this->setExpectedException(
-                       'Exception',
-                       'Global with key ' . self::GLOBAL_KEY_NONEXISTING . ' doesn\'t exist and cant be stashed'
+       public function testSetNonExistentGlobalsAreUnsetOnTearDown() {
+               $globalKey = 'abcdefg1234567';
+               $this->setMwGlobals( $globalKey, true );
+               $this->assertTrue(
+                       $GLOBALS[$globalKey],
+                       'Global failed to correctly set'
                );
 
-               $this->stashMwGlobals( self::GLOBAL_KEY_NONEXISTING );
+               $this->tearDown();
+
+               $this->assertFalse(
+                       isset( $GLOBALS[$globalKey] ),
+                       'Global failed to be correctly unset'
+               );
        }
 
        public function testOverrideMwServices() {
@@ -132,10 +138,9 @@ class MediaWikiTestCaseTest extends MediaWikiTestCase {
 
        /**
         * @covers MediaWikiTestCase::setLogger
-        * @covers MediaWikiTestCase::restoreLogger
+        * @covers MediaWikiTestCase::restoreLoggers
         */
-       public function testLoggersAreRestoredOnTearDown() {
-               // replacing an existing logger
+       public function testLoggersAreRestoredOnTearDown_replacingExistingLogger() {
                $logger1 = LoggerFactory::getInstance( 'foo' );
                $this->setLogger( 'foo', $this->getMock( LoggerInterface::class ) );
                $logger2 = LoggerFactory::getInstance( 'foo' );
@@ -144,17 +149,27 @@ class MediaWikiTestCaseTest extends MediaWikiTestCase {
 
                $this->assertSame( $logger1, $logger3 );
                $this->assertNotSame( $logger1, $logger2 );
+       }
 
-               // replacing a non-existing logger
+       /**
+        * @covers MediaWikiTestCase::setLogger
+        * @covers MediaWikiTestCase::restoreLoggers
+        */
+       public function testLoggersAreRestoredOnTearDown_replacingNonExistingLogger() {
                $this->setLogger( 'foo', $this->getMock( LoggerInterface::class ) );
-               $logger1 = LoggerFactory::getInstance( 'bar' );
+               $logger1 = LoggerFactory::getInstance( 'foo' );
                $this->tearDown();
-               $logger2 = LoggerFactory::getInstance( 'bar' );
+               $logger2 = LoggerFactory::getInstance( 'foo' );
 
                $this->assertNotSame( $logger1, $logger2 );
                $this->assertInstanceOf( '\Psr\Log\LoggerInterface', $logger2 );
+       }
 
-               // replacing same logger twice
+       /**
+        * @covers MediaWikiTestCase::setLogger
+        * @covers MediaWikiTestCase::restoreLoggers
+        */
+       public function testLoggersAreRestoredOnTearDown_replacingSameLoggerTwice() {
                $logger1 = LoggerFactory::getInstance( 'baz' );
                $this->setLogger( 'foo', $this->getMock( LoggerInterface::class ) );
                $this->setLogger( 'foo', $this->getMock( LoggerInterface::class ) );
index b79c192..0b28684 100644 (file)
@@ -25,6 +25,9 @@
        // killing the test and assuming timeout failure.
        QUnit.config.testTimeout = 60 * 1000;
 
+       // Reduce default animation duration from 400ms to 0ms for unit tests
+       $.fx.speeds._default = 0;
+
        // Add a checkbox to QUnit header to toggle MediaWiki ResourceLoader debug mode.
        QUnit.config.urlConfig.push( {
                id: 'debug',
index 9afd793..ca6a512 100644 (file)
@@ -1,18 +1,15 @@
 ( function ( $ ) {
-       QUnit.module( 'jquery.color', QUnit.newMwEnvironment( {
-               setup: function () {
-                       this.clock = this.sandbox.useFakeTimers();
-               }
-       } ) );
+       QUnit.module( 'jquery.color', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'animate', 1, function ( assert ) {
-               var $canvas = $( '<div>' ).css( 'background-color', '#fff' );
+       QUnit.test( 'animate', function ( assert ) {
+               var done = assert.async(),
+                       $canvas = $( '<div>' ).css( 'background-color', '#fff' ).appendTo( '#qunit-fixture' );
 
-               $canvas.animate( { backgroundColor: '#000' }, 10 ).promise().then( function () {
-                       var endColors = $.colorUtil.getRGB( $canvas.css( 'background-color' ) );
-                       assert.deepEqual( endColors, [ 0, 0, 0 ], 'end state' );
-               } );
-
-               this.clock.tick( 20 );
+               $canvas.animate( { 'background-color': '#000' }, 3 ).promise()
+                       .done( function () {
+                               var endColors = $.colorUtil.getRGB( $canvas.css( 'background-color' ) );
+                               assert.deepEqual( endColors, [ 0, 0, 0 ], 'end state' );
+                       } )
+                       .always( done );
        } );
 }( jQuery ) );
index c51e409..9c7660f 100644 (file)
@@ -1,11 +1,7 @@
 ( function ( mw, $ ) {
        var loremIpsum = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.';
 
-       QUnit.module( 'jquery.makeCollapsible', QUnit.newMwEnvironment( {
-               setup: function () {
-                       this.clock = this.sandbox.useFakeTimers();
-               }
-       } ) );
+       QUnit.module( 'jquery.makeCollapsible', QUnit.newMwEnvironment() );
 
        function prepareCollapsible( html, options ) {
                return $( $.parseHTML( html ) )
 
                        // ...expanding happens here
                        $toggle.trigger( 'click' );
-                       test.clock.tick( 500 );
                } );
 
                // ...collapsing happens here
                $toggle.trigger( 'click' );
-               test.clock.tick( 500 );
        } );
 
        QUnit.test( 'basic operation (<div>)', 5, function ( assert ) {
                        } );
 
                        $toggle.trigger( 'click' );
-                       test.clock.tick( 500 );
                } );
 
                $toggle.trigger( 'click' );
-               test.clock.tick( 500 );
        } );
 
        QUnit.test( 'basic operation (<table>)', 7, function ( assert ) {
                        } );
 
                        $toggle.trigger( 'click' );
-                       test.clock.tick( 500 );
                } );
 
                $toggle.trigger( 'click' );
-               test.clock.tick( 500 );
        } );
 
        function tableWithCaptionTest( $collapsible, test, assert ) {
                        } );
 
                        $toggle.trigger( 'click' );
-                       test.clock.tick( 500 );
                } );
 
                $toggle.trigger( 'click' );
-               test.clock.tick( 500 );
        }
 
        QUnit.test( 'basic operation (<table> with caption)', 10, function ( assert ) {
                        } );
 
                        $toggle.trigger( 'click' );
-                       test.clock.tick( 500 );
                } );
 
                $toggle.trigger( 'click' );
-               test.clock.tick( 500 );
        }
 
        QUnit.test( 'basic operation (<ul>)', 7, function ( assert ) {
                } );
 
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
-               this.clock.tick( 500 );
        } );
 
        QUnit.test( 'initial collapse (options.collapsed)', 2, function ( assert ) {
                } );
 
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
-               this.clock.tick( 500 );
        } );
 
        QUnit.test( 'clicks on links inside toggler pass through (options.linksPassthru)', 2, function ( assert ) {
                } );
 
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
-               this.clock.tick( 500 );
        } );
 
        QUnit.test( 'collapse/expand text (options.collapseText, options.expandText)', 2, function ( assert ) {
                } );
 
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
-               this.clock.tick( 500 );
        } );
 
        QUnit.test( 'cloned collapsibles can be made collapsible again', 2, function ( assert ) {
                } );
 
                $clone.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
-               test.clock.tick( 500 );
        } );
 }( mediaWiki, jQuery ) );
index 9d0fdf5..1676130 100644 (file)
@@ -3,16 +3,10 @@
                setup: function () {
                        this.server = this.sandbox.useFakeServer();
                        this.server.respondImmediately = true;
-                       this.clock = this.sandbox.useFakeTimers();
-               },
-               teardown: function () {
-                       // https://github.com/jquery/jquery/issues/2453
-                       this.clock.tick();
                }
        } ) );
 
-       QUnit.test( 'origin is included in GET requests', function ( assert ) {
-               QUnit.expect( 1 );
+       QUnit.test( 'origin is included in GET requests', 1, function ( assert ) {
                var api = new mw.ForeignApi( '//localhost:4242/w/api.php' );
 
                this.server.respond( function ( request ) {
                        request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
                } );
 
-               api.get( {} );
+               return api.get( {} );
        } );
 
-       QUnit.test( 'origin is included in POST requests', function ( assert ) {
-               QUnit.expect( 2 );
+       QUnit.test( 'origin is included in POST requests', 2, function ( assert ) {
                var api = new mw.ForeignApi( '//localhost:4242/w/api.php' );
 
                this.server.respond( function ( request ) {
@@ -33,7 +26,7 @@
                        request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
                } );
 
-               api.post( {} );
+               return api.post( {} );
        } );
 
 }( mediaWiki ) );
index a0c7daf..a79bff6 100644 (file)
@@ -2,29 +2,24 @@
        QUnit.module( 'mediawiki.api.category', QUnit.newMwEnvironment( {
                setup: function () {
                        this.server = this.sandbox.useFakeServer();
+                       this.server.respondImmediately = true;
                }
        } ) );
 
-       QUnit.test( '.getCategoriesByPrefix()', function ( assert ) {
-               QUnit.expect( 1 );
+       QUnit.test( '.getCategoriesByPrefix()', 1, function ( assert ) {
+               this.server.respondWith( [ 200, { 'Content-Type': 'application/json' },
+                       '{ "query": { "allpages": [ ' +
+                               '{ "title": "Category:Food" },' +
+                               '{ "title": "Category:Fool Supermarine S.6" },' +
+                               '{ "title": "Category:Fools" }' +
+                               '] } }'
+               ] );
 
-               var api = new mw.Api();
-
-               api.getCategoriesByPrefix( 'Foo' ).done( function ( matches ) {
+               return new mw.Api().getCategoriesByPrefix( 'Foo' ).then( function ( matches ) {
                        assert.deepEqual(
                                matches,
                                [ 'Food', 'Fool Supermarine S.6', 'Fools' ]
                        );
                } );
-
-               this.server.respond( function ( req ) {
-                       req.respond( 200, { 'Content-Type': 'application/json' },
-                               '{ "query": { "allpages": [ ' +
-                                       '{ "title": "Category:Food" },' +
-                                       '{ "title": "Category:Fool Supermarine S.6" },' +
-                                       '{ "title": "Category:Fools" }' +
-                                       '] } }'
-                       );
-               } );
        } );
 }( mediaWiki ) );
index 5880962..d8b5db8 100644 (file)
@@ -2,14 +2,21 @@
        QUnit.module( 'mediawiki.api.messages', QUnit.newMwEnvironment( {
                setup: function () {
                        this.server = this.sandbox.useFakeServer();
+                       this.server.respondImmediately = true;
                }
        } ) );
 
-       QUnit.test( '.getMessages()', function ( assert ) {
-               QUnit.expect( 1 );
+       QUnit.test( '.getMessages()', 1, function ( assert ) {
+               this.server.respondWith( /ammessages=foo%7Cbaz/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{ "query": { "allmessages": [' +
+                               '{ "name": "foo", "content": "Foo bar" },' +
+                               '{ "name": "baz", "content": "Baz Quux" }' +
+                               '] } }'
+               ] );
 
-               var api = new mw.Api();
-               api.getMessages( [ 'foo', 'baz' ] ).then( function ( messages ) {
+               return new mw.Api().getMessages( [ 'foo', 'baz' ] ).then( function ( messages ) {
                        assert.deepEqual(
                                messages,
                                {
                                }
                        );
                } );
-
-               this.server.respond( /ammessages=foo%7Cbaz/, [
-                       200,
-                       { 'Content-Type': 'application/json' },
-                       '{ "query": { "allmessages": [' +
-                               '{ "name": "foo", "content": "Foo bar" },' +
-                               '{ "name": "baz", "content": "Baz Quux" }' +
-                               '] } }'
-               ] );
        } );
 }( mediaWiki ) );
index 0797f32..7ed1875 100644 (file)
@@ -2,14 +2,12 @@
        QUnit.module( 'mediawiki.api.options', QUnit.newMwEnvironment( {
                setup: function () {
                        this.server = this.sandbox.useFakeServer();
+                       this.server.respondImmediately = true;
                }
        } ) );
 
-       QUnit.test( 'saveOption', function ( assert ) {
-               QUnit.expect( 2 );
-
-               var
-                       api = new mw.Api(),
+       QUnit.test( 'saveOption', 2, function ( assert ) {
+               var api = new mw.Api(),
                        stub = this.sandbox.stub( mw.Api.prototype, 'saveOptions' );
 
                api.saveOption( 'foo', 'bar' );
@@ -18,9 +16,7 @@
                assert.deepEqual( stub.getCall( 0 ).args, [ { foo: 'bar' } ], '#saveOptions called correctly' );
        } );
 
-       QUnit.test( 'saveOptions without Unit Separator', function ( assert ) {
-               QUnit.expect( 13 );
-
+       QUnit.test( 'saveOptions without Unit Separator', 13, function ( assert ) {
                var api = new mw.Api( { useUS: false } );
 
                // We need to respond to the request for token first, otherwise the other requests won't be sent
                                '{ "query": { "tokens": { "csrftoken": "+\\\\" } } }' ]
                );
 
-               api.saveOptions( {} ).done( function () {
-                       assert.ok( true, 'Request completed: empty case' );
-               } );
-               api.saveOptions( { foo: 'bar' } ).done( function () {
-                       assert.ok( true, 'Request completed: simple' );
-               } );
-               api.saveOptions( { foo: 'bar', baz: 'quux' } ).done( function () {
-                       assert.ok( true, 'Request completed: two options' );
-               } );
-               api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', baz: 'quux' } ).done( function () {
-                       assert.ok( true, 'Request completed: not bundleable' );
-               } );
-               api.saveOptions( { foo: null } ).done( function () {
-                       assert.ok( true, 'Request completed: reset an option' );
-               } );
-               api.saveOptions( { 'foo|bar=quux': null } ).done( function () {
-                       assert.ok( true, 'Request completed: reset an option, not bundleable' );
-               } );
-
                // Requests are POST, match requestBody instead of url
                this.server.respond( function ( request ) {
                        switch ( request.requestBody ) {
                                        assert.ok( false, 'Unexpected request: ' + request.requestBody );
                        }
                } );
-       } );
 
-       QUnit.test( 'saveOptions with Unit Separator', function ( assert ) {
-               QUnit.expect( 14 );
+               return QUnit.whenPromisesComplete(
+                       api.saveOptions( {} ).then( function () {
+                               assert.ok( true, 'Request completed: empty case' );
+                       } ),
+                       api.saveOptions( { foo: 'bar' } ).then( function () {
+                               assert.ok( true, 'Request completed: simple' );
+                       } ),
+                       api.saveOptions( { foo: 'bar', baz: 'quux' } ).then( function () {
+                               assert.ok( true, 'Request completed: two options' );
+                       } ),
+                       api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', baz: 'quux' } ).then( function () {
+                               assert.ok( true, 'Request completed: not bundleable' );
+                       } ),
+                       api.saveOptions( { foo: null } ).then( function () {
+                               assert.ok( true, 'Request completed: reset an option' );
+                       } ),
+                       api.saveOptions( { 'foo|bar=quux': null } ).then( function () {
+                               assert.ok( true, 'Request completed: reset an option, not bundleable' );
+                       } )
+               );
+       } );
 
+       QUnit.test( 'saveOptions with Unit Separator', 14, function ( assert ) {
                var api = new mw.Api( { useUS: true } );
 
                // We need to respond to the request for token first, otherwise the other requests won't be sent
                                '{ "query": { "tokens": { "csrftoken": "+\\\\" } } }' ]
                );
 
-               api.saveOptions( {} ).done( function () {
-                       assert.ok( true, 'Request completed: empty case' );
-               } );
-               api.saveOptions( { foo: 'bar' } ).done( function () {
-                       assert.ok( true, 'Request completed: simple' );
-               } );
-               api.saveOptions( { foo: 'bar', baz: 'quux' } ).done( function () {
-                       assert.ok( true, 'Request completed: two options' );
-               } );
-               api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', baz: 'quux' } ).done( function () {
-                       assert.ok( true, 'Request completed: bundleable with unit separator' );
-               } );
-               api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', 'baz=baz': 'quux' } ).done( function () {
-                       assert.ok( true, 'Request completed: not bundleable with unit separator' );
-               } );
-               api.saveOptions( { foo: null } ).done( function () {
-                       assert.ok( true, 'Request completed: reset an option' );
-               } );
-               api.saveOptions( { 'foo|bar=quux': null } ).done( function () {
-                       assert.ok( true, 'Request completed: reset an option, not bundleable' );
-               } );
-
                // Requests are POST, match requestBody instead of url
                this.server.respond( function ( request ) {
                        switch ( request.requestBody ) {
                                        assert.ok( false, 'Unexpected request: ' + request.requestBody );
                        }
                } );
+
+               return QUnit.whenPromisesComplete(
+                       api.saveOptions( {} ).done( function () {
+                               assert.ok( true, 'Request completed: empty case' );
+                       } ),
+                       api.saveOptions( { foo: 'bar' } ).done( function () {
+                               assert.ok( true, 'Request completed: simple' );
+                       } ),
+                       api.saveOptions( { foo: 'bar', baz: 'quux' } ).done( function () {
+                               assert.ok( true, 'Request completed: two options' );
+                       } ),
+                       api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', baz: 'quux' } ).done( function () {
+                               assert.ok( true, 'Request completed: bundleable with unit separator' );
+                       } ),
+                       api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', 'baz=baz': 'quux' } ).done( function () {
+                               assert.ok( true, 'Request completed: not bundleable with unit separator' );
+                       } ),
+                       api.saveOptions( { foo: null } ).done( function () {
+                               assert.ok( true, 'Request completed: reset an option' );
+                       } ),
+                       api.saveOptions( { 'foo|bar=quux': null } ).done( function () {
+                               assert.ok( true, 'Request completed: reset an option, not bundleable' );
+                       } )
+               );
        } );
 }( mediaWiki ) );
index dc0cff4..7d27352 100644 (file)
@@ -2,42 +2,44 @@
        QUnit.module( 'mediawiki.api.parse', QUnit.newMwEnvironment( {
                setup: function () {
                        this.server = this.sandbox.useFakeServer();
+                       this.server.respondImmediately = true;
                }
        } ) );
 
-       QUnit.test( 'Hello world', function ( assert ) {
-               QUnit.expect( 3 );
+       QUnit.test( '.parse( string )', function ( assert ) {
+               this.server.respondWith( /action=parse.*&text='''Hello(\+|%20)world'''/, [ 200,
+                       { 'Content-Type': 'application/json' },
+                       '{ "parse": { "text": "<p><b>Hello world</b></p>" } }'
+               ] );
 
-               var api = new mw.Api();
-
-               api.parse( '\'\'\'Hello world\'\'\'' ).done( function ( html ) {
+               return new mw.Api().parse( '\'\'\'Hello world\'\'\'' ).done( function ( html ) {
                        assert.equal( html, '<p><b>Hello world</b></p>', 'Parse wikitext by string' );
                } );
+       } );
 
-               api.parse( {
+       QUnit.test( '.parse( Object.toString )', function ( assert ) {
+               this.server.respondWith( /action=parse.*&text='''Hello(\+|%20)world'''/, [ 200,
+                       { 'Content-Type': 'application/json' },
+                       '{ "parse": { "text": "<p><b>Hello world</b></p>" } }'
+               ] );
+
+               return new mw.Api().parse( {
                        toString: function () {
                                return '\'\'\'Hello world\'\'\'';
                        }
                } ).done( function ( html ) {
                        assert.equal( html, '<p><b>Hello world</b></p>', 'Parse wikitext by toString object' );
                } );
+       } );
 
-               this.server.respondWith( /action=parse.*&text='''Hello\+world'''/, function ( request ) {
-                       request.respond( 200, { 'Content-Type': 'application/json' },
-                               '{ "parse": { "text": "<p><b>Hello world</b></p>" } }'
-                       );
-               } );
+       QUnit.test( '.parse( mw.Title )', function ( assert ) {
+               this.server.respondWith( /action=parse.*&page=Earth/, [ 200,
+                       { 'Content-Type': 'application/json' },
+                       '{ "parse": { "text": "<p><b>Earth</b> is a planet.</p>" } }'
+               ] );
 
-               api.parse( new mw.Title( 'Earth' ) ).done( function ( html ) {
+               return new mw.Api().parse( new mw.Title( 'Earth' ) ).done( function ( html ) {
                        assert.equal( html, '<p><b>Earth</b> is a planet.</p>', 'Parse page by Title object'  );
                } );
-
-               this.server.respondWith( /action=parse.*&page=Earth/, function ( request ) {
-                       request.respond( 200, { 'Content-Type': 'application/json' },
-                               '{ "parse": { "text": "<p><b>Earth</b> is a planet.</p>" } }'
-                       );
-               } );
-
-               this.server.respond();
        } );
 }( mediaWiki ) );
index 10fcd5d..b1bd12b 100644 (file)
@@ -1,8 +1,7 @@
 ( function ( mw, $ ) {
        QUnit.module( 'mediawiki.api.upload', QUnit.newMwEnvironment( {} ) );
 
-       QUnit.test( 'Basic functionality', function ( assert ) {
-               QUnit.expect( 2 );
+       QUnit.test( 'Basic functionality', 2, function ( assert ) {
                var api = new mw.Api();
                assert.ok( api.upload );
                assert.throws( function () {
@@ -10,8 +9,7 @@
                } );
        } );
 
-       QUnit.test( 'Set up iframe upload', function ( assert ) {
-               QUnit.expect( 5 );
+       QUnit.test( 'Set up iframe upload', 5, function ( assert ) {
                var $iframe, $form, $input,
                        api = new mw.Api();
 
index 64a5184..8641469 100644 (file)
@@ -2,37 +2,45 @@
        QUnit.module( 'mediawiki.api.watch', QUnit.newMwEnvironment( {
                setup: function () {
                        this.server = this.sandbox.useFakeServer();
+                       this.server.respondImmediately = true;
                }
        } ) );
 
-       QUnit.test( '.watch()', function ( assert ) {
-               QUnit.expect( 4 );
-
-               var api = new mw.Api();
-
-               // Ensure we don't mistake a single item array for a single item and vice versa.
-               // The query parameter in request is the same either way (separated by pipe).
-               api.watch( 'Foo' ).done( function ( item ) {
-                       assert.equal( item.title, 'Foo' );
-               } );
-
-               api.watch( [ 'Foo' ] ).done( function ( items ) {
-                       assert.equal( items[ 0 ].title, 'Foo' );
+       QUnit.test( '.watch( string )', function ( assert ) {
+               this.server.respond( function ( req ) {
+                       // Match POST requestBody
+                       if ( /action=watch.*&titles=Foo(&|$)/.test( req.requestBody ) ) {
+                               req.respond( 200, { 'Content-Type': 'application/json' },
+                                       '{ "watch": [ { "title": "Foo", "watched": true, "message": "<b>Added</b>" } ] }'
+                               );
+                       }
                } );
 
-               api.watch( [ 'Foo', 'Bar' ] ).done( function ( items ) {
-                       assert.equal( items[ 0 ].title, 'Foo' );
-                       assert.equal( items[ 1 ].title, 'Bar' );
+               return new mw.Api().watch( 'Foo' ).done( function ( item ) {
+                       assert.equal( item.title, 'Foo' );
                } );
+       } );
 
-               // Requests are POST, match requestBody instead of url
+       // Ensure we don't mistake a single item array for a single item and vice versa.
+       // The query parameter in request is the same either way (separated by pipe).
+       QUnit.test( '.watch( Array ) - single', function ( assert ) {
                this.server.respond( function ( req ) {
+                       // Match POST requestBody
                        if ( /action=watch.*&titles=Foo(&|$)/.test( req.requestBody ) ) {
                                req.respond( 200, { 'Content-Type': 'application/json' },
                                        '{ "watch": [ { "title": "Foo", "watched": true, "message": "<b>Added</b>" } ] }'
                                );
                        }
+               } );
+
+               return new mw.Api().watch( [ 'Foo' ] ).done( function ( items ) {
+                       assert.equal( items[ 0 ].title, 'Foo' );
+               } );
+       } );
 
+       QUnit.test( '.watch( Array ) - multi', function ( assert ) {
+               this.server.respond( function ( req ) {
+                       // Match POST requestBody
                        if ( /action=watch.*&titles=Foo%7CBar/.test( req.requestBody ) ) {
                                req.respond( 200, { 'Content-Type': 'application/json' },
                                        '{ "watch": [ ' +
                                );
                        }
                } );
+
+               return new mw.Api().watch( [ 'Foo', 'Bar' ] ).done( function ( items ) {
+                       assert.equal( items[ 0 ].title, 'Foo' );
+                       assert.equal( items[ 1 ].title, 'Bar' );
+               } );
        } );
+
 }( mediaWiki ) );
index 886e2b6..124c49f 100644 (file)
@@ -1,4 +1,3 @@
-/*jshint -W024 */
 ( function ( mw, $ ) {
        var repeat = function ( input, multiplier ) {
                return new Array( multiplier + 1 ).join( input );
                }, 'Throw error on empty string' );
        } );
 
-       QUnit.test( 'Case-sensivity', 3, function ( assert ) {
+       QUnit.test( 'Case-sensivity', 5, function ( assert ) {
                var title;
 
                // Default config
                title = new mw.Title( 'article' );
                assert.equal( title.toString(), 'Article', 'Default config: No sensitive namespaces by default. First-letter becomes uppercase' );
 
+               title = new mw.Title( 'ß' );
+               assert.equal( title.toString(), 'ß', 'Uppercasing matches PHP behaviour (ß -> ß, not SS)' );
+
+               title = new mw.Title( 'dž (digraph)' );
+               assert.equal( title.toString(), 'Dž_(digraph)', 'Uppercasing matches PHP behaviour (dž -> Dž, not DŽ)' );
+
                // $wgCapitalLinks = false;
                mw.config.set( 'wgCaseSensitiveNamespaces', [ 0, -2, 1, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15 ] );
 
index b12803d..97185fc 100644 (file)
@@ -1,4 +1,3 @@
-/*jshint -W024 */
 ( function ( mw, $ ) {
        QUnit.module( 'mediawiki.Uri', QUnit.newMwEnvironment( {
                setup: function () {
index caaef83..f848f3e 100644 (file)
        QUnit.test( 'Match PHP parser', mw.libs.phpParserData.tests.length, function ( assert ) {
                mw.messages.set( mw.libs.phpParserData.messages );
                var tasks = $.map( mw.libs.phpParserData.tests, function ( test ) {
+                       var done = assert.async();
                        return function ( next, abort ) {
-                               var done = assert.async();
                                getMwLanguage( test.lang )
                                        .then( function ( langClass ) {
                                                mw.config.set( 'wgUserLanguage', test.lang );
 
                assert.equal(
                        formatParse( 'uses-missing-int' ),
-                       '[doesnt-exist]',
+                       '⧼doesnt-exist⧽',
                        'int: where nested message does not exist'
                );
        } );
                },
                {
                        lang: 'hi',
-                       number: '१२३४५६,७८९',
+                       number: '१,२३,४५६',
                        result: '123456',
                        integer: true,
                        description: 'formatnum test for Hindi, Devanagari digits passed to get integer value'
                mw.messages.set( 'formatnum-msg', '{{formatnum:$1}}' );
                mw.messages.set( 'formatnum-msg-int', '{{formatnum:$1|R}}' );
                var queue = $.map( formatnumTests, function ( test ) {
+                       var done = assert.async();
                        return function ( next, abort ) {
-                               var done = assert.async();
                                getMwLanguage( test.lang )
                                        .then( function ( langClass ) {
                                                mw.config.set( 'wgUserLanguage', test.lang );
index e4c3851..b2fac3c 100644 (file)
                assert.equal( mw.language.commafy( 123456789.567, '###,###,#0.00' ), '1,234,567,89.56', 'Decimal part as group of 3 and last one 2' );
        } );
 
+       QUnit.test( 'mw.language.convertNumber', 2, function ( assert ) {
+               mw.language.setData( 'en', 'digitGroupingPattern', null );
+               mw.language.setData( 'en', 'digitTransformTable', null );
+               mw.language.setData( 'en', 'separatorTransformTable', { ',': '.', '.': ',' } );
+               mw.config.set( 'wgUserLanguage', 'en' );
+
+               assert.equal( mw.language.convertNumber( 1800 ), '1.800', 'formatting' );
+               assert.equal( mw.language.convertNumber( '1.800', true ), '1800', 'unformatting' );
+       } );
+
        function grammarTest( langCode, test ) {
                // The test works only if the content language is opt.language
                // because it requires [lang].js to be loaded.
index 7233a2e..92ee7dd 100644 (file)
                .done( function () {
                        assert.strictEqual( isAwesomeDone, true, 'test.promise module should\'ve caused isAwesomeDone to be true' );
                        delete mw.loader.testCallback;
-
                } )
                .fail( function () {
                        assert.ok( false, 'Error callback fired while loader.using "test.promise" module' );
                } );
        } );
 
+       QUnit.test( '.using() Error: Circular dependency', function ( assert ) {
+               var done = assert.async();
+
+               mw.loader.register( [
+                       [ 'test.circle1', '0', [ 'test.circle2' ] ],
+                       [ 'test.circle2', '0', [ 'test.circle3' ] ],
+                       [ 'test.circle3', '0', [ 'test.circle1' ] ]
+               ] );
+               mw.loader.using( 'test.circle3' ).then(
+                       function done() {
+                               assert.ok( false, 'Unexpected resolution, expected error.' );
+                       },
+                       function fail( e ) {
+                               assert.ok( /Circular/.test( String( e ) ), 'Detect circular dependency' );
+                       }
+               )
+               .always( done );
+       } );
+
+       QUnit.test( '.load() - Error: Circular dependency', function ( assert ) {
+               mw.loader.register( [
+                       [ 'test.circleA', '0', [ 'test.circleB' ] ],
+                       [ 'test.circleB', '0', [ 'test.circleC' ] ],
+                       [ 'test.circleC', '0', [ 'test.circleA' ] ]
+               ] );
+               assert.throws( function () {
+                       mw.loader.load( 'test.circleC' );
+               }, /Circular/, 'Detect circular dependency' );
+       } );
+
+       QUnit.test( '.using() - Error: Unregistered', function ( assert ) {
+               var done = assert.async();
+
+               mw.loader.using( 'test.using.unreg' ).then(
+                       function done() {
+                               assert.ok( false, 'Unexpected resolution, expected error.' );
+                       },
+                       function fail( e ) {
+                               assert.ok( /Unknown/.test( String( e ) ), 'Detect unknown dependency' );
+                       }
+               ).always( done );
+       } );
+
+       QUnit.test( '.load() - Error: Unregistered (ignored)', 0, function ( assert ) {
+               mw.loader.load( 'test.using.unreg2' );
+       } );
+
        QUnit.test( '.implement( styles={ "css": [text, ..] } )', 2, function ( assert ) {
                var $element = $( '<div class="mw-test-implement-a"></div>' ).appendTo( '#qunit-fixture' );
 
                assert.strictEqual( mw.track.callCount, 1 );
        } );
 
-       QUnit.test( 'Circular dependency', 1, function ( assert ) {
-               mw.loader.register( [
-                       [ 'test.circle1', '0', [ 'test.circle2' ] ],
-                       [ 'test.circle2', '0', [ 'test.circle3' ] ],
-                       [ 'test.circle3', '0', [ 'test.circle1' ] ]
-               ] );
-               assert.throws( function () {
-                       mw.loader.using( 'test.circle3' );
-               }, /Circular/, 'Detect circular dependency' );
-       } );
-
        QUnit.test( 'Out-of-order implementation', 9, function ( assert ) {
                mw.loader.register( [
                        [ 'test.module4', '0' ],
                mw.loader.load( target );
        } );
 
+       QUnit.test( 'Empty string module name - T28804', function ( assert ) {
+               var done = false;
+
+               assert.strictEqual( mw.loader.getState( '' ), null, 'State (unregistered)' );
+
+               mw.loader.register( '', 'v1' );
+               assert.strictEqual( mw.loader.getState( '' ), 'registered', 'State (registered)' );
+               assert.strictEqual( mw.loader.getVersion( '' ), 'v1', 'Version' );
+
+               mw.loader.implement( '', function () {
+                       done = true;
+               } );
+
+               return mw.loader.using( '', function () {
+                       assert.strictEqual( done, true, 'script ran' );
+                       assert.strictEqual( mw.loader.getState( '' ), 'ready', 'State (ready)' );
+               } );
+       } );
+
        QUnit.test( 'Executing race - T112232', 2, function ( assert ) {
                var done = false;
 
index 6cef4a7..436cb2e 100644 (file)
@@ -1,36 +1,56 @@
 ( function ( mw ) {
        QUnit.module( 'mediawiki.storage' );
 
-       QUnit.test( 'set/get with localStorage', 3, function ( assert ) {
-               this.sandbox.stub( mw.storage, 'localStorage', {
+       QUnit.test( 'set/get with storage support', function ( assert ) {
+               var stub = {
                        setItem: this.sandbox.spy(),
                        getItem: this.sandbox.stub()
-               } );
+               };
+               stub.getItem.withArgs( 'foo' ).returns( 'test' );
+               stub.getItem.returns( null );
+               this.sandbox.stub( mw.storage, 'store', stub );
 
                mw.storage.set( 'foo', 'test' );
-               assert.ok( mw.storage.localStorage.setItem.calledOnce );
+               assert.ok( stub.setItem.calledOnce );
 
-               mw.storage.localStorage.getItem.withArgs( 'foo' ).returns( 'test' );
-               mw.storage.localStorage.getItem.returns( null );
                assert.strictEqual( mw.storage.get( 'foo' ), 'test', 'Check value gets stored.' );
                assert.strictEqual( mw.storage.get( 'bar' ), null, 'Unset values are null.' );
        } );
 
-       QUnit.test( 'set/get without localStorage', 3, function ( assert ) {
-               this.sandbox.stub( mw.storage, 'localStorage', {
+       QUnit.test( 'set/get with storage methods disabled', function ( assert ) {
+               // This covers browsers where storage is disabled
+               // (quota full, or security/privacy settings).
+               // On most browsers, these interface will be accessible with
+               // their methods throwing.
+               var stub = {
                        getItem: this.sandbox.stub(),
                        removeItem: this.sandbox.stub(),
                        setItem: this.sandbox.stub()
-               } );
+               };
+               stub.getItem.throws();
+               stub.setItem.throws();
+               stub.removeItem.throws();
+               this.sandbox.stub( mw.storage, 'store', stub );
 
-               mw.storage.localStorage.getItem.throws();
                assert.strictEqual( mw.storage.get( 'foo' ), false );
-
-               mw.storage.localStorage.setItem.throws();
                assert.strictEqual( mw.storage.set( 'foo', 'test' ), false );
+               assert.strictEqual( mw.storage.remove( 'foo', 'test' ), false );
+       } );
+
+       QUnit.test( 'set/get with storage object disabled', function ( assert ) {
+               // On other browsers, these entire object is disabled.
+               // `'localStorage' in window` would be true (and pass feature test)
+               // but trying to read the object as window.localStorage would throw
+               // an exception. Such case would instantiate SafeStorage with
+               // undefined after the internal try/catch.
+               var old = mw.storage.store;
+               mw.storage.store = undefined;
 
-               mw.storage.localStorage.removeItem.throws();
+               assert.strictEqual( mw.storage.get( 'foo' ), false );
+               assert.strictEqual( mw.storage.set( 'foo', 'test' ), false );
                assert.strictEqual( mw.storage.remove( 'foo', 'test' ), false );
+
+               mw.storage.store = old;
        } );
 
 }( mediaWiki ) );
index 1518a80..bac8274 100644 (file)
@@ -1,4 +1,3 @@
-/*jshint -W024 */
 ( function ( mw ) {
        var specialCharactersPageName,
                // Can't mock SITENAME since jqueryMsg caches it at load
                goodbye = mw.message( 'goodbye' );
                assert.strictEqual( goodbye.exists(), false, 'Message.exists returns false for nonexistent messages' );
 
-               assertMultipleFormats( [ 'goodbye' ], [ 'plain', 'text' ], '<goodbye>', 'Message.toString returns <key> if key does not exist' );
-               // bug 30684
-               assertMultipleFormats( [ 'goodbye' ], [ 'parse', 'escaped' ], '&lt;goodbye&gt;', 'Message.toString returns properly escaped &lt;key&gt; if key does not exist' );
+               assertMultipleFormats( [ 'good<>bye' ], [ 'plain', 'text', 'parse', 'escaped' ], '⧼good&lt;&gt;bye⧽', 'Message.toString returns ⧼key⧽ if key does not exist' );
 
                assert.ok( mw.messages.set( 'plural-test-msg', 'There {{PLURAL:$1|is|are}} $1 {{PLURAL:$1|result|results}}' ), 'mw.messages.set: Register' );
                assertMultipleFormats( [ 'plural-test-msg', 6 ], [ 'text', 'parse', 'escaped' ], 'There are 6 results', 'plural get resolved' );
        QUnit.test( 'mw.msg', 14, function ( assert ) {
                assert.ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
                assert.equal( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'Gets message with default options (existing message)' );
-               assert.equal( mw.msg( 'goodbye' ), '<goodbye>', 'Gets message with default options (nonexistent message)' );
+               assert.equal( mw.msg( 'goodbye' ), '⧼goodbye⧽', 'Gets message with default options (nonexistent message)' );
 
                assert.ok( mw.messages.set( 'plural-item', 'Found $1 {{PLURAL:$1|item|items}}' ), 'mw.messages.set: Register' );
                assert.equal( mw.msg( 'plural-item', 5 ), 'Found 5 items', 'Apply plural for count 5' );
index fca25c5..c38b89c 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -341,6 +341,7 @@ function wfStreamThumb( array $params ) {
        // Check for thumbnail generation errors...
        $msg = wfMessage( 'thumbnail_error' );
        $errorCode = 500;
+
        if ( !$thumb ) {
                $errorMsg = $errorMsg ?: $msg->rawParams( 'File::transform() returned false' )->escaped();
                if ( $errorMsg instanceof MessageSpecifier &&
@@ -350,6 +351,7 @@ function wfStreamThumb( array $params ) {
                }
        } elseif ( $thumb->isError() ) {
                $errorMsg = $thumb->getHtmlMsg();
+               $errorCode = $thumb->getHttpStatusCode();
        } elseif ( !$thumb->hasFile() ) {
                $errorMsg = $msg->rawParams( 'No path supplied in thumbnail object' )->escaped();
        } elseif ( $thumb->fileIsSource() ) {