Merge "Increase Opera minimum for Grades A and C to 15"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 29 Nov 2017 20:54:00 +0000 (20:54 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 29 Nov 2017 20:54:00 +0000 (20:54 +0000)
198 files changed:
autoload.php
composer.json
includes/DefaultSettings.php
includes/GitInfo.php
includes/ServiceWiring.php
includes/api/i18n/mk.json
includes/api/i18n/sv.json
includes/changes/ChangesFeed.php
includes/installer/PostgresUpdater.php
includes/jobqueue/jobs/ClearUserWatchlistJob.php [new file with mode: 0644]
includes/libs/filebackend/SwiftFileBackend.php
includes/libs/mime/mime.info
includes/libs/mime/mime.types
includes/libs/objectcache/WANObjectCache.php
includes/logging/LogPager.php
includes/shell/Command.php
includes/shell/CommandFactory.php
includes/shell/FirejailCommand.php [new file with mode: 0644]
includes/shell/Shell.php
includes/shell/firejail.profile [new file with mode: 0644]
includes/watcheditem/WatchedItemStore.php
languages/i18n/ar.json
languages/i18n/be-tarask.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/hr.json
languages/i18n/hy.json
languages/i18n/id.json
languages/i18n/lb.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/mwl.json
languages/i18n/my.json
languages/i18n/pt-br.json
languages/i18n/qqq.json
languages/i18n/ru.json
languages/i18n/sat.json
languages/i18n/sq.json
languages/messages/MessagesAr.php
languages/messages/MessagesArz.php
languages/messages/MessagesCkb.php
languages/messages/MessagesDe.php
languages/messages/MessagesFa.php
languages/messages/MessagesKu_arab.php
languages/messages/MessagesLzh.php
maintenance/populateIpChanges.php
maintenance/postgres/archives/patch-ip_changes.sql [new file with mode: 0644]
maintenance/refreshFileHeaders.php
resources/Resources.php
resources/lib/moment/LICENSE
resources/lib/moment/README.md [new file with mode: 0644]
resources/lib/moment/locale/af.js
resources/lib/moment/locale/ar-ma.js
resources/lib/moment/locale/ar-sa.js
resources/lib/moment/locale/ar-tn.js
resources/lib/moment/locale/ar.js
resources/lib/moment/locale/az.js
resources/lib/moment/locale/be.js
resources/lib/moment/locale/bg.js
resources/lib/moment/locale/bm.js [new file with mode: 0644]
resources/lib/moment/locale/bn.js
resources/lib/moment/locale/bo.js
resources/lib/moment/locale/br.js
resources/lib/moment/locale/bs.js
resources/lib/moment/locale/ca.js
resources/lib/moment/locale/cs.js
resources/lib/moment/locale/cv.js
resources/lib/moment/locale/cy.js
resources/lib/moment/locale/da.js
resources/lib/moment/locale/de-at.js
resources/lib/moment/locale/de-ch.js [new file with mode: 0644]
resources/lib/moment/locale/de.js
resources/lib/moment/locale/dv.js
resources/lib/moment/locale/el.js
resources/lib/moment/locale/en-au.js
resources/lib/moment/locale/en-ca.js
resources/lib/moment/locale/en-gb.js
resources/lib/moment/locale/eo.js
resources/lib/moment/locale/es.js
resources/lib/moment/locale/et.js
resources/lib/moment/locale/eu.js
resources/lib/moment/locale/fa.js
resources/lib/moment/locale/fi.js
resources/lib/moment/locale/fo.js
resources/lib/moment/locale/fr-ca.js
resources/lib/moment/locale/fr.js
resources/lib/moment/locale/fy.js
resources/lib/moment/locale/gd.js
resources/lib/moment/locale/gl.js
resources/lib/moment/locale/gom-latn.js [new file with mode: 0644]
resources/lib/moment/locale/gu.js [new file with mode: 0644]
resources/lib/moment/locale/he.js
resources/lib/moment/locale/hi.js
resources/lib/moment/locale/hr.js
resources/lib/moment/locale/hu.js
resources/lib/moment/locale/hy-am.js
resources/lib/moment/locale/id.js
resources/lib/moment/locale/is.js
resources/lib/moment/locale/it.js
resources/lib/moment/locale/ja.js
resources/lib/moment/locale/jv.js
resources/lib/moment/locale/ka.js
resources/lib/moment/locale/kk.js
resources/lib/moment/locale/km.js
resources/lib/moment/locale/kn.js [new file with mode: 0644]
resources/lib/moment/locale/ko.js
resources/lib/moment/locale/ky.js
resources/lib/moment/locale/lb.js
resources/lib/moment/locale/lo.js
resources/lib/moment/locale/lt.js
resources/lib/moment/locale/lv.js
resources/lib/moment/locale/mi.js
resources/lib/moment/locale/mk.js
resources/lib/moment/locale/ml.js
resources/lib/moment/locale/mr.js
resources/lib/moment/locale/ms-my.js
resources/lib/moment/locale/ms.js
resources/lib/moment/locale/my.js
resources/lib/moment/locale/nb.js
resources/lib/moment/locale/ne.js
resources/lib/moment/locale/nl.js
resources/lib/moment/locale/nn.js
resources/lib/moment/locale/pa-in.js
resources/lib/moment/locale/pl.js
resources/lib/moment/locale/pt-br.js
resources/lib/moment/locale/pt.js
resources/lib/moment/locale/ro.js
resources/lib/moment/locale/ru.js
resources/lib/moment/locale/sd.js [new file with mode: 0644]
resources/lib/moment/locale/se.js
resources/lib/moment/locale/si.js
resources/lib/moment/locale/sk.js
resources/lib/moment/locale/sl.js
resources/lib/moment/locale/sq.js
resources/lib/moment/locale/sr-cyrl.js
resources/lib/moment/locale/sr.js
resources/lib/moment/locale/ss.js
resources/lib/moment/locale/sv.js
resources/lib/moment/locale/sw.js
resources/lib/moment/locale/ta.js
resources/lib/moment/locale/te.js
resources/lib/moment/locale/tet.js [new file with mode: 0644]
resources/lib/moment/locale/th.js
resources/lib/moment/locale/tl-ph.js
resources/lib/moment/locale/tr.js
resources/lib/moment/locale/tzm-latn.js
resources/lib/moment/locale/tzm.js
resources/lib/moment/locale/uk.js
resources/lib/moment/locale/ur.js [new file with mode: 0644]
resources/lib/moment/locale/uz-latn.js [new file with mode: 0644]
resources/lib/moment/locale/uz.js
resources/lib/moment/locale/vi.js
resources/lib/moment/locale/x-pseudo.js [deleted file]
resources/lib/moment/locale/yo.js [new file with mode: 0644]
resources/lib/moment/locale/zh-cn.js
resources/lib/moment/locale/zh-hk.js
resources/lib/moment/locale/zh-tw.js
resources/lib/moment/moment.js
resources/lib/oojs-ui/i18n/lv.json
resources/lib/oojs-ui/i18n/sl.json
resources/lib/oojs-ui/i18n/sr-ec.json
resources/lib/oojs-ui/i18n/sr-el.json
resources/lib/oojs-ui/i18n/ur.json
resources/lib/oojs-ui/oojs-ui-apex.js
resources/lib/oojs-ui/oojs-ui-core-apex.css
resources/lib/oojs-ui/oojs-ui-core-wikimediaui.css
resources/lib/oojs-ui/oojs-ui-core.js
resources/lib/oojs-ui/oojs-ui-core.js.map
resources/lib/oojs-ui/oojs-ui-toolbars-apex.css
resources/lib/oojs-ui/oojs-ui-toolbars-wikimediaui.css
resources/lib/oojs-ui/oojs-ui-toolbars.js
resources/lib/oojs-ui/oojs-ui-toolbars.js.map
resources/lib/oojs-ui/oojs-ui-widgets-apex.css
resources/lib/oojs-ui/oojs-ui-widgets-wikimediaui.css
resources/lib/oojs-ui/oojs-ui-widgets.js
resources/lib/oojs-ui/oojs-ui-widgets.js.map
resources/lib/oojs-ui/oojs-ui-wikimediaui.js
resources/lib/oojs-ui/oojs-ui-windows-apex.css
resources/lib/oojs-ui/oojs-ui-windows-wikimediaui.css
resources/lib/oojs-ui/oojs-ui-windows.js
resources/lib/oojs-ui/wikimedia-ui-base.less
resources/src/mediawiki.rcfilters/mw.rcfilters.js
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.LiveUpdateButtonWidget.less
resources/src/mediawiki.special/mediawiki.special.apisandbox.js
resources/src/mediawiki.special/mediawiki.special.preferences.styles.css
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
resources/src/mediawiki/htmlform/ooui.styles.less
resources/src/mediawiki/mediawiki.debug.js
resources/src/mediawiki/mediawiki.notification.css
tests/phpunit/includes/filebackend/SwiftFileBackendTest.php
tests/phpunit/includes/jobqueue/jobs/ClearUserWatchlistJobTest.php [new file with mode: 0644]
tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php
tests/phpunit/includes/shell/CommandFactoryTest.php
tests/phpunit/includes/shell/FirejailCommandTest.php [new file with mode: 0644]
tests/selenium/.eslintrc.json
tests/selenium/README.md

index 5a2156a..51daced 100644 (file)
@@ -265,6 +265,7 @@ $wgAutoloadLocalClasses = [
        'CleanupRemovedModules' => __DIR__ . '/maintenance/cleanupRemovedModules.php',
        'CleanupSpam' => __DIR__ . '/maintenance/cleanupSpam.php',
        'ClearInterwikiCache' => __DIR__ . '/maintenance/clearInterwikiCache.php',
+       'ClearUserWatchlistJob' => __DIR__ . '/includes/jobqueue/jobs/ClearUserWatchlistJob.php',
        'CliInstaller' => __DIR__ . '/includes/installer/CliInstaller.php',
        'CloneDatabase' => __DIR__ . '/includes/db/CloneDatabase.php',
        'CodeCleanerGlobalsPass' => __DIR__ . '/maintenance/CodeCleanerGlobalsPass.inc',
@@ -939,6 +940,7 @@ $wgAutoloadLocalClasses = [
        'MediaWiki\\ShellDisabledError' => __DIR__ . '/includes/exception/ShellDisabledError.php',
        'MediaWiki\\Shell\\Command' => __DIR__ . '/includes/shell/Command.php',
        'MediaWiki\\Shell\\CommandFactory' => __DIR__ . '/includes/shell/CommandFactory.php',
+       'MediaWiki\\Shell\\FirejailCommand' => __DIR__ . '/includes/shell/FirejailCommand.php',
        'MediaWiki\\Shell\\Result' => __DIR__ . '/includes/shell/Result.php',
        'MediaWiki\\Shell\\Shell' => __DIR__ . '/includes/shell/Shell.php',
        'MediaWiki\\Site\\MediaWikiPageNameNormalizer' => __DIR__ . '/includes/site/MediaWikiPageNameNormalizer.php',
index a5501d0..35783f2 100644 (file)
@@ -25,7 +25,7 @@
                "ext-xml": "*",
                "liuggio/statsd-php-client": "1.0.18",
                "mediawiki/at-ease": "1.1.0",
-               "oojs/oojs-ui": "0.24.2",
+               "oojs/oojs-ui": "0.24.3",
                "oyejorge/less.php": "1.7.0.14",
                "php": ">=5.5.9",
                "psr/log": "1.0.2",
index 3cd7ef1..dcbcb6e 100644 (file)
@@ -2554,6 +2554,8 @@ $wgGitInfoCacheDirectory = false;
  * It should be appended in the query string of static CSS and JS includes,
  * to ensure that client-side caches do not keep obsolete copies of global
  * styles.
+ *
+ * @deprecated since 1.31
  */
 $wgStyleVersion = '303';
 
@@ -4881,7 +4883,6 @@ $wgDefaultUserOptions = [
        'hidepatrolled' => 0,
        'hidecategorization' => 1,
        'imagesize' => 2,
-       'math' => 1,
        'minordefault' => 0,
        'newpageshidepatrolled' => 0,
        'nickname' => '',
@@ -7428,6 +7429,7 @@ $wgJobClasses = [
        'refreshLinksDynamic' => 'RefreshLinksJob',
        'activityUpdateJob' => 'ActivityUpdateJob',
        'categoryMembershipChange' => 'CategoryMembershipChangeJob',
+       'clearUserWatchlist' => 'ClearUserWatchlistJob',
        'cdnPurge' => 'CdnPurgeJob',
        'enqueue' => 'EnqueueJob', // local queue for multi-DC setups
        'null' => 'NullJob'
@@ -8270,6 +8272,22 @@ $wgPhpCli = '/usr/bin/php';
  */
 $wgShellLocale = 'C.UTF-8';
 
+/**
+ * Method to use to restrict shell commands
+ *
+ * Supported options:
+ * - 'autodetect': Autodetect if any restriction methods are available
+ * - 'firejail': Use firejail <https://firejail.wordpress.com/>
+ * - false: Don't use any restrictions
+ *
+ * @note If using firejail with MediaWiki running in a home directory different
+ *  from the webserver user, firejail 0.9.44+ is required.
+ *
+ * @since 1.31
+ * @var string|bool
+ */
+$wgShellRestrictionMethod = false;
+
 /** @} */ # End shell }
 
 /************************************************************************//**
index 8095fd7..f170a02 100644 (file)
@@ -232,6 +232,8 @@ class GitInfo {
                                ];
                                $result = Shell::command( $cmd )
                                        ->environment( [ 'GIT_DIR' => $this->basedir ] )
+                                       ->restrict( Shell::RESTRICT_DEFAULT | Shell::NO_NETWORK )
+                                       ->whitelistPaths( [ $this->basedir ] )
                                        ->execute();
 
                                if ( $result->getExitCode() === 0 ) {
index ae88d37..dad0630 100644 (file)
@@ -439,8 +439,9 @@ return [
                        'filesize' => $config->get( 'MaxShellFileSize' ),
                ];
                $cgroup = $config->get( 'ShellCgroup' );
+               $restrictionMethod = $config->get( 'ShellRestrictionMethod' );
 
-               $factory = new CommandFactory( $limits, $cgroup );
+               $factory = new CommandFactory( $limits, $cgroup, $restrictionMethod );
                $factory->setLogger( LoggerFactory::getInstance( 'exec' ) );
                $factory->logStderr();
 
index ce32e3f..10934b4 100644 (file)
        "apihelp-expandtemplates-param-includecomments": "Дали во изводот да се вклучени HTML-коментари.",
        "apihelp-expandtemplates-param-generatexml": "Создај XML-дрво на расчленување (заменето со $1prop=parsetree).",
        "apihelp-expandtemplates-example-simple": "Прошири го викитекстот <kbd><nowiki>{{Project:Sandbox}}</nowiki></kbd>.",
-       "apihelp-feedcontributions-summary": "Дава канал со придонеси на корисник.",
-       "apihelp-feedcontributions-param-feedformat": "Формат на каналот.",
+       "apihelp-feedcontributions-summary": "Дава тековник со придонеси на корисник.",
+       "apihelp-feedcontributions-param-feedformat": "Формат на тековникот.",
        "apihelp-feedcontributions-param-user": "За кои корисници да се прикажуваат придонесите.",
        "apihelp-feedcontributions-param-namespace": "По кој именски простор да се филтрираат придонесите:",
        "apihelp-feedcontributions-param-year": "Од година (и порано):",
        "apihelp-feedcontributions-param-hideminor": "Сокриј ситни уредувања.",
        "apihelp-feedcontributions-param-showsizediff": "Покажувај ја големинската разлика меѓу преработките.",
        "apihelp-feedcontributions-example-simple": "Покажувај придонеси на <kbd>Пример</kbd>.",
-       "apihelp-feedrecentchanges-summary": "Дава канал со скорешни промени.",
-       "apihelp-feedrecentchanges-param-feedformat": "Форматот на каналот.",
+       "apihelp-feedrecentchanges-summary": "Дава тековник со скорешни промени.",
+       "apihelp-feedrecentchanges-param-feedformat": "Форматот на тековникот.",
        "apihelp-feedrecentchanges-param-namespace": "На кој именски простор да се ограничи исходот.",
        "apihelp-feedrecentchanges-param-invert": "Сите именски простори освен избраниот.",
        "apihelp-feedrecentchanges-param-associated": "Вклучи придружни именски простори (разговор или главен).",
        "apihelp-feedrecentchanges-param-categories_any": "Прикажи само промени на страниците во било која од категориите.",
        "apihelp-feedrecentchanges-example-simple": "Прикажи скорешни промени",
        "apihelp-feedrecentchanges-example-30days": "Прикажувај скорешни промени 30 дена",
-       "apihelp-feedwatchlist-summary": "Дава канал од набљудуваните.",
-       "apihelp-feedwatchlist-param-feedformat": "Форматот на каналот.",
+       "apihelp-feedwatchlist-summary": "Дава тековник со набљудуваните.",
+       "apihelp-feedwatchlist-param-feedformat": "Форматот на тековникот.",
        "apihelp-feedwatchlist-param-hours": "Испиши страници изменети во рок од олку часови отсега.",
        "apihelp-feedwatchlist-param-linktosections": "Давај ме право на изменетите делови, ако е можно.",
-       "apihelp-feedwatchlist-example-default": "Прикажи го каналот од набљудуваните.",
+       "apihelp-feedwatchlist-example-default": "Прикажи го тековникот на набљудуваните.",
        "apihelp-feedwatchlist-example-all6hrs": "Прикажи ги сите промени во набљудуваните во последните 6 часа",
        "apihelp-filerevert-summary": "Врати податотека на претходна верзија.",
        "apihelp-filerevert-param-filename": "Име на целната податотека, без претставката „Податотека:“.",
index 39025ec..b1df86e 100644 (file)
        "apihelp-parse-param-pageid": "Tolka innehållet på denna sida. Åsidosätter <var>$1sidan</var>.",
        "apihelp-parse-param-prop": "Vilka bitar av information att få:",
        "apihelp-parse-paramvalue-prop-categorieshtml": "Ger HTML-version av kategorierna.",
+       "apihelp-parse-param-disablepp": "Använd <var>$1disablelimitreport</var> istället.",
        "apihelp-parse-param-preview": "Tolka i preview-läget.",
        "apihelp-parse-example-page": "Tolka en sida.",
        "apihelp-parse-example-text": "Tolka wikitext.",
        "apihelp-protect-summary": "Ändra skyddsnivån för en sida.",
        "apihelp-protect-example-protect": "Skydda en sida",
        "apihelp-purge-summary": "Rensa cachen för angivna titlar.",
+       "apihelp-purge-param-forcelinkupdate": "Uppdatera länktabellerna.",
        "apihelp-query-param-list": "Vilka listor att hämta.",
        "apihelp-query-param-meta": "Vilka metadata att hämta.",
        "apihelp-query-example-allpages": "Hämta sidversioner av sidor som börjar med <kbd>API/</kbd>.",
        "apihelp-query+allcategories-param-min": "Returnera endast kategorier med minst så här många medlemmar.",
        "apihelp-query+allcategories-param-max": "Returnera endast kategorier med som mest så här många medlemmar.",
        "apihelp-query+allcategories-param-limit": "Hur många kategorier att returnera.",
+       "apihelp-query+allcategories-param-prop": "Vilka egenskaper att hämta:",
        "apihelp-query+allcategories-paramvalue-prop-size": "Lägger till antal sidor i kategorin.",
        "apihelp-query+allcategories-paramvalue-prop-hidden": "Märker kategorier som är dolda med <code>_&#95;HIDDENCAT_&#95;</code>.",
        "apihelp-query+alldeletedrevisions-summary": "Lista alla raderade revisioner av en användare or inom en namnrymd.",
        "apihelp-query+alldeletedrevisions-example-ns-main": "Lista dem första 50 revideringarna i huvud-namnrymden",
        "apihelp-query+allfileusages-summary": "Lista all fil användningsområden, inklusive icke-existerande.",
        "apihelp-query+allfileusages-param-prefix": "Sök för all fil-titlar som börjar med detta värde.",
+       "apihelp-query+allfileusages-paramvalue-prop-title": "Lägger till filens titel.",
        "apihelp-query+allfileusages-param-limit": "Hur många saker att returnera totalt.",
        "apihelp-query+allfileusages-param-dir": "Riktningen att lista mot.",
        "apihelp-query+allfileusages-example-unique": "Lista unika filtitlar",
        "apihelp-query+categorymembers-summary": "Lista alla sidor i en angiven kategori.",
        "apihelp-query+categorymembers-paramvalue-prop-ids": "Lägger till sid-ID.",
        "apihelp-query+categorymembers-paramvalue-prop-title": "Lägger till titeln och namnrymds-ID för sidan.",
+       "apihelp-query+categorymembers-param-sort": "Egenskap att sortera efter.",
        "apihelp-query+categorymembers-param-dir": "I vilken riktning att sortera.",
        "apihelp-query+categorymembers-param-startsortkey": "Använd $1starthexsortkey istället.",
        "apihelp-query+categorymembers-param-endsortkey": "Använd $1endhexsortkey istället.",
        "apihelp-query+embeddedin-summary": "Hitta alla sidor som bäddar in (inkluderar) angiven titel.",
        "apihelp-query+embeddedin-param-dir": "Riktningen att lista mot.",
        "apihelp-query+embeddedin-param-limit": "Hur många sidor att returnera totalt.",
+       "apihelp-query+extlinks-param-limit": "Hur många länkar som ska returneras.",
        "apihelp-query+extlinks-example-simple": "Hämta en lista över externa länkar på <kbd>Main Page</kbd>.",
+       "apihelp-query+exturlusage-param-limit": "Hur många sidor att returnera.",
+       "apihelp-query+filearchive-param-limit": "Hur många bilder att returnera totalt.",
        "apihelp-query+filearchive-param-dir": "Riktningen att lista mot.",
        "apihelp-query+filearchive-paramvalue-prop-timestamp": "Lägger till tidsstämpel för den uppladdade versionen.",
        "apihelp-query+filearchive-paramvalue-prop-user": "Lägger till användaren som laddade upp bildversionen.",
+       "apihelp-query+filearchive-paramvalue-prop-dimensions": "Alias för storlek.",
+       "apihelp-query+filearchive-paramvalue-prop-description": "Lägger till beskrivning till bildversionen.",
        "apihelp-query+filearchive-example-simple": "Visa en lista över alla borttagna filer.",
        "apihelp-query+filerepoinfo-summary": "Returnera metainformation om bildegenskaper som konfigureras på wikin.",
        "apihelp-query+fileusage-summary": "Hitta alla sidor som använder angivna filer.",
+       "apihelp-query+fileusage-param-prop": "Vilka egenskaper att hämta:",
        "apihelp-query+fileusage-paramvalue-prop-title": "Titel för varje sida.",
        "apihelp-query+fileusage-paramvalue-prop-redirect": "Flagga om sidan är en omdirigering.",
        "apihelp-query+imageinfo-summary": "Returnerar filinformation och uppladdningshistorik.",
+       "apihelp-query+imageinfo-param-prop": "Vilka filinformation att hämta:",
+       "apihelp-query+imageinfo-paramvalue-prop-timestamp": "Lägger till tidsstämpel för den uppladdade versionen.",
        "apihelp-query+imageinfo-paramvalue-prop-userid": "Lägg till det användar-ID som laddade upp varje filversion.",
+       "apihelp-query+imageinfo-paramvalue-prop-dimensions": "Alias för storlek.",
+       "apihelp-query+images-param-limit": "Hur många filer att returnera.",
        "apihelp-query+images-param-dir": "Riktningen att lista mot.",
+       "apihelp-query+images-example-simple": "Hämta en lista över filer som används på [[Main Page]].",
        "apihelp-query+imageusage-summary": "Hitta alla sidor som användare angiven bildtitel.",
        "apihelp-query+imageusage-param-dir": "Riktningen att lista mot.",
        "apihelp-query+imageusage-example-simple": "Visa sidor med hjälp av [[:File:Albert Einstein Head.jpg]].",
index df964e0..7ac8cd0 100644 (file)
@@ -82,10 +82,11 @@ class ChangesFeed {
                        return null;
                }
 
+               $cache = ObjectCache::getMainWANInstance();
                $optionsHash = md5( serialize( $opts->getAllValues() ) ) . $wgRenderHashAppend;
-               $timekey = wfMemcKey(
+               $timekey = $cache->makeKey(
                        $this->type, $this->format, $wgLang->getCode(), $optionsHash, 'timestamp' );
-               $key = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash );
+               $key = $cache->makeKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash );
 
                FeedUtils::checkPurge( $timekey, $key );
 
index 91f569f..c38eb6a 100644 (file)
@@ -482,6 +482,7 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'addPgField', 'protected_titles', 'pt_reason_id', 'INTEGER NOT NULL DEFAULT 0' ],
                        [ 'addTable', 'comment', 'patch-comment-table.sql' ],
                        [ 'addIndex', 'site_stats', 'site_stats_pkey', 'patch-site_stats-pk.sql' ],
+                       [ 'addTable', 'ip_changes', 'patch-ip_changes.sql' ],
                ];
        }
 
diff --git a/includes/jobqueue/jobs/ClearUserWatchlistJob.php b/includes/jobqueue/jobs/ClearUserWatchlistJob.php
new file mode 100644 (file)
index 0000000..17c4b66
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Job to clear a users watchlist in batches.
+ *
+ * @author Addshore
+ *
+ * @ingroup JobQueue
+ * @since 1.31
+ */
+class ClearUserWatchlistJob extends Job {
+
+       /**
+        * @param User $user User to clear the watchlist for.
+        * @param int $maxWatchlistId The maximum wl_id at the time the job was first created.
+        *
+        * @return ClearUserWatchlistJob
+        */
+       public static function newForUser( User $user, $maxWatchlistId ) {
+               return new self(
+                       null,
+                       [ 'userId' => $user->getId(), 'maxWatchlistId' => $maxWatchlistId ]
+               );
+       }
+
+       /**
+        * @param Title|null $title Not used by this job.
+        * @param array $params
+        *  - batchSize,      Number of watchlist entries to remove at once.
+        *  - userId,         The ID for the user whose watchlist is being cleared.
+        *  - maxWatchlistId, The maximum wl_id at the time the job was first created,
+        */
+       public function __construct( Title $title = null, array $params ) {
+               if ( !array_key_exists( 'batchSize', $params ) ) {
+                       $params['batchSize'] = 1000;
+               }
+
+               parent::__construct(
+                       'clearUserWatchlist',
+                       SpecialPage::getTitleFor( 'EditWatchlist', 'clear' ),
+                       $params
+               );
+
+               $this->removeDuplicates = true;
+       }
+
+       public function run() {
+               $userId = $this->params['userId'];
+               $maxWatchlistId = $this->params['maxWatchlistId'];
+
+               $loadBalancer = MediaWikiServices::getInstance()->getDBLoadBalancer();
+               $dbw = $loadBalancer->getConnection( DB_MASTER );
+               $dbr = $loadBalancer->getConnection( DB_REPLICA, [ 'watchlist' ] );
+
+               // Wait before lock to try to reduce time waiting in the lock.
+               if ( !$loadBalancer->safeWaitForMasterPos( $dbr ) ) {
+                       $this->setLastError( 'Timed out while waiting for slave to catch up before lock' );
+                       return false;
+               }
+
+               // Use a named lock so that jobs for this user see each others' changes
+               $lockKey = "ClearUserWatchlistJob:$userId";
+               $scopedLock = $dbw->getScopedLockAndFlush( $lockKey, __METHOD__, 10 );
+               if ( !$scopedLock ) {
+                       $this->setLastError( "Could not acquire lock '$lockKey'" );
+                       return false;
+               }
+
+               if ( !$loadBalancer->safeWaitForMasterPos( $dbr ) ) {
+                       $this->setLastError( 'Timed out while waiting for slave to catch up within lock' );
+                       return false;
+               }
+
+               // Clear any stale REPEATABLE-READ snapshot
+               $dbr->flushSnapshot( __METHOD__ );
+
+               $watchlistIds = $dbr->selectFieldValues(
+                       'watchlist',
+                       'wl_id',
+                       [
+                               'wl_user' => $userId,
+                               'wl_id <= ' . $maxWatchlistId
+                       ],
+                       __METHOD__,
+                       [
+                               'ORDER BY' => 'wl_id ASC',
+                               'LIMIT' => $this->params['batchSize'],
+                       ]
+               );
+
+               if ( count( $watchlistIds ) == 0 ) {
+                       return true;
+               }
+
+               $dbw->delete( 'watchlist', [ 'wl_id' => $watchlistIds ], __METHOD__ );
+
+               // Commit changes and remove lock before inserting next job.
+               $lbf = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+               $lbf->commitMasterChanges( __METHOD__ );
+               unset( $scopedLock );
+
+               if ( count( $watchlistIds ) == $this->params['batchSize'] ) {
+                       JobQueueGroup::singleton()->push( new self( $this->getTitle(), $this->getParams() ) );
+               }
+
+               return true;
+       }
+
+       public function getDeduplicationInfo() {
+               $info = parent::getDeduplicationInfo();
+               // This job never has a namespace or title so we can't use it for deduplication
+               unset( $info['namespace'] );
+               unset( $info['title'] );
+               return $info;
+       }
+
+}
index 373ad93..27ce212 100644 (file)
@@ -181,6 +181,29 @@ class SwiftFileBackend extends FileBackendStore {
         * @param array $params
         * @return array Sanitized value of 'headers' field in $params
         */
+       protected function sanitizeHdrsStrict( array $params ) {
+               if ( !isset( $params['headers'] ) ) {
+                       return [];
+               }
+
+               $headers = $this->getCustomHeaders( $params['headers'] );
+               unset( $headers[ 'content-type' ] );
+
+               return $headers;
+       }
+
+       /**
+        * Sanitize and filter the custom headers from a $params array.
+        * Only allows certain "standard" Content- and X-Content- headers.
+        *
+        * When POSTing data, libcurl adds Content-Type: application/x-www-form-urlencoded
+        * if Content-Type is not set, which overwrites the stored Content-Type header
+        * in Swift - therefore for POSTing data do not strip the Content-Type header (the
+        * previously-stored header that has been already read back from swift is sent)
+        *
+        * @param array $params
+        * @return array Sanitized value of 'headers' field in $params
+        */
        protected function sanitizeHdrs( array $params ) {
                return isset( $params['headers'] )
                        ? $this->getCustomHeaders( $params['headers'] )
@@ -197,7 +220,7 @@ class SwiftFileBackend extends FileBackendStore {
                // Normalize casing, and strip out illegal headers
                foreach ( $rawHeaders as $name => $value ) {
                        $name = strtolower( $name );
-                       if ( preg_match( '/^content-(type|length)$/', $name ) ) {
+                       if ( preg_match( '/^content-length$/', $name ) ) {
                                continue; // blacklisted
                        } elseif ( preg_match( '/^(x-)?content-/', $name ) ) {
                                $headers[$name] = $value; // allowed
@@ -276,7 +299,7 @@ class SwiftFileBackend extends FileBackendStore {
                                'etag' => md5( $params['content'] ),
                                'content-type' => $contentType,
                                'x-object-meta-sha1base36' => $sha1Hash
-                       ] + $this->sanitizeHdrs( $params ),
+                       ] + $this->sanitizeHdrsStrict( $params ),
                        'body' => $params['content']
                ] ];
 
@@ -340,7 +363,7 @@ class SwiftFileBackend extends FileBackendStore {
                                'etag' => md5_file( $params['src'] ),
                                'content-type' => $contentType,
                                'x-object-meta-sha1base36' => $sha1Hash
-                       ] + $this->sanitizeHdrs( $params ),
+                       ] + $this->sanitizeHdrsStrict( $params ),
                        'body' => $handle // resource
                ] ];
 
@@ -391,7 +414,7 @@ class SwiftFileBackend extends FileBackendStore {
                        'headers' => [
                                'x-copy-from' => '/' . rawurlencode( $srcCont ) .
                                        '/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
-                       ] + $this->sanitizeHdrs( $params ), // extra headers merged into object
+                       ] + $this->sanitizeHdrsStrict( $params ), // extra headers merged into object
                ] ];
 
                $method = __METHOD__;
@@ -440,7 +463,7 @@ class SwiftFileBackend extends FileBackendStore {
                                'headers' => [
                                        'x-copy-from' => '/' . rawurlencode( $srcCont ) .
                                                '/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
-                               ] + $this->sanitizeHdrs( $params ) // extra headers merged into object
+                               ] + $this->sanitizeHdrsStrict( $params ) // extra headers merged into object
                        ]
                ];
                if ( "{$srcCont}/{$srcRel}" !== "{$dstCont}/{$dstRel}" ) {
index d8b8be7..3670243 100644 (file)
@@ -87,6 +87,7 @@ application/x-tcsh    [EXECUTABLE]
 application/x-tcl      [EXECUTABLE]
 application/x-perl     [EXECUTABLE]
 application/x-python   [EXECUTABLE]
+application/wasm       [EXECUTABLE]
 
 application/pdf application/acrobat    [OFFICE]
 application/msword             [OFFICE]
index f1cd59d..ef6854c 100644 (file)
@@ -187,3 +187,4 @@ chemical/x-mdl-rdfile rd
 chemical/x-mdl-rgfile rg
 application/x-amf amf
 application/sla stl
+application/wasm wasm
index ae7f36c..727e3c1 100644 (file)
@@ -137,6 +137,8 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
        const HOLDOFF_NONE = 0;
        /** Idiom for set()/getWithSetCallback() for "do not augment the storage medium TTL" */
        const STALE_TTL_NONE = 0;
+       /** Idiom for set()/getWithSetCallback() for "no post-expired grace period" */
+       const GRACE_TTL_NONE = 0;
 
        /** Idiom for getWithSetCallback() for "no minimum required as-of timestamp" */
        const MIN_TIMESTAMP_NONE = 0.0;
@@ -616,14 +618,13 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         * The "check" key essentially represents a last-modified time of an entity.
         * When the key is touched, the timestamp will be updated to the current time.
         * Keys using the "check" key via get(), getMulti(), or getWithSetCallback() will
-        * be invalidated. The timestamp of "check" is treated as being HOLDOFF_TTL seconds
-        * in the future by get*() methods in order to avoid race conditions where keys are
-        * updated with stale values (e.g. from a DB replica DB).
+        * be invalidated. This approach is useful if many keys depend on a single entity.
         *
-        * This method is typically useful for keys with hardcoded names or in some cases
-        * dynamically generated names, provided the number of such keys is modest. It sets a
-        * high TTL on the "check" key, making it possible to know the timestamp of the last
-        * change to the corresponding entities in most cases.
+        * The timestamp of the "check" key is treated as being HOLDOFF_TTL seconds in the
+        * future by get*() methods in order to avoid race conditions where keys are updated
+        * with stale values (e.g. from a lagged replica DB). A high TTL is set on the "check"
+        * key, making it possible to know the timestamp of the last change to the corresponding
+        * entities in most cases. This might use more cache space than resetCheckKey().
         *
         * When a few important keys get a large number of hits, a high cache time is usually
         * desired as well as "lockTSE" logic. The resetCheckKey() method is less appropriate
@@ -813,13 +814,21 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         *
         * @param string $key Cache key made from makeKey() or makeGlobalKey()
         * @param int $ttl Seconds to live for key updates. Special values are:
-        *   - WANObjectCache::TTL_INDEFINITE: Cache forever
-        *   - WANObjectCache::TTL_UNCACHEABLE: Do not cache at all
+        *   - WANObjectCache::TTL_INDEFINITE: Cache forever (subject to LRU-style evictions)
+        *   - WANObjectCache::TTL_UNCACHEABLE: Do not cache (if the key exists, it is not deleted)
         * @param callable $callback Value generation function
         * @param array $opts Options map:
         *   - checkKeys: List of "check" keys. The key at $key will be seen as invalid when either
-        *      touchCheckKey() or resetCheckKey() is called on any of these keys.
+        *      touchCheckKey() or resetCheckKey() is called on any of the keys in this list. This
+        *      is useful if thousands or millions of keys depend on the same entity. The entity can
+        *      simply have its "check" key updated whenever the entity is modified.
         *      Default: [].
+        *   - graceTTL: Consider reusing expired values instead of refreshing them if they expired
+        *      less than this many seconds ago. The odds of a refresh becomes more likely over time,
+        *      becoming certain once the grace period is reached. This can reduce traffic spikes
+        *      when millions of keys are compared to the same "check" key and touchCheckKey()
+        *      or resetCheckKey() is called on that "check" key.
+        *      Default: WANObjectCache::GRACE_TTL_NONE.
         *   - lockTSE: If the key is tombstoned or expired (by checkKeys) less than this many seconds
         *      ago, then try to have a single thread handle cache regeneration at any given time.
         *      Other threads will try to use stale values if possible. If, on miss, the time since
@@ -854,16 +863,18 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         *      This is useful if the source of a key is suspected of having possibly changed
         *      recently, and the caller wants any such changes to be reflected.
         *      Default: WANObjectCache::MIN_TIMESTAMP_NONE.
-        *   - hotTTR: Expected time-till-refresh (TTR) for keys that average ~1 hit/second (1 Hz).
-        *      Keys with a hit rate higher than 1Hz will refresh sooner than this TTR and vise versa.
-        *      Such refreshes won't happen until keys are "ageNew" seconds old. The TTR is useful at
+        *   - hotTTR: Expected time-till-refresh (TTR) in seconds for keys that average ~1 hit per
+        *      second (e.g. 1Hz). Keys with a hit rate higher than 1Hz will refresh sooner than this
+        *      TTR and vise versa. Such refreshes won't happen until keys are "ageNew" seconds old.
+        *      This uses randomization to avoid triggering cache stampedes. The TTR is useful at
         *      reducing the impact of missed cache purges, since the effect of a heavily referenced
         *      key being stale is worse than that of a rarely referenced key. Unlike simply lowering
-        *      $ttl, seldomly used keys are largely unaffected by this option, which makes it possible
-        *      to have a high hit rate for the "long-tail" of less-used keys.
+        *      $ttl, seldomly used keys are largely unaffected by this option, which makes it
+        *      possible to have a high hit rate for the "long-tail" of less-used keys.
         *      Default: WANObjectCache::HOT_TTR.
         *   - lowTTL: Consider pre-emptive updates when the current TTL (seconds) of the key is less
         *      than this. It becomes more likely over time, becoming certain once the key is expired.
+        *      This helps avoid cache stampedes that might be triggered due to the key expiring.
         *      Default: WANObjectCache::LOW_TTL.
         *   - ageNew: Consider popularity refreshes only once a key reaches this age in seconds.
         *      Default: WANObjectCache::AGE_NEW.
@@ -903,11 +914,14 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                                        use ( $callback, $version ) {
                                                if ( is_array( $oldValue )
                                                        && array_key_exists( self::VFLD_DATA, $oldValue )
+                                                       && array_key_exists( self::VFLD_VERSION, $oldValue )
+                                                       && $oldValue[self::VFLD_VERSION] === $version
                                                ) {
                                                        $oldData = $oldValue[self::VFLD_DATA];
                                                } else {
                                                        // VFLD_DATA is not set if an old, unversioned, key is present
                                                        $oldData = false;
+                                                       $oldAsOf = null;
                                                }
 
                                                return [
@@ -962,6 +976,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                $lowTTL = isset( $opts['lowTTL'] ) ? $opts['lowTTL'] : min( self::LOW_TTL, $ttl );
                $lockTSE = isset( $opts['lockTSE'] ) ? $opts['lockTSE'] : self::TSE_NONE;
                $staleTTL = isset( $opts['staleTTL'] ) ? $opts['staleTTL'] : self::STALE_TTL_NONE;
+               $graceTTL = isset( $opts['graceTTL'] ) ? $opts['graceTTL'] : self::GRACE_TTL_NONE;
                $checkKeys = isset( $opts['checkKeys'] ) ? $opts['checkKeys'] : [];
                $busyValue = isset( $opts['busyValue'] ) ? $opts['busyValue'] : null;
                $popWindow = isset( $opts['hotTTR'] ) ? $opts['hotTTR'] : self::HOT_TTR;
@@ -980,7 +995,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                $preCallbackTime = $this->getCurrentTime();
                // Determine if a cached value regeneration is needed or desired
                if ( $value !== false
-                       && $curTTL > 0
+                       && $this->isAliveOrInGracePeriod( $curTTL, $graceTTL )
                        && $this->isValid( $value, $versioned, $asOf, $minTime )
                        && !$this->worthRefreshExpiring( $curTTL, $lowTTL )
                        && !$this->worthRefreshPopular( $asOf, $ageNew, $popWindow, $preCallbackTime )
@@ -1631,13 +1646,44 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                return $ok;
        }
 
+       /**
+        * Check if a key is fresh or in the grace window and thus due for randomized reuse
+        *
+        * If $curTTL > 0 (e.g. not expired) this returns true. Otherwise, the chance of returning
+        * true decrease steadily from 100% to 0% as the |$curTTL| moves from 0 to $graceTTL seconds.
+        * This handles widely varying levels of cache access traffic.
+        *
+        * If $curTTL <= -$graceTTL (e.g. already expired), then this returns false.
+        *
+        * @param float $curTTL Approximate TTL left on the key if present
+        * @param int $graceTTL Consider using stale values if $curTTL is greater than this
+        * @return bool
+        */
+       protected function isAliveOrInGracePeriod( $curTTL, $graceTTL ) {
+               if ( $curTTL > 0 ) {
+                       return true;
+               } elseif ( $graceTTL <= 0 ) {
+                       return false;
+               }
+
+               $ageStale = abs( $curTTL ); // seconds of staleness
+               $curGTTL = ( $graceTTL - $ageStale ); // current grace-time-to-live
+               if ( $curGTTL <= 0 ) {
+                       return false; //  already out of grace period
+               }
+
+               // Chance of using a stale value is the complement of the chance of refreshing it
+               return !$this->worthRefreshExpiring( $curGTTL, $graceTTL );
+       }
+
        /**
         * Check if a key is nearing expiration and thus due for randomized regeneration
         *
-        * This returns false if $curTTL >= $lowTTL. Otherwise, the chance
-        * of returning true increases steadily from 0% to 100% as the $curTTL
-        * moves from $lowTTL to 0 seconds. This handles widely varying
-        * levels of cache access traffic.
+        * This returns false if $curTTL >= $lowTTL. Otherwise, the chance of returning true
+        * increases steadily from 0% to 100% as the $curTTL moves from $lowTTL to 0 seconds.
+        * This handles widely varying levels of cache access traffic.
+        *
+        * If $curTTL <= 0 (e.g. already expired), then this returns false.
         *
         * @param float $curTTL Approximate TTL left on the key if present
         * @param float $lowTTL Consider a refresh when $curTTL is less than this
@@ -1649,7 +1695,7 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                } elseif ( $curTTL >= $lowTTL ) {
                        return false;
                } elseif ( $curTTL <= 0 ) {
-                       return true;
+                       return false;
                }
 
                $chance = ( 1 - $curTTL / $lowTTL );
index df432e1..5404f35 100644 (file)
@@ -45,6 +45,12 @@ class LogPager extends ReverseChronologicalPager {
        /** @var string */
        private $action = '';
 
+       /** @var bool */
+       private $performerRestrictionsEnforced = false;
+
+       /** @var bool */
+       private $actionRestrictionsEnforced = false;
+
        /** @var LogEventsList */
        public $mLogEventsList;
 
@@ -177,14 +183,7 @@ class LogPager extends ReverseChronologicalPager {
                } else {
                        $this->mConds['log_user'] = $userid;
                }
-               // Paranoia: avoid brute force searches (T19342)
-               $user = $this->getUser();
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_USER ) . ' = 0';
-               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
-                       $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) .
-                               ' != ' . LogPage::SUPPRESSED_USER;
-               }
+               $this->enforcePerformerRestrictions();
 
                $this->performer = $name;
        }
