From: jenkins-bot Date: Fri, 18 May 2018 15:32:34 +0000 (+0000) Subject: Merge "Strip Unicode 6.3.0 directional formatting characters from title" X-Git-Tag: 1.34.0-rc.0~5394 X-Git-Url: http://git.cyclocoop.org/?a=commitdiff_plain;h=b5b6b477790a05823a81d5fbbf5e48af420cfbc7;hp=7564624d1ca80a4d2f1cc2b4d3d32d5d2e0bca38;p=lhc%2Fweb%2Fwiklou.git Merge "Strip Unicode 6.3.0 directional formatting characters from title" --- diff --git a/README b/README deleted file mode 100644 index ad9b9d9d83..0000000000 --- a/README +++ /dev/null @@ -1,33 +0,0 @@ -== MediaWiki == - -MediaWiki is a free and open-source wiki software package written in PHP. It -serves as the platform for Wikipedia and the other Wikimedia projects, used -by hundreds of millions of people each month. MediaWiki is localised in over -350 languages and its reliability and robust feature set have earned it a large -and vibrant community of third-party users and developers. - -MediaWiki is: - -* feature-rich and extensible, both on-wiki and with hundreds of extensions; -* scalable and suitable for both small and large sites; -* simple to install, working on most hardware/software combinations; and -* available in your language. - -For system requirements, installation, and upgrade details, see the files -RELEASE-NOTES, INSTALL, and UPGRADE. - -* Ready to get started? -** https://www.mediawiki.org/wiki/Special:MyLanguage/Download -* Looking for the technical manual? -** https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents -* Seeking help from a person? -** https://www.mediawiki.org/wiki/Special:MyLanguage/Communication -* Looking to file a bug report or a feature request? -** https://bugs.mediawiki.org/ -* Interested in helping out? -** https://www.mediawiki.org/wiki/Special:MyLanguage/How_to_contribute - -MediaWiki is the result of global collaboration and cooperation. The CREDITS -file lists technical contributors to the project. The COPYING file explains -MediaWiki's copyright and license (GNU General Public License, version 2 or -later). Many thanks to the Wikimedia community for testing and suggestions. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..ca703dbc0f --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +MediaWiki +=========== + +MediaWiki is a free and open-source wiki software package written in PHP. It +serves as the platform for Wikipedia and the other Wikimedia projects, used +by hundreds of millions of people each month. MediaWiki is localised in over +350 languages and its reliability and robust feature set have earned it a large +and vibrant community of third-party users and developers. + +MediaWiki is: + +* feature-rich and extensible, both on-wiki and with hundreds of extensions; +* scalable and suitable for both small and large sites; +* simple to install, working on most hardware/software combinations; and +* available in your language. + +For system requirements, installation, and upgrade details, see the files +RELEASE-NOTES, INSTALL, and UPGRADE. + +* Ready to get started? +** https://www.mediawiki.org/wiki/Special:MyLanguage/Download +* Looking for the technical manual? +** https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents +* Seeking help from a person? +** https://www.mediawiki.org/wiki/Special:MyLanguage/Communication +* Looking to file a bug report or a feature request? +** https://bugs.mediawiki.org/ +* Interested in helping out? +** https://www.mediawiki.org/wiki/Special:MyLanguage/How_to_contribute + +MediaWiki is the result of global collaboration and cooperation. The CREDITS +file lists technical contributors to the project. The COPYING file explains +MediaWiki's copyright and license (GNU General Public License, version 2 or +later). Many thanks to the Wikimedia community for testing and suggestions. diff --git a/README.mediawiki b/README.mediawiki deleted file mode 120000 index 100b93820a..0000000000 --- a/README.mediawiki +++ /dev/null @@ -1 +0,0 @@ -README \ No newline at end of file diff --git a/RELEASE-NOTES-1.32 b/RELEASE-NOTES-1.32 index 2124db9ff2..4663751bc1 100644 --- a/RELEASE-NOTES-1.32 +++ b/RELEASE-NOTES-1.32 @@ -17,6 +17,10 @@ production. 'html5-legacy' value for $wgFragmentMode is no longer accepted. * The experimental Html5Internal and Html5Depurate tidy drivers were removed. RemexHtml, which is the default, should be used instead. +* (T135963) You can now define a Content Security Policy for your wiki. This + adds a defense-in-depth feature to stop an attacker who has found a bug in + the parser allowing them to insert malicious attributes. Disabled by default, + you can configure this via $wgCSPHeader and $wgCSPReportOnlyHeader. === New features in 1.32 === * (T112474) Generalized the ResourceLoader mechanism for overriding modules @@ -39,10 +43,20 @@ production. * … === Action API changes in 1.32 === -* … +* Added templated parameters. + * A module can define a templated parameter like "{fruit}-quantity", where + the actual parameters recognized correspond to the values of a multi-valued + parameter. Then clients can make requests like + "fruits=apples|bananas&apples-quantity=1&bananas-quantity=5". + * action=paraminfo will return templated parameter definitions separately + from normal parameters. All parameter definitions now include an "index" + key to allow clients to maintain parameter ordering when merging normal and + templated parameters. === Action API internal changes in 1.32 === * Added 'ApiParseMakeOutputPage' hook. +* Parameter names may no longer contain '{' or '}', as these are now used for + templated parameters. === Languages updated in 1.32 === MediaWiki supports over 350 languages. Many localisations are updated regularly. @@ -92,6 +106,9 @@ because of Phabricator reports. of queueing style modules as well. * OutputPage::addModuleScripts() and ParserOutput::addModuleScripts are deprecated. Use addModules() instead. +* Overriding SearchEngine::{searchText,searchTitle,searchArchiveTitle} + in extending classes is deprecated. Extend related doSearch* methods + instead. === Other changes in 1.32 === * Soft hyphens (U+00AD) are now automatically removed from titles; these diff --git a/autoload.php b/autoload.php index ec0d59f479..c55b931235 100644 --- a/autoload.php +++ b/autoload.php @@ -225,6 +225,7 @@ $wgAutoloadLocalClasses = [ 'CapsCleanup' => __DIR__ . '/maintenance/cleanupCaps.php', 'CategoriesRdf' => __DIR__ . '/includes/CategoriesRdf.php', 'Category' => __DIR__ . '/includes/Category.php', + 'CategoryChangesAsRdf' => __DIR__ . '/maintenance/categoryChangesAsRdf.php', 'CategoryFinder' => __DIR__ . '/includes/CategoryFinder.php', 'CategoryMembershipChange' => __DIR__ . '/includes/changes/CategoryMembershipChange.php', 'CategoryMembershipChangeJob' => __DIR__ . '/includes/jobqueue/jobs/CategoryMembershipChangeJob.php', @@ -303,6 +304,7 @@ $wgAutoloadLocalClasses = [ 'Content' => __DIR__ . '/includes/content/Content.php', 'ContentHandler' => __DIR__ . '/includes/content/ContentHandler.php', 'ContentModelLogFormatter' => __DIR__ . '/includes/logging/ContentModelLogFormatter.php', + 'ContentSecurityPolicy' => __DIR__ . '/includes/ContentSecurityPolicy.php', 'ContextSource' => __DIR__ . '/includes/context/ContextSource.php', 'ContribsPager' => __DIR__ . '/includes/specials/pagers/ContribsPager.php', 'ConvertExtensionToRegistration' => __DIR__ . '/maintenance/convertExtensionToRegistration.php', @@ -359,6 +361,7 @@ $wgAutoloadLocalClasses = [ 'DateFormats' => __DIR__ . '/maintenance/language/date-formats.php', 'DateFormatter' => __DIR__ . '/includes/parser/DateFormatter.php', 'DeadendPagesPage' => __DIR__ . '/includes/specials/SpecialDeadendpages.php', + 'DeduplicateArchiveRevId' => __DIR__ . '/maintenance/deduplicateArchiveRevId.php', 'DeferrableCallback' => __DIR__ . '/includes/deferred/DeferrableCallback.php', 'DeferrableUpdate' => __DIR__ . '/includes/deferred/DeferrableUpdate.php', 'DeferredStringifier' => __DIR__ . '/includes/libs/DeferredStringifier.php', @@ -1159,6 +1162,7 @@ $wgAutoloadLocalClasses = [ 'PopulateBacklinkNamespace' => __DIR__ . '/maintenance/populateBacklinkNamespace.php', 'PopulateCategory' => __DIR__ . '/maintenance/populateCategory.php', 'PopulateContentModel' => __DIR__ . '/maintenance/populateContentModel.php', + 'PopulateExternallinksIndex60' => __DIR__ . '/maintenance/populateExternallinksIndex60.php', 'PopulateFilearchiveSha1' => __DIR__ . '/maintenance/populateFilearchiveSha1.php', 'PopulateImageSha1' => __DIR__ . '/maintenance/populateImageSha1.php', 'PopulateInterwiki' => __DIR__ . '/maintenance/populateInterwiki.php', diff --git a/composer.json b/composer.json index 8de402561b..833e3bfd0e 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "name": "mediawiki/core", "description": "Free software wiki application developed by the Wikimedia Foundation and others", + "type": "mediawiki-core", "keywords": ["mediawiki", "wiki"], "homepage": "https://www.mediawiki.org/", "authors": [ diff --git a/docs/hooks.txt b/docs/hooks.txt index b38bd666e4..9404e1448d 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -1186,6 +1186,31 @@ $lossy: boolean indicating whether lossy conversion is allowed. converted Content object. Note that $result->getContentModel() must return $toModel. +'ContentSecurityPolicyDefaultSource': Modify the allowed CSP load sources. This affects all +directives except for the script directive. If you want to add a script +source, see ContentSecurityPolicyScriptSource hook. +&$defaultSrc: Array of Content-Security-Policy allowed sources +$policyConfig: Current configuration for the Content-Security-Policy header +$mode: ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE + depending on type of header + +'ContentSecurityPolicyDirectives': Modify the content security policy directives. +Use this only if ContentSecurityPolicyDefaultSource and +ContentSecurityPolicyScriptSource do not meet your needs. +&$directives: Array of CSP directives +$policyConfig: Current configuration for the CSP header +$mode: ContentSecurityPolicy::REPORT_ONLY_MODE or + ContentSecurityPolicy::FULL_MODE depending on type of header + +'ContentSecurityPolicyScriptSource': Modify the allowed CSP script sources. +Note that you also have to use ContentSecurityPolicyDefaultSource if you +want non-script sources to be loaded from +whatever you add. +&$scriptSrc: Array of CSP directives +$policyConfig: Current configuration for the CSP header +$mode: ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE + depending on type of header + 'CustomEditor': When invoking the page editor Return true to allow the normal editor to be used, or false if implementing a custom editor, e.g. for a special namespace, etc. diff --git a/includes/ContentSecurityPolicy.php b/includes/ContentSecurityPolicy.php new file mode 100644 index 0000000000..21d7d57dcd --- /dev/null +++ b/includes/ContentSecurityPolicy.php @@ -0,0 +1,527 @@ +nonce = $nonce; + $this->response = $response; + $this->mwConfig = $mwConfig; + } + + /** + * Send a single CSP header based on a given policy config. + * + * @note Most callers will probably want ContentSecurityPolicy::sendHeaders() instead. + * @param array $csp ContentSecurityPolicy configuration + * @param int $reportOnly self::*_MODE constant + */ + public function sendCSPHeader( $csp, $reportOnly ) { + $policy = $this->makeCSPDirectives( $csp, $reportOnly ); + $headerName = $this->getHeaderName( $reportOnly ); + if ( $policy ) { + $this->response->header( + "$headerName: $policy" + ); + } + } + + /** + * Return the meta header to use for after load restricted mode + * + * This should restrict browsers that don't support nonce-sources. + * Idea stolen from + * https://blogs.dropbox.com/tech/2015/09/unsafe-inline-and-nonce-deployment/ + * + * @param array $csp CSP configuration + * @return string Content for meta tag + */ + public function getMetaHeader( $csp ) { + return $this->makeCSPDirectives( $csp, self::FULL_MODE_RESTRICTED ); + } + + /** + * Send CSP headers based on wiki config + * + * Main method that callers are expected to use + * @param IContextSource $context A context object, the associated OutputPage + * object must be the one that the page in question was generated with. + */ + public static function sendHeaders( IContextSource $context ) { + $out = $context->getOutput(); + $csp = new ContentSecurityPolicy( + $out->getCSPNonce(), + $context->getRequest()->response(), + $context->getConfig() + ); + + $cspConfig = $context->getConfig()->get( 'CSPHeader' ); + $cspConfigReportOnly = $context->getConfig()->get( 'CSPReportOnlyHeader' ); + + $csp->sendCSPHeader( $cspConfig, self::FULL_MODE ); + $csp->sendCSPHeader( $cspConfigReportOnly, self::REPORT_ONLY_MODE ); + + // Include header which increases security level after initial load. + // This helps mitigate attacks on browsers not supporting CSP2. It also + // helps mitigate attacks due to the shared nonce that non-logged in users + // get due to varnish cache. + // Unclear if this is the best place to insert the meta tag, or if + // it should be in a RL module. I figure its best to do this as early + // as possible. + // FIXME: Needs testing to see if this actually works properly + $metaHeader = $csp->getMetaHeader( $cspConfig ); + if ( $metaHeader ) { + $context->getOutput()->addScript( + ResourceLoader::makeInlineScript( + $csp->makeMetaInsertScript( + $metaHeader + ), + $out->getCSPNonce() + ) + ); + } + } + + /** + * Makes javascript to insert a meta CSP header after page load + * + * @see https://blogs.dropbox.com/tech/2015/09/unsafe-inline-and-nonce-deployment/ + * @param string $metaContents content of meta tag + * @return string JS for including in page + */ + private function makeMetaInsertScript( $metaContents ) { + return "$('\\x3Cmeta http-equiv=\"Content-Security-Policy\"\\x3E')" . + '.attr("content",' . + Xml::encodeJsVar( $metaContents ) . + ').prependTo($("head"))'; + } + + /** + * Get the name of the HTTP header to use. + * + * @param int $reportOnly Either self::REPORT_ONLY_MODE or self::FULL_MODE + * @return string Name of http header + * @throws UnexpectedValueException if you feed it self::FULL_MODE_RESTRICTED. + */ + private function getHeaderName( $reportOnly ) { + if ( $reportOnly === self::REPORT_ONLY_MODE ) { + return 'Content-Security-Policy-Report-Only'; + } elseif ( $reportOnly === self::FULL_MODE ) { + return 'Content-Security-Policy'; + } + throw new UnexpectedValueException( $reportOnly ); + } + + /** + * Determine what CSP policies to set for this page + * + * @param array|bool $config Policy configuration (Either $wgCSPHeader or $wgCSPReportOnlyHeader) + * @param int $mode self::REPORT_ONLY_MODE, self::FULL_MODE or Self::FULL_MODE_RESTRICTED + * @return string Policy directives, or empty string for no policy. + */ + private function makeCSPDirectives( $policyConfig, $mode ) { + if ( $policyConfig === false ) { + // CSP is disabled + return ''; + } + if ( $policyConfig === true ) { + $policyConfig = []; + } + + $mwConfig = $this->mwConfig; + + $additionalSelfUrls = $this->getAdditionalSelfUrls(); + $additionalSelfUrlsScript = $this->getAdditionalSelfUrlsScript(); + $nonceSrc = "'nonce-" . $this->nonce . "'"; + + // If no default-src is sent at all, it + // seems browsers (or at least some), interpret + // that as allow anything, but the spec seems + // to imply that data: and blob: should be + // blocked. + $defaultSrc = [ '*', 'data:', 'blob:' ]; + + $cssSrc = false; + $imgSrc = false; + $scriptSrc = [ "'unsafe-eval'", "'self'" ]; + if ( $mode !== self::FULL_MODE_RESTRICTED ) { + $scriptSrc[] = $nonceSrc; + } + $scriptSrc = array_merge( $scriptSrc, $additionalSelfUrlsScript ); + if ( isset( $policyConfig['script-src'] ) + && is_array( $policyConfig['script-src'] ) + ) { + foreach ( $policyConfig['script-src'] as $src ) { + $scriptSrc[] = $this->escapeUrlForCSP( $src ); + } + } + // Note: default on if unspecified. + if ( ( !isset( $policyConfig['unsafeFallback'] ) + || $policyConfig['unsafeFallback'] ) + && $mode !== self::FULL_MODE_RESTRICTED + ) { + // unsafe-inline should be ignored on browsers + // that support 'nonce-foo' sources. + // Some older versions of firefox don't follow this + // rule, but new browsers do. (Should be for at least + // firefox 40+). + $scriptSrc[] = "'unsafe-inline'"; + } + // If default source option set to true or + // an array of urls, set a restrictive default-src. + // If set to false, we send a lenient default-src, + // see the code above where $defaultSrc is set initially. + if ( isset( $policyConfig['default-src'] ) + && $policyConfig['default-src'] !== false + ) { + $defaultSrc = array_merge( + [ "'self'", 'data:', 'blob:' ], + $additionalSelfUrls + ); + if ( is_array( $policyConfig['default-src'] ) ) { + foreach ( $policyConfig['default-src'] as $src ) { + $defaultSrc[] = $this->escapeUrlForCSP( $src ); + } + } + } + + if ( !isset( $policyConfig['includeCORS'] ) || $policyConfig['includeCORS'] ) { + $CORSUrls = $this->getCORSSources(); + if ( !in_array( '*', $defaultSrc ) ) { + $defaultSrc = array_merge( $defaultSrc, $CORSUrls ); + } + // Unlikely to have * in scriptSrc, but doesn't + // hurt to check. + if ( !in_array( '*', $scriptSrc ) ) { + $scriptSrc = array_merge( $scriptSrc, $CORSUrls ); + } + } + + Hooks::run( 'ContentSecurityPolicyDefaultSource', [ &$defaultSrc, $policyConfig, $mode ] ); + Hooks::run( 'ContentSecurityPolicyScriptSource', [ &$scriptSrc, $policyConfig, $mode ] ); + + // Check if array just in case the hook made it false + if ( is_array( $defaultSrc ) ) { + $cssSrc = array_merge( $defaultSrc, [ "'unsafe-inline'" ] ); + } + + if ( $mode === self::FULL_MODE_RESTRICTED ) { + // report-uri disallowed in tags. + $reportUri = false; + } elseif ( isset( $policyConfig['report-uri'] ) && $policyConfig['report-uri'] !== true ) { + if ( $policyConfig['report-uri'] === false ) { + $reportUri = false; + } else { + $reportUri = $this->escapeUrlForCSP( $policyConfig['report-uri'] ); + } + } else { + $reportUri = $this->getReportUri( $mode ); + } + + // Only send an img-src, if we're sending a restricitve default. + if ( !is_array( $defaultSrc ) + || !in_array( '*', $defaultSrc ) + || !in_array( 'data:', $defaultSrc ) + || !in_array( 'blob:', $defaultSrc ) + ) { + // A future todo might be to make the whitelist options only + // add all the whitelisted sites to the header, instead of + // allowing all (Assuming there is a small number of sites). + // For now, the external image feature disables the limits + // CSP puts on external images. + if ( $mwConfig->get( 'AllowExternalImages' ) + || $mwConfig->get( 'AllowExternalImagesFrom' ) + || $mwConfig->get( 'AllowImageTag' ) + ) { + $imgSrc = [ '*', 'data:', 'blob:' ]; + } elseif ( $mwConfig->get( 'EnableImageWhitelist' ) ) { + $whitelist = wfMessage( 'external_image_whitelist' ) + ->inContentLanguage() + ->plain(); + if ( preg_match( '/^\s*[^\s#]/m', $whitelist ) ) { + $imgSrc = [ '*', 'data:', 'blob:' ]; + } + } + } + + $directives = []; + if ( $scriptSrc ) { + $directives[] = 'script-src ' . implode( ' ', $scriptSrc ); + } + if ( $defaultSrc ) { + $directives[] = 'default-src ' . implode( ' ', $defaultSrc ); + } + if ( $cssSrc ) { + $directives[] = 'style-src ' . implode( ' ', $cssSrc ); + } + if ( $imgSrc ) { + $directives[] = 'img-src ' . implode( ' ', $imgSrc ); + } + if ( $reportUri ) { + $directives[] = 'report-uri ' . $reportUri; + } + + Hooks::run( 'ContentSecurityPolicyDirectives', [ &$directives, $policyConfig, $mode ] ); + + return implode( '; ', $directives ); + } + + /** + * Get the default report uri. + * + * @param int $mode self::*_MODE constant. Do not use with self::FULL_MODE_RESTRICTED + * @return string The URI to send reports to. + * @throws UnexpectedValueException if given invalid mode. + */ + private function getReportUri( $mode ) { + if ( $mode === self::FULL_MODE_RESTRICTED ) { + throw new UnexpectedValueException( $mode ); + } + $apiArguments = [ + 'action' => 'cspreport', + 'format' => 'json' + ]; + if ( $mode === self::REPORT_ONLY_MODE ) { + $apiArguments['reportonly'] = '1'; + } + $reportUri = wfAppendQuery( wfScript( 'api' ), $apiArguments ); + + // Per spec, ';' and ',' must be hex-escaped in report uri + $reportUri = $this->escapeUrlForCSP( $reportUri ); + return $reportUri; + } + + /** + * Given a url, convert to form needed for CSP. + * + * Currently this does either scheme + host, or + * if protocol relative, just the host. Future versions + * could potentially preserve some of the path, if its determined + * that that would be a good idea. + * + * @note This does the extra escaping for CSP, but assumes the url + * has already had normal url escaping applied. + * @note This discards urls same as server name, as 'self' directive + * takes care of that. + * @param string $url + * @return string|bool Converted url or false on failure + */ + private function prepareUrlForCSP( $url ) { + $result = false; + if ( preg_match( '/^[a-z][a-z0-9+.-]*:$/i', $url ) ) { + // A schema source (e.g. blob: or data:) + return $url; + } + $bits = wfParseUrl( $url ); + if ( !$bits && strpos( $url, '/' ) === false ) { + // probably something like example.com. + // try again protocol-relative. + $url = '//' . $url; + $bits = wfParseUrl( $url ); + } + if ( $bits && isset( $bits['host'] ) + && $bits['host'] !== $this->mwConfig->get( 'ServerName' ) + ) { + $result = $bits['host']; + if ( $bits['scheme'] !== '' ) { + $result = $bits['scheme'] . $bits['delimiter'] . $result; + } + if ( isset( $bits['port'] ) ) { + $result .= ':' . $bits['port']; + } + $result = $this->escapeUrlForCSP( $result ); + } + return $result; + } + + /** + * Get additional script sources + * + * @return array Additional sources for loading scripts from + */ + private function getAdditionalSelfUrlsScript() { + $additionalUrls = []; + // wgExtensionAssetsPath for ?debug=true mode + $pathVars = [ 'LoadScript', 'ExtensionAssetsPath', 'ResourceBasePath' ]; + + foreach ( $pathVars as $path ) { + $url = $this->mwConfig->get( $path ); + $preparedUrl = $this->prepareUrlForCSP( $url ); + if ( $preparedUrl ) { + $additionalUrls[] = $preparedUrl; + } + } + $RLSources = $this->mwConfig->get( 'ResourceLoaderSources' ); + foreach ( $RLSources as $wiki => $sources ) { + foreach ( $sources as $id => $value ) { + $url = $this->prepareUrlForCSP( $value ); + if ( $url ) { + $additionalUrls[] = $url; + } + } + } + + return array_unique( $additionalUrls ); + } + + /** + * Get additional host names for the wiki (e.g. if static content loaded elsewhere) + * + * @note These are general load sources, not script sources + * @return array Array of other urls for wiki (for use in default-src) + */ + private function getAdditionalSelfUrls() { + // XXX on a foreign repo, the included description page can have anything on it, + // including inline scripts. But nobody sane does that. + + // In principle, you can have even more complex configs... (e.g. The urlsByExt option) + $pathUrls = []; + $additionalSelfUrls = []; + + // Future todo: The zone urls should never go into + // style-src. They should either be only in img-src, or if + // img-src unspecified they should be in default-src. Similarly, + // the DescriptionStylesheetUrl only needs to be in style-src + // (or default-src if style-src unspecified). + $callback = function ( $repo, &$urls ) { + $urls[] = $repo->getZoneUrl( 'public' ); + $urls[] = $repo->getZoneUrl( 'transcoded' ); + $urls[] = $repo->getZoneUrl( 'thumb' ); + $urls[] = $repo->getDescriptionStylesheetUrl(); + }; + $localRepo = RepoGroup::singleton()->getRepo( 'local' ); + $callback( $localRepo, $pathUrls ); + RepoGroup::singleton()->forEachForeignRepo( $callback, [ &$pathUrls ] ); + + // Globals that might point to a different domain + $pathGlobals = [ 'LoadScript', 'ExtensionAssetsPath', 'StylePath', 'ResourceBasePath' ]; + foreach ( $pathGlobals as $path ) { + $pathUrls[] = $this->mwConfig->get( $path ); + } + foreach ( $pathUrls as $path ) { + $preparedUrl = $this->prepareUrlForCSP( $path ); + if ( $preparedUrl !== false ) { + $additionalSelfUrls[] = $preparedUrl; + } + } + $RLSources = $this->mwConfig->get( 'ResourceLoaderSources' ); + + foreach ( $RLSources as $wiki => $sources ) { + foreach ( $sources as $id => $value ) { + $url = $this->prepareUrlForCSP( $value ); + if ( $url ) { + $additionalSelfUrls[] = $url; + } + } + } + + return array_unique( $additionalSelfUrls ); + } + + /** + * include domains that are allowed to send us CORS requests. + * + * Technically, $wgCrossSiteAJAXdomains lists things that are allowed to talk to us + * not things that we are allowed to talk to - but if something is allowed to talk to us, + * then there is a good chance that we should probably be allowed to talk to it. + * + * This is configurable with the 'includeCORS' key in the CSP config, and enabled + * by default. + * @note CORS domains with single character ('?') wildcards, are not included. + * @return array Additional hosts + */ + private function getCORSSources() { + $additionalUrls = []; + $CORSSources = $this->mwConfig->get( 'CrossSiteAJAXdomains' ); + foreach ( $CORSSources as $source ) { + if ( strpos( $source, '?' ) !== false ) { + // CSP doesn't support single char wildcard + continue; + } + $url = $this->prepareUrlForCSP( $source ); + if ( $url ) { + $additionalUrls[] = $url; + } + } + return $additionalUrls; + } + + /** + * CSP spec says ',' and ';' are not allowed to appear in urls. + * + * @note This assumes that normal escaping has been applied to the url + * @param string $url URL (or possibly just part of one) + * @return string + */ + private function escapeUrlForCSP( $url ) { + return str_replace( + [ ';', ',' ], + [ '%3B', '%2C' ], + $url + ); + } + + /** + * Does this browser give false positive reports? + * + * Some versions of firefox (40-42) incorrectly report a csp + * violation for nonce sources, despite allowing them. + * + * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1026520 + * @param string $ua User-agent header + * @return bool + */ + public static function falsePositiveBrowser( $ua ) { + return (bool)preg_match( '!Firefox/4[0-2]\.!', $ua ); + } + + /** + * Is CSP currently enabled (i.e. Should we set nonce attribute) + * + * @param Config $config Configuration object + * @return bool + */ + public static function isEnabled( Config $config ) { + return $config->get( 'CSPHeader' ) !== false + || $config->get( 'CSPReportOnlyHeader' ) !== false; + } +} diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index dcf648e79c..87ca0168bd 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -7864,10 +7864,6 @@ $wgActionFilteredLogs = [ 'autocreate' => [ 'autocreate' ], 'byemail' => [ 'byemail' ], ], - 'patrol' => [ - 'patrol' => [ 'patrol' ], - 'autopatrol' => [ 'autopatrol' ], - ], 'protect' => [ 'protect' => [ 'protect' ], 'modify' => [ 'modify' ], @@ -8752,6 +8748,34 @@ $wgMaxUserDBWriteDuration = false; */ $wgMaxJobDBWriteDuration = false; +/** + * Controls Content-Security-Policy header [Experimental] + * + * @see https://www.w3.org/TR/CSP2/ + * @since 1.32 + * @var bool|array true to send default version, false to not send. + * If an array, can have parameters: + * 'default-src' If true or array (of additional urls) will set a default-src + * directive, which limits what places things can load from. If false or not + * set, will send a default-src directive allowing all sources. + * 'includeCORS' If true or not set, will include urls from + * $wgCrossSiteAJAXdomains as an allowed load sources. + * 'unsafeFallback' Add unsafe-inline as a script source, as a fallback for + * browsers that do not understand nonce-sources [default on]. + * 'script-src' Array of additional places that are allowed to have JS be loaded from. + * 'report-uri' true to use MW api [default], false to disable, string for alternate uri + * @warning May cause slowness on windows due to slow random number generator. + */ +$wgCSPHeader = false; + +/** + * Controls Content-Security-Policy-Report-Only header + * + * @since 1.32 + * @var bool|array Same as $wgCSPHeader + */ +$wgCSPReportOnlyHeader = false; + /** * Mapping of event channels (or channel categories) to EventRelayer configuration. * diff --git a/includes/EditPage.php b/includes/EditPage.php index 4f6b7b4bbb..6d39e3a03d 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -4111,12 +4111,15 @@ ERROR; $script .= '});'; + $nonce = $wgOut->getCSPNonce(); + $wgOut->addScript( ResourceLoader::makeInlineScript( $script, $nonce ) ); + $toolbar = '
'; if ( Hooks::run( 'EditPageBeforeEditToolbar', [ &$toolbar ] ) ) { // Only add the old toolbar cruft to the page payload if the toolbar has not // been over-written by a hook caller - $wgOut->addScript( ResourceLoader::makeInlineScript( $script ) ); + $wgOut->addScript( ResourceLoader::makeInlineScript( $script, $nonce ) ); }; return $toolbar; diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 9569bc1fb4..7e8df7ee48 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -1513,9 +1513,10 @@ function wfHostname() { * If $wgShowHostnames is true, the script will also set 'wgHostname' to the * hostname of the server handling the request. * + * @param string $nonce Value from OutputPage::getCSPNonce * @return string */ -function wfReportTime() { +function wfReportTime( $nonce = null ) { global $wgShowHostnames; $elapsed = ( microtime( true ) - $_SERVER['REQUEST_TIME_FLOAT'] ); @@ -1525,7 +1526,7 @@ function wfReportTime() { if ( $wgShowHostnames ) { $reportVars['wgHostname'] = wfHostname(); } - return Skin::makeVariablesScript( $reportVars ); + return Skin::makeVariablesScript( $reportVars, $nonce ); } /** diff --git a/includes/Html.php b/includes/Html.php index 3bcf13132f..019e0785f9 100644 --- a/includes/Html.php +++ b/includes/Html.php @@ -557,10 +557,18 @@ class Html { * literal "" or (for XML) literal "]]>". * * @param string $contents JavaScript + * @param string $nonce Nonce for CSP header, from OutputPage::getCSPNonce() * @return string Raw HTML */ - public static function inlineScript( $contents ) { + public static function inlineScript( $contents, $nonce = null ) { $attrs = []; + if ( $nonce !== null ) { + $attrs['nonce'] = $nonce; + } else { + if ( ContentSecurityPolicy::isEnabled( RequestContext::getMain()->getConfig() ) ) { + wfWarn( "no nonce set on script. CSP will break it" ); + } + } if ( preg_match( '/[<&]/', $contents ) ) { $contents = "/**/"; @@ -574,10 +582,18 @@ class Html { * "". * * @param string $url + * @param string $nonce Nonce for CSP header, from OutputPage::getCSPNonce() * @return string Raw HTML */ - public static function linkedScript( $url ) { + public static function linkedScript( $url, $nonce = null ) { $attrs = [ 'src' => $url ]; + if ( $nonce !== null ) { + $attrs['nonce'] = $nonce; + } else { + if ( ContentSecurityPolicy::isEnabled( RequestContext::getMain()->getConfig() ) ) { + wfWarn( "no nonce set on script. CSP will break it" ); + } + } return self::element( 'script', $attrs ); } diff --git a/includes/OutputPage.php b/includes/OutputPage.php index fbc7b60439..52dfc1164e 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -304,6 +304,11 @@ class OutputPage extends ContextSource { */ private $mLinkHeader = []; + /** + * @var string The nonce for Content-Security-Policy + */ + private $CSPNonce; + /** * Constructor for OutputPage. This should not be called directly. * Instead a new RequestContext should be created and it will implicitly create @@ -475,7 +480,7 @@ class OutputPage extends ContextSource { if ( is_null( $version ) ) { $version = $this->getConfig()->get( 'StyleVersion' ); } - $this->addScript( Html::linkedScript( wfAppendQuery( $path, $version ) ) ); + $this->addScript( Html::linkedScript( wfAppendQuery( $path, $version ), $this->getCSPNonce() ) ); } /** @@ -485,7 +490,7 @@ class OutputPage extends ContextSource { * @param string $script JavaScript text, no script tags */ public function addInlineScript( $script ) { - $this->mScripts .= Html::inlineScript( $script ); + $this->mScripts .= Html::inlineScript( "\n$script\n", $this->getCSPNonce() ) . "\n"; } /** @@ -2433,6 +2438,8 @@ class OutputPage extends ContextSource { $response->header( "X-Frame-Options: $frameOptions" ); } + ContentSecurityPolicy::sendHeaders( $this ); + if ( $this->mArticleBodyOnly ) { echo $this->mBodytext; } else { @@ -2900,7 +2907,7 @@ class OutputPage extends ContextSource { } $pieces[] = Html::element( 'title', null, $this->getHTMLTitle() ); - $pieces[] = $this->getRlClient()->getHeadHtml(); + $pieces[] = $this->getRlClient()->getHeadHtml( $this->getCSPNonce() ); $pieces[] = $this->buildExemptModules(); $pieces = array_merge( $pieces, array_values( $this->getHeadLinksArray() ) ); $pieces = array_merge( $pieces, array_values( $this->mHeadItems ) ); @@ -2911,7 +2918,8 @@ class OutputPage extends ContextSource { ResourceLoaderContext::newDummyContext(), [ 'html5shiv' ], ResourceLoaderModule::TYPE_SCRIPTS, - [ 'sync' => true ] + [ 'sync' => true ], + $this->getCSPNonce() ) . ''; @@ -2992,7 +3000,8 @@ class OutputPage extends ContextSource { $this->getRlClientContext(), $modules, $only, - $extraQuery + $extraQuery, + $this->getCSPNonce() ); } @@ -3025,7 +3034,8 @@ class OutputPage extends ContextSource { $chunks[] = ResourceLoader::makeInlineScript( ResourceLoader::makeConfigSetScript( [ 'wgPageParseReport' => $this->limitReportJSData ] - ) + ), + $this->getCSPNonce() ); } @@ -3992,4 +4002,26 @@ class OutputPage extends ContextSource { ); } } + + /** + * Get (and set if not yet set) the CSP nonce. + * + * This value needs to be included in any ' ); } diff --git a/includes/resourceloader/ResourceLoaderClientHtml.php b/includes/resourceloader/ResourceLoaderClientHtml.php index bb8ab32998..d0a9c4248a 100644 --- a/includes/resourceloader/ResourceLoaderClientHtml.php +++ b/includes/resourceloader/ResourceLoaderClientHtml.php @@ -248,9 +248,10 @@ class ResourceLoaderClientHtml { * - Inline scripts can't be asynchronous. * - For styles, earlier is better. * + * @param string $nonce From OutputPage::getCSPNonce() * @return string|WrappedStringList HTML */ - public function getHeadHtml() { + public function getHeadHtml( $nonce ) { $data = $this->getData(); $chunks = []; @@ -259,13 +260,15 @@ class ResourceLoaderClientHtml { // See also #getDocumentAttributes() and /resources/src/startup.js. $chunks[] = Html::inlineScript( 'document.documentElement.className = document.documentElement.className' - . '.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );' + . '.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );', + $nonce ); // Inline RLQ: Set page variables if ( $this->config ) { $chunks[] = ResourceLoader::makeInlineScript( - ResourceLoader::makeConfigSetScript( $this->config ) + ResourceLoader::makeConfigSetScript( $this->config ), + $nonce ); } @@ -273,7 +276,8 @@ class ResourceLoaderClientHtml { $states = array_merge( $this->exemptStates, $data['states'] ); if ( $states ) { $chunks[] = ResourceLoader::makeInlineScript( - ResourceLoader::makeLoaderStateScript( $states ) + ResourceLoader::makeLoaderStateScript( $states ), + $nonce ); } @@ -281,14 +285,16 @@ class ResourceLoaderClientHtml { if ( $data['embed']['general'] ) { $chunks[] = $this->getLoad( $data['embed']['general'], - ResourceLoaderModule::TYPE_COMBINED + ResourceLoaderModule::TYPE_COMBINED, + $nonce ); } // Inline RLQ: Load general modules if ( $data['general'] ) { $chunks[] = ResourceLoader::makeInlineScript( - Xml::encodeJsCall( 'mw.loader.load', [ $data['general'] ] ) + Xml::encodeJsCall( 'mw.loader.load', [ $data['general'] ] ), + $nonce ); } @@ -296,7 +302,8 @@ class ResourceLoaderClientHtml { if ( $data['scripts'] ) { $chunks[] = $this->getLoad( $data['scripts'], - ResourceLoaderModule::TYPE_SCRIPTS + ResourceLoaderModule::TYPE_SCRIPTS, + $nonce ); } @@ -304,7 +311,8 @@ class ResourceLoaderClientHtml { if ( $data['styles'] ) { $chunks[] = $this->getLoad( $data['styles'], - ResourceLoaderModule::TYPE_STYLES + ResourceLoaderModule::TYPE_STYLES, + $nonce ); } @@ -312,7 +320,8 @@ class ResourceLoaderClientHtml { if ( $data['embed']['styles'] ) { $chunks[] = $this->getLoad( $data['embed']['styles'], - ResourceLoaderModule::TYPE_STYLES + ResourceLoaderModule::TYPE_STYLES, + $nonce ); } @@ -324,6 +333,7 @@ class ResourceLoaderClientHtml { $chunks[] = $this->getLoad( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, + $nonce, $startupQuery ); @@ -341,8 +351,8 @@ class ResourceLoaderClientHtml { return self::makeContext( $this->context, $group, $type ); } - private function getLoad( $modules, $only, array $extraQuery = [] ) { - return self::makeLoad( $this->context, (array)$modules, $only, $extraQuery ); + private function getLoad( $modules, $only, $nonce, array $extraQuery = [] ) { + return self::makeLoad( $this->context, (array)$modules, $only, $extraQuery, $nonce ); } private static function makeContext( ResourceLoaderContext $mainContext, $group, $type, @@ -369,11 +379,12 @@ class ResourceLoaderClientHtml { * @param ResourceLoaderContext $mainContext * @param array $modules One or more module names * @param string $only ResourceLoaderModule TYPE_ class constant - * @param array $extraQuery [optional] Array with extra query parameters for the request + * @param array $extraQuery Array with extra query parameters for the request + * @param string $nonce See OutputPage::getCSPNonce() [Since 1.32] * @return string|WrappedStringList HTML */ public static function makeLoad( ResourceLoaderContext $mainContext, array $modules, $only, - array $extraQuery = [] + array $extraQuery, $nonce ) { $rl = $mainContext->getResourceLoader(); $chunks = []; @@ -385,7 +396,7 @@ class ResourceLoaderClientHtml { $chunks = []; // Recursively call us for every item foreach ( $modules as $name ) { - $chunks[] = self::makeLoad( $mainContext, [ $name ], $only, $extraQuery ); + $chunks[] = self::makeLoad( $mainContext, [ $name ], $only, $extraQuery, $nonce ); } return new WrappedStringList( "\n", $chunks ); } @@ -427,7 +438,8 @@ class ResourceLoaderClientHtml { ); } else { $chunks[] = ResourceLoader::makeInlineScript( - $rl->makeModuleResponse( $context, $moduleSet ) + $rl->makeModuleResponse( $context, $moduleSet ), + $nonce ); } } else { @@ -461,7 +473,8 @@ class ResourceLoaderClientHtml { ] ); } else { $chunk = ResourceLoader::makeInlineScript( - Xml::encodeJsCall( 'mw.loader.load', [ $url ] ) + Xml::encodeJsCall( 'mw.loader.load', [ $url ] ), + $nonce ); } } diff --git a/includes/search/SearchEngine.php b/includes/search/SearchEngine.php index 7e6e8e6d0d..bd48e21364 100644 --- a/includes/search/SearchEngine.php +++ b/includes/search/SearchEngine.php @@ -69,12 +69,25 @@ abstract class SearchEngine { /** * Perform a full text search query and return a result set. * If full text searches are not supported or disabled, return null. - * STUB + * + * As of 1.32 overriding this function is deprecated. It will + * be converted to final in 1.34. Override self::doSearchText(). * * @param string $term Raw search term * @return SearchResultSet|Status|null */ - function searchText( $term ) { + public function searchText( $term ) { + return $this->doSearchText( $term ); + } + + /** + * Perform a full text search query and return a result set. + * + * @param string $term Raw search term + * @return SearchResultSet|Status|null + * @since 1.32 + */ + protected function doSearchText( $term ) { return null; } @@ -85,11 +98,25 @@ abstract class SearchEngine { * The results returned by this methods are only sugegstions and * may not end up being shown to the user. * + * As of 1.32 overriding this function is deprecated. It will + * be converted to final in 1.34. Override self::doSearchArchiveTitle(). + * * @param string $term Raw search term * @return Status * @since 1.29 */ - function searchArchiveTitle( $term ) { + public function searchArchiveTitle( $term ) { + return $this->doSearchArchiveTitle( $term ); + } + + /** + * Perform a title search in the article archive. + * + * @param string $term Raw search term + * @return Status + * @since 1.32 + */ + protected function doSearchArchiveTitle( $term ) { return Status::newGood( [] ); } @@ -98,10 +125,24 @@ abstract class SearchEngine { * If title searches are not supported or disabled, return null. * STUB * + * As of 1.32 overriding this function is deprecated. It will + * be converted to final in 1.34. Override self::doSearchTitle(). + * + * @param string $term Raw search term + * @return SearchResultSet|null + */ + public function searchTitle( $term ) { + return $this->doSearchTitle( $term ); + } + + /** + * Perform a title-only search query and return a result set. + * * @param string $term Raw search term * @return SearchResultSet|null + * @since 1.32 */ - function searchTitle( $term ) { + protected function doSearchTitle( $term ) { return null; } @@ -335,12 +376,25 @@ abstract class SearchEngine { return false; } $extractedNamespace = null; + $allkeywords = []; + + $allkeywords[] = wfMessage( 'searchall' )->inContentLanguage()->text() . ":"; + // force all: so that we have a common syntax for all the wikis + if ( !in_array( 'all:', $allkeywords ) ) { + $allkeywords[] = 'all:'; + } + + $allQuery = false; + foreach ( $allkeywords as $kw ) { + if ( strncmp( $query, $kw, strlen( $kw ) ) == 0 ) { + $extractedNamespace = null; + $parsed = substr( $query, strlen( $kw ) ); + $allQuery = true; + break; + } + } - $allkeyword = wfMessage( 'searchall' )->inContentLanguage()->text() . ":"; - if ( strncmp( $query, $allkeyword, strlen( $allkeyword ) ) == 0 ) { - $extractedNamespace = null; - $parsed = substr( $query, strlen( $allkeyword ) ); - } elseif ( strpos( $query, ':' ) !== false ) { + if ( !$allQuery && strpos( $query, ':' ) !== false ) { // TODO: should we unify with PrefixSearch::extractNamespace ? $prefix = str_replace( ' ', '_', substr( $query, 0, strpos( $query, ':' ) ) ); $index = $wgContLang->getNsIndex( $prefix ); diff --git a/includes/search/SearchMssql.php b/includes/search/SearchMssql.php index 57ca06e39f..43bd3bed27 100644 --- a/includes/search/SearchMssql.php +++ b/includes/search/SearchMssql.php @@ -31,9 +31,8 @@ class SearchMssql extends SearchDatabase { * * @param string $term Raw search term * @return SqlSearchResultSet - * @access public */ - function searchText( $term ) { + protected function doSearchText( $term ) { $resultSet = $this->db->query( $this->getQuery( $this->filter( $term ), true ) ); return new SqlSearchResultSet( $resultSet, $this->searchTerms ); } @@ -43,9 +42,8 @@ class SearchMssql extends SearchDatabase { * * @param string $term Raw search term * @return SqlSearchResultSet - * @access public */ - function searchTitle( $term ) { + protected function doSearchTitle( $term ) { $resultSet = $this->db->query( $this->getQuery( $this->filter( $term ), false ) ); return new SqlSearchResultSet( $resultSet, $this->searchTerms ); } @@ -54,9 +52,8 @@ class SearchMssql extends SearchDatabase { * Return a partial WHERE clause to limit the search to the given namespaces * * @return string - * @private */ - function queryNamespaces() { + private function queryNamespaces() { $namespaces = implode( ',', $this->namespaces ); if ( $namespaces == '' ) { $namespaces = '0'; @@ -71,7 +68,7 @@ class SearchMssql extends SearchDatabase { * * @return string */ - function queryLimit( $sql ) { + private function queryLimit( $sql ) { return $this->db->limitResult( $sql, $this->limit, $this->offset ); } @@ -95,7 +92,7 @@ class SearchMssql extends SearchDatabase { * @param bool $fulltext * @return string */ - function getQuery( $filteredTerm, $fulltext ) { + private function getQuery( $filteredTerm, $fulltext ) { return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' . $this->queryNamespaces() . ' ' . $this->queryRanking( $filteredTerm, $fulltext ) . ' ' ); @@ -117,9 +114,8 @@ class SearchMssql extends SearchDatabase { * @param string $filteredTerm * @param bool $fulltext * @return string - * @private */ - function queryMain( $filteredTerm, $fulltext ) { + private function queryMain( $filteredTerm, $fulltext ) { $match = $this->parseQuery( $filteredTerm, $fulltext ); $page = $this->db->tableName( 'page' ); $searchindex = $this->db->tableName( 'searchindex' ); @@ -134,7 +130,7 @@ class SearchMssql extends SearchDatabase { * @param bool $fulltext * @return string */ - function parseQuery( $filteredText, $fulltext ) { + private function parseQuery( $filteredText, $fulltext ) { global $wgContLang; $lc = $this->legalSearchChars( self::CHARS_NO_SYNTAX ); $this->searchTerms = []; diff --git a/includes/search/SearchMySQL.php b/includes/search/SearchMySQL.php index c98f7e337c..9a03ebe950 100644 --- a/includes/search/SearchMySQL.php +++ b/includes/search/SearchMySQL.php @@ -42,7 +42,7 @@ class SearchMySQL extends SearchDatabase { * * @return array */ - function parseQuery( $filteredText, $fulltext ) { + private function parseQuery( $filteredText, $fulltext ) { global $wgContLang; $lc = $this->legalSearchChars( self::CHARS_NO_SYNTAX ); // Minus syntax chars (" and *) @@ -133,7 +133,7 @@ class SearchMySQL extends SearchDatabase { ]; } - function regexTerm( $string, $wildcard ) { + private function regexTerm( $string, $wildcard ) { global $wgContLang; $regex = preg_quote( $string, '/' ); @@ -167,7 +167,7 @@ class SearchMySQL extends SearchDatabase { * @param string $term Raw search term * @return SqlSearchResultSet */ - function searchText( $term ) { + protected function doSearchText( $term ) { return $this->searchInternal( $term, true ); } @@ -177,7 +177,7 @@ class SearchMySQL extends SearchDatabase { * @param string $term Raw search term * @return SqlSearchResultSet */ - function searchTitle( $term ) { + protected function doSearchTitle( $term ) { return $this->searchInternal( $term, false ); } @@ -264,7 +264,7 @@ class SearchMySQL extends SearchDatabase { * @return array * @since 1.18 (changed) */ - function getQuery( $filteredTerm, $fulltext ) { + private function getQuery( $filteredTerm, $fulltext ) { $query = [ 'tables' => [], 'fields' => [], @@ -286,7 +286,7 @@ class SearchMySQL extends SearchDatabase { * @param bool $fulltext * @return string */ - function getIndexField( $fulltext ) { + private function getIndexField( $fulltext ) { return $fulltext ? 'si_text' : 'si_title'; } @@ -298,7 +298,7 @@ class SearchMySQL extends SearchDatabase { * @param bool $fulltext * @since 1.18 (changed) */ - function queryMain( &$query, $filteredTerm, $fulltext ) { + private function queryMain( &$query, $filteredTerm, $fulltext ) { $match = $this->parseQuery( $filteredTerm, $fulltext ); $query['tables'][] = 'page'; $query['tables'][] = 'searchindex'; @@ -316,7 +316,7 @@ class SearchMySQL extends SearchDatabase { * @param bool $fulltext * @return array */ - function getCountQuery( $filteredTerm, $fulltext ) { + private function getCountQuery( $filteredTerm, $fulltext ) { $match = $this->parseQuery( $filteredTerm, $fulltext ); $query = [ diff --git a/includes/search/SearchOracle.php b/includes/search/SearchOracle.php index 8bcd78fa66..7fe5b53ca6 100644 --- a/includes/search/SearchOracle.php +++ b/includes/search/SearchOracle.php @@ -64,7 +64,7 @@ class SearchOracle extends SearchDatabase { * @param string $term Raw search term * @return SqlSearchResultSet */ - function searchText( $term ) { + protected function doSearchText( $term ) { if ( $term == '' ) { return new SqlSearchResultSet( false, '' ); } @@ -79,7 +79,7 @@ class SearchOracle extends SearchDatabase { * @param string $term Raw search term * @return SqlSearchResultSet */ - function searchTitle( $term ) { + protected function doSearchTitle( $term ) { if ( $term == '' ) { return new SqlSearchResultSet( false, '' ); } @@ -92,7 +92,7 @@ class SearchOracle extends SearchDatabase { * Return a partial WHERE clause to limit the search to the given namespaces * @return string */ - function queryNamespaces() { + private function queryNamespaces() { if ( is_null( $this->namespaces ) ) { return ''; } @@ -111,7 +111,7 @@ class SearchOracle extends SearchDatabase { * * @return string */ - function queryLimit( $sql ) { + private function queryLimit( $sql ) { return $this->db->limitResult( $sql, $this->limit, $this->offset ); } @@ -134,7 +134,7 @@ class SearchOracle extends SearchDatabase { * @param bool $fulltext * @return string */ - function getQuery( $filteredTerm, $fulltext ) { + private function getQuery( $filteredTerm, $fulltext ) { return $this->queryLimit( $this->queryMain( $filteredTerm, $fulltext ) . ' ' . $this->queryNamespaces() . ' ' . $this->queryRanking( $filteredTerm, $fulltext ) . ' ' ); @@ -145,7 +145,7 @@ class SearchOracle extends SearchDatabase { * @param bool $fulltext * @return string */ - function getIndexField( $fulltext ) { + private function getIndexField( $fulltext ) { return $fulltext ? 'si_text' : 'si_title'; } @@ -172,7 +172,7 @@ class SearchOracle extends SearchDatabase { * @param bool $fulltext * @return string */ - function parseQuery( $filteredText, $fulltext ) { + private function parseQuery( $filteredText, $fulltext ) { global $wgContLang; $lc = $this->legalSearchChars( self::CHARS_NO_SYNTAX ); $this->searchTerms = []; diff --git a/includes/search/SearchPostgres.php b/includes/search/SearchPostgres.php index 5a50b176e9..729e528fd6 100644 --- a/includes/search/SearchPostgres.php +++ b/includes/search/SearchPostgres.php @@ -37,7 +37,7 @@ class SearchPostgres extends SearchDatabase { * @param string $term Raw search term * @return SqlSearchResultSet */ - function searchTitle( $term ) { + protected function doSearchTitle( $term ) { $q = $this->searchQuery( $term, 'titlevector', 'page_title' ); $olderror = error_reporting( E_ERROR ); $resultSet = $this->db->query( $q, 'SearchPostgres', true ); @@ -45,7 +45,7 @@ class SearchPostgres extends SearchDatabase { return new SqlSearchResultSet( $resultSet, $this->searchTerms ); } - function searchText( $term ) { + protected function doSearchText( $term ) { $q = $this->searchQuery( $term, 'textvector', 'old_text' ); $olderror = error_reporting( E_ERROR ); $resultSet = $this->db->query( $q, 'SearchPostgres', true ); @@ -61,7 +61,7 @@ class SearchPostgres extends SearchDatabase { * * @return string */ - function parseQuery( $term ) { + private function parseQuery( $term ) { wfDebug( "parseQuery received: $term \n" ); # # No backslashes allowed @@ -123,7 +123,7 @@ class SearchPostgres extends SearchDatabase { * @param string $colname * @return string */ - function searchQuery( $term, $fulltext, $colname ) { + private function searchQuery( $term, $fulltext, $colname ) { # Get the SQL fragment for the given term $searchstring = $this->parseQuery( $term ); diff --git a/includes/search/SearchResultSet.php b/includes/search/SearchResultSet.php index f25c7283eb..e3eb4c250e 100644 --- a/includes/search/SearchResultSet.php +++ b/includes/search/SearchResultSet.php @@ -173,6 +173,7 @@ class SearchResultSet { * Fetches next search result, or false. * STUB * FIXME: refactor as iterator, so we could use nicer interfaces. + * @deprecated since 1.32; Use self::extractResults() * @return SearchResult|false */ function next() { @@ -181,6 +182,7 @@ class SearchResultSet { /** * Rewind result set back to beginning + * @deprecated since 1.32; Use self::extractResults() */ function rewind() { } diff --git a/includes/search/SearchSqlite.php b/includes/search/SearchSqlite.php index af29212ba1..1dc37d2560 100644 --- a/includes/search/SearchSqlite.php +++ b/includes/search/SearchSqlite.php @@ -42,7 +42,7 @@ class SearchSqlite extends SearchDatabase { * @param bool $fulltext * @return string */ - function parseQuery( $filteredText, $fulltext ) { + private function parseQuery( $filteredText, $fulltext ) { global $wgContLang; $lc = $this->legalSearchChars( self::CHARS_NO_SYNTAX ); // Minus syntax chars (" and *) $searchon = ''; @@ -122,7 +122,7 @@ class SearchSqlite extends SearchDatabase { return " $field MATCH $searchon "; } - function regexTerm( $string, $wildcard ) { + private function regexTerm( $string, $wildcard ) { global $wgContLang; $regex = preg_quote( $string, '/' ); @@ -156,7 +156,7 @@ class SearchSqlite extends SearchDatabase { * @param string $term Raw search term * @return SqlSearchResultSet */ - function searchText( $term ) { + protected function doSearchText( $term ) { return $this->searchInternal( $term, true ); } @@ -166,7 +166,7 @@ class SearchSqlite extends SearchDatabase { * @param string $term Raw search term * @return SqlSearchResultSet */ - function searchTitle( $term ) { + protected function doSearchTitle( $term ) { return $this->searchInternal( $term, false ); } @@ -195,7 +195,7 @@ class SearchSqlite extends SearchDatabase { * Return a partial WHERE clause to limit the search to the given namespaces * @return string */ - function queryNamespaces() { + private function queryNamespaces() { if ( is_null( $this->namespaces ) ) { return ''; # search all } @@ -212,7 +212,7 @@ class SearchSqlite extends SearchDatabase { * @param string $sql * @return string */ - function limitResult( $sql ) { + private function limitResult( $sql ) { return $this->db->limitResult( $sql, $this->limit, $this->offset ); } @@ -223,7 +223,7 @@ class SearchSqlite extends SearchDatabase { * @param bool $fulltext * @return string */ - function getQuery( $filteredTerm, $fulltext ) { + private function getQuery( $filteredTerm, $fulltext ) { return $this->limitResult( $this->queryMain( $filteredTerm, $fulltext ) . ' ' . $this->queryNamespaces() @@ -235,7 +235,7 @@ class SearchSqlite extends SearchDatabase { * @param bool $fulltext * @return string */ - function getIndexField( $fulltext ) { + private function getIndexField( $fulltext ) { return $fulltext ? 'si_text' : 'si_title'; } @@ -246,7 +246,7 @@ class SearchSqlite extends SearchDatabase { * @param bool $fulltext * @return string */ - function queryMain( $filteredTerm, $fulltext ) { + private function queryMain( $filteredTerm, $fulltext ) { $match = $this->parseQuery( $filteredTerm, $fulltext ); $page = $this->db->tableName( 'page' ); $searchindex = $this->db->tableName( 'searchindex' ); @@ -255,7 +255,7 @@ class SearchSqlite extends SearchDatabase { "WHERE page_id=$searchindex.rowid AND $match"; } - function getCountQuery( $filteredTerm, $fulltext ) { + private function getCountQuery( $filteredTerm, $fulltext ) { $match = $this->parseQuery( $filteredTerm, $fulltext ); $page = $this->db->tableName( 'page' ); $searchindex = $this->db->tableName( 'searchindex' ); diff --git a/includes/skins/Skin.php b/includes/skins/Skin.php index 340bc2f5bd..5dfa7e36c3 100644 --- a/includes/skins/Skin.php +++ b/includes/skins/Skin.php @@ -401,12 +401,14 @@ abstract class Skin extends ContextSource { /** * @param array $data + * @param string $nonce OutputPage::getCSPNonce() * @return string */ - static function makeVariablesScript( $data ) { + static function makeVariablesScript( $data, $nonce = null ) { if ( $data ) { return ResourceLoader::makeInlineScript( - ResourceLoader::makeConfigSetScript( $data ) + ResourceLoader::makeConfigSetScript( $data ), + $nonce ); } else { return ''; diff --git a/includes/skins/SkinTemplate.php b/includes/skins/SkinTemplate.php index 1d5d534ace..507688dfcc 100644 --- a/includes/skins/SkinTemplate.php +++ b/includes/skins/SkinTemplate.php @@ -465,7 +465,7 @@ class SkinTemplate extends Skin { $tpl->set( 'debug', '' ); $tpl->set( 'debughtml', $this->generateDebugHTML() ); - $tpl->set( 'reporttime', wfReportTime() ); + $tpl->set( 'reporttime', wfReportTime( $out->getCSPNonce() ) ); // Avoid PHP 7.1 warning of passing $this by reference $skinTemplate = $this; diff --git a/includes/specialpage/ChangesListSpecialPage.php b/includes/specialpage/ChangesListSpecialPage.php index ac13f113b2..9e61ef738b 100644 --- a/includes/specialpage/ChangesListSpecialPage.php +++ b/includes/specialpage/ChangesListSpecialPage.php @@ -785,7 +785,8 @@ abstract class ChangesListSpecialPage extends SpecialPage { $out->addHTML( ResourceLoader::makeInlineScript( - ResourceLoader::makeMessageSetScript( $messages ) + ResourceLoader::makeMessageSetScript( $messages ), + $out->getCSPNonce() ) ); diff --git a/includes/specials/SpecialAllPages.php b/includes/specials/SpecialAllPages.php index f9c917d35e..ef05dd15b6 100644 --- a/includes/specials/SpecialAllPages.php +++ b/includes/specials/SpecialAllPages.php @@ -126,7 +126,7 @@ class SpecialAllPages extends IncludableSpecialPage { 'id' => 'namespace', 'label-message' => 'namespace', 'all' => null, - 'value' => $namespace, + 'default' => $namespace, ], 'hideredirects' => [ 'type' => 'check', @@ -141,7 +141,9 @@ class SpecialAllPages extends IncludableSpecialPage { unset( $fields['hideredirects'] ); } - $form = HTMLForm::factory( 'table', $fields, $this->getContext() ); + $context = new DerivativeContext( $this->getContext() ); + $context->setTitle( $this->getPageTitle() ); // Remove subpage + $form = HTMLForm::factory( 'table', $fields, $context ); $form->setMethod( 'get' ) ->setWrapperLegendMsg( 'allpages' ) ->setSubmitTextMsg( 'allpagessubmit' ) diff --git a/includes/specials/SpecialApiSandbox.php b/includes/specials/SpecialApiSandbox.php index c000d546d1..034e569e6c 100644 --- a/includes/specials/SpecialApiSandbox.php +++ b/includes/specials/SpecialApiSandbox.php @@ -37,7 +37,7 @@ class SpecialApiSandbox extends SpecialPage { $out->addJsConfigVars( 'apihighlimits', $this->getUser()->isAllowed( 'apihighlimits' ) ); $out->addModuleStyles( [ - 'mediawiki.special.apisandbox.styles', + 'mediawiki.special', ] ); $out->addModules( [ 'mediawiki.special.apisandbox', diff --git a/includes/specials/SpecialBotPasswords.php b/includes/specials/SpecialBotPasswords.php index 7b2d1bcbfd..f03565adef 100644 --- a/includes/specials/SpecialBotPasswords.php +++ b/includes/specials/SpecialBotPasswords.php @@ -21,6 +21,8 @@ * @ingroup SpecialPage */ +use MediaWiki\Logger\LoggerFactory; + /** * Let users manage bot passwords * @@ -40,8 +42,12 @@ class SpecialBotPasswords extends FormSpecialPage { /** @var string New password set, for communication between onSubmit() and onSuccess() */ private $password = null; + /** @var Psr\Log\LoggerInterface */ + private $logger = null; + public function __construct() { parent::__construct( 'BotPasswords', 'editmyprivateinfo' ); + $this->logger = LoggerFactory::getInstance( 'authentication' ); } /** @@ -277,6 +283,16 @@ class SpecialBotPasswords extends FormSpecialPage { $bp = BotPassword::newFromCentralId( $this->userId, $this->par ); if ( $bp ) { $bp->delete(); + $this->logger->info( + "Bot password {op} for {user}@{app_id}", + [ + 'app_id' => $this->par, + 'user' => $this->getUser()->getName(), + 'centralId' => $this->userId, + 'op' => 'delete', + 'client_ip' => $this->getRequest()->getIP() + ] + ); } return Status::newGood(); @@ -309,6 +325,18 @@ class SpecialBotPasswords extends FormSpecialPage { } if ( $bp->save( $this->operation, $password ) ) { + $this->logger->info( + "Bot password {op} for {user}@{app_id}", + [ + 'op' => $this->operation, + 'user' => $this->getUser()->getName(), + 'app_id' => $this->par, + 'centralId' => $this->userId, + 'restrictions' => $data['restrictions'], + 'grants' => $bp->getGrants(), + 'client_ip' => $this->getRequest()->getIP() + ] + ); return Status::newGood(); } else { // Messages: botpasswords-insert-failed, botpasswords-update-failed diff --git a/includes/specials/SpecialComparePages.php b/includes/specials/SpecialComparePages.php index 35cc6b84f2..28f04faa29 100644 --- a/includes/specials/SpecialComparePages.php +++ b/includes/specials/SpecialComparePages.php @@ -49,7 +49,7 @@ class SpecialComparePages extends SpecialPage { public function execute( $par ) { $this->setHeaders(); $this->outputHeader(); - $this->getOutput()->addModuleStyles( 'mediawiki.special.comparepages.styles' ); + $this->getOutput()->addModuleStyles( 'mediawiki.special' ); $form = HTMLForm::factory( 'ooui', [ 'Page1' => [ diff --git a/includes/specials/SpecialEditTags.php b/includes/specials/SpecialEditTags.php index 60d5fd7c8c..3db7edaf8e 100644 --- a/includes/specials/SpecialEditTags.php +++ b/includes/specials/SpecialEditTags.php @@ -76,7 +76,7 @@ class SpecialEditTags extends UnlistedSpecialPage { $this->outputHeader(); $this->getOutput()->addModules( [ 'mediawiki.special.edittags', - 'mediawiki.special.edittags.styles' ] ); + 'mediawiki.special' ] ); $this->submitClicked = $request->wasPosted() && $request->getBool( 'wpSubmit' ); diff --git a/includes/specials/SpecialMovepage.php b/includes/specials/SpecialMovepage.php index d30ff4329d..0069ea1bbe 100644 --- a/includes/specials/SpecialMovepage.php +++ b/includes/specials/SpecialMovepage.php @@ -143,8 +143,8 @@ class MovePageForm extends UnlistedSpecialPage { $out = $this->getOutput(); $out->setPageTitle( $this->msg( 'move-page', $this->oldTitle->getPrefixedText() ) ); + $out->addModuleStyles( 'mediawiki.special' ); $out->addModules( 'mediawiki.special.movePage' ); - $out->addModuleStyles( 'mediawiki.special.movePage.styles' ); $this->addHelpLink( 'Help:Moving a page' ); $out->addWikiMsg( $this->getConfig()->get( 'FixDoubleRedirects' ) ? diff --git a/includes/specials/SpecialPagesWithProp.php b/includes/specials/SpecialPagesWithProp.php index 34fcc78c7e..46ad31c4a8 100644 --- a/includes/specials/SpecialPagesWithProp.php +++ b/includes/specials/SpecialPagesWithProp.php @@ -60,7 +60,7 @@ class SpecialPagesWithProp extends QueryPage { public function execute( $par ) { $this->setHeaders(); $this->outputHeader(); - $this->getOutput()->addModuleStyles( 'mediawiki.special.pagesWithProp' ); + $this->getOutput()->addModuleStyles( 'mediawiki.special' ); $request = $this->getRequest(); $propname = $request->getVal( 'propname', $par ); diff --git a/includes/specials/SpecialPreferences.php b/includes/specials/SpecialPreferences.php index f67fe9f757..1cfcffa85d 100644 --- a/includes/specials/SpecialPreferences.php +++ b/includes/specials/SpecialPreferences.php @@ -36,8 +36,6 @@ class SpecialPreferences extends SpecialPage { function __construct() { parent::__construct( 'Preferences' ); - - $this->oouiEnabled = self::isOouiEnabled( $this->getContext() ); } /** @@ -56,6 +54,8 @@ class SpecialPreferences extends SpecialPage { } public function execute( $par ) { + $this->oouiEnabled = static::isOouiEnabled( $this->getContext() ); + $this->setHeaders(); $this->outputHeader(); $out = $this->getOutput(); diff --git a/includes/specials/SpecialPrefixindex.php b/includes/specials/SpecialPrefixindex.php index fac71b2d78..3ca3a85307 100644 --- a/includes/specials/SpecialPrefixindex.php +++ b/includes/specials/SpecialPrefixindex.php @@ -102,8 +102,10 @@ class SpecialPrefixindex extends SpecialAllPages { 'prefix' => [ 'label-message' => 'allpagesprefix', 'name' => 'prefix', + 'id' => 'nsfrom', 'type' => 'text', 'size' => '30', + 'default' => str_replace( '_', ' ', $from ), ], 'namespace' => [ 'type' => 'namespaceselect', @@ -111,7 +113,7 @@ class SpecialPrefixindex extends SpecialAllPages { 'id' => 'namespace', 'label-message' => 'namespace', 'all' => null, - 'value' => $namespace, + 'default' => $namespace, ], 'hidedirects' => [ 'class' => 'HTMLCheckField', @@ -124,7 +126,9 @@ class SpecialPrefixindex extends SpecialAllPages { 'label-message' => 'prefixindex-strip', ], ]; - $htmlForm = new HTMLForm( $formDescriptor, $this->getContext() ); + $context = new DerivativeContext( $this->getContext() ); + $context->setTitle( $this->getPageTitle() ); // Remove subpage + $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $context ); $htmlForm ->setMethod( 'get' ) ->setWrapperLegendMsg( 'prefixindex' ) diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php index f7cb654527..2eeafe6900 100644 --- a/includes/specials/SpecialUpload.php +++ b/includes/specials/SpecialUpload.php @@ -387,7 +387,7 @@ class SpecialUpload extends SpecialPage { } // Add styles for the warning, reused from the live preview - $this->getOutput()->addModuleStyles( 'mediawiki.special.upload.styles' ); + $this->getOutput()->addModuleStyles( 'mediawiki.special' ); $linkRenderer = $this->getLinkRenderer(); $warningHtml = '

' . $this->msg( 'uploadwarning' )->escaped() . "

\n" diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php index dda1dac3af..ea73347c1f 100644 --- a/includes/specials/SpecialWatchlist.php +++ b/includes/specials/SpecialWatchlist.php @@ -60,11 +60,10 @@ class SpecialWatchlist extends ChangesListSpecialPage { $output = $this->getOutput(); $request = $this->getRequest(); $this->addHelpLink( 'Help:Watching pages' ); + $output->addModuleStyles( [ 'mediawiki.special' ] ); $output->addModules( [ - 'mediawiki.special.changeslist.visitedstatus', 'mediawiki.special.watchlist', ] ); - $output->addModuleStyles( [ 'mediawiki.special.watchlist.styles' ] ); $mode = SpecialEditWatchlist::getMode( $request, $subpage ); if ( $mode !== false ) { diff --git a/includes/specials/forms/UploadForm.php b/includes/specials/forms/UploadForm.php index e561fe5882..8ab6f29f09 100644 --- a/includes/specials/forms/UploadForm.php +++ b/includes/specials/forms/UploadForm.php @@ -79,7 +79,7 @@ class UploadForm extends HTMLForm { # Add a link to edit MediaWiki:Licenses if ( $this->getUser()->isAllowed( 'editinterface' ) ) { - $this->getOutput()->addModuleStyles( 'mediawiki.special.upload.styles' ); + $this->getOutput()->addModuleStyles( 'mediawiki.special' ); $licensesLink = $linkRenderer->makeKnownLink( $this->msg( 'licenses' )->inContentLanguage()->getTitle(), $this->msg( 'licenses-edit' )->text(), diff --git a/includes/user/User.php b/includes/user/User.php index e235c18928..7189bea120 100644 --- a/includes/user/User.php +++ b/includes/user/User.php @@ -1813,14 +1813,14 @@ class User implements IDBAccessObject, UserIdentity { if ( self::isLocallyBlockedProxy( $ip ) ) { $block = new Block( [ 'byText' => wfMessage( 'proxyblocker' )->text(), - 'reason' => wfMessage( 'proxyblockreason' )->text(), + 'reason' => wfMessage( 'proxyblockreason' )->plain(), 'address' => $ip, 'systemBlock' => 'proxy', ] ); } elseif ( $this->isAnon() && $this->isDnsBlacklisted( $ip ) ) { $block = new Block( [ 'byText' => wfMessage( 'sorbs' )->text(), - 'reason' => wfMessage( 'sorbsreason' )->text(), + 'reason' => wfMessage( 'sorbsreason' )->plain(), 'address' => $ip, 'systemBlock' => 'dnsbl', ] ); @@ -1841,7 +1841,7 @@ class User implements IDBAccessObject, UserIdentity { if ( $block instanceof Block ) { # 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(); + $block->mReason = wfMessage( 'xffblockreason', $block->mReason )->plain(); } } @@ -1853,7 +1853,7 @@ class User implements IDBAccessObject, UserIdentity { $block = new Block( [ 'address' => $ip, 'byText' => 'MediaWiki default', - 'reason' => wfMessage( 'softblockrangesreason', $ip )->text(), + 'reason' => wfMessage( 'softblockrangesreason', $ip )->plain(), 'anonOnly' => true, 'systemBlock' => 'wgSoftBlockRanges', ] ); diff --git a/includes/utils/ExecutableFinder.php b/includes/utils/ExecutableFinder.php index 9679bfeeec..78b3f8e29b 100644 --- a/includes/utils/ExecutableFinder.php +++ b/includes/utils/ExecutableFinder.php @@ -94,6 +94,11 @@ class ExecutableFinder { * @return bool|string */ public static function findInDefaultPaths( $names, $versionInfo = false ) { + if ( Shell::isDisabled() ) { + // If we can't shell out, there's no point looking for executables + return false; + } + $paths = self::getPossibleBinPaths(); foreach ( (array)$names as $name ) { foreach ( $paths as $path ) { diff --git a/languages/i18n/ar.json b/languages/i18n/ar.json index bb4c25835e..6dc121f41e 100644 --- a/languages/i18n/ar.json +++ b/languages/i18n/ar.json @@ -4081,7 +4081,7 @@ "authmanager-authn-not-in-progress": "عملية التحقق ليست جارية أو بينات الجلسة تم فقدها. من فضلك ابدأ مرة ثانية من البداية.", "authmanager-authn-no-primary": "الاعتماد الموفر لم يمكن التحقق منه.", "authmanager-authn-no-local-user": "الاعتماد الموفر غير مرتبط بأي مستخدم على هذه الويكي.", - "authmanager-authn-no-local-user-link": "الاعتمادات الموفرة صحيحة لكن غير مرتبطة بأي مستخدم على هذه الويكي. سجل الدخول باستخدام طريقة أخرى، أو أنشيء مستخدما جديدا، وستمتلك الاختيار لوصل اعتماداتك السابقة لذلك الحساب.", + "authmanager-authn-no-local-user-link": "الاعتمادات الموفرة صحيحة لكن غير مرتبطة بأي مستخدم على هذه الويكي. سجل الدخول باستخدام طريقة أخرى، أو أنشئ حسابًا جديدًا، وستمتلك الاختيار لوصل اعتماداتك السابقة لذلك الحساب.", "authmanager-authn-autocreate-failed": "الإنشاء التلقائي لحساب محلي فشل: $1", "authmanager-change-not-supported": "الاعتمادات الموفرة لم يمكن تغييرها، حيث أن لا شيء سيستخدمها.", "authmanager-create-disabled": "إنشاء الحسابات معطل.", diff --git a/languages/i18n/as.json b/languages/i18n/as.json index 81b6d0f239..e118a0ceec 100644 --- a/languages/i18n/as.json +++ b/languages/i18n/as.json @@ -25,7 +25,7 @@ ] }, "tog-underline": "সংযোগসমূহ অধোৰেখিত কৰক:", - "tog-hideminor": "সাম্প্ৰতিক সাল-সলনিত অগুৰুত্বপূৰ্ণ সম্পাদনা নেদেখুৱাব", + "tog-hideminor": "শেহতীয়া সাল-সলনিত অগুৰুত্বপূৰ্ণ সম্পাদনা নেদেখুৱাব", "tog-hidepatrolled": "সাম্প্ৰতিক সাল-সলনিত তহলদাৰী সম্পাদনা নেদেখুৱাব", "tog-newpageshidepatrolled": "নতুন পৃষ্ঠা তালিকাত তহলদাৰী পৃষ্ঠাসমূহ নেদেখুৱাব", "tog-hidecategorization": "পৃষ্ঠাবোৰৰ শ্ৰেণীকৰণ লুকুৱাওক", @@ -1151,6 +1151,7 @@ "recentchanges-legend-plusminus": "(''±১২৩'')", "rcfilters-legend-heading": "সংক্ষিপ্ত ৰূপৰ তালিকা:", "rcfilters-other-review-tools": "আন পুনৰীক্ষণ সঁজুলি", + "rcfilters-filter-humans-label": "মানুহ (ব'ট নহয়)", "rcnotefrom": "$2ৰ পৰা হোৱা পৰিৱৰ্তনসমূহ (সৰ্বোচ্চ $1টা দেখুৱা হৈছে)।", "rclistfrom": "$3 $2ৰ পৰা নতুন সালসলনি দেখুৱাওক", "rcshowhideminor": "$1 -সংখ্যক নগণ্য সম্পাদনা", diff --git a/languages/i18n/ast.json b/languages/i18n/ast.json index b688b16228..911a6272b1 100644 --- a/languages/i18n/ast.json +++ b/languages/i18n/ast.json @@ -514,6 +514,7 @@ "botpasswords-existing": "Contraseñes de bots esistentes", "botpasswords-createnew": "Crear una contraseña nueva de bot", "botpasswords-editexisting": "Editar una contraseña de bot esistiente", + "botpasswords-label-needsreset": "(la contraseña tien de reaniciase)", "botpasswords-label-appid": "Nome del bot:", "botpasswords-label-create": "Crear", "botpasswords-label-update": "Anovar", @@ -537,6 +538,7 @@ "botpasswords-restriction-failed": "Hai torgues de contraseña de bot que torgaron esti aniciu de sesión.", "botpasswords-invalid-name": "El nome d'usuariu especificáu nun contien el separador de contraseña de bot («$1»).", "botpasswords-not-exist": "L'usuariu «$1» nun tien una contraseña de bot llamada «$2».", + "botpasswords-needs-reset": "Tien de reniciase la contraseña del robot «$2», propiedá {{GENDER:$1|del usuariu|de la usuaria}} «$1».", "resetpass_forbidden": "Nun puen camudase les contraseñes", "resetpass_forbidden-reason": "Les contraseñes nun pueden camudase: $1", "resetpass-no-info": "Tienes d'aniciar sesión pa entrar direutamente a esta páxina.", @@ -632,8 +634,8 @@ "subject-preview": "Vista previa del asuntu:", "previewerrortext": "Hebo un error al intentar entever los cambios.", "blockedtitle": "L'usuariu ta bloquiáu", - "blockedtext": "'''El to nome d'usuariu o direición IP ta bloquiáu.'''\n\nEl bloquéu fexolu $1.\nEl motivu conseñáu ye ''$2''.\n\n* Principiu del bloquéu: $8\n* Caducidá del bloquéu: $6\n* Usuariu a bloquiar: $7\n\nPues ponete'n contautu con $1 o con otru [[{{MediaWiki:Grouppage-sysop}}|alministrador]] p'aldericar sobre'l bloquéu.\nNun pues usar la función 'manda-y un corréu electrónicu a esti usuariu' a nun ser que tea especificada una direición de\ncorréu electrónicu válida nes tos [[Special:Preferences|preferencies de cuenta]] y que nun tengas torgao usala.\nLa to direición IP actual ye $3, y la ID del bloquéu ye #$5.\nPor favor, incluye tolos detalles anteriores nes consultes que faigas.", - "autoblockedtext": "La to direición IP bloquióse automáticamente porque usóla otru usuariu que foi bloquiáu por $1.\nEl motivu conseñáu ye:\n\n:''$2''\n\n* Principiu del bloquéu: $8\n* Caducidá del bloquéu: $6\n* Usuariu a bloquiar: $7\n\nPues ponete'n contautu con $1 o con otru de los [[{{MediaWiki:Grouppage-sysop}}|alministradores]] p'aldericar sobre'l bloquéu.\n\nTen en cuenta que nun pues usar la función «manda-y un corréu electrónicu a esti usuariu» a nun ser que tengas rexistrada una direición de corréu electrónicu válida nes [[Special:Preferences|preferencies d'usuariu]] y que nun tengas torgao usala.\n\nLa to direición IP actual ye $3, y la ID del bloquéu ye #$5.\nPor favor, incluye tolos detalles anteriores nes consultes que faigas.", + "blockedtext": "El to nome d'usuariu o direición IP ta bloquiáu.\n\nEl bloquéu fexolu $1.\nEl motivu conseñáu ye $2.\n\n* Principiu del bloquéu: $8\n* Caducidá del bloquéu: $6\n* Usuariu a bloquiar: $7\n\nPuedes comunicate con $1 o con otru [[{{MediaWiki:Grouppage-sysop}}|alministrador]] p'aldericar sobre'l bloquéu.\nNun puedes usar la función «{{int:emailuser}}» a nun ser que tea especificada una direición de corréu electrónicu válida nes tos [[Special:Preferences|preferencies de cuenta]] y que nun tengas torgao usala.\nLa to direición IP actual ye $3, y la ID del bloquéu ye #$5.\nPor favor, incluye tolos detalles anteriores nes consultes que faigas.", + "autoblockedtext": "La to direición IP bloquióse automáticamente porque usóla otru usuariu que foi bloquiáu por $1.\nEl motivu conseñáu ye:\n\n:$2\n\n* Principiu del bloquéu: $8\n* Caducidá del bloquéu: $6\n* Usuariu a bloquiar: $7\n\nPues ponete'n contautu con $1 o con otru de los [[{{MediaWiki:Grouppage-sysop}}|alministradores]] p'aldericar sobre'l bloquéu.\n\nTen en cuenta que nun pues usar la función «{{int:emailuser}}» a nun ser que tengas rexistrada una direición de corréu electrónicu válida nes [[Special:Preferences|preferencies d'usuariu]] y que nun tengas torgao usala.\n\nLa to direición IP actual ye $3, y la ID del bloquéu ye #$5.\nPor favor, incluye tolos detalles anteriores nes consultes que faigas.", "systemblockedtext": "El to nome d'usuariu o dirección IP bloquióse automáticamente pol software MediaWiki.\nEl motivu dau ye:\n\n:$2\n\n* Entamu del bloquéu: $8\n* Caducidá de bloquéu: $6\n* Destinatariu del bloquéu: $7\n\nLa to dirección IP actual ye $3.\nPor favor, incluye tolos anteriores en cualquier consulta que faigas.", "blockednoreason": "nun se dio nengún motivu", "whitelistedittext": "Tienes d'$1 pa editar páxines.", @@ -1485,7 +1487,7 @@ "recentchangeslinked-feed": "Cambios rellacionaos", "recentchangeslinked-toolbox": "Cambios rellacionaos", "recentchangeslinked-title": "Cambios rellacionaos con \"$1\"", - "recentchangeslinked-summary": "Esscribe'l nome d'una páxina pa ver los cambios nes páxines enllazaes a o dende esa páxina. (Pa ver los miembros d'una categoría, escribe Categoría:Nome de la categoría). Los cambios nes páxines de [[Special:Watchlist|la to llista de siguimientu]] tán en negrina.", + "recentchangeslinked-summary": "Esscribe'l nome d'una páxina pa ver los cambios nes páxines enllazaes a o dende esa páxina. (Pa ver los miembros d'una categoría, escribe {{ns:category}}:Nome de la categoría). Los cambios nes páxines de [[Special:Watchlist|la to llista de siguimientu]] tán en negrina.", "recentchangeslinked-page": "Nome de la páxina:", "recentchangeslinked-to": "Amosar los cambios de les páxines qu'enllacen en cuenta de los de la páxina dada", "recentchanges-page-added-to-category": "[[:$1]] amestóse a la categoría", @@ -3998,5 +4000,6 @@ "pagedata-title": "Datos de la páxina", "pagedata-text": "Esta páxina ufre una interfaz de datos pa les páxines. Escribe'l títulu de la páxina na URL, usando la sintaxis de subpáxina.\n* Aplícase la negociación de conteníu en base a la testera Accept del to cliente. Esto significa que los datos de la páxina van dase nel formatu que prefiera'l to cliente.", "pagedata-not-acceptable": "Nun s'alcontró nengún formatu que coincidiera. Tipos MIME soportaos: $1", - "pagedata-bad-title": "Títulu inválidu: $1." + "pagedata-bad-title": "Títulu inválidu: $1.", + "unregistered-user-config": "Por motivos de seguridá, les subpáxines d'usuariu JavaScript, CSS y JSON nun pueden cargase pa usuarios ensin rexistrar." } diff --git a/languages/i18n/azb.json b/languages/i18n/azb.json index f7e226557f..d6fb71661b 100644 --- a/languages/i18n/azb.json +++ b/languages/i18n/azb.json @@ -1220,7 +1220,7 @@ "recentchangeslinked-feed": "باغلی دَییشیکلیک‌لر", "recentchangeslinked-toolbox": "باغلی دَییشیکلیک‌لر", "recentchangeslinked-title": "''$1'' ایله باغلی دییشیکلر", - "recentchangeslinked-summary": "آشاغیداکی سیياهی، قئيد اوْلونان صحیفه‌‌يه (و يا قئيد اوْلونان کاتئقوْرياداکی صحیفه‌‌لره) داخیلی کئچید وئرن صحیفه‌‌لرده ائدیلمیش سوْن ديَیشیکلیکلرین سیياهیسیدیر. \n[[Special:Watchlist|ایزله‌مه سیياهینیزداکی]] صحیفه‌‌لر '''قالین''' شریفتله گؤستریلمیشدیر.", + "recentchangeslinked-summary": "آشاغیداکی ژورنال، قئيد اوْلونان صفحه‌‌يه (و يا قئيد اوْلونان بؤلمه‌ده‌کی صفحه‌‌لره) داخیلی کئچید وئرن صفحه‌‌لرده ائدیلمیش سوْن ديَیشیکلیکلرین لیستیدیر. \n[[Special:Watchlist|ایزله‌مه لیستینیزده]]‌کی صفحه‌‌لر '''قالین''' شریفتله گؤستریلمیشدیر.", "recentchangeslinked-page": "صفحه آدی:", "recentchangeslinked-to": "قئيد اوْلونان صحیفه‌‌ده‌کی دئيیل، اوْنا داخیلی کئچید وئرن صحیفه‌‌لرده‌کی ديَیشیکلیکلری گؤستر", "upload": "فایل یوکله‌", diff --git a/languages/i18n/be-tarask.json b/languages/i18n/be-tarask.json index df3cd07674..d6730e8f46 100644 --- a/languages/i18n/be-tarask.json +++ b/languages/i18n/be-tarask.json @@ -540,6 +540,7 @@ "botpasswords-restriction-failed": "Уваход ня выкананы праз абмежаваньні на пароль робата", "botpasswords-invalid-name": "Пададзенае імя ўдзельніка ня ўтрымлівае падзяляльнік для паролю робата («$1»).", "botpasswords-not-exist": "Удзельнік «$1» ня мае паролю для робата з назвай «$2».", + "botpasswords-needs-reset": "Пароль для робата зь імем «$2» {{GENDER:$1|удзельніка|удзельніцы}} «$1» мусіць быць скінуты.", "resetpass_forbidden": "Пароль ня можа быць зьменены", "resetpass_forbidden-reason": "Паролі ня могуць быць зьмененыя: $1", "resetpass-no-info": "Для непасрэднага доступу да гэтай старонкі Вам неабходна ўвайсьці ў сыстэму.", @@ -635,8 +636,8 @@ "subject-preview": "Папярэдні прагляд загалоўку:", "previewerrortext": "Адбылася памылка пры спробе папярэдняга прагляду вашых зьменаў.", "blockedtitle": "Удзельнік заблякаваны", - "blockedtext": "Ваш рахунак удзельніка ці IP-адрас быў заблякаваны.\n\nБлякаваньне выканаў $1.\nПрычына гэтага: $2.\n\n* Пачатак блякаваньня: $8\n* Сканчэньне блякаваньня: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне. Заўважце, што Вы ня зможаце ўжыць магчымасьць «даслаць ліст па электроннай пошце», пакуль не пазначыце сапраўдны адрас электроннай пошты ў Вашых [[Special:Preferences|наладах]], і калі гэта Вам не было забаронена.\nВаш IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што Вы будзеце рабіць.", - "autoblockedtext": "Ваш IP-адрас быў аўтаматычна заблякаваны, таму што ён ужываўся іншым удзельнікам, які быў заблякаваны $1.\nПрычына гэтага:\n\n:$2\n\n* Блякаваньне пачалося: $8\n* Блякаваньне скончыцца: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці з адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне.\n\nЗаўважце, што Вы ня зможаце ўжываць магчымасьць «даслаць ліст праз электронную пошту», пакуль ня будзе пазначаны дзейны адрас электроннай пошты ў Вашых [[Special:Preferences|наладах удзельніка]], і калі гэта Вам не было забаронена.\n\nВаш цяперашні IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што Вы будзеце рабіць.", + "blockedtext": "Ваш рахунак удзельніка ці IP-адрас быў заблякаваны.\n\nБлякаваньне выканаў $1.\nПрычына гэтага: $2.\n\n* Пачатак блякаваньня: $8\n* Сканчэньне блякаваньня: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне. Заўважце, што вы ня зможаце ўжыць магчымасьць «{{int:emailuser}}», пакуль не пазначыце сапраўдны адрас электроннай пошты ў вашых [[Special:Preferences|наладах]], і калі гэта вам не было забаронена.\nВаш IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што вы будзеце рабіць.", + "autoblockedtext": "Ваш IP-адрас быў аўтаматычна заблякаваны, таму што ён ужываўся іншым удзельнікам, які быў заблякаваны $1.\nПрычына гэтага:\n\n:$2\n\n* Блякаваньне пачалося: $8\n* Блякаваньне скончыцца: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці з адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне.\n\nЗаўважце, што вы ня зможаце ўжываць магчымасьць «{{int:emailuser}}», пакуль ня будзе пазначаны дзейны адрас электроннай пошты ў вашых [[Special:Preferences|наладах удзельніка]], і калі гэта вам не было забаронена.\n\nВаш цяперашні IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што вы будзеце рабіць.", "systemblockedtext": "Вашае імя ўдзельніка ці IP-адрас былі аўтаматычна заблякаваныя MediaWiki.\nЗ наступнай прычыны:\n\n:$2\n\n* Пачатак блякаваньня: $8\n* Сканчэньне блякаваньня: $6\n* Мэта блякаваньня: $7\n\nВаш цяперашні IP-адрас — $3.\nКалі ласка, уключайце ўсе пададзеныя вышэй дэталі ва ўсе запыты, што вы робіце.", "blockednoreason": "прычына не пазначана", "whitelistedittext": "Вам трэба $1, каб рэдагаваць старонкі.", @@ -1497,21 +1498,21 @@ "upload": "Загрузіць файл", "uploadbtn": "Загрузіць файл", "reuploaddesc": "Скасаваць загрузку і вярнуцца да формы загрузкі", - "upload-tryagain": "Даслаць зьмененае апісаньне файла", + "upload-tryagain": "Даслаць зьмененае апісаньне файлу", "upload-tryagain-nostash": "Даслаць паўторна загружаны файл і зьмененае апісаньне", "uploadnologin": "Вы не ўвайшлі ў сыстэму", "uploadnologintext": "Вам трэба $1, каб загружаць файлы.", "upload_directory_missing": "Загрузачная дырэкторыя ($1) адсутнічае і ня можа быць створаная сэрвэрам.", "upload_directory_read_only": "Сэрвэр ня мае правоў на запіс у дырэкторыю загружаных файлаў ($1).", "uploaderror": "Памылка загрузкі", - "upload-recreate-warning": "'''Увага: файл з такой назвай быў выдалены альбо перанесены.'''\n\nЖурнал выдаленьняў і пераносаў гэтай старонкі для зручнасьці пададзены тут:", + "upload-recreate-warning": "Увага: файл з такой назвай быў выдалены альбо перанесены.\n\nЖурнал выдаленьняў і пераносаў гэтай старонкі для зручнасьці пададзены тут:", "uploadtext": "Ужывайце форму ніжэй для загрузкі файлаў.\nКаб паглядзець ці адшукаць раней загружаныя файлы, глядзіце [[Special:FileList|сьпіс загружаных файлаў]], загрузкі таксама запісваюцца ў [[Special:Log/upload|журнал загрузак]], а выдаленьні — у [[Special:Log/delete|журнал выдаленьняў]].\n\nКаб улучыць файл у старонку, ужывайце адзін з наступных варыянтаў:\n* '''[[{{ns:file}}:File.jpg]]''' для поўнай вэрсіі файла\n* '''[[{{ns:file}}:File.png|200px|thumb|left|Подпіс да выявы]]''' для выявы шырынёй 200 піксэляў у рамцы і тэкстам «Подпіс да выявы» ў якасьці подпісу\n* '''[[{{ns:media}}:File.ogg]]''' для простай спасылкі на файл безь яго адлюстраваньня.", "upload-permitted": "{{PLURAL:$2|Дазволены тып|Дазволеныя тыпы}} файлаў: $1.", "upload-preferred": "{{PLURAL:$2|Пажаданы тып|Пажаданыя тыпы}} файлаў: $1.", "upload-prohibited": "{{PLURAL:$2|Забаронены тып|Забароненыя тыпы}} файлаў: $1.", "uploadlogpage": "Журнал загрузак", - "uploadlogpagetext": "Сьпіс апошніх загружаных файлаў.", - "filename": "Назва файла", + "uploadlogpagetext": "Ніжэй знаходзіцца сьпіс апошніх загружаных файлаў.\nГлядзіце [[Special:NewFiles|галерэю новых файлаў]] для больш візуальнага агляду.", + "filename": "Назва файлу", "filedesc": "Апісаньне", "fileuploadsummary": "Апісаньне:", "filereuploadsummary": "Зьмены ў файле:", @@ -1965,6 +1966,7 @@ "apisandbox-dynamic-parameters-add-label": "Дадаць парамэтар:", "apisandbox-dynamic-parameters-add-placeholder": "Назва парамэтру", "apisandbox-dynamic-error-exists": "Парамэтар з назвай «$1» ужо існуе.", + "apisandbox-templated-parameter-reason": "Гэты [[Special:ApiHelp/main#main/templatedparams|шаблённы парамэтар]] прапануецца паводле {{PLURAL:$1|1=значэньня|значэньняў}} $2.", "apisandbox-deprecated-parameters": "Састарэлыя парамэтры", "apisandbox-fetch-token": "Аўтазапаўненьне токену", "apisandbox-add-multi": "Дадаць", @@ -4005,5 +4007,6 @@ "pagedata-title": "Зьвесткі старонкі", "pagedata-text": "Гэтая старонка забясьпечвае інтэрфэйс зьвестак для старонак. Калі ласка, увядзіце назву старонкі ў URL-адрас з дапамогай сынтаксысу падстаронак.\n* Узгадненьне зьместу засноўваецца на загалоўку Accept вашага кліенту. Гэта значыць, што зьвесткі старонкі будуць пададзеныя ў фармаце, найлепшым для вашага кліенту.", "pagedata-not-acceptable": "Ня знойдзены адпаведны фармат. Падтрымліваюцца MIME-тыпы: $1", - "pagedata-bad-title": "Няслушная назва: $1." + "pagedata-bad-title": "Няслушная назва: $1.", + "unregistered-user-config": "З прычынаў бясьпекі JavaScript, CSS і JSON-падстаронкі ўдзельніка ня могуць быць загружаныя для незарэгістраваных удзельнікаў." } diff --git a/languages/i18n/be.json b/languages/i18n/be.json index 0333b61464..c7d9bf62e0 100644 --- a/languages/i18n/be.json +++ b/languages/i18n/be.json @@ -1023,7 +1023,7 @@ "recentchangesdays-max": "(найбольш $1 {{PLURAL:$1|дзень|дзён}})", "recentchangescount": "Перадвызначаная колькасць правак для паказу:", "prefs-help-recentchangescount": "Максімальная колькасць: 1000", - "prefs-help-watchlist-token2": "Гэта сакрэтны ключ да сеціўнай стужкі з Вашага спіса назірання.\nКожны, хто ведае гэты ключ, будзе мець магчымасць чытаць Ваш спіс назірання, таму не дзяліцеся ім.\nКалі трэба, можна [[Special:ResetTokens|скінуць яго]].", + "prefs-help-watchlist-token2": "Гэта сакрэтны ключ да сеціўнай стужкі з Вашага спісу назірання.\nКожны, хто ведае гэты ключ, будзе мець магчымасць чытаць Ваш спіс назірання, таму не дзяліцеся ім.\nКалі трэба, можна [[Special:ResetTokens|скінуць яго]].", "savedprefs": "Настройкі замацаваныя.", "savedrights": "Групы {{GENDER:$1|ўдзельніка|ўдзельніцы}} $1 захаваныя.", "timezonelegend": "Часавы пояс:", @@ -1576,7 +1576,7 @@ "uploaded-event-handler-on-svg": "Устаноўка атрыбутаў апрацоўшчыка падзей $1=\"$2\" у SVG файле не дазваляецца.", "uploaded-href-attribute-svg": "у SVG файлах атрыбутам href дазволены толькі мэты віду http:// або https://, знойдзена <$1 $2=\"$3\">.", "uploaded-href-unsafe-target-svg": "У ўкладзеным SVG файле знойдзена спасылка на небяспечныя звесткі: URI мэты <$1 $2=\"$3\">.", - "uploaded-animate-svg": "У ўкладзеным SVG файле знойдзены тэг \"animate\", здольны змяніць спасылку з дапамогай атрыбута \"from\" <$1 $2=\"$3\">.", + "uploaded-animate-svg": "Ва ўкладзеным SVG файле знойдзены тэг \"animate\", здольны змяніць спасылку з дапамогай атрыбута \"from\" <$1 $2=\"$3\">.", "uploaded-setting-event-handler-svg": "Устаноўка атрыбутаў апрацоўкі падзей заблакавана, у ўкладзеным SVG-файле знойдзены код <$1 $2=\"$3\">.", "uploaded-setting-href-svg": "Выкарыстанне тэга \"set\" для дадання атрыбута \"href\" у бацькоўскі элемент заблакавана.", "uploaded-wrong-setting-svg": "Ужыванне тэга \"set\" для задання ў якасці мэты аддаленага адраса/звестак/сцэнарыя для любога атрыбута заблакавана. У ўкладзеным SVG-файле знойдзены <set to=\"$1\">.", @@ -2663,7 +2663,7 @@ "tooltip-ca-undelete": "Аднавіць праўкі, зробленыя на гэтай старонцы перад тым, як яна была сцёрта", "tooltip-ca-move": "Перанесці гэтую старонку пад іншую назву", "tooltip-ca-watch": "Дадаць гэтую старонку да свайго спісу назіраных старонак", - "tooltip-ca-unwatch": "Выняць гэту старонку з вашага спіса назірання", + "tooltip-ca-unwatch": "Выняць гэтую старонку з Вашага спісу назірання", "tooltip-search": "Знайсці ў {{SITENAME}}", "tooltip-search-go": "Перайсці да старонкі з дакладна такой назвай, калі такая наогул існуе", "tooltip-search-fulltext": "Знайсці гэты тэкст у тэкстах старонак", @@ -3249,7 +3249,7 @@ "confirm-watch-button": "ОК", "confirm-watch-top": "Дабавіць старонку ў спіс назірання", "confirm-unwatch-button": "ОК", - "confirm-unwatch-top": "Выняць гэту старонку з вашага спіса назірання?", + "confirm-unwatch-top": "Выняць гэту старонку з Вашага спісу назірання?", "confirm-rollback-button": "Добра", "confirm-rollback-top": "Адкаціць праўкі гэтай старонкі?", "quotation-marks": "«$1»", @@ -3274,6 +3274,7 @@ "autosumm-replace": "Замена старонкі на '$1'", "autoredircomment": "Перасылае да [[$1]]", "autosumm-removed-redirect": "Выдаленае перенаправление на [[$1]]", + "autosumm-changed-redirect-target": "Мэта перасылкі зменена з [[$1]] на [[$2]]", "autosumm-new": "Новая старонка: '$1'", "autosumm-newblank": "Створана пустая старонка", "size-bytes": "$1 {{PLURAL:$1|байт|байты|байтаў}}", @@ -3283,7 +3284,7 @@ "watchlistedit-normal-legend": "Выдаленне складнікаў са спісу назірання", "watchlistedit-normal-explain": "Назвы старонак з ліку назіраных паказаныя ніжэй. Каб нешта выдаліць, адзначце клетку побач з адпаведным радком, пасля чаго націсніце \"Выняць складнікі\". Таксама можна правіць гэты спіс непасрэдна, [[Special:EditWatchlist/raw|без афармлення]].", "watchlistedit-normal-submit": "Выняць складнікі", - "watchlistedit-normal-done": "З вашага спіса назірання {{PLURAL:$1|быў выдалены|былі выдалены|было выдалена}} $1 {{PLURAL:$1|складнік|складнікі|складнікаў}}:", + "watchlistedit-normal-done": "З Вашага спісу назірання {{PLURAL:$1|быў выдалены|былі выдалены|было выдалена}} $1 {{PLURAL:$1|складнік|складнікі|складнікаў}}:", "watchlistedit-raw-title": "Нефарматаваны спіс назірання", "watchlistedit-raw-legend": "Правіць нефарматаваны спіс назірання", "watchlistedit-raw-explain": "Назвы старонак з ліку назіраных паказаныя ніжэй, без афармлення, адна назва на адзін радок; такім чынам, спіс можна правіць як звычайны тэкст. Па сканчэнні націсніце \"{{int:Watchlistedit-raw-submit}}\". Таксама гэта можна зрабіць праз [[Special:EditWatchlist|стандартны інтэрфейс]].", @@ -3544,6 +3545,7 @@ "logentry-delete-delete": "$1 {{GENDER:$2|выдаліў|выдаліла}} старонку $3", "logentry-delete-delete_redir": "$1 {{GENDER:$2|выдаліў|выдаліла}} перанакіраванне $3 шляхам перазапісу", "logentry-delete-restore": "$1 {{GENDER:$2|аднавіў|аднавіла}} старонку $3 ($4)", + "restore-count-revisions": "{{PLURAL:$1|1 версія|$1 версіі|$1 версій}}", "logentry-delete-event": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць {{PLURAL:$5|запісу журнала|$5 запісаў журнала}} $3: $4", "logentry-delete-revision": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць {{PLURAL:$5|версіі|$5 версій|$5 версій}} старонкі $3: $4", "logentry-delete-event-legacy": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць запісаў журнала $3", diff --git a/languages/i18n/bg.json b/languages/i18n/bg.json index b4b31f2b46..4fc42bc67e 100644 --- a/languages/i18n/bg.json +++ b/languages/i18n/bg.json @@ -628,6 +628,9 @@ "savechanges": "Съхраняване на промените", "publishpage": "Публикуване на страницата", "publishchanges": "Публикуване на промените", + "savearticle-start": "Съхраняване на страницата...", + "savechanges-start": "Съхраняване на промените...", + "publishpage-start": "Публикуване на страницата...", "publishchanges-start": "Публикуване на промените...", "preview": "Предварителен преглед", "showpreview": "Предварителен преглед", @@ -636,6 +639,7 @@ "anoneditwarning": "Внимание: Не сте влезли в системата. Ако направите редакция IP-адресът Ви ще бъде публично видим. Ако [$1 влезете] или си [$2 създадете акаунт], редакциите Ви ще бъдат свързани с потребителското Ви име, заедно с други преимущества.", "anonpreviewwarning": "Не сте влезли в системата. Ако съхраните редакцията си, тя ще бъде записана в историята на страницата с вашия IP-адрес.", "missingsummary": "Напомняне: Не е въведено кратко описание на промените.\nПри повторно натискане на бутона „$1“, редакцията ще бъде съхранена без резюме.", + "selfredirect": "Внимание: Пренасочвате страница към самата нея.\nМоже би сте посочили грешна цел за пренасочването или може би сте редактирали грешната страница.\nАко натиснете „$1“ отново, пренасочването ще бъде създадено.", "missingcommenttext": "Моля, въведете коментар.", "missingcommentheader": "Напомняне: Не е въведено заглавие на коментара.\nПри повторно натискане на „$1“, редакцията ще бъде записана без коментар.", "summary-preview": "Предварителен преглед на резюмето:", @@ -644,6 +648,7 @@ "blockedtitle": "Потребителят е блокиран", "blockedtext": "'''Вашето потребителско име (или IP-адрес) беше блокирано.'''\n\nБлокирането е извършено от $1. Посочената причина е: ''$2''\n\n*Начало на блокирането: $8\n*Край на блокирането: $6\n*Блокирането се отнася за: $7\n\nМожете да се свържете с $1 или с някой от останалите [[{{MediaWiki:Grouppage-sysop}}|администратори]], за да обсъдите блокирането.\n\nМожете да използвате услугата „Пращане писмо на потребител“ само ако не ви е забранена употребата ѝ и ако сте посочили валидна електронна поща в [[Special:Preferences|настройките]] си.\n\nВашият IP адрес е $3, а номерът на блокирането е $5. Включвайте едно от двете или и двете във всяко запитване, което правите.", "autoblockedtext": "IP-адресът ви беше блокиран автоматично, защото е бил използван от друг потребител, който е бил блокиран от $1.\nПосочената причина е:\n\n:''$2''\n\n* Начало на блокирането: $8\n* Край на блокирането: $6\n* Блокирането се отнася за: $7\n\nМожете да се свържете с $1 или с някой от останалите [[{{MediaWiki:Grouppage-sysop}}|администратори]], за да обсъдите блокирането.\n\nМожете да използвате услугата „Пращане писмо на потребител“ само ако не ви е забранена употребата ѝ и ако сте посочили валидна електронна поща в [[Special:Preferences|настройките]] си.\n\nТекущият ви IP-адрес е $3, а номерът на блокирането ви е $5. Включвайте ги във всяко питане, което правите.", + "systemblockedtext": "Вашето потребителско име или IP адрес беше автоматично блокирано от Медия Уики.\nПосочената причина е:\n\n:$2\n\n* Начало на блокирането: $8\n* Край на блокирането: $6\n* Блокирането се отнася за: $7\n\nВашият текущ IP адрес е $3.\nМоля, включете всичките детайли по-горе, ако правите каквито и да е запитвания.", "blockednoreason": "не е указана причина", "whitelistedittext": "Редактирането на страници изисква $1 в системата.", "confirmedittext": "Необходимо е да потвърдите електронната си поща, преди да редактирате страници.\nВъведете и потвърдете адреса си на [[Special:Preferences|страницата с настройките]].", @@ -1059,6 +1064,7 @@ "prefs-dateformat": "Формат на датата", "prefs-timeoffset": "Часово отместване", "prefs-advancedediting": "Общи настройки", + "prefs-developertools": "Инструменти за разработчици", "prefs-editor": "Редактор", "prefs-preview": "Преглед", "prefs-advancedrc": "Разширени настройки", @@ -1361,6 +1367,8 @@ "rcfilters-filter-humans-description": "Редакции, направени от редактори.", "rcfilters-filtergroup-reviewstatus": "Проверка на статуса", "rcfilters-filter-reviewstatus-unpatrolled-label": "Непатрулирано", + "rcfilters-filter-reviewstatus-manual-label": "Ръчно патрулирани", + "rcfilters-filter-reviewstatus-auto-label": "Автоматично патрулирани", "rcfilters-filtergroup-significance": "Значимост", "rcfilters-filter-minor-label": "Малки промени", "rcfilters-filter-minor-description": "Редакции, които не са отбелязани като малки промени.", @@ -1698,10 +1706,10 @@ "filedelete-intro-old": "Изтривате версията на [[Media:$1|$1]] към [$4 $3, $2].", "filedelete-comment": "Причина:", "filedelete-submit": "Изтриване", - "filedelete-success": "Файлът '''$1''' беше изтрит.", + "filedelete-success": "Файлът $1 беше изтрит.", "filedelete-success-old": "Версията на [[Media:$1|$1]] към $3, $2 е била изтрита.", "filedelete-nofile": "Файлът $1 не съществува.", - "filedelete-nofile-old": "Не съществува архивна версия на '''$1''' с указаните параметри.", + "filedelete-nofile-old": "Не съществува архивна версия на $1 с указаните параметри.", "filedelete-otherreason": "Друга/допълнителна причина:", "filedelete-reason-otherlist": "Друга причина", "filedelete-reason-dropdown": "*Общи причини за изтриване\n** Нарушение на авторските права\n** Файлът се повтаря", @@ -2157,7 +2165,7 @@ "protect-othertime": "Друг срок:", "protect-othertime-op": "друг срок", "protect-existing-expiry": "Оставащо време: $2, $3", - "protect-existing-expiry-infinity": "Existing expiration time: безсрочно", + "protect-existing-expiry-infinity": "Оставащо време: безсрочно", "protect-otherreason": "Друга/допълнителна причина:", "protect-otherreason-op": "Друга причина", "protect-dropdown": "* Стандартни причини за защита на страници\n** Чест обект на вандализъм\n** Чест обект на спам\n** Редакторска война\n** Страница, изискваща много сървърни ресурси", @@ -2177,7 +2185,7 @@ "restriction-level-all": "всички", "undelete": "Преглед на изтрити страници", "undeletepage": "Преглед и възстановяване на изтрити страници", - "undeletepagetitle": "'''По-долу е показан списък на изтритите версии на [[:$1|$1]]'''.", + "undeletepagetitle": "По-долу е показан списък на изтритите версии на [[:$1|$1]].", "viewdeletedpage": "Преглед на изтрити страници", "undeletepagetext": "{{PLURAL:$1|Следната страница беше изтрита, но все още се намира в архива и може да бъде възстановена|Следните $1 страници бяха изтрити, но все още се намират в архива и могат да бъдат възстановени}}. Архивът може да се почиства от време на време.", "undelete-fieldset-title": "Възстановяване на версии", diff --git a/languages/i18n/bn.json b/languages/i18n/bn.json index 574950e047..ccb1fb2538 100644 --- a/languages/i18n/bn.json +++ b/languages/i18n/bn.json @@ -654,8 +654,8 @@ "subject-preview": "বিষয়ের প্রাকদর্শন:", "previewerrortext": "আপনার পরিবর্তনগুলি প্রাকদর্শন করার চেষ্টা করার সময় একটি ত্রুটি ঘটেছে।", "blockedtitle": "ব্যবহারকারীকে বাধা দেয়া হয়েছে", - "blockedtext": "আপনার ব্যবহারকারী নাম বা আইপি ঠিকানাটিকে সম্পাদনায় বাধাদান করা হয়েছে।\n\n$1 এই বাধাটি প্রদান করেছেন। বাধার কারণ হিসেবে বলা হয়েছে:$2।\n\n* বাধা শুরুর সময়: $8\n* বাধা উঠিয়ে নেয়ার সময়: $6\n* যাকে বাধাদান করা হয়েছে: $7\n\nআপনি $1 অথবা অন্য [[{{MediaWiki:Grouppage-sysop}}|প্রশাসকদের]] সাথে এই বাধা সংক্রান্ত বিষয়ে আলোচনা করতে পারেন।\n\nআপনি \"ইমেইল করুন\" বৈশিষ্ট্যটি ব্যবহার করতে পারবেন না যদি না আপনার [[Special:Preferences|অ্যাকাউন্টের পছন্দসমূহে]] একটি বৈধ ইমেইল ঠিকানা নির্দিষ্ট না করা হয়ে থাকে এবং আপনাকে এটি ব্যবহার করা থেকে অবরুদ্ধ না করা হয়ে থাকে।\n\nআপনার বর্তমান আইপি ঠিকানা হল $3, এবং আপনার বাধা নং হল #$5।\nদয়া করে আপনার যেকোন জিজ্ঞাসাতে উপরের সমস্ত বিবরণ অন্তর্ভুক্ত করুন।", - "autoblockedtext": "আপনার আইপি ঠিকানাটিকে স্বয়ংক্রিয়ভাবে সম্পাদনায় বাধাদান করা হয়েছে কারণ এমন আরেকজন ব্যবহারকারী এটি ব্যবহার করেছেন, যাকে $1 বাধা দিয়েছেন।\nযে কারণে বাধা দেওয়া হয়েছে সেটি হল:\n\n:$2\n\n* বাধা শুরুর সময়: $8\n* বাধা শেষের সময়: $6\n* যাকে বাধাদান করা হয়েছে: $7\n\nআপনি $1-এর সাথে কিংবা অন্য যেকোন [[{{MediaWiki:Grouppage-sysop}}|প্রশাসকের]] সাথে যোগাযোগ করে এই বাধা সংক্রান্ত বিষয়ে আলোচনা করতে পারেন।\n\nলক্ষ্য করুন, আপনি \"এই ব্যবহারকারীকে ই-মেইল করুন\" বৈশিষ্ট্যটি ব্যবহার করতে পারবেন না যদি না আপনার [[Special:Preferences|অ্যাকাউন্টের পছন্দসমূহে]] একটি বৈধ ইমেইল ঠিকানা নিবন্ধিত না থাকে এবং আপনাকে এটি ব্যবহার করা থেকে অবরুদ্ধ না করা হয়ে থাকে।\n\nআপনার বর্তমান আইপি ঠিকানা হচ্ছে $3, এবং বাধা নং হল #$5।\nদয়া করে আপনার যেকোন জিজ্ঞাসাতে উপরের সমস্ত বিবরণ অন্তর্ভুক্ত করুন।", + "blockedtext": "আপনার ব্যবহারকারী নাম বা আইপি ঠিকানাটিকে সম্পাদনায় বাধাদান করা হয়েছে।\n\n$1 এই বাধাটি প্রদান করেছেন। বাধার কারণ হিসেবে বলা হয়েছে:$2।\n\n* বাধা শুরুর সময়: $8\n* বাধা উঠিয়ে নেয়ার সময়: $6\n* যাকে বাধাদান করা হয়েছে: $7\n\nআপনি $1 অথবা অন্য [[{{MediaWiki:Grouppage-sysop}}|প্রশাসকদের]] সাথে এই বাধা সংক্রান্ত বিষয়ে আলোচনা করতে পারেন।\n\nআপনি \"{{int:emailuser}}\" বৈশিষ্ট্যটি ব্যবহার করতে পারবেন না যদি না আপনার [[Special:Preferences|অ্যাকাউন্টের পছন্দসমূহে]] একটি বৈধ ইমেইল ঠিকানা নির্দিষ্ট না করা হয়ে থাকে এবং আপনাকে এটি ব্যবহার করা থেকে অবরুদ্ধ না করা হয়ে থাকে।\n\nআপনার বর্তমান আইপি ঠিকানা হল $3, এবং আপনার বাধা নং হল #$5।\nদয়া করে আপনার যেকোন জিজ্ঞাসাতে উপরের সমস্ত বিবরণ অন্তর্ভুক্ত করুন।", + "autoblockedtext": "আপনার আইপি ঠিকানাটিকে স্বয়ংক্রিয়ভাবে সম্পাদনায় বাধাদান করা হয়েছে কারণ এমন আরেকজন ব্যবহারকারী এটি ব্যবহার করেছেন, যাকে $1 বাধা দিয়েছেন।\nযে কারণে বাধা দেওয়া হয়েছে সেটি হল:\n\n:$2\n\n* বাধা শুরুর সময়: $8\n* বাধা শেষের সময়: $6\n* যাকে বাধাদান করা হয়েছে: $7\n\nআপনি $1-এর সাথে কিংবা অন্য যেকোন [[{{MediaWiki:Grouppage-sysop}}|প্রশাসকের]] সাথে যোগাযোগ করে এই বাধা সংক্রান্ত বিষয়ে আলোচনা করতে পারেন।\n\nলক্ষ্য করুন, আপনি \"{{int:emailuser}}\" বৈশিষ্ট্যটি ব্যবহার করতে পারবেন না যদি না আপনার [[Special:Preferences|অ্যাকাউন্টের পছন্দসমূহে]] একটি বৈধ ইমেইল ঠিকানা নিবন্ধিত না থাকে এবং আপনাকে এটি ব্যবহার করা থেকে অবরুদ্ধ না করা হয়ে থাকে।\n\nআপনার বর্তমান আইপি ঠিকানা হচ্ছে $3, এবং বাধা নং হল #$5।\nদয়া করে আপনার যেকোন জিজ্ঞাসাতে উপরের সমস্ত বিবরণ অন্তর্ভুক্ত করুন।", "systemblockedtext": "আপনার ব্যবহারকারী নাম অথবা আইপি ঠিকানাটিকে স্বয়ংক্রিয়ভাবে মিডিয়াউইকি দ্বারা বাধাদান করা হয়েছে। যে কারণটি দেওয়া হয়েছে, সেটি হল:\n\n:$2\n\n* বাধা শুরুর সময়: $8\n* বাধা উঠিয়ে নেয়ার সময়: $6\n* যাকে বাধাদান করা হয়েছে: $7\n\nআপনার বর্তমান আইপি ঠিকানাটি হল $3।\nদয়া করে আপনার যেকোন জিজ্ঞাসাতে উপরের সমস্ত বিবরণ অন্তর্ভুক্ত করুন।", "blockednoreason": "কোন কারণ দেওয়া হয়নি", "whitelistedittext": "পাতায় সম্পাদনা করতে অনুগ্রহ করে $1 করুন।", @@ -2282,7 +2282,7 @@ "protect-level-autoconfirmed": "শুধুমাত্র স্বয়ং পরীক্ষিত ব্যবহারকারীদের জন্য", "protect-level-sysop": "কেবল প্রশাসকদের জন্য অনুমতি", "protect-summary-cascade": "প্রপাতাকার", - "protect-expiring": "$1 (ইউটিসি) সময়ে মেয়াদোত্তীর্ণ", + "protect-expiring": "মেয়াদোত্তীর্ণ হবার তারিখ $1 (ইউটিসি)", "protect-expiring-local": "মেয়াদ উত্তীর্ণের সময় $1", "protect-expiry-indefinite": "অসীম", "protect-cascade": "এই পাতায় অন্তর্ভুক্ত পাতাগুলিও সুরক্ষিত করা হোক (প্রপাতাকার সুরক্ষা)", diff --git a/languages/i18n/ca.json b/languages/i18n/ca.json index f4158eae86..a8a60d559e 100644 --- a/languages/i18n/ca.json +++ b/languages/i18n/ca.json @@ -586,6 +586,7 @@ "botpasswords-restriction-failed": "Les restriccions de contrasenyes de bots impedeixen aquest inici de sessió.", "botpasswords-invalid-name": "El nom d'usuari especificat no conté el separador de contrasenya de bot («$1»).", "botpasswords-not-exist": "L'usuari «$1» no té una contrasenya de bot anomenada «$2».", + "botpasswords-needs-reset": "Cal reinicialitzar la contrasenya del robot «$2» que pertany a {{GENDER:$1|l’usuari|la usuària}} «$1».", "resetpass_forbidden": "No poden canviar-se les contrasenyes", "resetpass_forbidden-reason": "Les contrasenyes no es poden canviar: $1", "resetpass-no-info": "Heu d'estar registrats en un compte per a poder accedir directament a aquesta pàgina.", diff --git a/languages/i18n/ckb.json b/languages/i18n/ckb.json index 79f2b2b5b5..b23fbabc29 100644 --- a/languages/i18n/ckb.json +++ b/languages/i18n/ckb.json @@ -1174,6 +1174,8 @@ "rcfilters-limit-and-date-label": "$1 گۆڕانکاری، $2", "rcfilters-days-show-days": "$1 {{PLURAL:$1|ڕۆژ}}", "rcfilters-quickfilters": "پاڵوێنە پاشەکەوتکراوەکان", + "rcfilters-quickfilters-placeholder-title": "ھیچ پاڵوێنەیەک پاشەکەوت نەکراوە", + "rcfilters-quickfilters-placeholder-description": "بۆ پاشەکەوتکردنی ھەڵبژاردەی پاڵوێنەکان و دووبارە بەکارھێنانەوەیان، کرتە لەسەر نیشانی نیشانەی کتێبەکە بکە.", "rcfilters-savedqueries-defaultlabel": "پاڵوێنە پاشەکەوتکراوەکان", "rcfilters-savedqueries-setdefault": "بە بنەڕەتی کارای بکە", "rcfilters-savedqueries-new-name-label": "ناو", diff --git a/languages/i18n/cs.json b/languages/i18n/cs.json index a37e90a0bb..113a994616 100644 --- a/languages/i18n/cs.json +++ b/languages/i18n/cs.json @@ -541,6 +541,7 @@ "botpasswords-existing": "Stávající hesla pro boty", "botpasswords-createnew": "Vytvořit nové heslo pro boty", "botpasswords-editexisting": "Editovat existující heslo pro boty", + "botpasswords-label-needsreset": "(heslo se musí resetovat)", "botpasswords-label-appid": "Název bota:", "botpasswords-label-create": "Vytvořit", "botpasswords-label-update": "Aktualizovat", @@ -564,6 +565,7 @@ "botpasswords-restriction-failed": "Toto přihlášení bylo zamítnuto omezením hesel pro boty.", "botpasswords-invalid-name": "Uvedené uživatelské jméno neobsahuje oddělovač hesel pro boty („$1“).", "botpasswords-not-exist": "Uživatel „$1“ nemá heslo pro bota nazvaného „$2“.", + "botpasswords-needs-reset": "Heslo pro bota jménem „$2“ {{GENDER:$2|uživatele|uživatelky}} „$1“ se musí resetovat.", "resetpass_forbidden": "Hesla nelze změnit.", "resetpass_forbidden-reason": "Hesla nelze změnit: $1", "resetpass-no-info": "K této stránce mají přímý přístup jen přihlášení uživatelé.", @@ -659,8 +661,8 @@ "subject-preview": "Náhled předmětu:", "previewerrortext": "Při pokusu o zobrazení náhledu vaÅ¡ich změn doÅ¡lo k chybě.", "blockedtitle": "Uživatel zablokován", - "blockedtext": "Vaší IP adrese či uživatelskému jménu byla zablokována možnost editace.\n\nZablokování {{GENDER:$4|provedl|provedla}} $1.\nUdaným důvodem bylo $2.\n\n* Začátek blokování: $8\n* Zablokování vyprší: $6\n* Blokovaný uživatel: $7\n\nPokud chcete zablokování prodiskutovat, můžete kontaktovat {{GENDER:$4|uživatele|uživatelku}} $1 či jiného [[{{MediaWiki:Grouppage-sysop}}|správce]].\nUvědomte si, že nemůžete použít funkci „Poslat e-mail“, jestliže nemáte ve svém [[Special:Preferences|nastavení]] uvedenu platnou e-mailovou adresu nebo pokud vám byla tato možnost zakázána.\nVaÅ¡e IP adresa je $3 a identifikační číslo bloku je #$5; tyto údaje uvádějte ve vÅ¡ech dotazech na správce.", - "autoblockedtext": "VaÅ¡e IP adresa byla automaticky zablokována, protože ji používal jiný uživatel, kterého zablokoval $1.\nUdaný důvod blokování:\n\n:$2\n\n* Začátek blokování: $8\n* Konec blokování: $6\n* Původně blokovaný uživatel: $7\n\nZablokování můžete prodiskutovat se správcem $1 nebo některým z dalších [[{{MediaWiki:Grouppage-sysop}}|správců]].\n\nUvědomte si vÅ¡ak, že funkci „Poslat e-mail tomuto uživateli“ nemůžete použít, pokud nemáte ve svém [[Special:Preferences|uživatelském nastavení]] zadaný platný e-mail a nebylo vám zablokováno jeho užívání.\n\nVaÅ¡e současná IP adresa je $3, číslo vaÅ¡eho zablokování je #$5.\nProsíme, uveďte tyto údaje při komunikaci se správci.", + "blockedtext": "Vaší IP adrese či uživatelskému jménu byla zablokována možnost editace.\n\nZablokování {{GENDER:$4|provedl|provedla}} $1.\nUdaným důvodem bylo $2.\n\n* Začátek blokování: $8\n* Zablokování vyprší: $6\n* Blokovaný uživatel: $7\n\nPokud chcete zablokování prodiskutovat, můžete kontaktovat {{GENDER:$4|uživatele|uživatelku}} $1 či jiného [[{{MediaWiki:Grouppage-sysop}}|správce]].\nUvědomte si, že nemůžete použít funkci „{{int:emailuser}}“, jestliže nemáte ve svém [[Special:Preferences|nastavení]] uvedenu platnou e-mailovou adresu nebo pokud vám byla tato možnost zakázána.\nVaÅ¡e IP adresa je $3 a identifikační číslo bloku je #$5; tyto údaje uvádějte ve vÅ¡ech dotazech na správce.", + "autoblockedtext": "VaÅ¡e IP adresa byla automaticky zablokována, protože ji používal jiný uživatel, kterého zablokoval $1.\nUdaný důvod blokování:\n\n:$2\n\n* Začátek blokování: $8\n* Konec blokování: $6\n* Původně blokovaný uživatel: $7\n\nZablokování můžete prodiskutovat se správcem $1 nebo některým z dalších [[{{MediaWiki:Grouppage-sysop}}|správců]].\n\nUvědomte si vÅ¡ak, že funkci „{{int:emailuser}}“ nemůžete použít, pokud nemáte ve svém [[Special:Preferences|uživatelském nastavení]] zadaný platný e-mail a nebylo vám zablokováno jeho užívání.\n\nVaÅ¡e současná IP adresa je $3, číslo vaÅ¡eho zablokování je #$5.\nProsíme, uveďte tyto údaje při komunikaci se správci.", "systemblockedtext": "VaÅ¡e IP adresa byla automaticky zablokována softwarem MediaWiki.\nUdaný důvod blokování:\n\n:$2\n\n* Začátek blokování: $8\n* Konec blokování: $6\n* Původně blokovaný uživatel: $7\n\nVaÅ¡e současná IP adresa je $3.\nProsíme, uveďte tyto údaje při komunikaci se správci.", "blockednoreason": "důvod nebyl zadán", "whitelistedittext": "Pro editaci se musíte $1.", @@ -1988,6 +1990,7 @@ "apisandbox-dynamic-parameters-add-label": "Přidat parametr:", "apisandbox-dynamic-parameters-add-placeholder": "Jméno parametru", "apisandbox-dynamic-error-exists": "Parametr s názvem „$1“ již existuje.", + "apisandbox-templated-parameter-reason": "Tento [[Special:ApiHelp/main#main/templatedparams|Å¡ablonovaný parametr]] se nabízí na základě {{PLURAL:$1|hodnoty|hodnot}} parametru $2.", "apisandbox-deprecated-parameters": "Zavržené parametry", "apisandbox-fetch-token": "Automaticky naplnit token", "apisandbox-add-multi": "Přidat", @@ -4076,5 +4079,6 @@ "pagedata-title": "Data stránky", "pagedata-text": "Tato stránka poskytuje datové rozhraní ke stránkám. Uveďte prosím název stránky v URL pomocí syntaxe pro podstránky.\n* Funguje dohadování o obsahu na základě hlavičky Accept vaÅ¡eho klienta. To znamená, že data stránky budou poskytnuta ve formátu preferovaném vaším klientem.", "pagedata-not-acceptable": "Nenalezen odpovídající formát. Podporované MIME typy: $1", - "pagedata-bad-title": "Neplatný název: $1." + "pagedata-bad-title": "Neplatný název: $1.", + "unregistered-user-config": "Z bezpečnostních důvodů nelze načítat uživatelské podstránky s JavaScriptem, CSS nebo JSONem u neregistrovaných uživatelů." } diff --git a/languages/i18n/cu.json b/languages/i18n/cu.json index 6d27e3e037..4343b6140c 100644 --- a/languages/i18n/cu.json +++ b/languages/i18n/cu.json @@ -11,7 +11,7 @@ "Vvs-dm" ] }, - "tog-oldsig": "нꙑнѣшьн҄ь аѵтографъ :", + "tog-oldsig": "твои нꙑнѣшьн҄ь аѵтографъ :", "underline-always": "вьсѥгда", "underline-never": "никъгда", "sunday": "нєдѣлꙗ", @@ -83,13 +83,14 @@ "subcategories": "подъкатигорїѩ", "category-media-header": "катигорїѩ ⁖ $1 ⁖ дѣла", "category-empty": "''сѥи катигорїи нꙑнѣ страницѧ и дѣлъ нѣстъ''", - "hidden-categories": "{{PLURAL:$1|съкрꙑта катигорїꙗ|съкрꙑти катигорїи|съкрꙑтꙑ катигорїѩ}}", + "hidden-categories": "{{PLURAL:$1|съкрꙑта катигорїꙗ|съкрꙑтѣ катигорїи|съкрꙑтꙑ катигорїѩ}}", "hidden-category-category": "съкрꙑтꙑ катигорїѩ", "category-subcat-count": "{{PLURAL:$2|1=Сѥи катигорїи тъкъмо сꙗ подъкатигорїꙗ ѥстъ|Сѥи катигорїи {{PLURAL:$1|1=ѥдина подъкатигорїꙗ ѥстъ|2 подъкатигорїи ѥстє|$1 подъкатигорїѩ сѫтъ}} · а вьсѩ жє подъкатигорїѩ число $2 ѥстъ}}", "listingcontinuesabbrev": "· вѧщє", + "broken-file-category": "страницѧ ѩжє блаꙁничьнꙑ свѧꙁи съ дѣла имѫтъ", "about": "опьсаниѥ", "article": "члѣнъ", - "newwindow": "(иномь окънѣ)", + "newwindow": "(въ иномь окънѣ)", "cancel": "отъмѣтаниѥ", "moredotdotdot": "вѧщє ···", "mypage": "страница", @@ -97,9 +98,9 @@ "anontalk": "бєсѣда", "navigation": "плаваниѥ", "and": " и", - "faq": "чѧстꙑ въпроси", + "faq": "чѧсти въпроси", "actions": "дѣиства", - "namespaces": "имєнъ просторꙑ", + "namespaces": "имєнъ простори", "variants": "обраꙁи", "navigation-heading": "плаваниѥ", "errorpagetitle": "блаꙁна", @@ -140,7 +141,7 @@ "redirectedfrom": "(прѣнаправлѥниѥ отъ ⁖ $1 ⁖)", "redirectpagesub": "прѣнаправлѥниѥ", "redirectto": "прѣнаправлѥниѥ къ :", - "lastmodifiedat": "страницѧ послѣдьнꙗ мѣна сътворѥна $2 · $1 бѣ ⁙", + "lastmodifiedat": "сѥѩ страницѧ послѣдьнꙗ мѣна сътворѥна $2 · $1 бѣашє ⁙", "protectedpage": "сꙗ страница ꙁабранѥна ѥстъ", "jumpto": "прѣиди къ :", "jumptonavigation": "плаваниѥ", @@ -149,9 +150,9 @@ "aboutsite": "{{grammar:genitive|{{SITENAME}}}} опьсаниѥ", "aboutpage": "Project:О сѥмь опꙑтьствовании", "copyright": "подъ прощєниѥмь $1 пьсано ѥстъ · ащє ино нє каꙁано ѥстъ", - "copyrightpage": "{{ns:project}}:Творьцъ права", - "currentevents": "сѫщѧѩ вѣщи", - "currentevents-url": "Project:Сѫщѧѩ вѣщи", + "copyrightpage": "{{ns:project}}:Творьць права", + "currentevents": "сѫщѧѩ вѣщиѥ", + "currentevents-url": "Project:Сѫщѧѩ вѣщиѥ", "disclaimers": "отърицаниꙗ", "disclaimerpage": "Project:Главьно отърицаниѥ", "edithelp": "помощь по исправлѥниѭ", @@ -202,7 +203,7 @@ "viewsource": "страницѧ источьнъ обраꙁъ", "viewsource-title": "вижьдь страницѧ ⁖ $1 ⁖ источьнъ обраꙁъ", "exception-nologin": "тꙑ нє въшьлъ ѥси", - "welcomeuser": "Добрѣ прити · $1!", + "welcomeuser": "радоуи сѧ · $1", "welcomecreation-msg": "твоѥ польꙃєватєльско мѣсто сътворєно ѥстъ ⁙\nнꙑнѣ иꙁмѣнити [[Special:Preferences|{{GRAMMAR:genitive|{{SITENAME}}}} строи]] можєши", "yourname": "твоѥ имѧ", "userlogin-yourname": "польꙃєватєлꙗ имѧ", @@ -232,6 +233,7 @@ "createacct-benefit-heading": "{{SITENAME}} съꙁьдаѥтъ сѧ чьловѣкꙑ · ижє ꙗко тꙑ сѫтъ", "createacct-benefit-body1": "{{PLURAL:$1|мѣна|мѣнꙑ|мѣнъ}}", "createacct-benefit-body2": "{{PLURAL:$1|страница|страници|страницѧ}}", + "createacct-benefit-body3": "{{PLURAL:$1|послѣдьн҄ь дѣтєл҄ь|послѣдьнꙗ дѣтєлꙗ|послѣдьни дѣтєлє}}", "userexists": "сѫщє польꙃєватєлꙗ имѧ пьса ⁙\nбѫди добръ · ино сѥ иꙁобрѧщи", "loginerror": "въхода блаꙁна", "createacct-error": "мѣста сътворѥниꙗ блаꙁна", @@ -259,6 +261,8 @@ "link_tip": "вънѫтрьнꙗ съвѧꙁь", "extlink_sample": "http://www.example.com съвѧꙁи имѧ", "extlink_tip": "вънѣщьнꙗ съвѧꙁь (помьни о http://)", + "headline_sample": "тїтла напьсаниѥ", + "headline_tip": "тїтлъ рѧда В҃", "media_tip": "дѣла съвѧꙁь", "sig_tip": "твои аѵтографъ и нꙑнѣшьна врѣмѧ и дьнь", "summary": "опьсаниѥ :", @@ -266,7 +270,8 @@ "minoredit": "малаꙗ мѣна", "watchthis": "сѥѩ страницѧ блюдєниѥ", "savearticle": "съхранѥниѥ", - "showpreview": "мѣнꙑ поꙁьрѣниѥ (бєꙁ съхранѥниꙗ)", + "showpreview": "мѣнꙑ поꙁьрѣниѥ (бєс съхранѥниꙗ)", + "showdiff": "раꙁьницѧ поꙁьрѣниѥ", "blockedtitle": "польꙃєватєл҄ь ꙁаграждєнъ ѥстъ", "loginreqlink": "въниди", "newarticle": "(новъ)", @@ -274,7 +279,7 @@ "noarticletext-nopermission": "нꙑнѣ с̑ьдє ничєсожє нє напьсано ѥстъ ⁙\n[[Special:Search/{{PAGENAME}}|сѥѩ страницѧ имѧ искати]] дроугꙑ страницѧ или\n[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} съвѧꙁанꙑ їсторїѩ видѣти] можєши ⁙ сътворити жє сѭ страницѫ нє можєши", "userpage-userdoesnotexist": "польꙃєватєльска мѣста ⁖ $1 ⁖ нꙑнѣ нѣстъ ⁙\nпрѣдъ сътворѥниѥмь или исправлѥниѥмь сѥѩ страницѧ помꙑсли жє ащє исто тъ дѣиство ноуждьно ли", "userpage-userdoesnotexist-view": "польꙃєватєльско мѣсто ⁖ $1 ⁖ сътворєно нѣстъ", - "clearyourcache": "'''НАРОЧИТО''': По съхранѥнии можєши обити своѥго съмотрила съхранъ да видѣлъ би мѣнꙑ\n* '''Mozilla ли Firefox ли Safari''' ли жьмꙑи ''Shift'' а мꙑшиѭ жьми ''Reload'' или жьми ''Ctrl-F5'' ꙗко жє ''Ctrl-R'' (⌘-R вън Apple Mac)\n* '''Google Chrome:''' ли жьмꙑи ''Ctrl-Shift-R'' (⌘-Shift-R въ Mac)\n* '''Internet Explorer''' ли жьмꙑи ''Ctrl'' а мꙑшиѭ жьми ''Refresh'' или жьми ''Ctrl-F5'' \n* '''Опєрꙑ''' польꙃєватєльмъ можєть бꙑти ноужда пльнѣ поничьжити ихъ съмотрила съхранъ въ ''Tools → Preferences'' ⁙", + "clearyourcache": "НАРОЧИТО: По съхранѥнии можєши обити своѥго съмотрила съхранъ да видѣлъ би мѣнꙑ\n* Mozilla ли Firefox ли Safari''' ли жьмꙑи Shift'' а мꙑшиѭ жьми Reload или жьми Ctrl-F5 ꙗко жє Ctrl-R (⌘-R вън Apple Mac)\n* Google Chrome: ли жьмꙑи Ctrl-Shift-R'' (⌘-Shift-R въ Mac)\n* Internet Explorer''' ли жьмꙑи Ctrl а мꙑшиѭ жьми Refresh или жьми Ctrl-F5 \n* Опєрꙑ польꙃєватєльмъ можєть бꙑти ноужда пльнѣ поничьжити ихъ съмотрила съхранъ въ Tools → Preferences (Opera → Preferences вън Apple Mac) ⁙", "updated": "(оновлѥно ѥстъ)", "note": "'''НАРОЧИТО:'''", "editing": "исправлѥниѥ: $1", @@ -287,10 +292,14 @@ "template-protected": "(ꙁабранєно ѥстъ)", "template-semiprotected": "(чѧстьно ꙁабранѥно)", "hiddencategories": "сꙗ страница въ {{PLURAL:$1|1 съкрꙑтѣи катигорїи|$1 съкрꙑтѣхъ катигорїѩ}} сѧ авлꙗѥтъ :", - "moveddeleted-notice": "сꙗ страница поничьжєна ѥстъ ⁙\nпоничьжєниꙗ и прѣимєнованиꙗ їстории сѥѩ страницѧ нижѣ видѣти можєши", + "moveddeleted-notice": "сꙗ страница поничьжєна ѥстъ ⁙\nпоничьжєниꙗ ли прѣимєнованиꙗ ли ꙁабранѥниꙗ їсторїѩ на сѥи страници нижє видѣти можєши", "postedit-confirmation-created": "страница сътворѥна ѥстъ", "postedit-confirmation-saved": "твоꙗ мѣна съхранѥна ѥстъ", "viewpagelogs": "сѥѩ страницѧ їсторїѩ", + "revisionasof": "обраꙁъ отъ $1", + "revision-info": "страницѧ обраꙁъ отъ $1 ижє {{GENDER:$6|$2}}$7 сътвори", + "previousrevision": "← прѣждьн҄ь обраꙁъ", + "currentrevisionlink": "послѣдьн҄ь обраꙁъ", "cur": "нꙑ҃н", "last": "пс҃лд", "page_first": "прьва страница", @@ -321,6 +330,7 @@ "editundo": "отъмѣтаниѥ", "searchresults": "исканиꙗ слѣдьствиѥ", "searchresults-title": "исканиꙗ ⁖ $1 ⁖ слѣдьствиѥ", + "prevn": "прѣждьнѩ {{PLURAL:$1|$1}}", "viewprevnext": "виждь ($1 {{int:pipe-separator}} $2) ($3)", "searchmenu-exists": "'''страница имєньмь ⁖ [[:$1]] ⁖ ѥстъ створѥна ю'''", "searchmenu-new": "страницѫ \"⁖ [[:$1]] ⁖\" сътворити можєши {{PLURAL:$2|0=|ꙁъри такождє страница ижє по искании авлєна ѥстъ|ꙁьри такождє исканиꙗ слѣдьствиꙗ}}", @@ -330,11 +340,11 @@ "searchprofile-articles-tooltip": "ищи въ $1", "searchprofile-images-tooltip": "исканиѥ дѣлъ", "searchprofile-everything-tooltip": "ищи вьсѩ страницѧ въкоупомь съ бѣсєдꙑ", - "search-result-size": "$1 ({{PLURAL:$2|$2 слово|$2 слова|$2 словєсъ}})", - "search-redirect": "(прѣнаправлєниѥ $1)", + "search-result-size": "$1 ({{PLURAL:$2|$2 слово|$2 словєсѣ|$2 словєсъ}})", + "search-redirect": "(прѣнаправлєниѥ отъ $1)", "search-section": "(чѧсть $1)", "search-suggest": "⁖ $1 ⁖ мьниши ли", - "search-interwiki-caption": "родьствьна опꙑтьствованиꙗ", + "search-interwiki-caption": "иꙁд родьствьнъ опꙑтьствовании вѣстиѥ", "search-interwiki-more": "(вѧщє)", "searchall": "вьсꙗ", "search-nonefound": "исканиѥ сꙗ слова ничєсо жє нє авило ѥстъ", @@ -364,7 +374,7 @@ "prefs-namespaces": "имєнъ просторꙑ", "prefs-files": "дѣла", "username": "{{GENDER:$1|польꙃєватєлꙗ имѧ}} :", - "prefs-memberingroups": "{{GENDER:$2|польꙃєватєлꙗ}} {{PLURAL:$1|чинъ|чина|чинꙑ}} :", + "prefs-memberingroups": "{{GENDER:$2|польꙃєватєлꙗ|польꙃєватєлицѧ}} {{PLURAL:$1|чинъ|чина|чини}} :", "yourrealname": "истиньно имѧ :", "yourlanguage": "ѩꙁꙑкъ :", "yournick": "новъ аѵтографъ :", @@ -372,7 +382,7 @@ "gender-male": "онъ исправитъ страницѧ", "gender-female": "она исправитъ страницѧ", "prefs-signature": "аѵтографъ", - "userrights": "чина польꙃєватєлꙗ строи", + "userrights": "польꙃєватєлꙗ чинъ", "userrights-reason": "какъ съмꙑслъ :", "group": "чинъ :", "group-user": "польꙃєватєлє", @@ -518,7 +528,7 @@ "booksources-search-legend": "кънигъ кладѧꙃь исканиѥ", "booksources-search": "исканиѥ", "specialloguserlabel": "испльнитєл҄ь :", - "speciallogtitlelabel": "страницѧ или польꙃєватєлꙗ имѧ :", + "speciallogtitlelabel": "страницѧ или {{ns:user}}:польꙃєватєлꙗ имѧ :", "log": "їсторїѩ", "all-logs-page": "вьсѩ обьщѧ їсторїѩ", "allpages": "вьсѩ страницѧ", @@ -545,8 +555,8 @@ "watchlist": "блюдєниꙗ", "mywatchlist": "блюдєниꙗ", "watchlistfor2": "дѣлꙗ ⁖ $1 ⁖ $2", - "addedwatchtext": "страница ⁖ [[:$1]] ⁖ нꙑнѣ подъ твоимь [[Special:Watchlist|блюдєниѥмь]] ѥстъ ⁙\nвсꙗ ѥѩ и ѥѩжє бєсѣдꙑ страницѧ мѣнꙑ твоꙗ блюдєнии каталоꙃѣ покаꙁанꙑ бѫдѫтъ", - "removedwatchtext": "страница ⁖ [[:$1]] ⁖ нꙑнѣ твоѥго [[Special:Watchlist|блюдєниꙗ]] иꙁнєсєна ѥстъ", + "addedwatchtext": "страница ⁖ [[:$1]] ⁖ и ѥѩжє бєсѣда нꙑнѣ подъ твоимь [[Special:Watchlist|блюдєниѥмь]] ѥстє ⁙", + "removedwatchtext": "страница ⁖ [[:$1]] ⁖ и ѥѩжє бєсѣда нꙑнѣ ис твоѥго [[Special:Watchlist|блюдєниꙗ]] иꙁнєсєна ѥстъ", "watch": "блюдєниѥ", "watchthispage": "сѥѩ страницѧ блюдєниѥ", "unwatch": "остави блюдєниѥ", @@ -556,7 +566,7 @@ "created": "сътворѥнъ ѥстъ", "deletepage": "поничьжєниѥ", "excontent": "вънѫтри бѣ: '$1'", - "excontentauthor": "вънѫтри бѣ : '$1' (и послѣдьн҄ии дѣтєл҄ь бѣ '[[Special:Contributions/$2|$2]]')", + "excontentauthor": "вънѫтри бѣ : '$1' · и послѣдьн҄ии дѣтєл҄ь бѣ [[Special:Contributions/$2|$2]] ([[User talk:$2|бєсѣда]])", "delete-legend": "поничьжєниѥ", "actioncomplete": "дѣиство сътворєно ѥстъ", "deletedtext": "страница ⁖ $1 ⁖ поничьжєна ѥстъ ⁙\nвиждь ⁖ $2 ⁖ послѣдьнъ поничьжєниѩ дѣлꙗ", @@ -584,33 +594,34 @@ "undelete-show-file-submit": "да", "namespace": "имєнъ просторъ:", "invert": "обрати иꙁборъ", - "namespace_association": "съвѧꙁанꙑ имєнъ просторꙑ", + "namespace_association": "съвѧꙁани имєнъ простори", "blanknamespace": "(главьно)", "contributions": "{{GENDER:$1|польꙃєватєлꙗ|польꙃєватєлицѧ}} добродѣꙗниꙗ", "contributions-title": "польꙃєватєлꙗ ⁖ $1 ⁖ добродѣꙗниꙗ", "mycontris": "добродѣꙗниꙗ", "anoncontribs": "добродѣꙗниꙗ", - "contribsub2": "польꙃєватєлꙗ имѧ ⁖ {{GENDER:$3|$1}} ⁖ ѥстъ ($2)", + "contribsub2": "{{GENDER:$3|польꙃєватєлꙗ|польꙃєватєлицѧ}} имѧ ⁖ $1 ⁖ ѥстъ ($2)", "uctop": "(нꙑнѣщьн҄ь обраꙁъ)", "month": "отъ мѣсѧца и давѣѥ :", - "year": "отъ лѣта и давѣѥ :", + "year": "отъ лѣта и давѣи :", "sp-contributions-blocklog": "ꙁаграждєниꙗ їсторїꙗ", - "sp-contributions-deleted": "поничьжєнꙑ добродѣꙗниꙗ", + "sp-contributions-deleted": "{{GENDER:$1|поꙁєватєлꙗ|польꙃєватєлицѧ}} поничьжєнꙑ добродѣꙗниꙗ", "sp-contributions-uploads": "положєнꙑ дѣла", "sp-contributions-logs": "їсторїѩ", "sp-contributions-talk": "бєсѣда", "sp-contributions-username": "IP число или польꙃєватєлꙗ имѧ :", "sp-contributions-submit": "ищи", - "whatlinkshere": "дос҄ьдєщьнѩ съвѧꙁи", + "whatlinkshere": "дос҄ьдєщьнѩ съвѧꙁиѥ", "whatlinkshere-title": "страницѧ ижє съ ⁖ $1 ⁖ съвѧꙁи имѫтъ", "whatlinkshere-page": "страница :", + "linkshere": "сѩ страницѧ съ [[:$1]] съвѧꙁи имѫтъ :", "isredirect": "прѣнаправлѥниѥ", "istemplate": "внѫтри страницѧ", "isimage": "дѣла съвѧꙁь", - "whatlinkshere-links": "← съвѧꙁи", + "whatlinkshere-links": "← съвѧꙁиѥ", "whatlinkshere-hideredirs": "$1 прѣнаправлѥниꙗ", - "whatlinkshere-hidelinks": "$1 съвѧꙁи", - "whatlinkshere-filters": "ситꙑ", + "whatlinkshere-hidelinks": "$1 съвѧꙁиѥ", + "whatlinkshere-filters": "сита", "block": "ꙁагради польꙃєватєл҄ь", "blockip": "ꙁагради {{GENDER:$1|польꙃєватєл҄ь}}", "ipaddressorusername": "IP число или польꙃєватєлꙗ имѧ :", @@ -627,7 +638,7 @@ "blocklink": "ꙁагради", "contribslink": "добродѣꙗниꙗ", "blocklogpage": "ꙁаграждєниꙗ їсторїꙗ", - "blocklogentry": "ꙁаградилъ [[$1]] на врѣмѧ $2 $3", + "blocklogentry": "ꙁагради [[$1]] на врѣмѧ $2 $3", "block-log-flags-anononly": "тъкъмо анѡнѷмьнꙑ польꙃєватєлє", "block-log-flags-nocreate": "сътворѥниѥ мѣстъ ꙁабранєно ѥстъ", "ipb_already_blocked": "⁖ $1 ⁖ ю ꙁаграждєнъ ѥстъ", @@ -652,12 +663,13 @@ "tooltip-pt-userpage": "{{GENDER:|твоꙗ польꙃєватєл҄ьска}} страница", "tooltip-pt-mytalk": "{{GENDER:|твоꙗ}} бєсѣдꙑ страница", "tooltip-pt-preferences": "{{GENDER:|твои}} строи", - "tooltip-pt-watchlist": "страницѧ ижє ихъжє иꙁмѣнѥниꙗ подъ твоимь блюдєниѥмь сѫтъ", + "tooltip-pt-watchlist": "страницѧ ѩжє ихъжє иꙁмѣнѥниꙗ подъ твоимь блюдєниѥмь сѫтъ", "tooltip-pt-mycontris": "{{GENDER:|твоѩ}} добродѣꙗнии каталогъ", "tooltip-pt-logout": "ис̾ходъ", "tooltip-ca-talk": "сѥѩ страницѧ бєсѣда", "tooltip-ca-edit": "сѥѩ страницѧ исправлѥниѥ", "tooltip-ca-viewsource": "си страница ꙁабранєна ѥстъ ⁙\nѥѩ источьнъ обраꙁъ видєти можєши", + "tooltip-ca-history": "сѥѩ страницѧ прѣждьни обраꙁи", "tooltip-ca-protect": "сѥѩ страницѧ ꙁабранєниѥ", "tooltip-ca-delete": "сѥѩ страницѧ поничьжєниѥ", "tooltip-ca-move": "сѥѩ страницѧ прѣимєнованиѥ", @@ -666,14 +678,16 @@ "tooltip-search-go": "прѣиди къ страницѧ съ симь имєньмь ащє жє та страница ѥстъ", "tooltip-search-fulltext": "исканиѥ страницѧ ижє сѥ напьсаниѥ дрьжатъ", "tooltip-p-logo": "главьна страница", - "tooltip-n-mainpage": "виждь главьноу страницѫ", - "tooltip-n-mainpage-description": "виждь главьноу страницѫ", + "tooltip-n-mainpage": "виждь главьнѫ страницѫ", + "tooltip-n-mainpage-description": "виждь главьнѫ страницѫ", "tooltip-n-recentchanges": "послѣдьн҄ь мѣнъ каталогъ", - "tooltip-t-whatlinkshere": "страницѧ ижє съвѧꙁи дос҄ьдє имѫтъ", + "tooltip-n-randompage": "виждь страницѫ въ нєꙁаапѫ", + "tooltip-t-whatlinkshere": "страницѧ ѩжє съвѧꙁи дос҄ьдє имѫтъ", "tooltip-t-contributions": "{{GENDER:$1|польꙃєватєлꙗ|польꙃєватєлицѧ}} добродѣꙗнии каталогъ", "tooltip-t-upload": "положєниѥ дѣлъ", "tooltip-t-specialpages": "вьсѣѩ нарочьнъ страницѧ каталогъ", "tooltip-t-print": "сѥѩ страницѧ пєчатьнъ обраꙁъ", + "tooltip-t-permalink": "вѣчьна съвѧꙁь съ симь страницѧ обраꙁомь", "tooltip-ca-nstab-user": "виждь польꙃєватєлꙗ страницѫ", "tooltip-ca-nstab-special": "сѥ нарочьна страница ѥстъ · ѥѩжє иꙁмѣнꙗти нє можєши", "tooltip-ca-nstab-image": "виждь дѣла страницѫ", @@ -752,7 +766,7 @@ "tags-deactivate-reason": "какъ съмꙑслъ :", "htmlform-no": "нѣтъ", "htmlform-yes": "да", - "logentry-delete-delete": "$1 {{GENDER:$2|поничьжилъ|поничьжила}} страницѫ ⁖ $3 ⁖", + "logentry-delete-delete": "$1 {{GENDER:$2|поничьжи}} страницѫ ⁖ $3 ⁖", "logentry-block-block": "$1 {{GENDER:$2|ꙁаградилъ|ꙁаградила}} {{GENDER:$4|$3}} на врѣмѧ $5 $6", "logentry-suppress-block": "$1 {{GENDER:$2|ꙁаграждєнъ|ꙁаграждєна}} ѥстъ {{GENDER:$4|$3}} врѣмєньмь $5 $6", "logentry-move-move": "$1 {{GENDER:$2|нарєчє}} страницѫ ⁖ $3 ⁖ имєньмь ⁖ $4 ⁖", diff --git a/languages/i18n/cv.json b/languages/i18n/cv.json index 946c6c97f4..4de9d8c640 100644 --- a/languages/i18n/cv.json +++ b/languages/i18n/cv.json @@ -885,10 +885,10 @@ "tooltip-pt-logout": "Сеансне пĕтер", "tooltip-pt-createaccount": "Аккаунт ту та системӑна кӗр. Паллах, унсӑрах та юрать, анчах та аккаунтпа кӗни лайӑхрах.", "tooltip-ca-talk": "Статьяна сӳтсе явасси", - "tooltip-ca-edit": "Эле тӳрлет", + "tooltip-ca-edit": "Кăна тӳрлет", "tooltip-ca-addsection": "Çĕнĕ пай ту", "tooltip-ca-viewsource": "Ку страницӑна эсир улӑштарма пултараймастӑр. Ӑна мӗнле ҫырнине кӑна пӑхма пултаратӑр.", - "tooltip-ca-history": "Эле улӑштарнин кун-ҫулӗ", + "tooltip-ca-history": "Кунăн улӑшăннисем", "tooltip-ca-protect": "Улӑшратусенчен сыхласси", "tooltip-ca-delete": "Страницӑна кӑларса пӑрахмалли", "tooltip-ca-move": "Страницӑна урӑх ҫӗре куҫарасси", diff --git a/languages/i18n/de.json b/languages/i18n/de.json index 0470691a0e..6b212c91c2 100644 --- a/languages/i18n/de.json +++ b/languages/i18n/de.json @@ -712,8 +712,8 @@ "subject-preview": "Vorschau der Zusammenfassungszeile:", "previewerrortext": "Beim Versuch, eine Vorschau deiner Änderungen anzuzeigen, ist ein Fehler aufgetreten.", "blockedtitle": "Benutzer ist gesperrt", - "blockedtext": "'''Dein Benutzername oder deine IP-Adresse wurde gesperrt.'''\n\nDie Sperrung wurde vom Administrator $1 durchgeführt.\nAls Grund wurde ''$2'' angegeben.\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\nDu kannst die „E-Mail an diesen Benutzer“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\nDeine aktuelle IP-Adresse ist $3 und die Sperrkennung lautet $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.", - "autoblockedtext": "Deine IP-Adresse wurde automatisch gesperrt, da sie von einem anderen Benutzer genutzt wurde, der von $1 gesperrt wurde.\nAls Grund wurde angegeben:\n\n:''$2''\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\n\nDu kannst die „E-Mail an diesen Benutzer“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\n\nDeine aktuelle IP-Adresse ist $3, und die Sperr-ID ist $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.", + "blockedtext": "'''Dein Benutzername oder deine IP-Adresse wurde gesperrt.'''\n\nDie Sperrung wurde vom Administrator $1 durchgeführt.\nAls Grund wurde ''$2'' angegeben.\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\nDu kannst die „{{int:emailuser}}“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\nDeine aktuelle IP-Adresse ist $3 und die Sperrkennung lautet $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.", + "autoblockedtext": "Deine IP-Adresse wurde automatisch gesperrt, da sie von einem anderen Benutzer genutzt wurde, der von $1 gesperrt wurde.\nAls Grund wurde angegeben:\n\n:''$2''\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\n\nDu kannst die „{{int:emailuser}}“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\n\nDeine aktuelle IP-Adresse ist $3, und die Sperr-ID ist $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.", "systemblockedtext": "Dein Benutzername oder deine IP-Adresse wurde von MediaWiki automatisch gesperrt.\nDer angegebene Grund ist:\n\n:$2\n\n* Beginn der Sperre: $8\n* Ablauf der Sperre: $6\n* Sperre betrifft: $7\n\nDeine aktuelle IP-Adresse ist $3.\nBitte gib alle oben stehenden Details in jeder Anfrage an.", "blockednoreason": "keine Begründung angegeben", "whitelistedittext": "Du musst dich $1, um Seiten bearbeiten zu können.", @@ -2049,6 +2049,7 @@ "apisandbox-dynamic-parameters-add-label": "Parameter hinzufügen:", "apisandbox-dynamic-parameters-add-placeholder": "Name des Parameters", "apisandbox-dynamic-error-exists": "Ein Parameter mit dem Namen „$1“ ist bereits vorhanden.", + "apisandbox-templated-parameter-reason": "Diese [[Special:ApiHelp/main#main/templatedparams|Vorlagenparameter]] werden basierend auf {{PLURAL:$1|dem Wert|den Werten}} von $2 angeboten.", "apisandbox-deprecated-parameters": "Veraltete Parameter", "apisandbox-fetch-token": "Den Token automatisch ausfüllen", "apisandbox-add-multi": "Hinzufügen", @@ -4114,5 +4115,6 @@ "pagedata-title": "Seitendaten", "pagedata-text": "Diese Seite stellt eine Datenschnittstelle für Seiten zur Verfügung. Bitte gib mithilfe der Unterseitensyntax den Seitentitel in der URL an.\n* Übertragungen von Inhalten werden basierend auf dem Accept-Header deines Clients ausgeführt. Das bedeutet, dass die Seitendaten in dem Format zur Verfügung gestellt werden, das von deinem Client bevorzugt wird.", "pagedata-not-acceptable": "Kein passendes Format gefunden. Unterstützte MIME-Typen: $1", - "pagedata-bad-title": "Ungültiger Titel: $1." + "pagedata-bad-title": "Ungültiger Titel: $1.", + "unregistered-user-config": "Aus Sicherheitsgründen können JavaScript-, CSS- und JSON-Benutzerunterseiten nicht für unangemeldete Benutzer geladen werden." } diff --git a/languages/i18n/diq.json b/languages/i18n/diq.json index 2ad2c5a77d..1a80395594 100644 --- a/languages/i18n/diq.json +++ b/languages/i18n/diq.json @@ -1226,31 +1226,31 @@ "rcnotefrom": "Cêr de $2 ra nata {{PLURAL:$5|vurnayışiyê}} asenê (tewr vêşi $1 asenê) $3, $4", "rclistfrom": "$3 sehat $2 ra tepiya vurnayışanê neweyan bımotne", "rcshowhideminor": "Vırnayışê werdiy $1", - "rcshowhideminor-show": "Bımotne", + "rcshowhideminor-show": "Bımocne", "rcshowhideminor-hide": "Bınımne", "rcshowhidebots": "botan $1", - "rcshowhidebots-show": "Bımotne", + "rcshowhidebots-show": "Bımocne", "rcshowhidebots-hide": "Bınımne", "rcshowhideliu": "karberê qeydbiyay $1", "rcshowhideliu-show": "Bımocne", "rcshowhideliu-hide": "Bınımne", "rcshowhideanons": "$1 karberê bênamey", - "rcshowhideanons-show": "Bımotne", + "rcshowhideanons-show": "Bımocne", "rcshowhideanons-hide": "Bınımne", "rcshowhidepatr": "$1 vurnayışê ke dewriya geyrayê", "rcshowhidepatr-show": "Bımocne", "rcshowhidepatr-hide": "Bınımne", "rcshowhidemine": "vırnayışê mı $1", - "rcshowhidemine-show": "Bımotne", + "rcshowhidemine-show": "Bımocne", "rcshowhidemine-hide": "Bınımne", "rcshowhidecategorization": "kategorizasyoni $1", - "rcshowhidecategorization-show": "Bımotné", + "rcshowhidecategorization-show": "Bımocne", "rcshowhidecategorization-hide": "Bınımne", "rclinks": "$1 vurnayışê peyênê ke $2 rocanê peyênan de biyê, inan bımocne", "diff": "ferq", "hist": "verên", "hide": "Bınımne", - "show": "Bımotne", + "show": "Bımocne", "minoreditletter": "q", "newpageletter": "N", "boteditletter": "b", @@ -1583,7 +1583,7 @@ "withoutinterwiki": "Perrê ke zıwananê binan rê gıreyê cı çıni yo", "withoutinterwiki-summary": "Enê pelî ke versiyonê ziwanî binî ra link nidano.", "withoutinterwiki-legend": "Verole", - "withoutinterwiki-submit": "Bımotne", + "withoutinterwiki-submit": "Bımocne", "fewestrevisions": "Perrê kı tewr tayn timaryayê", "nbytes": "$1 {{PLURAL:$1|bayt|bayti}}", "ncategories": "$1 {{PLURAL:$1|Kategori|Kategoriy}}", @@ -1650,7 +1650,7 @@ "usereditcount": "$1 {{PLURAL:$1|vurnayîş|vurnayîşî}}", "usercreated": "$2 de $1 {{GENDER:$3|viraziya}}", "newpages": "Perrê newey", - "newpages-submit": "Bımotne", + "newpages-submit": "Bımocne", "newpages-username": "Nameyê karberi:", "ancientpages": "Tewr pelê kıhani", "move": "Bıkırışe", @@ -1689,7 +1689,7 @@ "specialloguserlabel": "Kerdoğ:", "speciallogtitlelabel": "Meqsed (sername ya zi {{ns:user}}:karberi rê nameyê karberi):", "log": "Qeydi", - "logeventslist-submit": "Bımotne", + "logeventslist-submit": "Bımocne", "all-logs-page": "Heme qeydê pêroyi", "alllogstext": "qey {{SITENAME}}i mocnayişê heme rocaneyani.\ntipa rocaneyi, nameyê karberi (herfa pil u qıci re hessas a), ya zi peli (reyna hessasiyê herfa pil u qıciyi) bıweçine u esayiş qıc kerê.", "logempty": "Qeydan dı malumato unasin çıni yo.", @@ -1730,7 +1730,7 @@ "linksearch-line": "$1, $2 ra link biya", "linksearch-error": "jokeri têna nameyê makina ya serekini de aseni/eseni.", "listusersfrom": "karber ê ke pey ıney detpêkeni ramocın:", - "listusers-submit": "Bımotne", + "listusers-submit": "Bımocne", "listusers-noresult": "karber nêdiyayo/a.", "listusers-blocked": "(blok biy)", "activeusers": "Lista karberanê aktifan", @@ -1820,7 +1820,7 @@ "wlnote": "$3 saete $4 ra dıme {{PLURAL:$2|yew saete de|'''$2''' saetan de}} {{PLURAL:$1|vurnayışo peyên|vurnayışê '''$1''' peyêni}} cêrderê.", "wlshowlast": "Peyni de $1 seata u $2 roca bıasne", "watchlist-hide": "Bınımne", - "watchlist-submit": "Bımotne", + "watchlist-submit": "Bımocne", "wlshowtime": "Periyoda zemani asenayışi:", "wlshowhideminor": "vırnayışê werdiy", "wlshowhidebots": "boti", @@ -1859,7 +1859,7 @@ "delete-confirm": "\"$1\" bestere", "delete-legend": "Bestere", "historywarning": "'''Teme:''' Pela ke şıma esterenê tede yew viyarte be teqriben $1 {{PLURAL:$1|versiyon esto|versiyoni estê}}:", - "historyaction-submit": "Bımotne", + "historyaction-submit": "Bımocne", "confirmdeletetext": "Tı ho yew pele u tarixê pele wederneno.\nTı ra rica keno, tı zani tı ho sekeno, tı zani neticeyanê eno wedarnayışi u tı zani tı ser [[{{MediaWiki:Policy-url}}|poliçe]] kar keno.", "actioncomplete": "Kar bi temam", "actionfailed": "kar nêbı", diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 4befdc5331..236d6e598d 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -660,8 +660,8 @@ "subject-preview": "Preview of subject:", "previewerrortext": "An error occurred while attempting to preview your changes.", "blockedtitle": "User is blocked", - "blockedtext": "Your username or IP address has been blocked.\n\nThe block was made by $1.\nThe reason given is $2.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.\nYou cannot use the \"email this user\" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.", - "autoblockedtext": "Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.\nThe reason given is:\n\n:$2\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou may contact $1 or one of the other [[{{MediaWiki:Grouppage-sysop}}|administrators]] to discuss the block.\n\nNote that you may not use the \"email this user\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.\n\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.", + "blockedtext": "Your username or IP address has been blocked.\n\nThe block was made by $1.\nThe reason given is $2.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.\nYou cannot use the \"{{int:emailuser}}\" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.", + "autoblockedtext": "Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.\nThe reason given is:\n\n:$2\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou may contact $1 or one of the other [[{{MediaWiki:Grouppage-sysop}}|administrators]] to discuss the block.\n\nNote that you may not use the \"{{int:emailuser}}\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.\n\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.", "systemblockedtext": "Your username or IP address has been automatically blocked by MediaWiki.\nThe reason given is:\n\n:$2\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYour current IP address is $3.\nPlease include all above details in any queries you make.", "blockednoreason": "no reason given", "whitelistedittext": "Please $1 to edit pages.", @@ -2082,6 +2082,7 @@ "apisandbox-dynamic-parameters-add-label": "Add parameter:", "apisandbox-dynamic-parameters-add-placeholder": "Parameter name", "apisandbox-dynamic-error-exists": "A parameter named \"$1\" already exists.", + "apisandbox-templated-parameter-reason": "This [[Special:ApiHelp/main#main/templatedparams|templated parameter]] is offered based on the {{PLURAL:$1|value|values}} of $2.", "apisandbox-deprecated-parameters": "Deprecated parameters", "apisandbox-fetch-token": "Auto-fill the token", "apisandbox-add-multi": "Add", @@ -4466,5 +4467,6 @@ "pagedata-title": "Page data", "pagedata-text": "This page provides a data interface to pages. Please provide the page title in the URL, using subpage syntax.\n* Content negotiation applies based on your client's Accept header. This means that the page data will be provided in the format preferred by your client.", "pagedata-not-acceptable": "No matching format found. Supported MIME types: $1", - "pagedata-bad-title": "Invalid title: $1." + "pagedata-bad-title": "Invalid title: $1.", + "unregistered-user-config": "For security reasons JavaScript, CSS and JSON user subpages cannot be loaded for unregistered users." } diff --git a/languages/i18n/eo.json b/languages/i18n/eo.json index 7353f90242..58cf7ddcb1 100644 --- a/languages/i18n/eo.json +++ b/languages/i18n/eo.json @@ -548,6 +548,7 @@ "botpasswords-existing": "Ekzistantaj robotaj pasvortoj", "botpasswords-createnew": "Krei novan robotan pasvorton", "botpasswords-editexisting": "Redakti ekzistantan robotan pasvorton", + "botpasswords-label-needsreset": "(oni devas rekomencigi la pasvorton)", "botpasswords-label-appid": "Robota nomo:", "botpasswords-label-create": "Krei", "botpasswords-label-update": "Ĝisdatigi", diff --git a/languages/i18n/es.json b/languages/i18n/es.json index 7199df934a..8360c61565 100644 --- a/languages/i18n/es.json +++ b/languages/i18n/es.json @@ -667,6 +667,7 @@ "botpasswords-existing": "Contraseñas de bots existentes", "botpasswords-createnew": "Crear una contraseña de robot nueva", "botpasswords-editexisting": "Editar una contraseña de robot existente", + "botpasswords-label-needsreset": "(la contraseña debe restablecerse)", "botpasswords-label-appid": "Nombre del robot:", "botpasswords-label-create": "Crear", "botpasswords-label-update": "Actualizar", @@ -690,6 +691,7 @@ "botpasswords-restriction-failed": "Las restricciones de la contraseña de bot impiden este inicio de sesión.", "botpasswords-invalid-name": "El nombre de usuario especificado no contiene el separador de contraseña de bot (\"$1\").", "botpasswords-not-exist": "El usuario \"$1\" no tiene una contraseña de bot llamada \"$2\".", + "botpasswords-needs-reset": "Se debe restablecer la contraseña del robot «$2», propiedad {{GENDER:$1|del usuario|de la usuaria}} «$1».", "resetpass_forbidden": "No se pueden cambiar las contraseñas", "resetpass_forbidden-reason": "Las contraseñas no pueden cambiarse: $1", "resetpass-no-info": "Debes iniciar sesión para acceder directamente a esta página.", @@ -786,7 +788,7 @@ "previewerrortext": "Se ha producido un error al intentar la vista previa de los cambios.", "blockedtitle": "El usuario está bloqueado", "blockedtext": "Tu nombre de usuario o dirección IP ha sido bloqueada.\n\nEl bloqueo lo hizo $1.\nLa razón dada es $2.\n\n* Inicio del bloqueo: $8\n* Caducidad del bloqueo: $6\n* Bloqueo destinado a: $7\n\nPuedes contactar a $1 o con otro de los [[{{MediaWiki:Grouppage-sysop}}|administradores]] para discutir el bloqueo.\nNo puedes utilizar la función «enviar correo electrónico a este usuario» a menos que tengas una dirección de correo electrónico válida registrada en tus [[Special:Preferences|preferencias de usuario]] y la función no haya sido también bloqueada.\n\nTu dirección IP actual es $3, y el identificador del bloqueo es #$5.\nIncluye todos los datos aquí mostrados en cualquier consulta que hagas.", - "autoblockedtext": "Tu dirección IP ha sido bloqueada automáticamente porque fue utilizada por otro usuario, que resultó bloqueado por $1.\nEl motivo dado es el siguiente:\n\n:$2\n\n* Inicio del bloqueo: $8\n* Caducidad del bloqueo: $6\n* Bloqueo destinado a: $7\n\nPuedes contactar con $1 o con otro de los [[{{MediaWiki:Grouppage-sysop}}|administradores]] para discutir el bloqueo.\n\nTen en cuenta que no puedes utilizar la función «enviar correo electrónico a este usuario» a menos que tengas una dirección de correo electrónico válida registrada en tus [[Special:Preferences|preferencias de usuario]] y la función no haya sido también bloqueada.\n\nTu dirección IP actual es $3, y el identificador del bloqueo es #$5.\nIncluye todos los datos aquí mostrados en cualquier consulta que hagas.", + "autoblockedtext": "Tu dirección IP ha sido bloqueada automáticamente porque fue utilizada por otro usuario, que resultó bloqueado por $1.\nEl motivo dado es el siguiente:\n\n:$2\n\n* Inicio del bloqueo: $8\n* Caducidad del bloqueo: $6\n* Bloqueo destinado a: $7\n\nPuedes contactar con $1 o con otro de los [[{{MediaWiki:Grouppage-sysop}}|administradores]] para discutir el bloqueo.\n\nObserva que no puedes utilizar la función «{{int:emailuser}}» a menos que hayas registrado una dirección de correo electrónico válida en tus [[Special:Preferences|preferencias de usuario]] y la función no haya sido también bloqueada.\n\nTu dirección IP actual es $3, y el identificador del bloqueo es n.º $5.\nIncluye todos los datos aquí mostrados en cualquier consulta que hagas.", "systemblockedtext": "Tu nombre de usuario o dirección IP ha sido bloqueado automáticamente por el software MediaWiki.\nLa razón dada es:\n\n:$2\n\n* Inicio del bloqueo: $8\n* Caducidad de bloqueo: $6\n* Destinatario del bloqueo: $7\n\nTu dirección IP actual es $3.\nPor favor, incluye todos los datos aquí mostrados en cualquier consulta que hagas.", "blockednoreason": "no se ha especificado el motivo", "whitelistedittext": "Tienes que $1 para editar páginas.", diff --git a/languages/i18n/eu.json b/languages/i18n/eu.json index f1004875f6..39336558f5 100644 --- a/languages/i18n/eu.json +++ b/languages/i18n/eu.json @@ -628,6 +628,7 @@ "savechanges": "Aldaketak gorde", "publishpage": "Orrialdea argitaratu", "publishchanges": "Aldaketak argitaratu", + "savearticle-start": "Gorde orria...", "savechanges-start": "Aldaketak gorde...", "publishpage-start": "Orrialdea argitaratu...", "publishchanges-start": "Aldaketak argitaratu...", diff --git a/languages/i18n/fi.json b/languages/i18n/fi.json index 0e22f6fed7..7a24fe7173 100644 --- a/languages/i18n/fi.json +++ b/languages/i18n/fi.json @@ -671,8 +671,8 @@ "subject-preview": "Aiheotsikon esikatselu:", "previewerrortext": "Muokkaustesi esikatselun toteuttamisessa on tapahtunut virhe.", "blockedtitle": "Käyttäjä on estetty", - "blockedtext": "'''Käyttäjätunnuksesi tai IP-osoitteesi on estetty.'''\n\nEston on asettanut $1.\nSyy: '''$2'''\n\n* Eston alkamisaika: $8\n* Eston päättymisaika: $6\n* Kohde: $7\n\nVoit keskustella ylläpitäjän $1 tai toisen [[{{MediaWiki:Grouppage-sysop}}|ylläpitäjän]] kanssa estosta.\nHuomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassa olevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] tai jos esto on asetettu koskemaan myös sähköpostin lähettämistä.\nIP-osoitteesi on $3 ja estotunnus on #$5.\nLiitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", - "autoblockedtext": "IP-osoitteesi on estetty automaattisesti, koska sitä on käyttänyt toinen käyttäjä, jonka on estänyt ylläpitäjä $1.\nEston syy on:\n\n:''$2''\n\n* Eston alkamisaika: $8\n* Eston päättymisaika: $6\n* Kohde: $7\n\nVoit keskustella ylläpitäjän $1 tai toisen [[{{MediaWiki:Grouppage-sysop}}|ylläpitäjän]] kanssa estosta.\n\nHuomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassa olevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] tai jos esto on asetettu koskemaan myös sähköpostin lähettämistä.\n\nIP-osoitteesi on $3 ja estotunnus on #$5.\nLiitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", + "blockedtext": "Käyttäjätunnuksesi tai IP-osoitteesi on estetty.\n\nEston on asettanut $1.\nAnnettu syy on $2.\n\n* Eston alkamisaika: $8\n* Eston päättymisaika: $6\n* Kohde: $7\n\nVoit keskustella ylläpitäjän $1 tai toisen [[{{MediaWiki:Grouppage-sysop}}|ylläpitäjän]] kanssa estosta.\nHuomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassa olevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] tai jos esto on asetettu koskemaan myös sähköpostin lähettämistä.\nIP-osoitteesi on $3 ja estotunnus on #$5.\nLiitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", + "autoblockedtext": "IP-osoitteesi on estetty automaattisesti, koska sitä on käyttänyt toinen käyttäjä, jonka on estänyt ylläpitäjä $1.\nAnnettu syy on:\n\n:$2\n\n* Eston alkamisaika: $8\n* Eston päättymisaika: $6\n* Kohde: $7\n\nVoit keskustella ylläpitäjän $1 tai toisen [[{{MediaWiki:Grouppage-sysop}}|ylläpitäjän]] kanssa estosta.\n\nHuomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassa olevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] tai jos esto on asetettu koskemaan myös sähköpostin lähettämistä.\n\nIP-osoitteesi on $3 ja estotunnus on #$5.\nLiitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", "systemblockedtext": "Käyttäjätunnuksesi tai IP-osoitteesi on automaattisesti estetty MediaWikin toimesta.\nAnnettu syy on:\n\n:$2\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nTämänhetkinen IP-osoitteesi on $3.\nOle hyvä ja liitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", "blockednoreason": "(syytä ei annettu)", "whitelistedittext": "Sinun täytyy $1, jotta voisit muokata sivuja.", @@ -1509,7 +1509,7 @@ "recentchangeslinked-feed": "Linkitettyjen sivujen muutokset", "recentchangeslinked-toolbox": "Linkitettyjen sivujen muutokset", "recentchangeslinked-title": "Sivulta $1 linkitettyjen sivujen muutokset", - "recentchangeslinked-summary": "Kirjoita sivun nimi nähdäksesi muutokset sivuihin jotka on linkitetty tai ovat tältä sivulta. (Nähdäksesi luokan jäsenet, kirjoita {{ns:category}}:Luokan nimi). Muutokset sivuihin [[Special:Watchlist|tarkkailulistallasi]] on lihavoitu.", + "recentchangeslinked-summary": "Kirjoita sivun nimi nähdäksesi muutokset sivuihin, joista on linkki tähän sivuun tai joihin on linkki tältä sivulta. (Luokan sisällön saat näkyviin kirjoittamalla {{ns:category}}:Luokan nimen). Muutokset [[Special:Watchlist|tarkkailulistallasi]] oleviin sivuihin on lihavoitu.", "recentchangeslinked-page": "Sivun nimi:", "recentchangeslinked-to": "Näytä sen sijaan muutokset sivuihin, joista on linkki tähän sivuun", "recentchanges-page-added-to-category": "[[:$1]] lisätty luokkaan", diff --git a/languages/i18n/fr.json b/languages/i18n/fr.json index 783a778bed..cd80060225 100644 --- a/languages/i18n/fr.json +++ b/languages/i18n/fr.json @@ -693,7 +693,7 @@ "botpasswords-restriction-failed": "Les restrictions de mot de passe de robots empêchent cette connexion.", "botpasswords-invalid-name": "Le nom d’utilisateur spécifié ne contient pas de séparateur de mot de passe de robots (« $1 »).", "botpasswords-not-exist": "L’{{GENDER:$1|utilisateur|utilisatrice}} « $1 » n’a pas de mot de passe de robot nommé « $2 ».", - "botpasswords-needs-reset": "Le mot de passe du robot de nom \"$2\" de l'utilisat{{GENDER:$1|eur}} \"$1\" doit être réinitialisé.", + "botpasswords-needs-reset": "Le mot de passe du robot de nom « $2 » de l’utilisat{{GENDER:$1|eur|rice}} « $1 » doit être réinitialisé.", "resetpass_forbidden": "Les mots de passe ne peuvent pas être changés", "resetpass_forbidden-reason": "Les mots de passe ne peuvent pas être modifiés : $1", "resetpass-no-info": "Vous devez être connecté(e) pour accéder directement à cette page.", @@ -789,8 +789,8 @@ "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 inclure tous les détails ci-dessus dans chacune des 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: $2.\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 inclure tous les détails ci-dessus dans chacune des requêtes que vous ferez.", + "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 inclure tous les détails ci-dessus dans chacune des 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: $2.\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é « {{int:emailuser}} » 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 inclure tous les détails ci-dessus dans chacune des requêtes que vous ferez.", "systemblockedtext": "Votre nom d'utilisateur ou votre adresse IP ont été bloqués automatiquement par MediaWiki.\nLa raison donnée est la suivante:\n\n: $2.\n\n* Le début du blocage: $8\n* Expiration du délai de blocage: $6\n* Elément concerné: $7\n\nVotre adresse IP actuelle est $3.\nVeuillez inclure tous les détails ci-dessus dans chacune des requêtes que vous ferez.", "blockednoreason": "aucune raison donnée", "whitelistedittext": "Vous devez vous $1 pour avoir la permission de modifier le contenu.", @@ -2132,6 +2132,7 @@ "apisandbox-dynamic-parameters-add-label": "Ajout du paramètre:", "apisandbox-dynamic-parameters-add-placeholder": "Nom du paramètre", "apisandbox-dynamic-error-exists": "Un paramètre nommé \"$1\" existe déjà.", + "apisandbox-templated-parameter-reason": "Ce [[Special:ApiHelp/main#main/templatedparams|paramètre de modèle]] est offert d’après {{PLURAL:$1|la valeur|les valeurs}} de $2.", "apisandbox-deprecated-parameters": "Paramètres désuets", "apisandbox-fetch-token": "Auto-remplissage du jeton", "apisandbox-add-multi": "Ajouter", @@ -4267,5 +4268,6 @@ "pagedata-title": "Données de page", "pagedata-text": "Cette page fournit une interface de données aux pages. Veuillez fournir le titre de la page dans l’URL en utilisant la syntaxe de sous-page.\n* La négociation de contenu s’applique d’après l’entête Accept de votre client. Cela veut dire que les données de la page seront fournies dans le format préféré par votre client.", "pagedata-not-acceptable": "Aucun format correspondant trouvé. Types MIME pris en charge : $1", - "pagedata-bad-title": "Titre non valide : $1." + "pagedata-bad-title": "Titre non valide : $1.", + "unregistered-user-config": "Pour des raisons de sécurité, les sous-pages utilisateur JavaScript, CSS et JSON ne peuvent pas être chargées pour des utilisateurs non inscrits." } diff --git a/languages/i18n/gcr.json b/languages/i18n/gcr.json index 584759be91..3fb3cb6ef0 100644 --- a/languages/i18n/gcr.json +++ b/languages/i18n/gcr.json @@ -122,7 +122,7 @@ "pagecategories": "{{PLURAL:$1|Katégori}}", "category_header": "Paj andan katégori-a « $1 »", "subcategories": "Soukatégori", - "category-media-header": "Médya andan katégori-a « $1 »", + "category-media-header": "Médja annan katégori « $1 »", "category-empty": "Sa katégori pa ka kontni atchwèlman pyès paj ni fiché miltimédya.", "hidden-categories": "{{PLURAL:$1|Katégori kaché}}", "hidden-category-category": "Katégori kaché", @@ -182,7 +182,7 @@ "unprotect": "Chanjé protèksyon-an", "newpage": "Nouvèl paj", "talkpagelinktext": "diskisyon", - "specialpage": "Paj spésyal", + "specialpage": "Paj èspésyal", "personaltools": "Zouti pèrsonèl", "talk": "Diskisyon", "views": "Afichaj", @@ -273,7 +273,7 @@ "nstab-main": "Paj", "nstab-user": "Paj di {{GENDER:{{ROOTPAGENAME}}|itilizatò|itilizatris}}", "nstab-media": "Médja", - "nstab-special": "Paj spésyal", + "nstab-special": "Paj èspésyal", "nstab-project": "À propo", "nstab-image": "Fiché", "nstab-mediawiki": "Mésaj", @@ -283,8 +283,8 @@ "mainpage-nstab": "Paj prensipal", "nosuchaction": "Aksyon enkonèt", "nosuchactiontext": "Aksyon-an spésifyé andan URL-a sa envalid.\nZòt pitèt mal antré URL-a ou swivi roun lyen éroné.\nLi pé égalman endiké oun anomali andan logisyèl itilizé pa {{SITENAME}}.", - "nosuchspecialpage": "Paj spésyal inègzistant", - "nospecialpagetext": "Zòt doumandé oun paj spésyal ki pa ka ègzisté.\n\nOun lis dé paj spésyal valid ka trouvé so kò asou [[Special:SpecialPages|{{int:specialpages}}]].", + "nosuchspecialpage": "Paj èspésyal inègzistant", + "nospecialpagetext": "Zòt doumandé oun paj èspésyal ki pa ka ègzisté.\n\nOun lis dé paj èspésyal valid ka trouvé so kò asou [[Special:SpecialPages|{{int:specialpages}}]].", "error": "Érò", "databaseerror": "Érò di baz di doné", "databaseerror-text": "Oun érò di rékèt di baz di doné aparèt.\nSala pé provini di roun anomali annan lojisyèl-a.", @@ -353,7 +353,7 @@ "mycustomjsprotected": "Zòt pa gen drwè di modifyé sa paj JavaScript.", "myprivateinfoprotected": "Zòt pa gen drwè di modifyé zòt enfòrmasyon pèrsonèl.", "mypreferencesprotected": "Zòt pa gen drwè di modifyé zòt préférans.", - "ns-specialprotected": "Paj spésyal-ya pa pouvé sa modifyé.", + "ns-specialprotected": "Paj èspésyal-ya pa pouvé fika modifyé.", "titleprotected": "Sa tit té protéjé kont tout kréyasyon pa [[User:$1|$1]].\nMotif fourni sa $2.", "filereadonlyerror": "Enposib di modifyé fiché-a « $1 » pas répèrtwar-a di fiché « $2 » sa an lèktir sèl.\n\nAdministratò sistèm ki li vérouyé té fourni sa motif : « $3 ».", "invalidtitle-knownnamespace": "Tit pa valid ké lèspas di non « $2 » é entitilé-a « $3 »", @@ -574,7 +574,7 @@ "nowiki_sample": "Antré tèks ki pa formaté isi", "nowiki_tip": "Ignoré sentaks wiki-a", "image_tip": "Fiché enséré", - "media_tip": "Lyen vèr roun fiché médya", + "media_tip": "Lyen bò'd roun fiché médja", "sig_tip": "Zòt signatir ké dat", "hr_tip": "Lign orizontal (pa an abizé)", "summary": "Rézimé :", @@ -593,7 +593,7 @@ "showpreview": "Prévizwalizé", "showdiff": "Wè modifikasyon-yan", "anoneditwarning": "Panga : zòt pa konèkté. Zòt adrès IP ké sa vizib di tout moun si zòt ka fè dé modifikasyon. Si zòt [$1 ka konèkté zòt kò] ou [$2 kréyé roun kont], zòt modifikasyon ké sq atribwé à zòt pròp non di itilizatò(ris) é zòt ké gen dé ròt avantaj.", - "blockedtext": "Zòt kont itilizatò ou zòt adrès IP bloké.\n\nBlokaj té éfèktchwé pa $1.\nRézon-an évoké sa swivant : $2.\n\n* Koumansman di blokaj : $8\n* Èkspirasyon di blokaj : $6\n* Kont bloké : $7.\n\nZòt pé kontakté $1 ou rounòt [[{{MediaWiki:Grouppage-sysop}}|administratò]] pou an diskité.\nZòt pa pé itilizé fonksyon-an « {{int:emailuser}} » sèlman si oun adrès di kouryé valid sa spésifyé andan zòt [[Special:Preferences|préférans]] é sèlman si sa fonksyonalité pa bloké.\nZòt adrèd IP atchwèl sa $3 é zòt idantifyan di blokaj sa $5.\nSouplé, enkli tout détay-ya lasou'l annan chakin dé rékèt ki zòt ké fè.", + "blockedtext": "Zòt kont itilizatò oben zòt adrès IP bloké.\n\nBlokaj té éfèktchwé pa $1.\nRézon-an évoké sa swivant : $2.\n\n* Koumansman di blokaj : $8\n* Èspirasyon di blokaj : $6\n* Kont bloké : $7.\n\nZòt pé kontakté $1 oben rounòt [[{{MediaWiki:Grouppage-sysop}}|administratò]] pou an diskité.\nZòt pa pouvé itilizé fonksyon-an « {{int:emailuser}} » rounso si oun adrès di kouryé valid sa èspésifyé andan zòt [[Special:Preferences|préférans]] é rounso si sa fonksyonalité pa bloké.\nZòt adrès IP atchwèl sa $3 é zòt idantifyan di blokaj sa $5.\nSouplé, enkli tout détay-ya lasou'l annan chakin dé rékèt ki zòt ké fè.", "loginreqlink": "konèkté so kò", "newarticletext": "Zòt té ka swiv roun lyen vèr roun paj ki pa ka ègzisté òkò. \nAtò di kréyé sa paj, antré zòt tèks annan bwat ki aprè (zòt pé konsilté [$1 paj d'èd-a] pou plis enfòrmasyon).\nSi zòt pa rivé{{GENDER:|}} isi pa éròr, kliké asou bouton Routour di zòt navigatò.", "anontalkpagetext": "----\nZòt asou paj di diskisyon di oun itilizatò anonim ki pa òkò kréyé di kont ou ki pa ka an itilizé.\nPou sa rézon, nou divèt itilizé so adrès IP pou idantifyé li.\nOun adrès IP pé sa partajé pa plizyò itilizatò.\nSi zòt roun itiliza{{GENDER:|ò|ris}} anonim é si zòt ka kontasté ki dé koumantèr ki pa ka konsèrné zòt sa adrèsé à zòt, zòt pé [[Special:CreateAccount|kréyé roun kont]] ou [[Special:UserLogin|konèkté zòt kò]] atò di évité tout konfizyon fitir ké ròt kontribitò anonim.", @@ -725,7 +725,7 @@ "recentchangeslinked-feed": "Swivi dé paj lyé", "recentchangeslinked-toolbox": "Swivi dé paj lyé", "recentchangeslinked-title": "Swivi dé paj asosyé à « $1 »", - "recentchangeslinked-summary": "Antré roun non di paj pou wè modifikasyon-yan ki fè résaman asou dé paj lyé dipi ou vèr sa paj (pou wè manm-yan di oun katégori, antré Katégori:Non di katégori). Modifikasyon-yan dé paj di [[Special:Watchlist|zòt lis di swivi]] sa an gra.", + "recentchangeslinked-summary": "Antré roun non di paj pou wè modifikasyon-yan ki fè résaman asou dé paj lyé dipi oben bò'd sa paj (pou wè manm-yan di oun katégori, antré {{ns:category}}:Non di katégori). Modifikasyon-yan dé paj di [[Special:Watchlist|zòt lis di swivi]] sa an gra.", "recentchangeslinked-page": "Non di paj :", "recentchangeslinked-to": "Afiché modifikasyon-yan dé paj ki ka konpòrté roun lyen vèr paj ki bay plito ki envèrs", "upload": "Enpòrté roun fiché", @@ -755,7 +755,7 @@ "sharedupload-desc-here": "Sa fiché ka provini di $1. Li pé sa itilizé pa dé ròt projè.\nSo dèskripsyon asou so [$2 paj di dèskripsyon] sa afiché anba.", "filepage-nofile": "Pyès fiché di sa non ka ègzisté.", "upload-disallowed-here": "Zòt pa pé ranplasé sa fiché.", - "randompage": "Paj o azar", + "randompage": "Paj o azò", "statistics": "Statistik", "double-redirect-fixer": "Korèktò di roudirèksyon", "nbytes": "$1 {{PLURAL:$1|òktè}}", @@ -884,7 +884,7 @@ "tooltip-n-portal": "À propo di projè, sa ki zòt pé fè, koté trouvé enfòrmasyon-yan", "tooltip-n-currentevents": "Trouvé plis d'enfòrmasyon asou atchwalité an kour", "tooltip-n-recentchanges": "Lis di modifikasyon résant asou wiki-a", - "tooltip-n-randompage": "Afiché roun paj o azar", + "tooltip-n-randompage": "Afiché roun paj o azò", "tooltip-n-help": "Aksè à lèd", "tooltip-t-whatlinkshere": "Lis di paj lyé ki ka pwenté asou sala", "tooltip-t-recentchangeslinked": "Lis di modifikasyon résant liyé à sa paj", @@ -892,12 +892,12 @@ "tooltip-t-contributions": "Wè lis dé kontribisyon di {{GENDER:$1|sa itilizatò|sa itilizatris}}", "tooltip-t-emailuser": "Voyé roun kouryé à {{GENDER:$1|sa itilizatò|sa itilizatris}}", "tooltip-t-upload": "Télévèrsé dé fiché", - "tooltip-t-specialpages": "Lis di tout paj spésyal", + "tooltip-t-specialpages": "Lis di tout paj èspésyal", "tooltip-t-print": "Vèrsyon enprimab di sa paj", "tooltip-t-permalink": "Adrès pèrmanant di sa vèrsyon di paj-a", "tooltip-ca-nstab-main": "Wè kontni di paj-a", "tooltip-ca-nstab-user": "Wè paj di itilizatò", - "tooltip-ca-nstab-special": "A roun paj spésyal, é li pa pé sa modifyé.", + "tooltip-ca-nstab-special": "A roun paj èspésyal, é li pa pouvé fika modifyé.", "tooltip-ca-nstab-project": "Wè paj-a di projè", "tooltip-ca-nstab-image": "Wè paj-a di fiché", "tooltip-ca-nstab-mediawiki": "Wè mésaj sistèm-a", @@ -984,7 +984,7 @@ "watchlisttools-raw": "Modifyé lis di swivi an mòd brout", "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|diskisyon]])", "redirect": "Roudirijé pa ID di fiché, itilizatò, paj, révizyon ou journal", - "redirect-summary": "Sa paj spésyal ka roudirijé vèr roun fiché (non di fiché fourni), oun paj (ID di révizyon ou di paj fourni), oun paj di itilizatò (idantifyan nimérik di itilizatò fourni), ou roun antré di journal (ID di journal fourni). Itilizasyon : [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], ou [[{{#Special:Redirect}}/logid/186]].", + "redirect-summary": "Sa paj èspésyal ka roudirijé bò'd roun fiché (non di fiché fourni), oun paj (ID di révizyon oben di paj fourni), oun paj di itilizatò (idantifyan nimérik di itilizatò fourni), oben roun antré di journal (ID di journal fourni). Itilizasyon : [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], oben [[{{#Special:Redirect}}/logid/186]].", "redirect-submit": "Validé", "redirect-lookup": "Sasé :", "redirect-value": "Valò :", @@ -992,7 +992,7 @@ "redirect-page": "ID di paj", "redirect-revision": "Révizyon di paj-a", "redirect-file": "Non di fiché", - "specialpages": "Paj spésyal", + "specialpages": "Paj èspésyal", "tag-filter": "Filtré [[Special:Tags|baliz]] :", "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Baliz}}]] : $2)", "tags-active-yes": "Wi", diff --git a/languages/i18n/gl.json b/languages/i18n/gl.json index 633d84dcbb..4fb87e7042 100644 --- a/languages/i18n/gl.json +++ b/languages/i18n/gl.json @@ -26,7 +26,8 @@ "Luan", "Hamilton Abreu", "Athena in Wonderland", - "Navhy" + "Navhy", + "PokéDex Nacional" ] }, "tog-underline": "Subliñar as ligazóns:", @@ -63,7 +64,7 @@ "tog-watchlisthideminor": "Agochar as edicións pequenas na lista de vixilancia", "tog-watchlisthideliu": "Agochar as edicións dos usuarios rexistrados na lista de vixilancia", "tog-watchlistreloadautomatically": "Recargar a lista de vixilancia automaticamente cando se produza un cambio nun filtro (necesítase JavaScript)", - "tog-watchlistunwatchlinks": "Engadir ligazóns directos para vixiar ou deixar de vixiar as entradas da lista de páxinas vixiadas (é necesario JavaScript para activar a funcionalidade)", + "tog-watchlistunwatchlinks": "Engadir ligazóns directos para vixiar ou deixar de vixiar ({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) as entradas da lista de páxinas vixiadas (é preciso JavaScript para activar a funcionalidade)", "tog-watchlisthideanons": "Agochar as edicións dos usuarios anónimos na lista de vixilancia", "tog-watchlisthidepatrolled": "Agochar as edicións patrulladas na lista de vixilancia", "tog-watchlisthidecategorization": "Agochar a categorización das páxinas", @@ -532,6 +533,7 @@ "botpasswords-existing": "Contrasinais de bots existentes", "botpasswords-createnew": "Crear un novo contrasinal de bot", "botpasswords-editexisting": "Editar un contrasinal de bot xa existente", + "botpasswords-label-needsreset": "(o contrasinal precisa ser redefinido)", "botpasswords-label-appid": "Nome do bot:", "botpasswords-label-create": "Crear", "botpasswords-label-update": "Actualizar", diff --git a/languages/i18n/he.json b/languages/i18n/he.json index 0946de246b..31b7caa3da 100644 --- a/languages/i18n/he.json +++ b/languages/i18n/he.json @@ -491,7 +491,7 @@ "noemail": "לא רשומה כתובת דואר אלקטרוני עבור ה{{GENDER:$1|משתמש|משתמשת}} \"$1\".", "noemailcreate": "יש לספק כתובת דואר אלקטרוני תקינה.", "passwordsent": "סיסמה חדשה נשלחה לכתובת הדואר האלקטרוני הרשומה עבור \"$1\".\nאנא היכנסו חזרה לאתר אחרי שתקבלו אותה.", - "blocked-mailpassword": "כתובת ה־IP שלך נחסמה מעריכה. כדי למנוע ניצול לרעה, אינך מורשה להשתמש באפשרות שחזור הסיסמה.", + "blocked-mailpassword": "כתובת ה־IP שלך נחסמה מעריכה. כדי למנוע ניצול לרעה, אין באפשרותך להשתמש באפשרות שחזור הסיסמה.", "eauthentsent": "דוא\"ל אימות נשלח לכתובת הדוא\"ל שצוינה.\nלפני שדברי דוא\"ל אחרים יישלחו לחשבון הזה, יהיה {{GENDER:|עליך|עלייך}} לפעול לפי ההוראות בדוא\"ל, כדי לאשר שהחשבון אכן שייך לך.", "throttled-mailpassword": "כבר נשלח דוא\"ל לאיפוס הסיסמה ב{{PLURAL:$1|שעה האחרונה|שעתיים האחרונות|Ö¾$1 השעות האחרונות}}.\nכדי למנוע ניצול לרעה, יכול להישלח רק דוא\"ל אחד כזה בכל {{PLURAL:$1|שעה|שעתיים|$1 שעות}}.", "mailerror": "שגיאה בשליחת דוא\"ל: $1", @@ -656,8 +656,8 @@ "subject-preview": "תצוגה מקדימה של הנושא:", "previewerrortext": "אירעה שגיאה בעת הניסיון להציג תצוגה מקדימה של השינויים שלך.", "blockedtitle": "המשתמש חסום", - "blockedtext": "שם המשתמש או כתובת ה־IP שלך נחסמו.\n\nהחסימה בוצעה על ידי $1.\nהסיבה שניתנה לכך היא $2.\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\nאין באפשרותך להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\" אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", - "autoblockedtext": "כתובת ה־IP שלך נחסמה באופן אוטומטי כיוון שמשתמש אחר, שנחסם על־ידי $1, השתמש בה.\nהסיבה שניתנה לחסימה היא:\n\n:$2\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\n\nאין באפשרותך להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\" אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\n\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", + "blockedtext": "שם המשתמש או כתובת ה־IP שלך נחסמו.\n\nהחסימה בוצעה על־ידי $1.\nהסיבה שניתנה לכך היא $2.\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\nכמו־כן, באפשרותך להשתמש בתכונת \"{{int:emailuser}}\", אלא אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", + "autoblockedtext": "כתובת ה־IP שלך נחסמה באופן אוטומטי כיוון שמשתמש אחר, שנחסם על־ידי $1, השתמש בה.\nהסיבה שניתנה לחסימה היא:\n\n:$2\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\n\nכמו־כן, באפשרותך להשתמש בתכונת \"{{int:emailuser}}\", אלא אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\n\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", "systemblockedtext": "שם המשתמש או כתובת ה־IP שלך נחסמו באופן אוטומטי על־ידי תוכנת מדיה־ויקי.\nהסיבה שניתנה לחסימה היא:\n\n:$2\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nכתובת ה־IP הנוכחית שלך היא $3.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", "blockednoreason": "לא ניתנה סיבה", "whitelistedittext": "נדרשת $1 כדי לערוך דפים.", @@ -1837,7 +1837,7 @@ "listduplicatedfiles-summary": "זוהי רשימה של קבצים שהגרסה החדשה ביותר שלהם זהה לגרסה החדשה ביותר של קובץ אחר כלשהו. רק קבצים מקומיים נבדקים לצורך זה.", "listduplicatedfiles-entry": "לקובץ [[:File:$1|$1]] יש [[$3|{{PLURAL:$2|עותק זהה|$2 עותקים זהים}}]].", "unusedtemplates": "תבניות שאינן בשימוש", - "unusedtemplatestext": "דף זה מכיל רשימה של כל הדפים במרחב השם {{ns:template}} שאינם נכללים בדף אחר. אנא זכרו לבדוק את הקישורים האחרים לתבניות לפני שתמחקו אותן.", + "unusedtemplatestext": "דף זה מכיל רשימה של כל הדפים במרחב השם \"{{ns:template}}\" שאינם נכללים בדף אחר.\nיש לזכור לבדוק את הקישורים האחרים לתבניות לפני מחיקתן.", "unusedtemplateswlh": "קישורים אחרים", "randompage": "דף אקראי", "randompage-nopages": "אין דפים {{PLURAL:$2|במרחב השם הבא|במרחבי השם הבאים}}: $1.", @@ -1882,22 +1882,22 @@ "brokenredirects-edit": "עריכה", "brokenredirects-delete": "מחיקה", "withoutinterwiki": "דפים ללא קישורי שפה", - "withoutinterwiki-summary": "הדפים הבאים אינם מקשרים לגרסאות שלהם בשפות אחרות:", + "withoutinterwiki-summary": "הדפים הבאים אינם מקשרים לגרסאות שלהם בשפות אחרות.", "withoutinterwiki-legend": "תחילית", "withoutinterwiki-submit": "הצגה", "fewestrevisions": "הדפים בעלי מספר העריכות הנמוך ביותר", "nbytes": "{{PLURAL:$1|בית אחד|$1 בתים}}", "ncategories": "{{PLURAL:$1|קטגוריה אחת|$1 קטגוריות}}", - "ninterwikis": "{{PLURAL:$1|קישור בינוויקי קחד|$1 קישורי בינוויקי}}", + "ninterwikis": "{{PLURAL:$1|קישור בינוויקי אחד|$1 קישורי בינוויקי}}", "nlinks": "{{PLURAL:$1|קישור אחד|$1 קישורים}}", "nmembers": "{{PLURAL:$1|דף אחד|$1 דפים}}", "nmemberschanged": "$1 ← {{PLURAL:$2|חבר אחד|$2 חברים}}", "nrevisions": "{{PLURAL:$1|גרסה אחת|$1 גרסאות}}", "nimagelinks": "בשימוש {{PLURAL:$1|בדף אחד|ב־$1 דפים}}", "ntransclusions": "בשימוש {{PLURAL:$1|בדף אחד|ב־$1 דפים}}", - "specialpage-empty": "אין תוצאות.", + "specialpage-empty": "אין תוצאות בדיווח התחזוקה הזה.", "lonelypages": "דפים יתומים", - "lonelypagestext": "הדפים הבאים אינם מקושרים ואינם מוכללים בדפים אחרים באתר {{SITENAME}}.", + "lonelypagestext": "הדפים הבאים אינם מקושרים מדפים אחרים ב{{GRAMMAR:תחילית|{{SITENAME}}}} ואינם מוכללים בהם.", "uncategorizedpages": "דפים חסרי קטגוריה", "uncategorizedcategories": "קטגוריות חסרות קטגוריה", "uncategorizedimages": "קבצים חסרי קטגוריה", @@ -1907,11 +1907,11 @@ "unusedimages": "קבצים שאינם בשימוש", "wantedcategories": "קטגוריות מבוקשות", "wantedpages": "דפים מבוקשים", - "wantedpages-summary": "רשימת דפים לא קיימים שמספר הקישורים אליהם הוא הגדול ביותר, למעט דפים שרק הפניות מקשרות אליהם. לרשימת דפים לא קיימים שיש הפניות המקשרות אליהם, ר' [[{{#special:BrokenRedirects}}|רשימת ההפניות הבלתי־תקינות]].", + "wantedpages-summary": "רשימת דפים לא קיימים שמספר הקישורים אליהם הוא הגדול ביותר, למעט דפים שרק הפניות מקשרות אליהם. לרשימת דפים לא קיימים שיש הפניות המקשרות אליהם, ניתן לעיין ב[[{{#special:BrokenRedirects}}|רשימת ההפניות הבלתי־תקינות]].", "wantedpages-badtitle": "כותרת בלתי תקינה ברשימת התוצאות: $1", "wantedfiles": "קבצים מבוקשים", "wantedfiletext-cat": "הקבצים הבאים נמצאים בשימוש, אך אינם קיימים. ייתכן שקבצים ממאגרים חיצוניים יהיו רשומים אף על פי שהם קיימים, אך שגיאות כאלה יהיו מחוקות. בנוסף, דפים שמטביעים קבצים שאינם קיימים רשומים בדף [[:$1]].", - "wantedfiletext-cat-noforeign": "הקבצים הבאים נמצאים בשימוש, אבל אינם קיימים. כמו־כן, דפים שמשתמשים בקבצים שאינם קיימים רשומים בדף [[:$1]].", + "wantedfiletext-cat-noforeign": "הקבצים הבאים נמצאים בשימוש, אבל אינם קיימים. כמו־כן, דפים שמטביעים קבצים שאינם קיימים רשומים בדף [[:$1]].", "wantedfiletext-nocat": "הקבצים הבאים נמצאים בשימוש, אך אינם קיימים. ייתכן שקבצים ממאגרים חיצוניים יהיו רשומים אף על פי שהם קיימים, אך שגיאות כאלה יהיו מחוקות.", "wantedfiletext-nocat-noforeign": "הקבצים הבאים נמצאים בשימוש, אבל אינם קיימים.", "wantedtemplates": "תבניות מבוקשות", @@ -1923,7 +1923,7 @@ "mostinterwikis": "הדפים עם המספר הרב ביותר של קישורי בינוויקי", "mostrevisions": "הדפים עם מספר העריכות הגבוה ביותר", "prefixindex": "כל הדפים עם התחילית", - "prefixindex-namespace": "כל הדפים עם התחילית (במרחב השם $1)", + "prefixindex-namespace": "כל הדפים עם התחילית (במרחב השם \"$1\")", "prefixindex-submit": "הצגה", "prefixindex-strip": "הסתרת התחילית ברשימה", "shortpages": "דפים קצרים", @@ -1931,9 +1931,9 @@ "deadendpages": "דפים ללא קישורים", "deadendpagestext": "הדפים הבאים אינם מקשרים לדפים אחרים באתר {{SITENAME}}.", "protectedpages": "דפים מוגנים", - "protectedpages-filters": "מסננים:", + "protectedpages-filters": "סינון:", "protectedpages-indef": "הגנות ללא הגבלת זמן בלבד", - "protectedpages-summary": "בדף זה רשומים הדפים הקיימים שמוגנים כרגע. לרשימת הכותרות שמוגנות מפני יצירה, ראו [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].", + "protectedpages-summary": "בדף זה רשומים הדפים הקיימים שמוגנים כרגע. רשימת הכותרות שמוגנות מפני יצירה מופיעה בדף [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].", "protectedpages-cascade": "הגנות מדורגות בלבד", "protectedpages-noredirect": "הסתרת הפניות", "protectedpagesempty": "אין כרגע דפים מוגנים עם הפרמטרים הללו.", @@ -1947,7 +1947,7 @@ "protectedpages-unknown-timestamp": "לא ידוע", "protectedpages-unknown-performer": "משתמש לא ידוע", "protectedtitles": "כותרות מוגנות", - "protectedtitles-summary": "בדף זה רשומות הכותרות של הדפים שמוגנים כעת מפני יצירה. לרשימת הדפים הקיימים שמוגנים, {{GENDER:|ראה|ראי|ראו}} [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].", + "protectedtitles-summary": "בדף זה רשומות הכותרות של הדפים שמוגנים כעת מפני יצירה. רשימת הדפים הקיימים שמוגנים מופיעה בדף [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].", "protectedtitlesempty": "אין כרגע כותרות מוגנות עם הפרמטרים האלה.", "protectedtitles-submit": "הצגת הדפים", "listusers": "רשימת משתמשים", @@ -1962,7 +1962,7 @@ "ancientpages": "דפים מוזנחים", "move": "העברה", "movethispage": "העברת דף זה", - "unusedimagestext": "הקבצים הבאים קיימים אך אינם מוטבעים בשום דף.\nשימו לב שאתרי אינטרנט אחרים עשויים לקשר לקובץ באמצעות כתובת URL ישירה, ולכן הוא עלול להופיע כאן למרות היותו בשימוש פעיל.", + "unusedimagestext": "הקבצים הבאים קיימים, אך אינם מוטבעים בשום דף.\nיש לשים לב לכך שאתרי אינטרנט אחרים עשויים לקשר לקובץ באמצעות כתובת URL ישירה, ולכן הוא עלול להופיע כאן למרות היותו בשימוש פעיל.", "unusedcategoriestext": "הקטגוריות הבאות קיימות, אבל לא נעשה שימוש בהן בשום דף או קטגוריה.", "notargettitle": "אין דף מטרה", "notargettext": "לא ציינת דף מטרה או משתמש לגביו תבוצע פעולה זו.", @@ -1970,14 +1970,14 @@ "nopagetext": "דף המטרה שציינת אינו קיים.", "pager-newer-n": "{{PLURAL:$1|הבאה|$1 הבאות}}", "pager-older-n": "{{PLURAL:$1|הקודמת|$1 הקודמות}}", - "suppress": "הסתרה", + "suppress": "העלמה", "querypage-disabled": "דף מיוחד זה מבוטל עקב בעיות ביצועים.", "apihelp": "עזרה עבור ה־API", "apihelp-no-such-module": "המודול \"$1\" לא נמצא.", "apisandbox": "ארגז החול של ה־API", "apisandbox-jsonly": "דרוש JavaScript כדי להשתמש בארגז החול של ה־API.", "apisandbox-api-disabled": "API אינו פעיל באתר הזה.", - "apisandbox-intro": "השתמשו בדף הזה כדי להתנסות בשימוש בשירות ה־API המבוסס Web של מדיה־ויקי.\nעיינו ב[[mw:API:Main page|תיעוד של ה־API]] (באנגלית) למידע נוסף של שימוש ב־API. למשל: [https://www.mediawiki.org/wiki/API#A_simple_example איך לקבל את התוכן של העמוד הראשי]. בחרו באחת הפעולות (actions) לדוגמאות נוספות.\n\nשימו לב שאף שמדובר ב\"ארגז חול\", פעולות שנעשות כאן עשויות לשנות את התוכן של אתר הוויקי.", + "apisandbox-intro": "ניתן להשתמש בדף הזה כדי להתנסות בשימוש בשירות ה־API המבוסס Web של מדיה־ויקי.\nאפשר לעיין ב[[mw:API:Main page|תיעוד של ה־API]] (באנגלית) למידע נוסף על שימוש ב־API. למשל: [https://www.mediawiki.org/wiki/API#A_simple_example איך לקבל את התוכן של העמוד הראשי]. יש לבחור באחת הפעולות (actions) לדוגמאות נוספות.\n\nלתשומת לבך: אף על פי שמדובר ב\"ארגז חול\", פעולות שנעשות כאן עשויות לשנות את התוכן של אתר הוויקי.", "apisandbox-submit": "ביצוע הבקשה", "apisandbox-reset": "ניקוי", "apisandbox-retry": "ניסיון נוסף", @@ -1990,11 +1990,12 @@ "apisandbox-dynamic-parameters-add-label": "הוספת פרמטר:", "apisandbox-dynamic-parameters-add-placeholder": "שם הפרמטר", "apisandbox-dynamic-error-exists": "פרמטר בשם \"$1\" כבר קיים.", + "apisandbox-templated-parameter-reason": "[[Special:ApiHelp/main#main/templatedparams|פרמטר התבנית]] הזה מוצע בהתבסס על {{PLURAL:$1|הערך של השדה|הערכים של השדות}} $2.", "apisandbox-deprecated-parameters": "פרמטרים מיושנים", "apisandbox-fetch-token": "מילוי אוטומטי של האסימון", "apisandbox-add-multi": "הוספה", "apisandbox-submit-invalid-fields-title": "חלק מהשדות אינם תקינים", - "apisandbox-submit-invalid-fields-message": "אנא תקנו את השדות המסומנים ונסו שוב.", + "apisandbox-submit-invalid-fields-message": "נא לתקן את השדות המסומנים ולנסות שוב.", "apisandbox-results": "תוצאות", "apisandbox-sending-request": "בקשת ה־API בשליחה...", "apisandbox-loading-results": "תוצאות ה־API בתהליך קבלה...", @@ -2005,7 +2006,7 @@ "apisandbox-request-url-label": "כתובת ה־URL של הבקשה:", "apisandbox-request-json-label": "ייצוג הבקשה כ־JSON:", "apisandbox-request-time": "זמן הבקשה: {{PLURAL:$1|מילישנייה אחת|$1 מילישניות}}", - "apisandbox-results-fixtoken": "אנא תקנו את האסימון ושלחו שוב", + "apisandbox-results-fixtoken": "יש לתקן את האסימון ולשלוח שוב", "apisandbox-results-fixtoken-fail": "קבלת האסימון \"$1\" נכשלה.", "apisandbox-alert-page": "שדות בדף זה אינם תקינים.", "apisandbox-alert-field": "הערך של שדה זה אינו תקין.", @@ -2019,8 +2020,8 @@ "booksources-search-legend": "חיפוש משאבי ספרות חיצוניים", "booksources-isbn": "מסת\"ב (ISBN):", "booksources-search": "חיפוש", - "booksources-text": "להלן רשימת קישורים לאתרים אחרים המוכרים ספרים חדשים ויד־שנייה, ושבהם עשוי להיות מידע נוסף לגבי ספרים שאתם מחפשים:", - "booksources-invalid-isbn": "המסת\"ב שניתן כנראה אינו תקין; אנא בדקו אם ביצעתם טעויות בהעתקה מהמידע המקורי.", + "booksources-text": "להלן רשימת קישורים לאתרים אחרים המוכרים ספרים חדשים ויד־שנייה, ושבהם עשוי להיות מידע נוסף לגבי ספרים שמעניינים אותך:", + "booksources-invalid-isbn": "המסת\"ב שניתן כנראה אינו תקין; יש לבדוק אם נעשו טעויות בהעתקה מהמידע המקורי.", "magiclink-tracking-rfc": "דפים שמשתמשים בקישורי קסם ל־RFC", "magiclink-tracking-rfc-desc": "דף זה משתמש בקישורי קסם ל־RFC. באתר [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] מוסבר כיצד יש לשנותם.", "magiclink-tracking-pmid": "דפים שמשתמשים בקישורי קסם ל־PMID", @@ -2047,10 +2048,10 @@ "allpagesfrom": "הצגת דפים החל מ:", "allpagesto": "הצגת דפים עד:", "allarticles": "כל הדפים", - "allinnamespace": "כל הדפים (מרחב השם $1)", + "allinnamespace": "כל הדפים (במרחב השם \"$1\")", "allpagessubmit": "הצגה", - "allpagesprefix": "הדפים ששמם מתחיל ב־:", - "allpagesbadtitle": "כותרת הדף שניתנה הייתה בלתי־תקינה או שהייתה בה קידומת של קישור לשפה אחרת או לוויקי אחר.\nייתכן שהיא מכילה תו אחד או יותר האסורים לשימוש בכותרות.", + "allpagesprefix": "הצגת דפים ששמם מתחיל ב־:", + "allpagesbadtitle": "כותרת הדף שניתנה הייתה בלתי־תקינה או שהייתה בה קידומת של קישור לשפה אחרת או לאתר ויקי אחר.\nייתכן שהיא מכילה תו אחד או יותר האסורים לשימוש בכותרות.", "allpages-bad-ns": "מרחב השם \"$1\" לא קיים ב{{grammar:תחילית|{{SITENAME}}}}.", "allpages-hide-redirects": "הסתרת הפניות", "cachedspecial-viewing-cached-ttl": "זוהי גרסה שמורה בזיכרון המטמון של דף זה, שעשויה להיות בת $1.", @@ -2058,7 +2059,7 @@ "cachedspecial-refresh-now": "צפייה באחרון.", "categories": "קטגוריות", "categories-submit": "הצגה", - "categoriespagetext": "{{PLURAL:$1|הקטגוריה הבאה כוללת|הקטגוריות הבאות כוללות}} דפים או קובצי מדיה.\n[[Special:UnusedCategories|קטגוריות שאינן בשימוש]] אינן מוצגות כאן.\nראו גם את [[Special:WantedCategories|רשימת הקטגוריות המבוקשות]].", + "categoriespagetext": "{{PLURAL:$1|הקטגוריה הבאה כוללת|הקטגוריות הבאות כוללות}} דפים או קובצי מדיה.\n[[Special:UnusedCategories|קטגוריות שאינן בשימוש]] לא מוצגות כאן.\nניתן לעיין גם ב[[Special:WantedCategories|רשימת הקטגוריות המבוקשות]].", "categoriesfrom": "הצגת קטגוריות החל מ:", "deletedcontributions": "תרומות משתמש מחוקות", "deletedcontributions-title": "תרומות משתמש מחוקות", @@ -2090,6 +2091,7 @@ "listgrouprights-helppage": "Help:הרשאות", "listgrouprights-members": "(רשימת חברים)", "listgrouprights-right-display": "$1 ($2)", + "listgrouprights-right-revoked": "$1 ($2)", "listgrouprights-addgroup": "הוספת משתמשים ל{{PLURAL:$2|קבוצה|קבוצות}}: $1", "listgrouprights-removegroup": "הסרת משתמשים מה{{PLURAL:$2|קבוצה|קבוצות}}: $1", "listgrouprights-addgroup-all": "הוספת משתמשים לכל הקבוצות", @@ -2112,13 +2114,13 @@ "trackingcategories-desc": "הקריטריון להכללה בקטגוריה", "restricted-displaytitle-ignored": "דפים שכותרת התצוגה שלהם אינה מופעלת", "restricted-displaytitle-ignored-desc": "בדף הזה מוגדרת כותרת תצוגה ({{DISPLAYTITLE}}) שאינה מופעלת, כי היא אינה תואמת לכותרת האמיתית של הדף.", - "noindex-category-desc": "הדף אינו מאונדקס על‏‏־ידי רובוטים כיוון שהוא כולל את מילת הקסם __NOINDEX__ והוא במרחב שם שבו דגל כזה מותר לשימוש.", - "index-category-desc": "הדף כולל את מילת הקסם __INDEX__ (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן הוא מאונדקס על‏‏֫־ידי רובוטים אף שכברירת מחדל הוא לא היה מאונדקס על ידם.", - "post-expand-template-inclusion-category-desc": "גודל הדף גדול מ‏‏־$wgMaxArticleSize לאחר הרחבת כל התבניות, ולכן כמה תבניות לא הורחבו.", - "post-expand-template-argument-category-desc": "הדף גדול מ־$wgMaxArticleSize לאחר הרחבת ארגומנט של תבנית (משהו בסוגריים משולשים, כגון {{{Foo}}})).", - "expensive-parserfunction-category-desc": "הדף משתמש ביותר מדי פונקציות מפענח יקרות לשימוש (כגון #קיים). ראו [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].", + "noindex-category-desc": "הדף אינו ממופתח על‏‏־ידי רובוטים כיוון שהוא כולל את מילת הקסם __לא_לחיפוש__ (או __NOINDEX__) והוא במרחב שם שבו דגל כזה מותר לשימוש.", + "index-category-desc": "הדף כולל את מילת הקסם __לחיפוש__ (או __INDEX__) (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן הוא ממופתח על־ידי רובוטים אף שכברירת מחדל הוא לא היה ממפותח על־ידיהם.", + "post-expand-template-inclusion-category-desc": "גודל הדף גדול מ‏‏־$wgMaxArticleSize לאחר הרחבת כל התבניות, ולכן כמה תבניות לא הורחבו.", + "post-expand-template-argument-category-desc": "הדף גדול מ־$wgMaxArticleSize לאחר הרחבת פרמטר של תבנית (משהו בסוגריים משולשים, כגון {{{Foo}}}).", + "expensive-parserfunction-category-desc": "הדף משתמש ביותר מדי פונקציות מפענח יקרות לשימוש (כגון #קיים או #ifexist). מידע נוסף: [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].", "broken-file-category-desc": "הדף כולל קישור שבור לקובץ (קישור להטבעת קובץ כאשר הקובץ אינו קיים).", - "hidden-category-category-desc": "הקטגוריה כוללת את הטקסט __קטגוריה_מוסתרת__ בתוכן הדף שלה, ולכן היא לא מופיעה בתיבת קישורי הקטגוריות בדפים כברירת מחדל.", + "hidden-category-category-desc": "הקטגוריה כוללת את הטקסט __קטגוריה_מוסתרת__ (או __HIDDENCAT__) בתוכן הדף שלה, ולכן היא לא מופיעה בתיבת קישורי הקטגוריות בדפים כברירת מחדל.", "trackingcategories-nodesc": "התיאור אינו זמין.", "trackingcategories-disabled": "הקטגוריה מבוטלת", "mailnologin": "אין כתובת לשליחה", @@ -2129,7 +2131,7 @@ "emailpagetext": "ניתן להשתמש בטופס שלהלן כדי לשלוח הודעת דואר אלקטרוני {{GENDER:$1|למשתמש זה|למשתמשת זו}}.\nכתובת הדואר האלקטרוני שהזנת ב[[Special:Preferences|העדפות המשתמש שלך]] תופיע ככתובת שההודעה נשלחה ממנה, כדי לאפשר תגובה ישירה.", "defemailsubject": "דוא\"ל מ{{GRAMMAR:תחילית|{{SITENAME}}}} מה{{GENDER:$1|משתמש|משתמשת}} \"$1\"", "usermaildisabled": "שליחת דוא\"ל למשתמשים מבוטלת", - "usermaildisabledtext": "אינכם מורשים לשלוח דואר אלקטרוני למשתמשים אחרים באתר זה", + "usermaildisabledtext": "אין באפשרותך לשלוח דואר אלקטרוני למשתמשים אחרים באתר זה", "noemailtitle": "אין כתובת דואר אלקטרוני", "noemailtext": "משתמש זה לא הזין כתובת דואר אלקטרוני תקינה.", "nowikiemailtext": "משתמש זה בחר שלא לקבל דואר אלקטרוני ממשתמשים אחרים.", @@ -2143,7 +2145,7 @@ "emailsubject": "נושא:", "emailmessage": "הודעה:", "emailsend": "שליחה", - "emailccme": "שִלחו לי העתק של ההודעה שלי.", + "emailccme": "שלחו לי העתק של ההודעה שלי.", "emailccsubject": "העתק של הודעתך למשתמש $1: $2", "emailsent": "הדואר נשלח", "emailsenttext": "הודעת הדואר האלקטרוני שלך נשלחה.", @@ -2153,26 +2155,26 @@ "watchlist": "רשימת המעקב", "mywatchlist": "רשימת המעקב", "watchlistfor2": "עבור $1 $2", - "nowatchlist": "אין דפים ברשימת המעקב.", + "nowatchlist": "אין דפים ברשימת המעקב שלך.", "watchlistanontext": "נדרשת כניסה לחשבון כדי לצפות או לערוך פריטים ברשימת המעקב.", "watchnologin": "לא נכנסת לחשבון", "addwatch": "הוספה לרשימת המעקב", "addedwatchtext": "הדף \"[[:$1]]\" ודף השיחה שלו נוספו ל[[Special:Watchlist|רשימת המעקב]] שלך.", "addedwatchtext-talk": "הדף \"[[:$1]]\" ודף התוכן המשויך אליו נוספו ל[[Special:Watchlist|רשימת המעקב]] שלך.", - "addedwatchtext-short": "הדף \"$1\" נוסף לרשימת המעקב.", + "addedwatchtext-short": "הדף \"$1\" נוסף לרשימת המעקב שלך.", "removewatch": "הסרה מרשימת המעקב", "removedwatchtext": "הדף \"[[:$1]]\" ודף השיחה שלו הוסרו מ[[Special:Watchlist|רשימת המעקב]] שלך.", "removedwatchtext-talk": "הדף \"[[:$1]]\" ודף התוכן המשויך אליו הוסרו מ[[Special:Watchlist|רשימת המעקב]] שלך.", - "removedwatchtext-short": "הדף \"$1\" הוסר מרשימת המעקב.", + "removedwatchtext-short": "הדף \"$1\" הוסר מרשימת המעקב שלך.", "watch": "מעקב", "watchthispage": "מעקב אחרי דף זה", "unwatch": "הפסקת מעקב", "unwatchthispage": "הפסקת המעקב אחרי דף זה", "notanarticle": "זהו אינו דף תוכן", "notvisiblerev": "הגרסה האחרונה שנוצרה על־ידי משתמש אחר נמחקה", - "watchlist-details": "ברשימת המעקב שלך יש {{PLURAL:$1|דף אחד|$1 דפים}} (ובנוסף להם, דפי שיחה).", + "watchlist-details": "ברשימת המעקב שלך יש {{PLURAL:$1|דף אחד|$1 דפים}} (ובנוסף {{PLURAL:$1|אליו, דף|להם, דפי}} שיחה).", "wlheader-enotif": "הודעות דוא\"ל מאופשרות.", - "wlheader-showupdated": "דפים שהשתנו מאז ביקורך האחרון בהם מוצגים ב'''הדגשה'''.", + "wlheader-showupdated": "דפים שהשתנו מאז ביקורך האחרון בהם מוצגים בהדגשה.", "wlnote": "להלן {{PLURAL:$1|השינוי האחרון|$1 השינויים האחרונים}} {{PLURAL:$2|בשעה האחרונה|בשעתיים האחרונות|ב־$2 השעות האחרונות}}, עד $4, $3.", "wlshowlast": "הצגת $1 שעות אחרונות $2 ימים אחרונים", "watchlist-hide": "הסתרת", @@ -2196,7 +2198,7 @@ "enotif_subject_moved": "הדף \"$1\" ב{{grammar:תחילית|{{SITENAME}}}} הועבר על־ידי $2", "enotif_subject_restored": "הדף \"$1\" ב{{grammar:תחילית|{{SITENAME}}}} שוחזר על־ידי $2", "enotif_subject_changed": "הדף \"$1\" ב{{grammar:תחילית|{{SITENAME}}}} שוּנה על־ידי $2", - "enotif_body_intro_deleted": "הדף \"$1\" באתר {{SITENAME}} נמחק ב־$PAGEEDITDATE על־ידי $2; ראו $3.", + "enotif_body_intro_deleted": "הדף \"$1\" באתר {{SITENAME}} נמחק ב־$PAGEEDITDATE על־ידי $2; להלן הקישור לדף: $3.", "enotif_body_intro_created": "הדף \"$1\" באתר {{SITENAME}} נוצר ב־$PAGEEDITDATE על־ידי $2; ראו $3 לגרסה הנוכחית של הדף.", "enotif_body_intro_moved": "הדף \"$1\" באתר {{SITENAME}} הועבר ב־$PAGEEDITDATE על־ידי $2; ראו $3 לגרסה הנוכחית של הדף.", "enotif_body_intro_restored": "הדף \"$1\" באתר {{SITENAME}} שוחזר ב־$PAGEEDITDATE על־ידי $2; ראו $3 לגרסה הנוכחית של הדף.", @@ -4110,5 +4112,6 @@ "pagedata-title": "מידע על הדף", "pagedata-text": "דף זה מהווה ממשק מידע לדפים. כדי להשתמש בו, כותרת הדף צריכה להופיע בכתובת ה־URL, בעזרת התחביר המתאים לדפי־משנה.\n* דף זה משתמש בשיטת \"ניתוב התוכן\" (Content negotiation) בהתבסס על כותרת ה־Accept ששולח צד הלקוח. פירוש הדבר הוא שהמידע על הדף יישלח בפורמט שצד הלקוח (כגון דפדפן) מעדיף.", "pagedata-not-acceptable": "לא נמצא פורמט נתמך. סוגי MIME נתמכים: $1", - "pagedata-bad-title": "כותרת בלתי־תקינה: $1." + "pagedata-bad-title": "כותרת בלתי־תקינה: $1.", + "unregistered-user-config": "מסיבות אבטחה, לא ניתן לטעון דפי JavaScript‏, CSS ו־JSON בדפי משנה של משתמשים שאינם קיימים." } diff --git a/languages/i18n/hu.json b/languages/i18n/hu.json index f82859f398..804e1ff867 100644 --- a/languages/i18n/hu.json +++ b/languages/i18n/hu.json @@ -669,8 +669,8 @@ "subject-preview": "Tárgy előnézete:", "previewerrortext": "Hiba történt a változások előnézetének megjelenítése során.", "blockedtitle": "A szerkesztő blokkolva van", - "blockedtext": "A szerkesztőnevedet vagy az IP-címedet blokkoltuk.\n\nA blokkolást $1 végezte el.\nAz általa felhozott indok: $2.\n\n* A blokk kezdete: $8\n* A blokk lejárata: $6\n* Blokkolt szerkesztő: $7\n\nKapcsolatba léphetsz $1 szerkesztőnkkel vagy egy másik [[{{MediaWiki:Grouppage-sysop}}|adminisztrátorral]], és megbeszélheted vele a blokkolást.\nAz „E-mail küldése ennek a szerkesztőnek” funkciót csak akkor használhatod, ha érvényes e-mail címet adtál meg [[Special:Preferences|fiókbeállításaidban]], és nem blokkolták a használatát.\nJelenlegi IP-címed: $3, a blokkolás azonosítószáma: #$5.\nKérjük, hogy érdeklődés esetén minden fenti részletet adj meg.", - "autoblockedtext": "Az IP-címed automatikusan blokkolva lett, mert korábban egy olyan szerkesztő használta, akit $1 blokkolt, az alábbi indoklással:\n\n:''$2''\n\n*A blokk kezdete: '''$8'''\n*A blokk lejárata: '''$6'''\n*Blokkolt szerkesztő: '''$7'''\n\nKapcsolatba léphetsz $1 szerkesztőnkkel, vagy egy másik [[{{MediaWiki:Grouppage-sysop}}|adminisztrátorral]], és megbeszélheted vele a blokkolást.\n\nAz 'E-mail küldése ennek a szerkesztőnek' funkciót csak akkor használhatod, ha érvényes e-mail címet adtál meg\n[[Special:Preferences|fiókbeállításaidban]], és nem blokkolták a használatát.\n\nJelenlegi IP-címed: $3, a blokkolás azonosítószáma: #$5.\nKérjük, hogy érdeklődés esetén mindkettőt add meg.", + "blockedtext": "A szerkesztőnevedet vagy az IP-címedet blokkoltuk.\n\nA blokkolást $1 végezte el.\nAz általa felhozott indok: $2.\n\n* A blokk kezdete: $8\n* A blokk lejárata: $6\n* Blokkolt szerkesztő: $7\n\nKapcsolatba léphetsz $1 szerkesztőnkkel vagy egy másik [[{{MediaWiki:Grouppage-sysop}}|adminisztrátorral]], és megbeszélheted vele a blokkolást.\nAz „{{int:emailuser}}” funkciót csak akkor használhatod, ha érvényes e-mail-címet adtál meg [[Special:Preferences|fiókbeállításaidban]], és nem blokkolták a használatát.\nJelenlegi IP-címed: $3, a blokkolás azonosítószáma: #$5.\nKérjük, hogy érdeklődés esetén minden fenti részletet adj meg.", + "autoblockedtext": "Az IP-címed automatikusan blokkolva lett, mert korábban egy olyan szerkesztő használta, akit $1 blokkolt, az alábbi indoklással:\n\n:''$2''\n\n*A blokk kezdete: '''$8'''\n*A blokk lejárata: '''$6'''\n*Blokkolt szerkesztő: '''$7'''\n\nKapcsolatba léphetsz $1 szerkesztőnkkel, vagy egy másik [[{{MediaWiki:Grouppage-sysop}}|adminisztrátorral]], és megbeszélheted vele a blokkolást.\n\nAz „{{int:emailuser}}” funkciót csak akkor használhatod, ha érvényes e-mail címet adtál meg\n[[Special:Preferences|fiókbeállításaidban]], és nem blokkolták a használatát.\n\nJelenlegi IP-címed: $3, a blokkolás azonosítószáma: #$5.\nKérjük, hogy érdeklődés esetén mindkettőt add meg.", "systemblockedtext": "A felhasználónevedet vagy IP-címedet automatikusan blokkolta a MediaWiki.\nA blokkolás indoka:\n\n:$2\n\n* A blokk kezdete: $8\n* A blokk lejárata: $6\n* Blokkolt szerkesztő: $7\n\nA jelenlegi IP-címed: $3.\nKérjük, hogy érdeklődés esetén minden fenti részletet adj meg.", "blockednoreason": "nem adott meg okot", "whitelistedittext": "Lapok szerkesztéséhez $1.", @@ -728,7 +728,7 @@ "longpageerror": "'''HIBA: Az általad beküldött szöveg {{PLURAL:$1|egy kilobájt|$1 kilobájt}} hosszú, ami több az engedélyezett {{PLURAL:$2|egy kilobájtnál|$2 kilobájtnál}}.\nA szerkesztést nem lehet elmenteni.'''", "readonlywarning": "FIGYELMEZTETÉS: A wiki adatbázisát karbantartás miatt zárolták, ezért most nem fogod tudni elmenteni a szerkesztéseidet!\nA lap szövegét másold egy szövegfájlba, amit később felhasználhatsz!\n\nAz adatbázist lezáró rendszeradminisztrátor az alábbi magyarázatot adta: $1", "protectedpagewarning": "Figyelem: Ez a lap védett, így csak adminisztrátori jogosultságokkal rendelkező szerkesztők módosíthatják.\nA legutolsó ide vonatkozó naplóbejegyzés alább látható:", - "semiprotectedpagewarning": "'''Megjegyzés:''' ez a lap védett, így regisztrálatlan vagy újonnan regisztrált szerkesztők nem módosíthatják.", + "semiprotectedpagewarning": "Megjegyzés: ez a lap védett, így regisztrálatlan vagy újonnan regisztrált szerkesztők nem módosíthatják.\nA lapra vonatkozó utolsó naplóbejegyzés alább látható:", "cascadeprotectedwarning": "Figyelem: ez a lap le van zárva, csak [[Special:ListGroupRights|megfelelő jogosultságú]] felhasználók szerkeszthetik, mert a következő kaszkádvédelemmel ellátott {{PLURAL:$1|lapon|lapokon}} be van illesztve:", "titleprotectedwarning": "'''Figyelem: Ez a lap le van védve, így csak a [[Special:ListGroupRights|megfelelő jogosultságokkal]] rendelkező szerkesztők hozhatják létre.'''\nA legutolsó ide vonatkozó naplóbejegyzés alább látható:", "templatesused": "A lapon használt {{PLURAL:$1|sablon|sablonok}}:", @@ -1349,7 +1349,7 @@ "rcfilters-tag-remove": "$1 eltávolítása", "rcfilters-legend-heading": "Rövidítések listája:", "rcfilters-other-review-tools": "Egyéb hasznos hivatkozások", - "rcfilters-group-results-by-page": "Csoportosítás eredményei lapok szerint", + "rcfilters-group-results-by-page": "Eredmények csoportosítása lapok szerint", "rcfilters-activefilters": "Aktív szűrők", "rcfilters-advancedfilters": "Haladó szűrők", "rcfilters-limit-title": "Megjelenítendő találatok száma", @@ -1516,7 +1516,7 @@ "recentchangeslinked-feed": "Kapcsolódó változtatások", "recentchangeslinked-toolbox": "Kapcsolódó változtatások", "recentchangeslinked-title": "A(z) $1 laphoz kapcsolódó változtatások", - "recentchangeslinked-summary": "Alább azon lapoknak a legutóbbi változtatásai láthatóak, amelyekre hivatkozik egy megadott lap. (Ha egy kategória tagjaira vagy kíváncsi, írd be, hogy Kategória:katerógianév.)\nA [[Special:Watchlist|figyelőlistádon]] szereplő lapok '''félkövérrel''' vannak jelölve.", + "recentchangeslinked-summary": "Alább azon lapoknak a legutóbbi változtatásai láthatóak, amelyekre hivatkozik egy megadott lap. (Ha egy kategória tagjaira vagy kíváncsi, írd be, hogy {{ns:category}}:katerógianév.)\nA [[Special:Watchlist|figyelőlistádon]] szereplő lapok félkövérrel vannak jelölve.", "recentchangeslinked-page": "Lap neve:", "recentchangeslinked-to": "Inkább az erre linkelő lapok változtatásait mutasd", "recentchanges-page-added-to-category": "[[:$1]] hozzáadva a kategóriához", @@ -4021,5 +4021,6 @@ "undelete-cantcreate": "Nem állíthatod helyre ezt a lapot, mert nem létezik ilyen című lap, és nincs jogosultságod létrehozni azt.", "pagedata-title": "Az oldal adatai", "pagedata-not-acceptable": "Nem található megfelelő formátum. Támogatott MIME-típusok: $1", - "pagedata-bad-title": "Érvénytelen cím: $1." + "pagedata-bad-title": "Érvénytelen cím: $1.", + "unregistered-user-config": "Biztonsági okokból JavaScript, CSS és JSON szerkesztői alapok nem töltődnek be regisztrálatlan felhasználóknak." } diff --git a/languages/i18n/ia.json b/languages/i18n/ia.json index 3efb8cac29..0c78329f5d 100644 --- a/languages/i18n/ia.json +++ b/languages/i18n/ia.json @@ -54,7 +54,7 @@ "tog-watchlisthideminor": "Celar modificationes minor in le observatorio", "tog-watchlisthideliu": "Celar modificationes de usatores registrate in le observatorio", "tog-watchlistreloadautomatically": "Recargar automaticamente le observatorio quando un filtro es cambiate (JavaScript requirite)", - "tog-watchlistunwatchlinks": "Adjunger ligamines directe pro disobservar/observar al entratas del observatorio (JavaScript es necessari pro le functionalitate de alternar)", + "tog-watchlistunwatchlinks": "Adjunger marcatores directe pro disobservar/observar ({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) al paginas sub observation que ha cambiate (JavaScript es necessari pro le functionalitate de alternar)", "tog-watchlisthideanons": "Celar modificationes de usatores anonyme in le observatorio", "tog-watchlisthidepatrolled": "Celar le modificationes patruliate in le observatorio", "tog-watchlisthidecategorization": "Celar le categorisation de paginas", @@ -362,8 +362,10 @@ "cascadeprotected": "Iste pagina ha essite protegite contra modificationes perque illo es transcludite in le sequente {{PLURAL:$1|pagina, le qual|paginas, le quales}} es protegite usante le option \"cascada\":\n$2", "namespaceprotected": "Tu non ha le permission de modificar paginas in le spatio de nomines '''$1'''.", "customcssprotected": "Tu non ha le permission de modificar iste pagina de CSS perque illo contine le configuration personal de un altere usator.", + "customjsonprotected": "Tu non ha le permission de modificar iste pagina JSON perque illo contine le configuration personal de un altere usator.", "customjsprotected": "Tu non ha le permission de modificar iste pagina de JavaScript perque illo contine le configuration personal de un altere usator.", "mycustomcssprotected": "Tu non ha le permission de modificar iste pagina de CSS.", + "mycustomjsonprotected": "Tu non ha le permission de modificar iste pagina JSON.", "mycustomjsprotected": "Tu non ha le permission de modificar iste pagina de JavaScript.", "myprivateinfoprotected": "Tu non ha le permission de modificar le proprie information private.", "mypreferencesprotected": "Tu non ha le permission de modificar le proprie preferentias.", @@ -458,12 +460,12 @@ "wrongpasswordempty": "Tu non entrava un contrasigno. Per favor reprova.", "passwordtooshort": "Le contrasignos debe continer al minus {{PLURAL:$1|1 character|$1 characteres}}.", "passwordtoolong": "Le contrasignos non pote esser plus longe de {{PLURAL:$1|1 character|$1 characteres}}.", - "passwordtoopopular": "Contrasignos habitual non pote esser usate. Per favor, elige un contrasigno plus unic.", + "passwordtoopopular": "Contrasignos habitual non pote esser usate. Per favor, elige un contrasigno plus difficile a divinar.", "password-name-match": "Tu contrasigno debe esser differente de tu nomine de usator.", "password-login-forbidden": "Le uso de iste nomine de usator e contrasigno ha essite prohibite.", "mailmypassword": "Reinitialisar contrasigno", "passwordremindertitle": "Nove contrasigno temporari pro {{SITENAME}}", - "passwordremindertext": "Alcuno (probabilemente tu, ab le adresse IP $1) requestava un nove\ncontrasigno pro {{SITENAME}} ($4).\nUn contrasigno temporari pro le usator \"$2\" ha essite create; iste\ncontrasigno es \"$3\". Si isto esseva le intention, tu debe ora\naperir un session e eliger un nove contrasigno. Le contrasigno temporari\nexpirara post {{PLURAL:$5|un die|$5 dies}}.\n\nSi un altere persona ha facite iste requesta, o si tu te ha rememorate\nle contrasigno e non plus vole cambiar lo, tu pote ignorar iste message\ne continuar a usar le contrasigno original.", + "passwordremindertext": "Alcuno (ab le adresse IP $1) requestava un nove\ncontrasigno pro {{SITENAME}} ($4).\nUn contrasigno temporari pro le usator \"$2\" ha essite create; iste\ncontrasigno es \"$3\". Si isto esseva le intention, tu debe ora\naperir un session e eliger un nove contrasigno. Le contrasigno temporari\nexpirara post {{PLURAL:$5|un die|$5 dies}}.\n\nSi un altere persona ha facite iste requesta, o si tu te ha rememorate\nle contrasigno e non plus vole cambiar lo, tu pote ignorar iste message\ne continuar a usar le contrasigno original.", "noemail": "Il non ha un adresse de e-mail registrate pro le usator \"$1\".", "noemailcreate": "Es necessari fornir un adresse de e-mail valide", "passwordsent": "Un nove contrasigno ha essite inviate al adresse de e-mail registrate pro \"$1\".\nPer favor aperi session de novo post reciper lo.", @@ -514,6 +516,7 @@ "botpasswords-existing": "Contrasignos de robot existente", "botpasswords-createnew": "Crear un nove contrasigno de robot", "botpasswords-editexisting": "Modificar un contrasigno de robot existente", + "botpasswords-label-needsreset": "(contrasigno debe esser reinitialisate)", "botpasswords-label-appid": "Nomine del robot:", "botpasswords-label-create": "Crear", "botpasswords-label-update": "Actualisar", @@ -537,6 +540,7 @@ "botpasswords-restriction-failed": "Session impedite per restrictiones de contrasigno de robot.", "botpasswords-invalid-name": "Iste nomine de usator non contine le separator pro contrasigno de robot (\"$1\").", "botpasswords-not-exist": "Le usator \"$1\" non ha un contrasigno de robot del nomine \"$2\".", + "botpasswords-needs-reset": "Le contrasigno pro le robot \"$2\" del {{GENDER:$1|usator}} \"$1\" debe esser reinitialisate.", "resetpass_forbidden": "Le contrasignos non pote esser cambiate", "resetpass_forbidden-reason": "Le contrasignos non pote esser cambiate: $1", "resetpass-no-info": "Tu debe aperir un session pro poter acceder directemente a iste pagina.", @@ -614,6 +618,10 @@ "savechanges": "Salveguardar modificationes", "publishpage": "Publicar pagina", "publishchanges": "Publicar modificationes", + "savearticle-start": "Salveguardar pagina…", + "savechanges-start": "Salveguardar modificationes…", + "publishpage-start": "Publicar pagina…", + "publishchanges-start": "Publicar modificationes…", "preview": "Previsualisation", "showpreview": "Monstrar previsualisation", "showdiff": "Detaliar modificationes", @@ -628,8 +636,8 @@ "subject-preview": "Previsualisation del subjecto:", "previewerrortext": "Un error ha occurrite durante le tentativa de previsualisar le cambiamentos.", "blockedtitle": "Le usator es blocate", - "blockedtext": "'''Tu nomine de usator o adresse IP ha essite blocate.'''\n\nLe blocada esseva facite per $1.\nLe motivo presentate es ''$2''.\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Le blocato intendite: $7\n\nTu pote contactar $1 o un altere [[{{MediaWiki:Grouppage-sysop}}|administrator]] pro discuter le blocada.\nTu non pote usar le function 'inviar e-mail a iste usator' salvo que un adresse de e-mail valide es specificate in le\n[[Special:Preferences|preferentias de tu conto]] e que tu non ha essite blocate de usar lo.\nTu adresse IP actual es $3, e le ID del blocada es #$5.\nPer favor include tote le detalios supra specificate in omne correspondentia.", - "autoblockedtext": "Tu adresse de IP ha essite automaticamente blocate proque un altere usator lo usava qui esseva blocate per $1.\nLe motivo presentate es:\n\n:''$2''\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Blocato intendite: $7\n\nTu pote contactar $1 o un del altere [[{{MediaWiki:Grouppage-sysop}}|administratores]] pro discuter le blocada.\n\nNota que tu non pote utilisar le function \"inviar e-mail a iste usator\" salvo que tu ha registrate un adresse de e-mail valide in tu [[Special:Preferences|preferentias de usator]] e que tu non ha essite blocate de usar lo.\n\nTu adresse IP actual es $3, e le ID del blocada es #$5.\nPer favor include tote le detalios supra specificate in omne correspondentia.", + "blockedtext": "Tu nomine de usator o adresse IP ha essite blocate.\n\nLe blocada esseva facite per $1.\nLe motivo presentate es $2.\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Le blocato intendite: $7\n\nTu pote contactar $1 o un altere [[{{MediaWiki:Grouppage-sysop}}|administrator]] pro discuter le blocada.\nTu pote solmente usar le function \"{{int:emailuser}}\" si un adresse de e-mail valide es specificate in le\n[[Special:Preferences|preferentias de tu conto]] e tu non ha essite blocate de usar lo.\nTu adresse IP actual es $3, e le ID del blocada es #$5.\nPer favor include tote le detalios supra specificate in omne correspondentia.", + "autoblockedtext": "Tu adresse IP ha essite automaticamente blocate perque un altere usator lo usava qui esseva blocate per $1.\nLe motivo presentate es:\n\n:$2\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Blocato intendite: $7\n\nTu pote contactar $1 o un del altere [[{{MediaWiki:Grouppage-sysop}}|administratores]] pro discuter le blocada.\n\nNota que tu pote solmente utilisar le function \"{{int:emailuser}}\" si tu ha registrate un adresse de e-mail valide in tu [[Special:Preferences|preferentias de usator]] e tu non ha essite blocate de usar lo.\n\nTu adresse IP actual es $3, e le ID del blocada es #$5.\nPer favor include tote le detalios supra specificate in omne correspondentia.", "systemblockedtext": "Tu nomine de usator o adresse IP ha essite blocate automaticamente per MediaWiki.\nLe motivo presentate es:\n\n:$2\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Blocato intendite: $7\n\nTu adresse IP actual es $3.\nPer favor, include tote le detalios enumerate hic supra in omne questiones que tu pone.", "blockednoreason": "nulle motivo specificate", "whitelistedittext": "Tu debe $1 pro poter modificar paginas.", @@ -652,12 +660,15 @@ "blocked-notice-logextract": "Iste usator es actualmente blocate.\nLe ultime entrata del registro de blocadas es reproducite ci infra pro information:", "clearyourcache": "Nota: Post confirmar, il pote esser necessari refrescar le cache de tu navigator pro vider le cambiamentos.\n* Firefox / Safari: Tenente Shift clicca Reload (Recargar), o preme Ctrl-F5 o Ctrl-R (⌘-R sur Mac)\n* Google Chrome: Preme Ctrl-Shift-R (⌘-Shift-R sur Mac)\n* Internet Explorer: Tenente Ctrl clicca Refresh (Refrescar), o preme Ctrl-F5 \n* Opera: Vade a Menu → Configurationes (Opera → Preferentias sur un Mac) e alora a Privacy & securitate → Rader datos de navigation → Files e imagines in cache.", "usercssyoucanpreview": "'''Consilio:''' Usa le button \"{{int:showpreview}}\" pro testar tu nove CSS ante de salveguardar lo.", + "userjsonyoucanpreview": "Consilio: Usa le button \"{{int:showpreview}}\" pro testar tu nove JSON ante de salveguardar lo.", "userjsyoucanpreview": "'''Consilio:''' Usa le button \"{{int:showpreview}}\" pro testar tu nove JavaScript ante de salveguardar lo.", "usercsspreview": "'''Non oblida que isto es solmente un previsualisation de tu CSS personalisate.'''\n'''Le modificationes non ha ancora essite salveguardate!'''", + "userjsonpreview": "Non oblida que isto es solmente un test/previsualisation de tu configuration JSON personal.\nIllo non ha ancora essite salveguardate!", "userjspreview": "'''Non oblida que isto es solmente un test/previsualisation de tu JavaScript personalisate.'''\n'''Illo non ha ancora essite salveguardate!'''", "sitecsspreview": "'''Non oblida que isto es solmente un previsualisation de iste CSS.'''\n'''Le modificationes non ha ancora essite salveguardate!'''", + "sitejsonpreview": "Non oblida que isto es solmente un previsualisation de iste configuration JSON.\nIllo non ha ancora essite salveguardate!", "sitejspreview": "'''Non oblida que isto es solmente un previsualisation de iste codice JavaScript.'''\n'''Le modificationes non ha ancora essite salveguardate!'''", - "userinvalidconfigtitle": "'''Attention:''' Le apparentia \"$1\" non existe.\nMemora que le paginas .css and .js personalisate usa un titulo in minusculas, p.ex. {{ns:user}}:Foo/vector.css e non {{ns:user}}:Foo/Vector.css.", + "userinvalidconfigtitle": "Attention: Le apparentia \"$1\" non existe.\nMemora que le paginas .css, .json e .js personalisate usa un titulo in minusculas, p.ex. {{ns:user}}:Foo/vector.css e non {{ns:user}}:Foo/Vector.css.", "updated": "(Actualisate)", "note": "'''Nota:'''", "previewnote": "'''Isto es solmente un previsualisation.'''\nLe modificationes non ha ancora essite publicate!", @@ -684,7 +695,7 @@ "longpageerror": "'''Error: Le texto que tu submitteva occupa {{PLURAL:$1|un kilobyte|$1 kilobytes}}, excedente le maximo de {{PLURAL:$2|un kilobyte|$2 kilobytes}}.'''\nIllo non pote esser salveguardate.", "readonlywarning": "Attention: Le base de datos ha essite blocate pro mantenentia. Tu non pote salveguardar tu modificationes in iste momento.\nNos recommenda copiar e collar le texto in un file e salveguardar lo pro plus tarde.\n\nLe administrator de systema qui ha blocate le base de datos ha fornite iste explication: $1", "protectedpagewarning": "'''Attention: Iste pagina ha essite protegite de sorta que solmente usatores con privilegios de administrator pote modificar lo.''' Le ultime entrata del registro es fornite hic infra pro referentia:", - "semiprotectedpagewarning": "'''Nota:''' Iste pagina ha essite protegite de maniera que solmente usatores registrate pote modificar lo. Le ultime entrata del registro es fornite hic infra pro referentia:", + "semiprotectedpagewarning": "Nota: Iste pagina ha essite protegite de maniera que solmente usatores autoconfirmate pote modificar lo. Le ultime entrata del registro es fornite hic infra pro referentia:", "cascadeprotectedwarning": "Attention: Iste pagina ha essite protegite de maniera que solmente usatores con [[Special:ListGroupRights|certe privilegios]] pote modificar lo, perque illo es transcludite in le sequente {{PLURAL:$1|pagina|paginas}} protegite in cascada:", "titleprotectedwarning": "'''Attention: Iste pagina ha essite protegite de maniera que [[Special:ListGroupRights|permissiones specific]] es requirite pro crear lo.''' Le ultime entrata del registro es fornite hic infra pro referentia:", "templatesused": "{{PLURAL:$1|Patrono|Patronos}} usate in iste pagina:", @@ -713,6 +724,7 @@ "postedit-confirmation-created": "Le pagina ha essite create.", "postedit-confirmation-restored": "Le pagina ha essite restaurate.", "postedit-confirmation-saved": "Tu modification ha essite salveguardate.", + "postedit-confirmation-published": "Tu modification ha essite publicate.", "edit-already-exists": "Non poteva crear un nove pagina.\nIllo existe ja.", "defaultmessagetext": "Texto predefinite del message", "content-failed-to-parse": "Impossibile processar le contento $2 pro le modello $1: $3", diff --git a/languages/i18n/ig.json b/languages/i18n/ig.json index d652bd1d6b..2a1d6320c2 100644 --- a/languages/i18n/ig.json +++ b/languages/i18n/ig.json @@ -153,7 +153,7 @@ "history": "Ịta ihüá", "history_short": "Ịta", "updatedmarker": "ihe gáráníru ké mgbe m byàrà nga mbu", - "printableversion": "Ùdì ǹke mbifụ̀", + "printableversion": "Ùdì ǹke mbipụ̀", "permalink": "Jikodo ekechịrị", "print": "Dotié", "view": "Lèzí", @@ -300,8 +300,10 @@ "logout": "Fwuör", "userlogout": "Fwuör", "notloggedin": "I bátà bò", + "userlogin-joinproject": "Bàkọ {{SITENAME}}", "createaccount": "Ké otụ buwa", "createaccountmail": "na e-mail", + "createacct-benefit-heading": "{{SITENAME}} sì nà aka ndị dị kà gị.", "createacct-benefit-body1": "{{PLURAL:$1|ḿmezi}}", "badretype": "Mkpurụ okwu ejị a gafẹ é jëghị.", "userexists": "Áhè ọ'bànifé tírí di na áká onye ozor.\nBíkó nwèré áhà nke ozor.", @@ -1055,6 +1057,7 @@ "pageinfo-header-edits": "Mèzí ịta", "pageinfo-length": "Ogologo ihü (na baitusu)", "pageinfo-article-id": "ID Ihü", + "pageinfo-toolboxlink": "Nkàta ihu", "pageinfo-redirectsto-info": "ọ́márí", "pageinfo-contentpage-yes": "Eeh", "pageinfo-protect-cascading-yes": "Eeh", @@ -1242,7 +1245,7 @@ "special-characters-group-latin": "Latin", "special-characters-group-latinextended": "Latin dọsàrà", "special-characters-group-ipa": "IPA", - "special-characters-group-symbols": "Nkárí", + "special-characters-group-symbols": "Akàrà", "special-characters-group-greek": "Greek", "special-characters-group-cyrillic": "Cyrillic", "special-characters-group-arabic": "Arabiki", diff --git a/languages/i18n/inh.json b/languages/i18n/inh.json index 80cf726cb6..126ac40635 100644 --- a/languages/i18n/inh.json +++ b/languages/i18n/inh.json @@ -154,7 +154,7 @@ "and": " а", "faq": "Каст-кастта телаш дола хаттараш", "actions": "Ардамаш", - "namespaces": "ЦIерий аренаш", + "namespaces": "ЦIерий моттигаш", "variants": "Эршаш", "navigation-heading": "Навигацен меню", "errorpagetitle": "ГӀалат", @@ -284,14 +284,14 @@ "missingarticle-diff": "(башхало: $1, $2)", "internalerror": "Чура гӀалат", "internalerror_info": "Чура гӀалат: $1", - "cannotdelete-title": "Мегаш яц дIаяккха оагIув \"$1\"", + "cannotdelete-title": "ДIаяккха йиш яц «$1» яха оагIув", "badtitle": "Мегаш йоаца цӀи", "badtitletext": "Езаш йола оагӀон цӀи нийса яц, яьсса я, е харцахь йоалаяй меттий юкъера цIи е интервики цӀи. Иштта, цӀера юкъе оттаде мегаш доаца хьаракаш нийсаденна хила мегаш да.", "viewsource": "Хьажар", - "viewsource-title": "Оагӏон $1 духхьара текстага хьажар", - "actionthrottled": "Сухалах доазув дар", - "protectedpagetext": "Ер оагIув лораяь я цу тIа хувцамаш е кхы дола ардамаш дергдоацаш.", - "viewsourcetext": "Укх оагIон доладалара (чура) текста бIаргатоха а кеп яьккха а йиш я хьа.", + "viewsource-title": "$1 яхача оагӏон чухьнахьарча текстага хьажар", + "actionthrottled": "Сухала доазув дар", + "protectedpagetext": "Ер оагIув лораяь я цу тIа хувцамаш дергдоацаш.", + "viewsourcetext": "Укх оагIон чухьнахьарча текстах бIаргатоха а, цунах кеп яьккха а, йиш я хьа.", "virus-unknownscanner": "йовзанза антивирус:", "welcomeuser": "Маьрша воагIалва, доакъашхо $1!", "yourname": "Дагара йоазон цIи:", @@ -396,11 +396,11 @@ "userpage-userdoesnotexist-view": "«$1» яха дагара йоазув долаш дац.", "clearyourcache": "Теркал де. Хетаргахьа, оагIув дIаязъяь яьлча шоай браузера кэш IоцIанъе езаргья шун, даь хувцамаш гургдолаш.\n* Firefox / Safari: Shift яха лак тоIояь лоаттаеш инструментий цхьа дакъа тIа тоIае Обновить е Ctrl-F5 тоIае е Ctrl-R (⌘-R Mac тIа)\n* Google Chrome: ТоIае Ctrl-Shift-R (⌘-Shift-R Mac тIа)\n* Internet Explorer: Ctrl яха лак тоIояь лоаттаеш, тоIае Обновить е Ctrl-F5 тоIае\n* Opera: ДехьагIо Menu → Настройки (Opera → Настройки Mac тIа), тIаккха Безопасность → Очистить историю посещений → Кэшированные изображения и файлы", "note": "'''Белгалдоахар:'''", - "previewnote": "'''Теркам бе, ер хьалххе бIаргтохар мара бац.'''\nХьа хувцамаш хIанза а дIаяздаь дац!", - "continue-editing": "Хувцар кхы дIахо де", + "previewnote": "'''Теркам бе! Ер хьалххе бIаргтохар мара бац.'''\nХьа хувцамаш хIанзехьа кхы а дIаяздаь дац!", + "continue-editing": "Хувцам бергболаш дIахо дехьавáла", "editing": "Хувцам: $1", - "creating": "«$1» оагIув хьакхоллар", - "editingsection": "Хувцам: $1 (оагӀон дáкъа)", + "creating": "«$1» яха оагIув хьакхоллар", + "editingsection": "Хувцар: $1 (оагӀон дáкъа)", "editingcomment": "Хувцам: $1 (оагӀон керда дáкъа)", "editconflict": "Хувцама вIашдухьалъоттам: $1", "yourtext": "Хьа текст", @@ -460,7 +460,7 @@ "mergehistory-reason": "Бахьан:", "mergelog": "ВIашагIтеха хиннарий тептар", "revertmerge": "Дéкъа", - "history-title": "\"$1\" — хувцамай истори", + "history-title": "«$1» яхача оагIон хувцамаш", "difference-title": "$1 — эршашта юкъе йола башхало", "lineno": "МугI $1:", "compareselectedversions": "ВIаши йиста хержа версеш", @@ -510,6 +510,7 @@ "mypreferences": "Оттамаш", "prefs-skin": "ТIера кийчдара тема", "skin-preview": "Хьалххе бIаргтохар", + "prefs-user-pages": "Доакъашхочун оагIонаш", "prefs-personal": "Доакъашхочун дараш", "prefs-rc": "Керда нийсдараш", "prefs-watchlist": "Зéма хьаязъяьр", @@ -532,7 +533,7 @@ "timezoneregion-indian": "Ð¥Iиндий океан", "timezoneregion-pacific": "Тийна океан", "prefs-searchoptions": "Лахар", - "prefs-namespaces": "ЦIерий аренаш", + "prefs-namespaces": "ЦIерий моттигаш", "prefs-files": "Файлаш", "youremail": "Электронни почта:", "username": "{{GENDER:$1|Доакъашхочун цӀи}}:", @@ -711,11 +712,11 @@ "allpages-hide-redirects": "ДIакъайладаха дӀа-хьа хьожавераш", "categories": "ОагӀаташ", "linksearch": "Арахьара тIахьожаяргаш лахар", - "linksearch-ns": "ЦIерий аренаш:", + "linksearch-ns": "ЦIерий моттигаш:", "linksearch-ok": "Хьалаха", "linksearch-line": "$1 яхача оагIонна тIатовжам $2 чура", "listgrouprights-members": "(доакъашхой хьаязъяьр)", - "listgrouprights-namespaceprotection-namespace": "ЦIерий аре", + "listgrouprights-namespaceprotection-namespace": "ЦIерий моттиг", "emailuser": "Доакъашхочоа каьхат", "usermessage-editor": "Системан дIакхоачадар", "watchlist": "Зем бара хьаязъяьр", @@ -773,7 +774,7 @@ "undeletelink": "бIаргтоха/юхадаккха", "undeleteviewlink": "хьажа", "undelete-search-submit": "Хьалáха", - "namespace": "ЦIерий аренаш:", + "namespace": "ЦIерий моттигаш:", "invert": "Хержар юхадаккха", "tooltip-invert": "Оттае ер белгало, хержа цIерий аре чу а (белгалъяь яле вIашагIъювзаенна цIерий аре чу а), оагIонаш тIа а даь хувцамаш къайладоахаргдолаш", "namespace_association": "Ювзаенна аре", diff --git a/languages/i18n/io.json b/languages/i18n/io.json index 8032223eea..eb097e6c2c 100644 --- a/languages/i18n/io.json +++ b/languages/i18n/io.json @@ -696,6 +696,7 @@ "rev-deleted-user-contribs": "[Uzero od IP-adreso eliminita - la redakto celesis de la kontributaji]", "rev-delundel": "montrar/celar", "rev-showdeleted": "montrar", + "revisiondelete": "Efacar/Restaurar revizi", "revdelete-show-file-submit": "Yes", "revdelete-hide-image": "Celar kontenajo dil arkivo", "revdelete-hide-comment": "Rezumo di redakto", @@ -873,6 +874,7 @@ "right-upload": "Adkargar arkivi", "right-writeapi": "Uzez API por skribar", "right-delete": "Efacar pagini", + "right-deleterevision": "Efacar e restaurar specifika revizi de la pagini", "right-browsearchive": "Serchar pagini efacita", "right-suppressrevision": "Vidar, celar e deskovrar specifika revizi di pagini de irga uzero", "right-blockemail": "Blokusar uzero pri sendar e-posto", @@ -1231,6 +1233,7 @@ "deleteotherreason": "Altra/suplementala motivo:", "deletereasonotherlist": "Altra motivo", "deletereason-dropdown": "*Ordinara motivi por efacado\n** \"Spam\" nedezirata mesaji\n** Vandalismo\n** Kopiyuro Violaco\n** Demandita da autoro\n** Nefuncionanta ligilo", + "deleting-backlinks-warning": "Atencez: [[Special:WhatLinksHere/{{FULLPAGENAME}}|Altra pagini]] ligesas ad or inkluzas la pagino quon vu deziras efacar.", "rollback": "Retrorulez redakti", "rollbacklink": "retrorulez", "rollbacklinkcount": "nuligar $1 {{PLURAL:$1|modifiko|modifiki}}", @@ -1276,13 +1279,20 @@ "restriction-upload": "Adkargar", "undelete": "Vidar efacita pagini", "undeletepage": "Vidar e restaurar efacita pagini", + "undeletepagetitle": "Yen la efacita versioni di la pagino [[:$1|$1]].", + "viewdeletedpage": "Vidar pagini efacita", "undeletepagetext": "La sequanta {{PLURAL:$1|pagino|pagini}} efacesis ma {{PLURAL:$1|ol|li}} ankore esas en la arkivo ed esas restaurebla. La arkivo povas netigesar periodale.", + "undelete-fieldset-title": "Restaurar revizi", + "undeleteextrahelp": "Por restaurar omna historio de la pagino, desselektez omna buxi e kliktez {{int:undeletebtn}}.\nPor selektar quala modifiki restauresos, markizez la buxi korespondanta a la revizi por restaurar, e kliktez {{int:undeletebtn}}.", "undeleterevisions": "$1 {{PLURAL:$1|revizo|revizi}} efacita", "undeletehistory": "Se vu restauros la pagino, omna antea revizi restauresos en la korespondanta historiala pagino.\nSe nova pagino kun la sama titulo kreesis pos l'efaco, la restaurita revizuri aparos en lua historiala pagino.", + "undeleterevdel": "La restauro ne facesos se to produktos partala o totala efaco de la maxim recenta revizo.\nCa kazi, vu mustas desselektar o trovar la maxim recenta versiono efacita.", + "undeletehistorynoadmin": "Ica pagino efacesis.\nLa motivo por l'efaco montresas en la rezumo adinfre, kune la detaligo dil uzeri qui redaktis la pagino ante lua efaco.\nLa kompleta texto di ca revizi efacita esas videbla nur por l'administreri.", "undeleterevision-missing": "Nevalida o mankanta revizo.\nSive vu skribis la ligilo nekorekte, sive la revizo restauresis o removesis del arkivo.", "undeletebtn": "Restaurar", "undeletelink": "vidar/restaurar", "undeleteviewlink": "videz", + "undeleteinvert": "Inversigar selektajo", "undeletecomment": "Motivo:", "undeletedpage": "$1 restauresis\n\nVidez la [[Special:Log/delete|'log' pri efaci]] por vidar omna recenta efaci e restauri.", "undelete-search-box": "Serchez efacita pagini", @@ -1678,6 +1688,7 @@ "tags-hitcount": "$1 {{PLURAL:$1|chanjo|chanji}}", "tags-create-explanation": "Segun predefino, la nova etiketi kreita divenos disponebla por uzado, sive da uzeri, sive da informatikoprogrami 'bot'.", "tags-create-warnings-above": "La sequanta {{PLURAL:$2|avizo|avizi}} renkontresis, probante kreir l'etiketo \"$1\":", + "tags-delete-not-found": "L'etiketo \"$1\" ne existas.", "tags-delete-too-many-uses": "L'etiketo \"$1\" uzesas en plua kam $2 {{PLURAL:$2|revizo|revizi}}, do ol ne povas eskartesar.", "tags-delete-warnings-after-delete": "L'etiketo \"$1\" efacesis, ma la sequanta {{PLURAL:$2|avizo|avizi}} renkontresis:", "tags-activate-not-found": "L'etiketo \"$1\" ne existas.", @@ -1701,6 +1712,7 @@ "logentry-protect-modify-cascade": "$1 {{GENDER:$2|modifikis}} la nivelo di protekto di $3 $4 [kaskade]", "logentry-upload-upload": "$1 {{GENDER:$2|uploaded}} $3", "logentry-upload-overwrite": "$1 {{GENDER:$2|parsendis}} nova versiono di $3", + "log-name-tag": "Protokolo di etiketi", "rightsnone": "(nula)", "searchsuggest-search": "Serchez en {{SITENAME}}", "searchsuggest-containing": "quan kontenas...", diff --git a/languages/i18n/is.json b/languages/i18n/is.json index eab988bbc1..d39a413ff3 100644 --- a/languages/i18n/is.json +++ b/languages/i18n/is.json @@ -1199,7 +1199,7 @@ "grant-viewrestrictedlogs": "Skoða lokaðar skráningar", "newuserlogpage": "Skrá yfir nýja notendur", "newuserlogpagetext": "Þetta er skrá yfir nýskráða notendur.", - "rightslog": "Réttindaskrá notenda", + "rightslog": "Réttindaskrá notanda", "rightslogtext": "Þetta er skrá yfir breytingar á réttindum notenda.", "action-read": "lesa þessa síðu", "action-edit": "breyta þessari síðu", @@ -1966,7 +1966,7 @@ "emailuser-title-notarget": "Senda tölvupóst", "emailpagetext": "Hafi notandinn tilgreint netfang í stillingunum sínum er hægt að senda póst til {{GENDER:$1|hans|hennar|hans}} hér.\nPóstfangið sem þú tilgreindir í [[Special:Preferences|stillingunum þínum]] birtist í \"Frá:\" hluta tölvupóstsins, svo að viðtakandi hans geti svarað beint til þín.", "defemailsubject": "{{SITENAME}} skilaboð frá notandanum \"$1\"", - "usermaildisabled": "Netfang notenda er óvirkt", + "usermaildisabled": "Netfang notanda er óvirkt", "usermaildisabledtext": "Þú getur ekki sent tölvupóst til annara notenda á þessum wiki", "noemailtitle": "Ekkert póstfang", "noemailtext": "Þessi notandi hefur ekki tilgreint gilt netfang.", @@ -2383,8 +2383,8 @@ "articleexists": "Annaðhvort er þegar til síða undir þessum titli, eða sá titill sem þú hefur valið er ekki gildur.\nVeldu einhvern annan titil.", "cantmove-titleprotected": "Þú getur ekki fært síðu á þessa staðsetningu, því nýi titillinn hefur verið verndaður gegn sköpun", "movetalk": "Færa meðfylgjandi spjallsíðu", - "move-subpages": "Færa undirstíður (upp að $1)", - "move-talk-subpages": "Færa undirstíður spjallsíðunnar (upp að $1)", + "move-subpages": "Færa undirsíður (upp að $1)", + "move-talk-subpages": "Færa undirsíður spjallsíðunnar (upp að $1)", "movepage-page-exists": "Síðan $1 er nú þegar til og er ekki hægt að yfirskrifa sjálfkrafa.", "movepage-page-moved": "Síðan $1 hefur verið færð á $2.", "movepage-page-unmoved": "Ekki var hægt að færa síðuna $1 á $2.", @@ -3511,7 +3511,7 @@ "tags-edit-reason": "Ástæða:", "tags-edit-success": "Breytingarnar voru framkvæmdar.", "tags-edit-nooldid-title": "Ógild markútgáfa", - "tags-edit-none-selected": "Vinsamlega veldu a.m.k. eitt merki til að bæta við eða fjarlægja.", + "tags-edit-none-selected": "Veldu a.m.k. eitt merki til að bæta við eða fjarlægja.", "comparepages": "Bera saman síður", "compare-page1": "Síða 1", "compare-page2": "Síða 2", diff --git a/languages/i18n/it.json b/languages/i18n/it.json index 3f601e3bf5..4a87f08bf3 100644 --- a/languages/i18n/it.json +++ b/languages/i18n/it.json @@ -734,8 +734,8 @@ "subject-preview": "Anteprima dell'oggetto:", "previewerrortext": "Si è verificato un errore durante il tentativo di mostrare l'anteprima delle tue modifiche.", "blockedtitle": "Utente bloccato.", - "blockedtext": "'''Il tuo nome utente o indirizzo IP è stato bloccato.'''\n\nIl blocco è stato imposto da $1. La motivazione del blocco è la seguente: ''$2''\n\n* Inizio del blocco: $8\n* Scadenza del blocco: $6\n* Intervallo di blocco: $7\n\nSe lo si desidera, è possibile contattare $1 o un altro [[{{MediaWiki:Grouppage-sysop}}|amministratore]] per discutere del blocco.\n\nSi noti che la funzione 'Scrivi all'utente' non è attiva se non è stato registrato un indirizzo e-mail valido nelle proprie [[Special:Preferences|preferenze]] o se l'utilizzo di tale funzione è stato bloccato.\n\nL'indirizzo IP attuale è $3, il numero ID del blocco è #$5.\nSi prega di specificare tutti i dettagli precedenti in qualsiasi richiesta di chiarimenti.", - "autoblockedtext": "Questo indirizzo IP è stato bloccato automaticamente perché condiviso con un altro utente, a sua volta bloccato da $1.\nLa motivazione del blocco è la seguente:\n\n:''$2''\n\n* Inizio del blocco: $8\n* Scadenza del blocco: $6\n* Intervallo di blocco: $7\n\nÈ possibile contattare $1 o un altro [[{{MediaWiki:Grouppage-sysop}}|amministratore]] per richiedere eventuali chiarimenti circa il blocco.\n\nSi noti che la funzione 'Scrivi all'utente' non è attiva se non è stato registrato un indirizzo e-mail valido nelle proprie [[Special:Preferences|preferenze]] e, comunque, se nell'applicare il blocco, tale funzione è stata disabilitata (per la durata del blocco).\n\nL'indirizzo IP attuale è $3, il numero ID del blocco è #$5\nSi prega di specificare tutti i dettagli qui inclusi nel compilare qualsiasi richiesta di chiarimenti.", + "blockedtext": "Il tuo nome utente o indirizzo IP è stato bloccato.\n\nIl blocco è stato imposto da $1. La motivazione del blocco è la seguente: $2.\n\n* Inizio del blocco: $8\n* Scadenza del blocco: $6\n* Intervallo di blocco: $7\n\nSe lo si desidera, è possibile contattare $1 o un altro [[{{MediaWiki:Grouppage-sysop}}|amministratore]] per discutere del blocco.\n\nSi noti che la funzione \"{{int:emailuser}}\" non è attiva se non è stato registrato un indirizzo email valido nelle proprie [[Special:Preferences|preferenze]] o se l'utilizzo di tale funzione è stato bloccato.\n\nL'indirizzo IP attuale è $3, il numero ID del blocco è #$5.\nSi prega di specificare tutti i dettagli precedenti in qualsiasi richiesta di chiarimenti.", + "autoblockedtext": "Questo indirizzo IP è stato bloccato automaticamente perché condiviso con un altro utente, a sua volta bloccato da $1.\nLa motivazione del blocco è la seguente:\n\n:$2\n\n* Inizio del blocco: $8\n* Scadenza del blocco: $6\n* Intervallo di blocco: $7\n\nÈ possibile contattare $1 o un altro [[{{MediaWiki:Grouppage-sysop}}|amministratore]] per richiedere eventuali chiarimenti circa il blocco.\n\nSi noti che la funzione \"{{int:emailuser}}\" non è attiva se non è stato registrato un indirizzo e-mail valido nelle proprie [[Special:Preferences|preferenze]] e, comunque, se nell'applicare il blocco, tale funzione è stata disabilitata (per la durata del blocco).\n\nL'indirizzo IP attuale è $3, il numero ID del blocco è #$5\nSi prega di specificare tutti i dettagli qui inclusi nel compilare qualsiasi richiesta di chiarimenti.", "systemblockedtext": "Il tuo nome utente o l'indirizzo IP è stato bloccato automaticamente da MediaWiki.\nLa motivazione del blocco è la seguente:\n\n:''$2''\n\n* Inizio del blocco: $8\n* Scadenza del blocco: $6\n* Intervallo di blocco: $7\n\nL'indirizzo IP attuale è $3.\nSi prega di specificare tutti i dettagli qui inclusi nel compilare qualsiasi richiesta di chiarimenti.", "blockednoreason": "nessuna motivazione indicata", "whitelistedittext": "Per modificare le pagine è necessario $1.", @@ -4078,5 +4078,6 @@ "undelete-cantedit": "Non puoi ripristinare questa pagina poiché non hai sufficienti permessi per modificarla.", "undelete-cantcreate": "Non puoi ripristinare questa pagina poiché la pagina con questo nome non è ancora inesistente e non hai sufficienti permessi per crearla.", "pagedata-not-acceptable": "Nessun formato corrispondente trovato. Tipi MIME supportati: $1", - "pagedata-bad-title": "Titolo non valido: $1." + "pagedata-bad-title": "Titolo non valido: $1.", + "unregistered-user-config": "Per motivi di sicurezza, non è possibile caricare sottopagine utente JavaScript, CSS e JSON per utenti non registrati." } diff --git a/languages/i18n/ja.json b/languages/i18n/ja.json index 3e5182e527..321c4eb692 100644 --- a/languages/i18n/ja.json +++ b/languages/i18n/ja.json @@ -1473,6 +1473,9 @@ "rcfilters-filter-reviewstatus-unpatrolled-description": "手動または自動で巡回されていない編集。", "rcfilters-filter-reviewstatus-unpatrolled-label": "未巡回", "rcfilters-filter-reviewstatus-manual-description": "巡回済みと手動でマークされた編集。", + "rcfilters-filter-reviewstatus-manual-label": "手動巡回", + "rcfilters-filter-reviewstatus-auto-description": "巡回済みと自動でマークされた編集。", + "rcfilters-filter-reviewstatus-auto-label": "自動巡回", "rcfilters-filtergroup-significance": "重要度", "rcfilters-filter-minor-label": "細部の編集", "rcfilters-filter-minor-description": "編集者が細部の編集とマークしたもの。", diff --git a/languages/i18n/jv.json b/languages/i18n/jv.json index 0d85f3bfa0..f4aa034f79 100644 --- a/languages/i18n/jv.json +++ b/languages/i18n/jv.json @@ -17,7 +17,8 @@ "아라", "Macofe", "Matma Rex", - "Fitoschido" + "Fitoschido", + "Notanotheramy" ] }, "tog-underline": "Garis ngisori pranala:", @@ -575,6 +576,7 @@ "savechanges": "Simpen owahan", "publishpage": "Babar kaca", "publishchanges": "Babar owahan", + "publishchanges-start": "Babar owahan...", "preview": "Pratuduh", "showpreview": "Deleng pratuduh", "showdiff": "Tuduhaké owahan", diff --git a/languages/i18n/ko.json b/languages/i18n/ko.json index 1b899914f5..09164d857b 100644 --- a/languages/i18n/ko.json +++ b/languages/i18n/ko.json @@ -4070,5 +4070,6 @@ "pagedata-title": "문서 데이터", "pagedata-text": "이 문서는 문서에 대한 데이터 인터페이스를 제공합니다. 하위 문서 문법을 사용하여 URL에 문서 제목을 지정해 주십시오.\n* 클라이언트의 Accept 헤더에 기반하여 내용이 절충됩니다. 즉, 문서 데이터는 클라이언트가 선호하는 형식으로 제공됩니다.", "pagedata-not-acceptable": "일치하는 형식을 찾을 수 없습니다. 지원하는 MIME 형식: $1", - "pagedata-bad-title": "유효하지 않은 제목: $1." + "pagedata-bad-title": "유효하지 않은 제목: $1.", + "unregistered-user-config": "보안을 이유로 자바스크립트, CSS, JSON 사용자 하위 문서들은 비등록 사용자에게는 불러올 수 없습니다." } diff --git a/languages/i18n/lb.json b/languages/i18n/lb.json index 8bea39a651..48f92a2289 100644 --- a/languages/i18n/lb.json +++ b/languages/i18n/lb.json @@ -510,6 +510,7 @@ "botpasswords-existing": "Aktuell Botpasswierder.", "botpasswords-createnew": "En neit Botpasswuert uleeën", "botpasswords-editexisting": "E Botpasswuert änneren", + "botpasswords-label-needsreset": "(Passwuert muss zréckgesat ginn)", "botpasswords-label-appid": "Numm vum Bot:", "botpasswords-label-create": "Uleeën", "botpasswords-label-update": "Aktualiséieren", @@ -623,7 +624,7 @@ "subject-preview": "Sujet kucken ouni ze späicheren:", "previewerrortext": "Beim Versuch fir Är Ännerungen ze weisen, ass e Feeler geschitt.", "blockedtitle": "Benotzer ass gespaart", - "blockedtext": "Äre Benotzernumm oder Är IP-Adress gouf gespaart.\n\nD'Spär gouf vum $1 gemaach. Als Grond gouf ''$2'' uginn.\n\n* Ufank vun der Spär: $8\n* Enn vun der Spär: $6\n* Spär betrëfft: $7\n\nDir kënnt den/d' $1 kontaktéieren oder ee vun den aneren [[{{MediaWiki:Grouppage-sysop}}|Administrateure]] fir iwwer d'Spär ze schwätzen.\n\nDëst sollt Dir besonnesch maachen, wann Dir d'Gefill hutt, datt de Grond fir d'Spären net bei Iech läit.\nD'Ursaach dofir ass an deem Fall, datt Dir eng dynamesch IP hutt, iwwer en Access-Provider, iwwer deen och aner Leit fueren.\nAus deem Grond ass et recommandéiert, sech e Benotzernumm zouzeleeën, fir all Mëssverständnes z'evitéieren.\n\nDir kënnt d'Funktioun \"Dësem Benotzer eng E-Mail schécken\" nëmme benotzen, wann Dir eng gëlteg E-Mail Adress bei Ären [[Special:Preferences|Astellungen]] aginn hutt.\nÄr aktuell IP-Adress ass $3 an d'Nummer vun der Spär ass #$5.\nSchreift all dës Informatioune w.e.g. bei all Ufro derbäi.", + "blockedtext": "Äre Benotzernumm oder Är IP-Adress gouf gespaart.\n\nD'Spär gouf vum $1 gemaach.\nAls Grond gouf $2 uginn.\n\n* Ufank vun der Spär: $8\n* Enn vun der Spär: $6\n* Spär betrëfft: $7\n\nDir kënnt den/d' $1 kontaktéieren oder ee vun den aneren [[{{MediaWiki:Grouppage-sysop}}|Administrateure]] fir iwwer d'Spär ze schwätzen.\n\nDëst sollt Dir besonnesch maachen, wann Dir d'Gefill hutt, datt de Grond fir d'Spären net bei Iech läit.\nD'Ursaach dofir ass an deem Fall, datt Dir eng dynamesch IP hutt, iwwer en Access-Provider, iwwer deen och aner Leit fueren.\nAus deem Grond ass et recommandéiert, sech e Benotzernumm zouzeleeën, fir all Mëssverständnes z'evitéieren.\n\nDir kënnt d'Funktioun \"{{int:emailuser}}\" nëmme benotzen, wann Dir eng gëlteg E-Mail Adress bei Ären [[Special:Preferences|Astellungen]] aginn hutt.\nÄr aktuell IP-Adress ass $3 an d'Nummer vun der Spär ass #$5.\nSchreift all dës Informatioune w.e.g. bei all Ufro derbäi.", "autoblockedtext": "Är IP-Adress gouf automatesch gespaart, well se vun engem anere Benotzer gebraucht gouf, an dee vum $1 gespaart gouf.\nDe Grond dofir war:\n\n:''$2''\n\n* Ufank vun der Spär: $8\n* Dauer vun der Spär: $6\n* D'Spär leeft of: $7\n\nDir kënnt de(n) $1 oder soss een [[{{MediaWiki:Grouppage-sysop}}|Administrateur]] kontaktéieren, fir iwwer déi Spär ze diskutéieren.\n\nBedenkt datt Dir d'Funktioun \"Dësem Benotzer eng E-Mail schécken\" benotze kënnt wann Dir eng gëlteg E-Mail-Adress an Ären [[Special:Preferences|Astellungen]] uginn hutt a wann dat net fir Iech gespaart gouf.\n\nÄr aktuell IP-Adress ass $3 an d'Nummer vun Ärer Spär ass $5.\nGitt dës Donnéeë w.e.g bei allen Ufroen zu dëser Spär un.", "blockednoreason": "Kee Grond uginn", "whitelistedittext": "Dir musst Iech $1, fir Säiten änneren ze kënnen.", @@ -1420,7 +1421,7 @@ "recentchangeslinked-feed": "Ännerungen op verlinkt Säiten", "recentchangeslinked-toolbox": "Ännerungen op verlinkt Säiten", "recentchangeslinked-title": "Ännerungen a Verbindung mat \"$1\"", - "recentchangeslinked-summary": "Gitt den Numm vun enger Säit a fir Ännerungen Säiten ze gesinn op déi oder vun deene gelinkt gëtt. Ännerungen op Säite vun [[Special:Watchlist|Ärer Iwwerwaachungslëscht]] si fett geschriwwen.", + "recentchangeslinked-summary": "Gitt den Numm vun enger Säit a fir Ännerungen op Säiten ze gesinn op déi oder vun deene gelinkt gëtt. (Fir d'Membere vun enger Kategorie ze gesinn gitt {{ns:category}}:Numm vun der Kategorie, an.) Ännerungen op Säite vun [[Special:Watchlist|Ärer Iwwerwaachungslëscht]] si fett geschriwwen.", "recentchangeslinked-page": "Säitennumm:", "recentchangeslinked-to": "Weis Ännerungen zu de verlinkte Säiten aplaz vun der gefroter Säit", "recentchanges-page-added-to-category": "[[:$1]] an d'Kategorie dobäigesat", diff --git a/languages/i18n/lfn.json b/languages/i18n/lfn.json index bad0415525..4f61fd5532 100644 --- a/languages/i18n/lfn.json +++ b/languages/i18n/lfn.json @@ -10,7 +10,8 @@ "Katxis", "Chabi", "Angel Blaise", - "Fitoschido" + "Fitoschido", + "Robin van der Vliet" ] }, "tog-underline": "Sulini de lias:", @@ -232,7 +233,7 @@ "disclaimerpage": "Project:Renunsia jeneral", "edithelp": "Aida sur edita", "helppage-top-gethelp": "Aida", - "mainpage": "Paje Xef", + "mainpage": "Paje xef", "mainpage-description": "Paje xef", "policy-url": "Project:Politica", "portal": "Porton de comunia", @@ -618,7 +619,7 @@ "subject-preview": "Previde de tema:", "previewerrortext": "Un era ia aveni en atenta previde tua cambias.", "blockedtitle": "Usor es impedida", - "blockedtext": "Tua nom de usor o adirije IP es impedida.\n\nLa impedi ia es fada par $1.\nLa razona donada es ''$2''.\n\n* Comensa de impedi: $8\n* Fini de impedi: $6\n* Conta impedida: $7\n\nTu pote contata $1 o un otra [[{{MediaWiki:Grouppage-sysop}}|dirijor]] per discute esta impedi.\nTu no pote usa la funsiona \"envia un eposta a esta usor\" estra si un adirije valida\nde eposta es spesifada en tua [[Special:Preferences|preferes de conta]] e tu no es impedida de usa lo.\nTua adirije IP presente es $3, e la numero de impedi es #$5.\nInclui tota esta detalias en cualce demandas cual tu fa, per favore.", + "blockedtext": "Tua nom de usor o adirije IP es impedida.\n\nLa impedi ia es fada par $1.\nLa razona donada es $2.\n\n* Comensa de impedi: $8\n* Fini de impedi: $6\n* Conta impedida: $7\n\nTu pote contata $1 o un otra [[{{MediaWiki:Grouppage-sysop}}|dirijor]] per discute esta impedi.\nTu no pote usa la funsiona \"{{int:emailuser}}\" estra si un adirije valida\nde eposta es spesifada en tua [[Special:Preferences|preferes de conta]] e tu no es impedida de usa lo.\nTua adirije IP presente es $3, e la numero de impedi es #$5.\nInclui tota esta detalias en cualce demandas cual tu fa, per favore.", "autoblockedtext": "Tua adirije IP ia es automata impedida car lo ia es usada par un otra usor, ci ia es impedida par $1.\nLa razona donada es ''$2''.\n\n* Comensa de impedi: $8\n* Fini de impedi: $6\n* Conta impedida: $7\n\nTu pote contata $1 o un otra [[{{MediaWiki:Grouppage-sysop}}|dirijor]] per discute esta impedi.\nTu no pote usa la funsiona \"envia un eposta a esta usor\" estra si un adirije valida de eposta es spesifada en tua [[Special:Preferences|preferes de conta]] e tu no es impedida de usa lo.\nTua adirije IP presente es $3, e la numero de impedi es #$5.\nInclui tota esta detalias en cualce demandas cual tu fa, per favore.", "systemblockedtext": "Tua nom de usor o adirije IP ia es automata impedida par MediaWiki.\nLa razona donada es $2.\n\n* Comensa de impedi: $8\n* Fini de impedi: $6\n* Conta impedida: $7\nTua adirije IP presente es $3.\nInclui tota esta detalias en cualce demandas cual tu fa, per favore.", "blockednoreason": "no razona donada", @@ -1451,7 +1452,7 @@ "recentchangeslinked-feed": "Cambias relatada", "recentchangeslinked-toolbox": "Cambias relatada", "recentchangeslinked-title": "Cambias relatada a \"$1\"", - "recentchangeslinked-summary": "Tape un nom de paje per vide cambias en pajes liada a o de acel paje. (Per vide membros de un categoria, tape bold.) Cambias a pajes en [[Special:Watchlist|tua lista monitorida]] es spesa.", + "recentchangeslinked-summary": "Tape un nom de paje per vide cambias en pajes liada a o de acel paje. (Per vide membros de un categoria, tape {{ns:category}}:Nom de categoria.) Cambias a pajes en [[Special:Watchlist|tua lista monitorida]] es spesa.", "recentchangeslinked-page": "Nom de paje:", "recentchangeslinked-to": "Mostra cambias a pajes cual lia a la paje indicada, en loca", "recentchanges-page-added-to-category": "[[:$1]] ajuntada a categoria", @@ -1931,6 +1932,7 @@ "apisandbox-dynamic-error-exists": "Un parametre nomida \"$1\" esiste ja.", "apisandbox-deprecated-parameters": "Parametres desaprobada", "apisandbox-fetch-token": "Autopleni la marca", + "apisandbox-add-multi": "Ajunta", "apisandbox-submit-invalid-fields-title": "Alga campos es nonvalida", "apisandbox-submit-invalid-fields-message": "Coreti la campos indicada, per favore, e reatenta.", "apisandbox-results": "Resultas", @@ -3705,6 +3707,7 @@ "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|bait|baites}}", "limitreport-expansiondepth": "Profondia la plu grande de despaci", "limitreport-expensivefunctioncount": "Cuantia de funsionas custosa de analisador sintatical", + "limitreport-unstrip-size-value": "$1/$2 {{PLURAL:$2|bait|baites}}", "expandtemplates": "Despaci stensiles", "expand_templates_intro": "Esta paje spesial prende vicitesto e despaci tota stensiles en lo, en modo recorsante. Lo despaci ance funsionas suportada de analisador sintatical como {{#language:…}} e variables como {{CURRENTDAY}}. En fato, lo despaci cuasi tota cosas entre brasetas risa duple.", "expand_templates_title": "Titulo de contesto, per {{FULLPAGENAME}}, etc.:", diff --git a/languages/i18n/lv.json b/languages/i18n/lv.json index 0c88fe6cd4..6f4154e79b 100644 --- a/languages/i18n/lv.json +++ b/languages/i18n/lv.json @@ -485,12 +485,14 @@ "user-mail-no-addy": "Mēģināja sÅ«tÄ«t e-pastu bez e-pasta adreses.", "user-mail-no-body": "Mēģināja sÅ«tÄ«t e-pastu ar tukÅ¡u vai nepamatoti Ä«su pamata daļu.", "changepassword": "MainÄ«t paroli", + "resetpass_announce": "Lai pabeigtu pieslēgÅ¡anos, tev ir jāuzstāda jauna parole.", "resetpass_header": "MainÄ«t konta paroli", "oldpassword": "Vecā parole", "newpassword": "Jaunā parole", "retypenew": "Atkārto jauno paroli", "resetpass_submit": "UzstādÄ«t paroli un ieiet", "changepassword-success": "Tava parole tika nomainÄ«ta!", + "changepassword-throttled": "JÅ«s esat veicis pārāk daudz pieslēgÅ¡anās mēģinājumus.\nLÅ«dzu, uzgaidiet $1 pirms mēģiniet vēlreiz.", "botpasswords": "Botu paroles", "botpasswords-disabled": "Botu paroles ir atspējotas.", "botpasswords-no-central-id": "Lai izmantotu botu paroles, tev jāpieslēdzas centralizētajam kontam.", @@ -709,6 +711,7 @@ "history-feed-description": "Å Ä«s wiki lapas versiju hronoloÄ£ija", "history-feed-item-nocomment": "$1 : $2", "history-feed-empty": "PieprasÄ«tā lapa nepastāv.\nIespējams, tā ir izdzēsta vai pārdēvēta.\nMēģiniet [[Special:Search|meklēt]], lai atrastu saistÄ«tas lapas!", + "history-edit-tags": "Labot iezÄ«mes izvēlētajām versijām", "rev-deleted-comment": "(labojuma kopsavilkums dzēsts)", "rev-deleted-user": "(lietotāja vārds nodzēsts)", "rev-deleted-event": "(reÄ£istra detaļas noņemtas)", @@ -819,6 +822,7 @@ "search-category": "(kategorija $1)", "search-file-match": "(atbilst faila saturam)", "search-suggest": "Vai jÅ«s domājāt: $1", + "search-rewritten": "Rāda rezultātus frāzei \"$1\". Meklēt pēc \"$2\".", "search-interwiki-caption": "Rezultāti no citiem projektiem", "search-interwiki-default": "Rezultāti no $1:", "search-interwiki-more": "(vairāk)", @@ -903,6 +907,7 @@ "default": "pēc noklusējuma", "prefs-files": "Faili", "prefs-custom-css": "PersonÄ«gais CSS", + "prefs-custom-json": "Pielāgots JSON", "prefs-custom-js": "PersonÄ«gais JS", "prefs-common-config": "Koplietojams CSS/JavaScript visās apdarēs:", "prefs-emailconfirm-label": "E-pasta statuss:", @@ -1024,8 +1029,10 @@ "right-editcontentmodel": "Labot lapas satura modeli", "right-editinterface": "IzmainÄ«t dalÄ«bnieka interfeisu", "right-editusercss": "IzmainÄ«t citu dalÄ«bnieku CSS failus", + "right-edituserjson": "IzmainÄ«t citu dalÄ«bnieku JSON failus", "right-edituserjs": "IzmainÄ«t citu dalÄ«bnieku JS failus", "right-editmyusercss": "Rediģējiet savus dalÄ«bnieka CSS failus", + "right-editmyuserjson": "IzmainÄ«t savus dalÄ«bnieka JSON failus", "right-editmyuserjs": "Rediģējiet savus dalÄ«bnieka JavaScript failus", "right-viewmywatchlist": "ApskatÄ«t savu uzraugāmo rakstu sarakstu", "right-viewmyprivateinfo": "Skatit savus privātos datus (piemēram, e-pasta adresi, Ä«sto vārdu)", @@ -1273,7 +1280,7 @@ "recentchangeslinked-feed": "SaistÄ«tās izmaiņas", "recentchangeslinked-toolbox": "SaistÄ«tās izmaiņas", "recentchangeslinked-title": "Izmaiņas, kas saistÄ«tas ar \"$1\"", - "recentchangeslinked-summary": "Å iet ir nesen izdarÄ«tās izmaiņas lapās, uz kurām ir saites no norādÄ«tās lapas (vai norādÄ«tajā kategorijā ietilpstošās lapas).\nLapas, kas ir tavā [[Special:Watchlist|uzraugāmo rakstu sarakstā]] ir '''treknas'''.", + "recentchangeslinked-summary": "Ievadi lapas nosaukumu, lai redzētu izmaiņas lapās, uz kurām vai vai no kuras ir saites ar Å¡o lapu (Lai redzētu kategorijā ietilpstošās, norādi {{ns:category}}:Kategorijas nosaukums).\nIzmaiņas lapās, kas ir tavā [[Special:Watchlist|uzraugāmo rakstu sarakstā]] ir treknrakstā.", "recentchangeslinked-page": "Lapas nosaukums:", "recentchangeslinked-to": "RādÄ«t izmaiņas lapās, kurās ir saites uz Å¡o lapu (nevis lapās uz kurām ir saites no Å¡Ä«s lapas)", "autochange-username": "MediaWiki automātiskā izmaiņa", @@ -1394,6 +1401,8 @@ "uploadstash-errclear": "Failu tÄ«rÄ«Å¡ana neizdevās.", "uploadstash-refresh": "Atsvaidzināt failu sarakstu", "uploadstash-thumbnail": "aplÅ«kot sÄ«kbildi", + "uploadstash-bad-path": "Ceļš nepastāv.", + "uploadstash-bad-path-invalid": "Ceļš nav derÄ«gs.", "uploadstash-bad-path-unknown-type": "Nezināms tips \"$1\".", "uploadstash-bad-path-unrecognized-thumb-name": "NeatpazÄ«ts sÄ«ktēla nosaukums.", "uploadstash-file-not-found-no-thumb": "Nevarēja iegÅ«t sÄ«kbildi.", @@ -1501,6 +1510,7 @@ "randompage": "NejauÅ¡a lapa", "randomincategory": "NejauÅ¡a lapa kategorijā", "randomincategory-invalidcategory": "\"$1\" nav derÄ«gs kategorijas nosaukums.", + "randomincategory-nopages": "Kategorijā [[:Category:$1|$1]] nav lapu.", "randomincategory-category": "Kategorija:", "randomincategory-legend": "NejauÅ¡a lapa kategorijā", "randomincategory-submit": "Aiziet!", @@ -1520,7 +1530,12 @@ "statistics-users": "ReÄ£istrēti dalÄ«bnieki", "statistics-users-active": "AktÄ«vi lietotāji", "statistics-users-active-desc": "Lietotāji, kas ir veikuÅ¡i jebkādu darbÄ«bu {{PLURAL:$1|iepriekšējās $1 dienās|iepriekšējā $1 dienā|iepriekšējās $1 dienās}}", + "pageswithprop": "Lapas ar lapas Ä«paÅ¡Ä«bu", + "pageswithprop-legend": "Lapas ar lapas Ä«paÅ¡Ä«bu", + "pageswithprop-text": "Å ajā lapā uzskaitÄ«tas lapas ar konkrētu lapas Ä«paÅ¡Ä«bu.", "pageswithprop-prop": "ĪpaÅ¡Ä«bas nosaukums:", + "pageswithprop-reverse": "Kārtot apgrieztā secÄ«bā", + "pageswithprop-sortbyvalue": "Kārtot pēc Ä«paÅ¡Ä«bas vērÄ«bas", "pageswithprop-submit": "Aiziet", "doubleredirects": "DivkārÅ¡as pāradresācijas lapas", "doubleredirectstext": "Å ajā lapā ir uzskaitÄ«tas pāradresācijas lapas, kuras pāradresē uz citām pāradresācijas lapām.\nKatrā rindiņā ir saites uz pirmo un otro pāradresācijas lapu, kā arÄ« pirmā rindiņa no otrās pāradresācijas lapas teksta, kas parasti ir faktiskā \"gala\" lapa, uz kuru vajadzētu bÅ«t saitei pirmajā lapā.\nNosvÄ«trotie ieraksti jau ir tikuÅ¡i salaboti.", @@ -1694,6 +1709,8 @@ "listgrouprights-namespaceprotection-header": "Vārdtelpas ierobežojumi", "listgrouprights-namespaceprotection-namespace": "Vārdtelpa", "listgrants-rights": "TiesÄ«bas", + "trackingcategories": "IzsekoÅ¡anas kategorijas", + "trackingcategories-msg": "IzsekoÅ¡anas kategorija", "trackingcategories-nodesc": "Apraksts nav pieejams.", "trackingcategories-disabled": "Kategorija ir atslēgta", "mailnologin": "Nav adreses, uz kuru sÅ«tÄ«t", @@ -2155,6 +2172,7 @@ "import-interwiki-submit": "Importēt", "import-mapping-namespace": "Importēt vārdtelpā:", "import-upload-filename": "Faila nosaukums:", + "import-upload-username-prefix": "Starpviki prefikss:", "import-comment": "Komentārs:", "importstart": "Importē lapas...", "import-revision-count": "$1 {{PLURAL:$1|versijas|versija|versijas}}", @@ -2842,9 +2860,11 @@ "tags-create-already-exists": "IezÄ«me \"$1\" jau pastāv.", "tags-delete-title": "Dzēst iezÄ«mi", "tags-delete-reason": "Iemesls:", + "tags-delete-not-found": "IezÄ«me \"$1\" nepastāv.", "tags-delete-no-permission": "Tev nav atļaujas dzēst izmaiņu iezÄ«mes.", "tags-activate-title": "Aktivizēt iezÄ«mi", "tags-activate-reason": "Iemesls:", + "tags-activate-not-found": "IezÄ«me \"$1\" nepastāv.", "tags-activate-submit": "Aktivizēt", "tags-deactivate-title": "Deaktivizēt iezÄ«mi", "tags-deactivate-reason": "Iemesls:", @@ -2921,6 +2941,7 @@ "logentry-newusers-create": "Lietotāja konts $1 tika {{GENDER:$2|izveidots}}", "logentry-newusers-create2": "$1 {{GENDER:$2|izveidoja}} lietotāja kontu $3", "logentry-newusers-autocreate": "Lietotaja konts $1 tika {{GENDER:$2|izveidots}} automātiski", + "logentry-protect-unprotect": "$1 {{GENDER:$2|noņēma}} aizsardzÄ«bu no $3", "logentry-protect-protect": "$1 {{GENDER:$2|aizsargāja}} $3 $4", "logentry-upload-upload": "$1 {{GENDER:$2|augÅ¡upielādēja}} $3", "logentry-upload-overwrite": "$1 augÅ¡upielādēja jaunu $3 versiju", @@ -2958,7 +2979,9 @@ "duration-centuries": "$1 {{PLURAL:$1|gadsimti|gadsimts|gadsimti}}", "duration-millennia": "$1 {{PLURAL:$1|tÅ«kstoÅ¡gades|tÅ«kstoÅ¡gade|tÅ«kstoÅ¡gades}}", "limitreport-title": "Parsētāja profilēšanas dati:", + "limitreport-cputime": "CPU laika lietojums", "limitreport-cputime-value": "$1 {{PLURAL:$1|sekundes|sekunde|sekundes}}", + "limitreport-walltime": "Reālā laika lietojums", "limitreport-walltime-value": "$1 {{PLURAL:$1|sekundes|sekunde|sekundes}}", "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|baiti|baits|baiti}}", "limitreport-templateargumentsize": "Veidnes argumenta izmērs", @@ -3006,6 +3029,7 @@ "special-characters-group-persian": "PersieÅ¡u", "special-characters-group-hebrew": "Ebreju", "special-characters-group-bangla": "Bengāļu", + "special-characters-group-tamil": "Tamilu", "special-characters-group-telugu": "Telugu", "special-characters-group-sinhala": "Singāļu", "special-characters-group-gujarati": "Gudžarati", @@ -3019,6 +3043,8 @@ "sessionprovider-generic": "$1 sesijas", "randomrootpage": "NejauÅ¡a saknes lapa", "log-action-filter-suppress": "Cenzēšanas veids:", + "log-action-filter-upload": "AugÅ¡upielādes veids:", + "log-action-filter-block-unblock": "Atbloķēšana", "log-action-filter-delete-delete": "Lapas dzēšana", "log-action-filter-managetags-create": "IezÄ«mes izveide", "log-action-filter-managetags-delete": "IezÄ«mes dzēšana", diff --git a/languages/i18n/mk.json b/languages/i18n/mk.json index 7783806a38..fc259b2a95 100644 --- a/languages/i18n/mk.json +++ b/languages/i18n/mk.json @@ -646,8 +646,8 @@ "subject-preview": "Преглед на насловот:", "previewerrortext": "Се појави грешка при обидот да се прегледаат промените.", "blockedtitle": "Корисникот е блокиран", - "blockedtext": "'''Вашето корисничко име или IP-адреса е блокирано.'''\n\nБлокирањето е направено од страна на $1.\nДаденото образложение е ''$2''.\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Корисникот што требало да биде блокиран: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со блокирањето.\nМожете да ја искористите можноста „Е-пошта до овој корисник“ ако е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и не ви е забрането да ја користите.\nВашата сегашна IP-адреса е $3, а назнака на блокирањето гласи #$5.\nВе молиме наведете ги сите подробности прикажани погоре, во вашата евентуална реакција.", - "autoblockedtext": "Вашата IP-адреса е автоматски блокирана бидејќи била користена од страна на друг корисник, кој бил блокиран од $1.\nДаденото образложение е следново:\n\n:''$2''\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Со намера да се блокира: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со ова блокирање.\n\nИмајте предвид дека можеби нема да можете да ја искористите можноста „Е-пошта до овој корисник“ доколку не е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и ви е забрането користитење на истата.\n\nВашата IP-адреса е $3, a ID на блокирањеto е $5.\nВе молиме наведете ги овие подробности доколку реагирате на блокирањето.", + "blockedtext": "Вашето корисничко име или IP-адреса е блокирано.\n\nБлокирањето е направено од страна на $1.\nДаденото образложение е ''$2''.\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Корисникот што требало да биде блокиран: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со блокирањето.\nМожете да ја искористите можноста „{{int:emailuser}}“ ако е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и не ви е забрането да ја користите.\nВашата сегашна IP-адреса е $3, а назнака на блокирањето гласи #$5.\nВе молиме наведете ги сите подробности прикажани погоре, во вашата евентуална реакција.", + "autoblockedtext": "Вашата IP-адреса е автоматски блокирана бидејќи била користена од страна на друг корисник, кој бил блокиран од $1.\nДаденото образложение е следново:\n\n:$2\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Со намера да се блокира: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со ова блокирање.\n\nИмајте предвид дека можеби нема да можете да ја искористите можноста „{{int:emailuser}}“ доколку не е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и ви е забрането користитење на истата.\n\nВашата IP-адреса е $3, a ID на блокирањеto е $5.\nВе молиме наведете ги овие подробности доколку реагирате на блокирањето.", "systemblockedtext": "Вашето корисничко име или IP-адреса е автоматски блокирано од МедијаВики.\nПонудена причина:\n\n:$2\n\n* Почеток на блокот: $8\n* Истек на блокот: $6\n* Блокот е наменет за: $7\n\nВашата тековна IP-адреса гласи $3.\nПрепишете ги сите горенаведени поединости доколку сакате да се распрашате кај надлежните во врска со блокот.", "blockednoreason": "не е наведена причина", "whitelistedittext": "Мора да сте $1 за да уредувате страници.", @@ -1983,6 +1983,7 @@ "apisandbox-dynamic-parameters-add-label": "Додај параметар:", "apisandbox-dynamic-parameters-add-placeholder": "Назив на параметарот", "apisandbox-dynamic-error-exists": "Праметарот по име „$1“ веќе постои.", + "apisandbox-templated-parameter-reason": "Овој [[Special:ApiHelp/main#main/templatedparams|шаблонизиран параметар]] се нуди според {{PLURAL:$1|вредноста|вредностите}} на $2.", "apisandbox-deprecated-parameters": "Застарени параметри", "apisandbox-fetch-token": "Самопополни ја шифрата", "apisandbox-add-multi": "Додај", @@ -3995,9 +3996,9 @@ "special-characters-group-hebrew": "Хебрејски", "special-characters-group-bangla": "Бенгалски", "special-characters-group-tamil": "тамилски", - "special-characters-group-telugu": "Телугу", + "special-characters-group-telugu": "Телушки", "special-characters-group-sinhala": "Синхалски", - "special-characters-group-gujarati": "Гуџарати", + "special-characters-group-gujarati": "Гуџаратски", "special-characters-group-devanagari": "деванагари", "special-characters-group-thai": "Тајландски", "special-characters-group-lao": "Лаошки", @@ -4163,5 +4164,6 @@ "pagedata-title": "Податоци за страницата", "pagedata-text": "Страницава дава посредник за податоци за страниците. Укажете го насловот на страницата во URL-то, користејќи ја синтаксата за потстраници.\n* Префрлањето на содржината се заснова на заглавието Прифати на вашиот клиент. Ова значи дека податоците за страницата ќе бидат ставени во форматот кој го претпочита вашиот клиент.", "pagedata-not-acceptable": "Не најдов соодветен формат. Поддржани MIME-типови: $1", - "pagedata-bad-title": "Неважечки наслов: $1." + "pagedata-bad-title": "Неважечки наслов: $1.", + "unregistered-user-config": "Од безбедносни причини, корисничките потстраници со JavaScript, CSS и JSON не се вчитуваат за нерегистрирани корисници." } diff --git a/languages/i18n/nds-nl.json b/languages/i18n/nds-nl.json index c023aac810..d394c0c6bd 100644 --- a/languages/i18n/nds-nl.json +++ b/languages/i18n/nds-nl.json @@ -2720,7 +2720,7 @@ "confirm-purge-title": "Herny disse syde", "confirm_purge_button": "Bevestig", "confirm-purge-top": "Klik up 'bevestig' üm et tüskengehöägen van disse syde te leagen.", - "confirm-purge-bottom": "Et leagmaken van et tüskengehöägen sörgt dervöär dat jy de lätste versy van een syde te syn krygen.", + "confirm-purge-bottom": "Et leagmaken van et tüskengehöägen sörgt dervöär dat jy de lätste versy van een syde te seen krygen.", "confirm-watch-button": "Oké", "confirm-watch-top": "Disse zied op joew volglieste zetten?", "confirm-unwatch-button": "Oké", diff --git a/languages/i18n/nl.json b/languages/i18n/nl.json index 656ef4f9a6..83e855fa62 100644 --- a/languages/i18n/nl.json +++ b/languages/i18n/nl.json @@ -117,7 +117,7 @@ "tog-enotifminoredits": "Mij e-mailen bij kleine bewerkingen van pagina’s en bestanden op mijn volglijst", "tog-enotifrevealaddr": "Mijn e-mailadres weergeven in e-mailberichten", "tog-shownumberswatching": "Het aantal gebruikers weergeven dat deze pagina volgt", - "tog-oldsig": "Uw bestaande ondertekening:", + "tog-oldsig": "Uw bestaande handtekening:", "tog-fancysig": "Handtekening als wikitekst behandelen (zonder automatische koppeling)", "tog-uselivepreview": "Voorvertoning weergeven zonder de pagina opnieuw te laden", "tog-forceeditsummary": "Een melding geven bij een lege bewerkingssamenvatting", @@ -706,8 +706,8 @@ "subject-preview": "Voorvertoning van het onderwerp:", "previewerrortext": "Er is een fout opgetreden tijdens het weergeven van uw wijzigingen.", "blockedtitle": "Gebruiker is geblokkeerd", - "blockedtext": "'''Uw gebruikersaccount of IP-adres is geblokkeerd.'''\n\nDe blokkade is uitgevoerd door $1.\nDe opgegeven reden is ''$2''.\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\nU kunt geen gebruik maken van de functie \"Deze gebruiker e-mailen\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]] en het gebruik van deze functie niet geblokkeerd is.\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", - "autoblockedtext": "Uw IP-adres is automatisch geblokkeerd, omdat het gebruikt is door een andere gebruiker, die geblokkeerd is door $1.\nDe opgegeven reden is:\n\n:''$2''\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\n\nU kunt geen gebruik maken van de functie \"Deze gebruiker e-mailen\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]], en het gebruik van deze functie niet is geblokkeerd.\n\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", + "blockedtext": "'''Uw gebruikersaccount of IP-adres is geblokkeerd.'''\n\nDe blokkade is uitgevoerd door $1.\nDe opgegeven reden is ''$2''.\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\nU kunt geen gebruik maken van de functie \"{{int:emailuser}}\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]] en het gebruik van deze functie niet geblokkeerd is.\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", + "autoblockedtext": "Uw IP-adres is automatisch geblokkeerd, omdat het gebruikt is door een andere gebruiker, die geblokkeerd is door $1.\nDe opgegeven reden is:\n\n:''$2''\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\n\nU kunt geen gebruik maken van de functie \"{{ing:emailuser}}\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]], en het gebruik van deze functie niet is geblokkeerd.\n\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", "systemblockedtext": "Uw gebruikersaccount of IP-adres is automatisch geblokkeerd door MediaWiki.\nDe opgegeven reden is:\n\n:$2\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nUw huidige IP-adres is $3.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", "blockednoreason": "geen reden opgegeven", "whitelistedittext": "U moet $1 om pagina's te bewerken.", @@ -4088,5 +4088,6 @@ "pagedata-title": "Paginagegevens", "pagedata-text": "Deze pagina biedt een data-interface voor pagina's. Geef een paginatitel op door deze in de URL op te nemen, op de manier van een deelpagina.\n* De inhoud wordt afgestemd op de door de client meegestuurde Accept Header. Dit betekent dat de gegevens voor de pagina worden aangeboden in het voorkeursformaat van uw client.", "pagedata-not-acceptable": "Er is geen overeenkomende indeling gevonden. Ondersteunde MIME-typen: $1", - "pagedata-bad-title": "Ongeldige titel: $1." + "pagedata-bad-title": "Ongeldige titel: $1.", + "unregistered-user-config": "Vanwege veiligheidsredenen wordt worden gebruikersdeelpagina's met JavaScript, CSS en JSON niet langer geladen voor gebruikers die niet zijn geregistreerd." } diff --git a/languages/i18n/oc.json b/languages/i18n/oc.json index f11e4fd10d..20f022a48c 100644 --- a/languages/i18n/oc.json +++ b/languages/i18n/oc.json @@ -737,7 +737,11 @@ "content-model-css": "CSS", "content-json-empty-object": "Objècte void", "content-json-empty-array": "Tablèu void", + "deprecated-self-close-category": "Paginas qu'utilizan d'etiquetas HTML autotampadas pas validas", + "deprecated-self-close-category-desc": "La pagina conten d'etiquetas HTML autotampadas pas validas, coma <b/> o <span/>. Lo comportament d'aquò cambiarà lèu per respectar l'especificacion HTML5, adonc lor emplec en wikitext es despreciat.", + "duplicate-args-warning": "Attention: [[:$1]] crida [[:$2]] amb mai d'una valor pel paramètre \"$3\". S'emplegarà solament la darrièra valor provesida.", "duplicate-args-category": "Paginas utilizant d'arguments duplicats dins los apèls de modèl", + "duplicate-args-category-desc": "La pagina conten de cridas a patrons qu'emplagan d'arguments duplicats, coma {{foo|bar=1|bar=2}} or {{foo|bar|1=baz}}.", "expensive-parserfunction-warning": "Atencion : Aquesta pagina conten tròp d’apèls dispendioses de foncions del parser.\n\nI deurià aver mens de {{PLURAL:$2|ampèl|ampèls}}, e actualament {{PLURAL:$1|i a $1 ampèl|i a $1 ampèls}}..", "expensive-parserfunction-category": "Paginas amb tròp d’apèls dispendioses de foncions parsaires", "post-expand-template-inclusion-warning": "Atencion : Aquesta pagina conten tròp d'inclusions de modèls.\nD'unas inclusions seràn pas efectuadas.", @@ -745,6 +749,9 @@ "post-expand-template-argument-warning": "Atencion : Aquesta pagina conten al mens un paramètre de modèl que l'inclusion es renduda impossibla. Aprèp extension, aqueste auriá produit un resultat tròp long, doncas, es pas estat inclús.", "post-expand-template-argument-category": "Paginas que contenon al mens un paramètre de modèl pas evaluat", "parser-template-loop-warning": "Modèl en bocla detectat : [[$1]]", + "template-loop-category": "Paginas amb boclas de patron", + "template-loop-category-desc": "La pagina conten una bocla dins lo patron, es a dire, un patron que se sona el meteis recursivament.", + "template-loop-warning": "Attencion: Aquesta pagina sona [[:$1]. Aquò es l'encausa d'una bocla de patron (una sonada infinida resursiva).", "parser-template-recursion-depth-warning": "Limit de longor de la recursion del modèl depassat ($1)", "language-converter-depth-warning": "Limit de prigondor del convertissor de lenga depassada ($1)", "node-count-exceeded-category": "Paginas ont nombre de nosèls es depassat", @@ -982,6 +989,7 @@ "prefs-watchlist-edits": "Nombre maximal de modificacions d'afichar dins la lista de seguiment :", "prefs-watchlist-edits-max": "Nombre maximum : 1000", "prefs-watchlist-token": "Geton per la lista de seguiment :", + "prefs-watchlist-managetokens": "Administrar los getons", "prefs-misc": "Preferéncias divèrsas", "prefs-resetpass": "Modificar lo senhal", "prefs-changeemail": "Cambiar o suprimir l'adreça electronica", @@ -1000,6 +1008,7 @@ "recentchangescount": "Nombre de modificacions d'afichar per defauta dins los cambiaments recents, los istorics e los logs :", "prefs-help-recentchangescount": "Nombre maximum : 1000", "prefs-help-watchlist-token2": "Aquí la clau secreta del flux Web de vòstra lista de seguiment.\nTota persona que la coneis poirà legir vòstra lista de seguiment, doncas, la comuniquetz pas.\nSe necessari, [[Special:ResetTokens|clicatz aicí per la reïnicializar]].", + "prefs-help-tokenmanagement": "Podètz veire e tornar inicializar la clau secreta del vòstre compte que pòt accedir al flux Web de la vòstre lista de seguit. Tota persona que coneis la clau poirà legir la vòstra lista, alara la compartissètz pas", "savedprefs": "Las preferéncias son estadas salvadas.", "savedrights": "Los dreits d'utilizaire de {{GENDER:$1|$1}} son estats enregistrats.", "timezonelegend": "Fus orari :", @@ -1020,6 +1029,7 @@ "timezoneregion-pacific": "Ocean Pacific", "allowemail": "Autorizar los autres utilizaires a me mandar de corrièls", "email-allow-new-users-label": "Autorizar corrièr electronic d'utilizaires nòus", + "email-blacklist-label": "Enebís a aqueles usatgièrs de m'enviar de corrièrs electronics:", "prefs-searchoptions": "Recèrca", "prefs-namespaces": "Noms d’espacis", "default": "defaut", @@ -1059,9 +1069,11 @@ "prefs-dateformat": "Format de las datas", "prefs-timeoffset": "Descalatge orari", "prefs-advancedediting": "Opcions generalas", + "prefs-developertools": "Aisinas del desvolopaire", "prefs-editor": "Editor", "prefs-preview": "Apercebut", "prefs-advancedrc": "Opcions avançadas", + "prefs-opt-out": "Refusar los melhoraments", "prefs-advancedrendering": "Opcions avançadas", "prefs-advancedsearchoptions": "Opcions avançadas", "prefs-advancedwatchlist": "Opcions avançadas", @@ -1070,12 +1082,14 @@ "prefs-tokenwatchlist": "Geton", "prefs-diffs": "Diferéncias", "prefs-help-prefershttps": "Aquesta preferéncia serà efectiva al moment de vòstra connexion que ven.", + "prefswarning-warning": "Avètz fach de cambiaments de las vòstras preferéncias que son pas encara efectuats.\nS'abandonatz la pagina sens clicar sus «$1», las preferéncias seràn pas mesas a jorn.", "prefs-tabs-navigation-hint": "Astúcia : Podètz utilizar las sagetas d'esquèrra e de dreita per navigar entre los onglets.", "userrights": "Dreits dels utilizaires", "userrights-lookup-user": "Seleccionar un utilizaire", "userrights-user-editname": "Entrar un nom d’utilizaire :", "editusergroup": "Cargar de gropes d’utilizaires", "editinguser": "Modificacion dels dreits de l’{{GENDER:$1|utilizaire|utilizaira}} [[User:$1|$1]] $2", + "viewinguserrights": "Afichatge dels dreches de {{GENDER:$1|user}} [[User:$1|$1]] $2", "userrights-editusergroup": "Modificar los gropes de l'utilizai{{GENDER:$1|e|a}}", "userrights-viewusergroup": "Afichar los gropes de l'utilizair{{GENDER:$1|e|a}}", "saveusergroups": "Enregistrar los gropes de l’{{GENDER:$1|utilizaire|utilizaira}}", @@ -1093,6 +1107,9 @@ "userrights-expiry-existing": "Data d'expiracion existenta : $2 à $3", "userrights-expiry-othertime": "Autre temps :", "userrights-expiry-options": "1 jorn:1 day,1 setmana:1 week,1 mes:1 month,3 meses:3 months,6 meses:6 months,1 an:1 year", + "userrights-invalid-expiry": "La data d'expiracion pel grop \"$1\" es pas valida.", + "userrights-expiry-in-past": "Lo temps d'expiracion pel grop \"$1\" es trespassat.", + "userrights-cannot-shorten-expiry": "Podètz pas acorchar la durada d'expiracion dels membres del grop \"$1\".Sonque los usatgièrs amb de permissions per apondre e levar aqueste grop o pòdon far.", "userrights-conflict": "Conflicte de modificacion de dreits d'utilizaire ! Relegissètz e confirmatz vòstras modificacions.", "group": "Grop :", "group-user": "Utilizaires", @@ -1119,6 +1136,7 @@ "right-createpage": "Crear de paginas (que son pas de paginas de discussion)", "right-createtalk": "Crear de paginas de discussion", "right-createaccount": "Crear de comptes d'utilizaire novèls", + "right-autocreateaccount": "Comença una session automaticament amb un compte d'usatgièr extèrne", "right-minoredit": "Marcar de cambiaments coma menors", "right-move": "Renomenar de paginas", "right-move-subpages": "Desplaçar de paginas amb lor sospaginas", diff --git a/languages/i18n/pl.json b/languages/i18n/pl.json index ab4d43a4ab..38ab5587d7 100644 --- a/languages/i18n/pl.json +++ b/languages/i18n/pl.json @@ -1092,7 +1092,7 @@ "recentchangescount": "Domyślna liczba wyświetlanych edycji w ostatnich zmianach, historii i rejestrach:", "prefs-help-recentchangescount": "Maksymalna liczba: 1000", "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ć]].", - "prefs-help-tokenmanagement": "Możesz zobaczyć i zresetować sekretny klucz przypisany do konta, służący do uzyskania dostępu do kanału internetowego zmian w obserwowanych przez ciebie stronach. Każdy, kto go zna, będzie mógł je zobaczyć, więc nie udostępniaj go.", + "prefs-help-tokenmanagement": "Możesz zobaczyć i zresetować tajny klucz przypisany do Twojego konta, służący do uzyskania dostępu do kanału internetowego zmian w obserwowanych przez ciebie stronach. Każdy, kto go zna, będzie mógł je zobaczyć, więc nie udostępniaj go.", "savedprefs": "Twoje preferencje zostały zapisane.", "savedrights": "Zapisano grupy {{GENDER:$1|użytkownika $1|użytkowniczki $1}}.", "timezonelegend": "Strefa czasowa:", diff --git a/languages/i18n/pms.json b/languages/i18n/pms.json index 0b9c96a5b5..5cd407adc4 100644 --- a/languages/i18n/pms.json +++ b/languages/i18n/pms.json @@ -18,7 +18,8 @@ "Purodha", "Macofe", "Matma Rex", - "Fitoschido" + "Fitoschido", + "Paolo Castellina" ] }, "tog-underline": "Anliure con la sotliniadura", @@ -46,7 +47,7 @@ "tog-shownumberswatching": "Smon-e ël nùmer d'utent che as ten-o la pàgina sot-euj", "tog-oldsig": "Firma esistenta:", "tog-fancysig": "Traté la firma com dël test wiki (sensa n'anliura automàtica)", - "tog-uselivepreview": "Dovré la fonsion ''Preuva dal viv''", + "tog-uselivepreview": "Dovré la fonsion ''Preuva dal viv'' sensa carié la pàgina", "tog-forceeditsummary": "Ciamé conferma se ël resumé dla modìfica a l'é veujd", "tog-watchlisthideown": "Stërmé mie modìfiche ant la ròba che im ten-o sot-euj", "tog-watchlisthidebots": "Stërmé le modìfiche fàite daj trigomiro ant la lista dle ròbe che im ten-o sot-euj", @@ -59,7 +60,7 @@ "tog-showhiddencats": "Smon-e le categorìe stërmà", "tog-norollbackdiff": "Fé nen vëdde le diferense apress d'avèj ripristinà", "tog-useeditwarning": "Aviseme quand che i chito na pàgina ëd modìfiche con dle modìfiche nen salvà", - "tog-prefershttps": "Dovré sempe na conession sigura pr'ësté andrinta al sistema", + "tog-prefershttps": "Dovré sempe na conession sicura quand ch'a l'é intrà ant ël sistema", "underline-always": "Sempe", "underline-never": "Mai", "underline-default": "Stàndard dël navigator o dël tema", @@ -151,10 +152,10 @@ "newwindow": "(as deurb ant na fnestra neuva)", "cancel": "Anulé", "moredotdotdot": "Ëd pì...", - "morenotlisted": "Costa lista a l'é nen completa.", + "morenotlisted": "Costa lista a podrìa esse nen completa.", "mypage": "Pàgina", "mytalk": "Ciaciarade", - "anontalk": "Ciaciarade për st'adrëssa IP-sì", + "anontalk": "Discussion", "navigation": "Navigassion", "and": " e", "faq": "Chestion frequente", @@ -173,6 +174,7 @@ "searcharticle": "Andé", "history": "Version pì veje", "history_short": "Stòria", + "history_small": "stòria", "updatedmarker": "agiornà da l'ùltima vira che i son passà", "printableversion": "Version bon-a për stampé", "permalink": "Anliura fissa", @@ -206,7 +208,7 @@ "redirectedfrom": "(Ridiression da $1)", "redirectpagesub": "Pàgina ëd ridiression", "redirectto": "Ridiression a:", - "lastmodifiedat": "Modificà l'ùltima vira ai $1 a $2.", + "lastmodifiedat": "Modificà l'ùltima vira dël $1, al $2.", "viewcount": "St'artìcol-sì a l'é stàit lesù {{PLURAL:$1|na vira|$1 vire}}.", "protectedpage": "Pàgina proteta", "jumpto": "Andé a:", @@ -340,7 +342,7 @@ "viewsource": "Vardé la sorgiss", "viewsource-title": "Vëdde la sorgiss ëd $1", "actionthrottled": "Assion limità", - "actionthrottledtext": "Për evité che 'd gent ò 'd màchine an carìo dla rumenta, st'assion-sì as peul nen fesse tròp ëd soèns, e chiel a l'ha arpetula tròpe vire. Ch'a sia gentil, ch'a preuva torna antra dontré minute.", + "actionthrottledtext": "Për evité che 'd gent ò 'd màchine an carìo dla rumenta, st'assion-sì as peul nen fesse tròp ëd soèns, e ti 't l'has arpetula tròpe vire. Sie gentil, preuva torna antra dontré minute.", "protectedpagetext": "Sta pàgina-sì a l'è stàita blocà për evité 'd modìfiche o d'àutre assion.", "viewsourcetext": "A peul vardé e copié la sorgiss dë sta pàgina.", "viewyourtext": "A peul vëdde e copié la sorgiss ëd soe modìfiche a costa pàgina-sì.", @@ -406,7 +408,7 @@ "createacct-reason": "Rason", "createacct-reason-ph": "Përchè a crea n'àutr cont", "createacct-submit": "Ch'a crea sò cont", - "createacct-another-submit": "Creé n'àutr cont", + "createacct-another-submit": "Creé un cont", "createacct-benefit-heading": "{{SITENAME}} a l'é fàit da 'd gent coma chiel.", "createacct-benefit-body1": "{{PLURAL:$1|modìfica|modìfiche}}", "createacct-benefit-body2": "{{PLURAL:$1|pàgina|pàgine}}", @@ -423,7 +425,7 @@ "noname": "A l'ha nen ëspessificà në stranòm vàlid.", "loginsuccesstitle": "Compliment! A l'é pen-a rintrà ant ël sistema.", "loginsuccess": "'''Adess a l'é colegà a {{SITENAME}} con lë stranòm «$1».'''", - "nosuchuser": "A-i é pa gnun utent con lë stranòm «$1».\nJë stranòm ëd j'utent a son sensìbij a le majùscole.\nCh'a contròla ël nòm che a l'ha batù, o [[Special:CreateAccount|ch'a crea un neuv cont]].", + "nosuchuser": "A-i é pa gnun utent con lë stranòm «$1».\nJë stranòm ëd j'utent a son sensìbij a le majùscole.\nContròla ël nòm ch'it l'has batù, o [[Special:CreateAccount|crea un cont neuv]].", "nosuchusershort": "A-i é pa gnun utent che as ciama «$1». Për piasì, che a contròla se a l'ha scrit tut giust.", "nouserspecified": "A venta che a specìfica në stranòm d'utent", "login-userblocked": "St'utent-sì a l'é blocà. A peul pa intré ant ël sistema.", @@ -443,7 +445,7 @@ "eauthentsent": "A l'adrëssa che a l'ha dane i l'oma mandaje un mëssagi ëd pòsta eletrònica për conferma.\nAnans che qualsëssìa àutr messagi ëd pòsta a ven-a mandà a 's cont-sì, a venta che a a fasa coma che a-j diso dë fé ant ël mëssagi, për confermé che ës cont a l'é da bon sò.", "throttled-mailpassword": "Na ciav neuva a l'é gia stàita mandà da manch che {{PLURAL:$1|n'ora|$1 ore}}. Për evité dj'abus, mach un mëssagi ëd ri-inissialisassion ëd ciav a sarà mandà minca {{PLURAL:$1|ora|$1 ore}}.", "mailerror": "Eror ën mandand via un mëssagi ëd pòsta eletrònica: $1", - "acct_creation_throttle_hit": "Dij visitador ëd costa wiki, an dovrand soa adrëssa IP a l'han creà {{PLURAL:$1|1 cont|$1 cont}} ant l'ùltim di, che a l'é tut lòn che as peul fesse ant cost temp.\nËd conseguensa, ij visitador che a deuvro costa adrëssa IP a peulo pì nen fé dij cont al moment.", + "acct_creation_throttle_hit": "Dij visitador ëd costa wiki, an dovrand soa adrëssa IP a l'han creà {{PLURAL:$1|1 cont|$1 cont}} ant l'ùltim $2, che a l'é tut lòn che as peul fesse ant cost temp.\nËd conseguensa, ij visitador che a deuvro costa adrëssa IP a peulo pì nen fé dij cont al moment.", "emailauthenticated": "Soa adrëssa ëd pòsta eletrònica a l'é stàita confirmà ël $2 a $3.", "emailnotauthenticated": "Soa adrëssa ëd pòsta eletrònica a l'é pa ancó stàita confirmà.\nPër qualsëssìa ëd coste funsion a sarà mandà gnun mëssagi.", "noemailprefs": "Che a specìfica n'adrëssa ëd pòsta eletrònica se a veul dovré coste funsion-sì.", @@ -456,7 +458,7 @@ "createaccount-title": "Creassion d'un cont për {{SITENAME}}", "createaccount-text": "Cheidun a l'ha duvertà un cont për soa adrëssa ëd pòsta eletrònica ansima a {{SITENAME}} ($4) butand da stranòm «$2» e da ciav «$3». A dovrìa rintré ant ël sistema e cambiesse soa ciav pì ampressa ch'a peul.\n\nSe sòn a l'é rivà për eror, a peul lassé perde e fé gnente sensa problema.", "login-throttled": "A l'ha fàit tròpi tentativ recent d'intré ant ël sistema.\nPër piasì, ch'a speta $1 prima ëd prové torna.", - "login-abort-generic": "Sò tentitiv d'intré ant ël sistema a l'é falì - Abortì", + "login-abort-generic": "Sò tentativ d'intré ant ël sistema a l'é falì - Abortì", "login-migrated-generic": "Sò cont a l'ha emigrà, e sò stranòm a esist pi nen su costa wiki.", "loginlanguagelabel": "Lenga: $1", "suspicious-userlogout": "Soa arcesta ëd seurte dal sistema a l'é stàita arfudà përchè a smija com s'a fussa stàita mandà da 'n navigador rot o da l'archiviassion an local d'un prëstanòm.", @@ -503,7 +505,7 @@ "passwordreset-emailtext-user": "L'utent $1 ansima a {{SITENAME}} a l'ha ciamà na riampostassion ëd soa ciav për {{SITENAME}} ($4). {{PLURAL:$3|Ël cont utent sì-sota a l'é|Ij cont utent sì-sota a son}} associà a st'adrëssa ëd pòsta eletrònica:\n\n$2\n\n{{PLURAL:$3|Costa ciav provisòria|Coste ciav provisòrie}} a scadran da-sì {{PLURAL:$5|un di|$5 di}}.\nA dovrìa intré ant ël sistema e serne na ciav neuva adess. Se quaidun d'àutr a l'ha fàit costa arcesta, o s'a l'é arcordasse soa ciav original, e a veul pa pi cangela, a peul ignoré ës mëssagi e continué a dovré soa veja ciav.", "passwordreset-emailelement": "Stranòm: \n$1\n\nCiav provisòria: \n$2", "passwordreset-emailsentemail": "Un mëssagi ëd riampostassion ëd la ciav a l'é stàit spedì.", - "changeemail": "Cangé l'adrëssa ëd pòsta eletrònica", + "changeemail": "Cangé o dëscancelé l'adrëssa ëd pòsta eletrònica", "changeemail-header": "Cangé l'adrëssa ëd pòsta eletrònica dël cont", "changeemail-no-info": "A dev esse intrà ant ël sistema për andé diretament a costa pàgina.", "changeemail-oldemail": "Adrëssa ëd pòsta eletrònica atual:", @@ -551,10 +553,10 @@ "anonpreviewwarning": "''A l'é nen rintrà ant ël sistema. An salvand a sarà memorisà soa adrëssa IP ant la stòria dle modìfiche ëd sa pàgina.''", "missingsummary": "'''Nòta:''' a l'ha butà gnun resumé dla modìfica. Se a sgnaca «$1» n'àutra vira, soa modìfica a resterà salvà sensa resumé.", "selfredirect": "Atension: A l'é an camin ch'a ridiression-a sa pàgina a chila-midema.\nMiraco a l'ha spessificà ël bërsaj sbalià për la ridiression, opura a l'é an camin ch'a modìfica la pàgina sbalià.\nS'a sgnaca torna ansima a «$1», la ridiression a sarà creà istess.", - "missingcommenttext": "Për piasì, che a buta un coment sì-sota.", + "missingcommenttext": "Për piasì, buta un coment sì-sota.", "missingcommentheader": "'''Ch'a ten-a da ment:''' A l'ha pa dàit ëd soget o d'intestassion për cost coment.\nSe a sgnaca torna «$1», soa modìfica a sarà salvà sensa gnun-a intestassion.", - "summary-preview": "Preuva dël resumé:", - "subject-preview": "Preuva dl'oget/intestassion:", + "summary-preview": "Preuva dla compilassion dël resumé:", + "subject-preview": "Previsualisassion dl'oget:", "previewerrortext": "A l'é rivaje n'eror durant ël tentativ ëd previsualisassion ëd soe modìfiche.", "blockedtitle": "L'utent a l'é blocà.", "blockedtext": "'''Sò stranòm ò pura adrëssa IP a l'é stàit blocà.'''\n\nËl blocagi a l'é stàit fàit da $1.\nComa rason a l'ha butà ''$2''.\n\n* Blocà a parte dal: $8\n* Fin al: $6\n* As veul blochesse: $7\n\nA peul butesse an contat con $1 ò pura n'àotr [[{{MediaWiki:Grouppage-sysop}}|aministrator]] për discute ëd sò blocagi.\nCh'a ten-a present ch'a podrà dovré la fonsion «mandeje un messagi ëd pòsta eletrònica a l'utent» mach s'a l'ha specificà n'adrëssa ëd vàlida ant [[Special:Preferences|sò gust]] e se sta fonsion a l'é nen ëstàita blocà 'cò chila.\nSoa adrëssa IP corenta a l'é $3, e l'identificativ dël blocagi a l'é #$5.\nPër piasì, ch'a-j buta tut e doj ant soe comunicassion ant sta question-sì.", @@ -843,7 +845,7 @@ "search-file-match": "(a corëspond al contnù d'archivi)", "search-suggest": "Vorìi-lo pa dì: $1", "search-rewritten": "Visualisassion dj'arzultà për $1. Sërché nopà $2.", - "search-interwiki-caption": "Proget frej", + "search-interwiki-caption": "Arzultà dij proget frej", "search-interwiki-default": "Arzultà da $1:", "search-interwiki-more": "(ëd pì)", "search-relatedarticle": "Corelà", @@ -886,7 +888,7 @@ "prefs-watchlist-token": "Geton ëd lòn che as ten sot euj:", "prefs-misc": "Sòn e lòn", "prefs-resetpass": "Cangé la ciav", - "prefs-changeemail": "Cangé l'adrëssa ëd pòsta eletrònica", + "prefs-changeemail": "Cangé o dëscancelé l'adrëssa ëd pòsta eletrònica", "prefs-setemail": "Amposté n'adrëssa ëd pòsta eletrònica", "prefs-email": "Opsion ëd pòsta eletrònica", "prefs-rendering": "Sembiansa", @@ -995,20 +997,20 @@ "group-bot": "Trigomiro", "group-sysop": "Aministrator", "group-bureaucrat": "Mangiapapé", - "group-suppress": "Supervisor", + "group-suppress": "Ancarià dle sopression", "group-all": "(utent)", "group-user-member": "{{GENDER:$1|utent}}", "group-autoconfirmed-member": "{{GENDER:$1|utent ch'a l'é convalidasse daspërchiel|utent ch'a l'é convalidasse daspërchila}}", "group-bot-member": "{{GENDER:$1|trigomiro}}", "group-sysop-member": "{{GENDER:$1|aministrator|aministratris}}", "group-bureaucrat-member": "{{GENDER:$1|mangiapapé}}", - "group-suppress-member": "{{GENDER:$1|supervisor}}", + "group-suppress-member": "{{GENDER:$1|ancarià dle sopression}}", "grouppage-user": "{{ns:project}}:Utent", "grouppage-autoconfirmed": "{{ns:project}}:Utent ch'a son convalidasse daspërlor", "grouppage-bot": "{{ns:project}}:Trigomiro", "grouppage-sysop": "{{ns:project}}:Aministrator", "grouppage-bureaucrat": "{{ns:project}}:Mangiapapé", - "grouppage-suppress": "{{ns:project}}:Supervisor", + "grouppage-suppress": "{{ns:project}}:Fà la sopression", "right-read": "Lese le pàgine", "right-edit": "Modifiché le pàgine", "right-createpage": "Creé dle pàgine (che a son pa dle pàgine ëd discussion)", diff --git a/languages/i18n/pt-br.json b/languages/i18n/pt-br.json index 877184cd94..43b003219b 100644 --- a/languages/i18n/pt-br.json +++ b/languages/i18n/pt-br.json @@ -617,6 +617,7 @@ "botpasswords-existing": "Senhas de robôs existentes", "botpasswords-createnew": "Crie uma nova senha de robô", "botpasswords-editexisting": "Editar uma senha de robô existente", + "botpasswords-label-needsreset": "(senha precisa ser redefinida)", "botpasswords-label-appid": "Nome do robô:", "botpasswords-label-create": "Criar", "botpasswords-label-update": "Atualizar", @@ -640,6 +641,7 @@ "botpasswords-restriction-failed": "Restrições de senha de robô evitam esta autenticação.", "botpasswords-invalid-name": "O nome de usuário especificado não contém o separador de senha de robô (\"$1\").", "botpasswords-not-exist": "O usuário \"$1\" não possui uma senha de robô \"$2\".", + "botpasswords-needs-reset": "A senha do robô de nome \"$2\" {{GENDER:$1|do usuário|da usuária}} \"$1\" deve ser redefinida.", "resetpass_forbidden": "As senhas não podem ser alteradas", "resetpass_forbidden-reason": "Senhas não podem ser alteradas: $1", "resetpass-no-info": "Você precisa estar autenticado para acessar esta página diretamente.", @@ -1111,7 +1113,7 @@ "recentchangescount": "Número de edições a apresentar por omissão nas mudanças recentes, nos historiais de páginas e nos registos:", "prefs-help-recentchangescount": "Número máximo: 1000", "prefs-help-watchlist-token2": "Esta é a senha secreta para o feed da Web com sua lista de tokens vigiados.\nQualquer pessoa que descobrir esta senha será capaz de ler sua lista, então não a compartilhe.\nSe você precisar [[Special:ResetTokens|você pode redefini-lo]].", - "prefs-help-tokenmanagement": "Você pode ver e redefinir a chave secreta para sua conta que pode acessar o feed da Web da sua lista de vigilância. Qualquer pessoa que conheça a chave poderá ler sua lista de observação, então não compartilhe.", + "prefs-help-tokenmanagement": "Pode ver e repor a chave secreta da sua conta que permite aceder ao feed da sua lista de páginas vigiadas. Qualquer pessoa que conheça a chave será capaz de ler a sua lista de páginas vigiadas, por isso não a partilhe.", "savedprefs": "As suas preferências foram salvas.", "savedrights": "Os grupos {{GENDER:$1|do usuário|da usuária}} $1 foram gravados.", "timezonelegend": "Fuso horário:", @@ -1141,7 +1143,7 @@ "prefs-custom-json": "JSON personalizado", "prefs-custom-js": "JS personalizado", "prefs-common-config": "CSS/JSON/JavaScript compartilhado por todos os temas:", - "prefs-reset-intro": "Você pode usar esta página para restaurar as suas preferências para os valores predefinidos do sítio.\nEsta ação não pode ser desfeita.", + "prefs-reset-intro": "Pode usar esta página para repor as configurações padrão das preferências.\nAs suas preferências serão modificadas para os valores predefinidos do site.\nEsta operação não pode ser desfeita.", "prefs-emailconfirm-label": "Confirmação do e-mail:", "youremail": "Seu e-mail:", "username": "Nome de {{GENDER:$1|usuário|usuária|usuário(a)}}:", @@ -1588,7 +1590,7 @@ "recentchangeslinked-feed": "Mudanças relacionadas", "recentchangeslinked-toolbox": "Mudanças relacionadas", "recentchangeslinked-title": "Mudanças relacionadas com “$1”", - "recentchangeslinked-summary": "Digite um nome de página para ver as alterações nas páginas vinculadas ou a partir dessa página. (Para ver membros de uma categoria, digite Categoria: Nome da categoria). Mudanças nas páginas em [[Special:Watchlist|lista de páginas vigiadas]] são exibidas em negrito", + "recentchangeslinked-summary": "Introduza o nome de uma página para ver as mudanças a todas as páginas que contêm hiperligações para ela ou para as quais a página fornecida contém hiperligações (para ver as que pertencem a uma categoria, introduza {{ns:category}}:Nome da categoria). As mudanças às suas [[Special:Watchlist|páginas vigiadas]] aparecem a negrito.", "recentchangeslinked-page": "Nome da página:", "recentchangeslinked-to": "Inversamente, mostrar mudanças nas páginas que contêm ligações para esta", "recentchanges-page-added-to-category": "[[:$1]]adicionada à categoria", @@ -2068,6 +2070,7 @@ "apisandbox-dynamic-parameters-add-label": "Parâmetro adicional", "apisandbox-dynamic-parameters-add-placeholder": "Nome do parâmetro", "apisandbox-dynamic-error-exists": "Um parâmetro chamado \"$1\" já existe.", + "apisandbox-templated-parameter-reason": "Este [[Special:ApiHelp/main#main/templatedparams|parâmetro de predefinição]] é oferecido com base {{PLURAL:$1|no valor|nos valores}} de $2.", "apisandbox-deprecated-parameters": "Parâmetros obsoletos", "apisandbox-fetch-token": "Preencher automaticamente o token", "apisandbox-add-multi": "Adicionar", diff --git a/languages/i18n/pt.json b/languages/i18n/pt.json index 9a67d6faef..85ad5b40cb 100644 --- a/languages/i18n/pt.json +++ b/languages/i18n/pt.json @@ -76,7 +76,8 @@ "Ngl2016", "RadiX", "MokaAkashiyaPT", - "Athena in Wonderland" + "Athena in Wonderland", + "Fitoschido" ] }, "tog-underline": "Sublinhar hiperligações:", @@ -583,6 +584,7 @@ "botpasswords-existing": "Palavras-passe de robô existentes", "botpasswords-createnew": "Criar uma nova palavra-passe para robô", "botpasswords-editexisting": "Editar uma palavra-passe de robô existente", + "botpasswords-label-needsreset": "(a palavra-passe precisa ser redefinida)", "botpasswords-label-appid": "Nome do robô:", "botpasswords-label-create": "Criar", "botpasswords-label-update": "Atualizar", @@ -606,6 +608,7 @@ "botpasswords-restriction-failed": "Restrições da palavra-passe de robô impedem esta autenticação.", "botpasswords-invalid-name": "O nome de utilizador especificado não contém o separador de palavra-passe de robô (\"$1\").", "botpasswords-not-exist": "O utilizador \"$1\" não tem uma palavra-passe para o robô chamado \"$2\".", + "botpasswords-needs-reset": "A palavra-passe do robô de nome \"$2\" {{GENDER:$1|do utilizador|da utilizadora}} \"$1\" deve ser redefinida.", "resetpass_forbidden": "As palavras-passe não podem ser alteradas", "resetpass_forbidden-reason": "As palavras-passe não podem ser alteradas: $1", "resetpass-no-info": "Precisa de iniciar sessão para aceder diretamente a esta página.", @@ -701,8 +704,8 @@ "subject-preview": "Antevisão do assunto:", "previewerrortext": "Ocorreu um erro enquanto tentava antever as suas alterações.", "blockedtitle": "O utilizador está bloqueado", - "blockedtext": "O seu nome de utilizador ou endereço IP foram bloqueados.\n\nO bloqueio foi realizado por $1.\nO motivo apresentado foi $2.\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\nNote que para utilizar a funcionalidade \"Contactar utilizador\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.", - "autoblockedtext": "O seu endereço IP foi bloqueado de forma automática porque foi utilizado recentemente por outro utilizador, o qual foi bloqueado por $1.\nO motivo apresentado foi:\n\n:$2\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\n\nNote que para utilizar a funcionalidade \"Contactar utilizador\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\n\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.", + "blockedtext": "O seu nome de utilizador ou endereço IP foram bloqueados.\n\nO bloqueio foi realizado por $1.\nO motivo apresentado foi $2.\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\nNote que para utilizar a funcionalidade \"{{int:emailuser}}\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.", + "autoblockedtext": "O seu endereço IP foi bloqueado de forma automática porque foi utilizado recentemente por outro utilizador, o qual foi bloqueado por $1.\nO motivo apresentado foi:\n\n:$2\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\n\nNote que para utilizar a funcionalidade \"{{int:emailuser}}\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\n\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.", "systemblockedtext": "O seu nome de utilizador ou endereço IP foram bloqueados automaticamente pelo MediaWiki.\nO motivo fornecido é:\n\n:$2\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nO seu endereço IP atual é $3.\nInclua todos os detalhes acima em quaisquer contactos sobre este assunto, por favor.", "blockednoreason": "sem motivo especificado", "whitelistedittext": "Precisa de $1 para poder editar páginas.", @@ -1561,7 +1564,7 @@ "recentchangeslinked-feed": "Alterações relacionadas", "recentchangeslinked-toolbox": "Alterações relacionadas", "recentchangeslinked-title": "Alterações relacionadas com \"$1\"", - "recentchangeslinked-summary": "Introduza o nome de uma página para ver as mudanças a todas as páginas que contêm hiperligações para ela ou para as quais a página fornecida contém hiperligações (para ver as que pertencem a uma categoria, introduza Categoria:Nome da categoria). As mudanças às suas [[Special:Watchlist|páginas vigiadas]] aparecem a negrito.", + "recentchangeslinked-summary": "Introduza o nome de uma página para ver as mudanças a todas as páginas que contêm hiperligações para ela ou para as quais a página fornecida contém hiperligações (para ver as que pertencem a uma categoria, introduza {{ns:category}}:Nome da categoria). As mudanças às suas [[Special:Watchlist|páginas vigiadas]] aparecem a negrito.", "recentchangeslinked-page": "Nome da página:", "recentchangeslinked-to": "Inversamente, mostrar mudanças às páginas que contêm hiperligações para esta", "recentchanges-page-added-to-category": "[[:$1]] foi adicionada à categoria", @@ -2040,6 +2043,7 @@ "apisandbox-dynamic-parameters-add-label": "Adicionar parâmetro:", "apisandbox-dynamic-parameters-add-placeholder": "Nome do parâmetro", "apisandbox-dynamic-error-exists": "Um parâmetro com o nome \"$1\" já existe.", + "apisandbox-templated-parameter-reason": "Este [[Special:ApiHelp/main#main/templatedparams|parâmetro modelado]] é oferecido com base {{PLURAL:$1|no valor|nos valores}} de $2.", "apisandbox-deprecated-parameters": "Parâmetros obsoletos", "apisandbox-fetch-token": "Auto-preencher o token", "apisandbox-add-multi": "Adicionar", @@ -2171,7 +2175,7 @@ "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": "Enviar correio eletrónico a {{GENDER:{{BASEPAGENAME}}|este utilizador|esta utilizadora|este(a) utilizador(a)}}", + "emailuser": "Enviar correio eletrónico a {{GENDER:{{BASEPAGENAME}}|este utilizador|esta utilizadora}}", "emailuser-title-target": "Enviar correio eletrónico a {{GENDER:$1|este utilizador|esta utilizadora}}", "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.", @@ -4069,5 +4073,6 @@ "pagedata-title": "Dados de página", "pagedata-text": "Esta página fornece uma interface de dados para páginas. Forneça o título da página no URL, usando a sintaxe de subpáginas, por favor.\n* Aplica-se a negociação de conteúdo com base no cabeçalho Accept do seu cliente. Isto significa que os dados da página serão fornecidos no formato preferido do seu cliente.", "pagedata-not-acceptable": "Não foi encontrado nenhum formato correspondente. Tipos MIME suportados: $1", - "pagedata-bad-title": "Título inválido: $1." + "pagedata-bad-title": "Título inválido: $1.", + "unregistered-user-config": "Por razões de segurança as subpáginas de utilizador com JavaScript, CSS e JSON não podem ser carregadas para utilizadores não registados." } diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index 17e26ae75d..0947db2173 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -2280,6 +2280,7 @@ "apisandbox-dynamic-parameters-add-label": "JavaScript label for the widget to add a new arbitrary parameter.", "apisandbox-dynamic-parameters-add-placeholder": "JavaScript text field placeholder for the widget to add a new arbitrary parameter.", "apisandbox-dynamic-error-exists": "Displayed as an error message from JavaScript when trying to add a new arbitrary parameter with a name that already exists. Parameters:\n* $1 - Parameter name that failed.", + "apisandbox-templated-parameter-reason": "Displayed (from JavaScript) on each instance of a templated parameter.\n\nParameters:\n* $1 - Number of fields in $2.\n* $2 - List of targeted fields, combined using {{msg-mw|comma-separator}} and {{msg-mw|and}}.", "apisandbox-deprecated-parameters": "JavaScript button label and fieldset legend for separating deprecated parameters in the UI.", "apisandbox-fetch-token": "Label for the button that fetches a CSRF token.", "apisandbox-add-multi": "Label for the button to add another value to a field that accepts multiple values\n{{Identical|Add}}", @@ -4664,5 +4665,6 @@ "pagedata-title": "Title shown on the special page when a form or text is presented", "pagedata-text": "Error shown when none of the formats acceptable to the client is supported (HTTP error 406). Parameters:\n* $1 - the list of supported MIME types", "pagedata-not-acceptable": "No matching format found. Supported MIME types: $1", - "pagedata-bad-title": "Error shown when the requested title is invalid. Parameters:\n* $1: the malformed ID" + "pagedata-bad-title": "Error shown when the requested title is invalid. Parameters:\n* $1: the malformed ID", + "unregistered-user-config": "Shown when viewing a user JS, CSS or JSON subpage with ?action=raw&ctype= where there is no such user. It is shown as a paragraph after a header saying 'Forbidden'." } diff --git a/languages/i18n/ru.json b/languages/i18n/ru.json index 99d05480ba..f80a820a15 100644 --- a/languages/i18n/ru.json +++ b/languages/i18n/ru.json @@ -633,6 +633,7 @@ "botpasswords-existing": "Существующие пароли бота", "botpasswords-createnew": "Создать новый пароль бота", "botpasswords-editexisting": "Редактировать существующий пароль бота", + "botpasswords-label-needsreset": "(пароль должен быть сброшен)", "botpasswords-label-appid": "Название бота:", "botpasswords-label-create": "Создать", "botpasswords-label-update": "Обновить", @@ -656,6 +657,7 @@ "botpasswords-restriction-failed": "Из-за ограничений, связанных с паролем бота, вход не произведён.", "botpasswords-invalid-name": "Указанное имя участника не содержит разделителя для пароля бота («$1»).", "botpasswords-not-exist": "У участника «$1» нет пароля для бота с названием «$2».", + "botpasswords-needs-reset": "Пароль для бота «$1» {{GENDER:$2|участника|участницы}} «$2» должен быть сброшен.", "resetpass_forbidden": "Пароль не может быть изменён", "resetpass_forbidden-reason": "Пароли не могут быть изменены: $1", "resetpass-no-info": "Чтобы обращаться непосредственно к этой странице, вам следует представиться системе.", @@ -751,8 +753,8 @@ "subject-preview": "Предпросмотр темы/заголовка:", "previewerrortext": "При попытке отобразить предварительный просмотр ваших изменений произошла ошибка.", "blockedtitle": "Участник заблокирован", - "blockedtext": "Ваша учётная запись или IP-адрес заблокированы.\n\nБлокировка произведена администратором $1.\nУказана следующая причина: «$2».\n\n* Начало блокировки: $8\n* Окончание блокировки: $6\n* Цель блокировки: $7\n\nВы можете связаться с $1 или любым другим [[{{MediaWiki:Grouppage-sysop}}|администратором]], чтобы обсудить блокировку.\nОбратите внимание, что вы не сможете использовать функцию «письмо участнику», если в своих [[Special:Preferences|персональных настройках]] не задали или не подтвердили корректный адрес электронной почты, или если ваша блокировка включает запрет отправки писем подобным образом.\nВаш IP-адрес — $3, идентификатор блокировки — $5.\nПожалуйста, указывайте эти сведения в любых своих обращениях.", - "autoblockedtext": "Ваш IP-адрес автоматически заблокирован в связи с тем, что он ранее использовался кем-то из участников, заблокированных {{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": "Ваша учётная запись или IP-адрес заблокированы.\n\nБлокировка произведена администратором $1.\nУказана следующая причина: $2.\n\n* Начало блокировки: $8\n* Окончание блокировки: $6\n* Цель блокировки: $7\n\nВы можете связаться с $1 или любым другим [[{{MediaWiki:Grouppage-sysop}}|администратором]], чтобы обсудить блокировку.\nОбратите внимание, что вы не сможете использовать функцию «{{int:emailuser}}», если в своих [[Special:Preferences|персональных настройках]] не задали или не подтвердили корректный адрес электронной почты, или если ваша блокировка включает запрет отправки писем подобным образом.\nВаш IP-адрес — $3, идентификатор блокировки — $5.\nПожалуйста, указывайте эти сведения в любых своих обращениях.", + "autoblockedtext": "Ваш IP-адрес автоматически заблокирован в связи с тем, что он ранее использовался кем-то из участников, заблокированных администратором $1. \nБыла указана следующая причина блокировки:\n\n: «$2».\n\n* Начало блокировки: $8\n* Окончание блокировки: $6\n* Цель блокировки: $7\n\nВы можете связаться с $1 или любым другим [[{{MediaWiki:Grouppage-sysop}}|администратором]], чтобы обсудить блокировку.\n\nОбратите внимание, что вы не сможете использовать функцию «{{int:emailuser}}», если в своих [[Special:Preferences|персональных настройках]] не задали или не подтвердили корректный адрес электронной почты, или если ваша блокировка включает запрет отправки писем подобным образом.\n\nВаш IP-адрес — $3, идентификатор блокировки — #$5.\nПожалуйста, указывайте эти сведения в любых своих обращениях.", "systemblockedtext": "Ваше имя участника или IP-адрес были автоматически заблокированы MediaWiki.\nУказана следующая причина:\n\n:$2\n\n* Начало блокировки: $8\n* Окончание блокировки: $6\n* Цель блокировки: $7\n\nВаш текущий IP-адрес $3.\nПожалуйста, указывайте все эти сведения в любых своих обращениях.", "blockednoreason": "причина не указана", "whitelistedittext": "Вы должны $1 для изменения страниц.", @@ -2096,6 +2098,7 @@ "apisandbox-dynamic-parameters-add-label": "Добавить параметр:", "apisandbox-dynamic-parameters-add-placeholder": "Имя параметра", "apisandbox-dynamic-error-exists": "Параметр с именем «$1» уже существует.", + "apisandbox-templated-parameter-reason": "Этот [[Special:ApiHelp/main#main/templatedparams|шаблонный параметр]] предлагается на основе {{PLURAL:$1|значения|значений}} $2.", "apisandbox-deprecated-parameters": "Устаревшие параметры", "apisandbox-fetch-token": "Автозаполнение токена", "apisandbox-add-multi": "Добавить", @@ -4126,7 +4129,7 @@ "mediastatistics-header-audio": "Аудио", "mediastatistics-header-video": "Видео", "mediastatistics-header-multimedia": "Мультимедиа", - "mediastatistics-header-office": "Офисные", + "mediastatistics-header-office": "Документы", "mediastatistics-header-text": "Текстовые", "mediastatistics-header-executable": "Исполняемые", "mediastatistics-header-archive": "Сжатые форматы", @@ -4326,5 +4329,6 @@ "pagedata-title": "Данные страницы", "pagedata-text": "Эта страница предоставляет интерфейс к данным страниц. Пожалуйста, введите заголовок страницы в URL, используя синтаксис подстраниц.\n* Согласование содержимого применяется основываясь на заголовке Accept вашего клиента. Это означает, что данные страницы будут предоставлены в формате, предпочитаемом вашим клиентом.", "pagedata-not-acceptable": "Соответствующий формат не найден. Поддерживаемые MIME-типы: $1", - "pagedata-bad-title": "Некорректный заголовок: $1." + "pagedata-bad-title": "Некорректный заголовок: $1.", + "unregistered-user-config": "По соображениям безопасности пользовательские подстраницы JavaScript, CSS и JSON не могут быть загружены для незарегистрированных участников." } diff --git a/languages/i18n/sat.json b/languages/i18n/sat.json index 65f27f6c1a..81537a0a4c 100644 --- a/languages/i18n/sat.json +++ b/languages/i18n/sat.json @@ -352,8 +352,8 @@ "userlogin-helplink2": "ᱵᱚᱞᱚᱜ ᱠᱷᱟᱹᱛᱤᱨ ᱜᱚᱸᱲᱚᱸ", "userlogin-createanother": "ᱮᱴᱟᱜ ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱢᱮ", "createacct-emailrequired": "ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ", - "createacct-emailoptional": "Email ᱴᱷᱤᱠᱱᱟ (ᱵᱟᱹᱲᱛᱤᱛᱮ)", - "createacct-email-ph": "ᱟᱢᱟᱜ email ᱴᱷᱤᱠᱱᱟ ᱵᱚᱞᱚᱭᱢᱮ", + "createacct-emailoptional": "ᱤᱢᱮᱞ ᱴᱷᱤᱠᱱᱟ (ᱟᱢᱠᱩᱥᱤ)", + "createacct-email-ph": "ᱟᱢᱟᱜ ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱟᱫᱮᱨᱢᱮ", "createacct-another-email-ph": "ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱟᱫᱮᱨᱢᱮ", "createaccountmail": "E-mail hotete", "createacct-realname": "ᱥᱚᱛ ᱧᱩᱛᱩᱢ (ᱚᱯᱥᱱᱟᱞ)", @@ -363,7 +363,7 @@ "createacct-another-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱢᱮ", "createacct-continue-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨ ᱛᱚᱝᱜᱮᱢᱮ", "createacct-another-continue-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨ ᱛᱚᱝᱜᱮᱢᱮ", - "createacct-benefit-heading": "{{SITENAME}} ᱟᱢ ᱞᱮᱠᱟᱱ ᱦᱚᱲ ᱦᱚᱛᱮᱛᱮ ᱛᱮᱭᱟᱨ ᱟᱠᱟᱱ᱾", + "createacct-benefit-heading": "{{SITENAME}} ᱫᱚ ᱟᱢ ᱞᱮᱠᱟᱱ ᱦᱚᱲ ᱦᱚᱛᱮᱛᱮ ᱛᱮᱭᱟᱨ ᱟᱠᱟᱱ᱾", "createacct-benefit-body1": "{{PLURAL:$1|ᱥᱟᱯᱲᱟᱣ|ᱥᱟᱯᱲᱟᱣᱠᱚ}}", "createacct-benefit-body2": "{{PLURAL:$1|ᱥᱟᱦᱴᱟ|ᱥᱟᱦᱴᱟᱠᱳ}}", "createacct-benefit-body3": "ᱱᱮᱛᱟᱨ {{PLURAL:$1|ᱮᱱᱮᱢᱤᱭᱟᱹ|ᱮᱱᱮᱢᱤᱭᱟᱹᱠᱚ}}", @@ -488,7 +488,7 @@ "summary-preview": "ᱜᱩᱴ ᱠᱟᱛᱷᱟ ᱩᱱᱩᱫᱩᱜ:", "subject-preview": "ᱜᱩᱴᱠᱟᱛᱷᱟ ᱩᱱᱩᱫᱩᱜ:", "blockedtitle": "ᱵᱮᱵᱷᱟᱨᱤᱡ ᱫᱚ ᱮᱥᱮᱫ ᱚᱪᱚᱣᱟᱠᱟᱱᱟᱭ", - "blockedtext": "ᱟᱢᱟᱜ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱧᱩᱛᱩᱢ ᱟᱨᱵᱟᱝ IP ᱵᱩᱴᱟᱹ ᱫᱚ ᱵᱚᱸᱫᱽ ᱟᱠᱟᱱᱟ á±¾ \n\nᱱᱚᱶᱟ ᱵᱚᱸᱫᱽ ᱫᱚ $1 ᱫᱟᱨᱟᱭᱛᱮ ᱦᱩᱭᱟᱠᱱᱟ á±¾\nᱱᱚᱶᱟ ᱨᱮᱱᱟᱜ ᱚᱡᱮ ᱫᱚ ᱮᱢᱮᱱᱟ $2.\n\n* ᱵᱚᱸᱫᱽ ᱮᱦᱚᱵ: $8\n* ᱵᱚᱸᱫᱽ ᱢᱩᱪᱟᱹᱫ: $6\n* ᱟᱥᱟᱦᱟᱱ ᱵᱚᱸᱫᱽᱠᱚ: $7\n\nᱟᱢ $1 ᱮᱢ ᱥᱟᱹᱜᱟᱹᱭ ᱫᱟᱲᱮᱭᱟᱭᱟ ᱵᱟᱝᱠᱷᱟᱱ ᱮᱴᱟᱜ [[{{MediaWiki:Grouppage-sysop}}|ᱟᱰᱢᱤᱱᱤᱥᱴᱨᱮᱴᱚᱨ]] ᱵᱚᱸᱫᱽ ᱵᱟᱵᱚᱫᱽ ᱛᱮ ᱜᱟᱞᱚᱪ ᱞᱟᱹᱜᱤᱫ á±¾\nᱟᱢ ᱵᱟᱢ ᱵᱮᱵᱷᱟᱨ ᱫᱟᱲᱮᱭᱟᱜ \"email this user\" ᱥᱩᱵᱤᱫᱷᱟ ᱡᱚᱛᱷᱟᱛ ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱛᱟᱢ ᱵᱟᱝ ᱛᱟᱦᱮᱸᱱ ᱠᱷᱟᱱ ᱟᱨ ᱱᱚᱶᱟ ᱫᱚ ᱪᱤᱱᱦᱟᱹᱣ-ᱟ [[Special:Preferences|ᱠᱷᱟᱛᱟ ᱧᱮᱞᱚᱚᱜ]] ᱠᱷᱚᱱ ᱟᱨ ᱟᱢ ᱫᱚ ᱵᱟᱢ ᱵᱚᱸᱫᱽ ᱟᱠᱟᱱᱟ ᱱᱚᱶᱟ ᱵᱮᱵᱷᱟᱨ ᱠᱷᱚᱱ á±¾\nᱟᱢᱟᱜ ᱱᱤᱛᱚᱜᱟᱜ IP ᱵᱩᱴᱟᱹ ᱫᱚ $3, ᱟᱨ ᱵᱚᱸᱫᱽ ID ᱫᱚ #$5 \nᱫᱟᱭᱟᱠᱟᱛᱮ ᱥᱮᱞᱮᱫᱽ ᱢᱮ ᱪᱮᱛᱟᱱᱟᱜ ᱠᱟᱛᱷᱟᱠᱚ ᱡᱚᱛᱚ ᱞᱮᱠᱟᱱ ᱠᱩᱠᱞᱤ ᱨᱮ á±¾", + "blockedtext": "ᱟᱢᱟᱜ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱧᱩᱛᱩᱢ ᱟᱨᱵᱟᱝ IP ᱵᱩᱴᱟᱹ ᱫᱚ ᱵᱚᱸᱫᱽ ᱟᱠᱟᱱᱟ á±¾ \n\nᱱᱚᱶᱟ ᱵᱚᱸᱫᱽ ᱫᱚ $1 ᱫᱟᱨᱟᱭᱛᱮ ᱦᱩᱭᱟᱠᱱᱟ á±¾\nᱱᱚᱶᱟ ᱨᱮᱱᱟᱜ ᱚᱡᱮ ᱫᱚ ᱮᱢᱮᱱᱟ $2.\n\n* ᱵᱚᱸᱫᱽ ᱮᱦᱚᱵ: $8\n* ᱵᱚᱸᱫᱽ ᱢᱩᱪᱟᱹᱫ: $6\n* ᱟᱥᱟᱦᱟᱱ ᱵᱚᱸᱫᱽᱠᱚ: $7\n\nᱟᱢ $1 ᱮᱢ ᱥᱟᱹᱜᱟᱹᱭ ᱫᱟᱲᱮᱭᱟᱭᱟ ᱵᱟᱝᱠᱷᱟᱱ ᱮᱴᱟᱜ [[{{MediaWiki:Grouppage-sysop}}|ᱟᱰᱢᱤᱱᱤᱥᱴᱨᱮᱴᱚᱨ]] ᱵᱚᱸᱫᱽ ᱵᱟᱵᱚᱫᱽ ᱛᱮ ᱜᱟᱞᱚᱪ ᱞᱟᱹᱜᱤᱫ á±¾\nᱟᱢ ᱵᱟᱢ ᱵᱮᱵᱷᱟᱨ ᱫᱟᱲᱮᱭᱟᱜ \"{{int:emailuser}}\" ᱥᱩᱵᱤᱫᱷᱟ ᱡᱚᱛᱷᱟᱛ ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱛᱟᱢ ᱵᱟᱝ ᱛᱟᱦᱮᱸᱱ ᱠᱷᱟᱱ ᱟᱨ ᱱᱚᱶᱟ ᱫᱚ ᱪᱤᱱᱦᱟᱹᱣ-ᱟ [[Special:Preferences|ᱠᱷᱟᱛᱟ ᱧᱮᱞᱚᱚᱜ]] ᱠᱷᱚᱱ ᱟᱨ ᱟᱢ ᱫᱚ ᱵᱟᱢ ᱵᱚᱸᱫᱽ ᱟᱠᱟᱱᱟ ᱱᱚᱶᱟ ᱵᱮᱵᱷᱟᱨ ᱠᱷᱚᱱ á±¾\nᱟᱢᱟᱜ ᱱᱤᱛᱚᱜᱟᱜ IP ᱵᱩᱴᱟᱹ ᱫᱚ $3, ᱟᱨ ᱵᱚᱸᱫᱽ ID ᱫᱚ #$5 \nᱫᱟᱭᱟᱠᱟᱛᱮ ᱥᱮᱞᱮᱫᱽ ᱢᱮ ᱪᱮᱛᱟᱱᱟᱜ ᱠᱟᱛᱷᱟᱠᱚ ᱡᱚᱛᱚ ᱞᱮᱠᱟᱱ ᱠᱩᱠᱞᱤ ᱨᱮ á±¾", "blockednoreason": "ᱡᱟᱸᱦᱟᱸᱱ ᱚᱡᱮ ᱵᱟᱝ ᱮᱢᱠᱟᱱᱟ", "whitelistedittext": "ᱥᱟᱦᱴᱟ ᱥᱟᱯᱲᱟᱣ ᱞᱟᱹᱜᱤᱛ $1 ᱮᱢ ᱦᱩᱭᱩᱜ-ᱟ᱾", "nosuchsectiontitle": "ᱛᱷᱚᱠ ᱵᱟᱝ ᱧᱟᱢᱞᱮᱱᱟ", @@ -500,7 +500,7 @@ "newarticle": "(ᱱᱟᱣᱟᱱᱟᱜ)", "newarticletext": "ᱟᱢ ᱚᱠᱟ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱡᱚᱱᱟᱲᱮᱢ ᱯᱟᱸᱡᱟᱸ ᱟᱹᱜᱩᱭᱫᱟ ᱚᱱᱚ ᱫᱚ ᱵᱟᱱᱩᱜ-ᱟ᱾\nᱚᱱᱟ ᱥᱟᱦᱴᱟ ᱛᱮᱭᱟᱨ ᱞᱟᱹᱜᱤᱛ ᱛᱮ, ᱞᱟᱛᱟᱨ ᱵᱟᱠᱥᱚ ᱵᱷᱤᱛᱨᱤᱨᱮ ᱚᱞ ᱮᱦᱚᱵ ᱢᱮ (ᱟᱨᱦᱚᱸ ᱡᱟᱹᱥᱛᱤ ᱵᱟᱰᱟᱭ ᱞᱟᱹᱜᱤᱛᱴᱮ [$1 ᱜᱚᱸᱲᱚᱸ ᱥᱟᱦᱴᱟ] ᱯᱟᱸᱡᱚᱸᱭᱢᱮ)á±¾\nᱟᱢ ᱵᱷᱩᱞᱛᱮ ᱱᱚᱸᱰᱮᱢ ᱦᱮᱡ ᱟᱠᱟᱱ ᱠᱷᱟᱡ, ᱟᱢᱟᱜ ᱵᱨᱟᱣᱡᱟᱨ ᱨᱮᱱᱟᱜ '''ᱛᱟᱭᱚᱢ''' ᱵᱟᱴᱚᱱ ᱞᱤᱱᱢᱮ᱾", "anontalkpagetext": "----\n\nᱱᱚᱶᱟ ᱫᱚ ᱜᱟᱞᱚᱪ ᱥᱟᱦᱴᱟ ᱠᱟᱱᱟ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱚᱣᱟᱜ ᱡᱟᱦᱟᱸᱭ ᱫᱚ ᱠᱷᱟᱛᱟ ᱵᱟᱭ ᱛᱮᱭᱟᱨ ᱟᱠᱟᱫᱟ ᱱᱤᱛ ᱦᱟᱹᱵᱤᱡ, ᱟᱨᱵᱟᱝ ᱡᱟᱦᱟᱸᱭ ᱵᱮᱵᱷᱟᱨ ᱟᱠᱟᱫᱟ ᱱᱚᱶᱟ á±¾\nᱚᱱᱟᱛᱮ ᱟᱞᱮ ᱮᱞᱮᱞ IP ᱞᱮ ᱵᱮᱵᱷᱟᱨᱮᱜ-ᱟ ᱩᱱᱤ ᱪᱤᱱᱦᱟᱹᱣ ᱞᱟᱹᱜᱤᱫ á±¾\nᱚᱱᱠᱟᱱ IP ᱵᱩᱴᱟᱹ ᱫᱚ ᱦᱟᱹᱴᱤᱧ ᱫᱟᱲᱮᱭᱟᱜ-ᱟ ᱛᱤᱢᱤᱱ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱫᱟᱨᱟᱭᱛᱮ á±¾\nᱡᱩᱫᱤ ᱟᱢ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱟᱱᱟᱢ ᱟᱨ ᱵᱷᱟᱹᱵᱤᱭᱮᱜ-ᱟᱢ ᱵᱟᱝ ᱡᱚᱲᱟᱣᱟᱱ ᱠᱟᱛᱷᱟ ᱟᱢᱮ ᱩᱫᱩᱜᱢᱮ ᱠᱟᱱᱟ, ᱮᱱᱠᱷᱟᱱ [[Special:CreateAccount|ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱢᱮ]] ᱟᱨᱵᱟᱝ [[Special:UserLogin|ᱞᱚᱜᱤᱱ]] ᱢᱮ ᱫᱟᱨᱟᱭ ᱵᱷᱮᱣᱱᱟ ᱠᱚ ᱥᱟᱦᱟᱭ ᱞᱟᱹᱜᱤᱫ ᱮᱴᱟᱜ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱚ ᱥᱟᱶ á±¾", - "noarticletext": "ᱱᱮᱛᱚᱜ ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟᱨᱮ ᱪᱮᱫᱜᱮ ᱵᱟᱹᱱᱩᱜ-ᱟ᱾\nᱮᱴᱟᱜ ᱥᱟᱦᱴᱟᱨᱮᱢ [[Special:Search/{{PAGENAME}}|search for this page title]],\n[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page].", + "noarticletext": "ᱱᱮᱛᱚᱜ ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟᱨᱮ ᱪᱮᱫᱜᱮ ᱵᱟᱹᱱᱩᱜ-ᱟ᱾\nᱮᱴᱟᱜ ᱥᱟᱦᱴᱟᱨᱮᱢ [[Special:Search/{{PAGENAME}}|ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱧᱩᱛᱩᱢ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ]],\n[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ᱡᱚᱲᱟᱣᱟᱱ ᱞᱚᱜᱽ ᱠᱚ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱥᱟᱯᱲᱟᱣ ᱢᱮ].", "noarticletext-nopermission": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟᱨᱮ ᱱᱤᱛᱚᱜ ᱪᱮᱫᱜᱮ ᱚᱞ ᱵᱟᱹᱱᱩᱜ-ᱟ᱾\n\nᱟᱢ [[Special:Search/{{PAGENAME}}|ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟᱨᱮᱱᱟᱜ ᱧᱤᱛᱩᱢᱮᱢ ᱥᱮᱸᱫᱽᱨᱟ ᱫᱟᱲᱮᱭᱟᱜ-ᱟ]] ᱮᱴᱟᱜ ᱥᱟᱦᱴᱟ ᱠᱚᱨᱮᱦᱚᱸ,\nᱟᱨᱵᱟᱝ [{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs].", "userpage-userdoesnotexist": "\"$1\" ńutuman jahãe beoharićaḱ ekauná¹­ do baṅ resá¹­ri hoeakana. Daya kate biḍạo katet́ ńelmẽ noa sakam do benoa/sompadonem menet́ kana se baṅ.", "userpage-userdoesnotexist-view": "ᱵᱮᱵᱦᱟᱨᱤᱭᱟᱜ \"$1\" ᱮᱠᱟᱣᱱᱴ ᱫᱚ ᱵᱟᱝ ᱨᱮᱥᱴᱨᱤ ᱟᱠᱟᱱᱟ᱾", @@ -638,7 +638,7 @@ "searchrelated": "ᱥᱟᱹᱜᱟᱹᱭᱟᱱᱠᱩ", "searchall": "ᱡᱚᱛᱚ", "search-showingresults": "{{PLURAL:$4|ᱚᱨᱡᱚ $1 ᱨᱮᱱᱟᱜ $3|ᱚᱨᱡᱚᱠᱚ $1 - $2 ᱨᱮᱱᱟᱜ $3}}", - "search-nonefound": "ᱠᱩᱠᱞᱤ ᱥᱟᱶᱛᱮ ᱯᱷᱚᱞ ᱵᱟᱝ ᱢᱤᱞᱟᱹᱮ ᱞᱮᱱᱟ᱾", + "search-nonefound": "ᱠᱩᱠᱞᱤ ᱥᱟᱶᱛᱮ ᱚᱨᱡᱚ ᱵᱟᱝ ᱯᱚᱲᱛᱟ ᱞᱮᱱᱟ᱾", "powersearch-ns": "ᱨᱟᱠᱷᱟ ᱧᱩᱛᱩᱢ ᱨᱮ ᱥᱮᱸᱫᱽᱨᱟ", "powersearch-togglelabel": "ᱠᱷᱚᱸᱡᱽ:", "powersearch-toggleall": "ᱡᱚᱛᱚ", @@ -786,7 +786,7 @@ "recentchangeslinked-feed": "ᱥᱟᱹᱜᱟᱹᱭᱟᱱ ᱵᱚᱫᱚᱞᱠᱚ", "recentchangeslinked-toolbox": "ᱥᱟᱹᱜᱟᱹᱭᱟᱱ ᱵᱚᱫᱚᱞᱠᱚ", "recentchangeslinked-title": "ᱵᱚᱫᱚᱞᱟᱜ ᱠᱚᱫᱚ \"$1\" ᱥᱟᱶᱛᱮ ᱡᱚᱲᱟᱣ ᱜᱮᱭᱟ", - "recentchangeslinked-summary": "ᱱᱚᱣᱟ ᱫᱚ ᱚᱱᱟ ᱛᱟᱹᱞᱠᱟᱹ ᱠᱟᱱᱟ ᱚᱠᱟ ᱫᱟ ᱱᱮᱵᱮᱛᱟᱨᱜᱮ ᱵᱚᱫᱚᱞ ᱦᱩᱭ ᱟᱠᱟᱱᱟ ᱚᱠᱟ ᱫᱚ ᱛᱷᱚᱠ ᱦᱟᱛᱟᱣ ᱟᱠᱟᱱ ᱥᱟᱠᱟᱢ ᱠᱷᱚᱱ᱾\n\n[[Special:Watchlist|ᱟᱢᱟᱜ ᱧᱮᱞ ᱞᱤᱥᱴᱤ]] ᱨᱮᱭᱟᱜ ᱥᱟᱦᱴᱟ ᱫᱚ ᱢᱚᱴᱟ ᱛᱮ ᱚᱞ ᱟᱠᱟᱱᱟ á±¾", + "recentchangeslinked-summary": "ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱧᱩᱛᱩᱢ ᱟᱫᱮᱨᱢᱮ ᱡᱟᱦᱟᱸ ᱠᱷᱚᱱ ᱡᱚᱱᱚᱲᱟᱣ ᱟᱨᱵᱟᱝ ᱥᱟᱦᱴᱟ ᱵᱚᱫᱚᱞ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱫ á±¾ (ᱛᱷᱚᱠ ᱨᱮᱱᱟᱜ ᱥᱚᱦᱮᱫ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱫ, ᱟᱫᱮᱨᱢᱮ {{ns:category}}:ᱛᱷᱚᱠ ᱧᱩᱛᱩᱢ) á±¾ [[Special:Watchlist|ᱟᱢᱟᱜ ᱧᱮᱞ ᱞᱤᱥᱴᱤ]] ᱨᱮᱱᱟᱜ ᱵᱚᱱᱚᱫᱚᱞᱟᱜ ᱥᱟᱦᱴᱟ ᱫᱚ ᱢᱚᱴᱟ ᱛᱮ ᱚᱞ ᱟᱠᱟᱱᱟ á±¾", "recentchangeslinked-page": "ᱥᱟᱦᱴᱟ ᱧᱤᱛᱩᱢ :", "recentchangeslinked-to": "ᱡᱚᱱᱚᱲ ᱥᱟᱦᱴᱟᱨᱮ ᱧᱮᱞ ᱚᱪᱚᱭ ᱢᱮ ᱮᱢᱟᱜ ᱥᱟᱦᱴᱟ ᱵᱟᱹᱜᱤ ᱠᱟᱛᱮ", "upload": "ᱨᱮᱫ ᱞᱟᱫᱮᱢᱮ", @@ -834,7 +834,7 @@ "filehist-thumb": "ᱴᱤᱯ", "filehist-thumbtext": "Thumbnail for version as of $1", "filehist-nothumb": "ᱵᱟᱹᱱᱩᱜ-ᱟ ᱴᱤᱯ-ᱨᱟᱢᱟ", - "filehist-user": "ᱵᱮᱵᱦᱟᱨᱤᱡ", + "filehist-user": "ᱵᱮᱵᱷᱟᱨᱤᱡ", "filehist-dimensions": "ᱡᱚᱠᱷᱟ", "filehist-filesize": "ᱨᱮᱫ ᱥᱟᱭᱤᱡᱽ", "filehist-comment": "ᱠᱟᱛᱷᱟ", @@ -869,7 +869,7 @@ "movethispage": "ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱥᱟᱦᱟᱭᱢᱮ", "pager-newer-n": "{{PLURAL:$1|1 ᱱᱟᱣᱟᱱᱟᱜ | ᱱᱟᱣᱟᱱᱟᱜ $1}}", "pager-older-n": "{{PLURAL:$1|ᱢᱟᱨᱮᱭᱟᱜ 1|ᱢᱟᱨᱮᱭᱟᱜ $1}}", - "booksources": "ᱯᱚᱛᱚᱵ ᱯᱷᱮᱰᱟᱛ ᱦᱚᱨᱠᱟ", + "booksources": "ᱯᱚᱛᱚᱵ ᱯᱷᱮᱰᱟᱛ ᱠᱚ", "booksources-search-legend": "ᱯᱚᱛᱚᱵ ᱨᱮᱭᱟᱜ ᱯᱷᱮᱰᱟᱛ ᱦᱚᱨ ᱞᱟᱹᱜᱤᱛ ᱥᱮᱸᱫᱽᱨᱟ", "booksources-search": "ᱥᱮᱸᱫᱽᱨᱟ", "specialloguserlabel": "ᱠᱟᱹᱢᱤᱭᱟᱹ:", @@ -964,8 +964,8 @@ "sp-contributions-submit": "ᱥᱮᱸᱫᱽᱨᱟ", "whatlinkshere": "ᱱᱚᱸᱰᱮ ᱫᱚ ᱪᱮᱫ ᱡᱚᱱᱚᱲ á± á±³", "whatlinkshere-title": "ᱚᱠᱟ ᱥᱟᱦᱴᱟ ᱠᱚᱫᱚ \"$1\" ᱨᱮ ᱡᱚᱱᱚᱲ ᱢᱮᱱᱟᱜ-ᱟ", - "whatlinkshere-page": "ᱥᱟᱦᱴᱟ", - "linkshere": "ᱞᱟᱛᱟᱨ ᱨᱮᱭᱟᱜ ᱥᱟᱦᱴᱟᱠᱚ ᱫᱚ '''[[:$1]]''' ᱡᱚᱱᱚᱲ ᱢᱮᱱᱟᱜ-ᱟ :", + "whatlinkshere-page": "ᱥᱟᱦᱴᱟ:", + "linkshere": "ᱞᱟᱛᱟᱨ ᱨᱮᱭᱟᱜ ᱥᱟᱦᱴᱟᱠᱚ ᱫᱚ [[:$1]] ᱥᱟᱶ ᱡᱚᱱᱚᱲ ᱢᱮᱱᱟᱜ-ᱟ :", "nolinkshere": "ᱥᱟᱦᱴᱟ ᱡᱚᱱᱚᱲ ᱵᱟᱱᱩᱜ-ᱟ ᱱᱤᱭᱟᱹ [[:$1]].", "isredirect": "ᱵᱟᱝ ᱥᱚᱡᱽᱦᱮ ᱥᱟᱦᱴᱟ", "istemplate": "ᱥᱮᱞᱮᱫ", @@ -1030,7 +1030,7 @@ "tooltip-ca-history": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱮᱱᱟᱝ ᱱᱟᱝ ᱧᱮᱞ ᱨᱩᱟᱹᱲ", "tooltip-ca-protect": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱨᱩᱠᱷᱤᱭᱟᱹᱭ ᱢᱮ", "tooltip-ca-delete": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱜᱮᱫᱽ ᱢᱮ", - "tooltip-ca-move": "ᱱᱚᱣᱲ ᱥᱟᱦᱴᱟ ᱠᱩᱞᱢᱮ", + "tooltip-ca-move": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱩᱪᱟᱹᱲᱢᱮ", "tooltip-ca-watch": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱫᱚ ᱟᱢᱟᱜ ᱧᱮᱞᱚᱜ ᱛᱟᱹᱞᱠᱟᱹᱨᱮ ᱡᱚᱲᱟᱣᱢᱮ", "tooltip-ca-unwatch": "ᱟᱢᱟᱜ ᱧᱮᱞ ᱛᱟᱹᱞᱠᱟᱹ ᱠᱷᱚᱡ ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱫᱚ ᱚᱪᱚᱜᱽ ᱢᱮ", "tooltip-search": "ᱥᱮᱸᱫᱽᱨᱟ {{SITENAME}}", @@ -1046,7 +1046,7 @@ "tooltip-n-help": "ᱥᱮᱸᱫᱽᱨᱟ ᱧᱟᱢ ᱨᱮᱭᱟᱜ ᱡᱟᱜᱟ", "tooltip-t-whatlinkshere": "ᱥᱟᱱᱟᱢ ᱩᱤᱠᱤ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱛᱟᱹᱞᱠᱟᱹ ᱟᱨ ᱡᱚᱱᱚᱲ ᱫᱚ ᱱᱚᱸᱰᱮ", "tooltip-t-recentchangeslinked": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱨᱮ ᱨᱚᱠᱟ ᱵᱚᱫᱚᱞ ᱟᱠᱟᱱ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱡᱚᱱᱚᱲ", - "tooltip-feed-atom": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱞᱟᱹᱜᱤᱛ Atom feed", + "tooltip-feed-atom": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱞᱟᱹᱜᱤᱫ ᱟᱴᱚᱢ ᱯᱷᱤᱰ", "tooltip-t-contributions": "ᱮᱱᱮᱢ ᱨᱮᱱᱟᱜ ᱛᱟᱹᱞᱠᱟᱹ {{GENDER:$1|ᱱᱩᱭ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}}", "tooltip-t-emailuser": "ᱢᱤᱫ ᱤᱢᱮᱞ ᱠᱩᱞᱟᱭᱢᱮ {{GENDER:$1|ᱱᱩᱭ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}}", "tooltip-t-upload": "ᱨᱮᱫ ᱠᱚ ᱞᱟᱫᱮᱢᱮ", @@ -1114,7 +1114,7 @@ "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|ᱥᱟᱦᱴᱟ|ᱥᱟᱦᱴᱟᱠᱚ}}", "file-info-size": "$1 x $2 pixels, file size: $3, MIME type: $4", "file-info-size-pages": "$1 × $2 ᱯᱤᱠᱥᱮᱞ, ᱨᱮᱫ ᱥᱚᱝ: $3, MIME ᱞᱮᱠᱟᱱ: $4, $5 {{PLURAL:$5|ᱥᱟᱦᱴᱟ|ᱥᱟᱦᱴᱟᱠᱚ}}", - "file-nohires": "ᱟᱭᱢᱟ ᱨᱮᱡᱩᱞᱮᱥᱚᱱ ᱵᱟᱱᱩᱜ-ᱟ᱾", + "file-nohires": "ᱥᱮᱬᱟ ᱨᱮᱡᱩᱞᱮᱥᱚᱱ ᱵᱟᱱᱩᱜ-ᱟ᱾", "svg-long-desc": "SVG ᱨᱮᱫ, ᱱᱚᱨᱢᱟᱞᱛᱮ $1 x $2 pixels, ᱨᱮᱫ ᱡᱟᱜᱟ: $3", "show-big-image": "ᱟᱥᱚᱞ ᱨᱮᱫ", "show-big-image-preview": "ᱧᱮᱞᱡᱚᱝ ᱨᱮᱱᱟᱜ ᱟᱠᱟᱨ:$1", diff --git a/languages/i18n/skr-arab.json b/languages/i18n/skr-arab.json index 0ee213e1cd..d549a85241 100644 --- a/languages/i18n/skr-arab.json +++ b/languages/i18n/skr-arab.json @@ -408,7 +408,7 @@ "yourdiff": "فرق", "templatesused": "ایں ورقے تے ورتے ڳئے {{PLURAL:$1|سانچے|سانچہ}}:", "templatesusedpreview": "ایں کچے کم تے ورتے ڳئے {{PLURAL:$1|سانچے|سانچہ}}:", - "template-protected": "(بچایا گیا)", + "template-protected": "(بچایا ڳیا)", "template-semiprotected": "(نیم محفوظ)", "hiddencategories": "ایہ ورقہ {{PLURAL:$1|1 لُکے زمریاں|$1 لکا زمرہ }} وچ شامل ہے:", "permissionserrors": "خطائے اجازت", @@ -861,7 +861,7 @@ "logentry-contentmodel-change-revertlink": "واپس", "logentry-contentmodel-change-revert": "واپس", "protectlogpage": "حفاظت لاگ", - "protectedarticle": "\"[[$1]]\" بچایا گیا اے", + "protectedarticle": "\"[[$1]]\" بچایا ڳیا ہے", "modifiedarticleprotection": "«[[$1]]» دا درجہ حفاظت تبدیل کیتا", "protectcomment": "سبب:", "protectexpiry": "مُکسی:", diff --git a/languages/i18n/sl.json b/languages/i18n/sl.json index f3e9296a7c..c5a187465b 100644 --- a/languages/i18n/sl.json +++ b/languages/i18n/sl.json @@ -515,6 +515,7 @@ "botpasswords-existing": "Obstoječa gesla botov", "botpasswords-createnew": "Ustvari novo geslo bota", "botpasswords-editexisting": "Uredi obstoječe geslo bota", + "botpasswords-label-needsreset": "(geslo mora biti ponastavljeno)", "botpasswords-label-appid": "Ime bota:", "botpasswords-label-create": "Ustvari", "botpasswords-label-update": "Posodobi", @@ -538,6 +539,7 @@ "botpasswords-restriction-failed": "Omejitve gesla bota preprečujejo to prijavo.", "botpasswords-invalid-name": "Navedeno uporabniÅ¡ko ime ne vsebuje ločila za geslo bota (»$1«).", "botpasswords-not-exist": "Uporabnik »$1« nima gesla bota z imenom »$2«.", + "botpasswords-needs-reset": "Geslo bota »$2« {{GENDER:$1|uporabnika|uporabnice}} »$1« mora biti ponastavljeno.", "resetpass_forbidden": "Gesla ne morete spremeniti", "resetpass_forbidden-reason": "Gesel nismo mogli spremeniti: $1", "resetpass-no-info": "Za neposreden dostop do te strani morate biti prijavljeni.", @@ -633,8 +635,8 @@ "subject-preview": "Predogled zadeve:", "previewerrortext": "Med poskusom prikaza predogleda vaÅ¡ih sprememb je priÅ¡lo do napake.", "blockedtitle": "Uporabnik je blokiran", - "blockedtext": "'''Urejanje z vaÅ¡im uporabniÅ¡kim imenom oziroma IP-naslovom je onemogočeno.'''\n\nBlokiral vas je $1.\nPodani razlog je ''$2''.\n\n* začetek blokade: $8\n* potek blokade: $6\n* blokirani uporabnik: $7\n\nO blokiranju se lahko pogovorite z uporabnikom/-co $1 ali katerim drugim [[{{MediaWiki:Grouppage-sysop}}|administratorjem]].\nVedite, da lahko ukaz »PoÅ¡lji uporabniku e-pismo« uporabite le, če ste v [[Special:Preferences|nastavitvah]] vpisali in potrdili svoj elektronski naslov in ta ni blokiran.\nVaÅ¡ IP-naslov je $3, Å¡tevilka blokade pa #$5.\nProsimo, vključite ju v vse morebitne poizvedbe.", - "autoblockedtext": "VaÅ¡ IP-naslov je bil samodejno blokiran, saj je bil uporabljen s strani drugega uporabnika, ki ga je blokiral $1.\nRazlog za to je bil naslednji:\n\n:''$2''\n\n* Začetek blokade: $8\n* Konec blokade: $6\n* Blokirani uporabnik: $7\n\nKontaktirate lahko $1 ali katerega od drugih [[{{MediaWiki:Grouppage-sysop}}|administratorjev]], da razpravljate o blokadi.\n\nVedite, da lahko funkcijo »{{:MediaWiki:Emailuser/sl}}« uporabljate le, če ste v svoje [[Special:Preferences|uporabniÅ¡ke nastavitve]] vnesli veljaven e-poÅ¡tni naslov, in vam njena uporaba ni bila preprečena.\n\nVaÅ¡ trenutni IP-naslov je $3, ID blokiranja pa #$5. Prosimo, vključite ta ID v vsako zastavljeno vpraÅ¡anje.", + "blockedtext": "Urejanje z vaÅ¡im uporabniÅ¡kim imenom oziroma IP-naslovom je onemogočeno.\n\nBlokiral vas je $1.\nPodani razlog je $2.\n\n* Začetek blokade: $8\n* Potek blokade: $6\n* Blokirani uporabnik: $7\n\nO blokiranju se lahko pogovorite z uporabnikom/-co $1 ali katerim drugim [[{{MediaWiki:Grouppage-sysop}}|administratorjem]].\nVedite, da lahko ukaz »{{int:emailuser}}« uporabite le, če ste v [[Special:Preferences|nastavitvah]] vpisali in potrdili svoj elektronski naslov in ta ni blokiran.\nVaÅ¡ IP-naslov je $3, Å¡tevilka blokade pa #$5.\nProsimo, vključite ju v vse morebitne poizvedbe.", + "autoblockedtext": "VaÅ¡ IP-naslov je bil samodejno blokiran, saj je bil uporabljen s strani drugega uporabnika, ki ga je blokiral $1.\nRazlog za to je bil naslednji:\n\n:$2\n\n* Začetek blokade: $8\n* Konec blokade: $6\n* Blokirani uporabnik: $7\n\nKontaktirate lahko $1 ali katerega od drugih [[{{MediaWiki:Grouppage-sysop}}|administratorjev]], da razpravljate o blokadi.\n\nVedite, da lahko funkcijo »{{int:emailuser}}« uporabljate le, če ste v svoje [[Special:Preferences|uporabniÅ¡ke nastavitve]] vnesli veljaven e-poÅ¡tni naslov, in vam njena uporaba ni bila preprečena.\n\nVaÅ¡ trenutni IP-naslov je $3, ID blokiranja pa #$5. Prosimo, vključite ta ID v vsako zastavljeno vpraÅ¡anje.", "systemblockedtext": "VaÅ¡e uporabniÅ¡ko ime ali IP-naslov je MediaWiki samodejn blokiral.\nPodani razlog je:\n\n:$2\n\n* Začetek blokade: $8\n* Potek blokade: $6\n* Blokirani uporabnik: $7\n\nVaÅ¡ trenutni IP-naslov je $3.\nProsimo, da v svoje poizvedbe vključite vse zgornje podatke.", "blockednoreason": "razlog ni podan", "whitelistedittext": "Za urejanje strani se morate $1.", @@ -3995,5 +3997,6 @@ "pagedata-title": "Podatki strani", "pagedata-text": "Ta stran nudi podatkovni vmesnik do strani. Prosimo, navedite naslov strani v URL-ju z uporabo skladnje podstrani.\n* Pogajanje o vsebini se nanaÅ¡a na glavo Accept vaÅ¡ega odjemalca. To pomeni, da bomo podatke strani posredovali v obliki, ki vaÅ¡emu odjemalcu bolj ustreza.", "pagedata-not-acceptable": "Nismo naÅ¡li ujemajoče oblike. Podprte vrste MIME: $1", - "pagedata-bad-title": "Neveljaven naslov: $1." + "pagedata-bad-title": "Neveljaven naslov: $1.", + "unregistered-user-config": "Iz varnostnih razlogov uporabniÅ¡kih podstrani JavaScript, CSS in JSON ne moremo naložiti neregistriranim uporabnikom." } diff --git a/languages/i18n/sv.json b/languages/i18n/sv.json index 534190a536..6bf1e4fe6c 100644 --- a/languages/i18n/sv.json +++ b/languages/i18n/sv.json @@ -577,6 +577,7 @@ "botpasswords-existing": "Befintliga botlösenord", "botpasswords-createnew": "Skapa ett nytt botlösenord", "botpasswords-editexisting": "Redigera ett befintligt botlösenord", + "botpasswords-label-needsreset": "(lösenordet behöver Ã¥terställas)", "botpasswords-label-appid": "Botnamn:", "botpasswords-label-create": "Skapa", "botpasswords-label-update": "Uppdatera", @@ -600,6 +601,7 @@ "botpasswords-restriction-failed": "Begränsningar av botlösenord tillÃ¥ter inte denna inloggning.", "botpasswords-invalid-name": "Det angivna användarnamnet innehÃ¥ller inte separatorn för botlösenord (\"$1\").", "botpasswords-not-exist": "Användaren \"$1\" har inte ett botlösenord som är \"$2\".", + "botpasswords-needs-reset": "Botlösenordet för botnamnet \"$2\" till {{GENDER:$1|användaren}} \"$1\" mÃ¥ste Ã¥terställas.", "resetpass_forbidden": "Lösenord kan inte ändras", "resetpass_forbidden-reason": "Lösenorden kan inte ändras: $1", "resetpass-no-info": "Du mÃ¥ste vara inloggad för att komma Ã¥t den här sidan direkt.", @@ -695,8 +697,8 @@ "subject-preview": "Förhandsgranskning av ämne:", "previewerrortext": "Ett fel uppstod när dina ändringar skulle förhandsgranskas.", "blockedtitle": "Användaren är blockerad", - "blockedtext": "'''Din IP-adress eller ditt användarnamn är blockerat.'''\n\nBlockeringen utfördes av $1 med motiveringen: ''$2''.\n\n* Blockeringen startade: $8\n* Blockeringen gäller till: $6.\n* Blockeringen var avsedd för: $7.\n\nDu kan kontakta $1 eller nÃ¥gon annan av [[{{MediaWiki:Grouppage-sysop}}|administratörerna]] för att diskutera blockeringen.\nOm du är inloggad och har uppgivit en e-postadress i dina [[Special:Preferences|inställningar]] sÃ¥ kan du använda funktionen 'Skicka e-post till den här användaren', sÃ¥vida du inte blivit blockerad frÃ¥n funktionen.\n\nDin IP-adress är $3 och blockerings-ID är #$5.\nVänligen ange informationen ovan i alla förfrÃ¥gningar som du gör i ärendet.", - "autoblockedtext": "Din IP-adress har blockerats automatiskt eftersom den har använts av en annan användare som blockerats av $1.\nMotiveringen av blockeringen var:\n\n:''$2''\n\n* Blockeringen startade: $8\n* Blockeringen gäller till: $6\n* Blockeringen är avsedd för: $7\n\nDu kan kontakta $1 eller nÃ¥gon annan [[{{MediaWiki:Grouppage-sysop}}|administratör]] för att diskutera blockeringen.\n\nObservera att du inte kan använda dig av funktionen \"skicka e-post till användare\" om du inte har registrerat en giltig e-postadress i [[Special:Preferences|dina inställningar]] eller om du har blivit blockerad frÃ¥n att skicka e-post.\n\nDin nuvarande IP-adress är $3, och blockerings-ID är #$5.\nVänligen ange informationen ovan i alla förfrÃ¥gningar som du gör i ärendet.", + "blockedtext": "'''Din IP-adress eller ditt användarnamn är blockerat.'''\n\nBlockeringen utfördes av $1 med motiveringen: ''$2''.\n\n* Blockeringen startade: $8\n* Blockeringen gäller till: $6.\n* Blockeringen var avsedd för: $7.\n\nDu kan kontakta $1 eller nÃ¥gon annan av [[{{MediaWiki:Grouppage-sysop}}|administratörerna]] för att diskutera blockeringen.\nOm du är inloggad och har uppgivit en e-postadress i dina [[Special:Preferences|inställningar]] sÃ¥ kan du använda funktionen \"{{int:emailuser}}\", sÃ¥vida du inte blivit blockerad frÃ¥n funktionen.\n\nDin IP-adress är $3 och blockerings-ID är #$5.\nVänligen ange informationen ovan i alla förfrÃ¥gningar som du gör i ärendet.", + "autoblockedtext": "Din IP-adress har blockerats automatiskt eftersom den har använts av en annan användare som blockerats av $1.\nMotiveringen av blockeringen var:\n\n:''$2''\n\n* Blockeringen startade: $8\n* Blockeringen gäller till: $6\n* Blockeringen är avsedd för: $7\n\nDu kan kontakta $1 eller nÃ¥gon annan [[{{MediaWiki:Grouppage-sysop}}|administratör]] för att diskutera blockeringen.\n\nObservera att du inte kan använda dig av funktionen \"{{int:emailuser}}\" om du inte har registrerat en giltig e-postadress i [[Special:Preferences|dina inställningar]] eller om du har blivit blockerad frÃ¥n att skicka e-post.\n\nDin nuvarande IP-adress är $3, och blockerings-ID är #$5.\nVänligen ange informationen ovan i alla förfrÃ¥gningar som du gör i ärendet.", "systemblockedtext": "Ditt användarnamn eller IP-adress h ar blockerats automatiskt av MediaWiki.\n\nMotiveringen av blockeringen var:\n\n:$2\n\n* Blockeringen startade: $8\n* Blockeringen gäller till: $6\n* Blockeringen är avsedd för: $7\n\nDin nuvarande IP-adress är $3.\nVänligen ange informationen ovan i alla förfrÃ¥gningar som du gör i ärendet.", "blockednoreason": "ingen motivering angavs", "whitelistedittext": "Vänligen $1 för att redigera sidor.", @@ -1549,7 +1551,7 @@ "recentchangeslinked-feed": "Relaterade ändringar", "recentchangeslinked-toolbox": "Relaterade ändringar", "recentchangeslinked-title": "Ändringar relaterade till \"$1\"", - "recentchangeslinked-summary": "Ange namnet pÃ¥ en sida för att se ändringar pÃ¥ sidor som länkas till eller frÃ¥n denna sida. (För att se medlemmar i en kategori, skriv Kategori:Namnet pÃ¥ kategorin). Ändringar pÃ¥ sidor i [[Special:Watchlist|din bevakningslista]] är fetstilta.", + "recentchangeslinked-summary": "Ange namnet pÃ¥ en sida för att se ändringar pÃ¥ sidor som länkas till eller frÃ¥n denna sida. (För att se medlemmar i en kategori, skriv {{ns:category}}:Namnet pÃ¥ kategorin). Ändringar pÃ¥ sidor i [[Special:Watchlist|din bevakningslista]] är fetstilta.", "recentchangeslinked-page": "Sidnamn:", "recentchangeslinked-to": "Visa ändringar pÃ¥ sidor med länkar till den givna sidan istället", "recentchanges-page-added-to-category": "[[:$1]] lades till i kategorin", @@ -4071,5 +4073,6 @@ "pagedata-title": "Siddata", "pagedata-text": "Denna sida tillhandahÃ¥ller ett datagränssnitt till sidor. Ange sidans titel i webbadressen med hjälp av undersidesyntax.\n* InnehÃ¥llsförhandling gäller baserat pÃ¥ att din klients Accept-header. Detta innebär att siddatan kommer att tillhandahÃ¥llas i det format som din klient föredrar.", "pagedata-not-acceptable": "Inga matchande format finns. MIME-typer som stöds:$1", - "pagedata-bad-title": "Ogiltig titel: $1." + "pagedata-bad-title": "Ogiltig titel: $1.", + "unregistered-user-config": "Av säkerhetsskäl kan inte undersidor med JavaScript, CSS och JSON läsas in för oregistrerade användare." } diff --git a/languages/i18n/szl.json b/languages/i18n/szl.json index d78fcd1489..3a94c67936 100644 --- a/languages/i18n/szl.json +++ b/languages/i18n/szl.json @@ -158,7 +158,7 @@ "and": " a", "faq": "FAQ", "actions": "Akcyje", - "namespaces": "Raumy mjan", + "namespaces": "Przestrzynie mian", "variants": "Ôpcyje", "navigation-heading": "Menu nawigacyje", "errorpagetitle": "Feler", @@ -260,7 +260,7 @@ "feed-invalid": "Ńywłaściwy typ kanałů informacyjnygo.", "feed-unavailable": "Kanoły informacyjne ńy sům dostympne", "site-rss-feed": "Kanoł RSS {{GRAMMAR:D.lp|$1}}", - "site-atom-feed": "Kanŏł Atom {{GRAMMAR:D.lp|$1}}", + "site-atom-feed": "Kanoł Atom {{GRAMMAR:D.lp|$1}}", "page-rss-feed": "Kanoł RSS \"$1\"", "page-atom-feed": "Kanoł Atom \"$1\"", "red-link-title": "$1 (niy ma zajty)", @@ -347,15 +347,15 @@ "welcomecreation-msg": "Uotwarli my sam lo Ćebje kůnto.\nPamjyntej coby posztalować [[Special:Preferences|preferencyji]]", "yourname": "Mjano użytkowńika:", "userlogin-yourname": "Mjano używocza", - "userlogin-yourname-ph": "Wszkryflej swoje mjano użytkowńika", + "userlogin-yourname-ph": "Wkludź swoje miano używacza", "createacct-another-username-ph": "Wszkryflej mjano użytkowńika", "yourpassword": "Hasło:", "userlogin-yourpassword": "Hasło", - "userlogin-yourpassword-ph": "Wszkryflej swoje hasło", - "createacct-yourpassword-ph": "Wszkryflej hasło", + "userlogin-yourpassword-ph": "Wkludź swoje hasło", + "createacct-yourpassword-ph": "Wkludź hasło", "yourpasswordagain": "Naszkryflej ausdruk zaś", "createacct-yourpasswordagain": "Potwjyrdź hasło", - "createacct-yourpasswordagain-ph": "Wszkryflej hasło jeszcze roz", + "createacct-yourpasswordagain-ph": "Wkludź hasło jeszcze rŏz", "userlogin-remembermypassword": "Ńy wylogůwywuj mje", "userlogin-signwithsecure": "Użyj bezpjecznygo połůnczyńa", "yourdomainname": "Twoja domyna", @@ -375,7 +375,7 @@ "userlogin-createanother": "Twůrz inksze kůnto", "createacct-emailrequired": "E-brif", "createacct-emailoptional": "E-brif (uopcjůnalne)", - "createacct-email-ph": "Wszkryflej swůj adres do e-brifa", + "createacct-email-ph": "Wkludź swojã adresã e-brifa", "createacct-another-email-ph": "Nastow e-brif", "createaccountmail": "Użyj chwilowygo hasła losowo genyrowanygo a wyślij je na wrychtowany adres e-brifa.", "createacct-realname": "Prawdźiwe imje a nazwisko (uopcjůnalńe)", @@ -718,7 +718,7 @@ "searchprofile-images": "Multimedyja", "searchprofile-everything": "Wszyjsko", "searchprofile-advanced": "Rozszerzůne", - "searchprofile-articles-tooltip": "Podszukowaniy we zorcie mian $1", + "searchprofile-articles-tooltip": "Podszukowaniy we przestrzyni mian $1", "searchprofile-images-tooltip": "Szukej plikōw", "searchprofile-everything-tooltip": "Podszukowaniy cołkij zawartości (a tyż zajtōw dyskusyje)", "searchprofile-advanced-tooltip": "Podszukowaniy we ôbranych zortach mian", @@ -1429,11 +1429,11 @@ "undelete-error-long": "Napotkano felery při wćepywańu nazod plika:\n\n$1", "undelete-show-file-confirm": "Jeżeś echt pewny co chcesz uobejzdrzeć wyćepano wersyjo plika „$1” s $2 $3?", "undelete-show-file-submit": "Ja", - "namespace": "Raum mjan:", + "namespace": "Przestrzyń mian:", "invert": "Wybjer na uopy", - "tooltip-invert": "Uoznacz te pole, coby ukryć půmjany na zajtach we uobranych raumach mjan (a powjůnzanych ze ńimi inkszymi raumami mjan, eli uoznaczůno)", - "namespace_association": "powjůnzany raum mjan", - "tooltip-namespace_association": "Uoznacz te pole, coby uwzglyndńić zajty dyskusyji i tyjmy powjůnzane ze uobranymi raumami mjan", + "tooltip-invert": "Ôznŏcz tyn kastlik, coby skryć pōmiany na zajtach we ôbranych przestrzyniach mian (i swiōnzanych ze nimi inkszymi przestrzyniami mian, eli ôznŏczōno)", + "namespace_association": "powiōnzanŏ przestrzyń mian", + "tooltip-namespace_association": "Ôznŏcz tyn kastlik, coby zawrzić zajty dyskusyje i tyjmy swiōnzane ze ôbranymi przestrzyniami mian", "blanknamespace": "(przodńo)", "contributions": "Ajnzac {{GENDER:$1|używocza|używoczki}}", "contributions-title": "Wkłod użytkowńika $1", diff --git a/languages/i18n/tr.json b/languages/i18n/tr.json index 0226e5c375..db9fe9667e 100644 --- a/languages/i18n/tr.json +++ b/languages/i18n/tr.json @@ -600,6 +600,7 @@ "botpasswords-existing": "Mevcut bot parolaları", "botpasswords-createnew": "Yeni bir bot parolası oluştur", "botpasswords-editexisting": "Mevcut bir bot parolasını düzenle", + "botpasswords-label-needsreset": "(parolanın sıfırlanması gerekiyor)", "botpasswords-label-appid": "Bot ismi:", "botpasswords-label-create": "Oluştur", "botpasswords-label-update": "Güncelle", @@ -621,6 +622,7 @@ "botpasswords-no-provider": "BotPasswordsSessionProvider kullanılamaz.", "botpasswords-restriction-failed": "Bot parolası kısıtlamaları bu oturum açma işlemini önlemektedir.", "botpasswords-invalid-name": "Belirtilen kullanıcı adı bot parolası ayırıcısı içermiyor (\"$1\").", + "botpasswords-needs-reset": "\"$1\" {{GENDER:$1|kullanıcısına}} ait \"$2\" adlı bot için bot parolası sıfırlanmalı.", "resetpass_forbidden": "Parolalar değiştirilememektedir", "resetpass_forbidden-reason": "Parolalar değiştirilemez: $1", "resetpass-no-info": "Bu sayfaya doğrudan erişmek için oturum açmanız gereklidir.", diff --git a/languages/i18n/yo.json b/languages/i18n/yo.json index e86700b7a7..38f7e624ac 100644 --- a/languages/i18n/yo.json +++ b/languages/i18n/yo.json @@ -1115,7 +1115,7 @@ "recentchangeslinked-feed": "Àtúná¹£e tó báramu", "recentchangeslinked-toolbox": "Àtúná¹£e tó báramu", "recentchangeslinked-title": "Àtúná¹£e tó báramu mọ́ \"$1\"", - "recentchangeslinked-summary": "Àkójọ àwọn àtúná¹£e tí a sẹ̀sẹ̀ á¹£e sí àwọn ojúewé tó jápọ̀ wá láti ojúewé pàtó kan (tàbí sí ìkan nìnú ẹ̀ka pàtó kan).\nÀwọn ojúewé inú [[Special:Watchlist|ìmójútó yín]] jẹ́ '''kedere'''.", + "recentchangeslinked-summary": "Ẹ tẹ orúkọ ojúewé láti rí àwọn àtúná¹£e lórí àwọn ojúewé tí wọ́n jápọ̀ sí tàbí jápọ̀ wá láti ọ̀dọ̀ ojúewé nà. (Láti rí àwọn ojúewé inú ẹ̀ka, ẹ tẹ {{ns:category}}:Orúkọ ẹ̀ka).\nÀwọn àtúná¹£e ojúewé inú [[Special:Watchlist|Ìtòjọ àmójútó yín]] ni àwọn tó hàn kedere.", "recentchangeslinked-page": "Orúkọ ojúewé:", "recentchangeslinked-to": "Àfihàn àwọn àtúná¹£e sí àwọn ojúewé tójápọ̀ mọ́ ojúewé ọ̀hún dípò", "upload": "Ìrùsókè fáìlì", diff --git a/languages/i18n/zgh.json b/languages/i18n/zgh.json index cc2c27ec29..8e18bf7f37 100644 --- a/languages/i18n/zgh.json +++ b/languages/i18n/zgh.json @@ -328,6 +328,8 @@ "searchall": "ⴰⴽⴽ", "search-nonefound": "ⵓⵔ ⵍⵍⵉⵏⵜ ⵜⵢⴰⴼⵓⵜⵉⵏ ⵉⵎⵙⴰⵙⴰⵏ â´· ⵓⵙⵓⵜⵔ.", "mypreferences": "ⵉⵙⵎⵏⵢⵉⴼⵏ", + "prefs-watchlist-days": "ⵓⵙⵙⴰⵏ ⵜⵓⵙⴽⵏⵉⵏ â´³ ⵓⵎⵓⵖ ⵓⵙⵎⵓⵇⵇⵍ", + "recentchangesdays": "ⵓⵙⵙⴰⵏ ⵜⵓⵙⴽⵏⵉⵏ â´³ ⵉⵙⵏⴼⵉⵍⵏ ⵉⵎⴳⴳⵓⵔⴰ", "prefs-files": "ⵉⴼⴰⵢⵍⵓⵜⵏ", "youremail": "ⵉⵎⴰⵢⵍ:", "yourlanguage": "ⵜⵓⵜⵍⴰⵢⵜ:", @@ -336,6 +338,7 @@ "prefs-signature": "ⴰⵙⴳⵎⴹ", "userrights-reason": "ⵜⴰⵎⵏⵜⵉⵍⵜ:", "group-sysop": "ⵉⵏⵎⵀⴰⵍⵏ", + "right-edit": "ⵙⵏⴼⵍ ⵜⴰⵙⵏⵉⵡⵉⵏ", "right-upload": "ⵙⴽⵜⵔ ⵉⴼⴰⵢⵍⵓⵜⵏ", "right-upload_by_url": "ⵙⴽⵜⵔ ⴰⴼⴰⵢⵍⵓ ⵙⴳ URL", "right-writeapi": "ⴰⵙⵙⵎⵔⵙ ⵏ API ⵉ ⵜⵉⵔⵔⴰ", @@ -355,6 +358,8 @@ "recentchanges-label-plusminus": "ⵜⴰⵙⵎⴽⵜⴰ ⵏ ⵜⴰⵙⵏⴰ â´°â´· ⵜⵙⵙⵏⴼⵍ ⵙ ⵓⵎⴹⴰⵏ â´°â´· ⵏ ⵉⴱⴰⵢⵜⵏ", "recentchanges-legend-heading": "ⴰⵙⵙⴼⵔⵓ:", "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ⵥⵔ ⴰⵍⵜⵓ [[Special:NewPages|ⵜⴰⵍⴳⴰⵎⵜ ⵏ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵜⵉⵎⴰⵢⵏⵓⵜⵉⵏ]])", + "rcfilters-days-title": "ⵓⵙⵙⴰⵏ ⵉⵎⴳⴳⵓⵔⴰ", + "rcfilters-days-show-days": "$1 ⵏ {{PLURAL:$1|ⵡⴰⵙⵙ|ⵡⵓⵙⵙⴰⵏ}}", "rclistfrom": "ⵙⴽⵏ ⵉⵙⵏⴼⵍⵏ ⵉⵎⴰⵢⵏⵓⵜⵏ ⵙⴳ $2,$3", "rcshowhideminor": "$1 ⵉⵙⵏⴼⴰⵍ ⵓⵎⵥⵉⵢⵏ", "rcshowhideminor-show": "ⵙⴽⵏ", @@ -427,6 +432,7 @@ "randompage": "ⵜⴰⵙⵏⴰ ⵜⴰⴷⵀⵎⴰⵙⵜ", "statistics": "ⴰⵙⵏⵎⴽⵜⴰ", "statistics-pages": "ⵜⴰⵙⵏⵉⵡⵉⵏ", + "brokenredirects-edit": "ⵙⵏⴼⵍ", "brokenredirects-delete": "ⴽⴽⵙ", "withoutinterwiki-legend": "ⴰⵣⵡⵉⵔ", "nbytes": "$1 {{PLURAL:$1|ⴱⴰⵢⵜ|ⵉⴷ ⴱⴰⵢⵜ}}", @@ -605,6 +611,7 @@ "show-big-image-preview": "ⵜⴰⵙⵎⴽⵜⴰ ⵏ ⵓⵣⵔⵉⵣⵡⴰⵔ â´°â´·: $1.", "show-big-image-other": "{{PLURAL:$2|ⵜⴰⴼⵙⴰⵢⵜ|ⵜⵉⴼⵙⴰⵢⵉⵏ}}: ⵢⴰⴹⵏ $1.", "show-big-image-size": "$1 × $2 ⵉⴷ ⴱⵉⴽⵙⵍ", + "days": "{{PLURAL:$1|$1 ⵡⴰⵙⵙ|$1 ⵡⵓⵙⵙⴰⵏ}}", "metadata": "ⵎⵉⵜⴰⴷⴰⵜⴰ", "metadata-help": "ⴰⵙⴷⴰⵡ â´° ⵢⵓⵎⴰ ⵉⵏⵖⵎⵉⵙⵏ ⵉⵎⵔⵏⴰⵏⵉⵏ, ⵉⵔⵡⴰⵙ ⵉⵙ ⴰⵙ ⵜⵜⵡⴰⵔⵏⵉⵏ ⵙ ⵍⴽⴰⵎⵉⵔⴰ ⵜⴰⵎⵓⵟⵟⵓⵏⵜ ⵏⵖ ⴰⵙⵏⴼⴰⵍ ⴰⵎⵓⵟⵟⵓⵏ ⵉⵜⵜⴰⵡⵙⵎⵔⵙⵏ â´³ ⵓⵙⵏⴼⵍⵓⵍ ⵏ ⵓⵙⴷⴰⵡ â´°.\nⵉⵖ ⵉⵜⵜⵙⵏⴼⵍ ⵓⵙⴷⴰⵡ â´° ⵙⴳ ⵡⴰⴷⴷⴰⴷ ⵏⵙ ⴰⵎⵓⴷⴰⵏ, ⴽⵔⴰ ⵏ ⵉⴼⵔⵓⵔⵉⵜⵏ ⵓⵔ ⵔⴰⵏ ⵙⵓⵍ ⴳⵔⵏ â´³ ⵓⵙⴷⴰⵡ ⵉⵜⵜⵙⵏⴼⵍⵏ.", "metadata-fields": "ⵉⴳⵔⴰⵏ ⵏ ⵎⵉⵜⴰⵉⵙⴼⴽⴰ ⵏ ⵜⵉⵡⵍⴰⴼⵉⵏ ⵏⵏⴰ ⵉⴼⵙⵔⵏ â´³ ⵜⴱⵔⴰⵜ â´°â´· ⵔⴰⴷ ⵉⵍⵉⵏ â´³ ⵜⴰⵙⵏⴰ ⵏ ⵓⵙⵏⵓⵎⵎⵍ ⵏ ⵜⴰⵡⵍⴰⴼⵜ ⴰⴽⵓⴷ ⵏⵏⴰ ⵉⵎⵓⵏ ⵓⵙⴽⵜⵓⵔ. ⵉⴳⵔⴰⵏ ⵢⴰⴹⵏ ⵔⴰⴷ ⴼⴼⵔⵏ ⵙ ⵓⵎⵕⴰⴹ.\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", @@ -647,6 +654,7 @@ "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|ⴰⵔⵛⵓⵎ|ⵉⵔⵛⵓⵎⵏ}}]]: $2)", "tags-active-yes": "ⵢⴰⵀ", "tags-active-no": "ⵓⵀⵓ", + "tags-edit": "ⵙⵏⴼⵍ", "tags-delete": "ⴽⴽⵙ", "tags-create-reason": "ⵜⴰⵎⵏⵜⵉⵍⵜ:", "tags-delete-reason": "ⵜⴰⵎⵏⵜⵉⵍⵜ:", diff --git a/languages/i18n/zh-hans.json b/languages/i18n/zh-hans.json index 1eaf278251..c890f9a7d9 100644 --- a/languages/i18n/zh-hans.json +++ b/languages/i18n/zh-hans.json @@ -719,8 +719,8 @@ "subject-preview": "主题的预览:", "previewerrortext": "尝试预览您的更改时发生错误。", "blockedtitle": "用户被封禁", - "blockedtext": "您的用户名或IP地址已被封禁。\n\n执行封禁的管理员是$1。封禁原因是$2。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联络$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当您在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才可以使用它。您当前的IP地址是$3,该封禁ID是#$5。请在您做出的任何查询中包含所有上述详情。", - "autoblockedtext": "您的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\n\n:$2\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]申诉该封禁。\n\n请注意,只有当您已在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才能发送电子邮件联系管理员。\n\n您当前的IP地址为$3,该封禁ID为#$5。请在您做出的任何查询中包含所有上述详情。", + "blockedtext": "您的用户名或IP地址已被封禁。\n\n执行封禁的管理员是$1。封禁原因是$2。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联络$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当您在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“{{int:emailuser}}”功能时,才可以使用它。您当前的IP地址是$3,该封禁ID是#$5。请在您做出的任何查询中包含所有上述详情。", + "autoblockedtext": "您的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\n\n:$2\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]申诉该封禁。\n\n请注意,只有当您已在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“{{int:emailuser}}”功能时,才能发送电子邮件联系管理员。\n\n您当前的IP地址为$3,该封禁ID为#$5。请在您做出的任何查询中包含所有上述详情。", "systemblockedtext": "您的用户名或IP地址已被MediaWiki自动封禁。封禁原因:\n\n:$2\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您当前的IP地址是$3。请在您做出的任何查询中包含所有上述详情。", "blockednoreason": "未给出原因", "whitelistedittext": "请$1以编辑页面。", diff --git a/languages/i18n/zh-hant.json b/languages/i18n/zh-hant.json index 3a14a15753..39f83618b0 100644 --- a/languages/i18n/zh-hant.json +++ b/languages/i18n/zh-hant.json @@ -134,7 +134,7 @@ "tog-watchlisthideminor": "隱藏監視清單中的次要修訂", "tog-watchlisthideliu": "隱藏監視清單中已登入使用者的編輯", "tog-watchlistreloadautomatically": "查詢條件變更時自動重新讀取監視清單(需要使用 JavaScript)", - "tog-watchlistunwatchlinks": "添加監視列表條目的直接(取消)監視鏈接(需要JavaScript才能打開功能)", + "tog-watchlistunwatchlinks": "為帶有變更的監試頁面添加直接(取消)監視標記({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}),需要 JavaScript 來打開功能", "tog-watchlisthideanons": "隱藏監視清單中匿名使用者的編輯", "tog-watchlisthidepatrolled": "隱藏監視清單中已巡查的編輯", "tog-watchlisthidecategorization": "隱藏頁面分類", @@ -442,7 +442,7 @@ "cascadeprotected": "此頁面被保護無法編輯,因為此頁面被以下開啟 \"連鎖保護\" 選項的{{PLURAL:$1|一頁|數頁}}保護頁面引用:\n$2", "namespaceprotected": "您沒有權限編輯 $1 命名空間的頁面。", "customcssprotected": "您並沒有權限編輯此 CSS 頁面,因為此頁面包含了其他使用者的個人設定。", - "customjsonprotected": "您沒有權限編輯此 CSS 頁面,因為此頁面包含了其他使用者的個人設定。", + "customjsonprotected": "您沒有權限編輯此JSON頁面,因為此頁面包含了其他使用者的個人設定。", "customjsprotected": "您並沒有權限編輯此 JavaScript 頁面,因為此頁面包含了其他使用者的個人設定。", "mycustomcssprotected": "您沒有權限編輯此 CSS 頁面。", "mycustomjsonprotected": "您沒有權限編輯此 JSON 頁面。", @@ -559,7 +559,7 @@ "noemailprefs": "在您的偏好設定中設定電子郵件地址,讓您可以使用這些功能。", "emailconfirmlink": "確認您的電子郵件地址", "invalidemailaddress": "無法接受格式不正確的電子郵件地址,請輸入正確的電子郵件地址格式或略過填寫該欄位。", - "cannotchangeemail": "æ­¤ Wiki 禁止更改帳號的電子郵件地址。", + "cannotchangeemail": "æ­¤ wiki 無法變更帳號的電子郵件地址。", "emaildisabled": "此網站不能傳送電子郵件。", "accountcreated": "已建立帳號", "accountcreatedtext": "使用者帳號 [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|對話]]) 已建立。", @@ -596,6 +596,7 @@ "botpasswords-existing": "已存在機器人密碼", "botpasswords-createnew": "建立新機器人密碼", "botpasswords-editexisting": "編輯已存在的機器人密碼", + "botpasswords-label-needsreset": "(密碼需要重新設定)", "botpasswords-label-appid": "機器人名稱:", "botpasswords-label-create": "建立", "botpasswords-label-update": "更新", @@ -619,6 +620,7 @@ "botpasswords-restriction-failed": "機器人密碼限制已拒絕此次登入。", "botpasswords-invalid-name": "指定的使用者名稱未包含機器人密碼分隔字元 (\"$1\")。", "botpasswords-not-exist": "使用者 \"$1\" 並沒有名稱為 \"$2\" 的機器人密碼。", + "botpasswords-needs-reset": "給{{GENDER:$1|使用者}}「$1」的機器人名稱「$2」該機器人密碼已重新設定。", "resetpass_forbidden": "無法變更密碼", "resetpass_forbidden-reason": "無法變更密碼:$1", "resetpass-no-info": "您必須直接登入存取這個頁面。", @@ -714,8 +716,8 @@ "subject-preview": "預覽主旨:", "previewerrortext": "嘗試預覽您的變更時發生錯誤。", "blockedtitle": "使用者已被封鎖", - "blockedtext": "您的使用者名稱或 IP 位址已被封鎖。\n\n您被 $1 封鎖,\n原因爲 $2。\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯絡 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件地址,且尚未被封鎖郵件功能,則您可透過 \"Email 聯絡此使用者\" 的功能來聯絡相關管理員。\n您目前的 IP 位址是 $3,此次封鎖的 ID 為 #$5。\n請您在詢問時附註以上詳細訊息。", - "autoblockedtext": "因先前的另一位使用者被 $1 封鎖,您的 IP 位址已被自動封鎖。\n原因是:\n\n:$2\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯絡 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件地址,且尚未被封鎖郵件功能,則您可透過 \"Email 聯絡此使用者\" 的功能來聯絡相關管理員。\n您目前的 IP 位址是 $3,此次封鎖的 ID 為 #$5。\n請您在詢問時附註以上詳細資料。", + "blockedtext": "您的使用者名稱或 IP 位址已被封鎖。\n\n您被 $1 封鎖,\n原因爲 $2。\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯絡 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件地址,且尚未被封鎖郵件功能,則您可透過 \"{{int:emailuser}}\" 的功能來聯絡相關管理員。\n您目前的 IP 位址是 $3,此次封鎖的 ID 為 #$5。\n請您在詢問時附註以上詳細訊息。", + "autoblockedtext": "因先前的另一位使用者被 $1 封鎖,您的 IP 位址已被自動封鎖。\n原因是:\n\n:$2\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯絡 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件地址,且尚未被封鎖郵件功能,則您可透過 \"{{int:emailuser}}\" 的功能來聯絡相關管理員。\n您目前的 IP 位址是 $3,此次封鎖的 ID 為 #$5。\n請您在詢問時附註以上詳細資料。", "systemblockedtext": "您的使用者名稱或 IP 位址已被 MediaWiki 自動封鎖,原因如下:\n\n:$2\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 被封鎖的使用者:$7\n\n您目前的 IP 位址為 $3。\n請在做詢問時附上以上資訊。", "blockednoreason": "未說明原因", "whitelistedittext": "請先 $1 才可編輯頁面。", @@ -738,10 +740,13 @@ "blocked-notice-logextract": "此使用者目前已被封鎖。\n以下為最近的封鎖紀錄以供參考:", "clearyourcache": "注意:在您儲存之後您必須清除瀏覽器快取才可看到最新的變更。\n* Firefox / Safari:按住 Shift 時點選 重新整理,或按 Ctrl-F5 或 Ctrl-R (Mac 則為 ⌘-R) \n* Google Chrome:按 Ctrl-Shift-R (Mac 則為 ⌘-Shift-R) \n* Internet Explorer:按住 Ctrl 時點選 重新整理,或按 Ctrl-F5\n* Opera:前往 選單 → 設定 (在 Mac 為 Opera → 偏好設定) 然後再到 隱私 & 安全性 → 清除瀏覽資料 → 已快取的圖片與檔案。", "usercssyoucanpreview": "提示:在儲存之前使用 \"{{int:showpreview}}\" 按鈕來測試您的新 CSS 。", + "userjsonyoucanpreview": "提示:在儲存之前使用 \"{{int:showpreview}}\" 按鈕來測試您的新 JSON。", "userjsyoucanpreview": "提示:在儲存之前使用 \"{{int:showpreview}}\" 按鈕來測試您的新 JavaScript 。", "usercsspreview": "您目前正預覽您的使用者 CSS,CSS 還尚未儲存!", + "userjsonpreview": "請注意您僅是在測試/預覽您的使用者 JSON 設定,內容還尚未儲存!", "userjspreview": "您目前正預覽您的使用者 JavaScript,JavaScript 還尚未儲存!", "sitecsspreview": "您目前正預覽此 CSS,CSS 還尚未儲存!", + "sitejsonpreview": "請注意您僅是在預覽此 JSON 設定,內容還尚未儲存!", "sitejspreview": "您目前正預覽此 JavaScript,JavaScript 還尚未儲存!", "userinvalidconfigtitle": "警告: 無此外觀樣式 \"$1\"。\n自訂的 .css、.json 和 .js 頁面要使用小寫標題,例如:{{ns:user}}:Foo/vector.css 與 {{ns:user}}:Foo/Vector.css 是不同的。", "updated": "(已更新)", @@ -770,7 +775,7 @@ "longpageerror": "錯誤:您所送出的文字內容共有 {{PLURAL:$1|1 KB|$1 KB}},已超出系統上限 {{PLURAL:$2|1 KB|$2 KB}}。\n\n無法儲存。", "readonlywarning": "警告:資料庫已被鎖定以進行維護,因此無法儲存您目前所做的編輯動作。\n您可先複製您的文字並貼上到文字檔案中儲存,稍後再儲存您編輯。\n\n鎖定資料庫的系統管理員有以下說明:$1", "protectedpagewarning": "警告:本頁已經被保護,只有擁有管理員權限的使用者才可編輯。\n以下提供最近的日誌以便參考:", - "semiprotectedpagewarning": "注意:本頁已經被保護,只有已註冊的使用者才可編輯。\n以下提供最近的日誌以便參考:", + "semiprotectedpagewarning": "注意:本頁已經被保護,只有自動確認使用者才可編輯。\n以下提供最近的日誌以便參考:", "cascadeprotectedwarning": "警告:由於本頁被下列{{PLURAL:$1|頁面|頁面}}嵌入,所以受連鎖保護。只有得到[[Special:ListGroupRights|特殊權限]]的使用者才可編輯。", "titleprotectedwarning": "警告:本頁面已被保護,需要 [[Special:ListGroupRights|特殊權限]] 方可建立。\n以下提供最近的日誌以便參考:", "templatesused": "此頁面使用了以下{{PLURAL:$1|模板}}:", @@ -840,7 +845,10 @@ "expansion-depth-exceeded-category-desc": "超出展開深度限制的頁面。", "expansion-depth-exceeded-warning": "頁面超出展開深度限制", "parser-unstrip-loop-warning": "偵測到 Unstrip 迴圈", - "unstrip-depth-warning": "Unstrip 遞迴超出限制 ($1)", + "unstrip-depth-warning": "Unstrip 深度超出限制 ($1)", + "unstrip-depth-category": "超出 unstrip 深度限制的頁面", + "unstrip-size-warning": "Unstrip 大小超出限制 ($1)", + "unstrip-size-category": "超出 unstrip 大小限制的頁面", "converter-manual-rule-error": "手動語言轉換規則時偵測到錯誤", "undo-success": "此編輯可以被還原。\n請檢查以下比較表,確認您是否要還原,然後儲存以下變更以完成編輯還原。", "undo-failure": "由於編輯的修訂間有衝突,此編輯不能還原。", @@ -981,7 +989,7 @@ "difference-multipage": "(頁面間的差異)", "lineno": "行 $1:", "compareselectedversions": "比較已選擇的修訂", - "showhideselectedversions": "更改已選擇修訂的顯示設定", + "showhideselectedversions": "變更已選擇修訂的顯示設定", "editundo": "撤銷", "diff-empty": "(無差異)", "diff-multi-sameuser": "(未顯示同一使用者於中間所作的 $1 次修訂)", @@ -1065,6 +1073,7 @@ "prefs-watchlist-edits": "監視清單中顯示的變更數量上限:", "prefs-watchlist-edits-max": "數量上限:1000", "prefs-watchlist-token": "監視清單金鑰:", + "prefs-watchlist-managetokens": "管理令牌", "prefs-misc": "其他", "prefs-resetpass": "變更密碼", "prefs-changeemail": "變更或移除電子郵件地址", @@ -1080,9 +1089,10 @@ "stub-threshold-disabled": "已停用", "recentchangesdays": "近期變更顯示的天數:", "recentchangesdays-max": "最多 $1 {{PLURAL:$1|天}}", - "recentchangescount": "預設顯示的編輯數:", + "recentchangescount": "在最近變更、頁面歷史、以及日誌裡,所預設顯示的編輯數:", "prefs-help-recentchangescount": "數量上限:1000", "prefs-help-watchlist-token2": "這是您的監視清單的網路訊息源所需密鑰。\n任何人只要知道密鑰就能夠讀取您的監視清單,所以請勿任意與它人共享。\n若有需要[[Special:ResetTokens|您可重設密鑰]]。", + "prefs-help-tokenmanagement": "您可以查看並重新設定您帳號裡用來存取您監視清單中訊息來源的密鑰。任何知道該密鑰的人皆可讀取您的監視清單,因此請不要將它分享出去。", "savedprefs": "已儲存您的偏好設定。", "savedrights": "已儲存 {{GENDER:$1|$1}} 的使用者權限。", "timezonelegend": "時區:", @@ -1419,7 +1429,7 @@ "rcfilters-savedqueries-already-saved": "這些過濾已被儲存。變更您的設定,來建立新的已儲存過濾。", "rcfilters-restore-default-filters": "還原預設過濾條件", "rcfilters-clear-all-filters": "清除所有過濾條件", - "rcfilters-show-new-changes": "顯示最新更改", + "rcfilters-show-new-changes": "檢視最新變更", "rcfilters-search-placeholder": "過濾變更(使用選單或搜尋過濾名稱)", "rcfilters-invalid-filter": "無效的過濾條件", "rcfilters-empty-filter": "沒有使用中的過濾條件。已顯示所有的貢獻。", @@ -1437,7 +1447,7 @@ "rcfilters-filter-editsbyself-label": "您的編輯", "rcfilters-filter-editsbyself-description": "您的貢獻", "rcfilters-filter-editsbyother-label": "其他人的變更", - "rcfilters-filter-editsbyother-description": "除了您以外的所有更改", + "rcfilters-filter-editsbyother-description": "除了您以外的所有變更。", "rcfilters-filtergroup-userExpLevel": "使用者註冊及經驗", "rcfilters-filter-user-experience-level-registered-label": "已註冊", "rcfilters-filter-user-experience-level-registered-description": "已登入編輯者。", @@ -1455,7 +1465,12 @@ "rcfilters-filter-humans-label": "人工 (非機器人)", "rcfilters-filter-humans-description": "由人類編輯者做出的編輯", "rcfilters-filtergroup-reviewstatus": "審查狀態", + "rcfilters-filter-reviewstatus-unpatrolled-description": "未手動或自動標記成已巡查的編輯。", "rcfilters-filter-reviewstatus-unpatrolled-label": "未巡查", + "rcfilters-filter-reviewstatus-manual-description": "被手動標示為已巡查的編輯。", + "rcfilters-filter-reviewstatus-manual-label": "手動巡查", + "rcfilters-filter-reviewstatus-auto-description": "由高階使用者做出的編輯會自動標記成已巡查。", + "rcfilters-filter-reviewstatus-auto-label": "自動巡查", "rcfilters-filtergroup-significance": "重要性", "rcfilters-filter-minor-label": "次要編輯", "rcfilters-filter-minor-description": "作者已標示為次要的編輯。", @@ -1465,14 +1480,14 @@ "rcfilters-filter-watchlist-watched-label": "在監視清單內", "rcfilters-filter-watchlist-watched-description": "您的監視清單內的變更", "rcfilters-filter-watchlist-watchednew-label": "新監視清單的變更", - "rcfilters-filter-watchlist-watchednew-description": "更改後您尚未檢視的監視頁面變更。", + "rcfilters-filter-watchlist-watchednew-description": "變更後您尚未檢視的監視頁面變更。", "rcfilters-filter-watchlist-notwatched-label": "不在監視清單內", "rcfilters-filter-watchlist-notwatched-description": "除了更改您的監視頁面以外的任何事項。", "rcfilters-filtergroup-watchlistactivity": "監視列表活動", "rcfilters-filter-watchlistactivity-unseen-label": "未讀變更", - "rcfilters-filter-watchlistactivity-unseen-description": "自從更改發生以來,對您沒有訪問的頁面做出的更改。", + "rcfilters-filter-watchlistactivity-unseen-description": "自從變更發生以來,對您沒有造訪的頁面做出的變更。", "rcfilters-filter-watchlistactivity-seen-label": "已讀變更", - "rcfilters-filter-watchlistactivity-seen-description": "自從更改發生以來,對您已訪問的頁面做出的更改。", + "rcfilters-filter-watchlistactivity-seen-description": "自從變更發生以來,對您已造訪的頁面做出的變更。", "rcfilters-filtergroup-changetype": "變更類型", "rcfilters-filter-pageedits-label": "頁面編輯", "rcfilters-filter-pageedits-description": "對 Wiki 內容、討論、分類說明所做的編輯…", @@ -1489,7 +1504,7 @@ "rcfilters-filter-lastrevision-label": "最新修訂版本", "rcfilters-filter-lastrevision-description": "只包括對頁面的近期變更。", "rcfilters-filter-previousrevision-label": "不是最新修訂版本", - "rcfilters-filter-previousrevision-description": "所有不是「最新修訂版本」的更改。", + "rcfilters-filter-previousrevision-description": "所有不是「最新修訂版本」的變更。", "rcfilters-filter-excluded": "已排除", "rcfilters-tag-prefix-namespace-inverted": ":不是$1", "rcfilters-exclude-button-off": "排除選項", @@ -1501,13 +1516,13 @@ "rcfilters-view-tags-help-icon-tooltip": "了解更多關於標記編輯的資訊", "rcfilters-liveupdates-button": "動態更新", "rcfilters-liveupdates-button-title-on": "關閉動態更新", - "rcfilters-liveupdates-button-title-off": "顯示有發生的新更改", - "rcfilters-watchlist-markseen-button": "標記所有更改為已查看", + "rcfilters-liveupdates-button-title-off": "顯示有發生的新變更", + "rcfilters-watchlist-markseen-button": "標記所有變更為已看過", "rcfilters-watchlist-edit-watchlist-button": "編輯您的監視頁面列表", "rcfilters-watchlist-showupdated": "自更改發生以來,對您尚未訪問的頁面做出的更改以粗體顯示,並帶有實心圓形標記。", - "rcfilters-preference-label": "隱藏改進的最近更改版本", + "rcfilters-preference-label": "隱藏改善的最近變更版本", "rcfilters-preference-help": "返回到2017年介面重新設計版,並重新新增這以後增加的工具。", - "rcfilters-filter-showlinkedfrom-label": "顯示連結自該頁面的頁面上的更改", + "rcfilters-filter-showlinkedfrom-label": "顯示連結自此頁面的頁面上的變更", "rcfilters-filter-showlinkedfrom-option-label": "連結自指定頁面的頁面", "rcfilters-filter-showlinkedto-label": "顯示連結到該頁面的頁面上的更改", "rcfilters-filter-showlinkedto-option-label": "連結到指定頁面的頁面", @@ -1554,9 +1569,9 @@ "recentchangeslinked-feed": "相關變更", "recentchangeslinked-toolbox": "相關變更", "recentchangeslinked-title": "與 \"$1\" 相關的變更", - "recentchangeslinked-summary": "輸入頁面名稱,來查看頁面所連入或連出頁面的變更。(要查看分類成員的話,請輸入 Category:分類名稱)。會對在[[Special:Watchlist|您的監視清單]]上頁面更改為粗體顯示。", + "recentchangeslinked-summary": "輸入頁面名稱,來查看頁面所連入或連出頁面的變更。(要查看分類成員的話,請輸入{{ns:category}}:分類名稱)。會對在[[Special:Watchlist|您的監視清單]]上頁面更改為粗體顯示。", "recentchangeslinked-page": "頁面名稱:", - "recentchangeslinked-to": "改顯示連結至指定頁面的變更", + "recentchangeslinked-to": "顯示連結至指定頁面的變更", "recentchanges-page-added-to-category": "[[:$1]] 已加入至分類", "recentchanges-page-added-to-category-bundled": "[[:$1]] 已加入至分類,[[Special:WhatLinksHere/$1|此頁面已被其他頁面引用]]", "recentchanges-page-removed-from-category": "[[:$1]] 已自分類移除", @@ -1974,6 +1989,7 @@ "deadendpages": "無連結頁面", "deadendpagestext": "以下在 {{SITENAME}} 中的頁面未連結到其他頁面。", "protectedpages": "受保護頁面", + "protectedpages-filters": "篩選:", "protectedpages-indef": "只顯示無限期的保護頁面", "protectedpages-summary": "此頁面列出目前受保護的頁面。 欲查詢受保護標題清單,請參考 [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]]。", "protectedpages-cascade": "只顯示連鎖的保護頁面", @@ -2317,7 +2333,7 @@ "unprotectedarticle": "已解除 \"[[$1]]\" 的保護", "movedarticleprotection": "已移動 \"[[$2]]\" 的保護設定至 \"[[$1]]\"", "protectedarticle-comment": "{{GENDER:$2|受保護}} \"[[$1]]\"", - "modifiedarticleprotection-comment": "{{GENDER:$2|已更改}} \"[[$1]]\" 的保護層級", + "modifiedarticleprotection-comment": "{{GENDER:$2|已變更}} \"[[$1]]\" 的保護層級", "unprotectedarticle-comment": "{{GENDER:$2|已移除}} \"[[$1]]\" 的保護", "protect-title": "變更 \"$1\" 的保護層級", "protect-title-notallowed": "檢視 \"$1\" 的保護層級", @@ -2543,7 +2559,7 @@ "blocklog-showlog": "此使用者先前被封鎖過。\n以下為封鎖紀錄以供參考:", "blocklog-showsuppresslog": "此使用者先前被封鎖並且隱藏過。\n以下為禁止顯示紀錄以供參考:", "blocklogentry": "已封鎖 [[$1]] 的期限至 $2 $3", - "reblock-logentry": "更改 [[$1]] 的封鎖期限至 $2 $3", + "reblock-logentry": "變更 [[$1]] 的封鎖設定,到期時間為 $2 $3", "blocklogtext": "此為使用者的封鎖及取消封鎖動作的記錄。\n未列出自動封鎖的 IP 位址。\n請參考 [[Special:BlockList|封鎖清單]] 中的目前正在作業的阻止與封鎖。", "unblocklogentry": "已解除封鎖 $1", "block-log-flags-anononly": "僅限匿名使用者", @@ -2559,7 +2575,7 @@ "ipb_expiry_temp": "隱藏使用者名稱的封鎖不可設定期限。", "ipb_hide_invalid": "無法禁止顯示此帳號;它擁有超過 $1 次的編輯。", "ipb_already_blocked": "已經封鎖 \"$1\"。", - "ipb-needreblock": "$1 已經被封鎖。您是否想更改設定?", + "ipb-needreblock": "$1 已經被封鎖。您是否想變更設定?", "ipb-otherblocks-header": "其他{{PLURAL:$1|封鎖}}", "unblock-hideuser": "由於此使用者名稱已被設為隱藏,您無法解除封鎖這個使用者。", "ipb_cant_unblock": "錯誤:查無封鎖 ID $1,可能已被解除封鎖。", @@ -2651,7 +2667,7 @@ "fix-double-redirects": "更新所有指向原標題的重新導向頁面", "move-leave-redirect": "留下重新導向頁面", "protectedpagemovewarning": "警告:本頁已經被保護,只有擁有管理員權限的使用者才可移動。\n以下提供最近的日誌以便參考:", - "semiprotectedpagemovewarning": "注意:本頁已經被保護,只有已註冊的使用者才可移動。\n以下提供最近的日誌以便參考:", + "semiprotectedpagemovewarning": "注意:本頁已經被保護,只有自動確認使用者才可移動。\n以下提供最近的日誌以便參考:", "move-over-sharedrepo": "[[:$1]] 已存在於共用檔案庫,將檔案移動到此標題會覆蓋該共用檔案。", "file-exists-sharedrepo": "選擇的檔案名稱於共用檔案庫已有其他檔案使用。\n請改選擇其他名稱。", "export": "匯出頁面", @@ -2834,6 +2850,7 @@ "group-bot.css": "/* æ­¤ CSS 會影響機器人 */", "group-sysop.css": "/* 這裡的 CSS 會影響管理員 */", "group-bureaucrat.css": "/* æ­¤ CSS 會影響行政員 */", + "common.json": "/* 在此的任一 JavaScript 會為全部使用者在所有頁面裡載入。 */", "common.js": "/* æ­¤ JavaScript 會用於使用者載入的每一個頁面。 */", "group-sysop.js": "/* 這裡的 JavaScript 會影響管理員 */", "anonymous": "{{SITENAME}} 的匿名{{PLURAL:$1|使用者}}", @@ -3551,8 +3568,8 @@ "tag-mw-new-redirect-description": "建立新重新導向或更改頁面為重新導向的編輯", "tag-mw-removed-redirect": "移除重新導向", "tag-mw-removed-redirect-description": "將現有重新導向更改為非重新導向的編輯", - "tag-mw-changed-redirect-target": "重新導向目標更改", - "tag-mw-changed-redirect-target-description": "更改重新導向目標的編輯", + "tag-mw-changed-redirect-target": "重新導向目標變更", + "tag-mw-changed-redirect-target-description": "變更重新導向目標的編輯", "tag-mw-blank": "清空", "tag-mw-blank-description": "清空頁面的編輯", "tag-mw-replace": "替換", @@ -3713,7 +3730,7 @@ "logentry-delete-event": "$1 {{GENDER:$2|已更改}} $3 中 {{PLURAL:$5|1 筆日誌|$5 筆日誌}}的可見性:$4", "logentry-delete-revision": "$1 {{GENDER:$2|已更改}}頁面 $3 中 {{PLURAL:$5|1 筆修訂|$5 筆修訂}}的可見性:$4", "logentry-delete-event-legacy": "$1 {{GENDER:$2|已變更}} $3 中日誌的可見性", - "logentry-delete-revision-legacy": "$1 {{GENDER:$2|已更改}}頁面 $3 中修訂的可見性", + "logentry-delete-revision-legacy": "$1 {{GENDER:$2|已變更}}頁面 $3 中修訂的可見性", "logentry-suppress-delete": "$1 {{GENDER:$2|已禁止顯示}}頁面 $3", "logentry-suppress-event": "$1 {{GENDER:$2|已暗中更改}} $3 中 {{PLURAL:$5|1 筆日誌|$5 筆日誌}}的可見性:$4", "logentry-suppress-revision": "$1 {{GENDER:$2|已暗中更改}}頁面 $3 中 {{PLURAL:$5|1 筆修訂|$5 筆修訂}}的可見性:$4", @@ -3752,10 +3769,10 @@ "logentry-protect-unprotect": "$1 {{GENDER:$2|已移除}} $3 的保護", "logentry-protect-protect": "$1 {{GENDER:$2|已保護}} $3 $4", "logentry-protect-protect-cascade": "$1 {{GENDER:$2|已保護}} $3 $4 [連鎖]", - "logentry-protect-modify": "$1 {{GENDER:$2|已更改}} $3 的保護層級 $4", - "logentry-protect-modify-cascade": "$1 {{GENDER:$2|已更改}} $3 的保護層級 $4 [連鎖]", + "logentry-protect-modify": "$1 {{GENDER:$2|已變更}} $3 的保護層級 $4", + "logentry-protect-modify-cascade": "$1 {{GENDER:$2|已變更}} $3 的保護層級 $4 [連鎖]", "logentry-rights-rights": "$1已將{{GENDER:$6|$3}}的使用者群組從$4{{GENDER:$2|更改}}至$5", - "logentry-rights-rights-legacy": "$1 {{GENDER:$2|已更改}} $3 的群組成員資格", + "logentry-rights-rights-legacy": "$1 {{GENDER:$2|已變更}} $3 的群組成員資格", "logentry-rights-autopromote": "$1 已自動{{GENDER:$2|提升}}從 $4 成為 $5", "logentry-upload-upload": "$1 {{GENDER:$2|已上傳}} $3", "logentry-upload-overwrite": "$1 {{GENDER:$2|上傳了}}新版本的 $3", @@ -3829,7 +3846,9 @@ "limitreport-templateargumentsize-value": "$1/$2 個{{PLURAL:$2|位元組}}", "limitreport-expansiondepth": "最高展開深度", "limitreport-expensivefunctioncount": "高消耗解析器函數次數", + "limitreport-unstrip-depth": "Unstrip 迴圈深度", "limitreport-unstrip-depth-value": "$1/$2", + "limitreport-unstrip-size": "Unstrip 傳遞擴充大小", "limitreport-unstrip-size-value": "$1/$2{{PLURAL:$2|位元組}}", "expandtemplates": "展開模板", "expand_templates_intro": "本特殊頁面會將 wiki 文字中的模板展開,可以包含支援的解析器語法,如 {{#language:…}} 與變數如 {{CURRENTDAY}}。\n實際上,絕大部分在雙括號中的內容都會被展開。", @@ -3857,12 +3876,12 @@ "pagelang-nonexistent-page": "頁面 $1 不存在。", "pagelang-unchanged-language": "頁面 $1 的語言已經設為 $2。", "pagelang-unchanged-language-default": "頁面 $1 的語言已經設為 wiki 的預設內容語言。", - "pagelang-db-failed": "資料庫更改頁面語言失敗。", + "pagelang-db-failed": "資料庫變更頁面語言失敗。", "right-pagelang": "變更頁面語言", "action-pagelang": "變更頁面語言", "log-name-pagelang": "語言變更日誌", "log-description-pagelang": "此頁為頁面語言的變更日誌。", - "logentry-pagelang-pagelang": "$1 {{GENDER:$2|已更改}}頁面 $3 的語言從 $4 到 $5", + "logentry-pagelang-pagelang": "$1 已將 $3 的語言從 $4 {{GENDER:$2|變更}}至 $5", "default-skin-not-found": "哎呀!您於 $wgDefaultSkin 設定的 Wiki 預設外觀 $1 無法使用。\n\n您的安裝程序應包含以下{{PLURAL:$4|外觀}}。請參考 [https://www.mediawiki.org/wiki/Manual:Skin_configuration 操作手冊:外觀設定] 以取得如何{{PLURAL:$4|開啟外觀並設為預設值}}的資訊。\n\n$2\n\n; 若您才剛安裝完 MediaWiki:\n: 您大概是使用 git 或直接透過原始碼使用其他方法安裝,這種情況是正常的。請嘗試安裝 [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org 的外觀目錄] 中的部份外觀使用以下方式:\n:* 下載 [https://www.mediawiki.org/wiki/Special:MyLanguage/Download tarball 安裝程式],該程式包含數個外觀與擴充套件。您可以複製並貼上至 skins/ 目錄。\n:* 自 [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org] 下載個別外觀 tarball。\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins 使用 Git 下載外觀]。\n: 若您是 MediaWiki 的開發人員,這麼做應該不會影響到您的 git 儲存庫。\n\n; 若您才剛升級 MediaWiki:\n: MediaWiki 1.24 與較新的版本不再自動開啟已安裝的外觀 (請參考 [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery 操作手冊:外觀自動搜尋])。您可以將下列{{PLURAL:$5|行}}貼上至 LocalSettings.php 來開啟{{PLURAL:$5|所有}}目前已經安裝的{{PLURAL:$5|外觀}}:\n\n
$3
\n\n; 若您才剛修改 LocalSettings.php:\n: 請再次確認您輸入的外觀名稱是否有誤。", "default-skin-not-found-no-skins": "哎呀!您於 $wgDefaultSkin 設定的 Wiki 預設外觀 $1 無法使用。\n\n您未安裝任何的外觀。\n\n; 若您才剛安裝完或升級完 MediaWiki:\n: 您大概是使用 git 或直接透過原始碼使用其他方法安裝,這種情況是正常的。 MediaWiki 1.24 或較新的版本在主要儲存庫中不再包含任何的外觀。 請嘗試安裝 [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org 的外觀目錄] 中的部份外觀使用以下方式:\n:* 下載 [https://www.mediawiki.org/wiki/Special:MyLanguage/Download tarball 安裝程式],該程式包含數個外觀與擴充套件。 您可以複製並貼上至 skins/ 目錄。\n:* 自 [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org] 下載個別外觀 tarball。\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins 使用 Git 下載外觀]。\n: 若您是 MediaWiki 的開發人員,這麼做應該不會影響到您的 git 儲存庫。 請參考 [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Skin_configuration 操作手冊:外觀設定] 以取得如何開啟外觀並設為預設值的資訊。", "default-skin-not-found-row-enabled": "* $1 / $2 (已開啟)", @@ -4001,7 +4020,7 @@ "authmanager-authplugin-setpass-failed-title": "密碼變更失敗", "authmanager-authplugin-setpass-failed-message": "認証外掛已拒絕密碼變更。", "authmanager-authplugin-create-fail": "認証外掛已拒絕帳號建立。", - "authmanager-authplugin-setpass-denied": "認証外掛不允許更改密碼。", + "authmanager-authplugin-setpass-denied": "驗證外掛程式不允許變更密碼。", "authmanager-authplugin-setpass-bad-domain": "無效網域。", "authmanager-autocreate-noperm": "不允許自動帳號建立。", "authmanager-autocreate-exception": "自動帳號建立因發生錯誤臨時關閉。", @@ -4059,6 +4078,7 @@ "unlinkaccounts-success": "已取消連結帳號。", "authenticationdatachange-ignored": "認證資料變更未被處理,可能未設定提供者?", "userjsispublic": "請注意:JavaScript 子頁面可被其他使用者檢視,不應包含機密資料。", + "userjsonispublic": "請注意:JSON 子頁面可被其它使用者檢視,因此不應包含機密資料。", "usercssispublic": "請注意:CSS 子頁面可被其他使用者檢視,不應包含機密資料。", "restrictionsfield-badip": "無效的 IP 位址或範圍:$1", "restrictionsfield-label": "允許的 IP 範圍:", @@ -4076,5 +4096,6 @@ "pagedata-title": "頁面資料", "pagedata-text": "此頁面提供了至頁面的資料介面。請使用子頁面語法在 URL 裡提供頁面標題。\n* 內容協商會基於您客戶端接受標頭來套用,這代表頁面資料會以由您客戶端所首選格式來提供。", "pagedata-not-acceptable": "查無符合的格式,支援的 MIME 類型有:$1", - "pagedata-bad-title": "無效的標題:$1。" + "pagedata-bad-title": "無效的標題:$1。", + "unregistered-user-config": "基於安全緣故未註冊的使用者不會載入 JavaScript、CSS,以及 JSON 使用者子頁面。" } diff --git a/maintenance/archives/patch-externallinks-el_index_60-drop-default.sql b/maintenance/archives/patch-externallinks-el_index_60-drop-default.sql new file mode 100644 index 0000000000..f9242c52bb --- /dev/null +++ b/maintenance/archives/patch-externallinks-el_index_60-drop-default.sql @@ -0,0 +1,2 @@ +-- @since 1.32 +ALTER TABLE /*$wgDBprefix*/externallinks ALTER COLUMN el_index_60 DROP DEFAULT; diff --git a/maintenance/categoryChangesAsRdf.php b/maintenance/categoryChangesAsRdf.php new file mode 100644 index 0000000000..a12cda78b4 --- /dev/null +++ b/maintenance/categoryChangesAsRdf.php @@ -0,0 +1,542 @@ +addDescription( "Generate RDF dump of category changes in a wiki." ); + + $this->setBatchSize( 200 ); + $this->addOption( 'output', "Output file (default is stdout). Will be overwritten.", false, + true, 'o' ); + $this->addOption( 'start', 'Starting timestamp (inclusive), in ISO or Mediawiki format.', + true, true, 's' ); + $this->addOption( 'end', 'Ending timestamp (exclusive), in ISO or Mediawiki format.', true, + true, 'e' ); + } + + /** + * Initialize external service classes. + */ + public function initialize() { + // SPARQL Update syntax is close to Turtle format, so we can use Turtle writer. + $this->rdfWriter = new TurtleRdfWriter(); + $this->categoriesRdf = new CategoriesRdf( $this->rdfWriter ); + } + + public function execute() { + global $wgRCMaxAge; + + $this->initialize(); + + $startTS = new MWTimestamp( $this->getOption( "start" ) ); + $endTS = new MWTimestamp( $this->getOption( "end" ) ); + $now = new MWTimestamp(); + + if ( $now->getTimestamp() - $startTS->getTimestamp() > $wgRCMaxAge ) { + $this->error( "Start timestamp too old, maximum RC age is $wgRCMaxAge!" ); + } + if ( $now->getTimestamp() - $endTS->getTimestamp() > $wgRCMaxAge ) { + $this->error( "End timestamp too old, maximum RC age is $wgRCMaxAge!" ); + } + + $this->startTS = $startTS->getTimestamp(); + $this->endTS = $endTS->getTimestamp(); + + $outFile = $this->getOption( 'output', 'php://stdout' ); + if ( $outFile === '-' ) { + $outFile = 'php://stdout'; + } + + $output = fopen( $outFile, 'wb' ); + + $this->categoriesRdf->setupPrefixes(); + $this->rdfWriter->start(); + + $prefixes = $this->getRdf(); + // We have to strip @ from prefix, since SPARQL UPDATE doesn't use them + // Also strip dot at the end. + $prefixes = preg_replace( [ '/^@/m', '/\s*[.]$/m' ], '', $prefixes ); + fwrite( $output, $prefixes ); + + $dbr = $this->getDB( DB_REPLICA, [ 'vslow' ] ); + + // Deletes go first because if the page was deleted, other changes + // do not matter. This only gets true deletes, i.e. not pages that were restored. + $this->handleDeletes( $dbr, $output ); + // Moves go before additions because if category is moved, we should not process creation + // as it would produce wrong data - because create row has old title + $this->handleMoves( $dbr, $output ); + // We need to handle restores too since delete may have happened in previous update. + $this->handleRestores( $dbr, $output ); + $this->handleAdds( $dbr, $output ); + $this->handleChanges( $dbr, $output ); + + // Update timestamp + fwrite( $output, $this->updateTS( $this->endTS ) ); + } + + /** + * Get SPARQL for updating set of categories + * @param IDatabase $dbr + * @param string[] $deleteUrls List of URIs to be deleted, with <> + * @param string[] $pages List of categories: id => title + * @param string $mark Marks which operation requests the query + * @return string SPARQL query + */ + private function getCategoriesUpdate( IDatabase $dbr, $deleteUrls, $pages, $mark ) { + if ( empty( $deleteUrls ) ) { + return ""; + } + + if ( !empty( $pages ) ) { + $this->writeParentCategories( $dbr, $pages ); + } + + return "# $mark\n" . sprintf( self::SPARQL_DELETE_INSERT, + $this->getRdf(), + implode( ' ', $deleteUrls ) ); + } + + /** + * Write data for a set of categories + * @param IDatabase $dbr + * @param string[] $pages List of categories: id => title + */ + private function writeParentCategories( IDatabase $dbr, $pages ) { + foreach ( $this->getCategoryLinksIterator( $dbr, array_keys( $pages ) ) as $row ) { + $this->categoriesRdf->writeCategoryLinkData( $pages[$row->cl_from], $row->cl_to ); + } + } + + /** + * Generate SPARQL Update code for updating dump timestamp + * @param string|int $timestamp Timestamp for last change + * @return string SPARQL Update query for timestamp. + */ + public function updateTS( $timestamp ) { + $dumpUrl = '<' . $this->categoriesRdf->getDumpURI() . '>'; + $ts = wfTimestamp( TS_ISO_8601, $timestamp ); + $tsQuery = <<mBatchSize + ); + $this->addTimestampConditions( $it, $dbr ); + $it->addJoinConditions( + [ + 'page_props' => [ + 'LEFT JOIN', [ 'pp_propname' => 'hiddencat', 'pp_page = rc_cur_id' ] + ], + 'category' => [ + 'LEFT JOIN', [ 'cat_title = rc_title' ] + ] + ] + ); + $it->setFetchColumns( array_merge( $columns, [ + 'rc_title', + 'rc_cur_id', + 'pp_propname', + 'cat_pages', + 'cat_subcats', + 'cat_files' + ] ) ); + return $it; + } + + /** + * Fetch newly created categories + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getNewCatsIterator( IDatabase $dbr ) { + $it = $this->setupChangesIterator( $dbr ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 1, + ] ); + return $it; + } + + /** + * Fetch moved categories + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getMovedCatsIterator( IDatabase $dbr ) { + $it = $this->setupChangesIterator( $dbr, [ 'page_title', 'page_namespace' ], [ 'page' ] ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 0, + 'rc_log_type' => 'move', + 'rc_type' => RC_LOG, + ] ); + $it->addJoinConditions( [ + 'page' => [ 'INNER JOIN', 'rc_cur_id = page_id' ], + ] ); + $this->addIndex( $it ); + return $it; + } + + /** + * Fetch deleted categories + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getDeletedCatsIterator( IDatabase $dbr ) { + $it = new BatchRowIterator( $dbr, + 'recentchanges', + [ 'rc_timestamp' ], + $this->mBatchSize + ); + $this->addTimestampConditions( $it, $dbr ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 0, + 'rc_log_type' => 'delete', + 'rc_log_action' => 'delete', + 'rc_type' => RC_LOG, + // We will fetch ones that do not have page record. If they do, + // this means they were restored, thus restoring handler will pick it up. + 'NOT EXISTS (SELECT * FROM page WHERE page_id = rc_cur_id)', + ] ); + $this->addIndex( $it ); + $it->setFetchColumns( [ 'rc_cur_id', 'rc_title' ] ); + return $it; + } + + /** + * Fetch restored categories + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getRestoredCatsIterator( IDatabase $dbr ) { + $it = $this->setupChangesIterator( $dbr ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 0, + 'rc_log_type' => 'delete', + 'rc_log_action' => 'restore', + 'rc_type' => RC_LOG, + // We will only fetch ones that have page record + 'EXISTS (SELECT page_id FROM page WHERE page_id = rc_cur_id)', + ] ); + $this->addIndex( $it ); + return $it; + } + + /** + * Fetch categorization changes + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getChangedCatsIterator( IDatabase $dbr ) { + $it = $this->setupChangesIterator( $dbr ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 0, + 'rc_type' => [ RC_EDIT, RC_CATEGORIZE ], + ] ); + $this->addIndex( $it ); + return $it; + } + + /** + * Add timestamp limits to iterator + * @param BatchRowIterator $it Iterator + * @param IDatabase $dbr + */ + private function addTimestampConditions( BatchRowIterator $it, IDatabase $dbr ) { + $it->addConditions( [ + 'rc_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( $this->startTS ) ), + 'rc_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( $this->endTS ) ), + ] ); + } + + /** + * Need to force index, somehow on terbium the optimizer chooses wrong one + * @param BatchRowIterator $it + */ + private function addIndex( BatchRowIterator $it ) { + $it->addOptions( [ + 'USE INDEX' => [ 'recentchanges' => 'new_name_timestamp' ] + ] ); + } + + /** + * Get iterator for links for categories. + * @param IDatabase $dbr + * @param array $ids List of page IDs + * @return Traversable + */ + protected function getCategoryLinksIterator( IDatabase $dbr, array $ids ) { + $it = new BatchRowIterator( + $dbr, + 'categorylinks', + [ 'cl_from', 'cl_to' ], + $this->mBatchSize + ); + $it->addConditions( [ + 'cl_type' => 'subcat', + 'cl_from' => $ids + ] ); + $it->setFetchColumns( [ 'cl_from', 'cl_to' ] ); + return new RecursiveIteratorIterator( $it ); + } + + /** + * Get accumulated RDF. + * @return string + */ + public function getRdf() { + return $this->rdfWriter->drain(); + } + + /** + * Handle category deletes. + * @param IDatabase $dbr + * @param resource $output File to write the output + */ + public function handleDeletes( IDatabase $dbr, $output ) { + // This only does "true" deletes - i.e. those that the page stays deleted + foreach ( $this->getDeletedCatsIterator( $dbr ) as $batch ) { + $deleteUrls = []; + foreach ( $batch as $row ) { + // This can produce duplicates, we don't care + $deleteUrls[] = '<' . $this->categoriesRdf->labelToUrl( $row->rc_title ) . '>'; + $this->processed[$row->rc_cur_id] = true; + } + fwrite( $output, $this->getCategoriesUpdate( $dbr, $deleteUrls, [], "Deletes" ) ); + } + } + + /** + * Write category data to RDF. + * @param stdclass $row Database row + */ + private function writeCategoryData( $row ) { + $this->categoriesRdf->writeCategoryData( + $row->rc_title, + $row->pp_propname === 'hiddencat', + (int)$row->cat_pages - (int)$row->cat_subcats - (int)$row->cat_files, + (int)$row->cat_subcats + ); + } + + /** + * @param IDatabase $dbr + * @param resource $output + */ + public function handleMoves( IDatabase $dbr, $output ) { + foreach ( $this->getMovedCatsIterator( $dbr ) as $batch ) { + $pages = []; + $deleteUrls = []; + foreach ( $batch as $row ) { + $deleteUrls[] = '<' . $this->categoriesRdf->labelToUrl( $row->rc_title ) . '>'; + + if ( isset( $this->processed[$row->rc_cur_id] ) ) { + // We already captured this one before + continue; + } + + if ( $row->page_namespace != NS_CATEGORY ) { + // If page was moved out of Category:, we'll just delete + continue; + } + $row->rc_title = $row->page_title; + $this->writeCategoryData( $row ); + $pages[$row->rc_cur_id] = $row->page_title; + $this->processed[$row->rc_cur_id] = true; + } + + fwrite( $output, $this->getCategoriesUpdate( $dbr, $deleteUrls, $pages, "Moves" ) ); + } + } + + /** + * @param IDatabase $dbr + * @param resource $output + */ + public function handleRestores( IDatabase $dbr, $output ) { + fwrite( $output, "# Restores\n" ); + // This will only find those restores that were not deleted later. + foreach ( $this->getRestoredCatsIterator( $dbr ) as $batch ) { + $pages = []; + foreach ( $batch as $row ) { + if ( isset( $this->processed[$row->rc_cur_id] ) ) { + // We already captured this one before + continue; + } + $this->writeCategoryData( $row ); + $pages[$row->rc_cur_id] = $row->rc_title; + $this->processed[$row->rc_cur_id] = true; + } + + if ( empty( $pages ) ) { + continue; + } + + $this->writeParentCategories( $dbr, $pages ); + + fwrite( $output, sprintf( self::SPARQL_INSERT, $this->getRdf() ) ); + } + } + + /** + * @param IDatabase $dbr + * @param resource $output + */ + public function handleAdds( IDatabase $dbr, $output ) { + fwrite( $output, "# Additions\n" ); + foreach ( $this->getNewCatsIterator( $dbr ) as $batch ) { + $pages = []; + foreach ( $batch as $row ) { + if ( isset( $this->processed[$row->rc_cur_id] ) ) { + // We already captured this one before + continue; + } + $this->writeCategoryData( $row ); + $pages[$row->rc_cur_id] = $row->rc_title; + $this->processed[$row->rc_cur_id] = true; + } + + if ( empty( $pages ) ) { + continue; + } + + $this->writeParentCategories( $dbr, $pages ); + fwrite( $output, sprintf( self::SPARQL_INSERT, $this->getRdf() ) ); + } + } + + /** + * @param IDatabase $dbr + * @param resource $output + */ + public function handleChanges( IDatabase $dbr, $output ) { + foreach ( $this->getChangedCatsIterator( $dbr ) as $batch ) { + $pages = []; + $deleteUrls = []; + foreach ( $batch as $row ) { + if ( isset( $this->processed[$row->rc_cur_id] ) ) { + // We already captured this one before + continue; + } + $this->writeCategoryData( $row ); + $pages[$row->rc_cur_id] = $row->rc_title; + $this->processed[$row->rc_cur_id] = true; + $deleteUrls[] = '<' . $this->categoriesRdf->labelToUrl( $row->rc_title ) . '>'; + } + + fwrite( $output, $this->getCategoriesUpdate( $dbr, $deleteUrls, $pages, "Changes" ) ); + } + } +} + +$maintClass = CategoryChangesAsRdf::class; +require_once RUN_MAINTENANCE_IF_MAIN; diff --git a/maintenance/deduplicateArchiveRevId.php b/maintenance/deduplicateArchiveRevId.php new file mode 100644 index 0000000000..dad79b060d --- /dev/null +++ b/maintenance/deduplicateArchiveRevId.php @@ -0,0 +1,209 @@ +addDescription( + 'Clean up duplicate ar_rev_id, both within archive and between archive and revision.' + ); + $this->setBatchSize( 10000 ); + } + + protected function getUpdateKey() { + return __CLASS__; + } + + protected function doDBUpdates() { + $this->output( "Deduplicating ar_rev_id...\n" ); + + $dbw = $this->getDB( DB_MASTER ); + + $minId = $dbw->selectField( 'archive', 'MIN(ar_rev_id)', [], __METHOD__ ); + $maxId = $dbw->selectField( 'archive', 'MAX(ar_rev_id)', [], __METHOD__ ); + $batchSize = $this->getBatchSize(); + + $this->arActorQuery = ActorMigration::newMigration()->getJoin( 'ar_user' ); + $revActorQuery = ActorMigration::newMigration()->getJoin( 'rev_user' ); + + for ( $id = $minId; $id <= $maxId; $id += $batchSize ) { + $endId = min( $maxId, $id + $batchSize - 1 ); + + $this->beginTransaction( $dbw, __METHOD__ ); + + // Lock the archive and revision table rows for the IDs we're checking + // to try to prevent deletions or undeletions from confusing things. + $dbw->selectRowCount( + 'archive', + 1, + [ 'ar_rev_id >= ' . (int)$id, 'ar_rev_id <= ' . (int)$endId ], + __METHOD__, + [ 'FOR UPDATE' ] + ); + $dbw->selectRowCount( + 'revision', + 1, + [ 'rev_id >= ' . (int)$id, 'rev_id <= ' . (int)$endId ], + __METHOD__, + [ 'LOCK IN SHARE MODE' ] + ); + + // Figure out the ar_rev_ids we actually need to look at + $res = $dbw->select( + [ 'archive', 'revision' ] + $revActorQuery['tables'], + [ 'rev_id', 'rev_timestamp', 'rev_sha1' ] + $revActorQuery['fields'], + [ 'ar_rev_id >= ' . (int)$id, 'ar_rev_id <= ' . (int)$endId ], + __METHOD__, + [ 'DISTINCT' ], + [ 'revision' => [ 'JOIN', 'ar_rev_id = rev_id' ] ] + $revActorQuery['joins'] + ); + $revRows = []; + foreach ( $res as $row ) { + $revRows[$row->rev_id] = $row; + } + + $arRevIds = $dbw->selectFieldValues( + [ 'archive' ], + 'ar_rev_id', + [ 'ar_rev_id >= ' . (int)$id, 'ar_rev_id <= ' . (int)$endId ], + __METHOD__, + [ 'GROUP BY' => 'ar_rev_id', 'HAVING' => 'COUNT(*) > 1' ] + ); + $arRevIds = array_values( array_unique( array_merge( $arRevIds, array_keys( $revRows ) ) ) ); + + if ( $arRevIds ) { + $this->processArRevIds( $dbw, $arRevIds, $revRows ); + } + + $this->output( "... $id-$endId\n" ); + $this->commitTransaction( $dbw, __METHOD__ ); + } + + $this->output( + "Finished deduplicating ar_rev_id. $this->deleted rows deleted, " + . "$this->reassigned assigned new IDs.\n" + ); + return true; + } + + /** + * Process a set of ar_rev_ids + * @param IDatabase $dbw + * @param int[] $arRevIds IDs to process + * @param object[] $revRows Existing revision-table row data + */ + private function processArRevIds( IDatabase $dbw, array $arRevIds, array $revRows ) { + // Select all the data we need for deduplication + $res = $dbw->select( + [ 'archive' ] + $this->arActorQuery['tables'], + [ 'ar_id', 'ar_rev_id', 'ar_namespace', 'ar_title', 'ar_timestamp', 'ar_sha1' ] + + $this->arActorQuery['fields'], + [ 'ar_rev_id' => $arRevIds ], + __METHOD__, + [], + $this->arActorQuery['joins'] + ); + + // Determine which rows we need to delete or reassign + $seen = []; + $toDelete = []; + $toReassign = []; + foreach ( $res as $row ) { + // Revision-table row exists? + if ( isset( $revRows[$row->ar_rev_id] ) ) { + $revRow = $revRows[$row->ar_rev_id]; + + // Record the rev_id as seen, so the code below will always delete or reassign. + if ( !isset( $seen[$revRow->rev_id] ) ) { + $seen[$revRow->rev_id] = [ + 'first' => "revision row", + ]; + } + + // Delete the archive row if it seems to be the same regardless + // of page, because moves can change IDs and titles. + if ( $row->ar_timestamp === $revRow->rev_timestamp && + $row->ar_sha1 === $revRow->rev_sha1 && + $row->ar_user === $revRow->rev_user && + $row->ar_user_text === $revRow->rev_user_text + ) { + $this->output( + "Row $row->ar_id duplicates revision row for rev_id $revRow->rev_id, deleting\n" + ); + $toDelete[] = $row->ar_id; + continue; + } + } + + $key = $this->getSeenKey( $row ); + if ( !isset( $seen[$row->ar_rev_id] ) ) { + // This rev_id hasn't even been seen yet, nothing to do besides record it. + $seen[$row->ar_rev_id] = [ + 'first' => "archive row $row->ar_id", + $key => $row->ar_id, + ]; + } elseif ( !isset( $seen[$row->ar_rev_id][$key] ) ) { + // The rev_id was seen, but not this particular change. Reassign it. + $seen[$row->ar_rev_id][$key] = $row->ar_id; + $this->output( + "Row $row->ar_id conflicts with {$seen[$row->ar_rev_id]['first']} " + . "for rev_id $row->ar_rev_id, reassigning\n" + ); + $toReassign[] = $row->ar_id; + } else { + // The rev_id was seen with a row that matches this change. Delete it. + $this->output( + "Row $row->ar_id duplicates archive row {$seen[$row->ar_rev_id][$key]} " + . "for rev_id $row->ar_rev_id, deleting\n" + ); + $toDelete[] = $row->ar_id; + } + } + + // Perform the updates + if ( $toDelete ) { + $dbw->delete( 'archive', [ 'ar_id' => $toDelete ], __METHOD__ ); + $this->deleted += $dbw->affectedRows(); + } + if ( $toReassign ) { + $this->reassigned += PopulateArchiveRevId::reassignArRevIds( $dbw, $toReassign ); + } + } + + /** + * Make a key identifying a "unique" change from a row + * @param object $row + * @return string + */ + private function getSeenKey( $row ) { + return implode( "\n", [ + $row->ar_namespace, + $row->ar_title, + $row->ar_timestamp, + $row->ar_sha1, + $row->ar_user, + $row->ar_user_text, + ] ); + } + +} + +$maintClass = "DeduplicateArchiveRevId"; +require_once RUN_MAINTENANCE_IF_MAIN; diff --git a/maintenance/fixExtLinksProtocolRelative.php b/maintenance/fixExtLinksProtocolRelative.php index c70b8be7c9..f5861e5a0b 100644 --- a/maintenance/fixExtLinksProtocolRelative.php +++ b/maintenance/fixExtLinksProtocolRelative.php @@ -71,11 +71,13 @@ class FixExtLinksProtocolRelative extends LoggedUpdateMaintenance { 'el_from' => $row->el_from, 'el_to' => $row->el_to, 'el_index' => "http:{$row->el_index}", + 'el_index_60' => substr( "http:{$row->el_index}", 0, 60 ), ], [ 'el_from' => $row->el_from, 'el_to' => $row->el_to, 'el_index' => "https:{$row->el_index}", + 'el_index_60' => substr( "https:{$row->el_index}", 0, 60 ), ] ], __METHOD__, [ 'IGNORE' ] ); diff --git a/maintenance/mssql/archives/patch-externallinks-el_index_60-drop-default.sql b/maintenance/mssql/archives/patch-externallinks-el_index_60-drop-default.sql new file mode 100644 index 0000000000..7755e66fd0 --- /dev/null +++ b/maintenance/mssql/archives/patch-externallinks-el_index_60-drop-default.sql @@ -0,0 +1,13 @@ +DECLARE @sql nvarchar(max) +SET @sql='' + +SELECT @sql= @sql + 'ALTER TABLE /*_*/externallinks DROP CONSTRAINT ' + df.name + '; ' +FROM sys.default_constraints df +JOIN sys.columns c + ON c.object_id = df.parent_object_id + AND c.column_id = df.parent_column_id +WHERE + df.parent_object_id = OBJECT_ID('/*_*/externallinks') + AND c.name = 'el_index_60';-- + +EXEC sp_executesql @sql; diff --git a/maintenance/mssql/tables.sql b/maintenance/mssql/tables.sql index 858260b34b..315cb20ce7 100644 --- a/maintenance/mssql/tables.sql +++ b/maintenance/mssql/tables.sql @@ -549,8 +549,7 @@ CREATE TABLE /*_*/externallinks ( -- This is el_index truncated to 60 bytes to allow for sortable queries that -- aren't supported by a partial index. - -- @todo Drop the default once this is deployed everywhere and code is populating it. - el_index_60 varbinary(60) NOT NULL default '' + el_index_60 varbinary(60) NOT NULL ); CREATE INDEX /*i*/el_from ON /*_*/externallinks (el_from); diff --git a/maintenance/populateArchiveRevId.php b/maintenance/populateArchiveRevId.php index b8b9e688e3..e493506237 100644 --- a/maintenance/populateArchiveRevId.php +++ b/maintenance/populateArchiveRevId.php @@ -32,6 +32,10 @@ require_once __DIR__ . '/Maintenance.php'; * @since 1.31 */ class PopulateArchiveRevId extends LoggedUpdateMaintenance { + + /** @var array|null Dummy revision row */ + private static $dummyRev = null; + public function __construct() { parent::__construct(); $this->addDescription( 'Populate ar_rev_id in pre-1.5 rows' ); @@ -58,7 +62,6 @@ class PopulateArchiveRevId extends LoggedUpdateMaintenance { return true; } - $rev = $this->makeDummyRevisionRow( $dbw ); $count = 0; while ( true ) { wfWaitForSlaves(); @@ -75,47 +78,60 @@ class PopulateArchiveRevId extends LoggedUpdateMaintenance { return true; } - try { - $updates = $dbw->doAtomicSection( __METHOD__, function ( $dbw, $fname ) use ( $arIds, $rev ) { - // Create new rev_ids by inserting dummy rows into revision and then deleting them. - $dbw->insert( 'revision', array_fill( 0, count( $arIds ), $rev ), $fname ); - $revIds = $dbw->selectFieldValues( - 'revision', - 'rev_id', - [ 'rev_timestamp' => $rev['rev_timestamp'] ], - $fname - ); - if ( !is_array( $revIds ) ) { - throw new UnexpectedValueException( 'Failed to insert dummy revisions' ); - } - if ( count( $revIds ) !== count( $arIds ) ) { - throw new UnexpectedValueException( - 'Tried to insert ' . count( $arIds ) . ' dummy revisions, but found ' - . count( $revIds ) . ' matching rows.' - ); - } - $dbw->delete( 'revision', [ 'rev_id' => $revIds ], $fname ); - - return array_combine( $arIds, $revIds ); - } ); - } catch ( UnexpectedValueException $ex ) { - $this->fatalError( $ex->getMessage() ); - } + $count += self::reassignArRevIds( $dbw, $arIds, [ 'ar_rev_id' => null ] ); + + $min = min( $arIds ); + $max = max( $arIds ); + $this->output( " ... $min-$max\n" ); + } + } - foreach ( $updates as $arId => $revId ) { - $dbw->update( - 'archive', - [ 'ar_rev_id' => $revId ], - [ 'ar_id' => $arId, 'ar_rev_id' => null ], - __METHOD__ + /** + * Assign new ar_rev_ids to a set of ar_ids. + * @param IDatabase $dbw + * @param int[] $arIds + * @param array $conds Extra conditions for the update + * @return int Number of updated rows + */ + public static function reassignArRevIds( IDatabase $dbw, array $arIds, array $conds = [] ) { + if ( !self::$dummyRev ) { + self::$dummyRev = self::makeDummyRevisionRow( $dbw ); + } + + $updates = $dbw->doAtomicSection( __METHOD__, function ( $dbw, $fname ) use ( $arIds ) { + // Create new rev_ids by inserting dummy rows into revision and then deleting them. + $dbw->insert( 'revision', array_fill( 0, count( $arIds ), self::$dummyRev ), $fname ); + $revIds = $dbw->selectFieldValues( + 'revision', + 'rev_id', + [ 'rev_timestamp' => self::$dummyRev['rev_timestamp'] ], + $fname + ); + if ( !is_array( $revIds ) ) { + throw new UnexpectedValueException( 'Failed to insert dummy revisions' ); + } + if ( count( $revIds ) !== count( $arIds ) ) { + throw new UnexpectedValueException( + 'Tried to insert ' . count( $arIds ) . ' dummy revisions, but found ' + . count( $revIds ) . ' matching rows.' ); - $count += $dbw->affectedRows(); } + $dbw->delete( 'revision', [ 'rev_id' => $revIds ], $fname ); - $min = min( array_keys( $updates ) ); - $max = max( array_keys( $updates ) ); - $this->output( " ... $min-$max\n" ); + return array_combine( $arIds, $revIds ); + } ); + + $count = 0; + foreach ( $updates as $arId => $revId ) { + $dbw->update( + 'archive', + [ 'ar_rev_id' => $revId ], + [ 'ar_id' => $arId ] + $conds, + __METHOD__ + ); + $count += $dbw->affectedRows(); } + return $count; } /** @@ -123,31 +139,41 @@ class PopulateArchiveRevId extends LoggedUpdateMaintenance { * * The row will have a wildly unlikely timestamp, and possibly a generic * user and comment, but will otherwise be derived from a revision on the - * wiki's main page. + * wiki's main page or some other revision in the database. * * @param IDatabase $dbw * @return array */ - private function makeDummyRevisionRow( IDatabase $dbw ) { + private static function makeDummyRevisionRow( IDatabase $dbw ) { $ts = $dbw->timestamp( '11111111111111' ); + $rev = null; + $mainPage = Title::newMainPage(); - if ( !$mainPage ) { - $this->fatalError( 'Main page does not exist' ); + $pageId = $mainPage ? $mainPage->getArticleId() : null; + if ( $pageId ) { + $rev = $dbw->selectRow( + 'revision', + '*', + [ 'rev_page' => $pageId ], + __METHOD__, + [ 'ORDER BY' => 'rev_timestamp ASC' ] + ); } - $pageId = $mainPage->getArticleId(); - if ( !$pageId ) { - $this->fatalError( $mainPage->getPrefixedText() . ' has no ID' ); + + if ( !$rev ) { + // No main page? Let's see if there are any revisions at all + $rev = $dbw->selectRow( + 'revision', + '*', + [], + __METHOD__, + [ 'ORDER BY' => 'rev_timestamp ASC' ] + ); } - $rev = $dbw->selectRow( - 'revision', - '*', - [ 'rev_page' => $pageId ], - __METHOD__, - [ 'ORDER BY' => 'rev_timestamp ASC' ] - ); if ( !$rev ) { - $this->fatalError( $mainPage->getPrefixedText() . ' has no revisions' ); + throw new UnexpectedValueException( 'No revisions are available to copy' ); } + unset( $rev->rev_id ); $rev = (array)$rev; $rev['rev_timestamp'] = $ts; @@ -166,7 +192,7 @@ class PopulateArchiveRevId extends LoggedUpdateMaintenance { __METHOD__ ); if ( $any ) { - $this->fatalError( "... Why does your database contain a revision dated $ts?" ); + throw new UnexpectedValueException( "... Why does your database contain a revision dated $ts?" ); } return $rev; diff --git a/maintenance/populateExternallinksIndex60.php b/maintenance/populateExternallinksIndex60.php new file mode 100644 index 0000000000..9b029fefaa --- /dev/null +++ b/maintenance/populateExternallinksIndex60.php @@ -0,0 +1,89 @@ +addDescription( + 'Populates the el_index_60 field in the externallinks table' ); + $this->setBatchSize( 200 ); + } + + protected function getUpdateKey() { + return 'populate externallinks.el_index_60'; + } + + protected function updateSkippedMessage() { + return 'externallinks.el_index_60 already populated.'; + } + + protected function doDBUpdates() { + $dbw = $this->getDB( DB_MASTER ); + $this->output( "Populating externallinks.el_index_60...\n" ); + + $count = 0; + $start = 0; + $last = $dbw->selectField( 'externallinks', 'MAX(el_id)', '', __METHOD__ ); + while ( $start <= $last ) { + $end = $start + $this->mBatchSize; + $this->output( "el_id $start - $end of $last\n" ); + $res = $dbw->select( 'externallinks', [ 'el_id', 'el_index' ], + [ + "el_id > $start", + "el_id <= $end", + 'el_index_60' => '', + ], + __METHOD__, + [ 'ORDER BY' => 'el_id' ] + ); + foreach ( $res as $row ) { + $count++; + $dbw->update( 'externallinks', + [ + 'el_index_60' => substr( $row->el_index, 0, 60 ), + ], + [ + 'el_id' => $row->el_id, + ], __METHOD__, [ 'IGNORE' ] + ); + } + wfWaitForSlaves(); + $start = $end; + } + $this->output( "Done, $count rows updated.\n" ); + + return true; + } +} + +$maintClass = "PopulateExternallinksIndex60"; +require_once RUN_MAINTENANCE_IF_MAIN; diff --git a/maintenance/postgres/tables.sql b/maintenance/postgres/tables.sql index 1a53359a99..492a0d5a4c 100644 --- a/maintenance/postgres/tables.sql +++ b/maintenance/postgres/tables.sql @@ -373,7 +373,7 @@ CREATE TABLE externallinks ( el_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, el_to TEXT NOT NULL, el_index TEXT NOT NULL, - el_index_60 BYTEA NOT NULL DEFAULT '' + el_index_60 BYTEA NOT NULL ); ALTER SEQUENCE externallinks_el_id_seq OWNED BY externallinks.el_id; CREATE INDEX externallinks_from_to ON externallinks (el_from,el_to); diff --git a/maintenance/resources/update-ooui.sh b/maintenance/resources/update-ooui.sh index 231001de45..889ab42b70 100755 --- a/maintenance/resources/update-ooui.sh +++ b/maintenance/resources/update-ooui.sh @@ -43,15 +43,15 @@ rm -r "$REPO_DIR/$TARGET_DIR" # Core and thematic code and styling mkdir -p "$REPO_DIR/$TARGET_DIR" -cp ./node_modules/oojs-ui/dist/oojs-ui-core.js{,.map} "$REPO_DIR/$TARGET_DIR" +cp ./node_modules/oojs-ui/dist/oojs-ui-core.js{,.map.json} "$REPO_DIR/$TARGET_DIR" cp ./node_modules/oojs-ui/dist/oojs-ui-core-{wikimediaui,apex}.css "$REPO_DIR/$TARGET_DIR" -cp ./node_modules/oojs-ui/dist/oojs-ui-widgets.js{,.map} "$REPO_DIR/$TARGET_DIR" +cp ./node_modules/oojs-ui/dist/oojs-ui-widgets.js{,.map.json} "$REPO_DIR/$TARGET_DIR" cp ./node_modules/oojs-ui/dist/oojs-ui-widgets-{wikimediaui,apex}.css "$REPO_DIR/$TARGET_DIR" -cp ./node_modules/oojs-ui/dist/oojs-ui-toolbars.js{,.map} "$REPO_DIR/$TARGET_DIR" +cp ./node_modules/oojs-ui/dist/oojs-ui-toolbars.js{,.map.json} "$REPO_DIR/$TARGET_DIR" cp ./node_modules/oojs-ui/dist/oojs-ui-toolbars-{wikimediaui,apex}.css "$REPO_DIR/$TARGET_DIR" -cp ./node_modules/oojs-ui/dist/oojs-ui-windows.js{,.map} "$REPO_DIR/$TARGET_DIR" +cp ./node_modules/oojs-ui/dist/oojs-ui-windows.js{,.map.json} "$REPO_DIR/$TARGET_DIR" cp ./node_modules/oojs-ui/dist/oojs-ui-windows-{wikimediaui,apex}.css "$REPO_DIR/$TARGET_DIR" -cp ./node_modules/oojs-ui/dist/oojs-ui-{wikimediaui,apex}.js{,.map} "$REPO_DIR/$TARGET_DIR" +cp ./node_modules/oojs-ui/dist/oojs-ui-{wikimediaui,apex}.js{,.map.json} "$REPO_DIR/$TARGET_DIR" # i18n mkdir -p "$REPO_DIR/$TARGET_DIR/i18n" diff --git a/maintenance/sqlite/archives/patch-externallinks-el_index_60-drop-default.sql b/maintenance/sqlite/archives/patch-externallinks-el_index_60-drop-default.sql new file mode 100644 index 0000000000..1d82f4d4d5 --- /dev/null +++ b/maintenance/sqlite/archives/patch-externallinks-el_index_60-drop-default.sql @@ -0,0 +1,21 @@ +-- To change the default on one column, sqlite requires we copy the whole table + +CREATE TABLE /*_*/externallinks_tmp ( + el_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, + el_from int unsigned NOT NULL default 0, + el_to blob NOT NULL, + el_index blob NOT NULL, + el_index_60 varbinary(60) NOT NULL +) /*$wgDBTableOptions*/; + +INSERT INTO /*_*/externallinks_tmp + SELECT el_id, el_from, el_to, el_index, el_index_60 FROM /*_*/externallinks; + +DROP TABLE /*_*/externallinks; +ALTER TABLE /*_*/externallinks_tmp RENAME TO /*_*/externallinks; + +CREATE INDEX /*i*/el_from ON /*_*/externallinks (el_from, el_to(40)); +CREATE INDEX /*i*/el_to ON /*_*/externallinks (el_to(60), el_from); +CREATE INDEX /*i*/el_index ON /*_*/externallinks (el_index(60)); +CREATE INDEX /*i*/el_index_60 ON /*_*/externallinks (el_index_60, el_id); +CREATE INDEX /*i*/el_from_index_60 ON /*_*/externallinks (el_from, el_index_60, el_id); diff --git a/maintenance/tables.sql b/maintenance/tables.sql index 34c63ed72a..ed3bd43991 100644 --- a/maintenance/tables.sql +++ b/maintenance/tables.sql @@ -932,8 +932,7 @@ CREATE TABLE /*_*/externallinks ( -- This is el_index truncated to 60 bytes to allow for sortable queries that -- aren't supported by a partial index. - -- @todo Drop the default once this is deployed everywhere and code is populating it. - el_index_60 varbinary(60) NOT NULL default '' + el_index_60 varbinary(60) NOT NULL ) /*$wgDBTableOptions*/; -- Forward index, for page edit, save diff --git a/package.json b/package.json index e9048ec0f1..1f23b1a09b 100644 --- a/package.json +++ b/package.json @@ -15,23 +15,23 @@ "grunt": "1.0.1", "grunt-banana-checker": "0.6.0", "grunt-contrib-copy": "1.0.0", - "grunt-contrib-watch": "1.0.0", + "grunt-contrib-watch": "1.0.1", "grunt-eslint": "20.1.0", "grunt-jsonlint": "1.1.0", "grunt-karma": "2.0.0", "grunt-stylelint": "0.10.0", - "karma": "1.7.1", + "karma": "2.0.2", "karma-chrome-launcher": "2.2.0", "karma-firefox-launcher": "1.0.1", "karma-mocha-reporter": "2.2.5", "karma-qunit": "2.0.1", "postcss-less": "1.1.5", - "qunit": "2.5.0", + "qunit": "2.6.0", "stylelint": "9.2.0", "stylelint-config-wikimedia": "0.4.3", "wdio-junit-reporter": "0.2.0", "wdio-mediawiki": "file:tests/selenium/wdio-mediawiki", - "wdio-mocha-framework": "0.5.8", + "wdio-mocha-framework": "0.5.13", "wdio-sauce-service": "0.3.1", "wdio-spec-reporter": "0.0.5", "webdriverio": "4.12.0" diff --git a/resources/Resources.php b/resources/Resources.php index ea4e5eafe7..77391a8ce7 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -303,8 +303,8 @@ return [ 'targets' => [ 'desktop', 'mobile' ], ], 'jquery.spinner' => [ - 'scripts' => 'resources/src/jquery/jquery.spinner.js', - 'styles' => 'resources/src/jquery/jquery.spinner.css', + 'scripts' => 'resources/src/jquery.spinner/spinner.js', + 'styles' => 'resources/src/jquery.spinner/spinner.css', 'targets' => [ 'desktop', 'mobile' ], ], 'jquery.jStorage' => [ @@ -1994,18 +1994,21 @@ return [ ], 'mediawiki.special' => [ 'styles' => [ - 'resources/src/mediawiki.special/mediawiki.special.css', - 'resources/src/mediawiki.special/mediawiki.special.userrights.css', + 'resources/src/mediawiki.special/special.css', + 'resources/src/mediawiki.special/apisandbox.css', + 'resources/src/mediawiki.special/comparepages.less', + 'resources/src/mediawiki.special/edittags.css', + 'resources/src/mediawiki.special/movePage.css', + 'resources/src/mediawiki.special/pagesWithProp.css', + 'resources/src/mediawiki.special/upload.css', + 'resources/src/mediawiki.special/userrights.css', + 'resources/src/mediawiki.special/watchlist.css', ], 'targets' => [ 'desktop', 'mobile' ], ], - 'mediawiki.special.apisandbox.styles' => [ - 'targets' => [ 'desktop', 'mobile' ], - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.top.css', - ], 'mediawiki.special.apisandbox' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.css', - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.js', + 'styles' => 'resources/src/mediawiki.special.apisandbox/apisandbox.css', + 'scripts' => 'resources/src/mediawiki.special.apisandbox/apisandbox.js', 'targets' => [ 'desktop', 'mobile' ], 'dependencies' => [ 'mediawiki.api', @@ -2034,6 +2037,7 @@ return [ 'apisandbox-dynamic-parameters-add-label', 'apisandbox-dynamic-parameters-add-placeholder', 'apisandbox-dynamic-error-exists', + 'apisandbox-templated-parameter-reason', 'apisandbox-deprecated-parameters', 'apisandbox-no-parameters', 'api-help-param-limit', @@ -2070,10 +2074,13 @@ return [ 'apisandbox-multivalue-all-values', 'api-format-prettyprint-status', 'blanknamespace', + 'comma-separator', + 'word-separator', + 'and' ], ], 'mediawiki.special.block' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.block.js', + 'scripts' => 'resources/src/mediawiki.special.block.js', 'dependencies' => [ 'oojs-ui-core', 'oojs-ui.styles.icons-editing-core', @@ -2086,7 +2093,7 @@ return [ ], ], 'mediawiki.special.changecredentials.js' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changecredentials.js', + 'scripts' => 'resources/src/mediawiki.special.changecredentials.js', 'dependencies' => [ 'mediawiki.api', 'mediawiki.htmlform.ooui' @@ -2094,39 +2101,33 @@ return [ 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.changeslist' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.css', + 'styles' => 'resources/src/mediawiki.special.changeslist.css', 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.changeslist.enhanced' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css', + 'styles' => 'resources/src/mediawiki.special.changeslist.enhanced.css', ], 'mediawiki.special.changeslist.legend' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css', + 'styles' => 'resources/src/mediawiki.special.changeslist.legend.css', 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.changeslist.legend.js' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js', + 'scripts' => 'resources/src/mediawiki.special.changeslist.legend.js', 'dependencies' => [ 'jquery.makeCollapsible', 'mediawiki.cookie', ], 'targets' => [ 'desktop', 'mobile' ], ], - 'mediawiki.special.changeslist.visitedstatus' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.visitedstatus.js', - ], - 'mediawiki.special.comparepages.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less', - ], 'mediawiki.special.contributions' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.contributions.js', + 'scripts' => 'resources/src/mediawiki.special.contributions.js', 'dependencies' => [ 'mediawiki.widgets.DateInputWidget', 'mediawiki.jqueryMsg', ] ], 'mediawiki.special.edittags' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.edittags.js', + 'scripts' => 'resources/src/mediawiki.special.edittags.js', 'dependencies' => [ 'jquery.chosen', 'jquery.lengthLimit', @@ -2136,39 +2137,30 @@ return [ 'tags-edit-chosen-no-results', ], ], - 'mediawiki.special.edittags.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.edittags.css', - ], 'mediawiki.special.import' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.import.js', + 'scripts' => 'resources/src/mediawiki.special.import.js', ], 'mediawiki.special.movePage' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.movePage.js', + 'scripts' => 'resources/src/mediawiki.special.movePage.js', 'dependencies' => [ 'mediawiki.widgets.visibleLengthLimit', 'mediawiki.widgets', ], ], - 'mediawiki.special.movePage.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.movePage.css', - ], 'mediawiki.special.pageLanguage' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.pageLanguage.js', + 'scripts' => 'resources/src/mediawiki.special.pageLanguage.js', 'dependencies' => [ 'oojs-ui-core', ], ], - 'mediawiki.special.pagesWithProp' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css', - ], 'mediawiki.special.preferences' => [ 'targets' => [ 'desktop', 'mobile' ], 'scripts' => [ - 'resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.tabs.legacy.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.personalEmail.js', + 'resources/src/mediawiki.special.preferences/confirmClose.js', + 'resources/src/mediawiki.special.preferences/convertmessagebox.js', + 'resources/src/mediawiki.special.preferences/tabs.legacy.js', + 'resources/src/mediawiki.special.preferences/timezone.js', + 'resources/src/mediawiki.special.preferences/personalEmail.js', ], 'messages' => [ 'prefs-tabs-navigation-hint', @@ -2184,17 +2176,19 @@ return [ ], 'mediawiki.special.preferences.styles' => [ 'targets' => [ 'desktop', 'mobile' ], - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.styles.legacy.css', + // legacy + 'styles' => 'resources/src/mediawiki.special.preferences.styles.css', ], 'mediawiki.special.preferences.ooui' => [ 'targets' => [ 'desktop', 'mobile' ], 'scripts' => [ - 'resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.editfont.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.personalEmail.js', + // FIXME: This uses files already belonging to another module + 'resources/src/mediawiki.special.preferences/confirmClose.js', + 'resources/src/mediawiki.special.preferences/convertmessagebox.js', + 'resources/src/mediawiki.special.preferences.ooui/editfont.js', + 'resources/src/mediawiki.special.preferences.ooui/tabs.js', + 'resources/src/mediawiki.special.preferences/timezone.js', + 'resources/src/mediawiki.special.preferences/personalEmail.js', ], 'messages' => [ 'prefs-tabs-navigation-hint', @@ -2213,14 +2207,14 @@ return [ ], 'mediawiki.special.preferences.styles.ooui' => [ 'targets' => [ 'desktop', 'mobile' ], - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.styles.css', + 'styles' => 'resources/src/mediawiki.special.preferences.styles.ooui.css', ], 'mediawiki.special.recentchanges' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.recentchanges.js', + 'scripts' => 'resources/src/mediawiki.special.recentchanges.js', 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.revisionDelete' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.revisionDelete.js', + 'scripts' => 'resources/src/mediawiki.special.revisionDelete.js', 'messages' => [ // @todo Load this message in content language 'colon-separator', @@ -2231,8 +2225,8 @@ return [ 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.search' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.js', - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.css', + 'scripts' => 'resources/src/mediawiki.special.search/search.js', + 'styles' => 'resources/src/mediawiki.special.search/search.css', 'dependencies' => 'mediawiki.widgets.SearchInputWidget', 'messages' => [ 'powersearch-togglelabel', @@ -2241,7 +2235,7 @@ return [ ], ], 'mediawiki.special.search.commonsInterwikiWidget' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js', + 'scripts' => 'resources/src/mediawiki.special.search.commonsInterwikiWidget.js', 'dependencies' => [ 'mediawiki.api', 'mediawiki.Uri', @@ -2254,24 +2248,23 @@ return [ ], ], 'mediawiki.special.search.interwikiwidget.styles' => [ - 'styles' => 'resources/src/mediawiki.special/' - . 'mediawiki.special.search.interwikiwidget.styles.less', + 'styles' => 'resources/src/mediawiki.special.search.interwikiwidget.styles.less', 'targets' => [ 'desktop', 'mobile' ] ], 'mediawiki.special.search.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.styles.css', + 'styles' => 'resources/src/mediawiki.special.search.styles.css', 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.undelete' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.undelete.js', + 'scripts' => 'resources/src/mediawiki.special.undelete.js', 'dependencies' => [ 'mediawiki.widgets.visibleLengthLimit', 'mediawiki.widgets', ], ], 'mediawiki.special.unwatchedPages' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.unwatchedPages.js', - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.unwatchedPages.css', + 'scripts' => 'resources/src/mediawiki.special.unwatchedPages/unwatchedPages.js', + 'styles' => 'resources/src/mediawiki.special.unwatchedPages/unwatchedPages.css', 'messages' => [ 'addedwatchtext-short', 'removedwatchtext-short', @@ -2291,9 +2284,9 @@ return [ ], 'mediawiki.special.upload' => [ 'templates' => [ - 'thumbnail.html' => 'resources/src/mediawiki.special/templates/thumbnail.html', + 'thumbnail.html' => 'resources/src/mediawiki.special.upload/templates/thumbnail.html', ], - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.upload.js', + 'scripts' => 'resources/src/mediawiki.special.upload/upload.js', 'messages' => [ 'widthheight', 'size-bytes', @@ -2306,7 +2299,7 @@ return [ 'prefs-editing', ], 'dependencies' => [ - 'mediawiki.special.upload.styles', + 'mediawiki.special', 'jquery.spinner', 'mediawiki.jqueryMsg', 'mediawiki.api', @@ -2318,22 +2311,19 @@ return [ 'user.options', ], ], - 'mediawiki.special.upload.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.upload.styles.css', - ], 'mediawiki.special.userlogin.common.styles' => [ 'targets' => [ 'desktop', 'mobile' ], 'skinStyles' => [ - 'default' => 'resources/src/mediawiki.special/mediawiki.special.userlogin.common.css', + 'default' => 'resources/src/mediawiki.special.userlogin.common.styles/userlogin.css', ], ], 'mediawiki.special.userlogin.login.styles' => [ 'styles' => [ - 'resources/src/mediawiki.special/mediawiki.special.userlogin.login.css', + 'resources/src/mediawiki.special.userlogin.login.styles/login.css', ], ], 'mediawiki.special.userlogin.signup.js' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js', + 'scripts' => 'resources/src/mediawiki.special.userlogin.signup.js', 'messages' => [ 'createacct-emailrequired', 'noname', @@ -2348,18 +2338,21 @@ return [ ], 'mediawiki.special.userlogin.signup.styles' => [ 'styles' => [ - 'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css', + 'resources/src/mediawiki.special.userlogin.signup.styles/signup.css', ], ], 'mediawiki.special.userrights' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userrights.js', + 'scripts' => 'resources/src/mediawiki.special.userrights.js', 'dependencies' => [ 'mediawiki.notification.convertmessagebox', 'jquery.lengthLimit', ], ], 'mediawiki.special.watchlist' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.watchlist.js', + 'scripts' => [ + 'resources/src/mediawiki.special.watchlist/watchlist.js', + 'resources/src/mediawiki.special.watchlist/visitedstatus.js', + ], 'messages' => [ 'addedwatchtext', 'addedwatchtext-talk', @@ -2379,11 +2372,8 @@ return [ 'user.options', ], ], - 'mediawiki.special.watchlist.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.watchlist.css', - ], 'mediawiki.special.version' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.version.css', + 'styles' => 'resources/src/mediawiki.special.version.css', ], /* MediaWiki Installer */ diff --git a/resources/src/jquery.spinner/images/spinner-large.gif b/resources/src/jquery.spinner/images/spinner-large.gif new file mode 100644 index 0000000000..72203fdd7f Binary files /dev/null and b/resources/src/jquery.spinner/images/spinner-large.gif differ diff --git a/resources/src/jquery.spinner/images/spinner.gif b/resources/src/jquery.spinner/images/spinner.gif new file mode 100644 index 0000000000..6146be4e88 Binary files /dev/null and b/resources/src/jquery.spinner/images/spinner.gif differ diff --git a/resources/src/jquery.spinner/spinner.css b/resources/src/jquery.spinner/spinner.css new file mode 100644 index 0000000000..9c819a65cb --- /dev/null +++ b/resources/src/jquery.spinner/spinner.css @@ -0,0 +1,36 @@ +.mw-spinner { + background-color: transparent; + background-position: center center; + background-repeat: no-repeat; +} + +.mw-spinner-small { + /* @embed */ + background-image: url( images/spinner.gif ); + height: 20px; + width: 20px; + /* Avoid issues with .mw-spinner-block when floated without width. */ + min-width: 20px; +} + +.mw-spinner-large { + /* @embed */ + background-image: url( images/spinner-large.gif ); + height: 32px; + width: 32px; + /* Avoid issues with .mw-spinner-block when floated without width. */ + min-width: 32px; +} + +.mw-spinner-block { + display: block; + /* This overrides width from .mw-spinner-large / .mw-spinner-small, + * This is where the min-width kicks in. + */ + width: 100%; +} + +.mw-spinner-inline { + display: inline-block; + vertical-align: middle; +} diff --git a/resources/src/jquery.spinner/spinner.js b/resources/src/jquery.spinner/spinner.js new file mode 100644 index 0000000000..9079cc09b7 --- /dev/null +++ b/resources/src/jquery.spinner/spinner.js @@ -0,0 +1,114 @@ +/** + * jQuery Spinner + * + * Simple jQuery plugin to create, inject and remove spinners. + * + * @class jQuery.plugin.spinner + */ +( function ( $ ) { + + // Default options for new spinners, + // stored outside the function to share between calls. + var defaults = { + id: undefined, + size: 'small', + type: 'inline' + }; + + $.extend( { + /** + * Create a spinner element + * + * The argument is an object with options used to construct the spinner (see below). + * + * It is a good practice to keep a reference to the created spinner to be able to remove it + * later. Alternatively, one can use the 'id' option and #removeSpinner (but make sure to choose + * an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts). + * + * CSS classes used: + * + * - .mw-spinner for every spinner + * - .mw-spinner-small / .mw-spinner-large for size + * - .mw-spinner-block / .mw-spinner-inline for display types + * + * Example: + * + * // Create a large spinner reserving all available horizontal space. + * var $spinner = $.createSpinner( { size: 'large', type: 'block' } ); + * // Insert above page content. + * $( '#mw-content-text' ).prepend( $spinner ); + * + * // Place a small inline spinner next to the "Save" button + * var $spinner = $.createSpinner( { size: 'small', type: 'inline' } ); + * // Alternatively, just `$.createSpinner();` as these are the default options. + * $( '#wpSave' ).after( $spinner ); + * + * // The following two are equivalent: + * $.createSpinner( 'magic' ); + * $.createSpinner( { id: 'magic' } ); + * + * @static + * @inheritable + * @param {Object|string} [opts] Options. If a string is given, it will be treated as the value + * of the `id` option. If an object is given, the possible option keys are: + * @param {string} [opts.id] If given, spinner will be given an id of "mw-spinner-{id}". + * @param {string} [opts.size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner. + * @param {string} [opts.type='inline'] 'inline' or 'block'. Inline creates an inline-block with + * width and height equal to spinner size. Block is a block-level element with width 100%, + * height equal to spinner size. + * @return {jQuery} + */ + createSpinner: function ( opts ) { + var $spinner; + + if ( opts !== undefined && $.type( opts ) !== 'object' ) { + opts = { + id: opts + }; + } + + opts = $.extend( {}, defaults, opts ); + + $spinner = $( '
' ).addClass( 'mw-spinner' ).attr( 'title', '...' ); + if ( opts.id !== undefined ) { + $spinner.attr( 'id', 'mw-spinner-' + opts.id ); + } + + $spinner.addClass( opts.size === 'large' ? 'mw-spinner-large' : 'mw-spinner-small' ); + $spinner.addClass( opts.type === 'block' ? 'mw-spinner-block' : 'mw-spinner-inline' ); + + return $spinner; + }, + + /** + * Remove a spinner element + * + * @static + * @inheritable + * @param {string} id Id of the spinner, as passed to #createSpinner + * @return {jQuery} The (now detached) spinner element + */ + removeSpinner: function ( id ) { + return $( '#mw-spinner-' + id ).remove(); + } + } ); + + /** + * Inject a spinner after each element in the collection + * + * Inserts spinner as siblings (not children) of the target elements. + * Collection contents remain unchanged. + * + * @param {Object|string} [opts] See #createSpinner + * @return {jQuery} + */ + $.fn.injectSpinner = function ( opts ) { + return this.after( $.createSpinner( opts ) ); + }; + + /** + * @class jQuery + * @mixins jQuery.plugin.spinner + */ + +}( jQuery ) ); diff --git a/resources/src/jquery/images/spinner-large.gif b/resources/src/jquery/images/spinner-large.gif deleted file mode 100644 index 72203fdd7f..0000000000 Binary files a/resources/src/jquery/images/spinner-large.gif and /dev/null differ diff --git a/resources/src/jquery/images/spinner.gif b/resources/src/jquery/images/spinner.gif deleted file mode 100644 index 6146be4e88..0000000000 Binary files a/resources/src/jquery/images/spinner.gif and /dev/null differ diff --git a/resources/src/jquery/jquery.spinner.css b/resources/src/jquery/jquery.spinner.css deleted file mode 100644 index 6c7bd0e660..0000000000 --- a/resources/src/jquery/jquery.spinner.css +++ /dev/null @@ -1,40 +0,0 @@ -.mw-spinner { - background-color: transparent; - background-position: center center; - background-repeat: no-repeat; -} - -.mw-spinner-small { - /* @embed */ - background-image: url( images/spinner.gif ); - height: 20px; - width: 20px; - /* Avoid issues with .mw-spinner-block when floated without width. */ - min-width: 20px; -} - -.mw-spinner-large { - /* @embed */ - background-image: url( images/spinner-large.gif ); - height: 32px; - width: 32px; - /* Avoid issues with .mw-spinner-block when floated without width. */ - min-width: 32px; -} - -.mw-spinner-block { - display: block; - /* This overrides width from .mw-spinner-large / .mw-spinner-small, - * This is where the min-width kicks in. - */ - width: 100%; -} - -.mw-spinner-inline { - display: inline-block; - vertical-align: middle; - - /* IE < 8 */ - zoom: 1; - *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */ -} diff --git a/resources/src/jquery/jquery.spinner.js b/resources/src/jquery/jquery.spinner.js deleted file mode 100644 index 9079cc09b7..0000000000 --- a/resources/src/jquery/jquery.spinner.js +++ /dev/null @@ -1,114 +0,0 @@ -/** - * jQuery Spinner - * - * Simple jQuery plugin to create, inject and remove spinners. - * - * @class jQuery.plugin.spinner - */ -( function ( $ ) { - - // Default options for new spinners, - // stored outside the function to share between calls. - var defaults = { - id: undefined, - size: 'small', - type: 'inline' - }; - - $.extend( { - /** - * Create a spinner element - * - * The argument is an object with options used to construct the spinner (see below). - * - * It is a good practice to keep a reference to the created spinner to be able to remove it - * later. Alternatively, one can use the 'id' option and #removeSpinner (but make sure to choose - * an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts). - * - * CSS classes used: - * - * - .mw-spinner for every spinner - * - .mw-spinner-small / .mw-spinner-large for size - * - .mw-spinner-block / .mw-spinner-inline for display types - * - * Example: - * - * // Create a large spinner reserving all available horizontal space. - * var $spinner = $.createSpinner( { size: 'large', type: 'block' } ); - * // Insert above page content. - * $( '#mw-content-text' ).prepend( $spinner ); - * - * // Place a small inline spinner next to the "Save" button - * var $spinner = $.createSpinner( { size: 'small', type: 'inline' } ); - * // Alternatively, just `$.createSpinner();` as these are the default options. - * $( '#wpSave' ).after( $spinner ); - * - * // The following two are equivalent: - * $.createSpinner( 'magic' ); - * $.createSpinner( { id: 'magic' } ); - * - * @static - * @inheritable - * @param {Object|string} [opts] Options. If a string is given, it will be treated as the value - * of the `id` option. If an object is given, the possible option keys are: - * @param {string} [opts.id] If given, spinner will be given an id of "mw-spinner-{id}". - * @param {string} [opts.size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner. - * @param {string} [opts.type='inline'] 'inline' or 'block'. Inline creates an inline-block with - * width and height equal to spinner size. Block is a block-level element with width 100%, - * height equal to spinner size. - * @return {jQuery} - */ - createSpinner: function ( opts ) { - var $spinner; - - if ( opts !== undefined && $.type( opts ) !== 'object' ) { - opts = { - id: opts - }; - } - - opts = $.extend( {}, defaults, opts ); - - $spinner = $( '
' ).addClass( 'mw-spinner' ).attr( 'title', '...' ); - if ( opts.id !== undefined ) { - $spinner.attr( 'id', 'mw-spinner-' + opts.id ); - } - - $spinner.addClass( opts.size === 'large' ? 'mw-spinner-large' : 'mw-spinner-small' ); - $spinner.addClass( opts.type === 'block' ? 'mw-spinner-block' : 'mw-spinner-inline' ); - - return $spinner; - }, - - /** - * Remove a spinner element - * - * @static - * @inheritable - * @param {string} id Id of the spinner, as passed to #createSpinner - * @return {jQuery} The (now detached) spinner element - */ - removeSpinner: function ( id ) { - return $( '#mw-spinner-' + id ).remove(); - } - } ); - - /** - * Inject a spinner after each element in the collection - * - * Inserts spinner as siblings (not children) of the target elements. - * Collection contents remain unchanged. - * - * @param {Object|string} [opts] See #createSpinner - * @return {jQuery} - */ - $.fn.injectSpinner = function ( opts ) { - return this.after( $.createSpinner( opts ) ); - }; - - /** - * @class jQuery - * @mixins jQuery.plugin.spinner - */ - -}( jQuery ) ); diff --git a/resources/src/mediawiki.language/mediawiki.language.init.js b/resources/src/mediawiki.language/mediawiki.language.init.js index e5cf26e8d3..077473ba01 100644 --- a/resources/src/mediawiki.language/mediawiki.language.init.js +++ b/resources/src/mediawiki.language/mediawiki.language.init.js @@ -77,7 +77,11 @@ if ( !( langData[ langCode ] instanceof mw.Map ) ) { langData[ langCode ] = new mw.Map(); } - langData[ langCode ].set( dataKey, value ); + if ( arguments.length > 2 ) { + langData[ langCode ].set( dataKey, value ); + } else { + langData[ langCode ].set( dataKey ); + } } }; diff --git a/resources/src/mediawiki.skinning/content.parsoid.less b/resources/src/mediawiki.skinning/content.parsoid.less index 27ecb1a4c7..d880e8bebd 100644 --- a/resources/src/mediawiki.skinning/content.parsoid.less +++ b/resources/src/mediawiki.skinning/content.parsoid.less @@ -55,7 +55,7 @@ figure[ typeof*='mw:Audio' ] { &.mw-halign-right { /* @noflip */ - margin: 0.5em 0 1.3em 1.4em; + margin: 0 0 0.5em 0.5em; /* @noflip */ clear: right; /* @noflip */ @@ -64,7 +64,7 @@ figure[ typeof*='mw:Audio' ] { &.mw-halign-left { /* @noflip */ - margin: 0.5em 1.4em 1.3em 0; + margin: 0 0.5em 0.5em 0; /* @noflip */ clear: left; /* @noflip */ @@ -116,6 +116,15 @@ figure[ typeof~='mw:Audio/Frame' ] { clear: right; float: right; + &.mw-halign-left { + /* @noflip */ + margin: 0.5em 1.4em 1.3em 0; + } + &.mw-halign-right { + /* @noflip */ + margin: 0.5em 0 1.3em 1.4em; + } + > *:first-child { > img, > video { diff --git a/resources/src/mediawiki.special.apisandbox/apisandbox.css b/resources/src/mediawiki.special.apisandbox/apisandbox.css new file mode 100644 index 0000000000..fe5ac416bf --- /dev/null +++ b/resources/src/mediawiki.special.apisandbox/apisandbox.css @@ -0,0 +1,110 @@ +.mw-apisandbox-toolbar { + background: #fff; + -webkit-position: sticky; + position: sticky; + top: 0; + margin-bottom: -1px; + padding: 0.5em 0; + border-bottom: 1px solid #a2a9b1; + text-align: right; + z-index: 1; +} + +#mw-apisandbox-ui .mw-apisandbox-link { + display: none; +} + +.mw-apisandbox-popup .oo-ui-popupWidget-body > .oo-ui-widget { + vertical-align: middle; +} + +/* So DateTimeInputWidget's calendar popup works... */ +.mw-apisandbox-popup .oo-ui-popupWidget-popup, +.mw-apisandbox-popup .oo-ui-popupWidget-body { + overflow: visible; +} + +/* Display contents of the popup on a single line */ +.mw-apisandbox-popup > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-body { + display: table; +} + +.mw-apisandbox-popup > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-body > * { + display: table-cell; +} + +.mw-apisandbox-popup > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-body > .oo-ui-buttonWidget { + padding-left: 0.5em; + width: 1%; +} + +.mw-apisandbox-spacer { + display: inline-block; + height: 1px; + width: 5em; +} + +.mw-apisandbox-help-field { + border-bottom: 1px solid rgba( 0, 0, 0, 0.1 ); +} + +.mw-apisandbox-help-field:last-child { + border-bottom: 0; +} + +.mw-apisandbox-optionalWidget { + width: 100%; +} + +.mw-apisandbox-optionalWidget.oo-ui-widget-disabled { + position: relative; + z-index: 0; /* New stacking context to prevent the cover from leaking out */ +} + +.mw-apisandbox-optionalWidget-cover { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 2; + cursor: pointer; +} + +.mw-apisandbox-optionalWidget-fields { + display: table; + width: 100%; +} + +.mw-apisandbox-optionalWidget-widget, +.mw-apisandbox-optionalWidget-checkbox { + display: table-cell; + vertical-align: middle; +} + +.mw-apisandbox-optionalWidget-checkbox { + width: 1%; /* Will be expanded by content */ + white-space: nowrap; + padding-left: 0.5em; +} + +.mw-apisandbox-textInputCode .oo-ui-inputWidget-input { + font-family: monospace, monospace; + font-size: 0.8125em; + -moz-tab-size: 4; + tab-size: 4; +} + +.mw-apisandbox-widget-field .oo-ui-textInputWidget { + /* Leave at least enough space for icon, indicator, and a sliver of text */ + min-width: 6em; +} + +.apihelp-deprecated { + font-weight: bold; + color: #d33; +} + +.apihelp-deprecated-value .oo-ui-labelElement-label { + text-decoration: line-through; +} diff --git a/resources/src/mediawiki.special.apisandbox/apisandbox.js b/resources/src/mediawiki.special.apisandbox/apisandbox.js new file mode 100644 index 0000000000..f936658ff3 --- /dev/null +++ b/resources/src/mediawiki.special.apisandbox/apisandbox.js @@ -0,0 +1,2073 @@ +( function ( $, mw, OO ) { + 'use strict'; + var ApiSandbox, Util, WidgetMethods, Validators, + $content, panel, booklet, oldhash, windowManager, + formatDropdown, + api = new mw.Api(), + bookletPages = [], + availableFormats = {}, + resultPage = null, + suppressErrors = true, + updatingBooklet = false, + pages = {}, + moduleInfoCache = {}, + baseRequestParams; + + /** + * A wrapper for a widget that provides an enable/disable button + * + * @class + * @private + * @constructor + * @param {OO.ui.Widget} widget + * @param {Object} [config] Configuration options + */ + function OptionalWidget( widget, config ) { + var k; + + config = config || {}; + + this.widget = widget; + this.$cover = config.$cover || + $( '
' ).addClass( 'mw-apisandbox-optionalWidget-cover' ); + this.checkbox = new OO.ui.CheckboxInputWidget( config.checkbox ) + .on( 'change', this.onCheckboxChange, [], this ); + + OptionalWidget[ 'super' ].call( this, config ); + + // Forward most methods for convenience + for ( k in this.widget ) { + if ( $.isFunction( this.widget[ k ] ) && !this[ k ] ) { + this[ k ] = this.widget[ k ].bind( this.widget ); + } + } + + widget.connect( this, { + change: [ this.emit, 'change' ] + } ); + + this.$cover.on( 'click', this.onOverlayClick.bind( this ) ); + + this.$element + .addClass( 'mw-apisandbox-optionalWidget' ) + .append( + this.$cover, + $( '
' ).addClass( 'mw-apisandbox-optionalWidget-fields' ).append( + $( '
' ).addClass( 'mw-apisandbox-optionalWidget-widget' ).append( + widget.$element + ), + $( '
' ).addClass( 'mw-apisandbox-optionalWidget-checkbox' ).append( + this.checkbox.$element + ) + ) + ); + + this.setDisabled( widget.isDisabled() ); + } + OO.inheritClass( OptionalWidget, OO.ui.Widget ); + OptionalWidget.prototype.onCheckboxChange = function ( checked ) { + this.setDisabled( !checked ); + }; + OptionalWidget.prototype.onOverlayClick = function () { + this.setDisabled( false ); + if ( $.isFunction( this.widget.focus ) ) { + this.widget.focus(); + } + }; + OptionalWidget.prototype.setDisabled = function ( disabled ) { + OptionalWidget[ 'super' ].prototype.setDisabled.call( this, disabled ); + this.widget.setDisabled( this.isDisabled() ); + this.checkbox.setSelected( !this.isDisabled() ); + this.$cover.toggle( this.isDisabled() ); + this.emit( 'change' ); + return this; + }; + + WidgetMethods = { + textInputWidget: { + getApiValue: function () { + return this.getValue(); + }, + setApiValue: function ( v ) { + if ( v === undefined ) { + v = this.paramInfo[ 'default' ]; + } + this.setValue( v ); + }, + apiCheckValid: function () { + var that = this; + return this.getValidity().then( function () { + return $.Deferred().resolve( true ).promise(); + }, function () { + return $.Deferred().resolve( false ).promise(); + } ).done( function ( ok ) { + ok = ok || suppressErrors; + that.setIcon( ok ? null : 'alert' ); + that.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() ); + } ); + } + }, + + dateTimeInputWidget: { + getValidity: function () { + if ( !Util.apiBool( this.paramInfo.required ) || this.getApiValue() !== '' ) { + return $.Deferred().resolve().promise(); + } else { + return $.Deferred().reject().promise(); + } + } + }, + + tokenWidget: { + alertTokenError: function ( code, error ) { + windowManager.openWindow( 'errorAlert', { + title: Util.parseMsg( 'apisandbox-results-fixtoken-fail', this.paramInfo.tokentype ), + message: error, + actions: [ + { + action: 'accept', + label: OO.ui.msg( 'ooui-dialog-process-dismiss' ), + flags: 'primary' + } + ] + } ); + }, + fetchToken: function () { + this.pushPending(); + return api.getToken( this.paramInfo.tokentype ) + .done( this.setApiValue.bind( this ) ) + .fail( this.alertTokenError.bind( this ) ) + .always( this.popPending.bind( this ) ); + }, + setApiValue: function ( v ) { + WidgetMethods.textInputWidget.setApiValue.call( this, v ); + if ( v === '123ABC' ) { + this.fetchToken(); + } + } + }, + + passwordWidget: { + getApiValueForDisplay: function () { + return ''; + } + }, + + toggleSwitchWidget: { + getApiValue: function () { + return this.getValue() ? 1 : undefined; + }, + setApiValue: function ( v ) { + this.setValue( Util.apiBool( v ) ); + }, + apiCheckValid: function () { + return $.Deferred().resolve( true ).promise(); + } + }, + + dropdownWidget: { + getApiValue: function () { + var item = this.getMenu().findSelectedItem(); + return item === null ? undefined : item.getData(); + }, + setApiValue: function ( v ) { + var menu = this.getMenu(); + + if ( v === undefined ) { + v = this.paramInfo[ 'default' ]; + } + if ( v === undefined ) { + menu.selectItem(); + } else { + menu.selectItemByData( String( v ) ); + } + }, + apiCheckValid: function () { + var ok = this.getApiValue() !== undefined || suppressErrors; + this.setIcon( ok ? null : 'alert' ); + this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() ); + return $.Deferred().resolve( ok ).promise(); + } + }, + + tagWidget: { + parseApiValue: function ( v ) { + if ( v === undefined || v === '' || v === '\x1f' ) { + return []; + } else { + v = String( v ); + if ( v[ 0 ] !== '\x1f' ) { + return v.split( '|' ); + } else { + return v.substr( 1 ).split( '\x1f' ); + } + } + }, + getApiValueForTemplates: function () { + return this.isDisabled() ? this.parseApiValue( this.paramInfo[ 'default' ] ) : this.getValue(); + }, + getApiValue: function () { + var items = this.getValue(); + if ( items.join( '' ).indexOf( '|' ) === -1 ) { + return items.join( '|' ); + } else { + return '\x1f' + items.join( '\x1f' ); + } + }, + setApiValue: function ( v ) { + if ( v === undefined ) { + v = this.paramInfo[ 'default' ]; + } + this.setValue( this.parseApiValue( v ) ); + }, + apiCheckValid: function () { + var ok = true, + pi = this.paramInfo; + + if ( !suppressErrors ) { + ok = this.getApiValue() !== undefined && !( + pi.allspecifier !== undefined && + this.getValue().length > 1 && + this.getValue().indexOf( pi.allspecifier ) !== -1 + ); + } + + this.setIcon( ok ? null : 'alert' ); + this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() ); + return $.Deferred().resolve( ok ).promise(); + }, + createTagItemWidget: function ( data, label ) { + var item = OO.ui.TagMultiselectWidget.prototype.createTagItemWidget.call( this, data, label ); + if ( this.paramInfo.deprecatedvalues && + this.paramInfo.deprecatedvalues.indexOf( data ) >= 0 + ) { + item.$element.addClass( 'apihelp-deprecated-value' ); + } + return item; + } + }, + + optionalWidget: { + getApiValue: function () { + return this.isDisabled() ? undefined : this.widget.getApiValue(); + }, + setApiValue: function ( v ) { + this.setDisabled( v === undefined ); + this.widget.setApiValue( v ); + }, + apiCheckValid: function () { + if ( this.isDisabled() ) { + return $.Deferred().resolve( true ).promise(); + } else { + return this.widget.apiCheckValid(); + } + } + }, + + submoduleWidget: { + single: function () { + var v = this.isDisabled() ? this.paramInfo[ 'default' ] : this.getApiValue(); + return v === undefined ? [] : [ { value: v, path: this.paramInfo.submodules[ v ] } ]; + }, + multi: function () { + var map = this.paramInfo.submodules, + v = this.isDisabled() ? this.paramInfo[ 'default' ] : this.getApiValue(); + return v === undefined || v === '' ? [] : String( v ).split( '|' ).map( function ( v ) { + return { value: v, path: map[ v ] }; + } ); + } + }, + + uploadWidget: { + getApiValueForDisplay: function () { + return '...'; + }, + getApiValue: function () { + return this.getValue(); + }, + setApiValue: function () { + // Can't, sorry. + }, + apiCheckValid: function () { + var ok = this.getValue() !== null || suppressErrors; + this.setIcon( ok ? null : 'alert' ); + this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() ); + return $.Deferred().resolve( ok ).promise(); + } + } + }; + + Validators = { + generic: function () { + return !Util.apiBool( this.paramInfo.required ) || this.getApiValue() !== ''; + } + }; + + /** + * @class mw.special.ApiSandbox.Util + * @private + */ + Util = { + /** + * Fetch API module info + * + * @param {string} module Module to fetch data for + * @return {jQuery.Promise} + */ + fetchModuleInfo: function ( module ) { + var apiPromise, + deferred = $.Deferred(); + + if ( moduleInfoCache.hasOwnProperty( module ) ) { + return deferred + .resolve( moduleInfoCache[ module ] ) + .promise( { abort: function () {} } ); + } else { + apiPromise = api.post( { + action: 'paraminfo', + modules: module, + helpformat: 'html', + uselang: mw.config.get( 'wgUserLanguage' ) + } ).done( function ( data ) { + var info; + + if ( data.warnings && data.warnings.paraminfo ) { + deferred.reject( '???', data.warnings.paraminfo[ '*' ] ); + return; + } + + info = data.paraminfo.modules; + if ( !info || info.length !== 1 || info[ 0 ].path !== module ) { + deferred.reject( '???', 'No module data returned' ); + return; + } + + moduleInfoCache[ module ] = info[ 0 ]; + deferred.resolve( info[ 0 ] ); + } ).fail( function ( code, details ) { + if ( code === 'http' ) { + details = 'HTTP error: ' + details.exception; + } else if ( details.error ) { + details = details.error.info; + } + deferred.reject( code, details ); + } ); + return deferred + .promise( { abort: apiPromise.abort } ); + } + }, + + /** + * Mark all currently-in-use tokens as bad + */ + markTokensBad: function () { + var page, subpages, i, + checkPages = [ pages.main ]; + + while ( checkPages.length ) { + page = checkPages.shift(); + + if ( page.tokenWidget ) { + api.badToken( page.tokenWidget.paramInfo.tokentype ); + } + + subpages = page.getSubpages(); + for ( i = 0; i < subpages.length; i++ ) { + if ( pages.hasOwnProperty( subpages[ i ].key ) ) { + checkPages.push( pages[ subpages[ i ].key ] ); + } + } + } + }, + + /** + * Test an API boolean + * + * @param {Mixed} value + * @return {boolean} + */ + apiBool: function ( value ) { + return value !== undefined && value !== false; + }, + + /** + * Create a widget for a parameter. + * + * @param {Object} pi Parameter info from API + * @param {Object} opts Additional options + * @return {OO.ui.Widget} + */ + createWidgetForParameter: function ( pi, opts ) { + var widget, innerWidget, finalWidget, items, $content, func, + multiModeButton = null, + multiModeInput = null, + multiModeAllowed = false; + + opts = opts || {}; + + switch ( pi.type ) { + case 'boolean': + widget = new OO.ui.ToggleSwitchWidget(); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.toggleSwitchWidget ); + pi.required = true; // Avoid wrapping in the non-required widget + break; + + case 'string': + case 'user': + if ( Util.apiBool( pi.multi ) ) { + widget = new OO.ui.TagMultiselectWidget( { + allowArbitrary: true, + allowDuplicates: Util.apiBool( pi.allowsduplicates ), + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.tagWidget ); + } else { + widget = new OO.ui.TextInputWidget( { + required: Util.apiBool( pi.required ) + } ); + } + if ( !Util.apiBool( pi.multi ) ) { + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + widget.setValidation( Validators.generic ); + } + if ( pi.tokentype ) { + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + $.extend( widget, WidgetMethods.tokenWidget ); + } + break; + + case 'text': + widget = new OO.ui.MultilineTextInputWidget( { + required: Util.apiBool( pi.required ) + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + widget.setValidation( Validators.generic ); + break; + + case 'password': + widget = new OO.ui.TextInputWidget( { + type: 'password', + required: Util.apiBool( pi.required ) + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + $.extend( widget, WidgetMethods.passwordWidget ); + widget.setValidation( Validators.generic ); + multiModeAllowed = true; + multiModeInput = widget; + break; + + case 'integer': + widget = new OO.ui.NumberInputWidget( { + required: Util.apiBool( pi.required ), + isInteger: true + } ); + widget.setIcon = widget.input.setIcon.bind( widget.input ); + widget.setIconTitle = widget.input.setIconTitle.bind( widget.input ); + widget.getValidity = widget.input.getValidity.bind( widget.input ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + if ( Util.apiBool( pi.enforcerange ) ) { + widget.setRange( pi.min || -Infinity, pi.max || Infinity ); + } + multiModeAllowed = true; + multiModeInput = widget; + break; + + case 'limit': + widget = new OO.ui.TextInputWidget( { + required: Util.apiBool( pi.required ) + } ); + widget.setValidation( function ( value ) { + var n, pi = this.paramInfo; + + if ( value === 'max' ) { + return true; + } else { + n = +value; + return !isNaN( n ) && isFinite( n ) && + Math.floor( n ) === n && + n >= pi.min && n <= pi.apiSandboxMax; + } + } ); + pi.min = pi.min || 0; + pi.apiSandboxMax = mw.config.get( 'apihighlimits' ) ? pi.highmax : pi.max; + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + multiModeAllowed = true; + multiModeInput = widget; + break; + + case 'timestamp': + widget = new mw.widgets.datetime.DateTimeInputWidget( { + formatter: { + format: '${year|0}-${month|0}-${day|0}T${hour|0}:${minute|0}:${second|0}${zone|short}' + }, + required: Util.apiBool( pi.required ), + clearable: false + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + $.extend( widget, WidgetMethods.dateTimeInputWidget ); + multiModeAllowed = true; + break; + + case 'upload': + widget = new OO.ui.SelectFileWidget(); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.uploadWidget ); + break; + + case 'namespace': + items = $.map( mw.config.get( 'wgFormattedNamespaces' ), function ( name, ns ) { + if ( ns === '0' ) { + name = mw.message( 'blanknamespace' ).text(); + } + return new OO.ui.MenuOptionWidget( { data: ns, label: name } ); + } ).sort( function ( a, b ) { + return a.data - b.data; + } ); + if ( Util.apiBool( pi.multi ) ) { + if ( pi.allspecifier !== undefined ) { + items.unshift( new OO.ui.MenuOptionWidget( { + data: pi.allspecifier, + label: mw.message( 'apisandbox-multivalue-all-namespaces', pi.allspecifier ).text() + } ) ); + } + + widget = new OO.ui.MenuTagMultiselectWidget( { + menu: { items: items }, + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.tagWidget ); + } else { + widget = new OO.ui.DropdownWidget( { + menu: { items: items }, + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.dropdownWidget ); + } + break; + + default: + if ( !Array.isArray( pi.type ) ) { + throw new Error( 'Unknown parameter type ' + pi.type ); + } + + items = pi.type.map( function ( v ) { + var config = { + data: String( v ), + label: String( v ), + classes: [] + }; + if ( pi.deprecatedvalues && pi.deprecatedvalues.indexOf( v ) >= 0 ) { + config.classes.push( 'apihelp-deprecated-value' ); + } + return new OO.ui.MenuOptionWidget( config ); + } ); + if ( Util.apiBool( pi.multi ) ) { + if ( pi.allspecifier !== undefined ) { + items.unshift( new OO.ui.MenuOptionWidget( { + data: pi.allspecifier, + label: mw.message( 'apisandbox-multivalue-all-values', pi.allspecifier ).text() + } ) ); + } + + widget = new OO.ui.MenuTagMultiselectWidget( { + menu: { items: items }, + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.tagWidget ); + if ( Util.apiBool( pi.submodules ) ) { + widget.getSubmodules = WidgetMethods.submoduleWidget.multi; + widget.on( 'change', ApiSandbox.updateUI ); + } + } else { + widget = new OO.ui.DropdownWidget( { + menu: { items: items }, + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.dropdownWidget ); + if ( Util.apiBool( pi.submodules ) ) { + widget.getSubmodules = WidgetMethods.submoduleWidget.single; + widget.getMenu().on( 'select', ApiSandbox.updateUI ); + } + if ( pi.deprecatedvalues ) { + widget.getMenu().on( 'select', function ( item ) { + this.$element.toggleClass( + 'apihelp-deprecated-value', + pi.deprecatedvalues.indexOf( item.data ) >= 0 + ); + }, [], widget ); + } + } + + break; + } + + if ( Util.apiBool( pi.multi ) && multiModeAllowed ) { + innerWidget = widget; + + multiModeButton = new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-add-multi' ).text() + } ); + $content = innerWidget.$element.add( multiModeButton.$element ); + + widget = new OO.ui.PopupTagMultiselectWidget( { + allowArbitrary: true, + allowDuplicates: Util.apiBool( pi.allowsduplicates ), + $overlay: true, + popup: { + classes: [ 'mw-apisandbox-popup' ], + padded: true, + $content: $content + } + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.tagWidget ); + + func = function () { + if ( !innerWidget.isDisabled() ) { + innerWidget.apiCheckValid().done( function ( ok ) { + if ( ok ) { + widget.addTag( innerWidget.getApiValue() ); + innerWidget.setApiValue( undefined ); + } + } ); + return false; + } + }; + + if ( multiModeInput ) { + multiModeInput.on( 'enter', func ); + } + multiModeButton.on( 'click', func ); + } + + if ( Util.apiBool( pi.required ) || opts.nooptional ) { + finalWidget = widget; + } else { + finalWidget = new OptionalWidget( widget ); + finalWidget.paramInfo = pi; + $.extend( finalWidget, WidgetMethods.optionalWidget ); + if ( widget.getSubmodules ) { + finalWidget.getSubmodules = widget.getSubmodules.bind( widget ); + finalWidget.on( 'disable', function () { setTimeout( ApiSandbox.updateUI ); } ); + } + if ( widget.getApiValueForTemplates ) { + finalWidget.getApiValueForTemplates = widget.getApiValueForTemplates.bind( widget ); + } + finalWidget.setDisabled( true ); + } + + widget.setApiValue( pi[ 'default' ] ); + + return finalWidget; + }, + + /** + * Parse an HTML string and call Util.fixupHTML() + * + * @param {string} html HTML to parse + * @return {jQuery} + */ + parseHTML: function ( html ) { + var $ret = $( $.parseHTML( html ) ); + return Util.fixupHTML( $ret ); + }, + + /** + * Parse an i18n message and call Util.fixupHTML() + * + * @param {string} key Key of message to get + * @param {...Mixed} parameters Values for $N replacements + * @return {jQuery} + */ + parseMsg: function () { + var $ret = mw.message.apply( mw.message, arguments ).parseDom(); + return Util.fixupHTML( $ret ); + }, + + /** + * Fix HTML for ApiSandbox display + * + * Fixes are: + * - Add target="_blank" to any links + * + * @param {jQuery} $html DOM to process + * @return {jQuery} + */ + fixupHTML: function ( $html ) { + $html.filter( 'a' ).add( $html.find( 'a' ) ) + .filter( '[href]:not([target])' ) + .attr( 'target', '_blank' ); + return $html; + }, + + /** + * Format a request and return a bunch of menu option widgets + * + * @param {Object} displayParams Query parameters, sanitized for display. + * @param {Object} rawParams Query parameters. You should probably use displayParams instead. + * @return {OO.ui.MenuOptionWidget[]} Each item's data should be an OO.ui.FieldLayout + */ + formatRequest: function ( displayParams, rawParams ) { + var jsonInput, + items = [ + new OO.ui.MenuOptionWidget( { + label: Util.parseMsg( 'apisandbox-request-format-url-label' ), + data: new OO.ui.FieldLayout( + new OO.ui.TextInputWidget( { + readOnly: true, + value: mw.util.wikiScript( 'api' ) + '?' + $.param( displayParams ) + } ), { + label: Util.parseMsg( 'apisandbox-request-url-label' ) + } + ) + } ), + new OO.ui.MenuOptionWidget( { + label: Util.parseMsg( 'apisandbox-request-format-json-label' ), + data: new OO.ui.FieldLayout( + jsonInput = new OO.ui.MultilineTextInputWidget( { + classes: [ 'mw-apisandbox-textInputCode' ], + readOnly: true, + autosize: true, + maxRows: 6, + value: JSON.stringify( displayParams, null, '\t' ) + } ), { + label: Util.parseMsg( 'apisandbox-request-json-label' ) + } + ).on( 'toggle', function ( visible ) { + if ( visible ) { + // Call updatePosition instead of adjustSize + // because the latter has weird caching + // behavior and the former bypasses it. + jsonInput.updatePosition(); + } + } ) + } ) + ]; + + mw.hook( 'apisandbox.formatRequest' ).fire( items, displayParams, rawParams ); + + return items; + }, + + /** + * Event handler for when formatDropdown's selection changes + */ + onFormatDropdownChange: function () { + var i, + menu = formatDropdown.getMenu(), + items = menu.getItems(), + selectedField = menu.findSelectedItem() ? menu.findSelectedItem().getData() : null; + + for ( i = 0; i < items.length; i++ ) { + items[ i ].getData().toggle( items[ i ].getData() === selectedField ); + } + } + }; + + /** + * Interface to ApiSandbox UI + * + * @class mw.special.ApiSandbox + */ + ApiSandbox = { + /** + * Initialize the UI + * + * Automatically called on $.ready() + */ + init: function () { + var $toolbar; + + $content = $( '#mw-apisandbox' ); + + windowManager = new OO.ui.WindowManager(); + $( 'body' ).append( windowManager.$element ); + windowManager.addWindows( { + errorAlert: new OO.ui.MessageDialog() + } ); + + $toolbar = $( '
' ) + .addClass( 'mw-apisandbox-toolbar' ) + .append( + new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-submit' ).text(), + flags: [ 'primary', 'progressive' ] + } ).on( 'click', ApiSandbox.sendRequest ).$element, + new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-reset' ).text(), + flags: 'destructive' + } ).on( 'click', ApiSandbox.resetUI ).$element + ); + + booklet = new OO.ui.BookletLayout( { + expanded: false, + outlined: true, + autoFocus: false + } ); + + panel = new OO.ui.PanelLayout( { + classes: [ 'mw-apisandbox-container' ], + content: [ booklet ], + expanded: false, + framed: true + } ); + + pages.main = new ApiSandbox.PageLayout( { key: 'main', path: 'main' } ); + + // Parse the current hash string + if ( !ApiSandbox.loadFromHash() ) { + ApiSandbox.updateUI(); + } + + $( window ).on( 'hashchange', ApiSandbox.loadFromHash ); + + $content + .empty() + .append( $( '

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

' ).attr( 'id', 'mw-apisandbox-ui' ) + .append( $toolbar ) + .append( panel.$element ) + ); + }, + + /** + * Update the current query when the page hash changes + * + * @return {boolean} Successful + */ + loadFromHash: function () { + var params, m, re, + hash = location.hash; + + if ( oldhash === hash ) { + return false; + } + oldhash = hash; + if ( hash === '' ) { + return false; + } + + // I'm surprised this doesn't seem to exist in jQuery or mw.util. + params = {}; + hash = hash.replace( /\+/g, '%20' ); + re = /([^&=#]+)=?([^&#]*)/g; + while ( ( m = re.exec( hash ) ) ) { + params[ decodeURIComponent( m[ 1 ] ) ] = decodeURIComponent( m[ 2 ] ); + } + + ApiSandbox.updateUI( params ); + return true; + }, + + /** + * Update the pages in the booklet + * + * @param {Object} [params] Optional query parameters to load + */ + updateUI: function ( params ) { + var i, page, subpages, j, removePages, + addPages = []; + + if ( !$.isPlainObject( params ) ) { + params = undefined; + } + + if ( updatingBooklet ) { + return; + } + updatingBooklet = true; + try { + if ( params !== undefined ) { + pages.main.loadQueryParams( params ); + } + addPages.push( pages.main ); + if ( resultPage !== null ) { + addPages.push( resultPage ); + } + pages.main.apiCheckValid(); + + i = 0; + while ( addPages.length ) { + page = addPages.shift(); + if ( bookletPages[ i ] !== page ) { + for ( j = i; j < bookletPages.length; j++ ) { + if ( bookletPages[ j ].getName() === page.getName() ) { + bookletPages.splice( j, 1 ); + } + } + bookletPages.splice( i, 0, page ); + booklet.addPages( [ page ], i ); + } + i++; + + if ( page.getSubpages ) { + subpages = page.getSubpages(); + for ( j = 0; j < subpages.length; j++ ) { + if ( !pages.hasOwnProperty( subpages[ j ].key ) ) { + subpages[ j ].indentLevel = page.indentLevel + 1; + pages[ subpages[ j ].key ] = new ApiSandbox.PageLayout( subpages[ j ] ); + } + if ( params !== undefined ) { + pages[ subpages[ j ].key ].loadQueryParams( params ); + } + addPages.splice( j, 0, pages[ subpages[ j ].key ] ); + pages[ subpages[ j ].key ].apiCheckValid(); + } + } + } + + if ( bookletPages.length > i ) { + removePages = bookletPages.splice( i, bookletPages.length - i ); + booklet.removePages( removePages ); + } + + if ( !booklet.getCurrentPageName() ) { + booklet.selectFirstSelectablePage(); + } + } finally { + updatingBooklet = false; + } + }, + + /** + * Reset button handler + */ + resetUI: function () { + suppressErrors = true; + pages = { + main: new ApiSandbox.PageLayout( { key: 'main', path: 'main' } ) + }; + resultPage = null; + ApiSandbox.updateUI(); + }, + + /** + * Submit button handler + * + * @param {Object} [params] Use this set of params instead of those in the form fields. + * The form fields will be updated to match. + */ + sendRequest: function ( params ) { + var page, subpages, i, query, $result, $focus, + progress, $progressText, progressLoading, + deferreds = [], + paramsAreForced = !!params, + displayParams = {}, + tokenWidgets = [], + checkPages = [ pages.main ]; + + // Blur any focused widget before submit, because + // OO.ui.ButtonWidget doesn't take focus itself (T128054) + $focus = $( '#mw-apisandbox-ui' ).find( document.activeElement ); + if ( $focus.length ) { + $focus[ 0 ].blur(); + } + + suppressErrors = false; + + // save widget state in params (or load from it if we are forced) + if ( paramsAreForced ) { + ApiSandbox.updateUI( params ); + } + params = {}; + while ( checkPages.length ) { + page = checkPages.shift(); + if ( page.tokenWidget ) { + tokenWidgets.push( page.tokenWidget ); + } + deferreds = deferreds.concat( page.apiCheckValid() ); + page.getQueryParams( params, displayParams ); + subpages = page.getSubpages(); + for ( i = 0; i < subpages.length; i++ ) { + if ( pages.hasOwnProperty( subpages[ i ].key ) ) { + checkPages.push( pages[ subpages[ i ].key ] ); + } + } + } + + if ( !paramsAreForced ) { + // forced params means we are continuing a query; the base query should be preserved + baseRequestParams = $.extend( {}, params ); + } + + $.when.apply( $, deferreds ).done( function () { + var formatItems, menu, selectedLabel, deferred, actions, errorCount; + + // Count how many times `value` occurs in `array`. + function countValues( value, array ) { + var count, i; + count = 0; + for ( i = 0; i < array.length; i++ ) { + if ( array[ i ] === value ) { + count++; + } + } + return count; + } + + errorCount = countValues( false, arguments ); + if ( errorCount > 0 ) { + actions = [ + { + action: 'accept', + label: OO.ui.msg( 'ooui-dialog-process-dismiss' ), + flags: 'primary' + } + ]; + if ( tokenWidgets.length ) { + // Check all token widgets' validity separately + deferred = $.when.apply( $, tokenWidgets.map( function ( w ) { + return w.apiCheckValid(); + } ) ); + + deferred.done( function () { + // If only the tokens are invalid, offer to fix them + var tokenErrorCount = countValues( false, arguments ); + if ( tokenErrorCount === errorCount ) { + delete actions[ 0 ].flags; + actions.push( { + action: 'fix', + label: mw.message( 'apisandbox-results-fixtoken' ).text(), + flags: 'primary' + } ); + } + } ); + } else { + deferred = $.Deferred().resolve(); + } + deferred.always( function () { + windowManager.openWindow( 'errorAlert', { + title: Util.parseMsg( 'apisandbox-submit-invalid-fields-title' ), + message: Util.parseMsg( 'apisandbox-submit-invalid-fields-message' ), + actions: actions + } ).closed.then( function ( data ) { + if ( data && data.action === 'fix' ) { + ApiSandbox.fixTokenAndResend(); + } + } ); + } ); + return; + } + + query = $.param( displayParams ); + + formatItems = Util.formatRequest( displayParams, params ); + + // Force a 'fm' format with wrappedhtml=1, if available + if ( params.format !== undefined ) { + if ( availableFormats.hasOwnProperty( params.format + 'fm' ) ) { + params.format = params.format + 'fm'; + } + if ( params.format.substr( -2 ) === 'fm' ) { + params.wrappedhtml = 1; + } + } + + progressLoading = false; + $progressText = $( '' ).text( mw.message( 'apisandbox-sending-request' ).text() ); + progress = new OO.ui.ProgressBarWidget( { + progress: false, + $content: $progressText + } ); + + $result = $( '
' ) + .append( progress.$element ); + + resultPage = page = new OO.ui.PageLayout( '|results|', { expanded: false } ); + page.setupOutlineItem = function () { + this.outlineItem.setLabel( mw.message( 'apisandbox-results' ).text() ); + }; + + if ( !formatDropdown ) { + formatDropdown = new OO.ui.DropdownWidget( { + menu: { items: [] }, + $overlay: true + } ); + formatDropdown.getMenu().on( 'select', Util.onFormatDropdownChange ); + } + + menu = formatDropdown.getMenu(); + selectedLabel = menu.findSelectedItem() ? menu.findSelectedItem().getLabel() : ''; + if ( typeof selectedLabel !== 'string' ) { + selectedLabel = selectedLabel.text(); + } + menu.clearItems().addItems( formatItems ); + menu.chooseItem( menu.getItemFromLabel( selectedLabel ) || menu.findFirstSelectableItem() ); + + // Fire the event to update field visibilities + Util.onFormatDropdownChange(); + + page.$element.empty() + .append( + new OO.ui.FieldLayout( + formatDropdown, { + label: Util.parseMsg( 'apisandbox-request-selectformat-label' ) + } + ).$element, + formatItems.map( function ( item ) { + return item.getData().$element; + } ), + $result + ); + ApiSandbox.updateUI(); + booklet.setPage( '|results|' ); + + location.href = oldhash = '#' + query; + + api.post( params, { + contentType: 'multipart/form-data', + dataType: 'text', + xhr: function () { + var xhr = new window.XMLHttpRequest(); + xhr.upload.addEventListener( 'progress', function ( e ) { + if ( !progressLoading ) { + if ( e.lengthComputable ) { + progress.setProgress( e.loaded * 100 / e.total ); + } else { + progress.setProgress( false ); + } + } + } ); + xhr.addEventListener( 'progress', function ( e ) { + if ( !progressLoading ) { + progressLoading = true; + $progressText.text( mw.message( 'apisandbox-loading-results' ).text() ); + } + if ( e.lengthComputable ) { + progress.setProgress( e.loaded * 100 / e.total ); + } else { + progress.setProgress( false ); + } + } ); + return xhr; + } + } ) + .catch( function ( code, data, result, jqXHR ) { + var deferred = $.Deferred(); + + if ( code !== 'http' ) { + // Not really an error, work around mw.Api thinking it is. + deferred.resolve( result, jqXHR ); + } else { + // Just forward it. + deferred.reject.apply( deferred, arguments ); + } + return deferred.promise(); + } ) + .then( function ( data, jqXHR ) { + var m, loadTime, button, clear, + ct = jqXHR.getResponseHeader( 'Content-Type' ), + loginSuppressed = jqXHR.getResponseHeader( 'MediaWiki-Login-Suppressed' ) || 'false'; + + $result.empty(); + if ( loginSuppressed !== 'false' ) { + $( '
' ) + .addClass( 'warning' ) + .append( Util.parseMsg( 'apisandbox-results-login-suppressed' ) ) + .appendTo( $result ); + } + if ( /^text\/mediawiki-api-prettyprint-wrapped(?:;|$)/.test( ct ) ) { + data = JSON.parse( data ); + if ( data.modules.length ) { + mw.loader.load( data.modules ); + } + if ( data.status && data.status !== 200 ) { + $( '
' ) + .addClass( 'api-pretty-header api-pretty-status' ) + .append( Util.parseMsg( 'api-format-prettyprint-status', data.status, data.statustext ) ) + .appendTo( $result ); + } + $result.append( Util.parseHTML( data.html ) ); + loadTime = data.time; + } else if ( ( m = data.match( /][\s\S]*<\/pre>/ ) ) ) { + $result.append( Util.parseHTML( m[ 0 ] ) ); + if ( ( m = data.match( /"wgBackendResponseTime":\s*(\d+)/ ) ) ) { + loadTime = parseInt( m[ 1 ], 10 ); + } + } else { + $( '
' )
+								.addClass( 'api-pretty-content' )
+								.text( data )
+								.appendTo( $result );
+						}
+						if ( paramsAreForced || data[ 'continue' ] ) {
+							$result.append(
+								$( '
' ).append( + new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-continue' ).text() + } ).on( 'click', function () { + ApiSandbox.sendRequest( $.extend( {}, baseRequestParams, data[ 'continue' ] ) ); + } ).setDisabled( !data[ 'continue' ] ).$element, + ( clear = new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-continue-clear' ).text() + } ).on( 'click', function () { + ApiSandbox.updateUI( baseRequestParams ); + clear.setDisabled( true ); + booklet.setPage( '|results|' ); + } ).setDisabled( !paramsAreForced ) ).$element, + new OO.ui.PopupButtonWidget( { + $overlay: true, + framed: false, + icon: 'info', + popup: { + $content: $( '
' ).append( Util.parseMsg( 'apisandbox-continue-help' ) ), + padded: true, + width: 'auto' + } + } ).$element + ) + ); + } + if ( typeof loadTime === 'number' ) { + $result.append( + $( '
' ).append( + new OO.ui.LabelWidget( { + label: mw.message( 'apisandbox-request-time', loadTime ).text() + } ).$element + ) + ); + } + + if ( jqXHR.getResponseHeader( 'MediaWiki-API-Error' ) === 'badtoken' ) { + // Flush all saved tokens in case one of them is the bad one. + Util.markTokensBad(); + button = new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-results-fixtoken' ).text() + } ); + button.on( 'click', ApiSandbox.fixTokenAndResend ) + .on( 'click', button.setDisabled, [ true ], button ) + .$element.appendTo( $result ); + } + }, function ( code, data ) { + var details = 'HTTP error: ' + data.exception; + $result.empty() + .append( + new OO.ui.LabelWidget( { + label: mw.message( 'apisandbox-results-error', details ).text(), + classes: [ 'error' ] + } ).$element + ); + } ); + } ); + }, + + /** + * Handler for the "Correct token and resubmit" button + * + * Used on a 'badtoken' error, it re-fetches token parameters for all + * pages and then re-submits the query. + */ + fixTokenAndResend: function () { + var page, subpages, i, k, + ok = true, + tokenWait = { dummy: true }, + checkPages = [ pages.main ], + success = function ( k ) { + delete tokenWait[ k ]; + if ( ok && $.isEmptyObject( tokenWait ) ) { + ApiSandbox.sendRequest(); + } + }, + failure = function ( k ) { + delete tokenWait[ k ]; + ok = false; + }; + + while ( checkPages.length ) { + page = checkPages.shift(); + + if ( page.tokenWidget ) { + k = page.apiModule + page.tokenWidget.paramInfo.name; + tokenWait[ k ] = page.tokenWidget.fetchToken(); + tokenWait[ k ] + .done( success.bind( page.tokenWidget, k ) ) + .fail( failure.bind( page.tokenWidget, k ) ); + } + + subpages = page.getSubpages(); + for ( i = 0; i < subpages.length; i++ ) { + if ( pages.hasOwnProperty( subpages[ i ].key ) ) { + checkPages.push( pages[ subpages[ i ].key ] ); + } + } + } + + success( 'dummy', '' ); + }, + + /** + * Reset validity indicators for all widgets + */ + updateValidityIndicators: function () { + var page, subpages, i, + checkPages = [ pages.main ]; + + while ( checkPages.length ) { + page = checkPages.shift(); + page.apiCheckValid(); + subpages = page.getSubpages(); + for ( i = 0; i < subpages.length; i++ ) { + if ( pages.hasOwnProperty( subpages[ i ].key ) ) { + checkPages.push( pages[ subpages[ i ].key ] ); + } + } + } + } + }; + + /** + * PageLayout for API modules + * + * @class + * @private + * @extends OO.ui.PageLayout + * @constructor + * @param {Object} [config] Configuration options + */ + ApiSandbox.PageLayout = function ( config ) { + config = $.extend( { prefix: '', expanded: false }, config ); + this.displayText = config.key; + this.apiModule = config.path; + this.prefix = config.prefix; + this.paramInfo = null; + this.apiIsValid = true; + this.loadFromQueryParams = null; + this.widgets = {}; + this.itemsFieldset = null; + this.deprecatedItemsFieldset = null; + this.templatedItemsCache = {}; + this.tokenWidget = null; + this.indentLevel = config.indentLevel ? config.indentLevel : 0; + ApiSandbox.PageLayout[ 'super' ].call( this, config.key, config ); + this.loadParamInfo(); + }; + OO.inheritClass( ApiSandbox.PageLayout, OO.ui.PageLayout ); + ApiSandbox.PageLayout.prototype.setupOutlineItem = function () { + this.outlineItem.setLevel( this.indentLevel ); + this.outlineItem.setLabel( this.displayText ); + this.outlineItem.setIcon( this.apiIsValid || suppressErrors ? null : 'alert' ); + this.outlineItem.setIconTitle( + this.apiIsValid || suppressErrors ? '' : mw.message( 'apisandbox-alert-page' ).plain() + ); + }; + + function widgetLabelOnClick() { + var f = this.getField(); + if ( $.isFunction( f.setDisabled ) ) { + f.setDisabled( false ); + } + if ( $.isFunction( f.focus ) ) { + f.focus(); + } + } + + /** + * Create a widget and the FieldLayouts it needs + * @private + * @param {Object} ppi API paraminfo data for the parameter + * @param {string} name API parameter name + * @return {Object} + * @return {OO.ui.Widget} return.widget + * @return {OO.ui.FieldLayout} return.widgetField + * @return {OO.ui.FieldLayout} return.helpField + */ + ApiSandbox.PageLayout.prototype.makeWidgetFieldLayouts = function ( ppi, name ) { + var j, l, widget, descriptionContainer, tmp, flag, count, button, widgetField, helpField, layoutConfig; + + widget = Util.createWidgetForParameter( ppi ); + if ( ppi.tokentype ) { + this.tokenWidget = widget; + } + if ( this.paramInfo.templatedparameters.length ) { + widget.on( 'change', this.updateTemplatedParameters, [ null ], this ); + } + + descriptionContainer = $( '
' ); + + tmp = Util.parseHTML( ppi.description ); + tmp.filter( 'dl' ).makeCollapsible( { + collapsed: true + } ).children( '.mw-collapsible-toggle' ).each( function () { + var $this = $( this ); + $this.parent().prev( 'p' ).append( $this ); + } ); + descriptionContainer.append( $( '
' ).addClass( 'description' ).append( tmp ) ); + + if ( ppi.info && ppi.info.length ) { + for ( j = 0; j < ppi.info.length; j++ ) { + descriptionContainer.append( $( '
' ) + .addClass( 'info' ) + .append( Util.parseHTML( ppi.info[ j ] ) ) + ); + } + } + flag = true; + count = Infinity; + switch ( ppi.type ) { + case 'namespace': + flag = false; + count = mw.config.get( 'wgFormattedNamespaces' ).length; + break; + + case 'limit': + if ( ppi.highmax !== undefined ) { + descriptionContainer.append( $( '
' ) + .addClass( 'info' ) + .append( + Util.parseMsg( + 'api-help-param-limit2', ppi.max, ppi.highmax + ), + ' ', + Util.parseMsg( 'apisandbox-param-limit' ) + ) + ); + } else { + descriptionContainer.append( $( '
' ) + .addClass( 'info' ) + .append( + Util.parseMsg( 'api-help-param-limit', ppi.max ), + ' ', + Util.parseMsg( 'apisandbox-param-limit' ) + ) + ); + } + break; + + case 'integer': + tmp = ''; + if ( ppi.min !== undefined ) { + tmp += 'min'; + } + if ( ppi.max !== undefined ) { + tmp += 'max'; + } + if ( tmp !== '' ) { + descriptionContainer.append( $( '
' ) + .addClass( 'info' ) + .append( Util.parseMsg( + 'api-help-param-integer-' + tmp, + Util.apiBool( ppi.multi ) ? 2 : 1, + ppi.min, ppi.max + ) ) + ); + } + break; + + default: + if ( Array.isArray( ppi.type ) ) { + flag = false; + count = ppi.type.length; + } + break; + } + if ( Util.apiBool( ppi.multi ) ) { + tmp = []; + if ( flag && !( widget instanceof OO.ui.TagMultiselectWidget ) && + !( + widget instanceof OptionalWidget && + widget.widget instanceof OO.ui.TagMultiselectWidget + ) + ) { + tmp.push( mw.message( 'api-help-param-multi-separate' ).parse() ); + } + if ( count > ppi.lowlimit ) { + tmp.push( + mw.message( 'api-help-param-multi-max', ppi.lowlimit, ppi.highlimit ).parse() + ); + } + if ( tmp.length ) { + descriptionContainer.append( $( '
' ) + .addClass( 'info' ) + .append( Util.parseHTML( tmp.join( ' ' ) ) ) + ); + } + } + if ( 'maxbytes' in ppi ) { + descriptionContainer.append( $( '
' ) + .addClass( 'info' ) + .append( Util.parseMsg( 'api-help-param-maxbytes', ppi.maxbytes ) ) + ); + } + if ( 'maxchars' in ppi ) { + descriptionContainer.append( $( '
' ) + .addClass( 'info' ) + .append( Util.parseMsg( 'api-help-param-maxchars', ppi.maxchars ) ) + ); + } + if ( ppi.usedTemplateVars && ppi.usedTemplateVars.length ) { + tmp = $(); + for ( j = 0, l = ppi.usedTemplateVars.length; j < l; j++ ) { + tmp = tmp.add( $( '' ).text( ppi.usedTemplateVars[ j ] ) ); + if ( j === l - 2 ) { + tmp = tmp.add( mw.message( 'and' ).parseDom() ); + tmp = tmp.add( mw.message( 'word-separator' ).parseDom() ); + } else if ( j !== l - 1 ) { + tmp = tmp.add( mw.message( 'comma-separator' ).parseDom() ); + } + } + descriptionContainer.append( $( '
' ) + .addClass( 'info' ) + .append( Util.parseMsg( + 'apisandbox-templated-parameter-reason', + ppi.usedTemplateVars.length, + tmp + ) ) + ); + } + + helpField = new OO.ui.FieldLayout( + new OO.ui.Widget( { + $content: '\xa0', + classes: [ 'mw-apisandbox-spacer' ] + } ), { + align: 'inline', + classes: [ 'mw-apisandbox-help-field' ], + label: descriptionContainer + } + ); + + layoutConfig = { + align: 'left', + classes: [ 'mw-apisandbox-widget-field' ], + label: name + }; + + if ( ppi.tokentype ) { + button = new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-fetch-token' ).text() + } ); + button.on( 'click', widget.fetchToken, [], widget ); + + widgetField = new OO.ui.ActionFieldLayout( widget, button, layoutConfig ); + } else { + widgetField = new OO.ui.FieldLayout( widget, layoutConfig ); + } + + // We need our own click handler on the widget label to + // turn off the disablement. + widgetField.$label.on( 'click', widgetLabelOnClick.bind( widgetField ) ); + + // Don't grey out the label when the field is disabled, + // it makes it too hard to read and our "disabled" + // isn't really disabled. + widgetField.onFieldDisable( false ); + widgetField.onFieldDisable = $.noop; + + widgetField.apiParamIndex = ppi.index; + + return { + widget: widget, + widgetField: widgetField, + helpField: helpField + }; + }; + + /** + * Update templated parameters in the page + * @private + * @param {Object} [params] Query parameters for initializing the widgets + */ + ApiSandbox.PageLayout.prototype.updateTemplatedParameters = function ( params ) { + var p, toProcess, doProcess, tmp, toRemove, + that = this, + pi = this.paramInfo, + prefix = that.prefix + pi.prefix; + + if ( !pi || !pi.templatedparameters.length ) { + return; + } + + if ( !$.isPlainObject( params ) ) { + params = null; + } + + toRemove = {}; + $.each( this.templatedItemsCache, function ( k, el ) { + if ( el.widget.isElementAttached() ) { + toRemove[ k ] = el; + } + } ); + + // This bit duplicates the PHP logic in ApiBase::extractRequestParams(). + // If you update this, see if that needs updating too. + toProcess = pi.templatedparameters.map( function ( p ) { + return { + name: prefix + p.name, + info: p, + vars: $.extend( {}, p.templatevars ), + usedVars: [] + }; + } ); + doProcess = function ( placeholder, target ) { + var values, container, index, usedVars, done; + + target = prefix + target; + + if ( !that.widgets[ target ] ) { + // The target wasn't processed yet, try the next one. + // If all hit this case, the parameter has no expansions. + return true; + } + + if ( !that.widgets[ target ].getApiValueForTemplates ) { + // Not a multi-valued widget, so it can't have expansions. + return false; + } + + values = that.widgets[ target ].getApiValueForTemplates(); + if ( !Array.isArray( values ) || !values.length ) { + // The target was processed but has no (valid) values. + // That means it has no expansions. + return false; + } + + // Expand this target in the name and all other targets, + // then requeue if there are more targets left or create the widget + // and add it to the form if all are done. + delete p.vars[ placeholder ]; + usedVars = p.usedVars.concat( [ target ] ); + placeholder = '{' + placeholder + '}'; + done = $.isEmptyObject( p.vars ); + if ( done ) { + container = Util.apiBool( p.info.deprecated ) ? that.deprecatedItemsFieldset : that.itemsFieldset; + index = container.getItems().findIndex( function ( el ) { + return el.apiParamIndex !== undefined && el.apiParamIndex > p.info.index; + } ); + if ( index < 0 ) { + index = undefined; + } + } + values.forEach( function ( value ) { + var name, newVars; + + if ( !/^[^{}]*$/.exec( value ) ) { + // Skip values that make invalid parameter names + return; + } + + name = p.name.replace( placeholder, value ); + if ( done ) { + if ( that.templatedItemsCache[ name ] ) { + tmp = that.templatedItemsCache[ name ]; + } else { + tmp = that.makeWidgetFieldLayouts( + $.extend( {}, p.info, { usedTemplateVars: usedVars } ), name + ); + that.templatedItemsCache[ name ] = tmp; + } + delete toRemove[ name ]; + if ( !tmp.widget.isElementAttached() ) { + that.widgets[ name ] = tmp.widget; + container.addItems( [ tmp.widgetField, tmp.helpField ], index ); + if ( index !== undefined ) { + index += 2; + } + } + if ( params ) { + tmp.widget.setApiValue( params.hasOwnProperty( name ) ? params[ name ] : undefined ); + } + } else { + newVars = {}; + $.each( p.vars, function ( k, v ) { + newVars[ k ] = v.replace( placeholder, value ); + } ); + toProcess.push( { + name: name, + info: p.info, + vars: newVars, + usedVars: usedVars + } ); + } + } ); + return false; + }; + while ( toProcess.length ) { + p = toProcess.shift(); + $.each( p.vars, doProcess ); + } + + toRemove = $.map( toRemove, function ( el, name ) { + delete that.widgets[ name ]; + return [ el.widgetField, el.helpField ]; + } ); + if ( toRemove.length ) { + this.itemsFieldset.removeItems( toRemove ); + this.deprecatedItemsFieldset.removeItems( toRemove ); + } + }; + + /** + * Fetch module information for this page's module, then create UI + */ + ApiSandbox.PageLayout.prototype.loadParamInfo = function () { + var dynamicFieldset, dynamicParamNameWidget, + that = this, + removeDynamicParamWidget = function ( name, layout ) { + dynamicFieldset.removeItems( [ layout ] ); + delete that.widgets[ name ]; + }, + addDynamicParamWidget = function () { + var name, layout, widget, button; + + // Check name is filled in + name = dynamicParamNameWidget.getValue().trim(); + if ( name === '' ) { + dynamicParamNameWidget.focus(); + return; + } + + if ( that.widgets[ name ] !== undefined ) { + windowManager.openWindow( 'errorAlert', { + title: Util.parseMsg( 'apisandbox-dynamic-error-exists', name ), + actions: [ + { + action: 'accept', + label: OO.ui.msg( 'ooui-dialog-process-dismiss' ), + flags: 'primary' + } + ] + } ); + return; + } + + widget = Util.createWidgetForParameter( { + name: name, + type: 'string', + 'default': '' + }, { + nooptional: true + } ); + button = new OO.ui.ButtonWidget( { + icon: 'trash', + flags: 'destructive' + } ); + layout = new OO.ui.ActionFieldLayout( + widget, + button, + { + label: name, + align: 'left' + } + ); + button.on( 'click', removeDynamicParamWidget, [ name, layout ] ); + that.widgets[ name ] = widget; + dynamicFieldset.addItems( [ layout ], dynamicFieldset.getItems().length - 1 ); + widget.focus(); + + dynamicParamNameWidget.setValue( '' ); + }; + + this.$element.empty() + .append( new OO.ui.ProgressBarWidget( { + progress: false, + text: mw.message( 'apisandbox-loading', this.displayText ).text() + } ).$element ); + + Util.fetchModuleInfo( this.apiModule ) + .done( function ( pi ) { + var prefix, i, j, tmp, + items = [], + deprecatedItems = [], + buttons = [], + filterFmModules = function ( v ) { + return v.substr( -2 ) !== 'fm' || + !availableFormats.hasOwnProperty( v.substr( 0, v.length - 2 ) ); + }; + + // This is something of a hack. We always want the 'format' and + // 'action' parameters from the main module to be specified, + // and for 'format' we also want to simplify the dropdown since + // we always send the 'fm' variant. + if ( that.apiModule === 'main' ) { + for ( i = 0; i < pi.parameters.length; i++ ) { + if ( pi.parameters[ i ].name === 'action' ) { + pi.parameters[ i ].required = true; + delete pi.parameters[ i ][ 'default' ]; + } + if ( pi.parameters[ i ].name === 'format' ) { + tmp = pi.parameters[ i ].type; + for ( j = 0; j < tmp.length; j++ ) { + availableFormats[ tmp[ j ] ] = true; + } + pi.parameters[ i ].type = tmp.filter( filterFmModules ); + pi.parameters[ i ][ 'default' ] = 'json'; + pi.parameters[ i ].required = true; + } + } + } + + // Hide the 'wrappedhtml' parameter on format modules + if ( pi.group === 'format' ) { + pi.parameters = pi.parameters.filter( function ( p ) { + return p.name !== 'wrappedhtml'; + } ); + } + + that.paramInfo = pi; + + items.push( new OO.ui.FieldLayout( + new OO.ui.Widget( {} ).toggle( false ), { + align: 'top', + label: Util.parseHTML( pi.description ) + } + ) ); + + if ( pi.helpurls.length ) { + buttons.push( new OO.ui.PopupButtonWidget( { + $overlay: true, + label: mw.message( 'apisandbox-helpurls' ).text(), + icon: 'help', + popup: { + width: 'auto', + padded: true, + $content: $( '