@@ -252,14 +251,7 @@ class LogPager extends ReverseChronologicalPager {
                } else {
                        $this->mConds['log_title'] = $title->getDBkey();
                }
-               // Paranoia: avoid brute force searches (T19342)
-               $user = $this->getUser();
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $this->mConds[] = $db->bitAnd( 'log_deleted', LogPage::DELETED_ACTION ) . ' = 0';
-               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
-                       $this->mConds[] = $db->bitAnd( 'log_deleted', LogPage::SUPPRESSED_ACTION ) .
-                               ' != ' . LogPage::SUPPRESSED_ACTION;
-               }
+               $this->enforceActionRestrictions();
        }
 
        /**
@@ -420,4 +412,39 @@ class LogPager extends ReverseChronologicalPager {
                parent::doQuery();
                $this->mDb->setBigSelects( 'default' );
        }
+
+       /**
+        * Paranoia: avoid brute force searches (T19342)
+        */
+       private function enforceActionRestrictions() {
+               if ( $this->actionRestrictionsEnforced ) {
+                       return;
+               }
+               $this->actionRestrictionsEnforced = true;
+               $user = $this->getUser();
+               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+                       $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_USER ) . ' = 0';
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
+                       $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) .
+                               ' != ' . LogPage::SUPPRESSED_USER;
+               }
+       }
+
+       /**
+        * Paranoia: avoid brute force searches (T19342)
+        */
+       private function enforcePerformerRestrictions() {
+               // Same as enforceActionRestrictions(), except for _USER instead of _ACTION bits.
+               if ( $this->performerRestrictionsEnforced ) {
+                       return;
+               }
+               $this->performerRestrictionsEnforced = true;
+               $user = $this->getUser();
+               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+                       $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_ACTION ) . ' = 0';
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
+                       $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_ACTION ) .
+                               ' != ' . LogPage::SUPPRESSED_ACTION;
+               }
+       }
 }
index 9f080d5..264c3b4 100644 (file)
@@ -68,6 +68,13 @@ class Command {
        /** @var string|false */
        private $cgroup = false;
 
+       /**
+        * bitfield with restrictions
+        *
+        * @var int
+        */
+       protected $restrictions = 0;
+
        /**
         * Constructor. Don't call directly, instead use Shell::command()
         *
@@ -212,6 +219,45 @@ class Command {
                return $this;
        }
 
+       /**
+        * Set additional restrictions for this request
+        *
+        * @since 1.31
+        * @param int $restrictions
+        * @return $this
+        */
+       public function restrict( $restrictions ) {
+               $this->restrictions |= $restrictions;
+
+               return $this;
+       }
+
+       /**
+        * Bitfield helper on whether a specific restriction is enabled
+        *
+        * @param int $restriction
+        *
+        * @return bool
+        */
+       protected function hasRestriction( $restriction ) {
+               return ( $this->restrictions & $restriction ) === $restriction;
+       }
+
+       /**
+        * If called, only the files/directories that are
+        * whitelisted will be available to the shell command.
+        *
+        * limit.sh will always be whitelisted
+        *
+        * @param string[] $paths
+        *
+        * @return $this
+        */
+       public function whitelistPaths( array $paths ) {
+               // Default implementation is a no-op
+               return $this;
+       }
+
        /**
         * String together all the options and build the final command
         * to execute
index 84dd50f..78f1d80 100644 (file)
@@ -20,6 +20,7 @@
 
 namespace MediaWiki\Shell;
 
+use ExecutableFinder;
 use Psr\Log\LoggerAwareTrait;
 use Psr\Log\NullLogger;
 
@@ -40,18 +41,47 @@ class CommandFactory {
        /** @var bool */
        private $doLogStderr = false;
 
+       /**
+        * @var string|bool
+        */
+       private $restrictionMethod;
+
+       /**
+        * @var string|bool
+        */
+       private $firejail;
+
        /**
         * Constructor
         *
         * @param array $limits See {@see Command::limits()}
         * @param string|bool $cgroup See {@see Command::cgroup()}
+        * @param string|bool $restrictionMethod
         */
-       public function __construct( array $limits, $cgroup ) {
+       public function __construct( array $limits, $cgroup, $restrictionMethod ) {
                $this->limits = $limits;
                $this->cgroup = $cgroup;
+               if ( $restrictionMethod === 'autodetect' ) {
+                       // On Linux systems check for firejail
+                       if ( PHP_OS === 'Linux' && $this->findFirejail() !== false ) {
+                               $this->restrictionMethod = 'firejail';
+                       } else {
+                               $this->restrictionMethod = false;
+                       }
+               } else {
+                       $this->restrictionMethod = $restrictionMethod;
+               }
                $this->setLogger( new NullLogger() );
        }
 
+       private function findFirejail() {
+               if ( $this->firejail === null ) {
+                       $this->firejail = ExecutableFinder::findInDefaultPaths( 'firejail' );
+               }
+
+               return $this->firejail;
+       }
+
        /**
         * When enabled, text sent to stderr will be logged with a level of 'error'.
         *
@@ -68,7 +98,11 @@ class CommandFactory {
         * @return Command
         */
        public function create() {
-               $command = new Command();
+               if ( $this->restrictionMethod === 'firejail' ) {
+                       $command = new FirejailCommand( $this->findFirejail() );
+               } else {
+                       $command = new Command();
+               }
                $command->setLogger( $this->logger );
 
                return $command
diff --git a/includes/shell/FirejailCommand.php b/includes/shell/FirejailCommand.php
new file mode 100644 (file)
index 0000000..79f679d
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+/**
+ * Copyright (C) 2017 Kunal Mehta <legoktm@member.fsf.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+namespace MediaWiki\Shell;
+
+use RuntimeException;
+
+/**
+ * Restricts execution of shell commands using firejail
+ *
+ * @see https://firejail.wordpress.com/
+ * @since 1.31
+ */
+class FirejailCommand extends Command {
+
+       /**
+        * @var string Path to firejail
+        */
+       private $firejail;
+
+       /**
+        * @var string[]
+        */
+       private $whitelistedPaths = [];
+
+       /**
+        * @param string $firejail Path to firejail
+        */
+       public function __construct( $firejail ) {
+               parent::__construct();
+               $this->firejail = $firejail;
+       }
+
+       /**
+        * @inheritDoc
+        */
+       public function whitelistPaths( array $paths ) {
+               $this->whitelistedPaths = array_merge( $this->whitelistedPaths, $paths );
+               return $this;
+       }
+
+       /**
+        * @inheritDoc
+        */
+       protected function buildFinalCommand() {
+               // If there are no restrictions, don't use firejail
+               if ( $this->restrictions === 0 ) {
+                       return parent::buildFinalCommand();
+               }
+
+               if ( $this->firejail === false ) {
+                       throw new RuntimeException( 'firejail is enabled, but cannot be found' );
+               }
+               // quiet has to come first to prevent firejail from adding
+               // any output.
+               $cmd = [ $this->firejail, '--quiet' ];
+               // Use a profile that allows people to add local overrides
+               // if their system is setup in an incompatible manner. Also it
+               // prevents any default profiles from running.
+               // FIXME: Doesn't actually override command-line switches?
+               $cmd[] = '--profile=' . __DIR__ . '/firejail.profile';
+
+               // By default firejail hides all other user directories, so if
+               // MediaWiki is inside a home directory (/home) but not the
+               // current user's home directory, pass --allusers to whitelist
+               // the home directories again.
+               static $useAllUsers = null;
+               if ( $useAllUsers === null ) {
+                       global $IP;
+                       // In case people are doing funny things with symlinks
+                       // or relative paths, resolve them all.
+                       $realIP = realpath( $IP );
+                       $currentUser = posix_getpwuid( posix_geteuid() );
+                       $useAllUsers = ( strpos( $realIP, '/home/' ) === 0 )
+                               && ( strpos( $realIP, $currentUser['dir'] ) !== 0 );
+                       if ( $useAllUsers ) {
+                               $this->logger->warning( 'firejail: MediaWiki is located ' .
+                                       'in a home directory that does not belong to the ' .
+                                       'current user, so allowing access to all home ' .
+                                       'directories (--allusers)' );
+                       }
+               }
+
+               if ( $useAllUsers ) {
+                       $cmd[] = '--allusers';
+               }
+
+               if ( $this->whitelistedPaths ) {
+                       // Always whitelist limit.sh
+                       $cmd[] = '--whitelist=' . __DIR__ . '/limit.sh';
+                       foreach ( $this->whitelistedPaths as $whitelistedPath ) {
+                               $cmd[] = "--whitelist={$whitelistedPath}";
+                       }
+               }
+
+               if ( $this->hasRestriction( Shell::NO_ROOT ) ) {
+                       $cmd[] = '--noroot';
+               }
+
+               $seccomp = [];
+
+               if ( $this->hasRestriction( Shell::SECCOMP ) ) {
+                       $seccomp[] = '@default';
+               }
+
+               if ( $this->hasRestriction( Shell::NO_EXECVE ) ) {
+                       $seccomp[] = 'execve';
+               }
+
+               if ( $seccomp ) {
+                       $cmd[] = '--seccomp=' . implode( ',', $seccomp );
+               }
+
+               if ( $this->hasRestriction( Shell::PRIVATE_DEV ) ) {
+                       $cmd[] = '--private-dev';
+               }
+
+               if ( $this->hasRestriction( Shell::NO_NETWORK ) ) {
+                       $cmd[] = '--net=none';
+               }
+
+               list( $fullCommand, $useLogPipe ) = parent::buildFinalCommand();
+
+               $builtCmd = implode( ' ', $cmd );
+
+               return [ "$builtCmd -- $fullCommand", $useLogPipe ];
+       }
+
+}
index 604c96a..6e4fd02 100644 (file)
@@ -41,6 +41,57 @@ use MediaWiki\MediaWikiServices;
  */
 class Shell {
 
+       /**
+        * Apply a default set of restrictions for improved
+        * security out of the box.
+        *
+        * Equal to NO_ROOT | SECCOMP | PRIVATE_DEV
+        *
+        * @note This value will change over time to provide increased security
+        *       by default, and is not guaranteed to be backwards-compatible.
+        * @since 1.31
+        */
+       const RESTRICT_DEFAULT = 7;
+
+       /**
+        * Disallow any root access. Any setuid binaries
+        * will be run without elevated access.
+        *
+        * @since 1.31
+        */
+       const NO_ROOT = 1;
+
+       /**
+        * Use seccomp to block dangerous syscalls
+        * @see <https://en.wikipedia.org/wiki/seccomp>
+        *
+        * @since 1.31
+        */
+       const SECCOMP = 2;
+
+       /**
+        * Create a private /dev
+        *
+        * @since 1.31
+        */
+       const PRIVATE_DEV = 4;
+
+       /**
+        * Restrict the request to have no
+        * network access
+        *
+        * @since 1.31
+        */
+       const NO_NETWORK = 8;
+
+       /**
+        * Deny execve syscall with seccomp
+        * @see <https://en.wikipedia.org/wiki/exec_(system_call)>
+        *
+        * @since 1.31
+        */
+       const NO_EXECVE = 16;
+
        /**
         * Returns a new instance of Command class
         *
diff --git a/includes/shell/firejail.profile b/includes/shell/firejail.profile
new file mode 100644 (file)
index 0000000..07f059b
--- /dev/null
@@ -0,0 +1,7 @@
+# Firejail profile used by MediaWiki when shelling out
+# See <https://firejail.wordpress.com/features-3/man-firejail-profile/> for
+# syntax documentation
+# Persistent local customizations
+include /etc/firejail/mediawiki.local
+# Persistent global definitions
+include /etc/firejail/globals.local
index 094297c..f29bd47 100644 (file)
@@ -212,6 +212,33 @@ class WatchedItemStore implements WatchedItemStoreInterface, StatsdAwareInterfac
                return $this->loadBalancer->getConnectionRef( $dbIndex, [ 'watchlist' ] );
        }
 
+       /**
+        * Queues a job that will clear the users watchlist using the Job Queue.
+        *
+        * @since 1.31
+        *
+        * @param User $user
+        */
+       public function clearUserWatchedItemsUsingJobQueue( User $user ) {
+               $job = ClearUserWatchlistJob::newForUser( $user, $this->getMaxId() );
+               // TODO inject me.
+               JobQueueGroup::singleton()->push( $job );
+       }
+
+       /**
+        * @since 1.31
+        * @return int The maximum current wl_id
+        */
+       public function getMaxId() {
+               $dbr = $this->getConnectionRef( DB_REPLICA );
+               return (int)$dbr->selectField(
+                       'watchlist',
+                       'MAX(wl_id)',
+                       '',
+                       __METHOD__
+               );
+       }
+
        /**
         * @since 1.31
         */
index 5a70364..ed95d9d 100644 (file)
        "cannotdelete-title": "تعذّر حذف الصفحة \"$1\"",
        "delete-hook-aborted": "أجهض خطّاف الحذف.\nلم يقدم أي توضيح.",
        "no-null-revision": "تعذر إنشاء مراجعة جديدة فارغة لصفحة \"$1\"",
-       "badtitle": "عÙ\86Ù\88اÙ\86 Ø³Ù\8aئ",
+       "badtitle": "عÙ\86Ù\88اÙ\86 Ø³Ù\8aØ¡",
        "badtitletext": "عنوان الصفحة المطلوب إما غير صحيح أو فارغ، وربما الرابط بين اللغات أو بين المشاريع خاطئ.\nربما يحوي محارف لا تصلح للاستخدام في العناوين.",
        "title-invalid-empty": "عنوان الصفحة المطلوبة فارغ أو يحتوي اسم النطاق فقط.",
        "title-invalid-utf8": "عنوان الصفحة المطلوب يحتوي سلسلة محارف UTF-8 غير صالحة.",
index 01b0361..bfcbaa1 100644 (file)
        "uploadstash-file-not-found-no-remote-thumb": "Памылка атрыманьня мініятуры: $1\nURL = $2",
        "uploadstash-file-not-found-missing-content-type": "Адсутнічае загаловак тыпу зьместу.",
        "uploadstash-file-not-found-not-exists": "Не атрымалася знайсьці шлях, ці не зьяўляецца простым файлам.",
+       "uploadstash-file-too-large": "Немагчыма апрацаваць файл памерам большым за $1 байтаў.",
+       "uploadstash-not-logged-in": "Удзельнік не ўвайшоў у сыстэму, файлы мусяць належаць удзельнікам.",
        "invalid-chunk-offset": "Няслушнае зрушэньне фрагмэнту",
        "img-auth-accessdenied": "Доступ забаронены",
        "img-auth-nopathinfo": "Адсутнічае PATH_INFO.\nВаш сэрвэр не ўстаноўлены на пропуск гэтай інфармацыі.\nМагчма, ён працуе праз CGI і не падтрымлівае img_auth.\nГлядзіце https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
index 427d3c2..26a686e 100644 (file)
        "apisandbox": "API-hiekkalaatikko",
        "apisandbox-jsonly": "JavaScript vaaditaan API-hiekkalaatikon käyttämiseen.",
        "apisandbox-api-disabled": "API on poistettu käytöstä tällä sivustolla.",
-       "apisandbox-intro": "Käytä tätä sivua kokeillaksesi '''MediaWikin verkkopalvelun API:a'''.\n[[mw:API:Main page|API-dokumentaatio]] kertoo lisää API:en käytöstä. Esimerkki: [https://www.mediawiki.org/wiki/API#A_simple_example hae etusivun sisältö]. Valitse toiminto nähdäksesi lisää esimerkkejä.\n\nHuomioi, että vaikka tämä on hiekkalaatikko, sivulla suorittamasi toiminnot saattavat muokata wikiä.",
+       "apisandbox-intro": "Käytä tätä sivua kokeillaksesi <strong>MediaWikin verkkopalvelun API:a</strong>.\n[[mw:API:Main page|API-dokumentaatio]] kertoo lisää API:en käytöstä. Esimerkki: [https://www.mediawiki.org/wiki/API#A_simple_example hae etusivun sisältö]. Valitse toiminto nähdäksesi lisää esimerkkejä.\n\nHuomioi, että vaikka tämä on hiekkalaatikko, sivulla suorittamasi toiminnot saattavat muokata wikiä.",
        "apisandbox-fullscreen": "Laajenna paneeli",
        "apisandbox-fullscreen-tooltip": "Laajenna hiekkalaatikkopaneeli täyttämään selainikkuna.",
        "apisandbox-unfullscreen": "Palaa sivunäkymään",
index c6160b1..47bbf94 100644 (file)
        "recentchangesdays-max": "(maximum $1 jour{{PLURAL:$1||s}})",
        "recentchangescount": "Nombre de modifications à afficher par défaut :",
        "prefs-help-recentchangescount": "Ceci inclut les modifications récentes, les pages d'historiques et les journaux.",
+       "prefs-help-tokenmanagement": "Vous pouvez voir et réinitialiser la clé secrète de votre compte qui peut accéder au flux Web de votre liste de suivi. Toute personne connaissant la clé pourra lire votre liste de suivi, alors ne la partagez pas.",
        "savedprefs": "Les préférences ont été sauvegardées.",
        "savedrights": "Les droits utilisateur de {{GENDER:$1|$1}} ont été enregistrés.",
        "timezonelegend": "Fuseau horaire :",
index e8ae8e4..6604aaa 100644 (file)
        "nosuchusershort": "Non existe ningún usuario chamado \"$1\".\nVerifique o nome que inseriu.",
        "nouserspecified": "Cómpre especificar un nome de usuario.",
        "login-userblocked": "Este usuario está bloqueado. Acceso non autorizado.",
-       "wrongpassword": "O contrasinal escrito é incorrecto.\nPor favor, insira outro.",
+       "wrongpassword": "O nome de usuario ou o contrasinal escrito son incorrectos.\nPor favor, probe de novo.",
        "wrongpasswordempty": "O campo do contrasinal estaba en branco.\nPor favor, inténteo de novo.",
        "passwordtooshort": "Os contrasinais deben conter, como mínimo, {{PLURAL:$1|1 carácter|$1 caracteres}}.",
        "passwordtoolong": "Os contrasinais non poden ser máis longo de {{PLURAL:$1|1 carácter|$1 caracteres}}.",
        "diff-multi-sameuser": "(Non se {{PLURAL:$1|mostra unha revisión|mostran $1 revisións}} do historial {{PLURAL:$1|feita|feitas}} polo mesmo usuario.)",
        "diff-multi-otherusers": "(Non se {{PLURAL:$1|mostra unha revisión|mostran $1 revisións}} do historial {{PLURAL:$1|feita|feitas}} por {{PLURAL:$2|outro usuario|$2 usuarios}}.)",
        "diff-multi-manyusers": "(Non se {{PLURAL:$1|mostra unha revisión|mostran $1 revisións}} do historial {{PLURAL:$1|feita|feitas}} por máis {{PLURAL:$2|dun usuario|de $2 usuarios}}.)",
+       "diff-paragraph-moved-tonew": "Moveuse o parágrafo. Prema para saltar para á nova localización.",
+       "diff-paragraph-moved-toold": "Moveuse o parágrafo. Prema para saltar para á localización anterior.",
        "difference-missing-revision": "Non se {{PLURAL:$2|atopou revisión ningunha|atoparon $2 revisións}} desta diferenza ($1).\n\nA miúdo, isto está provocado por seguir unha ligazón de diferenzas obsoleta cara a unha páxina que foi borrada.\nO [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rexistro de borrados] contén máis detalles.",
        "searchresults": "Resultados da procura",
        "searchresults-title": "Resultados da procura de \"$1\"",
        "prefs-watchlist-edits": "Número máximo de edicións que mostrar na lista de vixilancia:",
        "prefs-watchlist-edits-max": "Número máximo: 1000",
        "prefs-watchlist-token": "Pase para a lista de vixilancia:",
+       "prefs-watchlist-managetokens": "Xestionar identificadores",
        "prefs-misc": "Preferencias varias",
        "prefs-resetpass": "Cambiar o contrasinal",
        "prefs-changeemail": "Cambiar ou eliminar o enderezo de correo electrónico",
        "recentchangesdays-max": "Máximo: $1 {{PLURAL:$1|día|días}}",
        "recentchangescount": "Número de edicións a mostrar por defecto:",
        "prefs-help-recentchangescount": "Isto inclúe os cambios recentes, os historiais e mais os rexistros.",
-       "prefs-help-watchlist-token2": "Esta é a clave secreta da fonte de novas web para a súa lista de vixilancia.\nCalquera persoa que a saiba poderá ler a súa lista de vixilancia; non comparta esta clave.\n[[Special:ResetTokens|Prema aquí se necesita restablecela]].",
        "savedprefs": "Gardáronse as súas preferencias.",
        "savedrights": "Gardáronse os grupos de {{GENDER:$1|usuario|usuaria}} de $1.",
        "timezonelegend": "Fuso horario:",
        "rcfilters-savedqueries-apply-and-setdefault-label": "Crear filtro por defecto",
        "rcfilters-savedqueries-cancel-label": "Cancelar",
        "rcfilters-savedqueries-add-new-title": "Gardar a configuración do filtro actual",
-       "rcfilters-savedqueries-already-saved": "Estes filtro xa están gardados",
+       "rcfilters-savedqueries-already-saved": "Estes filtros xa están gardados. Cambie a súa configuración para crear un filtro gardado novo.",
        "rcfilters-restore-default-filters": "Restaurar os filtros por defecto",
        "rcfilters-clear-all-filters": "Borrar todos os filtros",
        "rcfilters-show-new-changes": "Mostrar os cambios máis recentes",
index faf24ef..fa6fa64 100644 (file)
        "revdelete-unsuppress": "Ukloni ograničenja na vraćenim izmjenama",
        "revdelete-log": "Razlog:",
        "revdelete-submit": "Primijeni na {{PLURAL:$1|odabranu inačicu|odabrane inačice}}",
-       "revdelete-success": "Vidljivost izmjene ažurirana.",
+       "revdelete-success": "Vidljivost izmjene je ažurirana.",
        "revdelete-failure": "'''Vidljivost inačice nije mogla biti ažurirana:'''\n$1",
        "logdelete-success": "Vidljivost uređivanja postavljena.",
        "logdelete-failure": "'''Vidljivost evidencije ne može biti postavljena:'''\n$1",
        "rcfilters-show-new-changes": "Vidi najnovije izmjene",
        "rcfilters-search-placeholder": "Filtriraj nedavne promjene (pretražite ili počnite unositi)",
        "rcfilters-invalid-filter": "Filter nije valjan",
-       "rcfilters-empty-filter": "Nema aktivnih filtra. Prikazani su svi doprinosi.",
+       "rcfilters-empty-filter": "Nema aktivnih filtara. Prikazani su svi doprinosi.",
        "rcfilters-filterlist-title": "Filtri",
        "rcfilters-filterlist-whatsthis": "Kako ovo radi?",
        "rcfilters-filterlist-feedbacklink": "Recite nam Vaše mišljenje o ovim (novim) oruđima za filtriranje",
index a218140..35bb97d 100644 (file)
        "wlshowlast": "Ցուցադրել վերջին $1 ժամերը $2 օրերը",
        "watchlist-hide": "Թաքցնել",
        "watchlist-submit": "Ցույց տալ",
+       "wlshowtime": "Ցուցադրելու ժամանակահատվածը.",
        "wlshowhideminor": "չնչին խմբագրումներ",
        "wlshowhidebots": "բոտեր",
        "wlshowhideliu": "գրանցված մասնակիցներ",
index 9175588..723f1e6 100644 (file)
        "diff-multi-sameuser": "({{PLURAL:$1|$1 revisi antara}} oleh pengguna yang sama tidak ditampilkan)",
        "diff-multi-otherusers": "({{PLURAL:$1|Satu revisi antara|$1 revisi antara}} oleh {{PLURAL:$2|satu pengguna lainnya|$2 pengguna}} tidak ditampilkan)",
        "diff-multi-manyusers": "({{PLURAL:$1|Satu|$1}} revisi antara oleh lebih dari $2 {{PLURAL:$2|satu|$2}} pengguna tak ditampilkan)",
+       "diff-paragraph-moved-tonew": "Paragraf dipindahkan. Klik untuk melompat ke lokasi baru.",
+       "diff-paragraph-moved-toold": "Paragraf dipindahkan. Klik untuk melompat ke lokasi lama.",
        "difference-missing-revision": "{{PLURAL:$2|Satu revisi|$2 revisi}} dari perbedaan ini ($1) {{PLURAL:$2|tidak|tidak}} ditemukan.\n\nHal ini biasanya disebabkan oleh tautan diff yang kedaluwarsa ke halaman yang sudah dihapus.\nRinciannya dapat ditemukan di [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log penghapusan].",
        "searchresults": "Hasil pencarian",
        "searchresults-title": "Hasil pencarian untuk \"$1\"",
        "prefs-watchlist-edits": "Jumlah maksimum perubahan yang ditampilkan dalam daftar pantauan:",
        "prefs-watchlist-edits-max": "Nilai maksimum: 1000",
        "prefs-watchlist-token": "Token daftar pantauan:",
+       "prefs-watchlist-managetokens": "Kelola token",
        "prefs-misc": "Lain-lain",
        "prefs-resetpass": "Ganti kata sandi",
        "prefs-changeemail": "Ubah atau hapus alamat surel",
        "rcfilters-savedqueries-apply-and-setdefault-label": "Buat penyaringan baku",
        "rcfilters-savedqueries-cancel-label": "Batalkan",
        "rcfilters-savedqueries-add-new-title": "Simpan pengaturan filter ini",
+       "rcfilters-savedqueries-already-saved": "Penyaringan ini telah tersimpan. Ubah pengaturan Anda untuk membuat saringan filter tersimpan baru.",
        "rcfilters-restore-default-filters": "Kembalikan filter bawaan",
        "rcfilters-clear-all-filters": "Hapus semua penyaringan",
        "rcfilters-show-new-changes": "Tampilkan perubahan terbaru",
-       "rcfilters-search-placeholder": "Filter perubahan terbaru (jelajahi atau masukkan input)",
+       "rcfilters-search-placeholder": "Filter perubahan terbaru (gunakan menu atau pencarian untuk menyaring nama)",
        "rcfilters-invalid-filter": "Penyqringan tidak sah",
        "rcfilters-empty-filter": "Tidak ada filter aktif. Semua kontribusi ditampilkan.",
        "rcfilters-filterlist-title": "Penyaringan",
        "uploadstash-bad-path": "Jalur tidak tersedia.",
        "uploadstash-bad-path-invalid": "Jalur tidak valid.",
        "uploadstash-bad-path-unknown-type": "Tipe tidak diketahui \"$1\".",
+       "uploadstash-bad-path-unrecognized-thumb-name": "Nama thumb tidak dikenali.",
+       "uploadstash-bad-path-bad-format": "Kunci \"$1\" bukan format yang layak.",
+       "uploadstash-file-not-found": "Kunci \"$1\" tidak ditemukan dalam penyimpanan.",
+       "uploadstash-file-not-found-no-object": "Tidak dapat membuat objek berkas lokal untuk thumbnail.",
        "invalid-chunk-offset": "Ofset potongan tidak valid",
        "img-auth-accessdenied": "Akses ditolak",
        "img-auth-nopathinfo": "PATH_INFO hilang.\nServer Anda tidak diatur untuk melewatkan informasi ini.\nServer tersebut mungkin berbasis CGI dan tidak dapat mendukung img_auth.\nLihat https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
index aa47a9d..4a945eb 100644 (file)
        "diff-multi-otherusers": "({{PLURAL:$1|Eng Tëscheversioun|$1 Tëscheversioune}} vun {{PLURAL:$2|engem anere|$2}} Benotzer {{PLURAL:$1|gëtt|ginn}} net gewisen)",
        "diff-multi-manyusers": "({{PLURAL:$1|Eng Tëscheversioun|$1 Tëscheversioune}} vu méi wéi $2 {{PLURAL:$2|Benotzer|Benotzer}} ginn net gewisen)",
        "diff-paragraph-moved-tonew": "Den Abschnitt gouf geréckelt. Klickt fir op déi nei Plaz ze sprangen.",
+       "diff-paragraph-moved-toold": "Den Abschnitt gouf geréckelt. Klickt fir op déi al Plaz ze sprangen.",
        "difference-missing-revision": "{{PLURAL:$2|Eng Versioun|$2 Versioune}} vun dëser Differenz ($1) {{PLURAL:$2|gouf|goufen}} net fonnt.\n\nDat geschitt normalerweis wann Dir op e vereelste Link vun enger Versioun vun enger Säit klickt déi geläscht ginn ass.\nDetailer fannt Dir am [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Logbuch vum Läschen].",
        "searchresults": "Resultat vum Sichen",
        "searchresults-title": "Resultater vum Sichen no \"$1\"",
index 2eec11f..9204663 100644 (file)
        "rcfilters-watchlist-markseen-button": "Atzīmēt visas izmaiņas kā apskatītas",
        "rcfilters-watchlist-edit-watchlist-button": "Labot manu uzraugāmo lapu sarakstu",
        "rcfilters-preference-label": "Paslēpt uzlaboto pēdējo izmaiņu versiju",
-       "rcnotefrom": "Šobrīd redzamas izmaiņas kopš '''$2''' (parādītas ne vairāk par '''$1''').",
+       "rcnotefrom": "Zemāk {{PLURAL:$5|redzamas izmaiņas|redzama izmaiņa|redzamas izmaiņas}} kopš <strong>$3, $4</strong> (parādītas ne vairāk kā <strong>$1</strong>).",
        "rclistfromreset": "Atiestatīt datuma izvēli",
        "rclistfrom": "Parādīt jaunas izmaiņas kopš $3 $2",
        "rcshowhideminor": "$1 maznozīmīgos",
        "zip-wrong-format": "Norādītais fails nebija ZIP fails.",
        "uploadstash-errclear": "Failu tīrīšana neizdevās.",
        "uploadstash-refresh": "Atsvaidzināt failu sarakstu",
+       "uploadstash-bad-path-unknown-type": "Nezināms tips \"$1\".",
+       "uploadstash-zero-length": "Faila garums ir nulle.",
        "img-auth-accessdenied": "Pieeja liegta",
        "img-auth-nopathinfo": "Trūkst PATH_INFO.\nJūsu serveris nav konfigurēts nodot šo informāciju.\nTas var būt bāzēts uz CGI un neatbalstīt img_auth.\nSkatīt https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "img-auth-nologinnWL": "Jūs neesat iegājis un \"$1\" nav baltajā sarakstā.",
        "img-auth-nofile": "Fails \"$1\" nepastāv.",
        "img-auth-isdir": "Jūs mēģinājāt piekļūt direktorijai \"$1\".\nAtļauta ir tikai failu piekļuve.",
        "img-auth-streaming": "Straumē \"$1\".",
+       "img-auth-noread": "Lietotājam nav atļaujas nolasīt \"$1\".",
        "http-invalid-url": "Nederīgs URL: $1",
        "http-read-error": "HTTP nolasīšanas kļūda.",
        "http-timed-out": "HTTP pieprasījumam ir iestājies noilgums.",
        "enotif_lastdiff": "$1 lai apskatītos šo izmaiņu.",
        "enotif_anon_editor": "anonīms dalībnieks $1",
        "enotif_body": "$WATCHINGUSERNAME,\n\n\n{{grammar:ģenitīvs|{{SITENAME}}}} lapu $PAGETITLE $CHANGEDORCREATED $PAGEEDITOR, $PAGEEDITDATE, pašreizējā versja ir $PAGETITLE_URL.\n\n$NEWPAGE\n\nIzmaiņu kopsavilkums bija: $PAGESUMMARY $PAGEMINOREDIT\n\nSazināties ar attiecīgo lietotāju:\ne-pasts: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nJa šo uzraugāmo lapu izmainīs vēl, turpmāku paziņojumu par to nebūs, kamēr tu to neatvērsi.\nTu arī vari atstatīt visu uzraugāmo lapu paziņojumu statusus uzraugāmo lapu sarakstā.\n\n             {{grammar:ģenitīvs|{{SITENAME}}}} paziņojumu sistēma\n\n--\nLai izmainītu uzraugāmo lapu saraksta uzstādījumus:\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nLai dzēstu lapu no uzraugāmo lapu saraksta:\n$UNWATCHURL\n\nPapildinformācija:\n$HELPPAGE",
+       "enotif_minoredit": "Šis ir maznozīmīgs labojums",
        "created": "izveidoja",
        "changed": "izmainīja",
        "deletepage": "Dzēst lapu",
        "modifiedarticleprotection": "izmainīja aizsardzības līmeni \"[[$1]]\"",
        "unprotectedarticle": "atcēla \"[[$1]]\" aizsardzību",
        "movedarticleprotection": "pārcēla aizsardzību no \"[[$2]]\" uz \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Aizsargāja}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Izmainīja aizsardzības līmeni}} lapai \"[[$1]]\"",
+       "unprotectedarticle-comment": "{{GENDER:$2|Noņēma aizsardzību}} lapai \"[[$1]]\"",
        "protect-title": "Izmainīt \"$1\" aizsargāšanas līmeni?",
        "protect-title-notallowed": "Apskatīt \"$1\" aizsrdzības līmeni",
        "prot_1movedto2": "\"[[$1]]\" pārdēvēju par \"[[$2]]\"",
        "protectedpagemovewarning": "'''Brīdinājums:''' Šī lapa ir aizsargāta, tikai lietotāji ar administratora privilēģijām var to pārvietot.\nPēdējais reģistra ieraksts ir apskatāms zemāk:",
        "semiprotectedpagemovewarning": "'''Piezīme:''' Šī lapa ir aizsargāta, tikai reģistrētie lietotāji var to pārvietot.\nPēdējais reģistra ieraksts ir apskatāms zemāk:",
        "move-over-sharedrepo": "== Fails jau pastāv ==\n[[:$1]] jau pastāv koplietotā repozitorijā. Pārvietošana uz šo nosaukumu aizstās koplietoto failu.",
+       "file-exists-sharedrepo": "Šis faila nosaukums jau tiek izmantots kopīgajā failu krātuvē.\nLūdzu, izvēlies citu nosaukumu.",
        "export": "Eksportēt lapas",
        "exporttext": "Šeit var eksportēt kādas noteiktas lapas vai lapu kopas tekstus un rediģēšanas hronoloģijas, XML formātā.\nŠādus datus pēc tam varēs ieimportēt citā MediaWiki wiki lietojot [[Special:Import|Importēt lapas]]\n\nLai eksportētu lapas, šajā laukā ievadi to nosaukumus, katrā rindiņā pa vienam, un izvēlies vai gribi tikai pašreizējo versiju ar informāciju par pēdējo izmaiņu, vai arī pašreizējo versiju kopā ar visām vecajām versijām un hronoloģiju\n\nPirmajā gadījumā var arī lietot šādu metodi, piem., [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] lapai \"[[{{MediaWiki:Mainpage}}]]\".",
        "exportall": "Eksportēt visas lapas",
        "minutes": "{{PLURAL:$1|$1 minūtes|$1 minūte|$1 minūtes}}",
        "hours": "{{PLURAL:$1|$1 stundas|$1 stunda|$1 stundas}}",
        "days": "{{PLURAL:$1|$1 dienas|$1 diena|$1 dienas}}",
+       "weeks": "{{PLURAL:$1|$1 nedēļas|$1 nedēļa|$1 nedēļas}}",
+       "months": "{{PLURAL:$1|$1 mēneši|$1 mēnesis|$1 mēneši}}",
+       "years": "{{PLURAL:$1|$1 gadi|$1 gads|$1 gadi}}",
        "ago": "pirms $1",
        "just-now": "tikko",
        "hours-ago": "pirms $1 {{PLURAL:$1|stundām|stundas|stundām}}",
        "confirm-watch-top": "Pievienot šo lapu uzraugāmo lapu sarakstam?",
        "confirm-unwatch-button": "Labi",
        "confirm-rollback-button": "Labi",
+       "confirm-rollback-top": "Atcelt labojumus šajā lapā?",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← iepriekšējā lapa",
        "imgmultipagenext": "nākamā lapa →",
        "imgmultigo": "Aiziet!",
        "compare-title-not-exists": "Norādītais nosaukums neeksistē.",
        "compare-revision-not-exists": "Norādītā versija neeksistē.",
        "diff-form": "Atšķirības",
+       "permanentlink-revid": "Versijas ID",
        "dberr-problems": "Atvainojiet!\nŠai vietnei ir radušās tehniskas problēmas.",
        "dberr-again": "Uzgaidiet dažas minūtes un pārlādējiet šo lapu.",
        "dberr-info": "(Nevar piekļūt datubāzei: $1)",
        "htmlform-chosen-placeholder": "Izvēlieties iespēju",
        "htmlform-cloner-create": "Pievienot vairāk",
        "htmlform-cloner-delete": "Noņemt",
+       "htmlform-date-placeholder": "GGGG-MM-DD",
        "htmlform-title-not-exists": "$1 nepastāv.",
        "logentry-delete-delete": "$1 {{GENDER:$2|izdzēsa}} lapu $3",
        "logentry-delete-delete_redir": "$1 {{GENDER:$2|izdzēsa}} pāradresāciju $3 pārrakstot",
index 6ed95e8..5a48670 100644 (file)
        "viewdeleted": "Да погледате $1?",
        "restorelink": "{{PLURAL:$1|едно избришано уредување|$1 избришани уредувања}}",
        "feedlinks": "Во вид:",
-       "feed-invalid": "Погрешен начин на претплата на емитувања",
-       "feed-unavailable": "RSS/Атом-емитувањата не се достапни",
-       "site-rss-feed": "$1 — RSS-емитувања",
-       "site-atom-feed": "$1 — Атом-емитувања",
-       "page-rss-feed": "„$1“ - RSS емитувања",
-       "page-atom-feed": "„$1“ — Атом-емитувања",
+       "feed-invalid": "Погрешен начин на претплата на тековникот.",
+       "feed-unavailable": "Здружените тековници не се достапни",
+       "site-rss-feed": "RSS-тековник на $1",
+       "site-atom-feed": "Атом-тековник на $1",
+       "page-rss-feed": "RSS-тековник на „$1“",
+       "page-atom-feed": "Атом-тековник на „$1“",
        "feed-atom": "Атом",
        "feed-rss": "RSS",
        "red-link-title": "$1 (страницата не постои)",
        "resettokens-no-tokens": "Нема шифри за враќање.",
        "resettokens-tokens": "Шифри:",
        "resettokens-token-label": "$1 (тековна вредност: $2)",
-       "resettokens-watchlist-token": "Шифра за каналот (Атом/RSS) на [[Special:Watchlist|измени во набљудуваните страници]]",
+       "resettokens-watchlist-token": "Шифра за тековникот (Атом/RSS) на [[Special:Watchlist|измени во набљудуваните]]",
        "resettokens-done": "Шифрата е вратена одново.",
        "resettokens-resetbutton": "Врати избрани шифри",
        "bold_sample": "Задебелен текст",
        "recentchangesdays-max": "(највеќе {{PLURAL:$1|еден ден|$1 дена}})",
        "recentchangescount": "Број на уредувања кои ќе се прикажуваат по основно:",
        "prefs-help-recentchangescount": "Подразбира скорешни промени, истории на страници и дневници.",
-       "prefs-help-tokenmanagement": "Можете да го погледате и одново зададете тајниот клуч з авашата сметка со кој се пристапува до семрежниот канал на вашите набљудувани. Секој еден што го знае клучот може да ви ги ги чита набљудуваните — затоа не го кажувајте никому.",
+       "prefs-help-tokenmanagement": "Можете да го погледате и одново зададете тајниот клуч з авашата сметка со кој се пристапува до семрежниот тековник на вашите набљудувани. Секој еден што го знае клучот може да ви ги ги чита набљудуваните — затоа не го кажувајте никому.",
        "savedprefs": "Вашите нагодувања се зачувани.",
        "savedrights": "Корисничките групи на {{GENDER:$1|$1}} се зачувани.",
        "timezonelegend": "Часовен појас:",
        "recentchanges-noresult": "Нема промени од дадениот период што одговараат на бараното.",
        "recentchanges-timeout": "Ова пребарување истече. Пробајте со поинакви параметри.",
        "recentchanges-network": "Поради техничка грешка, не можев да го вчитам исходот. Превчитајте ја страницата.",
-       "recentchanges-feed-description": "СледеÑ\9aе Ð½Ð° Ð½Ð°Ñ\98Ñ\81коÑ\80еÑ\88ниÑ\82е Ð¿Ñ\80омени Ð½Ð° Ð²Ð¸ÐºÐ¸Ñ\82о Ð²Ð¾ Ð¾Ð²Ð¸Ðµ ÐµÐ¼Ð¸Ñ\82Ñ\83ваÑ\9aа.",
+       "recentchanges-feed-description": "СледеÑ\9aе Ð½Ð° Ð½Ð°Ñ\98Ñ\81коÑ\80еÑ\88ниÑ\82е Ð¿Ñ\80омени Ð½Ð° Ð²Ð¸ÐºÐ¸Ñ\82о Ð²Ð¾ Ð¾Ð²Ð¾Ñ\98 Ñ\82ековник.",
        "recentchanges-label-newpage": "Нова страница",
        "recentchanges-label-minor": "Ова е ситна промена",
        "recentchanges-label-bot": "Ова уредување е направено од бот",
        "img-auth-nologinnWL": "Не сте најавени и „$1“ не е на списокот на допуштени.",
        "img-auth-nofile": "Податотеката „$1“ не постои.",
        "img-auth-isdir": "Се обидувате да пристапите до именикот „$1“.\nДопуштен е само податотечен пристап.",
-       "img-auth-streaming": "Емитување „$1“.",
+       "img-auth-streaming": "Емитување на „$1“.",
        "img-auth-public": "Функцијата на img_auth.php служи за излез на податотеки од лични викија.\nОва вики е нагодено како јавно вики.\nОд причини на оптимална сигурност, img_auth.php е оневозможен.",
        "img-auth-noread": "Корисникот нема пристап за читање на „$1“.",
        "http-invalid-url": "Неважечка URL: $1",
        "tooltip-n-help": "Место каде што може да се информирате.",
        "tooltip-t-whatlinkshere": "Список на сите вики-страници што водат овде",
        "tooltip-t-recentchangeslinked": "Скорешни промени на страници со врски на оваа страница",
-       "tooltip-feed-rss": "RSS емитување за оваа страница",
-       "tooltip-feed-atom": "Атом-емитување за оваа страница",
+       "tooltip-feed-rss": "RSS-тековник за оваа страница",
+       "tooltip-feed-atom": "Атом-тековник за оваа страница",
        "tooltip-t-contributions": "Список на придонеси {{GENDER:$1|на овој корисник}}",
        "tooltip-t-emailuser": "Испрати е-пошта {{GENDER:$1|на овој корисник}}",
        "tooltip-t-info": "Повеќе информаици за страницава",
index 4a3ecee..68d79e1 100644 (file)
        "recentchangesdays-max": "Mássimo: $1 {{PLURAL:$1|die|dies}}",
        "recentchangescount": "Númaro d'eidiçones a apersentar por omisson:",
        "prefs-help-recentchangescount": "Anclui mudanças recentes, stórico de páiginas i registros.",
-       "prefs-help-watchlist-token2": "Esta ye la chabe secreta pa l ''feed'' RSS de la sue lhista de páiginas begiadas.\nQualquiera pessona que coinça la chabe será capaç de lher la sue lhista de páiginas begiadas, por esso nun la dibulgue.\n[[Special:ResetTokens|Clique eiqui pa redefenir eilha]].",
        "timezonelegend": "Fuso hourário:",
        "localtime": "Hora lhocal:",
        "timezoneuseoffset": "Outro (specificar defréncia)",
index f72ad63..cedb445 100644 (file)
        "nosuchusershort": "\"$1\" အမည်ဖြင့် အသုံးပြုသူမရှိပါ။\nစာလုံးပေါင်း ပြန်စစ်ပေးပါရန်။",
        "nouserspecified": "အသုံးပြုသူအမည်ကို ဖော်ပြရမည်ဖြစ်သည်။",
        "login-userblocked": "ဤအသုံးပြုသူကို ပိတ်ပင်ထားသည်။ Login ဝင်ခြင်း ခွင့်မပြုပါ။",
-       "wrongpassword": "á\80\85á\80\80á\80¬á\80¸á\80\9dá\80¾á\80\80á\80ºá\80¡á\80\99á\80¾á\80¬းထည့်ထားသည်။\nကျေးဇူးပြု၍ ပြန်ကြိုးစားကြည့်ပါ။",
+       "wrongpassword": "á\80¡á\80\9eá\80¯á\80¶á\80¸á\80\95á\80¼á\80¯á\80\9eá\80°á\80¡á\80\99á\80\8aá\80º á\80\9eá\80­á\80¯á\80·á\80\99á\80\9fá\80¯á\80\90á\80º á\80\85á\80\80á\80¬á\80¸á\80\9dá\80¾á\80\80á\80º á\80\99á\80¾á\80¬á\80¸á\80\9aá\80½á\80\84á\80ºးထည့်ထားသည်။\nကျေးဇူးပြု၍ ပြန်ကြိုးစားကြည့်ပါ။",
        "wrongpasswordempty": "စကားဝှက်ထည့်ရမည်နေရာ ဗလာဖြစ်နေသည်။\nကျေးဇူးပြု၍ ပြန်ကြိုးစားကြည့်ပါ။",
        "passwordtooshort": "စကားဝှက်တွင် စကားလုံး အနည်းဆုံး {{PLURAL:$1|တစ်လုံး|$1 လုံး}} ရှိရမည်။",
        "password-name-match": "သင့်စကားဝှက်သည် အသုံးပြုသူအမည်နှင့် အတူတူမဖြစ်စေရဘဲ ကွဲပြားရမည်။",
        "showdiff": "ပြင်​ဆင်​ထား​သည်​များ​ကို​ ပြရန်",
        "anoneditwarning": "<strong>သတိပေးချက် - </strong> သင်သည် လော့ဂ်အင် ဝင်မထားပါ။ သင်တည်းဖြတ်မှု ပြုလုပ်ပါက သင့်အိုင်ပီလိပ်စာကို မည်သူမဆို တွေ့မြင်နိုင်မည်။ အကယ်၍ သင် <strong>[$1 လော့ဂ်အင်ဝင်]</strong> သို့မဟုတ် <strong>[$2 အကောင့်တစ်ခု ဖန်တီး]</strong>ပါက၊ သင့်တည်းဖြတ်မှုများသည် သင့်အမည်နှင့် တွဲဖက်မှတ်သားမည် ဖြစ်သည်။",
        "anonpreviewwarning": "သင်သည် logged in ဝင်မထားပါ။ သိမ်းဆည်းမည် ဆိုပါက သင်၏IP အား ဤစာမျက်နှာ မှတ်တမ်းတွင် မှတ်သားထားမည်ဖြစ်ပါသည်။",
-       "missingcommenttext": "á\80\80á\80»á\80±á\80¸á\80\87á\80°á\80¸á\80\95á\80¼á\80¯á\81\8d á\80¡á\80±á\80¬á\80\80á\80ºá\80\90á\80½á\80\84á\80º á\80\99á\80¾á\80\90á\80ºá\80\81á\80»á\80\80á\80ºá\80\90á\80\85á\80ºá\80\81á\80¯á\80\9bá\80±á\80¸á\80\95á\80«á\81\8b",
+       "missingcommenttext": "ကျေးဇူးပြု၍ မှတ်ချက်တစ်ခုရေးပါ။",
        "summary-preview": "တည်းဖြတ်အကျဉ်းချုပ် နမူနာ:",
        "subject-preview": "အကြောင်းအရာ နမူနာ:",
        "blockedtitle": "အသုံးပြုသူကို ပိတ်ပင်ထားသည်",
        "timezoneregion-europe": "ဥရောပ",
        "timezoneregion-indian": "အိန္ဒိယသမုဒ္ဒရာ",
        "timezoneregion-pacific": "ပစိဖိတ်သမုဒ္ဒရာ",
-       "allowemail": "á\80¡á\80\81á\80¼á\80¬á\80¸á\80¡á\80\9eá\80¯á\80¶á\80¸á\80\95á\80¼á\80¯á\80\9eá\80°á\80\99á\80»á\80¬á\80¸á\80\91á\80¶á\80\99á\80¾ á\80¡á\80®á\80¸á\80\99á\80±á\80¸á\80\99á\80»á\80¬á\80¸á\80\80á\80­á\80¯ á\80\9cá\80\80á\80ºá\80\81á\80ရန်",
+       "allowemail": "á\80\80á\80»á\80½á\80\94á\80ºá\80¯á\80\95á\80ºá\80\91á\80¶á\80\9eá\80­á\80¯á\80· á\80¡á\80\81á\80¼á\80¬á\80¸á\80¡á\80\9eá\80¯á\80¶á\80¸á\80\95á\80¼á\80¯á\80\9eá\80°á\80\99á\80»á\80¬á\80¸ á\80¡á\80®á\80¸á\80\99á\80±á\80¸á\80\9cá\80ºá\80\95á\80±á\80¸á\80\95á\80­á\80¯á\80·á\80\81á\80¼á\80\84á\80ºá\80¸á\80\80á\80­á\80¯ á\80\81á\80½á\80\84á\80·á\80ºá\80\95á\80¼á\80¯ရန်",
        "prefs-searchoptions": "ရှာဖွေရန်",
        "prefs-namespaces": "အမည်ညွှန်း",
        "default": "ပုံမှန်အားဖြင့်",
        "rcfilters-days-show-days": "$1 {{PLURAL:$1|ရက်|ရက်}}",
        "rcfilters-days-show-hours": "$1 {{PLURAL:$1|နာရီ|နာရီ}}",
        "rcfilters-quickfilters": "သိမ်းထားသော filter များ",
-       "rcfilters-quickfilters-placeholder-title": "မည်သည့် လင့်ခ်မှ မသိမ်းရသေးပါ",
+       "rcfilters-quickfilters-placeholder-title": "မည်သည့် filter မှ မသိမ်းရသေးပါ",
        "rcfilters-savedqueries-defaultlabel": "သိမ်းထားသော filter များ",
        "rcfilters-savedqueries-rename": "အမည်ပြန်ပြောင်းရန်",
        "rcfilters-savedqueries-setdefault": "မူလပုံသေအဖြစ် သတ်မှတ်ရန်",
        "rcfilters-filter-user-experience-level-unregistered-label": "မှတ်ပုံမတင်ထားသူ",
        "rcfilters-filter-user-experience-level-unregistered-description": "အကောင့်မဝင်ထားသည့် တည်းဖြတ်သူများ။",
        "rcfilters-filter-user-experience-level-newcomer-label": "လူသစ်များ",
-       "rcfilters-filter-user-experience-level-newcomer-description": "တည်းဖြတ်မှု ၁၀ ကြိမ်အောက်နှင့် လုပ်ကိုင်မှု ၄ ရက်အောက်ရှိသော မှတ်ပုံတင်ထားသည့် တည်းဖြတ်သူများ။",
+       "rcfilters-filter-user-experience-level-newcomer-description": "တည်းဖြတ်မှု ၁၀ ကြိမ်အောက် သို့မဟုတ် လုပ်ကိုင်မှု ၄ ရက်အောက်ရှိသော မှတ်ပုံတင်ထားသည့် တည်းဖြတ်သူများ။",
        "rcfilters-filter-user-experience-level-learner-label": "လေ့လာသူများ",
        "rcfilters-filter-user-experience-level-learner-description": "\"လူသစ်များ\" နှင့် \"အတွေ့အကြုံရှိ အသုံးပြုသူများ\" အကြားရှိ မှတ်ပုံတင်ထားသော တည်းဖြတ်သူများ။",
        "rcfilters-filter-user-experience-level-experienced-label": "အတွေ့အကြုံရှိ အသုံးပြုသူများ",
index e913e34..363d7bd 100644 (file)
        "youhavenewmessagesfromusers": "{{PLURAL:$4|Você tem}} $1 de {{PLURAL:$3|outro usuário|$3 usuários}} ($2).",
        "youhavenewmessagesmanyusers": "Você tem $1 de muitos usuários ($2).",
        "newmessageslinkplural": "{{PLURAL:$1|uma mensagem nova|999=mensagens novas}}",
-       "newmessagesdifflinkplural": "último {{PLURAL:$1|mudança|999=mudanças}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|última mudança|999=últimas mudanças}}",
        "youhavenewmessagesmulti": "Você tem novas mensagens em $1",
        "editsection": "editar",
        "editold": "editar",
index 654ac6a..83c8a93 100644 (file)
                        "Mainframe98",
                        "Pginer",
                        "Wladek92",
-                       "Gombang"
+                       "Gombang",
+                       "Trizek (WMF)"
                ]
        },
        "sidebar": "{{notranslate}}",
        "rcfilters-filter-user-experience-level-unregistered-label": "Label for the filter for showing edits made by anonymous editors.",
        "rcfilters-filter-user-experience-level-unregistered-description": "Description for the filter for showing edits made by anonymous editors.",
        "rcfilters-filter-user-experience-level-newcomer-label": "Label for the filter for showing edits made by new editors.",
-       "rcfilters-filter-user-experience-level-newcomer-description": "Description for the filter for showing edits made by new editors.",
+       "rcfilters-filter-user-experience-level-newcomer-description": "Description for the filter for showing edits made by new editors. The user has created the account less than 4 days ago (4th day included) ''or'' has made less than 10 edits (10 included).",
        "rcfilters-filter-user-experience-level-learner-label": "Label for the filter for showing edits made by learning editors.",
        "rcfilters-filter-user-experience-level-learner-description": "Description for the filter for showing edits made by learning editors.",
        "rcfilters-filter-user-experience-level-experienced-label": "Label for the filter for showing edits made by experienced editors.",
index a3299ed..2f34f98 100644 (file)
        "diff-multi-sameuser": "(не {{PLURAL:$1|показана $1 промежуточная версия|показаны $1 промежуточные версии|показано $1 промежуточных версий}} этого же участника)",
        "diff-multi-otherusers": "(не {{PLURAL:$1|показана $1 промежуточная версия|показаны $1 промежуточные версии|показано $1 промежуточных версий}} {{PLURAL:$2|$2 участника|$2 участников}})",
        "diff-multi-manyusers": "({{PLURAL:$1|не показана $1 промежуточная версия, сделанная|не показаны $1 промежуточных версий, сделанных|не показаны $1 промежуточные версии, сделанные}} более чем {{PLURAL:$2|$2 участником|$2 участниками}})",
+       "diff-paragraph-moved-tonew": "Параграф был перемещён. Нажмите, чтобы перейти к новому местоположению.",
+       "diff-paragraph-moved-toold": "Пункт был перемещен. Нажмите, чтобы перейти к старому местоположению.",
        "difference-missing-revision": "Не {{PLURAL:$2|1=найдена|найдены}} {{PLURAL:$2|$2 версия|$2 версий|$2 версии|1=одна из версий}} для этого сравнения ($1).\n\nТакое обычно случается при переходе по устаревшей ссылке сравнения версий для страницы, которая была удалена.\nПодробности могут быть в [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале удалений].",
        "searchresults": "Результаты поиска",
        "searchresults-title": "Поиск «$1»",
        "prefs-watchlist-edits": "Максимальное количество правок для показа в списке наблюдения:",
        "prefs-watchlist-edits-max": "Наибольшее значение: 1000",
        "prefs-watchlist-token": "Токен списка наблюдения:",
+       "prefs-watchlist-managetokens": "Управление токенами",
        "prefs-misc": "Другие настройки",
        "prefs-resetpass": "Изменить пароль",
        "prefs-changeemail": "изменить или удалить адрес электронной почты",
        "recentchangesdays-max": "(не более $1 {{PLURAL:$1|дня|дней}})",
        "recentchangescount": "Количество правок, отображаемое по умолчанию:",
        "prefs-help-recentchangescount": "Включает свежие правки, истории страниц, журналы.",
+       "prefs-help-tokenmanagement": "Вы можете просмотреть и сбросить для своей учётной записи секретный ключ, который может получить доступ к веб-каналу вашего списка наблюдения. Любой, кто знает ключ, сможет прочитать ваш список наблюдения, поэтому не делитесь им ни с кем.",
        "savedprefs": "Настройки сохранены.",
        "savedrights": "Группы {{GENDER:$1|участника|участницы}} $1 были сохранены.",
        "timezonelegend": "Часовой пояс:",
        "uploadstash-bad-path": "Путь не существует.",
        "uploadstash-bad-path-invalid": "Путь некорректен.",
        "uploadstash-bad-path-unknown-type": "Неизвестный тип «$1».",
+       "uploadstash-bad-path-unrecognized-thumb-name": "Нераспознанное имя миниатюры.",
        "uploadstash-file-not-found-no-thumb": "Не удалось получить миниатюру.",
        "uploadstash-file-not-found-missing-content-type": "Отсутствует заголовок content-type.",
        "uploadstash-wrong-owner": "Этот файл ($1) не принадлежит текущему участнику.",
+       "uploadstash-no-extension": "Пустое расширение.",
        "uploadstash-zero-length": "Файл нулевой длины.",
        "invalid-chunk-offset": "Недопустимое смещение фрагмента",
        "img-auth-accessdenied": "Доступ запрещён",
index f0e42bf..beaf3a0 100644 (file)
        "sunday": "ᱥᱤᱸᱜᱮ ᱢᱟᱦᱟᱸ",
        "monday": "ᱚᱛᱮ ᱢᱟᱦᱟᱸ",
        "tuesday": "ᱵᱟᱞᱮ ᱢᱟᱦᱟᱸ",
-       "wednesday": "Budh",
-       "thursday": "Lukhibar",
+       "wednesday": "ᱥᱟᱹᱜᱩᱱ ᱢᱟᱦᱟᱸ",
+       "thursday": "ᱥᱟᱹᱨᱫᱤ ᱢᱟᱦᱟᱸ",
        "friday": "ᱡᱟᱹᱨᱩᱢ ᱢᱟᱦᱟᱸ",
        "saturday": "ᱧᱩᱦᱩᱢ ᱢᱟᱦᱟᱸ",
-       "sun": "Aṭhwar",
-       "mon": "Som",
+       "sun": "ᱥᱤᱸᱜᱮ ᱢᱟᱦᱟᱸ",
+       "mon": "ᱚᱛᱮ ᱢᱟᱦᱟᱸ",
        "tue": "ᱵᱟᱞᱮ ᱢᱟᱦᱟᱸ",
-       "wed": "Budhbar",
-       "thu": "Lukhibar",
-       "fri": "Sokolbar",
-       "sat": "Sạnicar",
+       "wed": "ᱥᱟᱹᱜᱩᱱ ᱢᱟᱦᱟᱸ",
+       "thu": "ᱥᱟᱹᱨᱫᱤ ᱢᱟᱦᱟᱸ",
+       "fri": "ᱡᱟᱹᱨᱩᱢ ᱢᱟᱦᱟᱸ",
+       "sat": "ᱧᱩᱦᱩᱢ",
        "january": "ᱡᱟᱱᱩᱣᱟᱨᱤ",
        "february": "ᱯᱷᱮᱵᱽᱨᱩᱣᱟᱨᱤ",
        "march": "ᱢᱟᱨᱪ",
        "october": "ᱚᱠᱴᱚᱵᱚᱨ",
        "november": "ᱱᱚᱵᱷᱮᱢᱵᱚᱨ",
        "december": "ᱰᱤᱥᱮᱢᱵᱟᱨ",
-       "january-gen": "Jạnuạri",
+       "january-gen": "ᱡᱟᱱᱩᱣᱟᱨᱤ",
        "february-gen": "ᱯᱷᱮᱵᱽᱨᱩᱣᱟᱨᱤ",
-       "march-gen": "Marc",
+       "march-gen": "ᱢᱟᱨᱪ",
        "april-gen": "Epril",
        "may-gen": "Me",
        "june-gen": "Jun",
        "july-gen": "Julại",
        "august-gen": "Ago̠sṭ",
        "september-gen": "Se̠ṕṭembo̠r",
-       "october-gen": "O̠ḱ́ṭo̠bo̠r",
+       "october-gen": "ᱚᱠᱴᱚᱵᱚᱨ",
        "november-gen": "Nove̠mbo̠r",
-       "december-gen": "December",
+       "december-gen": "ᱰᱤᱥᱮᱢᱵᱚᱨ",
        "jan": "ᱡᱟᱱᱩᱣᱟᱨᱤ",
        "feb": "ᱯᱷᱮᱵᱽᱨᱩᱣᱟᱨᱤ",
        "mar": "ᱢᱟᱨᱪ",
        "october-date": "ᱚᱠᱴᱚᱵᱚᱨ $1",
        "november-date": "ᱱᱚᱵᱷᱮᱢᱵᱚᱨ $1",
        "december-date": "ᱰᱤᱥᱮᱢᱵᱚᱨ $1",
-       "pagecategories": "{{PLURAL:$1|Bivag|Bivagko}}",
-       "category_header": "Sakam korenaḱ rokom sokom \"$1\"",
+       "pagecategories": "{{PLURAL:$1|ᱛᱷᱚᱠ|ᱛᱷᱚᱠᱠᱩ}}",
+       "category_header": "ᱛᱷᱚᱠ ᱨᱮᱱ ᱥᱟᱦᱴᱟᱞᱩ \"$1\"",
        "subcategories": "Huḍiń rokom sokomko",
        "category-media-header": "\"$1\" babot reaḱ rokom sokomte emen meḍiya rẽtko",
        "category-empty": "\"Noa rokom sokom sakamre do nit jahan sakam se miḍiya rẽt do bạnuḱa.\"",
-       "hidden-categories": "{{PLURAL:$1|Dãnań renaḱ|Dãnań renaḱ ko}}",
+       "hidden-categories": "{{PLURAL:$1|ᱫᱟᱱᱟᱝ ᱛᱷᱚᱠ|ᱫᱟᱱᱟᱝ ᱛᱷᱚᱠᱠᱩ}}",
        "hidden-category-category": "Uku akan rokom sokom ko",
        "category-subcat-count": "{{PLURAL:$2| keṭagorire eken tayom hudińkeṭagori menaḱa. |Noa keṭagorire tayom menaḱa {{PLURAL:$1 hudińkeṭagoriko}}, jotokote $2}}",
        "category-subcat-count-limited": "Noa rokom sokomre latar reaḱ {{PLURAL:$1 gan kạṭic rokom sokom $1gan kạtic rokom sokom menaḱa}}",
        "about": "Lạgitte, Lạgti",
        "article": "ᱩᱱᱩᱫᱩᱜ ᱥᱟᱦᱴᱟ",
        "newwindow": "Nãwã khiṛki jhijme",
-       "cancel": "Badme",
+       "cancel": "ᱵᱟᱫᱽ",
        "moredotdotdot": "Aema",
        "mypage": "In̕aḱ sakam",
-       "mytalk": "Galmarao",
+       "mytalk": "ᱨᱚᱲ",
        "anontalk": "Nui baṅ ńutumanić beoharićaḱ galmarao sakam",
        "navigation": "ᱟᱹᱪᱩᱨᱵᱟᱲᱟ",
        "and": "&#32;ᱟᱨ",
        "permalink": "ᱛᱤᱨᱮᱡᱩᱜᱮ ᱡᱚᱱᱚᱲ",
        "print": "Chapa",
        "view": "ᱩᱰᱩᱜᱽᱢᱮ",
-       "view-foreign": "$1 re ńelme",
+       "view-foreign": "$1 ᱨᱮ ᱧᱮᱞ ᱢᱮ",
        "edit": "ᱥᱟᱯᱲᱟᱣ",
        "create": "Tearme",
        "create-local": "ᱢᱮᱥᱟᱭᱢᱮ ᱠᱟᱛᱷᱟ ᱠᱚ",
        "categorypage": "Babot reaḱ rokom sokom udugmẽ",
        "viewtalkpage": "Galmarao ńelme",
        "otherlanguages": "ᱮᱴᱟᱜ ᱯᱟᱹᱨᱥᱤ ᱛᱮ",
-       "redirectedfrom": "$1 khon ạcur heć akana",
+       "redirectedfrom": "($1 ᱠᱷᱚᱱ ᱟᱹᱪᱩᱨ ᱦᱮᱡᱠᱟᱱᱟ)",
        "redirectpagesub": "ᱵᱟᱝ ᱥᱚᱡᱽᱦᱮ ᱥᱟᱦᱴᱟ",
        "redirectto": "Ar hõ udugoḱakana:",
        "lastmodifiedat": "ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱢᱩᱪᱟᱹᱫ ᱫᱷᱟᱣ ᱵᱚᱫᱚᱞ ᱟᱠᱟᱱᱟ  $1 ᱢᱟᱹᱦᱤᱛ,  $2 ᱚᱠᱛᱚᱨᱮ",
        "currentevents-url": "Project: ᱱᱤᱛᱚᱜ ᱠᱷᱚᱵᱚᱨᱠᱳ",
        "disclaimers": "ᱫᱟᱹᱵᱤ ᱵᱟᱱᱩᱜᱠᱳ",
        "disclaimerpage": "Project: ᱥᱟᱫᱷᱟᱨᱚᱱ ᱫᱟᱹᱵᱤ ᱵᱟᱱᱩᱜᱠᱩ",
-       "edithelp": "Tońge goṛo",
+       "edithelp": "ᱥᱟᱯᱲᱟᱣ ᱜᱚᱸᱲᱚᱸ",
        "helppage-top-gethelp": "ᱜᱚᱲᱚ",
        "mainpage": "ᱢᱩᱬᱩᱛ ᱥᱟᱦᱴᱟ",
        "mainpage-description": "ᱢᱩᱬᱩᱛ ᱥᱟᱦᱴᱟ",
        "newmessagesdifflinkplural": "ᱢᱩᱪᱟᱹᱫ {{PLURAL:$1|ᱵᱚᱫᱚᱞ|999=ᱵᱚᱫᱚᱞᱠᱚ}}",
        "youhavenewmessagesmulti": "Amaḱ nãwã mesagko do $1 menaḱa",
        "editsection": "ᱥᱟᱯᱲᱟᱣ",
-       "editold": "Toṅge",
+       "editold": "ᱥᱟᱯᱲᱟᱣ",
        "viewsourceold": "Ńamoḱ jayga",
-       "editlink": "Tońge",
+       "editlink": "ᱥᱟᱯᱲᱟᱣ",
        "viewsourcelink": "ᱯᱷᱮᱰᱟᱛ ᱦᱚᱨ ᱧᱮᱞᱢᱮ",
        "editsectionhint": "ᱥᱟᱯᱲᱟᱣ ᱡᱟᱭᱜᱟ: $1",
        "toc": "ᱩᱱᱩᱫᱩᱜ",
        "nstab-media": "Media ᱥᱟᱦᱴᱟ",
        "nstab-special": "ᱚᱥᱚᱠᱟᱭᱛᱮᱭᱟᱜ ᱥᱟᱦᱴᱟ",
        "nstab-project": "ᱯᱨᱚᱡᱮᱠᱴ ᱥᱟᱦᱴᱟ",
-       "nstab-image": "Phayel",
+       "nstab-image": "ᱨᱮᱫ",
        "nstab-mediawiki": "Mesag",
        "nstab-template": "ᱪᱷᱟᱸᱪ",
        "nstab-help": "ᱜᱚᱸᱲᱚ ᱥᱟᱦᱴᱟ",
-       "nstab-category": "Juṛu ko",
+       "nstab-category": "ᱛᱷᱚᱠ",
        "mainpage-nstab": "ᱢᱩᱬᱩᱛ ᱥᱟᱦᱴᱟ",
        "nosuchaction": "Noṅkanaḱ kạmi bạnuḱa",
        "nosuchactiontext": "Noa URL re goṭa akan kạmi do ạnlekate baṅkana.\nAm do paseć mit́ṭen vul joṛaoem emakada se URL oltem vul akada.\nNoa do noṅkanaḱ menkana je {{SITENAME}} sayeṭre beoharen sofṭower re mit́ṭen vul menaḱa.",
        "userlogin-remembermypassword": "Bolo thirege dohokạńme",
        "yourdomainname": "Amaḱ ḍomen:",
        "externaldberror": "Hoe daṛeyaḱa jahan bahre reaḱ jacaeaḱ ḍaṭabes vul hoeakana se amaḱ bahre reaḱ ekaunṭ do nahaḱ halot aguire ạidạri bạnuḱa.",
-       "login": "bolok' duar",
+       "login": "ᱵᱚᱞᱚᱜ ᱢᱮ",
        "nav-login-createaccount": "Boloḱ́ duạr / ekaunt tearme",
        "logout": "Bahre oḍoń",
        "userlogout": "Bahre oḍoń",
        "createaccount": "Ṭhai benaome",
        "userlogin-resetpassword-link": "Amaḱ uku nambarem hiṛiń akada?",
        "userlogin-helplink2": "Bolon khạtir go̠ṛo̠",
+       "createacct-emailrequired": "ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ",
        "createacct-emailoptional": "Email ṭhikana (iccha lekate)",
        "createacct-email-ph": "Amaḱ e-mail ṭhikana emme",
+       "createacct-another-email-ph": "ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱟᱫᱮᱨᱢᱮ",
        "createaccountmail": "E-mail hotete",
        "createacct-submit": "Amaḱ account tearme",
+       "createacct-another-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱢᱮ",
+       "createacct-continue-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨ ᱛᱚᱝᱜᱮᱢᱮ",
+       "createacct-another-continue-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨ ᱛᱚᱝᱜᱮᱢᱮ",
        "createacct-benefit-heading": "{{SITENAME}} am lekan hoṛ hotete tear akan.",
        "createacct-benefit-body1": "{{PLURAL:$1|joṛao|joṛaoko}}",
        "createacct-benefit-body2": "{{PLURAL:$1|ᱥᱟᱦᱴᱟ|ᱥᱟᱦᱴᱟᱠᱳ}}",
        "badretype": "Am do okaṭaḱ oku nambarkom em keda ona do baṅ milạolena.",
        "userexists": "Laṛcaṛicaḱ ńutum em hoyena ona do beohar hoyakana.\nDayakatet́ eṭagaḱ ńutum bachaome.",
        "loginerror": "Bhitri bolok do vulgea",
+       "createacct-error": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨ ᱦᱩᱲᱟᱹᱜ",
        "createaccounterror": "Ekaunṭ do baṅ tear lena: $1",
        "nocookiesnew": "Beoharićaḱ ekaunṭ tear hoe akana, menkhan am do nit hạbićte ekaunṭre bam boloakana. {{SITENAME}} re kuki beohar kate beoharićaḱ ekaunṭre boloa.\nAmaḱ sendrare kukiko bondo hoeakana. Dayakate kukiko kạmi hoe ocoemẽ ar amaḱ nãwã beohar ńutum ar uku nambar beohar hotete noa ekaunṭre boloḱmẽ.",
        "nocookieslogin": "{{SITENAME}} re kuki hotete beoharićaḱ bhitri boloḱ do hoyoḱa. Amaḱ sendrare kuki bondo menaḱa. Kuki cạlu kate arhõ kurumuṭuimẽ.",
        "pt-login": "ᱵᱚᱞᱚᱜ ᱫᱩᱭᱟᱹᱨ",
        "pt-login-button": "Bolon",
        "pt-createaccount": "ᱴᱷᱟᱭ ᱵᱮᱱᱟᱣᱢᱮ",
-       "pt-userlogout": "Bahre oḍoń",
+       "pt-userlogout": "ᱚᱰᱚᱠᱚᱜ ᱢᱮ",
        "user-mail-no-addy": "Jahan e-mail ṭhikana bạgi kate e-mail kul kurumuṭu hoena.",
        "changepassword": "Uku nombor bodolme",
        "resetpass_header": "Ekaunṭ oku namber bodol",
        "retypenew": "Doṛhate oku namber olme",
        "resetpass_submit": "Oku namber joṛao ar bhitri bolok",
        "changepassword-success": "Amaḱ oku namber do napayte bodolena!\nNitoḱ do am bhitritem boloḱkana...",
+       "botpasswords-createnew": "ᱱᱟᱶᱟ ᱵᱚᱴ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱛᱮᱭᱟᱨᱢᱮ",
+       "botpasswords-label-appid": "ᱵᱚᱴ ᱧᱩᱛᱩᱢ:",
        "botpasswords-label-create": "ᱛᱮᱭᱟᱨ",
+       "botpasswords-label-update": "ᱟᱹᱨᱩ ᱯᱷᱮᱨᱟᱣ",
        "botpasswords-label-delete": "ᱜᱮᱫ ᱜᱤᱰᱤ",
        "resetpass_forbidden": "Oku namber do baṅ bodoloklena",
        "resetpass-no-info": "Noa sakam sojhete laṛcaṛ lạgit́te am do bhitri boloḱ hoyoḱtama.",
        "italic_sample": "Beka onol",
        "italic_tip": "Beka onol",
        "link_sample": "Joṛaotet́ reaḱ bohoḱ",
-       "link_tip": "Bhitri reak joṛaotet́",
+       "link_tip": "ᱵᱷᱤᱛᱨᱤ ᱡᱚᱱᱚᱲ",
        "extlink_sample": "http://www.nạmuna.makaṛgạṭi ạmạli",
        "extlink_tip": "Baherenaḱ jońṛao (disạyme http://prefix)",
        "headline_sample": "Bohok katha",
        "nowiki_sample": "Begor format olko bhoraome",
        "nowiki_tip": "wiki formatting bạgiyaḱme",
        "image_tip": "Tol Fael",
-       "media_tip": "file reaḱ jońṛao",
+       "media_tip": "ᱨᱮᱫ ᱡᱚᱱᱚᱲ",
        "sig_tip": "Amaḱ suhi sãote okte",
        "hr_tip": "Barabạri dag",
        "summary": "Guṭ katha",
        "subject": "Bisoy/Bohoḱ katha:",
-       "minoredit": "Noa do hudiń joṛao kami",
+       "minoredit": "ᱱᱚᱣᱟ ᱫᱚ ᱦᱩᱰᱤᱧ ᱥᱟᱯᱲᱟᱣ ᱠᱟᱱᱟ",
        "watchthis": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱧᱮᱞᱢᱮ",
        "savearticle": "ᱥᱟᱦᱴᱟ ᱫᱚᱦᱚᱭᱢᱮ",
        "preview": "Ńel, Unuduḱ",
        "showpreview": "Unuduḱ",
-       "showdiff": "Bodolko ńeloḱma",
+       "showdiff": "ᱵᱚᱫᱚᱞᱠᱩ ᱩᱫᱩᱜᱽ ᱢᱮ",
        "anoneditwarning": "<strong>ᱦᱩᱥᱤᱭᱟᱹᱨ:</strong> ᱟᱢ ᱵᱟᱢ ᱵᱚᱞᱚᱣᱟᱠᱟᱱᱟ ᱾ ᱡᱩᱫᱤ ᱟᱢ ᱡᱟᱦᱟᱸᱱᱟᱜ ᱥᱟᱯᱲᱟᱣᱟᱢ ᱟᱢᱟᱜ IP ᱵᱩᱴᱟᱹ ᱥᱚᱫᱚᱨ ᱛᱟᱦᱮᱸᱱᱟ ᱾ ᱡᱩᱫᱤ ᱟᱢ [$1 ᱵᱚᱞᱚᱱᱟᱢ]</strong> ᱟᱨᱵᱟᱝ <strong>[$2 ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱟᱢ]</strong>, ᱟᱢᱟᱜ ᱥᱟᱯᱲᱟᱣ ᱫᱚ ᱩᱫᱩᱜᱚᱜ-ᱟ ᱟᱢᱟᱜ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱧᱩᱛᱩᱢ, ᱥᱟᱶᱛᱮ ᱮᱴᱟᱜ ᱥᱩᱵᱤᱫᱷᱟ ᱠᱚ ᱾",
        "anonpreviewwarning": "\"Am do bhitri bam bolo akana. Noa sakamre amaḱ kạmiko jạre IP ṭhiikạ̣nare rukhiyạ ḱa.\"",
        "missingcommenttext": "Daya kate amaḱ menaḱ katha latare olmẽ.",
        "whitelistedittext": "Sakamre sompadon lạgit́te $1 em hoyoḱa.",
        "nosuchsectiontitle": "Pahaṭa bȧn ńamlena",
        "loginreqtitle": "Boloḱ jạruṛa",
-       "loginreqlink": "Bhitri boloḱ",
+       "loginreqlink": "ᱵᱚᱞᱚᱜ ᱢᱮ",
        "loginreqpagetext": "Eṭagaḱ sakamko ńel lạgit́te do am $1 hoyoḱ jạruṛtama.",
        "accmailtitle": "Uku nambar do kulena.",
        "accmailtext": "[[User talk:$1 $1]] lạgit́te aćte benaoen uku nambar do $2 kul hoena.\nBhitri bolo kateḱ noa nãwã ekaunṭ lạgit uku nambar \"[[Special:ChangePassword Change password]]\" sakam khonem bodol daṛyakya.",
        "newarticle": "(Nãwa)",
        "newarticletext": "Am do oka mitṭen joṛaoem pańja akada, onaṭak do bạnuḱa.\nOna sakam tear lạgit́te, latar reaḱ baksore ol ehoṕmẽ (arhõ jạsti baḍae lạgit́te [$1 help page] pańjaemẽ).\nAm do judi nonḍe vulkatem heć akan khan, tobe amaḱ sendrakore '''back''' baṭon linmẽ.",
        "anontalkpagetext": "----\n\n<em>ᱱᱚᱶᱟ ᱫᱚ ᱜᱟᱞᱚᱪ ᱥᱟᱦᱴᱟ ᱠᱟᱱᱟ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱚᱣᱟᱜ ᱡᱟᱦᱟᱸᱭ ᱫᱚ ᱠᱷᱟᱛᱟ ᱵᱟᱭ ᱛᱮᱭᱟᱨ ᱟᱠᱟᱫᱟ ᱱᱤᱛ ᱦᱟᱹᱵᱤᱡ, ᱟᱨᱵᱟᱝ ᱡᱟᱦᱟᱸᱭ ᱵᱮᱵᱷᱟᱨ ᱟᱠᱟᱫᱟ ᱱᱚᱶᱟ ᱾</em>\nᱚᱱᱟᱛᱮ ᱟᱞᱮ ᱮᱞᱮᱞ IP ᱞᱮ ᱵᱮᱵᱷᱟᱨᱮᱜ-ᱟ ᱩᱱᱤ ᱪᱤᱱᱦᱟᱹᱣ ᱞᱟᱹᱜᱤᱫ ᱾\nᱚᱱᱠᱟᱱ IP ᱵᱩᱴᱟᱹ ᱫᱚ ᱦᱟᱹᱴᱤᱧ ᱫᱟᱲᱮᱭᱟᱜ-ᱟ ᱛᱤᱢᱤᱱ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱫᱟᱨᱟᱭᱛᱮ ᱾\nᱡᱩᱫᱤ ᱟᱢ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱟᱱᱟᱢ ᱟᱨ ᱵᱷᱟᱹᱵᱤᱭᱮᱜ-ᱟᱢ ᱵᱟᱝ ᱡᱚᱲᱟᱣᱟᱱ ᱠᱟᱛᱷᱟ ᱟᱢᱮ ᱩᱫᱩᱜᱢᱮ ᱠᱟᱱᱟ, ᱮᱱᱠᱷᱟᱱ  [[Special:CreateAccount|ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱢᱮ]] ᱟᱨᱵᱟᱝ [[Special:UserLogin|ᱞᱚᱜᱤᱱ]] ᱢᱮ ᱫᱟᱨᱟᱭ ᱵᱷᱮᱣᱱᱟ ᱠᱚ ᱥᱟᱦᱟᱭ ᱞᱟᱹᱜᱤᱫ ᱮᱴᱟᱜ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱚ ᱥᱟᱶ ᱾",
-       "noarticletext": "Nitoḱ noa sakamre do cet́olge bạnuḱa.\n\nAm menlekhan eṭaḱ sakamkore [[Special:Search/{{PAGENAME}}|search for this page title]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page]</span>.",
+       "noarticletext": "ᱱᱮᱛᱚᱜ ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟᱨᱮ ᱪᱮᱫᱜᱮ ᱵᱟᱹᱱᱩᱜ-ᱟ᱾\nᱮᱴᱟᱜ ᱥᱟᱦᱴᱟᱨᱮᱢ [[Special:Search/{{PAGENAME}}|search for this page title]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page]</span>.",
        "noarticletext-nopermission": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟᱨᱮ ᱱᱤᱛᱚᱜ ᱪᱮᱫᱜᱮ ᱚᱞ ᱵᱟᱹᱱᱩᱜ-ᱟ᱾\n\nᱟᱢ [[Special:Search/{{PAGENAME}}|ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟᱨᱮᱱᱟᱜ ᱧᱤᱛᱩᱢᱮᱢ ᱥᱮᱸᱫᱽᱨᱟ ᱫᱟᱲᱮᱭᱟᱜ-ᱟ]] ᱮᱴᱟᱜ ᱥᱟᱦᱴᱟ ᱠᱚᱨᱮᱦᱚᱸ,\nᱟᱨᱵᱟᱝ <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>.",
        "userpage-userdoesnotexist": "\"<nowiki>$1</nowiki>\" ń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": "Beoharićaḱ \"$1\" ekaunṭ do baṅ resṭire akana.",
        "yourdiff": "Farak",
        "templatesused": "Noa sakamre beoharen {{PLURAL:$1 ṭempeleṭ ṭempeleṭko}}:",
        "templatesusedpreview": "{{PLURAL:$1|ᱪᱷᱟᱸᱪ|ᱪᱷᱟᱸᱪᱠᱚ}} ᱵᱮᱵᱷᱟᱨ ᱟᱠᱟᱱᱟ ᱱᱟᱶᱟ ᱧᱮᱱᱮᱞᱨᱮ:",
-       "template-protected": "Rukhiạ",
+       "template-protected": "(ᱨᱩᱠᱷᱤᱭᱟᱹ)",
        "template-semiprotected": "(Kạṭic-rukhiyạ)",
        "hiddencategories": "Noa sakam do {{PLURAL:$1 1 ukuakan bhag $1 uku akan bhagkorenaḱ}} gaõtarenge:",
        "nocreate-loggedin": "Nãwã sakam tear lạgit́te am do ạidạri em baṅ hoeakana.",
        "previousrevision": "ᱯᱟᱹᱦᱤᱞ ᱯᱟᱲᱦᱟᱣ ᱨᱩᱭᱟᱹᱣ",
        "nextrevision": "nãwate n'el ruar",
        "currentrevisionlink": "Nitoḱaḱ nãwa aroy",
-       "cur": "Boge",
+       "cur": "ᱱᱮᱛᱚᱜ",
        "next": "Laha seć",
-       "last": "Laha renaḱ",
+       "last": "ᱞᱟᱦᱟ ᱛᱮᱱᱟᱜ",
        "page_first": "Pahilaḱ",
        "page_last": "Mucạt́aḱ",
        "histlegend": "Farak bachao: oka nãwã aroeko tulạoem menet́kan, onako cinhạ em kate boloḱ se latar baṭon linmẽ.<br />\nUnuduḱ: '''({{int:cur}})''' = nahaḱ nãwã aroeko saõte tulạo, '''({{int:last}})''' = laha reaḱ nãwã aroe sãote tulạo, '''{{int:minoreditletter}}''' = huḍiń sompadon.",
        "searchresults-title": "\"$1\"  ᱨᱮᱱᱟᱜ ᱥᱮᱸᱫᱽᱨᱟ ᱯᱷᱚᱞ",
        "prevn": "Laha reaḱ {{PLURAL:$1|$1}}",
        "nextn": "Táyom teaḱ {{PLURAL:$1|$1}}",
+       "prev-page": "ᱯᱟᱪᱮ ᱥᱟᱦᱴᱟ",
+       "next-page": "ᱫᱟᱨᱟᱭ ᱥᱟᱦᱴᱟ",
        "prevn-title": "Laha renaḱ sakam $1 {{PLURAL:$1|result|results}}",
        "nextn-title": "Tayom $1 {{PLURAL:$1|result|results}}",
        "shown-title": "ᱥᱟᱦᱴᱟ $1 {{PLURAL:$1|ᱚᱨᱡᱚ|ᱚᱨᱡᱚᱠᱳ}} ᱩᱰᱩᱜᱽᱢᱮ",
        "viewprevnext": "Ńelme ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''Noa wiki re do \"[[:$1]] ńutum sakam menaḱa",
        "searchmenu-new": "<strong>ᱥᱟᱦᱴᱟ ᱛᱮᱭᱟᱨ ᱢᱮ \"[[:$1]]\" ᱱᱚᱶᱟ ᱣᱤᱠᱤ ᱨᱮ!</strong> {{PLURAL:$2|0=|ᱟᱢᱟᱜ ᱥᱮᱸᱫᱽᱨᱟ ᱛᱮ ᱧᱟᱢᱮᱱ ᱥᱟᱦᱴᱟ ᱧᱮᱞᱢᱮ|ᱧᱟᱢᱮᱱ ᱥᱮᱸᱫᱽᱨᱟ ᱚᱨᱡᱚ ᱠᱚ ᱦᱚᱸ ᱧᱮᱞᱢᱮ}}",
-       "searchprofile-articles": "á±¥á±\9fá±\9bá±\9aá±¢ ᱥᱟᱦᱴᱟᱠᱚ",
+       "searchprofile-articles": "ᱩᱱᱩᱫᱩá±\9c ᱥᱟᱦᱴᱟᱠᱚ",
        "searchprofile-images": "Multimedia",
-       "searchprofile-everything": "Sanamaḱ koge",
+       "searchprofile-everything": "ᱡᱚᱛᱚᱜᱮ",
        "searchprofile-advanced": "Sompadon",
-       "searchprofile-articles-tooltip": "$1 re ńelme",
-       "searchprofile-images-tooltip": "File sendra",
+       "searchprofile-articles-tooltip": "$1 ᱨᱮ ᱧᱮᱞᱢᱮ",
+       "searchprofile-images-tooltip": "ᱨᱮᱫᱠᱩ ᱥᱮᱸᱫᱽᱨᱟ",
        "searchprofile-everything-tooltip": "ᱡᱚᱛᱚ ᱥᱟᱛᱚᱢ ᱥᱟᱦᱴᱟᱨᱮ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ (ᱨᱚᱲ ᱥᱟᱦᱴᱟ ᱠᱚᱦᱚᱸ)",
        "searchprofile-advanced-tooltip": "Judạ ńutum re sẽndra",
        "search-result-size": "$1 ({{PLURAL:$2|1 ᱟᱹᱲᱟᱹ|$2 ᱟᱹᱲᱟᱹᱠᱳ}})",
        "search-interwiki-caption": "Hopon porjekṭko",
        "search-interwiki-default": "$1 folko:",
        "search-interwiki-more": "(Arhõ)",
+       "search-interwiki-more-results": "ᱵᱟᱹᱲᱛᱤ ᱚᱨᱡᱚᱠᱚ",
+       "search-relatedarticle": "ᱥᱟᱹᱜᱟᱹᱭᱟᱱ",
        "searchrelated": "songenko",
-       "searchall": "Sanamaḱ",
+       "searchall": "ᱡᱚᱛᱚ",
        "search-showingresults": "{{PLURAL:$4|ᱚᱨᱡᱚ <strong>$1</strong> ᱨᱮᱱᱟᱜ <strong>$3</strong>|ᱚᱨᱡᱚᱠᱚ <strong>$1 - $2</strong> ᱨᱮᱱᱟᱜ <strong>$3</strong>}}",
        "search-nonefound": "Kupuli leka roṛruạṛ bạnuḱa",
+       "powersearch-ns": "ᱨᱟᱠᱷᱟ ᱧᱩᱛᱩᱢ ᱨᱮ ᱥᱮᱸᱫᱽᱨᱟ",
        "powersearch-togglelabel": "Sendra",
        "powersearch-toggleall": "Sanamaḱ",
        "powersearch-togglenone": "Okaṭaḱ hõ baṅ",
        "preferences": "Pạsindko",
        "mypreferences": "Pạsindko",
+       "prefs-edits": "ᱥᱟᱯᱲᱟᱣᱟᱜ ᱮᱞ:",
        "prefs-skin": "Harta",
        "skin-preview": "Ńel, Unuduḱ",
        "datedefault": "Pạsind banuḱa",
        "username": "Beoharićaḱ ńutum:",
        "yourrealname": "Sạri ńutum",
        "yourlanguage": "ᱯᱟᱹᱨᱥᱤ:",
+       "yournick": "ᱱᱟᱶᱟ ᱥᱩᱦᱤ:",
        "gender-male": "Baba hoṛ",
        "gender-female": "Gogo hoṛ, Kuṛi, Kuṛi gidrạ",
        "email": "E-mail",
        "prefs-help-email": "E-mail ṭhikana do bạṛtitege, menkhan uku namber nãwãte benao jạruṛa, am do amaḱ uku nomborem hiṛiń keda.",
        "prefs-help-email-others": "Am são e-mail hotete jogajog dohoy lạgitte mitṭen joṛao se amaḱ katha roṛaḱ sakam bachao jońme.\nAmaḱ e-mail ṭhikạna do bań cabaḱa tinre onko do ko beohara",
+       "prefs-signature": "ᱥᱩᱦᱤ",
+       "prefs-editor": "ᱥᱟᱯᱲᱮᱛ",
+       "prefs-preview": "ᱧᱮᱞ ᱵᱤᱰᱟᱹᱣ",
        "userrights": "Beoharićaḱ laṛcaṛ ektiạrko",
        "userrights-lookup-user": "Beoharkoaḱ gãotako laṛcaṛ",
        "userrights-user-editname": "Beoharićaḱ ńutum emmẽ",
        "editusergroup": "Beoharićaḱ gãotako toṅgeymẽ",
        "userrights-editusergroup": "Beoharićaḱ gãotako toṅgeymẽ",
        "saveusergroups": "Beoharićaḱ gãotako rukhiyaymẽ",
+       "userrights-reason": "ᱚᱡᱮ:",
        "group-bot": "ᱵᱚᱴᱠᱚ",
        "group-sysop": "ᱟᱰᱢᱤᱱᱤᱥᱴᱨᱮᱴᱚᱨ",
        "grouppage-bot": "{{ns:project}}:ᱵᱚᱴᱠᱚ",
        "action-createaccount": "ᱱᱚᱶᱟ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱷᱟᱛᱟ ᱵᱮᱱᱟᱣ",
        "action-browsearchive": "ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ ᱜᱮᱫ ᱟᱠᱟᱱᱟ ᱥᱟᱦᱴᱟᱠᱚ",
        "nchanges": "$1 {{PLURAL:$1 bodol bodolko}}",
-       "enhancedrc-history": "Jạṛ",
+       "enhancedrc-history": "ᱱᱟᱜᱟᱢ",
        "recentchanges": "ᱱᱟᱣᱭᱟᱱᱟᱜ ᱵᱚᱫᱚᱞᱠᱳ",
        "recentchanges-legend": "Nahaḱ bodol teaḱko",
        "recentchanges-summary": "Noa sakamre wiki reaḱ joto khon nãwã bodolko paṅjaṅjaymẽ.",
        "recentchanges-noresult": "ᱮᱢᱞᱮᱱ ᱥᱚᱢᱚᱭ ᱵᱷᱤᱛᱤᱨ ᱨᱮ ᱵᱚᱫᱚᱞᱟᱜ ᱠᱚ ᱵᱟᱭ ᱢᱤᱫᱩᱜ ᱠᱟᱱᱟ ᱾",
        "recentchanges-feed-description": "Noa feedre wiki reaḱ joto khon nãwã bodolko paṅjaymẽ",
        "recentchanges-label-newpage": "ᱱᱚᱣᱟ ᱥᱟᱯᱲᱟᱣ ᱢᱤᱫᱴᱮᱱ ᱱᱟᱣᱟ ᱥᱟᱦᱴᱟᱭ ᱛᱮᱭᱟᱨᱠᱮᱫᱟ",
-       "recentchanges-label-minor": "Noado hudiń mạchi toṅge",
-       "recentchanges-label-bot": "Noa toṅge do bot hotete purauena",
+       "recentchanges-label-minor": "ᱱᱚᱣᱟ ᱫᱚ ᱦᱩᱰᱤᱧ ᱥᱟᱯᱲᱟᱣ ᱠᱟᱱᱟ",
+       "recentchanges-label-bot": "ᱱᱚᱣᱟ ᱥᱟᱯᱲᱟᱣ ᱫᱚ ᱵᱚᱴ ᱮ ᱠᱚᱨᱟᱣᱠᱟᱫᱟ",
        "recentchanges-label-unpatrolled": "Noa sompadon do ńit́ hạbić baṅ ńel ńamakana",
        "recentchanges-label-plusminus": "ᱥᱟᱦᱴᱟ ᱫᱚ  ᱵᱚᱫᱚᱞᱮᱱᱟ ᱱᱤᱱᱟᱹᱜ ᱮᱞ ᱵᱟᱭᱤᱴᱥ ᱛᱮ",
        "recentchanges-legend-heading": "<strong>ᱞᱤᱡᱮᱸᱰ:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ᱟᱨᱦᱚᱸ ᱧᱮᱞᱢᱮ [[Special:NewPages|ᱱᱟᱶᱟ ᱥᱟᱦᱴᱟ ᱞᱤᱥᱴᱤ]])",
        "rcnotefrom": "ᱞᱟᱛᱟᱨ {{PLURAL:$5|ᱵᱚᱫᱚᱞ|ᱵᱚᱫᱚᱞ ᱠᱚ}} <strong>$3, $4</strong> ᱠᱷᱚᱱ (<strong>$1</strong> ᱦᱟᱹᱵᱤᱡ ᱩᱫᱩᱜ-ᱮᱱᱟ)",
        "rclistfrom": "Nãwã  bodolko uduḱme $3 $2 khon ehoṕkate",
-       "rcshowhideminor": "$1 kaṭic culuń tońgeko",
+       "rcshowhideminor": "$1 ᱱᱟᱥᱮᱭᱟᱜ ᱥᱟᱯᱲᱟᱣᱠᱩ",
        "rcshowhideminor-show": "Uduḱme",
-       "rcshowhideminor-hide": "Danaṅ",
+       "rcshowhideminor-hide": "ᱫᱟᱱᱟᱝ",
        "rcshowhidebots": " boṭko $1",
-       "rcshowhidebots-show": "Uduḱme",
+       "rcshowhidebots-show": "ᱧᱮᱞ",
        "rcshowhidebots-hide": "Danaṅ",
        "rcshowhideliu": "Regisṭari beoharićko $1",
        "rcshowhideliu-show": "ᱧᱮᱞ",
-       "rcshowhideliu-hide": "Danaṅ",
-       "rcshowhideanons": "$1 Nũtum bańa bebohariḱ",
+       "rcshowhideliu-hide": "ᱫᱟᱱᱟᱝ",
+       "rcshowhideanons": "$1 ᱧᱤᱛᱩᱢ ᱵᱟᱱᱩᱜ ᱵᱮᱵᱦᱟᱨᱤᱪ",
        "rcshowhideanons-show": "Uduḱme",
-       "rcshowhideanons-hide": "Danaṅ",
+       "rcshowhideanons-hide": "ᱫᱟᱱᱟᱝ",
        "rcshowhidepatr": "$1 Biḍạen sompadonko",
-       "rcshowhidemine": "$1 ińaḱ tońgeko",
+       "rcshowhidemine": "$1 ᱤᱧᱟᱜ ᱥᱟᱯᱲᱟᱣᱠᱩ",
        "rcshowhidemine-show": "Uduḱme",
-       "rcshowhidemine-hide": "Danaṅ",
+       "rcshowhidemine-hide": "ᱫᱟᱱᱟᱝ",
        "rclinks": "$2 din lahare $1 bodol unuduḱme",
        "diff": "ᱡᱩᱫᱟᱹ",
        "hist": "ᱱᱟᱜᱟᱢ",
-       "hide": "Danaṅ",
-       "show": "Uduḱme",
+       "hide": "ᱫᱟᱱᱟᱝ",
+       "show": "ᱧᱮᱞ",
        "minoreditletter": "m",
        "newpageletter": "N",
        "boteditletter": "b",
        "recentchangeslinked-toolbox": "ᱥᱟᱹᱜᱟᱹᱭᱟᱱ ᱵᱚᱫᱚᱞᱠᱚ",
        "recentchangeslinked-title": "Bodolaḱko do \"$1\" sãote joṛao geya",
        "recentchangeslinked-summary": "ᱱᱚᱣᱟ ᱫᱚ ᱚᱱᱟ ᱛᱟᱹᱞᱠᱟᱹ ᱠᱟᱱᱟ ᱚᱠᱟ ᱫᱟ ᱱᱮᱵᱮᱛᱟᱨᱜᱮ ᱵᱚᱫᱚᱞ ᱦᱩᱭ ᱟᱠᱟᱱᱟ ᱚᱠᱟ ᱫᱚ category ᱦᱟᱛᱟᱣ ᱟᱠᱟᱱ ᱥᱟᱠᱟᱢ ᱠᱷᱚᱱ᱾\n\n[[Special:Watchlist|your watchlist]] ᱨᱮᱭᱟᱜ ᱥᱟᱦᱴᱟ ᱫᱚ'''bold''' .",
-       "recentchangeslinked-page": "sakạm ńutum",
+       "recentchangeslinked-page": "ᱥᱟᱦᱴᱟ ᱧᱤᱛᱩᱢ :",
        "recentchangeslinked-to": "Joṛaoaḱ sakamre ńel ocoyme emaḱ sakam bạgi katet",
        "upload": "ᱨᱮᱫ ᱞᱟᱫᱮᱢᱮ",
        "uploadbtn": "Rẽt rakabmẽ",
        "listfiles_date": "Tạrikh",
        "listfiles_name": "Ńutum",
        "listfiles_user": "Beoharić, Laṛcaṛic",
-       "file-anchor-link": "Re̕t",
+       "file-anchor-link": "ᱨᱮᱫ",
        "filehist": "ᱨᱮᱫ ᱨᱮᱭᱟᱜ ᱱᱟᱜᱟᱢ",
-       "filehist-help": "date re click me/somóy re click me fail reak obostha nel lagit",
+       "filehist-help": "ᱚᱠᱛᱚ ᱨᱮ ᱞᱤᱱ ᱢᱮ/ᱚᱠᱛᱚ ᱨᱮ ᱨᱮᱫ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱛ ᱞᱤᱱ ᱢᱮ",
        "filehist-deleteall": "Joto get giḍi",
        "filehist-deleteone": "Get giḍi",
        "filehist-revert": "Lahaleka",
-       "filehist-current": "Nitaḱ",
-       "filehist-datetime": "̣Tạrikh/So̠mo̠y",
+       "filehist-current": "ᱱᱤᱛᱚᱜ",
+       "filehist-datetime": "ᱛᱟᱹᱨᱤᱠᱷ/ᱚᱠᱛᱚ",
        "filehist-thumb": "Ṭip",
        "filehist-thumbtext": "Thumbnail for version as of $1",
        "filehist-nothumb": "ᱵᱟᱹᱱᱩᱜ-ᱟ ᱴᱤᱯ-ᱨᱟᱢᱟ",
-       "filehist-user": "Laṛcaṛić",
-       "filehist-dimensions": "Maṕ",
-       "filehist-comment": "Roṛ",
+       "filehist-user": "ᱵᱮᱵᱦᱟᱨᱤᱡᱽ",
+       "filehist-dimensions": "ᱡᱚᱠᱷᱟ",
+       "filehist-comment": "ᱠᱟᱛᱷᱟ",
        "imagelinks": "ᱯᱷᱟᱭᱤᱞ ᱵᱮᱣᱦᱟᱨ",
        "linkstoimage": "ᱞᱟᱛᱟᱨ ᱨᱮᱭᱟᱜ {{PLURAL:$1|ᱥᱟᱦᱴᱟ ᱡᱚᱱᱚᱲᱠᱚ|$1 ᱥᱟᱦᱴᱟᱠᱚ ᱡᱚᱱᱚᱲ}} ᱱᱤᱭᱟᱹ ᱨᱮᱫ ᱨᱮ:",
        "linkstoimage-more": "$1 ᱠᱷᱚᱱ ᱵᱟᱹᱲᱛᱤ {{PLURAL:$1|ᱥᱟᱦᱴᱟ ᱡᱚᱯᱲᱟᱣᱠᱚ|ᱥᱟᱦᱴᱟ ᱡᱚᱯᱲᱟᱣ}} ᱢᱮᱱᱟᱜ-ᱟ ᱱᱚᱣᱟ ᱨᱮᱫ ᱥᱟᱶ ᱾\nᱱᱚᱶᱟ ᱞᱤᱥᱴᱤ ᱩᱫᱩᱜᱮᱜ-ᱟᱭ {{PLURAL:$1|ᱮᱛᱚᱦᱚᱵ ᱥᱟᱦᱴᱟ ᱡᱚᱲᱟᱣ|ᱮᱛᱚᱦᱚᱵ $1 ᱥᱟᱦᱴᱟ ᱡᱚᱲᱟᱣᱠᱚ}} ᱥᱩᱢᱩᱝ ᱱᱚᱶᱟ ᱨᱮᱫ ᱥᱟᱶ ᱾\nᱢᱤᱫ [[Special:WhatLinksHere/$2|ᱡᱚᱛᱚ ᱞᱤᱥᱴᱤ]] ᱢᱮᱱᱟᱜ-ᱟ ᱾",
        "logempty": "ᱞᱚᱜᱽ ᱨᱮ ᱚᱱᱟᱞᱮᱠᱟᱱ ᱡᱤᱱᱤᱥ ᱵᱟᱹᱱᱩᱜ-ᱟ ᱾",
        "allpages": "ᱡᱚᱛᱚ ᱥᱟᱦᱴᱟ",
        "allarticles": "ᱡᱚᱛᱚ ᱥᱟᱦᱴᱟᱠᱳ",
-       "allpagessubmit": "Calaḱme",
+       "allpagessubmit": "ᱪᱟᱞᱟᱜ ᱢᱮ",
        "allpages-hide-redirects": "ᱢᱚᱦᱰᱟᱦᱟᱜᱠᱚ ᱫᱟᱱᱟᱝ",
        "categories": "rokom sokom",
        "linksearch-ok": "ᱥᱮᱸᱫᱽᱨᱟ",
        "emailsend": "Kulmẽ",
        "usermessage-editor": "ᱥᱤᱥᱴᱚᱢ ᱨᱟᱭᱵᱟᱨ",
        "watchlist": "ᱧᱮᱞᱟᱜ ᱞᱤᱥᱴᱤ",
-       "mywatchlist": "Ńeloḱgoḱ tạlika",
+       "mywatchlist": "ᱧᱮᱞᱟᱜ ᱞᱤᱥᱴᱤ",
        "watchlistfor2": "$1 ($2) lạ̣gitte",
        "watch": "Ńelme",
        "unwatch": "bang nelok' a",
        "actioncomplete": "kami Chabae-ena",
        "actionfailed": "Kami bang hoe-lena",
        "dellogpage": "Mãrao log",
-       "rollbacklink": "Ghurlạo ạcur",
+       "rollbacklink": "ᱜᱷᱩᱨᱞᱟᱹᱣ ᱟᱹᱪᱩᱨ",
        "rollbacklinkcount": "ᱜᱚᱰᱟᱣ ᱨᱩᱣᱟᱹᱲ $1 {{PLURAL:$1|ᱥᱟᱯᱲᱟᱣ|ᱥᱟᱯᱲᱟᱣᱠᱚ}}",
        "protectlogpage": "Rukhiyạy tala cạbi",
        "protectedarticle": "Rukhiyạgeya \"[[$1]]\"",
        "undeletelink": "Ńel/doho ruạṛ",
        "undeleteviewlink": "Ńel",
        "undelete-search-submit": "ᱥᱮᱸᱫᱽᱨᱟ",
-       "namespace": "Ńutum reaḱ ṭhai",
+       "namespace": "ᱧᱤᱛᱩᱢ ᱡᱟᱜᱟ",
        "invert": "Seć bachao",
        "tooltip-invert": "ᱱᱚᱶᱟ ᱵᱟᱠᱥᱟ ᱴᱤᱠ ᱢᱮ ᱥᱟᱦᱴᱟ ᱠᱷᱚᱱ ᱵᱚᱫᱚᱞᱟᱜᱠᱚ ᱫᱟᱱᱟᱝ ᱞᱟᱹᱜᱤᱫ  ᱵᱟᱛᱷᱚᱱ ᱨᱟᱠᱷᱟ ᱧᱩᱛᱩᱢ ᱥᱟᱶᱛᱮ (ᱟᱨ ᱡᱚᱯᱚᱲᱟᱣᱟᱱ ᱨᱟᱠᱷᱟ ᱧᱩᱛᱩᱢ ᱡᱩᱫᱤ ᱴᱤᱠ ᱟᱠᱟᱱᱟ)",
        "namespace_association": "ᱥᱚᱦᱚᱫᱤᱭᱟᱹ ᱨᱟᱠᱷᱟ ᱧᱩᱛᱩᱢ",
        "blanknamespace": "(ᱢᱩᱬᱩᱛ)",
        "contributions": "{{GENDER:$1|Beoharićaḱ }} Kạmiko",
        "contributions-title": "$1 Beoharićaḱ kạmiko",
-       "mycontris": "Ińaḱ kạmiko",
-       "anoncontribs": "Ińaḱ kạmiko",
+       "mycontris": "ᱮᱱᱮᱢᱠᱩ",
+       "anoncontribs": "ᱮᱱᱮᱢᱠᱩ",
        "contribsub2": "{{GENDER:$3|$1}} ($2) ᱞᱟᱹᱜᱤᱫ ᱛᱮ",
        "nocontribs": "ᱱᱚᱶᱟ ᱮᱢᱟᱜ ᱥᱟᱶ ᱡᱚᱲᱟᱣᱟᱱ ᱵᱚᱫᱚᱞᱠᱚ ᱵᱟᱭ ᱧᱟᱢᱞᱮᱱᱟ |",
        "uctop": "(ᱱᱤᱛᱚᱜ)",
        "isimage": "Ret joṛao",
        "whatlinkshere-prev": "{{PLURAL:$1 Laha reaḱ Laha reaḱ$1ṭen}}",
        "whatlinkshere-next": "{{PLURAL:$1 |Laha renaḱ | Laha renaḱko $1}}",
-       "whatlinkshere-links": "Joṛaoko",
+       "whatlinkshere-links": "← ᱡᱚᱱᱚᱲᱠᱚ",
        "whatlinkshere-hideredirs": "$1 arhõ unuduḱ",
        "whatlinkshere-hidetrans": "Selet́ $1",
-       "whatlinkshere-hidelinks": "$1 joṛaoko",
+       "whatlinkshere-hidelinks": "$1 ᱡᱚᱱᱚᱲᱠᱚ",
        "whatlinkshere-hideimages": "$1 ᱨᱮᱫ ᱡᱳᱱᱳᱲᱠᱚ",
-       "whatlinkshere-filters": "Sapha",
+       "whatlinkshere-filters": "ᱪᱷᱟᱹᱱᱤᱠᱩ",
        "block": "Beoharić esedem",
        "blockip": "Beoharić esedem",
        "ipboptions": "2 Ghonṭa : 2 hours, 1 maha:1 day, 3 maha : 3 days,1 hapta :1 week, 2 hapta : 2 weeks, 1 cando :1 month, 3 cando : 3 months,6 cando :6 months,  1 serma :1 year,  Aemamaha : infinite",
        "ipblocklist-submit": "Sendra",
        "infiniteblock": "ᱚᱦᱤᱥᱟᱹᱵᱽ",
        "emailblock": "E-mail do esetgea",
-       "blocklink": "Eset́",
+       "blocklink": "ᱮᱥᱮᱫᱽ",
        "unblocklink": "bań block",
        "change-blocklink": "block judạ",
        "contribslink": "ᱮᱱᱮᱢ",
        "tooltip-pt-watchlist": "Sakam tạlika okaṭak̕katet́ am do nãwã aroy lạgitem ńeleḱkan",
        "tooltip-pt-mycontris": "Mit́ṭen lisṭ {{GENDER:|amaḱ}} kạmiko reaḱ",
        "tooltip-pt-login": "ᱟᱢ ᱫᱚ ᱵᱚᱞᱟᱜ ᱞᱟᱹᱜᱤᱛ ᱩᱫᱽᱜᱟᱣᱤᱧ ᱮᱢᱟᱢᱠᱟᱱᱟ; ᱵᱚᱞᱚᱜ ᱞᱟᱜᱟᱜ-ᱟ ᱚᱝᱠᱟ ᱫᱚ ᱵᱟᱝ",
-       "tooltip-pt-logout": "O̠nḍo̠ńme",
+       "tooltip-pt-logout": "ᱚᱰᱚᱠᱚᱜ ᱢᱮ",
        "tooltip-pt-createaccount": "ᱟᱢ ᱫᱚ ᱢᱤᱫᱽᱴᱮᱱ ᱦᱤᱥᱟᱹᱵ ᱡᱷᱤᱪ ᱠᱟᱛᱮ ᱵᱚᱞᱚᱜ ᱞᱟᱹᱜᱤᱛᱤᱧ ᱩᱫᱽᱜᱟᱣᱮᱛ ᱢᱮᱭᱟ; ᱟᱫᱚ ᱡᱟᱹᱨᱩᱲ ᱵᱚᱞᱚᱜ ᱚᱝᱠᱟ ᱫᱚ ᱵᱟᱝ ᱠᱟᱱᱟ",
        "tooltip-ca-talk": "ᱥᱟᱛᱚᱢ ᱥᱟᱦᱴᱟ ᱞᱟᱹᱜᱤᱛ ᱜᱟᱞᱢᱟᱨᱟᱣ",
        "tooltip-ca-edit": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱥᱟᱯᱲᱟᱣᱢᱮ",
-       "tooltip-ca-addsection": "Nãwã sekson sạrdi",
+       "tooltip-ca-addsection": "ᱱᱟᱣᱟ ᱦᱟᱹᱴᱤᱧ ᱮᱦᱚᱵᱽ ᱢᱮ",
        "tooltip-ca-viewsource": "Noa sakam do poṭom gea\nOna te source em ńel daṛeaḱ",
        "tooltip-ca-history": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱮᱱᱟᱝ ᱱᱟᱝ ᱧᱮᱞ ᱨᱩᱟᱹᱲ",
        "tooltip-ca-protect": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱨᱩᱠᱷᱤᱭᱟᱹᱭ ᱢᱮ",
        "tooltip-n-help": "ᱥᱮᱸᱫᱽᱨᱟ ᱧᱟᱢ ᱨᱮᱭᱟᱜ ᱡᱟᱜᱟ",
        "tooltip-t-whatlinkshere": "ᱥᱟᱱᱟᱢ ᱩᱤᱠᱤ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱛᱟᱹᱞᱠᱟᱹ ᱟᱨ ᱡᱚᱱᱚᱲ ᱫᱚ ᱱᱚᱸᱰᱮ",
        "tooltip-t-recentchangeslinked": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱨᱮ ᱨᱚᱠᱟ ᱵᱚᱫᱚᱞ ᱟᱠᱟᱱ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱡᱚᱱᱚᱲ",
-       "tooltip-feed-atom": "Noa sakam lạgit́ atom phiḍ",
+       "tooltip-feed-atom": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱞᱟᱹᱜᱤᱛ Atom feed",
        "tooltip-t-contributions": "ᱮᱱᱮᱢ ᱨᱮᱱᱟᱜ ᱛᱟᱹᱞᱠᱟᱹ {{GENDER:$1|ᱱᱩᱭ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}}",
        "tooltip-t-emailuser": "ᱢᱤᱫ ᱤᱢᱮᱞ ᱠᱩᱞᱟᱭᱢᱮ {{GENDER:$1|ᱱᱩᱭ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}}",
        "tooltip-t-upload": "ᱨᱮᱫ ᱠᱚ ᱞᱟᱫᱮᱢᱮ",
        "tooltip-ca-nstab-mediawiki": "ᱥᱤᱥᱴᱚᱢ ᱢᱮᱥᱮᱡᱽ ᱧᱮᱞ",
        "tooltip-ca-nstab-template": "Forom uduḱme",
        "tooltip-ca-nstab-help": "ᱜᱚᱸᱲᱚ ᱥᱟᱦᱴᱟ ᱧᱮᱞᱢᱮ",
-       "tooltip-ca-nstab-category": "Rokom sokom sakamko udukme",
+       "tooltip-ca-nstab-category": "ᱛᱷᱚᱠ ᱥᱟᱦᱴᱟ ᱧᱮᱞᱢᱮ",
        "tooltip-minoredit": "Noa do huḍiń joṛao lekate lekhay me",
        "tooltip-save": "Bodolaḱko rukhiyayme",
        "tooltip-preview": "Amaḱ bodolaḱ uduḱme, noa beoharme ạuri rukhiyayre",
        "tooltip-diff": "Uduḱme okaṭaḱ onolem bodolakada",
        "tooltip-compareselectedversions": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱵᱟᱨᱭᱟ ᱧᱮᱞᱟᱹᱨᱩ ᱵᱷᱮᱜᱮᱫ ᱧᱮᱞ ᱢᱮ",
-       "tooltip-watch": "Amaḱ ńeloḱ sakamre noa do dohoyme",
+       "tooltip-watch": "ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱟᱢᱟᱜ ᱧᱮᱞᱚᱜ ᱛᱟᱹᱞᱠᱟᱹᱨᱮ ᱡᱚᱲᱟᱣᱢᱮ",
        "tooltip-rollback": "ᱫᱚᱲᱦᱟᱛᱮ ᱢᱤᱫ ᱫᱷᱟᱣ ᱞᱤᱱ ᱛᱮ contributor ᱟᱜ ᱢᱩᱪᱟᱹᱫ ᱥᱟᱯᱲᱟᱣ \"ᱜᱷᱩᱨᱞᱟᱹ ᱟᱹᱪᱩᱨ\" ᱢᱮ",
        "tooltip-undo": "Noa joṛao kạmire ulṭao \"bạgiyaḱme\" ar ńeloḱ lekate noa joṛao jhicme. Noa do am guḍ karon joṛaoe ektiyariye emama.",
        "tooltip-preferences-save": "Pạsindko rukhiyaymẽ",
        "file-info-size-pages": "$1 × $2 ᱯᱤᱠᱥᱮᱞ, ᱨᱮᱫ ᱥᱚᱝ: $3, MIME ᱞᱮᱠᱟᱱ: $4, $5 {{PLURAL:$5|ᱥᱟᱦᱴᱟ|ᱥᱟᱦᱴᱟᱠᱚ}}",
        "file-nohires": "Aema resulation nondḍe banuḱa",
        "svg-long-desc": "SVG rẽt, normalte $1 x $2 pixels, rẽt sayej: $3",
-       "show-big-image": "Mukhiạ phayel",
+       "show-big-image": "ᱟᱥᱚᱞ ᱨᱮᱫ",
        "show-big-image-preview": "Noa ńeloḱ akar do:$1",
-       "show-big-image-other": "Eman teaḱ {{PLURAL:$2|resolution|resolutions}}: $1",
+       "show-big-image-other": "ᱮᱢᱟᱱ ᱛᱮᱭᱟᱜ {{PLURAL:$2|resolution|resolutions}}: $1",
        "show-big-image-size": "$1 X $2 Pixels",
        "ilsubmit": "Sendra",
        "bydate": "ᱢᱟᱹᱦᱤᱛ ᱛᱮ",
        "saturday-at": "ᱧᱩᱦᱩᱢ ᱢᱟᱦᱟᱸ $1 ᱨᱮ",
        "yesterday-at": "ᱦᱚᱞᱟ $1 ᱨᱮ",
        "bad_image_list": "Format do latar re leka",
-       "metadata": "Meṭa khobor",
+       "metadata": "ᱢᱮᱴᱟ ᱥᱟᱹᱠᱷᱭᱟᱹᱛ",
        "metadata-help": "Noa rẹt redo bạṛti kathako menaḱa, paseć noa do ḍejiṭal kemera se skenar bebohar hoy kate ḍijiṭal benao. Judi noa ret noa reaḱ asolak khon nãwã aro lenkhan, paseć sanamaḱko thoṛa bań sodoroḱa noa retredo.",
        "metadata-fields": "Image metadata fields listed in this message will be included on image page display when the metadata table is collapsed.\nOthers will be hidden by default.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
        "exif-imagewidth": "Ganḍe",
        "exif-orientation": "ᱥᱟᱢᱟᱝ",
        "exif-xresolution": "ᱜᱤᱛᱤᱡ ᱛᱮ",
        "exif-yresolution": "ᱛᱤᱝᱜᱩ ᱛᱮ",
-       "exif-datetime": "Rẽt bodol reaḱ tạrikh ar okte",
+       "exif-datetime": "ᱨᱮᱫ ᱵᱚᱫᱚᱞ ᱛᱟᱹᱨᱤᱠᱷ ᱟᱨ ᱚᱠᱛᱚ",
        "exif-make": "Kemera tearić",
        "exif-model": "Kemera model",
        "exif-software": "Beoharen Software",
        "exif-unknowndate": "ᱚᱪᱤᱱᱦᱟᱹᱣ ᱢᱟᱹᱦᱤᱛ",
        "exif-orientation-1": "ᱥᱟᱫᱷᱟᱨᱚᱱ",
        "exif-dc-date": "ᱢᱟᱹᱦᱤᱛ",
-       "namespacesall": "sanam",
+       "namespacesall": "ᱡᱚᱛᱚ",
        "monthsall": "Sanamak",
        "quotation-marks": "\"$1\"",
        "imgmultipagenext": "ᱫᱟᱨᱟᱭ ᱥᱟᱦᱴᱟ 'n",
index 0755c09..c835d6c 100644 (file)
@@ -83,7 +83,6 @@
        "underline-never": "Asnjëherë",
        "underline-default": "Parapërcaktuar nga shfletuesi",
        "editfont-style": "Zgjidh stilin e gërmave të hapsirës:",
-       "editfont-default": "Sipas rregullit në shfletues",
        "editfont-monospace": "Germa me hapësirë të barabartë",
        "editfont-sansserif": "Germa Sans-serif",
        "editfont-serif": "Gërma serif",
        "explainconflict": "Dikush tjetër ka ndryshuar këtë faqe që kur ju filluat redaktimin.\nHpasira e sipërme tregon tekstin e faqes siç është aktualisht.\nNdryshimet tuaja janë shfaqur në hapsirën e poshtme.\nJu duhet t'ia bashkangjisni ndryshimet tuaja teksit ekzistues.\n<strong>Vetëm</strong> teksti në hapsirën e sipërme do të ruhet kur të shtypni \"$1\".",
        "yourtext": "Teksti juaj",
        "storedversion": "Rishikim i ruajtur",
-       "nonunicodebrowser": "'''Kujdes: Shfletuesi juaj ka mospërputhje me standartin unicode.'''\nEkziston një zgjidhje për redaktimin e sigurt të faqeve: Shkronjat jo-ASCII do të duken në kutinë e redaktimit si kod heksadecimal.",
        "editingold": "'''Kujdes: Po redaktoni një version të vjetër të kësaj faqeje.'''\nNë qoftë se e ruani, çdo ndryshim i bërë deri tani do të humbasë.'''",
        "yourdiff": "Ndryshimet",
        "copyrightwarning": "Ju lutemi, vini re! Të gjitha kontributet në {{SITENAME}} jepen për publikim sipas $2 (shiko $1 për më shumë detaje).\nNëse ju nuk dëshironi që shkrimet tuaja të redaktohen pa mëshirë dhe të shpërndahen sipas dëshirës, atëherë mos i vendosni këtu.<br />\nGjithashtu, ju po na premtoni ne që gjithçka e keni shkruar vetë, ose e keni kopjuar nga një domain publik ose nga burime të tjera  te hapura.\n'''Mos vendosni material të mbrojtur nga e drejta e autorit pa leje!'''",
        "recentchanges-submit": "Shfaq",
        "rcfilters-activefilters": "Filtrat aktiv",
        "rcfilters-advancedfilters": "Filtra të avancuar",
+       "rcfilters-limit-shownum": "Shfaq {{PLURAL:$1|ndryshimin e fundit|$1 ndryshimet e fundit}}",
        "rcfilters-quickfilters": "Filtrat e ruajtur",
        "rcfilters-quickfilters-placeholder-title": "Asnjë lidhje e ruajtur",
        "rcfilters-savedqueries-defaultlabel": "Filtrat e ruajtur",
        "block": "Blloko përdoruesin",
        "unblock": "Zhblloko përdoruesin",
        "blockip": "Blloko {{GENDER:$1|user}}",
-       "blockip-legend": "Blloko përdoruesin",
        "blockiptext": "Përdorni formularin e mëposhtëm për të hequr lejen e shkrimit për një përdorues ose IP specifike.\nKjo duhet bërë vetëm në raste vandalizmi, dhe në përputhje me [[{{MediaWiki:Policy-url}}|politikat]].\nPlotësoni arsyen specifike më poshtë (p.sh., tregoni faqet specifike që u vandalizuan).\nJu mund të bllokoni vargjet e adresës IP duke përdorur sintaksën [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR]; vargu më i madh i lejuar është /$1 për IPv4 dhe /$2 për IPv6.",
        "ipaddressorusername": "Adresë IP ose emër përdoruesi",
        "ipbexpiry": "Afati",
index e2845a5..3bc2245 100644 (file)
@@ -96,7 +96,10 @@ $digitTransformTable = [
        '7' => '٧', # &#x0667;
        '8' => '٨', # &#x0668;
        '9' => '٩', # &#x0669;
-       '.' => '٫', # &#x066b; wrong table ?
+];
+
+$separatorTransformTable = [
+       '.' => '٫', # &#x066b;
        ',' => '٬', # &#x066c;
 ];
 
index bb99553..a2f9f65 100644 (file)
@@ -341,6 +341,9 @@ $digitTransformTable = [
        '7' => '7',
        '8' => '8',
        '9' => '9',
+];
+
+$separatorTransformTable = [
        '.' => '.',
        ',' => ',',
 ];
index ad45b66..e615462 100644 (file)
@@ -130,7 +130,10 @@ $digitTransformTable = [
        '7' => '٧', # &#x0667;
        '8' => '٨', # &#x0668;
        '9' => '٩', # &#x0669;
-       '.' => '٫', # &#x066b; wrong table ?
+];
+
+$separatorTransformTable = [
+       '.' => '٫', # &#x066b;
        ',' => '٬', # &#x066c;
 ];
 
index 60e08cc..5227eba 100644 (file)
@@ -208,8 +208,8 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'HAUPTSEITENNAME_URL', 'VORDERSEITE_URL', 'HAUPTSEITE_URL', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'subst'                     => [ '0', 'ERS:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'SICHER_ERS:', 'SICHERERS:', 'SAFESUBST:' ],
-       'img_thumbnail'             => [ '1', 'miniatur', 'mini', 'thumb', 'thumbnail' ],
-       'img_manualthumb'           => [ '1', 'miniatur=$1', 'mini=$1', 'thumbnail=$1', 'thumb=$1' ],
+       'img_thumbnail'             => [ '1', 'mini', 'miniatur', 'thumb', 'thumbnail' ],
+       'img_manualthumb'           => [ '1', 'mini=$1', 'miniatur=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'rechts', 'right' ],
        'img_left'                  => [ '1', 'links', 'left' ],
        'img_none'                  => [ '1', 'ohne', 'none' ],
index 84dfabf..4e10908 100644 (file)
@@ -329,7 +329,10 @@ $digitTransformTable = [
        '8' => '۸', # &#x06f8;
        '9' => '۹', # &#x06f9;
        '%' => '٪', # &#x066a;
-       '.' => '٫', # &#x066b; wrong table?
+];
+
+$separatorTransformTable = [
+       '.' => '٫', # &#x066b;
        ',' => '٬', # &#x066c;
 ];
 
index 7551ccf..0a80a62 100644 (file)
@@ -29,6 +29,9 @@ $digitTransformTable = [
        '7' => '٧', # &#x0667;
        '8' => '٨', # &#x0668;
        '9' => '٩', # &#x0669;
-       '.' => '٫', # &#x066b; wrong table ?
+];
+
+$separatorTransformTable = [
+       '.' => '٫', # &#x066b;
        ',' => '٬', # &#x066c;
 ];
index 5214c46..1850d67 100644 (file)
@@ -148,6 +148,9 @@ $digitTransformTable = [
        '7' => '七',
        '8' => '八',
        '9' => '九',
+];
+
+$separatorTransformTable = [
        '.' => '點',
        ',' => '',
 ];
index 178c49a..4becf6d 100644 (file)
@@ -62,9 +62,14 @@ TEXT
        }
 
        public function doDBUpdates() {
+               $dbw = $this->getDB( DB_MASTER );
+
+               if ( !$dbw->tableExists( 'ip_changes' ) ) {
+                       $this->fatalError( 'ip_changes table does not exist' );
+               }
+
                $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
                $dbr = $this->getDB( DB_REPLICA, [ 'vslow' ] );
-               $dbw = $this->getDB( DB_MASTER );
                $throttle = intval( $this->getOption( 'throttle', 0 ) );
                $maxRevId = intval( $this->getOption( 'max-rev-id', 0 ) );
                $start = $this->getOption( 'rev-id', 0 );
diff --git a/maintenance/postgres/archives/patch-ip_changes.sql b/maintenance/postgres/archives/patch-ip_changes.sql
new file mode 100644 (file)
index 0000000..231ea1a
--- /dev/null
@@ -0,0 +1,10 @@
+CREATE SEQUENCE ip_changes_ipc_rev_id_seq;
+
+CREATE TABLE ip_changes (
+  ipc_rev_id        INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('ip_changes_ipc_rev_id_seq'),
+  ipc_rev_timestamp TIMESTAMPTZ NOT NULL DEFAULT '',
+  ipc_hex           BYTEA NOT NULL DEFAULT ''
+);
+
+CREATE INDEX ipc_rev_timestamp ON ip_changes (ipc_rev_timestamp);
+CREATE INDEX ipc_hex_time ON ip_changes (ipc_hex,ipc_rev_timestamp);
index bd625ba..3bae4b8 100644 (file)
@@ -40,6 +40,12 @@ class RefreshFileHeaders extends Maintenance {
                $this->addOption( 'media_type', 'Media type to filter for', false, true );
                $this->addOption( 'major_mime', 'Major mime type to filter for', false, true );
                $this->addOption( 'minor_mime', 'Minor mime type to filter for', false, true );
+               $this->addOption(
+                       'refreshContentType',
+                       'Set true to refresh file content type from mime data in db',
+                       false,
+                       false
+               );
                $this->setBatchSize( 200 );
        }
 
@@ -100,6 +106,9 @@ class RefreshFileHeaders extends Maintenance {
                        foreach ( $res as $row ) {
                                $file = $repo->newFileFromRow( $row );
                                $headers = $file->getContentHeaders();
+                               if ( $this->getOption( 'refreshContentType', false ) ) {
+                                       $headers['Content-Type'] = $row->img_major_mime . '/' . $row->img_minor_mime;
+                               }
 
                                if ( count( $headers ) ) {
                                        $backendOperations[] = [
index a5bfbc5..559aca8 100644 (file)
@@ -717,6 +717,7 @@ return [
                        'az' => 'resources/lib/moment/locale/az.js',
                        'be' => 'resources/lib/moment/locale/be.js',
                        'bg' => 'resources/lib/moment/locale/bg.js',
+                       'bm' => 'resources/lib/moment/locale/bm.js',
                        'bn' => 'resources/lib/moment/locale/bn.js',
                        'bo' => 'resources/lib/moment/locale/bo.js',
                        'br' => 'resources/lib/moment/locale/br.js',
@@ -728,6 +729,7 @@ return [
                        'da' => 'resources/lib/moment/locale/da.js',
                        'de' => 'resources/lib/moment/locale/de.js',
                        'de-at' => 'resources/lib/moment/locale/de-at.js',
+                       'de-ch' => 'resources/lib/moment/locale/de-ch.js',
                        'dv' => 'resources/lib/moment/locale/dv.js',
                        'el' => 'resources/lib/moment/locale/el.js',
                        'en' => 'resources/src/moment-dmy.js',
@@ -741,11 +743,13 @@ return [
                        'fa' => 'resources/lib/moment/locale/fa.js',
                        'fi' => 'resources/lib/moment/locale/fi.js',
                        'fo' => 'resources/lib/moment/locale/fo.js',
-                       'fr-ca' => 'resources/lib/moment/locale/fr-ca.js',
                        'fr' => 'resources/lib/moment/locale/fr.js',
+                       'fr-ca' => 'resources/lib/moment/locale/fr-ca.js',
                        'fy' => 'resources/lib/moment/locale/fy.js',
                        'gd' => 'resources/lib/moment/locale/gd.js',
                        'gl' => 'resources/lib/moment/locale/gl.js',
+                       'gom-Latn' => 'resources/lib/moment/locale/gom-latn.js',
+                       'gu' => 'resources/lib/moment/locale/gu.js',
                        'he' => 'resources/lib/moment/locale/he.js',
                        'hi' => 'resources/lib/moment/locale/hi.js',
                        'hr' => 'resources/lib/moment/locale/hr.js',
@@ -758,6 +762,7 @@ return [
                        'jv' => 'resources/lib/moment/locale/jv.js',
                        'ka' => 'resources/lib/moment/locale/ka.js',
                        'kk-cyrl' => 'resources/lib/moment/locale/kk.js',
+                       'kn' => 'resources/lib/moment/locale/kn.js',
                        'ko' => 'resources/lib/moment/locale/ko.js',
                        'ky' => 'resources/lib/moment/locale/ky.js',
                        'lo' => 'resources/lib/moment/locale/lo.js',
@@ -776,10 +781,11 @@ return [
                        'nn' => 'resources/lib/moment/locale/nn.js',
                        'pa' => 'resources/lib/moment/locale/pa-in.js',
                        'pl' => 'resources/lib/moment/locale/pl.js',
-                       'pt-br' => 'resources/lib/moment/locale/pt-br.js',
                        'pt' => 'resources/lib/moment/locale/pt.js',
+                       'pt-br' => 'resources/lib/moment/locale/pt-br.js',
                        'ro' => 'resources/lib/moment/locale/ro.js',
                        'ru' => 'resources/lib/moment/locale/ru.js',
+                       'sd' => 'resources/lib/moment/locale/sd.js',
                        'se' => 'resources/lib/moment/locale/se.js',
                        'si' => 'resources/lib/moment/locale/si.js',
                        'sk' => 'resources/lib/moment/locale/sk.js',
@@ -792,19 +798,23 @@ return [
                        'sw' => 'resources/lib/moment/locale/sw.js',
                        'ta' => 'resources/lib/moment/locale/ta.js',
                        'te' => 'resources/lib/moment/locale/te.js',
+                       'tet' => 'resources/lib/moment/locale/tet.js',
                        'th' => 'resources/lib/moment/locale/th.js',
                        'tl-ph' => 'resources/lib/moment/locale/tl-ph.js',
                        'tr' => 'resources/lib/moment/locale/tr.js',
                        'tzm' => 'resources/lib/moment/locale/tzm.js',
                        'tzm-latn' => 'resources/lib/moment/locale/tzm-latn.js',
                        'uk' => 'resources/lib/moment/locale/uk.js',
+                       'ur' => 'resources/lib/moment/locale/ur.js',
                        'uz' => 'resources/lib/moment/locale/uz.js',
+                       'uz-Latn' => 'resources/lib/moment/locale/uz-latn.js',
                        'vi' => 'resources/lib/moment/locale/vi.js',
+                       'yo' => 'resources/lib/moment/locale/yo.js',
+                       'zh-hans' => 'resources/lib/moment/locale/zh-cn.js',
+                       'zh-hant' => 'resources/lib/moment/locale/zh-tw.js',
                        'zh-cn' => 'resources/lib/moment/locale/zh-cn.js',
                        'zh-hk' => 'resources/lib/moment/locale/zh-hk.js',
                        'zh-tw' => 'resources/lib/moment/locale/zh-tw.js',
-                       'zh-hans' => 'resources/lib/moment/locale/zh-cn.js',
-                       'zh-hant' => 'resources/lib/moment/locale/zh-tw.js',
                ],
                // HACK: skinScripts come after languageScripts, and we need locale overrides to come
                // after locale definitions
@@ -947,6 +957,7 @@ return [
                ],
                'dependencies' => [
                        'jquery.footHovzer',
+                       'oojs-ui-core',
                ],
        ],
        'mediawiki.diff.styles' => [
index 9ee5374..8618b73 100644 (file)
@@ -1,4 +1,4 @@
-Copyright (c) 2011-2016 Tim Wood, Iskren Chernev, Moment.js contributors
+Copyright (c) JS Foundation and other contributors
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
diff --git a/resources/lib/moment/README.md b/resources/lib/moment/README.md
new file mode 100644 (file)
index 0000000..06783de
--- /dev/null
@@ -0,0 +1,61 @@
+[![Join the chat at https://gitter.im/moment/moment](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/moment/moment?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+[![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![MIT License][license-image]][license-url] [![Build Status][travis-image]][travis-url]
+[![Coverage Status](https://coveralls.io/repos/moment/moment/badge.svg?branch=develop)](https://coveralls.io/r/moment/moment?branch=develop)
+[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoment%2Fmoment.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoment%2Fmoment?ref=badge_shield)
+
+A lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.
+
+**[Documentation](http://momentjs.com/docs/)**
+
+## Port to ECMAScript 6 (version 2.10.0)
+
+Moment 2.10.0 does not bring any new features, but the code is now written in
+ECMAScript 6 modules and placed inside `src/`. Previously `moment.js`, `locale/*.js` and
+`test/moment/*.js`, `test/locale/*.js` contained the source of the project. Now
+the source is in `src/`, temporary build (ECMAScript 5) files are placed under
+`build/umd/` (for running tests during development), and the `moment.js` and
+`locale/*.js` files are updated only on release.
+
+If you want to use a particular revision of the code, make sure to run
+`grunt transpile update-index`, so `moment.js` and `locales/*.js` are synced
+with `src/*`. We might place that in a commit hook in the future.
+
+## Upgrading to 2.0.0
+
+There are a number of small backwards incompatible changes with version 2.0.0. [See the full descriptions here](https://gist.github.com/timrwood/e72f2eef320ed9e37c51#backwards-incompatible-changes)
+
+ * Changed language ordinal method to return the number + ordinal instead of just the ordinal.
+
+ * Changed two digit year parsing cutoff to match strptime.
+
+ * Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`.
+
+ * Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`.
+
+ * Removed the lang data objects from the top level namespace.
+
+ * Duplicate `Date` passed to `moment()` instead of referencing it.
+
+## [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
+
+## [Contributing](https://github.com/moment/moment/blob/develop/CONTRIBUTING.md)
+
+We're looking for co-maintainers! If you want to become a master of time please
+write to [ichernev](https://github.com/ichernev).
+
+## License
+
+Moment.js is freely distributable under the terms of the [MIT license](https://github.com/moment/moment/blob/develop/LICENSE).
+
+[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoment%2Fmoment.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoment%2Fmoment?ref=badge_large)
+
+[license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat
+[license-url]: LICENSE
+
+[npm-url]: https://npmjs.org/package/moment
+[npm-version-image]: http://img.shields.io/npm/v/moment.svg?style=flat
+[npm-downloads-image]: http://img.shields.io/npm/dm/moment.svg?style=flat
+
+[travis-url]: http://travis-ci.org/moment/moment
+[travis-image]: http://img.shields.io/travis/moment/moment/develop.svg?style=flat
index d1a0dda..a89257f 100644 (file)
@@ -7,67 +7,67 @@
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var af = moment.defineLocale('af', {
-        months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
-        monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
-        weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
-        weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
-        weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
-        meridiemParse: /vm|nm/i,
-        isPM : function (input) {
-            return /^nm$/i.test(input);
-        },
-        meridiem : function (hours, minutes, isLower) {
-            if (hours < 12) {
-                return isLower ? 'vm' : 'VM';
-            } else {
-                return isLower ? 'nm' : 'NM';
-            }
-        },
-        longDateFormat : {
-            LT : 'HH:mm',
-            LTS : 'HH:mm:ss',
-            L : 'DD/MM/YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY HH:mm',
-            LLLL : 'dddd, D MMMM YYYY HH:mm'
-        },
-        calendar : {
-            sameDay : '[Vandag om] LT',
-            nextDay : '[Môre om] LT',
-            nextWeek : 'dddd [om] LT',
-            lastDay : '[Gister om] LT',
-            lastWeek : '[Laas] dddd [om] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : 'oor %s',
-            past : '%s gelede',
-            s : '\'n paar sekondes',
-            m : '\'n minuut',
-            mm : '%d minute',
-            h : '\'n uur',
-            hh : '%d ure',
-            d : '\'n dag',
-            dd : '%d dae',
-            M : '\'n maand',
-            MM : '%d maande',
-            y : '\'n jaar',
-            yy : '%d jaar'
-        },
-        ordinalParse: /\d{1,2}(ste|de)/,
-        ordinal : function (number) {
-            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
-        },
-        week : {
-            dow : 1, // Maandag is die eerste dag van die week.
-            doy : 4  // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
+var af = moment.defineLocale('af', {
+    months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
+    monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
+    weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
+    weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
+    weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
+    meridiemParse: /vm|nm/i,
+    isPM : function (input) {
+        return /^nm$/i.test(input);
+    },
+    meridiem : function (hours, minutes, isLower) {
+        if (hours < 12) {
+            return isLower ? 'vm' : 'VM';
+        } else {
+            return isLower ? 'nm' : 'NM';
         }
-    });
+    },
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD/MM/YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY HH:mm',
+        LLLL : 'dddd, D MMMM YYYY HH:mm'
+    },
+    calendar : {
+        sameDay : '[Vandag om] LT',
+        nextDay : '[Môre om] LT',
+        nextWeek : 'dddd [om] LT',
+        lastDay : '[Gister om] LT',
+        lastWeek : '[Laas] dddd [om] LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : 'oor %s',
+        past : '%s gelede',
+        s : '\'n paar sekondes',
+        m : '\'n minuut',
+        mm : '%d minute',
+        h : '\'n uur',
+        hh : '%d ure',
+        d : '\'n dag',
+        dd : '%d dae',
+        M : '\'n maand',
+        MM : '%d maande',
+        y : '\'n jaar',
+        yy : '%d jaar'
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
+    ordinal : function (number) {
+        return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
+    },
+    week : {
+        dow : 1, // Maandag is die eerste dag van die week.
+        doy : 4  // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
+    }
+});
 
-    return af;
+return af;
 
-}));
\ No newline at end of file
+})));
index b12a7b1..cbd810b 100644 (file)
@@ -8,53 +8,53 @@
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var ar_ma = moment.defineLocale('ar-ma', {
-        months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
-        monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
-        weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
-        weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
-        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
-        weekdaysParseExact : true,
-        longDateFormat : {
-            LT : 'HH:mm',
-            LTS : 'HH:mm:ss',
-            L : 'DD/MM/YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY HH:mm',
-            LLLL : 'dddd D MMMM YYYY HH:mm'
-        },
-        calendar : {
-            sameDay: '[اليوم على الساعة] LT',
-            nextDay: '[غدا على الساعة] LT',
-            nextWeek: 'dddd [على الساعة] LT',
-            lastDay: '[أمس على الساعة] LT',
-            lastWeek: 'dddd [على الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : 'في %s',
-            past : 'منذ %s',
-            s : 'ثوان',
-            m : 'دقيقة',
-            mm : '%d دقائق',
-            h : 'ساعة',
-            hh : '%d ساعات',
-            d : 'يوم',
-            dd : '%d أيام',
-            M : 'شهر',
-            MM : '%d أشهر',
-            y : 'سنة',
-            yy : '%d سنوات'
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
+var arMa = moment.defineLocale('ar-ma', {
+    months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+    monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+    weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+    weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
+    weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+    weekdaysParseExact : true,
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD/MM/YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY HH:mm',
+        LLLL : 'dddd D MMMM YYYY HH:mm'
+    },
+    calendar : {
+        sameDay: '[اليوم على الساعة] LT',
+        nextDay: '[غدا على الساعة] LT',
+        nextWeek: 'dddd [على الساعة] LT',
+        lastDay: '[أمس على الساعة] LT',
+        lastWeek: 'dddd [على الساعة] LT',
+        sameElse: 'L'
+    },
+    relativeTime : {
+        future : 'في %s',
+        past : 'منذ %s',
+        s : 'ثوان',
+        m : 'دقيقة',
+        mm : '%d دقائق',
+        h : 'ساعة',
+        hh : '%d ساعات',
+        d : 'يوم',
+        dd : '%d أيام',
+        M : 'شهر',
+        MM : '%d أشهر',
+        y : 'سنة',
+        yy : '%d سنوات'
+    },
+    week : {
+        dow : 6, // Saturday is the first day of the week.
+        doy : 12  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return ar_ma;
+return arMa;
 
-}));
\ No newline at end of file
+})));
index 430a184..dccd0d8 100644 (file)
@@ -7,98 +7,99 @@
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var symbolMap = {
-        '1': '١',
-        '2': '٢',
-        '3': '٣',
-        '4': '٤',
-        '5': '٥',
-        '6': '٦',
-        '7': '٧',
-        '8': '٨',
-        '9': '٩',
-        '0': '٠'
-    }, numberMap = {
-        '١': '1',
-        '٢': '2',
-        '٣': '3',
-        '٤': '4',
-        '٥': '5',
-        '٦': '6',
-        '٧': '7',
-        '٨': '8',
-        '٩': '9',
-        '٠': '0'
-    };
+var symbolMap = {
+    '1': '١',
+    '2': '٢',
+    '3': '٣',
+    '4': '٤',
+    '5': '٥',
+    '6': '٦',
+    '7': '٧',
+    '8': '٨',
+    '9': '٩',
+    '0': '٠'
+};
+var numberMap = {
+    '١': '1',
+    '٢': '2',
+    '٣': '3',
+    '٤': '4',
+    '٥': '5',
+    '٦': '6',
+    '٧': '7',
+    '٨': '8',
+    '٩': '9',
+    '٠': '0'
+};
 
-    var ar_sa = moment.defineLocale('ar-sa', {
-        months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
-        monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
-        weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
-        weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
-        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
-        weekdaysParseExact : true,
-        longDateFormat : {
-            LT : 'HH:mm',
-            LTS : 'HH:mm:ss',
-            L : 'DD/MM/YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY HH:mm',
-            LLLL : 'dddd D MMMM YYYY HH:mm'
-        },
-        meridiemParse: /ص|م/,
-        isPM : function (input) {
-            return 'م' === input;
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return 'ص';
-            } else {
-                return 'م';
-            }
-        },
-        calendar : {
-            sameDay: '[اليوم على الساعة] LT',
-            nextDay: '[غدا على الساعة] LT',
-            nextWeek: 'dddd [على الساعة] LT',
-            lastDay: '[أمس على الساعة] LT',
-            lastWeek: 'dddd [على الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : 'في %s',
-            past : 'منذ %s',
-            s : 'ثوان',
-            m : 'دقيقة',
-            mm : '%d دقائق',
-            h : 'ساعة',
-            hh : '%d ساعات',
-            d : 'يوم',
-            dd : '%d أيام',
-            M : 'شهر',
-            MM : '%d أشهر',
-            y : 'سنة',
-            yy : '%d سنوات'
-        },
-        preparse: function (string) {
-            return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
-                return numberMap[match];
-            }).replace(/،/g, ',');
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            }).replace(/,/g, '،');
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
+var arSa = moment.defineLocale('ar-sa', {
+    months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+    monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+    weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+    weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+    weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+    weekdaysParseExact : true,
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD/MM/YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY HH:mm',
+        LLLL : 'dddd D MMMM YYYY HH:mm'
+    },
+    meridiemParse: /ص|م/,
+    isPM : function (input) {
+        return 'م' === input;
+    },
+    meridiem : function (hour, minute, isLower) {
+        if (hour < 12) {
+            return 'ص';
+        } else {
+            return 'م';
         }
-    });
+    },
+    calendar : {
+        sameDay: '[اليوم على الساعة] LT',
+        nextDay: '[غدا على الساعة] LT',
+        nextWeek: 'dddd [على الساعة] LT',
+        lastDay: '[أمس على الساعة] LT',
+        lastWeek: 'dddd [على الساعة] LT',
+        sameElse: 'L'
+    },
+    relativeTime : {
+        future : 'في %s',
+        past : 'منذ %s',
+        s : 'ثوان',
+        m : 'دقيقة',
+        mm : '%d دقائق',
+        h : 'ساعة',
+        hh : '%d ساعات',
+        d : 'يوم',
+        dd : '%d أيام',
+        M : 'شهر',
+        MM : '%d أشهر',
+        y : 'سنة',
+        yy : '%d سنوات'
+    },
+    preparse: function (string) {
+        return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
+            return numberMap[match];
+        }).replace(/،/g, ',');
+    },
+    postformat: function (string) {
+        return string.replace(/\d/g, function (match) {
+            return symbolMap[match];
+        }).replace(/,/g, '،');
+    },
+    week : {
+        dow : 0, // Sunday is the first day of the week.
+        doy : 6  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return ar_sa;
+return arSa;
 
-}));
\ No newline at end of file
+})));
index dfabae3..5f0d38b 100644 (file)
@@ -7,53 +7,53 @@
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var ar_tn = moment.defineLocale('ar-tn', {
-        months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
-        monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
-        weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
-        weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
-        weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
-        weekdaysParseExact : true,
-        longDateFormat: {
-            LT: 'HH:mm',
-            LTS: 'HH:mm:ss',
-            L: 'DD/MM/YYYY',
-            LL: 'D MMMM YYYY',
-            LLL: 'D MMMM YYYY HH:mm',
-            LLLL: 'dddd D MMMM YYYY HH:mm'
-        },
-        calendar: {
-            sameDay: '[اليوم على الساعة] LT',
-            nextDay: '[غدا على الساعة] LT',
-            nextWeek: 'dddd [على الساعة] LT',
-            lastDay: '[أمس على الساعة] LT',
-            lastWeek: 'dddd [على الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime: {
-            future: 'في %s',
-            past: 'منذ %s',
-            s: 'ثوان',
-            m: 'دقيقة',
-            mm: '%d دقائق',
-            h: 'ساعة',
-            hh: '%d ساعات',
-            d: 'يوم',
-            dd: '%d أيام',
-            M: 'شهر',
-            MM: '%d أشهر',
-            y: 'سنة',
-            yy: '%d سنوات'
-        },
-        week: {
-            dow: 1, // Monday is the first day of the week.
-            doy: 4 // The week that contains Jan 4th is the first week of the year.
-        }
-    });
+var arTn = moment.defineLocale('ar-tn', {
+    months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+    monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+    weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+    weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+    weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+    weekdaysParseExact : true,
+    longDateFormat: {
+        LT: 'HH:mm',
+        LTS: 'HH:mm:ss',
+        L: 'DD/MM/YYYY',
+        LL: 'D MMMM YYYY',
+        LLL: 'D MMMM YYYY HH:mm',
+        LLLL: 'dddd D MMMM YYYY HH:mm'
+    },
+    calendar: {
+        sameDay: '[اليوم على الساعة] LT',
+        nextDay: '[غدا على الساعة] LT',
+        nextWeek: 'dddd [على الساعة] LT',
+        lastDay: '[أمس على الساعة] LT',
+        lastWeek: 'dddd [على الساعة] LT',
+        sameElse: 'L'
+    },
+    relativeTime: {
+        future: 'في %s',
+        past: 'منذ %s',
+        s: 'ثوان',
+        m: 'دقيقة',
+        mm: '%d دقائق',
+        h: 'ساعة',
+        hh: '%d ساعات',
+        d: 'يوم',
+        dd: '%d أيام',
+        M: 'شهر',
+        MM: '%d أشهر',
+        y: 'سنة',
+        yy: '%d سنوات'
+    },
+    week: {
+        dow: 1, // Monday is the first day of the week.
+        doy: 4 // The week that contains Jan 4th is the first week of the year.
+    }
+});
 
-    return ar_tn;
+return arTn;
 
-}));
\ No newline at end of file
+})));
index 8bd2b1b..ae09617 100644 (file)
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var symbolMap = {
-        '1': '١',
-        '2': '٢',
-        '3': '٣',
-        '4': '٤',
-        '5': '٥',
-        '6': '٦',
-        '7': '٧',
-        '8': '٨',
-        '9': '٩',
-        '0': '٠'
-    }, numberMap = {
-        '١': '1',
-        '٢': '2',
-        '٣': '3',
-        '٤': '4',
-        '٥': '5',
-        '٦': '6',
-        '٧': '7',
-        '٨': '8',
-        '٩': '9',
-        '٠': '0'
-    }, pluralForm = function (n) {
-        return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
-    }, plurals = {
-        s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
-        m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
-        h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
-        d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
-        M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
-        y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
-    }, pluralize = function (u) {
-        return function (number, withoutSuffix, string, isFuture) {
-            var f = pluralForm(number),
-                str = plurals[u][pluralForm(number)];
-            if (f === 2) {
-                str = str[withoutSuffix ? 0 : 1];
-            }
-            return str.replace(/%d/i, number);
-        };
-    }, months = [
-        'كانون الثاني يناير',
-        'شباط فبراير',
-        'آذار مارس',
-        'نيسان أبريل',
-        'أيار مايو',
-        'حزيران يونيو',
-        'تموز يوليو',
-        'آب أغسطس',
-        'أيلول سبتمبر',
-        'تشرين الأول أكتوبر',
-        'تشرين الثاني نوفمبر',
-        'كانون الأول ديسمبر'
-    ];
+var symbolMap = {
+    '1': '١',
+    '2': '٢',
+    '3': '٣',
+    '4': '٤',
+    '5': '٥',
+    '6': '٦',
+    '7': '٧',
+    '8': '٨',
+    '9': '٩',
+    '0': '٠'
+};
+var numberMap = {
+    '١': '1',
+    '٢': '2',
+    '٣': '3',
+    '٤': '4',
+    '٥': '5',
+    '٦': '6',
+    '٧': '7',
+    '٨': '8',
+    '٩': '9',
+    '٠': '0'
+};
+var pluralForm = function (n) {
+    return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
+};
+var plurals = {
+    s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
+    m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
+    h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
+    d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
+    M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
+    y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
+};
+var pluralize = function (u) {
+    return function (number, withoutSuffix, string, isFuture) {
+        var f = pluralForm(number),
+            str = plurals[u][pluralForm(number)];
+        if (f === 2) {
+            str = str[withoutSuffix ? 0 : 1];
+        }
+        return str.replace(/%d/i, number);
+    };
+};
+var months = [
+    'كانون الثاني يناير',
+    'شباط فبراير',
+    'آذار مارس',
+    'نيسان أبريل',
+    'أيار مايو',
+    'حزيران يونيو',
+    'تموز يوليو',
+    'آب أغسطس',
+    'أيلول سبتمبر',
+    'تشرين الأول أكتوبر',
+    'تشرين الثاني نوفمبر',
+    'كانون الأول ديسمبر'
+];
 
-    var ar = moment.defineLocale('ar', {
-        months : months,
-        monthsShort : months,
-        weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
-        weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
-        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
-        weekdaysParseExact : true,
-        longDateFormat : {
-            LT : 'HH:mm',
-            LTS : 'HH:mm:ss',
-            L : 'D/\u200FM/\u200FYYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY HH:mm',
-            LLLL : 'dddd D MMMM YYYY HH:mm'
-        },
-        meridiemParse: /ص|م/,
-        isPM : function (input) {
-            return 'م' === input;
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return 'ص';
-            } else {
-                return 'م';
-            }
-        },
-        calendar : {
-            sameDay: '[اليوم عند الساعة] LT',
-            nextDay: '[غدًا عند الساعة] LT',
-            nextWeek: 'dddd [عند الساعة] LT',
-            lastDay: '[أمس عند الساعة] LT',
-            lastWeek: 'dddd [عند الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : 'بعد %s',
-            past : 'منذ %s',
-            s : pluralize('s'),
-            m : pluralize('m'),
-            mm : pluralize('m'),
-            h : pluralize('h'),
-            hh : pluralize('h'),
-            d : pluralize('d'),
-            dd : pluralize('d'),
-            M : pluralize('M'),
-            MM : pluralize('M'),
-            y : pluralize('y'),
-            yy : pluralize('y')
-        },
-        preparse: function (string) {
-            return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
-                return numberMap[match];
-            }).replace(/،/g, ',');
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            }).replace(/,/g, '،');
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
+var ar = moment.defineLocale('ar', {
+    months : months,
+    monthsShort : months,
+    weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+    weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+    weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+    weekdaysParseExact : true,
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'D/\u200FM/\u200FYYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY HH:mm',
+        LLLL : 'dddd D MMMM YYYY HH:mm'
+    },
+    meridiemParse: /ص|م/,
+    isPM : function (input) {
+        return 'م' === input;
+    },
+    meridiem : function (hour, minute, isLower) {
+        if (hour < 12) {
+            return 'ص';
+        } else {
+            return 'م';
         }
-    });
+    },
+    calendar : {
+        sameDay: '[اليوم عند الساعة] LT',
+        nextDay: '[غدًا عند الساعة] LT',
+        nextWeek: 'dddd [عند الساعة] LT',
+        lastDay: '[أمس عند الساعة] LT',
+        lastWeek: 'dddd [عند الساعة] LT',
+        sameElse: 'L'
+    },
+    relativeTime : {
+        future : 'بعد %s',
+        past : 'منذ %s',
+        s : pluralize('s'),
+        m : pluralize('m'),
+        mm : pluralize('m'),
+        h : pluralize('h'),
+        hh : pluralize('h'),
+        d : pluralize('d'),
+        dd : pluralize('d'),
+        M : pluralize('M'),
+        MM : pluralize('M'),
+        y : pluralize('y'),
+        yy : pluralize('y')
+    },
+    preparse: function (string) {
+        return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
+            return numberMap[match];
+        }).replace(/،/g, ',');
+    },
+    postformat: function (string) {
+        return string.replace(/\d/g, function (match) {
+            return symbolMap[match];
+        }).replace(/,/g, '،');
+    },
+    week : {
+        dow : 6, // Saturday is the first day of the week.
+        doy : 12  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return ar;
+return ar;
 
-}));
\ No newline at end of file
+})));
index 5400ed4..56021b4 100644 (file)
@@ -7,99 +7,99 @@
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var suffixes = {
-        1: '-inci',
-        5: '-inci',
-        8: '-inci',
-        70: '-inci',
-        80: '-inci',
-        2: '-nci',
-        7: '-nci',
-        20: '-nci',
-        50: '-nci',
-        3: '-üncü',
-        4: '-üncü',
-        100: '-üncü',
-        6: '-ncı',
-        9: '-uncu',
-        10: '-uncu',
-        30: '-uncu',
-        60: '-ıncı',
-        90: '-ıncı'
-    };
+var suffixes = {
+    1: '-inci',
+    5: '-inci',
+    8: '-inci',
+    70: '-inci',
+    80: '-inci',
+    2: '-nci',
+    7: '-nci',
+    20: '-nci',
+    50: '-nci',
+    3: '-üncü',
+    4: '-üncü',
+    100: '-üncü',
+    6: '-ncı',
+    9: '-uncu',
+    10: '-uncu',
+    30: '-uncu',
+    60: '-ıncı',
+    90: '-ıncı'
+};
 
-    var az = moment.defineLocale('az', {
-        months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
-        monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
-        weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
-        weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
-        weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
-        weekdaysParseExact : true,
-        longDateFormat : {
-            LT : 'HH:mm',
-            LTS : 'HH:mm:ss',
-            L : 'DD.MM.YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY HH:mm',
-            LLLL : 'dddd, D MMMM YYYY HH:mm'
-        },
-        calendar : {
-            sameDay : '[bugün saat] LT',
-            nextDay : '[sabah saat] LT',
-            nextWeek : '[gələn həftə] dddd [saat] LT',
-            lastDay : '[dünən] LT',
-            lastWeek : '[keçən həftə] dddd [saat] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : '%s sonra',
-            past : '%s əvvəl',
-            s : 'birneçə saniyyə',
-            m : 'bir dəqiqə',
-            mm : '%d dəqiqə',
-            h : 'bir saat',
-            hh : '%d saat',
-            d : 'bir gün',
-            dd : '%d gün',
-            M : 'bir ay',
-            MM : '%d ay',
-            y : 'bir il',
-            yy : '%d il'
-        },
-        meridiemParse: /gecə|səhər|gündüz|axşam/,
-        isPM : function (input) {
-            return /^(gündüz|axşam)$/.test(input);
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return 'gecə';
-            } else if (hour < 12) {
-                return 'səhər';
-            } else if (hour < 17) {
-                return 'gündüz';
-            } else {
-                return 'axşam';
-            }
-        },
-        ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
-        ordinal : function (number) {
-            if (number === 0) {  // special case for zero
-                return number + '-ıncı';
-            }
-            var a = number % 10,
-                b = number % 100 - a,
-                c = number >= 100 ? 100 : null;
-            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
+var az = moment.defineLocale('az', {
+    months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
+    monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
+    weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
+    weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
+    weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
+    weekdaysParseExact : true,
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD.MM.YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY HH:mm',
+        LLLL : 'dddd, D MMMM YYYY HH:mm'
+    },
+    calendar : {
+        sameDay : '[bugün saat] LT',
+        nextDay : '[sabah saat] LT',
+        nextWeek : '[gələn həftə] dddd [saat] LT',
+        lastDay : '[dünən] LT',
+        lastWeek : '[keçən həftə] dddd [saat] LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : '%s sonra',
+        past : '%s əvvəl',
+        s : 'birneçə saniyyə',
+        m : 'bir dəqiqə',
+        mm : '%d dəqiqə',
+        h : 'bir saat',
+        hh : '%d saat',
+        d : 'bir gün',
+        dd : '%d gün',
+        M : 'bir ay',
+        MM : '%d ay',
+        y : 'bir il',
+        yy : '%d il'
+    },
+    meridiemParse: /gecə|səhər|gündüz|axşam/,
+    isPM : function (input) {
+        return /^(gündüz|axşam)$/.test(input);
+    },
+    meridiem : function (hour, minute, isLower) {
+        if (hour < 4) {
+            return 'gecə';
+        } else if (hour < 12) {
+            return 'səhər';
+        } else if (hour < 17) {
+            return 'gündüz';
+        } else {
+            return 'axşam';
         }
-    });
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
+    ordinal : function (number) {
+        if (number === 0) {  // special case for zero
+            return number + '-ıncı';
+        }
+        var a = number % 10,
+            b = number % 100 - a,
+            c = number >= 100 ? 100 : null;
+        return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return az;
+return az;
 
-}));
\ No newline at end of file
+})));
index a76157c..83025fd 100644 (file)
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    function plural(word, num) {
-        var forms = word.split('_');
-        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+function plural(word, num) {
+    var forms = word.split('_');
+    return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+    var format = {
+        'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
+        'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
+        'dd': 'дзень_дні_дзён',
+        'MM': 'месяц_месяцы_месяцаў',
+        'yy': 'год_гады_гадоў'
+    };
+    if (key === 'm') {
+        return withoutSuffix ? 'хвіліна' : 'хвіліну';
     }
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        var format = {
-            'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
-            'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
-            'dd': 'дзень_дні_дзён',
-            'MM': 'месяц_месяцы_месяцаў',
-            'yy': 'год_гады_гадоў'
-        };
-        if (key === 'm') {
-            return withoutSuffix ? 'хвіліна' : 'хвіліну';
-        }
-        else if (key === 'h') {
-            return withoutSuffix ? 'гадзіна' : 'гадзіну';
-        }
-        else {
-            return number + ' ' + plural(format[key], +number);
-        }
+    else if (key === 'h') {
+        return withoutSuffix ? 'гадзіна' : 'гадзіну';
+    }
+    else {
+        return number + ' ' + plural(format[key], +number);
     }
+}
 
-    var be = moment.defineLocale('be', {
-        months : {
-            format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'),
-            standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_')
-        },
-        monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
-        weekdays : {
-            format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'),
-            standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
-            isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/
-        },
-        weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
-        weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
-        longDateFormat : {
-            LT : 'HH:mm',
-            LTS : 'HH:mm:ss',
-            L : 'DD.MM.YYYY',
-            LL : 'D MMMM YYYY г.',
-            LLL : 'D MMMM YYYY г., HH:mm',
-            LLLL : 'dddd, D MMMM YYYY г., HH:mm'
-        },
-        calendar : {
-            sameDay: '[Сёння ў] LT',
-            nextDay: '[Заўтра ў] LT',
-            lastDay: '[Учора ў] LT',
-            nextWeek: function () {
-                return '[У] dddd [ў] LT';
-            },
-            lastWeek: function () {
-                switch (this.day()) {
-                    case 0:
-                    case 3:
-                    case 5:
-                    case 6:
-                        return '[У мінулую] dddd [ў] LT';
-                    case 1:
-                    case 2:
-                    case 4:
-                        return '[У мінулы] dddd [ў] LT';
-                }
-            },
-            sameElse: 'L'
+var be = moment.defineLocale('be', {
+    months : {
+        format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'),
+        standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_')
+    },
+    monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
+    weekdays : {
+        format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'),
+        standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
+        isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/
+    },
+    weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+    weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD.MM.YYYY',
+        LL : 'D MMMM YYYY г.',
+        LLL : 'D MMMM YYYY г., HH:mm',
+        LLLL : 'dddd, D MMMM YYYY г., HH:mm'
+    },
+    calendar : {
+        sameDay: '[Сёння ў] LT',
+        nextDay: '[Заўтра ў] LT',
+        lastDay: '[Учора ў] LT',
+        nextWeek: function () {
+            return '[У] dddd [ў] LT';
         },
-        relativeTime : {
-            future : 'праз %s',
-            past : '%s таму',
-            s : 'некалькі секунд',
-            m : relativeTimeWithPlural,
-            mm : relativeTimeWithPlural,
-            h : relativeTimeWithPlural,
-            hh : relativeTimeWithPlural,
-            d : 'дзень',
-            dd : relativeTimeWithPlural,
-            M : 'месяц',
-            MM : relativeTimeWithPlural,
-            y : 'год',
-            yy : relativeTimeWithPlural
-        },
-        meridiemParse: /ночы|раніцы|дня|вечара/,
-        isPM : function (input) {
-            return /^(дня|вечара)$/.test(input);
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return 'ночы';
-            } else if (hour < 12) {
-                return 'раніцы';
-            } else if (hour < 17) {
-                return 'дня';
-            } else {
-                return 'вечара';
-            }
-        },
-        ordinalParse: /\d{1,2}-(і|ы|га)/,
-        ordinal: function (number, period) {
-            switch (period) {
-                case 'M':
-                case 'd':
-                case 'DDD':
-                case 'w':
-                case 'W':
-                    return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
-                case 'D':
-                    return number + '-га';
-                default:
-                    return number;
+        lastWeek: function () {
+            switch (this.day()) {
+                case 0:
+                case 3:
+                case 5:
+                case 6:
+                    return '[У мінулую] dddd [ў] LT';
+                case 1:
+                case 2:
+                case 4:
+                    return '[У мінулы] dddd [ў] LT';
             }
         },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        sameElse: 'L'
+    },
+    relativeTime : {
+        future : 'праз %s',
+        past : '%s таму',
+        s : 'некалькі секунд',
+        m : relativeTimeWithPlural,
+        mm : relativeTimeWithPlural,
+        h : relativeTimeWithPlural,
+        hh : relativeTimeWithPlural,
+        d : 'дзень',
+        dd : relativeTimeWithPlural,
+        M : 'месяц',
+        MM : relativeTimeWithPlural,
+        y : 'год',
+        yy : relativeTimeWithPlural
+    },
+    meridiemParse: /ночы|раніцы|дня|вечара/,
+    isPM : function (input) {
+        return /^(дня|вечара)$/.test(input);
+    },
+    meridiem : function (hour, minute, isLower) {
+        if (hour < 4) {
+            return 'ночы';
+        } else if (hour < 12) {
+            return 'раніцы';
+        } else if (hour < 17) {
+            return 'дня';
+        } else {
+            return 'вечара';
+        }
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}-(і|ы|га)/,
+    ordinal: function (number, period) {
+        switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+            case 'w':
+            case 'W':
+                return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
+            case 'D':
+                return number + '-га';
+            default:
+                return number;
         }
-    });
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return be;
+return be;
 
-}));
\ No newline at end of file
+})));
index deedab8..ee06d19 100644 (file)
@@ -7,84 +7,84 @@
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var bg = moment.defineLocale('bg', {
-        months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
-        monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
-        weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
-        weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
-        weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
-        longDateFormat : {
-            LT : 'H:mm',
-            LTS : 'H:mm:ss',
-            L : 'D.MM.YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY H:mm',
-            LLLL : 'dddd, D MMMM YYYY H:mm'
-        },
-        calendar : {
-            sameDay : '[Днес в] LT',
-            nextDay : '[Утре в] LT',
-            nextWeek : 'dddd [в] LT',
-            lastDay : '[Вчера в] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                    case 0:
-                    case 3:
-                    case 6:
-                        return '[В изминалата] dddd [в] LT';
-                    case 1:
-                    case 2:
-                    case 4:
-                    case 5:
-                        return '[В изминалия] dddd [в] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : 'след %s',
-            past : 'преди %s',
-            s : 'няколко секунди',
-            m : 'минута',
-            mm : '%d минути',
-            h : 'час',
-            hh : '%d часа',
-            d : 'ден',
-            dd : '%d дни',
-            M : 'месец',
-            MM : '%d месеца',
-            y : 'година',
-            yy : '%d години'
-        },
-        ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
-        ordinal : function (number) {
-            var lastDigit = number % 10,
-                last2Digits = number % 100;
-            if (number === 0) {
-                return number + '-ев';
-            } else if (last2Digits === 0) {
-                return number + '-ен';
-            } else if (last2Digits > 10 && last2Digits < 20) {
-                return number + '-ти';
-            } else if (lastDigit === 1) {
-                return number + '-ви';
-            } else if (lastDigit === 2) {
-                return number + '-ри';
-            } else if (lastDigit === 7 || lastDigit === 8) {
-                return number + '-ми';
-            } else {
-                return number + '-ти';
+var bg = moment.defineLocale('bg', {
+    months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
+    monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
+    weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
+    weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
+    weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+    longDateFormat : {
+        LT : 'H:mm',
+        LTS : 'H:mm:ss',
+        L : 'D.MM.YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY H:mm',
+        LLLL : 'dddd, D MMMM YYYY H:mm'
+    },
+    calendar : {
+        sameDay : '[Днес в] LT',
+        nextDay : '[Утре в] LT',
+        nextWeek : 'dddd [в] LT',
+        lastDay : '[Вчера в] LT',
+        lastWeek : function () {
+            switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[В изминалата] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[В изминалия] dddd [в] LT';
             }
         },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : 'след %s',
+        past : 'преди %s',
+        s : 'няколко секунди',
+        m : 'минута',
+        mm : '%d минути',
+        h : 'час',
+        hh : '%d часа',
+        d : 'ден',
+        dd : '%d дни',
+        M : 'месец',
+        MM : '%d месеца',
+        y : 'година',
+        yy : '%d години'
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+    ordinal : function (number) {
+        var lastDigit = number % 10,
+            last2Digits = number % 100;
+        if (number === 0) {
+            return number + '-ев';
+        } else if (last2Digits === 0) {
+            return number + '-ен';
+        } else if (last2Digits > 10 && last2Digits < 20) {
+            return number + '-ти';
+        } else if (lastDigit === 1) {
+            return number + '-ви';
+        } else if (lastDigit === 2) {
+            return number + '-ри';
+        } else if (lastDigit === 7 || lastDigit === 8) {
+            return number + '-ми';
+        } else {
+            return number + '-ти';
         }
-    });
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return bg;
+return bg;
 
-}));
\ No newline at end of file
+})));
diff --git a/resources/lib/moment/locale/bm.js b/resources/lib/moment/locale/bm.js
new file mode 100644 (file)
index 0000000..1de2b5e
--- /dev/null
@@ -0,0 +1,59 @@
+//! moment.js locale configuration
+//! locale : Bambara [bm]
+//! author : Estelle Comment : https://github.com/estellecomment
+
+;(function (global, factory) {
+   typeof exports === 'object' && typeof module !== 'undefined'
+       && typeof require === 'function' ? factory(require('../moment')) :
+   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+   factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+// Language contact person : Abdoufata Kane : https://github.com/abdoufata
+
+var bm = moment.defineLocale('bm', {
+    months : 'Zanwuyekalo_Fewuruyekalo_Marisikalo_Awirilikalo_Mɛkalo_Zuwɛnkalo_Zuluyekalo_Utikalo_Sɛtanburukalo_ɔkutɔburukalo_Nowanburukalo_Desanburukalo'.split('_'),
+    monthsShort : 'Zan_Few_Mar_Awi_Mɛ_Zuw_Zul_Uti_Sɛt_ɔku_Now_Des'.split('_'),
+    weekdays : 'Kari_Ntɛnɛn_Tarata_Araba_Alamisa_Juma_Sibiri'.split('_'),
+    weekdaysShort : 'Kar_Ntɛ_Tar_Ara_Ala_Jum_Sib'.split('_'),
+    weekdaysMin : 'Ka_Nt_Ta_Ar_Al_Ju_Si'.split('_'),
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD/MM/YYYY',
+        LL : 'MMMM [tile] D [san] YYYY',
+        LLL : 'MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
+        LLLL : 'dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm'
+    },
+    calendar : {
+        sameDay : '[Bi lɛrɛ] LT',
+        nextDay : '[Sini lɛrɛ] LT',
+        nextWeek : 'dddd [don lɛrɛ] LT',
+        lastDay : '[Kunu lɛrɛ] LT',
+        lastWeek : 'dddd [tɛmɛnen lɛrɛ] LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : '%s kɔnɔ',
+        past : 'a bɛ %s bɔ',
+        s : 'sanga dama dama',
+        m : 'miniti kelen',
+        mm : 'miniti %d',
+        h : 'lɛrɛ kelen',
+        hh : 'lɛrɛ %d',
+        d : 'tile kelen',
+        dd : 'tile %d',
+        M : 'kalo kelen',
+        MM : 'kalo %d',
+        y : 'san kelen',
+        yy : 'san %d'
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 4  // The week that contains Jan 4th is the first week of the year.
+    }
+});
+
+return bm;
+
+})));
index 1d49751..b6f942a 100644 (file)
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var symbolMap = {
-        '1': '১',
-        '2': '২',
-        '3': '৩',
-        '4': '৪',
-        '5': '৫',
-        '6': '৬',
-        '7': '৭',
-        '8': '৮',
-        '9': '৯',
-        '0': '০'
-    },
-    numberMap = {
-        '১': '1',
-        '২': '2',
-        '৩': '3',
-        '৪': '4',
-        '৫': '5',
-        '৬': '6',
-        '৭': '7',
-        '৮': '8',
-        '৯': '9',
-        '০': '0'
-    };
+var symbolMap = {
+    '1': '১',
+    '2': '২',
+    '3': '৩',
+    '4': '৪',
+    '5': '৫',
+    '6': '৬',
+    '7': '৭',
+    '8': '৮',
+    '9': '৯',
+    '0': '০'
+};
+var numberMap = {
+    '১': '1',
+    '২': '2',
+    '৩': '3',
+    '৪': '4',
+    '৫': '5',
+    '৬': '6',
+    '৭': '7',
+    '৮': '8',
+    '৯': '9',
+    '০': '0'
+};
 
-    var bn = moment.defineLocale('bn', {
-        months : 'জানুয়ারী_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
-        monthsShort : 'জানু_ফেব_মার্চ_এপ্র_মে_জুন_জুল_আগ_সেপ্ট_অক্টো_নভে_ডিসে'.split('_'),
-        weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার'.split('_'),
-        weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি'.split('_'),
-        weekdaysMin : 'রবি_সোম_মঙ্গ_বুধ_বৃহঃ_শুক্র_শনি'.split('_'),
-        longDateFormat : {
-            LT : 'A h:mm সময়',
-            LTS : 'A h:mm:ss সময়',
-            L : 'DD/MM/YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY, A h:mm সময়',
-            LLLL : 'dddd, D MMMM YYYY, A h:mm সময়'
-        },
-        calendar : {
-            sameDay : '[আজ] LT',
-            nextDay : '[আগামীকাল] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[গতকাল] LT',
-            lastWeek : '[গত] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : '%s পরে',
-            past : '%s আগে',
-            s : 'কয়েক সেকেন্ড',
-            m : 'এক মিনিট',
-            mm : '%d মিনিট',
-            h : 'এক ঘন্টা',
-            hh : '%d ঘন্টা',
-            d : 'এক দিন',
-            dd : '%d দিন',
-            M : 'এক মাস',
-            MM : '%d মাস',
-            y : 'এক বছর',
-            yy : '%d বছর'
-        },
-        preparse: function (string) {
-            return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
-        meridiemHour : function (hour, meridiem) {
-            if (hour === 12) {
-                hour = 0;
-            }
-            if ((meridiem === 'রাত' && hour >= 4) ||
-                    (meridiem === 'দুপুর' && hour < 5) ||
-                    meridiem === 'বিকাল') {
-                return hour + 12;
-            } else {
-                return hour;
-            }
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return 'রাত';
-            } else if (hour < 10) {
-                return 'সকাল';
-            } else if (hour < 17) {
-                return 'দুপুর';
-            } else if (hour < 20) {
-                return 'বিকাল';
-            } else {
-                return 'রাত';
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
+var bn = moment.defineLocale('bn', {
+    months : 'জানুয়ারী_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
+    monthsShort : 'জানু_ফেব_মার্চ_এপ্র_মে_জুন_জুল_আগ_সেপ্ট_অক্টো_নভে_ডিসে'.split('_'),
+    weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার'.split('_'),
+    weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি'.split('_'),
+    weekdaysMin : 'রবি_সোম_মঙ্গ_বুধ_বৃহঃ_শুক্র_শনি'.split('_'),
+    longDateFormat : {
+        LT : 'A h:mm সময়',
+        LTS : 'A h:mm:ss সময়',
+        L : 'DD/MM/YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY, A h:mm সময়',
+        LLLL : 'dddd, D MMMM YYYY, A h:mm সময়'
+    },
+    calendar : {
+        sameDay : '[আজ] LT',
+        nextDay : '[আগামীকাল] LT',
+        nextWeek : 'dddd, LT',
+        lastDay : '[গতকাল] LT',
+        lastWeek : '[গত] dddd, LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : '%s পরে',
+        past : '%s আগে',
+        s : 'কয়েক সেকেন্ড',
+        m : 'এক মিনিট',
+        mm : '%d মিনিট',
+        h : 'এক ঘন্টা',
+        hh : '%d ঘন্টা',
+        d : 'এক দিন',
+        dd : '%d দিন',
+        M : 'এক মাস',
+        MM : '%d মাস',
+        y : 'এক বছর',
+        yy : '%d বছর'
+    },
+    preparse: function (string) {
+        return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
+            return numberMap[match];
+        });
+    },
+    postformat: function (string) {
+        return string.replace(/\d/g, function (match) {
+            return symbolMap[match];
+        });
+    },
+    meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
+    meridiemHour : function (hour, meridiem) {
+        if (hour === 12) {
+            hour = 0;
+        }
+        if ((meridiem === 'রাত' && hour >= 4) ||
+                (meridiem === 'দুপুর' && hour < 5) ||
+                meridiem === 'বিকাল') {
+            return hour + 12;
+        } else {
+            return hour;
         }
-    });
+    },
+    meridiem : function (hour, minute, isLower) {
+        if (hour < 4) {
+            return 'রাত';
+        } else if (hour < 10) {
+            return 'সকাল';
+        } else if (hour < 17) {
+            return 'দুপুর';
+        } else if (hour < 20) {
+            return 'বিকাল';
+        } else {
+            return 'রাত';
+        }
+    },
+    week : {
+        dow : 0, // Sunday is the first day of the week.
+        doy : 6  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return bn;
+return bn;
 
-}));
\ No newline at end of file
+})));
index 3f6fe19..eb6db47 100644 (file)
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var symbolMap = {
-        '1': '༡',
-        '2': '༢',
-        '3': '༣',
-        '4': '༤',
-        '5': '༥',
-        '6': '༦',
-        '7': '༧',
-        '8': '༨',
-        '9': '༩',
-        '0': '༠'
-    },
-    numberMap = {
-        '༡': '1',
-        '༢': '2',
-        '༣': '3',
-        '༤': '4',
-        '༥': '5',
-        '༦': '6',
-        '༧': '7',
-        '༨': '8',
-        '༩': '9',
-        '༠': '0'
-    };
+var symbolMap = {
+    '1': '༡',
+    '2': '༢',
+    '3': '༣',
+    '4': '༤',
+    '5': '༥',
+    '6': '༦',
+    '7': '༧',
+    '8': '༨',
+    '9': '༩',
+    '0': '༠'
+};
+var numberMap = {
+    '༡': '1',
+    '༢': '2',
+    '༣': '3',
+    '༤': '4',
+    '༥': '5',
+    '༦': '6',
+    '༧': '7',
+    '༨': '8',
+    '༩': '9',
+    '༠': '0'
+};
 
-    var bo = moment.defineLocale('bo', {
-        months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
-        monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
-        weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
-        weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
-        weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
-        longDateFormat : {
-            LT : 'A h:mm',
-            LTS : 'A h:mm:ss',
-            L : 'DD/MM/YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY, A h:mm',
-            LLLL : 'dddd, D MMMM YYYY, A h:mm'
-        },
-        calendar : {
-            sameDay : '[དི་རིང] LT',
-            nextDay : '[སང་ཉིན] LT',
-            nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
-            lastDay : '[ཁ་སང] LT',
-            lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : '%s ལ་',
-            past : '%s སྔན་ལ',
-            s : 'ལམ་སང',
-            m : 'སྐར་མ་གཅིག',
-            mm : '%d སྐར་མ',
-            h : 'ཆུ་ཚོད་གཅིག',
-            hh : '%d ཆུ་ཚོད',
-            d : 'ཉིན་གཅིག',
-            dd : '%d ཉིན་',
-            M : 'ཟླ་བ་གཅིག',
-            MM : '%d ཟླ་བ',
-            y : 'ལོ་གཅིག',
-            yy : '%d ལོ'
-        },
-        preparse: function (string) {
-            return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
-        meridiemHour : function (hour, meridiem) {
-            if (hour === 12) {
-                hour = 0;
-            }
-            if ((meridiem === 'མཚན་མོ' && hour >= 4) ||
-                    (meridiem === 'ཉིན་གུང' && hour < 5) ||
-                    meridiem === 'དགོང་དག') {
-                return hour + 12;
-            } else {
-                return hour;
-            }
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return 'མཚན་མོ';
-            } else if (hour < 10) {
-                return 'ཞོགས་ཀས';
-            } else if (hour < 17) {
-                return 'ཉིན་གུང';
-            } else if (hour < 20) {
-                return 'དགོང་དག';
-            } else {
-                return 'མཚན་མོ';
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
+var bo = moment.defineLocale('bo', {
+    months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+    monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+    weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
+    weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+    weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+    longDateFormat : {
+        LT : 'A h:mm',
+        LTS : 'A h:mm:ss',
+        L : 'DD/MM/YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY, A h:mm',
+        LLLL : 'dddd, D MMMM YYYY, A h:mm'
+    },
+    calendar : {
+        sameDay : '[དི་རིང] LT',
+        nextDay : '[སང་ཉིན] LT',
+        nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
+        lastDay : '[ཁ་སང] LT',
+        lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : '%s ལ་',
+        past : '%s སྔན་ལ',
+        s : 'ལམ་སང',
+        m : 'སྐར་མ་གཅིག',
+        mm : '%d སྐར་མ',
+        h : 'ཆུ་ཚོད་གཅིག',
+        hh : '%d ཆུ་ཚོད',
+        d : 'ཉིན་གཅིག',
+        dd : '%d ཉིན་',
+        M : 'ཟླ་བ་གཅིག',
+        MM : '%d ཟླ་བ',
+        y : 'ལོ་གཅིག',
+        yy : '%d ལོ'
+    },
+    preparse: function (string) {
+        return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
+            return numberMap[match];
+        });
+    },
+    postformat: function (string) {
+        return string.replace(/\d/g, function (match) {
+            return symbolMap[match];
+        });
+    },
+    meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
+    meridiemHour : function (hour, meridiem) {
+        if (hour === 12) {
+            hour = 0;
+        }
+        if ((meridiem === 'མཚན་མོ' && hour >= 4) ||
+                (meridiem === 'ཉིན་གུང' && hour < 5) ||
+                meridiem === 'དགོང་དག') {
+            return hour + 12;
+        } else {
+            return hour;
         }
-    });
+    },
+    meridiem : function (hour, minute, isLower) {
+        if (hour < 4) {
+            return 'མཚན་མོ';
+        } else if (hour < 10) {
+            return 'ཞོགས་ཀས';
+        } else if (hour < 17) {
+            return 'ཉིན་གུང';
+        } else if (hour < 20) {
+            return 'དགོང་དག';
+        } else {
+            return 'མཚན་མོ';
+        }
+    },
+    week : {
+        dow : 0, // Sunday is the first day of the week.
+        doy : 6  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return bo;
+return bo;
 
-}));
\ No newline at end of file
+})));
index ca290f3..7233063 100644 (file)
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    function relativeTimeWithMutation(number, withoutSuffix, key) {
-        var format = {
-            'mm': 'munutenn',
-            'MM': 'miz',
-            'dd': 'devezh'
-        };
-        return number + ' ' + mutation(format[key], number);
+function relativeTimeWithMutation(number, withoutSuffix, key) {
+    var format = {
+        'mm': 'munutenn',
+        'MM': 'miz',
+        'dd': 'devezh'
+    };
+    return number + ' ' + mutation(format[key], number);
+}
+function specialMutationForYears(number) {
+    switch (lastNumber(number)) {
+        case 1:
+        case 3:
+        case 4:
+        case 5:
+        case 9:
+            return number + ' bloaz';
+        default:
+            return number + ' vloaz';
     }
-    function specialMutationForYears(number) {
-        switch (lastNumber(number)) {
-            case 1:
-            case 3:
-            case 4:
-            case 5:
-            case 9:
-                return number + ' bloaz';
-            default:
-                return number + ' vloaz';
-        }
+}
+function lastNumber(number) {
+    if (number > 9) {
+        return lastNumber(number % 10);
     }
-    function lastNumber(number) {
-        if (number > 9) {
-            return lastNumber(number % 10);
-        }
-        return number;
+    return number;
+}
+function mutation(text, number) {
+    if (number === 2) {
+        return softMutation(text);
     }
-    function mutation(text, number) {
-        if (number === 2) {
-            return softMutation(text);
-        }
+    return text;
+}
+function softMutation(text) {
+    var mutationTable = {
+        'm': 'v',
+        'b': 'v',
+        'd': 'z'
+    };
+    if (mutationTable[text.charAt(0)] === undefined) {
         return text;
     }
-    function softMutation(text) {
-        var mutationTable = {
-            'm': 'v',
-            'b': 'v',
-            'd': 'z'
-        };
-        if (mutationTable[text.charAt(0)] === undefined) {
-            return text;
-        }
-        return mutationTable[text.charAt(0)] + text.substring(1);
-    }
+    return mutationTable[text.charAt(0)] + text.substring(1);
+}
 
-    var br = moment.defineLocale('br', {
-        months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
-        monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
-        weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
-        weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
-        weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
-        weekdaysParseExact : true,
-        longDateFormat : {
-            LT : 'h[e]mm A',
-            LTS : 'h[e]mm:ss A',
-            L : 'DD/MM/YYYY',
-            LL : 'D [a viz] MMMM YYYY',
-            LLL : 'D [a viz] MMMM YYYY h[e]mm A',
-            LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
-        },
-        calendar : {
-            sameDay : '[Hiziv da] LT',
-            nextDay : '[Warc\'hoazh da] LT',
-            nextWeek : 'dddd [da] LT',
-            lastDay : '[Dec\'h da] LT',
-            lastWeek : 'dddd [paset da] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : 'a-benn %s',
-            past : '%s \'zo',
-            s : 'un nebeud segondennoù',
-            m : 'ur vunutenn',
-            mm : relativeTimeWithMutation,
-            h : 'un eur',
-            hh : '%d eur',
-            d : 'un devezh',
-            dd : relativeTimeWithMutation,
-            M : 'ur miz',
-            MM : relativeTimeWithMutation,
-            y : 'ur bloaz',
-            yy : specialMutationForYears
-        },
-        ordinalParse: /\d{1,2}(añ|vet)/,
-        ordinal : function (number) {
-            var output = (number === 1) ? 'añ' : 'vet';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
+var br = moment.defineLocale('br', {
+    months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
+    monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
+    weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
+    weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
+    weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
+    weekdaysParseExact : true,
+    longDateFormat : {
+        LT : 'h[e]mm A',
+        LTS : 'h[e]mm:ss A',
+        L : 'DD/MM/YYYY',
+        LL : 'D [a viz] MMMM YYYY',
+        LLL : 'D [a viz] MMMM YYYY h[e]mm A',
+        LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
+    },
+    calendar : {
+        sameDay : '[Hiziv da] LT',
+        nextDay : '[Warc\'hoazh da] LT',
+        nextWeek : 'dddd [da] LT',
+        lastDay : '[Dec\'h da] LT',
+        lastWeek : 'dddd [paset da] LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : 'a-benn %s',
+        past : '%s \'zo',
+        s : 'un nebeud segondennoù',
+        m : 'ur vunutenn',
+        mm : relativeTimeWithMutation,
+        h : 'un eur',
+        hh : '%d eur',
+        d : 'un devezh',
+        dd : relativeTimeWithMutation,
+        M : 'ur miz',
+        MM : relativeTimeWithMutation,
+        y : 'ur bloaz',
+        yy : specialMutationForYears
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}(añ|vet)/,
+    ordinal : function (number) {
+        var output = (number === 1) ? 'añ' : 'vet';
+        return number + output;
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 4  // The week that contains Jan 4th is the first week of the year.
+    }
+});
 
-    return br;
+return br;
 
-}));
\ No newline at end of file
+})));
index ddd346c..760a786 100644 (file)
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    function translate(number, withoutSuffix, key) {
-        var result = number + ' ';
-        switch (key) {
-            case 'm':
-                return withoutSuffix ? 'jedna minuta' : 'jedne minute';
-            case 'mm':
-                if (number === 1) {
-                    result += 'minuta';
-                } else if (number === 2 || number === 3 || number === 4) {
-                    result += 'minute';
-                } else {
-                    result += 'minuta';
-                }
-                return result;
-            case 'h':
-                return withoutSuffix ? 'jedan sat' : 'jednog sata';
-            case 'hh':
-                if (number === 1) {
-                    result += 'sat';
-                } else if (number === 2 || number === 3 || number === 4) {
-                    result += 'sata';
-                } else {
-                    result += 'sati';
-                }
-                return result;
-            case 'dd':
-                if (number === 1) {
-                    result += 'dan';
-                } else {
-                    result += 'dana';
-                }
-                return result;
-            case 'MM':
-                if (number === 1) {
-                    result += 'mjesec';
-                } else if (number === 2 || number === 3 || number === 4) {
-                    result += 'mjeseca';
-                } else {
-                    result += 'mjeseci';
-                }
-                return result;
-            case 'yy':
-                if (number === 1) {
-                    result += 'godina';
-                } else if (number === 2 || number === 3 || number === 4) {
-                    result += 'godine';
-                } else {
-                    result += 'godina';
-                }
-                return result;
-        }
+function translate(number, withoutSuffix, key) {
+    var result = number + ' ';
+    switch (key) {
+        case 'm':
+            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minuta';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'jedan sat' : 'jednog sata';
+        case 'hh':
+            if (number === 1) {
+                result += 'sat';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'sata';
+            } else {
+                result += 'sati';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dana';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mjesec';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'mjeseca';
+            } else {
+                result += 'mjeseci';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'godina';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'godine';
+            } else {
+                result += 'godina';
+            }
+            return result;
     }
+}
 
-    var bs = moment.defineLocale('bs', {
-        months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
-        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
-        monthsParseExact: true,
-        weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
-        weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
-        weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
-        weekdaysParseExact : true,
-        longDateFormat : {
-            LT : 'H:mm',
-            LTS : 'H:mm:ss',
-            L : 'DD.MM.YYYY',
-            LL : 'D. MMMM YYYY',
-            LLL : 'D. MMMM YYYY H:mm',
-            LLLL : 'dddd, D. MMMM YYYY H:mm'
+var bs = moment.defineLocale('bs', {
+    months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
+    monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
+    monthsParseExact: true,
+    weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+    weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+    weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+    weekdaysParseExact : true,
+    longDateFormat : {
+        LT : 'H:mm',
+        LTS : 'H:mm:ss',
+        L : 'DD.MM.YYYY',
+        LL : 'D. MMMM YYYY',
+        LLL : 'D. MMMM YYYY H:mm',
+        LLLL : 'dddd, D. MMMM YYYY H:mm'
+    },
+    calendar : {
+        sameDay  : '[danas u] LT',
+        nextDay  : '[sutra u] LT',
+        nextWeek : function () {
+            switch (this.day()) {
+                case 0:
+                    return '[u] [nedjelju] [u] LT';
+                case 3:
+                    return '[u] [srijedu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+            }
         },
-        calendar : {
-            sameDay  : '[danas u] LT',
-            nextDay  : '[sutra u] LT',
-            nextWeek : function () {
-                switch (this.day()) {
-                    case 0:
-                        return '[u] [nedjelju] [u] LT';
-                    case 3:
-                        return '[u] [srijedu] [u] LT';
-                    case 6:
-                        return '[u] [subotu] [u] LT';
-                    case 1:
-                    case 2:
-                    case 4:
-                    case 5:
-                        return '[u] dddd [u] LT';
-                }
-            },
-            lastDay  : '[jučer u] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                    case 0:
-                    case 3:
-                        return '[prošlu] dddd [u] LT';
-                    case 6:
-                        return '[prošle] [subote] [u] LT';
-                    case 1:
-                    case 2:
-                    case 4:
-                    case 5:
-                        return '[prošli] dddd [u] LT';
-                }
-            },
-            sameElse : 'L'
+        lastDay  : '[jučer u] LT',
+        lastWeek : function () {
+            switch (this.day()) {
+                case 0:
+                case 3:
+                    return '[prošlu] dddd [u] LT';
+                case 6:
+                    return '[prošle] [subote] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prošli] dddd [u] LT';
+            }
         },
-        relativeTime : {
-            future : 'za %s',
-            past   : 'prije %s',
-            s      : 'par sekundi',
-            m      : translate,
-            mm     : translate,
-            h      : translate,
-            hh     : translate,
-            d      : 'dan',
-            dd     : translate,
-            M      : 'mjesec',
-            MM     : translate,
-            y      : 'godinu',
-            yy     : translate
-        },
-        ordinalParse: /\d{1,2}\./,
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : 'za %s',
+        past   : 'prije %s',
+        s      : 'par sekundi',
+        m      : translate,
+        mm     : translate,
+        h      : translate,
+        hh     : translate,
+        d      : 'dan',
+        dd     : translate,
+        M      : 'mjesec',
+        MM     : translate,
+        y      : 'godinu',
+        yy     : translate
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}\./,
+    ordinal : '%d.',
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
 
-    return bs;
+return bs;
 
-}));
\ No newline at end of file
+})));
index 7882800..8064a5d 100644 (file)
@@ -7,75 +7,82 @@
        && typeof require === 'function' ? factory(require('../moment')) :
    typeof define === 'function' && define.amd ? define(['../moment'], factory) :
    factory(global.moment)
-}(this, function (moment) { 'use strict';
+}(this, (function (moment) { 'use strict';
 
 
-    var ca = moment.defineLocale('ca', {
-        months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
-        monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'),
-        monthsParseExact : true,
-        weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
-        weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
-        weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'),
-        weekdaysParseExact : true,
-        longDateFormat : {
-            LT : 'H:mm',
-            LTS : 'H:mm:ss',
-            L : 'DD/MM/YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY H:mm',
-            LLLL : 'dddd D MMMM YYYY H:mm'
+var ca = moment.defineLocale('ca', {
+    months : {
+        standalone: 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
+        format: 'de gener_de febrer_de març_d\'abril_de maig_de juny_de juliol_d\'agost_de setembre_d\'octubre_de novembre_de desembre'.split('_'),
+        isFormat: /D[oD]?(\s)+MMMM/
+    },
+    monthsShort : 'gen._febr._març_abr._maig_juny_jul._ag._set._oct._nov._des.'.split('_'),
+    monthsParseExact : true,
+    weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
+    weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
+    weekdaysMin : 'dg_dl_dt_dc_dj_dv_ds'.split('_'),
+    weekdaysParseExact : true,
+    longDateFormat : {
+        LT : 'H:mm',
+        LTS : 'H:mm:ss',
+        L : 'DD/MM/YYYY',
+        LL : 'D MMMM [de] YYYY',
+        ll : 'D MMM YYYY',
+        LLL : 'D MMMM [de] YYYY [a les] H:mm',
+        lll : 'D MMM YYYY, H:mm',
+        LLLL : 'dddd D MMMM [de] YYYY [a les] H:mm',
+        llll : 'ddd D MMM YYYY, H:mm'
+    },
+    calendar : {
+        sameDay : function () {
+            return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
         },
-        calendar : {
-            sameDay : function () {
-                return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            nextDay : function () {
-                return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            nextWeek : function () {
-                return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            lastDay : function () {
-                return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            lastWeek : function () {
-                return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            sameElse : 'L'
+        nextDay : function () {
+            return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
         },
-        relativeTime : {
-            future : 'en %s',
-            past : 'fa %s',
-            s : 'uns segons',
-            m : 'un minut',
-            mm : '%d minuts',
-            h : 'una hora',
-            hh : '%d hores',
-            d : 'un dia',
-            dd : '%d dies',
-            M : 'un mes',
-            MM : '%d mesos',
-            y : 'un any',
-            yy : '%d anys'
+        nextWeek : function () {
+            return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
         },
-        ordinalParse: /\d{1,2}(r|n|t|è|a)/,
-        ordinal : function (number, period) {
-            var output = (number === 1) ? 'r' :
-                (number === 2) ?