summaryrefslogtreecommitdiff
path: root/Echo
diff options
context:
space:
mode:
authorBrian Evans <grknight@gentoo.org>2018-11-20 10:08:19 -0500
committerBrian Evans <grknight@gentoo.org>2018-11-20 10:08:19 -0500
commitdb9979640e4e4ec713b356dcae22f90d05edf1fa (patch)
tree33fdda6e3bfd494effdbda85fba5d7df9f8be4f1 /Echo
parentUpdate Flow to REL1_30 (diff)
downloadextensions-db9979640e4e4ec713b356dcae22f90d05edf1fa.tar.gz
extensions-db9979640e4e4ec713b356dcae22f90d05edf1fa.tar.bz2
extensions-db9979640e4e4ec713b356dcae22f90d05edf1fa.zip
Update Echo to REL_1_30
Signed-off-by: Brian Evans <grknight@gentoo.org>
Diffstat (limited to 'Echo')
-rw-r--r--Echo/.csslintrc13
-rw-r--r--Echo/.eslintrc.json15
-rw-r--r--Echo/.gitignore28
-rw-r--r--Echo/.gitreview2
-rw-r--r--Echo/.jscsrc4
-rw-r--r--Echo/.jshintignore2
-rw-r--r--Echo/.jshintrc32
-rw-r--r--Echo/.mailmap16
-rw-r--r--Echo/.rubocop.yml25
-rw-r--r--Echo/.rubocop_todo.yml16
-rw-r--r--Echo/.stylelintrc.json7
-rw-r--r--Echo/CODE_OF_CONDUCT.md1
-rw-r--r--Echo/Echo.alias.php311
-rw-r--r--Echo/Echo.php442
-rw-r--r--Echo/Gemfile13
-rw-r--r--Echo/Gemfile.lock128
-rw-r--r--Echo/Gruntfile.js54
-rw-r--r--Echo/Hooks.php995
-rw-r--r--Echo/Makefile8
-rw-r--r--Echo/Notifier.php112
-rw-r--r--Echo/RELEASE_NOTES18
-rw-r--r--Echo/Rakefile10
-rw-r--r--Echo/Resources.php184
-rw-r--r--Echo/autoload.php103
-rw-r--r--Echo/composer.json10
-rw-r--r--Echo/composer.lock65
-rw-r--r--Echo/db_patches/echo_unread_wikis.sql18
-rw-r--r--Echo/db_patches/patch-add-echo_event-event_deleted.sql1
-rw-r--r--Echo/db_patches/patch-add-event_page_id-index.sql1
-rw-r--r--Echo/db_patches/patch-add-notification_event-index.sql1
-rw-r--r--Echo/db_patches/patch-add-page_event-index.sql1
-rw-r--r--Echo/db_patches/patch-add-user_read_timestamp-index.sql1
-rw-r--r--Echo/db_patches/patch-drop-echo_target_page-etp_user.sql11
-rw-r--r--Echo/db_patches/patch-drop-echo_target_page-etp_user.sqlite.sql26
-rw-r--r--Echo/db_patches/patch-notification-pk.sql3
-rw-r--r--Echo/echo.sql15
-rw-r--r--Echo/extension.json1024
-rw-r--r--Echo/gitinfo.json1
-rw-r--r--Echo/i18n/ace.json8
-rw-r--r--Echo/i18n/af.json56
-rw-r--r--Echo/i18n/ais.json68
-rw-r--r--Echo/i18n/am.json12
-rw-r--r--Echo/i18n/ang.json3
-rw-r--r--Echo/i18n/anp.json9
-rw-r--r--Echo/i18n/api/ar.json56
-rw-r--r--Echo/i18n/api/ast.json61
-rw-r--r--Echo/i18n/api/ba.json40
-rw-r--r--Echo/i18n/api/bg.json47
-rw-r--r--Echo/i18n/api/bn.json15
-rw-r--r--Echo/i18n/api/bs.json8
-rw-r--r--Echo/i18n/api/ca.json11
-rw-r--r--Echo/i18n/api/ce.json21
-rw-r--r--Echo/i18n/api/cs.json10
-rw-r--r--Echo/i18n/api/de.json51
-rw-r--r--Echo/i18n/api/en.json66
-rw-r--r--Echo/i18n/api/es.json46
-rw-r--r--Echo/i18n/api/et.json29
-rw-r--r--Echo/i18n/api/eu.json17
-rw-r--r--Echo/i18n/api/fa.json66
-rw-r--r--Echo/i18n/api/fi.json23
-rw-r--r--Echo/i18n/api/fr.json69
-rw-r--r--Echo/i18n/api/frr.json27
-rw-r--r--Echo/i18n/api/gl.json62
-rw-r--r--Echo/i18n/api/he.json51
-rw-r--r--Echo/i18n/api/hi.json22
-rw-r--r--Echo/i18n/api/hr.json8
-rw-r--r--Echo/i18n/api/hu.json40
-rw-r--r--Echo/i18n/api/id.json29
-rw-r--r--Echo/i18n/api/it.json47
-rw-r--r--Echo/i18n/api/ja.json20
-rw-r--r--Echo/i18n/api/kk-cyrl.json37
-rw-r--r--Echo/i18n/api/ko.json36
-rw-r--r--Echo/i18n/api/krc.json21
-rw-r--r--Echo/i18n/api/ksh.json34
-rw-r--r--Echo/i18n/api/lki.json21
-rw-r--r--Echo/i18n/api/lrc.json17
-rw-r--r--Echo/i18n/api/lt.json40
-rw-r--r--Echo/i18n/api/mai.json13
-rw-r--r--Echo/i18n/api/mk.json61
-rw-r--r--Echo/i18n/api/ml.json29
-rw-r--r--Echo/i18n/api/mr.json29
-rw-r--r--Echo/i18n/api/nap.json45
-rw-r--r--Echo/i18n/api/nb.json63
-rw-r--r--Echo/i18n/api/nl.json47
-rw-r--r--Echo/i18n/api/oc.json8
-rw-r--r--Echo/i18n/api/pl.json34
-rw-r--r--Echo/i18n/api/pms.json25
-rw-r--r--Echo/i18n/api/pt-br.json62
-rw-r--r--Echo/i18n/api/pt.json64
-rw-r--r--Echo/i18n/api/qqq.json68
-rw-r--r--Echo/i18n/api/ro.json15
-rw-r--r--Echo/i18n/api/roa-tara.json11
-rw-r--r--Echo/i18n/api/ru.json42
-rw-r--r--Echo/i18n/api/sah.json25
-rw-r--r--Echo/i18n/api/sl.json21
-rw-r--r--Echo/i18n/api/sv.json63
-rw-r--r--Echo/i18n/api/tr.json31
-rw-r--r--Echo/i18n/api/uk.json63
-rw-r--r--Echo/i18n/api/vi.json14
-rw-r--r--Echo/i18n/api/zh-hans.json62
-rw-r--r--Echo/i18n/api/zh-hant.json51
-rw-r--r--Echo/i18n/ar.json198
-rw-r--r--Echo/i18n/arq.json6
-rw-r--r--Echo/i18n/arz.json3
-rw-r--r--Echo/i18n/as.json3
-rw-r--r--Echo/i18n/ast.json202
-rw-r--r--Echo/i18n/atj.json19
-rw-r--r--Echo/i18n/awa.json2
-rw-r--r--Echo/i18n/ay.json1
-rw-r--r--Echo/i18n/az.json49
-rw-r--r--Echo/i18n/azb.json25
-rw-r--r--Echo/i18n/ba.json140
-rw-r--r--Echo/i18n/be-tarask.json149
-rw-r--r--Echo/i18n/be.json81
-rw-r--r--Echo/i18n/bg.json165
-rw-r--r--Echo/i18n/bgn.json10
-rw-r--r--Echo/i18n/bho.json3
-rw-r--r--Echo/i18n/bn.json196
-rw-r--r--Echo/i18n/bqi.json8
-rw-r--r--Echo/i18n/br.json84
-rw-r--r--Echo/i18n/bs.json222
-rw-r--r--Echo/i18n/ca.json163
-rw-r--r--Echo/i18n/cdo.json41
-rw-r--r--Echo/i18n/ce.json141
-rw-r--r--Echo/i18n/ckb.json79
-rw-r--r--Echo/i18n/cs.json195
-rw-r--r--Echo/i18n/csb.json9
-rw-r--r--Echo/i18n/cu.json5
-rw-r--r--Echo/i18n/cy.json49
-rw-r--r--Echo/i18n/da.json81
-rw-r--r--Echo/i18n/de.json211
-rw-r--r--Echo/i18n/din.json11
-rw-r--r--Echo/i18n/diq.json89
-rw-r--r--Echo/i18n/dsb.json44
-rw-r--r--Echo/i18n/dty.json9
-rw-r--r--Echo/i18n/el.json158
-rw-r--r--Echo/i18n/en-gb.json7
-rw-r--r--Echo/i18n/en.json237
-rw-r--r--Echo/i18n/eo.json134
-rw-r--r--Echo/i18n/es.json223
-rw-r--r--Echo/i18n/et.json155
-rw-r--r--Echo/i18n/eu.json105
-rw-r--r--Echo/i18n/fa.json234
-rw-r--r--Echo/i18n/fi.json180
-rw-r--r--Echo/i18n/fo.json1
-rw-r--r--Echo/i18n/fr.json236
-rw-r--r--Echo/i18n/frp.json3
-rw-r--r--Echo/i18n/frr.json65
-rw-r--r--Echo/i18n/fur.json9
-rw-r--r--Echo/i18n/fy.json8
-rw-r--r--Echo/i18n/gd.json58
-rw-r--r--Echo/i18n/gl.json203
-rw-r--r--Echo/i18n/glk.json9
-rw-r--r--Echo/i18n/gn.json1
-rw-r--r--Echo/i18n/gom-deva.json9
-rw-r--r--Echo/i18n/gom-latn.json8
-rw-r--r--Echo/i18n/gor.json9
-rw-r--r--Echo/i18n/grc.json9
-rw-r--r--Echo/i18n/gsw.json50
-rw-r--r--Echo/i18n/gu.json96
-rw-r--r--Echo/i18n/hak.json9
-rw-r--r--Echo/i18n/haw.json1
-rw-r--r--Echo/i18n/he.json252
-rw-r--r--Echo/i18n/hi.json167
-rw-r--r--Echo/i18n/hif-latn.json8
-rw-r--r--Echo/i18n/hr.json144
-rw-r--r--Echo/i18n/hsb.json49
-rw-r--r--Echo/i18n/hsn.json13
-rw-r--r--Echo/i18n/ht.json3
-rw-r--r--Echo/i18n/hu-formal.json8
-rw-r--r--Echo/i18n/hu.json172
-rw-r--r--Echo/i18n/hy.json124
-rw-r--r--Echo/i18n/ia.json64
-rw-r--r--Echo/i18n/id.json112
-rw-r--r--Echo/i18n/ie.json8
-rw-r--r--Echo/i18n/ilo.json49
-rw-r--r--Echo/i18n/inh.json9
-rw-r--r--Echo/i18n/io.json14
-rw-r--r--Echo/i18n/is.json80
-rw-r--r--Echo/i18n/it.json185
-rw-r--r--Echo/i18n/ja.json176
-rw-r--r--Echo/i18n/jam.json9
-rw-r--r--Echo/i18n/jut.json9
-rw-r--r--Echo/i18n/jv.json263
-rw-r--r--Echo/i18n/ka.json103
-rw-r--r--Echo/i18n/kab.json13
-rw-r--r--Echo/i18n/kbp.json9
-rw-r--r--Echo/i18n/khw.json3
-rw-r--r--Echo/i18n/kk-cyrl.json119
-rw-r--r--Echo/i18n/km.json2
-rw-r--r--Echo/i18n/kn.json13
-rw-r--r--Echo/i18n/ko.json189
-rw-r--r--Echo/i18n/krc.json73
-rw-r--r--Echo/i18n/krl.json10
-rw-r--r--Echo/i18n/ks-arab.json8
-rw-r--r--Echo/i18n/ksh.json182
-rw-r--r--Echo/i18n/ku-latn.json38
-rw-r--r--Echo/i18n/ky.json3
-rw-r--r--Echo/i18n/la.json48
-rw-r--r--Echo/i18n/lad.json5
-rw-r--r--Echo/i18n/lb.json183
-rw-r--r--Echo/i18n/lfn.json8
-rw-r--r--Echo/i18n/li.json8
-rw-r--r--Echo/i18n/lij.json131
-rw-r--r--Echo/i18n/lki.json83
-rw-r--r--Echo/i18n/lrc.json37
-rw-r--r--Echo/i18n/lt.json209
-rw-r--r--Echo/i18n/luz.json3
-rw-r--r--Echo/i18n/lv.json127
-rw-r--r--Echo/i18n/lzh.json9
-rw-r--r--Echo/i18n/mai.json104
-rw-r--r--Echo/i18n/mg.json12
-rw-r--r--Echo/i18n/mhr.json9
-rw-r--r--Echo/i18n/mk.json211
-rw-r--r--Echo/i18n/ml.json96
-rw-r--r--Echo/i18n/mn.json4
-rw-r--r--Echo/i18n/mr.json172
-rw-r--r--Echo/i18n/ms.json55
-rw-r--r--Echo/i18n/mt.json42
-rw-r--r--Echo/i18n/mwl.json52
-rw-r--r--Echo/i18n/my.json19
-rw-r--r--Echo/i18n/nan.json8
-rw-r--r--Echo/i18n/nap.json200
-rw-r--r--Echo/i18n/nb.json245
-rw-r--r--Echo/i18n/nds-nl.json78
-rw-r--r--Echo/i18n/nds.json8
-rw-r--r--Echo/i18n/ne.json85
-rw-r--r--Echo/i18n/nl-informal.json1
-rw-r--r--Echo/i18n/nl.json227
-rw-r--r--Echo/i18n/nn.json108
-rw-r--r--Echo/i18n/oc.json119
-rw-r--r--Echo/i18n/olo.json30
-rw-r--r--Echo/i18n/or.json27
-rw-r--r--Echo/i18n/pa.json64
-rw-r--r--Echo/i18n/pam.json10
-rw-r--r--Echo/i18n/pfl.json3
-rw-r--r--Echo/i18n/pl.json196
-rw-r--r--Echo/i18n/pms.json62
-rw-r--r--Echo/i18n/pnb.json6
-rw-r--r--Echo/i18n/ps.json47
-rw-r--r--Echo/i18n/pt-br.json225
-rw-r--r--Echo/i18n/pt.json219
-rw-r--r--Echo/i18n/qqq.json222
-rw-r--r--Echo/i18n/qu.json11
-rw-r--r--Echo/i18n/rm.json6
-rw-r--r--Echo/i18n/ro.json107
-rw-r--r--Echo/i18n/roa-tara.json71
-rw-r--r--Echo/i18n/ru.json228
-rw-r--r--Echo/i18n/rue.json3
-rw-r--r--Echo/i18n/sa.json5
-rw-r--r--Echo/i18n/sah.json101
-rw-r--r--Echo/i18n/sat.json9
-rw-r--r--Echo/i18n/scn.json48
-rw-r--r--Echo/i18n/sco.json3
-rw-r--r--Echo/i18n/sd.json34
-rw-r--r--Echo/i18n/sgs.json11
-rw-r--r--Echo/i18n/sh.json45
-rw-r--r--Echo/i18n/shn.json5
-rw-r--r--Echo/i18n/si.json14
-rw-r--r--Echo/i18n/sk.json126
-rw-r--r--Echo/i18n/skr-arab.json61
-rw-r--r--Echo/i18n/sl.json204
-rw-r--r--Echo/i18n/so.json50
-rw-r--r--Echo/i18n/sq.json48
-rw-r--r--Echo/i18n/sr-ec.json155
-rw-r--r--Echo/i18n/sr-el.json112
-rw-r--r--Echo/i18n/sty.json8
-rw-r--r--Echo/i18n/su.json7
-rw-r--r--Echo/i18n/sv.json200
-rw-r--r--Echo/i18n/szl.json3
-rw-r--r--Echo/i18n/ta.json37
-rw-r--r--Echo/i18n/tay.json37
-rw-r--r--Echo/i18n/tcy.json13
-rw-r--r--Echo/i18n/te.json47
-rw-r--r--Echo/i18n/tg-cyrl.json16
-rw-r--r--Echo/i18n/th.json84
-rw-r--r--Echo/i18n/tl.json43
-rw-r--r--Echo/i18n/tr.json186
-rw-r--r--Echo/i18n/tt-cyrl.json104
-rw-r--r--Echo/i18n/tt-latn.json9
-rw-r--r--Echo/i18n/udm.json8
-rw-r--r--Echo/i18n/ug-arab.json4
-rw-r--r--Echo/i18n/uk.json224
-rw-r--r--Echo/i18n/ur.json113
-rw-r--r--Echo/i18n/uz.json48
-rw-r--r--Echo/i18n/vec.json106
-rw-r--r--Echo/i18n/vep.json9
-rw-r--r--Echo/i18n/vi.json174
-rw-r--r--Echo/i18n/vro.json2
-rw-r--r--Echo/i18n/wa.json10
-rw-r--r--Echo/i18n/war.json6
-rw-r--r--Echo/i18n/wuu.json8
-rw-r--r--Echo/i18n/xmf.json5
-rw-r--r--Echo/i18n/yi.json118
-rw-r--r--Echo/i18n/yo.json19
-rw-r--r--Echo/i18n/yua.json16
-rw-r--r--Echo/i18n/yue.json23
-rw-r--r--Echo/i18n/zgh.json11
-rw-r--r--Echo/i18n/zh-hans.json219
-rw-r--r--Echo/i18n/zh-hant.json218
-rw-r--r--Echo/images/betafeatures-icon-notifications-ltr.svg27
-rw-r--r--Echo/images/betafeatures-icon-notifications-rtl.svg27
-rw-r--r--Echo/images/pending.gifbin0 -> 2032 bytes
-rw-r--r--Echo/includes/AttributeManager.php258
-rw-r--r--Echo/includes/BatchRowUpdate.php454
-rw-r--r--Echo/includes/Bundleable.php29
-rw-r--r--Echo/includes/Bundler.php48
-rw-r--r--Echo/includes/ContainmentSet.php90
-rw-r--r--Echo/includes/DataOutputFormatter.php125
-rw-r--r--Echo/includes/DeferredMarkAsDeletedUpdate.php72
-rw-r--r--Echo/includes/DeferredMarkAsReadUpdate.php39
-rw-r--r--Echo/includes/DiffParser.php194
-rw-r--r--Echo/includes/DiscussionParser.php796
-rw-r--r--Echo/includes/EchoDbFactory.php98
-rw-r--r--Echo/includes/EmailBatch.php175
-rw-r--r--Echo/includes/EmailBundler.php303
-rw-r--r--Echo/includes/EmailFormat.php6
-rw-r--r--Echo/includes/EmailFormatter.php858
-rw-r--r--Echo/includes/EmailFrequency.php8
-rw-r--r--Echo/includes/EventLogging.php81
-rw-r--r--Echo/includes/ForeignNotifications.php254
-rw-r--r--Echo/includes/ForeignWikiRequest.php164
-rw-r--r--Echo/includes/NotifUser.php611
-rw-r--r--Echo/includes/Notifier.php135
-rw-r--r--Echo/includes/ResourceLoaderEchoImageModule.php62
-rw-r--r--Echo/includes/SeenTime.php119
-rw-r--r--Echo/includes/UnreadWikis.php144
-rw-r--r--Echo/includes/UserLocator.php47
-rw-r--r--Echo/includes/api/ApiCrossWikiBase.php126
-rw-r--r--Echo/includes/api/ApiEchoArticleReminder.php112
-rw-r--r--Echo/includes/api/ApiEchoMarkRead.php76
-rw-r--r--Echo/includes/api/ApiEchoMarkSeen.php65
-rw-r--r--Echo/includes/api/ApiEchoNotifications.php650
-rw-r--r--Echo/includes/api/ApiEchoUnreadNotificationPages.php212
-rw-r--r--Echo/includes/cache/LocalCache.php12
-rw-r--r--Echo/includes/cache/RevisionLocalCache.php15
-rw-r--r--Echo/includes/cache/TitleLocalCache.php5
-rw-r--r--Echo/includes/controller/ModerationController.php41
-rw-r--r--Echo/includes/controller/NotificationController.php360
-rw-r--r--Echo/includes/formatters/ArticleReminderPresentationModel.php30
-rw-r--r--Echo/includes/formatters/BasicFormatter.php925
-rw-r--r--Echo/includes/formatters/CommentFormatter.php34
-rw-r--r--Echo/includes/formatters/EchoEventDigestFormatter.php53
-rw-r--r--Echo/includes/formatters/EchoEventFormatter.php71
-rw-r--r--Echo/includes/formatters/EchoFlyoutFormatter.php78
-rw-r--r--Echo/includes/formatters/EchoForeignPresentationModel.php49
-rw-r--r--Echo/includes/formatters/EchoHtmlDigestEmailFormatter.php226
-rw-r--r--Echo/includes/formatters/EchoHtmlEmailFormatter.php159
-rw-r--r--Echo/includes/formatters/EchoIcon.php88
-rw-r--r--Echo/includes/formatters/EchoModelFormatter.php31
-rw-r--r--Echo/includes/formatters/EchoPlainTextDigestEmailFormatter.php78
-rw-r--r--Echo/includes/formatters/EchoPlainTextEmailFormatter.php53
-rw-r--r--Echo/includes/formatters/EditFormatter.php87
-rw-r--r--Echo/includes/formatters/EditThresholdPresentationModel.php22
-rw-r--r--Echo/includes/formatters/EditUserTalkFormatter.php42
-rw-r--r--Echo/includes/formatters/EditUserTalkPresentationModel.php90
-rw-r--r--Echo/includes/formatters/EmailUserPresentationModel.php21
-rw-r--r--Echo/includes/formatters/EventPresentationModel.php678
-rw-r--r--Echo/includes/formatters/MentionFormatter.php27
-rw-r--r--Echo/includes/formatters/MentionPresentationModel.php129
-rw-r--r--Echo/includes/formatters/MentionStatusPresentationModel.php142
-rw-r--r--Echo/includes/formatters/NotificationFormatter.php190
-rw-r--r--Echo/includes/formatters/PageLinkFormatter.php199
-rw-r--r--Echo/includes/formatters/PageLinkedPresentationModel.php114
-rw-r--r--Echo/includes/formatters/PresentationModelSectionTrait.php96
-rw-r--r--Echo/includes/formatters/RevertedPresentationModel.php85
-rw-r--r--Echo/includes/formatters/SpecialNotificationsFormatter.php113
-rw-r--r--Echo/includes/formatters/UserRightsFormatter.php71
-rw-r--r--Echo/includes/formatters/UserRightsPresentationModel.php110
-rw-r--r--Echo/includes/formatters/WelcomePresentationModel.php25
-rw-r--r--Echo/includes/gateway/UserNotificationGateway.php95
-rw-r--r--Echo/includes/iterator/CallbackFilterIterator.php24
-rw-r--r--Echo/includes/iterator/FilteredSequentialIterator.php60
-rw-r--r--Echo/includes/iterator/MultipleIterator.php5
-rw-r--r--Echo/includes/jobs/NotificationDeleteJob.php15
-rw-r--r--Echo/includes/jobs/NotificationEmailBundleJob.php26
-rw-r--r--Echo/includes/jobs/NotificationJob.php12
-rw-r--r--Echo/includes/mapper/AbstractMapper.php8
-rw-r--r--Echo/includes/mapper/EventMapper.php173
-rw-r--r--Echo/includes/mapper/NotificationMapper.php356
-rw-r--r--Echo/includes/mapper/TargetPageMapper.php126
-rw-r--r--Echo/includes/model/Event.php244
-rw-r--r--Echo/includes/model/Notification.php138
-rw-r--r--Echo/includes/model/TargetPage.php68
-rw-r--r--Echo/includes/ooui/LabelIconWidget.php44
-rw-r--r--Echo/includes/schemaUpdate.php48
-rw-r--r--Echo/includes/special/NotificationPager.php71
-rw-r--r--Echo/includes/special/SpecialDisplayNotificationsConfiguration.php302
-rw-r--r--Echo/includes/special/SpecialNotifications.php276
-rw-r--r--Echo/includes/special/SpecialNotificationsMarkRead.php152
-rw-r--r--Echo/jsduck.external.js48
-rw-r--r--Echo/jsduck.json13
-rw-r--r--Echo/jsduck_custom_tags.rb83
-rw-r--r--Echo/maintenance/backfillReadBundles.php80
-rw-r--r--Echo/maintenance/backfillUnreadWikis.php73
-rw-r--r--Echo/maintenance/generateSampleNotifications.php499
-rw-r--r--Echo/maintenance/processEchoEmailBatch.php8
-rw-r--r--Echo/maintenance/removeInvalidNotification.php40
-rw-r--r--Echo/maintenance/removeInvalidTargetPage.php113
-rw-r--r--Echo/maintenance/removeOrphanedEvents.php72
-rw-r--r--Echo/maintenance/testDiscussionParser.php24
-rw-r--r--Echo/maintenance/updateEchoSchemaForSuppression.php43
-rw-r--r--Echo/modules/api/mw.echo.api.APIHandler.js273
-rw-r--r--Echo/modules/api/mw.echo.api.EchoApi.js339
-rw-r--r--Echo/modules/api/mw.echo.api.ForeignAPIHandler.js44
-rw-r--r--Echo/modules/api/mw.echo.api.LocalAPIHandler.js130
-rw-r--r--Echo/modules/api/mw.echo.api.NetworkHandler.js79
-rw-r--r--Echo/modules/api/mw.echo.api.PromisePrioritizer.js88
-rw-r--r--Echo/modules/api/mw.echo.api.js4
-rw-r--r--Echo/modules/controller/mw.echo.Controller.js791
-rw-r--r--Echo/modules/echo.mixins.less12
-rw-r--r--Echo/modules/echo.variables.less53
-rw-r--r--Echo/modules/ext.echo.init.js136
-rw-r--r--Echo/modules/ext.echo.moment-hack.js48
-rw-r--r--Echo/modules/hooks.txt25
-rw-r--r--Echo/modules/icons/CrossReferenced.pngbin322 -> 0 bytes
-rw-r--r--Echo/modules/icons/Deletion.pngbin291 -> 0 bytes
-rw-r--r--Echo/modules/icons/Featured.pngbin337 -> 0 bytes
-rw-r--r--Echo/modules/icons/Generic.pngbin536 -> 0 bytes
-rw-r--r--Echo/modules/icons/Gratitude.pngbin3231 -> 0 bytes
-rw-r--r--Echo/modules/icons/Help.pngbin3237 -> 0 bytes
-rw-r--r--Echo/modules/icons/NotificationsPage-ltr.pngbin235 -> 0 bytes
-rw-r--r--Echo/modules/icons/NotificationsPage-rtl.pngbin305 -> 0 bytes
-rw-r--r--Echo/modules/icons/Preferences.pngbin3128 -> 0 bytes
-rw-r--r--Echo/modules/icons/Revert.pngbin324 -> 0 bytes
-rw-r--r--Echo/modules/icons/Reviewed.pngbin309 -> 0 bytes
-rw-r--r--Echo/modules/icons/ReviewedWithTags.pngbin257 -> 0 bytes
-rw-r--r--Echo/modules/icons/Settings.pngbin349 -> 0 bytes
-rw-r--r--Echo/modules/icons/Talk.pngbin274 -> 0 bytes
-rw-r--r--Echo/modules/icons/apex/badgeicons.json14
-rw-r--r--Echo/modules/icons/badgeicons.json19
-rw-r--r--Echo/modules/icons/bellOn-rtl.svg2
-rw-r--r--Echo/modules/icons/changes.svg (renamed from Echo/modules/icons/speechBubble-rtl.svg)4
-rw-r--r--Echo/modules/icons/chat.svg4
-rw-r--r--Echo/modules/icons/double-check.svg5
-rw-r--r--Echo/modules/icons/edit-user-talk.svg4
-rw-r--r--Echo/modules/icons/emailuser.svg4
-rw-r--r--Echo/modules/icons/feedback.svg4
-rw-r--r--Echo/modules/icons/generic.svg7
-rw-r--r--Echo/modules/icons/global.svg4
-rw-r--r--Echo/modules/icons/help.svg10
-rw-r--r--Echo/modules/icons/link-blue.svg7
-rw-r--r--Echo/modules/icons/mediawiki/badgeicons.json20
-rw-r--r--Echo/modules/icons/mention-failure.svg4
-rw-r--r--Echo/modules/icons/mention-status-bundle.svg5
-rw-r--r--Echo/modules/icons/mention-success.svg5
-rw-r--r--Echo/modules/icons/mention.svg4
-rw-r--r--Echo/modules/icons/ooui-edit-ltr-progressive.svg4
-rw-r--r--Echo/modules/icons/ooui-edit-rtl-progressive.svg4
-rw-r--r--Echo/modules/icons/revert.svg10
-rw-r--r--Echo/modules/icons/reviewed.svg4
-rw-r--r--Echo/modules/icons/speechBubbles-ltr.svg (renamed from Echo/modules/icons/speechBubble-ltr.svg)4
-rw-r--r--Echo/modules/icons/speechBubbles-rtl.svg4
-rw-r--r--Echo/modules/icons/thanks-ltr.svg4
-rw-r--r--Echo/modules/icons/thanks-rtl.svg4
-rw-r--r--Echo/modules/icons/trash.svg4
-rw-r--r--Echo/modules/icons/tray.svg4
-rw-r--r--Echo/modules/icons/user-rights.svg4
-rw-r--r--Echo/modules/icons/user-speech-bubble.svg4
-rw-r--r--Echo/modules/logger/mw.echo.Logger.js50
-rw-r--r--Echo/modules/model/mw.echo.dm.BundleNotificationItem.js162
-rw-r--r--Echo/modules/model/mw.echo.dm.CrossWikiNotificationItem.js165
-rw-r--r--Echo/modules/model/mw.echo.dm.FiltersModel.js99
-rw-r--r--Echo/modules/model/mw.echo.dm.ModelManager.js484
-rw-r--r--Echo/modules/model/mw.echo.dm.NotificationGroupsList.js164
-rw-r--r--Echo/modules/model/mw.echo.dm.NotificationItem.js303
-rw-r--r--Echo/modules/model/mw.echo.dm.NotificationsList.js271
-rw-r--r--Echo/modules/model/mw.echo.dm.PaginationModel.js222
-rw-r--r--Echo/modules/model/mw.echo.dm.SeenTimeModel.js81
-rw-r--r--Echo/modules/model/mw.echo.dm.SortedList.js30
-rw-r--r--Echo/modules/model/mw.echo.dm.SourcePagesModel.js180
-rw-r--r--Echo/modules/model/mw.echo.dm.UnreadNotificationCounter.js147
-rw-r--r--Echo/modules/model/mw.echo.dm.js3
-rw-r--r--Echo/modules/mw.echo.js4
-rw-r--r--Echo/modules/nojs/mw.echo.alert.less10
-rw-r--r--Echo/modules/nojs/mw.echo.alert.monobook.less2
-rw-r--r--Echo/modules/nojs/mw.echo.badge.less104
-rw-r--r--Echo/modules/nojs/mw.echo.badge.modern.less8
-rw-r--r--Echo/modules/nojs/mw.echo.badge.monobook.less36
-rw-r--r--Echo/modules/nojs/mw.echo.badge.vector.less21
-rw-r--r--Echo/modules/nojs/mw.echo.notifications.less58
-rw-r--r--Echo/modules/nojs/mw.echo.special.less178
-rw-r--r--Echo/modules/ooui/mw.echo.ui.BadgeLinkWidget.js44
-rw-r--r--Echo/modules/ooui/mw.echo.ui.NotificationBadgeWidget.js320
-rw-r--r--Echo/modules/ooui/mw.echo.ui.NotificationOptionWidget.js131
-rw-r--r--Echo/modules/ooui/mw.echo.ui.NotificationsWidget.js134
-rw-r--r--Echo/modules/ooui/mw.echo.ui.PlaceholderOptionWidget.js24
-rw-r--r--Echo/modules/ooui/mw.echo.ui.js4
-rw-r--r--Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.less67
-rw-r--r--Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.modern.less13
-rw-r--r--Echo/modules/ooui/styles/mw.echo.ui.NotificationOptionWidget.less94
-rw-r--r--Echo/modules/ooui/styles/mw.echo.ui.NotificationOptionWidget.modern.less18
-rw-r--r--Echo/modules/ooui/styles/mw.echo.ui.NotificationsWidget.less9
-rw-r--r--Echo/modules/special/Feedback.pngbin435 -> 0 bytes
-rw-r--r--Echo/modules/special/FeedbackHover.pngbin424 -> 0 bytes
-rw-r--r--Echo/modules/special/Help.pngbin457 -> 0 bytes
-rw-r--r--Echo/modules/special/MoreInfo.pngbin303 -> 0 bytes
-rw-r--r--Echo/modules/special/MoreInfoHover.pngbin313 -> 0 bytes
-rw-r--r--Echo/modules/special/Preferences.pngbin3128 -> 0 bytes
-rw-r--r--Echo/modules/special/ext.echo.special.js208
-rw-r--r--Echo/modules/styles/LabelIconWidget.less13
-rw-r--r--Echo/modules/styles/mw.echo.ui.ActionMenuPopupWidget.less6
-rw-r--r--Echo/modules/styles/mw.echo.ui.ConfirmationPopupWidget.less24
-rw-r--r--Echo/modules/styles/mw.echo.ui.CrossWikiNotificationItemWidget.less74
-rw-r--r--Echo/modules/styles/mw.echo.ui.CrossWikiUnreadFilterWidget.less18
-rw-r--r--Echo/modules/styles/mw.echo.ui.CrossWikiUnreadFilterWidget.monobook.less7
-rw-r--r--Echo/modules/styles/mw.echo.ui.DatedNotificationsWidget.less22
-rw-r--r--Echo/modules/styles/mw.echo.ui.DatedSubGroupListWidget.less42
-rw-r--r--Echo/modules/styles/mw.echo.ui.FooterNoticeWidget.less39
-rw-r--r--Echo/modules/styles/mw.echo.ui.MenuItemWidget.less90
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.less92
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.modern.less18
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.monobook.less (renamed from Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.monobook.less)18
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationItemWidget.less290
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationItemWidget.modern.less25
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationsInboxWidget.less94
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationsListWidget.less22
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationsListWidget.monobook.less (renamed from Echo/modules/ooui/styles/mw.echo.ui.NotificationsWidget.monobook.less)2
-rw-r--r--Echo/modules/styles/mw.echo.ui.NotificationsWrapper.less3
-rw-r--r--Echo/modules/styles/mw.echo.ui.PageFilterWidget.less8
-rw-r--r--Echo/modules/styles/mw.echo.ui.PageNotificationsOptionWidget.less53
-rw-r--r--Echo/modules/styles/mw.echo.ui.PaginationWidget.less19
-rw-r--r--Echo/modules/styles/mw.echo.ui.PlaceholderItemWidget.less5
-rw-r--r--Echo/modules/styles/mw.echo.ui.SpecialHelpMenuWidget.less41
-rw-r--r--Echo/modules/styles/mw.echo.ui.SubGroupListWidget.less36
-rw-r--r--Echo/modules/styles/mw.echo.ui.ToggleReadCircleButtonWidget.less39
-rw-r--r--Echo/modules/styles/mw.echo.ui.overlay.less8
-rw-r--r--Echo/modules/styles/mw.echo.ui.overlay.minerva.less26
-rw-r--r--Echo/modules/styles/mw.echo.ui.overlay.monobook.less8
-rw-r--r--Echo/modules/styles/mw.echo.ui.overlay.vector.less3
-rw-r--r--Echo/modules/ui/mw.echo.ui.ActionMenuPopupWidget.js89
-rw-r--r--Echo/modules/ui/mw.echo.ui.BadgeLinkWidget.js77
-rw-r--r--Echo/modules/ui/mw.echo.ui.BundleNotificationItemWidget.js227
-rw-r--r--Echo/modules/ui/mw.echo.ui.ClonedNotificationItemWidget.js87
-rw-r--r--Echo/modules/ui/mw.echo.ui.ConfirmationPopupWidget.js67
-rw-r--r--Echo/modules/ui/mw.echo.ui.CrossWikiNotificationItemWidget.js360
-rw-r--r--Echo/modules/ui/mw.echo.ui.CrossWikiUnreadFilterWidget.js173
-rw-r--r--Echo/modules/ui/mw.echo.ui.DatedNotificationsWidget.js174
-rw-r--r--Echo/modules/ui/mw.echo.ui.DatedSubGroupListWidget.js67
-rw-r--r--Echo/modules/ui/mw.echo.ui.FooterNoticeWidget.js81
-rw-r--r--Echo/modules/ui/mw.echo.ui.MenuItemWidget.js137
-rw-r--r--Echo/modules/ui/mw.echo.ui.NotificationBadgeWidget.js376
-rw-r--r--Echo/modules/ui/mw.echo.ui.NotificationItemWidget.js422
-rw-r--r--Echo/modules/ui/mw.echo.ui.NotificationsInboxWidget.js347
-rw-r--r--Echo/modules/ui/mw.echo.ui.NotificationsListWidget.js244
-rw-r--r--Echo/modules/ui/mw.echo.ui.NotificationsWrapper.js83
-rw-r--r--Echo/modules/ui/mw.echo.ui.PageFilterWidget.js156
-rw-r--r--Echo/modules/ui/mw.echo.ui.PageNotificationsOptionWidget.js96
-rw-r--r--Echo/modules/ui/mw.echo.ui.PaginationWidget.js179
-rw-r--r--Echo/modules/ui/mw.echo.ui.PlaceholderItemWidget.js92
-rw-r--r--Echo/modules/ui/mw.echo.ui.ReadStateButtonSelectWidget.js64
-rw-r--r--Echo/modules/ui/mw.echo.ui.SingleNotificationItemWidget.js101
-rw-r--r--Echo/modules/ui/mw.echo.ui.SortedListWidget.js280
-rw-r--r--Echo/modules/ui/mw.echo.ui.SpecialHelpMenuWidget.js159
-rw-r--r--Echo/modules/ui/mw.echo.ui.SubGroupListWidget.js281
-rw-r--r--Echo/modules/ui/mw.echo.ui.ToggleReadCircleButtonWidget.js53
-rw-r--r--Echo/modules/ui/mw.echo.ui.js7
-rw-r--r--Echo/modules/viewmodel/mw.echo.dm.List.js272
-rw-r--r--Echo/modules/viewmodel/mw.echo.dm.NotificationItem.js176
-rw-r--r--Echo/modules/viewmodel/mw.echo.dm.NotificationList.js26
-rw-r--r--Echo/modules/viewmodel/mw.echo.dm.NotificationsModel.js428
-rw-r--r--Echo/modules/viewmodel/mw.echo.dm.js4
-rw-r--r--Echo/package.json37
-rw-r--r--Echo/phpcs.xml22
-rw-r--r--Echo/scripts/gen-autoload.php56
-rw-r--r--Echo/scripts/generatecss.php15
-rwxr-xr-xEcho/scripts/qunit.sh14
-rw-r--r--Echo/tests/NotificationsTest.php16
-rw-r--r--Echo/tests/bootstrap.php3
-rw-r--r--Echo/tests/browser/README.md1
-rw-r--r--Echo/tests/browser/ci.yml9
-rw-r--r--Echo/tests/browser/environments.yml48
-rw-r--r--Echo/tests/browser/features/flyout.feature17
-rw-r--r--Echo/tests/browser/features/flyout_nojs.feature12
-rw-r--r--Echo/tests/browser/features/messages.feature15
-rw-r--r--Echo/tests/browser/features/no_javascript.feature11
-rw-r--r--Echo/tests/browser/features/notifications.feature56
-rw-r--r--Echo/tests/browser/features/notifications_userrights.feature10
-rw-r--r--Echo/tests/browser/features/step_definition/badge_steps.rb10
-rw-r--r--Echo/tests/browser/features/step_definition/no_javascript.rb21
-rw-r--r--Echo/tests/browser/features/step_definition/notifications_steps.rb76
-rw-r--r--Echo/tests/browser/features/step_definition/popup_steps.rb11
-rw-r--r--Echo/tests/browser/features/step_definitions/common_steps.rb61
-rw-r--r--Echo/tests/browser/features/step_definitions/flyout_steps.rb18
-rw-r--r--Echo/tests/browser/features/step_definitions/messages_steps.rb17
-rw-r--r--Echo/tests/browser/features/step_definitions/notifications_steps.rb91
-rw-r--r--Echo/tests/browser/features/support/components/notifications.rb21
-rw-r--r--Echo/tests/browser/features/support/data_manager.rb11
-rw-r--r--Echo/tests/browser/features/support/echo_api_helper.rb25
-rw-r--r--Echo/tests/browser/features/support/echo_pageobject_extension.rb9
-rw-r--r--Echo/tests/browser/features/support/env.rb16
-rw-r--r--Echo/tests/browser/features/support/hooks.rb7
-rw-r--r--Echo/tests/browser/features/support/pages/article_page.rb16
-rw-r--r--Echo/tests/browser/features/support/pages/special_notifications_page.rb8
-rw-r--r--Echo/tests/externals/phantomjs-qunit-runner.js127
-rw-r--r--Echo/tests/phpunit/AttributeManagerTest.php525
-rw-r--r--Echo/tests/phpunit/BatchRowUpdateTest.php244
-rw-r--r--Echo/tests/phpunit/BundlerTest.php44
-rw-r--r--Echo/tests/phpunit/ContainmentSetTest.php15
-rw-r--r--Echo/tests/phpunit/DiffParserTest.php116
-rw-r--r--Echo/tests/phpunit/DiscussionParserTest.php1415
-rw-r--r--Echo/tests/phpunit/EchoDbFactoryTest.php1
-rw-r--r--Echo/tests/phpunit/EmailFormatterTest.php92
-rw-r--r--Echo/tests/phpunit/NotifUserTest.php108
-rw-r--r--Echo/tests/phpunit/TalkPageFunctionalTest.php19
-rw-r--r--Echo/tests/phpunit/ThankYouEditTest.php68
-rw-r--r--Echo/tests/phpunit/UserLocatorTest.php142
-rw-r--r--Echo/tests/phpunit/api/ApiEchoMarkReadTest.php16
-rw-r--r--Echo/tests/phpunit/api/ApiEchoNotificationsTest.php11
-rw-r--r--Echo/tests/phpunit/cache/TitleLocalCacheTest.php33
-rw-r--r--Echo/tests/phpunit/controller/NotificationControllerTest.php201
-rw-r--r--Echo/tests/phpunit/formatters/NotificationFormatterTest.php321
-rw-r--r--Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php67
-rw-r--r--Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php80
-rw-r--r--Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php108
-rw-r--r--Echo/tests/phpunit/mapper/AbstractMapperTest.php10
-rw-r--r--Echo/tests/phpunit/mapper/EventMapperTest.php87
-rw-r--r--Echo/tests/phpunit/mapper/NotificationMapperTest.php102
-rw-r--r--Echo/tests/phpunit/mapper/TargetPageMapperTest.php111
-rw-r--r--Echo/tests/phpunit/model/NotificationTest.php20
-rw-r--r--Echo/tests/phpunit/model/TargetPageTest.php37
-rw-r--r--Echo/tests/phpunit/revision_txt/747747747.txt3
-rw-r--r--Echo/tests/phpunit/revision_txt/747747748.txt11
-rw-r--r--Echo/tests/phpunit/revision_txt/747747749.txt11
-rw-r--r--Echo/tests/phpunit/revision_txt/747747750.txt11
-rw-r--r--Echo/tests/phpunit/revision_txt/747798765.txt9
-rw-r--r--Echo/tests/phpunit/revision_txt/747798766.txt19
-rw-r--r--Echo/tests/phpunit/revision_txt/747798767.txt25
-rw-r--r--Echo/tests/phpunit/revision_txt/747798768.txt17
-rw-r--r--Echo/tests/phpunit/revision_txt/747798770.txt25
-rw-r--r--Echo/tests/phpunit/revision_txt/747798771.txt27
-rw-r--r--Echo/tests/phpunit/revision_txt/747798772.txt35
-rw-r--r--Echo/tests/phpunit/revision_txt/987654321.txt2
-rw-r--r--Echo/tests/phpunit/revision_txt/987654322.txt2
-rw-r--r--Echo/tests/phpunit/revision_txt/987654323.txt4
-rw-r--r--Echo/tests/phpunit/revision_txt/987654324.txt2
-rw-r--r--Echo/tests/phpunit/revision_txt/987654325.txt4
-rw-r--r--Echo/tests/phpunit/revision_txt/987654400.txt (renamed from Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-01/empty-file)0
-rw-r--r--Echo/tests/phpunit/revision_txt/987654401.txt3
-rw-r--r--Echo/tests/phpunit/revision_txt/987667998.txt15
-rw-r--r--Echo/tests/phpunit/revision_txt/987667999.txt15
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js117
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js311
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js110
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js156
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js146
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js189
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js91
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js56
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js172
-rw-r--r--Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js85
-rw-r--r--Echo/tests/qunit/overlay/test_ext.echo.overlay.js8
-rw-r--r--Echo/tests/qunit/viewmodel/test_mw.echo.dm.NotificationsModel.js164
-rw-r--r--Echo/tests/rspec/README.md7
-rw-r--r--Echo/tests/rspec/notification_spec.rb55
-rw-r--r--Echo/vendor/autoload.php7
l---------Echo/vendor/bin/parallel-lint1
-rw-r--r--Echo/vendor/composer/ClassLoader.php413
-rw-r--r--Echo/vendor/composer/autoload_classmap.php41
-rw-r--r--Echo/vendor/composer/autoload_namespaces.php9
-rw-r--r--Echo/vendor/composer/autoload_psr4.php9
-rw-r--r--Echo/vendor/composer/autoload_real.php50
-rw-r--r--Echo/vendor/composer/installed.json51
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/.gitignore2
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/.travis.yml23
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/LICENSE26
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/README.md70
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/bin/skip-linting.php22
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/composer.json28
-rwxr-xr-xEcho/vendor/jakub-onderka/php-parallel-lint/parallel-lint4
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/parallel-lint.php112
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/phpcs-ruleset.xml71
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Error.php244
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/ErrorFormatter.php152
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/JsonSerializable.php7
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Manager.php272
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Output.php449
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/ParallelLint.php261
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/GitBlameProcess.php143
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/LintProcess.php67
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/PhpExecutable.php128
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/PhpProcess.php26
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/Process.php149
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/SkipLintProcess.php77
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Result.php197
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/Settings.php217
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/src/exceptions.php80
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/Manager.run.phpt122
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/ParallelLint.lint.phpt116
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/Settings.parseArguments.phpt72
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/SkipLintProcess.phpt40
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-02/example.php4
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-03/example.php4
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/dir1/dir2/index.php3
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/dir1/index.php2
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/index.php2
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-images/use-error.pngbin58486 -> 0 bytes
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-images/use-success.pngbin13394 -> 0 bytes
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/class.php6
-rw-r--r--Echo/vendor/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/trait.php6
-rw-r--r--Echo/version6
701 files changed, 37764 insertions, 20716 deletions
diff --git a/Echo/.csslintrc b/Echo/.csslintrc
deleted file mode 100644
index ec188a93..00000000
--- a/Echo/.csslintrc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "adjoining-classes": false,
- "box-model": false,
- "box-sizing": false,
- "fallback-colors": false,
- "ids": false,
- "important": false,
- "outline-none": false,
- "overqualified-elements": false,
- "qualified-headings": false,
- "universal-selector": false,
- "unqualified-attributes": false
-}
diff --git a/Echo/.eslintrc.json b/Echo/.eslintrc.json
new file mode 100644
index 00000000..488ab054
--- /dev/null
+++ b/Echo/.eslintrc.json
@@ -0,0 +1,15 @@
+{
+ "extends": "wikimedia",
+ "env": {
+ "browser": true,
+ "jquery": true,
+ "qunit": true
+ },
+ "globals": {
+ "OO": false,
+ "mediaWiki": false
+ },
+ "rules": {
+ "dot-notation": [ "error", { "allowKeywords": true } ]
+ }
+}
diff --git a/Echo/.gitignore b/Echo/.gitignore
index c71739dd..cb2aeb6c 100644
--- a/Echo/.gitignore
+++ b/Echo/.gitignore
@@ -1,7 +1,27 @@
-.svn
-*~
-*.kate-swp
-.*.swp
+.idea/
node_modules/
scripts/remotes/
tests/browser/screenshots
+/vendor
+/docs
+composer.lock
+
+# Editors
+*.kate-swp
+*~
+\#*#
+.#*
+.*.swp
+.project
+.buildpath
+.classpath
+.settings
+cscope.files
+cscope.out
+*.orig
+## NetBeans
+nbproject*
+project.index
+## Sublime
+sublime-*
+sftp-config.json
diff --git a/Echo/.gitreview b/Echo/.gitreview
index 026581be..e6a293fc 100644
--- a/Echo/.gitreview
+++ b/Echo/.gitreview
@@ -2,5 +2,5 @@
host=gerrit.wikimedia.org
port=29418
project=mediawiki/extensions/Echo.git
-defaultbranch=REL1_26
+track=1
defaultrebase=0
diff --git a/Echo/.jscsrc b/Echo/.jscsrc
deleted file mode 100644
index dc37ba8e..00000000
--- a/Echo/.jscsrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "preset": "wikimedia",
- "disallowDanglingUnderscores": null
-}
diff --git a/Echo/.jshintignore b/Echo/.jshintignore
deleted file mode 100644
index f1f4c6ac..00000000
--- a/Echo/.jshintignore
+++ /dev/null
@@ -1,2 +0,0 @@
-tests/externals/
-modules/hooks.txt
diff --git a/Echo/.jshintrc b/Echo/.jshintrc
deleted file mode 100644
index 6db2268d..00000000
--- a/Echo/.jshintrc
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- /* Common */
-
- // Enforcing
- "camelcase": true,
- "curly": true,
- "eqeqeq": true,
- "immed": true,
- "latedef": true,
- "newcap": true,
- "noarg": true,
- "noempty": true,
- "nonew": true,
- "quotmark": "single",
- "trailing": true,
- "undef": true,
- "unused": true,
- // Legacy
- "onevar": true,
-
- /* Local */
-
- // Environment
- "browser": true,
-
- "predef": [
- "jQuery",
- "QUnit",
- "OO",
- "mediaWiki"
- ]
-}
diff --git a/Echo/.mailmap b/Echo/.mailmap
new file mode 100644
index 00000000..b970c896
--- /dev/null
+++ b/Echo/.mailmap
@@ -0,0 +1,16 @@
+Benny Situ <bsitu@wikimedia.org>
+Erik Bernhardson <ebernhardson@wikimedia.org>
+Jon Robson <jrobson@wikimedia.org>
+Jon Robson <jrobson@wikimedia.org> <jdlrobson@gmail.com>
+Luke Welling <lwelling@wikimedia.org>
+Kunal Mehta <legoktm@gmail.com>
+Kunal Mehta <legoktm@gmail.com> <legoktm@member.fsf.org>
+Kunal Mehta <legoktm@gmail.com> <legoktm.wikpedia@gmail.com>
+Max Semenik <maxsem.wiki@gmail.com>
+Niklas Laxström <niklas.laxstrom@gmail.com>
+Roan Kattouw <roan.kattouw@gmail.com>
+Roan Kattouw <roan.kattouw@gmail.com> <catrope@users.mediawiki.org>
+Roan Kattouw <roan.kattouw@gmail.com> <roan@wikimedia.org>
+Ryan Kaldari <rkaldari@wikimedia.org>
+Ryan Kaldari <rkaldari@wikimedia.org> <kaldari@gmail.com>
+Terry Chay <tchay@wikimedia.org>
diff --git a/Echo/.rubocop.yml b/Echo/.rubocop.yml
index 7ce21af2..84567a59 100644
--- a/Echo/.rubocop.yml
+++ b/Echo/.rubocop.yml
@@ -1,25 +1,20 @@
-inherit_from: .rubocop_todo.yml
+AllCops:
+ StyleGuideCopsOnly: true
-Metrics/AbcSize:
- Enabled: false
-
-Metrics/ClassLength:
- Enabled: false
-
-Metrics/CyclomaticComplexity:
- Enabled: false
+Metrics/LineLength:
+ Max: 100
Metrics/MethodLength:
Enabled: false
-Metrics/ParameterLists:
- Enabled: false
-
-Metrics/PerceivedComplexity:
- Enabled: false
-
Style/Alias:
Enabled: false
Style/SignalException:
Enabled: false
+
+Style/StringLiterals:
+ EnforcedStyle: single_quotes
+
+Style/TrivialAccessors:
+ ExactNameMatch: true
diff --git a/Echo/.rubocop_todo.yml b/Echo/.rubocop_todo.yml
deleted file mode 100644
index 0649914a..00000000
--- a/Echo/.rubocop_todo.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-# This configuration was generated by `rubocop --auto-gen-config`
-# on 2015-02-23 09:43:04 -0700 using RuboCop version 0.29.0.
-# The point is for the user to remove these configuration records
-# one by one as the offenses are removed from the code base.
-# Note that changes in the inspected code, or installation of new
-# versions of RuboCop, may require this file to be generated again.
-
-# Offense count: 2
-# Configuration parameters: AllowURI, URISchemes.
-Metrics/LineLength:
- Max: 113
-
-# Offense count: 1
-# Configuration parameters: AllowedVariables.
-Style/GlobalVars:
- Enabled: false
diff --git a/Echo/.stylelintrc.json b/Echo/.stylelintrc.json
new file mode 100644
index 00000000..c0d30c62
--- /dev/null
+++ b/Echo/.stylelintrc.json
@@ -0,0 +1,7 @@
+{
+ "extends": "stylelint-config-wikimedia",
+ "rules": {
+ "declaration-no-important": null,
+ "selector-no-id": null
+ }
+}
diff --git a/Echo/CODE_OF_CONDUCT.md b/Echo/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..d8e5d087
--- /dev/null
+++ b/Echo/CODE_OF_CONDUCT.md
@@ -0,0 +1 @@
+The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Code_of_Conduct).
diff --git a/Echo/Echo.alias.php b/Echo/Echo.alias.php
index d02d2301..606688d0 100644
--- a/Echo/Echo.alias.php
+++ b/Echo/Echo.alias.php
@@ -5,251 +5,264 @@
* @file
* @ingroup Extensions
*/
-// @codingStandardsIgnoreFile
-$specialPageAliases = array();
+$specialPageAliases = [];
/** English (English) */
-$specialPageAliases['en'] = array(
- 'Notifications' => array( 'Notifications' ),
-);
+$specialPageAliases['en'] = [
+ 'Notifications' => [ 'Notifications' ],
+ 'DisplayNotificationsConfiguration' => [ 'DisplayNotificationsConfiguration' ],
+ 'NotificationsMarkRead' => [ 'NotificationsMarkRead' ],
+];
/** Arabic (العربية) */
-$specialPageAliases['ar'] = array(
- 'Notifications' => array( 'إشعارات' ),
-);
+$specialPageAliases['ar'] = [
+ 'Notifications' => [ 'إشعارات' ],
+];
/** Egyptian Arabic (مصرى) */
-$specialPageAliases['arz'] = array(
- 'Notifications' => array( 'اخطارات' ),
-);
+$specialPageAliases['arz'] = [
+ 'Notifications' => [ 'اخطارات' ],
+];
/** Avaric (авар) */
-$specialPageAliases['av'] = array(
- 'Notifications' => array( 'Уведомления' ),
-);
+$specialPageAliases['av'] = [
+ 'Notifications' => [ 'Уведомления' ],
+];
/** Western Balochi (بلوچی رخشانی) */
-$specialPageAliases['bgn'] = array(
- 'Notifications' => array( 'آگاه_کورتینۆک_ئان' ),
-);
+$specialPageAliases['bgn'] = [
+ 'Notifications' => [ 'آگاه_کورتینۆک_ئان' ],
+];
+
+/** Bengali (বাংলা) */
+$specialPageAliases['bn'] = [
+ 'Notifications' => [ 'বিজ্ঞপ্তি' ],
+ 'DisplayNotificationsConfiguration' => [ 'বিজ্ঞপ্তি_কনফিগারেশন_প্রদর্শন' ],
+ 'NotificationsMarkRead' => [ 'বিজ্ঞপ্তি_পঠিতরূপে_চিহ্নিত', 'বিজ্ঞপ্তি_পঠিত_হিসেবে_চিহ্নিত' ],
+];
/** Min Dong Chinese (Mìng-dĕ̤ng-ngṳ̄) */
-$specialPageAliases['cdo'] = array(
- 'Notifications' => array( '提醒' ),
-);
+$specialPageAliases['cdo'] = [
+ 'Notifications' => [ '提醒' ],
+];
/** Chechen (нохчийн) */
-$specialPageAliases['ce'] = array(
- 'Notifications' => array( 'ДӀахаийтар' ),
-);
+$specialPageAliases['ce'] = [
+ 'Notifications' => [ 'ДӀахаийтар' ],
+];
+
+/** Czech (čeština) */
+$specialPageAliases['cs'] = [
+ 'Notifications' => [ 'Upozornění' ],
+];
/** German (Deutsch) */
-$specialPageAliases['de'] = array(
- 'Notifications' => array( 'Benachrichtigungen' ),
-);
+$specialPageAliases['de'] = [
+ 'Notifications' => [ 'Benachrichtigungen' ],
+];
/** Zazaki (Zazaki) */
-$specialPageAliases['diq'] = array(
- 'Notifications' => array( 'Mengeneyi' ),
-);
+$specialPageAliases['diq'] = [
+ 'Notifications' => [ 'Mengeneyi' ],
+];
/** Greek (Ελληνικά) */
-$specialPageAliases['el'] = array(
- 'Notifications' => array( 'Ειδοποιήσεις' ),
-);
+$specialPageAliases['el'] = [
+ 'Notifications' => [ 'Ειδοποιήσεις' ],
+];
/** Esperanto (Esperanto) */
-$specialPageAliases['eo'] = array(
- 'Notifications' => array( 'Atentigoj' ),
-);
+$specialPageAliases['eo'] = [
+ 'Notifications' => [ 'Atentigoj' ],
+];
/** Spanish (español) */
-$specialPageAliases['es'] = array(
- 'Notifications' => array( 'Notificaciones' ),
-);
+$specialPageAliases['es'] = [
+ 'Notifications' => [ 'Notificaciones' ],
+];
/** Estonian (eesti) */
-$specialPageAliases['et'] = array(
- 'Notifications' => array( 'Teavitused' ),
-);
+$specialPageAliases['et'] = [
+ 'Notifications' => [ 'Teavitused' ],
+];
/** Persian (فارسی) */
-$specialPageAliases['fa'] = array(
- 'Notifications' => array( 'آگاه‌سازی‌ها' ),
-);
+$specialPageAliases['fa'] = [
+ 'Notifications' => [ 'آگاه‌سازی‌ها' ],
+];
/** Finnish (suomi) */
-$specialPageAliases['fi'] = array(
- 'Notifications' => array( 'Ilmoitukset' ),
-);
+$specialPageAliases['fi'] = [
+ 'Notifications' => [ 'Ilmoitukset' ],
+];
/** Galician (galego) */
-$specialPageAliases['gl'] = array(
- 'Notifications' => array( 'Notificacións' ),
-);
+$specialPageAliases['gl'] = [
+ 'Notifications' => [ 'Notificacións' ],
+];
/** Hawaiian (Hawai`i) */
-$specialPageAliases['haw'] = array(
- 'Notifications' => array( 'Notikala' ),
-);
+$specialPageAliases['haw'] = [
+ 'Notifications' => [ 'Notikala' ],
+];
/** Hebrew (עברית) */
-$specialPageAliases['he'] = array(
- 'Notifications' => array( 'הודעות', 'כל_ההודעות' ),
-);
+$specialPageAliases['he'] = [
+ 'Notifications' => [ 'הודעות', 'כל_ההודעות' ],
+];
/** Upper Sorbian (hornjoserbsce) */
-$specialPageAliases['hsb'] = array(
- 'Notifications' => array( 'Zdźělenja' ),
-);
+$specialPageAliases['hsb'] = [
+ 'Notifications' => [ 'Zdźělenja' ],
+];
/** Indonesian (Bahasa Indonesia) */
-$specialPageAliases['id'] = array(
- 'Notifications' => array( 'Notifikasi' ),
-);
+$specialPageAliases['id'] = [
+ 'Notifications' => [ 'Notifikasi' ],
+];
/** Italian (italiano) */
-$specialPageAliases['it'] = array(
- 'Notifications' => array( 'Notifiche' ),
-);
+$specialPageAliases['it'] = [
+ 'Notifications' => [ 'Notifiche' ],
+];
/** Japanese (日本語) */
-$specialPageAliases['ja'] = array(
- 'Notifications' => array( '通知' ),
-);
+$specialPageAliases['ja'] = [
+ 'Notifications' => [ '通知' ],
+];
/** Korean (한국어) */
-$specialPageAliases['ko'] = array(
- 'Notifications' => array( '알림' ),
-);
+$specialPageAliases['ko'] = [
+ 'Notifications' => [ '알림' ],
+];
/** Cornish (kernowek) */
-$specialPageAliases['kw'] = array(
- 'Notifications' => array( 'Argemynow' ),
-);
+$specialPageAliases['kw'] = [
+ 'Notifications' => [ 'Argemynow' ],
+];
/** Luxembourgish (Lëtzebuergesch) */
-$specialPageAliases['lb'] = array(
- 'Notifications' => array( 'Notifikatiounen' ),
-);
+$specialPageAliases['lb'] = [
+ 'Notifications' => [ 'Notifikatiounen' ],
+];
/** Northern Luri (لۊری شومالی) */
-$specialPageAliases['lrc'] = array(
- 'Notifications' => array( 'ڤارسیاریا' ),
-);
+$specialPageAliases['lrc'] = [
+ 'Notifications' => [ 'ڤارسیاریا' ],
+];
/** Macedonian (македонски) */
-$specialPageAliases['mk'] = array(
- 'Notifications' => array( 'Известувања' ),
-);
+$specialPageAliases['mk'] = [
+ 'Notifications' => [ 'Известувања' ],
+];
/** Malayalam (മലയാളം) */
-$specialPageAliases['ml'] = array(
- 'Notifications' => array( 'അറിയിപ്പുകൾ' ),
-);
+$specialPageAliases['ml'] = [
+ 'Notifications' => [ 'അറിയിപ്പുകൾ' ],
+];
/** Marathi (मराठी) */
-$specialPageAliases['mr'] = array(
- 'Notifications' => array( 'संदेश' ),
-);
+$specialPageAliases['mr'] = [
+ 'Notifications' => [ 'संदेश' ],
+];
/** Malay (Bahasa Melayu) */
-$specialPageAliases['ms'] = array(
- 'Notifications' => array( 'Pemberitahuan' ),
-);
+$specialPageAliases['ms'] = [
+ 'Notifications' => [ 'Pemberitahuan' ],
+];
/** Maltese (Malti) */
-$specialPageAliases['mt'] = array(
- 'Notifications' => array( 'Notifiki' ),
-);
+$specialPageAliases['mt'] = [
+ 'Notifications' => [ 'Notifiki' ],
+];
/** Norwegian Bokmål (norsk bokmål) */
-$specialPageAliases['nb'] = array(
- 'Notifications' => array( 'Varsler' ),
-);
+$specialPageAliases['nb'] = [
+ 'Notifications' => [ 'Varsler' ],
+];
/** Dutch (Nederlands) */
-$specialPageAliases['nl'] = array(
- 'Notifications' => array( 'Meldingen' ),
-);
+$specialPageAliases['nl'] = [
+ 'Notifications' => [ 'Meldingen' ],
+];
/** Punjabi (ਪੰਜਾਬੀ) */
-$specialPageAliases['pa'] = array(
- 'Notifications' => array( 'ਇਤਲਾਹਾਂ' ),
-);
+$specialPageAliases['pa'] = [
+ 'Notifications' => [ 'ਇਤਲਾਹਾਂ' ],
+];
/** Polish (polski) */
-$specialPageAliases['pl'] = array(
- 'Notifications' => array( 'Powiadomienia' ),
-);
+$specialPageAliases['pl'] = [
+ 'Notifications' => [ 'Powiadomienia' ],
+];
/** Portuguese (português) */
-$specialPageAliases['pt'] = array(
- 'Notifications' => array( 'Notificações' ),
-);
+$specialPageAliases['pt'] = [
+ 'Notifications' => [ 'Notificações' ],
+];
/** Brazilian Portuguese (português do Brasil) */
-$specialPageAliases['pt-br'] = array(
- 'Notifications' => array( 'Notificações' ),
-);
+$specialPageAliases['pt-br'] = [
+ 'Notifications' => [ 'Notificações' ],
+];
/** Quechua (Runa Simi) */
-$specialPageAliases['qu'] = array(
- 'Notifications' => array( 'Willaykuykuna' ),
-);
+$specialPageAliases['qu'] = [
+ 'Notifications' => [ 'Willaykuykuna' ],
+];
/** Russian (русский) */
-$specialPageAliases['ru'] = array(
- 'Notifications' => array( 'Уведомления' ),
-);
+$specialPageAliases['ru'] = [
+ 'Notifications' => [ 'Уведомления' ],
+];
/** Sicilian (sicilianu) */
-$specialPageAliases['scn'] = array(
- 'Notifications' => array( 'Notifiche' ),
-);
+$specialPageAliases['scn'] = [
+ 'Notifications' => [ 'Notifiche' ],
+];
/** Serbian (Cyrillic script) (српски (ћирилица)‎) */
-$specialPageAliases['sr-ec'] = array(
- 'Notifications' => array( 'Обавештења' ),
-);
+$specialPageAliases['sr-ec'] = [
+ 'Notifications' => [ 'Обавештења' ],
+];
/** Swedish (svenska) */
-$specialPageAliases['sv'] = array(
- 'Notifications' => array( 'Meddelanden' ),
-);
+$specialPageAliases['sv'] = [
+ 'Notifications' => [ 'Meddelanden' ],
+];
/** Ukrainian (українська) */
-$specialPageAliases['uk'] = array(
- 'Notifications' => array( 'Сповіщення' ),
-);
+$specialPageAliases['uk'] = [
+ 'Notifications' => [ 'Сповіщення', 'Уведомления' ],
+];
/** Urdu (اردو) */
-$specialPageAliases['ur'] = array(
- 'Notifications' => array( 'اطلاعات' ),
-);
+$specialPageAliases['ur'] = [
+ 'Notifications' => [ 'اطلاعات' ],
+];
/** Venetian (vèneto) */
-$specialPageAliases['vec'] = array(
- 'Notifications' => array( 'Notifiche' ),
-);
+$specialPageAliases['vec'] = [
+ 'Notifications' => [ 'Notifiche' ],
+];
/** Vietnamese (Tiếng Việt) */
-$specialPageAliases['vi'] = array(
- 'Notifications' => array( 'Thông_báo' ),
-);
+$specialPageAliases['vi'] = [
+ 'Notifications' => [ 'Thông_báo' ],
+];
/** Chinese (中文) */
-$specialPageAliases['zh'] = array(
- 'Notifications' => array( '通知' ),
-);
+$specialPageAliases['zh'] = [
+ 'Notifications' => [ '通知' ],
+];
/** Simplified Chinese (中文(简体)‎) */
-$specialPageAliases['zh-hans'] = array(
- 'Notifications' => array( '通知' ),
-);
+$specialPageAliases['zh-hans'] = [
+ 'Notifications' => [ '通知' ],
+];
/** Traditional Chinese (中文(繁體)‎) */
-$specialPageAliases['zh-hant'] = array(
- 'Notifications' => array( '通知' ),
-); \ No newline at end of file
+$specialPageAliases['zh-hant'] = [
+ 'Notifications' => [ '通知' ],
+];
diff --git a/Echo/Echo.php b/Echo/Echo.php
index 32b41e8d..ecb65bcc 100644
--- a/Echo/Echo.php
+++ b/Echo/Echo.php
@@ -24,432 +24,20 @@
* @licence MIT License
*/
-# Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly.
-if ( !defined( 'MEDIAWIKI' ) ) {
- echo <<<EOT
-To install this extension, put the following line in LocalSettings.php:
-require_once( "$IP/extensions/Echo/Echo.php" );
-EOT;
- exit( 1 );
-}
-
-// Extension credits that will show up on Special:Version
-$wgExtensionCredits['specialpage'][] = array(
- 'path' => __FILE__,
- 'name' => 'Echo',
- 'url' => 'https://www.mediawiki.org/wiki/Extension:Echo',
- 'author' => array( 'Andrew Garrett', 'Ryan Kaldari', 'Benny Situ', 'Luke Welling' ),
- 'descriptionmsg' => 'echo-desc',
- 'license-name' => 'MIT',
-);
-
-$wgMessagesDirs['Echo'] = __DIR__ . '/i18n';
-$wgExtensionMessagesFiles['EchoAliases'] = __DIR__ . '/Echo.alias.php';
-
-// This file is autogenerated by scripts/gen-autoload.php
-require __DIR__ . "/autoload.php";
-
-// Queable jobs
-$wgJobClasses['EchoNotificationJob'] = 'EchoNotificationJob';
-$wgJobClasses['MWEchoNotificationEmailBundleJob'] = 'MWEchoNotificationEmailBundleJob';
-// Job to delete older notifications
-$wgJobClasses['EchoNotificationDeleteJob'] = 'EchoNotificationDeleteJob';
-
-// API
-$wgAPIMetaModules['notifications'] = 'ApiEchoNotifications';
-$wgAPIModules['echomarkread'] = 'ApiEchoMarkRead';
-$wgAPIModules['echomarkseen'] = 'ApiEchoMarkSeen';
-
-// Special page
-$wgSpecialPages['Notifications'] = 'SpecialNotifications';
-
-// Housekeeping hooks
-$wgHooks['LoadExtensionSchemaUpdates'][] = 'EchoHooks::onLoadExtensionSchemaUpdates';
-$wgHooks['GetPreferences'][] = 'EchoHooks::getPreferences';
-$wgHooks['PersonalUrls'][] = 'EchoHooks::onPersonalUrls';
-$wgHooks['BeforePageDisplay'][] = 'EchoHooks::beforePageDisplay';
-$wgHooks['MakeGlobalVariablesScript'][] = 'EchoHooks::makeGlobalVariablesScript';
-$wgHooks['UnitTestsList'][] = 'EchoHooks::getUnitTests';
-$wgHooks['ResourceLoaderRegisterModules'][] = 'EchoHooks::onResourceLoaderRegisterModules';
-$wgHooks['EventLoggingRegisterSchemas'][] = 'EchoHooks::onEventLoggingRegisterSchemas';
-$wgHooks['ResourceLoaderTestModules'][] = 'EchoHooks::onResourceLoaderTestModules';
-$wgHooks['UserGroupsChanged'][] = 'EchoHooks::onUserGroupsChanged';
-$wgHooks['UserLoadOptions'][] = 'EchoHooks::onUserLoadOptions';
-$wgHooks['UserSaveOptions'][] = 'EchoHooks::onUserSaveOptions';
-$wgHooks['UserClearNewTalkNotification'][] = 'EchoHooks::onUserClearNewTalkNotification';
-$wgHooks['ParserTestTables'][] = 'EchoHooks::onParserTestTables';
-
-// Extension:UserMerge support
-$wgHooks['UserMergeAccountFields'][] = 'EchoHooks::onUserMergeAccountFields';
-$wgHooks['MergeAccountFromTo'][] = 'EchoHooks::onMergeAccountFromTo';
-$wgHooks['UserMergeAccountDeleteTables'][] = 'EchoHooks::onUserMergeAccountDeleteTables';
-
-// Extension initialization
-$wgExtensionFunctions[] = 'EchoHooks::initEchoExtension';
-
-require __DIR__ . '/Resources.php';
-
-$wgHooks['EchoGetBundleRules'][] = 'EchoHooks::onEchoGetBundleRules';
-$wgHooks['EchoAbortEmailNotification'][] = 'EchoHooks::onEchoAbortEmailNotification';
-
-// Hook appropriate events
-$wgHooks['ArticleSaveComplete'][] = 'EchoHooks::onArticleSaved';
-$wgHooks['AddNewAccount'][] = 'EchoHooks::onAccountCreated';
-$wgHooks['ArticleRollbackComplete'][] = 'EchoHooks::onRollbackComplete';
-$wgHooks['UserSaveSettings'][] = 'EchoHooks::onUserSaveSettings';
-
-// Disable ordinary user talk page email notifications
-$wgHooks['AbortTalkPageEmailNotification'][] = 'EchoHooks::onAbortTalkPageEmailNotification';
-$wgHooks['SendWatchlistEmailNotification'][] = 'EchoHooks::onSendWatchlistEmailNotification';
-// Disable the orange bar of death
-$wgHooks['GetNewMessagesAlert'][] = 'EchoHooks::abortNewMessagesAlert';
-$wgHooks['LinksUpdateAfterInsert'][] = 'EchoHooks::onLinksUpdateAfterInsert';
-
-// Configuration
-
-// Whether to turn on email batch function
-$wgEchoEnableEmailBatch = true;
-
-// URL for more information about the Echo notification system
-$wgEchoHelpPage = '//www.mediawiki.org/wiki/Special:MyLanguage/Help:Notifications';
-
-// Whether to use job queue to process web and email notifications, bypass the queue for now
-// since it's taking more than an hour to run in mediawiki.org, this is not acceptable for the
-// purpose of testing notification.
-$wgEchoUseJobQueue = false;
-
-// The organization address, the value should be defined in LocalSettings.php
-$wgEchoEmailFooterAddress = '';
-
-// The email address for both "from" and "reply to" on email notifications.
-// Should be defined in LocalSettings.php
-$wgNotificationSender = $wgPasswordSender;
-// Name for "from" on email notifications. Should be defined in LocalSettings.php
-// if null, uses 'emailsender' message
-$wgNotificationSenderName = null;
-// Name for "reply to" on email notifications. Should be defined in LocalSettings.php
-$wgNotificationReplyName = 'No Reply';
-
-// Use the main db if this is set to false, to use a specific external db, just
-// use any key defined in $wgExternalServers
-$wgEchoCluster = false;
-
-// The max notification count showed in badge
-// The max number showed in bundled message, eg, <user> and 99+ others <action>
-$wgEchoMaxNotificationCount = 99;
-
-// The max number of notifications allowed for a user to do a live update,
-// this is also the number of max notifications allowed for a user to have
-// @FIXME - the name is not intuitive, probably change it when the deleteJob patch
-// is deployed to both deployment branches
-$wgEchoMaxUpdateCount = 2000;
-
-// The time interval between each bundle email in seconds
-// set a small number for test wikis, should set this to 0 to disable email bundling
-// if there is no delay queue support
-$wgEchoBundleEmailInterval = 0;
-
-// Whether or not to enable a new talk page message alert for logged in users
-$wgEchoNewMsgAlert = true;
-
-// Define which output formats are available for each notification category
-$wgEchoDefaultNotificationTypes = array(
- 'all' => array(
- 'web' => true,
- 'email' => true,
- ),
- // Only send web notification for welcome event
- 'welcome' => array(
- 'email' => false,
- ),
-);
-
-// Definitions of the different types of notification delivery that are possible.
-// Each definition consists of a class name and a function name.
-// See also: EchoNotificationController class.
-$wgEchoNotifiers = array(
- 'web' => array( 'EchoNotifier', 'notifyWithNotification' ), // web-based notification
- 'email' => array( 'EchoNotifier', 'notifyWithEmail' ),
-);
-
-// List of usernames that will not trigger notification creation. This is initially
-// for bots that perform automated edits that are not important enough to regularly
-// spam people with notifications. Set to empty array when not in use.
-$wgEchoAgentBlacklist = array();
-
-// Page location of community maintained blacklist within NS_MEDIAWIKI. Set to null to disable.
-$wgEchoOnWikiBlacklist = 'Echo-blacklist';
-
-// sprintf format of per-user notification agent whitelists. Set to null to disable.
-$wgEchoPerUserWhitelistFormat = '%s/Echo-whitelist';
-
-// Define the categories that notifications can belong to. Categories can be
-// assigned the following parameters: priority, nodismiss, tooltip, and usergroups.
-// All parameters are optional.
-// If a notifications type doesn't have a category parameter, it is
-// automatically assigned to the 'other' category which is lowest priority and
-// has no preferences or dismissibility.
-// The priority parameter controls the order in which notifications are
-// displayed in preferences and batch emails. Priority ranges from 1 to 10. If
-// the priority is not specified, it defaults to 10, which is the lowest.
-// The usergroups param specifies an array of usergroups eligible to recieve the
-// notifications in the category. If no usergroups parameter is specified, all
-// groups are eligible.
-// The nodismiss parameter disables the dismissability of notifications in the
-// category. It can either be set to an array of output formats (see
-// $wgEchoNotifiers) or an array containing 'all'.
-$wgEchoNotificationCategories = array(
- 'system' => array(
- 'priority' => 9,
- 'no-dismiss' => array( 'all' ),
- ),
- 'user-rights' => array( // bug 55337
- 'priority' => 9,
- 'tooltip' => 'echo-pref-tooltip-user-rights',
- ),
- 'other' => array(
- 'no-dismiss' => array( 'all' ),
- ),
- 'edit-user-talk' => array(
- 'priority' => 1,
- 'no-dismiss' => array( 'web' ),
- 'tooltip' => 'echo-pref-tooltip-edit-user-talk',
- ),
- 'reverted' => array(
- 'priority' => 9,
- 'tooltip' => 'echo-pref-tooltip-reverted',
- ),
- 'article-linked' => array(
- 'priority' => 5,
- 'tooltip' => 'echo-pref-tooltip-article-linked',
- ),
- 'mention' => array(
- 'priority' => 4,
- 'tooltip' => 'echo-pref-tooltip-mention',
- ),
-);
-
-$echoIconPath = "Echo/modules/icons";
-
-// Defines icons, which are 30x30 images. This is passed to BeforeCreateEchoEvent so
-// extensions can define their own icons with the same structure. It is recommended that
-// extensions prefix their icon key. An example is myextension-name. This will help
-// avoid namespace conflicts.
-//
-// You can use either a path or a url, but not both.
-// The value of 'path' is relative to $wgExtensionAssetsPath.
-//
-// The value of 'url' should be a URL.
-//
-// You should customize the site icon URL, which is:
-// $wgEchoNotificationIcons['site']['url']
-$wgEchoNotificationIcons = array(
- 'placeholder' => array(
- 'path' => "$echoIconPath/Generic.png",
- ),
- 'trash' => array(
- 'path' => "$echoIconPath/Deletion.png",
- ),
- 'chat' => array(
- 'path' => "$echoIconPath/Talk.png",
- ),
- 'linked' => array(
- 'path' => "$echoIconPath/CrossReferenced.png",
- ),
- 'featured' => array(
- 'path' => "$echoIconPath/Featured.png",
- ),
- 'reviewed' => array(
- 'path' => "$echoIconPath/Reviewed.png",
- ),
- 'tagged' => array(
- 'path' => "$echoIconPath/ReviewedWithTags.png",
- ),
- 'revert' => array(
- 'path' => "$echoIconPath/Revert.png",
- ),
- 'checkmark' => array(
- 'path' => "$echoIconPath/Reviewed.png",
- ),
- 'gratitude' => array(
- 'path' => "$echoIconPath/Gratitude.png",
- ),
- 'site' => array(
- 'url' => false
- ),
-);
-
-// Definitions of the notification event types built into Echo.
-// If formatter-class isn't specified, defaults to EchoBasicFormatter.
-$wgEchoNotifications = array(
- 'welcome' => array(
- 'user-locators' => array(
- 'EchoUserLocator::locateEventAgent'
- ),
- 'category' => 'system',
- 'group' => 'positive',
- 'section' => 'alert',
- 'title-message' => 'notification-new-user',
- 'title-params' => array( 'agent' ),
- 'icon' => 'site',
- ),
- 'edit-user-talk' => array(
- 'user-locators' => array(
- 'EchoUserLocator::locateTalkPageOwner',
- ),
- 'primary-link' => array( 'message' => 'notification-link-text-view-message', 'destination' => 'section' ),
- 'secondary-link' => array( 'message' => 'notification-link-text-view-changes', 'destination' => 'diff' ),
- 'category' => 'edit-user-talk',
- 'group' => 'interactive',
- 'section' => 'message',
- 'bundle' => array( 'web' => true, 'email' => false ),
- 'formatter-class' => 'EchoEditUserTalkFormatter',
- 'title-message' => 'notification-edit-talk-page2',
- 'title-params' => array( 'agent', 'user', 'subject-anchor' ),
- 'bundle-message' => 'notification-edit-talk-page-bundle',
- 'bundle-params' => array( 'agent', 'user', 'agent-other-display', 'agent-other-count' ),
- 'flyout-message' => 'notification-edit-talk-page-flyout2',
- 'flyout-params' => array( 'agent', 'user', 'subject-anchor' ),
- 'email-subject-message' => 'notification-edit-talk-page-email-subject2',
- 'email-subject-params' => array( 'agent' ),
- 'email-body-batch-message' => 'notification-edit-talk-page-email-batch-body2',
- 'email-body-batch-params' => array( 'agent' ),
- 'email-body-batch-bundle-message' => 'notification-edit-user-talk-email-batch-bundle-body',
- 'email-body-batch-bundle-params' => array( 'agent', 'agent-other-display', 'agent-other-count' ),
- 'icon' => 'chat',
- 'immediate' => true,
- ),
- 'reverted' => array(
- 'user-locators' => array(
- array( 'EchoUserLocator::locateFromEventExtra', array( 'reverted-user-id' ) ),
- ),
- 'primary-link' => array( 'message' => 'notification-link-text-view-edit', 'destination' => 'diff' ),
- 'category' => 'reverted',
- 'group' => 'negative',
- 'section' => 'alert',
- 'formatter-class' => 'EchoEditFormatter',
- 'title-message' => 'notification-reverted2',
- 'title-params' => array( 'agent', 'title', 'difflink', 'number', 'userpage-contributions' ),
- 'flyout-message' => 'notification-reverted-flyout2',
- 'flyout-params' => array( 'agent', 'title', 'difflink', 'number' ),
- 'email-subject-message' => 'notification-reverted-email-subject2',
- 'email-subject-params' => array( 'agent', 'title', 'number' ),
- 'email-body-batch-message' => 'notification-reverted-email-batch-body2',
- 'email-body-batch-params' => array( 'agent', 'title', 'number' ),
- 'icon' => 'revert',
- ),
- 'page-linked' => array(
- 'user-locators' => array(
- 'EchoUserLocator::locateArticleCreator',
- ),
- 'primary-link' => array( 'message' => 'notification-link-text-view-page', 'destination' => 'link-from-page' ),
- 'category' => 'article-linked',
- 'group' => 'neutral',
- 'section' => 'alert',
- 'bundle' => array( 'web' => true, 'email' => true ),
- 'formatter-class' => 'EchoPageLinkFormatter',
- 'title-message' => 'notification-page-linked',
- 'title-params' => array( 'agent', 'title', 'link-from-page' ),
- 'bundle-message' => 'notification-page-linked-bundle',
- 'bundle-params' => array( 'agent', 'title', 'link-from-page', 'link-from-page-other-display', 'link-from-page-other-count' ),
- 'flyout-message' => 'notification-page-linked-flyout',
- 'flyout-params' => array( 'agent', 'title', 'link-from-page' ),
- 'email-subject-message' => 'notification-page-linked-email-subject',
- 'email-subject-params' => array(),
- 'email-body-batch-message' => 'notification-page-linked-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'title', 'link-from-page' ),
- 'email-body-batch-bundle-message' => 'notification-page-linked-email-batch-bundle-body',
- 'email-body-batch-bundle-params' => array( 'agent', 'title', 'link-from-page', 'link-from-page-other-display', 'link-from-page-other-count' ),
- 'icon' => 'linked',
- ),
- 'mention' => array(
- 'user-locators' => array(
- array( 'EchoUserLocator::locateFromEventExtra', array( 'mentioned-users' ) ),
- ),
- 'primary-link' => array( 'message' => 'notification-link-text-view-mention', 'destination' => 'section' ),
- 'secondary-link' => array( 'message' => 'notification-link-text-view-changes', 'destination' => 'diff' ),
- 'category' => 'mention',
- 'group' => 'interactive',
- 'section' => 'alert',
- 'formatter-class' => 'EchoMentionFormatter',
- 'title-message' => 'notification-mention',
- 'title-params' => array( 'agent', 'subject-anchor', 'title', 'section-title', 'main-title-text' ),
- 'flyout-message' => 'notification-mention-flyout',
- 'flyout-params' => array( 'agent', 'subject-anchor', 'title', 'section-title', 'main-title-text' ),
- 'email-subject-message' => 'notification-mention-email-subject',
- 'email-subject-params' => array( 'agent' ),
- 'email-body-batch-message' => 'notification-mention-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'title', 'section-title', 'main-title-text' ),
- 'icon' => 'chat',
- ),
- 'user-rights' => array(
- 'user-locators' => array(
- array( 'EchoUserLocator::locateFromEventExtra', array( 'user' ) ),
- ),
- 'primary-link' => array( 'message' => 'echo-learn-more', 'destination' => 'user-rights-list' ),
- 'category' => 'user-rights',
- 'group' => 'neutral',
- 'section' => 'alert',
- 'formatter-class' => 'EchoUserRightsFormatter',
- 'title-message' => 'notification-user-rights',
- 'title-params' => array( 'agent', 'user-rights-list' ),
- 'flyout-message' => 'notification-user-rights-flyout',
- 'flyout-params' => array( 'agent', 'user-rights-list' ),
- 'email-subject-message' => 'notification-user-rights-email-subject',
- 'email-subject-params' => array(),
- 'email-body-batch-message' => 'notification-user-rights-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'user-rights-list' ),
- 'icon' => 'site',
- ),
-);
-
-// Enable new talk page messages alert for all logged in users by default
-$wgDefaultUserOptions['echo-show-alert'] = true;
-
-// By default, send emails for each notification as they come in
-$wgDefaultUserOptions['echo-email-frequency'] = 0; /*EchoHooks::EMAIL_IMMEDIATELY*/
-
-if ( $wgAllowHTMLEmail ) {
- $wgDefaultUserOptions['echo-email-format'] = 'html'; /*EchoHooks::EMAIL_FORMAT_HTML*/
+if ( function_exists( 'wfLoadExtension' ) ) {
+ wfLoadExtension( 'Echo' );
+ // Keep i18n globals so mergeMessageFileList.php doesn't break
+ $wgMessagesDirs['Echo'] = [
+ __DIR__ . '/i18n',
+ __DIR__ . '/i18n/api',
+ ];
+ $wgExtensionMessagesFiles['EchoAliases'] = __DIR__ . '/Echo.alias.php';
+ /* wfWarn(
+ 'Deprecated PHP entry point used for Echo extension. ' .
+ 'Please use wfLoadExtension instead, ' .
+ 'see https://www.mediawiki.org/wiki/Extension_registration for more details.'
+ ); */
+ return;
} else {
- $wgDefaultUserOptions['echo-email-format'] = 'plain-text'; /*EchoHooks::EMAIL_FORMAT_PLAIN_TEXT*/
-}
-
-// Set all of the events to notify by web but not email by default (won't affect events that don't email)
-foreach ( $wgEchoNotificationCategories as $category => $categoryData ) {
- $wgDefaultUserOptions["echo-subscriptions-email-{$category}"] = false;
- $wgDefaultUserOptions["echo-subscriptions-web-{$category}"] = true;
+ die( 'This version of the Echo extension requires MediaWiki 1.25+' );
}
-
-// most settings default to web on, email off, but override these
-$wgDefaultUserOptions['echo-subscriptions-email-system'] = true;
-$wgDefaultUserOptions['echo-subscriptions-email-user-rights'] = true;
-$wgDefaultUserOptions['echo-subscriptions-web-article-linked'] = false;
-
-// Echo Configuration for EventLogging
-$wgEchoConfig = array(
- 'version' => '1.5',
- 'eventlogging' => array (
- /**
- * Properties:
- * - 'enabled': Whether it should be used
- * - 'revision': revision id of the schema
- * - 'client': whether the schema is needed client-side
- */
- 'Echo' => array (
- 'enabled' => false,
- 'revision' => 7572295,
- 'client' => false,
- ),
- 'EchoMail' => array (
- 'enabled' => false,
- 'revision' => 5467650,
- 'client' => false,
- ),
- 'EchoInteraction' => array (
- 'enabled' => false,
- 'revision' => 5782287,
- 'client' => true,
- ),
- )
-);
diff --git a/Echo/Gemfile b/Echo/Gemfile
index abeac307..70c1a10b 100644
--- a/Echo/Gemfile
+++ b/Echo/Gemfile
@@ -1,10 +1,7 @@
-# ruby=ruby-2.1.1
-# ruby-gemset=Echo
-
source 'https://rubygems.org'
-gem 'chunky_png'
-gem 'csscss'
-gem 'mediawiki_api'
-gem 'mediawiki_selenium'
-gem 'rubocop', require: false
+gem 'csscss', '~> 1.3.3'
+gem 'mediawiki_selenium', '~> 1.8'
+gem 'rake', '~> 11.1', '>= 11.1.1'
+gem 'rspec-mocks', '~> 2.99', '>= 2.99.4'
+gem 'rubocop', '~> 0.34.2', require: false
diff --git a/Echo/Gemfile.lock b/Echo/Gemfile.lock
index 56ba4b31..7a8d8130 100644
--- a/Echo/Gemfile.lock
+++ b/Echo/Gemfile.lock
@@ -1,107 +1,121 @@
GEM
remote: https://rubygems.org/
specs:
- ast (2.0.0)
- astrolabe (1.3.0)
- parser (>= 2.2.0.pre.3, < 3.0)
+ ast (2.1.0)
+ astrolabe (1.3.1)
+ parser (~> 2.2)
blankslate (3.1.3)
- builder (3.2.2)
- childprocess (0.5.5)
+ builder (3.2.3)
+ childprocess (0.6.2)
ffi (~> 1.0, >= 1.0.11)
- chunky_png (1.3.3)
- colorize (0.7.5)
+ colorize (0.7.7)
csscss (1.3.3)
colorize
parslet (>= 1.6.1, < 2.0)
- cucumber (1.3.18)
+ cucumber (1.3.20)
builder (>= 2.1.2)
diff-lcs (>= 1.1.3)
gherkin (~> 2.12)
multi_json (>= 1.7.5, < 2.0)
- multi_test (>= 0.1.1)
- data_magic (0.20)
+ multi_test (>= 0.1.2)
+ data_magic (1.0)
faker (>= 1.1.2)
- yml_reader (>= 0.4)
- diff-lcs (1.2.5)
- domain_name (0.5.23)
+ yml_reader (>= 0.6)
+ diff-lcs (1.3)
+ domain_name (0.5.20170223)
unf (>= 0.0.5, < 1.0.0)
- faker (1.4.3)
+ faker (1.7.3)
i18n (~> 0.5)
- faraday (0.9.1)
+ faraday (0.11.0)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
- ffi (1.9.6)
+ faraday_middleware (0.11.0.1)
+ faraday (>= 0.7.4, < 1.0)
+ ffi (1.9.17)
gherkin (2.12.2)
multi_json (~> 1.3)
- headless (1.0.2)
- http-cookie (1.0.2)
+ headless (2.3.1)
+ http-cookie (1.0.3)
domain_name (~> 0.5)
- i18n (0.7.0)
- json (1.8.2)
- mediawiki_api (0.3.0)
+ i18n (0.8.1)
+ json (2.0.3)
+ mediawiki_api (0.7.1)
faraday (~> 0.9, >= 0.9.0)
faraday-cookie_jar (~> 0.0, >= 0.0.6)
- mediawiki_selenium (0.4.2)
- cucumber (~> 1.3, >= 1.3.10)
- headless (~> 1.0, >= 1.0.1)
- json (~> 1.8, >= 1.8.1)
- mediawiki_api (~> 0.2, >= 0.2.1)
- page-object (~> 1.0)
+ faraday_middleware (~> 0.10, >= 0.10.0)
+ mediawiki_selenium (1.8.0)
+ cucumber (~> 1.3, >= 1.3.20)
+ headless (~> 2.0, >= 2.1.0)
+ json (~> 2.0, >= 2.0.2)
+ mediawiki_api (~> 0.7, >= 0.7.0)
+ page-object (~> 2.0)
rest-client (~> 1.6, >= 1.6.7)
+ rspec-core (~> 2.14, >= 2.14.4)
rspec-expectations (~> 2.14, >= 2.14.4)
+ selenium-webdriver (~> 3.1.0)
syntax (~> 1.2, >= 1.2.0)
- mime-types (2.4.3)
- multi_json (1.10.1)
- multi_test (0.1.1)
+ thor (~> 0.19, >= 0.19.1)
+ mime-types (2.99.3)
+ multi_json (1.12.1)
+ multi_test (0.1.2)
multipart-post (2.0.0)
- netrc (0.10.2)
- page-object (1.0.3)
+ net-http-persistent (2.9.4)
+ netrc (0.11.0)
+ page-object (2.0.0)
+ net-http-persistent (~> 2.9.4)
page_navigation (>= 0.9)
- selenium-webdriver (>= 2.44.0)
- watir-webdriver (>= 0.6.11)
- page_navigation (0.9)
- data_magic (>= 0.14)
- parser (2.2.0.2)
+ selenium-webdriver (~> 3.0)
+ watir (~> 6.0)
+ page_navigation (0.10)
+ data_magic (>= 0.22)
+ parser (2.2.2.6)
ast (>= 1.1, < 3.0)
- parslet (1.6.2)
+ parslet (1.7.1)
blankslate (>= 2.0, <= 4.0)
- powerpack (0.1.0)
+ powerpack (0.1.1)
rainbow (2.0.0)
- rest-client (1.7.2)
+ rake (11.1.1)
+ rest-client (1.8.0)
+ http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
+ rspec-core (2.99.2)
rspec-expectations (2.99.2)
diff-lcs (>= 1.1.3, < 2.0)
- rubocop (0.29.0)
+ rspec-mocks (2.99.4)
+ rubocop (0.34.2)
astrolabe (~> 1.3)
- parser (>= 2.2.0.1, < 3.0)
+ parser (>= 2.2.2.5, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
- ruby-progressbar (1.7.1)
- rubyzip (1.1.7)
- selenium-webdriver (2.44.0)
+ ruby-progressbar (1.7.5)
+ rubyzip (1.2.1)
+ selenium-webdriver (3.1.0)
childprocess (~> 0.5)
- multi_json (~> 1.0)
rubyzip (~> 1.0)
websocket (~> 1.0)
- syntax (1.2.0)
+ syntax (1.2.1)
+ thor (0.19.4)
unf (0.1.4)
unf_ext
- unf_ext (0.0.6)
- watir-webdriver (0.6.11)
- selenium-webdriver (>= 2.18.0)
- websocket (1.2.1)
- yml_reader (0.5)
+ unf_ext (0.0.7.2)
+ watir (6.2.0)
+ selenium-webdriver (~> 3.0)
+ websocket (1.2.4)
+ yml_reader (0.7)
PLATFORMS
ruby
DEPENDENCIES
- chunky_png
- csscss
- mediawiki_api
- mediawiki_selenium
- rubocop
+ csscss (~> 1.3.3)
+ mediawiki_selenium (~> 1.8)
+ rake (~> 11.1, >= 11.1.1)
+ rspec-mocks (~> 2.99, >= 2.99.4)
+ rubocop (~> 0.34.2)
+
+BUNDLED WITH
+ 1.14.6
diff --git a/Echo/Gruntfile.js b/Echo/Gruntfile.js
index 4d28c5e3..c389ce11 100644
--- a/Echo/Gruntfile.js
+++ b/Echo/Gruntfile.js
@@ -1,52 +1,52 @@
-/*jshint node:true */
+/* eslint-env node */
module.exports = function ( grunt ) {
- grunt.loadNpmTasks( 'grunt-contrib-csslint' );
- grunt.loadNpmTasks( 'grunt-contrib-jshint' );
+ var conf = grunt.file.readJSON( 'extension.json' );
+
+ grunt.loadNpmTasks( 'grunt-banana-checker' );
grunt.loadNpmTasks( 'grunt-contrib-watch' );
+ grunt.loadNpmTasks( 'grunt-eslint' );
grunt.loadNpmTasks( 'grunt-jsonlint' );
- grunt.loadNpmTasks( 'grunt-banana-checker' );
- grunt.loadNpmTasks( 'grunt-jscs' );
+ grunt.loadNpmTasks( 'grunt-stylelint' );
grunt.initConfig( {
- jshint: {
- options: {
- jshintrc: true
- },
- all: [
- '*.js',
- 'modules/**/*.js',
- 'tests/qunit/**/*.js'
+ eslint: {
+ src: [
+ '**/*.js',
+ '!node_modules/**',
+ '!vendor/**',
+ '!tests/externals/**',
+ '!docs/**'
]
},
- jscs: {
- src: '<%= jshint.all %>'
- },
- csslint: {
+ // Lint – Styling
+ stylelint: {
options: {
- csslintrc: '.csslintrc'
+ syntax: 'less'
},
- all: 'modules/**/*.css'
- },
- banana: {
- all: 'i18n/'
+ all: [
+ 'modules/**/*.css',
+ 'modules/**/*.less'
+ ]
},
+ banana: conf.MessagesDirs,
watch: {
files: [
- '.{csslintrc,jscsrc,jshintignore,jshintrc}',
- '<%= jshint.all %>',
- '<%= csslint.all %>'
+ '.{stylelintrc,eslintrc}.json',
+ '<%= eslint.all %>',
+ '<%= stylelint.all %>'
],
tasks: 'test'
},
jsonlint: {
all: [
'**/*.json',
- '!node_modules/**'
+ '!node_modules/**',
+ '!docs/**'
]
}
} );
- grunt.registerTask( 'lint', [ 'jscs', 'jshint', 'csslint', 'jsonlint', 'banana' ] );
+ grunt.registerTask( 'lint', [ 'eslint', 'stylelint', 'jsonlint', 'banana' ] );
grunt.registerTask( 'test', 'lint' );
grunt.registerTask( 'default', 'test' );
};
diff --git a/Echo/Hooks.php b/Echo/Hooks.php
index af81d40c..8e3db35d 100644
--- a/Echo/Hooks.php
+++ b/Echo/Hooks.php
@@ -1,12 +1,35 @@
<?php
+use MediaWiki\Auth\AuthManager;
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
+
class EchoHooks {
- const EMAIL_NEVER = -1; // Never send email notifications
- const EMAIL_IMMEDIATELY = 0; // Send email notificaitons immediately as they come in
- const EMAIL_DAILY_DIGEST = 1; // Send daily email digests
- const EMAIL_WEEKLY_DIGEST = 7; // Send weekly email digests
- const EMAIL_FORMAT_HTML = 'html';
- const EMAIL_FORMAT_PLAIN_TEXT = 'plain-text';
+ public static function registerExtension() {
+ global $wgNotificationSender, $wgPasswordSender, $wgAllowHTMLEmail,
+ $wgEchoNotificationCategories, $wgDefaultUserOptions;
+
+ $wgNotificationSender = $wgPasswordSender;
+
+ if ( $wgAllowHTMLEmail ) {
+ $wgDefaultUserOptions['echo-email-format'] = 'html'; /*EchoHooks::EMAIL_FORMAT_HTML*/
+ } else {
+ $wgDefaultUserOptions['echo-email-format'] = 'plain-text'; /*EchoHooks::EMAIL_FORMAT_PLAIN_TEXT*/
+ }
+
+ // Set all of the events to notify by web but not email by default (won't affect events that don't email)
+ foreach ( $wgEchoNotificationCategories as $category => $categoryData ) {
+ $wgDefaultUserOptions["echo-subscriptions-email-{$category}"] = false;
+ $wgDefaultUserOptions["echo-subscriptions-web-{$category}"] = true;
+ }
+
+ // most settings default to web on, email off, but override these
+ $wgDefaultUserOptions['echo-subscriptions-email-system'] = true;
+ $wgDefaultUserOptions['echo-subscriptions-email-user-rights'] = true;
+ $wgDefaultUserOptions['echo-subscriptions-web-article-linked'] = false;
+ $wgDefaultUserOptions['echo-subscriptions-web-mention-failure'] = false;
+ $wgDefaultUserOptions['echo-subscriptions-web-mention-success'] = false;
+ }
/**
* Initialize Echo extension with necessary data, this function is invoked
@@ -14,16 +37,28 @@ class EchoHooks {
*/
public static function initEchoExtension() {
global $wgEchoNotifications, $wgEchoNotificationCategories, $wgEchoNotificationIcons,
- $wgEchoConfig;
+ $wgEchoEventLoggingSchemas, $wgEchoMentionStatusNotifications, $wgAllowArticleReminderNotification, $wgAPIModules;
// allow extensions to define their own event
- Hooks::run( 'BeforeCreateEchoEvent', array( &$wgEchoNotifications, &$wgEchoNotificationCategories, &$wgEchoNotificationIcons ) );
+ Hooks::run( 'BeforeCreateEchoEvent', [ &$wgEchoNotifications, &$wgEchoNotificationCategories, &$wgEchoNotificationIcons ] );
+
+ // Only allow mention status notifications when enabled
+ if ( !$wgEchoMentionStatusNotifications ) {
+ unset( $wgEchoNotificationCategories['mention-failure'] );
+ unset( $wgEchoNotificationCategories['mention-success'] );
+ }
+
+ // Only allow article reminder notifications when enabled
+ if ( !$wgAllowArticleReminderNotification ) {
+ unset( $wgEchoNotificationCategories['article-reminder'] );
+ unset( $wgAPIModules['echoarticlereminder'] );
+ }
// turn schema off if eventLogging is not enabled
if ( !class_exists( 'EventLogging' ) ) {
- foreach ( $wgEchoConfig['eventlogging'] as $schema => $property ) {
+ foreach ( $wgEchoEventLoggingSchemas as $schema => $property ) {
if ( $property['enabled'] ) {
- $wgEchoConfig['eventlogging'][$schema]['enabled'] = false;
+ $wgEchoEventLoggingSchemas[$schema]['enabled'] = false;
}
}
}
@@ -42,7 +77,7 @@ class EchoHooks {
* ResourceLoaderTestModules hook handler
* @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderTestModules
*
- * @param array $testModules
+ * @param array &$testModules
* @param ResourceLoader $resourceLoader
* @return bool
*/
@@ -51,16 +86,16 @@ class EchoHooks {
) {
global $wgResourceModules;
- $testModuleBoilerplate = array(
+ $testModuleBoilerplate = [
'localBasePath' => __DIR__,
'remoteExtPath' => 'Echo',
- );
+ ];
// find test files for every RL module
$prefix = 'ext.echo';
foreach ( $wgResourceModules as $key => $module ) {
if ( substr( $key, 0, strlen( $prefix ) ) === $prefix && isset( $module['scripts'] ) ) {
- $testFiles = array();
+ $testFiles = [];
foreach ( $module['scripts'] as $script ) {
$testFile = 'tests/qunit/' . dirname( $script ) . '/test_' . basename( $script );
// if a test file exists for a given JS file, add it
@@ -70,10 +105,10 @@ class EchoHooks {
}
// if test files exist for given module, create a corresponding test module
if ( count( $testFiles ) > 0 ) {
- $testModules['qunit']["$key.tests"] = $testModuleBoilerplate + array(
- 'dependencies' => array( $key ),
+ $testModules['qunit']["$key.tests"] = $testModuleBoilerplate + [
+ 'dependencies' => [ $key ],
'scripts' => $testFiles,
- );
+ ];
}
}
}
@@ -82,8 +117,8 @@ class EchoHooks {
}
public static function onEventLoggingRegisterSchemas( array &$schemas ) {
- global $wgEchoConfig;
- foreach ( $wgEchoConfig['eventlogging'] as $schema => $property ) {
+ global $wgEchoEventLoggingSchemas;
+ foreach ( $wgEchoEventLoggingSchemas as $schema => $property ) {
if ( $property['enabled'] && $property['client'] ) {
$schemas[$schema] = $property['revision'];
}
@@ -92,27 +127,28 @@ class EchoHooks {
/**
* Handler for ResourceLoaderRegisterModules hook
+ * @param ResourceLoader &$resourceLoader
*/
public static function onResourceLoaderRegisterModules( ResourceLoader &$resourceLoader ) {
- global $wgEchoConfig;
+ global $wgEchoEventLoggingSchemas;
// ext.echo.logger is used by mobile notifications as well, so be sure not to add any
// dependencies that do not target mobile.
- $definition = array(
+ $definition = [
'position' => 'top',
- 'scripts' => array(
+ 'scripts' => [
'logger/mw.echo.Logger.js',
- ),
- 'dependencies' => array(
+ ],
+ 'dependencies' => [
'oojs'
- ),
+ ],
'localBasePath' => __DIR__ . '/modules',
'remoteExtPath' => 'Echo/modules',
- 'targets' => array( 'desktop', 'mobile' ),
- );
+ 'targets' => [ 'desktop', 'mobile' ],
+ ];
$hasSchemas = false;
- foreach ( $wgEchoConfig['eventlogging'] as $schema => $property ) {
+ foreach ( $wgEchoEventLoggingSchemas as $schema => $property ) {
if ( $property['enabled'] && $property['client'] ) {
$definition['dependencies'][] = 'schema.' . $schema;
$hasSchemas = true;
@@ -124,10 +160,26 @@ class EchoHooks {
}
$resourceLoader->register( 'ext.echo.logger', $definition );
+
+ global $wgExtensionDirectory, $wgEchoNotificationIcons, $wgEchoSecondaryIcons;
+ $resourceLoader->register( 'ext.echo.emailicons', [
+ 'class' => 'ResourceLoaderEchoImageModule',
+ 'icons' => $wgEchoNotificationIcons,
+ 'selector' => '.mw-echo-icon-{name}',
+ 'localBasePath' => $wgExtensionDirectory,
+ 'remoteExtPath' => 'Echo/modules'
+ ] );
+ $resourceLoader->register( 'ext.echo.secondaryicons', [
+ 'class' => 'ResourceLoaderEchoImageModule',
+ 'icons' => $wgEchoSecondaryIcons,
+ 'selector' => '.mw-echo-icon-{name}',
+ 'localBasePath' => $wgExtensionDirectory,
+ 'remoteExtPath' => 'Echo/modules'
+ ] );
}
/**
- * @param $updater DatabaseUpdater object
+ * @param DatabaseUpdater $updater
*/
public static function onLoadExtensionSchemaUpdates( DatabaseUpdater $updater ) {
global $wgEchoCluster;
@@ -145,6 +197,7 @@ class EchoHooks {
$updater->modifyExtensionField( 'echo_event', 'event_agent', "$dir/db_patches/patch-event_agent-split.sqlite.sql" );
$updater->modifyExtensionField( 'echo_event', 'event_variant', "$dir/db_patches/patch-event_variant_nullability.sqlite.sql" );
$updater->addExtensionField( 'echo_target_page', 'etp_id', "$dir/db_patches/patch-multiple_target_pages.sqlite.sql" );
+ $updater->dropExtensionField( 'echo_target_page', 'etp_user', "$dir/db_patches/patch-drop-echo_target_page-etp_user.sqlite.sql" );
// There is no need to run the patch-event_extra-size or patch-event_agent_ip-size because
// sqlite ignores numeric arguments in parentheses that follow the type name (ex: VARCHAR(255))
// see http://www.sqlite.org/datatype3.html Section 2.2 for more info
@@ -154,6 +207,7 @@ class EchoHooks {
$updater->modifyExtensionField( 'echo_event', 'event_extra', "$dir/db_patches/patch-event_extra-size.sql" );
$updater->modifyExtensionField( 'echo_event', 'event_agent_ip', "$dir/db_patches/patch-event_agent_ip-size.sql" );
$updater->addExtensionField( 'echo_target_page', 'etp_id', "$dir/db_patches/patch-multiple_target_pages.sql" );
+ $updater->dropExtensionField( 'echo_target_page', 'etp_user', "$dir/db_patches/patch-drop-echo_target_page-etp_user.sql" );
}
$updater->addExtensionField( 'echo_notification', 'notification_bundle_base',
@@ -162,20 +216,27 @@ class EchoHooks {
if ( $updater->getDB()->indexExists( 'echo_event', 'type_page', __METHOD__ ) ) {
$updater->addExtensionIndex( 'echo_event', 'event_type', "$dir/db_patches/patch-alter-type_page-index.sql" );
}
- $updater->dropTable( 'echo_subscription' );
+ $updater->dropExtensionTable( 'echo_subscription', "$dir/db_patches/patch-drop-echo_subscription.sql" );
$updater->dropExtensionField( 'echo_event', 'event_timestamp', "$dir/db_patches/patch-drop-echo_event-event_timestamp.sql" );
$updater->addExtensionField( 'echo_email_batch', 'eeb_event_hash',
"$dir/db_patches/patch-email_batch-new-field.sql" );
$updater->addExtensionField( 'echo_event', 'event_page_id', "$dir/db_patches/patch-add-echo_event-event_page_id.sql" );
$updater->addExtensionIndex( 'echo_event', 'echo_event_type', "$dir/db_patches/patch-alter-event_type-index.sql" );
$updater->addExtensionIndex( 'echo_notification', 'echo_user_timestamp', "$dir/db_patches/patch-alter-user_timestamp-index.sql" );
+ $updater->addExtensionIndex( 'echo_notification', 'echo_notification_event', "$dir/db_patches/patch-add-notification_event-index.sql" );
+ $updater->addPostDatabaseUpdateMaintenance( 'RemoveOrphanedEvents' );
+ $updater->addExtensionField( 'echo_event', 'event_deleted', "$dir/db_patches/patch-add-echo_event-event_deleted.sql" );
+ $updater->addExtensionIndex( 'echo_notification', 'echo_notification_user_read_timestamp', "$dir/db_patches/patch-add-user_read_timestamp-index.sql" );
+ $updater->addExtensionIndex( 'echo_target_page', 'echo_target_page_page_event', "$dir/db_patches/patch-add-page_event-index.sql" );
+ $updater->addExtensionIndex( 'echo_event', 'echo_event_page_id', "$dir/db_patches/patch-add-event_page_id-index.sql" );
+ $updater->dropExtensionIndex( 'echo_notification', 'user_event', "$dir/db_patches/patch-notification-pk.sql" );
}
/**
* Handler for EchoGetBundleRule hook, which defines the bundle rule for each notification
*
- * @param $event EchoEvent
- * @param $bundleString string Determines how the notification should be bundled, for example,
+ * @param EchoEvent $event
+ * @param string &$bundleString Determines how the notification should be bundled, for example,
* talk page notification is bundled based on namespace and title, the bundle string would be
* 'edit-user-talk-' + namespace + title, email digest/email bundling would use this hash as
* a key to identify bundle-able event. For web bundling, we bundle further based on user's
@@ -189,17 +250,52 @@ class EchoHooks {
$bundleString = 'edit-user-talk';
if ( $event->getTitle() ) {
$bundleString .= '-' . $event->getTitle()->getNamespace()
- . '-' . $event->getTitle()->getDBkey();
+ . '-' . $event->getTitle()->getDBkey();
}
- break;
+ break;
case 'page-linked':
$bundleString = 'page-linked';
if ( $event->getTitle() ) {
$bundleString .= '-' . $event->getTitle()->getNamespace()
- . '-' . $event->getTitle()->getDBkey();
+ . '-' . $event->getTitle()->getDBkey();
}
- break;
+ break;
+ case 'mention-success':
+ case 'mention-failure':
+ $bundleString = 'mention-status-' . $event->getExtraParam( 'revid' );
+ break;
}
+
+ return true;
+ }
+
+ /**
+ * Handler for the GetBetaFeaturePreferences hook.
+ * @see https://www.mediawiki.org/wiki/Manual:Hooks/GetBetaFeaturePreferences
+ *
+ * @param User $user User to get preferences for
+ * @param array &$preferences Preferences array
+ *
+ * @return bool true in all cases
+ */
+ public static function getBetaFeaturePreferences( User $user, array &$preferences ) {
+ global $wgExtensionAssetsPath, $wgEchoUseCrossWikiBetaFeature, $wgEchoCrossWikiNotifications;
+
+ if ( $wgEchoUseCrossWikiBetaFeature && $wgEchoCrossWikiNotifications ) {
+ $preferences['echo-cross-wiki-notifications'] = [
+ 'label-message' => 'echo-pref-beta-feature-cross-wiki-message',
+ 'desc-message' => 'echo-pref-beta-feature-cross-wiki-description',
+ // Paths to images that represents the feature.
+ 'screenshot' => [
+ 'rtl' => "$wgExtensionAssetsPath/Echo/images/betafeatures-icon-notifications-rtl.svg",
+ 'ltr' => "$wgExtensionAssetsPath/Echo/images/betafeatures-icon-notifications-ltr.svg",
+ ],
+ 'info-link' => 'https://www.mediawiki.org/wiki/Special:Mylanguage/Help:Notifications/Cross-wiki',
+ // Link to discussion about the feature - talk pages might work
+ 'discussion-link' => 'https://www.mediawiki.org/wiki/Help_talk:Notifications',
+ ];
+ }
+
return true;
}
@@ -207,50 +303,54 @@ class EchoHooks {
* Handler for GetPreferences hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/GetPreferences
*
- * @param $user User to get preferences for
- * @param &$preferences Preferences array
+ * @param User $user User to get preferences for
+ * @param array &$preferences Preferences array
*
* @throws MWException
* @return bool true in all cases
*/
public static function getPreferences( $user, &$preferences ) {
- global $wgEchoDefaultNotificationTypes, $wgAuth, $wgEchoEnableEmailBatch,
+ global $wgEchoEnableEmailBatch,
$wgEchoNotifiers, $wgEchoNotificationCategories, $wgEchoNotifications,
- $wgEchoNewMsgAlert, $wgAllowHTMLEmail;
+ $wgEchoNewMsgAlert, $wgAllowHTMLEmail, $wgEchoUseCrossWikiBetaFeature,
+ $wgEchoShowFooterNotice, $wgEchoCrossWikiNotifications, $wgEchoPerUserBlacklist;
+
+ $attributeManager = EchoAttributeManager::newFromGlobalVars();
// Show email frequency options
$never = wfMessage( 'echo-pref-email-frequency-never' )->plain();
$immediately = wfMessage( 'echo-pref-email-frequency-immediately' )->plain();
- $freqOptions = array(
- $never => self::EMAIL_NEVER,
- $immediately => self::EMAIL_IMMEDIATELY,
- );
+ $freqOptions = [
+ $never => EchoEmailFrequency::NEVER,
+ $immediately => EchoEmailFrequency::IMMEDIATELY,
+ ];
// Only show digest options if email batch is enabled
if ( $wgEchoEnableEmailBatch ) {
$daily = wfMessage( 'echo-pref-email-frequency-daily' )->plain();
$weekly = wfMessage( 'echo-pref-email-frequency-weekly' )->plain();
- $freqOptions += array(
- $daily => self::EMAIL_DAILY_DIGEST,
- $weekly => self::EMAIL_WEEKLY_DIGEST
- );
+ $freqOptions += [
+ $daily => EchoEmailFrequency::DAILY_DIGEST,
+ $weekly => EchoEmailFrequency::WEEKLY_DIGEST,
+ ];
}
- $preferences['echo-email-frequency'] = array(
+ $preferences['echo-email-frequency'] = [
'type' => 'select',
'label-message' => 'echo-pref-send-me',
'section' => 'echo/emailsettings',
'options' => $freqOptions
- );
+ ];
// Display information about the user's currently set email address
$prefsTitle = SpecialPage::getTitleFor( 'Preferences', false, 'mw-prefsection-echo' );
$link = Linker::link(
SpecialPage::getTitleFor( 'ChangeEmail' ),
wfMessage( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->escaped(),
- array(),
- array( 'returnto' => $prefsTitle->getFullText() )
+ [],
+ [ 'returnto' => $prefsTitle->getFullText() ]
);
- $emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : '';
- if ( $wgAuth->allowPropChange( 'emailaddress' ) ) {
+ $emailAddress = $user->getEmail() && $user->isAllowed( 'viewmyprivateinfo' )
+ ? htmlspecialchars( $user->getEmail() ) : '';
+ if ( $user->isAllowed( 'editmyprivateinfo' ) && self::isEmailChangeAllowed() ) {
if ( $emailAddress === '' ) {
$emailAddress .= $link;
} else {
@@ -258,38 +358,37 @@ class EchoHooks {
. wfMessage( 'parentheses' )->rawParams( $link )->escaped();
}
}
- $preferences['echo-emailaddress'] = array(
+ $preferences['echo-emailaddress'] = [
'type' => 'info',
'raw' => true,
'default' => $emailAddress,
'label-message' => 'echo-pref-send-to',
'section' => 'echo/emailsettings'
- );
+ ];
// Only show this option if html email is allowed, otherwise it is always plain text format
if ( $wgAllowHTMLEmail ) {
// Email format
- $preferences['echo-email-format'] = array(
+ $preferences['echo-email-format'] = [
'type' => 'select',
'label-message' => 'echo-pref-email-format',
'section' => 'echo/emailsettings',
- 'options' => array (
- wfMessage( 'echo-pref-email-format-html' )->plain() => self::EMAIL_FORMAT_HTML,
- wfMessage( 'echo-pref-email-format-plain-text' )->plain() => self::EMAIL_FORMAT_PLAIN_TEXT
- )
- );
+ 'options' => [
+ wfMessage( 'echo-pref-email-format-html' )->plain() => EchoEmailFormat::HTML,
+ wfMessage( 'echo-pref-email-format-plain-text' )->plain() => EchoEmailFormat::PLAIN_TEXT,
+ ]
+ ];
}
// Sort notification categories by priority
- $categoriesAndPriorities = array();
- foreach ( $wgEchoNotificationCategories as $category => $categoryData ) {
- // See if the category is not dismissable at all. Must do strict
- // comparison to true since no-dismiss can also be an array
- if ( isset( $categoryData['no-dismiss'] ) && in_array( 'all' , $categoryData['no-dismiss'] ) ) {
+ $categoriesAndPriorities = [];
+ foreach ( $attributeManager->getInternalCategoryNames() as $category ) {
+ // See if the category should be hidden from preferences.
+ if ( !$attributeManager->isCategoryDisplayedInPreferences( $category ) ) {
continue;
}
- $attributeManager = EchoAttributeManager::newFromGlobalVars();
- // See if user is eligible to recieve this notification (per user group restrictions)
+
+ // See if user is eligible to receive this notification (per user group restrictions)
if ( $attributeManager->getCategoryEligibility( $user, $category ) ) {
$categoriesAndPriorities[$category] = $attributeManager->getCategoryPriority( $category );
}
@@ -305,16 +404,16 @@ class EchoHooks {
// new wikis or Echo is disabled and re-enabled for some reason. We can update the name
// if Echo is ever merged to core
- // Build the columns (output formats)
- $columns = array();
+ // Build the columns (notify types)
+ $columns = [];
foreach ( $wgEchoNotifiers as $notifierType => $notifierData ) {
$formatMessage = wfMessage( 'echo-pref-' . $notifierType )->escaped();
$columns[$formatMessage] = $notifierType;
}
// Build the rows (notification categories)
- $rows = array();
- $tooltips = array();
+ $rows = [];
+ $tooltips = [];
foreach ( $validSortedCategories as $category ) {
$categoryMessage = wfMessage( 'echo-category-title-' . $category )->numParams( 1 )->escaped();
$rows[$categoryMessage] = $category;
@@ -324,22 +423,15 @@ class EchoHooks {
}
// Figure out the individual exceptions in the matrix and make them disabled
- $forceOptionsOff = $forceOptionsOn = array();
+ $forceOptionsOff = $forceOptionsOn = [];
foreach ( $wgEchoNotifiers as $notifierType => $notifierData ) {
foreach ( $validSortedCategories as $category ) {
- // See if this output format is non-dismissable
- if ( isset( $wgEchoNotificationCategories[$category]['no-dismiss'] )
- && in_array( $notifierType, $wgEchoNotificationCategories[$category]['no-dismiss'] ) )
- {
+ // See if this notify type is non-dismissable
+ if ( !$attributeManager->isNotifyTypeDismissableForCategory( $category, $notifierType ) ) {
$forceOptionsOn[] = "$notifierType-$category";
}
- // Make sure this output format is possible for this notification category
- if ( isset( $wgEchoDefaultNotificationTypes[$category] ) ) {
- if ( !$wgEchoDefaultNotificationTypes[$category][$notifierType] ) {
- $forceOptionsOff[] = "$notifierType-$category";
- }
- } elseif ( !$wgEchoDefaultNotificationTypes['all'][$notifierType] ) {
+ if ( !$attributeManager->isNotifyTypeAvailableForCategory( $category, $notifierType ) ) {
$forceOptionsOff[] = "$notifierType-$category";
}
}
@@ -352,7 +444,7 @@ class EchoHooks {
implode( ', ', $invalid )
) );
}
- $preferences['echo-subscriptions'] = array(
+ $preferences['echo-subscriptions'] = [
'class' => 'HTMLCheckMatrix',
'section' => 'echo/echosubscriptions',
'rows' => $rows,
@@ -361,14 +453,22 @@ class EchoHooks {
'force-options-off' => $forceOptionsOff,
'force-options-on' => $forceOptionsOn,
'tooltips' => $tooltips,
- );
+ ];
+
+ if ( !$wgEchoUseCrossWikiBetaFeature && $wgEchoCrossWikiNotifications ) {
+ $preferences['echo-cross-wiki-notifications'] = [
+ 'type' => 'toggle',
+ 'label-message' => 'echo-pref-cross-wiki-notifications',
+ 'section' => 'echo/echocrosswiki'
+ ];
+ }
if ( $wgEchoNewMsgAlert ) {
- $preferences['echo-show-alert'] = array(
+ $preferences['echo-show-alert'] = [
'type' => 'toggle',
'label-message' => 'echo-pref-new-message-indicator',
'section' => 'echo/newmessageindicator',
- );
+ ];
}
// If we're using Echo to handle user talk page post notifications,
@@ -383,58 +483,133 @@ class EchoHooks {
unset( $preferences['enotifusertalkpages']['section'] );
}
+ if ( $wgEchoShowFooterNotice ) {
+ $preferences['echo-dismiss-special-page-invitation'] = [
+ 'type' => 'api',
+ ];
+ }
+
+ if ( $wgEchoPerUserBlacklist ) {
+ $preferences['echo-notifications-blacklist'] = [
+ 'type' => 'usersmultiselect',
+ 'label-message' => 'echo-pref-notifications-blacklist',
+ 'section' => 'echo/blocknotificationslist',
+ ];
+ }
+
return true;
}
/**
- * Handler for ArticleSaveComplete hook
- * @see http://www.mediawiki.org/wiki/Manual:Hooks/ArticleSaveComplete
- * @param $article Article edited
- * @param $user User who edited
- * @param $text string New article text
- * @param $summary string Edit summary
- * @param $minoredit bool Minor edit or not
- * @param $watchthis bool Watch this article?
- * @param $sectionanchor string Section that was edited
- * @param $flags int Edit flags
- * @param $revision Revision that was created
- * @param $status Status
+ * Test whether email address change is supposed to be allowed
+ * @return bool
+ */
+ private static function isEmailChangeAllowed() {
+ global $wgAuth, $wgDisableAuthManager;
+
+ if ( class_exists( AuthManager::class ) && !$wgDisableAuthManager ) {
+ return AuthManager::singleton()->allowsPropertyChange( 'emailaddress' );
+ } else {
+ return $wgAuth->allowPropChange( 'emailaddress' );
+ }
+ }
+
+ /**
+ * Handler for PageContentSaveComplete hook
+ * @see http://www.mediawiki.org/wiki/Manual:Hooks/PageContentSaveComplete
+ * @param Article &$article Article edited
+ * @param User &$user User who edited
+ * @param Content $content New article text
+ * @param string $summary Edit summary
+ * @param bool $minoredit Minor edit or not
+ * @param bool $watchthis Watch this article?
+ * @param string $sectionanchor Section that was edited
+ * @param int &$flags Edit flags
+ * @param Revision $revision Revision that was created
+ * @param Status &$status
+ * @param int $baseRevId
+ * @param int $undidRevId
* @return bool true in all cases
*/
- public static function onArticleSaved( &$article, &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, $revision, &$status ) {
- global $wgEchoNotifications, $wgRequest;
+ public static function onPageContentSaveComplete( &$article, &$user, $content, $summary, $minoredit,
+ $watchthis, $sectionanchor, &$flags, $revision, &$status, $baseRevId, $undidRevId = 0 ) {
+ global $wgEchoNotifications;
if ( !$revision ) {
return true;
}
+ // unless status is "good" (not only ok, also no warnings or errors), we
+ // probably shouldn't process it at all (e.g. null edits)
+ if ( !$status->isGood() ) {
+ return true;
+ }
+
+ $title = $article->getTitle();
+
// Try to do this after the HTTP response
- DeferredUpdates::addCallableUpdate( function() use ( $revision ) {
+ DeferredUpdates::addCallableUpdate( function () use ( $revision ) {
EchoDiscussionParser::generateEventsForRevision( $revision );
} );
- // Handle the case of someone undoing an edit, either through the
- // 'undo' link in the article history or via the API.
- if ( isset( $wgEchoNotifications['reverted'] ) ) {
- $title = $article->getTitle();
- $undidRevId = $wgRequest->getVal( 'wpUndidRevision' );
- if ( $undidRevId ) {
- $undidRevision = Revision::newFromId( $undidRevId );
- if ( $undidRevision && $undidRevision->getTitle()->equals( $title ) ) {
- $victimId = $undidRevision->getUser();
- if ( $victimId ) { // No notifications for anonymous users
- EchoEvent::create( array(
- 'type' => 'reverted',
+ // If the user is not an IP and this is not a null edit,
+ // test for them reaching a congratulatory threshold
+ $thresholds = [ 1, 10, 100, 1000, 10000, 100000, 1000000 ];
+ if ( $user->isLoggedIn() && $status->value['revision'] ) {
+ $thresholdCount = $user->getEditCount();
+ if ( in_array( $thresholdCount, $thresholds ) ) {
+ DeferredUpdates::addCallableUpdate( function () use ( $user, $title, $thresholdCount ) {
+ $notificationMapper = new EchoNotificationMapper();
+ $notifications = $notificationMapper->fetchByUser( $user, 10, null, [ 'thank-you-edit' ] );
+ /** @var EchoNotification $notification */
+ foreach ( $notifications as $notification ) {
+ if ( $notification->getEvent()->getExtraParam( 'editCount' ) === $thresholdCount ) {
+ LoggerFactory::getInstance( 'Echo' )->debug(
+ '{user} (id: {id}) has already been thanked for their {count} edit',
+ [
+ 'user' => $user->getName(),
+ 'id' => $user->getId(),
+ 'count' => $thresholdCount,
+ ]
+ );
+ return;
+ }
+ }
+
+ EchoEvent::create( [
+ 'type' => 'thank-you-edit',
'title' => $title,
- 'extra' => array(
- 'revid' => $revision->getId(),
- 'reverted-user-id' => $victimId,
- 'reverted-revision-id' => $undidRevId,
- 'method' => 'undo',
- ),
'agent' => $user,
- ) );
- }
+ // Edit threshold notifications are sent to the agent
+ 'extra' => [
+ 'notifyAgent' => true,
+ 'editCount' => $thresholdCount,
+ ]
+ ]
+ );
+ } );
+ }
+ }
+
+ // Handle the case of someone undoing an edit, either through the
+ // 'undo' link in the article history or via the API.
+ if ( isset( $wgEchoNotifications['reverted'] ) && $undidRevId ) {
+ $undidRevision = Revision::newFromId( $undidRevId );
+ if ( $undidRevision && $undidRevision->getTitle()->equals( $title ) ) {
+ $victimId = $undidRevision->getUser();
+ if ( $victimId ) { // No notifications for anonymous users
+ EchoEvent::create( [
+ 'type' => 'reverted',
+ 'title' => $title,
+ 'extra' => [
+ 'revid' => $revision->getId(),
+ 'reverted-user-id' => $victimId,
+ 'reverted-revision-id' => $undidRevId,
+ 'method' => 'undo',
+ 'summary' => $summary,
+ ],
+ 'agent' => $user,
+ ] );
}
}
}
@@ -444,8 +619,8 @@ class EchoHooks {
/**
* Handler for EchoAbortEmailNotification hook
- * @param $user User
- * @param $event EchoEvent
+ * @param User $user
+ * @param EchoEvent $event
* @return bool true - send email, false - do not send email
*/
public static function onEchoAbortEmailNotification( $user, $event ) {
@@ -465,30 +640,49 @@ class EchoHooks {
}
/**
- * Handler for AddNewAccount hook.
- * @see http://www.mediawiki.org/wiki/Manual:Hooks/AddNewAccount
- * @param $user User object that was created.
- * @param $byEmail bool True when account was created "by email".
+ * Get overrides for new users. This allows changes that only apply going forward,
+ * without affecting existing users.
+ *
+ * @return array Associative array mapping key to bool for whether it should be enabled
+ */
+ public static function getNewUserPreferenceOverrides() {
+ return [
+ 'echo-subscriptions-web-reverted' => false,
+ 'echo-subscriptions-email-reverted' => false,
+ 'echo-subscriptions-web-article-linked' => true,
+ 'echo-subscriptions-email-mention' => true,
+ 'echo-subscriptions-email-article-linked' => true,
+ ];
+ }
+
+ /**
+ * Handler for LocalUserCreated hook.
+ * @see http://www.mediawiki.org/wiki/Manual:Hooks/LocalUserCreated
+ * @param User $user User object that was created.
+ * @param bool $autocreated True when account was auto-created
* @return bool
*/
- public static function onAccountCreated( $user, $byEmail ) {
-
- // new users get echo preferences set that are not the default settings for existing users
- $user->setOption( 'echo-subscriptions-web-reverted', false );
- $user->setOption( 'echo-subscriptions-email-reverted', false );
- $user->setOption( 'echo-subscriptions-web-article-linked', true );
- $user->setOption( 'echo-subscriptions-email-mention', true );
- $user->setOption( 'echo-subscriptions-email-article-linked', true );
- $user->saveSettings();
-
- EchoEvent::create( array(
- 'type' => 'welcome',
- 'agent' => $user,
- // welcome email is sent to agent
- 'extra' => array (
- 'notifyAgent' => true
- )
- ) );
+ public static function onLocalUserCreated( $user, $autocreated ) {
+ if ( !$autocreated ) {
+ $overrides = self::getNewUserPreferenceOverrides();
+ foreach ( $overrides as $prefKey => $value ) {
+ $user->setOption( $prefKey, $value );
+ }
+ $user->saveSettings();
+ EchoEvent::create( [
+ 'type' => 'welcome',
+ 'agent' => $user,
+ // Welcome notification is sent to the agent
+ 'extra' => [
+ 'notifyAgent' => true
+ ]
+ ] );
+ }
+
+ $seenTime = EchoSeenTime::newFromUser( $user );
+
+ // Set seen time to UNIX epoch, so initially all notifications are unseen.
+ $seenTime->setTime( wfTimestamp( TS_MW, 1 ), 'all' );
return true;
}
@@ -501,10 +695,14 @@ class EchoHooks {
* @param string[] $add strings corresponding to groups added
* @param string[] $remove strings corresponding to groups removed
* @param User|bool $performer
+ * @param string|bool $reason Reason given by the user changing the rights
+ * @param array $oldUGMs
+ * @param array $newUGMs
*
* @return bool
*/
- public static function onUserGroupsChanged( $user, $add, $remove, $performer ) {
+ public static function onUserGroupsChanged( $user, $add, $remove, $performer,
+ $reason, array $oldUGMs = [], array $newUGMs = [] ) {
if ( !$performer ) {
// TODO: Implement support for autopromotion
return true;
@@ -520,34 +718,64 @@ class EchoHooks {
return true;
}
- if ( $add || $remove ) {
+ // If any old groups are in $add, those groups are having their expiry
+ // changed, not actually being added
+ $expiryChanged = [];
+ $reallyAdded = [];
+ foreach ( $add as $group ) {
+ if ( isset( $oldUGMs[$group] ) ) {
+ $expiryChanged[] = $group;
+ } else {
+ $reallyAdded[] = $group;
+ }
+ }
+
+ if ( $expiryChanged ) {
+ // use a separate notification for these, so the notification text doesn't
+ // get too long
+ EchoEvent::create(
+ [
+ 'type' => 'user-rights',
+ 'extra' => [
+ 'user' => $user->getID(),
+ 'expiry-changed' => $expiryChanged,
+ 'reason' => $reason,
+ ],
+ 'agent' => $performer,
+ ]
+ );
+ }
+
+ if ( $reallyAdded || $remove ) {
EchoEvent::create(
- array(
+ [
'type' => 'user-rights',
- 'title' => Title::newMainPage(),
- 'extra' => array(
+ 'extra' => [
'user' => $user->getID(),
- 'add' => $add,
- 'remove' => $remove
- ),
+ 'add' => $reallyAdded,
+ 'remove' => $remove,
+ 'reason' => $reason,
+ ],
'agent' => $performer,
- )
+ ]
);
}
+
return true;
}
/**
* Handler for LinksUpdateAfterInsert hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/LinksUpdateAfterInsert
- * @param $linksUpdate LinksUpdate
- * @param $table string
- * @param $insertions array
+ * @param LinksUpdate $linksUpdate
+ * @param string $table
+ * @param array $insertions
* @return bool
*/
public static function onLinksUpdateAfterInsert( $linksUpdate, $table, $insertions ) {
- global $wgRequest, $wgUser;
+ global $wgRequest;
+ // FIXME: This doesn't work in 1.27+
// Rollback or undo should not trigger link notification
// @Todo Implement a better solution so it doesn't depend on the checking of
// a specific set of request variables
@@ -561,11 +789,20 @@ class EchoHooks {
// 3. non-transcluding pages &&
// 4. non-redirect pages
if ( $table !== 'pagelinks' || !MWNamespace::isContent( $linksUpdate->mTitle->getNamespace() )
- || !$linksUpdate->mRecursive || $linksUpdate->mTitle->isRedirect() )
- {
+ || !$linksUpdate->mRecursive || $linksUpdate->mTitle->isRedirect()
+ ) {
return true;
}
+ if ( is_callable( [ $linksUpdate, 'getTriggeringUser' ] ) ) {
+ $user = $linksUpdate->getTriggeringUser();
+ } else {
+ global $wgUser;
+ $user = $wgUser;
+ }
+
+ $revid = $linksUpdate->getRevision() ? $linksUpdate->getRevision()->getId() : null;
+
// link notification is boundless as you can include infinite number of links in a page
// db insert is expensive, limit it to a reasonable amount, we can increase this limit
// once the storage is on Redis
@@ -579,14 +816,17 @@ class EchoHooks {
continue;
}
- EchoEvent::create( array(
+ $linkFromPageId = $linksUpdate->mTitle->getArticleId();
+ EchoEvent::create( [
'type' => 'page-linked',
'title' => $title,
- 'agent' => $wgUser,
- 'extra' => array(
- 'link-from-page-id' => $linksUpdate->mTitle->getArticleId(),
- )
- ) );
+ 'agent' => $user,
+ 'extra' => [
+ 'target-page' => $linkFromPageId,
+ 'link-from-page-id' => $linkFromPageId,
+ 'revid' => $revid,
+ ]
+ ] );
$max--;
}
if ( $max < 0 ) {
@@ -600,19 +840,19 @@ class EchoHooks {
/**
* Handler for BeforePageDisplay hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay
- * @param $out OutputPage object
- * @param $skin Skin being used.
+ * @param OutputPage $out OutputPage object
+ * @param Skin $skin Skin being used.
* @return bool true in all cases
*/
- static function beforePageDisplay( $out, $skin ) {
+ public static function beforePageDisplay( $out, $skin ) {
if ( $out->getUser()->isLoggedIn() && $skin->getSkinName() !== 'minerva' ) {
// Load the module for the Notifications flyout
- $out->addModules( array( 'ext.echo.init' ) );
+ $out->addModules( [ 'ext.echo.init' ] );
// Load the styles for the Notifications badge
- $out->addModuleStyles( array(
+ $out->addModuleStyles( [
'ext.echo.styles.badge',
'ext.echo.badgeicons'
- ) );
+ ] );
}
return true;
@@ -622,112 +862,187 @@ class EchoHooks {
* Handler for PersonalUrls hook.
* Add a "Notifications" item to the user toolbar ('personal URLs').
* @see http://www.mediawiki.org/wiki/Manual:Hooks/PersonalUrls
- * @param &$personal_urls Array of URLs to append to.
- * @param &$title Title of page being visited.
+ * @param array &$personal_urls Array of URLs to append to.
+ * @param Title &$title Title of page being visited.
* @param SkinTemplate $sk
* @return bool true in all cases
*/
- static function onPersonalUrls( &$personal_urls, &$title, $sk ) {
- global $wgEchoNewMsgAlert;
+ public static function onPersonalUrls( &$personal_urls, &$title, $sk ) {
+ global $wgEchoNewMsgAlert, $wgEchoShowFooterNotice;
$user = $sk->getUser();
if ( $user->isAnon() ) {
return true;
}
- // Attempt to mark a notification as read when visiting a page,
- // ideally this should be deferred to end of request and update
- // the notification count accordingly
- // @Fixme - Find a better place to put this code
+ // Attempt to mark a notification as read when visiting a page
+ $subtractAlerts = 0;
+ $subtractMessages = 0;
+ $eventIds = [];
if ( $title->getArticleID() ) {
- $mapper = new EchoTargetPageMapper();
- $targetPages = $mapper->fetchByUserPageId( $user, $title->getArticleID() );
- if ( $targetPages ) {
- $eventIds = array_keys( $targetPages );
+ $eventMapper = new EchoEventMapper();
+ $events = $eventMapper->fetchUnreadByUserAndPage( $user, $title->getArticleID() );
+
+ if ( $events ) {
+ /* @var EchoEvent $event */
+ foreach ( $events as $event ) {
+ if ( $event->getSection() === EchoAttributeManager::MESSAGE ) {
+ $subtractMessages++;
+ } else {
+ // ALERT
+ $subtractAlerts++;
+ }
+ $eventIds[] = $event->getId();
+ }
+ }
+ }
+
+ // Attempt to mark as read the event IDs in the ?markasread= parameter, if present
+ $markAsReadIds = explode( '|', $sk->getOutput()->getRequest()->getText( 'markasread' ) );
+ if ( $markAsReadIds ) {
+ // gather the IDs that we didn't already find with target_pages
+ $eventsToMarkAsRead = [];
+ foreach ( $markAsReadIds as $markAsReadId ) {
+ $markAsReadId = intval( $markAsReadId );
+ if ( $markAsReadId !== 0 && !in_array( $markAsReadId, $eventIds ) ) {
+ $eventsToMarkAsRead[] = $markAsReadId;
+ }
+ }
+
+ if ( $eventsToMarkAsRead ) {
+ // fetch the notifications to adjust the counters
+ $notifMapper = new EchoNotificationMapper();
+ $notifs = $notifMapper->fetchByUserEvents( $user, $eventsToMarkAsRead );
+
+ foreach ( $notifs as $notif ) {
+ if ( !$notif->getReadTimestamp() ) {
+ if ( $notif->getEvent()->getSection() === EchoAttributeManager::MESSAGE ) {
+ $subtractMessages++;
+ } else {
+ $subtractAlerts++;
+ }
+ $eventIds[] = intval( $notif->getEvent()->getId() );
+ }
+ }
+ }
+ }
+
+ if ( $eventIds ) {
+ DeferredUpdates::addCallableUpdate( function () use ( $user, $eventIds ) {
$notifUser = MWEchoNotifUser::newFromUser( $user );
$notifUser->markRead( $eventIds );
- }
+ } );
}
// Add a "My notifications" item to personal URLs
$notifUser = MWEchoNotifUser::newFromUser( $user );
- $msgCount = $notifUser->getMessageCount();
- $alertCount = $notifUser->getAlertCount();
+ $msgCount = $notifUser->getMessageCount() - $subtractMessages;
+ $alertCount = $notifUser->getAlertCount() - $subtractAlerts;
+ // But make sure we never show a negative number (T130853)
+ $msgCount = max( 0, $msgCount );
+ $alertCount = max( 0, $alertCount );
$msgNotificationTimestamp = $notifUser->getLastUnreadMessageTime();
$alertNotificationTimestamp = $notifUser->getLastUnreadAlertTime();
- $seenAlertTime = EchoSeenTime::newFromUser( $user )->getTime( 'alert' );
- $seenMsgTime = EchoSeenTime::newFromUser( $user )->getTime( 'message' );
+ $seenTime = EchoSeenTime::newFromUser( $user );
+ if ( $title->isSpecial( 'Notifications' ) ) {
+ // If this is the Special:Notifications page, seenTime to now
+ $seenTime->setTime( wfTimestamp( TS_MW ), EchoAttributeManager::ALL );
+ }
+ $seenAlertTime = $seenTime->getTime( 'alert', TS_ISO_8601 );
+ $seenMsgTime = $seenTime->getTime( 'message', TS_ISO_8601 );
- $sk->getOutput()->addJsConfigVars( 'wgEchoSeenTime', array(
+ $sk->getOutput()->addJsConfigVars( 'wgEchoSeenTime', [
'alert' => $seenAlertTime,
- 'message' => $seenMsgTime
- ) );
+ 'notice' => $seenMsgTime,
+ ] );
+
+ if (
+ $wgEchoShowFooterNotice &&
+ !$user->getOption( 'echo-dismiss-special-page-invitation' )
+ ) {
+ $sk->getOutput()->addJsConfigVars( 'wgEchoShowSpecialPageInvitation', true );
+ }
- $msgText = EchoNotificationController::formatNotificationCount( $msgCount );
- $alertText = EchoNotificationController::formatNotificationCount( $alertCount );
+ $msgFormattedCount = EchoNotificationController::formatNotificationCount( $msgCount );
+ $alertFormattedCount = EchoNotificationController::formatNotificationCount( $alertCount );
+
+ $msgText = wfMessage( 'echo-notification-notice', $msgCount );
+ $alertText = wfMessage( 'echo-notification-alert', $alertCount );
$url = SpecialPage::getTitleFor( 'Notifications' )->getLocalURL();
// HACK: inverted icons only work in the "MediaWiki" OOUI theme
// Avoid flashes in skins that don't use it (T111821)
$sk->getOutput()->setupOOUI( strtolower( $sk->getSkinName() ), $sk->getOutput()->getLanguage()->getDir() );
- $oouiImageClass = get_class( OOUI\Theme::singleton() ) === 'OOUI\\MediaWikiTheme'
- ? 'oo-ui-image-invert'
- : '';
- $msgLinkClasses = array( "mw-echo-notifications-badge mw-echo-notification-badge-nojs $oouiImageClass oo-ui-iconElement oo-ui-iconElement-icon oo-ui-icon-speechBubble" );
- $alertLinkClasses = array( "mw-echo-notifications-badge mw-echo-notification-badge-nojs $oouiImageClass oo-ui-iconElement oo-ui-iconElement-icon" );
+ $msgLinkClasses = [ "mw-echo-notifications-badge", "mw-echo-notification-badge-nojs" ];
+ $alertLinkClasses = [ "mw-echo-notifications-badge", "mw-echo-notification-badge-nojs" ];
$hasUnseen = false;
if (
$msgCount != 0 && // no unread notifications
$msgNotificationTimestamp !== false && // should already always be false if count === 0
- ( $seenMsgTime === null || $seenMsgTime < $msgNotificationTimestamp->getTimestamp( TS_MW ) ) // there are no unseen notifications
+ ( $seenMsgTime === null || $seenMsgTime < $msgNotificationTimestamp->getTimestamp( TS_ISO_8601 ) ) // there are no unseen notifications
) {
$msgLinkClasses[] = 'mw-echo-unseen-notifications';
$hasUnseen = true;
+ } elseif ( $msgCount === 0 ) {
+ $msgLinkClasses[] = 'mw-echo-notifications-badge-all-read';
+ }
+
+ if ( $msgCount > MWEchoNotifUser::MAX_BADGE_COUNT ) {
+ $msgLinkClasses[] = 'mw-echo-notifications-badge-long-label';
}
- $alertIcon = "bell";
if (
$alertCount != 0 && // no unread notifications
$alertNotificationTimestamp !== false && // should already always be false if count === 0
- ( $seenAlertTime === null || $seenAlertTime < $alertNotificationTimestamp->getTimestamp( TS_MW ) ) // all notifications have already been seen
+ ( $seenAlertTime === null || $seenAlertTime < $alertNotificationTimestamp->getTimestamp( TS_ISO_8601 ) ) // all notifications have already been seen
) {
$alertLinkClasses[] = 'mw-echo-unseen-notifications';
- $alertIcon = "bellOn";
$hasUnseen = true;
+ } elseif ( $alertCount === 0 ) {
+ $alertLinkClasses[] = 'mw-echo-notifications-badge-all-read';
}
- $alertLinkClasses[] = 'oo-ui-icon-' . $alertIcon;
- $alertLink = array(
+ if ( $alertCount > MWEchoNotifUser::MAX_BADGE_COUNT ) {
+ $alertLinkClasses[] = 'mw-echo-notifications-badge-long-label';
+ }
+
+ $alertLink = [
'href' => $url,
'text' => $alertText,
'active' => ( $url == $title->getLocalUrl() ),
'class' => $alertLinkClasses,
- );
+ 'data' => [
+ 'counter-num' => $alertCount,
+ 'counter-text' => $alertFormattedCount,
+ ],
+ ];
- $insertUrls = array(
+ $insertUrls = [
'notifications-alert' => $alertLink,
- );
+ ];
- if ( $notifUser->hasMessages() ) {
- $msgLink = array(
- 'href' => $url,
- 'text' => $msgText,
- 'active' => ( $url == $title->getLocalUrl() ),
- 'class' => $msgLinkClasses,
- );
+ $msgLink = [
+ 'href' => $url,
+ 'text' => $msgText,
+ 'active' => ( $url == $title->getLocalUrl() ),
+ 'class' => $msgLinkClasses,
+ 'data' => [
+ 'counter-num' => $msgCount,
+ 'counter-text' => $msgFormattedCount,
+ ],
+ ];
- $insertUrls['notifications-message'] = $msgLink;
- }
+ $insertUrls['notifications-notice'] = $msgLink;
$personal_urls = wfArrayInsertAfter( $personal_urls, $insertUrls, 'userpage' );
if ( $hasUnseen ) {
// Record that the user is going to see an indicator that they have unread notifications
- RequestContext::getMain()->getStats()->increment( 'MediaWiki.echo.unseen' );
+ MediaWikiServices::getInstance()->getStatsdDataFactory()->increment( 'echo.unseen' );
}
// If the user has new messages, display a talk page alert
@@ -736,13 +1051,15 @@ class EchoHooks {
// * Enabled in user preferences
// * User actually has new messages
// * User is not viewing their user talk page, as user_newtalk
- // will not have been cleared yet. (bug T107655).
+ // will not have been cleared yet. (bug T107655).
if ( $wgEchoNewMsgAlert && $user->getOption( 'echo-show-alert' )
- && $user->getNewtalk() && !$user->getTalkPage()->equals( $title )
+ && $user->getNewtalk() && !$user->getTalkPage()->equals( $title )
) {
- $personal_urls['mytalk']['text'] = $sk->msg( 'echo-new-messages' )->text();
- $personal_urls['mytalk']['class'] = array( 'mw-echo-alert' );
- $sk->getOutput()->addModuleStyles( 'ext.echo.styles.alert' );
+ if ( Hooks::run( 'BeforeDisplayOrangeAlert', [ $user, $title ] ) ) {
+ $personal_urls['mytalk']['text'] = $sk->msg( 'echo-new-messages' )->text();
+ $personal_urls['mytalk']['class'] = [ 'mw-echo-alert' ];
+ $sk->getOutput()->addModuleStyles( 'ext.echo.styles.alert' );
+ }
}
return true;
@@ -751,11 +1068,11 @@ class EchoHooks {
/**
* Handler for AbortTalkPageEmailNotification hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/AbortTalkPageEmailNotification
- * @param $targetUser User
- * @param $title Title
+ * @param User $targetUser
+ * @param Title $title
* @return bool
*/
- static function onAbortTalkPageEmailNotification( $targetUser, $title ) {
+ public static function onAbortTalkPageEmailNotification( $targetUser, $title ) {
global $wgEchoNotifications;
// Send legacy talk page email notification if
@@ -773,12 +1090,12 @@ class EchoHooks {
/**
* Handler for AbortWatchlistEmailNotification hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/AbortWatchlistEmailNotification
- * @param $targetUser User
- * @param $title Title
- * @param $emailNotification EmailNotification The email notification object that sends non-echo notifications
+ * @param User $targetUser
+ * @param Title $title
+ * @param EmailNotification $emailNotification The email notification object that sends non-echo notifications
* @return bool
*/
- static function onSendWatchlistEmailNotification( $targetUser, $title, $emailNotification ) {
+ public static function onSendWatchlistEmailNotification( $targetUser, $title, $emailNotification ) {
// If a user is watching his/her own talk page, do not send talk page watchlist
// email notification if the user is receiving Echo talk page notification
if ( $title->isTalkPage() && $targetUser->getTalkPage()->equals( $title ) ) {
@@ -789,6 +1106,7 @@ class EchoHooks {
return false;
}
}
+
// Proceed to send watchlist email notification
return true;
}
@@ -796,62 +1114,45 @@ class EchoHooks {
/**
* Handler for MakeGlobalVariablesScript hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/MakeGlobalVariablesScript
- * @param &$vars array Variables to be added into the output
- * @param $outputPage OutputPage instance calling the hook
+ * @param array &$vars Variables to be added into the output
+ * @param OutputPage $outputPage OutputPage instance calling the hook
* @return bool true in all cases
*/
public static function makeGlobalVariablesScript( &$vars, OutputPage $outputPage ) {
- global $wgEchoHelpPage, $wgEchoMaxNotificationCount, $wgEchoConfig;
+ global $wgEchoEventLoggingSchemas, $wgEchoEventLoggingVersion;
$user = $outputPage->getUser();
// Provide info for the Overlay
- if ( ! $user->isAnon() ) {
- $vars['wgEchoOverlayConfiguration'] = array(
- 'notification-count' => MWEchoNotifUser::newFromUser( $user )->getFormattedNotificationCount(),
- 'max-notification-count' => $wgEchoMaxNotificationCount,
- );
- $vars['wgEchoHelpPage'] = $wgEchoHelpPage;
- $vars['wgEchoConfig'] = $wgEchoConfig;
+ if ( $user->isLoggedIn() ) {
+ $vars['wgEchoEventLoggingSchemas'] = $wgEchoEventLoggingSchemas;
+ $vars['wgEchoEventLoggingVersion'] = $wgEchoEventLoggingVersion;
} elseif (
$outputPage->getTitle()->equals( SpecialPage::getTitleFor( 'JavaScriptTest', 'qunit' ) ) ||
// Also if running from /plain or /export
$outputPage->getTitle()->isSubpageOf( SpecialPage::getTitleFor( 'JavaScriptTest', 'qunit' ) )
) {
// For testing purposes
- $vars['wgEchoConfig'] = array(
- 'eventlogging' => array(
- 'EchoInteraction' => array(),
- ),
- );
+ $vars['wgEchoEventLoggingSchemas'] = [
+ 'EchoInteraction' => [],
+ ];
}
return true;
}
- /**
- * Handler for UnitTestsList hook.
- * @see http://www.mediawiki.org/wiki/Manual:Hooks/UnitTestsList
- * @param &$files Array of unit test files
- * @return bool true in all cases
- */
- static function getUnitTests( &$files ) {
- // @codeCoverageIgnoreStart
- $directoryIterator = new RecursiveDirectoryIterator( __DIR__ . '/tests/phpunit/' );
-
- /**
- * @var SplFileInfo $fileInfo
- */
- $ourFiles = array();
- foreach ( new RecursiveIteratorIterator( $directoryIterator ) as $fileInfo ) {
- if ( substr( $fileInfo->getFilename(), -8 ) === 'Test.php' ) {
- $ourFiles[] = $fileInfo->getPathname();
+ public static function onOutputPageCheckLastModified( array &$modifiedTimes, OutputPage $out ) {
+ $user = $out->getUser();
+ if ( $user->isLoggedIn() ) {
+ $notifUser = MWEchoNotifUser::newFromUser( $user );
+ $lastUpdate = $notifUser->getGlobalUpdateTime();
+ if ( $lastUpdate !== false ) {
+ $modifiedTimes['notifications-global'] = $lastUpdate;
}
- }
- $files = array_merge( $files, $ourFiles );
- return true;
- // @codeCoverageIgnoreEnd
+ $modifiedTimes['notifications-seen-alert'] = EchoSeenTime::newFromUser( $user )->getTime( 'alert' );
+ $modifiedTimes['notifications-seen-message'] = EchoSeenTime::newFromUser( $user )->getTime( 'message' );
+ }
}
/**
@@ -860,16 +1161,16 @@ class EchoHooks {
* ArticleEditUpdateNewTalk hook since we still want the user_newtalk data
* to be updated and availble to client-side tools and the API.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/GetNewMessagesAlert
- * @param &$newMessagesAlert String An alert that the user has new messages
+ * @param string &$newMessagesAlert An alert that the user has new messages
* or an empty string if the user does not (empty by default)
- * @param $newtalks Array This will be empty if the user has no new messages
+ * @param array $newtalks This will be empty if the user has no new messages
* or an Array containing links and revisions if there are new messages
- * @param $user User The user who is loading the page
- * @param $out Output object
+ * @param User $user The user who is loading the page
+ * @param OutputPage $out Output object
* @return bool Should return false to prevent the new messages alert (OBOD)
* or true to allow the new messages alert
*/
- static function abortNewMessagesAlert( &$newMessagesAlert, $newtalks, $user, $out ) {
+ public static function abortNewMessagesAlert( &$newMessagesAlert, $newtalks, $user, $out ) {
global $wgEchoNotifications;
// If the user has the notifications flyout turned on and is receiving
@@ -888,30 +1189,30 @@ class EchoHooks {
/**
* Handler for ArticleRollbackComplete hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/ArticleRollbackComplete
- * @param $page WikiPage The article that was edited
- * @param $agent User The user who did the rollback
- * @param $newRevision Revision The revision the page was reverted back to
- * @param $oldRevision Revision The revision of the top edit that was reverted
+ * @param WikiPage $page The article that was edited
+ * @param User $agent The user who did the rollback
+ * @param Revision $newRevision The revision the page was reverted back to
+ * @param Revision $oldRevision The revision of the top edit that was reverted
* @return bool true in all cases
*/
- static function onRollbackComplete( $page, $agent, $newRevision, $oldRevision ) {
+ public static function onRollbackComplete( $page, $agent, $newRevision, $oldRevision ) {
$victimId = $oldRevision->getUser();
if (
$victimId && // No notifications for anonymous users
!$oldRevision->getContent()->equals( $newRevision->getContent() ) // No notifications for null rollbacks
) {
- EchoEvent::create( array(
+ EchoEvent::create( [
'type' => 'reverted',
'title' => $page->getTitle(),
- 'extra' => array(
+ 'extra' => [
'revid' => $page->getRevision()->getId(),
'reverted-user-id' => $victimId,
'reverted-revision-id' => $oldRevision->getId(),
'method' => 'rollback',
- ),
+ ],
'agent' => $agent,
- ) );
+ ] );
}
return true;
@@ -920,41 +1221,45 @@ class EchoHooks {
/**
* Handler for UserSaveSettings hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/UserSaveSettings
- * @param $user User whose settings were saved
+ * @param User $user whose settings were saved
* @return bool true in all cases
*/
- static function onUserSaveSettings( $user ) {
+ public static function onUserSaveSettings( $user ) {
// Extensions like AbuseFilter might create an account, but
// the tables we need might not exist. Bug 57335
if ( !defined( 'MW_UPDATER' ) ) {
// Reset the notification count since it may have changed due to user
// option changes. This covers both explicit changes in the preferences
// and changes made through the options API (since both call this hook).
- MWEchoNotifUser::newFromUser( $user )->resetNotificationCount();
+ DeferredUpdates::addCallableUpdate( function () use ( $user ) {
+ MWEchoNotifUser::newFromUser( $user )->resetNotificationCount();
+ } );
}
+
return true;
}
/**
* Handler for UserLoadOptions hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/UserLoadOptions
- * @param $user User whose options were loaded
- * @param $options Options can be modified
+ * @param User $user User whose options were loaded
+ * @param array &$options Options can be modified
* @return bool true in all cases
*/
public static function onUserLoadOptions( $user, &$options ) {
// Use existing enotifusertalkpages option for echo-subscriptions-email-edit-user-talk
if ( isset( $options['enotifusertalkpages'] ) ) {
- $options['echo-subscriptions-email-edit-user-talk'] = $options['enotifusertalkpages'];
+ $options['echo-subscriptions-email-edit-user-talk'] = $options['enotifusertalkpages'];
}
+
return true;
}
/**
* Handler for UserSaveOptions hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/UserSaveOptions
- * @param $user User whose options are being saved
- * @param $options Options can be modified
+ * @param User $user User whose options are being saved
+ * @param array &$options Options can be modified
* @return bool true in all cases
*/
public static function onUserSaveOptions( $user, &$options ) {
@@ -971,12 +1276,12 @@ class EchoHooks {
/**
* Handler for UserClearNewTalkNotification hook.
* @see http://www.mediawiki.org/wiki/Manual:Hooks/UserClearNewTalkNotification
- * @param $user User whose talk page notification should be marked as read
+ * @param User $user User whose talk page notification should be marked as read
* @return bool true in all cases
*/
public static function onUserClearNewTalkNotification( User $user ) {
if ( !$user->isAnon() ) {
- DeferredUpdates::addCallableUpdate( function() use ( $user ) {
+ DeferredUpdates::addCallableUpdate( function () use ( $user ) {
MWEchoNotifUser::newFromUser( $user )->clearTalkNotification();
} );
}
@@ -987,46 +1292,130 @@ class EchoHooks {
/**
* Handler for ParserTestTables hook, makes sure that Echo's tables are present during tests
* @see http://www.mediawiki.org/wiki/Manual:Hooks/UserClearNewTalkNotification
- * @param array $tables List of DB tables to be used for parser tests
+ * @param array &$tables List of DB tables to be used for parser tests
* @return bool true in all cases
*/
public static function onParserTestTables( &$tables ) {
$tables[] = 'echo_event';
$tables[] = 'echo_notification';
$tables[] = 'echo_email_batch';
+
+ return true;
+ }
+
+ /**
+ * Handler for EmailUserComplete hook.
+ * @see https://www.mediawiki.org/wiki/Manual:Hooks/EmailUserComplete
+ * @param MailAddress $address Adress of receiving user
+ * @param MailAddress $from Adress of sending user
+ * @param string $subject Subject of the mail
+ * @param string $text Text of the mail
+ * @return bool true in all cases
+ */
+ public static function onEmailUserComplete( $address, $from, $subject, $text ) {
+ global $wgContLang;
+
+ if ( $from->name === $address->name ) {
+ // nothing to notify
+ return true;
+ }
+ $userTo = User::newFromName( $address->name );
+ $userFrom = User::newFromName( $from->name );
+
+ $autoSubject = wfMessage( 'defemailsubject', $from->name )->inContentLanguage()->text();
+ if ( $subject === $autoSubject ) {
+ $autoFooter = "\n\n-- \n" . wfMessage( 'emailuserfooter', $from->name, $address->name )->inContentLanguage()->text();
+ $textWithoutFooter = preg_replace( '/' . preg_quote( $autoFooter, '/' ) . '$/', '', $text );
+ $preview = $wgContLang->truncate( $textWithoutFooter, 125 );
+ } else {
+ $preview = $subject;
+ }
+
+ EchoEvent::create( [
+ 'type' => 'emailuser',
+ 'extra' => [
+ 'to-user-id' => $userTo->getId(),
+ 'preview' => $preview,
+ ],
+ 'agent' => $userFrom,
+ ] );
+
return true;
}
/**
* For integration with the UserMerge extension.
*
- * @param array $updateFields
+ * @param array &$updateFields
* @return bool
*/
public static function onUserMergeAccountFields( &$updateFields ) {
// array( tableName, idField, textField )
$dbw = MWEchoDbFactory::newFromDefault()->getEchoDb( DB_MASTER );
- $updateFields[] = array( 'echo_event', 'event_agent_id', 'db' => $dbw );
- $updateFields[] = array( 'echo_notification', 'notification_user', 'db' => $dbw, 'options' => array( 'IGNORE' ) );
- $updateFields[] = array( 'echo_email_batch', 'eeb_user_id', 'db' => $dbw, 'options' => array( 'IGNORE' ) );
- $updateFields[] = array( 'echo_target_page', 'etp_user', 'db' => $dbw, 'options' => array( 'IGNORE' ) );
+ $updateFields[] = [ 'echo_event', 'event_agent_id', 'db' => $dbw ];
+ $updateFields[] = [ 'echo_notification', 'notification_user', 'db' => $dbw, 'options' => [ 'IGNORE' ] ];
+ $updateFields[] = [ 'echo_email_batch', 'eeb_user_id', 'db' => $dbw, 'options' => [ 'IGNORE' ] ];
return true;
}
public static function onMergeAccountFromTo( User &$oldUser, User &$newUser ) {
- MWEchoNotifUser::newFromUser( $oldUser )->resetNotificationCount( DB_MASTER );
- MWEchoNotifUser::newFromUser( $newUser )->resetNotificationCount( DB_MASTER );
+ DeferredUpdates::addCallableUpdate( function () use ( $oldUser, $newUser ) {
+ MWEchoNotifUser::newFromUser( $oldUser )->resetNotificationCount( DB_MASTER );
+ if ( !$newUser->isAnon() ) {
+ MWEchoNotifUser::newFromUser( $newUser )->resetNotificationCount( DB_MASTER );
+ }
+ } );
return true;
}
public static function onUserMergeAccountDeleteTables( &$tables ) {
$dbw = MWEchoDbFactory::newFromDefault()->getEchoDb( DB_MASTER );
- $tables['echo_notification'] = array( 'notification_user', 'db' => $dbw );
- $tables['echo_email_batch'] = array( 'eeb_user_id', 'db' => $dbw );
- $tables['echo_target_page'] = array( 'etp_user', 'db' => $dbw );
+ $tables['echo_notification'] = [ 'notification_user', 'db' => $dbw ];
+ $tables['echo_email_batch'] = [ 'eeb_user_id', 'db' => $dbw ];
+
+ return true;
+ }
+ /**
+ * Sets custom login message for redirect from notification page
+ *
+ * @param array &$messages
+ * @return bool
+ */
+ public static function onLoginFormValidErrorMessages( &$messages ) {
+ $messages[] = 'echo-notification-loginrequired';
return true;
}
+
+ public static function onResourceLoaderGetConfigVars( &$vars ) {
+ global $wgEchoFooterNoticeURL;
+
+ $vars['wgEchoMaxNotificationCount'] = MWEchoNotifUser::MAX_BADGE_COUNT;
+ $vars['wgEchoFooterNoticeURL'] = $wgEchoFooterNoticeURL;
+
+ return true;
+ }
+
+ public static function onArticleDeleteComplete( WikiPage &$article, User &$user, $reason, $articleId, Content $content = null, LogEntry $logEntry ) {
+ \DeferredUpdates::addCallableUpdate( function () use ( $articleId ) {
+ $eventMapper = new EchoEventMapper();
+ $eventIds = $eventMapper->fetchIdsByPage( $articleId );
+ EchoModerationController::moderate( $eventIds, true );
+ } );
+ return true;
+ }
+
+ public static function onArticleUndelete( Title $title, $create, $comment, $oldPageId ) {
+ if ( $create ) {
+ \DeferredUpdates::addCallableUpdate( function () use ( $oldPageId ) {
+ $eventMapper = new EchoEventMapper();
+ $eventIds = $eventMapper->fetchIdsByPage( $oldPageId );
+ EchoModerationController::moderate( $eventIds, false );
+ } );
+ }
+ return true;
+ }
+
}
diff --git a/Echo/Makefile b/Echo/Makefile
index 67f6c723..a12d6f45 100644
--- a/Echo/Makefile
+++ b/Echo/Makefile
@@ -16,7 +16,7 @@ remotes:
gerrit: remotes
@scripts/remotes/gerrit.py --project 'mediawiki/extensions/Echo' --gtscore -1 --ignorepattern 'WIP'
-# interactively make sure en.json and qqq.json have all the
+# interactively make sure en.json and qqq.json have all the
# same message keys
message: remotes
@python scripts/remotes/message.py
@@ -56,16 +56,12 @@ csscss: gems
###
# Testing
###
-test: phpunit qunit
+test: phpunit
# Run the projects phpunit tests
phpunit:
cd ${MW_INSTALL_PATH}/tests/phpunit && ${PHP} phpunit.php --configuration ${MW_INSTALL_PATH}/extensions/Echo/tests/echo.suite.xml --group=Echo
-# Run the projects qunit tests
-qunit:
- @scripts/qunit.sh
-
###
# Update this repository for csscss dependencies
###
diff --git a/Echo/Notifier.php b/Echo/Notifier.php
deleted file mode 100644
index fd45b1b6..00000000
--- a/Echo/Notifier.php
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-
-// @todo Fill in
-class EchoNotifier {
- /**
- * Record an EchoNotification for an EchoEvent
- * Currently used for web-based notifications.
- *
- * @param $user User to notify.
- * @param $event EchoEvent to notify about.
- */
- public static function notifyWithNotification( $user, $event ) {
- // Only create the notification if the user wants to recieve that type
- // of notification and they are eligible to recieve it. See bug 47664.
- $attributeManager = EchoAttributeManager::newFromGlobalVars();
- $userWebNotifications = $attributeManager->getUserEnabledEvents( $user, 'web' );
- if ( !in_array( $event->getType(), $userWebNotifications ) ) {
- return;
- }
-
- EchoNotification::create( array( 'user' => $user, 'event' => $event ) );
-
- MWEchoEventLogging::logSchemaEcho( $user, $event, 'web' );
- }
-
- /**
- * Send a Notification to a user by email
- *
- * @param $user User to notify.
- * @param $event EchoEvent to notify about.
- * @return bool
- */
- public static function notifyWithEmail( $user, $event ) {
- global $wgEnableEmail;
-
- if ( !$wgEnableEmail ) {
- return false;
- }
- // No valid email address or email notification
- if ( !$user->isEmailConfirmed() || $user->getOption( 'echo-email-frequency' ) < 0 ) {
- return false;
- }
-
- // Final check on whether to send email for this user & event
- if ( !Hooks::run( 'EchoAbortEmailNotification', array( $user, $event ) ) ) {
- return false;
- }
-
- $attributeManager = EchoAttributeManager::newFromGlobalVars();
- $userEmailNotifications = $attributeManager->getUserEnabledEvents( $user, 'email' );
- // See if the user wants to receive emails for this category or the user is eligible to receive this email
- if ( in_array( $event->getType(), $userEmailNotifications ) ) {
- global $wgEchoEnableEmailBatch, $wgEchoNotifications, $wgNotificationSender, $wgNotificationReplyName, $wgEchoBundleEmailInterval;
-
- $priority = $attributeManager->getNotificationPriority( $event->getType() );
-
- $bundleString = $bundleHash = '';
-
- // We should have bundling for email digest as long as either web or email bundling is on, for example, talk page
- // email bundling is off, but if a user decides to receive email digest, we should bundle those messages
- if ( !empty( $wgEchoNotifications[$event->getType()]['bundle']['web'] ) || !empty( $wgEchoNotifications[$event->getType()]['bundle']['email'] ) ) {
- Hooks::run( 'EchoGetBundleRules', array( $event, &$bundleString ) );
- }
- if ( $bundleString ) {
- $bundleHash = md5( $bundleString );
- }
-
- MWEchoEventLogging::logSchemaEcho( $user, $event, 'email' );
-
- // email digest notification ( weekly or daily )
- if ( $wgEchoEnableEmailBatch && $user->getOption( 'echo-email-frequency' ) > 0 ) {
- // always create a unique event hash for those events don't support bundling
- // this is mainly for group by
- if ( !$bundleHash ) {
- $bundleHash = md5( $event->getType() . '-' . $event->getId() );
- }
- MWEchoEmailBatch::addToQueue( $user->getId(), $event->getId(), $priority, $bundleHash );
- return true;
- }
-
- $addedToQueue = false;
-
- // only send bundle email if email bundling is on
- if ( $wgEchoBundleEmailInterval && $bundleHash && !empty( $wgEchoNotifications[$event->getType()]['bundle']['email'] ) ) {
- $bundler = MWEchoEmailBundler::newFromUserHash( $user, $bundleHash );
- if ( $bundler ) {
- $addedToQueue = $bundler->addToEmailBatch( $event->getId(), $priority );
- }
- }
-
- // send single notification if the email wasn't added to queue for bundling
- if ( !$addedToQueue ) {
- // instant email notification
- $toAddress = MailAddress::newFromUser( $user );
- $fromAddress = new MailAddress( $wgNotificationSender, EchoHooks::getNotificationSenderName() );
- $replyAddress = new MailAddress( $wgNotificationSender, $wgNotificationReplyName );
- // Since we are sending a single email, should set the bundle hash to null
- // if it is set with a value from somewhere else
- $event->setBundleHash( null );
- $email = EchoNotificationController::formatNotification( $event, $user, 'email', 'email' );
- $subject = $email['subject'];
- $body = $email['body'];
- $options = array( 'replyTo' => $replyAddress );
-
- UserMailer::send( $toAddress, $fromAddress, $subject, $body, $options );
- MWEchoEventLogging::logSchemaEchoMail( $user, 'single' );
- }
- }
-
- return true;
- }
-}
diff --git a/Echo/RELEASE_NOTES b/Echo/RELEASE_NOTES
index c6d0fcf4..ac617476 100644
--- a/Echo/RELEASE_NOTES
+++ b/Echo/RELEASE_NOTES
@@ -1,3 +1,21 @@
+July, 2016
+-----------
+* BREAKING CHANGE: In the cross-wiki summary in ApiEchoNotifications,
+ 'ts' is now ISO 8601.
+* BREAKING CHANGE: JS variables: wgEchoSeenTime now uses ISO 8601, and
+ alert/notice instead of alert/message. wgEchoInitialNotifCount has
+ been removed.
+* ApiEchoMarkSeen is moving to ISO 8601. Adjust your client; see API
+ documentation.
+
+April, 2016
+-----------
+* BREAKING CHANGE: $wgEchoDefaultNotificationTypes has been split into
+ three variables. See Echo.php for documentation:
+** $wgDefaultNotifyTypeAvailability
+** $wgNotifyTypeAvailabilityByCategory
+** $wgEchoNotifications[$notificationType]['notify-type-availability']
+
March, 2015
-----------
diff --git a/Echo/Rakefile b/Echo/Rakefile
index 6eef1216..76835007 100644
--- a/Echo/Rakefile
+++ b/Echo/Rakefile
@@ -8,7 +8,15 @@ RuboCop::RakeTask.new(:rubocop) do |task|
task.options = ['-c', '.rubocop.yml']
end
+require 'mediawiki_selenium/rake_task'
+MediawikiSelenium::RakeTask.new
+
+require 'rspec/core/rake_task'
+RSpec::Core::RakeTask.new do |t|
+ t.rspec_opts = 'tests/rspec/'
+end
+
task default: [:test]
desc 'Run all build/tests commands (CI entry point)'
-task test: [:rubocop]
+task test: [:rubocop, :spec, :selenium]
diff --git a/Echo/Resources.php b/Echo/Resources.php
deleted file mode 100644
index 9604c681..00000000
--- a/Echo/Resources.php
+++ /dev/null
@@ -1,184 +0,0 @@
-<?php
-/**
- * MediaWiki Extension: Echo
- * http://www.mediawiki.org/wiki/Extension:Echo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * This program is distributed WITHOUT ANY WARRANTY.
- */
-
-/**
- *
- * @file
- * @ingroup Extensions
- * @author Andrew Garrett, Benny Situ, Ryan Kaldari, Erik Bernhardson
- * @licence MIT License
- */
-
-$echoResourceTemplate = array(
- 'localBasePath' => __DIR__ . '/modules',
- 'remoteExtPath' => 'Echo/modules',
-);
-
-$wgResourceModules += array(
- 'ext.echo.ui' => $echoResourceTemplate + array(
- 'scripts' => array(
- 'ooui/mw.echo.ui.js',
- 'ooui/mw.echo.ui.PlaceholderOptionWidget.js',
- 'ooui/mw.echo.ui.NotificationsWidget.js',
- 'ooui/mw.echo.ui.NotificationOptionWidget.js',
- 'ooui/mw.echo.ui.BadgeLinkWidget.js',
- 'ooui/mw.echo.ui.NotificationBadgeWidget.js'
- ),
- 'styles' => array(
- 'ooui/styles/mw.echo.ui.NotificationsWidget.less',
- 'ooui/styles/mw.echo.ui.NotificationOptionWidget.less',
- 'ooui/styles/mw.echo.ui.NotificationBadgeWidget.less'
- ),
- 'skinStyles' => array(
- 'monobook' => array(
- 'ooui/styles/mw.echo.ui.NotificationsWidget.monobook.less',
- 'ooui/styles/mw.echo.ui.NotificationBadgeWidget.monobook.less'
- ),
- 'modern' => array(
- 'ooui/styles/mw.echo.ui.NotificationOptionWidget.modern.less',
- 'ooui/styles/mw.echo.ui.NotificationBadgeWidget.modern.less'
- )
- ),
- 'dependencies' => array(
- 'ext.echo.styles.badge',
- 'ext.echo.styles.notifications',
- 'ext.echo.dm',
- 'oojs-ui',
- 'ext.echo.logger',
- 'mediawiki.api',
- 'mediawiki.jqueryMsg',
- 'mediawiki.language',
- ),
- 'messages' => array(
- 'echo-overlay-link',
- 'echo-mark-all-as-read',
- 'echo-more-info',
- 'echo-feedback',
- 'echo-notification-alert',
- 'echo-notification-message',
- 'echo-notification-alert-text-only',
- 'echo-notification-message-text-only',
- 'echo-email-batch-bullet',
- 'echo-api-failure',
- 'echo-notification-placeholder',
- 'tooltip-pt-notifications-alert',
- 'tooltip-pt-notifications-message',
- 'mypreferences'
- ),
- 'targets' => array( 'desktop' ),
- ),
- 'ext.echo.dm' => $echoResourceTemplate + array(
- 'scripts' => array(
- 'viewmodel/mw.echo.dm.js',
- 'viewmodel/mw.echo.dm.NotificationItem.js',
- 'viewmodel/mw.echo.dm.List.js',
- 'viewmodel/mw.echo.dm.NotificationList.js',
- 'viewmodel/mw.echo.dm.NotificationsModel.js',
- ),
- 'dependencies' => array(
- 'oojs'
- ),
- 'targets' => array( 'desktop', 'mobile' ),
- ),
- 'ext.echo.base' => array(
- // This is a dummy module for backwards compatibility.
- // Most extensions that require ext.echo.base actually need
- // the logger. They will have to be adjusted to use the new
- // logger functionality, however.
- //
- // This module is mainly here to make sure other extensions
- // that rely on ext.echo.base don't explode, and that CI lets
- // us merge this while fixing the main extensions that require
- // to be changed due to the new structure.
- 'targets' => array( 'desktop', 'mobile' ),
- 'dependencies' => array( 'ext.echo.logger' )
- ),
- // ext.echo.logger is registered in EchoHooks::onResourceLoaderRegisterModules
- 'ext.echo.init' => $echoResourceTemplate + array(
- 'scripts' => array(
- 'ext.echo.init.js',
- ),
- 'targets' => array( 'desktop' ),
- ),
- // Base no-js styles
- 'ext.echo.styles.badge' => $echoResourceTemplate + array(
- 'position' => 'top',
- 'styles' => array(
- 'nojs/mw.echo.badge.less',
- ),
- 'targets' => array( 'desktop', 'mobile' ),
- ),
- // Styles for individual notification entries in flyout and Special:Notifications
- 'ext.echo.styles.notifications' => $echoResourceTemplate + array(
- 'position' => 'top',
- 'styles' => array(
- 'nojs/mw.echo.notifications.less'
- ),
- 'targets' => array( 'desktop', 'mobile' ),
- ),
- 'ext.echo.styles.alert' => $echoResourceTemplate + array(
- 'position' => 'top',
- 'styles' => array(
- 'nojs/mw.echo.alert.less',
- ),
- 'skinStyles' => array(
- 'monobook' => array(
- 'nojs/mw.echo.alert.monobook.less',
- ),
- 'modern' => array(
- 'nojs/mw.echo.alert.modern.less',
- ),
- ),
- 'targets' => array( 'desktop', 'mobile' ),
- ),
- 'ext.echo.styles.special' => $echoResourceTemplate + array(
- 'position' => 'top',
- 'styles' => array(
- 'nojs/mw.echo.special.less',
- ),
- 'targets' => array( 'desktop', 'mobile' ),
- ),
- 'ext.echo.special' => $echoResourceTemplate + array(
- 'scripts' => array(
- 'special/ext.echo.special.js',
- ),
- 'dependencies' => array(
- 'mediawiki.ui.button',
- 'mediawiki.api',
- 'ext.echo.ui',
- ),
- 'messages' => array(
- 'echo-load-more-error',
- 'echo-more-info',
- 'echo-feedback',
- ),
- ),
-
- // HACK: OOUI has an icon pack for these, but it's unhelpfully large and we don't
- // want to load more as render-blocking CSS than we have to (T112401)
- 'ext.echo.badgeicons' => $echoResourceTemplate + array(
- 'class' => 'ResourceLoaderOOUIImageModule',
- 'position' => 'top',
- 'name' => 'badgeicons',
- 'rootPath' => 'icons',
- 'selectorWithoutVariant' => '.oo-ui-icon-{name}',
- 'selectorWithVariant' => '.oo-ui-image-{variant}.oo-ui-icon-{name}',
- ),
-);
-
-unset( $echoResourceTemplate );
diff --git a/Echo/autoload.php b/Echo/autoload.php
deleted file mode 100644
index 41d95f40..00000000
--- a/Echo/autoload.php
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php
-// This file is generated by scripts/gen-autoload.php, do not adjust manually
-// @codingStandardsIgnoreFile
-global $wgAutoloadClasses;
-
-$wgAutoloadClasses += array(
- 'ApiEchoMarkRead' => __DIR__ . '/includes/api/ApiEchoMarkRead.php',
- 'ApiEchoMarkReadTest' => __DIR__ . '/tests/phpunit/api/ApiEchoMarkReadTest.php',
- 'ApiEchoMarkSeen' => __DIR__ . '/includes/api/ApiEchoMarkSeen.php',
- 'ApiEchoNotifications' => __DIR__ . '/includes/api/ApiEchoNotifications.php',
- 'ApiEchoNotificationsTest' => __DIR__ . '/tests/phpunit/api/ApiEchoNotificationsTest.php',
- 'BatchRowUpdateTest' => __DIR__ . '/tests/phpunit/BatchRowUpdateTest.php',
- 'CallbackFilterIterator' => __DIR__ . '/includes/iterator/CallbackFilterIterator.php',
- 'ContainmentSetTest' => __DIR__ . '/tests/phpunit/ContainmentSetTest.php',
- 'EchoAbstractEntity' => __DIR__ . '/includes/model/AbstractEntity.php',
- 'EchoAbstractMapper' => __DIR__ . '/includes/mapper/AbstractMapper.php',
- 'EchoAbstractMapperStub' => __DIR__ . '/tests/phpunit/mapper/AbstractMapperTest.php',
- 'EchoAbstractMapperTest' => __DIR__ . '/tests/phpunit/mapper/AbstractMapperTest.php',
- 'EchoArrayList' => __DIR__ . '/includes/ContainmentSet.php',
- 'EchoAttributeManager' => __DIR__ . '/includes/AttributeManager.php',
- 'EchoAttributeManagerTest' => __DIR__ . '/tests/phpunit/AttributeManagerTest.php',
- 'EchoBasicFormatter' => __DIR__ . '/includes/formatters/BasicFormatter.php',
- 'EchoBatchRowIterator' => __DIR__ . '/includes/BatchRowUpdate.php',
- 'EchoBatchRowUpdate' => __DIR__ . '/includes/BatchRowUpdate.php',
- 'EchoBatchRowWriter' => __DIR__ . '/includes/BatchRowUpdate.php',
- 'EchoCachedList' => __DIR__ . '/includes/ContainmentSet.php',
- 'EchoCallbackIterator' => __DIR__ . '/includes/iterator/CallbackIterator.php',
- 'EchoCatchableFatalErrorException' => __DIR__ . '/includes/exception/CatchableFatalErrorException.php',
- 'EchoCommentFormatter' => __DIR__ . '/includes/formatters/CommentFormatter.php',
- 'EchoContainmentList' => __DIR__ . '/includes/ContainmentSet.php',
- 'EchoContainmentSet' => __DIR__ . '/includes/ContainmentSet.php',
- 'EchoDataOutputFormatter' => __DIR__ . '/includes/DataOutputFormatter.php',
- 'EchoDeferredMarkAsReadUpdate' => __DIR__ . '/includes/DeferredMarkAsReadUpdate.php',
- 'EchoDiffGroup' => __DIR__ . '/includes/DiffParser.php',
- 'EchoDiffParser' => __DIR__ . '/includes/DiffParser.php',
- 'EchoDiffParserTest' => __DIR__ . '/tests/phpunit/DiffParserTest.php',
- 'EchoDiscussionParser' => __DIR__ . '/includes/DiscussionParser.php',
- 'EchoDiscussionParserTest' => __DIR__ . '/tests/phpunit/DiscussionParserTest.php',
- 'EchoEditFormatter' => __DIR__ . '/includes/formatters/EditFormatter.php',
- 'EchoEditUserTalkFormatter' => __DIR__ . '/includes/formatters/EditUserTalkFormatter.php',
- 'EchoEmailDecorator' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoEmailDigest' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoEmailFormatter' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoEmailFormatterTest' => __DIR__ . '/tests/phpunit/EmailFormatterTest.php',
- 'EchoEmailMode' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoEmailSingle' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoEvent' => __DIR__ . '/includes/model/Event.php',
- 'EchoEventMapper' => __DIR__ . '/includes/mapper/EventMapper.php',
- 'EchoEventMapperTest' => __DIR__ . '/tests/phpunit/mapper/EventMapperTest.php',
- 'EchoExecuteFirstArgumentStub' => __DIR__ . '/tests/phpunit/mapper/NotificationMapperTest.php',
- 'EchoFilteredSequentialIterator' => __DIR__ . '/includes/iterator/FilteredSequentialIterator.php',
- 'EchoHTMLEmailDecorator' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoHTMLEmailFormatter' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoHooks' => __DIR__ . '/Hooks.php',
- 'EchoIteratorDecorator' => __DIR__ . '/includes/iterator/IteratorDecorator.php',
- 'EchoLocalCache' => __DIR__ . '/includes/cache/LocalCache.php',
- 'EchoMentionFormatter' => __DIR__ . '/includes/formatters/MentionFormatter.php',
- 'EchoMultipleIterator' => __DIR__ . '/includes/iterator/MultipleIterator.php',
- 'EchoNotRecursiveIterator' => __DIR__ . '/includes/iterator/NotRecursiveIterator.php',
- 'EchoNotification' => __DIR__ . '/includes/model/Notification.php',
- 'EchoNotificationController' => __DIR__ . '/includes/controller/NotificationController.php',
- 'EchoNotificationDeleteJob' => __DIR__ . '/includes/jobs/NotificationDeleteJob.php',
- 'EchoNotificationFormatter' => __DIR__ . '/includes/formatters/NotificationFormatter.php',
- 'EchoNotificationFormatterTest' => __DIR__ . '/tests/phpunit/formatters/NotificationFormatterTest.php',
- 'EchoNotificationJob' => __DIR__ . '/includes/jobs/NotificationJob.php',
- 'EchoNotificationMapper' => __DIR__ . '/includes/mapper/NotificationMapper.php',
- 'EchoNotificationMapperTest' => __DIR__ . '/tests/phpunit/mapper/NotificationMapperTest.php',
- 'EchoNotificationTest' => __DIR__ . '/tests/phpunit/model/NotificationTest.php',
- 'EchoNotifier' => __DIR__ . '/Notifier.php',
- 'EchoOnWikiList' => __DIR__ . '/includes/ContainmentSet.php',
- 'EchoPageLinkFormatter' => __DIR__ . '/includes/formatters/PageLinkFormatter.php',
- 'EchoRevisionLocalCache' => __DIR__ . '/includes/cache/RevisionLocalCache.php',
- 'EchoRowUpdateGenerator' => __DIR__ . '/includes/BatchRowUpdate.php',
- 'EchoSeenTime' => __DIR__ . '/includes/SeenTime.php',
- 'EchoSuppressionRowUpdateGenerator' => __DIR__ . '/includes/schemaUpdate.php',
- 'EchoTalkPageFunctionalTest' => __DIR__ . '/tests/phpunit/TalkPageFunctionalTest.php',
- 'EchoTargetPage' => __DIR__ . '/includes/model/TargetPage.php',
- 'EchoTargetPageMapper' => __DIR__ . '/includes/mapper/TargetPageMapper.php',
- 'EchoTargetPageMapperTest' => __DIR__ . '/tests/phpunit/mapper/TargetPageMapperTest.php',
- 'EchoTargetPageTest' => __DIR__ . '/tests/phpunit/model/TargetPageTest.php',
- 'EchoTextEmailDecorator' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoTextEmailFormatter' => __DIR__ . '/includes/EmailFormatter.php',
- 'EchoTitleLocalCache' => __DIR__ . '/includes/cache/TitleLocalCache.php',
- 'EchoTitleLocalCacheTest' => __DIR__ . '/tests/phpunit/cache/TitleLocalCacheTest.php',
- 'EchoUserLocator' => __DIR__ . '/includes/UserLocator.php',
- 'EchoUserLocatorTest' => __DIR__ . '/tests/phpunit/UserLocatorTest.php',
- 'EchoUserNotificationGateway' => __DIR__ . '/includes/gateway/UserNotificationGateway.php',
- 'EchoUserNotificationGatewayTest' => __DIR__ . '/tests/phpunit/gateway/UserNotificationGatewayTest.php',
- 'EchoUserRightsFormatter' => __DIR__ . '/includes/formatters/UserRightsFormatter.php',
- 'FilteredSequentialIteratorTest' => __DIR__ . '/tests/phpunit/iterator/FilteredSequentialIteratorTest.php',
- 'MWEchoDbFactory' => __DIR__ . '/includes/EchoDbFactory.php',
- 'MWEchoDbFactoryTest' => __DIR__ . '/tests/phpunit/EchoDbFactoryTest.php',
- 'MWEchoEmailBatch' => __DIR__ . '/includes/EmailBatch.php',
- 'MWEchoEmailBundler' => __DIR__ . '/includes/EmailBundler.php',
- 'MWEchoEventLogging' => __DIR__ . '/includes/EventLogging.php',
- 'MWEchoNotifUser' => __DIR__ . '/includes/NotifUser.php',
- 'MWEchoNotifUserTest' => __DIR__ . '/tests/phpunit/NotifUserTest.php',
- 'MWEchoNotificationEmailBundleJob' => __DIR__ . '/includes/jobs/NotificationEmailBundleJob.php',
- 'NotificationControllerTest' => __DIR__ . '/tests/phpunit/controller/NotificationControllerTest.php',
- 'NotificationsTest' => __DIR__ . '/tests/NotificationsTest.php',
- 'SpecialNotifications' => __DIR__ . '/includes/special/SpecialNotifications.php',
- 'SuppressionMaintenanceTest' => __DIR__ . '/tests/phpunit/maintenance/SupressionMaintenanceTest.php',
-);
diff --git a/Echo/composer.json b/Echo/composer.json
index f2883f7a..78987234 100644
--- a/Echo/composer.json
+++ b/Echo/composer.json
@@ -1,10 +1,16 @@
{
"require-dev": {
- "jakub-onderka/php-parallel-lint": "0.9"
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "mediawiki/mediawiki-codesniffer": "0.12.0",
+ "jakub-onderka/php-console-highlighter": "0.3.2"
},
"scripts": {
"test": [
- "parallel-lint . --exclude vendor"
+ "parallel-lint . --exclude vendor --exclude node_modules",
+ "phpcs -p -s"
+ ],
+ "fix": [
+ "phpcbf"
]
}
}
diff --git a/Echo/composer.lock b/Echo/composer.lock
deleted file mode 100644
index 3028006d..00000000
--- a/Echo/composer.lock
+++ /dev/null
@@ -1,65 +0,0 @@
-{
- "_readme": [
- "This file locks the dependencies of your project to a known state",
- "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
- "This file is @generated automatically"
- ],
- "hash": "7216bf235ddb64e32a151e98e36d8775",
- "packages": [],
- "packages-dev": [
- {
- "name": "jakub-onderka/php-parallel-lint",
- "version": "v0.9",
- "source": {
- "type": "git",
- "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git",
- "reference": "1b693fb455201cacf595163c92bfb1adfa2158d8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/1b693fb455201cacf595163c92bfb1adfa2158d8",
- "reference": "1b693fb455201cacf595163c92bfb1adfa2158d8",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "jakub-onderka/php-console-highlighter": "~0.3",
- "nette/tester": "~1.3"
- },
- "suggest": {
- "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet"
- },
- "bin": [
- "parallel-lint"
- ],
- "type": "library",
- "autoload": {
- "classmap": [
- "./"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD"
- ],
- "authors": [
- {
- "name": "Jakub Onderka",
- "email": "jakub.onderka@gmail.com"
- }
- ],
- "description": "This tool check syntax of PHP files about 20x faster than serial check.",
- "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint",
- "time": "2015-06-16 10:17:07"
- }
- ],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": [],
- "prefer-stable": false,
- "prefer-lowest": false,
- "platform": [],
- "platform-dev": []
-}
diff --git a/Echo/db_patches/echo_unread_wikis.sql b/Echo/db_patches/echo_unread_wikis.sql
new file mode 100644
index 00000000..7af9a589
--- /dev/null
+++ b/Echo/db_patches/echo_unread_wikis.sql
@@ -0,0 +1,18 @@
+CREATE TABLE /*_*/echo_unread_wikis (
+ # Primary key
+ euw_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ # Global user id
+ euw_user INT UNSIGNED NOT NULL,
+ # Name of wiki
+ euw_wiki VARCHAR(30) NOT NULL,
+ # unread alerts count on that wiki
+ euw_alerts INT UNSIGNED NOT NULL,
+ # Timestamp of the most recent unread alert
+ euw_alerts_ts BINARY(14) NOT NULL,
+ # unread messages count on that wiki
+ euw_messages INT UNSIGNED NOT NULL,
+ # Timestamp of the most recent unread message
+ euw_messages_ts BINARY(14) NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE UNIQUE INDEX /*i*/echo_unread_wikis_user_wiki ON /*_*/echo_unread_wikis (euw_user,euw_wiki);
diff --git a/Echo/db_patches/patch-add-echo_event-event_deleted.sql b/Echo/db_patches/patch-add-echo_event-event_deleted.sql
new file mode 100644
index 00000000..3d8d61fd
--- /dev/null
+++ b/Echo/db_patches/patch-add-echo_event-event_deleted.sql
@@ -0,0 +1 @@
+ALTER TABLE /*_*/echo_event ADD COLUMN event_deleted tinyint unsigned NOT NULL DEFAULT 0;
diff --git a/Echo/db_patches/patch-add-event_page_id-index.sql b/Echo/db_patches/patch-add-event_page_id-index.sql
new file mode 100644
index 00000000..b3b99eeb
--- /dev/null
+++ b/Echo/db_patches/patch-add-event_page_id-index.sql
@@ -0,0 +1 @@
+CREATE INDEX /*i*/echo_event_page_id ON /*_*/echo_event (event_page_id);
diff --git a/Echo/db_patches/patch-add-notification_event-index.sql b/Echo/db_patches/patch-add-notification_event-index.sql
new file mode 100644
index 00000000..1243b804
--- /dev/null
+++ b/Echo/db_patches/patch-add-notification_event-index.sql
@@ -0,0 +1 @@
+CREATE INDEX /*i*/echo_notification_event ON /*_*/echo_notification (notification_event);
diff --git a/Echo/db_patches/patch-add-page_event-index.sql b/Echo/db_patches/patch-add-page_event-index.sql
new file mode 100644
index 00000000..d656fd0f
--- /dev/null
+++ b/Echo/db_patches/patch-add-page_event-index.sql
@@ -0,0 +1 @@
+CREATE INDEX /*i*/echo_target_page_page_event ON /*_*/echo_target_page (etp_page, etp_event);
diff --git a/Echo/db_patches/patch-add-user_read_timestamp-index.sql b/Echo/db_patches/patch-add-user_read_timestamp-index.sql
new file mode 100644
index 00000000..012e4371
--- /dev/null
+++ b/Echo/db_patches/patch-add-user_read_timestamp-index.sql
@@ -0,0 +1 @@
+CREATE INDEX /*i*/echo_notification_user_read_timestamp ON /*_*/echo_notification (notification_user, notification_read_timestamp);
diff --git a/Echo/db_patches/patch-drop-echo_target_page-etp_user.sql b/Echo/db_patches/patch-drop-echo_target_page-etp_user.sql
new file mode 100644
index 00000000..dad413cb
--- /dev/null
+++ b/Echo/db_patches/patch-drop-echo_target_page-etp_user.sql
@@ -0,0 +1,11 @@
+-- Patch to drop unused etp_user
+
+-- Drop indexes depending on etp_user
+DROP INDEX /*i*/echo_target_page_user_event ON /*_*/echo_target_page;
+DROP INDEX /*i*/echo_target_page_user_page_event ON /*_*/echo_target_page;
+
+-- Drop etp_user column
+ALTER TABLE /*_*/echo_target_page DROP etp_user;
+
+-- Add index on etp_event
+CREATE INDEX /*i*/echo_target_page_event ON /*_*/echo_target_page (etp_event);
diff --git a/Echo/db_patches/patch-drop-echo_target_page-etp_user.sqlite.sql b/Echo/db_patches/patch-drop-echo_target_page-etp_user.sqlite.sql
new file mode 100644
index 00000000..17aec6e2
--- /dev/null
+++ b/Echo/db_patches/patch-drop-echo_target_page-etp_user.sqlite.sql
@@ -0,0 +1,26 @@
+-- Patch to drop unused etp_user
+
+-- give current table temporary name
+ALTER TABLE /*_*/echo_target_page RENAME TO /*_*/temp_echo_target_page;
+
+-- recreate table without etp_user
+CREATE TABLE /*_*/echo_target_page (
+ etp_id int unsigned not null primary key auto_increment,
+ etp_page int unsigned not null default 0,
+ etp_event int unsigned not null default 0
+) /*$wgDBTableOptions*/;
+
+-- copy over old data into new table
+INSERT INTO /*_*/echo_target_page
+ (etp_page, etp_event)
+SELECT DISTINCT
+ etp_page, etp_event
+FROM
+ /*_*/temp_echo_target_page;
+
+-- drop the original table
+DROP TABLE /*_*/temp_echo_target_page;
+
+-- recreate indexes
+CREATE INDEX /*i*/echo_target_page_event ON /*_*/echo_target_page (etp_event);
+CREATE INDEX /*i*/echo_target_page_page_event ON /*_*/echo_target_page (etp_page, etp_event);
diff --git a/Echo/db_patches/patch-notification-pk.sql b/Echo/db_patches/patch-notification-pk.sql
new file mode 100644
index 00000000..9072d1f3
--- /dev/null
+++ b/Echo/db_patches/patch-notification-pk.sql
@@ -0,0 +1,3 @@
+DROP INDEX /*i*/user_event ON /*_*/echo_notification;
+
+ALTER TABLE /*_*/echo_notification ADD PRIMARY KEY (notification_user, notification_event);
diff --git a/Echo/echo.sql b/Echo/echo.sql
index 910203ad..9736c923 100644
--- a/Echo/echo.sql
+++ b/Echo/echo.sql
@@ -9,10 +9,12 @@ CREATE TABLE /*_*/echo_event (
event_page_namespace int unsigned null,
event_page_title varchar(255) binary null,
event_extra BLOB NULL,
- event_page_id int unsigned null
+ event_page_id int unsigned null,
+ event_deleted tinyint unsigned not null default 0
) /*$wgDBTableOptions*/;
CREATE INDEX /*i*/echo_event_type ON /*_*/echo_event (event_type);
+CREATE INDEX /*i*/echo_event_page_id ON /*_*/echo_event (event_page_id);
CREATE TABLE /*_*/echo_notification (
notification_event int unsigned not null,
@@ -21,15 +23,17 @@ CREATE TABLE /*_*/echo_notification (
notification_read_timestamp binary(14) null,
notification_bundle_base boolean not null default 1,
notification_bundle_hash varchar(32) binary not null, -- The hash for bundling notifications regardless of timestamp
- notification_bundle_display_hash varchar(32) binary not null -- The hash for displaying bundle notifications with regard to timestamp, this is is a subset of notification_bundle_hash
+ notification_bundle_display_hash varchar(32) binary not null, -- The hash for displaying bundle notifications with regard to timestamp, this is is a subset of notification_bundle_hash
+ PRIMARY KEY (notification_user, notification_event)
) /*$wgDBTableOptions*/;
CREATE INDEX /*i*/echo_user_timestamp ON /*_*/echo_notification (notification_user,notification_timestamp);
-CREATE UNIQUE INDEX /*i*/user_event ON /*_*/echo_notification (notification_user,notification_event);
CREATE INDEX /*i*/echo_notification_user_base_read_timestamp ON /*_*/echo_notification (notification_user, notification_bundle_base, notification_read_timestamp);
CREATE INDEX /*i*/echo_notification_user_base_timestamp ON /*_*/echo_notification (notification_user, notification_bundle_base, notification_timestamp, notification_event);
CREATE INDEX /*i*/echo_notification_user_hash_timestamp ON /*_*/echo_notification (notification_user, notification_bundle_hash, notification_timestamp);
CREATE INDEX /*i*/echo_notification_user_hash_base_timestamp ON /*_*/echo_notification (notification_user, notification_bundle_display_hash, notification_bundle_base, notification_timestamp);
+CREATE INDEX /*i*/echo_notification_event ON /*_*/echo_notification (notification_event);
+CREATE INDEX /*i*/echo_notification_user_read_timestamp ON /*_*/echo_notification (notification_user, notification_read_timestamp);
CREATE TABLE /*_*/echo_email_batch (
eeb_id int unsigned not null primary key auto_increment,
@@ -44,10 +48,9 @@ CREATE INDEX /*i*/echo_email_batch_user_hash_priority ON /*_*/echo_email_batch (
CREATE TABLE /*_*/echo_target_page (
etp_id int unsigned not null primary key auto_increment,
- etp_user int unsigned not null default 0,
etp_page int unsigned not null default 0,
etp_event int unsigned not null default 0
) /*$wgDBTableOptions*/;
-CREATE INDEX /*i*/echo_target_page_user_event ON /*_*/echo_target_page (etp_user, etp_event);
-CREATE INDEX /*i*/echo_target_page_user_page_event ON /*_*/echo_target_page (etp_user, etp_page, etp_event);
+CREATE INDEX /*i*/echo_target_page_event ON /*_*/echo_target_page (etp_event);
+CREATE INDEX /*i*/echo_target_page_page_event ON /*_*/echo_target_page (etp_page, etp_event);
diff --git a/Echo/extension.json b/Echo/extension.json
new file mode 100644
index 00000000..39606dbc
--- /dev/null
+++ b/Echo/extension.json
@@ -0,0 +1,1024 @@
+{
+ "name": "Echo",
+ "author": [
+ "Andrew Garrett",
+ "Ryan Kaldari",
+ "Benny Situ",
+ "Luke Welling",
+ "Kunal Mehta",
+ "Moriel Schottlender",
+ "Jon Robson"
+ ],
+ "url": "https://www.mediawiki.org/wiki/Extension:Echo",
+ "descriptionmsg": "echo-desc",
+ "license-name": "MIT",
+ "type": "specialpage",
+ "requires": {
+ "MediaWiki": ">= 1.29.0"
+ },
+ "callback": "EchoHooks::registerExtension",
+ "APIMetaModules": {
+ "notifications": "ApiEchoNotifications",
+ "unreadnotificationpages": "ApiEchoUnreadNotificationPages"
+ },
+ "APIModules": {
+ "echomarkread": "ApiEchoMarkRead",
+ "echomarkseen": "ApiEchoMarkSeen",
+ "echoarticlereminder": "ApiEchoArticleReminder"
+ },
+ "DefaultUserOptions": {
+ "echo-show-alert": true,
+ "echo-email-frequency": 0,
+ "echo-dismiss-special-page-invitation": 0
+ },
+ "ExtensionFunctions": [
+ "EchoHooks::initEchoExtension"
+ ],
+ "JobClasses": {
+ "EchoNotificationJob": "EchoNotificationJob",
+ "EchoNotificationDeleteJob": "EchoNotificationDeleteJob"
+ },
+ "SpecialPages": {
+ "Notifications": "SpecialNotifications",
+ "DisplayNotificationsConfiguration": "SpecialDisplayNotificationsConfiguration",
+ "NotificationsMarkRead": "SpecialNotificationsMarkRead"
+ },
+ "MessagesDirs": {
+ "Echo": [
+ "i18n",
+ "i18n/api"
+ ]
+ },
+ "ExtensionMessagesFiles": {
+ "EchoAliases": "Echo.alias.php"
+ },
+ "ResourceModules": {
+ "ext.echo.ui.desktop": {
+ "scripts": [
+ "ui/mw.echo.ui.BadgeLinkWidget.js",
+ "ui/mw.echo.ui.NotificationBadgeWidget.js"
+ ],
+ "styles": [
+ "styles/mw.echo.ui.NotificationBadgeWidget.less"
+ ],
+ "skinStyles": {
+ "monobook": [
+ "styles/mw.echo.ui.NotificationBadgeWidget.monobook.less"
+ ],
+ "modern": [
+ "styles/mw.echo.ui.NotificationBadgeWidget.modern.less"
+ ]
+ },
+ "dependencies": [
+ "ext.echo.ui",
+ "ext.echo.styles.badge",
+ "mediawiki.util",
+ "mediawiki.api.options"
+ ],
+ "messages": [
+ "echo-popup-footer-special-page-invitation",
+ "echo-popup-footer-special-page-invitation-link"
+ ],
+ "targets": [
+ "desktop"
+ ]
+ },
+ "ext.echo.ui": {
+ "scripts": [
+ "ui/mw.echo.ui.js",
+ "ui/mw.echo.ui.SortedListWidget.js",
+ "ui/mw.echo.ui.SubGroupListWidget.js",
+ "ui/mw.echo.ui.NotificationsListWidget.js",
+ "ui/mw.echo.ui.PlaceholderItemWidget.js",
+ "ui/mw.echo.ui.ToggleReadCircleButtonWidget.js",
+ "ui/mw.echo.ui.NotificationItemWidget.js",
+ "ui/mw.echo.ui.SingleNotificationItemWidget.js",
+ "ui/mw.echo.ui.CrossWikiNotificationItemWidget.js",
+ "ui/mw.echo.ui.BundleNotificationItemWidget.js",
+ "ui/mw.echo.ui.ClonedNotificationItemWidget.js",
+ "ui/mw.echo.ui.ActionMenuPopupWidget.js",
+ "ui/mw.echo.ui.MenuItemWidget.js",
+ "ui/mw.echo.ui.FooterNoticeWidget.js",
+ "ui/mw.echo.ui.NotificationsWrapper.js",
+ "ui/mw.echo.ui.ConfirmationPopupWidget.js",
+ "ext.echo.moment-hack.js"
+ ],
+ "styles": [
+ "styles/mw.echo.ui.overlay.less",
+ "styles/mw.echo.ui.NotificationItemWidget.less",
+ "styles/mw.echo.ui.ToggleReadCircleButtonWidget.less",
+ "styles/mw.echo.ui.CrossWikiNotificationItemWidget.less",
+ "styles/mw.echo.ui.NotificationsListWidget.less",
+ "styles/mw.echo.ui.PlaceholderItemWidget.less",
+ "styles/mw.echo.ui.SubGroupListWidget.less",
+ "styles/mw.echo.ui.ActionMenuPopupWidget.less",
+ "styles/mw.echo.ui.MenuItemWidget.less",
+ "styles/mw.echo.ui.FooterNoticeWidget.less",
+ "styles/mw.echo.ui.NotificationsWrapper.less",
+ "styles/mw.echo.ui.ConfirmationPopupWidget.less"
+ ],
+ "skinStyles": {
+ "monobook": [
+ "styles/mw.echo.ui.NotificationsListWidget.monobook.less",
+ "styles/mw.echo.ui.overlay.monobook.less"
+ ],
+ "modern": [
+ "styles/mw.echo.ui.NotificationItemWidget.modern.less"
+ ],
+ "vector": [
+ "styles/mw.echo.ui.overlay.vector.less"
+ ],
+ "minerva": [
+ "styles/mw.echo.ui.overlay.minerva.less"
+ ]
+ },
+ "dependencies": [
+ "ext.echo.logger",
+ "ext.echo.styles.notifications",
+ "ext.echo.controller",
+ "ext.echo.secondaryicons",
+ "oojs-ui-core",
+ "oojs-ui-widgets",
+ "moment",
+ "mediawiki.jqueryMsg",
+ "mediawiki.language",
+ "mediawiki.Title",
+ "mediawiki.notify",
+ "oojs-ui.styles.icons-user",
+ "oojs-ui.styles.icons-alerts",
+ "oojs-ui.styles.icons-content",
+ "oojs-ui.styles.icons-interactions",
+ "oojs-ui.styles.icons-moderation",
+ "oojs-ui.styles.icons-movement"
+ ],
+ "messages": [
+ "echo-badge-count",
+ "echo-overlay-link",
+ "echo-mark-all-as-read",
+ "echo-mark-wiki-as-read",
+ "echo-more-info",
+ "echo-feedback",
+ "echo-notification-alert",
+ "echo-notification-notice",
+ "echo-notification-loginrequired",
+ "echo-notification-popup-loginrequired",
+ "notification-link-text-expand-all",
+ "notification-link-text-collapse-all",
+ "notification-link-text-expand-alert-count",
+ "notification-link-text-expand-notice-count",
+ "notification-link-text-expand-all-count",
+ "notification-timestamp-ago-seconds",
+ "notification-timestamp-ago-minutes",
+ "notification-timestamp-ago-hours",
+ "notification-timestamp-ago-days",
+ "notification-timestamp-ago-months",
+ "notification-timestamp-ago-years",
+ "notification-timestamp-today",
+ "notification-timestamp-yesterday",
+ "echo-notification-markasread",
+ "echo-notification-markasunread",
+ "echo-notification-markasread-tooltip",
+ "echo-notification-more-options-tooltip",
+ "echo-notification-alert-text-only",
+ "echo-notification-notice-text-only",
+ "echo-email-batch-bullet",
+ "echo-notification-placeholder",
+ "tooltip-pt-notifications-alert",
+ "tooltip-pt-notifications-notice",
+ "mytalk",
+ "mypreferences",
+ "sunday",
+ "monday",
+ "tuesday",
+ "wednesday",
+ "thursday",
+ "friday",
+ "saturday"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.dm": {
+ "scripts": [
+ "mw.echo.js",
+ "model/mw.echo.dm.js",
+ "model/mw.echo.dm.SourcePagesModel.js",
+ "model/mw.echo.dm.PaginationModel.js",
+ "model/mw.echo.dm.FiltersModel.js",
+ "model/mw.echo.dm.SeenTimeModel.js",
+ "model/mw.echo.dm.ModelManager.js",
+ "model/mw.echo.dm.SortedList.js",
+ "model/mw.echo.dm.NotificationItem.js",
+ "model/mw.echo.dm.CrossWikiNotificationItem.js",
+ "model/mw.echo.dm.BundleNotificationItem.js",
+ "model/mw.echo.dm.NotificationsList.js",
+ "model/mw.echo.dm.NotificationGroupsList.js",
+ "model/mw.echo.dm.UnreadNotificationCounter.js"
+ ],
+ "dependencies": [
+ "oojs",
+ "ext.echo.api",
+ "moment"
+ ],
+ "messages": [
+ "echo-api-failure",
+ "echo-notification-loginrequired",
+ "echo-api-failure-cross-wiki"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.api": {
+ "scripts": [
+ "api/mw.echo.api.js",
+ "api/mw.echo.api.PromisePrioritizer.js",
+ "api/mw.echo.api.EchoApi.js",
+ "api/mw.echo.api.APIHandler.js",
+ "api/mw.echo.api.LocalAPIHandler.js",
+ "api/mw.echo.api.ForeignAPIHandler.js",
+ "api/mw.echo.api.NetworkHandler.js"
+ ],
+ "dependencies": [
+ "mediawiki.api",
+ "mediawiki.ForeignApi",
+ "oojs"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.controller": {
+ "scripts": [
+ "controller/mw.echo.Controller.js"
+ ],
+ "dependencies": [
+ "oojs",
+ "ext.echo.api",
+ "ext.echo.dm"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.base": {
+ "targets": [
+ "desktop",
+ "mobile"
+ ],
+ "dependencies": [
+ "ext.echo.logger"
+ ]
+ },
+ "ext.echo.init": {
+ "scripts": [
+ "ext.echo.init.js"
+ ],
+ "dependencies": [
+ "ext.echo.api",
+ "mediawiki.Uri"
+ ],
+ "targets": [
+ "desktop"
+ ]
+ },
+ "ext.echo.styles.badge": {
+ "position": "top",
+ "styles": [
+ "nojs/mw.echo.badge.less"
+ ],
+ "skinStyles": {
+ "monobook": [
+ "nojs/mw.echo.badge.monobook.less"
+ ],
+ "vector": [
+ "nojs/mw.echo.badge.vector.less"
+ ],
+ "modern": [
+ "nojs/mw.echo.badge.modern.less"
+ ]
+ },
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.styles.notifications": {
+ "position": "top",
+ "styles": [
+ "nojs/mw.echo.notifications.less",
+ "styles/LabelIconWidget.less"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.styles.alert": {
+ "position": "top",
+ "styles": [
+ "nojs/mw.echo.alert.less"
+ ],
+ "skinStyles": {
+ "monobook": [
+ "nojs/mw.echo.alert.monobook.less"
+ ],
+ "modern": [
+ "nojs/mw.echo.alert.modern.less"
+ ]
+ },
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.special": {
+ "scripts": [
+ "ui/mw.echo.ui.PaginationWidget.js",
+ "ui/mw.echo.ui.DatedSubGroupListWidget.js",
+ "ui/mw.echo.ui.DatedNotificationsWidget.js",
+ "ui/mw.echo.ui.ReadStateButtonSelectWidget.js",
+ "ui/mw.echo.ui.PageNotificationsOptionWidget.js",
+ "ui/mw.echo.ui.PageFilterWidget.js",
+ "ui/mw.echo.ui.CrossWikiUnreadFilterWidget.js",
+ "ui/mw.echo.ui.NotificationsInboxWidget.js",
+ "ui/mw.echo.ui.SpecialHelpMenuWidget.js",
+ "special/ext.echo.special.js"
+ ],
+ "styles": [
+ "styles/mw.echo.ui.PaginationWidget.less",
+ "styles/mw.echo.ui.DatedSubGroupListWidget.less",
+ "styles/mw.echo.ui.DatedNotificationsWidget.less",
+ "styles/mw.echo.ui.NotificationsInboxWidget.less",
+ "styles/mw.echo.ui.PageNotificationsOptionWidget.less",
+ "styles/mw.echo.ui.PageFilterWidget.less",
+ "styles/mw.echo.ui.CrossWikiUnreadFilterWidget.less",
+ "styles/mw.echo.ui.SpecialHelpMenuWidget.less"
+ ],
+ "skinStyles": {
+ "monobook": [
+ "styles/mw.echo.ui.CrossWikiUnreadFilterWidget.monobook.less"
+ ]
+ },
+ "dependencies": [
+ "ext.echo.ui",
+ "mediawiki.Uri",
+ "ext.echo.styles.special"
+ ],
+ "messages": [
+ "echo-load-more-error",
+ "notification-inbox-filter-read",
+ "notification-inbox-filter-unread",
+ "notification-inbox-filter-all",
+ "echo-notification-placeholder-filters",
+ "echo-specialpage-pagination-numnotifications",
+ "echo-specialpage-pagination-range",
+ "echo-specialpage-pagefilters-title",
+ "echo-specialpage-pagefilters-subtitle",
+ "echo-mark-all-as-read",
+ "echo-more-info",
+ "echo-learn-more",
+ "mypreferences",
+ "echo-feedback",
+ "echo-specialpage-section-markread"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.styles.special": {
+ "position": "top",
+ "styles": [
+ "nojs/mw.echo.special.less"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.echo.badgeicons": {
+ "class": "ResourceLoaderImageModule",
+ "position": "top",
+ "data": "icons/badgeicons.json",
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}"
+ }
+ },
+ "ResourceFileModulePaths": {
+ "localBasePath": "modules",
+ "remoteExtPath": "Echo/modules"
+ },
+ "Hooks": {
+ "LoadExtensionSchemaUpdates": "EchoHooks::onLoadExtensionSchemaUpdates",
+ "GetPreferences": "EchoHooks::getPreferences",
+ "PersonalUrls": "EchoHooks::onPersonalUrls",
+ "BeforePageDisplay": "EchoHooks::beforePageDisplay",
+ "MakeGlobalVariablesScript": "EchoHooks::makeGlobalVariablesScript",
+ "ResourceLoaderRegisterModules": "EchoHooks::onResourceLoaderRegisterModules",
+ "EventLoggingRegisterSchemas": "EchoHooks::onEventLoggingRegisterSchemas",
+ "ResourceLoaderTestModules": "EchoHooks::onResourceLoaderTestModules",
+ "UserGroupsChanged": "EchoHooks::onUserGroupsChanged",
+ "UserLoadOptions": "EchoHooks::onUserLoadOptions",
+ "UserSaveOptions": "EchoHooks::onUserSaveOptions",
+ "UserClearNewTalkNotification": "EchoHooks::onUserClearNewTalkNotification",
+ "ParserTestTables": "EchoHooks::onParserTestTables",
+ "EmailUserComplete": "EchoHooks::onEmailUserComplete",
+ "LoginFormValidErrorMessages": "EchoHooks::onLoginFormValidErrorMessages",
+ "OutputPageCheckLastModified": "EchoHooks::onOutputPageCheckLastModified",
+ "ArticleDeleteComplete": "EchoHooks::onArticleDeleteComplete",
+ "ArticleUndelete": "EchoHooks::onArticleUndelete",
+ "UserMergeAccountFields": "EchoHooks::onUserMergeAccountFields",
+ "MergeAccountFromTo": "EchoHooks::onMergeAccountFromTo",
+ "UserMergeAccountDeleteTables": "EchoHooks::onUserMergeAccountDeleteTables",
+ "EchoGetBundleRules": "EchoHooks::onEchoGetBundleRules",
+ "EchoAbortEmailNotification": "EchoHooks::onEchoAbortEmailNotification",
+ "PageContentSaveComplete": "EchoHooks::onPageContentSaveComplete",
+ "LocalUserCreated": "EchoHooks::onLocalUserCreated",
+ "ArticleRollbackComplete": "EchoHooks::onRollbackComplete",
+ "UserSaveSettings": "EchoHooks::onUserSaveSettings",
+ "AbortTalkPageEmailNotification": "EchoHooks::onAbortTalkPageEmailNotification",
+ "SendWatchlistEmailNotification": "EchoHooks::onSendWatchlistEmailNotification",
+ "GetNewMessagesAlert": "EchoHooks::abortNewMessagesAlert",
+ "LinksUpdateAfterInsert": "EchoHooks::onLinksUpdateAfterInsert",
+ "GetBetaFeaturePreferences": "EchoHooks::getBetaFeaturePreferences",
+ "ResourceLoaderGetConfigVars": "EchoHooks::onResourceLoaderGetConfigVars"
+ },
+ "config": {
+ "EchoEnableEmailBatch": {
+ "value": true
+ },
+ "EchoUseJobQueue": {
+ "value": false
+ },
+ "EchoEmailFooterAddress": {
+ "value": ""
+ },
+ "NotificationSenderName": {
+ "value": null
+ },
+ "NotificationReplyName": {
+ "value": "No Reply"
+ },
+ "EchoCluster": {
+ "value": false
+ },
+ "EchoSharedTrackingDB": {
+ "value": false
+ },
+ "EchoSharedTrackingCluster": {
+ "value": false
+ },
+ "EchoSectionTransition": {
+ "value": false
+ },
+ "EchoBundleTransition": {
+ "value": false
+ },
+ "EchoMaxUpdateCount": {
+ "value": 2000
+ },
+ "EchoMaxMentionsCount": {
+ "value": 50
+ },
+ "EchoMentionStatusNotifications": {
+ "value": false
+ },
+ "EchoMentionsOnMultipleSectionEdits": {
+ "value": true
+ },
+ "EchoMentionOnChanges": {
+ "value": true
+ },
+ "EchoBundleEmailInterval": {
+ "value": 0
+ },
+ "EchoNewMsgAlert": {
+ "value": true
+ },
+ "EchoShowFooterNotice": {
+ "value": false
+ },
+ "EchoFooterNoticeURL": {
+ "value": ""
+ },
+ "DefaultNotifyTypeAvailability": {
+ "value": {
+ "web": true,
+ "email": true
+ }
+ },
+ "NotifyTypeAvailabilityByCategory": {
+ "value": {
+ "emailuser": {
+ "web": true,
+ "email": false
+ },
+ "mention-failure": {
+ "web": true,
+ "email": false
+ },
+ "mention-success": {
+ "web": true,
+ "email": false
+ }
+ },
+ "merge_strategy": "array_plus_2d"
+ },
+ "EchoNotifiers": {
+ "value": {
+ "web": [
+ "EchoNotifier",
+ "notifyWithNotification"
+ ],
+ "email": [
+ "EchoNotifier",
+ "notifyWithEmail"
+ ]
+ }
+ },
+ "EchoAgentBlacklist": {
+ "value": []
+ },
+ "EchoOnWikiBlacklist": {
+ "value": "Echo-blacklist"
+ },
+ "EchoPerUserBlacklist": {
+ "value": false
+ },
+ "EchoPerUserWhitelistFormat": {
+ "value": "%s/Echo-whitelist"
+ },
+ "EchoCrossWikiNotifications": {
+ "value": false
+ },
+ "EchoUseCrossWikiBetaFeature": {
+ "value": false
+ },
+ "EchoNotificationCategories": {
+ "value": {
+ "system": {
+ "priority": 9,
+ "no-dismiss": [
+ "all"
+ ]
+ },
+ "user-rights": {
+ "priority": 9,
+ "tooltip": "echo-pref-tooltip-user-rights"
+ },
+ "other": {
+ "no-dismiss": [
+ "all"
+ ]
+ },
+ "edit-user-talk": {
+ "priority": 1,
+ "no-dismiss": [
+ "web"
+ ],
+ "tooltip": "echo-pref-tooltip-edit-user-talk"
+ },
+ "reverted": {
+ "priority": 9,
+ "tooltip": "echo-pref-tooltip-reverted"
+ },
+ "article-linked": {
+ "priority": 5,
+ "tooltip": "echo-pref-tooltip-article-linked"
+ },
+ "mention": {
+ "priority": 4,
+ "tooltip": "echo-pref-tooltip-mention"
+ },
+ "mention-failure": {
+ "priority": 4,
+ "tooltip": "echo-pref-tooltip-mention-failure"
+ },
+ "mention-success": {
+ "priority": 4,
+ "tooltip": "echo-pref-tooltip-mention-success"
+ },
+ "emailuser": {
+ "priority": 9,
+ "tooltip": "echo-pref-tooltip-emailuser"
+ },
+ "article-reminder": {
+ "priority": 1,
+ "tooltip": "echo-pref-tooltip-article-reminder"
+ }
+ },
+ "merge_strategy": "array_plus_2d"
+ },
+ "EchoNotificationIcons": {
+ "value": {
+ "placeholder": {
+ "path": "Echo/modules/icons/generic.svg"
+ },
+ "trash": {
+ "path": "Echo/modules/icons/trash.svg"
+ },
+ "chat": {
+ "path": "Echo/modules/icons/chat.svg"
+ },
+ "edit": {
+ "path": {
+ "ltr": "Echo/modules/icons/ooui-edit-ltr-progressive.svg",
+ "rtl": "Echo/modules/icons/ooui-edit-rtl-progressive.svg"
+ }
+ },
+ "edit-user-talk": {
+ "path": "Echo/modules/icons/edit-user-talk.svg"
+ },
+ "linked": {
+ "path": "Echo/modules/icons/link-blue.svg"
+ },
+ "mention": {
+ "path": "Echo/modules/icons/mention.svg"
+ },
+ "mention-failure": {
+ "path": "Echo/modules/icons/mention-failure.svg"
+ },
+ "mention-success": {
+ "path": "Echo/modules/icons/mention-success.svg"
+ },
+ "mention-status-bundle": {
+ "path": "Echo/modules/icons/mention-status-bundle.svg"
+ },
+ "reviewed": {
+ "path": "Echo/modules/icons/reviewed.svg"
+ },
+ "revert": {
+ "path": "Echo/modules/icons/revert.svg"
+ },
+ "user-rights": {
+ "path": "Echo/modules/icons/user-rights.svg"
+ },
+ "emailuser": {
+ "path": "Echo/modules/icons/emailuser.svg"
+ },
+ "help": {
+ "path": "Echo/modules/icons/help.svg"
+ },
+ "global": {
+ "path": "Echo/modules/icons/global.svg"
+ },
+ "site": {
+ "url": false
+ },
+ "article-reminder": {
+ "path": "Echo/modules/icons/global.svg"
+ }
+ },
+ "merge_strategy": "array_plus_2d"
+ },
+ "EchoSecondaryIcons": {
+ "value": {
+ "linked": {
+ "path": "Echo/modules/icons/link-blue.svg"
+ },
+ "changes": {
+ "path": "Echo/modules/icons/changes.svg"
+ },
+ "thanks": {
+ "path": {
+ "ltr": "Echo/modules/icons/thanks-ltr.svg",
+ "rtl": "Echo/modules/icons/thanks-rtl.svg"
+ }
+ },
+ "userSpeechBubble": {
+ "path": "Echo/modules/icons/user-speech-bubble.svg"
+ }
+ },
+ "merge_strategy": "array_plus_2d"
+ },
+ "EchoNotifications": {
+ "value": {
+ "welcome": {
+ "user-locators": [
+ "EchoUserLocator::locateEventAgent"
+ ],
+ "category": "system",
+ "group": "positive",
+ "section": "message",
+ "notify-type-availability": {
+ "email": false
+ },
+ "presentation-model": "EchoWelcomePresentationModel"
+ },
+ "edit-user-talk": {
+ "presentation-model": "EchoEditUserTalkPresentationModel",
+ "user-locators": [
+ "EchoUserLocator::locateTalkPageOwner"
+ ],
+ "category": "edit-user-talk",
+ "group": "interactive",
+ "section": "alert",
+ "bundle": {
+ "web": true,
+ "email": false
+ },
+ "immediate": true
+ },
+ "reverted": {
+ "presentation-model": "EchoRevertedPresentationModel",
+ "user-locators": [
+ [
+ "EchoUserLocator::locateFromEventExtra",
+ [
+ "reverted-user-id"
+ ]
+ ]
+ ],
+ "category": "reverted",
+ "group": "negative",
+ "section": "alert"
+ },
+ "page-linked": {
+ "presentation-model": "EchoPageLinkedPresentationModel",
+ "user-locators": [
+ "EchoUserLocator::locateArticleCreator"
+ ],
+ "category": "article-linked",
+ "group": "neutral",
+ "section": "message",
+ "bundle": {
+ "web": true,
+ "email": true,
+ "expandable": true
+ }
+ },
+ "mention": {
+ "user-locators": [
+ [
+ "EchoUserLocator::locateFromEventExtra",
+ [
+ "mentioned-users"
+ ]
+ ]
+ ],
+ "category": "mention",
+ "group": "interactive",
+ "section": "alert",
+ "presentation-model": "EchoMentionPresentationModel"
+ },
+ "mention-failure": {
+ "user-locators": [
+ [
+ "EchoUserLocator::locateEventAgent"
+ ]
+ ],
+ "category": "mention-failure",
+ "bundle": {
+ "web": true,
+ "expandable": true
+ },
+ "group": "negative",
+ "section": "alert",
+ "presentation-model": "EchoMentionStatusPresentationModel"
+ },
+ "mention-failure-too-many": {
+ "user-locators": [
+ [
+ "EchoUserLocator::locateEventAgent"
+ ]
+ ],
+ "category": "mention-failure",
+ "group": "negative",
+ "section": "alert",
+ "presentation-model": "EchoMentionStatusPresentationModel"
+ },
+ "mention-success": {
+ "user-locators": [
+ [
+ "EchoUserLocator::locateEventAgent"
+ ]
+ ],
+ "category": "mention-success",
+ "bundle": {
+ "web": true,
+ "expandable": true
+ },
+ "group": "positive",
+ "section": "alert",
+ "presentation-model": "EchoMentionStatusPresentationModel"
+ },
+ "user-rights": {
+ "user-locators": [
+ [
+ "EchoUserLocator::locateFromEventExtra",
+ [
+ "user"
+ ]
+ ]
+ ],
+ "category": "user-rights",
+ "group": "neutral",
+ "section": "alert",
+ "presentation-model": "EchoUserRightsPresentationModel"
+ },
+ "emailuser": {
+ "presentation-model": "EchoEmailUserPresentationModel",
+ "user-locators": [
+ [
+ "EchoUserLocator::locateFromEventExtra",
+ [
+ "to-user-id"
+ ]
+ ]
+ ],
+ "category": "emailuser",
+ "group": "neutral",
+ "section": "alert"
+ },
+ "foreign": {
+ "presentation-model": "EchoForeignPresentationModel",
+ "user-locators": [
+ "EchoUserLocator::locateEventAgent"
+ ],
+ "category": "foreign",
+ "group": "positive",
+ "section": "alert"
+ },
+ "thank-you-edit": {
+ "user-locators": [
+ "EchoUserLocator::locateEventAgent"
+ ],
+ "category": "system",
+ "notify-type-availability": {
+ "email": false
+ },
+ "group": "positive",
+ "presentation-model": "EchoEditThresholdPresentationModel",
+ "section": "message"
+ },
+ "article-reminder": {
+ "user-locators": [
+ "EchoUserLocator::locateEventAgent"
+ ],
+ "category": "article-reminder",
+ "group": "positive",
+ "presentation-model": "EchoArticleReminderPresentationModel",
+ "section": "message"
+ }
+ },
+ "merge_strategy": "array_plus_2d"
+ },
+ "EchoCacheVersion": {
+ "value": "1.12"
+ },
+ "EchoEventLoggingVersion": {
+ "value": "1.12"
+ },
+ "EchoEventLoggingSchemas": {
+ "value": {
+ "Echo": {
+ "enabled": false,
+ "revision": 7731316,
+ "client": false
+ },
+ "EchoMail": {
+ "enabled": false,
+ "revision": 5467650,
+ "client": false
+ },
+ "EchoInteraction": {
+ "enabled": false,
+ "revision": 15823738,
+ "client": true
+ }
+ },
+ "merge_strategy": "array_plus_2d"
+ },
+ "AllowArticleReminderNotification": {
+ "value": false,
+ "description": "This is a feature flag to the Article Reminder notification"
+ }
+ },
+ "manifest_version": 2,
+ "AutoloadClasses": {
+ "ApiCrossWikiBase": "includes/api/ApiCrossWikiBase.php",
+ "ApiEchoArticleReminder": "includes/api/ApiEchoArticleReminder.php",
+ "ApiEchoMarkRead": "includes/api/ApiEchoMarkRead.php",
+ "ApiEchoMarkReadTest": "tests/phpunit/api/ApiEchoMarkReadTest.php",
+ "ApiEchoMarkSeen": "includes/api/ApiEchoMarkSeen.php",
+ "ApiEchoNotifications": "includes/api/ApiEchoNotifications.php",
+ "ApiEchoNotificationsTest": "tests/phpunit/api/ApiEchoNotificationsTest.php",
+ "ApiEchoUnreadNotificationPages": "includes/api/ApiEchoUnreadNotificationPages.php",
+ "BackfillReadBundles": "maintenance/backfillReadBundles.php",
+ "BackfillUnreadWikis": "maintenance/backfillUnreadWikis.php",
+ "Bundleable": "includes/Bundleable.php",
+ "Bundler": "includes/Bundler.php",
+ "BundlerTest": "tests/phpunit/BundlerTest.php",
+ "ContainmentSetTest": "tests/phpunit/ContainmentSetTest.php",
+ "EchoAbstractEntity": "includes/model/AbstractEntity.php",
+ "EchoAbstractMapper": "includes/mapper/AbstractMapper.php",
+ "EchoAbstractMapperStub": "tests/phpunit/mapper/AbstractMapperTest.php",
+ "EchoAbstractMapperTest": "tests/phpunit/mapper/AbstractMapperTest.php",
+ "EchoArrayList": "includes/ContainmentSet.php",
+ "EchoAttributeManager": "includes/AttributeManager.php",
+ "EchoAttributeManagerTest": "tests/phpunit/AttributeManagerTest.php",
+ "EchoCachedList": "includes/ContainmentSet.php",
+ "EchoCallbackIterator": "includes/iterator/CallbackIterator.php",
+ "EchoCatchableFatalErrorException": "includes/exception/CatchableFatalErrorException.php",
+ "EchoContainmentList": "includes/ContainmentSet.php",
+ "EchoContainmentSet": "includes/ContainmentSet.php",
+ "EchoDataOutputFormatter": "includes/DataOutputFormatter.php",
+ "EchoDeferredMarkAsDeletedUpdate": "includes/DeferredMarkAsDeletedUpdate.php",
+ "EchoDiffGroup": "includes/DiffParser.php",
+ "EchoDiffParser": "includes/DiffParser.php",
+ "EchoDiffParserTest": "tests/phpunit/DiffParserTest.php",
+ "EchoDiscussionParser": "includes/DiscussionParser.php",
+ "EchoDiscussionParserTest": "tests/phpunit/DiscussionParserTest.php",
+ "EchoEditThresholdPresentationModel": "includes/formatters/EditThresholdPresentationModel.php",
+ "EchoEditUserTalkPresentationModel": "includes/formatters/EditUserTalkPresentationModel.php",
+ "EchoArticleReminderPresentationModel": "includes/formatters/ArticleReminderPresentationModel.php",
+ "EchoEmailFormat": "includes/EmailFormat.php",
+ "EchoEmailFrequency": "includes/EmailFrequency.php",
+ "EchoEmailUserPresentationModel": "includes/formatters/EmailUserPresentationModel.php",
+ "EchoEvent": "includes/model/Event.php",
+ "EchoEventDigestFormatter": "includes/formatters/EchoEventDigestFormatter.php",
+ "EchoEventFormatter": "includes/formatters/EchoEventFormatter.php",
+ "EchoEventMapper": "includes/mapper/EventMapper.php",
+ "EchoEventMapperTest": "tests/phpunit/mapper/EventMapperTest.php",
+ "EchoEventPresentationModel": "includes/formatters/EventPresentationModel.php",
+ "EchoExecuteFirstArgumentStub": "tests/phpunit/mapper/NotificationMapperTest.php",
+ "EchoFilteredSequentialIterator": "includes/iterator/FilteredSequentialIterator.php",
+ "EchoFlyoutFormatter": "includes/formatters/EchoFlyoutFormatter.php",
+ "EchoForeignNotifications": "includes/ForeignNotifications.php",
+ "EchoForeignPresentationModel": "includes/formatters/EchoForeignPresentationModel.php",
+ "EchoForeignWikiRequest": "includes/ForeignWikiRequest.php",
+ "EchoHooks": "Hooks.php",
+ "EchoHtmlDigestEmailFormatter": "includes/formatters/EchoHtmlDigestEmailFormatter.php",
+ "EchoHtmlEmailFormatter": "includes/formatters/EchoHtmlEmailFormatter.php",
+ "EchoIcon": "includes/formatters/EchoIcon.php",
+ "EchoIteratorDecorator": "includes/iterator/IteratorDecorator.php",
+ "EchoLocalCache": "includes/cache/LocalCache.php",
+ "EchoMentionPresentationModel": "includes/formatters/MentionPresentationModel.php",
+ "EchoMentionStatusPresentationModel": "includes/formatters/MentionStatusPresentationModel.php",
+ "EchoModelFormatter": "includes/formatters/EchoModelFormatter.php",
+ "EchoModerationController": "includes/controller/ModerationController.php",
+ "EchoMultipleIterator": "includes/iterator/MultipleIterator.php",
+ "EchoNotRecursiveIterator": "includes/iterator/NotRecursiveIterator.php",
+ "EchoNotification": "includes/model/Notification.php",
+ "EchoNotificationController": "includes/controller/NotificationController.php",
+ "EchoNotificationDeleteJob": "includes/jobs/NotificationDeleteJob.php",
+ "EchoNotificationJob": "includes/jobs/NotificationJob.php",
+ "EchoNotificationMapper": "includes/mapper/NotificationMapper.php",
+ "EchoNotificationMapperTest": "tests/phpunit/mapper/NotificationMapperTest.php",
+ "EchoNotificationTest": "tests/phpunit/model/NotificationTest.php",
+ "EchoNotifier": "includes/Notifier.php",
+ "EchoOOUI\\LabelIconWidget": "includes/ooui/LabelIconWidget.php",
+ "EchoOnWikiList": "includes/ContainmentSet.php",
+ "EchoPageLinkedPresentationModel": "includes/formatters/PageLinkedPresentationModel.php",
+ "EchoPlainTextDigestEmailFormatter": "includes/formatters/EchoPlainTextDigestEmailFormatter.php",
+ "EchoPlainTextEmailFormatter": "includes/formatters/EchoPlainTextEmailFormatter.php",
+ "EchoPresentationModelSectionTrait": "includes/formatters/PresentationModelSectionTrait.php",
+ "EchoRevertedPresentationModel": "includes/formatters/RevertedPresentationModel.php",
+ "EchoRevisionLocalCache": "includes/cache/RevisionLocalCache.php",
+ "EchoSeenTime": "includes/SeenTime.php",
+ "EchoSuppressionRowUpdateGenerator": "includes/schemaUpdate.php",
+ "EchoTalkPageFunctionalTest": "tests/phpunit/TalkPageFunctionalTest.php",
+ "EchoTargetPage": "includes/model/TargetPage.php",
+ "EchoTargetPageMapper": "includes/mapper/TargetPageMapper.php",
+ "EchoTargetPageMapperTest": "tests/phpunit/mapper/TargetPageMapperTest.php",
+ "EchoTargetPageTest": "tests/phpunit/model/TargetPageTest.php",
+ "EchoTitleLocalCache": "includes/cache/TitleLocalCache.php",
+ "EchoTitleLocalCacheTest": "tests/phpunit/cache/TitleLocalCacheTest.php",
+ "EchoUnreadWikis": "includes/UnreadWikis.php",
+ "EchoUserLocator": "includes/UserLocator.php",
+ "EchoUserLocatorTest": "tests/phpunit/UserLocatorTest.php",
+ "EchoUserNotificationGateway": "includes/gateway/UserNotificationGateway.php",
+ "EchoUserNotificationGatewayTest": "tests/phpunit/gateway/UserNotificationGatewayTest.php",
+ "EchoUserRightsPresentationModel": "includes/formatters/UserRightsPresentationModel.php",
+ "EchoWelcomePresentationModel": "includes/formatters/WelcomePresentationModel.php",
+ "FilteredSequentialIteratorTest": "tests/phpunit/iterator/FilteredSequentialIteratorTest.php",
+ "GenerateSampleNotifications": "maintenance/generateSampleNotifications.php",
+ "MWEchoDbFactory": "includes/EchoDbFactory.php",
+ "MWEchoDbFactoryTest": "tests/phpunit/EchoDbFactoryTest.php",
+ "MWEchoEmailBatch": "includes/EmailBatch.php",
+ "MWEchoEventLogging": "includes/EventLogging.php",
+ "MWEchoNotifUser": "includes/NotifUser.php",
+ "MWEchoNotifUserTest": "tests/phpunit/NotifUserTest.php",
+ "MWEchoThankYouEditTest": "tests/phpunit/ThankYouEditTest.php",
+ "NotificationControllerTest": "tests/phpunit/controller/NotificationControllerTest.php",
+ "NotificationPager": "includes/special/NotificationPager.php",
+ "NotificationsTest": "tests/NotificationsTest.php",
+ "ProcessEchoEmailBatch": "maintenance/processEchoEmailBatch.php",
+ "RemoveInvalidNotification": "maintenance/removeInvalidNotification.php",
+ "RemoveOrphanedEvents": "maintenance/removeOrphanedEvents.php",
+ "ResourceLoaderEchoImageModule": "includes/ResourceLoaderEchoImageModule.php",
+ "SpecialDisplayNotificationsConfiguration": "includes/special/SpecialDisplayNotificationsConfiguration.php",
+ "SpecialNotifications": "includes/special/SpecialNotifications.php",
+ "SpecialNotificationsFormatter": "includes/formatters/SpecialNotificationsFormatter.php",
+ "SpecialNotificationsMarkRead": "includes/special/SpecialNotificationsMarkRead.php",
+ "SuppressionMaintenanceTest": "tests/phpunit/maintenance/SupressionMaintenanceTest.php",
+ "TestDiscussionParser": "maintenance/testDiscussionParser.php",
+ "UpdateEchoSchemaForSuppression": "maintenance/updateEchoSchemaForSuppression.php"
+ }
+}
diff --git a/Echo/gitinfo.json b/Echo/gitinfo.json
new file mode 100644
index 00000000..bea5149a
--- /dev/null
+++ b/Echo/gitinfo.json
@@ -0,0 +1 @@
+{"headSHA1": "d64a26dd69ead0c3c4618b136a71dcab964b691f\n", "head": "d64a26dd69ead0c3c4618b136a71dcab964b691f\n", "remoteURL": "https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo", "branch": "d64a26dd69ead0c3c4618b136a71dcab964b691f\n", "headCommitDate": "1535056172"} \ No newline at end of file
diff --git a/Echo/i18n/ace.json b/Echo/i18n/ace.json
new file mode 100644
index 00000000..aeaec342
--- /dev/null
+++ b/Echo/i18n/ace.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Si Gam Acèh"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "Beuneuri thèe"
+}
diff --git a/Echo/i18n/af.json b/Echo/i18n/af.json
index 4df77dc2..b0d26796 100644
--- a/Echo/i18n/af.json
+++ b/Echo/i18n/af.json
@@ -1,7 +1,10 @@
{
"@metadata": {
"authors": [
- "Naudefj"
+ "Naudefj",
+ "Servien",
+ "Fwolff",
+ "Biggs ZA"
]
},
"echo-desc": "Kennisgewing-stelsel",
@@ -9,7 +12,9 @@
"prefs-emailsettings": "E-posopsies",
"prefs-displaynotifications": "Vertoonopsies",
"prefs-echosubscriptions": "Hou my op hoogte oor hierdie gebeurtenisse",
+ "prefs-echocrosswiki": "Kennisgewings van ander wiki's",
"prefs-newmessageindicator": "Nuwe boodskap-indikator",
+ "prefs-blocknotificationslist": "Stilgebruikers",
"echo-pref-send-me": "Stuur my:",
"echo-pref-send-to": "Stuur na:",
"echo-pref-email-format": "E-posformaat:",
@@ -27,26 +32,63 @@
"echo-category-title-edit-user-talk": "Boodskap{{PLURAL:$1||pe}} op u besprekingsblad",
"echo-category-title-article-linked": "Bladsyskakel{{PLURAL:$1||s}}",
"echo-category-title-reverted": "Wysiging {{PLURAL:$1|teruggerol}}",
+ "echo-category-title-other": "{{PLURAL:$1|Ander}}",
"echo-category-title-system": "{{PLURAL:$1|Stelsel}}",
- "echo-no-agent": "[Niemand]",
- "echo-no-title": "[Geen bladsy]",
"notifications": "Kennisgewings",
+ "tooltip-pt-notifications-alert": "{{GENDER:|U}} kennisgewings",
+ "tooltip-pt-notifications-notice": "{{GENDER:|U}} boodskappe",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nuwe gebruikers",
"echo-specialpage": "Kennisgewings",
+ "echo-specialpage-section-markread": "Merk groep as gelees",
+ "echo-specialpage-markasread": "Kennisgewing: Merk as gelees",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|kennisgewing|kennisgewings}}",
+ "echo-specialpage-pagefilters-title": "Onlangse aktiwiteit",
+ "echo-specialpage-pagefilters-subtitle": "Bladsye met ongelese kennisgewings",
+ "notificationsmarkread-legend": "Merk kennisgewing as gelees",
+ "echo-none": "U het geen kennisgewings nie.",
"echo-more-info": "Meer inligting",
"echo-feedback": "Terugvoer",
+ "echo-popup-footer-special-page-invitation": "<strong>Probeer die herontwerpte kennisgewingsbladsy.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "'n Heel nuwe uiterlik en nuwe funksies.",
+ "echo-api-failure": "Kan kennisgewings nie ophaal nie.",
+ "echo-api-failure-cross-wiki": "Toegang tot die eksterne domein is geweier.",
+ "echo-notification-placeholder": "Daar is geen kennisgewings nie.",
+ "echo-notification-placeholder-filters": "Daar is geen kennisgewings wat aan hierdie kriteria voldoen nie.",
+ "echo-notification-loginrequired": "U moet aangemeld wees om u kennisgewings te sien.",
+ "echo-notification-markasread": "Merk as gelees",
+ "echo-notification-markasunread": "Merk as ongelees",
+ "echo-notification-markasread-tooltip": "Merk as gelees",
+ "echo-notification-more-options-tooltip": "Meer opsies",
+ "notification-link-text-expand-all": "Vou oop",
+ "notification-link-text-expand-notice-count": "Sien {{PLURAL:$1|$1 kennisgewing|$1 kennisgewings}}",
+ "notification-link-text-collapse-all": "Vou toe",
"notification-link-text-view-message": "Wys boodskap",
"notification-link-text-view-mention": "Wys vermelding",
"notification-link-text-view-changes": "Wys veranderings",
"notification-link-text-view-page": "Wys bladsy",
+ "notification-link-text-what-links-here": "Al die skakels na hierdie bladsy",
+ "notification-welcome-linktext": "Welkom",
"notification-link-text-view-edit": "Wys wysiging",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|het 'n boodskap}} op u [[User talk:$2#$3|besprekingsblad]] geplaas.",
- "echo-email-subject-default": "Nuwe kennisgewing op {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1ma}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1j}}",
+ "notification-timestamp-today": "Vandag",
+ "notification-timestamp-yesterday": "Gister",
+ "notification-inbox-filter-read": "Gelees",
+ "notification-inbox-filter-unread": "Ongelees",
+ "notification-inbox-filter-all": "Alles",
"echo-email-body-default": "U het 'n nuwe kennisgewing op {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "U het 'n nuwe kennisgewing.",
+ "echo-notification-alert-text-only": "Kennisgewings",
+ "echo-notification-notice-text-only": "Boodskappe",
"echo-overlay-link": "Alle kennisgewings",
"echo-overlay-title": "<b>Kennisgewings</b>",
"echo-mark-all-as-read": "Merk alles as gelees",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|kennisgewing|kennisgewings}} gemerk as gelees",
"echo-date-today": "Vandag",
"echo-date-yesterday": "Gister",
- "echo-email-batch-link-text-view-all-notifications": "Wys alle kennisgewings"
+ "echo-email-batch-link-text-view-all-notifications": "Wys alle kennisgewings",
+ "notification-header-foreign-notice": "Meer kennisgewings vanaf {{PLURAL:$5|'n ander wiki|$5 ander wiki's}}"
}
diff --git a/Echo/i18n/ais.json b/Echo/i18n/ais.json
new file mode 100644
index 00000000..74a5d36f
--- /dev/null
+++ b/Echo/i18n/ais.json
@@ -0,0 +1,68 @@
+{
+ "@metadata": {
+ "authors": [
+ "Benel",
+ "Bunukwiki",
+ "Tokoabibi"
+ ]
+ },
+ "prefs-echo": "patakus",
+ "prefs-emailsettings": "imyiyo(email) mapili’ay",
+ "prefs-displaynotifications": "paazih tu mapiliay",
+ "prefs-echocrosswiki": "milakuid wiki patakus",
+ "prefs-newmessageindicator": "baluhay palatuh satuzu’ a sakaluk",
+ "echo-pref-send-me": "pabahel takuwanan:",
+ "echo-pref-send-to": "pabahel katukuh i:",
+ "echo-pref-web": "calay-kasabelih(wangyei)",
+ "echo-pref-email": "imyiyo(email)",
+ "echo-pref-email-frequency-daily": "paydemiad patakus pecu’ nu lacul",
+ "echo-pref-email-frequency-weekly": "paylipay patakus pecu’ nu lacul",
+ "echo-pref-email-format-html": "HTML",
+ "echo-pref-email-format-plain-text": "sulit a dada’",
+ "echo-pref-beta-feature-cross-wiki-message": "pacunusen patakus sasahicaan",
+ "echo-learn-more": "sayadahay ku tineng",
+ "echo-log": "nubinawlan a nasulitan nazipa’an",
+ "echo-new-messages": "izaw baluhay palatuh kisu",
+ "echo-error-no-formatter": "caay henay misaheci kese nu takus.",
+ "notifications": "patakus",
+ "tooltip-pt-notifications-alert": "{{GENDER:|misuay}}pacekil",
+ "echo-displaynotificationsconfiguration": "paazih patakus setin",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "paykakuniza a takus",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "masilsilay a kakuniza",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "mahasa mitakus sasakawawen",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "pataayaw tu kawaw miwawah",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "ayzaay a misaungayay",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "baluhay misaungayay",
+ "echo-specialpage-section-markread": "silusi tu luyaluy ku maasipay",
+ "echo-specialpage-markasread": "takus: silusi naasip tuway",
+ "echo-specialpage-markasread-invalid-id": "sikawaw ID la’cus",
+ "echo-specialpage-pagefilters-title": "capiay a saungay nu binawlan",
+ "echo-specialpage-pagefilters-subtitle": "yamalyilu caay maasipay a kasabelih nu tukus",
+ "notificationsmarkread-legend": "ya takus silusi namasiptu",
+ "echo-none": "inayi’ amahicahica tu patakus numisu.",
+ "echo-more-info": "sayadahay a cesyun",
+ "echo-feedback": "nabalucu’an hwidubaku",
+ "echo-popup-footer-special-page-invitation-link": "sakacinizaniza baluhayay a nuhekalan atu kungneng.",
+ "echo-notification-placeholder": "inayi’ ku hicahica a takus.",
+ "echo-notification-markasread": "silusi sanay u maasipay tu",
+ "echo-notification-markasread-tooltip": "silusi sanay u maasipay tu",
+ "echo-notification-more-options-tooltip": "sayadahay a mapiliay",
+ "notification-link-text-expand-all": "micuwat",
+ "notification-link-text-collapse-all": "piked",
+ "notification-link-text-view-message": "ciwsace tu palatuh",
+ "notification-link-text-view-page": "ciwsace tu kasabelih",
+ "notification-link-text-view-edit": "ciwsace tu mikawaway-kalumyiti",
+ "notification-link-article-reminder": "ciwsace tu kasabelih",
+ "notification-timestamp-today": "ayza a demiad",
+ "notification-timestamp-yesterday": "nacila",
+ "notification-inbox-filter-read": "miasip",
+ "notification-inbox-filter-unread": "caay henay miasip",
+ "notification-inbox-filter-all": "hamin",
+ "echo-notification-alert-text-only": "pacekil",
+ "echo-notification-notice-text-only": "habutuday a patakus",
+ "echo-overlay-link": "sacahamin a takus",
+ "echo-overlay-title": "<b>patakus</b>",
+ "echo-date-today": "ayza a demiad",
+ "echo-date-yesterday": "nacila",
+ "echo-email-batch-link-text-view-all-notifications": "ciwsace tu sacahamin a satakus"
+}
diff --git a/Echo/i18n/am.json b/Echo/i18n/am.json
index d3103f3f..954929af 100644
--- a/Echo/i18n/am.json
+++ b/Echo/i18n/am.json
@@ -26,10 +26,7 @@
"echo-pref-tooltip-article-linked": "ማንኛው ሰው እኔ ወደ ፈጠርኩት መጣጥፍ በሌላ መጣጥፍ ውስጥ መያያዣ ሲያቀርብ አስታውቀኝ።",
"echo-pref-tooltip-reverted": "ማንኛው ሰው የእኔን ለውጦች ሲገለብጥ አስታውቀኝ።",
"echo-pref-tooltip-mention": "ማንኛውም ሰው ወደ እኔ ውይይት ገጽ በሌላ ውይይት ገጽ ላይ መያያዣ ሲያቀርብ አስታውቀኝ።",
- "echo-no-agent": "[Nobody]",
- "echo-no-title": "[No page]",
"notifications": "ማስታወቂያዎች",
- "tooltip-pt-notifications": "የእርስዎ ማስታወቂያዎች",
"echo-specialpage": "ማስታወቂያዎች",
"echo-anon": "ማስታወቂያዎችን ለማየት [$1 የብዕር ስም ያውጡ] ወይም [$2 በብዕር ስምዎ ይግቡ]።",
"echo-none": "ምንም ማስታወቂያዎች የሎትም።",
@@ -40,15 +37,6 @@
"notification-link-text-view-changes": "ማነጻጸሪያ ለማየት",
"notification-link-text-view-page": "ገጽ ለማየት",
"notification-link-text-view-edit": "ማነጻጸሪያ ለማየት",
- "notification-edit-talk-page2": "[[User:$1|$1]] [[User talk:$2#$3|በውይይት ገጽዎ]] ላይ መልዕክት {{GENDER:$1|ትቷል|ትታለች|ትተዋል}}።",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] በውይይት ገጽዎ ላይ በ«[[User talk:$2#$3|$4]]» ርዕስ ስር መልዕክት {{GENDER:$1|ትቷል|ትታለች|ትተዋል}}።",
- "notification-edit-talk-page-flyout2": "$1 [[User talk:$2#$3|በውይይት ገጽዎ]] ላይ መልዕክት {{GENDER:$1|ትቷል|ትታለች|ትተዋል}}።",
- "notification-edit-talk-page-flyout-with-section": "$1 በውይይት ገጽዎ ላይ በ«[[User talk:$2#$3|$4]]» ርዕስ ስር መልዕክት {{GENDER:$1|ትቷል|ትታለች|ትተዋል}}።",
- "notification-page-linked": "$1 በ[[:$3]] ላይ ወደ [[:$2]] መያያዣ {{GENDER:$1|ፈጥሯል|ፈጥራለች|ፈጥረዋል}}። [[Special:WhatLinksHere/$2|ወደዚህ ገጽ ያሉት መያያዣዎች ሁሉ ይዩ]]።",
- "notification-page-linked-flyout": "በ[[:$3]] ላይ ወደ [[:$2]] ገጽ መያያዣ ተፈጥሯል።",
- "notification-add-comment2": "[[User:$1|$1]] በ$4 ገጽ በ«[[$3|$2]]» ርዕስ ላይ አስተያየት {{GENDER:$1|ሰጥቷል|ስጥታለች|ስጥተዋል}}።",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] በ[[$3]] ላይ አዲስ ውይይት በ«$2» ርዕስ {{GENDER:$1|ጀመረ|ጀመረች|ጀመሩ}}።",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] አዲስ መልዕክት {{GENDER:$1|ልኮሎታል}}፣ «[[$3#$2|$2]]»።",
"echo-overlay-link": "ሁሉም ማስታወቂያዎች",
"echo-overlay-title": "<b>ማስታወቂያዎች</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|ማስታወቂያ|ማስታወቂያዎች}}</b> (ከ$2 {{PLURAL:$2|ያልታየ|ያልታዩ}} ውስጥ {{PLURAL:$1|ዱ|ቱ}})",
diff --git a/Echo/i18n/ang.json b/Echo/i18n/ang.json
index 4e1a7371..d5c84333 100644
--- a/Echo/i18n/ang.json
+++ b/Echo/i18n/ang.json
@@ -3,6 +3,5 @@
"authors": [
"Gott wisst"
]
- },
- "tooltip-pt-notifications": "Þīna andwendinga"
+ }
}
diff --git a/Echo/i18n/anp.json b/Echo/i18n/anp.json
new file mode 100644
index 00000000..d5f5ca67
--- /dev/null
+++ b/Echo/i18n/anp.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Angpradesh"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|आपन॑ के}} जागरुकता संदेश",
+ "tooltip-pt-notifications-message": "{{GENDER:|आपन॑ के}} संदेश"
+}
diff --git a/Echo/i18n/api/ar.json b/Echo/i18n/api/ar.json
new file mode 100644
index 00000000..3ae1687f
--- /dev/null
+++ b/Echo/i18n/api/ar.json
@@ -0,0 +1,56 @@
+{
+ "@metadata": {
+ "authors": [
+ "Abanima",
+ "Hiba Alshawi",
+ "Khaled",
+ "Maroen1990",
+ "Meno25",
+ "بدارين",
+ "محمد أحمد عبد الفتاح"
+ ]
+ },
+ "apihelp-echomarkread-description": "علم الإخطارات للقراءة للمستخدم الحالي.",
+ "apihelp-echomarkread-param-list": "قائمة بأرقام الإخطارات للتعليم كمقروءة.",
+ "apihelp-echomarkread-param-unreadlist": "قائمة بأرقام الإخطارات للتعليم كغير مقروءة.",
+ "apihelp-echomarkread-param-all": "لو مضبوطة؛ تعلم على كل إخطارات المستخدم كمقروءة.",
+ "apihelp-echomarkread-param-sections": "قائمة الأقسام للتعليم كمقروءة.",
+ "apihelp-echomarkread-example-1": "علم على الإخطار 8 كمقروء",
+ "apihelp-echomarkread-example-2": "تعليم جميع الإشعارات كمقروءة",
+ "apihelp-echomarkread-example-3": "علم على الإخطار 1 كمقروء",
+ "apihelp-echomarkseen-description": "التعليم على الإخطارات كمنظورة للمستخدم الحالي.",
+ "apihelp-echomarkseen-example-1": "التعليم على الإخطارات من كل الأنواع كمنظورة",
+ "apihelp-echomarkseen-param-type": "نوع الإشعارت لتحديد كما تبدو على أنها: 'تنبيه' 'رسالة' أو 'كل'.",
+ "apihelp-echomarkseen-param-timestampFormat": "صيغة الطابع الزمني للاستخدام للناتج 'ISO_8601' أو 'MW'. 'MW' مستغنى عنه هنا، لذا فكل العملاء ينبغي أن يتحولوا إلى 'ISO_8601'. هذا المعامل ستتم إزالته، و 'ISO_8601' سيصبح صيغة الناتج الوحيدة.",
+ "apihelp-query+notifications-description": "الحصول على الإخطارات قيد الانتظار للمستخدم الحالي.",
+ "apihelp-query+notifications-param-prop": "طلب تفاصيل.",
+ "apihelp-query+notifications-param-sections": "اقسام الأشعار للأستعلام (أي بمعنى بعض الثنائي من \"تنبيه\" و \"رسالة\").",
+ "apihelp-query+notifications-param-groupbysection": "ما إذا يتم جمع النتيجة بالقسم. كل قسم يتم جلبه بشكل مستقل لو مضبوط.",
+ "apihelp-query+notifications-param-filter": "فلترة الإخارات أرجعت.",
+ "apihelp-query+notifications-param-format": "لو محدد، فالإخطارات سيتم إرجاعها مهيئة بهذه الطريقة.",
+ "apihelp-query+notifications-paramvalue-format-text": "صيغة نص عادي",
+ "apihelp-query+notifications-paramvalue-format-model": "بيانات إشعارات خام",
+ "apihelp-query+notifications-paramvalue-format-special": "مهيئة لصفحة Special:Notifications (وفقط هذه!) لا تعتمد على HTML إذ أنه ربما يتغير في أي وقت.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">مستغنى عنه</span>. استخدم <kbd>$1format=model</kbd> للبيانات الخام",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">مستغنى عنه</span>. استخدم <kbd>$1format=model</kbd> للبيانات الخام",
+ "apihelp-query+notifications-param-limit": "العدد الأقصى للإخطارات في النتائج.",
+ "apihelp-query+notifications-param-wikis": "قائمة الويكيات لجلب الإخطارات منها (افتراضيا فقط الويكي الحالية).",
+ "apihelp-query+notifications-param-crosswikisummary": "صحيح للاشتراك في ملخص إخطار للإخطارات على الويكيات الأجنبية.",
+ "apihelp-query+notifications-param-alertcontinue": "عندما تكون المزيد من نتائج التنبيهات متوفرة، استخدم هذه للاستمرار.",
+ "apihelp-query+notifications-param-unreadfirst": "ما إذا كان يتم عرض التذكيرات غير المقروءة أولا (فقط تستخدم لو أن الgroupbysection غير مضبوط).",
+ "apihelp-query+notifications-param-alertunreadfirst": "ما إذا كان تذكيرات الرسائل غير المقروءة يتم عرضها أولا (فقط تستخدم لو كانت الgroupbysection مضبوطة).",
+ "apihelp-query+notifications-param-messagecontinue": "عندما تكون المزيد من النتائج الرسائل المتاحة، واستخدم هذا للمتابعة.",
+ "apihelp-query+notifications-param-messageunreadfirst": "ما إذ كنت تريد عرض التنبيهات غير المقروءة أولا (تستخدم فقط إذا ما كانت groupbysection مضبوطة).",
+ "apihelp-query+notifications-param-titles": "فقط أرجع الإخطارات لهذه الصفحات. للحصول على الإخطارات غير المرتبطة بأي صفحة، استخدم [] كعنوان.",
+ "apihelp-query+notifications-param-bundle": "ما إذا كان يتم عرض الإخطارات غير المقروءة المتوافقة مع الحزمة طبقا لقواعد أنواع حزم الإخطارات.",
+ "apihelp-query+notifications-example-1": "قائمة الإشعارات",
+ "apihelp-query+notifications-example-2": "إخطارات القائمة، التي تم تجميعها حسب القسم، مع احصاء",
+ "apihelp-query+unreadnotificationpages-description": "الحصول على الصفحات التي لها إخطارات غير مقروءة للمستخدم الحالي.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "جمع صفحات النقاش مع صفحات موضوعها، وجمع الإخطارات غير المرتبطة مع صفحة مع صفحة المستخدم للمستخدم الحالي.",
+ "apihelp-query+unreadnotificationpages-param-limit": "العدد الأقصى للصفحات للإرجاع.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "قائمة بالويكيات لجلب الصفحات مع الإخطارات غير المقروءة منها (افتراضيا الويكي الحالية فقط).",
+ "apihelp-query+unreadnotificationpages-example-1": "قائمة الصفحات مع (عدد) الإخطارات غير المقروءة",
+ "apiwarn-echo-deprecation-timestampformat": "صيغة خرج MW timestamp مستغنى عنها هنا. في المستقبل، ISO 8601 سيتم استخدامها دائما لصيغة خرج الطابع الزمني. عدل عميلك واضبط <var>timestampFormat</var> إلى <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> تم الاستغناء عنها وستتم إزالتها قريبا. استخدم <kbd>notformat=model</kbd> للحصول على البيانات الخام أو <kbd>notformat=special</kbd> لHTML المهيأ مسبقا.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> تم الاستغناء عنها وستتم إزالتها قريبا. استخدم <kbd>notformat=special</kbd> بدلا منها."
+}
diff --git a/Echo/i18n/api/ast.json b/Echo/i18n/api/ast.json
new file mode 100644
index 00000000..ffd74b91
--- /dev/null
+++ b/Echo/i18n/api/ast.json
@@ -0,0 +1,61 @@
+{
+ "@metadata": {
+ "authors": [
+ "Xuacu"
+ ]
+ },
+ "apihelp-echomarkread-description": "Marcar les notificaciones como lleíes pal usuariu actual.",
+ "apihelp-echomarkread-summary": "Marcar les notificaciones como lleíes pal usuariu actual.",
+ "apihelp-echomarkread-param-list": "Llista d'IDs de notificaciones pa marcar como lleíes.",
+ "apihelp-echomarkread-param-unreadlist": "Llista d'IDs de notificaciones pa marcar como non lleíes.",
+ "apihelp-echomarkread-param-all": "Si se seleiciona, marca toles notificaciones d'un usuariu como lleíes.",
+ "apihelp-echomarkread-param-sections": "Llista de seiciones a marcar como lleíes.",
+ "apihelp-echomarkread-example-1": "Marcar la notificación 8 como lleída.",
+ "apihelp-echomarkread-example-2": "Marcar toles notificaciones como lleíes",
+ "apihelp-echomarkread-example-3": "Marcar la notificación 1 como non lleída",
+ "apihelp-echomarkseen-description": "Marcar les notificaciones como vistes pal usuariu actual.",
+ "apihelp-echomarkseen-summary": "Marcar les notificaciones como vistes pal usuariu actual.",
+ "apihelp-echomarkseen-example-1": "Marcar los avisos de tolos tipos como lleíos",
+ "apihelp-echomarkseen-param-type": "Tipu d'avisos pa marcar como lleíos: 'alert' (alerta), 'message' (mensaxe) o 'all' (toos).",
+ "apihelp-echomarkseen-param-timestampFormat": "Formatu de la marca de tiempu a usar pa la salida, 'ISO_8601' o 'MW'. 'MW' tá anticuao equí, de mou que tolos clientes tendríen de cambiase a 'ISO_8601'. Esti parámetru va desaniciase, y 'ISO_8601' sedrá l'únicu formatu de salida.",
+ "apihelp-query+notifications-description": "Recibir les notificaciones n'espera pal usuariu actual.",
+ "apihelp-query+notifications-summary": "Recibir les notificaciones n'espera pal usuariu actual.",
+ "apihelp-query+notifications-param-prop": "Detalles a solicitar.",
+ "apihelp-query+notifications-param-sections": "Les secciones d'avisu a consultar (esto ye, dalguna combinación de 'alert' y 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Si hai qu'agrupar los resultaos por seición. Cada seición recíbese por separao si se configura.",
+ "apihelp-query+notifications-param-filter": "Avisos devueltos pol filtru.",
+ "apihelp-query+notifications-param-format": "Si s'especifica, les notificaciones devolveránse con esti formatu.",
+ "apihelp-query+notifications-paramvalue-format-model": "Datos de notificación en bruto",
+ "apihelp-query+notifications-paramvalue-format-special": "Con formatu pa la páxina Special:Notifications (¡y solo pa esa!) Nun t'enfotes nel HTML, porque puede camudar en cualquier momentu.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Anticuáu</span>. Usa <kbd>$1format=model</kbd> pa datos en bruto",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Anticuáu</span>. Usa <kbd>$1format=model</kbd> pa datos en bruto",
+ "apihelp-query+notifications-param-limit": "El máximu númberu de notificaciones a devolver.",
+ "apihelp-query+notifications-param-wikis": "Llista de wikis de les que llograr notificaciones (de manera predeterminada, sólo la wiki actual).",
+ "apihelp-query+notifications-param-crosswikisummary": "Verdadero pa suscribite a un resume de notificaciones en wikis foriates.",
+ "apihelp-query+notifications-param-alertcontinue": "Cando tean disponibles más resultaos d'alerta, usa esto pa siguir.",
+ "apihelp-query+notifications-param-unreadfirst": "Si hai qu'amosar primero los avisos d'alertes sin lleer (sólo s'usa si nun ta activao groupbysection).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Si hai qu'amosar primero los avisos de mensaxes sin lleer (usao sólo si ta activao groupbysection).",
+ "apihelp-query+notifications-param-messagecontinue": "Cando tean disponibles más resultaos de mensaxes, usa esto pa siguir.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Si hai qu'amosar primero los avisos d'alertes sin lleer (usao sólo si ta activao groupbysection).",
+ "apihelp-query+notifications-param-titles": "Namái devolver los avisos d'estes páxines. Pa recibir avisos que nun tean venceyaos con nenguna páxina, usa [] como títulu.",
+ "apihelp-query+notifications-param-bundle": "Si hai qu'amosar los avisos compatibles con agrupamientu non lleíos acordies coles regles d'agrupamientu de tipos de notificación.",
+ "apihelp-query+notifications-example-1": "Llista d'avisos",
+ "apihelp-query+notifications-example-2": "Llista d'avisos, agrupaos por seición, incluyendo contadores",
+ "apihelp-query+unreadnotificationpages-description": "Llograr les páxines pa les qu'hai notificaciones ensin lleer pal usuariu actual.",
+ "apihelp-query+unreadnotificationpages-summary": "Llograr les páxines pa les qu'hai notificaciones ensin lleer pal usuariu actual.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Agrupar les páxines d'alderique xunto coles sos páxines principales, y agrupar los avisos non asociaos con una páxina xuntos colos de la páxina del usuariu actual.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Númberu máximu de páxines a devolver.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Llista de wikis de les que llograr les páxines con avisos ensin lleer (de manera predeterminada, sólo la wiki actual).",
+ "apihelp-query+unreadnotificationpages-example-1": "Llista páxines con (la cantidá de) notificaciones ensin lleer",
+ "apihelp-echoarticlereminder-summary": "Pidir un recordatoriu futuru sobre l'artículu especificáu",
+ "apihelp-echoarticlereminder-param-pageid": "ID del artículu del que recordar al usuariu",
+ "apihelp-echoarticlereminder-param-title": "Títulu del artículu del que recordar al usuariu",
+ "apihelp-echoarticlereminder-param-timestamp": "Marca de tiempu na que recordar al usuariu",
+ "apihelp-echoarticlereminder-param-comment": "Comentariu opcional del usuariu a incluir nel recordatoriu",
+ "apihelp-echoarticlereminder-example-1": "Crear un avisu recordatoriu d'artículu pa mañana con comentariu",
+ "apihelp-echoarticlereminder-example-2": "Crear un avisu recordatoriu d'artículu pa mañana ensin comentariu",
+ "apiwarn-echo-deprecation-timestampformat": "El formatu de marca de tiempu MW a usar pa la salida tá anticuáu equí. Nel futuru siempre va usase ISO_8601 pal formatu de salida de marca de tiempu. Axusta'l to cliente y configura <var>timestampFormat</var> como <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> ta anticuáu y desaniciaráse ceo. Usa <kbd>notformat=model</kbd> p'algamar los datos en bruto o <kbd>notformat=special</kbd> pa HTML pre-representáu.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> ta anticuáu y desaniciaráse ceo. Usa <kbd>notformat=special</kbd> nel so llugar.",
+ "apierror-echo-event-creation-failed": "Nun pudo crease una actividá d'Echo"
+}
diff --git a/Echo/i18n/api/ba.json b/Echo/i18n/api/ba.json
new file mode 100644
index 00000000..56dc6913
--- /dev/null
+++ b/Echo/i18n/api/ba.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sagan",
+ "Айсар",
+ "Лилиә",
+ "Янмурза Баки"
+ ]
+ },
+ "apihelp-echomarkread-description": "Ҡулланыусы өсөн барлыҡ белдереүҙәрҙее уҡылған тип билдәләү",
+ "apihelp-echomarkread-param-list": "Уҡылмағандар тип билдәләү өсөн ID белдереүҙәр исемлеге",
+ "apihelp-echomarkread-param-unreadlist": "Уҡылмағандар тип билдәләү өсөн ID белдереүҙәр исемлеге",
+ "apihelp-echomarkread-param-all": "Әгәр күрһәтелһә, ҡулланыусының бөтә белдереүҙәрен уҡылған тип билдәләй",
+ "apihelp-echomarkread-param-sections": " Уҡылған тип билдәләү өсөн бүлектәр исемлеге",
+ "apihelp-echomarkread-example-1": "8-се белдереүҙе уҡылған тип билдәләргә",
+ "apihelp-echomarkread-example-2": "Барлыҡ белдереүҙәрҙе уҡылған тип билдәләү",
+ "apihelp-echomarkread-example-3": "1-се белдереүҙе уҡылмаған тип билдәләргә",
+ "apihelp-echomarkseen-description": "Был ҡулланыусы өсөн барлыҡ белдереүҙәрҙе уҡылған тип билдәләү",
+ "apihelp-echomarkseen-example-1": "Бөтә типтағы белдереүҙәрҙе уҡылған тип билдәләргә",
+ "apihelp-echomarkseen-param-type": "Уҡылған билдәләренә белдереүҙәр төрө: 'alert', 'message' йәки 'all'.",
+ "apihelp-query+notifications-description": "Ағымдағы ҡатнашыусыны көткән, белдереүҙәрҙе алырға",
+ "apihelp-query+notifications-param-prop": "Ихтыяж ваҡлыҡтары",
+ "apihelp-query+notifications-param-sections": "Талаптар өсөн белдереү бүлектәр (йәки ниндәйҙер тура килеү 'alert' һәм 'message')",
+ "apihelp-query+notifications-param-groupbysection": "Бүлектәр буйынса алынған һөҙөмтәне төркөмгә айырыу кәрәкме. Алдан күрһәтелһә, һәр бүлек айырым сығарыла.",
+ "apihelp-query+notifications-param-filter": "Кире ҡайтарылған белдереүҙәрҙе һөҙөргә.",
+ "apihelp-query+notifications-param-format": "Бойороҡ бирелһә, хәбәрҙәр ошолай форматлаштырып кире ҡайтарыласаҡ.",
+ "apihelp-query+notifications-paramvalue-format-text": "Текст форматы",
+ "apihelp-query+notifications-paramvalue-format-model": "Эшкәртелмәгән белдереү мәғлүмәттәре",
+ "apihelp-query+notifications-paramvalue-format-special": "Ошо Special:Notifications бите өсөн генә (!) форматлаштырылған. Был HTMLға ышанмағыҙ, ул ҡапыл ғына үҙгәреүе мөмкин.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Иҫкергән</span>. Тәүге күрһәткестәргә <kbd>$1format=model</kbd> ҡулланығыҙ",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Иҫкергән</span>. Тәүге күрһәткестәргә <kbd>$1format=model</kbd> ҡулланығыҙ",
+ "apihelp-query+notifications-param-limit": "Кире ҡайтарылған белдереүҙәрҙең иң күп һаны",
+ "apihelp-query+notifications-param-alertcontinue": "Иғтибарлыраҡ булһағыҙ, һөҙөмтәләрегеҙ күберәк буласаҡ, был функцияны дауам итеү өсөн файҙаланығыҙ.",
+ "apihelp-query+notifications-param-unreadfirst": "Уҡылмаған иҫкәртеүҙәрҙе беренсе сиратта күрһәтергә кәрәкме (groupbysection булған осраҡта ғына ҡулланыла).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Уҡылмаған иҫкәртеүҙәрҙе беренсе сиратта күрһәтергә кәрәкме (groupbysection булған осраҡта ғына ҡулланыла).",
+ "apihelp-query+notifications-param-messagecontinue": "Хәбәрҙәр өсөн һөҙөмтәләр күберәк булһа, был функцияны дауам итеү өсөн файҙаланығыҙ.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Уҡылмаған иҫкәртеүҙәрҙе беренсе сиратта күрһәтергә кәрәкме (groupbysection булған осраҡта ғына ҡулланыла).",
+ "apihelp-query+notifications-example-1": "Белдерүҙәр исемлеге",
+ "apihelp-query+notifications-example-2": "Һаны күрһәтелеп, төркөмләп бүленгән белдереүҙәр исемлеге."
+}
diff --git a/Echo/i18n/api/bg.json b/Echo/i18n/api/bg.json
new file mode 100644
index 00000000..2d719035
--- /dev/null
+++ b/Echo/i18n/api/bg.json
@@ -0,0 +1,47 @@
+{
+ "@metadata": {
+ "authors": [
+ "StanProg",
+ "Vodnokon4e"
+ ]
+ },
+ "apihelp-echomarkread-description": "Отбелязване на съобщенията от този потребител като прочетени.",
+ "apihelp-echomarkread-param-list": "Списък на ID известията за маркиране като прочетени.",
+ "apihelp-echomarkread-param-unreadlist": "Списък на ID известията за маркиране като непрочетени",
+ "apihelp-echomarkread-param-all": "Ако е зададено, означи всички известия от потребители като прочетени.",
+ "apihelp-echomarkread-param-sections": "Списък на разделите за маркиране като прочетени.",
+ "apihelp-echomarkread-example-1": "Отбелязване на известие 8 като прочетено",
+ "apihelp-echomarkread-example-2": "Отбелязване на всички съобщения като прочетени",
+ "apihelp-echomarkread-example-3": "Отбелязване на известие 1 като прочетено",
+ "apihelp-echomarkseen-description": "Отбелязване на известията за този потребител като видяни.",
+ "apihelp-echomarkseen-example-1": "Отбелязване на известията от всички видове като видяни",
+ "apihelp-echomarkseen-param-type": "Вид съобщения за маркиране като прочетени: 'предупреждение', 'съобщение' или 'всички'.",
+ "apihelp-echomarkseen-param-timestampFormat": "Формат за дата и време в изходните данни, „ISO_8601“ или „MW“. Тук „MW“ е отхвърлен, и всички клиенти трябва да се прехвърлят на „ISO_8601“. Този параметър ще бъде отстранен, а „ISO_8601“ ще стане единствения формат за изходни данни.",
+ "apihelp-query+notifications-description": "Получаване на известия, чакащи текущия потребител.",
+ "apihelp-query+notifications-param-prop": "Подробности за заявката.",
+ "apihelp-query+notifications-param-sections": "Раздели за уведомяване по заявка (например комбинация от 'предупреждение' и 'съобщения').",
+ "apihelp-query+notifications-param-groupbysection": "Дали да са групират резултатите по раздел. Ако е зададено, всеки раздел се задава поотделно.",
+ "apihelp-query+notifications-param-filter": "Филтриране на върнатите известия.",
+ "apihelp-query+notifications-param-format": "Ако е указано, известията ще се завръщат форматирани по този начин.",
+ "apihelp-query+notifications-paramvalue-format-model": "Необработени данни за съобщения",
+ "apihelp-query+notifications-paramvalue-format-special": "Форматирано за служебната страница за известия (и само за това!) Не разчитайте на HTML, тъй като може да се промени по всяко време.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Отхвърлено</span>. Използвайте <kbd>$1format=model</kbd> за изходните данни",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Отхвърлено</span>. Използвайте <kbd>$1format=model</kbd> за изходните данни",
+ "apihelp-query+notifications-param-limit": "Максимален брой на върнати съобщения.",
+ "apihelp-query+notifications-param-wikis": "Списък на уикита, от които искате да получавате известия (по подразбиране — само текущото уики).",
+ "apihelp-query+notifications-param-crosswikisummary": "Право на включване в обобщена нотификация за уведомления от чуждестранни уикита.",
+ "apihelp-query+notifications-param-alertcontinue": "Използвайте тази опция за да продължите, когато са налице повече резултати за известия.",
+ "apihelp-query+notifications-param-unreadfirst": "Дали първоначално да се показват непрочетените известия (използва се само ако groupbysection не е зададено).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Дали първоначално да се показват непрочетените известия (използва се само ако groupbysection е зададено).",
+ "apihelp-query+notifications-param-messagecontinue": "Използвайте тази опция за да продължите, когато са налице повече резултати за съобщения.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Дали първоначално да се показват непрочетените съобщения (използва се само ако groupbysection е зададено).",
+ "apihelp-query+notifications-param-titles": "Извежда съобщения само за тези страници. За да получите съобщение, които не е свързано с нито една страница, вместо името използвайте [].",
+ "apihelp-query+notifications-param-bundle": "Дали да се показват включените съвместими непрочетени известия, според вида на правилата за видове известяване.",
+ "apihelp-query+notifications-example-1": "Списък на известията",
+ "apihelp-query+notifications-example-2": "Списък с известия, групирани в раздели, с посочване на броя им",
+ "apihelp-query+unreadnotificationpages-description": "Получи страници, за които има непрочетени известия за текущия потребител.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Групиране на беседи заедно с беседите им, и групиране на съобщенията, които не са свързани със страница, заедно със страницата на текущия потребител.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Максимален брой на страници за връщане.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Списък на уикита с непрочетени известия (по подразбиране — само текущото уики).",
+ "apihelp-query+unreadnotificationpages-example-1": "Списък на страници с (брой) непрочетени съобщения"
+}
diff --git a/Echo/i18n/api/bn.json b/Echo/i18n/api/bn.json
new file mode 100644
index 00000000..f5c426cc
--- /dev/null
+++ b/Echo/i18n/api/bn.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aftabuzzaman"
+ ]
+ },
+ "apihelp-echomarkread-description": "বর্তমান ব্যবহারকারীর জন্য বিজ্ঞপ্তি পঠিত হিসাবে চিহ্নিত করে।",
+ "apihelp-echomarkread-example-1": "বিজ্ঞপ্তি ৮ দেখা হয়েছে হিসাবে চিহ্নিত করে",
+ "apihelp-echomarkread-example-2": "সকল বিজ্ঞপ্তি পঠিত হিসেবে চিহ্নিত করুন",
+ "apihelp-echomarkseen-example-1": "সব ধরনের বিজ্ঞপ্তি দেখা হয়েছে হিসাবে চিহ্নিত করে",
+ "apihelp-query+notifications-param-prop": "অনুরোধের বিবরণ।",
+ "apihelp-query+notifications-param-messagecontinue": "যখন আরো বার্তা ফলাফল উপলব্ধ থাকে, তা অব্যাহত রাখার জন্য এটি ব্যবহার করুন।",
+ "apihelp-query+notifications-example-1": "বিজ্ঞপ্তির তালিকা",
+ "apihelp-query+notifications-example-2": "বিজ্ঞপ্তির তালিকা, গণনাসহ, দলগতভাবে অনুচ্ছেদে ভাগ করা"
+}
diff --git a/Echo/i18n/api/bs.json b/Echo/i18n/api/bs.json
new file mode 100644
index 00000000..be4dc742
--- /dev/null
+++ b/Echo/i18n/api/bs.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Srdjan m"
+ ]
+ },
+ "apihelp-query+notifications-example-1": "Ispiši obavještenja"
+}
diff --git a/Echo/i18n/api/ca.json b/Echo/i18n/api/ca.json
new file mode 100644
index 00000000..b202c77c
--- /dev/null
+++ b/Echo/i18n/api/ca.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Toniher"
+ ]
+ },
+ "apihelp-echomarkread-example-2": "Marca totes les notificacions com a llegides",
+ "apihelp-query+notifications-param-prop": "Detalls per sol·licitar.",
+ "apihelp-query+notifications-param-wikis": "Llista de wikis d'on recollir les notificacions (per defecte només el wiki actual).",
+ "apihelp-query+notifications-example-1": "Llista les notificacions"
+}
diff --git a/Echo/i18n/api/ce.json b/Echo/i18n/api/ce.json
new file mode 100644
index 00000000..3cc79364
--- /dev/null
+++ b/Echo/i18n/api/ce.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Умар"
+ ]
+ },
+ "apihelp-echomarkread-description": "Билгалде дӀахаийтарш хьаьжна сана.",
+ "apihelp-echomarkread-param-list": "Хьажжина сана билгалдаран ID дӀахаийтарийн могӀам.",
+ "apihelp-echomarkread-param-all": "Декъашхочун массо дӀахаийтарш дешна санна билгалдо.",
+ "apihelp-echomarkread-param-sections": "Хьажжина сана билгалдаран декъийн могӀам.",
+ "apihelp-echomarkread-example-1": "Билгалде 8 дӀахаийтар дешна санна",
+ "apihelp-echomarkread-example-2": "Билгалде массо дӀахаийтарш дешна санна",
+ "apihelp-echomarkseen-description": "Билгалде хӀокху декъашхочун дӀахаийтарш дешна сана.",
+ "apihelp-echomarkseen-example-1": "Билгалде массо тайпа долу дӀахаийтарш дешна санна",
+ "apihelp-query+notifications-param-prop": "Дехарна ма-дарра.",
+ "apihelp-query+notifications-param-filter": "Юхадирзина дӀахаийтарш литта.",
+ "apihelp-query+notifications-paramvalue-format-text": "Йозанан формат",
+ "apihelp-query+notifications-paramvalue-format-model": "Кечъбанза дӀахаийтаран хаамаш",
+ "apihelp-query+notifications-example-1": "ДӀахаийтарийн могӀам",
+ "apihelp-query+unreadnotificationpages-param-limit": "Юхаялоран агӀонийн максимале дукхалла"
+}
diff --git a/Echo/i18n/api/cs.json b/Echo/i18n/api/cs.json
new file mode 100644
index 00000000..74d20653
--- /dev/null
+++ b/Echo/i18n/api/cs.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Martin Urbanec",
+ "Mormegil"
+ ]
+ },
+ "apihelp-echomarkread-example-2": "Označit všechny upozornění jako přečtené",
+ "apihelp-echomarkseen-example-1": "Označit oznámení všech typů jako přečtená"
+}
diff --git a/Echo/i18n/api/de.json b/Echo/i18n/api/de.json
new file mode 100644
index 00000000..ed7e2fe9
--- /dev/null
+++ b/Echo/i18n/api/de.json
@@ -0,0 +1,51 @@
+{
+ "@metadata": {
+ "authors": [
+ "MGChecker",
+ "Metalhead64",
+ "Purodha",
+ "Tiin"
+ ]
+ },
+ "apihelp-echomarkread-description": "Benachrichtigungen für den aktuellen Benutzer als gelesen markieren.",
+ "apihelp-echomarkread-param-list": "Eine Liste von Benachrichtigungskennungen, um sie als gelesen zu markieren.",
+ "apihelp-echomarkread-param-unreadlist": "Eine Liste mit Benachrichtigungskennungen, die als ungelesen markiert werden sollen.",
+ "apihelp-echomarkread-param-all": "Falls festgelegt, markiert alle Benutzerbenachrichtigungen als gelesen.",
+ "apihelp-echomarkread-param-sections": "Eine Liste der Abschnitte, die als gelesen markiert werden sollen.",
+ "apihelp-echomarkread-example-1": "Benachrichtigung 8 als gelesen markieren",
+ "apihelp-echomarkread-example-2": "Alle Benachrichtigungen als gelesen markieren",
+ "apihelp-echomarkread-example-3": "Markiert die Benachrichtigung 1 als ungelesen",
+ "apihelp-echomarkseen-description": "Benachrichtigungen für den derzeitigen Benutzer als gesehen markieren.",
+ "apihelp-echomarkseen-example-1": "Benachrichtigungen aller Typen als gesehen markieren",
+ "apihelp-echomarkseen-param-type": "Benachrichtigungstypen, die als gesehen markiert werden sollen: „alert“, „message“ oder „all“.",
+ "apihelp-echomarkseen-param-timestampFormat": "Zu verwendendes Zeitstempelformat für die Ausgabe. „ISO_8601“ oder „MW“. „MW“ ist hier veraltet, so dass alle Clients auf „ISO_8601“ wechseln sollten. Dieser Parameter wird entfernt und „ISO_8601“ wird das einzige Ausgabeformat.",
+ "apihelp-query+notifications-description": "Benachrichtigungen abrufen, die auf den aktuellen Benutzer warten.",
+ "apihelp-query+notifications-param-prop": "Einzelheiten der Anfrage.",
+ "apihelp-query+notifications-param-sections": "Die abzufragenden Benachrichtigungsabschnitte (z.&nbsp;B. eine Kombination aus „alert“ und „message“).",
+ "apihelp-query+notifications-param-groupbysection": "Ob das Ergebnis nach Abschnitt gruppiert werden soll. Jeder Abschnitt wird separat abgerufen, wenn es eingestellt wird.",
+ "apihelp-query+notifications-param-filter": "Filtert zurückgegebene Benachrichtigungen.",
+ "apihelp-query+notifications-param-format": "Falls angegeben, werden die zurückgegebenen Benachrichtigungen auf diese Weise formatiert.",
+ "apihelp-query+notifications-paramvalue-format-model": "Rohe Benachrichtigungsdaten",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Veraltet</span>. Für Rohdaten <kbd>$1format=model</kbd> verwenden.",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Veraltet</span>. Für Rohdaten <kbd>$1format=model</kbd> verwenden.",
+ "apihelp-query+notifications-param-limit": "Die maximale Anzahl zurückzugebender Benachrichtigungen.",
+ "apihelp-query+notifications-param-wikis": "Liste der Wikis, von denen Benachrichtigungen abgerufen werden sollen (standardmäßig nur das aktuelle Wiki).",
+ "apihelp-query+notifications-param-alertcontinue": "Falls mehr Alarmergebnisse verfügbar sind, dies zum Fortfahren verwenden.",
+ "apihelp-query+notifications-param-unreadfirst": "Ob ungelesene Benachrichtigungen zuerst angezeigt werden sollen (wird nur verwendet, wenn groupbysection nicht festgelegt ist).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Ob ungelesene Nachrichten zuerst angezeigt werden sollen (wird nur verwendet, wenn groupbysection festgelegt ist).",
+ "apihelp-query+notifications-param-messagecontinue": "Falls mehrere Nachrichtenergebnisse verfügbar sind, dies zum Fortfahren verwenden.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Ob ungelesene Meldungen zuerst angezeigt werden sollen (wird nur verwendet, wenn groupbysection festgelegt ist).",
+ "apihelp-query+notifications-param-titles": "Gibt nur Benachrichtigungen für diese Seiten zurück. Um Benachrichtigungen abzurufen, die mit keiner bestimmten Seite verknüpft sind, verwende als Titel [].",
+ "apihelp-query+notifications-param-bundle": "Ob bündelkompatible ungelesene Benachrichtigungen übereinstimmend mit den Benachrichtigungstyp-Bündelregeln angezeigt werden sollen.",
+ "apihelp-query+notifications-example-1": "Benachrichtigungen auflisten",
+ "apihelp-query+notifications-example-2": "Benachrichtigungen auflisten, gruppiert nach Abschnitt, mit Zählern",
+ "apihelp-query+unreadnotificationpages-description": "Ruft Seiten ab, für die es für den aktuellen Benutzer ungelesene Benachrichtigungen gibt.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Gruppiert Diskussionsseiten zusammen mit ihrer dazugehörigen Seite und Gruppenbenachrichtigungen, die nicht mit einer Seite zusammen mit der aktuellen Benutzerseite verknüpft sind.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Die maximale Anzahl der zurückzugebenden Seiten.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Listet die Wikis auf, von denen Seiten mit ungelesenen Benachrichtigungen abgerufen werden sollen (Standard: Nur das aktuelle Wiki).",
+ "apihelp-query+unreadnotificationpages-example-1": "Listet Seiten mit (ihre Menge der) ungelesenen Benachrichtigungen auf",
+ "apiwarn-echo-deprecation-timestampformat": "Das MW-Zeitstempel-Ausgabeformat ist hier veraltet. In Zukunft wird immer ISO 8601 für das Ausgabezeitstempelformat verwendet. Passe deinen Client an und lege <var>timestampFormat</var> auf <kbd>ISO_8601</kbd> fest.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> ist veraltet und wird bald entfernt. Verwende <kbd>notformat=model</kbd>, um die Rohdaten zu erhalten oder <kbd>notformat=special</kbd> für vorgerendertes HTML.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> ist veraltet und wird bald entfernt. Verwende stattdessen <kbd>notformat=special</kbd>.",
+ "apierror-echo-event-creation-failed": "Es konnte kein Echo-Ereignis erstellt werden"
+}
diff --git a/Echo/i18n/api/en.json b/Echo/i18n/api/en.json
new file mode 100644
index 00000000..4ca9fb1c
--- /dev/null
+++ b/Echo/i18n/api/en.json
@@ -0,0 +1,66 @@
+{
+ "@metadata": {
+ "authors": [
+ "Brad Jorsch",
+ "Matthew Flaschen",
+ "Matthias Mullie",
+ "Moriel Schottlender",
+ "Roan Kattouw",
+ "Stephane Bisson"
+ ]
+ },
+ "apihelp-echomarkread-description": "Mark notifications as read for the current user.",
+ "apihelp-echomarkread-summary": "Mark notifications as read for the current user.",
+ "apihelp-echomarkread-param-list": "A list of notification IDs to mark as read.",
+ "apihelp-echomarkread-param-unreadlist": "A list of notification IDs to mark as unread.",
+ "apihelp-echomarkread-param-all": "If set, marks all of a user's notifications as read.",
+ "apihelp-echomarkread-param-sections": "A list of sections to mark as read.",
+ "apihelp-echomarkread-example-1": "Mark notification 8 as read",
+ "apihelp-echomarkread-example-2": "Mark all notifications as read",
+ "apihelp-echomarkread-example-3": "Mark notification 1 as unread",
+ "apihelp-echomarkseen-description": "Mark notifications as seen for the current user.",
+ "apihelp-echomarkseen-summary": "Mark notifications as seen for the current user.",
+ "apihelp-echomarkseen-example-1": "Mark notifications of all types as seen",
+ "apihelp-echomarkseen-param-type": "Type of notifications to mark as seen: 'alert', 'message' or 'all'.",
+ "apihelp-echomarkseen-param-timestampFormat": "Timestamp format to use for output, 'ISO_8601' or 'MW'. 'MW' is deprecated here, so all clients should switch to 'ISO_8601'. This parameter will be removed, and 'ISO_8601' will become the only output format.",
+ "apihelp-query+notifications-description": "Get notifications waiting for the current user.",
+ "apihelp-query+notifications-summary": "Get notifications waiting for the current user.",
+ "apihelp-query+notifications-param-prop": "Details to request.",
+ "apihelp-query+notifications-param-sections": "The notification sections to query (i.e. some combination of 'alert' and 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Whether to group the result by section. Each section is fetched separately if set.",
+ "apihelp-query+notifications-param-filter": "Filter notifications returned.",
+ "apihelp-query+notifications-param-format": "If specified, notifications will be returned formatted this way.",
+ "apihelp-query+notifications-paramvalue-format-model": "Raw notification data",
+ "apihelp-query+notifications-paramvalue-format-special": "Formatted for Special:Notifications page (and only that!) Do not rely on the HTML as it may change at any given time.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Deprecated</span>. Use <kbd>$1format=model</kbd> for raw data",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Deprecated</span>. Use <kbd>$1format=model</kbd> for raw data",
+ "apihelp-query+notifications-param-limit": "The maximum number of notifications to return.",
+ "apihelp-query+notifications-param-wikis": "List of wikis to fetch notifications from (defaults to only current wiki).",
+ "apihelp-query+notifications-param-crosswikisummary": "True to opt in to a summary notification of notifications on foreign wikis.",
+ "apihelp-query+notifications-param-alertcontinue": "When more alert results are available, use this to continue.",
+ "apihelp-query+notifications-param-unreadfirst": "Whether to show unread notifications first (only used if groupbysection is not set).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Whether to show unread message notifications first (only used if groupbysection is set).",
+ "apihelp-query+notifications-param-messagecontinue": "When more message results are available, use this to continue.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Whether to show unread alert notifications first (only used if groupbysection is set).",
+ "apihelp-query+notifications-param-titles": "Only return notifications for these pages. To get notifications not associated with any page, use [] as a title.",
+ "apihelp-query+notifications-param-bundle": "Whether to show bundle compatible unread notifications according to notification types bundling rules.",
+ "apihelp-query+notifications-example-1": "List notifications",
+ "apihelp-query+notifications-example-2": "List notifications, grouped by section, with counts",
+ "apihelp-query+unreadnotificationpages-description": "Get pages for which there are unread notifications for the current user.",
+ "apihelp-query+unreadnotificationpages-summary": "Get pages for which there are unread notifications for the current user.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Group talk pages together with their subject page, and group notifications not associated with a page together with the current user's user page.",
+ "apihelp-query+unreadnotificationpages-param-limit": "The maximum number of pages to return.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "List of wikis to fetch pages with unread notifications from (defaults to only current wiki).",
+ "apihelp-query+unreadnotificationpages-example-1": "List pages with (their amount of) unread notifications",
+ "apihelp-echoarticlereminder-summary": "Request a future reminder about the specified article",
+ "apihelp-echoarticlereminder-param-pageid": "ID of article to remind the user about",
+ "apihelp-echoarticlereminder-param-title": "Title of article to remind the user about",
+ "apihelp-echoarticlereminder-param-timestamp": "On which timestamp to remind the user",
+ "apihelp-echoarticlereminder-param-comment": "Optional user comment to include in the reminder",
+ "apihelp-echoarticlereminder-example-1" : "Create an article reminder notification for tomorrow with comment",
+ "apihelp-echoarticlereminder-example-2" : "Create an article reminder notification for tomorrow without comment",
+ "apiwarn-echo-deprecation-timestampformat": "The MW timestamp output format is deprecated here. In the future, ISO 8601 will always be used for the output timestamp format. Adjust your client and set <var>timestampFormat</var> to <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> has been deprecated and will be removed soon. Use <kbd>notformat=model</kbd> to get the raw data or <kbd>notformat=special</kbd> for pre-rendered HTML.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> has been deprecated and will be removed soon. Use <kbd>notformat=special</kbd> instead.",
+ "apierror-echo-event-creation-failed": "Could not create Echo event"
+}
diff --git a/Echo/i18n/api/es.json b/Echo/i18n/api/es.json
new file mode 100644
index 00000000..29247e72
--- /dev/null
+++ b/Echo/i18n/api/es.json
@@ -0,0 +1,46 @@
+{
+ "@metadata": {
+ "authors": [
+ "Allan Aguilar",
+ "Fitoschido",
+ "Jduranboger",
+ "Macofe"
+ ]
+ },
+ "apihelp-echomarkread-description": "Marcar notificaciones como leídas para el usuario actual.",
+ "apihelp-echomarkread-param-list": "Lista de identificaciones de notificación para marcar como leídas.",
+ "apihelp-echomarkread-param-unreadlist": "Una lista de identificadores de notificación para marcar como leídas.",
+ "apihelp-echomarkread-param-all": "Si se establece, marca todas las notificaciones de un usuario como leídas.",
+ "apihelp-echomarkread-param-sections": "Lista de secciones a marcar como leídas.",
+ "apihelp-echomarkread-example-1": "Marca la notificación 8 como leída",
+ "apihelp-echomarkread-example-2": "Marca todas las notificaciones como leídas",
+ "apihelp-echomarkread-example-3": "Marca la notificación 1 como no leída",
+ "apihelp-echomarkseen-description": "Marca las notificaciones como vistas para el usuario actual.",
+ "apihelp-echomarkseen-example-1": "Marca las notificaciones de todos los tipos como vistas",
+ "apihelp-echomarkseen-param-type": "Tipo de notificaciones para marcar como leídas: 'alert' (alerta), 'message' (mensaje) o 'all' (todas).",
+ "apihelp-query+notifications-description": "Recibe notificaciones en espera para el usuario actual.",
+ "apihelp-query+notifications-param-prop": "Detalles que solicitar.",
+ "apihelp-query+notifications-param-sections": "Las secciones de notificación para consultar (o sea, alguna combinación de «alerta» y «mensaje»).",
+ "apihelp-query+notifications-param-groupbysection": "Si se agrupan los resultados por sección. Cada sección se obtiene por separado si así se establece.",
+ "apihelp-query+notifications-param-filter": "Filtra las notificaciones recibidas.",
+ "apihelp-query+notifications-param-format": "Si se especifica, las notificaciones se recibirán en este formato.",
+ "apihelp-query+notifications-paramvalue-format-text": "Formato de texto plano",
+ "apihelp-query+notifications-paramvalue-format-model": "Datos de notificación en crudo",
+ "apihelp-query+notifications-paramvalue-format-special": "Con formato para la página Special:Notifications (¡y solo esa!) No confíes en el HTML, ya que puede cambiar en cualquier momento.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Desaconsejado</span>. Usa <kbd>$1format=model</kbd> para datos en crudo",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Desaconsejado</span>. Usa <kbd>$1format=model</kbd> para datos en crudo",
+ "apihelp-query+notifications-param-limit": "Número máximo de notificaciones a recibir.",
+ "apihelp-query+notifications-param-wikis": "Lista de wikis desde las cuales obtener notificaciones (usa el wiki actual de manera predeterminada).",
+ "apihelp-query+notifications-param-alertcontinue": "Cuando haya más resultados de alerta disponibles, utiliza esto para continuar.",
+ "apihelp-query+notifications-param-unreadfirst": "Si se muestran las notificaciones sin leer primero (sólo se utiliza si se establece groupbysection).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Si se muestran las notificaciones de mensajes sin leer primero (sólo se usa si se establece groupbysection).",
+ "apihelp-query+notifications-param-messagecontinue": "Cuando haya más resultados de mensajes disponibles, utiliza esto para continuar.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Si se muestran las notificaciones de alertas sin leer primero (sólo se utiliza si se establece groupbysection).",
+ "apihelp-query+notifications-param-titles": "Sólo devolver las notificaciones de estas páginas. Para obtener notificaciones no asociadas a ninguna página, usa [] como un título.",
+ "apihelp-query+notifications-example-1": "Lista de notificaciones",
+ "apihelp-query+notifications-example-2": "Lista notificaciones, agrupadas por sección, incluyendo contadores",
+ "apihelp-query+unreadnotificationpages-description": "Obtener las páginas para las que hay notificaciones sin leer para el usuario actual.",
+ "apihelp-query+unreadnotificationpages-param-limit": "El máximo número de páginas que se devolverán.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Lista de wikis desde las cuales obtener notificaciones sin leer (usa el wiki actual de manera predeterminada).",
+ "apihelp-query+unreadnotificationpages-example-1": "Lista páginas con (la cantidad de) notificaciones sin leer"
+}
diff --git a/Echo/i18n/api/et.json b/Echo/i18n/api/et.json
new file mode 100644
index 00000000..54636106
--- /dev/null
+++ b/Echo/i18n/api/et.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pikne"
+ ]
+ },
+ "apihelp-echomarkread-description": "Antud kasutaja teavituste loetuks märkimine.",
+ "apihelp-echomarkread-param-list": "Loetelu identifikaatoritest, mida märkida loetuks.",
+ "apihelp-echomarkread-param-all": "Kui valitud, märgitakse kõik kasutaja teavitused loetuks.",
+ "apihelp-echomarkread-param-sections": "Loetelu jaotistest, mida märkida loetuks.",
+ "apihelp-echomarkread-example-1": "Märgi teavitus 8 loetuks",
+ "apihelp-echomarkread-example-2": "Märgi kõik teavitused loetuks",
+ "apihelp-echomarkseen-description": "Antud kasutaja teavituste nähtuks märkimine.",
+ "apihelp-echomarkseen-example-1": "Märgi igat tüüpi teavitused nähtuks",
+ "apihelp-echomarkseen-param-type": "Mis tüüpi teavitused märkida nähtuks: 'alert' (märguanne), 'message' (sõnum) või 'all' (kõik).",
+ "apihelp-query+notifications-description": "Antud kasutaja tähelepanu ootavate teavituste hankimine.",
+ "apihelp-query+notifications-param-prop": "Päringu üksikasjad.",
+ "apihelp-query+notifications-param-sections": "Päritav teavituste jaotis (s.o kombinatsioon tüüpidest 'alert' ja 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Kas rühmitada tulemus jaotiste kaupa. Kui valitud, tehakse väljavõte iga jaotise kohta eraldi.",
+ "apihelp-query+notifications-param-filter": "Tagastatavate teavituste filtrimine.",
+ "apihelp-query+notifications-param-format": "Kui määratud, tagastatakse teavitused sellises vormingus.",
+ "apihelp-query+notifications-param-limit": "Tagastatavate teavituste ülemmäär.",
+ "apihelp-query+notifications-param-alertcontinue": "Kui tulemustes on saadaval rohkem märguandeid, kasutada seda jätkamiseks.",
+ "apihelp-query+notifications-param-alertunreadfirst": "Kas näidata kõigepealt lugemata sõnumeid (kasutuses ainult siis, kui \"groupbysection\" on määratud).",
+ "apihelp-query+notifications-param-messagecontinue": "Kui tulemustes on saadaval rohkem sõnumeid, kasutada seda jätkamiseks.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Kas näidata kõigepealt lugemata teavitusi (kasutuses ainult siis, kui \"groupbysection\" on määratud).",
+ "apihelp-query+notifications-example-1": "Loetle teavitused",
+ "apihelp-query+notifications-example-2": "Loetle teavitused jaotiste kaupa üldarvudega"
+}
diff --git a/Echo/i18n/api/eu.json b/Echo/i18n/api/eu.json
new file mode 100644
index 00000000..550c8e9f
--- /dev/null
+++ b/Echo/i18n/api/eu.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mikel Ibaiba",
+ "Subi"
+ ]
+ },
+ "apihelp-query+notifications-example-1": "Zerrendatu jakinarazpenak",
+ "apihelp-query+notifications-example-2": "Zerrendatu jakinarazpenak, atalka antolaturik, kontagailuekin",
+ "apihelp-echoarticlereminder-summary": "Etorkizunerako artikulu espezifiko baten oroigarria eskatu",
+ "apihelp-echoarticlereminder-param-pageid": "Identifikazio artikulua erabiltzaileari gogorarazteko",
+ "apihelp-echoarticlereminder-param-title": "Artikuluaren izenburua erabiltzaileari gogorarazteko",
+ "apihelp-echoarticlereminder-param-comment": "Aukerako oharra erabiltzaileari gogorarazteko",
+ "apihelp-echoarticlereminder-example-1": "Biharko jakinarazpenean oharra duen arkikulua sortu",
+ "apihelp-echoarticlereminder-example-2": "Biharko jakinarazpenean oharrik gabeko arkikulua sortu",
+ "apierror-echo-event-creation-failed": "Ezin izan da Echo ekitaldia sortu"
+}
diff --git a/Echo/i18n/api/fa.json b/Echo/i18n/api/fa.json
new file mode 100644
index 00000000..e62d6109
--- /dev/null
+++ b/Echo/i18n/api/fa.json
@@ -0,0 +1,66 @@
+{
+ "@metadata": {
+ "authors": [
+ "4nn1l2",
+ "Dalba",
+ "Huji",
+ "Mjbmr",
+ "Reza1615",
+ "فلورانس"
+ ]
+ },
+ "apihelp-echomarkread-description": "آگاهی‌ها برای کاربر کنونی به عنوان خوانده‌شده نشانه‌گذاری شوند.",
+ "apihelp-echomarkread-summary": "علامت گذاری آگاه‌سازی‌ها به عنوان خوانده شده برای کاربر فعلی",
+ "apihelp-echomarkread-param-list": "فهرستی از شناسه های آگاه سازی به عنوان خوانده شده",
+ "apihelp-echomarkread-param-unreadlist": "فهرستی از شناسه‌های آگاه‌سازی برای علامت زدن به عنوان خوانده‌نشده",
+ "apihelp-echomarkread-param-all": "اگر تنظیم شده‌باشد، همهٔ آگهی‌های یک کاربر به عنوان خوانده‌شده نشانه‌گذاری شوند.",
+ "apihelp-echomarkread-param-sections": "فهرستی از شناسه های آگاه سازی به عنوان خوانده شده",
+ "apihelp-echomarkread-example-1": "علامت‌گذاری آگاه‌سازی 8 به عنوان خوانده شده",
+ "apihelp-echomarkread-example-2": "علامت‌گذاری تمامی اعلان‌ها به عنوان خوانده شده",
+ "apihelp-echomarkread-example-3": "علامت‌گذاری آگاه‌سازی 1 به عنوان خوانده‌نشده",
+ "apihelp-echomarkseen-description": "علامت گذاری به عنوان اطلاعیه خوانده شده برای کاربر فعلی",
+ "apihelp-echomarkseen-summary": "علامت گذاری آگاه‌سازی‌ها به عنوان دیده شده برای کاربر فعلی.",
+ "apihelp-echomarkseen-example-1": "علامت‌گذاری همهٔ انواع اعلان‌ها به عنوان دیده‌شده",
+ "apihelp-echomarkseen-param-type": "نوع اعلان‌هایی که خوانده‌شده علامت زده شوند: «آگاه‌سازی»، «پیام»، یا «همه»",
+ "apihelp-echomarkseen-param-timestampFormat": "ساختار تاریخ استفاده شده برای خروجی 'ISO_8601' یا 'MW' است. 'MW' در اینجا دیگر مورد استفاده نیست در نتیجه همهٔ کاربران باید از 'ISO_8601' استفاده کنند. این متغییر حذف خواهد شد و 'ISO_8601' به عنوان تنها ساختار خروجی انتخاب خواهد شد.",
+ "apihelp-query+notifications-description": "دریافت اعلان‌های منتظر کاربر کنونی.",
+ "apihelp-query+notifications-summary": "دریافت اعلان‌های منتظر کاربر کنونی.",
+ "apihelp-query+notifications-param-prop": "جزئیات به درخواست.",
+ "apihelp-query+notifications-param-sections": "بخش آگاه‌سازی پرسمان (مانند هشدار و پیام بعضی از مشارکت‌ها)",
+ "apihelp-query+notifications-param-groupbysection": "برای گروه‌بندی نتایج توسط بخش، در صورت تنظیم هر بخش به صورت جداگانه دریافت می‌شود.",
+ "apihelp-query+notifications-param-filter": "پالایش آگاه‌سازی‌های دریافتی",
+ "apihelp-query+notifications-param-format": "در صورت تخصیص داده شدن، آگاه‌سازی‌ها به صورت این فرمت بازگردانده می‌شوند.",
+ "apihelp-query+notifications-paramvalue-format-model": "اطلاعات خام آگاه‌سازی",
+ "apihelp-query+notifications-paramvalue-format-special": "ساختار یافته برای صفحهٔ Special:Notifications (فقط برای آن!) به HTML توجه نکنید که هر زمان ممکن است عوض شود.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">نهی شده</span>. از <kbd>$1format=model</kbd> برای اطلاعات خام استفاده کنید",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">نهی شده</span>. از <kbd>$1format=model</kbd> برای اطلاعات خام استفاده کنید",
+ "apihelp-query+notifications-param-limit": "حداکثر تعداد آگاه‌سازی‌ها برگردانده شده.",
+ "apihelp-query+notifications-param-wikis": "فهرست ویکی‌هایی که آگاه‌سازی از آنها دریافت می‌شود (پیش‌فرض فقط این ویکی)",
+ "apihelp-query+notifications-param-crosswikisummary": "True to opt in to a summary notification of notifications on foreign wikis.",
+ "apihelp-query+notifications-param-alertcontinue": "زمانی که هشدارهای زیادی موجود هست، از این برای ادامه دادن استفاده کنید.",
+ "apihelp-query+notifications-param-unreadfirst": "برای نمایش آگاه‌سازی‌های مطالعه نشده در ابتدا (فقط اگر گروه بندی بر پایهٔ بخش تنظیم نشده‌باشد، استفاده می‌شود).",
+ "apihelp-query+notifications-param-alertunreadfirst": "برای نمایش آگاه‌سازی‌های خوانده نشده در ابتدای کار (فقط اگر گروه بندی بر پایهٔ بخش تنظیم نشده‌باشد، استفاده می‌شود).",
+ "apihelp-query+notifications-param-messagecontinue": "زمانی که هشدارهای زیادی موجود هست، از این برای ادامه دادن استفاده کنید.",
+ "apihelp-query+notifications-param-messageunreadfirst": "برای نمایش آگاه‌سازی‌های خوانده‌نشده در ابتدای کار (فقط اگر گروه بندی بر پایهٔ بخش تنظیم نشده‌باشد، استفاده می‌شود).",
+ "apihelp-query+notifications-param-titles": "Only return notifications for these pages. To get notifications not associated with any page, use [] as a title.",
+ "apihelp-query+notifications-param-bundle": "\nWhether to show bundle compatible unread notifications according to notification types bundling rules.",
+ "apihelp-query+notifications-example-1": "اعلان‌ها را فهرست کن",
+ "apihelp-query+notifications-example-2": "فهرست اعلان‌ها، بخش بندیش شده، همراه با شمار آن‌ها.",
+ "apihelp-query+unreadnotificationpages-description": "دریافت صفحه‌هایی که برایش آگاه‌سازی‌های خوانده‌نشده‌ای برای کاربر فعلی وجود دارد.",
+ "apihelp-query+unreadnotificationpages-summary": "دریافت صفحه‌هایی که برایش آگاه‌سازی‌های خوانده‌نشده‌ای برای کاربر فعلی وجود دارد.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "گروه صفحهٔ بحث‌ها همراه با صفحهٔ موضوعشان و آگاه‌سازی گروهی ارتباطی به صفحهٔ کاربری این کاربر ندارد.",
+ "apihelp-query+unreadnotificationpages-param-limit": "حداکثر صفحاتی که برگردانده می‌شود.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "فهرست ویکی‌هایی که آگاه‌سازی از آنها دریافت می‌شود (پیش‌فرض فقط این ویکی).",
+ "apihelp-query+unreadnotificationpages-example-1": "فهرست کردن صفحه‌ها همراه (مقدار) آگاه‌سازی‌های خوانده‌نشده",
+ "apihelp-echoarticlereminder-summary": "درخواست یادآور برای یک مقالهٔ خاص",
+ "apihelp-echoarticlereminder-param-pageid": "شناسهٔ مقاله برای یادآوری به کاربر",
+ "apihelp-echoarticlereminder-param-title": "عنوان مقاله برای یادآوری به کاربر",
+ "apihelp-echoarticlereminder-param-timestamp": "در چه زمانی یادآوری به کاربر انجام شد",
+ "apihelp-echoarticlereminder-param-comment": "توضیح اختیاری کاربر برای یادآوری",
+ "apihelp-echoarticlereminder-example-1": "ساخت یادآوری برای فردا همراه با توضیح",
+ "apihelp-echoarticlereminder-example-2": "ساخت یادآوری برای فردا همراه بدون توضیح",
+ "apiwarn-echo-deprecation-timestampformat": "قالب خروجی مدیاویکی در اینجا منسوخ شده‌است. در آینده، ایزو ۸۶۰۱ همواره برای قالب خروجی برچسب زمان استفاده خواهد شد. برنامهٔ خود را تنظیم کنید و <var>timestampFormat</var> را برابر <kbd>ISO_8601</kbd> قرار دهید.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> منسوخ شده و به زودی حذف خواهد شد. از <kbd>notformat=model</kbd> برای گرفتن داده‌های خام و از <kbd>notformat=special</kbd> برای گرفتن اچ‌تی‌ام‌ال استفاده کنید.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> منسوخ شده و به زودی حذف خواهد شد. به جای آن از <kbd>notformat=special</kbd> استفاده کنید.",
+ "apierror-echo-event-creation-failed": "امکان ساخت رویداد سامانه آگاه‌سازی وجود ندارد"
+}
diff --git a/Echo/i18n/api/fi.json b/Echo/i18n/api/fi.json
new file mode 100644
index 00000000..9d8a8419
--- /dev/null
+++ b/Echo/i18n/api/fi.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Nike",
+ "Pxos"
+ ]
+ },
+ "apihelp-echomarkread-description": "Merkitse ilmoitukset luetuiksi nykyisen käyttäjän kohdalla.",
+ "apihelp-echomarkread-param-list": "Luettelo niistä ilmoitusten tunnusnumeroista, jotka voi merkitä luetuiksi.",
+ "apihelp-echomarkread-param-all": "Jos tämä on valittu, kaikki käyttäjän ilmoitukset merkitään luetuiksi.",
+ "apihelp-echomarkread-param-sections": "Luettelo osioista, jotka voi merkitä luetuiksi.",
+ "apihelp-echomarkread-example-1": "Merkitse ilmoitus 8 luetuksi.",
+ "apihelp-echomarkread-example-2": "Merkitse kaikki ilmoitukset luetuiksi.",
+ "apihelp-echomarkread-example-3": "Merkitse ilmoitus 1 lukemattomaksi",
+ "apihelp-echomarkseen-description": "Merkitse ilmoitukset nähdyiksi nykyisen käyttäjän kannalta.",
+ "apihelp-echomarkseen-example-1": "Merkitse kaikenlaiset ilmoitukset nähdyiksi",
+ "apihelp-echomarkseen-param-type": "Nähdyiksi merkittävien ilmoitusten laatu: 'hälytysilmoitus', 'viesti' tai 'kaikki'.",
+ "apihelp-query+notifications-example-1": "Luettele ilmoitukset",
+ "apihelp-query+notifications-example-2": "Luettele ilmoitukset ryhmiteltyinä osioihin lukumäärän kera",
+ "apihelp-query+unreadnotificationpages-description": "Hae sivut, joihin liittyy lukemattomia ilmoituksia pyynnön tekevällä käyttäjällä.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Sivujen enimmäismäärä vastauksessa.",
+ "apihelp-query+unreadnotificationpages-example-1": "Luettele sivut ja niihin liittyvien lukemattomien ilmoitusten määrä"
+}
diff --git a/Echo/i18n/api/fr.json b/Echo/i18n/api/fr.json
new file mode 100644
index 00000000..28b4332f
--- /dev/null
+++ b/Echo/i18n/api/fr.json
@@ -0,0 +1,69 @@
+{
+ "@metadata": {
+ "authors": [
+ "GeekEmad",
+ "Gomoko",
+ "Orlodrim",
+ "Pols12",
+ "Trial",
+ "Wladek92",
+ "Yasten",
+ "Urhixidur",
+ "Verdy p"
+ ]
+ },
+ "apihelp-echomarkread-description": "Marquer les notifications comme lues pour l’utilisateur actuel.",
+ "apihelp-echomarkread-summary": "Marquer les notifications comme lues pour l’utilisateur actuel.",
+ "apihelp-echomarkread-param-list": "Une liste des IDs de notification à marquer comme lues.",
+ "apihelp-echomarkread-param-unreadlist": "Une liste des IDs de notification à marquer comme non lue.",
+ "apihelp-echomarkread-param-all": "Si défini, marque toutes les notifications de l’utilisateur comme lues.",
+ "apihelp-echomarkread-param-sections": "Une liste des sections à marquer comme lues.",
+ "apihelp-echomarkread-example-1": "Marquer la notification 8 comme lue",
+ "apihelp-echomarkread-example-2": "Marquer toutes les notifications comme lues",
+ "apihelp-echomarkread-example-3": "Marquer la notification 1 comme non lue",
+ "apihelp-echomarkseen-description": "Marquer les notifications comme vues pour l’utilisateur actuel.",
+ "apihelp-echomarkseen-summary": "Marquer les notifications comme vues pour l'utilisateur courant.",
+ "apihelp-echomarkseen-example-1": "Marquer les notifications de tous types comme vues.",
+ "apihelp-echomarkseen-param-type": "Type de notifications à marquer comme vues : 'alert', 'message' ou 'all'.",
+ "apihelp-echomarkseen-param-timestampFormat": "Format d’horodatage à utiliser pour la sortie, 'ISO_8601' ou 'MW'. 'MW' est ici désuet, donc tous les clients devraient basculer vers 'ISO_8601'. Ce paramètre sera supprimé, et 'ISO_8601' deviendra le seul format de sortie.",
+ "apihelp-query+notifications-description": "Obtenir les notifications en attente pour l’utilisateur courant.",
+ "apihelp-query+notifications-summary": "Obtenir les notifications en attente pour l’utilisateur actuel.",
+ "apihelp-query+notifications-param-prop": "Détails à demander.",
+ "apihelp-query+notifications-param-sections": "Les sections de notification à demander (c'est-à-dire une combinaison de 'alert' et 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Indique s’il faut grouper les résultats par section. Chaque section est analysée séparément si défini.",
+ "apihelp-query+notifications-param-filter": "Filtrer les notifications renvoyées.",
+ "apihelp-query+notifications-param-format": "Si spécifié, les notifications seront renvoyées dans ce format.",
+ "apihelp-query+notifications-paramvalue-format-model": "Données de notification brutes",
+ "apihelp-query+notifications-paramvalue-format-special": "Formaté pour la page Special:Notifications (et seulement pour elle !) Ne vous fiez pas au code HTML, car il peut changer à tout moment.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Désuet</span>. Utiliser <kbd>$1format=model</kbd> pour les données brutes",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Désuet</span>. Utiliser <kbd>$1format=model</kbd> pour les données brutes",
+ "apihelp-query+notifications-param-limit": "Le nombre maximal de notifications à renvoyer.",
+ "apihelp-query+notifications-param-wikis": "Liste des wikis à partir desquels récupérer les notifications (par défaut, seul le wiki courant).",
+ "apihelp-query+notifications-param-crosswikisummary": "Vrai pour choisir une notification de résumé pour les notifications sur les wikis externes",
+ "apihelp-query+notifications-param-alertcontinue": "Quand plus d’alertes sont disponibles, utiliser cela pour continuer.",
+ "apihelp-query+notifications-param-unreadfirst": "S’il faut afficher les notifications non lues en premier ou non (utilisé uniquement si <kbd>groupbysection</kbd> n’est pas défini).",
+ "apihelp-query+notifications-param-alertunreadfirst": "S’il faut afficher d’abord les notifications de messages non lus ou non (utilisé uniquement si <kbd>groupbysection</kbd> est défini).",
+ "apihelp-query+notifications-param-messagecontinue": "Quand plus de résultats de message sont disponibles, utiliser cela pour continuer.",
+ "apihelp-query+notifications-param-messageunreadfirst": "S’il faut afficher les notifications d’alerte non lues en premier ou non (utilisé uniquement si <kbd>groupbysection</kbd> est défini).",
+ "apihelp-query+notifications-param-titles": "Retourne uniquement les notifications concernant ces pages. Pour obtenir des notifications associées à aucune page, utilisez [] comme titre.",
+ "apihelp-query+notifications-param-bundle": "Indique s'il faut afficher les notifications non lues compatibles avec les règles de regroupement des types de notification.",
+ "apihelp-query+notifications-example-1": "Lister les notifications",
+ "apihelp-query+notifications-example-2": "Lister les notifications, groupées par section, avec les compteurs",
+ "apihelp-query+unreadnotificationpages-description": "Obtenez les pages pour lesquelles il y a des notifications non lues pour l'utilisateur actuel.",
+ "apihelp-query+unreadnotificationpages-summary": "Obtenir les pages pour lesquelles il y a des notifications non lues concernant l’utilisateur courant.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Grouper les pages de discussion ensemble avec leur page de sujet, et grouper ensemble les notifications non associées avec une page avec la page de l’utilisateur actuel.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Nombre maximal de pages à renvoyer.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Liste des wikis pour télécharger les pages comportant des notifications non lues (par défaut, seulement pour le wiki courant).",
+ "apihelp-query+unreadnotificationpages-example-1": "Liste des pages avec (leur quantité) de notifications non lues",
+ "apihelp-echoarticlereminder-summary": "Demander un rappel futur concernant l'article spécifié",
+ "apihelp-echoarticlereminder-param-pageid": "ID de l'article à rappeler à l'utilisateur",
+ "apihelp-echoarticlereminder-param-title": "Titre de l'article à rappeler à l'utilisateur",
+ "apihelp-echoarticlereminder-param-timestamp": "A quel moment rappeler l'utilisateur",
+ "apihelp-echoarticlereminder-param-comment": "Commentaire optionnel utilisateur à inclure lors du rappel",
+ "apihelp-echoarticlereminder-example-1": "Créer une notification de rappel d'article pour demain avec commentaire",
+ "apihelp-echoarticlereminder-example-2": "Créer une notification de rappel d'article pour demain sans commentaire",
+ "apiwarn-echo-deprecation-timestampformat": "Le format de sortie utilisant l’horodatage MW est désuet ici. À l’avenir, la norme ISO 8601 sera toujours utilisée pour le format d’horodatage en sortie. Ajustez votre client et mettez <var>timestampFormat</var> à <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> est devenu désuet et va être supprimé bientôt. Utiliser <kbd>notformat=model</kbd> pour avoir le format brut ou <kbd>notformat=special</kbd> pour le html préformaté.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> est désuet et sera bientôt supprimé. Utilisez <kbd>notformat=special</kbd> à la place.",
+ "apierror-echo-event-creation-failed": "Impossible de créer l'évènement Echo"
+}
diff --git a/Echo/i18n/api/frr.json b/Echo/i18n/api/frr.json
new file mode 100644
index 00000000..3754b27d
--- /dev/null
+++ b/Echo/i18n/api/frr.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Murma174"
+ ]
+ },
+ "apihelp-echomarkread-description": "Bööden för di uugenblakelk brüker ruad uunwise",
+ "apihelp-echomarkread-param-list": "En list faan bööd-IDs ruad uuntuwisin",
+ "apihelp-echomarkread-param-all": "Wan det so fäästlaanj as, wurd aal a bööden üs al leesen uunwiset.",
+ "apihelp-echomarkread-param-sections": "En list faan kirwer ruad uuntuwisin.",
+ "apihelp-echomarkread-example-1": "Bööd 8 üs al leesen uunwise",
+ "apihelp-echomarkread-example-2": "Aal a bööden üs al leesen uunwise",
+ "apihelp-echomarkseen-description": "Bööden för di uugenblakelk brüker üs uunluket markiare",
+ "apihelp-echomarkseen-example-1": "Bööden üs uunluket markiare",
+ "apihelp-query+notifications-description": "Bööden för di uugenblakelk brüker haale.",
+ "apihelp-query+notifications-param-prop": "Enkelthaiden uuntufraagin.",
+ "apihelp-query+notifications-param-sections": "Bööd kirwer uftufraagin",
+ "apihelp-query+notifications-param-groupbysection": "Of det resultaat efter kirwer uunwiset woort. Arke kirew woort enkelt haalet, wan det so fäästlaanj as.",
+ "apihelp-query+notifications-param-format": "Bööden wurd formatiaret uunwiset, wan det so fäästlaanj as.",
+ "apihelp-query+notifications-param-limit": "Det huuchst taal faan uunwiset bööden.",
+ "apihelp-query+notifications-param-alertcontinue": "Wann diar muar resultaaten san, brük det heer, am widjer tu maagin.",
+ "apihelp-query+notifications-param-alertunreadfirst": "Of diar bööden tuiarst uunwiset wurd skel, diar noch ei leesen wurden san.",
+ "apihelp-query+notifications-param-messagecontinue": "Wann diar muar resultaaten san, brük det heer, am widjer tu maagin.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Of diar bööden tuiarst uunwiset wurd skel, diar noch ei leesen wurden san.",
+ "apihelp-query+notifications-example-1": "List faan din bööden",
+ "apihelp-query+notifications-example-2": "List faan din bööden, efter a rä faan a kirwer, mä taalen"
+}
diff --git a/Echo/i18n/api/gl.json b/Echo/i18n/api/gl.json
new file mode 100644
index 00000000..58a72230
--- /dev/null
+++ b/Echo/i18n/api/gl.json
@@ -0,0 +1,62 @@
+{
+ "@metadata": {
+ "authors": [
+ "Banjo",
+ "Elisardojm",
+ "Toliño"
+ ]
+ },
+ "apihelp-echomarkread-description": "Marcar notificacións coma lidas para o usuario actual.",
+ "apihelp-echomarkread-summary": "Marcar notificacións coma lidas para o usuario actual.",
+ "apihelp-echomarkread-param-list": "Lista de identificadores de notificacións a marcar coma lidas.",
+ "apihelp-echomarkread-param-unreadlist": "Lista de identificadores de notificacións a marcar coma non lidas.",
+ "apihelp-echomarkread-param-all": "Si se establece, marca todas as notificacións dun usuario como lidas.",
+ "apihelp-echomarkread-param-sections": "Unha lista das seccións a marcar como lidas.",
+ "apihelp-echomarkread-example-1": "Marcar a notificación 8 coma lida",
+ "apihelp-echomarkread-example-2": "Marcar tódalas notificacións como lidas",
+ "apihelp-echomarkread-example-3": "Marcar a notificación 1 coma non lida",
+ "apihelp-echomarkseen-description": "Marcar notificacións coma lidas para o usuario actual.",
+ "apihelp-echomarkseen-summary": "Marcar notificacións coma vistas para o usuario actual.",
+ "apihelp-echomarkseen-example-1": "Marcar notificacións de todos os tipos como lidas",
+ "apihelp-echomarkseen-param-type": "Tipo de notificacións para marcar como lidas: 'alert' (alerta), 'message' (mensaxe) ou 'all' (todas).",
+ "apihelp-echomarkseen-param-timestampFormat": "Formato de selo de tempo a usar para a saída, 'ISO_8601' ou 'MW'. 'MW' está obsoleto aquí, polo que tódolos clientes deberían cambiarse a 'ISO_8601'. Este parámetro será eliminado, e 'ISO_8601' converterase no único formato de saída.",
+ "apihelp-query+notifications-description": "Obter notificacións de espera para o usuario actual.",
+ "apihelp-query+notifications-summary": "Obter notificacións de espera para o usuario actual.",
+ "apihelp-query+notifications-param-prop": "Detalles que solicitar.",
+ "apihelp-query+notifications-param-sections": "As seccións de notificación a consultar (p.ex. algunha combinación de 'alerta' e 'mensaxe').",
+ "apihelp-query+notifications-param-groupbysection": "Si se agrupan os resultados por sección. Cada sección obtense por separado si así se establece.",
+ "apihelp-query+notifications-param-filter": "Filtrar as notificacións devoltas.",
+ "apihelp-query+notifications-param-format": "Se se especifica, as notificacións devolveranse neste formato.",
+ "apihelp-query+notifications-paramvalue-format-model": "Datos de notificación en bruto",
+ "apihelp-query+notifications-paramvalue-format-special": "Con formato para a páxina Special:Notifications (e só esa!) Non confíe no HTML xa que pode cambiar en calquera momento.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Obsoleto</span>. Utilice <kbd>$1format=model</kbd> para os datos en bruto",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Obsoleto</span>. Utilice <kbd>$1format=model</kbd> para os datos en bruto",
+ "apihelp-query+notifications-param-limit": "Número máximo de notificacións a devolver.",
+ "apihelp-query+notifications-param-wikis": "Lista das wikis desde as que recuperar as notificacións (por defecto só a wiki actual).",
+ "apihelp-query+notifications-param-crosswikisummary": "Certo para optar a unha notificación de resumo de notifiacións en wikis foráneas.",
+ "apihelp-query+notifications-param-alertcontinue": "Cando estean dispoñibles alertas adicionais, use esta opción para continuar.",
+ "apihelp-query+notifications-param-unreadfirst": "Decidir se mostrar as notificacións non vistas primeiro (só empregado se groupbysection non está definido).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Mostra as notificacións de mensaxes sen ler primeiro (só usado se está activado groupbysection).",
+ "apihelp-query+notifications-param-messagecontinue": "Cando novos mensaxes estean dispoñibles, use esta opción para continuar.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Mostra as notificacións de alertas sen ler primeiro (só usado se está activado groupbysection).",
+ "apihelp-query+notifications-param-titles": "Devolver só as notificacións destas páxinas. Para obter as notificacións non asociadas cunha páxina, use [] como título.",
+ "apihelp-query+notifications-param-bundle": "Se mostrar as notificacións non lidas compatibles coas regras de agrupamento de tipos de notificación.",
+ "apihelp-query+notifications-example-1": "Listar as notificacións",
+ "apihelp-query+notifications-example-2": "Listar as notificacións, agrupadas por seccións, incluíndo os contadores",
+ "apihelp-query+unreadnotificationpages-description": "Obter as páxinas para as que hai notificacións sen ler para o usuario actual.",
+ "apihelp-query+unreadnotificationpages-summary": "Obter as páxinas para as que hai notificacións sen ler para o usuario actual.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Agrupar as páxinas de conversa xunto coas súas páxinas asociadas, e agrupar xuntas as notificacións non asociadas cunha páxina coa páxina de usuario actual.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Número máximo de páxinas a devolver.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Lista de wikis para buscar páxinas con notificacións sen ler (por defecto só na wiki actual).",
+ "apihelp-query+unreadnotificationpages-example-1": "Listar as páxinas con notificacións sen ler (xunto ao número de notificacións sen ler)",
+ "apihelp-echoarticlereminder-param-pageid": "Identificador do artigo a lembrar ó usuario",
+ "apihelp-echoarticlereminder-param-title": "Título do artigo a lembrar ó usuario",
+ "apihelp-echoarticlereminder-param-timestamp": "En que data e hora lembrar ó usuario",
+ "apihelp-echoarticlereminder-param-comment": "Comentario opcional a incluír no aviso",
+ "apihelp-echoarticlereminder-example-1": "Crear unha notificación de aviso de artigo para mañá con comentario",
+ "apihelp-echoarticlereminder-example-2": "Crear unha notificación de aviso de artigo para mañá sen comentario",
+ "apiwarn-echo-deprecation-timestampformat": "O formato de saída MediaWiki de data e hora está obsoleto aquí. No futuro, sempre se usará como formato de saída de data e hora o ISO 8601. Axuste o seu cliente e defina o <var>timestampFormat</var> como <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> está obsoleto e será eliminado pronto. Use <kbd>notformat=model</kbd> para obter os datos en bruto ou <kbd>notformat=special</kbd> para o HTML preformatado.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> está obsoleto e será eliminado en breve. Substituír por <kbd>notformat=special</kbd>.",
+ "apierror-echo-event-creation-failed": "Non se puido crear o evento Echo"
+}
diff --git a/Echo/i18n/api/he.json b/Echo/i18n/api/he.json
new file mode 100644
index 00000000..49327e83
--- /dev/null
+++ b/Echo/i18n/api/he.json
@@ -0,0 +1,51 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Guycn2"
+ ]
+ },
+ "apihelp-echomarkread-description": "סימון שכל ההודעות נקראו עבור המשתמש הנוכחי.",
+ "apihelp-echomarkread-param-list": "רשימת מזהי התראות שצריך לסמן שהן נקראו.",
+ "apihelp-echomarkread-param-unreadlist": "רשימת מזהי הודעה לסימון כהודעות שלא נקראו.",
+ "apihelp-echomarkread-param-all": "אם זה מוגדר, כל ההודעות של המשתמש תסומנה בתור הודעות שנקראו.",
+ "apihelp-echomarkread-param-sections": "רשימת פסקאות שיש לסמן שהן נקראו.",
+ "apihelp-echomarkread-example-1": "לסמן שהודעה 8 נקראה",
+ "apihelp-echomarkread-example-2": "לסמן שכל ההתראות נקראו",
+ "apihelp-echomarkread-example-3": "סימון הודעה 1 כהודעה שלא נקראה",
+ "apihelp-echomarkseen-description": "סימון הודעות כהודעות שנקראו עבור המשתמש הנוכחי.",
+ "apihelp-echomarkseen-example-1": "לסמן שהתראות מכל הסוגים נראו",
+ "apihelp-echomarkseen-param-type": "סוג ההודעות לסמן בתור הודעות שנראו: 'alert'‏, 'message' או 'all'.",
+ "apihelp-echomarkseen-param-timestampFormat": "תסדיר חותם־זמן שישמש בפלט, 'ISO_8601' או 'MW'. תסדיר 'MW' מיושן כאן, אז כל הלקוחות אמורים לעבור ל־'ISO_8601'. הפרמטר הזה יוסר ותסדיר הפלט היחיד יהיה 'ISO_8601'.",
+ "apihelp-query+notifications-description": "קבלת התראות שממתינות למשתמש הנוכחי.",
+ "apihelp-query+notifications-param-prop": "אילו פרטים לבקש.",
+ "apihelp-query+notifications-param-sections": "אזורי ההודעות שצריך לאחזר (כלומר, שילוב כלשהו של 'alert' ו־'message').",
+ "apihelp-query+notifications-param-groupbysection": "האם לקבץ את התוצאות לפי פסקה. כל פסקה מאוחזרת בנפרד אם זה מוגדר.",
+ "apihelp-query+notifications-param-filter": "סינון ההודעות שהוחזרו.",
+ "apihelp-query+notifications-param-format": "אם זה מצוין, ההודעות תוחזרנה עם עיצוב כזה.",
+ "apihelp-query+notifications-paramvalue-format-text": "תסדיר טקסט רגיל",
+ "apihelp-query+notifications-paramvalue-format-model": "נתוני התראה גולמיים",
+ "apihelp-query+notifications-paramvalue-format-special": "מעוצב בשביל דף Special:Notifications (ורק בשביל זה!). אין לסמוך על ה־HTML היות שהוא יכול להשתנות בכל זמן.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">מיושן</span>. נא להשתמש ב־<kbd dir=\"ltr\">$1format=model</kbd> לנתונים גולמיים",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">מיושן</span>. נא להשתמש ב־<kbd dir=\"ltr\">$1format=model</kbd> לנתונים גולמיים",
+ "apihelp-query+notifications-param-limit": "המספר המרבי של ההודעות להחזיר.",
+ "apihelp-query+notifications-param-wikis": "רשימת אתרי הוויקי שמהם תאוחזרנה הודעות (בררת המחדל היא אתר הוויקי הנוכחי).",
+ "apihelp-query+notifications-param-crosswikisummary": "הערך true יפעיל הודעה מסוכמת על הודעות מאתרי ויקי אחרים.",
+ "apihelp-query+notifications-param-alertcontinue": "כשזמינות עוד תוצאות התראה, יש להשתמש בזה כדי להמשיך.",
+ "apihelp-query+notifications-param-unreadfirst": "האם להציג הודעות שלא נקראו קודם (משמש רק אם groupbysection לא הוגדר).",
+ "apihelp-query+notifications-param-alertunreadfirst": "האם להציג מונה הודעות מסר שלא נקראו תחילה (משמש רק אם groupbysection לא הוגדר).",
+ "apihelp-query+notifications-param-messagecontinue": "כשזמינות עוד תוצאות הודעות, יש להשתמש בזה כדי להמשיך.",
+ "apihelp-query+notifications-param-messageunreadfirst": "האם להציג הודעות התראה שלא נקראו תחילה (משמש רק אם groupbysection לא הוגדר).",
+ "apihelp-query+notifications-param-titles": "להחזיר רק התראות עבור הדפים האלה. כדי לקבל התראות שאינן שייכות לשום דף, יש להשתמש בטקסט [] בתור הכותרת.",
+ "apihelp-query+notifications-param-bundle": "האם להציג התראות תואמות־חבילה בהתאם לחוקי החבילה של סוגי ההתראות.",
+ "apihelp-query+notifications-example-1": "רשימת הודעות",
+ "apihelp-query+notifications-example-2": "רשימת הודעות, מקובצות לפי פסקה, עם מונים",
+ "apihelp-query+unreadnotificationpages-description": "קבלת דפים שעבורם יש הודעות שלא נקראו למשתמש הנוכחי.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "לקבץ דפי שיחה יחד עם דפי התוכן המשויכים להם, ולקבץ הודעות שאינן משויכות לשום דף לדף המשתמש של המשתמש הנוכחי.",
+ "apihelp-query+unreadnotificationpages-param-limit": "המספר המרבי של דפים להחזיר.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "רשימת אתרי ויקי שמהם יאוחזרו דפים עם הודעות שלא נקראו (אם לא נאמר אחרת, רק הוויקי הנוכחי).",
+ "apihelp-query+unreadnotificationpages-example-1": "רשימת דפים עם (כמות של) הודעות שלא נקראו",
+ "apiwarn-echo-deprecation-timestampformat": "תסדיר חותם הזמן של מדיה־ויקי הוגדר כאן בתור מיושן. בעתיד, ISO 8601 תמיד ישמש לפלט של חותם הזמן. נא לתקן את הלקוח שלך ולהגדיר את <var>timestampFormat</var> לערך <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> הוכרז בתור מיושן ויוסר כליל בקרוב. נא להשתמש ב־<kbd>notformat=model</kbd> כדי לקבל את הנתונים הגולמיים או ב־<kbd>notformat=special</kbd> בשביל HTML שכבר הוכן לתצוגה.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> הוכרז בתור מיושן ויוסר כליל בקרוב. נא להשתמש ב־<kbd>notformat=special</kbd> במקומו."
+}
diff --git a/Echo/i18n/api/hi.json b/Echo/i18n/api/hi.json
new file mode 100644
index 00000000..027b7040
--- /dev/null
+++ b/Echo/i18n/api/hi.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hindustanilanguage",
+ "Sfic"
+ ]
+ },
+ "apihelp-echomarkread-description": "वर्तमान सदस्य की अधिसूचनाओं पढ़ी गई रेखांकित करें।",
+ "apihelp-echomarkread-param-list": "अधिसूचनाओं के आई०डी० की सूची जिन्हें पढ़े जाने के तौर पर रेखांकित करना है।",
+ "apihelp-echomarkread-param-all": "यदि तय हो, किसी सदस्य की सारे अधिसूचनाओं पढ़े जाने के तौर पर रेखांकित करें।",
+ "apihelp-echomarkread-param-sections": "अनुभागों की सूची जिन्हें पढ़े जाने के तौर पर रेखांकित करना है।",
+ "apihelp-echomarkread-example-1": "अधिसूचना ८ को पढ़े जाने के तौर पर चिन्हित करें",
+ "apihelp-echomarkread-example-2": "सभी अधिसूचनाओं को पढ़े जाने के तौर पर चिन्हित करें",
+ "apihelp-echomarkread-example-3": "सूचना 1 को न पढ़ा चिन्हित करें",
+ "apihelp-echomarkseen-description": "वर्तमान सदस्य की अधिसूचनाओं पढ़ी गई रेखांकित करें।",
+ "apihelp-echomarkseen-example-1": "अधिसूचनाओं को देखे जाने के तौर पर चिन्हित करें",
+ "apihelp-query+notifications-param-sections": "पूछताछ के अधिसूचना अनुभाग",
+ "apihelp-query+notifications-paramvalue-format-text": "सादापाठ्य प्रारूप",
+ "apihelp-query+notifications-paramvalue-format-model": "पंक्ति में सूचना डाटा",
+ "apihelp-query+notifications-example-1": "अधिसूचनाओं को सूचीबद्ध करें",
+ "apihelp-query+notifications-example-2": "अधिसूचनाओं को सूचीबद्ध अनुभाग के अनुसार सम्मिलित करके गिनकर करें"
+}
diff --git a/Echo/i18n/api/hr.json b/Echo/i18n/api/hr.json
new file mode 100644
index 00000000..4c1fdfc7
--- /dev/null
+++ b/Echo/i18n/api/hr.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bugoslav"
+ ]
+ },
+ "apihelp-query+notifications-example-1": "Ispis obavijesti"
+}
diff --git a/Echo/i18n/api/hu.json b/Echo/i18n/api/hu.json
new file mode 100644
index 00000000..fe6ce2ff
--- /dev/null
+++ b/Echo/i18n/api/hu.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "Tacsipacsi",
+ "Tgr"
+ ]
+ },
+ "apihelp-echomarkread-description": "Értesítések olvasottnak jelölése az aktuális felhasználó számára.",
+ "apihelp-echomarkread-param-list": "Az olvasottnak jelölendő értesítések ID-inek listája.",
+ "apihelp-echomarkread-param-unreadlist": "Olvasatlannak jelölendő értesítésazonosítók listája.",
+ "apihelp-echomarkread-param-all": "Ha meg van adva, az adott felhasználó összes értesítését olvasottnak jelöli.",
+ "apihelp-echomarkread-param-sections": "Az olvasottnak jelölendő szakaszok listája.",
+ "apihelp-echomarkread-example-1": "A 8-as számú értesítés olvasottnak jelölése",
+ "apihelp-echomarkread-example-2": "Az összes értesítés olvasottnak jelölése",
+ "apihelp-echomarkread-example-3": "1-es azonosítójú értesítés megjelölése olvasatlanként",
+ "apihelp-echomarkseen-description": "Értesítések látottnak jelölése az aktuális felhasználó számára.",
+ "apihelp-echomarkseen-example-1": "Az összes fajta értesítés látottnak jelölése.",
+ "apihelp-echomarkseen-param-type": "A látottnak jelölendő értesítések típusa: 'alert', 'message' vagy 'all'.",
+ "apihelp-echomarkseen-param-timestampFormat": "A kimenetben használandó időbélyeg-formátum, „ISO_8601” vagy „MW”. Az „MW” elavult itt, minden kliensnek „ISO_8601”-re kellene váltania. Ez a paraméter el lesz távolítva, és az „ISO_8601” lesz az egyetlen kimeneti formátum.",
+ "apihelp-query+notifications-description": "Az aktuális felhasználónak szóló értesítések lekérdezése.",
+ "apihelp-query+notifications-param-prop": "A lekérdezendő részletek.",
+ "apihelp-query+notifications-param-sections": "A lekérdezendő szakaszok ('alert' és/vagy 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Eredmény csoportosítása szakaszok szerint.",
+ "apihelp-query+notifications-param-filter": "Visszaadott értesítések szűrése.",
+ "apihelp-query+notifications-param-format": "Az értesítések formátuma.",
+ "apihelp-query+notifications-paramvalue-format-model": "Nyers értesítési adatok",
+ "apihelp-query+notifications-paramvalue-format-special": "Formázva a Special:Notifications lapra (és csak arra!). Ne hagyatkozz a HTML-re, mivel bármikor változhat.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Elavult</span>. Használd a(z) <kbd>$1format=model</kbd>t nyers adatokért.",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Elavult</span>. Használd a(z) <kbd>$1format=model</kbd>t nyers adatokért.",
+ "apihelp-query+notifications-param-limit": "Az egy választban visszaadott értesítések maximális száma.",
+ "apihelp-query+notifications-param-wikis": "Az értesítésekért lekérdezendő wikik listája (alapértelmezetten csak a jelenlegi).",
+ "apihelp-query+notifications-param-alertcontinue": "Ha nem minden figyelmeztetés fért bele a válaszba, ezzel lehet lekérdezni a továbbiakat.",
+ "apihelp-query+notifications-param-unreadfirst": "Előrevegye-e az olvasatlan értesítéseket (csak akkor van használatban, ha a groupbysection meg van adva).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Előrevegye-e az olvasatlan üzeneteket (csak akkor van használatban, ha a groupbysection meg van adva).",
+ "apihelp-query+notifications-param-messagecontinue": "Ha nem minden üzenet fért bele a válaszba, ezzel lehet lekérdezni a továbbiakat.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Előrevegye-e az olvasatlan figyelmezetetéseket (csak akkor van használatban, ha a groupbysection meg van adva).",
+ "apihelp-query+notifications-param-titles": "Csak az ezen lapokhoz kapcsolódó értesítések lekérése. A laphoz nem kötődő értesítések címeként [] használható.",
+ "apihelp-query+notifications-example-1": "Értesítések listázása",
+ "apihelp-query+notifications-example-2": "Értesítések listázása, szakaszonkénti bontásban, darabszámmal"
+}
diff --git a/Echo/i18n/api/id.json b/Echo/i18n/api/id.json
new file mode 100644
index 00000000..d7e87e35
--- /dev/null
+++ b/Echo/i18n/api/id.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rachmat.Wahidi",
+ "William Surya Permana"
+ ]
+ },
+ "apihelp-echomarkread-description": "Tandai pemberitahuan dari pengguna ini sebagai telah dibaca.",
+ "apihelp-echomarkread-param-list": "Daftar ID pemberitahuan yang ingin ditandai sebagai telah dibaca.",
+ "apihelp-echomarkread-param-all": "Jika ditetapkan, menandai semua pemberitahuan pengguna sebagai telah dibaca.",
+ "apihelp-echomarkread-param-sections": "Daftar bagian yang ingin ditandai sebagai telah dibaca.",
+ "apihelp-echomarkread-example-1": "Tandai pemberitahuan 8 sebagai telah dibaca",
+ "apihelp-echomarkread-example-2": "Tandai semua pemberitahuan sebagai telah dibaca",
+ "apihelp-query+notifications-description": "Dapatkan penungguan pemberitahuan untuk pengguna ini.",
+ "apihelp-query+notifications-param-prop": "Rincian yang diminta.",
+ "apihelp-query+notifications-param-sections": "Bagian pemberitahuan yang ingin didapatkan.",
+ "apihelp-query+notifications-param-groupbysection": "Menentukan apakah perlu mengelompokkan hasil berdasarkan bagian. Jika ditetapkan, setiap bagian diambil secara terpisah.",
+ "apihelp-query+notifications-param-format": "Jika ditetapkan, pemberitahuan akan menghasilkan format seperti ini.",
+ "apihelp-query+notifications-param-limit": "Jumlah maksimum pemberitahuan yang dihasilkan.",
+ "apihelp-query+notifications-param-alertcontinue": "Saat ada lebih banyak hasil penanda yang tersedia, gunakan ini untuk melanjutkan.",
+ "apihelp-query+notifications-param-alertunreadfirst": "Menentukan apakah harus menampilkan pemberitahuan pesan yang belum dibaca terlebih dahulu.",
+ "apihelp-query+notifications-param-messagecontinue": "Saat ada lebih banyak hasil pesan yang tersedia, gunakan ini untuk melanjutkan.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Menentukan apakah harus menampilkan pemberitahuan penanda terlebih dahulu.",
+ "apihelp-query+notifications-example-1": "Daftar pemberitahuan",
+ "apihelp-query+notifications-example-2": "Daftar pemberitahuan, dikelompokkan berdasarkan bagian, dengan jumlah",
+ "apihelp-query+unreadnotificationpages-param-limit": "Jumlah halaman maksimum yang ditampilkan.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Daftar wiki untuk mengambil halaman dengan pemberitahuan belum dibaca (baku hanya pada wiki ini).",
+ "apihelp-query+unreadnotificationpages-example-1": "Daftarkan halaman dengan (jumlah) pemberitahuan belum dibaca"
+}
diff --git a/Echo/i18n/api/it.json b/Echo/i18n/api/it.json
new file mode 100644
index 00000000..fdb9b95f
--- /dev/null
+++ b/Echo/i18n/api/it.json
@@ -0,0 +1,47 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beta16",
+ "Fringio",
+ "Matteocng"
+ ]
+ },
+ "apihelp-echomarkread-description": "Contrassegna tutte le notifiche come lette per l'utente attuale.",
+ "apihelp-echomarkread-summary": "Contrassegna tutte le notifiche come lette per l'utente attuale.",
+ "apihelp-echomarkread-param-list": "Un elenco di ID notifiche da contrassegnare come lette.",
+ "apihelp-echomarkread-param-unreadlist": "Un elenco di ID notifiche da contrassegnare come non lette.",
+ "apihelp-echomarkread-param-all": "Se impostato, contrassegna tutte le notifiche dell'utente come lette.",
+ "apihelp-echomarkread-param-sections": "Un elenco di sezioni da contrassegnare come lette.",
+ "apihelp-echomarkread-example-1": "Contrassegna la notifica 8 come letta",
+ "apihelp-echomarkread-example-2": "Contrassegna tutte le notifiche come lette",
+ "apihelp-echomarkread-example-3": "Contrassegna la notifica 1 come non letta",
+ "apihelp-echomarkseen-description": "Contrassegna le notifiche come viste per l'utente attuale.",
+ "apihelp-echomarkseen-example-1": "Contrassegna le notifiche di tutti i tipi come viste",
+ "apihelp-echomarkseen-param-type": "Tipo di notifiche da contrassegnare come viste: 'alert', 'message' or 'all'.",
+ "apihelp-query+notifications-description": "Ottieni le notifiche in attesa per l'utente attuale.",
+ "apihelp-query+notifications-summary": "Ottieni le notifiche in attesa per l'utente attuale.",
+ "apihelp-query+notifications-param-prop": "Dettagli da richiedere.",
+ "apihelp-query+notifications-param-sections": "Le sezioni delle notifiche da consultare (per esempio, una combinazione di 'avviso' e 'messaggio').",
+ "apihelp-query+notifications-param-groupbysection": "Se raggruppare i risultati per sezione. Ogni sezione viene recuperata separatamente se impostato.",
+ "apihelp-query+notifications-param-filter": "Filtra le notifiche restituite.",
+ "apihelp-query+notifications-param-format": "Se specificato, le notifiche verranno restituite formattate in questo modo.",
+ "apihelp-query+notifications-paramvalue-format-model": "Dati grezzi notifica",
+ "apihelp-query+notifications-paramvalue-format-special": "Formattato per la pagina Special:Notifications (e solo quella!) Non fare affidamento sul HTML dato che può cambiare in qualsiasi momento.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Deprecato</span>. Usa <kbd>$1format=model</kbd> per dati grezzi",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Deprecato</span>. Usa <kbd>$1format=model</kbd> per dati grezzi",
+ "apihelp-query+notifications-param-limit": "Il numero massimo di notifiche da recuperare.",
+ "apihelp-query+notifications-param-wikis": "Elenco di wiki da cui recuperare le notifiche (predefinito solo il wiki attuale).",
+ "apihelp-query+notifications-param-alertcontinue": "Quando più risultati 'avviso' sono disponibili, usa questo per continuare.",
+ "apihelp-query+notifications-param-unreadfirst": "Se mostrare le notifiche non lette prima (usato solo se groupbysection è impostato).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Se mostrare le notifiche dei messaggi non letti prima (usato solo se groupbysection è impostato).",
+ "apihelp-query+notifications-param-messagecontinue": "Quando più risultati 'messaggio' sono disponibili, usa questo per continuare.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Se mostrare le notifiche degli avvisi non letti prima (usato solo se groupbysection è impostato).",
+ "apihelp-query+notifications-param-titles": "Restituisce solo le notifiche per queste pagine. Per ottenere le notifiche non associate ad alcuna pagina, usa [] come titolo.",
+ "apihelp-query+notifications-example-1": "Elenco notifiche",
+ "apihelp-query+notifications-example-2": "Elenco notifiche, raggruppate per sezione, con i conteggi",
+ "apihelp-query+unreadnotificationpages-description": "Ottieni le pagine per le quali ci sono notifiche non lette per l'utente attuale.",
+ "apihelp-query+unreadnotificationpages-summary": "Ottieni le pagine per le quali ci sono notifiche non lette per l'utente attuale.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Il numero massimo di pagine da restituire.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Elenco di wiki da cui recuperare le pagine con notifiche non lette (predefinito solo il wiki attuale).",
+ "apihelp-query+unreadnotificationpages-example-1": "Elenca le pagine con (il loro numero di) notifiche non lette"
+}
diff --git a/Echo/i18n/api/ja.json b/Echo/i18n/api/ja.json
new file mode 100644
index 00000000..2312e93c
--- /dev/null
+++ b/Echo/i18n/api/ja.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "2nd-player",
+ "Otokoume"
+ ]
+ },
+ "apihelp-echomarkread-description": "現在の利用者への通知を既読にする。",
+ "apihelp-echomarkread-summary": "現在の利用者への通知を既読にする。",
+ "apihelp-echomarkread-param-list": "既読にする通知IDのリスト。",
+ "apihelp-echomarkread-param-unreadlist": "未読にする通知IDのリスト。",
+ "apihelp-echomarkread-param-all": "設定すると、すべての通知を既読にします。",
+ "apihelp-echomarkread-example-1": "通知 8 を既読にする",
+ "apihelp-echomarkread-example-2": "すべての通知を既読にする",
+ "apihelp-echomarkread-example-3": "通知 1 を未読にする",
+ "apihelp-query+notifications-param-limit": "返す通知の最大数。",
+ "apihelp-query+notifications-example-1": "通知を一覧表示する",
+ "apihelp-query+notifications-example-2": "通知をセクションによりグループ化し、カウントで一覧表示する",
+ "apihelp-query+unreadnotificationpages-param-limit": "返すページの最大数。"
+}
diff --git a/Echo/i18n/api/kk-cyrl.json b/Echo/i18n/api/kk-cyrl.json
new file mode 100644
index 00000000..787bde14
--- /dev/null
+++ b/Echo/i18n/api/kk-cyrl.json
@@ -0,0 +1,37 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arystanbek"
+ ]
+ },
+ "apihelp-echomarkread-description": "Қазіргі қатысушы үшін ескертпелер оқылған деп белгілеу",
+ "apihelp-echomarkread-param-list": "Ескертпе сәйкендіргіштерін оқылды деп белгілеу.",
+ "apihelp-echomarkread-param-unreadlist": "Ескертпе ID тізімін оқылды деп белгілеу.",
+ "apihelp-echomarkread-param-all": "Орнатсаңыз, қатысушының барлық хабарландырулары оқылған деп белгіленеді.",
+ "apihelp-echomarkread-param-sections": "Бөлімдер тізімін оқылды деп белгілеу.",
+ "apihelp-echomarkread-example-1": "8 ескертпені оқылды деп белгілеу",
+ "apihelp-echomarkread-example-2": "Барлық ескертпелерді оқылды деп белгілеу",
+ "apihelp-echomarkread-example-3": "1 ескертпені оқылмаған деп белгілеу",
+ "apihelp-echomarkseen-description": "Қазіргі қатысушы үшін ескертпелер көрілген деп белгілеу",
+ "apihelp-echomarkseen-example-1": "Ескертпелердің барлық түрін көрдім деп белгілеу",
+ "apihelp-echomarkseen-param-type": "Қаралды деп белгіленетін хабарландыру түрі: 'ескертпе', 'хабарлама' немесе 'барлығы'.",
+ "apihelp-query+notifications-description": "Қазіргі қатысушы үшін күтілген хабарландыруларды алу",
+ "apihelp-query+notifications-param-prop": "Сұраныс егжей-тегжейлері.",
+ "apihelp-query+notifications-param-sections": "Сұраныс үшін ескертпе бөлімдері ('alert' және 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Бөлім бойынша нәтижені топтауы тиіс. Егер орнатса, әрбір бөлім бөлектей шығарылады.",
+ "apihelp-query+notifications-param-filter": "Оралған ескертпелерді сүзгілеу.",
+ "apihelp-query+notifications-param-format": "Егер көрсетсе, ескертпелер осылайша форматталады.",
+ "apihelp-query+notifications-paramvalue-format-text": "Текстік формат",
+ "apihelp-query+notifications-paramvalue-format-model": "Өңделмеген ескертпе дерегі",
+ "apihelp-query+notifications-paramvalue-format-special": "Special:Notifications беті үшін форматталады (және тек бұл ғана!) Бұл HTML мәтінге жауап бермеңіз, өйткені оны кез келген уақытта өзгерте аласыз.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Ескірген</span>. Қайнар дерегі үшін <kbd>$1format=model</kbd> қолданыңыз",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Ескірген</span>. Қайнар дерегі үшін <kbd>$1format=model</kbd> қолданыңыз",
+ "apihelp-query+notifications-param-limit": "Қайтару үшін ескертпелердің ең көп саны.",
+ "apihelp-query+notifications-param-alertcontinue": "Көбірек ескерту нәтижелері бар болған кезде, жалғастыру үшін осыны пайдаланыңыз.",
+ "apihelp-query+notifications-param-unreadfirst": "Бірінші оқылмаған дабыл ескертпелерін көрсету (тек егер groupbysection көрсетілмеген болса қолданылады).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Бірінші оқылмаған хабарлама ескертпелерін көрсету (тек егер groupbysection көрсетілген болса қолданылады).",
+ "apihelp-query+notifications-param-messagecontinue": "Көбірек хабарлама нәтижелері бар болған кезде, жалғастыру үшін осыны пайдаланыңыз.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Бірінші оқылмаған дабыл ескертпелерін көрсету (тек егер groupbysection көрсетілген болса қолданылады).",
+ "apihelp-query+notifications-example-1": "Ескертпелер тізімі",
+ "apihelp-query+notifications-example-2": "Санымен көрсетілген, бөлімі бойынша топталған ескертпелер сан"
+}
diff --git a/Echo/i18n/api/ko.json b/Echo/i18n/api/ko.json
new file mode 100644
index 00000000..61ea7517
--- /dev/null
+++ b/Echo/i18n/api/ko.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hwangjy9",
+ "Priviet",
+ "Revi",
+ "Ykhwong",
+ "아라"
+ ]
+ },
+ "apihelp-echomarkread-description": "현재 사용자의 알림을 읽은 것으로 표시",
+ "apihelp-echomarkread-summary": "현재 사용자의 알림을 읽은 것으로 표시합니다.",
+ "apihelp-echomarkread-param-list": "읽은 것으로 표시할 알림 ID의 목록.",
+ "apihelp-echomarkread-param-unreadlist": "읽지 않은 것으로 처리할 알림 ID의 목록.",
+ "apihelp-echomarkread-param-all": "설정되어 있다면, 모든 사용자의 알림을 읽은 것으로 표시합니다.",
+ "apihelp-echomarkread-param-sections": "읽은 것으로 표시할 문단의 목록.",
+ "apihelp-echomarkread-example-1": "알림 8을 읽은 것으로 표시",
+ "apihelp-echomarkread-example-2": "모든 알림을 읽은 것으로 표시",
+ "apihelp-echomarkread-example-3": "알림 1을 읽지 않은 것으로 표시",
+ "apihelp-echomarkseen-description": "이 사용자가 알림을 본 것으로 표시.",
+ "apihelp-echomarkseen-summary": "현재 사용자가 알림을 본 것으로 표시합니다.",
+ "apihelp-echomarkseen-example-1": "모든 종류의 알림을 본 것으로 표시.",
+ "apihelp-echomarkseen-param-type": "읽은 것으로 표시할 알림의 종류: 'alert', 'message' 또는 'all'.",
+ "apihelp-query+notifications-description": "현재 사용자를 기다리고 있는 알림을 얻어옵니다.",
+ "apihelp-query+notifications-summary": "현재 사용자를 기다리고 있는 알림을 가져옵니다.",
+ "apihelp-query+notifications-param-prop": "상세한 요청 내용.",
+ "apihelp-query+notifications-param-sections": "쿼리로의 알림 부분 (예를 들어 'alert'과 'message'의 어떤 조합).",
+ "apihelp-query+notifications-param-filter": "필터 알림 반환됨.",
+ "apihelp-query+notifications-param-alertcontinue": "더 많은 경보 결과를 사용할 수 있을 때, 계속하려면 이것을 사용합니다.",
+ "apihelp-query+notifications-param-messageunreadfirst": "읽지 않은 경보 알림을 먼저 보여줄지 여부 (groupbysection이 설정되어 있는 경우에만 사용됨).",
+ "apihelp-query+notifications-param-titles": "이 문서들의 알림만 반환합니다. 어떠한 문서에도 속하지 않은 알림을 받으려면 제목으로 []를 사용하세요.",
+ "apihelp-query+notifications-param-bundle": "규칙을 묶는 알림 유형에 따라 묶음과 호환되는 읽지 않은 알림을 보여줄지의 여부.",
+ "apihelp-query+notifications-example-1": "알림 리스트",
+ "apihelp-query+unreadnotificationpages-param-wikis": "읽지 않은 알림 문서를 가져올 위키 목록입니다. (기본값으로는 현재 위키만)",
+ "apierror-echo-event-creation-failed": "Echo 이벤트를 만들 수 없습니다"
+}
diff --git a/Echo/i18n/api/krc.json b/Echo/i18n/api/krc.json
new file mode 100644
index 00000000..38e17171
--- /dev/null
+++ b/Echo/i18n/api/krc.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ernác"
+ ]
+ },
+ "apihelp-echomarkread-description": "Бу къошулуучу ючюн билдириулени окъулгъанлача белгиле.",
+ "apihelp-echomarkread-param-list": "Окъулгъанлача белгилер ючюн ID'лени билдириулени тизмеси.",
+ "apihelp-echomarkread-param-all": "Бегитилген эсе, къошулуучуну бары джазгъанларын да окъулгъанлача белгилейди.",
+ "apihelp-echomarkread-param-sections": "Окъулгъанлача белгилер ючюн бёлюмлени тизмеси.",
+ "apihelp-echomarkread-example-1": "8'чи билдириуню окъулгъанча белгиле",
+ "apihelp-echomarkread-example-2": "Бютеу бары билдириулени да окъулгъанлача белгиле",
+ "apihelp-echomarkseen-description": "Бу къошулуучу ючюн билдириулени окъулгъанлача белгиле.",
+ "apihelp-echomarkseen-example-1": "Хар тюрлю билдириуню да окъулгъанча белгиле",
+ "apihelp-echomarkseen-param-type": "Окъулгъанлача белгилер ючюн билдириулени тюрлюлери: 'билдириу', 'джазылгъан' неда 'бютеу'.",
+ "apihelp-query+notifications-description": "Бу къошулуучуну сакълагъан билдириулеге къараб ал.",
+ "apihelp-query+notifications-param-prop": "Соруу ючюн деталла.",
+ "apihelp-query+notifications-param-sections": "Соруу ючюн билдириу тюрлюлери ('билдириу' бла 'джазылгъан' дегенлени комбинациялары).",
+ "apihelp-query+notifications-param-limit": "Къайтарылыучу билдириулени максимал саны.",
+ "apihelp-query+notifications-example-1": "Билдириулени тизмеси"
+}
diff --git a/Echo/i18n/api/ksh.json b/Echo/i18n/api/ksh.json
new file mode 100644
index 00000000..c6080780
--- /dev/null
+++ b/Echo/i18n/api/ksh.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Purodha"
+ ]
+ },
+ "apihelp-echomarkread-description": "Makkehr, dat dä aktoälle Metmaacher di Meddeijlonge jelässe hät.",
+ "apihelp-echomarkread-param-list": "En leß met dä Kännonge för di Meddeijlonge, di op „jelässe“ jesaz wähde sulle.",
+ "apihelp-echomarkread-param-all": "Wann aanjekleck, dunn all däm Metmaacher singe Meddeijlonge op „jelässe“ säze.",
+ "apihelp-echomarkread-param-sections": "En Leß met Affschnedde, di op „jelässe“ jesaz wähde sulle.",
+ "apihelp-echomarkread-example-1": "Säz de Meddeijlong aach op „jelässe“.",
+ "apihelp-echomarkread-example-2": "Säz alle Meddeijlonge op „jelässe“.",
+ "apihelp-echomarkread-example-3": "Säz de eezde Meddeijlong op „nit jelässe“.",
+ "apihelp-echomarkseen-description": "Makkehr, dat dä aktoälle Metmaacher di Meddeijlonge jesinn hät.",
+ "apihelp-echomarkseen-example-1": "Makehr alle Zoote Meddeijlong als „jesinn“",
+ "apihelp-echomarkseen-param-type": "De Zoot Metdeijlong zom als jesinn Makkehre: „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">alert</kbd>“, „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">message</kbd>“ udder „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">all</kbd>“,",
+ "apihelp-query+notifications-description": "Holl däm aktoälle Metmaacher sing Waadeschlang met Meddeilonge.",
+ "apihelp-query+notifications-param-prop": "De Einzelheijte för dernoh ze frohre.",
+ "apihelp-query+notifications-param-sections": "De Afschnedde met de oot Nohreeschte zom holle, allsu esu jät wi „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">alert</kbd>“ un \n„<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">message</kbd>“ udder beeds.",
+ "apihelp-query+notifications-param-groupbysection": "Of de Leß en Jroppe vun Afschnedde sin sull.\nJehde Affschnedd es för sesch, wann dat aanjeklegg es.",
+ "apihelp-query+notifications-param-format": "Wann aanjejovve, wähde de Nohreeschte en dä Manier daajeschtällt.",
+ "apihelp-query+notifications-paramvalue-format-text": "Eijfach Täx Fommaht",
+ "apihelp-query+notifications-paramvalue-format-model": "Rüh Dahte vun de Medeijlonge",
+ "apihelp-query+notifications-param-limit": "Nit mih, wi esu vill Meddeijlonge ußjävve.",
+ "apihelp-query+notifications-param-alertcontinue": "Wann mih Meddeijlonge ze holle sin, nemm dat för wigger ze maache.",
+ "apihelp-query+notifications-param-unreadfirst": "Ov de unjelässe Meddeijlonge am Aanfang schtonn sulle. Bedügg nix, wann et Jroppehre aanjeschalld es.",
+ "apihelp-query+notifications-param-alertunreadfirst": "Ov de unjelässe Meddeijlonge övver Nohreeschte am Aanfang schtonn sulle. Bedügg nix, wann et Jroppehre ußjeschalld es.",
+ "apihelp-query+notifications-param-messagecontinue": "Wann mih Nohreeschte ze holle sin, nemm dat för wigger ze maache.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Ov de unjelässe Nohreeschte övver Meddeijlonge am Aanfang schtonn sulle. Bedügg nix, wann et Jroppehre aanjeschalld es.",
+ "apihelp-query+notifications-param-titles": "Jiff blohß de Benohreeschtejonge för di Sigge uß. Öm Benohreeschtejonge ze krijje, di met keijne beschtemmpte Sigg zesammehange donn, jiv [] als Övverschreff en.",
+ "apihelp-query+notifications-example-1": "Meddeijlonge opleßte",
+ "apihelp-query+notifications-example-2": "Meddeijlonge opleßte, noh Affschnedde, met der Aanzahl",
+ "apihelp-query+unreadnotificationpages-param-limit": "De jrüüßte Zahl Sigge för ußzejävve."
+}
diff --git a/Echo/i18n/api/lki.json b/Echo/i18n/api/lki.json
new file mode 100644
index 00000000..5ef01f20
--- /dev/null
+++ b/Echo/i18n/api/lki.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hosseinblue",
+ "Reza1615"
+ ]
+ },
+ "apihelp-echomarkread-description": "آگهی‌ها برای کاربر کنونی به عنوان خوانده‌شده نشانه‌گذاری شوند.",
+ "apihelp-echomarkread-param-list": "فهرستی از شناسه های آگاه سازی به عنوان خوانده شده",
+ "apihelp-echomarkread-param-all": "اگر تنظیم شده‌باشد، همهٔ آگهی‌های یک کاربر به عنوان خوانده‌شده نشانه‌گذاری شوند.",
+ "apihelp-echomarkread-param-sections": "فهرستی از شناسه های آگاه سازی به عنوان خوانده شده",
+ "apihelp-echomarkread-example-1": "علامت گذاری 8 اعلان آگاه سازی به عنوان خوانده شده",
+ "apihelp-echomarkread-example-2": "علامت‌گذاری تمامی اعلان‌ها به عنوان خوانده شده",
+ "apihelp-echomarkseen-description": "علامت گذاری به عنوان اطلاعیه خوانده شده برای کاربر فعلی",
+ "apihelp-echomarkseen-example-1": "علامت‌گذاری همهٔ انواع اعلان‌ها به عنوان دیده‌شده",
+ "apihelp-echomarkseen-param-type": "نوع اعلان‌هایی که خوانده‌شده علامت زده شوند: «آگاه‌سازی»، «پیام»، یا «همه»",
+ "apihelp-query+notifications-description": "دریافت اعلان‌های منتظر کاربر کنونی.",
+ "apihelp-query+notifications-param-prop": "جزئیات به درخواست.",
+ "apihelp-query+notifications-example-1": "اعلان‌ها را فهرست کن",
+ "apihelp-query+notifications-example-2": "فهرست اعلان‌ها، بخش بندیش شده، همراه با شمار آن‌ها."
+}
diff --git a/Echo/i18n/api/lrc.json b/Echo/i18n/api/lrc.json
new file mode 100644
index 00000000..2690d754
--- /dev/null
+++ b/Echo/i18n/api/lrc.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mogoeilor"
+ ]
+ },
+ "apihelp-echomarkread-description": "نشودار کردن وارسیاریا چی حنه بیه یا سی کاریاری ایسنی.",
+ "apihelp-echomarkread-param-sections": "نومجایی د بهرجایایی که چی حنه بیه نشودار بیه.",
+ "apihelp-echomarkread-example-1": "هشت گله وارسیاری نه چی حنه بیه یا نشودار بک",
+ "apihelp-echomarkread-example-2": "همه وارسیاری یا نه چی حنه بیه یا نشودار بک",
+ "apihelp-query+notifications-description": "وارسیاری آهره داری کردن سی کاریار ایسنی نه وه دس بئیرت.",
+ "apihelp-query+notifications-param-prop": "جزئیات حاسته بیه.",
+ "apihelp-query+notifications-param-sections": "بهرجایا وارسیاری سی پورس کردن.",
+ "apihelp-query+notifications-param-limit": "بیشترونه شماره وارسیاریا سی ؤرئشتن",
+ "apihelp-query+notifications-param-alertunreadfirst": "آیا اول وارسیاریا پیغومیا نحنه نه نشو بیه.",
+ "apihelp-query+notifications-example-1": "نومجا وارسیاریا"
+}
diff --git a/Echo/i18n/api/lt.json b/Echo/i18n/api/lt.json
new file mode 100644
index 00000000..3d9244b5
--- /dev/null
+++ b/Echo/i18n/api/lt.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "Albertas",
+ "Eitvys200"
+ ]
+ },
+ "apihelp-echomarkread-description": "Pažymėti pranešimus kaip perskaitytus dabartinio naudotojo.",
+ "apihelp-echomarkread-param-list": "ID sąrašas pranešimų, kuriuos pažymėti kaip perskaitytus.",
+ "apihelp-echomarkread-param-unreadlist": "Pranešimų ID sąrašas, kuriuos pažymėti kaip neperskaitytus.",
+ "apihelp-echomarkread-param-all": "Jeigu nustatyta, pažymi visus naudotojo pranešimus kaip perskaitytus.",
+ "apihelp-echomarkread-param-sections": "Sąrašas skyrių, kuriuos pažymėti kaip perskaitytus.",
+ "apihelp-echomarkread-example-1": "Pažymėti pranešimą 8 kaip perskaitytą",
+ "apihelp-echomarkread-example-2": "Pažymėti visus pranešimus kaip perskaitytus",
+ "apihelp-echomarkread-example-3": "Žymėti pranešimą 1 kaip neskaityta",
+ "apihelp-echomarkseen-description": "Pažymėti pranešimus kaip peržiūrėtus dabartinio naudotojo.",
+ "apihelp-echomarkseen-example-1": "Pažymėti visų tipų pranešimus kaip peržiūrėtus",
+ "apihelp-echomarkseen-param-type": "Tipas pranešimų, kuriuos pažymėti kaip peržiūrėtus: 'alert', 'message' arba 'all'.",
+ "apihelp-query+notifications-description": "Gauti pranešimus, kurie laukia dabartinio naudotojo.",
+ "apihelp-query+notifications-param-prop": "Informacija, kurios prašyti.",
+ "apihelp-query+notifications-param-sections": "Pranešimo sekcijos, su kuriomis vykdyti užklausą (t.y. kokia nors kombinacija iš 'alert' ir 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Ar grupuoti rezultatus pagal skyrius. Kiekvienas skyrius yra paimamas atskirai, jeigu taip nustatyta.",
+ "apihelp-query+notifications-param-filter": "Filtruoti grąžintus pranešimus.",
+ "apihelp-query+notifications-param-format": "Jeigu nustatyta, pranešimai bus grąžinami suformatuoti šiuo būdu.",
+ "apihelp-query+notifications-paramvalue-format-model": "Gryni pranešimų duomenys",
+ "apihelp-query+notifications-param-limit": "Maksimalus pranešimų skaičius, kurį grąžinti.",
+ "apihelp-query+notifications-param-wikis": "Viki sąrašas, iš kurių gauti pranešimus (numatytasis - tik dabartinė viki).",
+ "apihelp-query+notifications-param-alertcontinue": "Kai prieinama daugiau įspėjimo rezultatų, tęsimui naudoti tai.",
+ "apihelp-query+notifications-param-unreadfirst": "Ar rodyti neskaitytus pranešimus pirmiau (naudojama tik jei nenustatytas groupbysection).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Ar pirmiau rodyti neperskaitytų žinučių pranešimus (naudojama tik jei groupbysection yra nustatytas).",
+ "apihelp-query+notifications-param-messagecontinue": "Kai prieinama daugiau žinučių rezultatų, tęsimui naudoti tai.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Ar pirmiau rodyti neperskaitytus įspėjimų pranešimus (naudojama tik jei groupbysection yra nustatytas).",
+ "apihelp-query+notifications-param-titles": "Gražinti tik pranešimus šiems puslapiams. Kad gautumėte pranešimus, nesusijusius su puslapiu, naudokite [] kaip pavadinimą.",
+ "apihelp-query+notifications-example-1": "Rodyti pranešimus",
+ "apihelp-query+notifications-example-2": "Rodyti pranešimus, sugrupuotus pagal skyrius, su kiekiais",
+ "apihelp-query+unreadnotificationpages-description": "Gauti puslapius, iš kurių dabartinis vartotojas turi neskaitytų pranešimų.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Maksimalus grąžinamų puslapių skaičius.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Viki sąrašas, iš kurių gauti neskaitytus pranešimus (numatytasis - tik dabartinė viki).",
+ "apihelp-query+unreadnotificationpages-example-1": "Nurodyti puslapius su neskaitytais pranešimais (jų kiekiu)"
+}
diff --git a/Echo/i18n/api/mai.json b/Echo/i18n/api/mai.json
new file mode 100644
index 00000000..558a4847
--- /dev/null
+++ b/Echo/i18n/api/mai.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "बिप्लब आनन्द"
+ ]
+ },
+ "apihelp-echomarkread-example-1": "अधिसूचना ८ के पढल गेल कहि चिन्हित करी",
+ "apihelp-echomarkread-example-2": "सभ अधिसूचनासभ पढल गेल कहि चिन्हित करी",
+ "apihelp-echomarkread-example-3": "सूचना 1 के नै पढल चिन्हित करी",
+ "apihelp-echomarkseen-description": "वर्तमान प्रयोगकर्ताक अधिसूचनासभ पढल गेल रेखाङ्कित करी।",
+ "apihelp-query+notifications-example-1": "अधिसूचनासभ सूचीबद्ध करी",
+ "apihelp-query+notifications-example-2": "अधिसूचनासभ सूचीबद्ध अनुभागक अनुसार सम्मिलित करि गिनकर करी"
+}
diff --git a/Echo/i18n/api/mk.json b/Echo/i18n/api/mk.json
new file mode 100644
index 00000000..ffad0e7a
--- /dev/null
+++ b/Echo/i18n/api/mk.json
@@ -0,0 +1,61 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06"
+ ]
+ },
+ "apihelp-echomarkread-description": "Означи ги сите известувања како прочитани за тековниот корисник.",
+ "apihelp-echomarkread-summary": "Означи ги сите известувања како прочитани за тековниот корисник.",
+ "apihelp-echomarkread-param-list": "Список на назнаки на известувањата што треба да се означат како прочитани.",
+ "apihelp-echomarkread-param-unreadlist": "Список на назнаки на известувањата што треба да се означат како непрочитани.",
+ "apihelp-echomarkread-param-all": "Ако е зададено, ги означува сите известувања на еден корисник како прочитани.",
+ "apihelp-echomarkread-param-sections": "Список на поднаслови што треба да се означат како прочитани.",
+ "apihelp-echomarkread-example-1": "Означи го известувањето 8 како прочитано",
+ "apihelp-echomarkread-example-2": "Означиу ги сите известувања како прочитани",
+ "apihelp-echomarkread-example-3": "Означи го известувањето 1 како прочитано",
+ "apihelp-echomarkseen-description": "Означи ги известувањата како прочитани за тековниот корисник.",
+ "apihelp-echomarkseen-summary": "Означи ги известувањата како прочитани за тековниот корисник.",
+ "apihelp-echomarkseen-example-1": "Означи ги известувањања од сите видови како прочитани",
+ "apihelp-echomarkseen-param-type": "Видови известувања што треба да се означат како видени: „alert“, „message“ или „all“.",
+ "apihelp-echomarkseen-param-timestampFormat": "Формат за датум и време во изводот, „ISO_8601“ или „MW“. Тука „MW“ е застарен, па така сите клиенти треба да се префрлат на „ISO_8601“. Овој параметар ќе биде отстранет, а „ISO_8601“ ќе стане единствениот формат на изводот.",
+ "apihelp-query+notifications-description": "Дај ги известувањата што го исчекуваат тековниот корисник.",
+ "apihelp-query+notifications-summary": "Дај ги известувањата што го исчекуваат тековниот корисник.",
+ "apihelp-query+notifications-param-prop": "Подробности што треба да се побараат.",
+ "apihelp-query+notifications-param-sections": "Известителните поднаслови што треба да се побараат (т.е. некоја комбинација од „alert“ и „message“).",
+ "apihelp-query+notifications-param-groupbysection": "Дали да се групира исходот по поднаслови. Ако е зададено, секој поднаслов се дава посебно.",
+ "apihelp-query+notifications-param-filter": "Филтрирај ги известувањата во исходот.",
+ "apihelp-query+notifications-param-format": "Ако е укажано, известувањата ќе се дадат форматирани на овој начин.",
+ "apihelp-query+notifications-paramvalue-format-model": "Сирово известување",
+ "apihelp-query+notifications-paramvalue-format-special": "Форматирано за службената страница за известувања (и само за нив!) Не се ослонувајте на HTML бидејќи може да се измени во секое време.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Застарено</span>. Користете <kbd>$1format=model</kbd> за сирови податоци",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Застарено</span>. Користете <kbd>$1format=model</kbd> за сирови податоци",
+ "apihelp-query+notifications-param-limit": "Највеќе известувања што ќе се дадат.",
+ "apihelp-query+notifications-param-wikis": "Список на викија од кои треба да се преземат известувања (по основно: само тековното вики).",
+ "apihelp-query+notifications-param-crosswikisummary": "Точно за да изберете добивање на известувања од нематични викија во збирен краток преглед.",
+ "apihelp-query+notifications-param-alertcontinue": "Употребете го ова за да продолжите кога има повеќе напомени за известувања.",
+ "apihelp-query+notifications-param-unreadfirst": "Дали да се прикажуваат прво непрочитаните известувања (се користи само ако не е зададен groupbysection).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Дали прво да се прикажуваат непрочитаните известувања за порака. (се користи само ако е зададен groupbysection).",
+ "apihelp-query+notifications-param-messagecontinue": "Употребете го ова за да продолжите кога има повеќе исходни ставки за пораки.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Дали прво да се прикажуваат непрочитаните напомени за известувања. (се користи само ако е зададен groupbysection).",
+ "apihelp-query+notifications-param-titles": "Добивање на известувања само од од овие страници. За да добивате известувања неповрзани со ниедна страница, користете го [] како наслов.",
+ "apihelp-query+notifications-param-bundle": "Дали да се прикажува збир од складни непрочитани известувања според правилата за збирање на видовите известувања.",
+ "apihelp-query+notifications-example-1": "Испиши известувања",
+ "apihelp-query+notifications-example-2": "Испиши известувања, групирани по поднаслови, со бројност",
+ "apihelp-query+unreadnotificationpages-description": "Дај страници за кои постојат непрочитани известувања за тековниот корисник.",
+ "apihelp-query+unreadnotificationpages-summary": "Дај страници за кои постојат непрочитани известувања за тековниот корисник.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Групните страници за разговор заедно со нивните предметни страници и групните известувања неповрзани со страница заедно со корисничката страница на тековниот корисник.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Највеќе страници за прикажување.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Список на викија од кои треба да се преземат непрочитани известувања (по основно: само тековното вики).",
+ "apihelp-query+unreadnotificationpages-example-1": "Наведи страници со (бројот на) непрочитани известувања",
+ "apihelp-echoarticlereminder-summary": "Побарај потсетник за укажаната статија",
+ "apihelp-echoarticlereminder-param-pageid": "Назнака на статијата за која ќе се потсети корисникот",
+ "apihelp-echoarticlereminder-param-title": "Наслов на статијата за која ќе се потсети корисникот",
+ "apihelp-echoarticlereminder-param-timestamp": "Кога да се потсети корисникот",
+ "apihelp-echoarticlereminder-param-comment": "Корисничка прибелешка во потсетникот (по желба)",
+ "apihelp-echoarticlereminder-example-1": "Создај потсетник за статијата за утре со содржина",
+ "apihelp-echoarticlereminder-example-2": "Создај потсетник за статија за утре без содржина",
+ "apiwarn-echo-deprecation-timestampformat": "Изводниот формат MW за датуми и време тука е застарен. Во иднина, за таа намена ќе се користи исклучиво ISO 8601. Прилагодете го клиентот и наместете го <var>timestampFormat</var> на <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> е застаре и наскоро ќе биде отстранет. Сировите податоци ќе ги добиете со <kbd>notformat=model</kbd>, а <kbd>notformat=special</kbd> служи за предиспишан HTML.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> е застарен и наскоро ќе биде отстранет. Наместо него, користете го <kbd>notformat=special</kbd>.",
+ "apierror-echo-event-creation-failed": "Не можев да направам настан за Ехо"
+}
diff --git a/Echo/i18n/api/ml.json b/Echo/i18n/api/ml.json
new file mode 100644
index 00000000..2b36af2b
--- /dev/null
+++ b/Echo/i18n/api/ml.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Praveenp"
+ ]
+ },
+ "apihelp-echomarkread-description": "ഇപ്പോഴത്തെ ഉപയോക്താവിന്റെ അറിയിപ്പുകൾ വായിച്ചതായി അടയാളപ്പെടുത്തുക.",
+ "apihelp-echomarkread-param-list": "വായിച്ചതായി അടയാളപ്പെടുത്തേണ്ട അറിയിപ്പ് ഐ.ഡി.കളുടെ പട്ടിക.",
+ "apihelp-echomarkread-param-all": "സജ്ജമെങ്കിൽ ഉപയോക്താവിനുള്ള അറിയിപ്പുകളെല്ലാം വായിച്ചതായി അടയാളപ്പെടുത്തുക.",
+ "apihelp-echomarkread-param-sections": "വായിച്ചതായി അടയാളപ്പെടുത്തേണ്ട ഭാഗങ്ങളുടെ പട്ടിക.",
+ "apihelp-echomarkread-example-1": "അറിയിപ്പ് 8 വായിച്ചതായി അടയാളപ്പെടുത്തുക",
+ "apihelp-echomarkread-example-2": "എല്ലാ അറിയിപ്പുകളും വായിച്ചതായി അടയാളപ്പെടുത്തുക",
+ "apihelp-echomarkseen-description": "ഇപ്പോഴത്തെ ഉപയോക്താവ് കണ്ടെന്ന് അറിയിപ്പുകളിൽ അടയാളപ്പെടുത്തുക.",
+ "apihelp-echomarkseen-example-1": "എല്ലാ തരത്തിലുമുള്ള അറിയിപ്പുകളും കണ്ടെന്ന് അടയാളപ്പെടുത്തുക",
+ "apihelp-echomarkseen-param-type": "കണ്ടതായി അടയാളപ്പെടുത്തേണ്ട അറിയിപ്പുകളുടെ തരം: 'അറിയിപ്പ്', 'സന്ദേശം', 'എല്ലാം'.",
+ "apihelp-query+notifications-description": "ഇപ്പോഴത്തെ ഉപയോക്താവിനായി കാത്തുനിൽക്കുന്ന അറിയിപ്പുകൾ ലഭ്യമാക്കുക.",
+ "apihelp-query+notifications-param-prop": "അഭ്യർത്ഥനയുടെ വിശദാംശങ്ങൾ.",
+ "apihelp-query+notifications-param-sections": "ചോദിക്കേണ്ട അറിയിപ്പ് ഭാഗങ്ങൾ (അതായത് 'അറിയിപ്പ്', 'സന്ദേശം' എന്നിവയുടെ മിശ്രണം).",
+ "apihelp-query+notifications-param-groupbysection": "ഫലങ്ങൾ വിഭാഗമനുസരിച്ച് വർഗ്ഗീകരിക്കണോ. സജ്ജമെങ്കിൽ ഓരോ ഭാഗവും വ്യത്യസ്തമായിട്ടാവും എടുക്കുക.",
+ "apihelp-query+notifications-param-filter": "അരിപ്പയുടെ അറിയിപ്പുകൾ തിരിച്ചയച്ചിരിക്കുന്നു.",
+ "apihelp-query+notifications-param-format": "വ്യക്തമാക്കിയിട്ടുണ്ടെങ്കിൽ, അറിയിപ്പുകൾ ഇതുവഴിയായിരിക്കും വിന്യസികുക.",
+ "apihelp-query+notifications-param-limit": "എടുക്കേണ്ട അറിയിപ്പുകളുടെ പരമാവധി എണ്ണം.",
+ "apihelp-query+notifications-param-alertcontinue": "അധികം അറിയിപ്പ് ഫലങ്ങൾ ലഭ്യമായിരിക്കുമ്പോൾ, തുടരാൻ ഇതുപയോഗിക്കുക.",
+ "apihelp-query+notifications-param-alertunreadfirst": "വായിക്കാത്ത സന്ദേശ അറിയിപ്പുകൾ ആദ്യം പ്രദർശിപ്പിക്കണോ.",
+ "apihelp-query+notifications-param-messagecontinue": "അധികം സന്ദേശ ഫലങ്ങൾ ലഭ്യമായിരിക്കുമ്പോൾ, തുടരാൻ ഇതുപയോഗിക്കുക.",
+ "apihelp-query+notifications-param-messageunreadfirst": "വായിക്കാത്ത വിവരദായക അറിയിപ്പുകൾ ആദ്യം പ്രദർശിപ്പിക്കണോ.",
+ "apihelp-query+notifications-example-1": "അറിയിപ്പുകൾ പട്ടികയാക്കുക",
+ "apihelp-query+notifications-example-2": "അറിയിപ്പുകൾ വിഭാഗമനുസരിച്ച് എണ്ണം നൽകി വർഗ്ഗീകരിച്ച് പട്ടികയാക്കുക"
+}
diff --git a/Echo/i18n/api/mr.json b/Echo/i18n/api/mr.json
new file mode 100644
index 00000000..4595770b
--- /dev/null
+++ b/Echo/i18n/api/mr.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "V.narsikar"
+ ]
+ },
+ "apihelp-echomarkread-description": "सध्याच्या सदस्यासाठी अधिसूचनांवर वाचले अशी खूण करा.",
+ "apihelp-echomarkread-param-list": "वाचले म्हणून खूण करण्यास अधिसूचना ओळखणींची यादी.",
+ "apihelp-echomarkread-param-unreadlist": "वाचले नाही अशी खूण करण्यास अधिसूचनांच्या ओळखणींची यादी.",
+ "apihelp-echomarkread-param-all": "जर स्थापिल्या गेले तर, कोणत्याही सदस्यांच्या सर्व अधिसूचनांवर वाचले अशी खूण करते.",
+ "apihelp-echomarkread-param-sections": "वाचले म्हणून खूण करण्यास विभागांची यादी.",
+ "apihelp-echomarkread-example-1": "अधिसूचना क्रमांक ८ वर वाचले अशी खूण करा",
+ "apihelp-echomarkread-example-2": "सर्व अधिसूचना वाचल्यात अशी खूण करा",
+ "apihelp-echomarkread-example-3": "अधिसूचना १ वर वाचले नाही अशी खूण करा",
+ "apihelp-echomarkseen-description": "सध्याच्या सदस्यास अधिसूचना बघितल्या अशी खूण करा.",
+ "apihelp-echomarkseen-example-1": "सर्व प्रकारच्या अधिसूचना बघितल्या अशी खूण करा",
+ "apihelp-echomarkseen-param-type": "बघितले अशी खूण करण्यास, अधिसूचनेचे प्रकार:'सजगता', 'संदेश' किंवा 'सर्व'.",
+ "apihelp-query+notifications-description": "सध्याच्या सदस्यासाठी ताटकळत असलेल्या अधिसूचना प्राप्त करा.",
+ "apihelp-query+notifications-param-prop": "विनंती करावयाचा तपशिल.",
+ "apihelp-query+notifications-param-sections": "पृच्छा करावयासाठीचे विभाग (म्हणजे - 'सजगता' व 'संदेश' यांची सरमिसळ).",
+ "apihelp-query+notifications-param-groupbysection": "निकालाचे विभागानुसार गट करावयाचे काय. जर स्थापिल्या गेले तर,प्रत्येक विभागास वेगळ्या रितीने पुरवठा होतो.",
+ "apihelp-query+notifications-param-format": "जर नमूद केले तर, अधिसूचना या प्रकारे प्रारुपण करुन पाठविल्या जातील.",
+ "apihelp-query+notifications-param-wikis": "अधिसूचना पुरवाविण्यास असलेली विकिंची यादी (फक्त सध्याच्या विकिसाठीच फक्त अविचल)",
+ "apihelp-query+notifications-param-messagecontinue": "जेंव्हा अधिक संदेश निकाल उपलब्ध असतील, याचा वापर पुढे जाण्यास करा.",
+ "apihelp-query+notifications-param-titles": "या पानांसाठीच्या फक्त परतीच्या अधिसूचना.कोणत्याही पानाशी संलग्न नसलेल्या अधिसूचना मिळविण्यास,[]शीर्षक म्हणून वापरा.",
+ "apihelp-query+notifications-example-1": "अधिसूचनांची यादी करा",
+ "apihelp-query+notifications-example-2": "अधिसूचनांचे विभागानुसार गट पाडून,मोजणीसह यादी करा",
+ "apihelp-query+unreadnotificationpages-example-1": "पानांची यादी न वाचलेल्या अधिसूचना (त्यांच्या आकड्यांसह)"
+}
diff --git a/Echo/i18n/api/nap.json b/Echo/i18n/api/nap.json
new file mode 100644
index 00000000..3f6ca243
--- /dev/null
+++ b/Echo/i18n/api/nap.json
@@ -0,0 +1,45 @@
+{
+ "@metadata": {
+ "authors": [
+ "C.R."
+ ]
+ },
+ "apihelp-echomarkread-description": "Nzegna tutt' 'e notifiche comm'a fossero liggiute 'a ll'utente.",
+ "apihelp-echomarkread-param-list": "N'elenco 'e ll'ID notifiche 'a nzegnare comme fossero lette.",
+ "apihelp-echomarkread-param-unreadlist": "N'elenco 'e ll'ID notifiche 'a nzegnare comme nun fossero lette.",
+ "apihelp-echomarkread-param-all": "Si mpustato, contrassegna tutte 'e notifiche 'e ll'utente comme fossero lette.",
+ "apihelp-echomarkread-param-sections": "N'elenco d' 'e sezine ca s'avesser'a nzegnà comme liggiute.",
+ "apihelp-echomarkread-example-1": "Nzegna 'a notifica 8 comme liggiuta",
+ "apihelp-echomarkread-example-2": "Nzegna tutt' 'e notifiche comme fossero liggiute",
+ "apihelp-echomarkread-example-3": "Nzegna 'a notifica 1 comme nun liggiuta",
+ "apihelp-echomarkseen-description": "Nzegna 'e notifiche comme fossero liggiute 'a ll'utente 'e mo'.",
+ "apihelp-echomarkseen-example-1": "Nzegna tutte 'e notifiche comme liggiute",
+ "apihelp-echomarkseen-param-type": "Tipo 'e notifica pe' nzegnà visto comme: 'allerta', 'mmasciata' o 'tutto'.",
+ "apihelp-query+notifications-description": "Piglia 'e notifiche ca stesser'aspettann'a ll'utente.",
+ "apihelp-query+notifications-param-prop": "Dettaglie d' 'a richiesta.",
+ "apihelp-query+notifications-param-sections": "'E seziune 'e notifica a se ffà 'a query (fossero p'esempio na cumbinazione 'allerta' e 'mmasciata').",
+ "apihelp-query+notifications-param-groupbysection": "Si vulite accucchià 'o risultato pe' sezziona. Ogne seziona se pigliasse comme fosse a spartuta si chisto se buò ffà.",
+ "apihelp-query+notifications-param-filter": "Notifiche 'e filtre turnate.",
+ "apihelp-query+notifications-param-format": "Quanno fosse specificato, 'e notifiche fossero turnate cu stu formato.",
+ "apihelp-query+notifications-paramvalue-format-text": "Testo furmato semprice",
+ "apihelp-query+notifications-paramvalue-format-model": "Notifica 'e date 'ncruro",
+ "apihelp-query+notifications-paramvalue-format-special": "Furmattato p' 'a paggena 'e Special:Notifications (e sulo chesta!) Non v'affidà surtant'a 'o codece HTML pecché chesto putesse cagnà int'a n'atu mumento.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Obsoleto</span>. Ausà <kbd>$1format=model</kbd> p' 'e date 'ncruro",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Obsoleto</span>. Ausà <kbd>$1format=model</kbd> p' 'e date 'ncruro",
+ "apihelp-query+notifications-param-limit": "'O nummero massimo 'e notifiche ca s'avess'a turnà.",
+ "apihelp-query+notifications-param-wikis": "Elenco 'e wiki addò se piglià 'e notifiche (predefinito surtanto 'o wiki 'e mò).",
+ "apihelp-query+notifications-param-crosswikisummary": "Overo (True) pe' puté dicere sì a se piglia nu riassunto 'e notifiche 'e wiki 'e fore.",
+ "apihelp-query+notifications-param-alertcontinue": "Quanno stessero cchiù risultate ccà a disposizione, facite stu prucesso pe cuntinuà.",
+ "apihelp-query+notifications-param-unreadfirst": "Si vulite fà vedé 'e notifiche nun liggiute primma (ausato surtanto si groupbysection fosse mpustato).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Si s'avess'a mmusta na mmasciata nun liggiuta 'e notifiche apprimma (ausato surtanto si groupbysection fosse mpustato).",
+ "apihelp-query+notifications-param-messagecontinue": "Quanno cchiù mmasciate sarranno a disposiziona, ausa chesto pe' cuntinuà.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Si vulite mmustà notifiche senza lieggere primma (ausato surtanto si groupbysection fosse mpustato).",
+ "apihelp-query+notifications-param-titles": "Turnasse surtanto 'e notifiche pe' sti ppaggene. Pe' se puté piglià notifiche nun azzeccate a na paggena, ausate [] comme fosse 'o titolo.",
+ "apihelp-query+notifications-example-1": "Elenca notifiche",
+ "apihelp-query+notifications-example-2": "Elenca notifiche, raggruppate pe' seziona, cu 'e cuntegge",
+ "apihelp-query+unreadnotificationpages-description": "Piglià paggene p' 'e quale ce stanno notifiche ca nun fossero ancora ligiute 'a ll'utente 'e mò.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Paggene 'e chiacchiera 'e gruppo nziem'a ll'argomento suo, e notifiche 'e gruppo nun suòcie a na paggena nziem'a na paggena utente.",
+ "apihelp-query+unreadnotificationpages-param-limit": "'O nummero massimo 'e paggene ca s'avess'a turnà.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Elenco 'e wiki addò se piglià paggene ch' 'e notifiche nun liggiute (predefinite surtanto a 'o wiki 'e mò).",
+ "apihelp-query+unreadnotificationpages-example-1": "Elenco 'e paggene cu ('o cunto 'e) notifche senza lieggere"
+}
diff --git a/Echo/i18n/api/nb.json b/Echo/i18n/api/nb.json
new file mode 100644
index 00000000..78cde5bd
--- /dev/null
+++ b/Echo/i18n/api/nb.json
@@ -0,0 +1,63 @@
+{
+ "@metadata": {
+ "authors": [
+ "Danmichaelo",
+ "Jeblad",
+ "Jon Harald Søby"
+ ]
+ },
+ "apihelp-echomarkread-description": "Merk beskjeder som leste for den aktuelle brukeren.",
+ "apihelp-echomarkread-summary": "Marker varsler som lest for den gjeldende brukeren.",
+ "apihelp-echomarkread-param-list": "En liste over ID-er for beskjeder som skal merkes som lest.",
+ "apihelp-echomarkread-param-unreadlist": "En liste av beskjed-IDer som merkes som ulest.",
+ "apihelp-echomarkread-param-all": "Merk alle brukerens beskjeder som lest.",
+ "apihelp-echomarkread-param-sections": "En liste over seksjoner som skal markeres som leste.",
+ "apihelp-echomarkread-example-1": "Merk beskjed 8 som lest",
+ "apihelp-echomarkread-example-2": "Merk alle beskjeder som leste",
+ "apihelp-echomarkread-example-3": "Merk beskjed 1 som ulest",
+ "apihelp-echomarkseen-description": "Merk beskjeder som sett for den gjeldende brukeren.",
+ "apihelp-echomarkseen-summary": "Marker varsler som sett for den gjeldende brukeren.",
+ "apihelp-echomarkseen-example-1": "Merk beskjeder av alle typer som sett",
+ "apihelp-echomarkseen-param-type": "Type beskjeder som skal merkes som sett: 'alert', 'message' eller 'all'.",
+ "apihelp-echomarkseen-param-timestampFormat": "Tidsstempelformat for resultatet, «ISO_8601» eller «MW». «MW» er foreldet her, så alle klienter bør bytte til «ISO_8601». Denne parameteren vil fjernes, og «ISO_8601» vil bli det eneste mulige formatet.",
+ "apihelp-query+notifications-description": "Hent ventende beskjeder for den aktuelle brukeren.",
+ "apihelp-query+notifications-summary": "Hent varsler som venter for den gjeldende brukeren.",
+ "apihelp-query+notifications-param-prop": "Detaljer som skal forespørres.",
+ "apihelp-query+notifications-param-sections": "Beskjedstypene som skal spørres (f.eks. en kombinasjon av 'alert' og 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Hvorvidt resultatet skal grupperes etter seksjon. Hver seksjon hentes hver for seg hvis gitt.",
+ "apihelp-query+notifications-param-filter": "Filtrer returnerte beskjeder.",
+ "apihelp-query+notifications-param-format": "Hvis angitt blir beskjedene formatert på denne måten.",
+ "apihelp-query+notifications-paramvalue-format-model": "Rå beskjedsdata",
+ "apihelp-query+notifications-paramvalue-format-special": "Formatert for siden Spesial:Beskjeder (og bare den!) Ikke stol på HTML-utlegget da det kan endres uten varsel.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Utgått</span>. Bruk <kbd>$1format=model</kbd> for rådata",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Utgått</span>. Bruk <kbd>$1format=model</kbd> for rådata",
+ "apihelp-query+notifications-param-limit": "Maks antall beskjeder som skal returneres.",
+ "apihelp-query+notifications-param-wikis": "Liste av wikier hvorfra det hentes beskjeder (standard er bare nåværende wiki).",
+ "apihelp-query+notifications-param-crosswikisummary": "Sann for å opt inn til et sammendrag av beskjeder fra fremmede wikier.",
+ "apihelp-query+notifications-param-alertcontinue": "Når flere resultat-varsler er tilgjengelig, bruk denne for å fortsette.",
+ "apihelp-query+notifications-param-unreadfirst": "Skal uleste beskjeder vises først (bare brukt hvis groupbysection ikke er satt).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Hvorvidt uleste beskjeder skal vises først (kun brukt hvis groupbysection er satt).",
+ "apihelp-query+notifications-param-messagecontinue": "Når flere resultat-meldinger er tilgjengelig, bruk denne for å fortsette.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Hvorvidt uleste beskjeder skal vises først (kun brukt hvos groupbysection er satt).",
+ "apihelp-query+notifications-param-titles": "Bare returner notiser for disse sidene. For å få notiser som ikke er knyttet til noen side, bruk [] som tittel.",
+ "apihelp-query+notifications-param-bundle": "Hvorvidt uleste beskjeder skal grupperes.",
+ "apihelp-query+notifications-example-1": "List beskjeder",
+ "apihelp-query+notifications-example-2": "List beskjeder, gruppert etter seksjon, med antall",
+ "apihelp-query+unreadnotificationpages-description": "Få sider som har uleste notiser for gjeldende bruker.",
+ "apihelp-query+unreadnotificationpages-summary": "Hent sider det er uleste varsler for for den gjeldende brukeren.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Grupper diskusjonssider sammen med hovedsidene, og grupper beskjeder som ikke er knytta til en side sammen med den aktive brukerens brukerside.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Maksimalt antall av sider som skal returneres.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Liste av wikier som det skal hentes sider fra og som har uleste notiser (som standard kun inneværende wiki).",
+ "apihelp-query+unreadnotificationpages-example-1": "List sider med (deres antall av) uleste notiser.",
+ "apihelp-echoarticlereminder-summary": "Be om fremtidig påminnelse om den gitte artikkelen",
+ "apihelp-echoarticlereminder-param-pageid": "ID-en til artikkelen brukeren skal minnes på",
+ "apihelp-echoarticlereminder-param-title": "Tittelen på artikkelen brukeren skal minnes på",
+ "apihelp-echoarticlereminder-param-timestamp": "Hvilket tidsstempel brukeren skal minnes på på",
+ "apihelp-echoarticlereminder-param-comment": "Valgfri brukerkommentar som skal inkluderes i påminnelsen",
+ "apihelp-echoarticlereminder-example-1": "Opprett et varsel for artikkelpåminnelse for i morgen med kommentar",
+ "apihelp-echoarticlereminder-example-2": "Opprett et varsel for artikkelpåminnelse for i morgen uten kommentar",
+ "apiwarn-echo-deprecation-timestampformat": "MW-tidsstempelformatet er utdatert her. I fermtiden vil alltid ISO 8601 brukes for resultatet av tidsstempelformatet. Endre innstillingene i klienten din og sett <var>timestampFormat</var> til <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> er utdatert og vil fjernes snart. Bruk <kbd>notformat=model</kbd> for å få rådata eller <kbd>notformat=special</kbd> for forhåndsrendret HTML.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> er utdatert og vil fjernes snart. Bruk <kbd>notformat=special</kbd> i stedet.",
+ "apierror-echo-event-creation-failed": "Kunne ikke opprette Echo-hendelse"
+}
diff --git a/Echo/i18n/api/nl.json b/Echo/i18n/api/nl.json
new file mode 100644
index 00000000..0b02161b
--- /dev/null
+++ b/Echo/i18n/api/nl.json
@@ -0,0 +1,47 @@
+{
+ "@metadata": {
+ "authors": [
+ "Catrope",
+ "MrLeopold",
+ "Romaine",
+ "Siebrand",
+ "Sjoerddebruin",
+ "Mainframe98"
+ ]
+ },
+ "apihelp-echomarkread-description": "Meldingen van de huidige gebruiker markeren als gelezen.",
+ "apihelp-echomarkread-summary": "Meldingen van de huidige gebruiker markeren als gelezen.",
+ "apihelp-echomarkread-param-list": "Een lijst van ID's van meldingen om te markeren als gelezen.",
+ "apihelp-echomarkread-param-unreadlist": "Lijst van meldings-ID's om die als ongelezen gemarkeerd moeten worden.",
+ "apihelp-echomarkread-param-all": "Indien ingesteld, worden alle meldingen van de gebruiker gemarkeerd als gelezen.",
+ "apihelp-echomarkread-param-sections": "Een lijst van secties om te markeren als gelezen.",
+ "apihelp-echomarkread-example-1": "Melding 8 als gelezen markeren",
+ "apihelp-echomarkread-example-2": "Alle meldingen als gelezen markeren",
+ "apihelp-echomarkread-example-3": "Markeer melding 1 als ongelezen.",
+ "apihelp-echomarkseen-description": "Aangeven dat de huidige gebruiker zijn of haar meldingen heeft gezien.",
+ "apihelp-echomarkseen-summary": "Aangeven dat de huidige gebruiker zijn of haar meldingen heeft gezien.",
+ "apihelp-echomarkseen-example-1": "Aangeven dat meldingen van alle soorten zijn gezien",
+ "apihelp-echomarkseen-param-type": "Soorten meldingen om te markeren als gezien: 'alert', 'message' of 'all'.",
+ "apihelp-query+notifications-description": "Wachtende meldingen voor de huidige gebruiker opvragen.",
+ "apihelp-query+notifications-param-prop": "Details voor verzoek.",
+ "apihelp-query+notifications-param-sections": "De notificatieonderdelen in de zoekopdracht, bijvoorbeeld een combinatie van \"alert\" en \"message\".",
+ "apihelp-query+notifications-param-groupbysection": "Of resultaat op onderdeel gegroepeerd moeten worden. Elk onderdeel wordt separaat opgehaald als dit is ingesteld.",
+ "apihelp-query+notifications-param-filter": "De opgevraagde meldingen filteren.",
+ "apihelp-query+notifications-param-format": "Indien opgegeven, worden meldingen teruggegeven met deze opmaak.",
+ "apihelp-query+notifications-paramvalue-format-model": "Rauwe meldingsdata",
+ "apihelp-query+notifications-paramvalue-format-special": "Formaat voor gebruik op Speciaal:Meldingen (en alleen op die pagina!) Vertrouw niet op deze HTML, het formaat kan op elk moment veranderen.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Verouderd</span>. Gebruik <kbd>$1format=model</kbd> voor rauwe data",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Veroudered</span>. Gebruik <kbd>$1format=model</kbd> voor rauwe data",
+ "apihelp-query+notifications-param-limit": "Het maximum aantal opgevraagde meldingen beperken.",
+ "apihelp-query+notifications-param-wikis": "Lijst van wiki's om meldingen van te ontvangen (standaard alleen de huidige wiki).",
+ "apihelp-query+notifications-param-crosswikisummary": "Voeg samengevatte informatie over meldingen op andere wiki's toe.",
+ "apihelp-query+notifications-param-alertcontinue": "Gebruik dit voor continueren als er meer waarschuwingen beschikbaar zijn.",
+ "apihelp-query+notifications-param-unreadfirst": "Of ongelezen meldingen als eerste moeten worden weergegeven (wordt genegeerd als groupbysection niet gebruikt is).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Of ongelezen meldingen over berichten als eerste moeten worden weergeven (wordt genegeerd als groupbysection niet gebruikt is).",
+ "apihelp-query+notifications-param-messagecontinue": "Gebruik dit voor continueren als er meer berichten beschikbaar zijn.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Of ongelezen meldingen als eerste moeten worden weergeven (wordt genegeerd als groupbysection niet gebruikt is).",
+ "apihelp-query+notifications-example-1": "Meldingen opvragen",
+ "apihelp-query+notifications-example-2": "Meldingen, gesorteerd op sectie en met aantal meldingen, opvragen",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Groepeer overlegpagina's samen met hun onderwerpspagina en groepsmeldingen die niet verbonden zijn aan een pagina samen met de gebruikerspagina van de huidige gebruiker.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Het maximale aantal weer te geven pagina's."
+}
diff --git a/Echo/i18n/api/oc.json b/Echo/i18n/api/oc.json
new file mode 100644
index 00000000..0e03113b
--- /dev/null
+++ b/Echo/i18n/api/oc.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31"
+ ]
+ },
+ "apihelp-echomarkread-example-2": "Marcar totas las notificacions coma legidas"
+}
diff --git a/Echo/i18n/api/pl.json b/Echo/i18n/api/pl.json
new file mode 100644
index 00000000..41c16229
--- /dev/null
+++ b/Echo/i18n/api/pl.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chrumps",
+ "Woytecr"
+ ]
+ },
+ "apihelp-echomarkread-description": "Oznacz powiadomienia jako przeczytane dla bieżącego użytkownika.",
+ "apihelp-echomarkread-param-list": "Lista ID powiadomień do oznaczenia jako przeczytane.",
+ "apihelp-echomarkread-param-unreadlist": "Lista ID powiadomień do oznaczenia jako nieprzeczytane.",
+ "apihelp-echomarkread-param-all": "Jeżeli ustawiono, oznacza wszystkie powiadomienia użytkownika jako przeczytane.",
+ "apihelp-echomarkread-param-sections": "Lista sekcji do oznaczania jako przeczytane.",
+ "apihelp-echomarkread-example-1": "Oznacz powiadomienie 8 jako przeczytane",
+ "apihelp-echomarkread-example-2": "Oznacz wszystkie powiadomienia jako przeczytane",
+ "apihelp-echomarkread-example-3": "Oznacz powiadomienie 1 jako nieprzeczytane",
+ "apihelp-echomarkseen-description": "Oznacz powiadomienia jako przeczytane dla bieżącego użytkownika.",
+ "apihelp-echomarkseen-example-1": "Oznacz powiadomienia wszystkich typów jako przeczytane",
+ "apihelp-echomarkseen-param-type": "Typ powiadomień do oznaczenia jako przeczytane: 'alert', 'message' lub 'all'.",
+ "apihelp-query+notifications-description": "Pobierz powiadomienia oczekujące dla bieżącego użytkownika.",
+ "apihelp-query+notifications-param-prop": "Szczegóły żądania.",
+ "apihelp-query+notifications-param-sections": "Sekcje powiadomień, o które zapytać (tj. jakieś połączenie 'alert' i 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Czy grupować wynik według sekcji. Każda sekcja jest pobierana osobno jeśli ustawiono.",
+ "apihelp-query+notifications-param-filter": "Filtruj zwrócone powiadomienia.",
+ "apihelp-query+notifications-param-format": "Jeśli określono, powiadomienia zostaną zwrócone sformatowane w taki sposób.",
+ "apihelp-query+notifications-paramvalue-format-text": "Format tekstowy",
+ "apihelp-query+notifications-paramvalue-format-model": "Surowe dane powiadomienia",
+ "apihelp-query+notifications-paramvalue-format-special": "Sformatowane dla strony Specjalna:Powiadomienia (i tylko tej!). Nie polegaj na HTML, jako że może zmienić się w dowolnym czasie.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Zdeprecjonowane</span>. Użyj <kbd>$1format=model</kbd> dla surowych danych",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Zdeprecjonowane</span>. Użyj <kbd>$1format=model</kbd> dla surowych danych",
+ "apihelp-query+notifications-param-limit": "Maksymalna liczba zwracanych powiadomień.",
+ "apihelp-query+notifications-param-wikis": "Lista wiki, z których pobrać powiadomienia (domyślnie tylko bieżąca wiki).",
+ "apihelp-query+notifications-example-1": "Spis powiadomień",
+ "apihelp-query+unreadnotificationpages-param-limit": "Maksymalna liczba zwracanych stron."
+}
diff --git a/Echo/i18n/api/pms.json b/Echo/i18n/api/pms.json
new file mode 100644
index 00000000..ee7e4795
--- /dev/null
+++ b/Echo/i18n/api/pms.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Borichèt"
+ ]
+ },
+ "apihelp-echomarkread-description": "Marché le notìfiche coma lesùe për l'utent atual.",
+ "apihelp-echomarkread-param-list": "Na lista d'ID ëd notìfica da marché coma lesù.",
+ "apihelp-echomarkread-param-all": "Si definì, a marca tute le notìfiche ëd n'utent coma lesùe.",
+ "apihelp-echomarkread-param-sections": "Na lista ëd session da marché coma lesùe.",
+ "apihelp-echomarkread-example-1": "Marché la notìtica 8 coma lesùa",
+ "apihelp-echomarkread-example-2": "Marché tute le notìfiche coma lesùe",
+ "apihelp-query+notifications-description": "Oten-e le notìfiche an atèisa për l'utent atual.",
+ "apihelp-query+notifications-param-prop": "Detaj da ciamé.",
+ "apihelp-query+notifications-param-sections": "Le session ëd notìfica da ciamé.",
+ "apihelp-query+notifications-param-groupbysection": "S'a venta argropé j'arzultà për session. Minca na session a l'é analisà për sò cont s'a l'é definì.",
+ "apihelp-query+notifications-param-format": "Si spessificà, le notìfiche a sarà mandà ant ës formà.",
+ "apihelp-query+notifications-param-limit": "Ël nùmer màssim ëd notìfiche da mandé.",
+ "apihelp-query+notifications-param-alertcontinue": "Cand a son disponìbij vàire arzultà d'alerta, dovré sòn për andé anans.",
+ "apihelp-query+notifications-param-alertunreadfirst": "S'a venta smon-e prima le notìfiche dij mëssagi nen lesù.",
+ "apihelp-query+notifications-param-messagecontinue": "Cand vàire arzultà ëd mëssagi a son disponìbij, dovré sòn për andé anans.",
+ "apihelp-query+notifications-param-messageunreadfirst": "S'a venta smon-e prima le notìfiche d'alerta nen lesùe.",
+ "apihelp-query+notifications-example-1": "Listé le modìfiche",
+ "apihelp-query+notifications-example-2": "Lista dle notìfiche, argropà për session, con ij conteur"
+}
diff --git a/Echo/i18n/api/pt-br.json b/Echo/i18n/api/pt-br.json
new file mode 100644
index 00000000..11ed245b
--- /dev/null
+++ b/Echo/i18n/api/pt-br.json
@@ -0,0 +1,62 @@
+{
+ "@metadata": {
+ "authors": [
+ "TheEduGobi",
+ "Felipe L. Ewald"
+ ]
+ },
+ "apihelp-echomarkread-description": "Marcar notificações como lidas para o usuário atual.",
+ "apihelp-echomarkread-summary": "Marcar notificações como lidas para o usuário atual.",
+ "apihelp-echomarkread-param-list": "Uma lista de IDs de notificação para marcar como lidos.",
+ "apihelp-echomarkread-param-unreadlist": "Uma lista de IDs de notificação para marcar como não lido.",
+ "apihelp-echomarkread-param-all": "Se habilitado, marca todas as notificações de um usuário como lidas.",
+ "apihelp-echomarkread-param-sections": "Uma lista de seções para marcar como lidas.",
+ "apihelp-echomarkread-example-1": "Marcar a notificação 8 como lida",
+ "apihelp-echomarkread-example-2": "Marcar todas as notificações como lidas",
+ "apihelp-echomarkread-example-3": "Marcar a notificação 1 como não lida",
+ "apihelp-echomarkseen-description": "Marcar notificações como vistas para o usuário atual.",
+ "apihelp-echomarkseen-summary": "Marcar notificações como vistas para o usuário atual.",
+ "apihelp-echomarkseen-example-1": "Marcar notificações de todos os tipos como vistas",
+ "apihelp-echomarkseen-param-type": "Tipo de notificações para marcar como vistas: 'alerta', 'mensagem' ou 'tudo'.",
+ "apihelp-echomarkseen-param-timestampFormat": "Formato do carimbo de data/hora para usar para saída, 'ISO_8601' ou 'MW'. 'MW' está obsoleto aqui, então todos os clientes devem mudar para 'ISO_8601'. Este parâmetro será removido e 'ISO_8601' se tornará o único formato de saída.",
+ "apihelp-query+notifications-description": "Receber notificações aguardando pelo usuário atual.",
+ "apihelp-query+notifications-summary": "Receber notificações aguardando pelo usuário atual.",
+ "apihelp-query+notifications-param-prop": "Detalhes para solicitar.",
+ "apihelp-query+notifications-param-sections": "As seções de notificação para consultar (ou seja, uma combinação de 'alerta' e 'mensagem').",
+ "apihelp-query+notifications-param-groupbysection": "Se agrupar ou não os resultados por seção. Se habilitado, cada seção será obtida separadamente.",
+ "apihelp-query+notifications-param-filter": "Filtrar notificações retornadas.",
+ "apihelp-query+notifications-param-format": "Se especificado, o retorno das notificações será formatado desta maneira.",
+ "apihelp-query+notifications-paramvalue-format-model": "Dados de notificação brutos",
+ "apihelp-query+notifications-paramvalue-format-special": "Formatado para a páginaSpecial:Notifications (e só isso!) Não confie no HTML, pois pode mudar a qualquer momento.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Obsoleto</span>. Use <kbd>$1format=model</kbd> para dados raw",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Obsoleto</span>. Use <kbd>$1format=model</kbd> para dados raw",
+ "apihelp-query+notifications-param-limit": "O número máximo do retorno das notificações.",
+ "apihelp-query+notifications-param-wikis": "Lista de wikis para as quais buscar notificações(padrão apenas wiki atual).",
+ "apihelp-query+notifications-param-crosswikisummary": "Verdadeiro para optar por uma notificação sumária de notificações em wikis estrangeiras.",
+ "apihelp-query+notifications-param-alertcontinue": "Quando mais resultados de alerta estiverem disponíveis, use isto para continuar.",
+ "apihelp-query+notifications-param-unreadfirst": "Seja para exibir as notificações não lidas primeiro (usadas apenas se a seção de grupo não estiver configurada).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Se exibir notificações de mensagens não lidas primeiro ou não.",
+ "apihelp-query+notifications-param-messagecontinue": "Quando mais resultados de mensagem estiverem disponíveis, use isto para continuar.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Se exibir notificações de alertas não lidas primeiro ou não.",
+ "apihelp-query+notifications-param-titles": "Somente as notificações de retorno para essas páginas. Para receber notificações não associadas a qualquer página, use [] como título.",
+ "apihelp-query+notifications-param-bundle": "Seja para mostrar notificações não lidas compatíveis com o pacote de acordo com as regras de agrupamento dos tipos de notificação.",
+ "apihelp-query+notifications-example-1": "Listar notificações",
+ "apihelp-query+notifications-example-2": "Listar notificações agrupadas por seção, incluindo contadores",
+ "apihelp-query+unreadnotificationpages-description": "Obter páginas para as quais há notificações não lidas para o usuário atual.",
+ "apihelp-query+unreadnotificationpages-summary": "Obter páginas para as quais há notificações não lidas para o usuário atual.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Agrupar páginas de discussão em conjunto com a página de assunto e notificações de grupo não associadas a uma página juntamente com a página de usuário do usuário atual.",
+ "apihelp-query+unreadnotificationpages-param-limit": "O número máximo de páginas para retornar.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Lista de wikis para as quais buscar páginas com notificações não lidas de (padrão apenas wiki atual).",
+ "apihelp-query+unreadnotificationpages-example-1": "Listar páginas com (a quantidade de) notificações não lidas",
+ "apihelp-echoarticlereminder-summary": "Solicite um lembrete futuro sobre o artigo especificado",
+ "apihelp-echoarticlereminder-param-pageid": "ID do artigo para o qual lembrar ao usuário",
+ "apihelp-echoarticlereminder-param-title": "Título do artigo para o qual lembrar ao usuário",
+ "apihelp-echoarticlereminder-param-timestamp": "Em qual timestamp lembrar o usuário",
+ "apihelp-echoarticlereminder-param-comment": "Comentário de usuário opcional para incluir no lembrete",
+ "apihelp-echoarticlereminder-example-1": "Crie uma notificação de lembrete do artigo para amanhã com comentários",
+ "apihelp-echoarticlereminder-example-2": "Crie uma notificação de lembrete do artigo para amanhã sem comentários",
+ "apiwarn-echo-deprecation-timestampformat": "O formato de saída do timestamp do MW está obsoleto aqui. No futuro, o ISO 8601 sempre será usado para o formato do timestamp de saída. Ajuste seu cliente e defina <var>timestampFormat</var> para <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> foi depreciado e será removido em breve. Use <kbd>notformat=model</kbd> para obter os dados brutos ou <kbd>notformat=special</kbd> para o HTML pré-renderizado.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> foi depreciado e será removido em breve. Use <kbd>notformat=special</kbd> em vez disso.",
+ "apierror-echo-event-creation-failed": "Não foi possível criar evento Echo"
+}
diff --git a/Echo/i18n/api/pt.json b/Echo/i18n/api/pt.json
new file mode 100644
index 00000000..62d9b279
--- /dev/null
+++ b/Echo/i18n/api/pt.json
@@ -0,0 +1,64 @@
+{
+ "@metadata": {
+ "authors": [
+ "Diniscoelho",
+ "Fúlvio",
+ "Hamilton Abreu",
+ "Vitorvicentevalente"
+ ]
+ },
+ "apihelp-echomarkread-description": "Marcar notificações como lidas para o utilizador atual.",
+ "apihelp-echomarkread-summary": "Marcar notificações como lidas para o utilizador atual.",
+ "apihelp-echomarkread-param-list": "Uma lista de identificadores de notificações a marcar como lidas.",
+ "apihelp-echomarkread-param-unreadlist": "Uma lista de identificadores de notificações a marcar como não lidas.",
+ "apihelp-echomarkread-param-all": "Se definido, marca todas as notificações de um utilizador como lidas.",
+ "apihelp-echomarkread-param-sections": "Uma lista de secções a marcar como lidas.",
+ "apihelp-echomarkread-example-1": "Marcar a notificação 8 como lida",
+ "apihelp-echomarkread-example-2": "Marcar todas as notificações como lidas",
+ "apihelp-echomarkread-example-3": "Marcar a notificação 1 como não lida",
+ "apihelp-echomarkseen-description": "Marcar as notificações como vistas pelo utilizador atual.",
+ "apihelp-echomarkseen-summary": "Marcar as notificações como vistas pelo utilizador atual.",
+ "apihelp-echomarkseen-example-1": "Marcar as notificações de todos os tipos como vistas",
+ "apihelp-echomarkseen-param-type": "Tipos de notificações a marcar como vistas: 'alert', 'message' ou 'all'.",
+ "apihelp-echomarkseen-param-timestampFormat": "Formato da data e hora a usar no resultado, 'ISO_8601' ou 'MW'. 'MW' é agora obsoleto aqui, por isso todos os clientes devem mudar para 'ISO_8601'. Este parâmetro será removido e 'ISO_8601' passará a ser o único formato de saída.",
+ "apihelp-query+notifications-description": "Obter notificações à espera do utilizador atual.",
+ "apihelp-query+notifications-summary": "Obter notificações à espera do utilizador atual.",
+ "apihelp-query+notifications-param-prop": "Detalhes a pedir.",
+ "apihelp-query+notifications-param-sections": "As secções das notificações a consultar (isto é, uma combinação de 'alert' e 'message')",
+ "apihelp-query+notifications-param-groupbysection": "Indica se o resultado deve ser agrupado por secções. Se definida, cada secção é obtida em separado.",
+ "apihelp-query+notifications-param-filter": "Filtrar as notificações devolvidas.",
+ "apihelp-query+notifications-param-format": "Se especificado, as notificações serão devolvidas neste formato.",
+ "apihelp-query+notifications-paramvalue-format-model": "Dados de notificações em bruto",
+ "apihelp-query+notifications-paramvalue-format-special": "Formatado para a página Special:Notifications (e só para esse efeito!) Não confie no formato HTML porque este pode ser alterado a qualquer altura.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Obsoleto</span>. Usar <kbd>$1format=model</kbd> para os dados em bruto",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Obsoleto</span>. Usar <kbd>$1format=model</kbd> para os dados em bruto",
+ "apihelp-query+notifications-param-limit": "O número máximo de notificações a devolver.",
+ "apihelp-query+notifications-param-wikis": "Lista de wikis onde obter notificações (por padrão, só a wiki atual).",
+ "apihelp-query+notifications-param-crosswikisummary": "Verdadeiro, para optar por uma notificação sumária de notificações em wikis externas.",
+ "apihelp-query+notifications-param-alertcontinue": "Quando existem mais resultados de alertas disponíveis, usar isto para continuar.",
+ "apihelp-query+notifications-param-unreadfirst": "Indica se as notificações não lidas devem ser mostradas primeiro (só é usado se groupbysection não estiver definido).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Indica se as notificações de mensagem não lidas devem ser mostradas primeiro (só é usado se groupbysection estiver definido).",
+ "apihelp-query+notifications-param-messagecontinue": "Quando existem mais resultados de mensagens disponíveis, usar isto para continuar.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Indica se as notificações de alerta não lidas devem ser mostradas primeiro (só é usado se groupbysection estiver definido).",
+ "apihelp-query+notifications-param-titles": "Devolver só as notificações associadas a estas páginas. Para obter as notificações não associadas a qualquer página, use [] como título.",
+ "apihelp-query+notifications-param-bundle": "Indica se as notificações não lidas compatíveis com agrupamentos, devem ser mostradas de acordo com as regras de agrupamento de tipos de notificação.",
+ "apihelp-query+notifications-example-1": "Listar notificações",
+ "apihelp-query+notifications-example-2": "Listar notificações, agrupadas por secção, com contagens",
+ "apihelp-query+unreadnotificationpages-description": "Obter as páginas que contêm notificações não lidas para o utilizador atual.",
+ "apihelp-query+unreadnotificationpages-summary": "Obter as páginas que contêm notificações não lidas para o utilizador atual.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Agrupar as páginas de discussão com a respetiva página de conteúdo, e agrupar as notificações não associadas a uma página com a página do utilizador atual.",
+ "apihelp-query+unreadnotificationpages-param-limit": "O número máximo de páginas a serem devolvidas.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Lista de wikis onde obter páginas com notificações não lidas (por padrão, só a wiki atual).",
+ "apihelp-query+unreadnotificationpages-example-1": "Listar páginas com notificações não lidas e respetiva quantidade",
+ "apihelp-echoarticlereminder-summary": "Pedir uma relembrança futura acerca do artigo especificado",
+ "apihelp-echoarticlereminder-param-pageid": "Identificador do artigo a relembrar ao utilizador",
+ "apihelp-echoarticlereminder-param-title": "Título do artigo a relembrar ao utilizador",
+ "apihelp-echoarticlereminder-param-timestamp": "Em que data e hora relembrar o utilizador",
+ "apihelp-echoarticlereminder-param-comment": "Comentário opcional a ser incluído na relembrança",
+ "apihelp-echoarticlereminder-example-1": "Criar uma notificação de relembrança de artigo para amanhã com comentário",
+ "apihelp-echoarticlereminder-example-2": "Criar uma notificação de relembrança de artigo para amanhã sem comentário",
+ "apiwarn-echo-deprecation-timestampformat": "O formato de saída MediaWiki de data e hora foi descontinuado. De futuro, será sempre usado como formato de saída de data e hora o ISO 8601. Ajuste o seu cliente e defina o <var>timestampFormat</var> como <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> foi descontinuado e será removido em breve. Use <kbd>notformat=model</kbd> para obter os dados em bruto ou <kbd>notformat=special</kbd> para obter HTML pré-composto.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> foi descontinuado e será removido em breve. Substituir por <kbd>notformat=special</kbd>.",
+ "apierror-echo-event-creation-failed": "Não foi possível criar o evento Echo"
+}
diff --git a/Echo/i18n/api/qqq.json b/Echo/i18n/api/qqq.json
new file mode 100644
index 00000000..e19e34ee
--- /dev/null
+++ b/Echo/i18n/api/qqq.json
@@ -0,0 +1,68 @@
+{
+ "@metadata": {
+ "authors": [
+ "Brad Jorsch",
+ "Matthew Flaschen",
+ "Matthias Mullie",
+ "Moriel Schottlender",
+ "Roan Kattouw",
+ "Stephane Bisson",
+ "Umherirrender",
+ "Liuxinyu970226"
+ ]
+ },
+ "apihelp-echomarkread-description": "{{doc-apihelp-description|echomarkread}}",
+ "apihelp-echomarkread-summary": "{{doc-apihelp-summary|echomarkread}}",
+ "apihelp-echomarkread-param-list": "{{doc-apihelp-param|echomarkread|list}}",
+ "apihelp-echomarkread-param-unreadlist": "{{doc-apihelp-param|echomarkread|unreadlist}}",
+ "apihelp-echomarkread-param-all": "{{doc-apihelp-param|echomarkread|all}}",
+ "apihelp-echomarkread-param-sections": "{{doc-apihelp-param|echomarkread|sections}}",
+ "apihelp-echomarkread-example-1": "{{doc-apihelp-example|echomarkread}}",
+ "apihelp-echomarkread-example-2": "{{doc-apihelp-example|echomarkread}}",
+ "apihelp-echomarkread-example-3": "{{doc-apihelp-example|echomarkread}}",
+ "apihelp-echomarkseen-description": "{{doc-apihelp-description|echomarkseen}}",
+ "apihelp-echomarkseen-summary": "{{doc-apihelp-summary|echomarkseen}}",
+ "apihelp-echomarkseen-example-1": "{{doc-apihelp-example|echomarkseen}}",
+ "apihelp-echomarkseen-param-type": "{{doc-apihelp-param|echomarkseen|type}}",
+ "apihelp-echomarkseen-param-timestampFormat": "{{doc-apihelp-param|echomarkseen|timestampFormat}}",
+ "apihelp-query+notifications-description": "{{doc-apihelp-description|query+notifications}}",
+ "apihelp-query+notifications-summary": "{{doc-apihelp-summary|query+notifications}}",
+ "apihelp-query+notifications-param-prop": "{{doc-apihelp-param|query+notifications|prop}}",
+ "apihelp-query+notifications-param-sections": "{{doc-apihelp-param|query+notifications|sections}} Do not translate the quoted strings.",
+ "apihelp-query+notifications-param-groupbysection": "{{doc-apihelp-param|query+notifications|groupbysection}}",
+ "apihelp-query+notifications-param-filter": "{{doc-apihelp-param|query+notifications|filter}}",
+ "apihelp-query+notifications-param-format": "{{doc-apihelp-param|query+notifications|format}}",
+ "apihelp-query+notifications-paramvalue-format-model": "{{doc-apihelp-paramvalue|query+notifications|format|model}}",
+ "apihelp-query+notifications-paramvalue-format-special": "{{doc-apihelp-paramvalue|query+notifications|format|special}}",
+ "apihelp-query+notifications-paramvalue-format-flyout": "{{doc-apihelp-paramvalue|query+notifications|format|flyout}}\n{{doc-important|You can translate the word \"Deprecated\", but please do not alter the <code><nowiki>class=\"apihelp-deprecated\"</nowiki></code> attribute}}",
+ "apihelp-query+notifications-paramvalue-format-html": "{{doc-apihelp-paramvalue|query+notifications|format|html}}\n{{doc-important|You can translate the word \"Deprecated\", but please do not alter the <code><nowiki>class=\"apihelp-deprecated\"</nowiki></code> attribute}}",
+ "apihelp-query+notifications-param-limit": "{{doc-apihelp-param|query+notifications|limit}}",
+ "apihelp-query+notifications-param-wikis": "{{doc-apihelp-param|query+notifications|wikis}}",
+ "apihelp-query+notifications-param-crosswikisummary": "{{doc-apihelp-param|query+notifications|crosswikisummary}}",
+ "apihelp-query+notifications-param-alertcontinue": "{{doc-apihelp-param|query+notifications|alertcontinue}}",
+ "apihelp-query+notifications-param-unreadfirst": "{{doc-apihelp-param|query+notifications|unreadfirst}}",
+ "apihelp-query+notifications-param-alertunreadfirst": "{{doc-apihelp-param|query+notifications|alertunreadfirst}}",
+ "apihelp-query+notifications-param-messagecontinue": "{{doc-apihelp-param|query+notifications|messagecontinue}}",
+ "apihelp-query+notifications-param-messageunreadfirst": "{{doc-apihelp-param|query+notifications|messageunreadfirst}}",
+ "apihelp-query+notifications-param-titles": "{{doc-apihelp-param|query+notifications|titles}}",
+ "apihelp-query+notifications-param-bundle": "{{doc-apihelp-param|query+notifications|bundle}}",
+ "apihelp-query+notifications-example-1": "{{doc-apihelp-example|query+notifications}}",
+ "apihelp-query+notifications-example-2": "{{doc-apihelp-example|query+notifications}}",
+ "apihelp-query+unreadnotificationpages-description": "{{doc-apihelp-description|query+unreadnotificationpages}}",
+ "apihelp-query+unreadnotificationpages-summary": "{{doc-apihelp-summary|query+unreadnotificationpages}}",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "{{doc-apihelp-param|query+unreadnotificationpages|grouppages}}",
+ "apihelp-query+unreadnotificationpages-param-limit": "{{doc-apihelp-param|query+unreadnotificationpages|limit}}",
+ "apihelp-query+unreadnotificationpages-param-wikis": "{{doc-apihelp-param|query+unreadnotificationpages|wikis}}",
+ "apihelp-query+unreadnotificationpages-example-1": "{{doc-apihelp-example|query+unreadnotificationpages}}",
+ "apihelp-echoarticlereminder-summary": "{{doc-apihelp-summary|echoarticlereminder}}",
+ "apihelp-echoarticlereminder-param-pageid": "{{doc-apihelp-param|echoarticlereminder|pageid}}",
+ "apihelp-echoarticlereminder-param-title": "{{doc-apihelp-param|echoarticlereminder|title}}",
+ "apihelp-echoarticlereminder-param-timestamp": "{{doc-apihelp-param|echoarticlereminder|timestamp}}",
+ "apihelp-echoarticlereminder-param-comment": "{{doc-apihelp-param|echoarticlereminder|comment}}",
+ "apihelp-echoarticlereminder-example-1": "{{doc-apihelp-example|echoarticlereminder}}",
+ "apihelp-echoarticlereminder-example-2": "{{doc-apihelp-example|echoarticlereminder}}",
+ "apiwarn-echo-deprecation-timestampformat": "{{doc-apierror}}",
+ "apiwarn-echo-deprecation-flyout": "{{doc-apierror}}",
+ "apiwarn-echo-deprecation-html": "{{doc-apierror}}",
+ "apierror-echo-event-creation-failed": "{{doc-apierror}}"
+}
diff --git a/Echo/i18n/api/ro.json b/Echo/i18n/api/ro.json
new file mode 100644
index 00000000..25f9ef9b
--- /dev/null
+++ b/Echo/i18n/api/ro.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Reception123"
+ ]
+ },
+ "apihelp-echomarkread-description": "Marcați notificările ca citite pentru utilizatorul curent.",
+ "apihelp-echomarkread-param-list": "Lista de ID-ul de notificare pentru a marca ca fiind citite.",
+ "apihelp-echomarkread-param-all": "Dacă este setat, marchează toate notificările a unui utilizator ca citite.",
+ "apihelp-echomarkread-param-sections": "O listă de sectiuni a fi marcată ca citită.",
+ "apihelp-echomarkread-example-1": "Marca notificare 8 ca fiind citită.",
+ "apihelp-echomarkread-example-2": "Marchează toate notificările ca find citite.",
+ "apihelp-echomarkseen-description": "Marcați notificările ca citite pentru utilizatorul curent.",
+ "apihelp-echomarkseen-example-1": "Marcați notificarile de toate tipurile ca văzute"
+}
diff --git a/Echo/i18n/api/roa-tara.json b/Echo/i18n/api/roa-tara.json
new file mode 100644
index 00000000..7b25d4ff
--- /dev/null
+++ b/Echo/i18n/api/roa-tara.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joetaras"
+ ]
+ },
+ "apihelp-echomarkread-example-1": "Signe 'a notifiche 8 cumme lette",
+ "apihelp-echomarkread-example-2": "Signe tutte le notifiche cumme lette",
+ "apihelp-echomarkread-example-3": "Signe 'a notifiche 1 cumme lette",
+ "apihelp-query+notifications-example-1": "Elenghe de le notifiche"
+}
diff --git a/Echo/i18n/api/ru.json b/Echo/i18n/api/ru.json
new file mode 100644
index 00000000..399540ed
--- /dev/null
+++ b/Echo/i18n/api/ru.json
@@ -0,0 +1,42 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mailman",
+ "Marina Melik-Adamyan",
+ "Okras",
+ "Putnik",
+ "Sunpriat"
+ ]
+ },
+ "apihelp-echomarkread-description": "Отметить уведомления как прочитанные для текущего пользователя.",
+ "apihelp-echomarkread-param-list": "Список ID уведомлений для отметки прочитанными.",
+ "apihelp-echomarkread-param-unreadlist": "Список ID уведомлений для отметки непрочитанными.",
+ "apihelp-echomarkread-param-all": "Если задано, отметает все уведомления пользователя как прочитанные.",
+ "apihelp-echomarkread-param-sections": "Список разделов для пометки как прочитанных.",
+ "apihelp-echomarkread-example-1": "Пометить уведомление 8 как прочитанное",
+ "apihelp-echomarkread-example-2": "Отметить все уведомления как прочитанные",
+ "apihelp-echomarkread-example-3": "Пометить уведомление 1 как непрочитанное",
+ "apihelp-echomarkseen-description": "Отметить уведомления как прочитанные для данного пользователя.",
+ "apihelp-echomarkseen-example-1": "Отметить уведомления всех типов как прочитанные",
+ "apihelp-echomarkseen-param-type": "Тип уведомлений для отметки прочитанными: 'alert', 'message' или 'all'.",
+ "apihelp-query+notifications-description": "Получать уведомления, ожидающие текущего пользователя.",
+ "apihelp-query+notifications-param-prop": "Подробности для запроса.",
+ "apihelp-query+notifications-param-sections": "Разделы уведомлений для запроса (т. е. некое сочетание 'alert' и 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Следует ли группировать результат по разделам. Если задано, каждый раздел извлекается отдельно.",
+ "apihelp-query+notifications-param-filter": "Фильтровать возвращённые уведомления.",
+ "apihelp-query+notifications-param-format": "Если определено, уведомления будут возвращены отформатированными таким образом.",
+ "apihelp-query+notifications-paramvalue-format-text": "Текстовый формат",
+ "apihelp-query+notifications-paramvalue-format-model": "Необработанные данные уведомления",
+ "apihelp-query+notifications-paramvalue-format-special": "Отформатированое для страницы Special:Notifications (и только её!) Не полагайтесь на этот HTML, так как он может измениться в любой момент.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Устарело</span>. Используйте <kbd>$1format=model</kbd> для исходных данных",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Устарело</span>. Используйте <kbd>$1format=model</kbd> для исходных данных",
+ "apihelp-query+notifications-param-limit": "Максимальное количество возвращаемых уведомлений.",
+ "apihelp-query+notifications-param-alertcontinue": "Когда доступно больше результатов для предупреждений, используйте это для продолжения.",
+ "apihelp-query+notifications-param-unreadfirst": "Нужно ли показывать непрочитанные уведомления вначале (используется только если groupbysection не установлен).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Нужно ли показывать непрочитанные уведомления о сообщениях в первую очередь (используется только если указан groupbysection).",
+ "apihelp-query+notifications-param-messagecontinue": "Когда доступно больше результатов для сообщений, используйте это для продолжения.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Нужно ли показывать непрочитанные уведомления о оповещениях в первую очередь (используется только если указан groupbysection).",
+ "apihelp-query+notifications-example-1": "Список уведомлений",
+ "apihelp-query+notifications-example-2": "Список уведомлений, сгруппированных по разделам, с указанием количества",
+ "apihelp-query+unreadnotificationpages-param-limit": "Максимальное количество страниц для возврата"
+}
diff --git a/Echo/i18n/api/sah.json b/Echo/i18n/api/sah.json
new file mode 100644
index 00000000..317bc8a7
--- /dev/null
+++ b/Echo/i18n/api/sah.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "HalanTul",
+ "Марианна",
+ "София"
+ ]
+ },
+ "apihelp-echomarkread-description": "Билиҥҥи туттааччыга биллэриилэри ааҕыллыбыт курдук бэлиэтээ",
+ "apihelp-echomarkread-example-1": "8 биллэриини ааҕыллыбыт курдук бэлиэтээ",
+ "apihelp-echomarkread-example-2": "Биллэриилэри ааҕыллыбыт курдук бэлиэтээ",
+ "apihelp-echomarkread-example-3": "1 биллэриини ааҕыллыбатах курдук бэлиэтээ",
+ "apihelp-echomarkseen-description": "Билиҥҥи туттааччыга биллэриилэри ааҕыллыбыт курдук бэлиэтээ",
+ "apihelp-echomarkseen-example-1": "Биллэриилэри бары көрүҥүн ааҕыллыбыт курдук аах",
+ "apihelp-query+notifications-description": "Билиҥҥи туттааччыга биллэриилэри ааҕыллыбыт курдук бэлиэтээ",
+ "apihelp-query+notifications-param-prop": "чымпык ыйытыга",
+ "apihelp-query+notifications-param-filter": "Төннөрүллүбүт биллэриилэри сиидэлээһин.",
+ "apihelp-query+notifications-paramvalue-format-text": "Тиэкис формаата",
+ "apihelp-query+notifications-paramvalue-format-model": "Көннөрүллүбэтэх биллэриилэр даннайдара",
+ "apihelp-query+notifications-param-limit": "Төннөрүллэр биллэриилэр муҥутуур ахсааннара.",
+ "apihelp-query+notifications-example-1": "Биллэриилэр испииһэктэрэ",
+ "apihelp-query+unreadnotificationpages-description": "Билиҥҥи туттааччыга ааҕыллыбатах биллэриилэрин сирэйдэрин ылыы.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Төннөрүллэр биллэриилэр муҥутуур ахсааннара.",
+ "apihelp-query+unreadnotificationpages-example-1": "Сирэйдэр испиэһэктэрин (ахсааннарын) ааҕыллыбатах биллэриилэрэ"
+}
diff --git a/Echo/i18n/api/sl.json b/Echo/i18n/api/sl.json
new file mode 100644
index 00000000..d7bf9831
--- /dev/null
+++ b/Echo/i18n/api/sl.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Janezdrilc"
+ ]
+ },
+ "apihelp-echomarkread-description": "Označi obvestila za prebrana za trenutnega uporabnika.",
+ "apihelp-echomarkread-param-list": "Seznam ID-jev obvestil za označitev za prebrano.",
+ "apihelp-echomarkread-param-unreadlist": "Seznam ID-jev obvestil za označitev za neprebrano.",
+ "apihelp-echomarkread-param-all": "Ob nastavitvi označi vsa uporabnikova obvestila za prebrana.",
+ "apihelp-echomarkread-param-sections": "Seznam delov za označitev za prebrano.",
+ "apihelp-echomarkread-example-1": "Označi obvestilo 8 za prebrano",
+ "apihelp-echomarkread-example-2": "Označi vsa obvestila za prebrana",
+ "apihelp-echomarkread-example-3": "Označi obvestilo 1 za neprebrano",
+ "apihelp-echomarkseen-description": "Označi obvestila za ogledana za trenutnega uporabnika.",
+ "apihelp-echomarkseen-example-1": "Označi vse vrste obvestil za ogledane",
+ "apihelp-echomarkseen-param-type": "Vrste obvestil za označitev za ogledano: 'opomnik', 'sporočilo' ali 'vse'.",
+ "apihelp-echomarkseen-param-timestampFormat": "Datumski odtis pri izpisovanju, 'ISO_8601' ali 'MW'. 'MW' se ne priporoča, zato ga naj uporabniki zamenjajo z 'ISO_8601'. Ko bo ukinjen, bo ostal v uporabi le 'ISO_8601'.",
+ "apihelp-query+notifications-description": "Poglej obvestila, ki so na čakanju za trenutnega uporabnika.",
+ "apihelp-query+notifications-param-prop": "Zahtevane podrobnosti."
+}
diff --git a/Echo/i18n/api/sv.json b/Echo/i18n/api/sv.json
new file mode 100644
index 00000000..e89f7c2b
--- /dev/null
+++ b/Echo/i18n/api/sv.json
@@ -0,0 +1,63 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ainali",
+ "Lokal Profil",
+ "WikiPhoenix"
+ ]
+ },
+ "apihelp-echomarkread-description": "Markera aviseringar som lästa för den aktuella användaren.",
+ "apihelp-echomarkread-summary": "Markera aviseringar som lästa för den aktuella användaren.",
+ "apihelp-echomarkread-param-list": "En lista över aviserings-ID att markera som lästa.",
+ "apihelp-echomarkread-param-unreadlist": "En lista över aviserings-ID att markera som olästa.",
+ "apihelp-echomarkread-param-all": "Om angiven, markerar en användares alla aviseringar som lästa.",
+ "apihelp-echomarkread-param-sections": "En lista över avsnitt att markera som lästa.",
+ "apihelp-echomarkread-example-1": "Markera avisering 8 som läst",
+ "apihelp-echomarkread-example-2": "Markera alla aviseringar som lästa",
+ "apihelp-echomarkread-example-3": "Markera avisering 1 som oläst",
+ "apihelp-echomarkseen-description": "Märk aviseringar som lästa för aktuell användare.",
+ "apihelp-echomarkseen-summary": "Märk aviseringar som lästa för aktuell användare.",
+ "apihelp-echomarkseen-example-1": "Märk alla sorters aviseringar som lästa",
+ "apihelp-echomarkseen-param-type": "Aviseringstypen att märka som läst: 'alert', 'message' eller 'all'.",
+ "apihelp-echomarkseen-param-timestampFormat": "Tidstämpelformat att använda som utmatning, 'ISO_8601' eller 'MW'. 'MW' är föråldrat här, så alla klienter bör byta till 'ISO_8601'. Denna parameter kommer att tas bort och 'ISO_8601' kommer att bli det enda utmatningsformatet.",
+ "apihelp-query+notifications-description": "Hämta aviseringar som väntar på aktuell användare.",
+ "apihelp-query+notifications-summary": "Hämta aviseringar som väntar på aktuell användare.",
+ "apihelp-query+notifications-param-prop": "Detaljer som ska begäras.",
+ "apihelp-query+notifications-param-sections": "De aviseringsavsnitt som ska undersökas (d.v.s. en kombination av 'alert' och 'message').",
+ "apihelp-query+notifications-param-groupbysection": "Om resultaten ska grupperas efter avsnitt. Om angivet hämtas vart avsnitt separat.",
+ "apihelp-query+notifications-param-filter": "Filtrera aviseringar att returnera.",
+ "apihelp-query+notifications-param-format": "Om angivet, returneras aviseringar formaterade på detta sätt.",
+ "apihelp-query+notifications-paramvalue-format-model": "Rå aviseringsdata",
+ "apihelp-query+notifications-paramvalue-format-special": "Formaterad för sidan Special:Meddelanden (och bara där!) Förlita dig inte på HTML-koden då den kan ändras när som helst.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Föråldrad</span>. Använd <kbd>$1format=model</kbd> för rå data",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Föråldrad</span>. Använd <kbd>$1format=model</kbd> för rå data",
+ "apihelp-query+notifications-param-limit": "Det maximala antalet aviseringar som ska returneras.",
+ "apihelp-query+notifications-param-wikis": "Lista över wikis att hämta aviseringar från (är endast aktuell wiki som standard).",
+ "apihelp-query+notifications-param-crosswikisummary": "Aktivera för att få en sammanfattning över aviseringar på andra wikis.",
+ "apihelp-query+notifications-param-alertcontinue": "När fler resultat finns för systemmeddelande, använd detta för att fortsätta.",
+ "apihelp-query+notifications-param-unreadfirst": "Om du vill visa olästa aviseringar först (används endast om groupbysection inte är inställd).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Om du vill visa olästa meddelandeaviseringar först (används endast om groupbysection inte är inställd).",
+ "apihelp-query+notifications-param-messagecontinue": "När fler meddelanden finns tillgängliga, använd detta för att fortsätta.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Om du vill visa olästa systemmeddelandeaviseringar först (används endast om groupbysection inte är inställd).",
+ "apihelp-query+notifications-param-titles": "Returnera endast aviseringar för dessa sidor. Använd [] som en titel för att få aviseringar som inte associeras med någon sida.",
+ "apihelp-query+notifications-param-bundle": "Om olästa aviseringar ska grupperas enligt reglerna för grupperade aviseringstyper.",
+ "apihelp-query+notifications-example-1": "Lista aviseringar",
+ "apihelp-query+notifications-example-2": "Listan aviseringar grupperade efter avsnitt, med antal",
+ "apihelp-query+unreadnotificationpages-description": "Hämta sidor där det finns olästa aviseringar för aktuell användare.",
+ "apihelp-query+unreadnotificationpages-summary": "Hämta sidor där det finns olästa aviseringar för aktuell användare.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Gruppera diskussionssidor tillsammans med dess ämnessidor och gruppera aviseringar som inte är associerade med en sida tillsammans med den aktuella användarens användarsida.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Maximala antalet sidor att returnera.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Lista över wikis att hämta sidor med olästa aviseringar ifrån (endast aktuell wiki är standard).",
+ "apihelp-query+unreadnotificationpages-example-1": "Lista sidor med (deras antal av) olästa aviseringar",
+ "apihelp-echoarticlereminder-summary": "Begär en framtida påminnelse om den valda artikeln",
+ "apihelp-echoarticlereminder-param-pageid": "ID för artikeln att påminna användaren om",
+ "apihelp-echoarticlereminder-param-title": "Titel för artikel att påminna användaren om",
+ "apihelp-echoarticlereminder-param-timestamp": "Vilken tidstämpel att påminna användaren på",
+ "apihelp-echoarticlereminder-param-comment": "Valfri användarkommentar att inkludera i påminnelsen",
+ "apihelp-echoarticlereminder-example-1": "Skapa en artikelpåminnelse via en avisering för imorgon med en kommentar",
+ "apihelp-echoarticlereminder-example-2": "Skapa en artikelpåminnelse via en avisering för imorgon utan en kommentar",
+ "apiwarn-echo-deprecation-timestampformat": "MW-tidsstämpelns utmatningsformat är föråldrat här. I framtiden kommer ISO 8601 alltid att användas för utmatningens tidstämpelsformat. Justera din klient och ändra <var>timestampFormat</var> till <kbd>ISO_8601</kbd>.",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd> har blivit föråldrat och kommer att tas bort snart. Använd <kbd>notformat=model</kbd> för att få rå data eller <kbd>notformat=special</kbd> för förrenderad HTML.",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd> har blivit föråldrat och kommer snart att tas bort. Använd <kbd>notformat=special</kbd> istället.",
+ "apierror-echo-event-creation-failed": "Kunde inte skapa Echo-händelse"
+}
diff --git a/Echo/i18n/api/tr.json b/Echo/i18n/api/tr.json
new file mode 100644
index 00000000..e8ad6c71
--- /dev/null
+++ b/Echo/i18n/api/tr.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arystanbek",
+ "KorkmazO",
+ "McAang",
+ "Sayginer"
+ ]
+ },
+ "apihelp-echomarkread-description": "Geçerli kullanıcı için okundu olarak işaretle bildirimleri.",
+ "apihelp-echomarkread-param-list": "Okundu olarak işaretlemek için bildirim Kimliklerinin bir listesini.",
+ "apihelp-echomarkread-param-all": "Set, okumak gibi bir kullanıcı Bildirimleri tüm işaretler.",
+ "apihelp-echomarkread-param-sections": "Okundu olarak işaretlemek için bölümler bir listesini.",
+ "apihelp-echomarkread-example-1": "Mark bildirim 8 gibi okumak",
+ "apihelp-echomarkread-example-2": "Tüm bildirimleri okunmuş olarak işaretle",
+ "apihelp-echomarkseen-description": "Geçerli kullanıcı için görüldüğü gibi Mark bildirimleri.",
+ "apihelp-echomarkseen-example-1": "Her tür bildirimi okundu olarak işaretle",
+ "apihelp-echomarkseen-param-type": "'Uyarı', 'mesaj' ya da 'tümü' olarak işaretlemek için bildirimlerin türü.",
+ "apihelp-query+notifications-description": "Bildirimler, geçerli kullanıcı için bekliyor.",
+ "apihelp-query+notifications-param-prop": "İstek detayları.",
+ "apihelp-query+notifications-param-sections": "Sorgu için bildirim bölümleri (örneğin bazı 'uyarı' ve 'mesaj'kombinasyonu)",
+ "apihelp-query+notifications-param-groupbysection": "Olsun bölüm sonuç grup için. Her bölüm set halinde ayrı ayrı getirildi.",
+ "apihelp-query+notifications-param-format": "Belirtilmişse, bildirimleri biçimlendirilmiş bu şekilde iade edilecektir.",
+ "apihelp-query+notifications-param-limit": "Gösterilebilecek azami bildirim sayısı.",
+ "apihelp-query+notifications-param-alertcontinue": "Daha uyanık sonuçlar mevcut olduğunda, bu devam etmek için kullanın.",
+ "apihelp-query+notifications-param-alertunreadfirst": "İster okunmamış mesaj bildirimlerini göstermek.",
+ "apihelp-query+notifications-param-messagecontinue": "Daha fazla ileti sonuçlar mevcut olduğunda, bu devam etmek için kullanın.",
+ "apihelp-query+notifications-param-messageunreadfirst": "İster okunmamış uyarı bildirimleri göstermek.",
+ "apihelp-query+notifications-example-1": "Liste bildirimleri",
+ "apihelp-query+notifications-example-2": "Sayılarla birlikte bölümlere göre gruplandırılmış bildirimler listesi"
+}
diff --git a/Echo/i18n/api/uk.json b/Echo/i18n/api/uk.json
new file mode 100644
index 00000000..92b8a67f
--- /dev/null
+++ b/Echo/i18n/api/uk.json
@@ -0,0 +1,63 @@
+{
+ "@metadata": {
+ "authors": [
+ "Base",
+ "Piramidion",
+ "Ата"
+ ]
+ },
+ "apihelp-echomarkread-description": "Позначити для поточного користувача сповіщення як прочитані.",
+ "apihelp-echomarkread-summary": "Позначити сповіщення як прочитані для поточного користувача.",
+ "apihelp-echomarkread-param-list": "Список ідентифікаторів сповіщень, які позначити як прочитані.",
+ "apihelp-echomarkread-param-unreadlist": "Список ідентифікаторів сповіщень, які треба позначити як непрочитані",
+ "apihelp-echomarkread-param-all": "Якщо встановлено, позначає всі сповіщення користувача прочитаними.",
+ "apihelp-echomarkread-param-sections": "Список розділів, які позначити як прочитані.",
+ "apihelp-echomarkread-example-1": "Позначити сповіщення 8 як прочитане.",
+ "apihelp-echomarkread-example-2": "Позначити всі сповіщення як прочитані",
+ "apihelp-echomarkread-example-3": "Позначити сповіщення 1 як непрочитане",
+ "apihelp-echomarkseen-description": "Позначити всі сповіщення як прочитані для поточного користувача.",
+ "apihelp-echomarkseen-summary": "Позначити сповіщення як переглянуті для поточного користувача.",
+ "apihelp-echomarkseen-example-1": "Позначити сповіщення усіх типів як переглянуті",
+ "apihelp-echomarkseen-param-type": "Тип сповіщення, яке позначити переглянутим: «alert», «message» або «all».",
+ "apihelp-echomarkseen-param-timestampFormat": "Формат мітки часу, що має бути використаний на виході: 'ISO_8601' або 'MW'. 'MW' тут є застарілим, тому всі клієнти повинні перейти на 'ISO_8601'. Цей параметр буде усунуто, а формат 'ISO_8601' стане єдиним вихідним форматом.",
+ "apihelp-query+notifications-description": "Отримати сповіщення, які чекають поточного користувача.",
+ "apihelp-query+notifications-summary": "Отримувати сповіщення, що очікують на дію поточного користувача.",
+ "apihelp-query+notifications-param-prop": "Деталі запиту.",
+ "apihelp-query+notifications-param-sections": "Розділи сповіщень для запиту (тобто якась комбінація «alert» та «message»).",
+ "apihelp-query+notifications-param-groupbysection": "Чи групувати результати за розділами. Кожен розділ буде отримуватись окремо якщо встановлено.",
+ "apihelp-query+notifications-param-filter": "Виведено сповіщення фільтрів.",
+ "apihelp-query+notifications-param-format": "Якщо вказано, сповіщення буде отримано форматованими таким чином.",
+ "apihelp-query+notifications-paramvalue-format-model": "Необроблені дані сповіщень",
+ "apihelp-query+notifications-paramvalue-format-special": "Відформатовано для сторінки Special:Notifications (і тільки її!) Не покладайтеся на HTML, оскільки він може змінитися в будь-який момент.",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">Застаріло</span>. Використовуйте <kbd>$1format=model</kbd> для необроблених даних",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">Застаріло</span>. Використовуйте <kbd>$1format=model</kbd> для необроблений даних",
+ "apihelp-query+notifications-param-limit": "Максимальне число сповіщень для повернення.",
+ "apihelp-query+notifications-param-wikis": "Список вікі для отримання сповіщень (за замовчуванням — тільки поточна вікі).",
+ "apihelp-query+notifications-param-crosswikisummary": "True — увімкнути підсумкове сповіщення про сповіщення з інших вікі.",
+ "apihelp-query+notifications-param-alertcontinue": "Коли доступно більше звісток, використовуйте це, щоб продовжити.",
+ "apihelp-query+notifications-param-unreadfirst": "Чи показувати непрочитані сповіщення першими (використовується лише якщо не встановлено groupbysection).",
+ "apihelp-query+notifications-param-alertunreadfirst": "Чи показувати спершу непрочитані сповіщення про повідомлення (використовується лише якщо встановлено groupbysection).",
+ "apihelp-query+notifications-param-messagecontinue": "Коли доступно більше повідомлень, використовуйте це, щоб продовжити.",
+ "apihelp-query+notifications-param-messageunreadfirst": "Чи показувати спершу непрочитані звістки (використовується лише якщо встановлено groupbysection).",
+ "apihelp-query+notifications-param-titles": "Виводити лише сповіщення для цих сторінок. Щоб отримати сповіщення, не пов'язані з жодною сторінкою, замість назви використайте [].",
+ "apihelp-query+notifications-param-bundle": "Чи показувати пучок сумісних непрочитаних сповіщень згідно з правилами зв'язування типів сповіщень.",
+ "apihelp-query+notifications-example-1": "Список сповіщень",
+ "apihelp-query+notifications-example-2": "Список сповіщень, згрупованих за розділами, із зазначенням кількостей",
+ "apihelp-query+unreadnotificationpages-description": "Отримати сторінки, для яких є непрочитані сповіщення для поточного користувача.",
+ "apihelp-query+unreadnotificationpages-summary": "Отримувати сповіщення, щодо яких є непрочитані сповіщення для поточного користувача.",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "Згрупувати сторінки обговорення з їхніми основними сторінками, та згрупувати сповіщення, не пов'язані зі сторінкою, разом зі сторінкою поточного користувача.",
+ "apihelp-query+unreadnotificationpages-param-limit": "Максимальна кількість сторінок для виведення.",
+ "apihelp-query+unreadnotificationpages-param-wikis": "Список вікі для отримання сторінок з непрочитаними сповіщеннями (за замовчуванням — тільки поточна вікі).",
+ "apihelp-query+unreadnotificationpages-example-1": "Список сторінок з непрочитаними повідомленнями (і кількістю)",
+ "apihelp-echoarticlereminder-summary": "Подати запит на майбутнє нагадування про вказану статтю",
+ "apihelp-echoarticlereminder-param-pageid": "Ідентифікатор статті, про яку слід нагадати користувачеві",
+ "apihelp-echoarticlereminder-param-title": "Назва статті, про яку слід нагадати користувачеві",
+ "apihelp-echoarticlereminder-param-timestamp": "Мітка часу, коли користувачеві слід надіслати нагадування",
+ "apihelp-echoarticlereminder-param-comment": "Необов'язковий коментар користувача, який має бути включений у нагадування",
+ "apihelp-echoarticlereminder-example-1": "Створити сповіщення з нагадуванням про статтю на завтра з коментарем",
+ "apihelp-echoarticlereminder-example-2": "Створити сповіщення з нагадуванням про статтю на завтра без коментаря",
+ "apiwarn-echo-deprecation-timestampformat": "Вихідний формат мітки часу MW є застарілим тут. У майбутньому для вихідного формату мітки часу завжди використовуватиметься ISO 8601. Налаштуйте свій клієнт і встановіть <kbd>ISO_8601</kbd> для <var>timestampFormat</var>.",
+ "apiwarn-echo-deprecation-flyout": "Параметр <kbd>notformat=flyout</kbd> є застарілим і невдовзі його буде усунуто. Використовуйте <kbd>notformat=model</kbd>, щоб отримати сирі дані, або <kbd>notformat=special</kbd>, щоб отримати попередньо оброблений HTML.",
+ "apiwarn-echo-deprecation-html": "Параметр <kbd>notformat=html</kbd> є застарілим, і невдовзі його буде усунуто. Натомість використовуйте <kbd>notformat=special</kbd>.",
+ "apierror-echo-event-creation-failed": "Не вдалося створити Echo-подію"
+}
diff --git a/Echo/i18n/api/vi.json b/Echo/i18n/api/vi.json
new file mode 100644
index 00000000..08214121
--- /dev/null
+++ b/Echo/i18n/api/vi.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Max20091",
+ "Minh Nguyen"
+ ]
+ },
+ "apihelp-echomarkread-param-list": "Danh sách các ID thông báo để đánh dấu là đã đọc.",
+ "apihelp-echomarkread-example-2": "Đánh dấu tất cả thông báo là đã đọc",
+ "apihelp-query+notifications-param-prop": "Chi tiết để yêu cầu.",
+ "apihelp-query+notifications-paramvalue-format-text": "Định dạng văn bản thuần",
+ "apihelp-query+notifications-paramvalue-format-model": "Dữ liệu thông báo thô",
+ "apihelp-query+notifications-example-1": "Danh sách thông báo"
+}
diff --git a/Echo/i18n/api/zh-hans.json b/Echo/i18n/api/zh-hans.json
new file mode 100644
index 00000000..e94d78a2
--- /dev/null
+++ b/Echo/i18n/api/zh-hans.json
@@ -0,0 +1,62 @@
+{
+ "@metadata": {
+ "authors": [
+ "Liuxinyu970226",
+ "Yfdyh000"
+ ]
+ },
+ "apihelp-echomarkread-description": "对当前用户标记通知为已读。",
+ "apihelp-echomarkread-summary": "对当前用户标记通知为已读。",
+ "apihelp-echomarkread-param-list": "要标记已读的通知ID列表。",
+ "apihelp-echomarkread-param-unreadlist": "要标记未读的通知ID列表。",
+ "apihelp-echomarkread-param-all": "如果设置,标记一位用户的所有通知为已读。",
+ "apihelp-echomarkread-param-sections": "要标记为已读的部分列表。",
+ "apihelp-echomarkread-example-1": "标记通知8为已读",
+ "apihelp-echomarkread-example-2": "标记所有通知为已读",
+ "apihelp-echomarkread-example-3": "标记通知1为未读",
+ "apihelp-echomarkseen-description": "对当前用户标记通知为已读。",
+ "apihelp-echomarkseen-summary": "对当前用户标记通知为已读。",
+ "apihelp-echomarkseen-example-1": "标记所有类型的通知为已读",
+ "apihelp-echomarkseen-param-type": "要标记为已读的通知类型:“alert”、“message”或“all”。",
+ "apihelp-echomarkseen-param-timestampFormat": "用于输出的时间戳格式,“ISO_8601”或“MW”。“MW”在此被弃用,因此所有客户端应切换为“ISO_8601”。此参数将被移除,且“ISO_8601”将成为唯一的输出格式。",
+ "apihelp-query+notifications-description": "获取当前用户等待的通知。",
+ "apihelp-query+notifications-summary": "获取当前用户等待的通知。",
+ "apihelp-query+notifications-param-prop": "请求的细节。",
+ "apihelp-query+notifications-param-sections": "要查询的通知部分(也就是说“alert”和“message”的一些结合)。",
+ "apihelp-query+notifications-param-groupbysection": "是否按章节分组结果。如果设置,将分别获取每个章节。",
+ "apihelp-query+notifications-param-filter": "过滤返回的通知。",
+ "apihelp-query+notifications-param-format": "如果指定,通知将以此格式返回。",
+ "apihelp-query+notifications-paramvalue-format-model": "原始通知数据",
+ "apihelp-query+notifications-paramvalue-format-special": "格式化用于Special:Notifications页面(并仅限于此!)不要依赖HTML,这可能在任何指定的时间更改。",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">已弃用</span>。使用<kbd>$1format=model</kbd>用于原始数据",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">已弃用</span>。使用<kbd>$1format=model</kbd>用于原始数据",
+ "apihelp-query+notifications-param-limit": "返回通知的最大数量。",
+ "apihelp-query+notifications-param-wikis": "要检索通知表单的wiki列表(默认仅当前wiki)。",
+ "apihelp-query+notifications-param-crosswikisummary": "设置为真以启用外来wiki上通知的摘要通知。",
+ "apihelp-query+notifications-param-alertcontinue": "当更多提醒结果可用时,使用这个继续。",
+ "apihelp-query+notifications-param-unreadfirst": "是否首先显示未读通知(只当groupbysection未设置时使用)。",
+ "apihelp-query+notifications-param-alertunreadfirst": "是否首先显示未读的消息通知(只当groupbysection已设置时使用)。",
+ "apihelp-query+notifications-param-messagecontinue": "当更多消息结果可用时,使用这个继续。",
+ "apihelp-query+notifications-param-messageunreadfirst": "是否首先显示未读的提醒通知(只当groupbysection已设置时使用)。",
+ "apihelp-query+notifications-param-titles": "只返回这些页面的通知。要获取未分配给任何页面的通知,使用[]作为标题。",
+ "apihelp-query+notifications-param-bundle": "是否根据通知类型捆绑规则,显示兼容捆绑的未读通知。",
+ "apihelp-query+notifications-example-1": "列举通知",
+ "apihelp-query+notifications-example-2": "列出通知,按节分组,带有数量",
+ "apihelp-query+unreadnotificationpages-description": "获取当前用户未读通知的相关页面。",
+ "apihelp-query+unreadnotificationpages-summary": "获取当前用户未读通知的相关页面。",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "将讨论页与它们的主题页面一起分组,并将未分配给某一页面的通知与当前用户的用户页一起分组。",
+ "apihelp-query+unreadnotificationpages-param-limit": "返回页面的最大数量。",
+ "apihelp-query+unreadnotificationpages-param-wikis": "要取得来自未读通知页面的wiki列表(默认仅当前wiki)。",
+ "apihelp-query+unreadnotificationpages-example-1": "列举有(对应数量)未读通知的页面",
+ "apihelp-echoarticlereminder-summary": "请求今后有关特定条目的提醒",
+ "apihelp-echoarticlereminder-param-pageid": "要提醒用户的有关条目ID",
+ "apihelp-echoarticlereminder-param-title": "要提醒用户的有关条目标题",
+ "apihelp-echoarticlereminder-param-timestamp": "提醒用户的时间戳",
+ "apihelp-echoarticlereminder-param-comment": "包含在提醒中的可选用户注释",
+ "apihelp-echoarticlereminder-example-1": "为明天创建带注释的条目提醒通知",
+ "apihelp-echoarticlereminder-example-2": "为明天创建没有注释的条目提醒通知",
+ "apiwarn-echo-deprecation-timestampformat": "MW时间戳输出格式在此处已弃用。今后输出的时间戳格式将总是使用ISO 8601格式。请调整您的客户端,并设置<var>timestampFormat</var>为<kbd>ISO_8601</kbd>",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd>已弃用,并将很快被移除。请使用<kbd>notformat=model</kbd>以获取原始数据,或使用<kbd>notformat=special</kbd>以获取预渲染HTML。",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd>已弃用,并将很快被移除。请改用<kbd>notformat=special</kbd>。",
+ "apierror-echo-event-creation-failed": "无法创建Echo活动"
+}
diff --git a/Echo/i18n/api/zh-hant.json b/Echo/i18n/api/zh-hant.json
new file mode 100644
index 00000000..f4b00c2a
--- /dev/null
+++ b/Echo/i18n/api/zh-hant.json
@@ -0,0 +1,51 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cwlin0416",
+ "Winstonyin"
+ ]
+ },
+ "apihelp-echomarkread-description": "把目前使用者的通知標記為已讀。",
+ "apihelp-echomarkread-param-list": "要標記為已讀的通知 ID 清單。",
+ "apihelp-echomarkread-param-unreadlist": "要標記為未讀的通知 ID 清單。",
+ "apihelp-echomarkread-param-all": "一旦設定,將會把某個使用者的所有通知標記為已讀。",
+ "apihelp-echomarkread-param-sections": "要標記為已讀的章節清單。",
+ "apihelp-echomarkread-example-1": "把通知 8 標記為已讀",
+ "apihelp-echomarkread-example-2": "把所有通知標記為已讀",
+ "apihelp-echomarkread-example-3": "把通知 1 標記為未讀",
+ "apihelp-echomarkseen-description": "把目前使用者的通知標記為已讀",
+ "apihelp-echomarkseen-example-1": "把所有類型的通知標記為已讀",
+ "apihelp-echomarkseen-param-type": "標記為已讀的通知類型:'alert'、'message' 或 'all'。",
+ "apihelp-echomarkseen-param-timestampFormat": "用於輸出的時間戳格式 'ISO_8601' 或 'MW'。'MW' 將被棄用,因此所有客戶端都應改用 'ISO_8601'。此參數將會被移除,而 'ISO_8601' 將會成為唯一的輸出格式。",
+ "apihelp-query+notifications-description": "取得目前使用者等待的通知。",
+ "apihelp-query+notifications-param-prop": "請求的詳細資料。",
+ "apihelp-query+notifications-param-sections": "要查詢的通知章節 (例如部份 'alert' 與 'message' 的組合)。",
+ "apihelp-query+notifications-param-groupbysection": "是否要依據章節來分類查詢結果。 若開啟此功能,每個章節會分開擷取。",
+ "apihelp-query+notifications-param-filter": "過濾返回的通知。",
+ "apihelp-query+notifications-param-format": "若有指定,通知將會以此指定的格式回傳結果。",
+ "apihelp-query+notifications-paramvalue-format-text": "純文字格式",
+ "apihelp-query+notifications-paramvalue-format-model": "原始通知資料",
+ "apihelp-query+notifications-paramvalue-format-special": "格式用於Special:Notifications頁面(僅限於此!)。不要依賴HTML,因為它在任何時候都可能會變化。",
+ "apihelp-query+notifications-paramvalue-format-flyout": "<span class=\"apihelp-deprecated\">棄用</span>。原始數據請用<kbd>$1format=model</kbd>",
+ "apihelp-query+notifications-paramvalue-format-html": "<span class=\"apihelp-deprecated\">棄用</span>。原始數據請用<kbd>$1format=model</kbd>",
+ "apihelp-query+notifications-param-limit": "要回傳的通知數量上限。",
+ "apihelp-query+notifications-param-wikis": "要擷取通知的wiki清單(預設為目前的wiki)。",
+ "apihelp-query+notifications-param-crosswikisummary": "若設為真,會啟用外來wiki通知的摘要通知。",
+ "apihelp-query+notifications-param-alertcontinue": "當有多個警告的結果時,使用此參數來繼續。",
+ "apihelp-query+notifications-param-unreadfirst": "是否要先顯示未讀的通知(僅當groupbysection未設定時使用)。",
+ "apihelp-query+notifications-param-alertunreadfirst": "是否要先顯示未讀的訊息通知(僅當groupbysection未設定時使用)。",
+ "apihelp-query+notifications-param-messagecontinue": "當有更多訊息結果時,使用此參數來繼續。",
+ "apihelp-query+notifications-param-messageunreadfirst": "是否要先顯示未讀的警告通知(僅當groupbysection未設定時使用)。",
+ "apihelp-query+notifications-param-titles": "只返回这些页面的通知。要獲取未分配給任何頁面的通知,使用[]作為標題。",
+ "apihelp-query+notifications-param-bundle": "是否根據通知類型捆綁規則,顯示兼容捆綁的未讀通知。",
+ "apihelp-query+notifications-example-1": "通知清單",
+ "apihelp-query+notifications-example-2": "依章節分類通知清單並顯示總數",
+ "apihelp-query+unreadnotificationpages-description": "獲取目前使用者有未讀通知的頁面。",
+ "apihelp-query+unreadnotificationpages-param-grouppages": "將討論頁與對應的主題頁面歸在一起,並將未分配給某一頁面的通知與目前使用者的使用者頁面歸在一起。",
+ "apihelp-query+unreadnotificationpages-param-limit": "回傳的頁面數量上限。",
+ "apihelp-query+unreadnotificationpages-param-wikis": "要擷取未讀通知的wiki清單(預設為目前的wiki)。",
+ "apihelp-query+unreadnotificationpages-example-1": "列出有未讀通知的頁面(及其未讀通知數量)",
+ "apiwarn-echo-deprecation-timestampformat": "此處棄用MW時間戳輸出格式。今後的時間戳輸出格式將總是使用ISO 8601。請將您的客戶端<var>timestampFormat</var>調整為<kbd>ISO_8601</kbd>。",
+ "apiwarn-echo-deprecation-flyout": "<kbd>notformat=flyout</kbd>已棄用,並將很快被移除。請用<kbd>notformat=model</kbd>獲取原始數據,或用<kbd>notformat=special</kbd>獲取預渲染HTML。",
+ "apiwarn-echo-deprecation-html": "<kbd>notformat=html</kbd>已棄用,並將很快被移除。請改用<kbd>notformat=special</kbd>。"
+}
diff --git a/Echo/i18n/ar.json b/Echo/i18n/ar.json
index 806ddc37..8fd9b999 100644
--- a/Echo/i18n/ar.json
+++ b/Echo/i18n/ar.json
@@ -13,7 +13,17 @@
"Omda4wady",
"Khaled",
"محمد أحمد عبد الفتاح",
- "Hiba Alshawi"
+ "Hiba Alshawi",
+ "Shbib Al-Subaie",
+ "Macofe",
+ "Sonic N800",
+ "Maroen1990",
+ "Catrope",
+ "علاء",
+ "بدارين",
+ "Izoozo",
+ "Moud hosny",
+ "ديفيد"
]
},
"echo-desc": "نظام لإخطار المستخدمين عن الأحداث والرسائل",
@@ -21,7 +31,9 @@
"prefs-emailsettings": "خيارات البريد الإلكتروني",
"prefs-displaynotifications": "خيارات العرض",
"prefs-echosubscriptions": "أعلمني بشأن هذه الأحداث",
+ "prefs-echocrosswiki": "إشعارات عابرة للويكي",
"prefs-newmessageindicator": "مؤشر الرسائل الجديدة",
+ "prefs-blocknotificationslist": "المستخدمون الممنوعون",
"echo-pref-send-me": "أرسل لي:",
"echo-pref-send-to": "أرسل إلى:",
"echo-pref-email-format": "صيغة البريد الإلكتروني:",
@@ -33,99 +45,177 @@
"echo-pref-email-frequency-weekly": "ملخصا أسبوعيا للإشعارات",
"echo-pref-email-format-html": "إتش تي إم إل",
"echo-pref-email-format-plain-text": "نص خام",
+ "echo-pref-cross-wiki-notifications": "أظهر الإشعارات من ويكيات أخرى.",
+ "echo-pref-notifications-blacklist": "لا تعرض الإخطارات من هؤلاء المستخدمين. ([[mw:Help:Notifications#mute|اعرف المزيد]])",
"echo-pref-new-message-indicator": "أظهر مؤشر رسائل صفحة النقاش في شريط الأدوات",
+ "echo-pref-beta-feature-cross-wiki-message": "إشعارات معززة",
+ "echo-pref-beta-feature-cross-wiki-description": "اعرض ونظّم الإشعارات بطريقة أكثر سهولة. بما في ذلك الإشعارات عبر الويكي، التي تتيح لك رؤية إشعاراتك في مواقع الويكي الأخرى. (لاستلام الإشعارات عبر الويكي، يجب عليك تفعيل خاصية البيتا على هذه الويكي.)",
"echo-learn-more": "معرفة المزيد",
+ "echo-log": "السجل العلني",
"echo-new-messages": "لديك رسائل جديدة",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|رسالة|رسائل}} صفحة النقاش",
"echo-category-title-article-linked": "{{PLURAL:$1|وصلة|وصلات}} صفحة",
"echo-category-title-reverted": "إلغاء {{PLURAL:$1|تعديل|تعديلات}}",
"echo-category-title-mention": "{{PLURAL:$1|إشارة|إشارات}}",
+ "echo-category-title-mention-failure": "فشلت {{PLURAL:$1|الإشارة|الإشارات}}",
+ "echo-category-title-mention-success": "نجحت {{PLURAL:$1|الإشارة|الإشارات}}",
"echo-category-title-other": "{{PLURAL:$1|أخرى}}",
"echo-category-title-system": "{{PLURAL:$1|النظام}}",
"echo-category-title-user-rights": "{{PLURAL:$1|تغيير صلاحيات المستخدم|تغييرات صلاحيات المستخدم}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|بريد إلكتروني من مسخدم آخر|بريد إلكتروني من مستخدمين آخرين}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|تذكير|تذكيرات}} الصفحة",
"echo-pref-tooltip-edit-user-talk": "أعلمني عندما توضع رسائل أو ردود في صفحة نقاشي.",
- "echo-pref-tooltip-article-linked": "أعلمني عندما توضع في مقالة ما وصلة لصفحة أنشأتها.",
- "echo-pref-tooltip-reverted": "أعلمني عندما إلغاء تعديل أجريته.",
- "echo-pref-tooltip-mention": "أعلمني عندما توضع في صفحة نقاش ما وصلة لصفحتي.",
- "echo-pref-tooltip-user-rights": "أعلمني عند تغيير صلاحياتي.",
- "echo-no-agent": "[لا أحد]",
- "echo-no-title": "[لا صفحة]",
+ "echo-pref-tooltip-article-linked": "أعلمني عندما توضع في صفحة أخرى وصلة لصفحة أنشأتها.",
+ "echo-pref-tooltip-reverted": "أعلمني عندما إلغاء تعديل أجريته، بواسطة أداة الرجوع أو الاسترجاع.",
+ "echo-pref-tooltip-mention": "أعلمني عندما يضع مستخدم ما وصلة لصفحتي.",
+ "echo-pref-tooltip-mention-failure": "أبلغني عندما لا يمكنني إرسال إخطار لشخص ما.",
+ "echo-pref-tooltip-mention-success": "أخطرني عند إرسال إشارة إلى شخص ما.",
+ "echo-pref-tooltip-user-rights": "أعلمني عندما يغير شخص ما صلاحياتي.",
+ "echo-pref-tooltip-emailuser": "أعلمني عندما يرسل أحد ما بريدًا إلكترونيًا إليَّ.",
+ "echo-pref-tooltip-article-reminder": "أخطرني حول هذه الصفحة عندما أسأل.",
"echo-error-no-formatter": "لم يحدد للإشعارات أي تنسيق.",
"notifications": "إشعارات",
- "tooltip-pt-notifications-alert": "إخطاراتك",
- "tooltip-pt-notifications-message": "{{GENDER:|رسائلك}}",
+ "tooltip-pt-notifications-alert": "{{GENDER:|إخطاراتك}}",
+ "tooltip-pt-notifications-notice": "{{GENDER:|إخطاراتك}}",
+ "echo-displaynotificationsconfiguration": "عرض تنبهات الإعدادات",
+ "echo-displaynotificationsconfiguration-summary": "هذا لمحة عامة عن كيفية اعداد الإخطارات في هذه الويكي.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "الإشعارات حسب التصنيف",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "ترتيب الأنواع",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "في المقطع ما يصنف كل نوع من الإخطار",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "وسائل التنبيه المسموح بها",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "ما هي وسائل التنبيه التي تدعم كل فئة",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "ما هي وسائل التنبيه المستخدمة لكل نوع؛ لا ينطبق إلا على أنواع داخل الفئات التي تكون مخفية من التفضيلات",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "مفعلة افتراضيا",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "المستخدمون الحاليون",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "المستخدمون الجدد",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "طرق الإشعار المطلوبه",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "ما هي طرق الاشعارات المطلوبة لكل فئة من فئات",
"echo-specialpage": "إشعارات",
+ "echo-specialpage-section-markread": "اعتبر المجموعة مقروءة",
+ "echo-specialpage-markasread": "إخطار: وضع علامة كمقروء",
+ "echo-specialpage-markasread-invalid-id": "رقم حدث غير صحيح",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|لا إشعار|إشعار واحد|إشعاران|$1 إشعارات|$1 إشعارا|$1 إشعار}}",
+ "echo-specialpage-pagefilters-title": "النشاطات الحديثة",
+ "echo-specialpage-pagefilters-subtitle": "صفحات لها إشعارات غير مقروءة",
+ "notificationsmarkread-legend": "علم على الإخطار كمقروء",
"echo-anon": "لتلقي الإشعارات، [$1 أنشئ حسابا] أو [$2 سجل الدخول].",
"echo-none": "ليس لديك أي إشعارات",
"echo-more-info": "المزيد",
"echo-feedback": "تعليقات",
+ "echo-popup-footer-special-page-invitation": "<strong>جرب صفحة الإخطارات المعاد تصميمها.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "كل الخصائص والمظاهر الجديدة.",
+ "echo-api-failure": "تعذّر إظهار الإشعارات.",
+ "echo-api-failure-cross-wiki": "رُفض الوصول إلى النطاق البعيد.",
+ "echo-notification-placeholder": "لا توجد أية إخطارات.",
+ "echo-notification-placeholder-filters": "لا يُوجد إشعارات تنطبق عليها الخيارات المحددة.",
+ "echo-notification-loginrequired": "يجب عليك تسجيل الدخول للاطلاع على إشعاراتك.",
+ "echo-notification-popup-loginrequired": "من فضلك سجل الدخول لعرض إشعاراتك.",
+ "echo-notification-markasread": "علّم كمقروءة",
+ "echo-notification-markasunread": "أبقها غير مقروءة",
+ "echo-notification-markasread-tooltip": "علّم كمقروءة",
+ "echo-notification-more-options-tooltip": "المزيد من الخيارات",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|توقف|توقفي}} عن مراقبة النشاط الجديد على \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|أنت}} لم تعد تراقب الصفحة \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|أنت}} يمكنك مراقبة [$2 هذه الصفحة] في أي وقت.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|تابع|تابعي}} النشاط الجديد على \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|أنت}} الآن تراقب الصفحة \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|أنت}} تستطيع التوقف عن مشاهدة [$2 هذه الصفحة] في أي وقت.",
+ "notification-link-text-expand-all": "اعرض الكل",
+ "notification-link-text-expand-alert-count": "أظهر {{PLURAL:$1|$1 تنبيه|تنبيهًا واحدًا|تنبيهين|$1 تنبيهات|$1 تنبيهًا}}",
+ "notification-link-text-expand-notice-count": "اعرض {{PLURAL:$1|لا إخطارات|إخطارًا واحدًا|إخطارين|$1 إخطارات|$1 إخطارًا}}",
+ "notification-link-text-expand-all-count": "اعرض {{PLURAL:$1|إشعارًا واحدًا|إشعارين اثنين|$1 إشعارات|$1 إشعارًا}}",
+ "notification-link-text-collapse-all": "اطو",
"notification-link-text-view-message": "اعرض الرسالة",
"notification-link-text-view-mention": "اعرض الإشارة",
- "notification-link-text-view-changes": "اعرض التعديلات",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|عرض الإشارة|عرض الإشارات}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|اعرض}} التعديلات",
"notification-link-text-view-page": "اعرض الصفحة",
+ "notification-header-edit-user-talk": "{{GENDER:$2|بعث|بعثت}} $1 رسالةً إليك في <strong>{{GENDER:$3|صفحة نقاشك}}</strong>.",
+ "notification-header-edit-user-talk-with-section": "{{GENDER:$2|بعث|بعثت}} $1 رسالةً إليك في <strong>{{GENDER:$3|صفحة نقاشك}}</strong> في \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "أضيفت وصلة لصفحة <strong>$3</strong> في صفحة <strong>$4</strong>.",
+ "notification-compact-header-page-linked": "موصول من <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "أضيفت وصلات من {{PLURAL:$5||صفحة أخرى|صفحتين أخرتين|$5 صفحات أخرى|100=99+ صفحة أخرى}} إلى <strong>$3</strong>.",
+ "notification-header-article-reminder": "صفحة {{GENDER:$2|طلبت}} تذكيرك بخصوصها هي في <strong>$3</strong>",
+ "notification-link-text-what-links-here": "كل الوصلات إلى هذه الصفحة",
+ "notification-header-mention-other": "{{GENDER:$2|أشار|أشارت}} $1 {{GENDER:$3|لك|لكِ}} في صفحة <strong>$4</strong> في قسم \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|أشار|أشارت}} {{GENDER:$3|لك|لكِ}} في <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "{{GENDER:$2|أشار|أشارت}} $1 {{GENDER:$3|لك|لكِ}} في <strong>صفحة نقاش {{GENDER:$5|}} $4</strong> في \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "{{GENDER:$2|أشار|أشارت}} $1 {{GENDER:$3|لك|لكِ}} في <strong>صفحة نقاش مستخدم {{GENDER:$5|ل}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "{{GENDER:$2|أشار|أشارت}} $1 {{GENDER:$3|لك|لكِ}} في <strong>صفحة {{GENDER:$2|نقاشه|نقاشها}}</strong> في قسم \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|أشار|أشارت}} {{GENDER:$3|لك}} على صفحة <strong>{{GENDER:$2|نقاشه|نقاشها}}</strong>.",
+ "notification-header-mention-article-talkpage": "{{GENDER:$2|أشار|أشارت}} $1 {{GENDER:$3|إليك|إليكِ}} في صفحة نقاش <strong>$4</strong> في قسم \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "{{GENDER:$2|أشار|أشارت}} $1 {{GENDER:$3|إليك|إليكِ}} في صفحة نقاش <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|إشارتك|إشارتكِ}} إلى <strong>$3</strong> لم ترسل لأن المستخدم لم يُعثر عليه.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|إشارتك|إشارتكِ}} إلى <strong>$3</strong> لم ترسل لأن المستخدم مجهول.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|أنت}} حاولت أن تذكر أكثر من\n $3 {{PLURAL:$3|مستخدم|مستخدمين}}، جميع ما ذُكِرت أعلاه فوق الحد لم تُرسَل.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|تذكير|$3 تذكير}} {{GENDER:$2|قمت بها}} على صفحة نقاش <strong>$4</strong> لم {{PLURAL:$3|يمكن}} إرسالها.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>اسم المستخدم غير موجود:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>الأيبيهات لا يمكن إخطارها:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|إشارتك|إشارتكِ}} إلى <strong>$3</strong> أرسلت.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|تذكير|$3 تذكير}} {{GENDER:$2|قمت بها}} على صفحة النقاش <strong>$4</strong> {{PLURAL:$3|تم}} إرسالها.",
+ "notification-compact-header-mention-success": "<strong>لقد {{GENDER:$2|أشرت|أشرتِ}} إلى:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|إخطار|$3 إخطار}} حول التذكيرات {{GENDER:$2|التي قمت بها}} على صفحة النقاش <strong>$4</strong> talk page: {{PLURAL:$5|$5 لم يتم إرسالها}}، {{PLURAL:$6|$6 أرسلت}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$1|غُيرت|غُيرت}} صلاحيات المستخدم الخاصة {{GENDER:$4|بك|بكِ}}. أضفت إلى: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|صلاحياتك}} تم {{GENDER:$1|تغييرها}}. أنت لم تعد عضوا في: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|صلاحياتك}} تم {{GENDER:$1|تغييرها}}. أنت تمت إضافتك إلى: $2. أنت لم تعد عضوا في: $4.",
+ "notification-header-user-rights-expiry-change": "تاريخ انتهاء {{GENDER:$4|عضويتك}} في {{PLURAL:$3|المجموعة|المجموعات}} التالية تم {{GENDER:$1|تغييرها}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|مرحبًا بك|مرحبًا بكِ}} في {{SITENAME}}، $1! نحن سعداءٌ {{GENDER:$2|بتواجدك|بتواجدكِ}} هنا.",
+ "notification-welcome-linktext": "أهلاً بك.",
+ "notification-header-thank-you-1-edit": "لقد {{GENDER:$2|قمت|قمتِ}} قبل قليل {{GENDER:$2|بتعديلك|بتعديلكِ}} الأول؛ شكرًا {{GENDER:$2|لك|لكِ}}، ومرحبًا بك!",
+ "notification-header-thank-you-10-edit": "لقد {{GENDER:$2|قمت|قمتِ}} {{GENDER:$2|بتعديلك|بتعديلكِ}} العاشر؛ شكرًا {{GENDER:$2|لك|لكِ}}، و{{GENDER:$2|واصل|واصلي}} العمل!",
+ "notification-header-thank-you-100-edit": "لقد {{GENDER:$2|قمت|قمتِ}} قبل قليل {{GENDER:$2|بتعديلك|بتعديلكِ}} رقم مئة؛ شكرًا جزيلًا {{GENDER:$2|لك|لكِ}}!",
+ "notification-header-thank-you-1000-edit": "لقد {{GENDER:$2|قمت|قمتِ}} قبل قليل {{GENDER:$2|بتعديلك|بتعديلكِ}} رقم ألف؛ شكرًا {{GENDER:$2|لك|لكِ}} لكونك مساهمًا عظيمًا!",
+ "notification-header-thank-you-10000-edit": "لقد {{GENDER:$2|قمت|قمتِ}} قبل قليل {{GENDER:$2|بتعديلك|بتعديلكِ}} رقم عشرة آلاف؛ شكرًا جزيلًا {{GENDER:$2|لك|لكِ}}!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|أنت}} قمت حالا {{GENDER:$2|بتعديلك}} رقم مائة ألف؛ شكرا {{GENDER:$2|لك}} لمساهمة مذهلة!",
+ "notification-header-thank-you-1000000-edit": "لقد {{GENDER:$2|قمت|قمتِ}} قبل قليل {{GENDER:$2|بتعديلك|بتعديلكِ}} رقم مليون؛ شكرًا {{GENDER:$2|لك|لكِ}} على مساهمتك المذهلة!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|تعديلك|تعديلكِ}}",
"notification-link-text-view-edit": "اعرض التعديل",
- "notification-edit-talk-page2": "{{GENDER:$1|بعث|بعثت}} لك [[User:$1|$1]] برسالة في [[User talk:$2#$3|صفحة نقاشك]].",
- "notification-edit-talk-page-with-section": "{{GENDER:$1|بعث|بعثت}} لك [[User:$1|$1]] برسالة في قسم [[User talk:$2#$3|$4]] من [[User talk:$2#$3|صفحة نقاشك]].",
- "notification-edit-talk-page-flyout2": "{{GENDER:$1|بعث|بعثت}} لك $1 برسالة في [[User talk:$2#$3|صفحة نقاشك]].",
- "notification-edit-talk-page-flyout-with-section": "{{GENDER:$1|بعث|بعثت}} لك $1 برسالة في قسم [[User talk:$2#$3|$4]] من صفحة نقاشك.",
- "notification-page-linked": "{{GENDER:$1|وضعت}} وصلة لصفحة [[:$2]] في [[:$3]]. [[Special:WhatLinksHere/$2|انظر جميع وصلات تلك الصفحة]].",
- "notification-page-linked-flyout": "{{GENDER:$1|وضعت}} وصلة لصفحة [[:$2]] في [[:$3]].",
- "notification-add-comment2": "{{GENDER:$1|علق|علقت}} [[User:$1|$1]] على \"[[$3|$2]]\" في صفحة نقاش \"$4\".",
- "notification-add-talkpage-topic2": "{{GENDER:$1|أنشأ|أنشأت}} [[User:$1|$1]] قسما جديدا بعنوان \"$2\" في [[$3]].",
- "notification-add-talkpage-topic-yours2": "{{GENDER:$1|أرسل|أرسلت}} لك [[User:$1|$1]] رسالة بعنوان \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "{{GENDER:$1|علق|علقت}} [[User:$1|$1]] على \"[[$3#$2|$2]]\" في صفحة نقاشك.",
- "notification-mention": "{{GENDER:$1|أشار|أشارت}} إليك [[User:$1|$1]] في قسم \"[[:$3#$2|$4]]\" من صفحة نقاش $5.",
- "notification-mention-flyout": "{{GENDER:$1|أشار|أشارت}} إليك $1 في قسم \"[[:$3#$2|$4]]\" في صفحة نقاش $5.",
- "notification-mention-nosection": "{{GENDER:$1|أشار|أشارت}} [[User:$1|$1]] إليك على [[:$3|صفحة نقاش $2]].",
- "notification-mention-nosection-flyout": "{{GENDER:$1|أشار|أشارت}} $1 إليك في [[:$3|صفحة نقاش $2]].",
- "notification-user-rights": "[[Special:Log/rights/$1|{{GENDER:$1|غير|غيرت}}]] [[User:$1|$1]] صلاحياتك. $2. [[Special:ListGroupRights|المزيد]]",
- "notification-user-rights-flyout": "{{GENDER:$1|غير|غيرت}} $1 صلاحياتك. $2. [[Special:ListGroupRights|المزيد]]",
- "notification-user-rights-add": "أنت الآن عضو في {{PLURAL:$2|مجموعة|مجموعات}}: $1",
- "notification-user-rights-remove": "ألغيت عضويتك في {{PLURAL:$2|مجموعة|مجموعات}}: $1",
- "notification-new-user": "$1، مرحبا بك في {{SITENAME}}. أسعدنا بلقياك.",
- "notification-reverted2": "{{GENDER:$1|ألغى|ألغت}} [[User:$1|$1]] {{PLURAL:$4|تعديلك في [[:$2]]|تعديلاتك في [[:$2]]}}. $3",
- "notification-reverted-flyout2": "{{GENDER:$1|ألغى|ألغت}} $1 {{PLURAL:$4|تعديلك في $2|تعديلاتك في $2}}. $3",
+ "notification-link-article-reminder": "عرض الصفحة",
+ "notification-header-reverted": "{{PLURAL:$4|تعديلك في <strong>$3</strong>|تعديلاك في <strong>$3</strong>|تعديلاتك في <strong>$3</strong>}} {{GENDER:$2|ألغيت|ألغيت}}",
+ "notification-header-emailuser": "{{GENDER:$2|أرسل|أرسلت}} $1 بريدا إلكترونيا إليك.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|بعث|بعثت}} لك $1 برسالة في {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|بعث|بعثت}} لك $1 برسالة في صفحة نقاشك.",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|بعث|بعثت}} لك $1 برسالة في صفحة نقاشك في \"$2\".",
"notification-page-linked-email-subject": "وضعت وصلة لصفحة أنشأتها في {{SITENAME}}",
- "notification-page-linked-email-batch-body": "{{GENDER:$1|وضعت}} وصلة إلى $2 في $3.",
"notification-reverted-email-subject2": "{{GENDER:$1|ألغي{{PLURAL:$3||ت}}}} {{PLURAL:$3|تعديلك|تعديلاتك}} في {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{GENDER:$1|ألغى|ألغت}} $1 {{PLURAL:$3|تعديلك|تعديلاتك}} في $2.",
- "notification-mention-email-subject": " {{GENDER:$1|أشار|أشارت}} إليك $1 في {{SITENAME}}",
- "notification-mention-email-batch-body": " {{GENDER:$1|أشار|أشارت}} إليك $1 في قسم \"$3\" من صفحة نقاش $4.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|أشار|أشارت}} إليك في صفحة نقاش $2.",
+ "notification-mention-email-subject": "{{GENDER:$1|أشار|أشارت}} $1 {{GENDER:$2|إليك}} في {{SITENAME}}",
"notification-user-rights-email-subject": "غيرت صلاحياتك في {{SITENAME}}",
- "notification-user-rights-email-batch-body": "{{GENDER:$1|غير|غيرت}} $1 صلاحياتك. $2.",
- "echo-email-subject-default": "إشعار جديد في {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|ثانية واحدة|ثانيتين|$1 ثوان|$1 ثانية}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|دقيقة واحدة|دقيقتين|$1 دقائق|$1 دقيقة}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|ساعة واحدة|ساعتين|$1 ساعات|$1 ساعة}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|يوم واحد|يومين|$1 أيام|$1 يومًا}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|شهر واحد|شهرين|$1 أشهر|$1 شهرًا}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|عام واحد|عامين|$1 أعوام|$1 عام}}",
+ "notification-timestamp-today": "اليوم",
+ "notification-timestamp-yesterday": "أمس",
+ "notification-inbox-filter-read": "المقروءة",
+ "notification-inbox-filter-unread": "غير المقروءة",
+ "notification-inbox-filter-all": "الكل",
"echo-email-body-default": "لديك إشعار جديد في {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "لديك إشعار جديد.",
+ "echo-email-footer-default-html": "للتحكم في أي رسائل البريد الإلكتروني نرسلها لك، <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">تحقق من تفضيلاتك</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nللتحكم في رسائل الإلكترونية التي نرسلها لك، انظر التفضيلات:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "للتحكم في رسائل الإلكترونية التي نرسلها لك، <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">انظر التفضيلات</a>.<br />\n$1",
+ "echo-email-plain-footer": "للتحكم في ما هي رسائل البريد الإلكتروني التي نرسلها {{GENDER:$1|إليك}}، تحقق من {{GENDER:$1|تفضيلاتك}}:",
+ "echo-email-html-footer-preference-link-text": "تحقق من {{GENDER:$1|تفضيلاتك}}",
+ "echo-email-html-footer-with-link": "للتحكم في ما هي رسائل البريد الإلكتروني التي نرسلها {{GENDER:$2|إليك}}، $1.",
"echo-notification-alert": "{{PLURAL:$1|إخطار|إخطاران|إخطارات ($1)|100=إخطارات (أكثر من 99)}}",
- "echo-notification-message": "{{PLURAL:$1|رسالة|رسالتان|رسائل ($1)|100=رسائل (+99)}}",
+ "echo-notification-notice": "{{PLURAL:$1|ملاحظة ($1)|ملاحظات ($1)|100=ملاحظات (99+)}}",
"echo-notification-alert-text-only": "تنبيهات",
- "echo-notification-message-text-only": "رسائل",
+ "echo-notification-notice-text-only": "إخطارات",
"echo-overlay-link": "كل الإشعارات",
"echo-overlay-title": "<b>إشعارات</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|إشعارات}}</b> (عرض $1 من $2 لم تقرأ)",
"echo-mark-all-as-read": "اعتبرها كلها مقروءة",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|إخطار|إخطارات}} تم التعليم عليها كمقروءة",
+ "echo-mark-wiki-as-read": "علّم الكل كمقروء في الويكي المحددة: $1",
"echo-date-today": "اليوم",
"echo-date-yesterday": "أمس",
- "echo-load-more-error": "وقع خطأ في إيراد المزيد من النتائج.",
- "notification-edit-talk-page-bundle": "{{GENDER:$1|{{PLURAL:$4|بعث}}|{{PLURAL:$4|بعثت}}}} لك $1 و{{PLURAL:$4|مستخدم آخر|مستخدم آخر|مستخدمان آخران|$3 آخرون}} برسائل في [[User talk:$2|صفحة نقاشك]].",
- "notification-page-linked-bundle": "{{GENDER:$1|وضعت}} وصلة إلى $2 في $3 و{{PLURAL:$5|صفحة أخرى|صفحة أخرى|صفحتين أخريين|$4 صفحات أخرى|$4 صفحة أخرى}}. [[Special:WhatLinksHere/$2|انظر جميع الوصلات إلى هذه الصفحة]]",
- "notification-edit-user-talk-email-batch-bundle-body": "{{GENDER:$1|{{PLURAL:$3|بعث}}|{{PLURAL:$3|بعثت}}}} لك $1 و{{PLURAL:$3|مستخدم آخر|مستخدم آخر|مستخدمان آخران|$2 مستخدمين آخرين|$2 مستخدما آخر|$2 مستخدم آخر}} برسائل في صفحة نقاشك.",
- "notification-page-linked-email-batch-bundle-body": "{{GENDER:$1|وضعت}} وصلة إلى $2 في $3 و{{PLURAL:$5|صفحة أخرى|صفحة أخرى|صفحتين أخريين|$4 صفحات أخرى|$4 صفحة أخرى}}.",
+ "echo-load-more-error": "وقع خطأ أثناء جلب المزيد من النتائج.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|لا رسائل|رسالة جديدة|رسالتان جديدتان|$1 رسائل جديدة|$1 رسالة جديدة}} على </strong>صفحة {{GENDER:$3|نقاشك|نقاشكِ}}.<strong>",
"echo-email-batch-subject-daily": "لديك {{PLURAL:$2|إشعار جديد|إشعارات جديدة}} في {{SITENAME}}",
"echo-email-batch-subject-weekly": "لديك {{PLURAL:$2|إشعار جديد|إشعارات جديدة}} في {{SITENAME}} هذا الأسبوع",
"echo-email-batch-body-intro-daily": "سلام $1،\nهذا ملخص لنشاطات اليوم في {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "سلام $1،\nهذا ملخص لنشاطات الأسبوع في {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "اعرض كل الإشعارات",
- "echo-rev-deleted-text-view": "هذه النسخة من الصفحة قد حذفت.",
- "apihelp-echomarkseen-param-type": "نوع الإشعارت لتحديد كما تبدو على أنها: 'تنبيه' 'رسالة' أو 'كل'.",
- "apihelp-query+notifications-param-prop": "طلب تفاصيل.",
- "apihelp-query+notifications-param-sections": "اقسام الأشعار للأستعلام (أي بمعنى بعض الثنائي من \"تنبيه\" و \"رسالة\").",
- "apihelp-query+notifications-param-limit": "العدد الأقصى للإخطارات في النتائج.",
- "apihelp-query+notifications-example-1": "قائمة الإشعارات"
+ "notification-header-foreign-alert": "إخطارات أكثر من {{PLURAL:$5|لا موقع ويكي|موقع ويكي آخر|موقعين ويكي آخرين|$5 مواقع ويكي أخرى}}",
+ "notification-header-foreign-notice": "مزيد من الإشعارات من {{PLURAL:$5|ويكي أخر|$5 ويكيات أخرى}}",
+ "notification-header-foreign-all": "المزيد من الإخطارات من {{PLURAL:$5|ويكي أخرى|$5 ويكيات أخرى}}"
}
diff --git a/Echo/i18n/arq.json b/Echo/i18n/arq.json
index 62491129..7c7fdf19 100644
--- a/Echo/i18n/arq.json
+++ b/Echo/i18n/arq.json
@@ -1,8 +1,10 @@
{
"@metadata": {
"authors": [
- "Oldstoneage"
+ "Oldstoneage",
+ "GeekEmad"
]
},
- "tooltip-pt-notifications": "التعلومات"
+ "tooltip-pt-notifications-alert": "إخطاراتك",
+ "tooltip-pt-notifications-message": "رسايلك"
}
diff --git a/Echo/i18n/arz.json b/Echo/i18n/arz.json
index d6af3d0e..8b4a685f 100644
--- a/Echo/i18n/arz.json
+++ b/Echo/i18n/arz.json
@@ -3,6 +3,5 @@
"authors": [
"Ghaly"
]
- },
- "tooltip-pt-notifications": "إشعاراتك"
+ }
}
diff --git a/Echo/i18n/as.json b/Echo/i18n/as.json
index dfec5cea..0fb34392 100644
--- a/Echo/i18n/as.json
+++ b/Echo/i18n/as.json
@@ -6,5 +6,6 @@
},
"echo-new-messages": "আপোনালৈ নতুন বাৰ্তা আহিছে",
"notifications": "জাননী",
- "tooltip-pt-notifications": "আপোনাৰ জাননীসমূহ"
+ "tooltip-pt-notifications-alert": "{{GENDER:|আপোনাৰ}} জাননী",
+ "tooltip-pt-notifications-message": "{{GENDER:|আপোনাৰ}} বাৰ্তাসমূহ"
}
diff --git a/Echo/i18n/ast.json b/Echo/i18n/ast.json
index 6338de68..3a72e6c7 100644
--- a/Echo/i18n/ast.json
+++ b/Echo/i18n/ast.json
@@ -1,7 +1,8 @@
{
"@metadata": {
"authors": [
- "Xuacu"
+ "Xuacu",
+ "Macofe"
]
},
"echo-desc": "Sistema p'avisar a los usuarios sobre actividaes y mensaxes",
@@ -9,7 +10,9 @@
"prefs-emailsettings": "Opciones de corréu",
"prefs-displaynotifications": "Opciones de vista",
"prefs-echosubscriptions": "Avisame d'estos socesos",
+ "prefs-echocrosswiki": "Notificaciones ente wikis",
"prefs-newmessageindicator": "Indicador de mensaxe nuevu",
+ "prefs-blocknotificationslist": "Llista de bloqueos",
"echo-pref-send-me": "Unviame:",
"echo-pref-send-to": "Unviar a:",
"echo-pref-email-format": "Formatu del corréu:",
@@ -21,116 +24,177 @@
"echo-pref-email-frequency-weekly": "Un resume selmanal de los avisos",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Testu simple",
+ "echo-pref-cross-wiki-notifications": "Amosar notificaciones d'otres wikis",
+ "echo-pref-notifications-blacklist": "Llista de nomes d'usuariu que tán na llista prieta pa disparar la mayor parte d'avisos de Echo (les ediciones na páxina d'alderique d'usuariu entá dispararán los avisos)",
"echo-pref-new-message-indicator": "Amosar un indicador de mensaxe na páxina d'alderique na mio barra de ferramientes",
+ "echo-pref-beta-feature-cross-wiki-message": "Notificaciones enantaes",
+ "echo-pref-beta-feature-cross-wiki-description": "Ver y organizar les notificaciones más fácilmente. Incluye notificaciones ente wikis, lo que te permite ver mensaxes d'otres wikis. (Pa recibir notificaciones ente wikis nuna wiki determinada tienes d'activar la carauterística beta nesa wiki)",
"echo-learn-more": "Más información",
+ "echo-log": "Rexistru públicu",
"echo-new-messages": "Tien mensaxes nuevos",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mensaxe|Mensaxes}} na páxina d'alderique",
"echo-category-title-article-linked": "{{PLURAL:$1|Enllaz|Enllaces}} a páxina",
"echo-category-title-reverted": "{{PLURAL:$1|Inversión|Inversiones}} d'edición",
"echo-category-title-mention": "{{PLURAL:$1|Mención|Menciones}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Mención fallida|Menciones fallíes}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Mención correuta|Menciones correutes}}",
"echo-category-title-other": "{{PLURAL:$1|Otros}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Cambiu de permisos d'usuariu|Cambios de permisos d'usuariu}}",
- "echo-pref-tooltip-edit-user-talk": "Avisame cuando alguién dexe un mensaxe na mio páxina d'alderique.",
- "echo-pref-tooltip-article-linked": "Avisame cuando alguién enllace dende un artículu a una páxina que yo creé.",
- "echo-pref-tooltip-reverted": "Avisame cuando alguién revierta una edición de mió, usando les ferramientes desfacer o revertir.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Corréu electrónicu d'otru usuariu|Correos electrónicos d'otros usuarios}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Recordatoriu d'artículu|Recordatorios d'artículu}} de la páxina",
+ "echo-pref-tooltip-edit-user-talk": "Avisame cuando dalguién dexe un mensaxe o conteste na mio páxina d'alderique.",
+ "echo-pref-tooltip-article-linked": "Avisame cuando dalguién enllace a una páxina que yo creé dende una páxina d'artículu.",
+ "echo-pref-tooltip-reverted": "Avisame cuando dalguién revierta una edición fecha por min, usando les ferramientes desfacer o revertir.",
"echo-pref-tooltip-mention": "Avisame cuando dalguién enllace a la mio páxina d'usuariu.",
+ "echo-pref-tooltip-mention-failure": "Avisame cuando nun pueda unviar una mención a dalguién.",
+ "echo-pref-tooltip-mention-success": "Avisame cuando unvie una mención a dalguién.",
"echo-pref-tooltip-user-rights": "Avisame cuando dalguién cambie los mios permisos d'usuariu.",
- "echo-no-agent": "[Naide]",
- "echo-no-title": "[Ensin páxina]",
+ "echo-pref-tooltip-emailuser": "Avisame cuando daquién me mande un corréu electrónicu.",
+ "echo-pref-tooltip-article-reminder": "Recordame d'esti artículu cuando lo pidí.",
"echo-error-no-formatter": "Nun se definió formatu dalu pal avisu",
"notifications": "Avisos",
"tooltip-pt-notifications-alert": "{{GENDER:|Les tos}} alertes",
- "tooltip-pt-notifications-message": "{{GENDER:|Los tos}} mensaxes",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Los tos}} avisos",
+ "echo-displaynotificationsconfiguration": "Amosar la configuración de notificaciones",
+ "echo-displaynotificationsconfiguration-summary": "Esti ye un resume de cómo se configuren les Notificaciones nesta wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notificaciones per categoría",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Ordenación de tipos",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "En que sección s'ordena cada tipu de notificación",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Métodos de notificación permitíos",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Cuálos métodos de notificación s'almiten pa cada categoría",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Cuálos métodos de notificación s'almiten pa cada tipu; namái s'aplica a los tipos dientro de les categoríes que tán tapecíes nes preferencies",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Activaes de mou predetermináu",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Usuarios esistentes",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Usuarios nuevos",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Métodos de notificación riquíos",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Cuálos métodos de notificación son obligatorios pa cada categoría",
"echo-specialpage": "Avisos",
+ "echo-specialpage-section-markread": "Marca el grupu como lleíu",
+ "echo-specialpage-markasread": "Notificación: marcar como lleída",
+ "echo-specialpage-markasread-invalid-id": "ID de socesu inválidu",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|avisu|avisos}}",
+ "echo-specialpage-pagefilters-title": "Actividá recién",
+ "echo-specialpage-pagefilters-subtitle": "Páxines con notificaciones ensin lleer",
+ "notificationsmarkread-legend": "Marcar la notificación como lleída",
"echo-anon": "Pa recibir avisos, [$1 cree una cuenta] o [$2 anicie sesión].",
"echo-none": "Nun tien avisos.",
"echo-more-info": "Más información",
"echo-feedback": "La so opinión",
+ "echo-popup-footer-special-page-invitation": "<strong>Prueba la páxina de notificaciones rediseñada.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Aspeutu y carauterístiques nuevos dafechu.",
+ "echo-api-failure": "Nun pudieron recuperase les notificaciones.",
+ "echo-api-failure-cross-wiki": "Refugóse l'accesu al dominiu remotu.",
+ "echo-notification-placeholder": "Nun hai notificaciones.",
+ "echo-notification-placeholder-filters": "Nun hai notificaciones que casen con esos criterios.",
+ "echo-notification-loginrequired": "Tienes d'aniciar sesión pa ver los avisos.",
+ "echo-notification-popup-loginrequired": "Anicia sesión pa ver los tos avisos.",
+ "echo-notification-markasread": "Marcar como lleíu",
+ "echo-notification-markasunread": "Marcar como non lleída",
+ "echo-notification-markasread-tooltip": "Marcar como lleí­da",
+ "echo-notification-more-options-tooltip": "Más opciones",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Dexar}} de siguir l'actividá nueva en «$1»",
+ "notification-dynamic-actions-unwatch-confirmation": "Yá nun {{GENDER:$3|tas}} siguiendo la páxina «$1»",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Puedes}} siguir [$2 esta páxina] en cualquier momentu.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Siguir}} l'actividá nueva en «$1»",
+ "notification-dynamic-actions-watch-confirmation": "Agora {{GENDER:$3|tas}} siguiendo la páxina «$1»",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Puedes}} dexar de siguir [$2 esta páxina] en cualquier momentu.",
+ "notification-link-text-expand-all": "Espander",
+ "notification-link-text-expand-alert-count": "Ver $1 {{PLURAL:$1|alerta|alertes}}",
+ "notification-link-text-expand-notice-count": "Ver {{PLURAL:$1|$1 avisu|$1 avisos}}",
+ "notification-link-text-expand-all-count": "Ver {{PLURAL:$1|l'avisu|$1 avisos}}",
+ "notification-link-text-collapse-all": "Anubrir",
"notification-link-text-view-message": "Ver el mensaxe",
"notification-link-text-view-mention": "Ver la mención",
- "notification-link-text-view-changes": "Ver los cambios",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Ver mención|Ver menciones}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Ver}} los cambios",
"notification-link-text-view-page": "Ver la páxina",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|dexó}} un mensaxe na <strong>{{GENDER:$3|to}} páxina d'alderique</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|dexó}} un mensaxe na <strong>{{GENDER:$3|to}} páxina d'alderique</strong> en «<strong>$4</strong>».",
+ "notification-header-page-linked": "Féxose un enllaz dende <strong>$4</strong> a <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Enllazáu dende <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Ficiéronse enllaces dende {{PLURAL:$5||$5 páxines|100=99+ páxines}} a <strong>$3</strong>.",
+ "notification-header-article-reminder": "En <strong>$3</strong> hai un artículu del que {{GENDER:$2|pidisti}} un recordatoriu",
+ "notification-link-text-what-links-here": "Tolos enllaces a esta páxina",
+ "notification-header-mention-other": "$1 {{GENDER:$3|te}} {{GENDER:$2|mentó}} en <strong>$4</strong> nel filu «<strong>$5</strong>».",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|te}} {{GENDER:$2|mentó}} en <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|te}} {{GENDER:$2|mentó}} na <strong>páxina d'alderique {{GENDER:$5|del usuariu|de la usuaria}} $4</strong> en «<strong>$6</strong>».",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|te}} {{GENDER:$2|mentó}} na <strong>páxina d'alderique {{GENDER:$5|del usuariu|de la usuaria}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|te}} {{GENDER:$2|mentó}} na <strong>{{GENDER:$2|so}} páxina d'alderique</strong> de <strong>«$4»</strong>.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|te}} {{GENDER:$2|mentó}} na <strong>{{GENDER:$2|so}} páxina d'alderique</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|te}} {{GENDER:$2|mentó}} na páxina d'alderique de <strong>$4</strong> en «<strong>$5</strong>».",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|te}} {{GENDER:$2|mentó}} na páxina d'alderique de <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|La to}} mención de <strong>$3</strong> nun s'unvió porque nun s'alcontró l'usuariu.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|La to}} mención de <strong>$3</strong> nun s'unvió porque l'usuariu ye anónimu.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Tentasti}} mencionar más de $3 {{PLURAL:$3|usuariu|usuarios}}. Toles menciones que pasaron de la llende nun s'unviaron.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Una mención|$3 menciones}} que {{GENDER:$2|fixisti}} na páxina d'alderique de <strong>$4</strong> nun {{PLURAL:$3|pudo|pudieron}} unviase.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>El nome d'usuariu nun esiste:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Nun pueden mentase IP:</strong> $1",
+ "notification-header-mention-success": "Unvióse la {{GENDER:$2|to}}mención de «<strong>$3</strong>».",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Unvióse una mención|Unviáronse $3 menciones}} que {{GENDER:$2|fixisti}} na páxina d'alderique de <strong>$4</strong>.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Mentasti a}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Una notificación|$3 notificaciones}} sobro menciones {{GENDER:$2|que fixisti}} na páxina d'alderique <strong>$4</strong>: {{PLURAL:$5|$5 nun s'unvió|$5 nun s'unviaron}}, {{PLURAL:$6|$6 unvióse|$6 unviáronse}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$1|Cambiáronse}} {{GENDER:$4|los tos}} permisos d'usuariu. Amestáronte a: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$1|Cambiáronse}} {{GENDER:$4|los tos}} permisos d'usuariu. Yá nun yes miembru de: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$1|Cambiáronse}} {{GENDER:$6|los tos}} permisos d'usuariu. Amestáronte a $2. Yá nun yes miembru de: $4.",
+ "notification-header-user-rights-expiry-change": "La data de caducidá de la {{GENDER:$4|to}} pertenencia {{PLURAL:$3|al siguiente grupu|a los siguientes grupos}} {{GENDER:$1|cambióse}}: $2.",
+ "notification-header-welcome": "¡{{GENDER:$2|Bienveníu|Bienvenida}} a {{SITENAME}}, $1! Préstanos que {{GENDER:$2|teas}} equí.",
+ "notification-welcome-linktext": "Bienveníu/a",
+ "notification-header-thank-you-1-edit": "Vienes de facer la {{GENDER:$2|to}} primera edición. ¡Gracies y {{GENDER:$2|bienveníu|bienvenida}}!",
+ "notification-header-thank-you-10-edit": "Vienes de facer la {{GENDER:$2|to}} décima edición. ¡Gracies y {{GENDER:$2|sigui}} col bon trabayu!",
+ "notification-header-thank-you-100-edit": "Vienes de facer la {{GENDER:$2|to}} centésima edición. ¡Munchísimes gracies!",
+ "notification-header-thank-you-1000-edit": "Vienes de facer la {{GENDER:$2|to}} milésima edición. ¡Munches gracies por ser {{GENDER:$2|un collaborador|una collaboradora}} tan grande!",
+ "notification-header-thank-you-10000-edit": "Vienes de facer la {{GENDER:$2|to}} diezmilésima edición. ¡Milenta gracies!",
+ "notification-header-thank-you-100000-edit": "Vienes de facer la {{GENDER:$2|to}} cienmilésima edición. ¡Munches gracies por ser {{GENDER:$2|un collaborador|una collaboradora}} tan ablucante!",
+ "notification-header-thank-you-1000000-edit": "Vienes de facer la {{GENDER:$2|to}} milllonésima edición. ¡Munches gracies por ser {{GENDER:$2|un collaborador|una collaboradora}} tan plasmante!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|La to}} edición",
"notification-link-text-view-edit": "Ver la edición",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|dexó}} un mensaxe na so [[User talk:$2#$3|páxina d'alderique]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|dexó}} un mensaxe na so páxina d'alderique en [[User talk:$2#$3|$4]].",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|dexó}} un mensaxe na so [[User talk:$2#$3|páxina d'alderique]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|dexó}} un mensaxe na so páxina d'alderique en «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "[[:$2]] {{GENDER:$1|enllazóse}} dende [[:$3]]. [[Special:WhatLinksHere/$2|Ver tolos enllaces a esta páxina]].",
- "notification-page-linked-flyout": "[[:$2]] {{GENDER:$1|enllazóse}} dende [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|comentó}} sobro \"[[$3|$2]]\" na páxina d'alderique \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|amestó}} l'asuntu nuevu \"$2\" en [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|unvió-y}} un mensaxe: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|comentó}} sobro \"[[$3#$2|$2]]\" na so páxina d'alderique",
- "notification-mention": "[[User:$1|$1]] fizo-y una {{GENDER:$1|mención}} nel alderique de $5 en «[[:$3#$2|$4]]».",
- "notification-mention-flyout": "$1 fizo-y una {{GENDER:$1|mención}} nel alderique de $5 en «[[:$3#$2|$4]]».",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|mentó-y}} na [[:$3|páxina d'alderique de $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|mentó-y}} na [[:$3|páxina d'alderique de $2]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|camudó}}]] los sos permisos d'usuariu. $2. [[Special:ListGroupRights|Más información]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|camudó}} los sos permisos d'usuariu. $2. [[Special:ListGroupRights|Más información]]",
- "notification-user-rights-add": "Agora ye miembru d'{{PLURAL:$2|esti grupu|estos grupos}}: $1",
- "notification-user-rights-remove": "Dexó de ser miembru d'{{PLURAL:$2|esti grupu|estos grupos}}: $1",
- "notification-new-user": "¡Dámoste la bienvenida a {{SITENAME}}, $1! Préstanos que teas equí.",
- "notification-reverted2": "[[User:$1|$1]] {{GENDER:$1|invertió}} {{PLURAL:$4|la so edición|les sos ediciones}} en [[:$2]] $3",
- "notification-reverted-flyout2": "$1 {{GENDER:$1|invertió}} {{PLURAL:$4|la so edición|les sos ediciones}} en $2 $3",
+ "notification-link-article-reminder": "Ver l'artículu",
+ "notification-header-reverted": "{{PLURAL:$4|La to edición {{GENDER:$2|invertióse}}|Les tos ediciones {{GENDER:$2|invertiéronse}}}}'n <strong>$3</strong>",
+ "notification-header-emailuser": "$1 {{GENDER:$2|unvióte}} un corréu electrónicu.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|dexó-y}} un mensaxe en {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|dexó}} un mensaxe na to páxina d'alderique.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|dexó}} un mensaxe na so páxina d'alderique en «$2».",
"notification-page-linked-email-subject": "Una páxina que creasti enllazóse'n {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 {{GENDER:$1|enllazóse}} dende $3",
"notification-reverted-email-subject2": "{{PLURAL:$3|Desfizose la so edición|Desficieronse les sos ediciones}} {{GENDER:$1|en}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "$1 {{GENDER:$1|desfizo}} {{PLURAL:$3|la so edición|les sos ediciones}} en $2",
- "notification-mention-email-subject": "$1 fizo-y una {{GENDER:$1|mención}} en {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 fizo-y una {{GENDER:$1|mención}} nel alderique de $4 en «$3».",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|mentó-y}} na páxina d'alderique de $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|fíxote}} una {{GENDER:$1|mención}} en {{SITENAME}}",
"notification-user-rights-email-subject": "Camudaron los sos permisos d'usuariu en {{SITENAME}}",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|camudó}} los sos permisos d'usuariu. $2",
- "echo-email-subject-default": "Nuevu avisu en {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "$1 {{PLURAL:$1|mes|meses}}",
+ "notification-timestamp-ago-years": "$1 {{PLURAL:$1|añu|años}}",
+ "notification-timestamp-today": "Güei",
+ "notification-timestamp-yesterday": "Ayeri",
+ "notification-inbox-filter-read": "Lleer",
+ "notification-inbox-filter-unread": "Non lleíes",
+ "notification-inbox-filter-all": "Toes",
"echo-email-body-default": "Tien un nuevu avisu en {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Tien un nuevu avisu",
- "echo-email-footer-default": "$2\n\nPa controlar los correos que-y unviamos, compruebe les sos preferencies:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Pa controlar los correos electrónicos que-y unviamos, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">compruebe les sos preferencies</a>.<br />\n$1",
+ "echo-email-footer-default-html": "Para controlar qué correos electrónicos t'unviamos, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">revisa les preferencies</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPa controlar qué correos t'unviamos, comprueba les preferencies:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Para controlar qué correos electrónicos {{GENDER:$1|t}}'unviamos, revisa les {{GENDER:$1|tos}} preferencies:",
+ "echo-email-html-footer-preference-link-text": "comprueba les {{GENDER:$1|tos}} preferencies",
+ "echo-email-html-footer-with-link": "Pa controlar qué mensaxes de corréu electrónicu {{GENDER:$2|t'unviamos}}, $1.",
"echo-notification-alert": "{{PLURAL:$1|($1) alerta|($1) alertes|100=(99+) alertes}}",
- "echo-notification-message": "{{PLURAL:$1|($1) mensaxe|($1) mensaxes|100=(99+) mensaxes}}",
+ "echo-notification-notice": "{{PLURAL:$1|Avisu ($1)|Avisos ($1)|100=Avisos (más de 100)}}",
"echo-notification-alert-text-only": "Alertes",
- "echo-notification-message-text-only": "Mensaxes",
+ "echo-notification-notice-text-only": "Avisos",
"echo-overlay-link": "Tolos avisos",
"echo-overlay-title": "<b>Avisos</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Avisu|Avisos}}</b> (amosando $1 de $2 ensin lleer)",
"echo-mark-all-as-read": "Marcar too como lleío",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|avisu marcáu como lleíu|avisos marcaos como lleíos}}",
+ "echo-mark-wiki-as-read": "Marcar toes como lleíes na wiki seleccionada: $1",
"echo-date-today": "Güei",
"echo-date-yesterday": "Ayeri",
"echo-load-more-error": "Hubo un error al descargar más resultaos.",
- "notification-edit-talk-page-bundle": "$1 y {{PLURAL:$4|otra persona|otres $3 persones}} {{GENDER:$1|dexaron}} un mensaxe na so [[User talk:$2|páxina d'alderique]].",
- "notification-page-linked-bundle": "$2 {{GENDER:$1|enllazóse}} dende $3 y $4 {{PLURAL:$5|páxina|páxines}} más. [[Special:WhatLinksHere/$2|Ver tolos enllaces a esta páxina]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 y {{PLURAL:$3|otra persona|otres $2 persones}} {{GENDER:$1|dexaron}} un mensaxe na so páxina d'alderique",
- "notification-page-linked-email-batch-bundle-body": "$2 {{GENDER:$1|enllazóse}} dende $3 y {{PLURAL:$5|otra páxina|otres $4 páxines}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Un mensaxe nuevu|$1 mensaxes nuevos|100=99+ mensaxes nuevos}} na <strong>{{GENDER:$3|to}} páxina d'alderique</strong>.",
"echo-email-batch-subject-daily": "Tien {{PLURAL:$2|un avisu nuevu|avisos nuevos}} en {{SITENAME}}",
"echo-email-batch-subject-weekly": "Tien {{PLURAL:$2|un avisu nuevu|avisos nuevos}} en {{SITENAME}} esta selmana",
"echo-email-batch-body-intro-daily": "Hola, $1:\nEsti ye un resume personal de la actividá de güei en {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Hola, $1:\nEsti ye un resume personal de la actividá selmanal en {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "Ver toles notificaciones",
- "echo-rev-deleted-text-view": "Esta revisión de páxina ta encaboxada",
- "apihelp-echomarkread-description": "Marcar les notificaciones como lleíes pal usuariu actual.",
- "apihelp-echomarkread-param-list": "Llista d'IDs de notificaciones pa marcar como lleíes.",
- "apihelp-echomarkread-param-all": "Si se seleiciona, marca toles notificaciones d'un usuariu como lleíes.",
- "apihelp-echomarkread-param-sections": "Llista de seiciones a marcar como lleíes.",
- "apihelp-echomarkread-example-1": "Marcar la notificación 8 como lleída.",
- "apihelp-echomarkread-example-2": "Marcar toles notificaciones como lleíes",
- "apihelp-echomarkseen-description": "Marcar les notificaciones como vistes pal usuariu actual.",
- "apihelp-echomarkseen-example-1": "Marcar los avisos de tolos tipos como lleíos",
- "apihelp-echomarkseen-param-type": "Tipu d'avisos pa marcar como lleíos: 'alert' (alerta), 'message' (mensaxe) o 'all' (toos).",
- "apihelp-query+notifications-description": "Recibir les notificaciones n'espera pal usuariu actual.",
- "apihelp-query+notifications-param-prop": "Detalles a solicitar.",
- "apihelp-query+notifications-param-sections": "Les secciones d'avisu a consultar (esto ye, dalguna combinación de 'alert' y 'message').",
- "apihelp-query+notifications-param-groupbysection": "Si hai qu'agrupar los resultaos por seición. Cada seición recíbese por separao si se configura.",
- "apihelp-query+notifications-param-format": "Si s'especifica, les notificaciones devolveránse con esti formatu.",
- "apihelp-query+notifications-param-limit": "El máximu númberu de notificaciones a devolver.",
- "apihelp-query+notifications-param-index": "Si s'especifica, devolveráse una llista ordenada d'identificadores de notificación.",
- "apihelp-query+notifications-param-alertcontinue": "Cando tean disponibles más resultaos d'alerta, usa esto pa siguir.",
- "apihelp-query+notifications-param-alertunreadfirst": "Si hai qu'amosar primero los avisos de mensaxes sin lleer.",
- "apihelp-query+notifications-param-messagecontinue": "Cando tean disponibles más resultaos de mensaxes, usa esto pa siguir.",
- "apihelp-query+notifications-param-messageunreadfirst": "Si hai qu'amosar primero los avisos d'alertes sin lleer.",
- "apihelp-query+notifications-example-1": "Llista d'avisos",
- "apihelp-query+notifications-example-2": "Llista d'avisos, agrupaos por seición, incluyendo contadores"
+ "notification-header-foreign-alert": "Más alertes {{PLURAL:$5|d'otra wiki|de $5 wikis más}}",
+ "notification-header-foreign-notice": "Más avisos {{PLURAL:$5|d'otra wiki|de $5 wikis más}}",
+ "notification-header-foreign-all": "Más notificaciones {{PLURAL:$5|d'otra wiki|de $5 wikis más}}"
}
diff --git a/Echo/i18n/atj.json b/Echo/i18n/atj.json
new file mode 100644
index 00000000..bddee72e
--- /dev/null
+++ b/Echo/i18n/atj.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dereckson",
+ "Benoit Rochon",
+ "Ninmeka"
+ ]
+ },
+ "echo-pref-email": "Matcetcicihikan",
+ "echo-category-title-article-linked": "Masinhikan {{PLURAL:$1|tapitik|tapitiki}}",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Kir}} ki mikawasimikon",
+ "notification-link-text-expand-all": "Otamirota",
+ "notification-link-text-view-page": "Ocki matcecikinakanik",
+ "notification-welcome-linktext": "Miro peicak",
+ "notification-timestamp-today": "Ke kicikak",
+ "notification-inbox-filter-read": "Tapwatcike",
+ "notification-inbox-filter-all": "Kaskina",
+ "echo-date-today": "Ke kicikak"
+}
diff --git a/Echo/i18n/awa.json b/Echo/i18n/awa.json
index f69f2732..b1008daf 100644
--- a/Echo/i18n/awa.json
+++ b/Echo/i18n/awa.json
@@ -5,12 +5,10 @@
]
},
"notifications": "अधिसूचना",
- "tooltip-pt-notifications": "आप कय अधिसूचना",
"echo-email-subject-default": "{{SITENAME}} पे नँवा अधिसूचना",
"echo-email-body-default": "आप कय लिए {{SITENAME}} पे नँवा अधिसूचना है:\n\n$1",
"echo-email-batch-body-default": "आप कय लिए नँवा अधिसूचना है।",
"echo-email-footer-default": "$2\n\nहमारी ओर से भेजे जाने वाले ईमेलों पर नियंत्रण करने के लिये कृपया अपनी पसन्द देखिए:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "हमारी ओर से भेजे जाने वाले ईमेलों पर नियंत्रण करने के लिये <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">अपनी पसन्द देखिए</a>।<br />\n\n$1",
"echo-notification-alert-text-only": "एलर्ट",
"echo-notification-message-text-only": "सनेशा",
"echo-overlay-link": "कुल अधिसूचना",
diff --git a/Echo/i18n/ay.json b/Echo/i18n/ay.json
index 18e20091..b1df8787 100644
--- a/Echo/i18n/ay.json
+++ b/Echo/i18n/ay.json
@@ -21,7 +21,6 @@
"echo-pref-email-frequency-weekly": "Resumen semanal de notificaciones",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Texto sin formato",
- "echo-pref-notify-show-link": "Mostrar notificaciones en mi barra de herramientas",
"echo-pref-new-message-indicator": "Mostrar el indicador de mensajes en la barra de herramientas",
"echo-learn-more": "Más información",
"echo-new-messages": "Tienes mensajes nuevos",
diff --git a/Echo/i18n/az.json b/Echo/i18n/az.json
index 8855a5eb..faf4651c 100644
--- a/Echo/i18n/az.json
+++ b/Echo/i18n/az.json
@@ -4,7 +4,8 @@
"Interfase",
"Khan27",
"Wertuose",
- "Dağlı95"
+ "Dağlı95",
+ "Serkanland"
]
},
"echo-desc": "Bildiriş sistemi",
@@ -24,7 +25,7 @@
"echo-pref-email-frequency-weekly": "Həftəlik bildirişlər",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Sadə mətn",
- "echo-pref-notify-show-link": "Dəyişiklikləri mənim alətlər panelimdə göstər",
+ "echo-pref-cross-wiki-notifications": "Digər vikipediyalardan bildirişləri göstər",
"echo-pref-new-message-indicator": "Müzakirə səhifəsindəki mesaj indikatorunu alətlər panelimdə göstər",
"echo-learn-more": "Daha ətraflı",
"echo-new-messages": "Yeni mesajlarınız var",
@@ -32,41 +33,47 @@
"echo-category-title-article-linked": "Səhifəyə {{PLURAL:$1|keçid|keçidlər}}",
"echo-category-title-reverted": "Redaktələrin {{PLURAL:$1|1=ləğv|ləğvi}}",
"notifications": "Bildirişlər",
- "tooltip-pt-notifications": "Sizin bildirişləriniz",
+ "tooltip-pt-notifications-alert": "Xəbərdarlıqlarınız",
+ "tooltip-pt-notifications-notice": "Bildirişləriniz",
"echo-specialpage": "Bildirişlər",
+ "echo-specialpage-section-markread": "Qrupu oxunmuş kimi işarələ",
+ "echo-specialpage-pagefilters-title": "Son hərəkətlər",
+ "echo-specialpage-pagefilters-subtitle": "Oxunmamış bildirişlər olan səhifələr",
"echo-none": "Sizə bildiriş yoxdur",
"echo-more-info": "Daha ətraflı",
"echo-feedback": "Rəy",
+ "echo-notification-placeholder-filters": "Bu kriteriyaya uyğun bildirişlər yoxdur.",
+ "echo-notification-markasread-tooltip": "Oxunulmuş kimi işarələ",
+ "echo-notification-more-options-tooltip": "Digər parametrlər",
+ "notification-link-text-expand-all": "Aç",
+ "notification-link-text-collapse-all": "Bağla",
"notification-link-text-view-message": "Məktuba bax",
"notification-link-text-view-mention": "Qeydə bax",
- "notification-link-text-view-changes": "Dəyişiklərə bax",
+ "notification-link-text-view-changes": "Dəyişikliklərə bax",
"notification-link-text-view-page": "Səhifəyə bax",
+ "notification-header-edit-user-talk": "$1 <strong>müzakirə {{GENDER:$3|səhifənizə}}</strong> bir mesaj {{GENDER:$2|qoyub}}.",
+ "notification-header-page-linked": "<strong>$4</strong> səhifəsindən <strong>$3</strong> səhifəsinə keçid verildi.",
+ "notification-bundle-header-page-linked": "{{PLURAL:$5||$5 səhifə|100=99+ səhifə}}dən <strong>$3</strong> səhifəsinə keçid verildi.",
+ "notification-link-text-what-links-here": "Bu səhifəyə olan bütün keçidlər",
+ "notification-header-welcome": "{{SITENAME}} saytına {{GENDER:$2|xoş gəldiniz}}, $1! Sizi burada görməyimizə çox şadıq.",
"notification-link-text-view-edit": "Redaktəyə bax",
- "notification-edit-talk-page2": "[[User:$1|$1]] sizin [[User talk:$2#$3|müzakirə səhifənizdə]] məktub {{GENDER:$1|qoyub}} .",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] sizin müzakirə səhifənizdə \"[[User talk:$2#$3|$4]]\" başlıqlı mesaj {{GENDER:$1|qoyub}}.",
- "notification-edit-talk-page-flyout2": "Sizin [[User talk:$2#$3|müzakirə səhifənizdə]] mesaj $1 {{GENDER:$1|qoyub}}.",
- "notification-page-linked": "[[:$2]] səhifəsinə [[:$3]] səhifəsindən {{GENDER:$1|keçid verilib}}. [[Special:WhatLinksHere/$2|Bu səhifəyə olan bütün keçidlərə bax]].",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] [[$3]] səhifəsində yeni \"$2\" başlıqlı mövzu {{GENDER:$1|əlavə edib|əlavə edib}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] tərəfindən sizə mesaj {{GENDER:$1|göndərilib|göndərilib}}: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$2|$2]] sizin müzakirə səhifənizindəki «[[$4#$3|$3]]» başlıqlı mövzuya {{GENDER:$1|fikir bildirdi|fikir bildirdi}}.",
- "notification-mention": "[[User:$1|$1]] sizin adınızı $5 danışıq səhifəsinin \"[[:$3#$2|$4]]\" bölməsində $1 qeyd edib.",
- "notification-mention-flyout": "[[User:$1|$1]] sizin adınızı $5 danışıq səhifəsinin \"[[:$3#$2|$4]]\" bölməsində $1 qeyd edib.",
- "notification-mention-nosection": "[[User:$1|$1]] sizin adınızı [[:$3|müzakirə səhifəsind $2]] qeyd edib.",
- "notification-new-user": "'''$1''' {{SITENAME}} saytına xoş gəlmisiniz! Sizi burada görməyimizə çox şadıq. Uğurlar!",
"notification-edit-talk-page-email-subject2": "İstifadəçi $1 \"{{SITENAME}}\" saytındakı müzakirə səhifənizdə sizə mesaj yazıb",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|İstifadəçi}} sizin müzakirə səhifənizdə məktub $1 {{GENDER:$1|yazıb}}",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|İstifadəçi}} sizin müzakirə səhifənizdə «$2» bölməsində məktub $1 {{GENDER:$1|yazıb}}",
"notification-mention-email-subject": "{{GENDER:$1|İstifadəçi}} sizin adınızı «{{SITENAME}}» səhifəsində $1 {{GENDER:$1|qeyd edib}}",
- "notification-mention-email-batch-body": "Sizin adınız $4 danışıq səhifəsinin $3 bölməsində $1 {{GENDER:$1|qeyd edilib}}",
- "notification-mention-nosection-email-batch-body": "Sizin adınız $2 danışıq səhifəsinin $1 {{GENDER:$1|qeyd edilib}}",
- "echo-email-subject-default": "«{{SITENAME}}» saytında yeni bildiriş var",
+ "notification-timestamp-today": "Bu gün",
+ "notification-inbox-filter-read": "Oxunmuş",
+ "notification-inbox-filter-unread": "Oxunmamış",
+ "notification-inbox-filter-all": "Hamısı",
"echo-email-body-default": "Sizə {{SITENAME}} səhifəsində yeni bildiriş var :\n\n$1",
- "echo-email-batch-body-default": "Sizə yeni bildiriş var",
+ "echo-notification-alert": "{{PLURAL:$1|Xəbərdarlıq ($1)|Xəbərdarlıqlar ($1)|100=Xəbərdarlıqlar (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Bildiri. ($1)|Bildirişlər ($1)|100=Bildirişlər (99+)}}",
+ "echo-notification-alert-text-only": "Xəbərdarlıqlar",
+ "echo-notification-notice-text-only": "Bildirişlər",
"echo-overlay-link": "Bütün bildirişlər",
"echo-overlay-title": "<b>Bildirişlər</b>",
"echo-overlay-title-overflow": "<b>Bildirişlər</b> $2 {{PLURAL|$2|oxunmamış|oxunmamışlar}})dan $1 ({{PLURAL|$1|göstərilib|göstəriliblər}}",
"echo-mark-all-as-read": "Hamısını oxunmuş kimi qeyd et",
- "echo-date-today": "Bugün",
+ "echo-date-today": "Bu gün",
"echo-date-yesterday": "Dünən",
"echo-email-batch-subject-daily": "Sizin {{SITENAME}}-da {{PLURAL:$2|yeni bildiriş|yeni bildirişləriniz|}} var",
"echo-email-batch-subject-weekly": "Sizin bu həftə {{SITENAME}}-da {{PLURAL:$2|yeni bildiriş|yeni bildirişləriniz|}} var",
diff --git a/Echo/i18n/azb.json b/Echo/i18n/azb.json
index 0ad234d6..7b3a6ba3 100644
--- a/Echo/i18n/azb.json
+++ b/Echo/i18n/azb.json
@@ -5,7 +5,8 @@
"Amir a57",
"Koroğlu",
"Ebrahimi-amir",
- "Alp Er Tunqa"
+ "Alp Er Tunqa",
+ "Ilğım"
]
},
"echo-desc": "بیلدیریش سیستِمی",
@@ -24,30 +25,36 @@
"echo-pref-email-frequency-weekly": "هفته‌لیک بیلدیری‌لرین بیر قیساسی",
"echo-pref-email-format-html": "اچ‌تی‌ام‌ال",
"echo-pref-email-format-plain-text": "ساده متن",
- "echo-new-messages": "یئنی پیام‌لارینیز واردیر",
- "echo-category-title-edit-user-talk": "دانیشیق صفحه‌سی پیامی",
+ "echo-new-messages": "یئنی مساژلارینیز واردیر",
+ "echo-category-title-edit-user-talk": "دانیشیق صفحه‌سی {{PLURAL:$1|مساژی|مساژلاری}}",
"echo-category-title-article-linked": "صفحه {{PLURAL:$1|باغلانتیسی|باغلانتی‌لاری}}",
"echo-category-title-reverted": "دییشدیرمه قایتاریشی",
- "echo-no-agent": "[هئچ کیمسه]",
- "echo-no-title": "[هئچ صحیفه]",
+ "echo-category-title-emailuser": "{{PLURAL:$1|آیری ایشلدندن ایمئیل|آیری ایشلدنلردن ایمئیل}}",
"echo-error-no-formatter": "بیلدیری اوچون بیر فورمت تعریفی یوخدور",
"notifications": "بیلدیریلر",
+ "tooltip-pt-notifications-alert": "سیزین {{GENDER:|بیلدیریشلرینیز}}",
"echo-specialpage": "بیلدیری‌لر",
"echo-anon": "بیلدیریلری آلماق اوچون، [$1 بیر حساب یارادین] یادا [$2 گیریش ائدین].",
"echo-none": "سیزین بیلدیرینیز یوخدور.",
"echo-more-info": "آرتیقراق بیلگی",
- "echo-feedback": "دؤنوت",
- "notification-new-user": "{{SITENAME}}-ه خوش گلمیسینیز، $1!",
- "notification-reverted2": "سیزین دییشدیرمه‌لرینیز [[:$2]]ده [[User:$1|$1]] الی ایله {{PLURAL:$4|قایتار|قایتار}}یلدی. $3",
- "echo-email-subject-default": "{{SITENAME}}-ده یئنی بیلدیری",
+ "echo-feedback": "فیدبک",
+ "notification-header-edit-user-talk-with-section": "$1 <strong>{{GENDER:$3|سیزین}} دانیشیق صفحه‌نیزین \"</strong>$4\"<strong>-ده </strong> بیر مساژ {{GENDER:$2|یازیبدیر}}.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|سیزه}} <strong>$4</strong>-ده {{GENDER:$2|ایشاره ائتدی}}.",
+ "notification-header-user-rights-add-only": "ایشلدن حاقلارینیز دَییشیلیبدیر. بۇنلارا آرتیریلمیشسینیز: $2.",
+ "notification-header-user-rights-remove-only": "ایشلدن حاقلارینیز دَییشیلیبدیر. بۇنلاردا آرتیق عۆضو دئییلسینیز: $2.",
+ "notification-header-user-rights-add-and-remove": "ایشلدن حاقلارینیز دَییشیلیبدیر. بۇنلارا آرتیریلمیشسینیز: $2. بۇنلاردا آرتیق عۆضو دئییلسینیز: $4.",
+ "notification-header-reverted": "<strong>$3</strong> صفحه‌سینده {{PLURAL:$4|ائتدیگینیز دییشیک‌لیک|ائتدیگینیز دییشیک‌لیک‌لر}} {{GENDER:$2|قایتاریلیبدیر}}.",
"echo-email-body-default": "سیزین {{SITENAME}}-ده یئنی بیلدیرینیز واردیر:\n\n$1",
"echo-email-footer-default": "$2\n\nسیزه هانکی ایمیل‌لرین گله بیله‌جگینی دَییشمگه، باخین:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-notification-alert-text-only": "بیلدیری‌لر",
+ "echo-notification-notice-text-only": "بیلدیریلر",
"echo-overlay-link": "بوتون بیلدیریلر",
"echo-overlay-title": "منیم بیلدیریلریم",
"echo-overlay-title-overflow": "منیم بیلدیریلریم ($2 اوخونمامیشدان $1-ی گؤستریلیر)",
"echo-date-today": "بوگون",
"echo-date-yesterday": "دونن",
"echo-load-more-error": "آرتیق نتیجه‌لری گتیرنده بیر خطا قاباغا گلدی.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|بیر یئنی مساژ|$1 یئنی مساژ|100=99+ یئنی مساژ}} <strong>{{GENDER:$3|سیزین}} دانیشیق صفحه‌نیزده</strong> دۇرور.",
"echo-email-batch-subject-daily": "سیزین بوگون $1 {{PLURAL:$2|بیلدیرینیز}} واردیر",
"echo-email-batch-subject-weekly": "سیزین بو هفته $1 {{PLURAL:$2|بیلدیرینیز}} واردیر"
}
diff --git a/Echo/i18n/ba.json b/Echo/i18n/ba.json
index 6067fb7f..96bd9ee8 100644
--- a/Echo/i18n/ba.json
+++ b/Echo/i18n/ba.json
@@ -1,13 +1,145 @@
{
"@metadata": {
"authors": [
- "Ләйсән"
+ "Ләйсән",
+ "Sagan",
+ "Азат Хәлилов",
+ "Танзиля Кутлугильдина",
+ "Вильданова Гюзель",
+ "Айсар",
+ "Янмурза Баки",
+ "Lizalizaufa",
+ "Банат Валеева-Яубасарова",
+ "Лилиә"
]
},
+ "echo-desc": "Ҡатнашыусыларҙың ваҡиғалар һәм хәбәрҙәр тураһында белдереүҙәр системаһы",
"prefs-echo": "Белдереүҙәр",
+ "prefs-emailsettings": "Электрон почта көйләүҙәре",
+ "prefs-displaynotifications": "Күренеш көйләүҙәре",
+ "prefs-echosubscriptions": "Миңә был ваҡиғалар тураһында хәбәр итергә",
+ "prefs-echocrosswiki": "Кросс-вики белдереүҙәре",
+ "prefs-newmessageindicator": "яңы хаттар тураһында белдереү",
+ "echo-pref-send-me": "миңә ебәрергә",
+ "echo-pref-send-to": "Ебәрергә",
+ "echo-pref-email-format": "Хаттарҙың ҙурлығы",
+ "echo-pref-web": "Веб",
+ "echo-pref-email": "Электрон почта адресы",
+ "echo-pref-email-frequency-never": "Электрон почта аша миңә белдереүҙәр ебәрмәҫкә",
+ "echo-pref-email-frequency-immediately": "килеү ваҡытынса айырым белдереүҙәр",
+ "echo-pref-email-frequency-daily": "көндәлек белдереүҙәр хаҡында мәғлүмәт",
+ "echo-pref-email-frequency-weekly": "аҙналыҡ белдереүҙәр хаҡында мәғлүмәт",
+ "echo-pref-email-format-html": "HTML",
+ "echo-pref-email-format-plain-text": "ғәҙәти яҙма",
+ "echo-pref-cross-wiki-notifications": "Башҡа викилар белдереүҙәрен күрһәтергә",
+ "echo-pref-new-message-indicator": "Фекер алышыу сәхифәмдә хәбәрҙәр тураһында белдереүҙе минең ҡоралдар панелендә күрһәтергә",
+ "echo-pref-beta-feature-cross-wiki-message": "Киңәйтелгән белдереүҙәр",
+ "echo-pref-beta-feature-cross-wiki-description": "Белдереүҙәрҙе ябайыраҡ ҡарарға һәм ойошторорға ярҙам итә. Башҡа викилар хәбәрҙәрен күреү мөмкинлеген биргән кросс-вики белдереүҙәрҙе үҙ эсенә ала. (Был вики-проектта шундай хәбәрҙәр алыр өсөн, тейешле бета-функцияны ҡабыҙыр кәрәк.)",
+ "echo-learn-more": "Күберәк белергә",
+ "echo-log": "һәр кем аңларлыҡ журнал",
+ "echo-new-messages": "Һеҙгә яңы хәбәрҙәр бар",
+ "echo-category-title-edit-user-talk": "фекер алышыу сәхифәмдә {{PLURAL:$1|1=хәбәр|хәбәрҙәр}}",
+ "echo-category-title-article-linked": "$1 {{PLURAL:$1|һылтанма}}",
+ "echo-category-title-reverted": "үҙгәртеүҙәрҙе {{PLURAL:$1|1=кире ҡағыу|кире ҡағыуҙар}}",
+ "echo-category-title-mention": "{{PLURAL:$1|1=телгә алыу|телгә алыуҙар}}",
+ "echo-category-title-other": "{{PLURAL:$1|1=башҡа|башҡалар}}",
+ "echo-category-title-system": "{{PLURAL:$1|Системалы}}",
+ "echo-category-title-user-rights": "Ҡулланыусы хоҡуҡтарын {{PLURAL:$1|үҙгәртеү}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Башҡа ҡатнашыусыларҙан}} электрон хат",
+ "echo-pref-tooltip-edit-user-talk": "Башҡалар хәбәр ебәргәндә йәки минең фекер алышыу битендә яҙғанда, миңә хәбәр итергә.",
+ "echo-pref-tooltip-article-linked": "Мин эшләгән биттәргә башҡа биттән кемдер һылтанғанда, миңә хәбәр итергә.",
+ "echo-pref-tooltip-reverted": "Мин төҙәткәнде башҡалар кире ҡайтарған осраҡта миңә хәбәр итергә.",
+ "echo-pref-tooltip-mention": "Минең ҡатнашыусы битенә башҡалар һылтанған осраҡта миңә хәбәр итергә.",
+ "echo-pref-tooltip-user-rights": "Минең ҡатнашыусы хоҡуҡтарын үҙгәрткән осраҡта миңә хәбәр итергә.",
+ "echo-pref-tooltip-emailuser": "Башҡалар миңә электрон хат ебәргән осраҡта миңә хәбәр итергә.",
+ "echo-error-no-formatter": "Форматлау белдереү ебәреү өсөн билдәләнмәгән.",
"notifications": "Белдереүҙәр",
- "tooltip-pt-notifications": "Һеҙҙең белдереүҙәр",
- "echo-specialpage": "Минең белдереүҙәр",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Һеҙҙең}} иҫкәртеүҙәр",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Һеҙҙең}} хәбәрҙәр",
+ "echo-displaynotificationsconfiguration": "Белдереү көйләүҙәрен күрһәтергә",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Категориялар буйынса белдереүҙәр",
+ "echo-specialpage": "Белдереүҙәр",
+ "echo-anon": "Белдереү алыу өсөн, [$1 иҫәп яҙмаһы булдырығыҙ] йәки [$2 танылығыҙ].",
+ "echo-none": "Һеҙ белдереүҙәр алманығыҙ.",
+ "echo-more-info": "Ентекләберәк",
+ "echo-feedback": "Кире бәйләнеш",
+ "echo-api-failure": "Белдереү алып булманы.",
+ "echo-api-failure-cross-wiki": "Юйылған доменға инеү тыйылды.",
+ "echo-notification-placeholder": "Белдереү юҡ.",
+ "echo-notification-loginrequired": "Белдереүҙе ҡарау өсөн һеҙ танылырға тейеш.",
+ "echo-notification-popup-loginrequired": "Белдереүҙе ҡарау өсөн танылығыҙ.",
+ "echo-notification-markasread": "Уҡылған тип билдәләргә",
+ "echo-notification-markasunread": "Уҡылмағаған тип билдәләргә",
+ "notification-link-text-expand-all": "Асыу",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 белдереүҙе}} ҡарарға",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 белдереүҙе}} күрһәтергә",
+ "notification-link-text-collapse-all": "Ҡапыл ябылыу",
+ "notification-link-text-view-message": "Яңы хәбәрҙәр",
+ "notification-link-text-view-mention": "Белдереүҙе ҡарарға",
+ "notification-link-text-view-changes": "Үҙгәртеүҙәрҙе {{GENDER:$1|ҡарарға}}",
+ "notification-link-text-view-page": "Битте ҡарау",
+ "notification-header-edit-user-talk": "$1 '''{{GENDER:$3|һеҙҙең}} фекер алышыу битендә''' хәбәр {{GENDER:$2|ҡалдырҙы}}.",
+ "notification-header-edit-user-talk-with-section": "$1 '''{{GENDER:$3|Һеҙҙең}} фекер алашыу битендә''' \"'''$4'''\" хәбәр {{GENDER:$2|ҡалдырҙы}}.",
+ "notification-header-page-linked": "<strong>$4</strong> битенән <strong>$3</strong> битенә һылтанма яһалды.",
+ "notification-bundle-header-page-linked": "Был биттән {{PLURAL:$5|$5 башҡа биттән|100=99+ башҡа биттән}} ошонда <strong>$3</strong> һылтанма эшләнеләр.",
+ "notification-link-text-what-links-here": "Бөтә һылтанмаларҙы был биткә",
+ "notification-header-mention-other": "$1 {{GENDER:$3|һеҙҙе}} <strong>$4</strong> битендә «<strong>$5</strong>» бүлегендә {{GENDER:$2|телгә}} алды.",
+ "notification-header-mention-other-nosection": "$1 һеҙҙе{{GENDER:$2||фекерләшеү}} {{GENDER:$3|битендә}} телгә алды «$4».",
+ "notification-header-mention-user-talkpage-v2": "$1 һеҙҙе{{GENDER:$2||фекерләшеү}} {{GENDER:$3|битендә}} телгә<strong>алды {{GENDER:$5|$4}}</strong> бүлектә «<strong>$6</strong>».",
+ "notification-header-mention-user-talkpage-nosection": "$1 һеҙҙе{{GENDER:$2||фекерләшеү}} {{GENDER:$3|битендә}} телгә<strong>алды {{GENDER:$5|$4}}</strong> бүлегендә.",
+ "notification-header-mention-agent-talkpage": "$1 һеҙҙе{{GENDER:$2||үҙенең}} {{GENDER:$3}} фекерләшеү <strong>{{GENDER:$2|битендә}} </strong> бүлегендә «<strong>$4</strong>» телгә алды.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 һеҙҙе{{GENDER:$2||үҙенең}} {{GENDER:$3|вас}} фекерләшеү <strong>{{GENDER:$2|битендә}} телгә алды</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2||}} {{GENDER:$3|һеҙҙе}} «<strong>$4</strong>» фекерләшеү битендәге «<strong>$5</strong>» бүлегендә телгә алды.",
+ "notification-header-mention-article-talkpage-nosection": "$1 һеҙҙе{{GENDER:$2||фекерләшеү}} {{GENDER:$3|битендә}} телгә алды «$4».",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Һеҙҙең}} ҡатнашыусы хоҡуғығыҙ үҙгәртелде {{GENDER:$1|изменены}}. Һеҙ төркөмгә өҫтәлдегеҙ{{GENDER:$4|}}: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Һеҙҙең}} ҡатнашыусы хоҡуғығыҙ {{GENDER:$1|үҙгәртелде}}. $2 -се группаға башҡаса инмәйһегеҙ.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Һеҙҙең}} ҡатнашыусы хоҡуҡтар {{GENDER:$1|үҙгәртелде}}. Һеҙ $2 -гә өҫтәлгән инегеҙ. $4 -кә башҡаса инмәйһегеҙ.",
+ "notification-header-welcome": " $1, {{SITENAME}} сайтҡа {{GENDER:$2|рәхим итегеҙ}}! {{GENDER:$2|Һеҙҙе}} бында сәләмләүебеҙгә шатбыҙ.",
+ "notification-welcome-linktext": "Рәхим итегеҙ!",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Һеҙ}} яңы ғына {{GENDER:$2|үҙегеҙҙең}} беренсе үҙгәртеүегеҙҙе эшләнегеҙ. Хеҙмәтегеҙ өсөн {{GENDER:$2|һеҙгә}} ҙур рәхмәт, һәм рәхим итегеҙ!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Һеҙ}} яңы ғына {{GENDER:$2|үҙегеҙҙең}} унынсы үҙгәртеү эшләнегеҙ. Хеҙмәтегеҙ өсөн {{GENDER:$2|һеҙ}} ҙур рәхмәт, артабан да шулай дауам итегеҙ!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Һеҙ}} яңы ғына {{GENDER:$2|үҙегеҙҙең}} йөҙөнсө үҙгәртеү эшләнегеҙ. Хеҙмәтегеҙ өсөн ҙур рәхмәт!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Һеҙ}} яңы ғына {{GENDER:$2|үҙегеҙҙең}} меңенсе үҙгәртеү эшләнегеҙ; ҙур ҡушымтаға {{GENDER:$2|һеҙгә}} рәхмәт!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Һеҙ}} яңы ғына {{GENDER:$2|үҙегеҙҙең}} ун меңенсе үҙгәртеү эшләнегеҙ. Хеҙмәтегеҙ өсөн {{GENDER:$2|һеҙгә}} ҙур рәхмәт!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Һеҙ}} яңы ғына {{GENDER:$2|үҙегеҙҙең}} йөҙ меңенсе үҙгәртеү эшләнегеҙ; ҙур ҡушымтаға {{GENDER:$2|һеҙгә}} ғәжәп ҙур һөҙөмтәгеҙгә рәхмәт!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Һеҙ}} яңы ғына {{GENDER:$2|үҙегеҙҙең}} миллион үҙгәртеү эшләнегеҙ; иҫ китәрлек ҙур ҡушымтаға {{GENDER:$2|һеҙгә}} рәхмәт!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Һеҙҙең}} үҙгәртеү",
+ "notification-link-text-view-edit": "Үҙгәртеүҙе ҡарарға",
+ "notification-header-reverted": "{{PLURAL:$4|1=Һеҙҙең}} <strong>$3</strong> битендәге төҙәтмә {{GENDER:$2|{{PLURAL:$4|кире ҡағылды}}}}.",
+ "notification-header-emailuser": "$1{{GENDER:$2|ебәргән}} һеҙгә электрон почта аша ебәрелгән.",
+ "notification-edit-talk-page-email-subject2": "{{GENDER:$1|Ҡатнашыусы}} $1 «{{SITENAME}}» сайтында һеҙгә хәбәр ҡалдырҙы.",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|һулда}} һеҙҙең менән әңгәмәнең \"$2\" битендәге хәбәр.",
+ "notification-page-linked-email-subject": "Һеҙ төҙөгән биткә «{{SITENAME}}» сайтында һылтанма яһалды",
+ "notification-reverted-email-subject2": "«{{SITENAME}}» Сайттағы {{PLURAL:$3|1=һеҙҙең үҙгәртеүҙәрҙе}} {{GENDER:$1|кемдер}} кире алды.",
+ "notification-mention-email-subject": "«{{SITENAME}}» сайтында {{GENDER:$2|һеҙҙе}} $1 телгә алды {{GENDER:$1}}",
+ "notification-user-rights-email-subject": "Һеҙҙең хоҡуҡтарығыҙ сайтта «{{SITENAME}}» үҙгәртелде",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|Системалы}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 мин}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1сәғ}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 көн}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 ай}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1йыл}}",
+ "notification-timestamp-today": "Бөгөн",
+ "notification-timestamp-yesterday": "Кисә",
+ "notification-inbox-filter-read": "Уҡыу",
+ "notification-inbox-filter-unread": "Уҡылмағандар",
+ "notification-inbox-filter-all": "Барыһы",
+ "echo-email-body-default": "Һеҙҙең сайтта «{{SITENAME}}» яңы белдереү бар:\n\n$1",
+ "echo-email-footer-default": "$2\n\nҺеҙҙең эл. почтаға ниндәй хәбәр ебәрелгәнен ҡарап барыр өсөн, үҙегеҙҙең шәхси көйләүҙәрегеҙҙе тикшерегеҙ:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-notification-alert": "{{PLURAL:$1|Хәбәр ($1)|Хәбәрҙәр ($1)|100=Хәбәрҙәр (99+)}}",
+ "echo-notification-alert-text-only": "Иҫкәртеүҙәр",
"echo-overlay-link": "Бөтә белдереүҙәр",
- "echo-overlay-title": "Минең белдереүҙәр"
+ "echo-overlay-title": "<b>Белдереүҙәр</b>",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Белдереүҙәр}}</b> ({{PLURAL:$1|күрһәтелгән|күрһәтелгәндәр}} $1 $2-нән {{PLURAL:$2|уҡылмағанды|уҡылмағандарҙы}})",
+ "echo-mark-all-as-read": "Барыһын да уҡылған тип билдәләргә",
+ "echo-date-today": "Бөгөн",
+ "echo-date-yesterday": "Кисә",
+ "echo-load-more-error": "Өҫтәлмә яңылыҡтар алғанда хата сыҡты",
+ "notification-bundle-header-edit-user-talk-v2": "$1 {{PLURAL:$1|яңы хәбәр|100=99+ яңы хәбәр}} һеҙҙең <strong>{{GENDER:$3|фекерләшеү}} битендә</strong>.",
+ "echo-email-batch-subject-daily": "Проектта «{{SITENAME}}» һеҙ {{PLURAL:$2|$2 яңы белдереү|$2 яңы белдереүҙәр|$2 яңы белдереүҙәрҙең|1=яңы белдереү}} алдығыҙ",
+ "echo-email-batch-subject-weekly": "Проектта «{{SITENAME}}» был аҙнала {{PLURAL:$2|$2 яңы белдереү|$2 яңы белдереүҙәр|$2 яңы белдереүҙәрҙең|1=яңы белдереү}} алдығыҙ",
+ "echo-email-batch-body-intro-daily": "Сәләм, $1!\nБына һеҙҙең бөғөнғө эшмәкәрлегегеҙгә күҙәтеү {{SITENAME}}.",
+ "echo-email-batch-body-intro-weekly": "Сәләм, $1!\nБына һеҙгә ҡыҫҡаса аҙналыҡ эшмәкәрлеккә күҙәтеү {{SITENAME}}.",
+ "echo-email-batch-link-text-view-all-notifications": "Бөтә белдереүҙәрҙе ҡарарға",
+ "notification-header-foreign-alert": "{{PLURAL:$5|Башҡа викинан|$5 Башҡа викиларҙан}} белдереүҙәр бар"
}
diff --git a/Echo/i18n/be-tarask.json b/Echo/i18n/be-tarask.json
index a976a994..e0fa1704 100644
--- a/Echo/i18n/be-tarask.json
+++ b/Echo/i18n/be-tarask.json
@@ -4,7 +4,8 @@
"Base",
"Renessaince",
"Wizardist",
- "Red Winged Duck"
+ "Red Winged Duck",
+ "Macofe"
]
},
"echo-desc": "Сыстэма апавяшчэньня ўдзельнікаў пра падзеі і паведамленьні",
@@ -12,7 +13,9 @@
"prefs-emailsettings": "Налады e-mail",
"prefs-displaynotifications": "Налады паказу",
"prefs-echosubscriptions": "Паведамляць мне пра гэтыя падзеі",
+ "prefs-echocrosswiki": "Міжвікі-апавяшчэньні",
"prefs-newmessageindicator": "Індыкатар новых паведамленьняў",
+ "prefs-blocknotificationslist": "Ігнаруемыя ўдзельнікі",
"echo-pref-send-me": "Даслаць мне:",
"echo-pref-send-to": "Даслаць да:",
"echo-pref-email-format": "Фармат e-mail:",
@@ -24,72 +27,133 @@
"echo-pref-email-frequency-weekly": "Штотыднёвая зборка абвестак",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Просты тэкст",
+ "echo-pref-cross-wiki-notifications": "Паказваць апавяшчэньні зь іншых вікаў",
+ "echo-pref-notifications-blacklist": "Не паказваць паведамленьні ад гэтых удзельнікаў. ([[mw:Help:Notifications#mute|даведацца болей]])",
"echo-pref-new-message-indicator": "Паказваць індыкатар паведамленьняў на старонцы гутарак у маёй панэлі",
+ "echo-pref-beta-feature-cross-wiki-message": "Пашыраныя апавяшчэньні",
+ "echo-pref-beta-feature-cross-wiki-description": "Спрашчае прагляд і арганізацыю паведамленьняў. Утрымлівае «крос-вікі» паведамленьні, што дае вам магчымасьць бачыць абвесткі зь іншых вікі (каб атрымліваць такія паведамленьні з пэўнай вікі, вы мусіце актываваць бэта-функцыю ў гэтай вікі).",
"echo-learn-more": "Даведацца болей",
+ "echo-log": "Публічны журнал",
"echo-new-messages": "Вы маеце новыя паведамленьні",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|1=Паведамленьне|Паведамленьні}} ў гутарках",
"echo-category-title-article-linked": "{{PLURAL:$1|1=Спасылка|Спасылкі}} на старонку",
"echo-category-title-reverted": "{{PLURAL:$1|1=Адкат праўкі|Адкаты правак}}",
"echo-category-title-mention": "{{PLURAL:$1|1=Згадваньне|Згадваньні}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|1=Няўдалая згадка|Няўдалыя згадкі}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|1=Удалая згадка|Удалыя згадкі}}",
"echo-category-title-other": "{{PLURAL:$1|1=Іншае|Іншыя}}",
"echo-category-title-system": "{{PLURAL:$1|1=Сыстэмнае|Сыстэмныя}}",
"echo-category-title-user-rights": "{{PLURAL:$1|1=Зьмена|Зьмены}} правоў удзельніка",
- "echo-pref-tooltip-edit-user-talk": "Паведамляць, калі нехта дасылае паведамленьне на маю старонку гутарак.",
- "echo-pref-tooltip-article-linked": "Паведамляць, калі нехта спасылаецца на створаную мной старонку зь іншага артыкула.",
- "echo-pref-tooltip-reverted": "Паведамляць, калі нехта адкатвае зробленую мной праўку.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|1=Ліст электроннай пошты ад іншага ўдзельніка|Лісты электроннай пошты ад іншых удзельнікаў}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|напамін з старонкі|напаміны з старонак}}",
+ "echo-pref-tooltip-edit-user-talk": "Паведамляць, калі нехта пакідае паведамленьне або адказ на маёй старонцы гутарак.",
+ "echo-pref-tooltip-article-linked": "Паведамляць, калі нехта спасылаецца на створаную мной старонку зь іншай старонкі.",
+ "echo-pref-tooltip-reverted": "Паведамляць, калі нехта адмяняе зробленую мной праўку з дапамогай функцыі адмены ці адкату.",
"echo-pref-tooltip-mention": "Паведамляць, калі нехта спасылаецца на маю старонку ўдзельніка.",
- "echo-no-agent": "[Ніхто]",
- "echo-no-title": "[Няма старонкі]",
+ "echo-pref-tooltip-mention-failure": "Паведамляць мне, калі я не магу даслаць згадку каму-небудзь.",
+ "echo-pref-tooltip-mention-success": "Паведамляць мне, калі я дасылаю згадку каму-небудзь.",
+ "echo-pref-tooltip-user-rights": "Паведамляць мне, калі нехта зьмяняе мае правы ўдзельніка.",
+ "echo-pref-tooltip-emailuser": "Паведамляць мне, калі нехта дасылае мне ліст электроннай поштай.",
+ "echo-pref-tooltip-article-reminder": "Паведамляць мне пра гэтую старонку, калі я запытаю.",
"echo-error-no-formatter": "Фарматаваньне для абвестак ня вызначана",
"notifications": "Абвесткі",
- "tooltip-pt-notifications-alert": "{{GENDER:|Вашыя}} апавяшчэньні",
- "tooltip-pt-notifications-message": "{{GENDER:|Вашыя}} паведамленьні",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Вашыя}} паведамленьні",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Вашыя}} абвесткі",
+ "echo-displaynotificationsconfiguration": "Паказаць налады паведамленьняў",
+ "echo-displaynotificationsconfiguration-summary": "Гэта агляд наладак паведамленьняў у гэтай вікі.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Паведамленьні паводле катэгорыяў",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Сартаваньне паводле тыпаў",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "У які разьдзел сартуецца кожны тып паведамленьня",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Дазволеныя спосабы паведамленьняў",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Якія спосабы паведамленьняў падтрымліваюцца кожнай катэгорыяй",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Якія спосабы паведамленьняў падтрымліваюцца для кожнага тыпу; ужываецца толькі для тыпаў у катэгорыях, якія схаваныя з наладаў",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Уключана па змоўчаньні",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Існыя ўдзельнікі",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Новыя ўдзельнікі",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Абавязковыя спосабы паведамленьняў",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Якія спосабы паведамленьняў зьяўляюцца абавязковымі для кожнай катэгорыі",
"echo-specialpage": "Абвесткі",
+ "echo-specialpage-section-markread": "Пазначыць групу як прачытаную",
+ "echo-specialpage-markasread": "Паведамленьне: пазначыць як прачытанае",
+ "echo-specialpage-markasread-invalid-id": "Няслушны ідэнтыфікатар падзеі",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|паведамленьне|паведамленьні|паведамленьняў}}",
+ "echo-specialpage-pagefilters-title": "Нядаўняя актыўнасьць",
+ "echo-specialpage-pagefilters-subtitle": "Старонкі зь непрачытанымі паведамленьнямі",
+ "notificationsmarkread-legend": "Пазначыць паведамленьне як прачытанае",
"echo-anon": "Для атрыманьня абвестак [$1 стварыце рахунак] або [$2 увайдзіце].",
"echo-none": "Вы ня маеце абвестак.",
"echo-more-info": "Болей",
"echo-feedback": "Водгук",
+ "echo-popup-footer-special-page-invitation": "<strong>Паспрабуйце абноўленую старонку паведамленьняў.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Цалкам новы выгляд і функцыі.",
+ "echo-api-failure": "Памылка пры атрыманьні паведамленьняў.",
+ "echo-api-failure-cross-wiki": "Доступ да аддаленага дамэну быў забаронены.",
+ "echo-notification-placeholder": "Няма паведамленьняў.",
+ "echo-notification-placeholder-filters": "Няма паведамленьняў, якія адпавядаюць гэтым крытэрам.",
+ "echo-notification-loginrequired": "Вы мусіце ўвайсьці, каб пабачыць вашыя паведамленьні.",
+ "echo-notification-popup-loginrequired": "Калі ласка, увайдзіце, каб пабачыць вашыя паведамленьні.",
+ "echo-notification-markasread": "Пазначыць як прачытанае",
+ "echo-notification-markasunread": "Пазначыць як непрачытанае",
+ "echo-notification-markasread-tooltip": "Пазначыць як прачытанае",
+ "echo-notification-more-options-tooltip": "Болей парамэтраў",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Не}} сачыць за зьменамі на старонцы «$1»",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Вы}} больш не назіраеце за старонкай «$1»",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Вы}} можаце пачаць назіраць за [$2 гэтай старонкай] у любы час.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Сачыць}} за новай актыўнасьцю на старонцы «$1»",
+ "notification-dynamic-actions-watch-confirmation": "Цяпер {{GENDER:$3|вы}} назіраеце за старонкай «$1»",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Вы}} можаце спыніць назіраньне за [$2 гэтай старонкай] у любы час.",
+ "notification-link-text-expand-all": "Разгарнуць",
+ "notification-link-text-expand-alert-count": "Паказаць {{PLURAL:$1|$1 папярэджаньне|$1 папярэджаньні|$1 папярэджаньняў}}",
+ "notification-link-text-expand-notice-count": "Паказаць {{PLURAL:$1|$1 абвестку|$1 абвесткі|$1 абвестак}}",
+ "notification-link-text-expand-all-count": "Паказаць {{PLURAL:$1|$1 паведамленьне|$1 паведамленьні|$1 паведамленьняў}}",
+ "notification-link-text-collapse-all": "Згарнуць",
"notification-link-text-view-message": "Праглядзець паведамленьне",
"notification-link-text-view-mention": "Праглядзець згадваньне",
- "notification-link-text-view-changes": "Праглядзець зьмены",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|1=Праглядзець згадку|Праглядзець згадкі}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Праглядзець}} зьмены",
"notification-link-text-view-page": "Праглядзець старонку",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|пакінуў|пакінула}} паведамленьне на <strong>{{GENDER:$3|вашай}} старонцы размоваў</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|пакінуў|пакінула}} паведамленьне на <strong>{{GENDER:$3|вашай}} старонцы размоваў</strong> у «<strong>$4</strong>».",
+ "notification-header-page-linked": "Была зробленая спасылка з <strong>$4</strong> на <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Спаслаліся з <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Спасылкі былі зробленыя з {{PLURAL:$5|$5 старонкі|$5 старонак|100=99+ старонак}} на <strong>$3</strong>.",
+ "notification-header-article-reminder": "Старонка, пра якую {{GENDER:$2|вы}} прасілі нагадаць — <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Усе спасылкі на гэтую старонку",
+ "notification-header-mention-other": "$1 {{GENDER:$2|згадаў|згадала}} {{GENDER:$3|вас}} на старонцы <strong>$4</strong> у разьдзеле «<strong>$5</strong>».",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|згадаў|згадала}} {{GENDER:$3|вас}} на старонцы <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|згадаў|згадала}} {{GENDER:$3|вас}} на <strong>старонцы гутарак {{GENDER:$5|удзельніка|удзельніцы}} $4</strong> у разьдзеле «<strong>$6</strong>».",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|згадаў|згадала}} {{GENDER:$3|вас}} на <strong>старонцы гутарак {{GENDER:$5|удзельніка|удзельніцы}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|згадаў|згадала}} {{GENDER:$3|вас}} на <strong>{{GENDER:$2|сваёй}} старонцы размоваў</strong> у разьдзеле «<strong>$4</strong>».",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|згадаў|згадала}} {{GENDER:$3|вас}} на <strong>{{GENDER:$2|сваёй}} старонцы гутарак</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|згадаў|згадала}} {{GENDER:$3|вас}} на старонцы абмеркаваньня <strong>$4</strong> у разьдзеле «<strong>$5</strong>».",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|згадаў|згадала}} {{GENDER:$3|вас}} на старонцы абмеркаваньня <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Вашая}} згадка <strong>$3</strong> не была дасланая, бо такі ўдзельнік ня знойдзены.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Вашая}} згадка <strong>$3</strong> не была дасланая, бо ўдзельнік зьяўляецца ананімам.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Вы}} паспрабавалі згадаць больш чым $3 {{PLURAL:$3|удзельніка|удзельнікаў}}. Усе згадкі, якія перавышаюць гэты ліміт, не былі дасланыя.",
+ "notification-header-mention-failure-bundle": "$3 {{PLURAL:$3|згадка|згадкі|згадак}}, {{PLURAL:$3|1=якую|якія}} {{GENDER:$2|вы зрабілі}} на старонцы абмеркаваньня <strong>$4</strong> ня {{PLURAL:$3|1=можа быць дасланая|могуць быць дасланыя}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Імя ўдзельніка не існуе:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-адрасы ня могуць быць згаданыя:</strong> $1",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Вы}} толькі што зрабілі {{GENDER:$2|вашую}} першую праўку; дзякуем {{GENDER:$2|вам}} і запрашаем!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Вы}} толькі што зрабілі {{GENDER:$2|вашую}} дзясятую праўку; дзякуем {{GENDER:$2|вам}}, так трымаць!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Вы}} толькі што зрабілі {{GENDER:$2|вашую}} сотую праўку; дзякуй {{GENDER:$2|вам}} вялікі!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Вы}} толькі што зрабілі {{GENDER:$2|вашую}} тысячную праўку; дзякуй {{GENDER:$2|вам}} за вялікі ўнёсак!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Вы}} толькі што зрабілі {{GENDER:$2|вашую}} дзесяцітысячную праўку; дзякуй {{GENDER:$2|вам}} велізарны!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Вы}} толькі што зрабілі {{GENDER:$2|вашую}} статысячную праўку; дзякуй {{GENDER:$2|вам}} за дзівосны ўнёсак!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Вы}} толькі што зрабілі {{GENDER:$2|вашую}} мільённую праўку; дзякуй {{GENDER:$2|вам}} за ашаламляльны ўнёсак!",
"notification-link-text-view-edit": "Праглядзець праўку",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|пакінуў|пакінула}} паведамленьне на Вашай [[User talk:$2#$3|старонцы гутарак]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|пакінуў|пакінула}} паведамленьне на вашай старонцы гутарак у «[[User talk:$2#$3|$4]]».",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|пакінуў|пакінула}} паведамленьне на Вашай [[User talk:$2#$3|старонцы гутарак]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|пакінуў|пакінула}} паведамленьне на вашай старонцы гутарак у «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "На [[:$2]] {{GENDER:$1|спаслаліся}} з [[:$3]]. [[Special:WhatLinksHere/$2|усе спасылкі на гэтую старонку]].",
- "notification-page-linked-flyout": "На [[:$2]] {{GENDER:$1|спаслаліся}} з [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|пакінуў|пакінула}} камэнтар у тэме «[[$3|$2]]» на старонцы абмеркаваньня «$4»",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|стварыў|стварыла}} новую тэму «$2» у [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|даслаў|даслала}} Вам паведамленьне: «[[$3#$2|$2]]»",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|пакінуў|пакінула}} камэнтар у тэме «[[$3#$2|$2]]» на вашай старонцы гутарак",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|згадаў|згадала}} Вас на старонцы размоваў $5 у «[[:$3#$2|$4]]».",
- "notification-mention-flyout": "$1 {{GENDER:$1|згадаў|згадала}} Вас на старонцы абмеркаваньня $5 у «[[:$3#$2|$4]]».",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|зьмяніў|зьмяніла}}]] Вашыя правы. $2. [[Special:ListGroupRights|Даведайцеся болей]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|зьмяніў|зьмяніла}} вашыя правы. $2. [[Special:ListGroupRights|Даведайцеся больш]]",
- "notification-user-rights-add": "Цяпер Вы ўваходзіце ў {{PLURAL:$2|1=гэтую групу|гэтыя групы}}: $1",
- "notification-user-rights-remove": "Цяпер вы не ўваходзіце ў {{PLURAL:$2|1=гэтую групу|гэтыя групы}}: $1",
- "notification-new-user": "Вітаем у {{GRAMMAR:месны|{{SITENAME}}}}, $1! Мы радыя бачыць Вас.",
- "notification-reverted2": "{{PLURAL:$4|1=Вашая праўка|Вашыя праўкі}} на старонцы [[:$2]] {{PLURAL:$4|1=была скасавная|былі скасаваныя}} {{GENDER:$1|ўдзельнікам|ўдзельніцай}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "$1 {{GENDER:$1|скасаваў|скасавала}} {{PLURAL:$4|1=Вашую праўку|Вашыя праўкі}} на старонцы $2. $3",
+ "notification-header-reverted": "{{PLURAL:$4|1=Вашая праўка|Вашыя праўкі}} на старонцы <strong>$3</strong> {{GENDER:$2|{{PLURAL:$4|1=была скасаваная|былі скасаваныя}}}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|даслаў|даслала}} вам ліст электроннай поштай.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|пакінуў|пакінула}} Вам паведамленьне на {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|пакінуў|пакінула}} паведамленьне на вашай старонцы гутарак.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|пакінуў|пакінула}} паведамленьне на Вашай старонцы гутарак у «$2».",
"notification-page-linked-email-subject": "На старонку, якую вы стварылі, спаслаліся ў {{GRAMMAR:месны|{{SITENAME}}}}",
- "notification-page-linked-email-batch-body": "На $2 {{GENDER:$1|спаслаліся}} з $3.",
"notification-reverted-email-subject2": "$1 {{GENDER:$1|скасаваў|скасавала}} {{PLURAL:$3|1=Вашую праўку|Вашыя праўкі}} на сайце {{SITENAME}}",
- "notification-reverted-email-batch-body2": "$1 {{GENDER:$1|скасаваў|скасавала}} {{PLURAL:$3|1=Вашую праўку|Вашыя праўкі}} на старонцы «$2».",
- "notification-mention-email-subject": "$1 {{GENDER:$1|згадаў|згадала}} Вас у {{GRAMMAR:месны|{{SITENAME}}}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|згадаў|згадала}} Вас на старонцы абмеркаваньня $4 у «$3».",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|згадаў|згадала}} {{GENDER:$2|Вас}} у {{GRAMMAR:месны|{{SITENAME}}}}",
"notification-user-rights-email-subject": "Вашыя правы ў {{GRAMMAR:месны|{{SITENAME}}}} былі зьмененыя",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|зьмяніў|зьмяніла}} Вашыя правы. $2",
- "echo-email-subject-default": "Новая абвестка ад {{GRAMMAR:родны|{{SITENAME}}}}",
+ "notification-inbox-filter-all": "Усе",
"echo-email-body-default": "Для Вас ёсьць новая абвестка ў {{GRAMMAR:месны|{{SITENAME}}}}:\n\n$1",
- "echo-email-batch-body-default": "Вы маеце новую абвестку",
- "echo-email-footer-default": "$2\n\nКаб выбраць, якія лісты мы дасылацьмем Вам, наведайце свае налады:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Каб абраць лісты, якія Вы жадаеце атрымліваць, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">праверце свае налады</a>.<br />\n$1",
- "echo-notification-alert-text-only": "Апавяшчэньні",
+ "echo-email-footer-default": "$2\n\nКаб кантраляваць, якія лісты мы дасылацьмем Вам, наведайце свае налады:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-notification-alert-text-only": "Паведамленьні",
+ "echo-notification-notice-text-only": "Абвесткі",
"echo-overlay-link": "Усе абвесткі",
"echo-overlay-title": "<b>Абвесткі</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|1=Паведамленьне|Паведамленьні}}</b> ({{PLURAL:$1|1=паказанае|паказаныя}} $1 з $2 {{PLURAL:$2|1=непрачытанага|непрачытаных}})",
@@ -97,14 +161,9 @@
"echo-date-today": "Сёньня",
"echo-date-yesterday": "Учора",
"echo-load-more-error": "Узьнікла памылка ў час атрыманьня дадатковых вынікаў.",
- "notification-edit-talk-page-bundle": "$1 і $3 {{PLURAL:$4|іншы ўдзельнік|іншыя ўдзельнікі|іншых удзельнікаў}} пакінулі паведамленьне на Вашай [[User talk:$2|старонцы гутарак]].",
- "notification-page-linked-bundle": "$1 {{GENDER:$1|дадаў|дадала}} спасылку на $2 на старонцы $3 і {{PLURAL:$5|1=іншай старонцы|$4 іншых старонках}}. [[Special:WhatLinksHere/$2|Глядзіце ўсе спасылкі на гэтую старонку]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 і $2 {{PLURAL:$3|1=іншы|іншых}} пакінулі паведамленьне на Вашай старонцы гутарак.",
- "notification-page-linked-email-batch-bundle-body": "$1 {{GENDER:$1|дадаў|дадала}} спасылку на $2 на старонцы $3 і яшчэ $4 {{PLURAL:$5|старонцы|старонках}}.",
"echo-email-batch-subject-daily": "Вы атрымалі {{PLURAL:$2|новую абвестку|новыя абвесткі|новых абвестак}} на {{SITENAME}}",
"echo-email-batch-subject-weekly": "На гэтым тыдні Вы атрымалі {{PLURAL:$2|новую абвестку|новыя абвесткі|новых абвестак}} на {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Вітаем, $1!\nВось агляд сёньняшняй актыўнасьці ў {{GRAMMAR:месны|{{SITENAME}}}} для Вас.",
"echo-email-batch-body-intro-weekly": "Вітаем, $1!\nВось тыднёвы агляд актыўнасьці ў {{GRAMMAR:месны|{{SITENAME}}}} для вас.",
- "echo-email-batch-link-text-view-all-notifications": "Праглядзець усе абвесткі",
- "echo-rev-deleted-text-view": "Гэтая вэрсія старонкі была схаваная."
+ "echo-email-batch-link-text-view-all-notifications": "Праглядзець усе абвесткі"
}
diff --git a/Echo/i18n/be.json b/Echo/i18n/be.json
index 307611a9..d2ba7f0f 100644
--- a/Echo/i18n/be.json
+++ b/Echo/i18n/be.json
@@ -3,10 +3,11 @@
"authors": [
"Дзяніс Тутэйшы",
"Чаховіч Уладзіслаў",
- "Mikalai Udodau"
+ "Mikalai Udodau",
+ "Macofe"
]
},
- "echo-desc": "Сістэма паведамленняў",
+ "echo-desc": "Сістэма апавяшчэння ўдзельнікаў пра падзеі і паведамленні",
"prefs-echo": "Паведамленні",
"prefs-emailsettings": "Настройкі эл. пошты",
"prefs-displaynotifications": "Настройкі адлюстравання",
@@ -23,7 +24,6 @@
"echo-pref-email-frequency-weekly": "Штотыдневы агляд паведамленняў",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Просты тэкст",
- "echo-pref-notify-show-link": "Паказаць паведамленні ў маёй панэлі інструментаў",
"echo-pref-new-message-indicator": "Паказаць у маёй панэлі інструментаў індыкатар паведамленняў на старонцы абмеркавання",
"echo-learn-more": "Даведацца больш",
"echo-new-messages": "У вас ёсць новыя паведамленні",
@@ -34,81 +34,74 @@
"echo-category-title-other": "{{PLURAL:$1|Іншае|Іншыя}}",
"echo-category-title-system": "{{PLURAL:$1|Сістэмнае|Сістэмныя}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Змяненне доступаў удзельніка|Змяненні доступаў удзельніка}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|1=Ліст электроннай пошты ад іншага ўдзельніка|Лісты электроннай пошты ад іншых удзельнікаў}}",
"echo-pref-tooltip-edit-user-talk": "Паведамляць мне, калі хтосьці пакідае паведамленне ці адказвае на маёй старонцы размоў.",
"echo-pref-tooltip-article-linked": "Паведамляць мне, калі хтосьці спасылаецца ў артыкулах на створаную мной старонку",
"echo-pref-tooltip-reverted": "Паведамляць мне, калі хтосьці адмяніў маю праўку, выкарыстаўшы функцыю адмены ці адкату.",
"echo-pref-tooltip-mention": "Паведамляць мне, калі хтосьці высылаецца на маю старонку ўдзельніка.",
"echo-pref-tooltip-user-rights": "Паведамляць мне, калі хтосьці змяняе мае правы доступу.",
- "echo-no-agent": "[Ніхто]",
- "echo-no-title": "[Няма старонкі]",
+ "echo-pref-tooltip-emailuser": "Апавяшчаць мяне, калі хто-небудзь шле мне ліст электроннай поштай.",
"echo-error-no-formatter": "Фарматаванне не вызначана для паведамлення",
- "echo-error-preference": "Памылка: Не ўдалося задаць настройкі ўдзельніка",
- "echo-error-token": "Памылка: не ўдалося атрымаць маркер удзельніка (user token)",
"notifications": "Паведамленні",
- "tooltip-pt-notifications": "Вашы паведамленні",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Вашы}} апавяшчэнні",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Вашы}} апавяшчэнні",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Новыя ўдзельнікі",
"echo-specialpage": "Паведамленні",
+ "echo-specialpage-section-markread": "Пазначыць групу як прачытаную",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|апавяшчэнне|апавяшчэнні|апавяшчэнняў}}",
+ "echo-specialpage-pagefilters-title": "Нядаўняя актыўнасць",
+ "notificationsmarkread-legend": "Пазначыць апавяшчэнні як прачытаныя",
"echo-anon": "Каб атрымліваць паведамленні, [$1 стварыце ўліковы запіс] ці [$2 прадстаўцеся].",
"echo-none": "Вы не атрымлівалі паведамленняў.",
"echo-more-info": "Больш падрабязна",
"echo-feedback": "Зваротная сувязь",
+ "echo-api-failure": "Немагчыма атрымаць апавяшчэнні. Калі ласка, паспрабуйце яшчэ раз. (Памылка $1)",
+ "echo-api-failure-cross-wiki": "Доступ к аддаленаму дамену забаронены.",
+ "echo-notification-placeholder": "Няма апавяшчэнняў.",
+ "echo-notification-loginrequired": "Вы павінны ўвайсці, каб пабачыць паведамленні.",
+ "echo-notification-markasread": "Адзначыць як прачытанае",
+ "echo-notification-markasunread": "Адзначыць як нечытанае",
+ "echo-notification-markasread-tooltip": "Адзначыць як прачытанае",
+ "notification-link-text-expand-all": "Разгарнуць",
+ "notification-link-text-expand-alert-count": "Паказаць {{PLURAL:$1|$1 папярэджанне|$1 папярэджанні|$1 папярэджанняў}}",
+ "notification-link-text-expand-all-count": "Разгарнуць {{PLURAL:$1|$1 апавяшчэнне|$1 апавяшчэнні|$1 апавяшчэнняў}}",
+ "notification-link-text-collapse-all": "Згарнуць",
"notification-link-text-view-message": "Прагляд паведамленняў",
"notification-link-text-view-mention": "Прагляд згадкі",
- "notification-link-text-view-changes": "Прагляд змен",
+ "notification-link-text-view-changes": "{{GENDER:$1|Прагляд}} змен",
"notification-link-text-view-page": "Прагляд старонкі",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|пакінуў|пакінула}} паведамленне на <strong>{{GENDER:$3|вашай}} старонцы размоў</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|пакінуў|пакінула}} паведамленне на <strong>{{GENDER:$3|вашай}} старонцы размоў</strong> у \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "Зроблена спасылка з <strong>$4</strong> на <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Усе спасылкі на гэту старонку",
"notification-link-text-view-edit": "Прагляд праўкі",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|пакінуў|пакінула}} паведамленне на вашай [[User talk:$2#$3|старонцы размоў]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|пакінуў|пакінула}} паведамленне на вашай старонцы размоў \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|пакінуў|пакінула}} паведамленне на вашай [[User talk:$2#$3|старонцы размоў]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|пакінуў|пакінула}} паведамленне на вашай старонцы размоў \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] была {{GENDER:$1|звязана}} з [[:$3]]. [[Special:WhatLinksHere/$2|Гл. усе спасылкі на гэту старонку]].",
- "notification-page-linked-flyout": "[[:$2]] была {{GENDER:$1|звязана}} з [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|пракаментаваў|пракаментавала}} тэму \"[[$3|$2]]\" на старонцы размоў \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|дадаў|дадала}} новую тэму \"$2\" на старонцы [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|адправіў|адправіла}} вам паведамленне: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|пракаментаваў|пракаментавала}} тэму \"[[$3#$2|$2]]\" на вашай старонцы размоў.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|згадаў|згадала}} вас на старонцы размоў $5 у раздзеле \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|згадаў|згадала}} вас на старонцы размоў $5 у раздзеле \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|згадаў|згадала}} вас на [[:$3|$2 старонцы размоў]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|згадаў|згадала}} вас на [[:$3|$2 старонцы размоў]].",
- "notification-user-rights": "Вашы правы карыстальніка [[Special:Log/rights/$1|{{GENDER:$1|змяніў|змяніла}}]] [[User:$1|$1]]. $2. [[Special:ListGroupRights|Падрабязней]]",
- "notification-user-rights-flyout": "Вашы правы доступу {{GENDER:$1|змяніў|змяніла}} $1. $2. [[Special:ListGroupRights|Падрабязней]]",
- "notification-user-rights-add": "Вы цяпер удзельнік {{PLURAL:$2|1=наступнай групы|наступных груп}}: $1",
- "notification-user-rights-remove": "Вы больш не ўваходзіце ў {{PLURAL:$2|1=наступную групу|наступныя групы}}: $1",
- "notification-new-user": "Вітаем у {{GRAMMAR:месны|{{SITENAME}}}}, $1! Рады бачыць вас.",
- "notification-reverted2": "{{PLURAL:$4|1=Вашу праўку на старонцы [[:$2]]|Вашы праўкі на старонцы [[:$2]]}} {{GENDER:$1|скасаваў|скасавала}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|1=Вашу праўку на старонцы $2|Вашы праўкі на старонцы $2}} {{GENDER:$1|скасаваў|скасавала}} $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|1=Вашу праўку на старонцы $3|Вашы праўкі на старонцы $3}} {{GENDER:$2|скасаваў|скасавала}} $1.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|Удзельнік|Удзельніца}} $1 {{GENDER:$1|пакінуў|пакінула}} вам паведамленне на пляцоўцы «{{SITENAME}}»",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|Удзельнік|Удзельніца}} $1 {{GENDER:$1|пакінуў|пакінула}} паведамленне на вашай старонцы размоў:",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Удзельнік|Удзельніца}} $1 {{GENDER:$1|пакінуў|пакінула}} вам паведамленне на вашай старонцы размоў у раздзеле (тэме) «$2»",
"notification-page-linked-email-subject": "На сайце «{{SITENAME}}» з'явілася спасылка на вашу старонку ўдзельніка",
- "notification-page-linked-email-batch-body": "{{GENDER:$1|Удзельнік|удзельніца}} $1 {{GENDER:$1|спаслаўся|спаслалася}} на $2 з $3",
"notification-reverted-email-subject2": "{{GENDER:$1|Хтосьці}} адмяніў {{PLURAL:$3|вашу праўку|вашы праўкі}} на сайце «{{SITENAME}}»",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Ваша праўка на старонцы «$2» была адменена|Вашы праўкі на старонцы «$2» былі адменены}} {{GENDER:$1|ўдзельнікам|ўдзельніцай}} $1.",
"notification-mention-email-subject": "{{GENDER:$1|Удзельнік|Удзельніца}} $1 {{GENDER:$1|згадаў|згадала}} вас на сайце «{{SITENAME}}»",
- "notification-mention-email-batch-body": "{{GENDER:$1|Удзельнік|Удзельніца}} $1 {{GENDER:$1|згадаў|згадала}} вас на старонцы размоў $4 на сайце «$3».",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|згадаў|згадала}} вас на старонцы размоў $2.",
"notification-user-rights-email-subject": "Вашы правы на сайце «{{SITENAME}}» былі зменены",
- "notification-user-rights-email-batch-body": "Вашы правы былі зменены {{GENDER:$1|ўдзельнікам|ўдзельніцай}} $1. $2.",
- "echo-email-subject-default": "Новыя паведамленні на сайце «{{SITENAME}}»",
+ "notification-timestamp-today": "Сёння",
+ "notification-timestamp-yesterday": "Учора",
+ "notification-inbox-filter-read": "Чытаныя",
+ "notification-inbox-filter-unread": "Непрачытаныя",
+ "notification-inbox-filter-all": "Усе",
"echo-email-body-default": "У вас ёсць новае паведамленне на сайце «{{SITENAME}}»: $1",
- "echo-email-batch-body-default": "У вас ёсць новае паведамленне",
"echo-email-footer-default": "$2 Для кантролю за тым, якія паведамленні адпраўляюцца вам па эл. пошце, праверце свае персанальныя настройкі: {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}} $1",
- "echo-email-footer-default-html": "Для кантролю за тым, якія паведамленні адпраўляюцца вам па эл. пошце, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">праверце свае персанальныя настройкі</a><br /> $1",
+ "echo-notification-notice-text-only": "Абвесткі",
"echo-overlay-link": "Усе паведамленні",
"echo-overlay-title": "<b>Паведамленні</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Паведамленні}}</b> ({{PLURAL|$1|паказана|паказаны}} $1 з $2 {{PLURAL|$2|непрачытанага|непрачытаных}})",
"echo-mark-all-as-read": "Пазначыць усе як прачытаныя",
+ "echo-mark-wiki-as-read": "Пазначыць усе як прачытаныя ў выбранай вікі: $1",
"echo-date-today": "Сёння",
"echo-date-yesterday": "Учора",
"echo-load-more-error": "Адбылася памылка пры атрыманні дадатковых вынікаў.",
- "notification-edit-talk-page-bundle": "$1 і $3 {{PLURAL:$4|іншы|іншых}} {{PLURAL:$4|ўдзельнік|удзельнікаў}} пакінулі паведамленне на вашай [[User talk:$2|старонцы размоў]].",
- "notification-page-linked-bundle": "На старонку «$2» ёсць {{GENDER:$1|спасылка}} са старонкі «$3» і яшчэ $4 {{PLURAL:$5|старонкі|старонак}}. [[Special:WhatLinksHere/$2|Гл. усе спасылкі на гэту старонку]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 і $2 {{PLURAL:$3|іншы|іншых}} {{PLURAL:$3|ўдзельнік|удзельнікаў}} пакінулі паведамленне на вашай старонцы размоў.",
- "notification-page-linked-email-batch-bundle-body": "На старонку «$2» ёсць {{GENDER:$1|спасылка}} са старонкі «$3» і яшчэ $4 {{PLURAL:$5|старонкі|старонак}}",
"echo-email-batch-subject-daily": "Вы атрымалі $2 {{PLURAL:$2|новае паведамленне ў|новых паведамлення ў|новых паведамленняў у}} праекце «{{SITENAME}}»",
"echo-email-batch-subject-weekly": "На гэтым тыдні вы атрымалі $2 {{PLURAL:$2|новае паведамленне ў|новых паведамлення ў|новых паведамленняў у}} праекце «{{SITENAME}}»",
"echo-email-batch-body-intro-daily": "Прывітанне, $1! Вось кароткі агляд сённяшняй дзейнасці ў {{SITENAME}} для вас.",
"echo-email-batch-body-intro-weekly": "Прывітанне, $1! Вось кароткі тыднёвы агляд дзейнасці ў {{SITENAME}} для вас.",
"echo-email-batch-link-text-view-all-notifications": "Праглядзець усе паведамленні",
- "echo-rev-deleted-text-view": "Гэта версія старонкі была схавана"
+ "notification-header-foreign-notice": "Больш абвестак з {{PLURAL:$5|іншай вікі|$5 іншых вікі}}"
}
diff --git a/Echo/i18n/bg.json b/Echo/i18n/bg.json
index dbd26400..7d460edc 100644
--- a/Echo/i18n/bg.json
+++ b/Echo/i18n/bg.json
@@ -4,15 +4,24 @@
"Aceofhearts1968",
"DCLXVI",
"Termininja",
- "Borislav"
+ "Borislav",
+ "Лорд Бъмбъри",
+ "Vodnokon4e",
+ "V111P",
+ "Spiritia",
+ "Ket",
+ "StanProg",
+ "ShockD"
]
},
- "echo-desc": "Система за известия",
+ "echo-desc": "Система за уведомяване на потребителите за събития и съобщения",
"prefs-echo": "Известия",
"prefs-emailsettings": "Настройки за е-поща",
"prefs-displaynotifications": "Настройки за показване",
"prefs-echosubscriptions": "Получаване на известие за следните събития",
+ "prefs-echocrosswiki": "Известия от други уикита",
"prefs-newmessageindicator": "Индикатор за ново съобщение",
+ "prefs-blocknotificationslist": "Заглушени потребители",
"echo-pref-send-me": "Съдържание на е-писмата:",
"echo-pref-send-to": "Адрес за получаване:",
"echo-pref-email-format": "Формат на е-писмата:",
@@ -24,62 +33,172 @@
"echo-pref-email-frequency-weekly": "Седмично резюме на известията",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "обикновен текст",
+ "echo-pref-cross-wiki-notifications": "Показване на известия от други уикита",
+ "echo-pref-notifications-blacklist": "Да не се показват известия от следните потребители.\n([[mw:Help:Notifications#mute|learn more]])",
"echo-pref-new-message-indicator": "Показване на индикатор за съобщения на беседата в лентата с моите инструменти",
+ "echo-pref-beta-feature-cross-wiki-message": "Подобрени известявания",
+ "echo-pref-beta-feature-cross-wiki-description": "Наблюдавайте и организирайте по-лесно известията си. Включва „cross-wiki“ известия, които ви позволяват да видите съобщенията си от други уикипроекти на едно място. (За да получaвате тези известия в даден уикипроект, трябва да активирате бета функцията в него.)",
"echo-learn-more": "Повече подробности",
+ "echo-log": "Публичен дневник",
"echo-new-messages": "Имате нови съобщения",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Съобщение|Съобщения}} на беседата",
"echo-category-title-article-linked": "{{PLURAL:$1|Препратка|Препратки}} към страници",
"echo-category-title-reverted": "{{PLURAL:$1|Връщане|Връщания}} на редакция",
"echo-category-title-mention": "{{PLURAL:$1|Споменаване|Споменавания}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Неуспешно споменаване|Неуспешни споменавания}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Успешно споменаване|Успешни споменавания}}",
"echo-category-title-other": "{{PLURAL:$1|Други}}",
"echo-category-title-system": "{{PLURAL:$1|Системни известия}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Промяна|Промени}} на потребителските права",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Писмо от друг потребител|Писма от други потребители}}",
"echo-pref-tooltip-edit-user-talk": "Известяване, когато някой остави съобщение или отговор на беседата ми.",
"echo-pref-tooltip-article-linked": "Известяване, когато някой постави препратка в статия към създадена от мен страница.",
"echo-pref-tooltip-reverted": "Известяване, когато някой премахне или отмени моя редакция чрез инструмента за връщане.",
"echo-pref-tooltip-mention": "Известяване, когато някой постави препратка към потребителската ми страница.",
+ "echo-pref-tooltip-mention-failure": "Уведоми ме, когато не съм успял да изпратя споменаване на някого.",
+ "echo-pref-tooltip-mention-success": "Уведоми ме, когато изпратя споменаване на някого.",
"echo-pref-tooltip-user-rights": "Известяване, когато някой промени потребителските ми права.",
- "echo-no-agent": "[Никой]",
- "echo-no-title": "[Няма страница]",
+ "echo-pref-tooltip-emailuser": "Известяване, когато някой ми изпрати е-поща.",
"echo-error-no-formatter": "Не е посочено форматиране на известията.",
"notifications": "Известия",
- "tooltip-pt-notifications": "Вашите известия",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Вашите}} известия",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Вашите}} уведомления",
+ "echo-displaynotificationsconfiguration": "Показване на настройките за известия",
+ "echo-displaynotificationsconfiguration-summary": "Това е преглед на настройките за известия на това уики.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Известия по категории",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Подреждане по видове",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Подреждане на видовете известия по секции",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Позволени начини за известяване",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Кои начините за уведомяване се поддържат във всяка категория",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Кои са начините за уведомяване се поддържат за всеки вид – прилага се само за видове в рамките на категории, които са скрити от настройките.",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Включени по подразбиране",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Съществуващи потребители",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Нови потребители",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Необходими методи за известяване",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Кои начини за уведомяване са задължителни за всяка категория",
"echo-specialpage": "Известия",
+ "echo-specialpage-section-markread": "Отбелязване на групата като прочетена",
+ "echo-specialpage-markasread": "Известие: Отбелязване като прочетено",
+ "echo-specialpage-markasread-invalid-id": "Номер на невалидно събитие",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|известие|известия}}",
+ "echo-specialpage-pagefilters-title": "Последни действия",
+ "echo-specialpage-pagefilters-subtitle": "Страници с непрочетени известия",
+ "notificationsmarkread-legend": "Отбелязване на известието като прочетено",
"echo-anon": "За получаване на известия е необходимо да [$1 регистрирате сметка] или [$2 влезте] в системата.",
"echo-none": "Нямате известия.",
"echo-more-info": "Повече информация",
"echo-feedback": "Обратна връзка",
+ "echo-popup-footer-special-page-invitation": "<strong>Опитайте обновената страница за известия.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Нов изглед и нови възможности.",
+ "echo-api-failure": "Неуспешно извличане на известия.",
+ "echo-api-failure-cross-wiki": "Отказан е достъп до външен домейн.",
+ "echo-notification-placeholder": "Няма известия.",
+ "echo-notification-placeholder-filters": "Няма известия отговарящи на зададените критерии.",
+ "echo-notification-loginrequired": "Трябва да се влезли в системата, за да може да видите известията си.",
+ "echo-notification-popup-loginrequired": "Моля влезте в системата, за да видите известията си.",
+ "echo-notification-markasread": "Отбелязване като прочетено",
+ "echo-notification-markasunread": "Отбелязване като непрочетено",
+ "echo-notification-markasread-tooltip": "Отбелязване като прочетено",
+ "echo-notification-more-options-tooltip": "Допълнителни опции",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Спрете}} проследяването на новите промени на страницата „$1“",
+ "notification-dynamic-actions-unwatch-confirmation": "Вече не {{GENDER:$3|наблюдавате}} страницата „$1“",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Можете}} да възобновите проследяването на [$2 на тази страница] във всеки един момент.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Следете}} новите промени на страницата „$1“",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Вие}} следите промените на страницата „$1“",
+ "notification-dynamic-actions-watch-confirmation-description": "Може да {{GENDER:$3|спрете}} проследяването на [$2 на тази страница] във всеки един момент.",
+ "notification-link-text-expand-all": "Разгръщане",
+ "notification-link-text-expand-alert-count": "Показване на {{PLURAL:$1|$1 сигнал|$1 на сигнали}}",
+ "notification-link-text-expand-notice-count": "Показване на {{PLURAL:$1|$1 съобщение|$1 на съобщения}}",
+ "notification-link-text-expand-all-count": "Показване на {{PLURAL:$1|$1 известие|$1 известия}}",
+ "notification-link-text-collapse-all": "Свиване",
"notification-link-text-view-message": "Преглед на известието",
"notification-link-text-view-mention": "Преглед на споменаването",
- "notification-link-text-view-changes": "Преглед на промените",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Преглед на споменаване|Преглед на споменавания}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Преглед}} на промените",
"notification-link-text-view-page": "Преглед на страницата",
+ "notification-header-edit-user-talk": "$1 остави {{GENDER:$2||}} съобщение на <strong>{{GENDER:$3|Вашата}} беседа</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 остави {{GENDER:$2||}} съобщение на <strong>{{GENDER:$3|вашата}} беседа</strong>, в раздел „<strong>$4</strong>“.",
+ "notification-header-page-linked": "Направена е препратка от <strong>$4</strong> до <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Направена е препратка от $<strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Направени са препратки от {{PLURAL:$5||$5 страници|100=чрез 99 страници}} до <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Всички връзки към страницата",
+ "notification-header-mention-other": "$1 {{GENDER:$3|ви}} {{GENDER:$2|спомена}} на беседата на <strong>$4</strong>, в раздел „$5“.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|Ви}} {{GENDER:$2|спомена}} на беседата на <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|Ви}} {{GENDER:$2|<strong>спомена</strong>}} на <strong>беседата</strong> {{GENDER:$5|на}} <strong>$4</strong>, в раздел „$6“.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|Ви}} {{GENDER:$2|<strong>спомена</strong>}} на <strong>беседата</strong> {{GENDER:$5|на}} <strong>$4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|Ви}} {{GENDER:$2|спомена}} на {{GENDER:$2|неговата|нейната|своята}} беседа, в раздел „$4“.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|Ви}} {{GENDER:$2|спомена}} на {{GENDER:$2|своята}} беседа.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|Ви}} {{GENDER:$2|спомена}} в беседата $<strong>$4</strong>, в раздел „$5“.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|Ви}} {{GENDER:$2|спомена}} на беседата на <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Вашето}} споменаване на <strong>$3</strong> не е изпратено, защото потребителят не бе намерен.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Вашето}} споменаване на <strong>$3</strong> не е изпратено, защото потребителят е анонимен.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Вашите}} споменавания не бяха изпратени, защото превишават лимита от $3 {{PLURAL:$3|потребител|потребителя}}.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Споменаването, което|$3 Споменаванията, които}} {{GENDER:$2|направихте}} на беседата <strong>$4</strong>, {{PLURAL:$3|не може да бъде изпратено|не могат да бъдат изпратени}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Потребителското име не съществува:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-адреси не могат да бъдат споменавани:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Вашето}} споменаване на <strong>$3</strong> бе изпратено.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Споменаването|$3 Споменаванията}} {{GENDER:$2|които направихте}} на беседата на <strong>$4</strong>, {{PLURAL:$3|бяха изпратени}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Споменахте}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Известието|$3 Известията}} за споменавания {{GENDER:$2|които направихте}} на беседата: $<strong>$4</strong>, {{PLURAL:$5|$5 не беше изпратено|$5 не бяха изпратени}}, {{PLURAL:$6|$6 бе изпратено|$6 бяха изпратени}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Вашите}} потребителски права бяха {{GENDER:$1|променени}}. Бяхте добавени в група: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Вашите}} потребителски права бяха {{GENDER:$1|променени}}. Вече не сте член на група: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Вашите}} потребителски права бяха {{GENDER:$1|променени}}. Бяхте добавени в група: $2. Вече не сте член на група: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Добре дошли}} в {{SITENAME}}, $1! Радваме се, че {{GENDER:$2|сте}} тук.",
+ "notification-welcome-linktext": "Добре дошли!",
+ "notification-header-thank-you-1-edit": "Току-що {{GENDER:$2|направихте}} {{GENDER:$2|Вашата}} първа редакция. {{GENDER:$2|Благодарим}} Ви и добре дошли!",
+ "notification-header-thank-you-10-edit": "Току-що {{GENDER:$2|направихте}} {{GENDER:$2|Вашата}} десета редакция. {{GENDER:$2|Благодарим}} Ви и моля, продължавайте все така!",
+ "notification-header-thank-you-100-edit": "Току-що {{GENDER:$2|направихте}} {{GENDER:$2|своята}} стотна редакция. {{GENDER:$2|Благодарим}} ви много!",
+ "notification-header-thank-you-1000-edit": "Току-що {{GENDER:$2|направихте}} {{GENDER:$2|Вашата}} хилядна редакция. {{GENDER:$2|Благодарим}} Ви за големия принос!",
+ "notification-header-thank-you-10000-edit": "Току-що {{GENDER:$2|направихте}} {{GENDER:$2|своята}} десетхилядна редакция. {{GENDER:$2|Благодарим}} ви много!",
+ "notification-header-thank-you-100000-edit": "Току-що {{GENDER:$2|направихте}} {{GENDER:$2|вашата}} стохилядна редакция. {{GENDER:$2|Благодарим}} Ви за изключителния принос!",
+ "notification-header-thank-you-1000000-edit": "Току-що {{GENDER:$2|направихте}} {{GENDER:$2|вашата}} милионна редакция. {{GENDER:$2|Благодарим}} Ви за невероятния принос!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Вашата}} редакция",
"notification-link-text-view-edit": "Преглед на редакцията",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|остави}} съобщение на Вашата [[User talk:$2#$3|беседа]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|остави}} съобщение на Вашата беседа „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|остави}} съобщение на Вашата [[User talk:$2#$3|беседа]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|остави}} съобщение на Вашата беседа „[[User talk:$2#$3|$4]]“.",
- "notification-mention": "[[User:$1|$1]] Ви {{GENDER:$1|спомена}} на беседата на страницата $5 в раздела \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 Ви {{GENDER:$1|спомена}} на беседата на страницата $5 в раздела \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] Ви {{GENDER:$1|спомена}} на [[:$3|беседата на страницата $2]].",
- "notification-mention-nosection-flyout": "$1 Ви {{GENDER:$1|спомена}} на [[:$3|беседата на страницата $2]].",
- "notification-new-user": "Добре дошли в {{SITENAME}}, $1! Радостно е, че сте сред нас.",
- "notification-mention-email-batch-body": "$1 Ви {{GENDER:$1|спомена}} на беседата на страницата $4 в раздела \"$3\".",
- "notification-user-rights-email-subject": "Потребителските ви права в {{SITENAME}} бяха променени",
- "echo-email-subject-default": "Ново известие в {{SITENAME}}",
+ "notification-header-reverted": "{{PLURAL:$4|Ваша редакция|Ваши редакции}} на страница <strong>$3</strong> {{GENDER:$2|{{PLURAL:$4|е върната|са върнати}}}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|Ви изпрати}} имейл.",
+ "notification-edit-talk-page-email-subject2": "$1 ви {{GENDER:$1|остави}} съобщение на {{SITENAME}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|остави}} съобщение на вашата беседа, в раздел „$2“.",
+ "notification-page-linked-email-subject": "Страницата, създадена от вас, бе свързана с {{SITENAME}}",
+ "notification-reverted-email-subject2": "{{PLURAL:$3|Вашата редакция|Вашите редакции}} на {{SITENAME}} {{GENDER:$1|бе върната|бяха върнати}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|Ви}} {{GENDER:$1|спомена}} в {{SITENAME}}",
+ "notification-user-rights-email-subject": "Потребителските Ви права в {{SITENAME}} бяха променени",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 сек}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 мин}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ч}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 ден|$1 дена}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 месец|$1 месеца}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 г}}",
+ "notification-timestamp-today": "Днес",
+ "notification-timestamp-yesterday": "Вчера",
+ "notification-inbox-filter-read": "Прочетени",
+ "notification-inbox-filter-unread": "Непрочетени",
+ "notification-inbox-filter-all": "Всички",
"echo-email-body-default": "Имате ново известие в {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Имате ново известие.",
+ "echo-email-footer-default-html": "За да изберете какви имейли да ви изпращаме, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">проверете настройките си</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nЗа да изберете какви имейли да ви изпращаме, проверете настройките си:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "За да изберете какви ел. писма да {{GENDER:$1|Ви}} изпращаме, проверете {{GENDER:$1|настройките си}}:",
+ "echo-email-html-footer-preference-link-text": "проверете {{GENDER:$1|своите}} настройки",
+ "echo-email-html-footer-with-link": "За да изберете какви имейли да {{GENDER:$2|ви}} изпращаме, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Сигнал ($1)|Сигнали ($1)|100=Сигнали (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Съобщение ($1)|Съобщения ($1)|100=Съобщения (99+)}}",
+ "echo-notification-alert-text-only": "Известия",
+ "echo-notification-notice-text-only": "Уведомления",
"echo-overlay-link": "Всички известия",
"echo-overlay-title": "<b>Известия</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Известия}}</b> (показване на $1 от $2 непрочетени))",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Известие|Известия}}</b> (показване на $1 от $2 непрочетени)",
"echo-mark-all-as-read": "Отбелязване на всички като прочетени",
+ "echo-mark-all-as-read-confirmation": "{{PLURAL:$1|Съобщение|Съобщения}}, маркирани като прочетени",
+ "echo-mark-wiki-as-read": "Отбелязване на всички като прочетени в избраната уики: $1",
"echo-date-today": "Днес",
"echo-date-yesterday": "Вчера",
"echo-load-more-error": "Възникна грешка при извличане на още резултати.",
- "notification-edit-talk-page-bundle": "$1 и {{PLURAL:$4|някой друг|още $3 други потребителя}} {{GENDER:$1|оставиха}} съобщение на Вашата [[User talk:$2|беседа]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 и {{PLURAL:$3|някой друг|още $2 други потребителя}} {{GENDER:$1|оставиха}} съобщение на Вашата беседа.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Ново съобщение|$1 нови съобщения|100=99+ нови съобщения}} на <strong>{{GENDER:$3|вашата}} беседа</strong>.",
"echo-email-batch-subject-daily": "Имате {{PLURAL:$2|ново известие|нови известия}} в {{SITENAME}}",
"echo-email-batch-subject-weekly": "Имате {{PLURAL:$2|ново известие|нови известия}} в {{SITENAME}} от тази седмица",
"echo-email-batch-body-intro-daily": "Здравейте $1,\nПо-долу е показано резюме на активността в {{SITENAME}} за днес.",
"echo-email-batch-body-intro-weekly": "Здравейте $1,\nПо-долу е показано резюме на активността в {{SITENAME}} през седмицата.",
- "echo-email-batch-link-text-view-all-notifications": "Преглед на всички известия"
+ "echo-email-batch-link-text-view-all-notifications": "Преглед на всички известия",
+ "notification-header-foreign-alert": "Още известия от {{PLURAL:$5|друго уики|$5 други уикита}}",
+ "notification-header-foreign-notice": "Още съобщения от {{PLURAL:$5|друго уики|$5 други уикита}}",
+ "notification-header-foreign-all": "Още известия от {{PLURAL:$5|друго уики|$5 други уикита}}"
}
diff --git a/Echo/i18n/bgn.json b/Echo/i18n/bgn.json
index 443a8424..e555b3e5 100644
--- a/Echo/i18n/bgn.json
+++ b/Echo/i18n/bgn.json
@@ -1,7 +1,8 @@
{
"@metadata": {
"authors": [
- "Baloch Afghanistan"
+ "Baloch Afghanistan",
+ "Ibrahim khashrowdi"
]
},
"echo-pref-send-me": "په من دیم دئ:",
@@ -14,13 +15,12 @@
"echo-learn-more": "گیشتیر بزانیت",
"echo-category-title-other": "{{PLURAL:$1|دیگرین}}",
"echo-category-title-system": "{{PLURAL:$1|سیستیم}}",
- "echo-no-agent": "[هیچ کس]",
- "echo-no-title": "[بیدون ورق]",
"notifications": "نئ مئلوماتان",
- "tooltip-pt-notifications": "شمی مئلوماتان",
- "echo-specialpage": "نئ مئلوماتان",
+ "tooltip-pt-notifications-alert": "{{GENDER:|شمئ}} اخطاران",
+ "echo-specialpage": "اعلان‌هان",
"notification-link-text-view-message": "پیامئ دیستین",
"notification-link-text-view-page": "تاکدیمی دیستین",
+ "notification-inbox-filter-all": "موچین",
"echo-date-today": "مروچی",
"echo-date-yesterday": "زئ"
}
diff --git a/Echo/i18n/bho.json b/Echo/i18n/bho.json
index e134db0d..c4d9ef37 100644
--- a/Echo/i18n/bho.json
+++ b/Echo/i18n/bho.json
@@ -5,5 +5,6 @@
"SatyamMishra"
]
},
- "tooltip-pt-notifications": "हमार अधिसूचना"
+ "tooltip-pt-notifications-alert": "{{GENDER:|राउर}} सूचना",
+ "echo-notification-alert-text-only": "सूचना"
}
diff --git a/Echo/i18n/bn.json b/Echo/i18n/bn.json
index 5e533140..e488c65c 100644
--- a/Echo/i18n/bn.json
+++ b/Echo/i18n/bn.json
@@ -6,18 +6,23 @@
"Jayantanth",
"Nasir8891",
"Sayak Sarkar",
- "Aftabuzzaman"
+ "Aftabuzzaman",
+ "Macofe",
+ "Kayser Ahmad",
+ "Bodhisattwa"
]
},
- "echo-desc": "ঘটনা এবং বার্তা সম্পর্কে ব্যবহারকারীদের বিজ্ঞপ্তি দেয়ার জন্য সিস্টেম",
+ "echo-desc": "ঘটনা এবং বার্তা সম্পর্কে ব্যবহারকারীদের বিজ্ঞপ্তি দেয়ার জন্য ব্যবস্থা",
"prefs-echo": "বিজ্ঞপ্তি",
"prefs-emailsettings": "ইমেইল অপশন",
"prefs-displaynotifications": "প্রদর্শনের অপশন",
"prefs-echosubscriptions": "এই ঘটনা সম্পর্কে আমাকে অবহিত করো",
+ "prefs-echocrosswiki": "আন্তঃ-উইকি বিজ্ঞপ্তি",
"prefs-newmessageindicator": "নতুন বার্তা নির্দেশক",
+ "prefs-blocknotificationslist": "নিঃশব্দকৃত ব্যবহারকারী",
"echo-pref-send-me": "আমাকে পাঠাও:",
"echo-pref-send-to": "প্রাপক:",
- "echo-pref-email-format": "ইমেইল ফরমেট:",
+ "echo-pref-email-format": "ইমেইল বিন্যাস:",
"echo-pref-web": "ওয়েব",
"echo-pref-email": "ইমেইল",
"echo-pref-email-frequency-never": "আমাকে কোনো ইমেইল বিজ্ঞপ্তি পাঠিও না",
@@ -26,103 +31,176 @@
"echo-pref-email-frequency-weekly": "সাপ্তাহিক বিজ্ঞপ্তির একটি সারাংশ",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "সরল লেখা",
- "echo-pref-new-message-indicator": "আমার টুলবারে আলাপ পাতা বার্তা নির্দেশক (বিজ্ঞপ্তি) দেখাও",
+ "echo-pref-cross-wiki-notifications": "অন্যান্য উইকিগুলি থেকে বিজ্ঞপ্তি দেখাও",
+ "echo-pref-notifications-blacklist": "এই ব্যবহারকারীদের থেকে বিজ্ঞপ্তি প্রদর্শন করবেন না। ([[mw:Help:Notifications#mute|আরও জানুন]])",
+ "echo-pref-new-message-indicator": "আমার সরঞ্জামদণ্ডে আলাপ পাতার বার্তা নির্দেশক দেখাও",
+ "echo-pref-beta-feature-cross-wiki-message": "উন্নত বিজ্ঞপ্তি",
+ "echo-pref-beta-feature-cross-wiki-description": "আরো সহজে বিজ্ঞপ্তি দেখুন ও সংগঠিত করুন। এটি আন্তঃ-উইকি বিজ্ঞপ্তিসহ, যা আপনার অন্যান্য উইকির বার্তাগুলি দেখতে দিবে। (একটি প্রদত্ত উইকিতে আন্তঃ উইকি বিজ্ঞপ্তি পেতে, আপনাকে সেই উইকিতে বেটা বৈশিষ্ট্য সক্রিয় করা আবশ্যক।)",
"echo-learn-more": "আরও জানুন",
+ "echo-log": "প্রকাশ্য লগ",
"echo-new-messages": "আপনার নতুন বার্তা এসেছে",
"echo-category-title-edit-user-talk": "আলাপ পাতার {{PLURAL:$1|বার্তা|বার্তাসমূহ}}",
"echo-category-title-article-linked": "পাতা {{PLURAL:$1|সংযোগ|সংযোগসমূহ}}",
"echo-category-title-reverted": "সম্পাদনা {{PLURAL:$1|ফেরত}}",
"echo-category-title-mention": "{{PLURAL:$1|উল্লেখ|উল্লেখসমূহ}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|উল্লেখ|উল্লেখসমূহ}} ব্যর্থ হয়েছে",
+ "echo-category-title-mention-success": "{{PLURAL:$1|উল্লেখ|উল্লেখসমূহ}} সফল হয়েছে",
"echo-category-title-other": "{{PLURAL:$1|অন্য}}",
"echo-category-title-system": "{{PLURAL:$1|সিস্টেম}}",
"echo-category-title-user-rights": "{{PLURAL:$1|ব্যবহারকারীর অধিকার পরিবর্তন}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|অন্য ব্যবহারকারীর কাছ থেকে ইমেইল|অন্যান্য ব্যবহারকারীর কাছ থেকে ইমেইলসমূহ}}",
"echo-pref-tooltip-edit-user-talk": "আমার আলাপ পাতায় কেউ বার্তা রাখলে বা উত্তর দিলে আমাকে বিজ্ঞপ্তি দাও।",
- "echo-pref-tooltip-article-linked": "যদি কেউ অন্য পাতায় আমার তৈরি কোনো পাতার লিঙ্ক প্রদান করে তাহলে আমাকে বিজ্ঞপ্তি দাও।",
+ "echo-pref-tooltip-article-linked": "কেউ অন্য পাতায় আমার তৈরি কোনো পাতার লিঙ্ক প্রদান করলে আমাকে বিজ্ঞপ্তি দিন।",
"echo-pref-tooltip-reverted": "পূর্বাবস্থা বা রোলব্যাক সরঞ্জাম দিয়ে কেউ আমার সম্পাদনা ফেরত নিলে আমাকে বিজ্ঞপ্তি দাও।",
"echo-pref-tooltip-mention": "কেউ আমার ব্যবহারকারী পাতার লিঙ্ক প্রদান করলে আমাকে বিজ্ঞপ্তি দাও।",
+ "echo-pref-tooltip-mention-failure": "আমার কাউকে উল্লেখ করতে ব্যর্থ হলে আমাকে বিজ্ঞপ্তি দাও।",
+ "echo-pref-tooltip-mention-success": "আমি কাউকে উল্লেখ করলে আমাকে বিজ্ঞপ্তি দাও।",
"echo-pref-tooltip-user-rights": "কেউ আমার ব্যবহারকারীর অধিকার পরিবর্তন করলে আমাকে বিজ্ঞপ্তি দাও।",
- "echo-no-agent": "[কেউ নাই]",
- "echo-no-title": "[কোনো পাতা নাই]",
- "echo-error-no-formatter": "বিজ্ঞপ্তির জন্য কোনো ফরমেটিং নির্ধারিত হয়নি",
+ "echo-pref-tooltip-emailuser": "কেউ আমাকে একটি ইমেল প্রেরণ করলে আমাকে বিজ্ঞপ্তি দাও।",
+ "echo-error-no-formatter": "বিজ্ঞপ্তির জন্য কোন বিন্যাস সংজ্ঞায়িত করা হয়নি।",
"notifications": "বিজ্ঞপ্তি",
"tooltip-pt-notifications-alert": "{{GENDER:|আপনার}} অবহিতি",
- "tooltip-pt-notifications-message": "{{GENDER:|আপনার}} বার্তা",
+ "tooltip-pt-notifications-notice": "{{GENDER:|আপনার}} বিজ্ঞপ্তি",
+ "echo-displaynotificationsconfiguration": "বিজ্ঞপ্তি কনফিগারেশন দেখুন",
+ "echo-displaynotificationsconfiguration-summary": "এটি এই উইকিতে কিভাবে বিজ্ঞপ্তি কনফিগার করা আছে তাঁর উপর একটি আলোকপাত।",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "বিষয়শ্রেণী অনুযায়ী বিজ্ঞপ্তি",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "ধরন অনুযায়ী বাচাই করুন",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "যে অনুচ্ছেদে প্রতিটি বিজ্ঞপ্তির ধরন বাছাই করা হবে",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "মঞ্জুরিপ্রাপ্ত বিজ্ঞপ্তির পদ্ধতি",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "প্রতিটি বিষয়শ্রেণীর জন্য যে বিজ্ঞপ্তির পদ্ধতি সমর্থিত",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "প্রতিটি ধরনের জন্য যে বিজ্ঞপ্তির পদ্ধতি সমর্থিত; শুধুমাত্র বিষয়শ্রেণীর ধরনের ক্ষেত্রে প্রযোজ্য যা পছন্দসমূহ থেকে লুকায়িত",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "পূর্বনির্ধারিত রুপে সক্রিয়",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "বিদ্যমান ব্যবহারকারী",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "নতুন ব্যবহারকারী",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "প্রয়োজনীয় বিজ্ঞপ্তির পদ্ধতি",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "প্রতিটি বিষয়শ্রেণীর জন্য যে বিজ্ঞপ্তির পদ্ধতি আবশ্যিক",
"echo-specialpage": "বিজ্ঞপ্তি",
+ "echo-specialpage-section-markread": "গ্রুপ পঠিত হিসেবে চিহ্নিত করুন",
+ "echo-specialpage-markasread": "বিজ্ঞপ্তি: পঠিত হিসেবে চিহ্নিত করুন",
+ "echo-specialpage-markasread-invalid-id": "অবৈধ ঘটনা আইডি",
+ "echo-specialpage-pagination-numnotifications": "$1টি {{PLURAL:$1|বিজ্ঞপ্তি}}",
+ "echo-specialpage-pagefilters-title": "সাম্প্রতিক কার্যকলাপ",
+ "echo-specialpage-pagefilters-subtitle": "অপঠিত বিজ্ঞপ্তিসহ পাতা",
+ "notificationsmarkread-legend": "বিজ্ঞপ্তি পঠিত হিসেবে চিহ্নিত করুন",
"echo-anon": "বিজ্ঞপ্তি পেতে, [$1 অ্যাকাউন্ট তৈরি] অথবা [$2 প্রবেশ] করুন।",
"echo-none": "আপনার কোন বিজ্ঞপ্তি নাই।",
"echo-more-info": "আরও তথ্য",
"echo-feedback": "প্রতিক্রিয়া",
+ "echo-popup-footer-special-page-invitation": "<strong>পুনঃনকশা করা বিজ্ঞপ্তি পাতাটি ব্যবহার করে দেখুন।</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "নতুন চেহারায় ও নতুন বৈশিষ্ট্যে।",
"echo-quotation-marks": "“$1”",
+ "echo-api-failure": "বিজ্ঞপ্তি আনতে ব্যর্থ হয়েছে।",
+ "echo-api-failure-cross-wiki": "রিমোট ডোমেইনে প্রবেশ অস্বীকৃত হয়েছে।",
+ "echo-notification-placeholder": "এখানে কোন বিজ্ঞপ্তি নেই।",
+ "echo-notification-placeholder-filters": "এই শর্তগুলির সাথে মিলে যায় এমন কোন বিজ্ঞপ্তি নেই।",
+ "echo-notification-loginrequired": "আপনাকে আপনার বিজ্ঞপ্তি দেখতে অবশ্যই প্রবেশ করতে হবে।",
+ "echo-notification-popup-loginrequired": "আপনার বিজ্ঞপ্তি দেখতে প্রবেশ করুন",
+ "echo-notification-markasread": "পঠিত হিসেবে চিহ্নিত করুন",
+ "echo-notification-markasunread": "অপঠিত হিসেবে চিহ্নিত করুন",
+ "echo-notification-markasread-tooltip": "পঠিত হিসেবে চিহ্নিত করুন",
+ "echo-notification-more-options-tooltip": "আরো বিকল্প",
+ "notification-dynamic-actions-unwatch": "\"$1\"-এ নতুন কার্যকলাপ নজর রাখা {{GENDER:$3|বন্ধ করুন}}",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|আপনি}} আর \"$1\" পাতাটি নজরে রাখছেন না",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|আপনি}} যেকোন সময় [$2 এই পাতায়] নজরে রাখতে পারেন।",
+ "notification-dynamic-actions-watch": "\"$1\"-এ নতুন কার্যকলাপ {{GENDER:$3|অনুসরণ করুন}}",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|আপনি}} এখন \"$1\" পাতাটি নজরে রাখছেন।",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|আপনি}} যেকোন সময় [$2 এই পাতায়] নজর রাখা বন্ধ করতে পারেন।",
+ "notification-link-text-expand-all": "বিস্তৃত করুন",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1টি অবহিতি}} দেখুন",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|$1টি}} বিজ্ঞপ্তি দেখুন",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1টি বিজ্ঞপ্তি}} দেখুন",
+ "notification-link-text-collapse-all": "সংকোচন",
"notification-link-text-view-message": "বার্তা দেখাও",
"notification-link-text-view-mention": "উল্লেখণ দেখাও",
- "notification-link-text-view-changes": "পরিবর্তনসমূহ দেখাও",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|উল্লেখ দেখুন|উল্লেখগুলি দেখুন}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|পরিবর্তনসমূহ}} দেখুন",
"notification-link-text-view-page": "পাতা দেখাও",
+ "notification-header-edit-user-talk": "$1 <strong>{{GENDER:$3|আপনার}} আলাপ পাতায়</strong> একটি বার্তা {{GENDER:$2|দিয়েছেন}}।",
+ "notification-header-edit-user-talk-with-section": "$1 <strong>{{GENDER:$3|আপনার}} আলাপ পাতায়</strong> \"<strong>$4</strong>\"-এ একটি বার্তা {{GENDER:$2|দিয়েছেন}}।",
+ "notification-header-page-linked": "<strong>$4</strong> থেকে <strong>$3</strong>-এ একটি সংযোগ তৈরি করা হয়েছে।",
+ "notification-compact-header-page-linked": "<strong>$1</strong> থেকে সংযুক্ত।",
+ "notification-bundle-header-page-linked": "{{PLURAL:$5||$5টি|100=৯৯+টি}} পাতা থেকে <strong>$3</strong>-এ সংযোগ তৈরি করা হয়েছে।",
+ "notification-link-text-what-links-here": "এই পাতার সাথে সংযুক্ত সকল সংযোগ",
+ "notification-header-mention-other": "$1 <strong>$4</strong>-এর \"<strong>$5</strong>\"-এ {{GENDER:$3|আপনাকে}} {{GENDER:$2|উল্লেখ করেছেন}}।",
+ "notification-header-mention-other-nosection": "$1 <strong>$4</strong>-এ {{GENDER:$3|আপনাকে}} {{GENDER:$2|উল্লেখ করেছেন}}।",
+ "notification-header-mention-user-talkpage-v2": "$1 <strong>$4-{{GENDER:$5|এর}} ব্যবহারকারী আলাপ পাতায়</strong> \"<strong>$6</strong>\"-এ {{GENDER:$3|আপনাকে}} {{GENDER:$2|উল্লেখ করেছেন}}।",
+ "notification-header-mention-user-talkpage-nosection": "$1 <strong>$4-{{GENDER:$5|এর}} ব্যবহারকারী আলাপ পাতায়</strong> {{GENDER:$3|আপনাকে}} {{GENDER:$2|উল্লেখ করেছেন}}।",
+ "notification-header-mention-agent-talkpage": "$1 <strong>{{GENDER:$2|তাঁর}} আলাপ পাতায়</strong> \"<strong>$4</strong>\"-এ {{GENDER:$3|আপনাকে}} {{GENDER:$2|উল্লেখ করেছেন}}।",
+ "notification-header-mention-agent-talkpage-nosection": "$1 <strong>{{GENDER:$2|তাঁর|তাঁর|তাঁদের}} আলাপ পাতায়</strong> {{GENDER:$3|আপনাকে}} {{GENDER:$2|উল্লেখ করেছেন}}।",
+ "notification-header-mention-article-talkpage": "$1 <strong>$4</strong>-এর আলাপ পাতায় \"<strong>$5</strong>\"-এ {{GENDER:$3|আপনাকে}} {{GENDER:$2|উল্লেখ করেছেন}}।",
+ "notification-header-mention-article-talkpage-nosection": "$1 ''$4'''-এর আলাপ পাতায় {{GENDER:$3|আপনাকে}} {{GENDER:$2|উল্লেখ করেছেন}}।",
+ "notification-header-mention-failure-user-unknown": "<strong>$3</strong>-এর জন্য {{GENDER:$2|আপনার করা}} উল্লেখ পাঠানো যায়নি কারণ ব্যবহারকারীকে পাওয়া যায়নি।",
+ "notification-header-mention-failure-user-anonymous": "<strong>$3</strong>-এর জন্য {{GENDER:$2|আপনার করা}} উল্লেখ পাঠানো যায়নি কারণ ব্যবহারকারী বেনামী ছিলেন।",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|আপনার}} করা উল্লেখগুলি পাঠানো যায়নি কারণ তা $3-এর সীমা ছাড়িয়ে গেছে।",
+ "notification-header-mention-failure-bundle": "<strong>$4</strong> আলাপ পাতায় {{GENDER:$2|আপনার করা}} {{PLURAL:$3|একটি উল্লেখ|$3টি উল্লেখ}} পাঠানো যায়নি।",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>ব্যবহারকারী নামের অস্তিত্ব নেই:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>আইপিসমূহকে উল্লেখ করা যাবে না:</strong> $1",
+ "notification-header-mention-success": "<strong>$3</strong>-এর জন্য {{GENDER:$2|আপনার করা}} উল্লেখ পাঠানো হয়েছে।",
+ "notification-header-mention-success-bundle": "<strong>$4</strong> আলাপ পাতায় {{GENDER:$2|আপনার করা}} {{PLURAL:$3|একটি উল্লেখ|$3টি উল্লেখ}} পাঠানো হয়েছে।",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|আপনি উল্লেখ করেছেন}}:</strong> $3",
+ "notification-header-mention-status-bundle": "<strong>$4</strong> আলাপ পাতায় {{GENDER:$2|আপনার করা}} উল্লেখ সম্পর্কে {{PLURAL:$3|একটি বিজ্ঞপ্তি|$3টি বিজ্ঞপ্তি}}: {{PLURAL:$5|$5টি পাঠানো যায়নি}}, {{PLURAL:$6|$6টি পাঠানো গেছে}}।",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|আপনার}} ব্যবহারকারী অধিকার {{GENDER:$1|পরিবর্তিত হয়েছে}}। আপনাকে এখানে যোগ করা হয়েছে: $2।",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|আপনার}} ব্যবহারকারী অধিকার {{GENDER:$1|পরিবর্তিত হয়েছে}}। আপনি এখন আর এই দলের সদস্য নন: $2।",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|আপনার}} ব্যবহারকারী অধিকার {{GENDER:$1|পরিবর্তিত হয়েছে}}। আপনাকে এখানে যোগ করা হয়েছে: $2। আপনি এখন আর এই দলের সদস্য নন: $4।",
+ "notification-header-user-rights-expiry-change": "নিন্মলিখিত {{PLURAL:$3|দলে|দলগুলিতে}} {{GENDER:$4|আপনার}} সদস্যতা শেষ হওয়ার সময়সীমা {{GENDER:$1|পরিবর্তিত হয়েছে}}: $2।",
+ "notification-header-welcome": "{{SITENAME}}-এ {{GENDER:$2|স্বাগতম}}, $1! {{GENDER:$2|আপনাকে}} এখানে দেখে আমরা আনন্দিত।",
+ "notification-welcome-linktext": "স্বাগতম",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|আপনি}} এইমাত্র {{GENDER:$2|আপনার}} প্রথম সম্পাদনা করেছেন; {{GENDER:$2|আপনাকে}} ধন্যবাদ, এবং স্বাগতম!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|আপনি}} এইমাত্র {{GENDER:$2|আপনার}} দশম সম্পাদনা করেছেন; {{GENDER:$2|আপনাকে}} ধন্যবাদ, এবং দয়া করে অব্যাহত রাখুন!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|আপনি}} এইমাত্র {{GENDER:$2|আপনার}} শততম সম্পাদনা করেছেন; {{GENDER:$2|আপনাকে}} অনেক ধন্যবাদ!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|আপনি}} এইমাত্র {{GENDER:$2|আপনার}} এক হাজারতম সম্পাদনা করেছেন; একজন দুর্দান্ত অবদানকারী হওয়ার জন্য {{GENDER:$2|আপনাকে}} ধন্যবাদ!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|আপনি}} এইমাত্র {{GENDER:$2|আপনার}} দশ হাজারতম সম্পাদনা করেছেন; {{GENDER:$2|আপনাকে}} অনেক ধন্যবাদ!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|আপনি}} এইমাত্র {{GENDER:$2|আপনার}} এক লক্ষতম সম্পাদনা করেছেন; একজন অসাধারণ অবদানকারী হওয়ার জন্য {{GENDER:$2|আপনাকে}} ধন্যবাদ!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|আপনি}} এইমাত্র {{GENDER:$2|আপনার}} এক লক্ষতম সম্পাদনা করেছেন; একজন অসাধারণ অবদানকারী হওয়ার জন্য {{GENDER:$2|আপনাকে}} ধন্যবাদ!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|আপনার}} সম্পাদনা",
"notification-link-text-view-edit": "সম্পাদনা দেখাও",
- "notification-edit-talk-page2": "[[User:$1|$1]] আপনার [[User talk:$2#$3|আলাপ পাতায়]] একটি বার্তা {{GENDER:$1|রেখেছেন}}।",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] আপনার আলাপ পাতার \"[[User talk:$2#$3|$4]]\"-এ একটি বার্তা {{GENDER:$1|রেখেছেন}}।",
- "notification-edit-talk-page-flyout2": "$1 আপনার [[User talk:$2#$3|আলাপ পাতায়]] একটি বার্তা {{GENDER:$1|রেখেছেন}}।",
- "notification-edit-talk-page-flyout-with-section": "$1 আপনার আলাপ পাতার \"[[User talk:$2#$3|$4]]\"-এ একটি বার্তা {{GENDER:$1|রেখেছেন}}।",
- "notification-page-linked": "[[:$3]] থেকে [[:$2]] {{GENDER:$1|সংযুক্ত}} রয়েছে। [[Special:WhatLinksHere/$2|এই পাতার সাথে সকল সংযোগ দেখুন]]।",
- "notification-page-linked-flyout": "[[:$3]] থেকে [[:$2]] {{GENDER:$1|সংযুক্ত}} রয়েছে।",
- "notification-add-comment2": "[[User:$1|$1]] \"[[$3|$2]]\" সম্পর্কে \"$4\"-এর আলাপ পাতায় {{GENDER:$1|মন্তব্য করেছেন}}।",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] [[$3]]-এ \"$2\" সম্পর্কে একটি নতুন বিষয় {{GENDER:$1|পোষ্ট করেছেন}}।",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] আপনাকে একটি বার্তা {{GENDER:$1|পাঠিয়েছেন}}: \"[[$3#$2|$2]]\"।",
- "notification-add-comment-yours2": "[[User:$1|$1]] আপনার আলাপ পাতায় \"[[$3#$2|$2]]\" সম্পর্কে {{GENDER:$1|মন্তব্য করেছেন}}।",
- "notification-mention": "[[User:$1|$1]] $5-এর আলাপ পাতায় [[:$3#$2|$4]]-এ আপনাকে {{GENDER:$1|উল্লেখ করেছেন}}।",
- "notification-mention-flyout": "$1 $5-এর আলাপ পাতায় \"[[:$3#$2|$4]]\"-এ আপনাকে {{GENDER:$1|উল্লেখ করেছেন}}।",
- "notification-mention-nosection": "[[User:$1|$1]] [[:$3|$2-এর আলাপ পাতায়]] আপনাকে {{GENDER:$1|উল্লেখ করেছেন}}।",
- "notification-mention-nosection-flyout": "$1 [[:$3|$2-এর আলাপ পাতায়]] আপনাকে {{GENDER:$1|উল্লেখ করেছেন}}।",
- "notification-user-rights": "[[User:$1|$1]] আপনার ব্যবহারকারী অধিকার [[Special:Log/rights/$1|{{GENDER:$1|পরিবর্তন করেছেন}}]]। $2। [[Special:ListGroupRights|আরও জানুন]]",
- "notification-user-rights-flyout": "$1 আপনার ব্যবহারকারী অধিকার {{GENDER:$1|পরিবর্তন করেছেন}}। $2। [[Special:ListGroupRights|আরও জানুন]]",
- "notification-user-rights-add": "আপনি এখন থেকে {{PLURAL:$2|এই দলের|এই দলসমূহের}} একজন সদস্য: $1",
- "notification-user-rights-remove": "আপনি আর {{PLURAL:$2|এই দলের|এই দলসমূহের}} সদস্য নন।: $1",
- "notification-new-user": "{{SITENAME}} সাইটে স্বাগতম, $1! আপনাকে এখানে পেয়ে আমরা খুব আনন্দিত।",
- "notification-reverted2": "{{PLURAL:$4[[:$2]]-এ আপনার সম্পাদনা|[[:$2]]-এ আপনার সম্পাদনাগুলো}} [[User:$1|$1]] দ্বারা {{GENDER:$1|পূর্বাবস্থায়}} নেওয়া হয়েছে। $3",
- "notification-reverted-flyout2": "$2-এ আপনার {{PLURAL:$4|সম্পাদনা|সম্পাদনাগুলো}} $1 দ্বারা {{GENDER:$1|পূর্বাবস্থায়}} নেয়া হয়েছে। $3",
+ "notification-link-article-reminder": "পাতা দেখুন",
+ "notification-header-reverted": "<strong>$3</strong>-এ আপনার করা {{PLURAL:$4|সম্পাদনা|সম্পাদনাগুলো}} {{GENDER:$2|পূর্বাবস্থায় নেয়া হয়েছে}}।",
+ "notification-header-emailuser": "$1 আপনাকে একটি ইমেইল {{GENDER:$2|পাঠিয়েছেন}}।",
"notification-edit-talk-page-email-subject2": "$1 {{SITENAME}} এ আপনার জন্য একটি বার্তা {{GENDER:$1|রেখেছেন}}",
- "notification-edit-talk-page-email-batch-body2": "$1 আপনার আলাপ পাতায় একটি বার্তা {{GENDER:$1|রেখেছেন}}।",
"notification-edit-talk-page-email-batch-body-with-section": "$1 আপনার আলাপ পাতায় \"$2\"-এ একটি বার্তা {{GENDER:$1|রেখেছেন}}।",
"notification-page-linked-email-subject": "আপনার তৈরিকৃত একটি পাতা {{SITENAME}} সাইটে সংযোগ করা হয়েছে।",
- "notification-page-linked-email-batch-body": "$2 পাতাটি $3 হতে {{GENDER:$1|সংযুক্ত}}।",
"notification-reverted-email-subject2": "{{SITENAME}}-এ আপনার {{PLURAL:$3|সম্পাদনা|সম্পাদনাগুলো}} {{GENDER:$1|পূর্বাবস্থায়}} নেয়া হয়েছে",
- "notification-reverted-email-batch-body2": "$1 দ্বারা {{PLURAL:$3|$2-এ আপনার সম্পাদনা|$2-এ আপনার সম্পাদনাগুলি}} {{GENDER:$1|পূর্বাবস্থায়}} নেয়া হয়েছে।",
- "notification-mention-email-subject": "$1 আপনাকে {{SITENAME}}-এ {{GENDER:$1|উল্লেখ করেছেন}}",
- "notification-mention-email-batch-body": "$1 আপনাকে $4-এর আলাপ পাতায় \"$3\"-এ {{GENDER:$1|উল্লেখ করেছেন}}।",
- "notification-mention-nosection-email-batch-body": "$1 $2-এর আলাপ পাতায় আপনাকে {{GENDER:$1|উল্লেখ করেছেন}}।",
- "notification-user-rights-email-subject": "{{SITENAME}}-এ আপনার ব্যবহারকারী অধিকার পরবর্তন হয়েছে",
- "notification-user-rights-email-batch-body": "$1 আপনার অধিকারসমূহ {{GENDER:$1|পরিবর্তন করেছেন}}। $2।",
- "echo-email-subject-default": "{{SITENAME}} এ নতুন বিজ্ঞপ্তি",
- "echo-email-body-default": "{{SITENAME}} এ আপনার একটি নতুন বিজ্ঞপ্তি রয়েছে:\n\n$1",
- "echo-email-batch-body-default": "আপনার নতুন একটি বিজ্ঞপ্তি রয়েছে।",
- "echo-email-footer-default": "$2\n\nযে ইমেইল আমরা আপনাকে পাঠাই তা নিয়ন্ত্রণ করতে, আপনার পছন্দসমূহ পরীক্ষা করুন:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|আপনাকে}} {{SITENAME}}-এ {{GENDER:$1|উল্লেখ করেছেন}}",
+ "notification-user-rights-email-subject": "{{SITENAME}}-এ আপনার ব্যবহারকারী অধিকার পরিবর্তন হয়েছে",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 সে}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 মি}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ঘ}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 দিন}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 মাস}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 বছর}}",
+ "notification-timestamp-today": "আজ",
+ "notification-timestamp-yesterday": "গতকাল",
+ "notification-inbox-filter-read": "পঠিত",
+ "notification-inbox-filter-unread": "অপঠিত",
+ "notification-inbox-filter-all": "সব",
+ "echo-email-body-default": "{{SITENAME}}-এ আপনার একটি নতুন বিজ্ঞপ্তি রয়েছে:\n\n$1",
"echo-email-footer-default-html": "যে ইমেইল আমরা আপনাকে পাঠাই তা নিয়ন্ত্রণ করতে, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">আপনার পছন্দসমূহ পরীক্ষা করুন</a>।<br />\n$1",
+ "echo-email-footer-default": "$2\n\nযে ইমেইল আমরা আপনাকে পাঠাই তা নিয়ন্ত্রণ করতে, আপনার পছন্দসমূহ পরীক্ষা করুন:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "আমরা {{GENDER:$1|আপনাকে}} কোন ইমেইল পাঠাই তা নিয়ন্ত্রণ করতে, {{GENDER:$1|আপনার}} পছন্দসমূহ পরীক্ষা করুন:",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|আপনার}} পছন্দসমূহ পরীক্ষা করুন",
+ "echo-email-html-footer-with-link": "আমরা {{GENDER:$2|আপনাকে}} যে ইমেইল পাঠাই তা নিয়ন্ত্রণ করতে, $1।",
"echo-notification-alert": "{{PLURAL:$1|অবহিতি ($1)|100=অবহিতি (৯৯+)}}",
- "echo-notification-message": "{{PLURAL:$1|বার্তা ($1)|100=বার্তা (৯৯+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|বিজ্ঞপ্তি ($1)|100=বিজ্ঞপ্তি (৯৯+)}}",
"echo-notification-alert-text-only": "অবহিতি",
- "echo-notification-message-text-only": "বার্তা",
+ "echo-notification-notice-text-only": "বিজ্ঞপ্তি",
"echo-overlay-link": "সকল বিজ্ঞপ্তি",
"echo-overlay-title": "<b>বিজ্ঞপ্তি</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|বিজ্ঞপ্তি}}</b> (অপঠিত $2টির মধ্যে $1টি প্রদর্শিত হচ্ছে)",
- "echo-mark-all-as-read": "সব পঠিত বলে চিহ্নিত",
+ "echo-mark-all-as-read": "সব পঠিত হিসেবে চিহ্নিত করুন",
+ "echo-mark-all-as-read-confirmation": "$1টি {{PLURAL:$1|বিজ্ঞপ্তি}} পঠিত হিসেবে করা হয়েছে",
+ "echo-mark-wiki-as-read": "নির্বাচিত উইকিতে সব পঠিত হিসেবে চিহ্নিত করুন: $1",
"echo-date-today": "আজ",
"echo-date-yesterday": "গতকাল",
"echo-load-more-error": "আরও ফলাফল আনার সময় কোনো ত্রুটি হয়েছে।",
- "notification-edit-talk-page-bundle": "$1 এবং আরো $3 {{PLURAL:$4|জন}} [[User talk:$2|আপনার আলাপ পাতায়]] একটি {{GENDER:$1|বার্তা}} রেখেছেন।",
- "notification-page-linked-bundle": "$3 এবং আরো $4টি {{PLURAL:$5|পাতায়}} $2 পাতার {{GENDER:$1|সংযোগ}} রয়েছে।[[Special:WhatLinksHere/$2|সংযোগকারী পাতাগুলিকে দেখুন]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 এবং আরও $2 {{PLURAL:$3|জন}} আপনার আলাপ পাতায় বার্তা {{GENDER:$1|দিয়েছেন}}।",
- "notification-page-linked-email-batch-bundle-body": "$3 এবং আরো $4টি {{PLURAL:$5|পাতায়}} $2 পাতার {{GENDER:$1|সংযোগ}} রয়েছে।",
+ "notification-bundle-header-edit-user-talk-v2": "আপনি <strong>{{GENDER:$3|আপনার}} আলাপ পাতায়</strong> {{PLURAL:$1|একটি|$1টি|100=৯৯+টি}} নতুন বার্তা পেয়েছেন।",
"echo-email-batch-subject-daily": "আপনি {{SITENAME}}-এ {{PLURAL:$2|একটি নতুন বিজ্ঞপ্তি|নতুন বিজ্ঞপ্তিসমূহ}} পেয়েছেন",
"echo-email-batch-subject-weekly": "এই সপ্তাহে আপনি {{SITENAME}}-এ {{PLURAL:$2|একটি নতুন বিজ্ঞপ্তি|নতুন বিজ্ঞপ্তিসমূহ}} পেয়েছেন",
"echo-email-batch-body-intro-daily": "প্রিয় $1,\n{{SITENAME}} সাইটে আপনার জন্য দিনের কার্যক্রমের সারাংশ এখানে দেওয়া হল।",
"echo-email-batch-body-intro-weekly": "প্রিয় $1,\n{{SITENAME}} সাইটে আপনার জন্য সপ্তাহের কার্যক্রমের সারাংশ এখানে দেওয়া হল।",
"echo-email-batch-link-text-view-all-notifications": "সকল বিজ্ঞপ্তি দেখাও",
- "echo-rev-deleted-text-view": "এই পাতা সংস্করণটি বাতিল করা হয়েছে।",
- "apihelp-echomarkread-description": "বর্তমান ব্যবহারকারীর জন্য বিজ্ঞপ্তি পঠিত হিসাবে চিহ্নিত করে।",
- "apihelp-echomarkread-example-1": "বিজ্ঞপ্তি ৮ দেখা হয়েছে হিসাবে চিহ্নিত করে",
- "apihelp-echomarkread-example-2": "পঠিত হিসাবে সকল বিজ্ঞপ্তি চিহ্নিত করুন",
- "apihelp-echomarkseen-example-1": "সব ধরনের বিজ্ঞপ্তি দেখা হয়েছে হিসাবে চিহ্নিত করে",
- "apihelp-query+notifications-param-prop": "অনুরোধের বিবরণ।",
- "apihelp-query+notifications-param-messagecontinue": "যখন আরো বার্তা ফলাফল উপলব্ধ থাকে, তা অব্যাহত রাখার জন্য এটি ব্যবহার করুন।",
- "apihelp-query+notifications-example-1": "বিজ্ঞপ্তির তালিকা",
- "apihelp-query+notifications-example-2": "বিজ্ঞপ্তির তালিকা, গণনাসহ, দলগতভাবে অনুচ্ছেদে ভাগ করা"
+ "notification-header-foreign-alert": "{{PLURAL:$5|আরেকটি উইকি থেকে|$5টি উইকি থেকে}} আরো অবহিতি",
+ "notification-header-foreign-notice": "{{PLURAL:$5|আরেকটি উইকি|$5টি উইকি}} থেকে আরো বিজ্ঞপ্তি",
+ "notification-header-foreign-all": "{{PLURAL:$5|আরেকটি উইকি|$5টি উইকি}} থেকে আরো বিজ্ঞপ্তি",
+ "echo-badge-count": "{{PLURAL:$1|$1|100=৯৯+}}"
}
diff --git a/Echo/i18n/bqi.json b/Echo/i18n/bqi.json
new file mode 100644
index 00000000..64f27430
--- /dev/null
+++ b/Echo/i18n/bqi.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mogoeilor"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|ايسا}} آلشدا"
+}
diff --git a/Echo/i18n/br.json b/Echo/i18n/br.json
index 62209ef7..fed64e0d 100644
--- a/Echo/i18n/br.json
+++ b/Echo/i18n/br.json
@@ -4,92 +4,100 @@
"Fohanno",
"Fulup",
"Y-M D",
- "Gwenn-Ael"
+ "Gwenn-Ael",
+ "Pymouss"
]
},
- "echo-desc": "Reizhiad kemennoù",
+ "echo-desc": "Reizhiad da gas keloù d'an implijerien diwar-benn darvoudoù ha kemennadennoù",
"prefs-echo": "Kemennoù",
"prefs-emailsettings": "Dibarzhioù postel",
"prefs-displaynotifications": "Dibarzhioù diskwel",
- "prefs-echosubscriptions": "Kemenn din an darvoudoù-mañ",
+ "prefs-echosubscriptions": "Kas keloù din diwar-benn an darvoudoù-mañ",
+ "prefs-echocrosswiki": "Kemennoù etrewiki",
"prefs-newmessageindicator": "Merker kemennadenn nevez",
"echo-pref-send-me": "Kas din :",
"echo-pref-send-to": "Kas da :",
"echo-pref-email-format": "Furmad ar postel :",
"echo-pref-web": "Web",
"echo-pref-email": "Postel",
- "echo-pref-email-frequency-never": "Arabat kas posteloù kemenn din",
- "echo-pref-email-frequency-immediately": "Kemennoù hiniennel evel ma teuont",
+ "echo-pref-email-frequency-never": "Arabat kas kemennoù din dre bostel",
+ "echo-pref-email-frequency-immediately": "Kemennoù hiniennel bep ma teuont",
"echo-pref-email-frequency-daily": "Un diverrañ pemdeziek eus ar c'hemennoù",
"echo-pref-email-frequency-weekly": "Un diverrañ sizhuniek eus ar c'hemennoù",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Testenn blaen",
+ "echo-pref-cross-wiki-notifications": "Diskouez kemennoù eus wikioù all",
+ "echo-pref-beta-feature-cross-wiki-message": "Kemennoù gwellaet",
"echo-learn-more": "Gouzout hiroc'h",
- "echo-new-messages": "Kemennadennoù nevez zo ganeoc'h",
- "echo-category-title-edit-user-talk": "{{PLURAL:$1|Kemennadenn|Kemennadennoù}} ar bajenn gaozeal",
+ "echo-new-messages": "Kemennadennoù nevez hoc'h eus",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|Ur gemennadenn|Kemennadennoù}} er bajenn gaozeal",
"echo-category-title-article-linked": "Pajenn {{PLURAL:$1|link}}",
"echo-category-title-reverted": "{{PLURAL:$1|Kemm|Kemmoù}} nullet",
"echo-category-title-mention": "{{PLURAL:$1|Meneg}}",
"echo-category-title-other": "{{PLURAL:$1|All}}",
"echo-category-title-system": "{{PLURAL:$1|Sistem}}",
- "echo-pref-tooltip-edit-user-talk": "Kemenn din pa vez postet ur gemennadenn gant unan bennak pe pa respont war ma fajenn gaozeal.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Postel digant un implijer all|Posteloù digant implijerien all}}",
+ "echo-pref-tooltip-edit-user-talk": "Kemenn din pa vez postet ur gemennadenn pe pa vez respontet din gant unan bennak war ma fajenn gaozeal.",
"echo-pref-tooltip-article-linked": "Ma c'hemenn pa vez graet ul liamm war-du ur bajennn am eus krouet gant unan bennak adalek pajenn ur pennad.",
+ "echo-pref-tooltip-reverted": "Kemenn din pa vez distaolet ur c'hemm graet ganin, en ur ober gant an ostilh disteurel pe distreiñ.",
"echo-pref-tooltip-mention": "Kelaouiñ ac'hanon pa vez menneget va fajenn implijer gant unan bennak.",
"echo-pref-tooltip-user-rights": "Kelaouiñ ac'hanon pa vez kemmet va gwirioù implijer gant unan bennak.",
- "echo-no-agent": "[Den]",
- "echo-no-title": "[Pajenn ebet]",
+ "echo-error-no-formatter": "N'eus bet spisaet furmad ebet evit ar c'hemennadennoù.",
"notifications": "Kemennoù",
- "tooltip-pt-notifications-alert": "{{GENDER:|Ho}} kememmoù diwall",
- "tooltip-pt-notifications-message": "{{GENDER:|Ho}} kemennoù",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Ho}} kemennoù-diwall",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Ho}} kemennoù",
+ "echo-displaynotificationsconfiguration": "Diskwel kefluniadur ar c'hemennoù",
+ "echo-displaynotificationsconfiguration-summary": "Setu aze ur brassell war ar mod m'eo kefluniet ar c'hemennoù er wiki-mañ.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Kemennoù dre rummad",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "E pe rann emañ urzhiet kement doare kemenn zo",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Peseurt hentenn kemenn zo skoret evit pep rummad",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Implijerien nevez",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Rekis eo kaout hentennoù kemenn",
"echo-specialpage": "Kemennoù",
+ "echo-specialpage-markasread": "Kemenn : merket evel lennet",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|c'hemenn|kemenn}}",
+ "echo-specialpage-pagefilters-subtitle": "Pajennoù enno kemennoù n'int ket bet lennet",
"echo-anon": "Evit resev kemennoù, [$1 krouit ur gont] pe [$2 kevreit].",
"echo-none": "N'ho peus resevet kemenn ebet.",
"echo-more-info": "Gouzout hiroc'h",
"echo-feedback": "Sonjoù",
+ "echo-popup-footer-special-page-invitation": "<strong>Klaskit gant ar bajenn kemennoù, un tres nevez zo ganti.</strong> [$2 $1]",
+ "echo-api-failure": "N'eus ket bet gallet mont da gerc'hat ar c'hemennadennoù.",
+ "echo-notification-placeholder": "N'eus kemenn ebet.",
+ "echo-notification-loginrequired": "Ret eo deoc'h kevreañ evit gallout lenn ho kemennoù.",
+ "notification-link-text-expand-alert-count": "Diskouez $1 galv-diwall",
+ "notification-link-text-expand-all-count": "Gwelet {{PLURAL:$1|$1 c'hemenn|$1 kemenn}}",
+ "notification-link-text-collapse-all": "Pakañ",
"notification-link-text-view-message": "Gwelet ar gemennadenn",
"notification-link-text-view-mention": "Gwelet ar meneg",
"notification-link-text-view-changes": "Diskouez ar c'hemmoù",
"notification-link-text-view-page": "Gwelet ar bajenn",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|en deus|he deus}} skrivet ur c'hemennad war <strong>{{GENDER:$3|ho}} pajenn gaozeal</strong> e kevrenn \"<strong>$4</strong>\".",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Ur c'hemenn|$3 kemen}} diwar-benn menegoù {{GENDER:$2|graet ganeoc'h}} e bajenn gaozeal <strong>$4</strong> : $5 {{PLURAL:$5|n'eo ket bet kaset|n'int ket bet kaset}}, ha {{PLURAL:$6|$6 zo bet kaset}}.",
"notification-link-text-view-edit": "Gwelet ar c'hemm",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|en deus|he deus}} lezet ur gemennadenn war ho [[User talk:$2#$3|pajenn gaozeal]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|en deus|he deus}} lezet ur gemennadenn war ho pajenn kaozeal e-barzh \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|en deus|he deus}} lezet ur gemennadenn war ho [[User talk:$2#$3|pajenn gaozeal]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|en deus|he deus}} lezet ur gemennadenn war ho pajenn gaozeal e-barzh \"[[User talk:$2#$3|$4]]\".",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|en deus|he deus}} kaset ur gemennadenn deoc'h: \"[[$3#$2|$2]]\".",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|en deus|he deus}} meneget ac'hanoc'h war ar bajenn gaozeal $5 e-barzh \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|en deus|he deus}} meneget ac'hanoc'h war ar bajenn gaozeal $5 e-barzh \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|en deus|he deus}} meneget ac'hanoc'h war [[:$3|pajenn gaozeal $2]].",
- "notification-user-rights-add": "Bremañ ez oc'h un ezel eus {{PLURAL:$2|ar strollad-mañ|ar strolladoù-mañ}}: $1",
- "notification-user-rights-remove": "N'oc'h ket ken un ezel eus ar {{PLURAL:$2|strollad|strolladoù}}-mañ : $1",
- "notification-new-user": "Degemer mat er {{SITENAME}}, $1!",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|en|he}} deus laosket deoc'h ur gemennadenn\nwar {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|en deus|he deus}} lezet ur gemennadenn war ho pajenn gaozeal :",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|en deus|he deus}} embannet ur gemennadenn war ho pajenn gaozeal diwar-benn \"$2\".",
"notification-page-linked-email-subject": "Liammet eo bet ho pajenn ouzh {{SITENAME}}",
"notification-mention-email-subject": "$1 {{GENDER:$1|en deus|he deus}} ho meneget war {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|en deus|he deus}} meneget ac'hanoc'h war ar bajenn gaozeal $4 e-barzh \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|en deus|he deus}} meneget ac'hanoc'h war ar bajenn gaozeal $2.",
"notification-user-rights-email-subject": "Cheñchet eo ho kwirioù implijer war {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Kemmet eo bet ho kwirioù implijer gant $1. $2.",
- "echo-email-subject-default": "Kemenn nevez e {{SITENAME}}",
- "echo-email-body-default": "Ur c'hemenn nevez ho peus war {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Ur c'hemenn nevez ho peus resevet.",
+ "notification-inbox-filter-read": "Lennet",
+ "notification-inbox-filter-unread": "Anlennet",
+ "echo-email-body-default": "Ur gemennadenn nevez zo ganeoc'h war {{SITENAME}}:\n\n$1",
"echo-email-footer-default": "$2\n\nEvit kontrollañ peseurt posteloù a gasomp deoc'h, gwiriit ho penndibaboù : {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Evit kontrollañ peseurt posteloù a gasomp deoc'h, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">gwiriit ho tibaboù</a>.<br />\n$1",
- "echo-notification-message": "{{PLURAL:$1|Kemennadenn ($1)|Kemennadennoù ($1)|100=Kemennadennoù (99+)}}",
- "echo-notification-message-text-only": "Kemennadennoù",
+ "echo-notification-alert-text-only": "Kemennoù-diwall",
"echo-overlay-link": "An holl gemennoù",
"echo-overlay-title": "<b>Kemennoù</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Kemennoù}}</b> (o tiskouez $1 diwar $2 nann-lennet)",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Kemenn|Kemennoù}}</b> (o tiskouez $1 diwar $2 hep lenn)",
"echo-mark-all-as-read": "Merkañ an holl evel lennet",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|c'hemenn|kemenn}} merket evel lennet",
"echo-date-today": "Hiziv",
"echo-date-yesterday": "Dec'h",
"echo-load-more-error": "Ur fazi zo bet en ur glask disoc'hoù all.",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 hag $2 {{PLURAL:$3|unan|re}} all {{GENDER:$1|o deus}} lezet ur gemennadenn war ho pajenn gaozeal.",
"echo-email-batch-subject-daily": "{{PLURAL:$2|Ur c'hemenn|Kemennoù}} nevez hoc'h eus war {{SITENAME}}",
- "echo-email-batch-subject-weekly": "{{PLURAL:$2|Ur c'hemenn|Kemennoù}} nevez hoc'h eus war {{SITENAME}} ar sizhun-mañ",
+ "echo-email-batch-subject-weekly": "{{PLURAL:$2|Ur c'hemenn|Kemennoù}} nevez hoc'h eus war {{SITENAME}} er sizhun-mañ",
"echo-email-batch-body-intro-daily": "Demat deoc'h $1,\nSetu amañ un diverradur eus obererezh an deiz war {{SITENAME}} evidoc'h.",
"echo-email-batch-body-intro-weekly": "Demat deoc'h $1,\nSetu amañ un diverradur eus obererezh ar sizhun-mañ war {{SITENAME}} evidoc'h.",
- "echo-email-batch-link-text-view-all-notifications": "Gwelet an holl gemennoù",
- "echo-rev-deleted-text-view": "Lamet eo bet an adwel pajenn-mañ."
+ "echo-email-batch-link-text-view-all-notifications": "Gwelet an holl gemennadennoù",
+ "notification-header-foreign-alert": "Muioc'h a c'halvoù-diwall eus {{PLURAL:$5|ur wiki-all|$5 wiki-all}}",
+ "notification-header-foreign-all": "Kemennoù ouzhpenn war {{PLURAL:$5|ur wiki all|$5 wiki all}}"
}
diff --git a/Echo/i18n/bs.json b/Echo/i18n/bs.json
index 0c09f2a3..32ac8c86 100644
--- a/Echo/i18n/bs.json
+++ b/Echo/i18n/bs.json
@@ -7,113 +7,195 @@
"Palapa",
"KWiki",
"Semso98",
- "Srdjan m"
+ "Srdjan m",
+ "Macofe"
]
},
- "echo-desc": "Obavještajni sistem",
+ "echo-desc": "Sistem za obavještavanje korisnika o dešavanjima i porukama",
"prefs-echo": "Obavještenja",
"prefs-emailsettings": "Opcije e-pošte",
"prefs-displaynotifications": "Opcije prikaza",
- "prefs-echosubscriptions": "Obavijesti me o tim događajima",
+ "prefs-echosubscriptions": "Obavijesti me o ovim događajima",
+ "prefs-echocrosswiki": "Obavještenja s drugih wikija",
"prefs-newmessageindicator": "Indikator za nove poruke",
+ "prefs-blocknotificationslist": "Crna lista",
"echo-pref-send-me": "Pošalji mi:",
- "echo-pref-send-to": "Pošalji:",
+ "echo-pref-send-to": "Pošalji na:",
"echo-pref-email-format": "Format e-pošte:",
- "echo-pref-web": "Web",
- "echo-pref-email": "E-pošta",
+ "echo-pref-web": "Na wikiju",
+ "echo-pref-email": "E-poštom",
"echo-pref-email-frequency-never": "Ne šalji mi obavještenja preko e-pošte",
- "echo-pref-email-frequency-immediately": "Lična obavještenja kako dolaze u",
+ "echo-pref-email-frequency-immediately": "Pojedinačna obavještenja čim se pojave",
"echo-pref-email-frequency-daily": "Dnevni sažetak obavještenja",
"echo-pref-email-frequency-weekly": "Sedmični sažetak obavještenja",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Obični tekst",
- "echo-pref-new-message-indicator": "Pokaži indikator da je dobijena poruka na stranici za razgovor u mojoj alatnoj traci",
+ "echo-pref-cross-wiki-notifications": "Prikaži obavještenja s drugih wikija",
+ "echo-pref-notifications-blacklist": "Spisak korisnika koji Vam, u većini slučajeva, neće moći slati obavještenja koristeći Echo (ne utiče na izmjene na Vašoj stranici za razgovor; [[mw:Help:Notifications#mute|detaljnije]])",
+ "echo-pref-new-message-indicator": "Prikaži indikator da je dobijena poruka na stranici za razgovor u mojoj alatnoj traci",
+ "echo-pref-beta-feature-cross-wiki-message": "Poboljšana obavještenja",
+ "echo-pref-beta-feature-cross-wiki-description": "Omogućava lakši pregled i organizaciju obavještenja. Također omogućava obavještenja kad dobijete poruku na drugim wikijima. (Da biste vidjeli obavještenja s nekog wikija, na tom wikiju morate aktivirati ovu beta mogućnost.)",
"echo-learn-more": "Saznajte više",
+ "echo-log": "Javni zapisnik",
"echo-new-messages": "Imate nove poruke",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Poruke}} na stranici za razgovor",
"echo-category-title-article-linked": "{{PLURAL:$1|Linkovi na stranicu}}",
"echo-category-title-reverted": "{{PLURAL:$1|Vraćanje izmjena}}",
"echo-category-title-mention": "{{PLURAL:$1|Spominjanje|Spominjanja}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Neuspješno spominjanje|Neuspješna spominjanja}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Uspješno spominjanje|Uspješna spominjanja}}",
"echo-category-title-other": "{{PLURAL:$1|Ostalo}}",
"echo-category-title-system": "{{PLURAL:$1|Sistem}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Promjena korisničkih prava}}",
- "echo-pref-tooltip-edit-user-talk": "Obavijesti me kad neko ostavi poruku ili odgovor na mojoj stranici za razgovor.",
- "echo-pref-tooltip-article-linked": "Obavijesti me kada neko linkuje na stranicu koju sam napravio od stranice članaka.",
- "echo-pref-tooltip-reverted": "Obavijesti me kada neko vrati uređivanje koje sam napravio/la, korištenjem naredbe undo ili alatom za vraćanje.",
- "echo-pref-tooltip-mention": "Obavijesti me kada me neko spomene na nekoj stranici za razgovor.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-pošta od drugog korisnika|E-pošta od drugih korisnika}}",
+ "echo-pref-tooltip-edit-user-talk": "Obavijesti me kad mi neko odgovori ili postavi novu poruku na mojoj stranici za razgovor.",
+ "echo-pref-tooltip-article-linked": "Obavijesti me kad neko poveže stranicu koju sam napravio/-la s nekom drugom stranicom.",
+ "echo-pref-tooltip-reverted": "Obavijesti me kad neko poništi ili vrati moje uređivanje.",
+ "echo-pref-tooltip-mention": "Obavijesti me kad neko doda link ka mojoj korisničkoj stranici.",
+ "echo-pref-tooltip-mention-failure": "Obavijesti me kad neko nije dobio obavještenje nakon što ih spomenem.",
+ "echo-pref-tooltip-mention-success": "Obavijesti me kad neko uspješno dobije obavještenje nakon što ih spomenem.",
"echo-pref-tooltip-user-rights": "Obavijesti me kad neko promijeni moja korisnička prava.",
- "echo-no-agent": "[Niko]",
- "echo-no-title": "[Nema stranice]",
+ "echo-pref-tooltip-emailuser": "Obavijesti me kad mi neko pošalje e-poruku.",
"echo-error-no-formatter": "Nema formatiranja određenog za obavještavanje.",
"notifications": "Obavještenja",
"tooltip-pt-notifications-alert": "{{GENDER:|Vaša}} obavještenja",
- "tooltip-pt-notifications-message": "{{GENDER:|Vaše}} poruke",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Vaša}} sitna obavještenja",
+ "echo-displaynotificationsconfiguration": "Konfiguracija prikaza obavještenja",
+ "echo-displaynotificationsconfiguration-summary": "Ovo je pregled toga kako su obavještenja postavljena na ovoj wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Obavještenja po kategoriji",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sortiranje po vrstama",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "U koji će se dio svaka vrsta obavještenja sortirati",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Dozvoljene metode za obavještavanje",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Koje su metode dozvoljene za svaku kategoriju",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Koje su metode podržane za svaku vrstu; odnosi se samo na vrste unutar kategorija koje su sakrivene od postavki",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Uključeno po podrazumijevanim postavkama",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Postojeći korisnici",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Novi korisnici",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Zahtijevana metode za obavještavanje",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Koje su metode obavezne za svaku kategoriju",
"echo-specialpage": "Obavještenja",
+ "echo-specialpage-section-markread": "Označi grupu kao pročitanu",
+ "echo-specialpage-markasread": "Obavještenje: Označi kao pročitano",
+ "echo-specialpage-markasread-invalid-id": "Neispravan ID događaja",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|obavještenje|obavještenja}}",
+ "echo-specialpage-pagefilters-title": "Nedavna aktivnost",
+ "echo-specialpage-pagefilters-subtitle": "Stranice s nepročitanim obavještenjima",
+ "notificationsmarkread-legend": "Označi obavještenje kao pročitano",
"echo-anon": "Da biste primili obaveštenja, morate se [[Special:UserLogin|prijaviti]] ili [[Special:Userlogin/signup|napraviti račun]].",
"echo-none": "Nemate obavještenja",
"echo-more-info": "Više informacija",
"echo-feedback": "Povratna informacija",
- "notification-link-text-view-message": "Pogledaj poruku",
- "notification-link-text-view-mention": "Pogledajte spominjanje",
- "notification-link-text-view-changes": "Pogledaj izmjene",
- "notification-link-text-view-page": "Pogledaj stranicu",
- "notification-link-text-view-edit": "Pogledaj uređivanje",
- "notification-edit-talk-page2": "[[User:$1|$1]] vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj [[User talk:$2#$3|stranici za razgovor]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj [[User talk:$2#$3|stranici za razgovor]].",
- "notification-edit-talk-page-flyout-with-section": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Stranica [[:$2]] je {{GENDER:$1|povezana}} sa stranicom [[:$3]]. [[Special:WhatLinksHere/$2|Pogledajte sve veze prema ovoj stranici]].",
- "notification-page-linked-flyout": "[[:$2]] je {{GENDER:$1|povezana}} sa [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] je {{GENDER:$1|ostavio|ostavila}} komentar na \"[[$3|$2]]\" na \"$4\" stranici za razgovor.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] je {{GENDER:$1|postavio|postavila}} novu temu \"$2\" na [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] vam je {{GENDER:$1|poslao|poslala}} poruku: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] je {{GENDER:$1|komentarisao|komentarisala}} temu \"[[$3#$2|$2]]\" na vašoj stranici za razgovor.",
- "notification-mention": "[[User:$1|$1]] vas je {{GENDER:$1|spomenuо|spomenula}} na stranici za razgovor $5 u \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 vas je {{GENDER:$1|spomenuо|spomenula}} na stranici za razgovor $5 u \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] vas je {{GENDER:$1|spomenuo|spomenula}} na [[:$3|stranici za razgovor $2]].",
- "notification-mention-nosection-flyout": "$1 vas je {{GENDER:$1|spomenuo|spomenula}} na [[:$3|stranici za razgovor $2]].",
- "notification-user-rights": "Vaša korisnička prava [[Special:Log/rights/$1|su bila {{GENDER:$1|izmijenjena}}]] od strane [[User:$1|$1]]. $2. [[Special:ListGroupRights|Saznajte više]]",
- "notification-user-rights-flyout": "Vaša korisnička prava {{GENDER:$1|izmijenjena}} su od strane $1. $2. [[Special:ListGroupRights|Saznajte više]]",
- "notification-user-rights-add": "Od sada ste član {{PLURAL:$2|ove grupe|ovih grupa}}: $1",
- "notification-user-rights-remove": "Više niste član {{PLURAL:$2|ove grupe|ovih grupa}}: $1",
- "notification-new-user": "$1, dobro došli na {{SITENAME}}! Drago nam je što ste ovdje.",
- "notification-reverted2": "{{PLURAL:$4|Vaša izmjena na [[:$2]] je poništena|Vaše izmjene na [[:$2]] su poništene}} {{GENDER:$1|od}} strane [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Vaša izmjena na $2 je poništena|Vaše izmjene na $2 su poništene}} {{GENDER:$1|od}} strane $1. $3",
- "notification-edit-talk-page-email-subject2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor.",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u \"$2\".",
- "notification-page-linked-email-subject": "Stranica koju se napravili bila je povezana sa {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 je {{GENDER:$1|povezana}} sa $3.",
- "notification-reverted-email-subject2": "{{PLURAL:$3|Vaša izmjena je {{GENDER:$1|poništena}}|Vaše izmjene su {{GENDER:$1|poništene}}}} na {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Vaša izmjena na $2 je poništena|Vaše izmjene na $2 su poništene}} {{GENDER:$1|od}} strane $1.",
- "notification-mention-email-subject": "$1 vas je {{GENDER:$1|spomenuо|spomenula}} na {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 vas je {{GENDER:$1|spomenuо|spomenula}} na stranici za razgovor $4 u \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 vas je {{GENDER:$1|spomenuo|spomenula}} na stranici za razgovor $2.",
- "notification-user-rights-email-subject": "Vaša korisnička prava su se promijenila na {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Vaša korisnička prava su {{GENDER:$1|promjenjena}} od strane $1. $2",
- "echo-email-subject-default": "Novo obavještenje na {{SITENAME}}",
- "echo-email-body-default": "Imate novo obavještenje na {{SITENAME}}: \n\n$1",
- "echo-email-batch-body-default": "Imate novo obavještenje.",
- "echo-email-footer-default": "$2\n\nDa kontrolišete koje vam email poruke šaljemo, provjerite svoje postavke:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Da kontrolišete koje vam email poruke šaljemo, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">provjerite vaše postavke</a>.<br />\n$1",
- "echo-notification-message": "{{PLURAL:$1|Poruka ($1)|Poruke ($1)|100=Poruke (99+)}}",
+ "echo-popup-footer-special-page-invitation": "<strong>Isprobajte redizajniranu stranicu s obavještenjima.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Potpuno novi izgled i mogućnosti.",
+ "echo-api-failure": "Dobavljanje obavještenja nije uspjelo.",
+ "echo-api-failure-cross-wiki": "Odbijen pristup vanjskoj domeni.",
+ "echo-notification-placeholder": "Nema obavještenja.",
+ "echo-notification-placeholder-filters": "Nema obavještenja po zadanim kriterijima.",
+ "echo-notification-loginrequired": "Morate biti prijavljeni da biste vidjeli svoja obavještenja.",
+ "echo-notification-popup-loginrequired": "Prijavite se da biste vidjeli svoja obavještenja.",
+ "echo-notification-markasread": "Označi kao pročitano",
+ "echo-notification-markasunread": "Označi kao nepročitano",
+ "echo-notification-markasread-tooltip": "Označi kao pročitano",
+ "echo-notification-more-options-tooltip": "Više opcija",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Prestani}} pratiti novu aktivnost na \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "Više {{GENDER:$3|ne pratite}} stranicu \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Možete}} pratiti [$2 ovu stranicu] u bilo kom trenutku.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Prati}} novu aktivnost na \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "Sad {{GENDER:$3|pratite}} stranicu \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Možete}} prestati pratiti [$2 ovu stranicu] u bilo kom trenutku.",
+ "notification-link-text-expand-all": "Proširi",
+ "notification-link-text-expand-alert-count": "Prikaži {{PLURAL:$1|obavještenje|$1 obavještenja}}",
+ "notification-link-text-expand-notice-count": "Vidi {{PLURAL:$1|$1 obavještenje|$1 obavještenja}}",
+ "notification-link-text-expand-all-count": "Prikaži {{PLURAL:$1|obavještenje|$1 obavještenja}}",
+ "notification-link-text-collapse-all": "Sakrij",
+ "notification-link-text-view-message": "Prikaži poruku",
+ "notification-link-text-view-mention": "Prikaži spominjanje",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Vidi spominjanje|Vidi spominjanja}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Prikaži}} izmjene",
+ "notification-link-text-view-page": "Prikaži stranicu",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$3|Vam}} je {{GENDER:$2|ostavio|ostavila}} poruku na <strong>{{GENDER:$3|Vašoj}} stranici za razgovor</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$3|Vam}} je {{GENDER:$2|ostavio|ostavila}} poruku na <strong>{{GENDER:$3|Vašoj}} stranici za razgovor</strong> u odlomku \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "Stranica <strong>$3</strong> je povezana sa <strong>$4</strong>.",
+ "notification-compact-header-page-linked": "Povezano sa stranice <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Stranica <strong>$3</strong> povezana je {{PLURAL:$5|1=s jednom stranicom|sa $5 stranice|sa $5 stranica|100=s preko 99 stranica}}.",
+ "notification-link-text-what-links-here": "Svi linkovi ka ovoj stranici",
+ "notification-header-mention-other": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>$4</strong> u odlomku \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>stranici za razgovor s {{GENDER:$5|korisnikom|korisnicom}} $4</strong> u odlomku \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>stranici za razgovor s {{GENDER:$5|korisnikom|korisnicom}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>svojoj stranici za razgovor</strong> u odlomku \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>svojoj stranici za razgovor</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na stranici za razgovor <strong>$4</strong> u odlomku \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na stranici za razgovor <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Vaše}} spominjanje korisnika <strong>$3</strong> nije poslano jer korisničko ime nije pronađeno.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Vaše}} spominjanje korisnika <strong>$3</strong> nije poslano jer je neprijavljeni korisnik anoniman.",
+ "notification-header-mention-failure-too-many": "Pokušali {{GENDER:$2|ste}} spomenuti više od $3 {{PLURAL:$3|korisnika}}. Spominjanja preko tog ograničenja nisu poslana.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Osoba koju|$3 osobe koje|$3 osoba koje}} {{GENDER:$2|ste}} spomenuli na stranici za razgovor <strong>$4</strong> nije {{PLURAL:$3|dobila|dobile|dobilo}} obavještenje da ste {{PLURAL:$3|je|ih}} spomenuli.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Korisničko ime ne postoji:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Ne možete spominjati IP-adrese:</strong> $1",
+ "notification-header-mention-success": "<strong>$3</strong> je {{GENDER:$3|obaviješten|obaviještena}} da {{GENDER:$2|ste}} {{GENDER:$3|ga|je}} spomenuli.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Osoba koju|$3 osobe koje|$3 osoba koje}} {{GENDER:$2|ste}} spomenuli na stranici za razgovor <strong>$4</strong> {{PLURAL:$3|dobila je|dobile su|dobilo je}} obavještenje da ste {{PLURAL:$3|je|ih}} spomenuli.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Spomenuli ste}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Obavještenje|$3 obavještenja}} o spominjanjima koja {{GENDER:$2|ste poslali}} na stranici za razgovor <strong>$4</strong>: {{PLURAL:$5|$5 nije isporučeno|$5 nisu isporučena|$5 nije isporučeno}}, {{PLURAL:$6|$6 je isporučeno|$6 su isporučena|$6 je isporučeno}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Vaša}} korisnička prava su {{GENDER:$1|promijenjena}}. Sad ste član sljedećih grupa: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Vaša}} korisnička prava su {{GENDER:$1|promijenjena}}. Više niste član sljedećih grupa: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Vaša}} korisnička prava su {{GENDER:$1|promijenjena}}. Sad ste član sljedećih grupa: $2. Više niste član sljedećih grupa: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Dobro došli}} na {{GRAMMAR:akuzativ|{{SITENAME}}}}, $1! Drago nam je što {{GENDER:$2|ste}} ovdje.",
+ "notification-welcome-linktext": "Dobro došli",
+ "notification-header-thank-you-1-edit": "Upravo {{GENDER:$2|ste}} napravili prvu izmjenu; hvala {{GENDER:$2|Vam}} i dobro došli!",
+ "notification-header-thank-you-10-edit": "Upravo {{GENDER:$2|ste}} napravili {{GENDER:$2|svoju}} desetu izmjenu; hvala {{GENDER:$2|Vam}} i samo tako nastavite!",
+ "notification-header-thank-you-100-edit": "Upravo {{GENDER:$2|ste}} napravili {{GENDER:$2|svoju}} stotu izmjenu; mnogo {{GENDER:$2|Vam}} hvala!",
+ "notification-header-thank-you-1000-edit": "Upravo {{GENDER:$2|ste}} napravili {{GENDER:$2|svoju}} hiljaditu izmjenu; hvala {{GENDER:$2|Vam}} na fantastičnom doprinosu!",
+ "notification-header-thank-you-10000-edit": "Upravo {{GENDER:$2|ste}} napravili {{GENDER:$2|svoju}} 10.000. izmjenu; mnogo {{GENDER:$2|Vam}} hvala!",
+ "notification-header-thank-you-100000-edit": "Upravo {{GENDER:$2|ste}} napravili {{GENDER:$2|svoju}} 100.000. izmjenu; hvala {{GENDER:$2|Vam}} na fenomenalnom doprinosu!",
+ "notification-header-thank-you-1000000-edit": "Upravo {{GENDER:$2|ste}} napravili {{GENDER:$2|svoju}} milionsku izmjenu; hvala {{GENDER:$2|Vam}} na zadivljujućem doprinosu!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Vaša}} izmjena",
+ "notification-link-text-view-edit": "Prikaži izmjenu",
+ "notification-header-reverted": "{{PLURAL:$4|Vaša izmjena na <strong>$3</strong> {{GENDER:$2|poništena}} je|Vaše izmjene na <strong>$3</strong> {{GENDER:$2|poništene}} su}}.",
+ "notification-header-emailuser": "$1 Vam je {{GENDER:$2|poslao|poslala}} e-poruku.",
+ "notification-edit-talk-page-email-subject2": "$1 Vam je {{GENDER:$1|ostavio|ostavila}} poruku na {{GRAMMAR:dativ|{{SITENAME}}}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 Vam je {{GENDER:$1|ostavio|ostavila}} poruku na Vašoj stranici za razgovor u \"$2\".",
+ "notification-page-linked-email-subject": "Stranica koju ste napravila povezana je na {{GRAMMAR:dativ|{{SITENAME}}}}",
+ "notification-reverted-email-subject2": "{{PLURAL:$3|Vaša izmjena je {{GENDER:$1|poništena}}|Vaše izmjene su {{GENDER:$1|poništene}}}} na {{GRAMMAR:dativ|{{SITENAME}}}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|Vas}} je {{GENDER:$1|spomenuo|spomenula}} na {{GRAMMAR:dativ|{{SITENAME}}}}",
+ "notification-user-rights-email-subject": "Vaša korisnička prava na {{GRAMMAR:dativ|{{SITENAME}}}} su promijenjena",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 sek.}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min.}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|1=1 sat|$1 sata|$1 sati}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|1=1 dan|$1 dana}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mj.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 god.}}",
+ "notification-timestamp-today": "Danas",
+ "notification-timestamp-yesterday": "Jučer",
+ "notification-inbox-filter-read": "Pročitano",
+ "notification-inbox-filter-unread": "Nepročitano",
+ "notification-inbox-filter-all": "Sve",
+ "echo-email-body-default": "Imate novo obavještenje na {{GRAMMAR:dativ|{{SITENAME}}}}: \n\n$1",
+ "echo-email-footer-default-html": "Da biste promijenili koje Vam e-poruke šaljemo, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">provjerite svoje postavke</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nDa biste promijenili koje Vam e-poruke šaljemo, provjerite svoje postavke:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Da biste promijenili koje {{GENDER:$1|Vam}} e-poruke šaljemo, provjerite {{GENDER:$1|svoje}} postavke:",
+ "echo-email-html-footer-preference-link-text": "provjerite {{GENDER:$1|svoje}} postavke",
+ "echo-email-html-footer-with-link": "Da biste promijenili koje {{GENDER:$2|Vam}} e-poruke šaljemo, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Obavještenje ($1)|Obavještenja ($1)|100=Obavještenja (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Obavještenje ($1)|Obavještenja ($1)|100=Obavještenja (99+)}}",
"echo-notification-alert-text-only": "Obavještenja",
- "echo-notification-message-text-only": "Poruke",
+ "echo-notification-notice-text-only": "Sitna obavještenja",
"echo-overlay-link": "Sva obavještenja",
"echo-overlay-title": "<b>Obavještenja</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Obavještenja}}</b> (prikaz $1 od $2 nepročitanih)",
"echo-mark-all-as-read": "Označi sve kao pročitano",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|obavještenje označeno kao pročitano|obavještenja označena kao pročitana}}",
+ "echo-mark-wiki-as-read": "Označi sve kao pročitano u izabranom wikiju: $1",
"echo-date-today": "Danas",
"echo-date-yesterday": "Jučer",
"echo-load-more-error": "Greška se pojavila za vrijeme dobavljanja više rezultata.",
- "notification-edit-talk-page-bundle": "$1 i $3 {{PLURAL:$4|ostali|ostale}} {{GENDER:$1|ostavili}} su poruku na vašoj [[User talk:$2|stranici za razgovor]].",
- "notification-page-linked-bundle": "$2 {{GENDER:$1|povezana}} je sa $3 i $4 {{PLURAL:$5|druge stranice|drugih stranica}}. [[Special:WhatLinksHere/$2|Pogledaj sve linkove na ovu stranicu.]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 i $2 {{PLURAL:$3|ostali|ostalih}} {{GENDER:$1|ostavili}} su poruku na vašoj stranici za razgovor.",
- "notification-page-linked-email-batch-bundle-body": "Stranica $2 {{GENDER:$1|povezana}} je sa $3 i $4 {{PLURAL:$5|druge stranice|drugih stranica}}.",
- "echo-email-batch-subject-daily": "Imate {{PLURAL:$2|novo obavještenje|nova obavještenja}} na {{SITENAME}}",
- "echo-email-batch-subject-weekly": "Imate {{PLURAL:$2|novo obavještenje|nova obavještenja}} na {{SITENAME}} ove sedmice",
- "echo-email-batch-body-intro-daily": "Zdravo $1,\nOvo je sažetak današnjih aktivnosti na {{SITENAME}} za Vas.",
- "echo-email-batch-body-intro-weekly": "Zdravo $1,\nOvo je sažetak sedmičnih aktivnosti na {{SITENAME}} za Vas.",
- "echo-email-batch-link-text-view-all-notifications": "Pogledaj sva obavještenja",
- "echo-rev-deleted-text-view": "Revizija ove stranice je zabranjena."
+ "notification-bundle-header-edit-user-talk-v2": "Imate {{PLURAL:$1|1=jednu novu poruku|$1 nove poruke|$1 novih poruka|100=više od 99 novih poruka}} na <strong>{{GENDER:$3|Vašoj}} stranici za razgovor</strong>.",
+ "echo-email-batch-subject-daily": "Imate {{PLURAL:$2|novo obavještenje|nova obavještenja}} na {{GRAMMAR:dativ|{{SITENAME}}}}",
+ "echo-email-batch-subject-weekly": "Imate {{PLURAL:$2|novo obavještenje|nova obavještenja}} na {{GRAMMAR:dativ|{{SITENAME}}}} ove sedmice",
+ "echo-email-batch-body-intro-daily": "Zdravo $1,\nOvo je sažetak današnjih aktivnosti na {{GRAMMAR:dativ|{{SITENAME}}}} za Vas.",
+ "echo-email-batch-body-intro-weekly": "Zdravo $1,\nOvo je sažetak sedmičnih aktivnosti na {{GRAMMAR:dativ|{{SITENAME}}}} za Vas.",
+ "echo-email-batch-link-text-view-all-notifications": "Prikaži sva obavještenja",
+ "notification-header-foreign-alert": "Više obavještenja {{PLURAL:$5|s jedne druge wiki|sa $5 druga wikija|sa $5 drugih wikija}}",
+ "notification-header-foreign-notice": "Više obavještenja {{PLURAL:$5|s jednog drugog wikija|sa $5 druga wikija|sa $5 drugih wikija}}",
+ "notification-header-foreign-all": "Više obavještenja {{PLURAL:$5|s jedne druge wiki|sa $5 druga wikija|sa $5 drugih wikija}}"
}
diff --git a/Echo/i18n/ca.json b/Echo/i18n/ca.json
index ab2f552a..a7566cdb 100644
--- a/Echo/i18n/ca.json
+++ b/Echo/i18n/ca.json
@@ -8,14 +8,17 @@
"Vriullop",
"පසිඳු කාවින්ද",
"Fitoschido",
- "Ssola"
+ "Ssola",
+ "Nemo bis",
+ "Toniher"
]
},
- "echo-desc": "Sistema de notificacions",
+ "echo-desc": "Sistema per notificar als usuaris sobre esdeveniments i missatges",
"prefs-echo": "Notificacions",
"prefs-emailsettings": "Opcions de correu electrònic",
"prefs-displaynotifications": "Opcions de visualització",
"prefs-echosubscriptions": "Notifica'm sobre aquests esdeveniments",
+ "prefs-echocrosswiki": "Notificacions interwiki",
"prefs-newmessageindicator": "Indicador de missatges nous",
"echo-pref-send-me": "Envia’m:",
"echo-pref-send-to": "Envia a:",
@@ -28,90 +31,162 @@
"echo-pref-email-frequency-weekly": "Un resum setmanal de notificacions",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Text net",
+ "echo-pref-cross-wiki-notifications": "Mostra les notificacions d'altres wikis",
"echo-pref-new-message-indicator": "Mostra l'indicador de missatges en pàgina de discussió a la meva barra d'eines",
+ "echo-pref-beta-feature-cross-wiki-message": "Notificacions millorades",
+ "echo-pref-beta-feature-cross-wiki-description": "Mostra i organitza les notificacions més fàcilment. Inclou les notificacions multi-wiki que permet veure els missatges d'altres wikis. (Per rebre notificacions d'altres wikis en un wiki determinat, heu d'activar la funcionalitat beta en aquest wiki.)",
"echo-learn-more": "Més informació",
+ "echo-log": "Registre públic",
"echo-new-messages": "Teniu nous missatges",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Missatge|Missatges}} de discussió",
"echo-category-title-article-linked": "{{PLURAL:$1|Enllaç|Enllaços}} de pàgina",
"echo-category-title-reverted": "{{PLURAL:$1|Reversió d'edició|Reversions d'edicions}}",
"echo-category-title-mention": "{{PLURAL:$1|Menció|Mencions}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Menció que ha fallat|Mencions que han fallat}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Menció enviada|Mencions enviades}} satisfactòriament",
"echo-category-title-other": "{{PLURAL:$1|Altres}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Canvi de drets d'usuari|Canvis de drets d'usuari}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Correu electrònic d'un altre usuari|Correus electrònics d'altres usuaris}}",
"echo-pref-tooltip-edit-user-talk": "Avisa'm quan algú envia un missatge o respon a la meva pàgina de discussió.",
"echo-pref-tooltip-article-linked": "Avisa'm quan algú enllaça des d'un article a una pàgina que he creat.",
"echo-pref-tooltip-reverted": "Avisa'm quan algú reverteix una modificació que he fet, emprant l'eina per a desfer o revocar.",
- "echo-pref-tooltip-mention": "Avisa'm quan algú enllaça a la meva pàgina d'usuari des de qualsevol pàgina de discussió.",
+ "echo-pref-tooltip-mention": "Notifica'm quan algú enllaci a la meva pàgina d'usuari.",
+ "echo-pref-tooltip-mention-failure": "Notifica'm quan no pugui enviar una menció a algú.",
+ "echo-pref-tooltip-mention-success": "Notifica'm quan enviï una menció a algú.",
"echo-pref-tooltip-user-rights": "Avisa’m quan algú canviï els meus drets d’usuari.",
- "echo-no-agent": "[Ningú]",
- "echo-no-title": "[Cap pàgina]",
+ "echo-pref-tooltip-emailuser": "Notifica'm quan algú m'enviï un correu electrònic.",
"echo-error-no-formatter": "Cap format definit per a la notificació.",
"notifications": "Notificacions",
"tooltip-pt-notifications-alert": "{{GENDER:|Les vostres}} alertes",
- "tooltip-pt-notifications-message": "{{GENDER:|Els vostres}} missatges",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Els vostres}} avisos",
+ "echo-displaynotificationsconfiguration": "Presentació de la configuració de notificacions",
+ "echo-displaynotificationsconfiguration-summary": "Aquesta és una visió general de com estan configurades les notificacions en aquest wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notificacions per categoria",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Classificació",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "En quina secció es classifica cada tipus de notificació",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Mètodes de notificació permesos",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Quins mètodes de notificació s'usen per a cada categoria",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Quins mètodes de notificació s'usen per a cada tipus; només s'aplica als tipus en categories que estan ocultes en les preferències",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Habilitat per defecte",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Usuaris existents",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Usuaris nous",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Mètodes de notificació requerits",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Quins mètodes de notificació són obligatoris per a cada categoria",
"echo-specialpage": "Notificacions",
+ "echo-specialpage-section-markread": "Marca el grup com a llegit",
+ "echo-specialpage-markasread": "Notificació: marca com a llegida",
+ "echo-specialpage-markasread-invalid-id": "ID d'esdeveniment no vàlid",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notificació|notificacions}}",
+ "echo-specialpage-pagefilters-title": "Activitat recent",
+ "echo-specialpage-pagefilters-subtitle": "Pàgines amb notificacions sense llegir",
+ "notificationsmarkread-legend": "Marca la notificació com a llegida",
"echo-anon": "Per a rebre notificacions, [[Special:Userlogin/signup|creeu un compte]] o [[Special:UserLogin|registreu-vos]].",
"echo-none": "No teniu cap notificació.",
"echo-more-info": "Més informació",
"echo-feedback": "Comentaris",
+ "echo-popup-footer-special-page-invitation": "<strong>Proveu el nou disseny de la pàgina de notificacions.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Nou aspecte i funcionalitats.",
+ "echo-api-failure": "La recuperació de notificacions ha fallat.",
+ "echo-api-failure-cross-wiki": "L'accés al domini remot ha estat denegat.",
+ "echo-notification-placeholder": "No hi ha cap notificació.",
+ "echo-notification-placeholder-filters": "No hi ha cap notificació que coincideixi amb aquests criteris.",
+ "echo-notification-loginrequired": "Heu d'iniciar sessió per a veure les notificacions.",
+ "echo-notification-popup-loginrequired": "Inicieu la sessió per veure les notificacions.",
+ "echo-notification-markasread": "Marca com a llegit",
+ "echo-notification-markasunread": "Marca com a no llegit",
+ "echo-notification-markasread-tooltip": "Marca com a llegit",
+ "echo-notification-more-options-tooltip": "Més opcions",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Deixa}} de seguir la nova activat de «$1»",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Ja}} no esteu seguint la pàgina «$1»",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Podeu}} seguir [$2 aquesta pàgina] en qualsevol moment.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Seguiu}} la nova activitat a «$1»",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Esteu}} seguint la pàgina «$1»",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Podeu}} deixar de seguir [$2 aquesta pàgina] en qualsevol moment.",
+ "notification-link-text-expand-all": "Amplia",
+ "notification-link-text-expand-alert-count": "Mostra {{PLURAL:$1|$1 alerta|$1 alertes}}",
+ "notification-link-text-expand-notice-count": "Mostra {{PLURAL:$1|$1 avís|$1 avisos}}",
+ "notification-link-text-expand-all-count": "Mostra {{PLURAL:$1|$1 notificació|$1 notificacions}}",
+ "notification-link-text-collapse-all": "Amaga",
"notification-link-text-view-message": "Mostra el missatge",
"notification-link-text-view-mention": "Mostra la menció",
- "notification-link-text-view-changes": "Mostra els canvis",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Mostra la menció|Mostra les mencions}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Mostra}} els canvis",
"notification-link-text-view-page": "Mostra la pàgina",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|ha deixat}} un missatge en la <strong>{{GENDER:$3|vostra}} pàgina de discussió</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|ha deixat}} un missatge en la <strong>{{GENDER:$3|vostra}} pàgina de discussió</strong> a «<strong>$4</strong>».",
+ "notification-header-page-linked": "S'ha creat un enllaç a <strong>$4</strong> vers <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Enllaçades des de <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Enllaços creats des de {{PLURAL:$5||$5 pàgines|100=més d'un centenar de pàgines}} vers <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Tots els enllaços a aquesta pàgina",
+ "notification-header-mention-other": "$1 {{GENDER:$3|us}} ha {{GENDER:$2|mencionat}} a <strong>$4</strong> en «<strong>$5</strong>».",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|us}} ha {{GENDER:$2|mencionat}} a <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|us}} ha {{GENDER:$2|mencionat}} en la <strong>pàgina de discussió {{GENDER:$5|de}} $4</strong> a «<strong>$6</strong>».",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|us}} ha {{GENDER:$2|mencionat}} en la <strong>pàgina de discussió {{GENDER:$5|de}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|us}} ha {{GENDER:$2|mencionat}} en <strong>{{GENDER:$2|la seva}} pàgina de discussió</strong> a «<strong>$4</strong>».",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|us}} ha {{GENDER:$2|mencionat}} en <strong>{{GENDER:$2|la seva}} pàgina de discussió</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|us}} {{GENDER:$2|ha mencionat}} en la pàgina de discussió <strong>$4</strong> a «<strong>$5</strong>».",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|us}} {{GENDER:$2|ha mencionat}} en la pàgina de discussió <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|La vostra}} menció a <strong>$3</strong> no s'ha enviat perquè no s'ha trobat l'usuari.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|La vostra}} menció a <strong>$3</strong> no s'ha enviat perquè l'usuari és anònim.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>El nom d'usuari no existeix:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Les IP no es poden mencionar:</strong> $1",
+ "notification-header-mention-success": "S'ha enviat {{GENDER:$2|la vostra}} menció a <strong>$3</strong>.",
+ "notification-header-user-rights-add-only": "Els vostres drets d'usuari han estat {{GENDER:$1|modificats}}. Heu estat {{GENDER:$4|afegit|afegida}} a: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Els vostres}} drets d'usuari han estat {{GENDER:$1|modificats}}. Ja no sou membre de: $2.",
+ "notification-header-user-rights-add-and-remove": "Els vostres drets d'usuari han estat {{GENDER:$1|modificats}}. Heu estat {{GENDER:$6|afegit|afegida}} a: $2. Ja no sou membre de: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Benvingut|Benvinguda}} al projecte {{SITENAME}}, $1! Ens alegrem que {{GENDER:$2|estigueu}} aquí.",
+ "notification-welcome-linktext": "Benvinguts",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Acabeu}} de fer {{GENDER:$2|la vostra}} primera modificació; {{GENDER:$2|us}} ho agraïm i us donem la benvinguda!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Acabeu}} de fer {{GENDER:$2|la vostra}} desena modificació; gràcies i endavant!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Acabeu}} de fer un centenar de modificacions; moltes gràcies!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Acabeu}} de fer un miler de modificacions; us agraïm que sigueu {{GENDER:$2|un gran col·laborador|una gran col·laboradora}}!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Acabeu}} de fer deu mil modificacions; moltíssimes gràcies!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Acabeu}} de fer cent mil modificacions; gràcies per {{GENDER:$2|la vostra}} col·laboració increïble!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Acabeu}} de fer un milió de modificacions; us agraïm {{GENDER:$2|la vostra}} col·laboració sorprenent!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|La vostra}} modificació",
"notification-link-text-view-edit": "Mostra la modificació",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|ha deixat}} un missatge a la vostra [[User talk:$2#$3|pàgina de discussió]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|ha deixat}} un missatge a la vostra pàgina de discussió sobre \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|ha deixat}} un missatge a la vostra [[User talk:$2#$3|pàgina de discussió]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|ha deixat}} un missatge a la vostra pàgina de discussió sobre «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "S'ha {{GENDER:$1|enllaçat}} [[:$2]] des de [[:$3]]. [[Special:WhatLinksHere/$2|Vegeu tots els enllaços a aquesta pàgina]].",
- "notification-page-linked-flyout": "S'ha {{GENDER:$1|enllaçat}} [[:$2]] des de [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|ha fet un comentari}} sobre «[[$3|$2]]» a la pàgina de discussió «$4».",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|ha publicat}} un nou fil de discussió «$2» a [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] us {{GENDER:$1|ha enviat}} un missatge: «[[$3#$2|$2]]».",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|ha fet un comentari}} sobre «[[$3#$2|$2]]» a la vostra pàgina de discussió.",
- "notification-mention": "[[User:$1|$1]] us {{GENDER:$1|ha mencionat}} a $5 en la seva pàgina de discussió sobre «[[:$3#$2|$4]]».",
- "notification-mention-flyout": "$1 us {{GENDER:$1|ha mencionat}} en la pàgina de discussió de $5 sobre «[[:$3#$2|$4]]».",
- "notification-user-rights": "Els vostres drets d'accés [[Special:Log/rights/$1|han estat {{GENDER:$1|canviats}}]] per [[User:$1|$1]]. $2. [[Special:ListGroupRights|Més informació]]",
- "notification-user-rights-flyout": "Els vostres drets d'accés han estat {{GENDER:$1|canviats}} per $1. $2. [[Special:ListGroupRights|Més informació]]",
- "notification-user-rights-add": "Ara sou membre d'{{PLURAL:$2|aquest grup|aquests grups}}: $1",
- "notification-user-rights-remove": "Heu deixat de pertànyer {{PLURAL:$2|al següent grup|als següents grups}}: $1",
- "notification-new-user": "Benvingut al projecte {{SITENAME}}, $1! Ens alegrem que estiguis aquí.",
- "notification-reverted2": "{{PLURAL:$4|S'ha revertit la vostra edició a [[:$2]] |S'ha revertit les vostres edicions a [[:$2]]}} {{GENDER:$1|per}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|S'ha revertit la vostra edició a $2|S'ha revertit les vostres edicions a $2}} {{GENDER:$1|per}} $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|La vostra edició a <strong>$3</strong> ha estat revertida|Les vostres edicions a <strong>$3</strong> han estat revertides}}{{GENDER:$2|}}",
+ "notification-header-emailuser": "$1 us ha {{GENDER:$2|enviat}} un correu electrònic.",
"notification-edit-talk-page-email-subject2": "$1 us {{GENDER:$1|ha deixat}} un missatge al projecte {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 us {{GENDER:$1|ha deixat}} un missatge en la vostra pàgina de discussió:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 us {{GENDER:$1|ha deixat}} un missatge en la vostra pàgina de discussió sobre «$2».",
- "notification-page-linked-email-subject": "S'ha enllaçat la vostra pàgina al projecte {{SITENAME}}",
- "notification-page-linked-email-batch-body": "S'ha {{GENDER:$1|enllaçat}} $2 des de $3.",
+ "notification-page-linked-email-subject": "Una pàgina que vau crear s'ha enllaçat en el projecte {{SITENAME}}",
"notification-reverted-email-subject2": "{{PLURAL:$3|S'ha revertit la vostra edició|S'han revertit les vostres edicions}} {{GENDER:$1|al projecte}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|S'ha revertit la vostra edició a $2|S'ha revertit les vostres edicions a $2}} {{GENDER:$1|}}per $1.",
- "notification-mention-email-subject": "$1 us ha {{GENDER:$1|mencionat}} a {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 us ha {{GENDER:$1|mencionat}} a la pàgina de discussió de $4, a \"$3\".",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|us}} ha {{GENDER:$1|mencionat}} en el projecte {{SITENAME}}",
"notification-user-rights-email-subject": "Els vostres permisos d'usuari han canviat a {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Els vostres permisos d'usuari han estat {{GENDER:$1|canviats}} per $1. $2.",
- "echo-email-subject-default": "Notificació de nou a {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1a}}",
+ "notification-timestamp-today": "Avui",
+ "notification-timestamp-yesterday": "Ahir",
+ "notification-inbox-filter-read": "Llegides",
+ "notification-inbox-filter-unread": "No llegides",
+ "notification-inbox-filter-all": "Totes",
"echo-email-body-default": "Teniu una nova notificació a {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Teniu una nova notificació.",
"echo-email-footer-default": "$2\n\nPer a controlar quins correus us enviem, reviseu les vostres preferències:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Per a controlar quins correus us enviem, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">reviseu les vostres preferències</a>.<br />\n$1",
+ "echo-email-html-footer-with-link": "Per controlar quins missatges de correu electrònic {{GENDER:$2|us}} enviem, $1.",
"echo-notification-alert": "{{PLURAL:$1|Alertes ($1)|100=Alertes (+99)}}",
- "echo-notification-message": "{{PLURAL:$1|Missatges ($1)|100=Missatges (+99)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Avisos ($1)|100=Avisos (més de 100)}}",
"echo-notification-alert-text-only": "Alertes",
- "echo-notification-message-text-only": "Missatges",
+ "echo-notification-notice-text-only": "Avisos",
"echo-overlay-link": "Totes les notificacions",
"echo-overlay-title": "<b>Notificacions</b>",
- "echo-overlay-title-overflow": "<b>Notificacions</b> (mostrant $1 de $2 no llegides)",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificació|Notificacions}}</b> (mostrant $1 de $2 no llegides)",
"echo-mark-all-as-read": "Marca'ls tots com a llegits",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notificació marcada com a llegida|notificacions marcades com a llegides}}",
+ "echo-mark-wiki-as-read": "Marca-les totes com a llegides en el wiki seleccionat: $1",
"echo-date-today": "Avui",
"echo-date-yesterday": "Ahir",
"echo-load-more-error": "S'ha produït un error en obtenir més resultats.",
- "notification-edit-talk-page-bundle": "$1 i $3 {{PLURAL:$4|més}} {{GENDER:$1|han deixat}} un missatge a la vostra [[User talk:$2|pàgina de discussió]].",
- "notification-page-linked-bundle": "S'ha {{GENDER:$1|enllaçat}} $2 des de $3 i $4 {{PLURAL:$5|pàgina|pàgines}} més. [[Special:WhatLinksHere/$2|Vegeu tots els enllaços a aquesta pàgina]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 i $2 {{PLURAL:$3|més}} {{GENDER:$1|han deixat}} un missatge a la seva pàgina de discussió.",
- "notification-page-linked-email-batch-bundle-body": "$2 ha {{GENDER:$1|enllaçat}} {{PLURAL:$5|una altra pàgina|altres pàgines}} des de $3 i $4.",
"echo-email-batch-subject-daily": "Teniu {{PLURAL:$2|una nova notificació|noves notificacions}} al projecte {{SITENAME}}",
"echo-email-batch-subject-weekly": "Teniu {{PLURAL:$2|una nova notificació|noves notificacions}} d'aquesta setmana al projecte {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Hola $1,\nAquí teniu un resum de l'activitat d'avui a {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Hola $1,\nAquí teniu un resum de l'activitat d'aquesta setmana a {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "Vegeu totes les notificacions",
- "echo-rev-deleted-text-view": "S'ha suprimit aquesta revisió de pàgina."
+ "notification-header-foreign-alert": "Més alertes {{PLURAL:$5|d'un altre wiki|de $5 altres wikis}}",
+ "notification-header-foreign-notice": "Més avisos {{PLURAL:$5|d'un altre wiki|de $5 altres wikis}}",
+ "notification-header-foreign-all": "Més notificacions {{PLURAL:$5|d'un altre wiki|de $5 altres wikis}}"
}
diff --git a/Echo/i18n/cdo.json b/Echo/i18n/cdo.json
index 40e36eb7..0de715d6 100644
--- a/Echo/i18n/cdo.json
+++ b/Echo/i18n/cdo.json
@@ -23,7 +23,6 @@
"echo-pref-email-frequency-weekly": "蜀禮拜蜀回其通知總結",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "純文本",
- "echo-pref-notify-show-link": "敆我其工具欄顯示通知",
"echo-pref-new-message-indicator": "敆我其工具欄顯示討論頁信息指示",
"echo-learn-more": "學習更更価仂囝",
"echo-new-messages": "汝有新其信息",
@@ -37,13 +36,8 @@
"echo-pref-tooltip-article-linked": "有儂鏈接我趁論文頁面創建其頁面其辰候通知我。",
"echo-pref-tooltip-reverted": "有儂使撤銷或者回滾工具回退我其修改其辰候通知我。",
"echo-pref-tooltip-mention": "有儂鏈接遘我其用戶頁其辰候通知我。",
- "echo-no-agent": "[無儂]",
- "echo-no-title": "[無頁]",
"echo-error-no-formatter": "未規定通知其格式。",
- "echo-error-preference": "有綻:無能耐設置用戶其喜好。",
- "echo-error-token": "有綻:無能耐得遘用戶其標誌。",
"notifications": "通知",
- "tooltip-pt-notifications": "汝其通知",
"echo-specialpage": "通知",
"echo-anon": "卜想收遘通知,著[$1 開賬號]或者[$2 躒入]。",
"echo-none": "汝無通知。",
@@ -54,41 +48,15 @@
"notification-link-text-view-changes": "看蜀看改變",
"notification-link-text-view-page": "看蜀看頁面",
"notification-link-text-view-edit": "看蜀看修改",
- "notification-edit-talk-page2": "[[User:$1|$1]]敆汝其[[User talk:$2#$3|討論頁]]{{GENDER:$1|留下}}蜀萆信息。",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]]敆汝其討論頁「[[User talk:$2#$3|$4]]」{{GENDER:$1|留下}}蜀萆信息。",
- "notification-edit-talk-page-flyout2": "$1敆汝其[[User talk:$2#$3|討論頁]]{{GENDER:$1|留下}}蜀條信息。",
- "notification-edit-talk-page-flyout-with-section": "$1敆汝其討論頁「[[User talk:$2#$3|$4]]」{{GENDER:$1|留下}}蜀條信息。",
- "notification-page-linked": "[[:$2]]趁[[:$3]]𡅏{{GENDER:$1|鏈}}過來。[[Special:WhatLinksHere/$2|看全部鏈遘茲蜀頁其鏈接]]。",
- "notification-page-linked-flyout": "[[:$2]]是趁[[:$3]]𡅏{{GENDER:$1|鏈}}過來。",
- "notification-add-comment2": "[[User:$1|$1]]敆「$4」其討論頁𡅏{{GENDER:$1|評論}}「[[$3|$2]]」。",
- "notification-add-talkpage-topic2": "[[User:$1|$1]]敆[[$3]]𡅏{{GENDER:$1|發表}}蜀萆新其话題「$2」。",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]]{{GENDER:$1|發}}給汝蜀條信息:「[[$3#$2|$2]]」。",
- "notification-add-comment-yours2": "[[User:$1|$1]]敆汝其討論頁𡅏{{GENDER:$1|評論}}「[[$3#$2|$2]]」。",
- "notification-mention": "[[User:$1|$1]]敆$5其討論頁其「[[:$3#$2|$4]]」𡅏{{GENDER:$1|提遘}}汝。",
- "notification-mention-flyout": "$1敆$5其討論頁其「[[:$3#$2|$4]]」𡅏{{GENDER:$1|提遘}}汝。",
- "notification-user-rights": "汝其用戶權利乞[[User:$1|$1]][[Special:Log/rights/$1|{{GENDER:$1|改去}}]]。$2. [[Special:ListGroupRights|學習更更価]]",
- "notification-user-rights-flyout": "汝其用戶權限乞$1{{GENDER:$1|改去}}。$2。[[Special:ListGroupRights|學習更更価]]",
- "notification-user-rights-add": "汝現在是{{PLURAL:$2|茲蜀組|茲幾組}}其成頁:$1",
- "notification-user-rights-remove": "汝不再是{{PLURAL:$2|茲蜀組|茲幾組}}其成員了:$1",
- "notification-new-user": "歡迎來遘{{SITENAME}},$1!儂家各儂雅高興看見汝敆這塊。",
- "notification-reverted2": "汝{{PLURAL:$4|敆[[:$2]]上其修改}}已經乞[[User:$1|$1]]{{GENDER:$1|回滾}}了。$3",
- "notification-reverted-flyout2": "汝{{PLURAL:$4|敆$2上其修改}}已經乞$1{{GENDER:$1|回滾}}。$3",
+ "notification-header-reverted": "汝{{PLURAL:$4|敆$3上其修改}}已經乞$1{{GENDER:$2|回滾}}。",
"notification-edit-talk-page-email-subject2": "$1敆{{SITENAME}}𡅏給汝{{GENDER:$1|留下}}蜀條信息",
- "notification-edit-talk-page-email-batch-body2": "$1敆汝其討論頁𡅏{{GENDER:$1|留下}}蜀條信息:",
"notification-edit-talk-page-email-batch-body-with-section": "$1敆汝其用戶討論頁其「$2」𡅏{{GENDER:$1|留下}}蜀條信息。",
"notification-page-linked-email-subject": "汝其頁面鏈遘{{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2是趁$3𡅏{{GENDER:$1|鏈}}過來。",
"notification-reverted-email-subject2": "汝其{{PLURAL:$3|修改}}敆{{SITENAME}}𡅏乞{{GENDER:$1|回滾}}去",
- "notification-reverted-email-batch-body2": "汝其{{PLURAL:$3|敆$2懸頂其修改已經}}乞$1{{GENDER:$1|回滾}}了。",
"notification-mention-email-subject": "$1敆{{SITENAME}}𡅏{{GENDER:$1|提遘}}汝",
- "notification-mention-email-batch-body": "$1敆$4其討論頁其「$3」𡅏{{GENDER:$1|提遘mentioned}}汝。",
"notification-user-rights-email-subject": "汝其用戶權利敆{{SITENAME}}𡅏乞改去了。",
- "notification-user-rights-email-batch-body": "汝其用戶權利乞$1改去了。$2。",
- "echo-email-subject-default": "敆{{SITENAME}}懸頂有新其通知",
"echo-email-body-default": "汝敆{{SITENAME}}懸頂有新其通知:\n\n$1",
- "echo-email-batch-body-default": "汝有蜀萆新其通知。",
"echo-email-footer-default": "為𡅏控制儂家發給汝其底蜀種電子郵件,檢查汝其喜好:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$2:$1",
- "echo-email-footer-default-html": "為𡅏控制儂家發給汝底蜀種電批,起動<a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">檢查蜀下汝其喜好</a>。<br />\n$1",
"echo-overlay-link": "全部通知",
"echo-overlay-title": "<b>通知</b>",
"echo-overlay-title-overflow": "<b>通知</b>(未讀其通知顯示出$1條,共總有$2條)",
@@ -96,14 +64,9 @@
"echo-date-today": "今旦",
"echo-date-yesterday": "昨冥",
"echo-load-more-error": "獲取更更価其結果辰候發生错误。",
- "notification-edit-talk-page-bundle": "$1共$3{{PLURAL:$4|其它}}敆汝其[[User talk:$2|討論頁]]𡅏{{GENDER:$1|留下}}蜀條信息。",
- "notification-page-linked-bundle": "$2是趁$3共其它$4{{PLURAL:$5|頁}}𡅏{{GENDER:$1|鏈}}過其。[[Special:WhatLinksHere/$2|看全部鏈遘茲蜀頁其鏈接]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1其其它$2{{PLURAL:$3|隻}}儂敆汝其討論頁上{{GENDER:$1|留下}}蜀條信息。",
- "notification-page-linked-email-batch-bundle-body": "$2是趁$3共其它$4{{PLURAL:$5|頁}}𡅏{{GENDER:$1|鏈}}過來。",
"echo-email-batch-subject-daily": "汝敆{{SITENAME}}𡅏有{{PLURAL:$2|新其通知}}",
"echo-email-batch-subject-weekly": "汝茲蜀禮拜敆{{SITENAME}}𡅏有{{PLURAL:$2|新其通知}}",
"echo-email-batch-body-intro-daily": "嘿$1,\n這是汝其今旦敆{{SITENAME}}懸頂其活動。",
"echo-email-batch-body-intro-weekly": "嘿$1,\n這是汝其茲蜀禮拜敆{{SITENAME}}懸頂其活動。",
- "echo-email-batch-link-text-view-all-notifications": "看全部通知",
- "echo-rev-deleted-text-view": "茲頁其修定已經乞限制了。"
+ "echo-email-batch-link-text-view-all-notifications": "看全部通知"
}
diff --git a/Echo/i18n/ce.json b/Echo/i18n/ce.json
index da3447ac..2366b034 100644
--- a/Echo/i18n/ce.json
+++ b/Echo/i18n/ce.json
@@ -1,7 +1,9 @@
{
"@metadata": {
"authors": [
- "Умар"
+ "Умар",
+ "Macofe",
+ "Исмаил Садуев"
]
},
"echo-desc": "Декъашхойн хиларг а, хаамаш а болу дӀахаийтаран система",
@@ -9,109 +11,152 @@
"prefs-emailsettings": "Электронан поштан гӀирс нисбар",
"prefs-displaynotifications": "Гуш болу гӀирсаш",
"prefs-echosubscriptions": "ХӀокху хиларах лаьцна хаийта",
+ "prefs-echocrosswiki": "Кросс-вики дӀахаийтарш",
"prefs-newmessageindicator": "Керлачу хааман индикатор",
+ "prefs-blocknotificationslist": "Ӏаьржа могӀам",
"echo-pref-send-me": "Баийта соьга:",
"echo-pref-send-to": "Хаам баийта тӀе:",
"echo-pref-email-format": "Хааман формат:",
"echo-pref-web": "Веб",
"echo-pref-email": "Электронан пошт",
- "echo-pref-email-frequency-never": "Сан эл. почте ма баийта хаамаш",
+ "echo-pref-email-frequency-never": "Сан эл. поште ма баийта хаамаш",
"echo-pref-email-frequency-immediately": "Къаьстина хаамаш тӀедаре хьаьжжина",
"echo-pref-email-frequency-daily": "ХӀор денна хаам",
"echo-pref-email-frequency-weekly": "ХӀор кӀиранах хаам",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Цхьалхе йоза",
+ "echo-pref-cross-wiki-notifications": "Кхечу викиш чура хаамаш гайта",
+ "echo-pref-notifications-blacklist": "ХӀокху декъашхошкара хаамаш ма гайта. ([[mw:Help:Notifications#mute|мадарра]])",
"echo-pref-new-message-indicator": "Сан панелан тӀехь гайта хааман индикатор",
+ "echo-pref-beta-feature-cross-wiki-message": "Дика дина дӀахаийтарш",
+ "echo-pref-beta-feature-cross-wiki-description": "Жим атта хьажар а, дӀахаийтарийн организаци а. Цуьнца ю кросс-вики-дӀахаийтарш, оцо кхечу викиш чура хаамаш гойту.",
"echo-learn-more": "Цул совнаха хаа",
+ "echo-log": "Массо тӀекхочу тептар",
"echo-new-messages": "Хьуна кхаьчна керла хаам",
"echo-category-title-edit-user-talk": "Дийцаре агӀонехь {{PLURAL:$1|хаам|хаамаш}}",
"echo-category-title-article-linked": "АгӀона тӀе {{PLURAL:$1|хьажорг}}",
"echo-category-title-reverted": "{{PLURAL:$1|нисдар юхадаккхар|нисдарш юхадаккхар}}",
"echo-category-title-mention": "{{PLURAL:$1|хаам|хаамаш}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Нисцадела хьахор|Нисцадела хьахорш}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Кхиамца хьахор|Кхиамца хьахорш}}",
"echo-category-title-other": "{{PLURAL:$1|кхин долу|кхин дерш}}",
"echo-category-title-system": "{{PLURAL:$1|Системан}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Декъашхочун бакъо хийцар|Декъашхочун бакъонаш хийцар}}",
+ "echo-category-title-emailuser": "Кхечу {{PLURAL:$1|декъашхочунгара|декъашхошкара}} электронан пошта",
"echo-pref-tooltip-edit-user-talk": "Хаийта соьга, цхьам хаам баийтача я сан дийцаре агӀорахь жоп делча.",
"echo-pref-tooltip-article-linked": "Хаийта соьга, цхьам ас кхоьллина агӀона тӀе хьажорг цхьан агӀонашкахь йитича.",
"echo-pref-tooltip-reverted": "Хаийта соьга, цхьам сан нисдар юха даьккхича.",
"echo-pref-tooltip-mention": "Хаийта соьга, цхьам сан долара агӀона тӀе хьажорг цхьан дийцаре агӀорахь йитича.",
"echo-pref-tooltip-user-rights": "Сан бакъонаш цхьаммо хийцича хаам бе соьга.",
- "echo-no-agent": "[Цхьа а]",
- "echo-no-title": "[АгӀо яц]",
+ "echo-pref-tooltip-emailuser": "Хаийта соьга, цхьам сан электронан поште яздича.",
"echo-error-no-formatter": "Хааман формат билгалйина яц",
"notifications": "ДӀахаийтарш",
"tooltip-pt-notifications-alert": "{{GENDER:|Хьан}} дӀахаийтарш",
- "tooltip-pt-notifications-message": "{{GENDER:|Хьан}} хаамаш",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Хьан}} хаамаш",
+ "echo-displaynotificationsconfiguration": "Гайта дӀахаийтаран нисдаран гӀирс",
+ "echo-displaynotificationsconfiguration-summary": "ХӀара хӀокху вики-сайтан тӀехь дӀахаийтаран нисдаран гӀирсашка хьажар ду.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "ДӀахаийтарш категорешкахула",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Тайпанаш къастор",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Шуьйра дӀахаийтарш",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "ХӀора категори чура ловш йолу дӀахаийтаран таронаш",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Ӏадйитаран кепаца латина ю",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Болуш болу декъашхой",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Керла декъашхой",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Оьшуш йолу хаамийн кепаш",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "ХӀора категори хила езаш йолу таронаш",
"echo-specialpage": "ДӀахаийтарш",
+ "echo-specialpage-section-markread": "Тоба ешна санна билгалъе",
+ "echo-specialpage-markasread": "ДӀахаийтар: билгалъе ешна санна",
+ "echo-specialpage-markasread-invalid-id": "Хиламийн нийса йоцу идентификатор",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|дӀахаийтар}}",
+ "echo-specialpage-pagefilters-title": "Дукха хан йоцуш дийнарг",
+ "echo-specialpage-pagefilters-subtitle": "Дешна доцу дӀахаийтарш долу агӀонаш",
+ "notificationsmarkread-legend": "Билгалде дӀахаийтар дешна санна",
"echo-anon": "Хаамаш хилийта, [$1 декъашхочун дӀаяздар кхолла] я [$2 чугӀо].",
"echo-none": "Хьуна хаамаш ца беара.",
"echo-more-info": "Ма-дарра",
"echo-feedback": "ЮхагӀо зӀе",
+ "echo-popup-footer-special-page-invitation": "<strong>Мах хадабе карлаяьккхинчу дӀахаийтаран агӀона.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Керла дизайн а, функцеш а.",
+ "echo-api-failure": "ДӀахаийтаршка хьажа цаделира.",
+ "echo-api-failure-cross-wiki": "ДӀаяьккхинчу доменан тӀекхача цало.",
+ "echo-notification-placeholder": "ДӀахаийтарш дац.",
+ "echo-notification-placeholder-filters": "Цхьаа дӀахаийтар дац.",
+ "echo-notification-loginrequired": "ДӀахаийтаршка хьажа системин чугӀо",
+ "echo-notification-popup-loginrequired": "Дехар до, дӀахаийтаршка хьажа симтемин чугӀо.",
+ "echo-notification-markasread": "Билгалъе ешна сана",
+ "echo-notification-markasunread": "Билгалъе ца ешна сана",
+ "echo-notification-markasread-tooltip": "Билгалъе ешна сана",
+ "echo-notification-more-options-tooltip": "Дукха варианташ",
+ "notification-link-text-expand-all": "Хьажа массаьрга",
+ "notification-link-text-expand-alert-count": "Гайта {{PLURAL:$1|$1 дӀахьедар}}",
+ "notification-link-text-expand-all-count": "Гайта {{PLURAL:$1|$1 дӀахаийтар}}",
+ "notification-link-text-collapse-all": "Къайлаяха массо",
"notification-link-text-view-message": "Хааме хьажар",
"notification-link-text-view-mention": "Хааме хьажар",
"notification-link-text-view-changes": "Хийцаме хьажар",
"notification-link-text-view-page": "Хьажа агӀоне",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|битина}} хаам {{GENDER:$3|хьан}} дийцаре агӀонгахь.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|хаам битина}} {{GENDER:$3|хьан}} дийцаре агӀонгара «$4» дакъа тӀехь.",
+ "notification-header-page-linked": "Хьажорг йина <strong>$4</strong> → <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Уьйр ю $1",
+ "notification-bundle-header-page-linked": "$4 а, $5 а агӀонаш {{PLURAL:$6|кхечу агӀон тӀера|кхечу агӀонаш тӀера}} $3 тӀе хьажийна.",
+ "notification-link-text-what-links-here": "ХӀокху агӀонна тӀе массо хьажоргаш",
+ "notification-header-mention-other": "$1 {{GENDER:$2|хьахийна}} {{GENDER:$3|хьо}} <strong>$4</strong> агӀона «$5» дакъа тӀехь.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|хьахийна}} {{GENDER:$3|хьо}} <strong>$4</strong> агӀонгахь.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|хьахийна}} {{GENDER:$3|хьо}} '''{{GENDER:$5|$4}}''' дийцаре агӀонгахь «$6» дакъа тӀехь.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|хьахийна}} {{GENDER:$3|хьо}} '''{{GENDER:$5|$4}}''' дийцаре агӀонгахь.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|хьахийна}} {{GENDER:$3|хьо}} {{GENDER:$2|шен}} «$4» дийцаре агӀонгахь.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|хьахийна}} {{GENDER:$3|хьо}} {{GENDER:$2|шен}} дийцаре агӀонгахь.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|хьахийна}} {{GENDER:$3|хьо}} «$4» дийцаре агӀона «$5» дакъа тӀехь.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|хьахийна}} {{GENDER:$3|хьо}} «$4» дийцаре агӀонгахь.",
+ "notification-welcome-linktext": "Марша догӀийла",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Хьан}} нисдар",
"notification-link-text-view-edit": "Нисдаре хьажар",
- "notification-edit-talk-page2": "Декъашхочо [[User:$1|$1]] хьан [[User talk:$2#$3|дийцаре агӀонехь]] {{GENDER:$1|битина}}. хаам.",
- "notification-edit-talk-page-with-section": "Хьан дийцаре агӀонехь [[User:$1|$1]] {{GENDER:$1|битина}} хаам \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|Декъашхочо}} хьан [[User talk:$2#$3|дийцаре агӀонехь]] битина хаам.",
- "notification-edit-talk-page-flyout-with-section": "Хьан дийцаре агӀонехь $1 {{GENDER:$1|битина}} хаам \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] и {{GENDER:$1|йихкина}} оцу [[:$3]]. [[Special:WhatLinksHere/$2|Хьажа. ХӀокху агӀона массо хьажоргаш]].",
- "notification-page-linked-flyout": "[[:$2]] и {{GENDER:$1|йихкина}} оцу [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|хаам биттина}} темехь \"[[$3|$2]]\" \"$4\" дийцаре агӀонехь.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|тӀетоьхна}} керла тем \"$2\" [[$3]] агӀонехь.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] хьога хаам {{GENDER:$1|хьажийна}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|хаам биттина}} темехь \"[[$3#$2|$2]]\" дийцаре агӀонехь.",
- "notification-mention": "[[User:$1|$1]] хьо {{GENDER:$1|хьахийна}} дийцаре агӀонехь $5 декъехь \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "хьо {{GENDER:$1|хьахийна}} дийцаре агӀонехь $5 декъехь \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] хьо хьахийна [[:$3|дийцаре агӀонехь $2]].",
- "notification-mention-nosection-flyout": "{{GENDER:$1||декъашхочо}} хьо хьахийна [[:$3|дийцаре агӀонехь $2]].",
- "notification-user-rights": "Хьан бакъонаш [[Special:Log/rights/$1|{{GENDER:$1|хийцина}}]] [[User:$1|$1]]. $2. [[Special:ListGroupRights|Мадарра]]",
- "notification-user-rights-flyout": "Декъашхочун бакъонаш {{GENDER:$1|хийцина}} $1. $2. [[Special:ListGroupRights|Мадарра]]",
- "notification-user-rights-add": "ХӀинца хьо {{PLURAL:$2|1=тобан юкъа эцна|тобанийн юкъа эцна}}: $1",
- "notification-user-rights-remove": "Хьан хӀокху {{PLURAL:$2|тобан|тобанийн}} бакъо дӀаяьккхина: $1",
- "notification-new-user": "Марша догӀилла {{SITENAME}}, $1! Хьо кхузахь хиларна даккхийде тхо.",
- "notification-reverted2": "{{PLURAL:$4|АгӀонехь [[:$2]] хьан нисдар|АгӀонехь [[:$2]] хьан нисдарш}} {{GENDER:$1|юхадаькхина}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|АгӀонехь $2 хьан нисдар|АгӀонехь $2 хьан нисдарш}} {{GENDER:$1|юхадаькхина}} $1. $3",
+ "notification-link-article-reminder": "АгӀоне хьажар",
+ "notification-header-reverted": "{{PLURAL:$4|АгӀонехь $3 хьан нисдар}} {{GENDER:$2|юхадаькхина}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|баийтина}} хьога хаам.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|Декъашхочо}} $1 «{{SITENAME}}» сайтехь хьуна хаам {{GENDER:$1|биттина}}",
- "notification-edit-talk-page-email-batch-body2": "Хьан дийцаре агӀонехь {{GENDER:$1|декъашхочо}} $1 {{GENDER:$1|битина}} хаам:",
"notification-edit-talk-page-email-batch-body-with-section": "Хьан дийцаре агӀонехь {{GENDER:$1|декъашхочо}} $1 {{GENDER:$1|битина}} хаам (темехь) «$2»",
"notification-page-linked-email-subject": "«{{SITENAME}}» сайтехь ахьа кхоьллина агӀона тӀе хьажорг хӀоттина",
- "notification-page-linked-email-batch-body": "{{GENDER:$1|Декъашхо}} $1 {{GENDER:$1|тӀетеввжина}} цу $2 $3",
"notification-reverted-email-subject2": "{{GENDER:$1|Цхьам}} «{{SITENAME}}» сайтехь хьан {{PLURAL:$3|нисдар юхадаькхина|нисдарш юхадаьхина}}",
- "notification-reverted-email-batch-body2": "{{GENDER:$1|Декъашхочо}} $1 {{PLURAL:$3|«$2» агӀонехь хьан нисдар юхадаьккхина|«$2» агӀонехь хьан нисдарш юхадаьхина}}.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|Декъашхочо}} «{{SITENAME}}» сайтехь хьо хьахийна",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|хьахийна}} хьо $4 дийцарийн агӀо \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 декъашхочо хьо хьахийна $2 агӀона чохь.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|Декъашхочо}} «{{SITENAME}}» сайтехь {{GENDER:$2|хьо}} хьахийна",
"notification-user-rights-email-subject": "Сайтехь «{{SITENAME}}» хьан бакъонаш хийцина",
- "notification-user-rights-email-batch-body": "{{GENDER:$1|Декъашхочо}} хьан бакъонаш хийцина $1. $2.",
- "echo-notification-count": "$1+",
- "echo-email-subject-default": "Сайтехь «{{SITENAME}}» керла хаам",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 с}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 м.}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 сахь.}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 д.}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 б}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 ш.}}",
+ "notification-timestamp-today": "Тахана",
+ "notification-timestamp-yesterday": "Селхана",
+ "notification-inbox-filter-read": "Ешар",
+ "notification-inbox-filter-unread": "Ца ешнарш",
+ "notification-inbox-filter-all": "Массо",
"echo-email-body-default": "Сайтехь «{{SITENAME}}» хьога керла хаам бу:\n\n$1",
- "echo-email-batch-body-default": "Хьан керла хаам бу",
- "echo-email-footer-default": "$2\n\nЭлектронан почте муьлха хаамаш богӀуш бу хьажа а уьш дӀанисбан а декъашхочун гӀирсе хьажа :\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Электронан поште муьлха хаамаш кхоьхуьтуш бу хьажа а уьш дӀанисбан а <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">Википедин поштан гӀирсе хьажа </a><br />\n$1",
+ "echo-email-footer-default-html": "Оха кхоьхьуьтуш болу хаамашан контроль ян <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">хьажа гӀирсега</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nЭлектронан поште муьлха хаамаш богӀуш бу хьажа а уьш дӀанисбан а декъашхочун гӀирсе хьажа :\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-html-footer-preference-link-text": "хьажа {{GENDER:$1|хьайн}} нисдаран гӀирсе",
+ "echo-email-html-footer-with-link": "Оха {{GENDER:$2|хьайга}}, $1 кхоьхьуьтуш болу хаамашан контроль ян.",
"echo-notification-alert": "{{PLURAL:$1|ДӀахьедар ($1)|100=ДӀахьедар (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Хаам ($1)|100=Хаам (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Хаамаш ($1)|100=Хаамаш (99+)}}",
"echo-notification-alert-text-only": "ДӀахаийтарш",
- "echo-notification-message-text-only": "Хаам",
+ "echo-notification-notice-text-only": "Хаамаш",
"echo-overlay-link": "Массо хаамаш",
"echo-overlay-title": "<b>Хаамаш</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Хаам}}</b> ({{PLURAL:$1|гайтина}} $1 царах $2 {{PLURAL:$2|беша бац}})",
- "echo-mark-all-as-read": "Массо билгалъе еша сана",
+ "echo-mark-all-as-read": "Массо билгалъе ешна сана",
+ "echo-mark-wiki-as-read": "Хаьржинчу вики чура ерриге ешна санна билгалъе: $1",
"echo-date-today": "Тахана",
"echo-date-yesterday": "Селхана",
"echo-load-more-error": "Кхин тӀе хилам схьаоьцуш гӀалат хила",
- "notification-edit-talk-page-bundle": "$1 а $3 {{PLURAL:$4|кхи}} {{GENDER:$1|декъашхоша}} хьан [[User talk:$2|дийцаре агӀонехь хаам битина]].",
- "notification-page-linked-bundle": "АгӀона тӀе «$2» {{GENDER:$1|хьажорг}} ю «$3» агӀона чура а кхин $4 {{PLURAL:$5|агӀона|агӀонийн}}. [[Special:WhatLinksHere/$2|Хьажа массо хьажоргашка]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 а $2 {{PLURAL:$3|кхин}} {{GENDER:$1|декъашхоша}} хьан дийцаре агӀонехь хаам битина.",
- "notification-page-linked-email-batch-bundle-body": "АгӀона «$2» тӀе {{GENDER:$1|хьажорг ю}} «$3» агӀона чура а кхин $4 {{PLURAL:$5|агӀона|агӀонийн}} чура а",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|керла хаам бу}} <strong>{{GENDER:$3|хьан}} дийцаре агӀонгахь</strong>.",
"echo-email-batch-subject-daily": "Хьоьга кхаьчна $2 {{PLURAL:$2|керла хаам|керла хаамаш}} «{{SITENAME}}» проектехь",
"echo-email-batch-subject-weekly": "ХӀокху кӀиран чохь хьоьга кхаьчна $2 {{PLURAL:$2|керла хаам|керла хаамаш}} «{{SITENAME}}» проектехь",
"echo-email-batch-body-intro-daily": "Маршалла, $1!\nТахан хилларг {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Маршалла, $1!\nТахан хилларг {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "Массо хаамашка хьажар",
- "echo-rev-deleted-text-view": "Хьара агӀона верси къайлаяьккхина",
- "apihelp-echomarkread-description": "Билгалде дӀахаийтарш хьаьжна сана.",
- "apihelp-echomarkread-param-list": "Хьажжина сана билгалдаран ID дӀахаийтарийн могӀам."
+ "notification-header-foreign-alert": "Дукха дӀахьедарш {{PLURAL:$5|кхечу вики чура|$5 кхечу викеш чура}}",
+ "notification-header-foreign-notice": "Дукха хаамаш {{PLURAL:$5|кхечу вики чура|$5 кхечу викеш чура}}",
+ "notification-header-foreign-all": "Дукха дӀахьедарш {{PLURAL:$5|кхечу вики чура|$5 кхечу викеш чура}}"
}
diff --git a/Echo/i18n/ckb.json b/Echo/i18n/ckb.json
index 6eb4c312..689971bc 100644
--- a/Echo/i18n/ckb.json
+++ b/Echo/i18n/ckb.json
@@ -1,10 +1,15 @@
{
"@metadata": {
"authors": [
- "Calak"
+ "Calak",
+ "Asoxor",
+ "Macofe",
+ "Sarchia",
+ "Muhammed taha",
+ "Lost Whispers"
]
},
- "echo-desc": "سیستەمی ئاگادارییەکان",
+ "echo-desc": "سیستەمی ئاگادارکردنەوەی بەکارھێنەران سەبارەت بە ڕووداوەکان و پەیامەکان",
"prefs-echo": "ئاگادارییەکان",
"prefs-emailsettings": "ھەڵبژاردەکانی ئیمەیل",
"prefs-displaynotifications": "ھەڵبژاردەکانی پێشاندان",
@@ -16,9 +21,9 @@
"echo-pref-web": "وێب",
"echo-pref-email": "ئیمەیل",
"echo-pref-email-frequency-never": "ھیچ ئاگاداراییەکم بە ئیمەیل بۆ مەنێرە",
- "echo-pref-email-frequency-immediately": "ئاگادارییە تاکەکەسییەکان ھەر وەکی دێن",
- "echo-pref-email-frequency-daily": "کورتەیەکی رۆژانەی ئاگادارییەکان",
- "echo-pref-email-frequency-weekly": "کورتەیەکی حەفتانەی ئاگادارییەکان",
+ "echo-pref-email-frequency-immediately": "ھەر ئەو کاتەی کە تاکە ئاگادارییەکم بۆ دێت",
+ "echo-pref-email-frequency-daily": "ڕۆژێک جارێک، پوختەیەکی ئاگادارییەکان",
+ "echo-pref-email-frequency-weekly": "ھەفتەیەک جارێک، پوختەیەکی ئاگادارییەکان",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "دەقی ساکار",
"echo-pref-new-message-indicator": "نیشاندەری پەیامی پەڕەی لێدوان لە تووڵامرازەکەمدا نیشان بدە",
@@ -31,66 +36,49 @@
"echo-category-title-other": "{{PLURAL:$1|دیکە}}",
"echo-category-title-system": "{{PLURAL:$1|سیستەم}}",
"echo-category-title-user-rights": "{{PLURAL:$1|گۆڕانی مافەکانی بەکارھێنەر}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|ئیمێل لە بەکارھێنەرێکی ترەوە|ئیمێلەکان لە بەکارھێنارانی ترەوە}}",
"echo-pref-tooltip-edit-user-talk": "کاتێک کەسێک لە پەڕەی لێدوانمدا پەیامێکی نارد یان وەڵامی دامەوە، ئاگادارم بکە.",
"echo-pref-tooltip-article-linked": "کاتێک کەسێک لە پەڕەیەکی وتاردا بە پەڕەیەک کە من دروستم کردووە بەستەری دا، ئاگادارم بکە.",
"echo-pref-tooltip-reverted": "کاتێک کەسێک دەستکارییەکی من کردوومە بە ئامرازی پووچەڵکردنەوە یان گەڕاندنەوە دەگەڕێنێتەوە، ئاگادارم بکە.",
- "echo-pref-tooltip-mention": "کاتێک کەسێک لە پەڕەیەکی لێدواندا بە پەڕەی بەکارھێنەریی من بەستەری دا، ئاگادارم بکە.",
- "echo-no-agent": "[هیچ کەس]",
- "echo-no-title": "[بێ سەردێڕ]",
+ "echo-pref-tooltip-mention": "ئاگادارم بکەرەوە، ئەگەر کەسێک بۆ پەڕەی بەکارھێنەریی من بەستەری دانا.",
+ "echo-pref-tooltip-user-rights": "ئاگاداردم بکەرەوە، کاتێک کە کەسێک مافە بەکارھێنەرییەکانم دەگۆڕێت.",
+ "echo-pref-tooltip-emailuser": "ئاگادارم بەکەرەوە کاتێک کە کەسێک ئیمێلێکم بۆ دەنێرێت.",
"echo-error-no-formatter": "ھیچ شێوازێک بۆ ئاگاداری دیاری نەکراوە.",
"notifications": "ئاگادارییەکان",
"tooltip-pt-notifications-alert": "{{GENDER:|ھۆشدارەکانت}}",
- "tooltip-pt-notifications-message": "{{GENDER:|پەیامەکانەت}}",
"echo-specialpage": "ئاگادارییەکان",
+ "echo-specialpage-pagefilters-title": "چالاکیی تازە",
+ "echo-specialpage-pagefilters-subtitle": "پەڕەکانی ئاگادارییە نەخوێندراوەکان",
"echo-anon": "بۆ وەرگرتنی ئاگادارییەکان، [$1 ھەژمارێک دروست بکە] یان [$2 بچۆ ژوورەوە].",
- "echo-none": "ئاگادارییەکت نییە.",
+ "echo-none": "ھیچ ئاگادارییەکت نییە.",
"echo-more-info": "زانیاریی زیاتر",
"echo-feedback": "بەردەنگ",
+ "echo-notification-placeholder": "ھیچ ئاگادارییەک نییە.",
+ "echo-notification-markasread": "نیشانکردن وەکوو خوێنراو",
+ "echo-notification-markasunread": "نیشانکردن وەکوو نەخوێنراوە",
+ "echo-notification-markasread-tooltip": "نیشانکردن وەکوو خوێنراو",
"notification-link-text-view-message": "پەیام ببینە",
"notification-link-text-view-mention": "ئاماژە ببینە",
- "notification-link-text-view-changes": "گۆڕانکارییەکان ببینە",
+ "notification-link-text-view-changes": "{{GENDER:$1|دەستکارییەکانی ببینە}}",
"notification-link-text-view-page": "پەڕە ببینە",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|ئاماژەی بە}} {{GENDER:$3|تۆ}} کرد لە پەڕەی <strong>لێدوانەکەی {{GENDER:$2|خۆی|خۆی|خۆیان}}</strong>.",
+ "notification-header-welcome": "$1، {{GENDER:$2|بەخێربێیت}} بۆ {{SITENAME}}! خۆشحاڵین کە {{GENDER:$2|ھاتوویت}} بۆ ئێرە.",
+ "notification-welcome-linktext": "بەخێربێیت",
"notification-link-text-view-edit": "دەستکاری ببینە",
- "notification-edit-talk-page2": "[[User:$1|$1]] پەیامێکی لە [[User talk:$2#$3|پەڕەی لێدوان]]تدا {{GENDER:$1|نووسی}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] پەیامێکی لە [[User talk:$2#$3|پەڕەی لێدوان]]ت لە \"[[User talk:$2#$3|$4]]\"دا {{GENDER:$1|نووسی}}.",
- "notification-edit-talk-page-flyout2": "$1 پەیامێکی لە [[User talk:$2#$3|پەڕەی لێدوان]]تدا {{GENDER:$1|نووسی}}.",
- "notification-edit-talk-page-flyout-with-section": "$1 پەیامێکی لە [[User talk:$2#$3|پەڕەی لێدوان]]ت لە \"[[User talk:$2#$3|$4]]\"دا {{GENDER:$1|نووسی}}.",
- "notification-page-linked": "[[:$2]] لە [[:$3]]دا {{GENDER:$1|بەستەر درا}}. [[Special:WhatLinksHere/$2|ھەموو بەستەرە بەسراوەکان بەم پەڕەیەوە ببینە]].",
- "notification-page-linked-flyout": "[[:$2]] لە [[:$3]]دا {{GENDER:$1|بەستەر درا}}.",
- "notification-add-comment2": "[[User:$1|$1]] لە «[[$3|$2]]»ی پەڕەی لێدوانی «$4»دا بۆچۆنی نووسی.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] بابەتی نوێی «$2»ی لە [[$3]]دا نووسی.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] پەیامێکی بۆ ناردی: «[[$3#$2|$2]]».",
- "notification-add-comment-yours2": "[[User:$1|$1]] لە «[[$3#$2|$2]]»ی پەڕەی لێدوانتدا بۆچۆنی نووسی.",
- "notification-mention": "[[User:$1|$1]] لە پەڕەی لێدوانی $5 لە «[[:$3#$2|$4]]»دا ئاماژەی پێ‌کردی.",
- "notification-mention-flyout": "$1 لە پەڕەی لێدوانی $5 لە «[[:$3#$2|$4]]»دا ئاماژەی پێ‌کردی.",
- "notification-mention-nosection": "[[User:$1|$1]] لە [[:$3|پەڕەی لێدوانی $2]]دا ئاماژەی {{GENDER:$1| پێ‌کردی}}.",
- "notification-mention-nosection-flyout": "$1 لە [[:$3|پەڕەی لێدوانی $2]]دا ئاماژەی {{GENDER:$1| پێ‌کردی}}.",
- "notification-user-rights": "مافەکانی بەکارھێنەریت لە لایەن [[User:$1|$1]]ەوە [[Special:Log/rights/$1|{{GENDER:$1|گۆڕدرا}}]]. $2. [[Special:ListGroupRights|زیاتر بزانە]]",
- "notification-user-rights-flyout": "مافەکانی بەکارھێنەریت لە لایەن $1ەوە {{GENDER:$1|گۆڕدرا}}. $2. [[Special:ListGroupRights|زیاتر بزانە]]",
- "notification-user-rights-add": "تۆ ھەر ئێستا ئەندامی ئەم {{PLURAL:$2|گرووپە|گرووپانە}}ی: $1",
- "notification-user-rights-remove": "تۆ ئیتر ئەندامی ئەم {{PLURAL:$2|گرووپە|گرووپانە}} نی: $1",
- "notification-new-user": "بەخێرھاتی بۆ {{SITENAME}}، $1! کەیفخۆشین لێرەی.",
- "notification-reverted2": "{{PLURAL:$4|دەستکارییەکەت|دەستکارییەکانت}} لە [[:$2]]دا لە لایەن [[User:$1|$1]]ەوە {{GENDER:$1|گەڕێنرایەوە}}. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|دەستکارییەکەت|دەستکارییەکانت}} لە $2دا لە لایەن $1ەوە {{GENDER:$1|گەڕێنرایەوە}}. $3",
+ "notification-header-reverted": "{{PLURAL:$4|دەستکارییەکەت|دەستکارییەکانت}} لە $3دا لە لایەن $1ەوە {{GENDER:$2|گەڕێنرایەوە}}.",
+ "notification-header-emailuser": "$1 ئیمێلێکی بۆ {{GENDER:$2|ناردی}}.",
"notification-edit-talk-page-email-subject2": "$1 لە {{SITENAME}}دا پەیامێکی بۆ ناردی.",
- "notification-edit-talk-page-email-batch-body2": "$1 لە پەڕەی لێدوانتدا پەیامێکی نارد.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 لە پەڕەی لێدوانت لە «$2»دا پەیامێکی نارد.",
"notification-page-linked-email-subject": "پەڕەکەت لە {{SITENAME}}دا بەستەر درا.",
- "notification-page-linked-email-batch-body": "$2 لە $3دا {{GENDER:$1|بەستەر درا}}.",
"notification-reverted-email-subject2": "{{PLURAL:$3|دەستکارییەکەت|دەستکارییەکانت}} لە {{SITENAME}}دا {{GENDER:$1|گەڕێنرایەوە}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|دەستکارییەکەت|دەستکارییەکانت}} لە $2دا لە لایەن $1ەوە {{GENDER:$1|گەڕێنرایەوە}}.",
"notification-mention-email-subject": "$1 لە {{SITENAME}}دا ئاماژەی پێ‌کردی.",
- "notification-mention-email-batch-body": "$1 لە پەڕەی لێدوانی $4 لە «$3»دا ئاماژەی پێ‌کردی.",
- "notification-mention-nosection-email-batch-body": "$1 لە پەڕەی لێدوانی $2دا ئاماژەی {{GENDER:$1|پێ‌کردی}}.",
"notification-user-rights-email-subject": "مافەکانی بەکارھێنەریت لە {{SITENAME}}دا گۆڕدرا.",
- "notification-user-rights-email-batch-body": "مافەکانی بەکارھێنەریت لە لایەن $1ەوە گۆڕدرا. $2.",
- "echo-email-subject-default": "ئاگادارییەکی نوێ لە {{SITENAME}}",
+ "notification-inbox-filter-read": "خوێندنەوە",
+ "notification-inbox-filter-unread": "نەخوێنراوە",
+ "notification-inbox-filter-all": "ھەموو",
"echo-email-body-default": "ئاگادارییەکی نوێت ھەیە لە {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "ئاگادارییەکی نوێت ھەیە.",
"echo-email-footer-default": "$2\n\nبۆ کۆنترۆڵی ئەو ئیمەیلانەی بۆت دەنێرین، ھەڵبژاردەکانت تاوتوێ بکە:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "\n\nبۆ کۆنترۆڵی ئەو ئیمەیلانەی بۆت دەنێرین، <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">ھەڵبژاردەکانت تاوتوێ بکە</a>.<br />:\n$1",
"echo-notification-alert-text-only": "ھۆشدارەکان",
- "echo-notification-message-text-only": "پەیامەکان",
"echo-overlay-link": "ھەموو ئاگادارییەکان",
"echo-overlay-title": "<b>ئاگادارییەکان</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|ئاگادارییەکان}}</b> (نیشاندانی $1 لە $2ی نەخوێنراو)",
@@ -98,14 +86,9 @@
"echo-date-today": "ئەمڕۆ",
"echo-date-yesterday": "دوێنێ",
"echo-load-more-error": "ھەڵەیەک لە کاتی وەرگرتنی ئاکامی زیاتر ڕووی دا.",
- "notification-edit-talk-page-bundle": "$1 و $3ی {{PLURAL:$4|تر}} لە [[User talk:$2|پەڕەی لێدوان]]تدا پەیامێکیان ناردووە.",
- "notification-page-linked-bundle": "$2 لە $3 و $4 {{PLURAL:$5|پەڕە}}ی تردا {{GENDER:$1|بەستەر درا}}. [[Special:WhatLinksHere/$2|ھەموو بەسراوەکان بەم پەڕەیە ببینە]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 و $2ی {{PLURAL:$3|تر}} لە پەڕەی لێدوانتدا پەیامێکیان ناردووە.",
- "notification-page-linked-email-batch-bundle-body": "$2 لە $3 و $4 {{PLURAL:$5|پەڕە}}ی تردا {{GENDER:$1|بەستەر درا}}.",
"echo-email-batch-subject-daily": "لە {{SITENAME}}دا {{PLURAL:$2|ئاگادارییەکی نوێت|ئاگاداریی نوێت}} ھەیە",
"echo-email-batch-subject-weekly": "لە {{SITENAME}}دا {{PLURAL:$2|ئاگادارییەکی نوێت|ئاگاداریی نوێت}} لەم حەفتەیەدا ھەیە",
"echo-email-batch-body-intro-daily": "سڵاو $1،\nئەمە کۆرتەیەکە لە چالاکییەکانی ئەمرۆی {{SITENAME}} بۆ تۆ.",
"echo-email-batch-body-intro-weekly": "سڵاو $1،\nئەمە کۆرتەیەکە لە چالاکییەکانی حەفتانەی {{SITENAME}} بۆ تۆ.",
- "echo-email-batch-link-text-view-all-notifications": "ھەموو ئاگادارییەکان ببینە",
- "echo-rev-deleted-text-view": "پێداچوونەوەی ئەم پەڕەیە بێسراوە."
+ "echo-email-batch-link-text-view-all-notifications": "ھەموو ئاگادارییەکان ببینە"
}
diff --git a/Echo/i18n/cs.json b/Echo/i18n/cs.json
index 16c6ac7c..d9e00ef4 100644
--- a/Echo/i18n/cs.json
+++ b/Echo/i18n/cs.json
@@ -6,7 +6,13 @@
"Mormegil",
"Vks",
"Matěj Suchánek",
- "Cvanca"
+ "Cvanca",
+ "Teslaton",
+ "Kvetoslav47",
+ "Dvorapa",
+ "Danny B.",
+ "Meliganai",
+ "Martin Urbanec"
]
},
"echo-desc": "Systém pro upozorňování uživatelů na události a zprávy",
@@ -14,7 +20,9 @@
"prefs-emailsettings": "Nastavení e-mailu",
"prefs-displaynotifications": "Možnosti zobrazení",
"prefs-echosubscriptions": "Upozorněte mě na…",
+ "prefs-echocrosswiki": "Upozornění napříč projekty",
"prefs-newmessageindicator": "Indikátor nových zpráv",
+ "prefs-blocknotificationslist": "Ztlumení uživatelé",
"echo-pref-send-me": "Posílejte mi:",
"echo-pref-send-to": "Posílat na:",
"echo-pref-email-format": "Formát e-mailu:",
@@ -26,97 +34,178 @@
"echo-pref-email-frequency-weekly": "Týdenní souhrn upozornění",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Prostý text",
+ "echo-pref-cross-wiki-notifications": "Zobrazovat upozornění z jiných wiki",
+ "echo-pref-notifications-blacklist": "Nezobrazovat notifikace od těchto uživatelů. ([[mw:Help:Notifications#mute|dozvědět se více]])",
"echo-pref-new-message-indicator": "Zobrazit indikátor diskusních zpráv v mém panelu nástrojů",
+ "echo-pref-beta-feature-cross-wiki-message": "Vylepšená upozornění",
+ "echo-pref-beta-feature-cross-wiki-description": "Prohlížejte si a organizujte upozornění snadněji. Zahrnuje upozornění napříč wikiprojekty, což vám umožňuje vidět zprávy z jiných wiki. (Abyste na dané wiki přijímali upozornění napříč wikiprojekty, musíte na té wiki zapnout tuto betafunkci.)",
"echo-learn-more": "Další informace",
+ "echo-log": "Veřejný záznam",
"echo-new-messages": "Máte nové zprávy",
- "echo-category-title-edit-user-talk": "{{PLURAL:$1|příspěvek|příspěvky}} v diskusi",
- "echo-category-title-article-linked": "{{PLURAL:$1|odkaz|odkazy}} na stránku",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|příspěvek|příspěvky}} na diskusní stránce",
+ "echo-category-title-article-linked": "{{PLURAL:$1|odkaz|odkazy}} na vytvořenou stránku",
"echo-category-title-reverted": "{{PLURAL:$1|vrácenou úpravu|vrácené úpravy}}",
"echo-category-title-mention": "{{PLURAL:$1|zmínku|zmínky}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|neprovedenou zmínku|neprovedené zmínky}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|úspěšnou zmínku|úspěšné zmínky}}",
"echo-category-title-other": "{{PLURAL:$1|jinou událost|jiné události}}",
"echo-category-title-system": "{{PLURAL:$1|systémovou událost|systémové události}}",
"echo-category-title-user-rights": "{{PLURAL:$1|změnu|změny}} uživatelských práv",
+ "echo-category-title-emailuser": "{{PLURAL:$1|e-mail od jiného uživatele|e-maily od jiných uživatelů}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|upomínku|upomínky}} ke stránkám",
"echo-pref-tooltip-edit-user-talk": "Upozorněte mě, když mi někdo na mé diskusní stránce napíše zprávu nebo odpoví.",
- "echo-pref-tooltip-article-linked": "Upozorněte mě, když někdo na stránku, kterou jsem založil, odkáže z článku.",
- "echo-pref-tooltip-reverted": "Upozorněte mě, když někdo úpravu, kterou jsem provedl, vrátí pomocí nástrojů pro zrušení editace nebo vrácení zpět.",
+ "echo-pref-tooltip-article-linked": "Upozorněte mě, když někdo na stránku, kterou jsem {{GENDER:|založil|založila}}, odkáže z jiné stránky.",
+ "echo-pref-tooltip-reverted": "Upozorněte mě, když někdo úpravu, kterou jsem {{GENDER:|provedl|provedla}}, vrátí pomocí nástrojů pro zrušení editace nebo vrácení zpět.",
"echo-pref-tooltip-mention": "Upozorněte mě, když někdo odkáže na mou uživatelskou stránku.",
+ "echo-pref-tooltip-mention-failure": "Upozorněte mě, když někomu nešlo odeslat zmínku.",
+ "echo-pref-tooltip-mention-success": "Upozorněte mě, když někomu odešlu zmínku.",
"echo-pref-tooltip-user-rights": "Upozorněte mě, když někdo změní moje uživatelská práva.",
- "echo-no-agent": "[Nikdo]",
- "echo-no-title": "[Žádná stránka]",
- "echo-error-no-formatter": "Upozornění nemá definováno formátování",
+ "echo-pref-tooltip-emailuser": "Upozorněte mě, když mi někdo pošle e-mail.",
+ "echo-error-no-formatter": "Upozornění nemá definováno formátování.",
"notifications": "Upozornění",
"tooltip-pt-notifications-alert": "{{GENDER:|Vaše}} upozornění",
- "tooltip-pt-notifications-message": "{{GENDER:|Vaše}} zprávy",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Vaše}} oznámení",
+ "echo-displaynotificationsconfiguration": "Zobrazení konfigurace Notifikací",
+ "echo-displaynotificationsconfiguration-summary": "Toto je přehled konfigurace Notifikací na této wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notifikace podle kategorií",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Třídění typů",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Do které sekce se každý typ notifikace zařadí",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Povolené notifikační metody",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Které notifikační metody jsou podporovány pro každou kategorii",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Které notifikační metody jsou podporovány pro každý typ; platí pouze pro typy v rámci kategorií, které jsou v nastavení skryty",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Implicitně zapnuté",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Stávající uživatelé",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Noví uživatelé",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Vyžadované notifikační metody",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Které notifikační metody jsou pro každou kategorii povinné",
"echo-specialpage": "Upozornění",
+ "echo-specialpage-section-markread": "Označit skupinu jako přečtenou",
+ "echo-specialpage-markasread": "Oznámení: Označit jako přečtené",
+ "echo-specialpage-markasread-invalid-id": "Chybné ID události",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|upozornění}}",
+ "echo-specialpage-pagefilters-title": "Nedávná aktivita",
+ "echo-specialpage-pagefilters-subtitle": "Stránky s nepřečtenými upozorněními",
+ "notificationsmarkread-legend": "Označit oznámení jako přečtené",
"echo-anon": "Pro zobrazování upozornění je nutné [$1 vytvořit si účet] nebo [$2 se přihlásit].",
- "echo-none": "Nemáte žádné upozornění.",
+ "echo-none": "Nemáte žádná upozornění.",
"echo-more-info": "Více informací",
"echo-feedback": "Názor",
+ "echo-popup-footer-special-page-invitation": "<strong>Vyzkoušejte přepracovanou stránku s upozorněními.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Včetně nového vzhledu a funkcí.",
"echo-quotation-marks": "„$1“",
+ "echo-api-failure": "Nepodařilo se načíst oznámení.",
+ "echo-api-failure-cross-wiki": "Přístup ke vzdálené doméně byl odepřen.",
"echo-notification-placeholder": "Nemáte žádná upozornění.",
+ "echo-notification-placeholder-filters": "Nemáte žádná upozornění odpovídající těmto kritériím.",
+ "echo-notification-loginrequired": "Musíte se přihlásit, abyste mohli vidět svá upozornění.",
+ "echo-notification-popup-loginrequired": "Pro prohlížení svých oznámení se prosím přihlaste.",
+ "echo-notification-markasread": "Označit jako přečtené",
+ "echo-notification-markasunread": "Označit jako nepřečtené",
+ "echo-notification-markasread-tooltip": "Označit jako přečtené",
+ "echo-notification-more-options-tooltip": "Více možností",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Přestat}} sledovat novou aktivitu na stránce „$1“",
+ "notification-dynamic-actions-unwatch-confirmation": "Stránku „$1“ už nadále {{GENDER:$3|nesledujete}}",
+ "notification-dynamic-actions-unwatch-confirmation-description": "[$2 Tuto stránku] můžete kdykoli {{GENDER:$3|sledovat}}.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Sledovat}} novou aktivitu na stránce „$1“",
+ "notification-dynamic-actions-watch-confirmation": "Odteď {{GENDER:$3|sledujete}} stránku „$1“",
+ "notification-dynamic-actions-watch-confirmation-description": "[$2 Tuto stránku] můžete kdykoli {{GENDER:$3|přestat sledovat}}.",
+ "notification-link-text-expand-all": "Rozbalit",
+ "notification-link-text-expand-alert-count": "Zobrazit {{PLURAL:$1|$1 upozornění}}",
+ "notification-link-text-expand-notice-count": "Zobrazit {{PLURAL:$1|$1 oznámení}}",
+ "notification-link-text-expand-all-count": "Zobrazit {{PLURAL:$1|$1 oznámení}}",
+ "notification-link-text-collapse-all": "Sbalit",
"notification-link-text-view-message": "Zobrazit zprávu",
"notification-link-text-view-mention": "Zobrazit zmínku",
- "notification-link-text-view-changes": "Zobrazit změny",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Zobrazit zmínku|Zobrazit zmínky}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Zobrazit}} změny",
"notification-link-text-view-page": "Zobrazit stránku",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$3|vám}} {{GENDER:$2|napsal|napsala}} na <strong>vaši diskusní stránku</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$3|vám}} {{GENDER:$2|napsal|napsala}} na <strong>vaši diskusní stránku</strong> k „<strong>$4</strong>“.",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Ze stránky <strong>$4</strong> byl vytvořen odkaz na stránku <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Ze stránky <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "{{PLURAL:$5||Ze $5 stránek|Z $5 stránek|100=Z více než 99 stránek}} byly vytvořeny odkazy na stránku <strong>$3</strong>.",
+ "notification-header-article-reminder": "Stránka, na kterou jste si {{GENDER:$2|přál být upozorněn|přála být upozorněna}}, se nachází na <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Všechny odkazy na tuto stránku",
+ "notification-header-mention-other": "$1 {{GENDER:$3|vás}} {{GENDER:$2|zmínil|zmínila}} v diskusi <strong>$4</strong> u „<strong>$5</strong>“.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|vás}} {{GENDER:$2|zmínil|zmínila}} v diskusi <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|vás}} {{GENDER:$2|zmínil|zmínila}} v <strong>diskusi {{GENDER:$5|uživatele|uživatelky}} $4</strong> u „<strong>$6</strong>“.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|vás}} {{GENDER:$2|zmínil|zmínila}} v <strong>diskusi {{GENDER:$5|uživatele|uživatelky}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|vás}} {{GENDER:$2|zmínil|zmínila}} na <strong>své diskusní stránce</strong> u „<strong>$4</strong>“.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|vás}} {{GENDER:$2|zmínil|zmínila}} na <strong>své diskusní stránce</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|vás}} {{GENDER:$2|zmínil|zmínila}} v diskusi k článku <strong>$4</strong> u „<strong>$5</strong>“.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|vás}} {{GENDER:$2|zmínil|zmínila}} v diskusi k článku <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Vaše}} zmínka uživatele <strong>$3</strong> nemohla být odeslána, protože uživatel nebyl nalezen.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Vaše}} zmínka uživatele <strong>$3</strong> nemohla být odeslána, protože uživatel je anonymní.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Pokusil|Pokusila|Pokusil(a)}} jste se zmínit více než {{PLURAL:$3|jednoho uživatele|$3 uživatele|$3 uživatelů}}. Všechny zmínky nad tento limit nebyly odeslány.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Jednu vaši zmínku|$3 vaše zmínky|$3 vašich zmínek}} na diskusní stránce <strong>$4</strong> {{GENDER:$2|nebylo}} možné odeslat.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Uživatelské jméno neexistuje:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP adresy nelze zmínit:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Vaše}} zmínka {{GENDER:$3|uživatele|uživatelky}} <strong>$3</strong> byla odeslána.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|{{GENDER:$2|Vaše}} zmínka|$3 vaše zmínky|$3 vašich zmínek}} na diskusní stránce <strong>$4</strong> {{PLURAL:$3|byla odeslána|byly odeslány|bylo odesláno}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Zmínil|Zmínila|Zmínil(a)}} jste:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Upozornění|$3 upozornění}} na {{GENDER:$2|vámi}} provedené zmínky na diskusní stránce <strong>$4</strong>: {{PLURAL:$5|jedna neodeslaná|$5 neodeslané|$5 neodeslaných}}, {{PLURAL:$6|jedna odeslaná|$6 odeslané|$6 odeslaných}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Vaše}} uživatelská práva byla {{GENDER:$1|změněna}}. Nyní patříte do: $2.",
+ "notification-header-user-rights-remove-only": "Vaše uživatelská práva byla {{GENDER:$1|změněna}}. Už nejste {{GENDER:$4|členem|členkou}}: $2.",
+ "notification-header-user-rights-add-and-remove": "Vaše uživatelská práva byla {{GENDER:$1|změněna}}. Nyní patříte do: $2. Už nejste {{GENDER:$6|členem|členkou}}: $4.",
+ "notification-header-user-rights-expiry-change": "Čas vypršení {{GENDER:$4|vašeho}} členství v {{PLURAL:$3|následující skupině|následujících skupinách}} byl {{GENDER:$1|změněn}}: $2.",
+ "notification-header-welcome": "Vítejte na {{GRAMMAR:6sg|{{SITENAME}}}}, {{GENDER:$2|uživateli|uživatelko}} $1! Jsme rádi, že jste zde.",
+ "notification-welcome-linktext": "Vítejte",
+ "notification-header-thank-you-1-edit": "Právě jste {{GENDER:$2|provedl|provedla}} svou první editaci. Díky a vítejte!",
+ "notification-header-thank-you-10-edit": "Právě jste {{GENDER:$2|provedl|provedla}} svou desátou editaci. Díky a jen tak dál!",
+ "notification-header-thank-you-100-edit": "Právě jste {{GENDER:$2|provedl|provedla}} svou stou editaci. Velké díky!",
+ "notification-header-thank-you-1000-edit": "Právě jste {{GENDER:$2|provedl|provedla}} svou tisící editaci. Díky, jste {{GENDER:$2|skvělý přispěvatel|skvělá přispěvatelka}}!",
+ "notification-header-thank-you-10000-edit": "Právě jste {{GENDER:$2|provedl|provedla}} svou desetitisící editaci. Velmi velké díky!",
+ "notification-header-thank-you-100000-edit": "Právě jste {{GENDER:$2|provedl|provedla}} svou stotisící editaci. Díky za váš úžasný příspěvek!",
+ "notification-header-thank-you-1000000-edit": "Právě jste {{GENDER:$2|provedl|provedla}} svou miliontou editaci. Díky za váš ohromující příspěvek!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Vaše}} editace",
"notification-link-text-view-edit": "Zobrazit editaci",
- "notification-edit-talk-page2": "[[User:$1|$1]] vám {{GENDER:$1|napsal|napsala}} na [[User talk:$2#$3|vaši diskusní stránku]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] vám {{GENDER:$1|napsal|napsala}} na vaši diskusní stránku k „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "$1 vám {{GENDER:$1|napsal|napsala}} na [[User talk:$2#$3|vaši diskusní stránku]].",
- "notification-edit-talk-page-flyout-with-section": "$1 vám {{GENDER:$1|napsal|napsala}} na vaši diskusní stránku k „[[User talk:$2#$3|$4]]“.",
- "notification-page-linked": "Do stránky [[:$3]] {{GENDER:$1|byl přidán}} odkaz na stránku [[:$2]]. [[Special:WhatLinksHere/$2|Zobrazit všechny odkazy na tuto stránku]].",
- "notification-page-linked-flyout": "Do stránky [[:$3]] {{GENDER:$1|byl přidán}} odkaz na stránku [[:$2]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|přidal|přidala}} komentář k „[[$3|$2]]“ na stránce „$4“",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|přidal|přidala}} komentář na nové téma „$2“ na stránce „[[$3]]“",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] vám {{GENDER:$1|poslal|poslala}} zprávu: „[[$3#$2|$2]]“",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|přidal|přidala}} komentář k „[[$3#$2|$2]]“ na vaší diskusní stránce",
- "notification-mention": "[[User:$1|$1]] vás {{GENDER:$1|zmínil|zmínila}} v diskusi k „$5“ u „[[:$3#$2|$4]]“.",
- "notification-mention-flyout": "$1 vás {{GENDER:$1|zmínil|zmínila}} v diskusi $5 u „[[:$3#$2|$4]]“.",
- "notification-mention-nosection": "[[User:$1|$1]] vás {{GENDER:$1|zmínil|zmínila}} v [[:$3|diskusi ke stránce $2]].",
- "notification-mention-nosection-flyout": "$1 vás {{GENDER:$1|zmínil|zmínila}} v [[:$3|diskusi ke stránce $2]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|změnil|změnila}}]] vaše uživatelská práva. $2. [[Special:ListGroupRights|Více informací]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|změnil|změnila}} vaše uživatelská práva. $2. [[Special:ListGroupRights|Více informací]]",
- "notification-user-rights-add": "Nyní patříte do {{PLURAL:$2|této skupiny|těchto skupin}}: $1",
- "notification-user-rights-remove": "Nadále už nepatříte do {{PLURAL:$2|této skupiny|těchto skupin}}: $1",
- "notification-new-user": "Vítejte na {{grammar:6sg|{{SITENAME}}}}, {{GENDER:$1|uživateli|uživatelko}} $1! Těší nás, že jste tu.",
- "notification-reverted2": "[[User:$1|$1]] {{GENDER:$1|revertoval|revertovala}} {{PLURAL:$4|vaši editaci|vaše editace}} stránky [[:$2]] $3",
- "notification-reverted-flyout2": "$1 {{GENDER:$1|revertoval|revertovala}} {{PLURAL:$4|vaši editaci|vaše editace}} stránky $2 $3",
- "notification-edit-talk-page-email-subject2": "$1 vám na {{grammar:6sg|{{SITENAME}}}} {{GENDER:$1|napsal|napsala}} zprávu.",
- "notification-edit-talk-page-email-batch-body2": "$1 vám {{GENDER:$1|napsal|napsala}} na vaši diskusní stránku.",
+ "notification-link-article-reminder": "Zobrazit stránku",
+ "notification-header-reverted": "Vaše editace stránky <strong>$3</strong> {{PLURAL:$4|byla vrácena|byly vráceny}} {{GENDER:$2|zpět}}.",
+ "notification-header-emailuser": "$1 vám {{GENDER:$2|poslal|poslala}} e-mail.",
+ "notification-edit-talk-page-email-subject2": "$1 vám na {{grammar:6sg|{{SITENAME}}}} {{GENDER:$1|napsal|napsala}} zprávu",
"notification-edit-talk-page-email-batch-body-with-section": "$1 vám {{GENDER:$1|napsal|napsala}} na vaši diskusní stránku k „$2“.",
"notification-page-linked-email-subject": "Na {{grammar:6sg|{{SITENAME}}}} někdo odkázal na vámi založenou stránku",
- "notification-page-linked-email-batch-body": "Do stránky $3 {{GENDER:$1|byl přidán}} odkaz na stránku $2",
"notification-reverted-email-subject2": "$1 {{GENDER:$1|revertoval|revertovala}} {{PLURAL:$3|vaši editaci|vaše editace}} na {{grammar:6sg|{{SITENAME}}}}",
- "notification-reverted-email-batch-body2": "$1 {{GENDER:$1|revertoval|revertovala}} {{PLURAL:$3|vaši editaci|vaše editace}} stránky $2.",
- "notification-mention-email-subject": "$1 vás na {{grammar:6sg|{{SITENAME}}}} {{GENDER:$1|zmínil|zmínila}}",
- "notification-mention-email-batch-body": "$1 vás {{GENDER:$1|zmínil|zmínila}} v diskusi $4 u „$3“.",
- "notification-mention-nosection-email-batch-body": "$1 vás {{GENDER:$1|zmínil|zmínila}} v diskusi ke stránce $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|vás}} na {{grammar:6sg|{{SITENAME}}}} {{GENDER:$1|zmínil|zmínila}}",
"notification-user-rights-email-subject": "Na {{grammar:6sg|{{SITENAME}}}} byla změněna vaše uživatelská práva",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|změnil|změnila}} vaše uživatelská práva. $2",
- "echo-email-subject-default": "Nové upozornění na {{grammar:6sg|{{SITENAME}}}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 měs.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 r}}",
+ "notification-timestamp-today": "Dnes",
+ "notification-timestamp-yesterday": "Včera",
+ "notification-inbox-filter-read": "Přečtená",
+ "notification-inbox-filter-unread": "Nepřečtená",
+ "notification-inbox-filter-all": "Všechna",
"echo-email-body-default": "Na {{grammar:6sg|{{SITENAME}}}} máte nové upozornění:\n\n$1",
- "echo-email-batch-body-default": "Máte nové upozornění",
+ "echo-email-footer-default-html": "Posílání e-mailů si můžete přizpůsobit v <a href=\"$2\" style=\"text-decoration: none; color: #3868B0;\">nastavení</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nPosílání e-mailů si můžete přizpůsobit v nastavení:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Posílání e-mailů si můžete přizpůsobit <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">v nastavení</a>.<br />\n$1",
+ "echo-email-plain-footer": "Posílání e-mailů si {{GENDER:$1|můžete}} přizpůsobit v nastavení:",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|nastavení}}",
+ "echo-email-html-footer-with-link": "Posílání e-mailů si {{GENDER:$2|můžete}} přizpůsobit v $1.",
"echo-notification-alert": "{{PLURAL:$1|Upozornění ($1)|100=Upozornění (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Zpráva ($1)|Zprávy ($1)|100=Zprávy (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Oznámení ($1)|100=Oznámení (99+)}}",
"echo-notification-alert-text-only": "Upozornění",
- "echo-notification-message-text-only": "Zprávy",
+ "echo-notification-notice-text-only": "Oznámení",
"echo-overlay-link": "Všechna upozornění",
"echo-overlay-title": "<b>Upozornění</b>",
- "echo-overlay-title-overflow": "<b>Upozornění</b> (zobrazuje se $1 z $2 {{PLURAL:$1|nepřečteného|nepřečtených}})",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Upozornění}}</b> ({{PLURAL:$1|zobrazuje|zobrazují|zobrazuje}} se $1 z $2 {{PLURAL:$2|nepřečteného|nepřečtených}})",
"echo-mark-all-as-read": "Označit vše jako přečtené",
+ "echo-mark-all-as-read-confirmation": "$1 oznámení {{PLURAL:$1|označeno jako přečtené|označena jako přečtená|označeno jako přečtená}}",
+ "echo-mark-wiki-as-read": "Označit všechno za přečtené ve vybrané wiki: $1",
"echo-date-today": "Dnes",
"echo-date-yesterday": "Včera",
"echo-load-more-error": "Při načítání dalších výsledků došlo k chybě.",
- "notification-edit-talk-page-bundle": "$1 a $3 {{PLURAL:$4|další}} vám napsali na [[User talk:$2|vaši diskusní stránku]].",
- "notification-page-linked-bundle": "Do stránky $3 a $4 {{PLURAL:$5|další stránky|dalších stránek}} {{GENDER:$1|byly přidány}} odkazy na stránku $2: [[Special:WhatLinksHere/$2|Zobrazit všechny odkazy na tuto stránku]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 a $2 {{PLURAL:$3|další}} vám napsali na vaši diskusní stránku",
- "notification-page-linked-email-batch-bundle-body": "Do stránky $3 a $4 {{PLURAL:$5|další stránky|dalších stránek}} {{GENDER:$1|byly přidány}} odkazy na stránku $2",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|$1 nová zpráva|$1 nové zprávy|$1 nových zpráv|100=Více než 99 nových zpráv}} na <strong>{{GENDER:$3|vaší}} diskusní stránce</strong>.",
"echo-email-batch-subject-daily": "Na {{grammar:6sg|{{SITENAME}}}} dnes máte {{PLURAL:$2|nové|nová}} upozornění",
"echo-email-batch-subject-weekly": "Na {{grammar:6sg|{{SITENAME}}}} máte tento týden {{PLURAL:$2|nové|nová}} upozornění",
- "echo-email-batch-body-intro-daily": "Ahoj, uživateli $1,\n\nzde pro vás máme shrnutí dnešní aktivity na {{grammar:6sg|{{SITENAME}}}}",
+ "echo-email-batch-body-intro-daily": "Ahoj, uživateli $1,\n\nzde pro vás máme shrnutí dnešní aktivity na {{grammar:6sg|{{SITENAME}}}}.",
"echo-email-batch-body-intro-weekly": "Ahoj, uživateli $1,\n\nzde pro vás máme shrnutí aktivity na {{grammar:6sg|{{SITENAME}}}} za tento týden",
"echo-email-batch-link-text-view-all-notifications": "Zobrazit všechna upozornění",
- "echo-rev-deleted-text-view": "Tato verze stránky byla utajena",
- "apihelp-echomarkseen-example-1": "Označit oznámení všech typů jako přečtená"
+ "notification-header-foreign-alert": "Více upozornění z {{PLURAL:$5|další wiki|$5 dalších wiki}}",
+ "notification-header-foreign-notice": "Více oznámení z {{PLURAL:$5|další wiki|$5 dalších wiki}}",
+ "notification-header-foreign-all": "Další notifikace z {{PLURAL:$5|jiné wiki|$5 jiných wiki}}"
}
diff --git a/Echo/i18n/csb.json b/Echo/i18n/csb.json
new file mode 100644
index 00000000..a7266e5d
--- /dev/null
+++ b/Echo/i18n/csb.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kaszeba"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "Mòjé alarmë",
+ "notification-link-article-reminder": "Òbôczë starnã"
+}
diff --git a/Echo/i18n/cu.json b/Echo/i18n/cu.json
index d35964fb..7b4b7369 100644
--- a/Echo/i18n/cu.json
+++ b/Echo/i18n/cu.json
@@ -7,5 +7,10 @@
"echo-learn-more": "поꙁнаи вѧщє",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|напьсаниѥ|напьсании|напьсаниꙗ}} бєсѣдꙑ страницѣ",
"echo-category-title-system": "{{PLURAL:$1|сѷстима}}",
+ "tooltip-pt-notifications-alert": "{{GENDER:|твоѩ}} повѣщєниꙗ",
+ "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|напьса}} твоѥи [[User talk:$2#$3|бєсѣдꙑ страници]]",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|напьса}} {{GENDER:$3|твоѥи}} бєсѣдꙑ страници въ чѧсти ⁖ $4 ⁖",
+ "notification-add-talkpage-topic2": "[[User:$1|$1]] новоу бєсѣдꙑ чѧсть имєньмь ⁖ $2 ⁖ {{GENDER:$1|почѧ}} страници ⁖ [[$3]] ⁖",
+ "echo-date-today": "дьньсь",
"echo-date-yesterday": "вьчєра"
}
diff --git a/Echo/i18n/cy.json b/Echo/i18n/cy.json
index b3c7fb57..50731042 100644
--- a/Echo/i18n/cy.json
+++ b/Echo/i18n/cy.json
@@ -1,7 +1,9 @@
{
"@metadata": {
"authors": [
- "Lloffiwr"
+ "Lloffiwr",
+ "Robin Owain",
+ "Diafol"
]
},
"echo-desc": "Sustem hysbysu",
@@ -21,7 +23,6 @@
"echo-pref-email-frequency-weekly": "Crynodeb wythnosol o'r hysbysiadau",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Testun plaen",
- "echo-pref-notify-show-link": "Dangos hysbysiadau yn fy mar offer",
"echo-pref-new-message-indicator": "Dangos arwydd bod neges newydd ar fy nhudalen sgwrs yn fy mar offer",
"echo-learn-more": "Darllen mwy",
"echo-new-messages": "Mae negeseuon newydd gennych",
@@ -35,13 +36,9 @@
"echo-pref-tooltip-article-linked": "Fy hysbysu pan fo rhywun yn gosod cyswllt o ryw erthygl i dudalen a ddechreuais i.",
"echo-pref-tooltip-reverted": "Hysbyswch fi pan fo rhywun yn dadwneud golygiad o'm heiddo i, drwy ddefnyddio'r teclynnau dadwneud neu wrthdroi.",
"echo-pref-tooltip-mention": "Hysbyswch fi pan fo rhywun yn gosod cyswllt at fy nhudalen defnyddiwr oddi wrth rhyw dudalen sgwrs.",
- "echo-no-agent": "[Neb]",
- "echo-no-title": "[Dim tudalen]",
"echo-error-no-formatter": "Ni phenwyd unrhyw fformat i'r hysbysiad.",
- "echo-error-preference": "Gwall: Ni ellid gosod y dewis yn newisiadau'r defnyddiwr.",
- "echo-error-token": "Gwall: Ni ellid adalw tocyn y defnyddiwr.",
"notifications": "Hysbysiadau",
- "tooltip-pt-notifications": "Eich hysbysiadau",
+ "tooltip-pt-notifications-alert": "Eich hysbysiadau",
"echo-specialpage": "Hysbysiadau",
"echo-anon": "Er mwyn derbyn hysbysiadau, [$1 dechreuwch gyfrif] neu [$2 mewngofnodwch].",
"echo-none": "Nid oes unrhyw hysbysiadau gennych.",
@@ -52,44 +49,15 @@
"notification-link-text-view-changes": "Gweld y newidiadau",
"notification-link-text-view-page": "Gweld y dudalen",
"notification-link-text-view-edit": "Gweld y golygiad",
- "notification-edit-talk-page2": "{{GENDER:$1|Gadawodd}} [[User:$1|$1]] neges ar eich [[User talk:$2#$3|tudalen sgwrs]].",
- "notification-edit-talk-page-with-section": "{{GENDER:$1|Gadawodd}} [[User:$1|$1]] neges ar eich tudalen sgwrs yn yr adran \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "{{GENDER:$1|Gadawodd}} $1 neges ar eich [[User talk:$2#$3|tudalen sgwrs]].",
- "notification-edit-talk-page-flyout-with-section": "{{GENDER:$1|Gadawodd}} $1 neges ar eich tudalen sgwrs yn yr adran \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "{{GENDER:$1|Cysylltwyd}} [[:$2]] o [[:$3]]. [[Special:WhatLinksHere/$2|Gweler yr holl gysylltau i'r dudalen hon]].",
- "notification-page-linked-flyout": "{{GENDER:$1|Cysylltwyd}} [[:$2]] o [[:$3]].",
- "notification-add-comment2": "{{GENDER:$1|Gadawodd}} [[User:$1|$1]] sylw am \"[[$3|$2]]\" ar y dudalen sgwrs \"$4\".",
- "notification-add-talkpage-topic2": "{{GENDER:$1|Gosododd}} [[User:$1|$1]] sylw ar y pwnc newydd \"$2\" ar [[$3]].",
- "notification-add-talkpage-topic-yours2": "{{GENDER:$1|Anfonodd}} [[User:$1|$1]] neges atoch: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "{{GENDER:$1|Gosododd}} [[User:$1|$1]] sylw am \"[[$3#$2|$2]]\" ar eich tudalen sgwrs.",
- "notification-mention": "{{GENDER:$1|Cyfeiriodd}} [[User:$1|$1]] atoch ar dudalen sgwrs $5 yn yr adran \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "{{GENDER:$1|Cyfeiriodd}} $1 atoch ar dudalen sgwrs $5 yn yr adran \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "{{GENDER:$1|Cyfeiriodd}} [[User:$1|$1]] atoch ar [[:$3|dudalen sgwrs $2]].",
- "notification-mention-nosection-flyout": "{{GENDER:$1|Cyfeiriodd}} $1 atoch ar [[:$3|dudalen sgwrs $2]].",
- "notification-user-rights": "[[Special:Log/rights/$1|{{GENDER:$1|Newidiwyd}}]] eich galluoedd defnyddiwr gan [[User:$1|$1]]. $2. [[Special:ListGroupRights|Darllen mwy]]",
- "notification-user-rights-flyout": "{{GENDER:$1|Newidiwyd}} eich galluoedd defnyddiwr gan $1. $2. [[Special:ListGroupRights|Darllen mwy]]",
- "notification-user-rights-add": "Rydych nawr yn aelod o'r {{PLURAL:$2|grŵp hwn|grŵp hwn|grwpiau hyn}}: $1",
- "notification-user-rights-remove": "Nid ydych bellach yn aelod o'r {{PLURAL:$2|grŵp hwn|grŵp hwn|grwpiau hyn}}: $1",
- "notification-new-user": "Croeso i {{SITENAME}}, $1! Rydym yn falch eich bod wedi cyrraedd.",
- "notification-reverted2": "{{GENDER:$1|Dadwneuthpwyd}} eich {{PLURAL:$4||golygiad ar [[:$2]]|golygiadau ar [[:$2]]}} gan [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{GENDER:$1|Dadwneuthpwyd}} eich {{PLURAL:$4||golygiad ar $2|golygiadau ar $2}} gan $1. $3",
+ "notification-header-reverted": "{{GENDER:$2|Dadwneuthpwyd}} eich {{PLURAL:$4||golygiad ar $3|golygiadau ar $3}} gan $1.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|Gosododd}} $1 neges i chi ar {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|Gosododd}} $1 neges ar eich tudalen sgwrs:",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Gosododd}} $1 neges ar eich tudalen sgwrs yn \"$2\".",
"notification-page-linked-email-subject": "Cysylltwyd i'ch tudalen ar {{SITENAME}}",
- "notification-page-linked-email-batch-body": "{{GENDER:$1|Gosodwyd}} cyswllt o $3 i $2.",
"notification-reverted-email-subject2": "{{GENDER:$1|Dadwnaethpwyd}} eich {{PLURAL:$3||golygiad|golygiadau}} ar {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{GENDER:$1|Dadwnaethpwyd}} eich {{PLURAL:$3||golygiad|golygiadau}}ar $2 gan $1.",
"notification-mention-email-subject": "{{GENDER:$1|Cyfeiriodd}} $1 atoch ar {{SITENAME}}",
- "notification-mention-email-batch-body": "{{GENDER:$1|Cyfeiriodd}} $1 atoch ar dudalen sgwrs $4 yn yr adran \"$3\".",
- "notification-mention-nosection-email-batch-body": "{{GENDER:$1|Cyfeiriodd}} $1 atoch ar y dudalen sgwrs $2.",
"notification-user-rights-email-subject": "Newidiodd eich galluoedd fel defnyddiwr ar {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Newidiwyd eich galluoedd {{GENDER:$1|defnyddiwr}} gan $1. $2.",
- "echo-email-subject-default": "Hysbysiad newydd ar {{SITENAME}}",
"echo-email-body-default": "Mae hysbysiad newydd gennych ar {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Mae hysbysiad newydd gennych.",
"echo-email-footer-default": "$2\n\nOs am reoli yr ebyst y cewch gennym, ewch i'ch dewisiadau:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "I reoli'r ebyst i'w hanfon atoch, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">ewch i'ch dewisiadau</a>.<br />\n$1",
"echo-overlay-link": "Pob hysbysiad",
"echo-overlay-title": "<b>Hysbysiadau</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Hysbysiadau}}</b> (yn dangos $1 o $2 heb eu darllen)",
@@ -97,14 +65,9 @@
"echo-date-today": "Heddiw",
"echo-date-yesterday": "Ddoe",
"echo-load-more-error": "Cafwyd gwall wrth nôl rhagor o ganlyniadau.",
- "notification-edit-talk-page-bundle": "{{GENDER:$1|Gadawodd}} $1 a $3 {{PLURAL:$4|a $3 arall|ac $3 arall|a $3 eraill}} negeseuon ar eich [[User talk:$2|tudalen defnyddiwr]].",
- "notification-page-linked-bundle": "{{GENDER:$1|Gosodwyd}} cysylltiad at $2 o $3 {{PLURAL:$5||ac $4 dudalen arall|a $4 dudalen arall|a $4 o dudalennau eraill}}. [[Special:WhatLinksHere/$2|Gweler yr holl gysylltiadau i'r dudalen hon]]",
- "notification-edit-user-talk-email-batch-bundle-body": "{{GENDER:$1|Gadawodd}} $1 {{PLURAL:$3||ac $2 arall||a $2 arall| a $2 eraill}} negeseuon ar eich tudalen sgwrs.",
- "notification-page-linked-email-batch-bundle-body": "{{GENDER:$1|Gosodwyd}} gyswllt i $2 oddi wrth $3 {{PLURAL:$5||ac $4 dudalen arall|a $2 dudalen arall|a $2 o dudalennau eraill}}.",
"echo-email-batch-subject-daily": "Mae {{PLURAL:$2||hysbysiad|hysbysiadau}} newydd gennych ar {{SITENAME}}",
"echo-email-batch-subject-weekly": "Mae {{PLURAL:$2||hysbysiad|hysbysiadau}} newydd gennych yr wythnos hon ar {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Sut mae $1,\nDyma grynodeb i chi o weithgaredd heddiw ar {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Sut mae $1,\nDyma grynodeb i chi o weithgaredd yr wythnos hon ar {{SITENAME}}.",
- "echo-email-batch-link-text-view-all-notifications": "Gweld yr holl hysbysiadau",
- "echo-rev-deleted-text-view": "Cuddiwyd y diwygiad hwn o'r dudalen."
+ "echo-email-batch-link-text-view-all-notifications": "Gweld yr holl hysbysiadau"
}
diff --git a/Echo/i18n/da.json b/Echo/i18n/da.json
index 89bc95a2..e96aaaa4 100644
--- a/Echo/i18n/da.json
+++ b/Echo/i18n/da.json
@@ -6,10 +6,14 @@
"Palnatoke",
"Sarrus",
"Tjernobyl",
- "Thomsen"
+ "Thomsen",
+ "Cgtdk",
+ "Macofe",
+ "Simeondahl",
+ "SimmeD"
]
},
- "echo-desc": "Meddelelsessystem",
+ "echo-desc": "System til at give brugere besked om handlinger og meddelelser",
"prefs-echo": "Meddelelser",
"prefs-emailsettings": "E-mailindstillinger",
"prefs-displaynotifications": "Indstillinger for visning",
@@ -26,9 +30,10 @@
"echo-pref-email-frequency-weekly": "En ugentlig oversigt over meddelelser",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Plain text",
- "echo-pref-notify-show-link": "Vis meddelelser i min værktøjslinje",
+ "echo-pref-cross-wiki-notifications": "Vis notifikationer fra andre wikier",
"echo-pref-new-message-indicator": "Vis indikator for meddelelser på diskussionssiden i min værktøjslinje",
"echo-learn-more": "Find ud af mere",
+ "echo-log": "Offentlig log",
"echo-new-messages": "Du har nye beskeder",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Besked|Beskeder}} på diskussionsside",
"echo-category-title-article-linked": "{{PLURAL:$1|Sidehenvisning|Sidehenvisninger}}",
@@ -37,19 +42,18 @@
"echo-category-title-other": "{{PLURAL:$1|Anden|Andre}}",
"echo-category-title-system": "{{PLURAL:$1|System}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Ændring af brugerrettighed|Ændring af brugerrettigheder}}",
- "echo-pref-tooltip-edit-user-talk": "Giv mig besked når nogen skriver en besked eller et svar på min diskussionsside.",
- "echo-pref-tooltip-article-linked": "Giv mig beked når nogen henviser til en side som jeg har oprettet, fra en artikelside.",
- "echo-pref-tooltip-reverted": "Giv mig besked når nogen tilbagestiller en redigering som jeg lavet, ved at bruge fjern redigering eller rul tilbage.",
+ "echo-pref-tooltip-edit-user-talk": "Giv mig besked, når nogen skriver en besked eller et svar på min diskussionsside.",
+ "echo-pref-tooltip-article-linked": "Giv mig besked, når nogen henviser til en side, som jeg har oprettet, fra en artikelside.",
+ "echo-pref-tooltip-reverted": "Giv mig besked, når nogen tilbagestiller en redigering, som jeg lavet, ved at bruge \"fjern redigering\" eller \"rul tilbage\".",
"echo-pref-tooltip-mention": "Giv mig besked når nogen henviser til min brugerside.",
- "echo-pref-tooltip-user-rights": "Giv mig besked når nogen ændrer mine brugerrettigheder.",
- "echo-no-agent": "[Ingen]",
- "echo-no-title": "[Ingen side]",
+ "echo-pref-tooltip-user-rights": "Giv mig besked, når nogen ændrer mine brugerrettigheder.",
+ "echo-pref-tooltip-emailuser": "Giv mig besked, når nogen sender mig en email.",
"echo-error-no-formatter": "Der er ikke defineret et format for meddelelsen",
- "echo-error-preference": "Fejl: Kunne ikke gemme brugerindstillinger",
- "echo-error-token": "Fejl: Kunne ikke hente brugertoken",
"notifications": "Meddelelser",
- "tooltip-pt-notifications": "Dine meddelelser",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Dine}} alarmer",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Dine}} meddelelser",
"echo-specialpage": "Meddelelser",
+ "echo-specialpage-pagefilters-subtitle": "Sider med ulæste meddelelser",
"echo-anon": "For at modtage meddelelser skal du [$1 oprette en konto] eller [$2 logge ind].",
"echo-none": "Du har ingen meddelelser.",
"echo-more-info": "Mere information",
@@ -58,45 +62,30 @@
"notification-link-text-view-mention": "Se omtale",
"notification-link-text-view-changes": "Se ændringer",
"notification-link-text-view-page": "Se side",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|efterlod}} en meddelelse på <strong>{{GENDER:$3|din}} diskussionsside</strong>.",
+ "notification-header-page-linked": "Der blev oprettet et link fra <strong>$4</strong> til <strong>$3</strong>",
+ "notification-header-mention-other": "$1 {{GENDER:$2|nævnte}} {{GENDER:$3|dig}} på <strong>$4</strong> i \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|nævnte}} {{GENDER:$3|dig}} på <strong>$4</strong>.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|nævnte}} {{GENDER:$3|dig}} på <strong>{{GENDER:$2|sin|sin|sin}} diskussionsside</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|nævnte}} {{GENDER:$3|dig}} på <strong>$4</strong>s diskussionsside i \"<strong>$5</strong>\".",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Dine}} brugerrettigheder blev {{GENDER:$1|ændret}}. Du er blevet tilføjet til: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Dine}} brugerrettigheder blev {{GENDER:$1|ændret}}. Du er ikke længere medlem af: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Dine}} brugerrettigheder blev {{GENDER:$1|Ændret}}. Du er blevet tilføjet til: $2. Du er ikke længere medlem af: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Velkommen}} til {{SITENAME}}, $1! Vi er glade for {{GENDER:$2|du}} er her.",
+ "notification-welcome-linktext": "Velkommen",
"notification-link-text-view-edit": "Se redigering",
- "notification-edit-talk-page2": "[[User:$1|$1]] skrev en besked på din [[User talk:$2#$3|diskussionsside]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] lagde en besked på din diskussionsside i \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 skrev et indlæg på din [[User talk:$2#$3|diskussionsside]].",
- "notification-edit-talk-page-flyout-with-section": "$1 lagde en besked på din diskussionside i \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Der blev {{GENDER:$1|henvist}} til [[:$2]] fra [[:$3]]. [[Special:WhatLinksHere/$2|Se alle henvisninger til siden]].",
- "notification-page-linked-flyout": "Der blev {{GENDER:$1|henvist}} til [[:$2]] fra [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] kommenterede om \"[[$3|$2]]\" på diskussionssiden \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] skrev et nyt indlæg om \"$2\" på [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] har sendt dig en besked: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] kommenterede om \"[[$3#$2|$2]]\" på din diskussionsside",
- "notification-mention": "[[User:$1|$1]] omtalte dig på diskussionssiden $5 i \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 omtalte dig på diskussionssiden $5 i \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|nævnte}} dig på [[:$3|diskussionssiden for \"$2\"]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|nævnte}} dig på [[:$3|diskussionssiden for \"$2\"]].",
- "notification-user-rights": "Dine brugerrettigheder [[Special:Log/rights/$1|blev ændret]] af [[User:$1|$1]]. $2. [[Special:ListGroupRights|Find ud af mere]]",
- "notification-user-rights-flyout": "Dine brugerrettigheder blev ændret af $1. $2. [[Special:ListGroupRights|Find ud af mere]]",
- "notification-user-rights-add": "Du er nu medlem af {{PLURAL:$2|denne gruppe|disse grupper}}: $1",
- "notification-user-rights-remove": "du er ikke længere medlem af {{PLURAL:$2|denne gruppe|disse grupper}}: $1",
- "notification-new-user": "Velkommen til {{SITENAME}}, $1! Vi er glade for at du er her.",
- "notification-reverted2": "{{PLURAL:$4|Din redigering af [[:$2]] er blevet tilbagestillet|Dine redigeringer af [[:$2]] er blevet tilbagestillede}} af [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Din redigering af $2 er blevet tilbagestillet|Dine redigeringer af $2 er blevet tilbagestillede}} af $1 $3",
+ "notification-header-reverted": "{{PLURAL:$4|Din redigering af <strong>$3</strong> er blevet tilbagestillet|Dine redigeringer af <strong>$3</strong> er blevet tilbagestillede}} af $2",
"notification-edit-talk-page-email-subject2": "$1 lagde en besked til dig på {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 skrev et indlæg på din diskussionsside",
"notification-edit-talk-page-email-batch-body-with-section": "$1 lagde en besked på din diskussionsside i \"$2\".",
"notification-page-linked-email-subject": "En side som du oprettede blev henvist til på {{SITENAME}}",
- "notification-page-linked-email-batch-body": "Der {{GENDER:$1|blev}} henvist til $2 fra $3",
"notification-reverted-email-subject2": "{{PLURAL:$3|Din redigering blev|Dine redigeringer blev}} {{GENDER:$1|omgjort}} på {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Din redigering|Dine redigeringer}} på $2 er omgjort af $1.",
"notification-mention-email-subject": "$1 omtalte dig på {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 omtalte dig på diskussionssiden $4 i \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|nævnte}} dig på diskussionssiden for \"$2\".",
"notification-user-rights-email-subject": "Dine brugerrettigheder er blevet ændret på {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Dine brugerrettigheder er blevet ændret af $1. $2",
- "echo-email-subject-default": "Ny meddelelse på {{SITENAME}}",
+ "notification-timestamp-today": "I dag",
+ "notification-inbox-filter-read": "Læs",
"echo-email-body-default": "Der er en ny meddelelse til dig på {{SITENAME}}\n\n$1",
- "echo-email-batch-body-default": "Der er en ny meddelelse til dig",
"echo-email-footer-default": "$2\n\nTjek dine indstillinger for at se hvilke e-mails vi sender til dig:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "For at styre hvilke e-mails, vi sender til dig, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">tjek dine indstillinger</a><br />\n$1",
+ "echo-notification-alert": "{{PLURAL:$1|Meddelelse ($1)|Meddelelser ($1)|100=Meddelelser (99+)}}",
"echo-overlay-link": "Alle meddelelser",
"echo-overlay-title": "<b>Meddelelser</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Meddelelser}}<b> (viser $1 af $2 ulæste)",
@@ -104,14 +93,10 @@
"echo-date-today": "I dag",
"echo-date-yesterday": "I går",
"echo-load-more-error": "Der skete en fejl under hentningen af flere resultater.",
- "notification-edit-talk-page-bundle": "$1 og $3 {{PLURAL:$4|andre}} lagde en besked på din [[User talk:$2|diskussionsside]].",
- "notification-page-linked-bundle": "$2 {{GENDER:$1|blev}} henvist til fra $3 og $4 {{PLURAL:$5|anden side|andre sider}}. [[Special:WhatLinksHere/$2|Se alle henvisninger til siden]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 og $2 {{PLURAL:$3|anden|andre}} skrev indlæg på din diskussionsside",
- "notification-page-linked-email-batch-bundle-body": "$2 {{GENDER:$1|blev}} henvist til fra $3 og $4 {{PLURAL:$5|anden side|andre sider}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|En ny besked|$1 nye beskeder|100=99+ nye beskeder}} på <strong>{{GENDER:$3|din}} diskussionsside</strong>.",
"echo-email-batch-subject-daily": "Du har {{PLURAL:$2|en ny meddelelse|$2 nye meddelelser}} på {{SITENAME}}",
"echo-email-batch-subject-weekly": "Du har {{PLURAL:$2|en ny meddelelse|$2 nye meddelelser}} på {{SITENAME}} i denne uge",
"echo-email-batch-body-intro-daily": "Hej $1,\nHer er en oversigt over dagens aktivitet på {{SITENAME}} for dig.",
"echo-email-batch-body-intro-weekly": "Hej $1,\nHer er et resumé af denne uges aktivitet på {{SITENAME}} for dig.",
- "echo-email-batch-link-text-view-all-notifications": "Se alle meddelelser",
- "echo-rev-deleted-text-view": "Denne sideversion er skjult."
+ "echo-email-batch-link-text-view-all-notifications": "Se alle meddelelser"
}
diff --git a/Echo/i18n/de.json b/Echo/i18n/de.json
index 9fa363a4..34d0e7ac 100644
--- a/Echo/i18n/de.json
+++ b/Echo/i18n/de.json
@@ -8,15 +8,21 @@
"ChrisiPK",
"Suriyaa Kudo",
"Purodha",
- "Tiin"
+ "Tiin",
+ "Predatorix",
+ "FriedhelmW",
+ "MGChecker",
+ "Vogone"
]
},
- "echo-desc": "System zur Benachrichtigung von Benutzern über Ereignisse und Nachrichten",
+ "echo-desc": "Stellt ein System zur Benachrichtigung von Benutzern über Ereignisse und Nachrichten bereit",
"prefs-echo": "Benachrichtigungen",
"prefs-emailsettings": "E-Mail-Optionen",
"prefs-displaynotifications": "Anzeigeoptionen",
"prefs-echosubscriptions": "Bei diesen Ereignissen benachrichtigen",
+ "prefs-echocrosswiki": "Wikiübergreifende Benachrichtigungen",
"prefs-newmessageindicator": "Hinweise zu neuen Nachrichten",
+ "prefs-blocknotificationslist": "Ignorierte Benutzer",
"echo-pref-send-me": "Sende mir:",
"echo-pref-send-to": "Sende an:",
"echo-pref-email-format": "E-Mail-Format:",
@@ -24,122 +30,183 @@
"echo-pref-email": "E-Mail",
"echo-pref-email-frequency-never": "Keine Benachrichtigungen",
"echo-pref-email-frequency-immediately": "Individuelle Benachrichtigung zu jedem Ereignis",
- "echo-pref-email-frequency-daily": "Tägliche Benachrichtigung zu den Ereignissen",
- "echo-pref-email-frequency-weekly": "Wöchentliche Benachrichtigung zu den Ereignissen",
+ "echo-pref-email-frequency-daily": "Tägliche Zusammenfassung der Benachrichtigungen",
+ "echo-pref-email-frequency-weekly": "Wöchentliche Zusammenfassung der Benachrichtigungen",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Nur Text",
+ "echo-pref-cross-wiki-notifications": "Benachrichtigungen von anderen Wikis anzeigen",
+ "echo-pref-notifications-blacklist": "Benachrichtigungen von diesen Benutzern nicht anzeigen ([[mw:Help:Notifications#mute|mehr erfahren]]).",
"echo-pref-new-message-indicator": "Hinweise zu neuen Nachrichten in meiner Benutzerleiste anzeigen",
+ "echo-pref-beta-feature-cross-wiki-message": "Erweiterte Benachrichtigungen",
+ "echo-pref-beta-feature-cross-wiki-description": "Betrachte und organisiere deine Benachrichtigungen einfacher. Beinhaltet wikiübergreifende Benachrichtigungen, die dich Nachrichten von anderen Wikis sehen lassen. Um wikiübergreifende Benachrichtigungen auf einem angegebenen Wiki zu erhalten, musst du die entsprechende Beta-Funktion auf diesem Wiki aktivieren.",
"echo-learn-more": "Mehr erfahren",
+ "echo-log": "Öffentliches Logbuch",
"echo-new-messages": "Du hast neue Nachrichten",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Diskussionsseitennachricht|Diskussionsseitennachrichten}}",
"echo-category-title-article-linked": "{{PLURAL:$1|Seitenverlinkung|Seitenverlinkungen}}",
"echo-category-title-reverted": "{{PLURAL:$1|Rückgängigmachung einer Bearbeitung|Rückgängigmachungen von Bearbeitungen}}",
"echo-category-title-mention": "{{PLURAL:$1|Erwähnung|Erwähnungen}}",
+ "echo-category-title-mention-failure": "Erfolglose {{PLURAL:$1|Erwähnung|Erwähnungen}}",
+ "echo-category-title-mention-success": "Erfolgreiche {{PLURAL:$1|Erwähnung|Erwähnungen}}",
"echo-category-title-other": "{{PLURAL:$1|Andere}}",
"echo-category-title-system": "{{PLURAL:$1|System}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Benutzerrechteänderung|Benutzerrechteänderungen}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-Mail von einem anderen Benutzer|E-Mails von anderen Benutzern}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Seitenerinnerung|Seitenerinnerungen}}",
"echo-pref-tooltip-edit-user-talk": "Benachrichtige mich, wenn jemand eine Nachricht oder eine Antwort auf meiner Diskussionsseite hinterlässt.",
- "echo-pref-tooltip-article-linked": "Benachrichtige mich, wenn jemand in einem Artikel auf eine Seite verlinkt, die ich erstellt habe.",
+ "echo-pref-tooltip-article-linked": "Benachrichtige mich, wenn jemand auf einer Seite auf eine andere von mir erstellte Seite verlinkt.",
"echo-pref-tooltip-reverted": "Benachrichtige mich, wenn jemand eine von mir gemachte Bearbeitung rückgängig macht oder zurücksetzt.",
"echo-pref-tooltip-mention": "Benachrichtige mich, wenn jemand auf meine Benutzerseite verlinkt.",
+ "echo-pref-tooltip-mention-failure": "Benachrichtige mich, wenn ich keine Erwähnung an jemanden versenden konnte.",
+ "echo-pref-tooltip-mention-success": "Benachrichtige mich, wenn ich eine Erwähnung an jemanden versandt habe.",
"echo-pref-tooltip-user-rights": "Benachrichtige mich, wenn jemand meine Benutzerrechte ändert.",
- "echo-no-agent": "[Niemand]",
- "echo-no-title": "[Keine Seite]",
+ "echo-pref-tooltip-emailuser": "Benachrichtige mich, wenn mir jemand eine E-Mail sendet.",
+ "echo-pref-tooltip-article-reminder": "Benachrichtige mich über diese Seite, wenn ich dies verlange.",
"echo-error-no-formatter": "Keine Formatierung zur Benachrichtigung definiert",
"notifications": "Benachrichtigungen",
"tooltip-pt-notifications-alert": "{{GENDER:|Deine}} Meldungen",
- "tooltip-pt-notifications-message": "{{GENDER:|Deine}} Nachrichten",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Deine}} Mitteilungen",
+ "echo-displaynotificationsconfiguration": "Benachrichtigungskonfiguration anzeigen",
+ "echo-displaynotificationsconfiguration-summary": "Dies ist eine Übersicht, wie Benachrichtigungen auf diesem Wiki konfiguriert sind.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Benachrichtigungen nach Kategorie",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sortierung der Typen",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Welcher Abschnitt jedes Benachrichtigungstyps einsortiert ist",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Erlaubte Benachrichtigungsmethoden",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Welche Benachrichtigungsmethoden für jede Kategorie unterstützt werden",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Welche Benachrichtigungsmethoden für jeden Typ unterstützt werden. Nur auf die Typen innerhalb Kategorien zutreffend, die in den Einstellungen ausgeblendet sind.",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Standardmäßig aktiviert",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Vorhandene Benutzer",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Neue Benutzer",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Erforderliche Benachrichtigungsmethoden",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Welche Benachrichtigungsmethoden für jede Kategorie verpflichtend sind",
"echo-specialpage": "Benachrichtigungen",
+ "echo-specialpage-section-markread": "Gruppe als gelesen markieren",
+ "echo-specialpage-markasread": "Benachrichtigung: Als gelesen markieren",
+ "echo-specialpage-markasread-invalid-id": "Ungültige Ereigniskennung",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|Eine Benachrichtigung|$1 Benachrichtigungen}}",
+ "echo-specialpage-pagefilters-title": "Letzte Aktivität",
+ "echo-specialpage-pagefilters-subtitle": "Seiten mit ungelesenen Benachrichtigungen",
+ "notificationsmarkread-legend": "Benachrichtigung als gelesen markieren",
"echo-anon": "Um Benachrichtigungen erhalten zu können, muss man ein [$1 Benutzerkonto anlegen] oder sich [$2 anmelden].",
"echo-none": "Du hast keine Benachrichtigungen.",
"echo-more-info": "Mehr Informationen",
- "echo-feedback": "Rückmeldung",
- "echo-api-failure": "Benachrichtigungen konnten nicht abgerufen werden. Bitte erneut versuchen. (Fehler $1)",
+ "echo-feedback": "Rückmeldungen",
+ "echo-popup-footer-special-page-invitation": "<strong>Teste die neu gestaltete Benachrichtigungsseite.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Mit neuem Aussehen und neuen Funktionen.",
+ "echo-api-failure": "Benachrichtigungen konnten nicht abgerufen werden.",
+ "echo-api-failure-cross-wiki": "Der Zugriff auf die Remote-Domäne wurde abgelehnt.",
"echo-notification-placeholder": "Es gibt keine Benachrichtigungen.",
+ "echo-notification-placeholder-filters": "Es gibt keine Benachrichtigungen, die diesen Kriterien entsprechen.",
+ "echo-notification-loginrequired": "Du musst dich anmelden, um deine Benachrichtigungen zu sehen.",
+ "echo-notification-popup-loginrequired": "Bitte melde dich an, um deine Benachrichtigungen anzusehen.",
+ "echo-notification-markasread": "Als gelesen markieren",
+ "echo-notification-markasunread": "Als ungelesen markieren",
+ "echo-notification-markasread-tooltip": "Als gelesen markieren",
+ "echo-notification-more-options-tooltip": "Weitere Optionen",
+ "notification-dynamic-actions-unwatch": "Neue Aktivitäten zu „$1“ {{GENDER:$3|nicht}} mehr beobachten",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Du}} beobachtest nicht mehr die Seite „$1“",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Du}} kannst jederzeit [$2 diese Seite] beobachten.",
+ "notification-dynamic-actions-watch": "Neuen Aktivitäten zu „$1“ {{GENDER:$3|folgen}}",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Du}} beobachtest jetzt die Seite „$1“",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Du}} kannst jederzeit mit dem Beobachten [$2 dieser Seite] aufhören.",
+ "notification-link-text-expand-all": "Ausklappen",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|Eine Meldung|$1 Meldungen}} ansehen",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|Eine Mitteilung|$1 Mitteilungen}} ansehen",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|Eine Benachrichtigung|$1 Benachrichtigungen}} ansehen",
+ "notification-link-text-collapse-all": "Einklappen",
"notification-link-text-view-message": "Nachricht ansehen",
"notification-link-text-view-mention": "Erwähnung ansehen",
- "notification-link-text-view-changes": "Änderungen ansehen",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Erwähnung|Erwähnungen}} ansehen",
+ "notification-link-text-view-changes": "{{GENDER:$1|Änderungen}} ansehen",
"notification-link-text-view-page": "Seite ansehen",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|hinterließ}} eine Nachricht auf <strong>{{GENDER:$3|deiner}} Diskussionsseite</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|hinterließ}} eine Nachricht auf <strong>{{GENDER:$3|deiner}} Diskussionsseite</strong> in „<strong>$4</strong>“.",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Ein Link von <strong>$4</strong> auf <strong>$3</strong> wurde erstellt.",
+ "notification-compact-header-page-linked": "Verlinkt von <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Links von {{PLURAL:$5||$5 Seiten|100=mehr als 99 Seiten}} auf <strong>$3</strong>.",
+ "notification-header-article-reminder": "Eine Seite, an die {{GENDER:$2|du}} erinnert werden möchtest, befindet sich unter <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Alle Links auf diese Seite",
+ "notification-header-mention-other": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$3|dich}} auf <strong>$4</strong> in „<strong>$5</strong>“.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$3|dich}} auf <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$3|dich}} auf der <strong>Benutzerdiskussionsseite {{GENDER:$5|von}} $4</strong> in „<strong>$6</strong>“.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$3|dich}} auf der <strong>Benutzerdiskussionsseite {{GENDER:$5|von}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$3|dich}} auf <strong>{{GENDER:$2|seiner|ihrer}} Diskussionsseite</strong> in „<strong>$4</strong>“.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$3|dich}} auf <strong>{{GENDER:$2|seiner|ihrer}} Diskussionsseite</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$3|dich}} auf der Diskussionsseite von <strong>$4</strong> in „<strong>$5</strong>“.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$3|dich}} auf der Diskussionsseite von <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Deine}} Erwähnung von <strong>$3</strong> wurde nicht gesendet, da der Benutzer nicht gefunden wurde.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Deine}} Erwähnung von <strong>$3</strong> wurde nicht gesendet, da der Benutzer anonym ist.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Du}} hast versucht, mehr als {{PLURAL:$3|einen|$3}} Benutzer zu erwähnen. Alle Erwähnungen oberhalb dieser Grenze werden nicht versandt.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Eine {{GENDER:$2|durchgeführte}} Erwähnung|$3 {{GENDER:$2|durchgeführte}} Erwähnungen}} auf der Diskussionsseite <strong>$4</strong> {{PLURAL:$3|konnte|konnten}} nicht gesendet werden.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Benutzername ist nicht vorhanden:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-Adressen können nicht erwähnt werden:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Deine}} Erwähnung von <strong>$3</strong> wurde gesendet.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Eine {{GENDER:$2|durchgeführte}} Erwähnung|$3 {{GENDER:$2|durchgeführte}} Erwähnungen}} auf der Diskussionsseite <strong>$4</strong> {{PLURAL:$3|wurde|wurden}} gesendet.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Du}} hast erwähnt:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Eine {{GENDER:$2|durchgeführte}} Benachrichtigung|$3 {{GENDER:$2|durchgeführte}} Benachrichtigungen}} über Erwähnungen auf der Diskussionsseite <strong>$4</strong>: {{PLURAL:$5|Eine|$5}} nicht gesendet, {{PLURAL:$6|eine|$6}} gesendet.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Deine}} Benutzerrechte wurden {{GENDER:$1|geändert}}. Du wurdest hinzugefügt zu: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Deine}} Benutzerrechte wurden {{GENDER:$1|geändert}}. Du bist kein Mitglied mehr von: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Deine}} Benutzerrechte wurden {{GENDER:$1|geändert}}. Du wurdest hinzugefügt zu: $2. Du bist kein Mitglied mehr von: $4.",
+ "notification-header-user-rights-expiry-change": "Der Ablauf {{GENDER:$4|deiner}} Mitgliedschaft in {{PLURAL:$3|der folgenden Gruppe|den folgenden Gruppen}} wurde {{GENDER:$1|geändert}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Willkommen}} bei {{SITENAME}}, $1! Wir sind froh, dass {{GENDER:$2|du}} da bist.",
+ "notification-welcome-linktext": "Willkommen",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Du}} hast gerade {{GENDER:$2|deine}} erste Bearbeitung durchgeführt. {{GENDER:$2|Vielen}} Dank und willkommen!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Du}} hast gerade {{GENDER:$2|deine}} zehnte Bearbeitung durchgeführt. {{GENDER:$2|Vielen}} Dank! Mach weiter so!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Du}} hast gerade {{GENDER:$2|deine}} hundertste Bearbeitung durchgeführt. {{GENDER:$2|Vielen}} Dank!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Du}} hast gerade {{GENDER:$2|deine}} tausendste Bearbeitung durchgeführt. {{GENDER:$2|Vielen}} Dank! Du bist ein großartiger Autor!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Du}} hast gerade {{GENDER:$2|deine}} zehntausendste Bearbeitung durchgeführt. {{GENDER:$2|Vielen}} herzlichen Dank!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Du}} hast gerade {{GENDER:$2|deine}} hunderttausendste Bearbeitung durchgeführt. {{GENDER:$2|Vielen}} Dank für einen hervorragenden Beitrag!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Du}} hast gerade {{GENDER:$2|deine}} millionste Bearbeitung durchgeführt. {{GENDER:$2|Vielen}} Dank für einen erstaunlichen Beitrag!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Deine}} Bearbeitung",
"notification-link-text-view-edit": "Bearbeitung ansehen",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|hinterließ}} eine Nachricht auf deiner [[User talk:$2#$3|Diskussionsseite]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|hinterließ}} eine Nachricht auf deiner Diskussionsseite zum Thema „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|hinterließ}} eine Nachricht auf deiner [[User talk:$2#$3|Diskussionsseite]].",
- "notification-edit-talk-page-flyout-with-section": "„$1“ {{GENDER:$1|hinterließ}} eine Nachricht auf deiner Diskussionsseite zum Thema „[[User talk:$2#$3|$4]]“.",
- "notification-page-linked": "[[:$2]] wurde von der Seite [[:$3]] {{GENDER:$1|verlinkt}}. [[Special:WhatLinksHere/$2|Alle Links auf diese Seite ansehen]].",
- "notification-page-linked-flyout": "[[:$2]] wurde von der Seite [[:$3]] {{GENDER:$1|verlinkt}}.",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|kommentierte}} auf „[[$3|$2]]“ auf der Diskussionsseite von „$4“",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|startete}} das neue Thema „$2“ auf [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] hat dir eine Nachricht {{GENDER:$1|gesandt}}: „[[$3#$2|$2]]“",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|kommentierte}} auf „[[$3#$2|$2]]“ auf deiner Diskussionsseite",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|erwähnte}} dich auf der Seite „$5“ in „[[:$3#$2|$4]]“.",
- "notification-mention-flyout": "$1 {{GENDER:$1|erwähnte}} dich auf der Seite „$5“ in „[[:$3#$2|$4]]“.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|erwähnte}} dich auf der [[:$3|Seite „$2“]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|erwähnte}} dich auf der [[:$3|Seite „$2“]].",
- "notification-user-rights": "Deine Benutzerrechte wurden von [[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|geändert}}]]. $2. [[Special:ListGroupRights|Weitere Informationen]]",
- "notification-user-rights-flyout": "Deine Benutzerrechte wurden von $1 {{GENDER:$1|geändert}}. $2. [[Special:ListGroupRights|Weitere Informationen]]",
- "notification-user-rights-add": "Du bist jetzt Mitglied dieser {{PLURAL:$2|Benutzergruppe|Benutzergruppen}}: $1",
- "notification-user-rights-remove": "Du bist nicht länger Mitglied dieser {{PLURAL:$2|Benutzergruppe|Benutzergruppen}}: $1",
- "notification-new-user": "Willkommen bei {{SITENAME}}, $1! Wir freuen uns, dass du hier bist.",
- "notification-reverted2": "Deine {{PLURAL:$4|Bearbeitung an der Seite [[:$2]] wurde|Bearbeitungen an der Seite [[:$2]] wurden}} von [[User:$1|$1]] {{GENDER:$1|rückgängig}} gemacht. $3",
- "notification-reverted-flyout2": "Deine {{PLURAL:$4|Bearbeitung an der Seite $2 wurde|Bearbeitungen an der Seite $2 wurden}} von $1 {{GENDER:$1|rückgängig}} gemacht. $3",
+ "notification-link-article-reminder": "Seite ansehen",
+ "notification-header-reverted": "Deine {{PLURAL:$4|Bearbeitung an der Seite <strong>$3</strong> wurde|Bearbeitungen an der Seite <strong>$3</strong> wurden}} {{GENDER:$2|rückgängig}} gemacht.",
+ "notification-header-emailuser": "$1 hat dir eine E-Mail {{GENDER:$2|gesendet}}.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|hinterließ}} dir eine Nachricht auf {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|hinterließ}} eine Nachricht auf deiner Diskussionsseite.",
"notification-edit-talk-page-email-batch-body-with-section": "„$1“ {{GENDER:$1|hinterließ}} eine Nachricht auf deiner Diskussionsseite zum Thema „$2“.",
"notification-page-linked-email-subject": "Eine Seite, die du erstellt hast, wurde auf {{SITENAME}} verlinkt",
- "notification-page-linked-email-batch-body": "$2 wurde von der Seite $3 {{GENDER:$1|verlinkt}}",
- "notification-reverted-email-subject2": "Deine {{PLURAL:$3|Bearbeitung wurde|Bearbeitungen wurden}} auf {{SITENAME}} {{GENDER:$1|rückgängig}} gemacht",
- "notification-reverted-email-batch-body2": "Deine {{PLURAL:$3|Bearbeitung an der Seite $2 wurde|Bearbeitungen an der Seite $2 wurden}} von $1 {{GENDER:$1|rückgängig}} gemacht",
- "notification-mention-email-subject": "$1 {{GENDER:$1|erwähnte}} dich auf {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|erwähnte}} dich auf der Diskussionsseite von $4 in „$3“.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|erwähnte}} dich auf der Diskussionsseite „$2“.",
+ "notification-reverted-email-subject2": "Deine {{PLURAL:$3|Bearbeitung auf {{SITENAME}} wurde|Bearbeitungen auf {{SITENAME}} wurden}} {{GENDER:$1|rückgängig}} gemacht",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|erwähnte}} {{GENDER:$2|dich}} auf {{SITENAME}}",
"notification-user-rights-email-subject": "Deine Benutzerrechte auf „{{SITENAME}}“ wurden geändert.",
- "notification-user-rights-email-batch-body": "Deine Benutzerrechte wurden von $1 {{GENDER:$1|geändert}}. $2",
- "echo-email-subject-default": "Neue Benachrichtigung auf {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|Eine Sekunde|$1 Sekunden}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|Eine Minute|$1 Minuten}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|Eine Stunde|$1 Stunden}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|Ein Tag|$1 Tage}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|Ein Monat|$1 Monate}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|Ein Jahr|$1 Jahre}}",
+ "notification-timestamp-today": "Heute",
+ "notification-timestamp-yesterday": "Gestern",
+ "notification-inbox-filter-read": "Gelesen",
+ "notification-inbox-filter-unread": "Ungelesen",
+ "notification-inbox-filter-all": "Alle",
"echo-email-body-default": "Es gibt eine neue Benachrichtigung auf {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Du hast eine neue Benachrichtigung",
- "echo-email-footer-default": "$2\n\nUm zu steuern, welche E-Mails wir dir senden, nutze deine Einstellungen:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-email-footer-default-html": "Um zu steuern, welche E-Mails wir dir senden, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">nutze deine Einstellungen</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nUm zu steuern, welche E-Mails wir dir senden, nutze deine Einstellungen:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Um zu steuern, welche E-Mails wir {{GENDER:$1|dir}} senden, überprüfe {{GENDER:$1|deine}} Einstellungen:",
+ "echo-email-html-footer-preference-link-text": "überprüfe {{GENDER:$1|deine}} Einstellungen",
+ "echo-email-html-footer-with-link": "Um zu steuern, welche E-Mails wir {{GENDER:$2|dir}} senden, $1.",
"echo-notification-alert": "{{PLURAL:$1|Eine Meldung|$1 Meldungen|100=99+ Meldungen}}",
- "echo-notification-message": "{{PLURAL:$1|Eine Nachricht|$1 Nachrichten|100=99+ Nachrichten}}",
+ "echo-notification-notice": "{{PLURAL:$1|Mitteilung ($1)|Mitteilungen ($1)|100=Mehr als 99 Mitteilungen}}",
"echo-notification-alert-text-only": "Meldungen",
- "echo-notification-message-text-only": "Nachrichten",
+ "echo-notification-notice-text-only": "Mitteilungen",
"echo-overlay-link": "Alle Benachrichtigungen",
"echo-overlay-title": "<b>Benachrichtigungen</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Benachrichtigungen}}</b> ($1 von $2 ungelesenen werden angezeigt)",
"echo-mark-all-as-read": "Alle als gelesen markieren",
+ "echo-mark-all-as-read-confirmation": "{{PLURAL:$1|Eine Benachrichtigung|$1 Benachrichtigungen}} als gelesen markiert",
+ "echo-mark-wiki-as-read": "Alle als gelesen markieren in dem ausgewählten Wiki: $1",
"echo-date-today": "Heute",
"echo-date-yesterday": "Gestern",
"echo-load-more-error": "Beim Abrufen weiterer Ergebnisse ist ein Fehler aufgetreten.",
- "notification-edit-talk-page-bundle": "$1 und {{PLURAL:$4|ein weiterer Benutzer|$3 weitere Benutzer}} {{GENDER:$1|hinterließen}} eine Nachricht auf deiner [[User talk:$2|Diskussionsseite]].",
- "notification-page-linked-bundle": "$2 wurde von $3 und {{PLURAL:$5|einer weiteren Seite|$4 weiteren Seiten}} {{GENDER:$1|verlinkt}}. [[Special:WhatLinksHere/$2|Alle Links auf diese Seite ansehen]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 und {{PLURAL:$3|ein weiterer Benutzer|$2 weitere Benutzer}} {{GENDER:$1|hinterließen}} eine Nachricht auf deiner Diskussionsseite",
- "notification-page-linked-email-batch-bundle-body": "$2 wurde von $3 und {{PLURAL:$5|einer weiteren Seite|$4 weiteren Seiten}} {{GENDER:$1|verlinkt}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Eine neue Nachricht|$1 neue Nachrichten|100=Mehr als 99 neue Nachrichten}} auf <strong>{{GENDER:$3|deiner}} Diskussionsseite</strong>.",
"echo-email-batch-subject-daily": "Du hast {{PLURAL:$2|eine neue Benachrichtigung|neue Benachrichtigungen}} auf {{SITENAME}}",
"echo-email-batch-subject-weekly": "Du hast diese Woche {{PLURAL:$2|eine neue Benachrichtigung|neue Benachrichtigungen}} auf {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Hallo $1,\nHier ist für dich eine Zusammenfassung der Aktivitäten auf {{SITENAME}} von heute.",
"echo-email-batch-body-intro-weekly": "Hallo $1,\nHier ist für dich eine Zusammenfassung der Aktivitäten auf {{SITENAME}} von dieser Woche.",
"echo-email-batch-link-text-view-all-notifications": "Alle Benachrichtigungen ansehen",
- "echo-rev-deleted-text-view": "Diese Seitenversion wurde unterdrückt",
- "apihelp-echomarkread-description": "Benachrichtigungen für den aktuellen Benutzer als gelesen markieren.",
- "apihelp-echomarkread-param-list": "Eine Liste von Benachrichtigungskennungen, um sie als gelesen zu markieren.",
- "apihelp-echomarkread-param-all": "Falls festgelegt, markiert alle Benutzerbenachrichtigungen als gelesen.",
- "apihelp-echomarkread-param-sections": "Eine Liste der Abschnitte, die als gelesen markiert werden sollen.",
- "apihelp-echomarkread-example-1": "Benachrichtigung 8 als gelesen markieren",
- "apihelp-echomarkread-example-2": "Alle Benachrichtigungen als gelesen markieren",
- "apihelp-echomarkseen-description": "Benachrichtigungen für den derzeitigen Benutzer als gesehen markieren.",
- "apihelp-echomarkseen-example-1": "Benachrichtigungen aller Typen als gesehen markieren",
- "apihelp-echomarkseen-param-type": "Benachrichtigungstypen, die als gesehen markiert werden sollen: „alert“, „message“ oder „all“.",
- "apihelp-query+notifications-description": "Benachrichtigungen abrufen, die auf den aktuellen Benutzer warten.",
- "apihelp-query+notifications-param-prop": "Einzelheiten der Anfrage.",
- "apihelp-query+notifications-param-sections": "Die abzufragenden Benachrichtigungsabschnitte (z.&nbsp;B. eine Kombination aus „alert“ und „message“).",
- "apihelp-query+notifications-param-groupbysection": "Ob das Ergebnis nach Abschnitt gruppiert werden soll. Jeder Abschnitt wird separat abgerufen, wenn es eingestellt wird.",
- "apihelp-query+notifications-param-format": "Falls angegeben, werden die zurückgegebenen Benachrichtigungen auf diese Weise formatiert.",
- "apihelp-query+notifications-param-limit": "Die maximale Anzahl zurückzugebender Benachrichtigungen.",
- "apihelp-query+notifications-param-index": "Falls angegeben, wird eine Liste von Benachrichtigungskennungen in der Reihenfolge zurückgegeben.",
- "apihelp-query+notifications-param-alertcontinue": "Falls mehr Alarmergebnisse verfügbar sind, dies zum Fortfahren verwenden.",
- "apihelp-query+notifications-param-alertunreadfirst": "Ob ungelesene Nachrichten zuerst angezeigt werden sollen.",
- "apihelp-query+notifications-param-messagecontinue": "Falls mehrere Nachrichtenergebnisse verfügbar sind, dies zum Fortfahren verwenden.",
- "apihelp-query+notifications-param-messageunreadfirst": "Ob ungelesene Meldungen zuerst angezeigt werden sollen.",
- "apihelp-query+notifications-example-1": "Benachrichtigungen auflisten",
- "apihelp-query+notifications-example-2": "Benachrichtigungen auflisten, gruppiert nach Abschnitt, mit Zählern"
+ "notification-header-foreign-alert": "Weitere Meldungen von {{PLURAL:$5|einem anderen Wiki|$5 anderen Wikis}}",
+ "notification-header-foreign-notice": "Weitere Mitteilungen von {{PLURAL:$5|einem anderen Wiki|$5 anderen Wikis}}",
+ "notification-header-foreign-all": "Weitere Benachrichtigungen von {{PLURAL:$5|einem weiteren Wiki|$5 weiteren Wikis}}",
+ "echo-foreign-wiki-lang": "$1 – $2"
}
diff --git a/Echo/i18n/din.json b/Echo/i18n/din.json
new file mode 100644
index 00000000..9ffe5315
--- /dev/null
+++ b/Echo/i18n/din.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dinkawiki",
+ "Amire80"
+ ]
+ },
+ "notifications": "Notifications",
+ "tooltip-pt-notifications-alert": "Nyïïn {{GENDER:|ku}}",
+ "echo-overlay-link": "Käcïlɛ̈k ëbɛ̈n"
+}
diff --git a/Echo/i18n/diq.json b/Echo/i18n/diq.json
index 3ad42014..d379bf0b 100644
--- a/Echo/i18n/diq.json
+++ b/Echo/i18n/diq.json
@@ -6,10 +6,13 @@
"Marmase",
"Mirzali",
"Gorizon",
- "Sayginer"
+ "Sayginer",
+ "Kumkumuk",
+ "Velg",
+ "Gırd"
]
},
- "echo-desc": "Sistemê tebliğati",
+ "echo-desc": "Karbera heqdê weqan u mesavan malumat dayen sisten",
"prefs-echo": "Mengeney",
"prefs-emailsettings": "Opsiyona e-posta",
"prefs-displaynotifications": "Weçinayışa mocnayışi",
@@ -24,42 +27,86 @@
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Metno pan",
"echo-learn-more": "Zewbi",
+ "echo-log": "Qeydê umumi",
"echo-new-messages": "Şımaré mesaco newe esto",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mesacê|Mesacên}} pela werênayışi",
"echo-category-title-article-linked": "Para {{PLURAL:$1|link|linki}}",
"echo-category-title-reverted": "Timara {{PLURAL:$1|terknayış|terknayışi}}",
"echo-category-title-mention": "{{PLURAL:$1|Bahs kerden|Bahs kerdeni}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Bahs kerden|Bahs kerdeni}} xeta bı",
"echo-category-title-other": "{{PLURAL:$1|Zewbi}}",
"echo-category-title-system": "{{PLURAL:$1|sistem}}",
- "echo-no-agent": "[Kesek]",
- "echo-no-title": "[Pele Çıniya]",
"notifications": "Mengene",
- "tooltip-pt-notifications": "Beyanatê to",
+ "tooltip-pt-notifications-alert": "Hayê {{GENDER:|şıma}}",
+ "tooltip-pt-notifications-notice": "Pêhesnayışé {{GENDER:|şıma}}",
+ "echo-displaynotificationsconfiguration": "Eyaranê pêhesnayışa bıasne",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Hesıbyaye deyne aktiv",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Karberê mewcudi",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Karberê neweyi",
"echo-specialpage": "Mengeney",
- "echo-none": "Beyanatê to çıniyê.",
- "echo-more-info": "Zêde (vêşi) melumat",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|mengene|mengeney}}",
+ "echo-specialpage-pagefilters-title": "Aktiviteya peyêne",
+ "echo-none": "Pêhesnayışê şıma çıniyê.",
+ "echo-more-info": "Tayêna melumat",
"echo-feedback": "Peydrışten",
+ "echo-notification-markasread": "Wanaye nışan ke",
+ "echo-notification-markasunread": "Nêwanaye nışan ke",
+ "echo-notification-markasread-tooltip": "Wanaye nışan ke",
+ "echo-notification-more-options-tooltip": "Dehana zaf weçenegi",
+ "notification-link-text-expand-all": "Hera ke",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 iqazi|$1 iqazan}} bıvin",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|$1 beyanati|$1 beyanatan}} bıvin",
+ "notification-link-text-expand-all-count": "$1 {{PLURAL:$1|mengene|mengeneyan}} bıvin",
+ "notification-link-text-collapse-all": "Teng kı",
"notification-link-text-view-message": "Qaytê mesaci ke",
"notification-link-text-view-mention": "Qayt ke, cao ke qalê to biyo",
- "notification-link-text-view-changes": "Qaytê vırnayışan ke",
- "notification-link-text-view-page": "Qaytê pele ke",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Behsi bıasne|Bahsan bıasne }}",
+ "notification-link-text-view-changes": "Vurriyayışa {{GENDER:$1|bıvin}}",
+ "notification-link-text-view-page": "Bewne perre",
+ "notification-compact-header-page-linked": "<strong>$1</strong> ra gıre biyo.",
+ "notification-link-text-what-links-here": "Ena perre rê pêro linki",
+ "notification-header-mention-other": "$1 zerreyê <strong>$4</strong> \"<strong>$5</strong>\" de {{GENDER:$3|şıma sero}} {{GENDER:$2|qal kerd}}.",
+ "notification-header-mention-other-nosection": "$1, per da <strong>$4</strong> dı {{GENDER:$3|tora}} {{GENDER:$2|bahs kerd}}.",
+ "notification-header-user-rights-remove-only": "Heqa karberiya {{GENDER:$4|şıma}} {{GENDER:$1|vurriye}}. Şıma ezayê ena grube niyê: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Xeyr ameyê}} be {{SITENAME}}, $1! Tiya de {{GENDER:$2|biyena şıma}} ra zerreweşime.",
+ "notification-welcome-linktext": "Xeyr amey",
+ "notification-header-thank-you-1-edit": "Şıma {{GENDER:$2|vurnayışa}} xoya sıfteyëna {{GENDER:$2|kerd a. }}; teşekur kem u şıma xeyr ameyê!",
+ "notification-header-thank-you-10-edit": "Şıma {{GENDER:$2|vurnayışa}} 10 yi {{GENDER:$2|kerd a. }}; teşekur kem. Dewam kerê!",
+ "notification-header-thank-you-100-edit": "Şıma {{GENDER:$2|vurnayışa}} 100 yi {{GENDER:$2|kerd a. }}; teşekur kem.",
+ "notification-header-thank-you-1000-edit": "Şıma {{GENDER:$2|vurnayışa}} 1000 yi {{GENDER:$2|kerd a }}; şoma gırd iştirak kerd teşekur kem.",
+ "notification-header-thank-you-10000-edit": "Şıma {{GENDER:$2|vurnayışa}} 10, 000 yi {{GENDER:$2|kerd a. }}; teşekur kem.",
+ "notification-header-thank-you-100000-edit": "Şıma {{GENDER:$2|vurnayışa}} 100,000 i {{GENDER:$2|kerd a. }}; teşekur kem.",
+ "notification-header-thank-you-1000000-edit": "Şıma {{GENDER:$2|vurnayışa}} milyoni {{GENDER:$2|kerd a }}; teşekur kem. Şıma ra ata kes çıni yo",
+ "notification-link-thank-you-edit": "Vurnayışê {{GENDER:$1|şıma}}",
"notification-link-text-view-edit": "Qaytê vırnayışi ke",
- "notification-edit-talk-page2": "[[User:$1|$1]], perda [[User talk:$2#$3| mesacande]] to de zew mesaco newe {{GENDER:$1|vırada}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]], Pera masecan de \"[[User talk:$2#$3|$4]]\" de mewzu {{GENDER:$1|vırade}}.",
- "notification-edit-talk-page-flyout2": "$1, [[User talk:$2#$3|pela werênayışê şıma]] de yew mesac {{GENDER:$1|caverda}}.",
- "notification-edit-talk-page-flyout-with-section": "$1, pela werênayışê şıma de sernameyê \"[[User talk:$2#$3|$4]]\" rê yew mesac {{GENDER:$1|caverda}}.",
- "notification-reverted2": "[[User:$1|$1]] {{PLURAL:$4|vurnayışi [[:$2]] |vurnayışê [[:$2]] }} çımraviyarnayışanê $3 {{GENDER:$1|peyser}} gırewti.",
- "notification-reverted-flyout2": "$1 {{PLURAL:$4|vırnayışa $2 |vırnayışane $2 }} rewizyona $3 {{GENDER:$1|peyser}} grot",
+ "notification-header-reverted": "{{PLURAL:$4|Vurnayışê <strong>$3</strong> |vurnayışê <strong>$3</strong> }} şıma karber $1 {{GENDER:$2|peyser gırewt}}",
+ "notification-header-emailuser": "$1 şıma rê yew e-poste {{GENDER:$2|rışt}}.",
+ "notification-edit-talk-page-email-subject2": "$1 to rê {{SITENAME}} de yew mesac {{GENDER:$1|caverda}}",
"notification-edit-talk-page-email-batch-body-with-section": "$1, pela werênayışê şıma de be sernameyê \"$2\" ra yew mesac {{GENDER:$1|caverda}}.",
- "echo-email-subject-default": "{{SITENAME}} de beyanato newe",
+ "notification-page-linked-email-subject": "Perer rê {{SITENAME}} ra gıre deya yo",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1sa}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1r}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1me}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1ser}}",
+ "notification-timestamp-today": "Noroc",
+ "notification-timestamp-yesterday": "Vızér",
+ "notification-inbox-filter-read": "Bıwanê",
+ "notification-inbox-filter-unread": "Nêwaniya ya",
+ "notification-inbox-filter-all": "Pêro",
"echo-email-body-default": "{{SITENAME}} de beyanatê do newe esto:\n\n$1",
- "echo-email-batch-body-default": "Yew beyanatê to esto.",
+ "echo-email-html-footer-preference-link-text": "tercihanê xo kontrol ke",
+ "echo-notification-alert": "{{PLURAL:$1|($1) iqaz|($1) iqaza|100= (99+) iqazan}}",
+ "echo-notification-alert-text-only": "İqazi",
+ "echo-notification-notice-text-only": "Mengeney",
"echo-overlay-link": "Pêro beyanati",
- "echo-overlay-title": "<b>Tebliği</b>",
- "echo-mark-all-as-read": "Pêrine wende nışan ke",
+ "echo-overlay-title": "<b>Mengeney </b>",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Mengen|$1 Mengeney }}</b> ($2 nêwaneya ra $1 teney asenê)",
+ "echo-mark-all-as-read": "Pêron waniyaye nışan bık",
+ "echo-mark-wiki-as-read": "Wiki dı pêron wanaye nışan bık:$1",
"echo-date-today": "Ewro",
"echo-date-yesterday": "Vızér",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 û $2 {{PLURAL:$3|karberi|karberan}} pela werênayışê şıma de yew mesac {{GENDER:$1|caverda}}.",
"echo-email-batch-link-text-view-all-notifications": "Qaytê beyanatan pêrine ke",
- "echo-rev-deleted-text-view": "Vırnayışê na pele dard we."
+ "notification-header-foreign-notice": "{{PLURAL:$5|juna wiki|$5 tayna wiki}} ra zeder neticey"
}
diff --git a/Echo/i18n/dsb.json b/Echo/i18n/dsb.json
index 03d4b0a7..02032634 100644
--- a/Echo/i18n/dsb.json
+++ b/Echo/i18n/dsb.json
@@ -21,7 +21,6 @@
"echo-pref-email-frequency-weekly": "Tyźeński pśeglěd powěźeńkow",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Lutny tekst",
- "echo-pref-notify-show-link": "Powěźeńki w symbolowej rědce pokazaś",
"echo-pref-new-message-indicator": "Powěsćowy indikator diskusijnego boka w symbolowej rědce pokazaś",
"echo-learn-more": "Dalšne informacije",
"echo-new-messages": "Maš nowe powěsći",
@@ -35,13 +34,8 @@
"echo-pref-tooltip-article-linked": "Informěruj mě, gaž něchten wótkazujo na bok, kótaryž som z nastawka napórał.",
"echo-pref-tooltip-reverted": "Informěruj mě, gaž něchten z pomocu anulěrowanja abo rěda anulěrujo změnu, kótaruž som cynił.",
"echo-pref-tooltip-mention": "Informěruj mě, gaž něchten wótkazujo z někakego diskusijnego boka k mójomu wužywarskemu bokoju.",
- "echo-no-agent": "[Nichten]",
- "echo-no-title": "[Žeden bok]",
"echo-error-no-formatter": "Za powěźeńku njejo se formatěrowanje definěrowało.",
- "echo-error-preference": "Zmólka: Wužywarske nastajenje njedajo se stajiś.",
- "echo-error-token": "Zmólka: Wužywarski token njedajo se wótwołaś.",
"notifications": "Powěźeńki",
- "tooltip-pt-notifications": "Twóje powěźeńki",
"echo-specialpage": "Powěźeńki",
"echo-anon": "Aby powěźeńki dostał, [$1 napóraj konto] abo [$2 pśizjaw se].",
"echo-none": "Njamaš powěźeńki",
@@ -52,44 +46,15 @@
"notification-link-text-view-changes": "Změny pokazaś",
"notification-link-text-view-page": "Bok se woglědaś",
"notification-link-text-view-edit": "Změnu pokazaś",
- "notification-edit-talk-page2": "[[User:$1|$1]] jo powěsć na twójom [[User talk:$2#$3|diskusijnem boku]] {{GENDER:$1|zawóstajił|zawóstajiła}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] jo powěsć na twójom diskusijnem boku w \"[[User talk:$2#$3|$4]]\" {{GENDER:$1|zawóstajił|zawóstajiła}}.",
- "notification-edit-talk-page-flyout2": "$1 jo powěsć na twójom [[User talk:$2#$3|diskusijnem boku]] {{GENDER:$1|zawóstajił|zawóstajiła}}.",
- "notification-edit-talk-page-flyout-with-section": "$1 jo powěsć na twójom diskusijnem boku w \"[[User talk:$2#$3|$4]]\" {{GENDER:$1|zawóstajił|zawóstajiła}}.",
- "notification-page-linked": "[[:$2]] jo se wót [[:$3]] {{GENDER:$1|wótkazał|wótkazała}}. [[Special:WhatLinksHere/$2|Wšykne wótkaze k toś tomu bokoju pokazaś]].",
- "notification-page-linked-flyout": "[[:$2]] jo se wót [[:$3]] {{GENDER:$1|wótkazał|wótkazała}}.",
- "notification-add-comment2": "[[User:$1|$1]] jo na \"[[$3|$2]]\" na diskusijnem boku \"$4\" {{GENDER:$1|komentěrował|komentěrowała}}.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] jo nowu temu \"$2\" na [[$3]] {{GENDER:$1|startował|startowała}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] jo śi powěsć {{GENDER:$1|pósłał|pósłała}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] jo na \"[[$3#$2|$2]]\" na twójom diskusijnem boku {{GENDER:$1|komentěrował|komentěrowała}}.",
- "notification-mention": "[[User:$1|$1]] jo śi na diskusijnem boku $5 w \"[[:$3#$2|$4]]\" {{GENDER:$1|naspomnjeł|naspomnjeła}}.",
- "notification-mention-flyout": "$1 jo śi na diskusijnem boku $5 w \"[[:$3#$2|$4]]\" {{GENDER:$1|naspomnjeł|naspomnjeła}}.",
- "notification-mention-nosection": "[[User:$1|$1]] jo śi na [[:$3|diskusijnem boku $2]] {{GENDER:$1|naspomnjeł|naspomnjeła}}.",
- "notification-mention-nosection-flyout": "$1 jo śi na [[:$3|diskusijnem boku $2]] {{GENDER:$1|naspomnjeł|naspomnjeła}}.",
- "notification-user-rights": "Twóje wužywarske pšawa [[Special:Log/rights/$1|su se wót [[User:$1|$1]] {{GENDER:$1|změnili}}]] . $2. [[Special:ListGroupRights|Dalšne informacije]]",
- "notification-user-rights-flyout": "Twóje wužywarske pšawa su se wót $1 {{GENDER:$1|změnili}}. $2. [[Special:ListGroupRights|Dalšne informacije]]",
- "notification-user-rights-add": "Sy něnto cłonk {{PLURAL:$2|toś teje kupki|toś teju kupkowu|toś tych kupkow}}: $1",
- "notification-user-rights-remove": "Njejsy wěcej cłonk {{PLURAL:$2|toś teje kupki|toś teju kupkowu|toś tych kupkow}}: $1",
- "notification-new-user": "Witaj do {{GRAMMAR:genitiw|{{SITENAME}}}}, $1! Wjaselimy se, až sy how.",
- "notification-reverted2": "[[User:$1|$1]] jo {{PLURAL:$4|změnu na [[:$2]]|změnje na [[:$2]]|změny na [[:$2]]}} {{GENDER:$1|anulěrował|anulěrowała}}. $3",
- "notification-reverted-flyout2": "$1 jo {{PLURAL:$4|změnu na $2|změnje na $2|změny na $2}} {{GENDER:$1|anulěrował|anulěrowała}}. $3",
+ "notification-header-reverted": "$1 jo {{PLURAL:$4|změnu na $3|změnje na $3|změny na $3}} {{GENDER:$2|anulěrował|anulěrowała}}.",
"notification-edit-talk-page-email-subject2": "$1 jo śi powěsć na {{GRAMMAR:lokatiw|{{SITENAME}}}} {{GENDER:$1|zawóstajił|zawóstajiła}}",
- "notification-edit-talk-page-email-batch-body2": "$1 jo powěsć na twójom diskusijnem boku {{GENDER:$1|zawóstajił|zawóstajiła}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 jo powěsć wó \"$2\" na twójom diskusijnem boku {{GENDER:$1|zawóstajił|zawóstajiła}}.",
"notification-page-linked-email-subject": "Twój bok jo se na {{GRAMMAR:lokatiw|{{SITENAME}}}} wótkazał.",
- "notification-page-linked-email-batch-body": "$2 jo se z $3 {{GENDER:$1|wótkazał}}.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Twója změna jo|Twójej změnje stej|Twóje změny su}} se na {{GRAMMAR:lokatiw|{{SITENAME}}}}{{GENDER:$1|{{PLURAL:$3|anulěrowała|anulěrowałej|anulěrowali}}}}",
- "notification-reverted-email-batch-body2": "$1 jo {{PLURAL:$3|twóju změnu na $2|twójej změnje na $2|twóje změny na $2}} {{GENDER:$1|anulěrował|anulěrowała}}.",
"notification-mention-email-subject": "$1 jo śi na {{GRAMMAR:lokatiw|{{SITENAME}}}} {{GENDER:$1|naspomnjeł|naspomnjeła}}",
- "notification-mention-email-batch-body": "$1 jo śi na diskusijnem boku $4 w \"$3\" {{GENDER:$1|naspomnjeł|naspomnjeła}}.",
- "notification-mention-nosection-email-batch-body": "$1 jo śi na diskusijnem boku $2 {{GENDER:$1|naspomnjeł|naspomnjeła}}.",
"notification-user-rights-email-subject": "Twóje wužywarske pšawa su se na {{GRAMMAR:lokatiw|{{SITENAME}}}} změnili",
- "notification-user-rights-email-batch-body": "Twóje wužywarske pšawa su se wót $1 {{GENDER:$1|změnili}}. $2",
- "echo-email-subject-default": "Nowa powěźeńka na {{GRAMMAR:lokatiw|{{SITENAME}}}}",
"echo-email-body-default": "Maš nowu powěźeńku na {{GRAMMAR:lokatiw|{{SITENAME}}}}:\n\n$1",
- "echo-email-batch-body-default": "Maš nowu powěźeńku.",
"echo-email-footer-default": "$2\n\nAby kontrěrolował, kótare e-maile śi sćelomy, pśeglědaj swóje nastajenja:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Aby kontrolěrował, kótare e-maile śi sćelomy, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">pśeglědaj swóje nastajenja</a>.<br />\n$1",
"echo-overlay-link": "Wšykne powěźeńki",
"echo-overlay-title": "<b>Powěźeńki</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Poěźeńka|Powěźeńce|Powěźeńki}}</b> ($1 z $2 {{PLURAL:$2|njepśecytaneje|njepśecytaneju|njepśecytanych}} se {{PLURAL:$1|pokazujo|pokazujotej|pokazuju|pokazujo}})",
@@ -97,14 +62,9 @@
"echo-date-today": "Źinsa",
"echo-date-yesterday": "Cora",
"echo-load-more-error": "Pśi wobstarowanju dalšnych wuslědkow jo zmólka nastała.",
- "notification-edit-talk-page-bundle": "$1 a {{PLURAL:$4|dalšny wužywaŕ jo|$3 dalšnej wužywarja stej|$3 dalšne wužywarje su|$3 dalšnych wužywarjow jo}} powěsć na twójom [[User talk:$2|diskusijnem boku]] {{PLURAL:$4|zawóstajił|zawóstajiłej|zawóstajili|zawóstajiło}}.",
- "notification-page-linked-bundle": "$2 jo se z $3 a {{PLURAL:$5|jadnogo dalšnego boka|$4 dalšneju bokowu|$4 dalšnych bokow}} {{GENDER:$1|wotkazał}}. [[Special:WhatLinksHere/$2|Wšykne wótkaze k toś tomu bokoju pokazaś]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 a {{PLURAL:$3|dalšny wužywaŕ stej|$2 dalšnej wužywarja su|$2 dalšne wužywarje su|$2 dalšnych wužywarjow su}} powěsć na twójom diskusijnem boku {{GENDER:$1|zawóstajiłej|zawóstajili}}.",
- "notification-page-linked-email-batch-bundle-body": "$2 jo se wót $3 a {{PLURAL:$5|jadnogo dalšnego boka|$4 dalšneju bokowu|$4 dalšnych bokow}} {{GENDER:$1|wótkazał}}.",
"echo-email-batch-subject-daily": "Maš {{PLURAL:$2|nowu powěźeńku|nowej powěźeńce|nowe powěźeńki}} na {{GRAMMAR:lokatiw|{{SITENAME}}}}",
"echo-email-batch-subject-weekly": "Maš {{PLURAL:$2|nowu powěźeńku|nowej powěźeńce|nowe powěźeńki}} na {{GRAMMAR:lokatiw|{{SITENAME}}}} toś ten tyźeń",
"echo-email-batch-body-intro-daily": "Witaj $1,\n\nhow jo zespominanje źinsajšnych aktiwitow na {{GRAMMAR:lokatiw|{{SITENAME}}}} za tebje.",
"echo-email-batch-body-intro-weekly": "Witja $1,\n\nhow jo zespominanje aktiwitow z toś togo tyźenja na {{GRAMMAR:lokatiw|{{SITENAME}}}} za tebje.",
- "echo-email-batch-link-text-view-all-notifications": "Wšykne powěźeńki pokazaś",
- "echo-rev-deleted-text-view": "Toś ta bokowa wersija jo se pódtłocyła."
+ "echo-email-batch-link-text-view-all-notifications": "Wšykne powěźeńki pokazaś"
}
diff --git a/Echo/i18n/dty.json b/Echo/i18n/dty.json
index da9b5b6a..26cc9e79 100644
--- a/Echo/i18n/dty.json
+++ b/Echo/i18n/dty.json
@@ -3,9 +3,14 @@
"authors": [
"रमेश सिंह बोहरा",
"जनक राज भट्ट",
- "राम प्रसाद जोशी"
+ "राम प्रसाद जोशी",
+ "Nirajan pant"
]
},
"tooltip-pt-notifications-alert": "{{GENDER:|तमरा}} अलर्टहरू",
- "tooltip-pt-notifications-message": "{{GENDER:|तमरा}} रैबारहरू"
+ "notification-dynamic-actions-unwatch": "\"$1\"मी नौला कृयाकलाप तक्द {{GENDER:$3|बन्द}} अरऽ",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|तम}} आब \"$1\" पन्ना नाइहेद्दार्‍याऽ",
+ "notification-dynamic-actions-watch": "\"$1\"मी नौलो कृयाकलाप {{GENDER:$3|पछ्याऽ}}",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|तम}} अइल \"$1\" पन्ना हेद्दाछऽ",
+ "notification-dynamic-actions-watch-confirmation-description": "[$2 यो पन्ना] तक्द {{GENDER:$3|तम}} कज्याइँलै बन्द अरिसकन्छऽ"
}
diff --git a/Echo/i18n/el.json b/Echo/i18n/el.json
index 00fdbde3..5a5cb84f 100644
--- a/Echo/i18n/el.json
+++ b/Echo/i18n/el.json
@@ -8,97 +8,145 @@
"Protnet",
"Xaris333",
"ZaDiak",
- "Auslaender"
+ "Auslaender",
+ "Giorgos456",
+ "Tsoukali",
+ "Ανώνυμος Βικιπαιδιστής"
]
},
"echo-desc": "Σύστημα για την ενημέρωση των χρηστών σχετικά με τα γεγονότα και τα μηνύματα",
- "prefs-echo": "Ειδοποιήσεις",
+ "prefs-echo": "Ενημερώσεις",
"prefs-emailsettings": "Επιλογές ηλεκτρονικού ταχυδρομείου",
"prefs-displaynotifications": "Επιλογές εμφάνισης",
"prefs-echosubscriptions": "Να ειδοποιούμαι σχετικά με αυτά τα γεγονότα",
+ "prefs-echocrosswiki": "Cross-wiki ενημερώσεις",
"prefs-newmessageindicator": "Δείκτης νέων μηνυμάτων",
"echo-pref-send-me": "Στείλτε μου:",
"echo-pref-send-to": "Αποστολή σε:",
"echo-pref-email-format": "Μορφή ηλεκτρονικού ταχυδρομείου:",
"echo-pref-web": "Ιστοσελίδα",
"echo-pref-email": "Ηλεκτρονικό ταχυδρομείο",
- "echo-pref-email-frequency-never": "Μην μου στέλνετε ειδοποιήσεις μέσω ηλεκτρονικού ταχυδρομείου",
- "echo-pref-email-frequency-immediately": "Μεμονωμένες κοινοποιήσεις, καθώς έρχονται",
- "echo-pref-email-frequency-daily": "Ημερήσια σύνοψη ειδοποιήσεων",
- "echo-pref-email-frequency-weekly": "Εβδομαδιαία σύνοψη ειδοποιήσεων",
+ "echo-pref-email-frequency-never": "Μην μου στέλνετε ενημερώσεις μέσω ηλεκτρονικού ταχυδρομείου",
+ "echo-pref-email-frequency-immediately": "Μεμονωμένες ενημερώσεις, καθώς έρχονται",
+ "echo-pref-email-frequency-daily": "Ημερήσια σύνοψη ενημερώσεων",
+ "echo-pref-email-frequency-weekly": "Εβδομαδιαία σύνοψη ενημερώσεων",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Απλό κείμενο",
+ "echo-pref-cross-wiki-notifications": "Εμφάνιση ενημερώσεων από άλλα wiki",
"echo-pref-new-message-indicator": "Να εμφανίζεται, στη γραμμή εργαλείων, ο δείκτης μηνυμάτων της σελίδας συζήτησης",
+ "echo-pref-beta-feature-cross-wiki-message": "Ενισχυμένες ενημερώσεις",
+ "echo-pref-beta-feature-cross-wiki-description": "Προβάλετε και οργανώσετε τις ενημερώσεις πιο εύκολα. Περιλαμβάνει cross-wiki ενημερώσεις, οι οποίες σας επιτρέπουν να δείτε μηνύματα από άλλα wiki. (Για να λάβετε cross-wiki ενημερώσεις σχετικά με ένα συγκεκριμένο wiki, θα πρέπει να ενεργοποιήσετε το εργαλείο beta στο συγκεκριμένο wiki.)",
"echo-learn-more": "Μάθετε περισσότερα",
+ "echo-log": "Δημόσια καταγραφή",
"echo-new-messages": "Έχετε νέα μηνύματα",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Μήνυμα|Μηνύματα}} στη σελίδα συζήτησης",
"echo-category-title-article-linked": "{{PLURAL:$1|Σύνδεσμος|Σύνδεσμοι}} σελίδας",
"echo-category-title-reverted": "{{PLURAL:$1|Επαναφορά|Επαναφορές}} επεξεργασίας",
"echo-category-title-mention": "{{PLURAL:$1|Αναφορά|Αναφορές}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Αποτυχημένη αναφορά|Αποτυχημένες αναφορές}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Επιτυχημένη αναφορά|Επιτυχημένες αναφορές}}",
"echo-category-title-other": "{{PLURAL:$1|Άλλα}}",
"echo-category-title-system": "{{PLURAL:$1|Σύστημα}}",
- "echo-pref-tooltip-edit-user-talk": "Να ειδοποιούμαι όταν κάποιος δημοσιεύσει ένα μήνυμα ή απαντήσεις στη σελίδα συζήτησής μου.",
- "echo-pref-tooltip-article-linked": "Να ειδοποιούμαι όταν κάποιος συνδέει σε σελίδα που δημιούργησα από μια σελίδα λήμματος.",
- "echo-pref-tooltip-reverted": "Να ειδοποιούμαι όταν κάποιος αναστρέφει μια επεξεργασία που έκανα, χρησιμοποιώντας το εργαλείο αναίρεσης ή επαναφοράς.",
- "echo-pref-tooltip-mention": "Να ειδοποιούμαι όταν κάποιος προσθέτει σύνδεσμο προς τη σελίδα χρήστη μου.",
- "echo-no-agent": "[Κανένας]",
- "echo-no-title": "[Καμία σελίδα]",
- "echo-error-no-formatter": "Δεν έχει οριστεί μορφοποίηση για την ειδοποίηση",
- "notifications": "Ειδοποιήσεις",
- "tooltip-pt-notifications-alert": "{{GENDER:|Δικές σας}} ειδοποιήσεις",
- "tooltip-pt-notifications-message": "{{GENDER:|Τα δικά σας}} μηνύματα",
- "echo-specialpage": "Ειδοποιήσεις",
- "echo-anon": "Για να λαμβάνετε ειδοποιήσεις, [$1 δημιουργήστε ένα λογαριασμό] ή [$2 συνδεθείτε].",
- "echo-none": "Δεν έχετε ειδοποιήσεις.",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Αλλαγή δικαιωμάτων χρήστη|Αλλαγές δικαιωμάτων χρήστη}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Email από άλλο χρήστη|Email από άλλους χρήστες}}",
+ "echo-pref-tooltip-edit-user-talk": "Να ενημερώνομαι όταν κάποιος δημοσιεύσει ένα μήνυμα ή απαντήσεις στη σελίδα συζήτησής μου.",
+ "echo-pref-tooltip-article-linked": "Να ενημερώνομαι όταν κάποιος συνδέει τη σελίδα που δημιούργησα σε μια σελίδα λήμματος.",
+ "echo-pref-tooltip-reverted": "Να ενημερώνομαι όταν κάποιος αναστρέφει μια επεξεργασία που έκανα, χρησιμοποιώντας το εργαλείο αναίρεσης ή επαναφοράς.",
+ "echo-pref-tooltip-mention": "Να ενημερώνομαι όταν κάποιος προσθέτει σύνδεσμο προς τη σελίδα χρήστη μου.",
+ "echo-pref-tooltip-user-rights": "Να ενημερώνομαι με όταν κάποιος αλλάζει τα δικαιώματα χρήστη μου.",
+ "echo-pref-tooltip-emailuser": "Να ενημερώνομαι όταν κάποιος μου στέλνει email.",
+ "echo-error-no-formatter": "Δεν έχει οριστεί μορφοποίηση για την ενημέρωση.",
+ "notifications": "Ενημερώσεις",
+ "tooltip-pt-notifications-alert": "Οι ειδοποιήσεις {{GENDER:|σας}}",
+ "tooltip-pt-notifications-notice": "Οι ενημερώσεις {{GENDER:|σας}}",
+ "echo-displaynotificationsconfiguration": "Εμφάνιση διαμόρφωσης Ενημερώσεων",
+ "echo-displaynotificationsconfiguration-summary": "Αυτή είναι μια επισκόπηση του τρόπου με τον οποίο έχουν ρυθμιστεί οι Ενημερώσεις σε αυτό το wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Ενημερώσεις ανά κατηγορία",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Ταξινόμηση άνα τύπο",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Τμήμα στο οποίο ειναι ταξινομημένος κάθε τύπος ενημέρωσης",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Επιτρεπτές μεθόδοι ενημέρωσης",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Ποιές μέθοδοι κοινοποίησης υποστηρίζονται για κάθε κατηγορία",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Ποιές μέθοδοι κοινοποίησης υποστηρίζονται για κάθε τύπο* ισχύει μόνο για τους τύπους εντώς ειδών κατηγορίας που είναι κρυμμένα από τις προτιμήσεις",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Ενεργοποιημένη από προεπιλογή",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Υπάρχοντες χρήστες",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Νέοι χρήστες",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Απαιτούμενες μέθοδοι ειδοποίησης",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Ποιές μέθοδοι ειδοποίησης είναι υποχρεωτικές για κάθε κατηγορία",
+ "echo-specialpage": "Ενημερώσεις",
+ "echo-specialpage-markasread": "Ενημέρωση: Σημείωση ως αναγνωσμένη",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|ενημέρωση|ενημερώσεις}}",
+ "echo-specialpage-pagefilters-title": "Πρόσφατη δραστηριότητα",
+ "echo-specialpage-pagefilters-subtitle": "Σελίδες με μη αναγνωσμένες ενημερώσεις",
+ "notificationsmarkread-legend": "Σημείωση ενημέρωσης ως αναγνωσμένης",
+ "echo-anon": "Για να λαμβάνετε ενημερώσεις, [$1 δημιουργήστε ένα λογαριασμό] ή [$2 συνδεθείτε].",
+ "echo-none": "Δεν έχετε ενημερώσεις.",
"echo-more-info": "Περισσότερες πληροφορίες",
"echo-feedback": "Ανατροφοδότηση",
+ "echo-popup-footer-special-page-invitation": "<strong>Δοκιμάστε την επανασχεδιασμένη σελίδα Ενημερώσεων.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Πλήρης νέα εμφάνιση και λειτουργίες.",
+ "echo-api-failure": "Δεν μπόρεσαν να ανακτηθούν ενημερώσεις.",
+ "echo-api-failure-cross-wiki": "Πρόσβαση στον απομακρυσμένο τομέα απορρίφθηκε.",
+ "echo-notification-placeholder": "Δεν υπάρχουν ενημερώσεις.",
+ "echo-notification-placeholder-filters": "Δεν υπάρχουν ενημερώσεις που ταιριάζουν με αυτά τα κριτήρια.",
+ "echo-notification-loginrequired": "Πρέπει να συνδεθείτε για να δείτε τις ενημερώσεις σας.",
+ "echo-notification-popup-loginrequired": "Παρακαλούμε συνδεθείτε για να δείτε τις ενημερώσεις σας.",
+ "echo-notification-markasread": "Σήμανση ως διαβασμένο",
+ "echo-notification-markasunread": "Σήμανση ως αδιάβαστο",
+ "echo-notification-markasread-tooltip": "Σήμανση ως διαβασμένο",
+ "echo-notification-more-options-tooltip": "Περισσότερες επιλογές",
+ "notification-link-text-expand-all": "Ανάπτυξη",
+ "notification-link-text-expand-alert-count": "Εμφάνιση {{PLURAL:$1|$1 ειδοποίησης|$1 ειδοποιήσεων}}",
+ "notification-link-text-expand-notice-count": "Εμφάνιση {{PLURAL:$1|$1 ενημέρωσης|$1 ενημερώσεων}}",
+ "notification-link-text-expand-all-count": "Εμφάνιση {{PLURAL:$1|$1 ενημέρωσης|$1 ενημερώσεων}}",
+ "notification-link-text-collapse-all": "Σύμπτυξη",
"notification-link-text-view-message": "Προβολή μηνύματος",
"notification-link-text-view-mention": "Προβολή αναφοράς",
- "notification-link-text-view-changes": "Προβολή αλλαγών",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Προβολή αναφοράς|Προβολή αναφορών}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Προβολή}} αλλαγών",
"notification-link-text-view-page": "Προβολή σελίδας",
+ "notification-header-edit-user-talk": "{{GENDER:$2|Ο|Η}} $1 σας άφησε ένα μήνυμα στην <strong>σελίδα συζήτησής {{GENDER:$3|σας}}</strong>.",
+ "notification-header-edit-user-talk-with-section": "{{GENDER:$2|Ο|Η}} $1 σας άφησε ένα μήνυμα στην <strong>σελίδα συζήτησής {{GENDER:$3|σας}}</strong> στο «<strong>$4</strong>».",
+ "notification-header-page-linked": "Ένας σύνδεσμος έγινε από την <strong>$4</strong> στην <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Συνδέθηκε από την <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Συνδέσεις έγιναν από {{PLURAL:$5||$5 σελίδες|100=99+ σελίδες}} στην <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Όλοι οι σύνδεσμοι προς αυτήν τη σελίδα",
+ "notification-header-mention-agent-talkpage": "{{GENDER:$2|Ο|Η}} $1 σας {{GENDER:$3|ανάφερε}} στην <strong>σελίδα συζήτησής {{GENDER:$2|του|της}}</strong> στο «<strong>$4</strong>».",
+ "notification-welcome-linktext": "Καλώς ήρθατε",
"notification-link-text-view-edit": "Προβολή επεξεργασίας",
- "notification-edit-talk-page2": "{{GENDER:$1|Ο|Η}} [[User:$1|$1]] άφησε μήνυμα στη [[User talk:$2#$3|σελίδα συζήτησής]] σας.",
- "notification-edit-talk-page-with-section": "{{GENDER:$1|Ο|Η}} [[User:$1|$1]] άφησε μήνυμα στην ενότητα \"[[User talk:$2#$3|$4]] της σελίδας συζήτησης σας.",
- "notification-edit-talk-page-flyout2": "{{GENDER:$1|Ο|Η}} $1 άφησε μήνυμα στη [[User talk:$2#$3|σελίδα συζήτησής]] σας.",
- "notification-edit-talk-page-flyout-with-section": "{{GENDER:$1|Ο|Η}} $1 άφησε μήνυμα στη σελίδα συζήτησής στη [[User talk:$2#$3|$4]].",
- "notification-page-linked": "Η σελίδα [[:$2]] {{GENDER:$1|συνδέθηκε}} από τη σελίδα [[:$3]]. [[Special:WhatLinksHere/$2|Δείτε όλους τους συνδέσμους προς αυτή τη σελίδα]].",
- "notification-page-linked-flyout": "Η σελίδα [[:$2]] {{GENDER:$1|συνδέθηκε}} από τη σελίδα [[:$3]].",
- "notification-add-comment2": "{{GENDER:$1|Ο|Η}} [[User:$1|$1]] σχολίασε στο \"[[$3|$2]]\" στην συζήτηση \"$4\".",
- "notification-mention": "{{GENDER:$1|Ο|Η}} [[User:$1|$1]] {{GENDER:$1|σας ανάφερε}} στην ενότητα \"[[:$3#$2|$4]]\" της σελίδας $5.",
- "notification-mention-flyout": "{{GENDER:$1|Ο|Η}} [[User:$1|$1]] {{GENDER:$1|σας ανάφερε}} στην ενότητα \"[[:$3#$2|$4]]\" της σελίδας συζήτησης $5.",
- "notification-new-user": "Καλώς ήρθατε στο {{SITENAME}}, $1! Χαιρόμαστε που είστε εδώ.",
- "notification-reverted2": "{{PLURAL:$4|Η επεξεργασία σας στην [[:$2]] έχει|Οι επεξεργασίες σας στην [[:$2]] έχουν}} αναστραφεί από {{GENDER:$1|τον|την}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Η επεξεργασία σας στην $2 έχει|Οι επεξεργασίες σας στην $2 έχουν}} αναστραφεί από {{GENDER:$1|τον|την}} $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Η επεξεργασία σας στην <strong>$3</strong> έχει|Οι επεξεργασίες σας στην <strong>$3</strong> έχουν}} {{GENDER:$2|αναστραφεί}}.",
+ "notification-header-emailuser": "{{GENDER:$2|Ο|Η}} $1 σας έστειλε ένα email.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|Ο|Η}} $1 σας άφησε ένα μήνυμα στη {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|Ο|Η}} $1 άφησε ένα μήνυμα στην σελίδα συζήτησής σας:",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Ο|Η}} $1 άφησε ένα μήνυμα στην σελίδα συζήτησής σας στην \"$2\"",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Η επεξεργασία σας στην $2 έχει|Οι επεξεργασίες σας στην $2 έχουν}} αναστραφεί από {{GENDER:$1|τον|την}} $1.",
- "notification-mention-email-subject": "{{GENDER:$1|Ο|Η}} $1 σας ανέφερε στη {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|σας ανάφερε}} στην ενότητα \"$3\" της σελίδας $4.",
- "notification-mention-nosection-email-batch-body": "{{GENDER:$1|Ο|Η}} $1 σας ανάφερε στην σελίδα συζήτησης $2.",
+ "notification-page-linked-email-subject": "Μια σελίδα που δημιουργήσατε συνθέθηκε σε {{SITENAME}}",
+ "notification-mention-email-subject": "{{GENDER:$1|Ο|Η}} $1 {{GENDER:$2|σας}} ανέφερε στη {{SITENAME}}",
"notification-user-rights-email-subject": "Τα δικαιώματα χρήστη σας έχουν αλλάξει στη {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Τα δικαιώματα χρήστη σας έχουν αλλάξει από {{GENDER:$1|τον|την}} $1. $2.",
- "echo-email-subject-default": "Νέα ειδοποίηση στο {{SITENAME}}",
- "echo-email-body-default": "Έχετε μια νέα ειδοποίηση στη {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Έχετε μια νέα ειδοποίηση.",
- "echo-email-footer-default": "$2\n\nΓια να ελέγξετε ποια μηνύματα σας στέλνουμε, πηγαίνετε στις προτιμήσεις σας:\n\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Για να ελέγξετε ποια μηνύματα σας στέλνουμε, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">πηγαίνετε στις προτιμήσεις σας</a>.<br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|Ειδοποιήσεις ($1)|Ειδοποιήσεις ($1)|100=Ειδοποιήσεις (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Μήνυμα ($1)|Μηνύματα ($1)|100=Μηνύματα (99+)}}",
- "echo-overlay-link": "Όλες οι ειδοποιήσεις",
- "echo-overlay-title": "<b>Ειδοποιήσεις</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Ειδοποιήσεις}}</b> (εμφανίζονται $1 από $2 μη αναγνωσμένες)",
+ "notification-timestamp-today": "Σήμερα",
+ "notification-timestamp-yesterday": "Χθες",
+ "notification-inbox-filter-read": "Αναγνωσμένες",
+ "notification-inbox-filter-unread": "Μη αναγνωσμένες",
+ "notification-inbox-filter-all": "Όλες",
+ "echo-email-body-default": "Έχετε μια νέα ενημέρωση στη {{SITENAME}}:\n\n\n$1",
+ "echo-email-footer-default-html": "Για να ελέγξετε ποια email σας στέλνουμε, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">ελέγξτε τις προτιμήσεις σας</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nΓια να ελέγξετε ποια email σας στέλνουμε, πηγαίνετε στις προτιμήσεις σας:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-html-footer-preference-link-text": "ελέγξτε τις προτιμήσεις σας",
+ "echo-notification-alert": "{{PLURAL:$1|Ειδοποίηση ($1)|Ειδοποιήσεις ($1)|100=Ειδοποιήσεις (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Προειδοποίηση ($1)|Ανακοινώσεις ($1)|100=Ανακοινώσεις (99+)}}",
+ "echo-notification-alert-text-only": "Ειδοποιήσεις",
+ "echo-notification-notice-text-only": "Ενημερώσεις",
+ "echo-overlay-link": "Όλες οι ενημερώσεις",
+ "echo-overlay-title": "<b>Ενημερώσεις</b>",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Ενημέρωση|Ενημερώσεις}}</b> (εμφανίζονται $1 από $2 μη αναγνωσμένες)",
"echo-mark-all-as-read": "Σήμανση όλων ως αναγνωσμένες",
"echo-date-today": "Σήμερα",
"echo-date-yesterday": "Χθες",
"echo-load-more-error": "Παρουσιάστηκε σφάλμα κατά την ανάκτηση περισσότερων αποτελέσματων.",
- "notification-edit-talk-page-bundle": "{{GENDER:$1|Ο|Η}} $1 και $3 {{PLURAL:$4|άλλος|άλλοι}} άφησαν μηνύματα στην [[User talk:$2|σελίδα συζήτησής σας]].",
- "notification-page-linked-bundle": "Η $2 {{GENDER:$1|συνδέθηκε}} από τη σελίδα $3 και $4 {{PLURAL:$5|άλλη σελίδα|άλλες σελίδες}}. [[Special:WhatLinksHere/$2|Δείτε όλους τους συνδέσμους]] προς αυτή τη σελίδα",
- "notification-edit-user-talk-email-batch-bundle-body": "Ο χρήστης $1 και $2 {{PLURAL:$3|άλλος χρήστης|άλλοι χρήστες}} {{GENDER:$1|άφησαν}} ένα μήνυμα στη σελίδα συζήτησης σας.",
- "echo-email-batch-subject-daily": "Έχετε {{PLURAL:$2|μια νέα ειδοποίηση|νέες ειδοποιήσεις}} στη {{SITENAME}}",
- "echo-email-batch-subject-weekly": "Έχετε {{PLURAL:$2|μια νέα ειδοποίηση|νέες ειδοποιήσεις}} στη {{SITENAME}} αυτή την εβδομάδα",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Ένα νέο μήνυμα|$1 νέα μηνύματα|100=99+ νέα μηνύματα}} στη <strong>σελίδα συζήτησής {{GENDER:$3|σας}}</strong>.",
+ "echo-email-batch-subject-daily": "Έχετε {{PLURAL:$2|μια νέα ενημέρωση|νέες ενημερώσεις}} στη {{SITENAME}}",
+ "echo-email-batch-subject-weekly": "Έχετε {{PLURAL:$2|μια νέα ενημέρωση|νέες ενημερώσεις}} στη {{SITENAME}} αυτή την εβδομάδα",
"echo-email-batch-body-intro-daily": "Γεια $1,\nΕδώ είναι μια περίληψη της σημερινής δραστηριότητας στη {{SITENAME}} για εσάς.",
"echo-email-batch-body-intro-weekly": "Γεια $1,\nΕδώ είναι μια περίληψη της δραστηριότητας αυτής της εβδομάδας στη {{SITENAME}} για εσάς.",
- "echo-email-batch-link-text-view-all-notifications": "Δείτε όλες τις ειδοποιήσεις",
- "echo-rev-deleted-text-view": "Αυτή η αναθεώρηση σελίδας έχει καταργηθεί."
+ "echo-email-batch-link-text-view-all-notifications": "Δείτε όλες τις ενημερώσεις",
+ "notification-header-foreign-alert": "Περισσότερες ειδοποιήσεις από {{PLURAL:$5|άλλο wiki|$5 άλλα wiki}}",
+ "notification-header-foreign-notice": "Περισσότερες κοινοποιήσεις από {{PLURAL:$5|άλλο wiki|$5 άλλα wiki}}",
+ "notification-header-foreign-all": "Περισσότερες ενημερώσεις από {{PLURAL:$5|άλλο wiki|$5 άλλα wiki}}"
}
diff --git a/Echo/i18n/en-gb.json b/Echo/i18n/en-gb.json
index 3dc7de74..bb1b253c 100644
--- a/Echo/i18n/en-gb.json
+++ b/Echo/i18n/en-gb.json
@@ -1,7 +1,10 @@
{
"@metadata": {
"authors": [
- "Shirayuki"
+ "Shirayuki",
+ "Mhutti1",
+ "Shahjad ansari"
]
- }
+ },
+ "echo-pref-beta-feature-cross-wiki-message": "Enhanced notifications"
}
diff --git a/Echo/i18n/en.json b/Echo/i18n/en.json
index 86e34243..795a5abf 100644
--- a/Echo/i18n/en.json
+++ b/Echo/i18n/en.json
@@ -1,7 +1,38 @@
{
"@metadata": {
"authors": [
- "Andrew Garrett"
+ "Andrew Garrett",
+ "Alangi Derick",
+ "Alex Monk",
+ "Amir E. Aharoni",
+ "Andrew Garrett",
+ "Benny Situ",
+ "Brad Jorsch",
+ "Erik Bernhardson",
+ "James D. Forrester",
+ "Jon Robson",
+ "Kunal Mehta",
+ "lokal-profil",
+ "lwelling",
+ "MatmaRex",
+ "Matthew Flaschen",
+ "Matthias Mullie",
+ "mhutti1",
+ "Moriel Schottlender",
+ "Nemo bis",
+ "Nischay Nahata",
+ "Raimond Spekking",
+ "Reedy",
+ "Roan Kattouw",
+ "Ryan Kaldari",
+ "Siebrand Mazeland",
+ "Stephane Bisson",
+ "theopolisme",
+ "Tony Thomas",
+ "Terry Chay",
+ "umherirrender",
+ "Yuki Shira"
+
]
},
"echo-desc": "System for notifying users about events and messages",
@@ -9,7 +40,9 @@
"prefs-emailsettings": "Email options",
"prefs-displaynotifications": "Display options",
"prefs-echosubscriptions": "Notify me about these events",
+ "prefs-echocrosswiki": "Cross-wiki notifications",
"prefs-newmessageindicator": "New message indicator",
+ "prefs-blocknotificationslist": "Muted users",
"echo-pref-send-me": "Send me:",
"echo-pref-send-to": "Send to:",
"echo-pref-email-format": "Email format:",
@@ -21,94 +54,179 @@
"echo-pref-email-frequency-weekly": "A weekly summary of notifications",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Plain text",
+ "echo-pref-cross-wiki-notifications": "Show notifications from other wikis",
+ "echo-pref-notifications-blacklist": "Do not display notifications from these users. ([[mw:Help:Notifications#mute|learn more]])",
"echo-pref-new-message-indicator": "Show talk page message indicator in my toolbar",
+ "echo-pref-beta-feature-cross-wiki-message": "Enhanced notifications",
+ "echo-pref-beta-feature-cross-wiki-description": "View and organize notifications more easily. Includes cross-wiki notifications, which lets you see messages from other wikis. (To receive cross-wiki notifications on a given wiki, you must activate the beta feature on that wiki.)",
"echo-learn-more": "Learn more",
+ "echo-log": "Public log",
"echo-new-messages": "You have new messages",
"echo-category-title-edit-user-talk": "Talk page {{PLURAL:$1|message|messages}}",
"echo-category-title-article-linked": "Page {{PLURAL:$1|link|links}}",
"echo-category-title-reverted": "Edit {{PLURAL:$1|revert|reverts}}",
"echo-category-title-mention": "{{PLURAL:$1|Mention|Mentions}}",
+ "echo-category-title-mention-failure": "Failed {{PLURAL:$1|mention|mentions}}",
+ "echo-category-title-mention-success": "Successful {{PLURAL:$1|mention|mentions}}",
"echo-category-title-other": "{{PLURAL:$1|Other}}",
"echo-category-title-system": "{{PLURAL:$1|System}}",
"echo-category-title-user-rights": "{{PLURAL:$1|User rights change|User rights changes}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Email from other user|Emails from other users}}",
+ "echo-category-title-article-reminder": "Page {{PLURAL:$1|reminder|reminders}}",
"echo-pref-tooltip-edit-user-talk": "Notify me when someone posts a message or replies on my talk page.",
- "echo-pref-tooltip-article-linked": "Notify me when someone links to a page I created from an article page.",
+ "echo-pref-tooltip-article-linked": "Notify me when someone links to a page I created from another page.",
"echo-pref-tooltip-reverted": "Notify me when someone reverts an edit I made, by using the undo or rollback tool.",
"echo-pref-tooltip-mention": "Notify me when someone links to my user page.",
+ "echo-pref-tooltip-mention-failure": "Notify me when I could not send out a mention to someone.",
+ "echo-pref-tooltip-mention-success": "Notify me when I send out a mention to someone.",
"echo-pref-tooltip-user-rights": "Notify me when someone changes my user rights.",
- "echo-no-agent": "[Nobody]",
- "echo-no-title": "[No page]",
+ "echo-pref-tooltip-emailuser": "Notify me when someone sends me an email.",
+ "echo-pref-tooltip-article-reminder": "Notify me about this page when I ask.",
"echo-error-no-formatter": "No formatting defined for notification.",
"notifications": "Notifications",
"tooltip-pt-notifications-alert": "{{GENDER:|Your}} alerts",
- "tooltip-pt-notifications-message": "{{GENDER:|Your}} messages",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Your}} notices",
+ "echo-displaynotificationsconfiguration": "Display Notifications configuration",
+ "echo-displaynotificationsconfiguration-summary": "This is an overview of how Notifications are configured on this wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notifications by category",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sorting of types",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Which section each notification type is sorted into",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Allowed notification methods",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Which notification methods are supported for each category",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Which notification methods are supported for each type; only applies to types within categories that are hidden from preferences",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Enabled by default",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Existing users",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "New users",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Required notification methods",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Which notification methods are mandatory for each category",
"echo-specialpage": "Notifications",
+ "echo-specialpage-section-markread": "Mark group as read",
+ "echo-specialpage-markasread": "Notification: Mark as read",
+ "echo-specialpage-markasread-invalid-id": "Invalid event ID",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notification|notifications}}",
+ "echo-specialpage-pagination-range": "$1 - $2",
+ "echo-specialpage-pagefilters-title": "Recent activity",
+ "echo-specialpage-pagefilters-subtitle": "Pages with unread notifications",
+ "notificationsmarkread-legend": "Mark notification as read",
"echo-anon": "To receive notifications, [$1 create an account] or [$2 log in].",
"echo-none": "You have no notifications.",
"echo-more-info": "More info",
"echo-feedback": "Feedback",
+ "echo-popup-footer-special-page-invitation": "<strong>Try the redesigned Notifications page.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "All new look and features.",
"echo-quotation-marks": "\"$1\"",
- "echo-api-failure": "Could not retrieve notifications. Please try again. (Error $1)",
+ "echo-api-failure": "Failed to fetch notifications.",
+ "echo-api-failure-cross-wiki": "Access to the remote domain was denied.",
"echo-notification-placeholder": "There are no notifications.",
+ "echo-notification-placeholder-filters": "There are no notifications matching these criteria.",
+ "echo-notification-loginrequired": "You must login to see your notifications.",
+ "echo-notification-popup-loginrequired": "Please log in to view your notifications.",
+ "echo-notification-markasread": "Mark as read",
+ "echo-notification-markasunread": "Mark as unread",
+ "echo-notification-markasread-tooltip": "Mark as read",
+ "echo-notification-more-options-tooltip": "More options",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Stop}} watching new activity on \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|You}} are no longer watching the page \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|You}} can watch [$2 this page] anytime.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Follow}} new activity on \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|You}} are now watching the page \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|You}} can stop watching [$2 this page] anytime.",
+ "notification-link-text-expand-all": "Expand",
+ "notification-link-text-expand-alert-count": "View {{PLURAL:$1|$1 alert|$1 alerts}}",
+ "notification-link-text-expand-notice-count": "View {{PLURAL:$1|$1 notice|$1 notices}}",
+ "notification-link-text-expand-all-count": "View {{PLURAL:$1|$1 notification|$1 notifications}}",
+ "notification-link-text-collapse-all": "Collapse",
"notification-link-text-view-message": "View message",
"notification-link-text-view-mention": "View mention",
- "notification-link-text-view-changes": "View changes",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|View mention|View mentions}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|View}} changes",
"notification-link-text-view-page": "View page",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|left}} a message on <strong>{{GENDER:$3|your}} talk page</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|left}} a message on <strong>{{GENDER:$3|your}} talk page</strong> in \"<strong>$4</strong>\".",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "A link was made from <strong>$4</strong> to <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Linked from <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Links were made from {{PLURAL:$5||$5 pages|100=99+ pages}} to <strong>$3</strong>.",
+ "notification-header-article-reminder": "A page {{GENDER:$2|you}} have requested to be reminded about is at <strong>$3</strong>",
+ "notification-link-text-what-links-here": "All links to this page",
+ "notification-body-mention": "$1",
+ "notification-header-mention-other": "$1 {{GENDER:$2|mentioned}} {{GENDER:$3|you}} on <strong>$4</strong> in \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|mentioned}} {{GENDER:$3|you}} on <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|mentioned}} {{GENDER:$3|you}} on the <strong>user talk page {{GENDER:$5|of}} $4</strong> in \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|mentioned}} {{GENDER:$3|you}} on the <strong>user talk page {{GENDER:$5|of}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|mentioned}} {{GENDER:$3|you}} on <strong>{{GENDER:$2|his|her|their}} talk page</strong> in \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|mentioned}} {{GENDER:$3|you}} on <strong>{{GENDER:$2|his|her|their}} talk page</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|mentioned}} {{GENDER:$3|you}} on the <strong>$4</strong> talk page in \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|mentioned}} {{GENDER:$3|you}} on the <strong>$4</strong> talk page.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Your}} mention of <strong>$3</strong> was not sent because the user was not found.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Your}} mention of <strong>$3</strong> was not sent because the user is anonymous.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|You}} tried to mention more than $3 {{PLURAL:$3|user|users}}. All mentions above that limit were not sent.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|A mention|$3 mentions}} {{GENDER:$2|you made}} on the <strong>$4</strong> talk page {{PLURAL:$3|could}} not be sent.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Username does not exist:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IPs cannot be mentioned:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Your}} mention of <strong>$3</strong> was sent.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|A mention|$3 mentions}} {{GENDER:$2|you made}} on the <strong>$4</strong> talk page {{PLURAL:$3|were}} sent.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|You mentioned}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|A notification|$3 notifications}} about mentions {{GENDER:$2|you made}} on the <strong>$4</strong> talk page: {{PLURAL:$5|$5 not sent}}, {{PLURAL:$6|$6 sent}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Your}} user rights were {{GENDER:$1|changed}}. You have been added to: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Your}} user rights were {{GENDER:$1|changed}}. You are no longer a member of: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Your}} user rights were {{GENDER:$1|changed}}. You have been added to: $2. You are no longer a member of: $4.",
+ "notification-header-user-rights-expiry-change": "The expiry of {{GENDER:$4|your}} membership in the following {{PLURAL:$3|group|groups}} has been {{GENDER:$1|changed}}: $2.",
+ "notification-body-user-rights": "$1",
+ "notification-header-welcome": "{{GENDER:$2|Welcome}} to {{SITENAME}}, $1! We're glad {{GENDER:$2|you're}} here.",
+ "notification-welcome-link": "",
+ "notification-welcome-linktext": "Welcome",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|You}} just made {{GENDER:$2|your}} first edit; thank {{GENDER:$2|you}}, and welcome!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|You}} just made {{GENDER:$2|your}} tenth edit; thank {{GENDER:$2|you}}, and please keep going!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|You}} just made {{GENDER:$2|your}} hundredth edit; thank {{GENDER:$2|you}} very much!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|You}} just made {{GENDER:$2|your}} thousandth edit; thank {{GENDER:$2|you}} for being a great contributor!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|You}} just made {{GENDER:$2|your}} ten thousandth edit; thank {{GENDER:$2|you}} so very much!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|You}} just made {{GENDER:$2|your}} hundred thousandth edit; thank {{GENDER:$2|you}} for an amazing contribution!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|You}} just made {{GENDER:$2|your}} millionth edit; thank {{GENDER:$2|you}} for an astonishing contribution!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Your}} edit",
"notification-link-text-view-edit": "View edit",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|left}} a message on your [[User talk:$2#$3|talk page]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|left}} a message on your talk page in \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|left}} a message on your [[User talk:$2#$3|talk page]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|left}} a message on your talk page in \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] was {{GENDER:$1|linked}} from [[:$3]]. [[Special:WhatLinksHere/$2|See all links to this page]].",
- "notification-page-linked-flyout": "[[:$2]] was {{GENDER:$1|linked}} from [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|commented}} on \"[[$3|$2]]\" on the \"$4\" talk page.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|posted}} a new topic \"$2\" on [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|sent}} you a message: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|commented}} on \"[[$3#$2|$2]]\" on your talk page.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|mentioned}} you on the $5 talk page in \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|mentioned}} you on the $5 talk page in \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|mentioned}} you on the [[:$3|$2 talk page]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|mentioned}} you on the [[:$3|$2 talk page]].",
- "notification-user-rights": "Your user rights [[Special:Log/rights/$1|were {{GENDER:$1|changed}}]] by [[User:$1|$1]]. $2. [[Special:ListGroupRights|Learn more]]",
- "notification-user-rights-flyout": "Your user rights were {{GENDER:$1|changed}} by $1. $2. [[Special:ListGroupRights|Learn more]]",
- "notification-user-rights-add": "You are now a member of {{PLURAL:$2|this group|these groups}}: $1",
- "notification-user-rights-remove": "You are no longer a member of {{PLURAL:$2|this group|these groups}}: $1",
- "notification-new-user": "Welcome to {{SITENAME}}, $1! We're glad you're here.",
- "notification-reverted2": "Your {{PLURAL:$4|edit on [[:$2]] has|edits on [[:$2]] have}} been {{GENDER:$1|reverted}} by [[$5|$1]]. $3",
- "notification-reverted-flyout2": "Your {{PLURAL:$4|edit on $2 has|edits on $2 have}} been {{GENDER:$1|reverted}} by $1. $3",
+ "notification-link-article-reminder": "View page",
+ "notification-header-reverted": "Your {{PLURAL:$4|edit on <strong>$3</strong> was|edits on <strong>$3</strong> were}} {{GENDER:$2|reverted}}.",
+ "notification-body-reverted": "$1",
+ "notification-header-emailuser": "$1 {{GENDER:$2|sent}} you an email.",
+ "notification-body-emailuser": "$1",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|left}} you a message on {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|left}} a message on your talk page.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|left}} a message on your talk page in \"$2\".",
"notification-page-linked-email-subject": "A page you created was linked on {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 was {{GENDER:$1|linked}} from $3.",
"notification-reverted-email-subject2": "Your {{PLURAL:$3|edit was|edits were}} {{GENDER:$1|reverted}} on {{SITENAME}}",
- "notification-reverted-email-batch-body2": "Your {{PLURAL:$3|edit on $2 has been|edits on $2 have been}} {{GENDER:$1|reverted}} by $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|mentioned}} you on {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|mentioned}} you on the $4 talk page in \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|mentioned}} you on the $2 talk page.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|mentioned}} {{GENDER:$2|you}} on {{SITENAME}}",
"notification-user-rights-email-subject": "Your user rights have changed on {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Your user rights were {{GENDER:$1|changed}} by $1. $2.",
- "echo-notification-count": "$1+",
- "echo-email-subject-default": "New notification at {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mo}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1yr}}",
+ "notification-timestamp-today": "Today",
+ "notification-timestamp-yesterday": "Yesterday",
+ "notification-inbox-filter-read": "Read",
+ "notification-inbox-filter-unread": "Unread",
+ "notification-inbox-filter-all": "All",
"echo-email-body-default": "You have a new notification at {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "You have a new notification.",
- "echo-email-footer-default": "$2\n\nTo control which emails we send you, check your preferences:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-email-footer-default-html": "To control which emails we send you, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">check your preferences</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nTo control which emails we send you, check your preferences:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "To control which emails we send {{GENDER:$1|you}}, check {{GENDER:$1|your}} preferences:",
+ "echo-email-html-footer-preference-link-text": "check {{GENDER:$1|your}} preferences",
+ "echo-email-html-footer-with-link": "To control which emails we send {{GENDER:$2|you}}, $1.",
"echo-notification-alert": "{{PLURAL:$1|Alert ($1)|Alerts ($1)|100=Alerts (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Message ($1)|Messages ($1)|100=Messages (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notice ($1)|Notices ($1)|100=Notices (99+)}}",
"echo-notification-alert-text-only": "Alerts",
- "echo-notification-message-text-only": "Messages",
+ "echo-notification-notice-text-only": "Notices",
"echo-overlay-link": "All notifications",
"echo-overlay-title": "<b>Notifications</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notification|Notifications}}</b> (showing $1 of $2 unread)",
"echo-mark-all-as-read": "Mark all as read",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notification|notifications}} marked as read",
+ "echo-mark-wiki-as-read": "Mark all as read in selected wiki: $1",
"echo-date-today": "Today",
"echo-date-yesterday": "Yesterday",
"echo-load-more-error": "An error occurred while fetching more results.",
- "notification-edit-talk-page-bundle": "$1 and $3 {{PLURAL:$4|other|others}} {{GENDER:$1|left}} a message on your [[User talk:$2|talk page]].",
- "notification-page-linked-bundle": "$2 was {{GENDER:$1|linked}} from $3 and $4 other {{PLURAL:$5|page|pages}}. [[Special:WhatLinksHere/$2|See all links to this page]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 and $2 {{PLURAL:$3|other|others}} {{GENDER:$1|left}} a message on your talk page.",
- "notification-page-linked-email-batch-bundle-body": "$2 was {{GENDER:$1|linked}} from $3 and $4 other {{PLURAL:$5|page|pages}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|One new message|$1 new messages|100=99+ new messages}} on <strong>{{GENDER:$3|your}} talk page</strong>.",
"echo-email-batch-separator": "--",
"echo-email-batch-bullet": "•",
"echo-email-batch-subject-daily": "You have {{PLURAL:$2|a new notification|new notifications}} at {{SITENAME}}",
@@ -116,27 +234,10 @@
"echo-email-batch-body-intro-daily": "Hi $1,\nHere's a summary of today's activity on {{SITENAME}} for you.",
"echo-email-batch-body-intro-weekly": "Hi $1,\nHere's a summary of this week's activity on {{SITENAME}} for you.",
"echo-email-batch-link-text-view-all-notifications": "View all notifications",
- "echo-rev-deleted-text-view": "This page revision has been suppressed.",
- "apihelp-echomarkread-description": "Mark notifications as read for the current user.",
- "apihelp-echomarkread-param-list": "A list of notification IDs to mark as read.",
- "apihelp-echomarkread-param-all": "If set, marks all of a user's notifications as read.",
- "apihelp-echomarkread-param-sections": "A list of sections to mark as read.",
- "apihelp-echomarkread-example-1": "Mark notification 8 as read",
- "apihelp-echomarkread-example-2": "Mark all notifications as read",
- "apihelp-echomarkseen-description": "Mark notifications as seen for the current user.",
- "apihelp-echomarkseen-example-1": "Mark notifications of all types as seen",
- "apihelp-echomarkseen-param-type": "Type of notifications to mark as seen: 'alert', 'message' or 'all'.",
- "apihelp-query+notifications-description": "Get notifications waiting for the current user.",
- "apihelp-query+notifications-param-prop": "Details to request.",
- "apihelp-query+notifications-param-sections": "The notification sections to query (i.e. some combination of 'alert' and 'message').",
- "apihelp-query+notifications-param-groupbysection": "Whether to group the result by section. Each section is fetched separately if set.",
- "apihelp-query+notifications-param-format": "If specified, notifications will be returned formatted this way.",
- "apihelp-query+notifications-param-limit": "The maximum number of notifications to return.",
- "apihelp-query+notifications-param-index": "If specified, a list of notification IDs, in order, will be returned.",
- "apihelp-query+notifications-param-alertcontinue": "When more alert results are available, use this to continue.",
- "apihelp-query+notifications-param-alertunreadfirst": "Whether to show unread message notifications first.",
- "apihelp-query+notifications-param-messagecontinue": "When more message results are available, use this to continue.",
- "apihelp-query+notifications-param-messageunreadfirst": "Whether to show unread alert notifications first.",
- "apihelp-query+notifications-example-1": "List notifications",
- "apihelp-query+notifications-example-2": "List notifications, grouped by section, with counts"
+ "notification-header-foreign-alert": "More alerts from {{PLURAL:$5|another wiki|$5 other wikis}}",
+ "notification-header-foreign-notice": "More notices from {{PLURAL:$5|another wiki|$5 other wikis}}",
+ "notification-header-foreign-all": "More notifications from {{PLURAL:$5|another wiki|$5 other wikis}}",
+ "notification-body-foreign": "$1",
+ "echo-foreign-wiki-lang": "$1 - $2",
+ "echo-badge-count": "{{PLURAL:$1|$1|100=99+}}"
}
diff --git a/Echo/i18n/eo.json b/Echo/i18n/eo.json
index c8202b2d..66bb1d3f 100644
--- a/Echo/i18n/eo.json
+++ b/Echo/i18n/eo.json
@@ -3,7 +3,12 @@
"authors": [
"KuboF",
"Tlustulimu",
- "Yekrats"
+ "Yekrats",
+ "Robin van der Vliet",
+ "Lucas",
+ "Macofe",
+ "Gamliel Fishkin",
+ "NMaia"
]
},
"echo-desc": "Sistemo por sciigado uzantojn pri okazaĵoj kaj mesaĝoj",
@@ -11,6 +16,7 @@
"prefs-emailsettings": "Retpoŝtaj opcioj",
"prefs-displaynotifications": "Montraj opcioj",
"prefs-echosubscriptions": "Sciigu min pri tiuj ĉi okazaĵoj",
+ "prefs-echocrosswiki": "Transvikiaj sciigoj",
"prefs-newmessageindicator": "Indikilo pri novaj mesaĝoj",
"echo-pref-send-me": "Sendadi al mi:",
"echo-pref-send-to": "Sendadi al:",
@@ -23,79 +29,120 @@
"echo-pref-email-frequency-weekly": "Semajnan resumon de sciigoj",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Ordinara teksto",
+ "echo-pref-cross-wiki-notifications": "Montri sciigojn el aliaj vikioj",
"echo-pref-new-message-indicator": "Montri indikilon pri diskutaj mesaĝoj en mia ilobreto",
+ "echo-pref-beta-feature-cross-wiki-message": "Plibonigitaj sciigoj",
"echo-learn-more": "Lerni plu",
+ "echo-log": "Publika protokolo",
"echo-new-messages": "Vi havas novajn mesaĝojn",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mesaĝo|Mesaĝoj}} en diskutpaĝo",
"echo-category-title-article-linked": "{{PLURAL:$1|Ligilo|Ligiloj}} al paĝo",
"echo-category-title-reverted": "{{PLURAL:$1|Malfaro|Malfaroj}} de redakto",
"echo-category-title-mention": "{{PLURAL:$1|Mencio|Mencioj}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Malsukcesa mencio|Malsukcesaj mencioj}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Sukcesa mencio|Sukcesaj mencioj}}",
"echo-category-title-other": "{{PLURAL:$1|Aliaj}}",
"echo-category-title-system": "{{PLURAL:$1|Sistemo}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Ŝanĝo de uzanto-rajto|Ŝanĝoj de uzanto-rajtoj}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Retpoŝta mesaĝo de alia uzanto|Retpoŝtaj mesaĝoj de aliaj uzantoj}}",
"echo-pref-tooltip-edit-user-talk": "Sciigu min kiam iu komencas diskuton aŭ respondas en mia diskutpaĝo.",
"echo-pref-tooltip-article-linked": "Sciigu min kiam iu de artikolo ligas al paĝo kiun mi kreis.",
"echo-pref-tooltip-reverted": "Sciigu min kiam iu malfaras mian redakton per ilo por malfari aŭ amasmalfari.",
"echo-pref-tooltip-mention": "Sciigu min kiam iu ligas al mia uzantopaĝo.",
+ "echo-pref-tooltip-mention-failure": "Sciigi al mi kiam mi ne sendis mencion al iu.",
+ "echo-pref-tooltip-mention-success": "Sciigi al mi kiam mi sendas mencion al iu.",
"echo-pref-tooltip-user-rights": "Sciigu min, se iu ŝanĝas miajn rajtojn de uzanto.",
- "echo-no-agent": "[Neniu]",
- "echo-no-title": "[Sen Paĝo]",
+ "echo-pref-tooltip-emailuser": "Sciigu min kiam iu sendas al mi retpoŝtan mesaĝon.",
"echo-error-no-formatter": "Neniu aranĝo difinita por sciigo.",
"notifications": "Sciigoj",
"tooltip-pt-notifications-alert": "{{GENDER:|Viaj}} sciigoj",
- "tooltip-pt-notifications-message": "{{GENDER:|Viaj}} mesaĝoj",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Viaj}} sciigoj",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Estantaj uzantoj",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Novaj uzantoj",
"echo-specialpage": "Sciigoj",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|sciigo|sciigoj}}",
+ "echo-specialpage-pagefilters-title": "Antaŭnelongaj aktivaĵoj",
+ "echo-specialpage-pagefilters-subtitle": "Paĝoj kun nelegitaj sciigoj",
+ "notificationsmarkread-legend": "Marki sciigon kiel legite",
"echo-anon": "Po ricevadi sciigojn oni bezonas [$1 krei konton] aŭ [$2 ensaluti].",
"echo-none": "Vi ne havas sciigojn.",
"echo-more-info": "Pliaj informoj",
"echo-feedback": "Rimarkoj",
+ "echo-popup-footer-special-page-invitation": "<strong>Gustumu la redizajnitan paĝon Sciigoj.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "La tuta nova aspekto kaj ecoj.",
+ "echo-api-failure": "Ne sukcesis akiri la sciigojn.",
+ "echo-notification-placeholder": "Ne estas iuj sciigoj.",
+ "echo-notification-placeholder-filters": "Ne estas sciigoj konformaj al ĉi tiu kriterio.",
+ "echo-notification-loginrequired": "Vi devas ensaluti por vidi viajn sciigojn.",
+ "echo-notification-popup-loginrequired": "Bonvolu ensaluti por vidi viajn sciigojn.",
+ "echo-notification-markasread": "Marki kiel legitan.",
+ "echo-notification-markasunread": "Marki kiel nelegitan",
+ "echo-notification-markasread-tooltip": "Marki kiel legite",
+ "echo-notification-more-options-tooltip": "Pliaj agordoj",
+ "notification-link-text-expand-all": "Etendi",
+ "notification-link-text-expand-alert-count": "Vidi {{PLURAL:$1|sciigo|$1 sciigoj}}n",
+ "notification-link-text-expand-notice-count": "Vidi {{PLURAL:$1|sciigo|$1 sciigoj}}n",
+ "notification-link-text-collapse-all": "Kaŝi",
"notification-link-text-view-message": "Montri mesaĝon",
"notification-link-text-view-mention": "Montri mencion",
- "notification-link-text-view-changes": "Montri ŝanĝojn",
+ "notification-link-text-view-changes": "{{GENDER:$1|Montri}} ŝanĝojn",
"notification-link-text-view-page": "Montri paĝon",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|lasis}} mesaĝon sur <strong>{{GENDER:$3|via}} diskutpaĝo</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|lasis}} mesaĝon sur <strong>{{GENDER:$3|via}} diskutpaĝo</strong> en «<strong>$4</strong>».",
+ "notification-header-page-linked": "Ligilo estis kreita de <strong>$4</strong> al <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Ligita el <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Ligiloj estis kreitaj el {{PLURAL:$5||$5 paĝoj|100=pli ol 99 aliaj paĝoj}} al <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Ĉiuj ligiloj al ĉi tiu paĝo",
+ "notification-header-mention-other": "$1 {{GENDER:$2|menciis}} {{GENDER:$3|vin}} sur <strong>$4</strong> en \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|menciis}} {{GENDER:$3|vin}} sur <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|menciis}} {{GENDER:$3|vin}} sur la <strong>uzanto-diskutopaĝo {{GENDER:$5|de}} $4</strong> en \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|menciis}} {{GENDER:$3|vin}} sur la <strong>uzanto-diskutopaĝo {{GENDER:$5|de}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|menciis}} {{GENDER:$3|vin}} sur <strong>{{GENDER:$2|sia}} diskutpaĝo</strong> en «<strong>$4</strong>».",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|menciis}} {{GENDER:$3|vin}} sur <strong>{{GENDER:$2|sia}} diskutopaĝo</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|menciis}} {{GENDER:$3|vin}} sur la diskutopaĝo de <strong>$4</strong> en \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|menciis}} {{GENDER:$3|vin}} sur la diskutopaĝo de <strong>$4</strong>.",
+ "notification-header-mention-success": "{{GENDER:$2|Via}} mencio de <strong>$3</strong> estis sendita.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Mencio, kiu|$3 mencioj, kiuj}}n {{GENDER:$2|vi faris}} en la diskutpaĝo <strong>$4</strong>, estis sendita{{PLURAL:$3||j}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Vi menciis}}:</strong> $3",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Viaj}} rajtoj de uzanto estis {{GENDER:$1|ŝanĝitaj}}. Vi estis aldonita al: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Viaj}} rajtoj de uzanto estis {{GENDER:$1|ŝanĝitaj}}. Vi ne plu estas membro de: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Viaj}} rajtoj de uzanto estis {{GENDER:$1|ŝanĝitaj}}. Vi estis aldonita al: $2. Vi ne plu estas membro de: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Bonvenon}} al {{SITENAME}}, $1! Ni ĝojas, ke {{GENDER:$2|vi}} estas ĉi tie.",
+ "notification-welcome-linktext": "Bonvenon",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Vi}} ĵus faris {{GENDER:$2|vian}} unuan redakton. Dankon al {{GENDER:$2|vi}}, kaj bonvenon!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Vi}} ĵus faris {{GENDER:$2|vian}} dekan redakton. Dankon al {{GENDER:$2|vi}}, kaj bonvolu daŭrigi tiel!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Vi}} ĵus faris {{GENDER:$2|vian}} centan redakton. Multan dankon al {{GENDER:$2|vi}}!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Vi}} ĵus faris {{GENDER:$2|vian}} milan redakton. Dankon al {{GENDER:$2|vi}}, ke vi estas bonega kontribuanto!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Vi}} ĵus faris {{GENDER:$2|vian}} dekmilan redakton. Koran dankon al {{GENDER:$2|vi}}!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Vi}} ĵus faris {{GENDER:$2|vian}} centmilan redakton. Dankegon al {{GENDER:$2|vi}} por bona kontribuado!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Vi}} ĵus faris {{GENDER:$2|vian}} milionan redakton. Dankegon al {{GENDER:$2|vi}} por mire multaj kontribuoj!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Via}} redakto",
"notification-link-text-view-edit": "Montri redakton",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|lasis}} mesaĝon en via [[User talk:$2#$3|diskutpaĝo]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|lasis}} mesaĝon sur via diskutopaĝo en „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|lasis}} mesaĝon sur via [[User talk:$2#$3|diskutopaĝo]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|lasis}} mesaĝon sur via diskutopaĝo en \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] estis {{GENDER:$1|ligata}} de [[:$3]]. [[Special:WhatLinksHere/$2|Ligiloj ĉi tien]].",
- "notification-page-linked-flyout": "[[:$2]] estis {{GENDER:$1|ligita}} de [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|komentis}} sur \"[[$3|$2]]\" sur la diskutopaĝo de \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|afiŝis}} novan temon \"$2\" sur [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|sendis}} al vi mesaĝon: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|komentis}} sur \"[[$3#$2|$2]]\" sur via diskutopaĝo.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|menciis}} vin sur la diskutopaĝo de $5 en \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|menciis}} vin sur la diskutopaĝo de $5 en \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|menciis}} vin sur la [[:$3|diskutopaĝo „$2“]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|menciis}} vin sur la [[:$3|diskutopaĝo „$2“]].",
- "notification-user-rights": "Viaj uzantorajtoj [[Special:Log/rights/$1|estis {{GENDER:$1|ŝanĝitaj}}]] de [[User:$1|$1]]. $2. [[Special:ListGroupRights|Pliaj informoj]]",
- "notification-user-rights-flyout": "Viaj uzantorajtoj estis {{GENDER:$1|ŝanĝitaj}} de $1. $2. [[Special:ListGroupRights|Pliaj informoj]]",
- "notification-user-rights-add": "Vi estas nun membro de {{PLURAL:$2|ĉi tiu grupo|ĉi tiuj grupoj}}: $1",
- "notification-user-rights-remove": "Vi ne plu estas membro de {{PLURAL:$2|ĉi tiu grupo|ĉi tiuj grupoj}}: $1",
- "notification-new-user": "Bonvenon al {{SITENAME}}, $1! Ni ĝojas, ke vi estas ĉi tie.",
- "notification-reverted2": "{{PLURAL:$4|Via redakto sur [[:$2]] estis {{GENDER:$1|malfarita}}|Viaj redaktoj sur [[:$2]] estis {{GENDER:$1|malfaritaj}}}} de [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Via redakto sur $2 estis {{GENDER:$1|malfarita}}|Viaj redaktoj sur $2 estis {{GENDER:$1|malfaritaj}}}} de $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Via redakto sur $3 estis {{GENDER:$2|malfarita}}|Viaj redaktoj sur $3 estis {{GENDER:$2|malfaritaj}}}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|sendis}} al vi retpoŝtan mesaĝon.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|lasis}} al vi mesaĝon sur {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|lasis}} mesaĝon sur via diskutopaĝo.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|lasis}} mesaĝon sur via diskutopaĝo pri \"$2\".",
"notification-page-linked-email-subject": "Paĝo kiun vi kreis estas ligita en {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 estis {{GENDER:$1|ligita}} de $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Via redakto estis {{GENDER:$1|malfarita}}|Viaj redaktoj estis {{GENDER:$1|malfaritaj}}}} sur {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Via redakto sur $2 estis {{GENDER:$1|malfarita}}|Viaj redaktoj sur $2 estis {{GENDER:$1|malfaritaj}}}} de $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|menciis}} vin sur {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|menciis}} vin sur la diskutopaĝo de $4 en \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|menciis}} vin sur la diskutopaĝo „$2“.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|menciis}} {{GENDER:$2|vin}} sur {{SITENAME}}",
"notification-user-rights-email-subject": "Viaj uzantorajtoj estis ŝanĝitaj sur {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Viaj uzantorajtoj estis {{GENDER:$1|ŝanĝitaj}} de $1. $2.",
- "echo-email-subject-default": "Nova sciigo en {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|sekundo|$1 sekundoj}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|minuto|$1 minutoj}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|horo|$1 horoj}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|tago|$1 tagoj}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|monato|$1 monatoj}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|jaro|$1 jaroj}}",
+ "notification-timestamp-today": "Hodiaŭ",
+ "notification-timestamp-yesterday": "Hieraŭ",
+ "notification-inbox-filter-read": "Legita",
+ "notification-inbox-filter-unread": "Nelegita",
+ "notification-inbox-filter-all": "Ĉiuj",
"echo-email-body-default": "Vi havas novan noton ĉe {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Vi havas novajn sciigojn.",
"echo-email-footer-default": "$2\n\nPor kontroli kiujn retpoŝtaĵojn ni sendas al vi, kontrolu viajn preferojn:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Por kontroli kiujn retpoŝtaĵojn ni sendas al vi, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">kontrolu viajn preferojn</a>.<br />\n$1",
+ "echo-email-html-footer-preference-link-text": "kontroli {{GENDER:$1|viajn}} preferojn",
"echo-notification-alert": "{{PLURAL:$1|Atentigo ($1)|Atentigoj ($1)|100=Atentigoj (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Mesaĝo ($1)|Mesaĝoj ($1)|100=Mesaĝoj (99+)}}",
"echo-notification-alert-text-only": "Sciigoj",
- "echo-notification-message-text-only": "Mesaĝoj",
+ "echo-notification-notice-text-only": "Sciigoj",
"echo-overlay-link": "Ĉiuj sciigoj",
"echo-overlay-title": "<b>Sciigoj</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Sciigo|Sciigoj}}</b> (montrante $1 de $2 {{PLURAL:$2|nelegita|nelegitaj}})",
@@ -103,17 +150,12 @@
"echo-date-today": "Hodiaŭ",
"echo-date-yesterday": "Hieraŭ",
"echo-load-more-error": "Okazis eraro dum venigo de pliaj rezultoj.",
- "notification-edit-talk-page-bundle": "$1 kaj {{PLURAL:$4|alia uzanto|$3 aliaj uzantoj}} {{GENDER:$1|lasis}} mesaĝon sur via [[User talk:$2|diskutopaĝo]].",
- "notification-page-linked-bundle": "$2 estis {{GENDER:$1|ligita}} de $3 kaj $4 {{PLURAL:$5|plia paĝo|pliaj paĝoj}}. [[Special:WhatLinksHere/$2|Ligiloj ĉi tien]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 kaj {{PLURAL:$3|alia uzanto|$2 aliaj uzantoj}} {{GENDER:$1|lasis}} mesaĝon sur via diskutopaĝo.",
- "notification-page-linked-email-batch-bundle-body": "$2 estis {{GENDER:$1|ligita}} de $3 kaj $4 {{PLURAL:$5|plia paĝo|pliaj paĝoj}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Nova mesaĝo|$1 novaj mesaĝoj|100=pli ol 99 novaj mesaĝoj}} sur <strong>{{GENDER:$3|via}} diskutopaĝo</strong>.",
"echo-email-batch-subject-daily": "Vi havas {{PLURAL:$2|novan sciigon|novajn sciigojn}} sur {{SITENAME}}",
"echo-email-batch-subject-weekly": "Vi ĉisemajne havas {{PLURAL:$2|novan sciigon|novajn sciigojn}} sur {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Saluton $1,\nĈi tie estas resumo de hodiaŭaj aktivaĵoj sur {{SITENAME}} por vi.",
"echo-email-batch-body-intro-weekly": "Saluton $1,\nĈi tie estas resumo de la aktivaĵoj de ĉi tiu semajno sur {{SITENAME}} por vi.",
"echo-email-batch-link-text-view-all-notifications": "Montri ĉiujn sciigojn",
- "echo-rev-deleted-text-view": "Ĉi tiu revizio de la paĝo estis subpremita.",
- "apihelp-echomarkread-description": "Marki sciigojn legitaj por tiu ĉi uzanto.",
- "apihelp-echomarkread-example-2": "Marki ĉiujn sciigojn legitaj",
- "apihelp-query+notifications-description": "Ricevi sciigojn atentantajn por tiu ĉi uzanto."
+ "notification-header-foreign-alert": "Pliaj sciigoj el {{PLURAL:$5|alia vikio|$5 aliaj vikioj}}",
+ "notification-header-foreign-notice": "Pliaj sciigoj el {{PLURAL:$5|alia vikio|$5 aliaj vikioj}}"
}
diff --git a/Echo/i18n/es.json b/Echo/i18n/es.json
index 39b910c0..8e862966 100644
--- a/Echo/i18n/es.json
+++ b/Echo/i18n/es.json
@@ -18,7 +18,17 @@
"Themasterriot",
"Macofe",
"Amitie 10g",
- "Peter Bowman"
+ "Peter Bowman",
+ "Allan Aguilar",
+ "Mgpena",
+ "Ciencia Al Poder",
+ "Lemondoge",
+ "Rubentl134",
+ "2axterix2",
+ "Dgstranz",
+ "Hamilton Abreu",
+ "Matiia",
+ "Javiersanp"
]
},
"echo-desc": "Sistema para notificar a los usuarios sobre eventos y mensajes",
@@ -26,10 +36,12 @@
"prefs-emailsettings": "Opciones de correo electrónico",
"prefs-displaynotifications": "Opciones de visualización",
"prefs-echosubscriptions": "Notificarme sobre estos eventos",
+ "prefs-echocrosswiki": "Notificaciones de varios wikis",
"prefs-newmessageindicator": "Indicador de mensajes nuevos",
+ "prefs-blocknotificationslist": "Usuarios silenciados",
"echo-pref-send-me": "Enviarme:",
"echo-pref-send-to": "Enviar a:",
- "echo-pref-email-format": "Formato del mensaje:",
+ "echo-pref-email-format": "Formato del correo electrónico:",
"echo-pref-web": "Web",
"echo-pref-email": "Correo electrónico",
"echo-pref-email-frequency-never": "No enviarme notificaciones por correo electrónico",
@@ -38,118 +50,169 @@
"echo-pref-email-frequency-weekly": "Resumen semanal de notificaciones",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Texto sin formato",
- "echo-pref-new-message-indicator": "Mostrar un indicador de mensajes nuevos en la barra de herramientas",
+ "echo-pref-cross-wiki-notifications": "Mostrar notificaciones de otros wikis",
+ "echo-pref-notifications-blacklist": "No mostrar notificaciones de estos usuarios. ([[mw:Help:Notifications#mute|más información]])",
+ "echo-pref-new-message-indicator": "Mostrar en la barra de herramientas el indicador de mensajes en mi página de discusión",
+ "echo-pref-beta-feature-cross-wiki-message": "Notificaciones mejoradas",
+ "echo-pref-beta-feature-cross-wiki-description": "Ver y organizar las notificaciones más fácilmente. Incluye las notificaciones entre wikis, que te permite ver los mensajes de otros wikis. (Para recibir notificaciones transwiki en un wiki dado, debes activar la función en pruebas en ese wiki.)",
"echo-learn-more": "Más información",
+ "echo-log": "Registro público",
"echo-new-messages": "Tienes mensajes nuevos",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mensaje|Mensajes}} en la página de discusión",
"echo-category-title-article-linked": "{{PLURAL:$1|Enlace|Enlaces}} de página",
- "echo-category-title-reverted": "{{PLURAL:$1|Reversión de edición|Reversiones de ediciones}}",
+ "echo-category-title-reverted": "{{PLURAL:$1|Reversión|Reversiones}} de edición",
"echo-category-title-mention": "{{PLURAL:$1|Mención|Menciones}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Mención fallida|Menciones fallidas}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Mención exitosa|Menciones exitosas}}",
"echo-category-title-other": "{{PLURAL:$1|Otro|Otros}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Cambio de permisos de usuario|Cambios de permisos de usuarios}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Correo electrónico de otro usuario|Correos electrónicos de otros usuarios}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Recordatorio de páginas|Recordatorios de páginas}}",
"echo-pref-tooltip-edit-user-talk": "Notificarme cuando alguien publique un mensaje o responda en mi página de discusión.",
- "echo-pref-tooltip-article-linked": "Notificarme cuando alguien enlace en un artículo a una página creada por mí.",
+ "echo-pref-tooltip-article-linked": "Notificarme cuando alguien enlace a una página creada a partir de otra página.",
"echo-pref-tooltip-reverted": "Notificarme cuando alguien revierta una edición mía mediante las herramientas de deshacer o revertir.",
- "echo-pref-tooltip-mention": "Notificarme cuando alguien enlace mi página de usuario.",
- "echo-pref-tooltip-user-rights": "Notificarme cuando alguien cambie mis derechos de usuario.",
- "echo-no-agent": "[Nadie]",
- "echo-no-title": "[No hay ninguna página]",
+ "echo-pref-tooltip-mention": "Notificarme cuando alguien enlace mi página de {{GENDER:|usuario|usuaria}}.",
+ "echo-pref-tooltip-mention-failure": "Notificarme cuando no pueda enviar una mención a alguien.",
+ "echo-pref-tooltip-mention-success": "Notificarme cuando envíe una mención a alguien.",
+ "echo-pref-tooltip-user-rights": "Notificarme cuando alguien cambie mis derechos de {{GENDER:|usuario|usuaria}}.",
+ "echo-pref-tooltip-emailuser": "Notificarme cuando alguien me envíe un correo electrónico.",
+ "echo-pref-tooltip-article-reminder": "Notificarme sobre esta página cuando lo solicite.",
"echo-error-no-formatter": "No se definió ningún formato para las notificaciones.",
"notifications": "Notificaciones",
"tooltip-pt-notifications-alert": "{{GENDER:|Tus}} alertas",
- "tooltip-pt-notifications-message": "{{GENDER:|Tus}} mensajes",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Tus}} avisos",
+ "echo-displaynotificationsconfiguration": "Configuración del exhibidor de notificaciones",
+ "echo-displaynotificationsconfiguration-summary": "Este es un resumen de cómo se configuran las notificaciones en este wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notificaciones por categoría",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Clasificación de tipos",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Sección en la que se clasificará cada tipo de notificación",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Métodos de notificación permitidos",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Cuáles métodos de notificación están admitidos para cada categoría",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Cuáles métodos de notificación están admitidos para cada tipo; sólo se aplica a los tipos dentro de las categorías que están ocultos de las preferencias",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Activadas predeterminadamente",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Usuarios existentes",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Usuarios nuevos",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Métodos de notificación requeridos",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Cuáles métodos de notificación son obligatorios para cada categoría",
"echo-specialpage": "Notificaciones",
- "echo-anon": "[$1 Crea una cuenta] o [$2 accede] para recibir notificaciones.",
+ "echo-specialpage-section-markread": "Marcar sección como leída",
+ "echo-specialpage-markasread": "Notificación: marcar como leída",
+ "echo-specialpage-markasread-invalid-id": "Identificador de evento no válido",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notificación|notificaciones}}",
+ "echo-specialpage-pagefilters-title": "Actividad reciente",
+ "echo-specialpage-pagefilters-subtitle": "Páginas con notificaciones sin leer",
+ "notificationsmarkread-legend": "Marcar la notificación como leída",
+ "echo-anon": "Para recibir notificaciones, [$1 regístrate] o [$2 accede a tu cuenta].",
"echo-none": "No tienes notificaciones.",
"echo-more-info": "Más información",
"echo-feedback": "Comentarios",
- "echo-api-failure": "No se pudieron recuperar las notificaciones. Inténtalo de nuevo. (Error $1)",
+ "echo-popup-footer-special-page-invitation": "<strong>Prueba la página rediseñada de notificaciones.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Nuevo aspecto y funcionalidades.",
+ "echo-api-failure": "Error al obtener las notificaciones.",
+ "echo-api-failure-cross-wiki": "Se denegó el acceso al dominio remoto.",
"echo-notification-placeholder": "No hay notificaciones.",
+ "echo-notification-placeholder-filters": "No hay notificaciones que coincidan con estos criterios.",
+ "echo-notification-loginrequired": "Debes iniciar sesión para ver tus notificaciones.",
+ "echo-notification-popup-loginrequired": "Inicia sesión para ver tus notificaciones.",
+ "echo-notification-markasread": "Marcar como leído",
+ "echo-notification-markasunread": "Marcar como no leído",
+ "echo-notification-markasread-tooltip": "Marcar como leí­da",
+ "echo-notification-more-options-tooltip": "Más opciones",
+ "notification-link-text-expand-all": "Expandir",
+ "notification-link-text-expand-alert-count": "Ver {{PLURAL:$1|$1 alerta|$1 alertas}}",
+ "notification-link-text-expand-notice-count": "Ver {{PLURAL:$1|$1 aviso|$1 avisos}}",
+ "notification-link-text-expand-all-count": "Ver {{PLURAL:$1|$1 notificación|$1 notificaciones}}",
+ "notification-link-text-collapse-all": "Contraer",
"notification-link-text-view-message": "Ver mensaje",
"notification-link-text-view-mention": "Ver la mención",
- "notification-link-text-view-changes": "Ver cambios",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Ver mención|Ver menciones}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Ver}} cambios",
"notification-link-text-view-page": "Ver página",
+ "notification-header-edit-user-talk": "$1 te {{GENDER:$2|dejó}} un mensaje en '''{{GENDER:$3|tu}} página de discusión'''.",
+ "notification-header-edit-user-talk-with-section": "$1 te {{GENDER:$2|dejó}} un mensaje en <strong>{{GENDER:$3|tu}} página de discusión</strong> en «<strong>$4</strong>».",
+ "notification-header-page-linked": "Se creó un enlace desde <strong>$4</strong> a <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Enlazado desde <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Se crearon enlaces desde {{PLURAL:$5||$5 páginas|100=más de 99 páginas}} a <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Todos los enlaces a esta página",
+ "notification-header-mention-other": "$1 {{GENDER:$3|te}} ha {{GENDER:$2|mencionado}} en <strong>$4</strong> en el hilo «<strong>$5</strong>».",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|te}} ha {{GENDER:$2|mencionado}} en <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|te}} ha {{GENDER:$2|mencionado}} en la <strong>página de discusión {{GENDER:$5|del usuario|de la usuaria}} $4</strong> en «<strong>$6</strong>».",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|te}} ha {{GENDER:$2|mencionado}} en la '''página de discusión {{GENDER:$5|del usuario|de la usuaria}} $4'''.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|te}} ha {{GENDER:$2|mencionado}} en <strong>{{GENDER:$2|su}} página de discusión</strong> en el hilo «<strong>$4</strong>».",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|te}} ha {{GENDER:$2|mencionado}} en '''{{GENDER:$2|su}} página de discusión'''.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|te}} ha {{GENDER:$2|mencionado}} en la página de discusión de <strong>$4</strong> en el hilo «<strong>$5</strong>».",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|te}} ha {{GENDER:$2|mencionado}} en la página de discusión de <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Tu}} mención de <strong>$3</strong> no se envió porque el usuario no se encontró.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Tu}} mención de <strong>$3</strong> no se envió porque el usuario es anónimo.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Intentaste}} mencionar a más de $3 {{PLURAL:$3|usuario|usuarios}}. No se enviaron las menciones que superaron ese límite.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Una mención|$3 menciones}} que {{GENDER:$2|hiciste}} en la página de discusión de <strong>$4</strong> no se {{PLURAL:$3|pudo|pudieron}} enviar.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>El nombre de usuario no existe:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>No se pueden mencionar IP:</strong> $1",
+ "notification-header-mention-success": "Se ha enviado {{GENDER:$2|tu}} mención a <strong>$3</strong>.",
+ "notification-header-mention-success-bundle": "Se {{PLURAL:$3|ha enviado una mención|han enviado $3 menciones}} que {{GENDER:$2|hiciste}} en la página de discusión de <strong>$4</strong>.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Mencionaste a}}:</strong> $3",
+ "notification-header-mention-status-bundle": "De {{PLURAL:$3|una notificación|$3 notificaciones}} sobre menciones que {{GENDER:$2|hiciste}} en la página de discusión de <strong>$4</strong>, {{PLURAL:$5|1 no se ha|$5 no se han}} enviado y {{PLURAL:$6|1 se ha|$6 se han}} enviado.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Tus}} permisos de usuario han sido {{GENDER:$1|modificados}}. Ahora perteneces a: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Tus}} permisos de usuario han sido {{GENDER:$1|modificados}}. Ya no eres miembro de: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Tus}} permisos de usuario han sido {{GENDER:$1|modificados}}. Ahora perteneces a: $2. Ya no eres miembro de: $4.",
+ "notification-header-welcome": "¡{{GENDER:$2|Bienvenido|Bienvenida}} a {{SITENAME}}, $1! Nos alegra que estés aquí.",
+ "notification-welcome-linktext": "Te damos la bienvenida",
+ "notification-header-thank-you-1-edit": "Acabas de hacer {{GENDER:$2|tu}} primera edición. Gracias y ¡{{GENDER:$2|bienvenido|bienvenida}}!",
+ "notification-header-thank-you-10-edit": "Acabas de hacer {{GENDER:$2|tu}} décima edición. Gracias y ¡sigue así!",
+ "notification-header-thank-you-100-edit": "Acabas de hacer {{GENDER:$2|tu}} centésima edición. ¡Muchas gracias!",
+ "notification-header-thank-you-1000-edit": "Acabas de hacer {{GENDER:$2|tu}} milésima edición. ¡Gracias por ser {{GENDER:$2|un gran colaborador|una gran colaboradora}}!",
+ "notification-header-thank-you-10000-edit": "Acabas de hacer {{GENDER:$2|tu}} edición número diez mil. ¡Muchas gracias!",
+ "notification-header-thank-you-100000-edit": "Acabas de hacer {{GENDER:$2|tu}} edición número cien mil. ¡Muchas gracias por tu increíble contribución!",
+ "notification-header-thank-you-1000000-edit": "Acabas de hacer {{GENDER:$2|tu}} millonésima edición. ¡Gracias por tu asombrosa contribución!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Tu}} edición",
"notification-link-text-view-edit": "Ver edición",
- "notification-edit-talk-page2": "[[User:$1|$1]] te ha dejado un mensaje en tu [[User talk:$2#$3|página de discusión]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] te ha dejado un mensaje en tu página de discusión: «[[User talk:$2#$3|$4]]».",
- "notification-edit-talk-page-flyout2": "$1 te ha dejado un mensaje en tu [[User talk:$2#$3|página de discusión]].",
- "notification-edit-talk-page-flyout-with-section": "$1 te ha dejado un mensaje en tu página de discusión: «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "[[:$2]] se ha {{GENDER:$1|enlazado}} desde [[:$3]]. [[Special:WhatLinksHere/$2|Ver todos los enlaces a esta página]].",
- "notification-page-linked-flyout": "[[:$2]] se ha {{GENDER:$1|enlazado}} desde [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|comentó}} en la sección \"[[$3|$2]]\" de la página de discusión de \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] inició un nuevo hilo, \"$2\", en [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|te envió}} un mensaje: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|comentó}} \"[[$3#$2|$2]]\" en tu página de discusión.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|te mencionó}} en la página de discusión de $5 en \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|te mencionó}} en la página de discusión de $5 en \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] te ha mencionado en la [[:$3|página de discusión de $2]].",
- "notification-mention-nosection-flyout": "$1 te ha {{GENDER:$1|mencionado}} en la [[:$3|$2 página de discusión]].",
- "notification-user-rights": "Tus permisos de usuario [[Special:Log/rights/$1|han sido {{GENDER:$1|modificados}}]] por [[User:$1|$1]]. $2. [[Special:ListGroupRights|Ver más]]",
- "notification-user-rights-flyout": "Tus permisos de usuario {{GENDER:$1|han sido modificados}} por $1. $2. [[Special:ListGroupRights|Ver más]]",
- "notification-user-rights-add": "Ahora eres miembro de {{PLURAL:$2|este grupo|estos grupos}}: $1",
- "notification-user-rights-remove": "Has dejado de pertenecer {{PLURAL:$2|al siguiente grupo|a los siguientes grupos}}: $1",
- "notification-new-user": "¡Te damos la bienvenida a {{SITENAME}}, $1! Nos alegra que estés aquí.",
- "notification-reverted2": "{{PLURAL:$4|Tu edición en [[:$2]] ha sido revertida|Tus ediciones en [[:$2]] han sido revertidas}} por [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Tu edición en $2 ha sido revertida|Tus ediciones en $2 han sido revertidas}} por $1. $3",
+ "notification-link-article-reminder": "Ver página",
+ "notification-header-reverted": "{{PLURAL:$4|Tu edición en <strong>$3</strong> fue {{GENDER:$2|revertida}}|Tus ediciones en <strong>$3</strong> fueron {{GENDER:$2|revertidas}}}}.",
+ "notification-header-emailuser": "$1 te ha {{GENDER:$2|enviado}} un correo electrónico.",
"notification-edit-talk-page-email-subject2": "$1 te ha {{GENDER:$1|dejado}} un mensaje en {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 te ha {{GENDER:$1|dejado}} un mensaje en tu página de discusión.",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 te ha dejado un mensaje en tu página de discusión: «$2»",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 te {{GENDER:$1|ha dejado}} un mensaje en tu página de discusión sobre «$2».",
"notification-page-linked-email-subject": "Se ha enlazado una página creada por ti en {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 se ha {{GENDER:$1|enlazado}} desde $3.",
- "notification-reverted-email-subject2": "{{PLURAL:$3|Tu edición fue {{GENDER:$1|revertida}}|Tus ediciones fueron revertidas}} en {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Tu edición en $2 ha sido {{GENDER:$1|revertida}}|Tus ediciones en $2 han sido revertidas}} por $1.",
- "notification-mention-email-subject": "$1 te ha {{GENDER:$1|mencionado}} en {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 te ha {{GENDER:$1|mencionado}} en la página de discusión de $4, en \"$3\"",
- "notification-mention-nosection-email-batch-body": "$1 te ha mencionado en la página de discusión de $2.",
+ "notification-reverted-email-subject2": "{{PLURAL:$3|Tu edición fue {{GENDER:$1|revertida}}|Tus ediciones fueron {{GENDER:$1|revertidas}}}} en {{SITENAME}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|te}} ha {{GENDER:$1|mencionado}} en {{SITENAME}}",
"notification-user-rights-email-subject": "Tus permisos de usuario en {{SITENAME}} han sido modificados.",
- "notification-user-rights-email-batch-body": "Tus permisos de usuario fueron {{GENDER:$1|modificados}} por $1. $2.",
- "echo-email-subject-default": "Nueva notificación en {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mes|$1 meses}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 año|$1 años}}",
+ "notification-timestamp-today": "Hoy",
+ "notification-timestamp-yesterday": "Ayer",
+ "notification-inbox-filter-read": "Leídas",
+ "notification-inbox-filter-unread": "No leídas",
+ "notification-inbox-filter-all": "Todas",
"echo-email-body-default": "Tienes una nueva notificación en {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Tienes una notificación nueva.",
- "echo-email-footer-default": "$2\n\nPara controlar los emails que te enviamos, visita:\n{{canonicalurl:{{#Especial:Preferencias}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Para controlar los emails que te enviamos, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">verifica tus preferencias</a>.<br />\n$1",
+ "echo-email-footer-default-html": "Para controlar cuáles correos electrónicos te enviamos, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">revisa tus preferencias</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPara controlar cuáles correos electrónicos te enviamos, revisa tus preferencias:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Para controlar cuáles correos electrónicos {{GENDER:$1|te}} enviamos, revisa {{GENDER:$1|tus}} preferencias:",
+ "echo-email-html-footer-preference-link-text": "revisa {{GENDER:$1|tus}} preferencias",
+ "echo-email-html-footer-with-link": "Para controlar qué correos electrónicos {{GENDER:$2|te}} enviamos, $1.",
"echo-notification-alert": "{{PLURAL:$1|Alerta ($1)|Alertas ($1)|100=Alertas (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Mensaje ($1)|Mensajes ($1)|100=Mensajes (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Aviso ($1)|Avisos ($1)|100=Avisos (99+)}}",
"echo-notification-alert-text-only": "Alertas",
- "echo-notification-message-text-only": "Mensajes",
+ "echo-notification-notice-text-only": "Avisos",
"echo-overlay-link": "Todas las notificaciones",
"echo-overlay-title": "<b>Notificaciones</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificación|Notificaciones}}</b> (se muestran $1 de $2 sin leer)",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificación|Notificaciones}}</b> (se {{PLURAL:$1|muestra|muestran}} $1 de $2 sin leer)",
"echo-mark-all-as-read": "Marcar todo como leído",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notificación marcada como leída|notificaciones marcadas como leídas}}",
+ "echo-mark-wiki-as-read": "Marcar como leídas todas las notificaciones del wiki seleccionado: $1",
"echo-date-today": "Hoy",
"echo-date-yesterday": "Ayer",
"echo-load-more-error": "Se ha producido un error al intentar obtener más resultados.",
- "notification-edit-talk-page-bundle": "$1 y $3 {{PLURAL:$4|usuario|usuarios}} más han escrito en tu [[User talk:$2|página de discusión]].",
- "notification-page-linked-bundle": "$2 fue {{GENDER:$1|enlazado|enlazada|enlazado}} desde $3 y $4 {{PLURAL:$5|página|páginas}} más. [[Special:WhatLinksHere/$2|Mira todos los enlaces a esta página]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 y $2 {{PLURAL:$3|usuario|usuarios}} más {{GENDER:$1|han escrito}} en tu página de discusión.",
- "notification-page-linked-email-batch-bundle-body": "$2 fue {{GENDER:$1|enlazada}} desde $3 y $4 {{PLURAL:$5|página|páginas}} más.",
- "echo-email-batch-subject-daily": "Tienes {{PLURAL:$2|una notificación nueva|notificaciones nuevas}} en {{SITENAME}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Un mensaje nuevo|$1 mensajes nuevos|100=99+ mensajes nuevos}} en <strong>{{GENDER:$3|tu}} página de discusión</strong>.",
+ "echo-email-batch-subject-daily": "Tienes {{PLURAL:$2|una nueva notificación|nuevas notificaciones}} en {{SITENAME}}",
"echo-email-batch-subject-weekly": "Tienes {{PLURAL:$2|una nueva notificación|nuevas notificaciones}} en {{SITENAME}} esta semana",
- "echo-email-batch-body-intro-daily": "Hola, $1:\nAquí está un resumen de la actividad de hoy en {{SITENAME}}.",
- "echo-email-batch-body-intro-weekly": "Hola, $1:\nAquí está un resumen de la actividad de esta semana en {{SITENAME}}.",
+ "echo-email-batch-body-intro-daily": "Hola, $1:\nAquí tienes un resumen personal de la actividad de hoy en {{SITENAME}}.",
+ "echo-email-batch-body-intro-weekly": "Hola, $1:\nAquí tienes un resumen personal de la actividad de esta semana en {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "Ver todas las notificaciones",
- "echo-rev-deleted-text-view": "Esta revisión de página ha sido suprimida.",
- "apihelp-echomarkread-description": "Marcar notificaciones como leídas para el usuario actual.",
- "apihelp-echomarkread-param-list": "Lista de IDs de notificación para marcar como leído.",
- "apihelp-echomarkread-param-all": "Si se establece, marca todas las notificaciones de un usuario como leídas.",
- "apihelp-echomarkread-param-sections": "Lista de secciones a marcar como leídas.",
- "apihelp-echomarkread-example-1": "Marca la notificación 8 como leída.",
- "apihelp-echomarkread-example-2": "Marca todas las notificaciones como leídas.",
- "apihelp-echomarkseen-description": "Marcar las notificaciones como leídas para el usuario actual.",
- "apihelp-echomarkseen-example-1": "Marcar las notificaciones de todos los tipos como leídas",
- "apihelp-echomarkseen-param-type": "Tipo de notificaciones para marcar como leídas: 'alert' (alerta), 'message' (mensaje) or 'all (todas)'.",
- "apihelp-query+notifications-description": "Recibe notificaciones de espera para el usuario actual.",
- "apihelp-query+notifications-param-prop": "Detalles que solicitar.",
- "apihelp-query+notifications-param-sections": "Las secciones de notificación que consultar (o sea, alguna combinación de 'alert' y 'message').",
- "apihelp-query+notifications-param-groupbysection": "Si se agrupan los resultados por sección. Cada sección se obtiene por separado si así se establece.",
- "apihelp-query+notifications-param-format": "Si se especifica, las notificaciones se recibirán en éste formatdo.",
- "apihelp-query+notifications-param-limit": "Número máximo de notificaciones a recibir.",
- "apihelp-query+notifications-param-index": "Si se especifica, se recibirá una lista de IDs de notificación.",
- "apihelp-query+notifications-param-alertcontinue": "Cuando están disponibles alertas adicionales, utilice esta opción para continuar.",
- "apihelp-query+notifications-param-alertunreadfirst": "Muestra las notificaciones de mensajes sin leer primero.",
- "apihelp-query+notifications-param-messagecontinue": "Cuando nuevos mensajes están disponibles, utilice esta opción para continuar.",
- "apihelp-query+notifications-param-messageunreadfirst": "Muestra las notificaciones de alertas sin leer primero.",
- "apihelp-query+notifications-example-1": "Lista de notificaciones",
- "apihelp-query+notifications-example-2": "Lista de notificaciones, agrupadas por sección, incluyendo contadores."
+ "notification-header-foreign-alert": "Más alertas de {{PLURAL:$5|otra wiki|otras $5 wikis}}",
+ "notification-header-foreign-notice": "Más avisos de {{PLURAL:$5|otra wiki|otras $5 wikis}}",
+ "notification-header-foreign-all": "Más notificaciones de {{PLURAL:$5|otra wiki|otras $5 wikis}}"
}
diff --git a/Echo/i18n/et.json b/Echo/i18n/et.json
index b81fd4b7..4a068d5e 100644
--- a/Echo/i18n/et.json
+++ b/Echo/i18n/et.json
@@ -3,7 +3,10 @@
"authors": [
"Avjoska",
"Kyng",
- "Pikne"
+ "Pikne",
+ "Игорь Бродский",
+ "Macofe",
+ "Cumbril"
]
},
"echo-desc": "Süsteem, millega teavitatakse kasutajaid sündmustest ja sõnumitest",
@@ -11,7 +14,9 @@
"prefs-emailsettings": "E-posti suvandid",
"prefs-displaynotifications": "Kuvaseaded",
"prefs-echosubscriptions": "Teavita mind neist sündmustest",
+ "prefs-echocrosswiki": "Vikideülesed teavitused",
"prefs-newmessageindicator": "Uue sõnumi indikaator",
+ "prefs-blocknotificationslist": "Vaigistatud kasutajad",
"echo-pref-send-me": "Saada mulle:",
"echo-pref-send-to": "Saada aadressile:",
"echo-pref-email-format": "E-posti vorming:",
@@ -23,6 +28,8 @@
"echo-pref-email-frequency-weekly": "Teavituste nädalakokkuvõte",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Lihttekst",
+ "echo-pref-cross-wiki-notifications": "Näita teavitusi teistest vikidest",
+ "echo-pref-notifications-blacklist": "Neilt kasutajatelt teavitusi ei näidata. ([[mw:Help:Notifications#mute|lisateave]])",
"echo-pref-new-message-indicator": "Näita arutelulehekülje postituste indikaatorit minu tööriistaribal",
"echo-learn-more": "Lisateave",
"echo-new-messages": "Sulle on uusi sõnumeid",
@@ -30,111 +37,123 @@
"echo-category-title-article-linked": "{{PLURAL:$1|Leheküljelink|Leheküljelingid}}",
"echo-category-title-reverted": "Tühistatud {{PLURAL:$1|muudatus|muudatused}}",
"echo-category-title-mention": "{{PLURAL:$1|Mainimine|Mainimised}}",
+ "echo-category-title-mention-failure": "Nurjunud {{PLURAL:$1|mainimine|mainimised}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Edukas mainimine|Edukad mainimised}}",
"echo-category-title-other": "{{PLURAL:$1|Muu}}",
"echo-category-title-system": "{{PLURAL:$1|Süsteem}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Kasutajaõiguste muutmine|Kasutajaõiguste muutmised}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-kiri teiselt kasutajalt|E-kiri teistelt kasutajatelt}}",
"echo-pref-tooltip-edit-user-talk": "Teavita mind, kui keegi postitab või vastab minu aruteluleheküljel.",
- "echo-pref-tooltip-article-linked": "Teavita mind, kui keegi lingib mõnest artiklist minu alustatud leheküljele.",
+ "echo-pref-tooltip-article-linked": "Teavita mind, kui keegi lingib teiselt leheküljelt minu alustatud leheküljele.",
"echo-pref-tooltip-reverted": "Teavita mind, kui keegi tühistab minu muudatuse, kasutades eemaldus- või tühistusfunktsiooni.",
"echo-pref-tooltip-mention": "Teavita mind, kui keegi lingib minu kasutajaleheküljele.",
+ "echo-pref-tooltip-mention-failure": "Teavita mind, kui mul ei õnnestunud kellelegi mainimist saata.",
+ "echo-pref-tooltip-mention-success": "Teavita mind, kui saadan kellelegi mainimise.",
"echo-pref-tooltip-user-rights": "Teavita mind, kui keegi muudab minu kasutajaõigusi.",
- "echo-no-agent": "[Eikeegi]",
- "echo-no-title": "[Lehekülge pole]",
+ "echo-pref-tooltip-emailuser": "Teavita mind, kui keegi saadab mulle e-kirja.",
"echo-error-no-formatter": "Teavituse vormindusviis on määramata.",
"notifications": "Teavitused",
"tooltip-pt-notifications-alert": "Sinu märguanded",
- "tooltip-pt-notifications-message": "{{GENDER:|Sinu}} sõnumid",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Sinu}} märkused",
"echo-specialpage": "Teavitused",
+ "echo-specialpage-section-markread": "Märgi rühm loetuks",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|Üks teavitus|$1 teavitust}}",
+ "echo-specialpage-pagination-range": "$1–$2",
+ "echo-specialpage-pagefilters-title": "Viimased teavitused",
+ "echo-specialpage-pagefilters-subtitle": "Lugemata teavitustega leheküljed",
"echo-anon": "Et teavitusi saada, [$1 loo konto] või [$2 logi sisse].",
"echo-none": "Sul pole uusi teavitusi.",
"echo-more-info": "Lisateave",
"echo-feedback": "Tagasiside",
- "echo-api-failure": "Teavitusi ei õnnestunud hankida. Palun proovi uuesti. (Tõrge $1)",
+ "echo-api-failure": "Teavitusi ei õnnestunud hankida.",
"echo-notification-placeholder": "Teavitused puuduvad.",
+ "echo-notification-placeholder-filters": "Neile kriteeriumitele vastavad teavitused puuduvad.",
+ "echo-notification-loginrequired": "Teavituste nägemiseks pead sisse logima.",
+ "echo-notification-markasread": "Märgi loetuks",
+ "echo-notification-markasunread": "Märgi lugemata teavituseks",
+ "echo-notification-markasread-tooltip": "Märgi loetuks",
+ "echo-notification-more-options-tooltip": "Veel valikuid",
+ "notification-link-text-expand-all": "Näita",
+ "notification-link-text-expand-alert-count": "Vaata {{PLURAL:$1|üht|$1}} märguannet",
+ "notification-link-text-expand-notice-count": "Vaata {{PLURAL:$1|üht|$1}} märkust",
+ "notification-link-text-expand-all-count": "Vaata {{PLURAL:$1|üht|$1}} teavitust",
+ "notification-link-text-collapse-all": "Peida",
"notification-link-text-view-message": "Vaata sõnumit",
"notification-link-text-view-mention": "Vaata mainimist",
- "notification-link-text-view-changes": "Vaata muudatusi",
+ "notification-link-text-view-changes": "{{GENDER:$1|Vaata}} muudatusi",
"notification-link-text-view-page": "Vaata lehekülge",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|jättis}} sõnumi <strong>{{GENDER:$3|sinu}} aruteluleheküljele</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|jättis}} sõnumi <strong>{{GENDER:$3|sinu}} arutelulehekülje</strong> alaosasse \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "Leheküljele \"<strong>$3</strong>\" lingiti asukohast \"<strong>$4</strong>\".",
+ "notification-bundle-header-page-linked": "Leheküljele \"<strong>$3</strong>\" lingiti {{PLURAL:$5||$5 leheküljelt|100=rohkem kui 99 leheküljelt}}.",
+ "notification-link-text-what-links-here": "Kõiki lingid sellele leheküljele",
+ "notification-header-mention-other": "$1 {{GENDER:$2|mainis}} {{GENDER:$3|sind}} lehekülje \"<strong>$4</strong>\" alaosas \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|mainis}} {{GENDER:$3|sind}} leheküljel \"<strong>$4</strong>\".",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|mainis}} {{GENDER:$3|sind}} <strong>{{GENDER:$5|kasutaja}} $4 arutelulehekülje</strong> alaosas \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|mainis}} {{GENDER:$3|sind}} <strong>{{GENDER:$5|kasutaja}} $4 aruteluleheküljel</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|mainis}} {{GENDER:$3|sind}} <strong>{{GENDER:$2|oma}} arutelulehekülje</strong> alaosas \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|mainis}} {{GENDER:$3|sind}} <strong>{{GENDER:$2|oma}} aruteluleheküljel</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|mainis}} {{GENDER:$3|sind}} lehekülje \"<strong>$4</strong>\" arutelu alaosas \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|mainis}} {{GENDER:$3|sind}} lehekülje \"<strong>$4</strong>\" arutelus.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Sinu}} kasutajaõigusi {{GENDER:$1|muudeti}}. Sind lisati rühma: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Sinu}} kasutajaõigusi {{GENDER:$1|muudeti}}. Sa ei kuulu enam rühma: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Sinu}} kasutajaõigused {{GENDER:$1|muudeti}}. Kuulud nüüd järgmistesse rühmadesse: $2. Sa ei kuulu enam järgmistesse rühmadesse: $4.",
+ "notification-header-user-rights-expiry-change": "{{GENDER:$4|Sinu}} liikmesuse aegumistähtaeg {{PLURAL:$3|järgmises rühmas|järgmistes rühmades}} on {{GENDER:$1|muudetud}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Tere}} tulemast saidile {{SITENAME}}, $1! Meil on hea meel, et siin oled.",
+ "notification-welcome-linktext": "Tere tulemast",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Tegid}} just esimese muudatuse. Aitäh ja tere tulemast!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Tegid}} just oma kümnenda muudatuse. Aitäh ja jõudu!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Tegid}} just oma sajanda muudatuse. Suur tänu!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Tegid}} just oma tuhandenda muudatuse. Aitäh, et oled viljakas kaastööline!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Tegid}} just oma kümnetuhandenda muudatuse. Suur-suur tänu!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Tegid}} just oma sajatuhandenda muudatuse. Aitäh tohutu kaastöö eest!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Tegid}} just oma miljonenda muudatuse. Aitäh imetlusväärse kaastöö eest!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Sinu}} muudatus",
"notification-link-text-view-edit": "Vaata muudatust",
- "notification-edit-talk-page2": "[[User:$1|$1]] jättis sõnumi sinu [[User talk:$2#$3|aruteluleheküljele]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] jättis sõnumi sinu arutelulehekülje alaosasse \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 jättis sõnumi sinu [[User talk:$2#$3|aruteluleheküljele]].",
- "notification-edit-talk-page-flyout-with-section": "$1 jättis sõnumi sinu arutelulehekülje alaosasse \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Leheküljele [[:$2]] {{GENDER:$1|lingiti}} asukohast [[:$3]]. [[Special:WhatLinksHere/$2|Vaata kõiki linke sellele leheküljele]].",
- "notification-page-linked-flyout": "Leheküljele [[:$2]] {{GENDER:$1|lingiti}} asukohast [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] lisas kommentaari lehekülje \"$4\" arutelu alaosasse \"[[$3|$2]]\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|postitas}} uue teema \"$2\" arutellu [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|saatis}} sulle sõnumi: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] lisas kommentaari sinu arutelulehekülje alaosasse \"[[$3#$2|$2]]\".",
- "notification-mention": "[[User:$1|$1]] mainis sind lehekülje \"$5\" arutelu alaosas \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 mainis sind lehekülje \"$5\" arutelu alaosas \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] mainis sind lehekülje \"$2\" [[:$3|arutelus]].",
- "notification-mention-nosection-flyout": "$1 mainis sind lehekülje \"$2\" [[:$3|arutelus]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|muutis]] sinu kasutajaõigusi. $2. [[Special:ListGroupRights|Lisateave]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|muutis}} sinu kasutajaõigusi. $2. [[Special:ListGroupRights|Lisateave]]",
- "notification-user-rights-add": "Kuulud nüüd {{PLURAL:$2|sellesse rühma|nendesse rühmadesse}}: $1",
- "notification-user-rights-remove": "Sa ei kuulu enam {{PLURAL:$2|sellesse rühma|nendesse rühmadesse}}: $1",
- "notification-new-user": "Tere tulemast saidile {{SITENAME}}, $1! Meil on hea meel, et siin oled.",
- "notification-reverted2": "[[User:$1|$1]] tühistas sinu {{PLURAL:$4|muudatuse|muudatused}} leheküljel [[:$2]]. $3",
- "notification-reverted-flyout2": "$1 tühistas sinu {{PLURAL:$4|muudatuse|muudatused}} leheküljel \"$2\". $3",
+ "notification-header-reverted": "Sinu {{PLURAL:$4|muudatus|muudatused}} leheküljel \"<strong>$3</strong>\" on {{GENDER:$2|tühistatud}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|saatis}} sulle e-kirja.",
"notification-edit-talk-page-email-subject2": "$1 jättis sulle {{GRAMMAR:inessive|{{SITENAME}}}} sõnumi",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|jättis}} sinu aruteluleheküljele sõnumi.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|jättis}} sinu arutelulehele sõnumi \"$2\":",
"notification-page-linked-email-subject": "{{GRAMMAR:inessive|{{SITENAME}}}} lingiti sinu alustatud leheküljele",
- "notification-page-linked-email-batch-body": "Leheküljele \"$2\" {{GENDER:$1|lingiti}} asukohast \"$3\".",
"notification-reverted-email-subject2": "Sinu {{PLURAL:$3|muudatus|muudatused}} {{GRAMMAR:inessive|{{SITENAME}}}} {{GENDER:$1|tühistati}}",
- "notification-reverted-email-batch-body2": "$1 tühistas võrgukohas {{SITENAME}} leheküljel \"$2\" sinu {{PLURAL:$3|muudatuse|muudatused}}",
- "notification-mention-email-subject": "$1 mainis {{GRAMMAR:inessive|{{SITENAME}}}} sind",
- "notification-mention-email-batch-body": "$1 mainis sind lehekülje \"$4\" arutelu alaosas \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 mainis sind lehekülje \"$2\" arutelus.",
+ "notification-mention-email-subject": "$1 mainis {{GRAMMAR:inessive|{{SITENAME}}}} {{GENDER:$2|sind}}",
"notification-user-rights-email-subject": "{{GRAMMAR:inessive|{{SITENAME}}}} muudeti sinu kasutajaõigusi",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|muutis}} sinu kasutajaõigusi. $2.",
- "echo-email-subject-default": "Uus teavitus {{GRAMMAR:inessive|{{SITENAME}}}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 t}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 p}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 k}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 a}}",
+ "notification-timestamp-today": "Täna",
+ "notification-timestamp-yesterday": "Eile",
+ "notification-inbox-filter-read": "Loetud",
+ "notification-inbox-filter-unread": "Lugemata",
+ "notification-inbox-filter-all": "Kõik",
"echo-email-body-default": "Võrgukohas {{SITENAME}} on sulle uus teavitus:\n\n$1",
- "echo-email-batch-body-default": "Sulle on uus teavitus.",
+ "echo-email-footer-default-html": "Et määrata, milliseid kirju sulle saadetakse, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">vaata üle oma eelistused</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nEt valida, milliseid e-kirju sulle saadetakse, sea oma eelistusi:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Et valida, milliseid e-kirju sulle saadetakse, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">sea oma eelistusi</a>.<br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|Üks märguanne|$1 märguannet|0=Märguandeid pole.|100=Üle 99 märguande}}",
- "echo-notification-message": "{{PLURAL:$1|Üks sõnum|$1 sõnumit|0=Sõnumeid pole.|100=Üle 99 sõnumi}}",
+ "echo-email-plain-footer": "Et määrata, milliseid kirju {{GENDER:$1|sulle}} saadetakse, vaata üle oma eelistused:",
+ "echo-email-html-footer-preference-link-text": "vaata üle {{GENDER:$1|oma}} eelistused",
+ "echo-email-html-footer-with-link": "Et määrata, milliseid kirju {{GENDER:$2|sulle}} saadetakse, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Märguanne ($1)|Märguanded ($1)|100=Märguanded (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Märkus ($1)|Märkused ($1)|100=Märkused (99+)}}",
"echo-notification-alert-text-only": "Märguanded",
- "echo-notification-message-text-only": "Sõnumid",
+ "echo-notification-notice-text-only": "Märkused",
"echo-overlay-link": "Kõik teavitused",
"echo-overlay-title": "<b>Teavitused</b>",
"echo-overlay-title-overflow": "<b>Teavitused</b> (näidatakse {{PLURAL:$1|üht|$1}} $2-st lugemata teavitusest)",
"echo-mark-all-as-read": "Märgi kõik loetuks",
+ "echo-mark-all-as-read-confirmation": "{{PLURAL:$1|Üks teavitus|$1 teavitust}} märgitud loetuks.",
"echo-date-today": "Täna",
"echo-date-yesterday": "Eile",
"echo-load-more-error": "Rohkemate tulemuste laadimisel ilmnes tõrge.",
- "notification-edit-talk-page-bundle": "$1 ja veel {{PLURAL:$4|üks kasutaja|$3 kasutajat}} jätsid sõnumi sinu [[User talk:$2|aruteluleheküljele]].",
- "notification-page-linked-bundle": "Leheküljele \"$2\" {{GENDER:$1|lingiti}} asukohast \"$3\" ja veel {{PLURAL:$5|ühelt|$4}} leheküljelt. [[Special:WhatLinksHere/$2|Vaata kõiki linke sellele leheküljele]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 ja veel {{PLURAL:$3|üks kasutaja|$2 kasutajat}} jätsid sõnumi sinu aruteluleheküljele.",
- "notification-page-linked-email-batch-bundle-body": "Leheküljele \"$2\" {{GENDER:$1|lingiti}} asukohast \"$3\" ja veel {{PLURAL:$5|ühelt|$4}} leheküljelt.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Üks uus sõnum|$1 uut sõnumit|100=Üle 99 uue sõnumi}} <strong>{{GENDER:$3|sinu}} aruteluleheküljel</strong>.",
"echo-email-batch-subject-daily": "Sulle on {{GRAMMAR:inessive|{{SITENAME}}}} {{PLURAL:$2|uus teavitus|uusi teavitusi}}",
"echo-email-batch-subject-weekly": "Sulle on sellel nädalal {{GRAMMAR:inessive|{{SITENAME}}}} {{PLURAL:$2|uus teavitus|uusi teavitusi}}",
"echo-email-batch-body-intro-daily": "Tere, $1.\nSiin on sulle kokkuvõte võrgukohas {{SITENAME}} täna toimunust.",
"echo-email-batch-body-intro-weekly": "Tere, $1.\nSiin on sulle kokkuvõte võrgukohas {{SITENAME}} sellel nädalal toimunust.",
"echo-email-batch-link-text-view-all-notifications": "Vaata kõiki teavitusi",
- "echo-rev-deleted-text-view": "Lehekülje see redaktsioon on varjatud.",
- "apihelp-echomarkread-description": "Antud kasutaja teavituste loetuks märkimine.",
- "apihelp-echomarkread-param-list": "Loetelu identifikaatoritest, mida märkida loetuks.",
- "apihelp-echomarkread-param-all": "Kui valitud, märgitakse kõik kasutaja teavitused loetuks.",
- "apihelp-echomarkread-param-sections": "Loetelu jaotistest, mida märkida loetuks.",
- "apihelp-echomarkread-example-1": "Märgi teavitus 8 loetuks",
- "apihelp-echomarkread-example-2": "Märgi kõik teavitused loetuks",
- "apihelp-echomarkseen-description": "Antud kasutaja teavituste nähtuks märkimine.",
- "apihelp-echomarkseen-example-1": "Märgi igat tüüpi teavitused nähtuks",
- "apihelp-echomarkseen-param-type": "Mis tüüpi teavitused märkida nähtuks: 'alert' (märguanne), 'message' (sõnum) või 'all' (kõik).",
- "apihelp-query+notifications-description": "Antud kasutaja tähelepanu ootavate teavituste hankimine.",
- "apihelp-query+notifications-param-prop": "Päringu üksikasjad.",
- "apihelp-query+notifications-param-sections": "Päritav teavituste jaotis (s.o kombinatsioon tüüpidest 'alert' ja 'message').",
- "apihelp-query+notifications-param-groupbysection": "Kas rühmitada tulemus jaotiste kaupa. Kui valitud, tehakse väljavõte iga jaotise kohta eraldi.",
- "apihelp-query+notifications-param-format": "Kui määratud, tagastatakse teavitused sellises vormingus.",
- "apihelp-query+notifications-param-limit": "Tagastatavate teavituste ülemmäär.",
- "apihelp-query+notifications-param-index": "Kui määratud, tagastatakse teavituste identifikaatorite järjestatud loetelu.",
- "apihelp-query+notifications-param-alertcontinue": "Kui tulemustes on saadaval rohkem märguandeid, kasutada seda jätkamiseks.",
- "apihelp-query+notifications-param-alertunreadfirst": "Kas näidata kõigepealt lugemata sõnumeid.",
- "apihelp-query+notifications-param-messagecontinue": "Kui tulemustes on saadaval rohkem sõnumeid, kasutada seda jätkamiseks.",
- "apihelp-query+notifications-param-messageunreadfirst": "Kas näidata kõigepealt lugemata teavitusi.",
- "apihelp-query+notifications-example-1": "Loetle teavitused",
- "apihelp-query+notifications-example-2": "Loetle teavitused jaotiste kaupa üldarvudega"
+ "notification-header-foreign-alert": "Veel märguandeid {{PLURAL:$5|teisest|$5 teisest}} vikist",
+ "notification-header-foreign-notice": "Veel märkusi {{PLURAL:$5|teisest|$5 teisest}} vikist",
+ "notification-header-foreign-all": "Veel teavitusi {{PLURAL:$5|teisest|$5 teisest}} vikist"
}
diff --git a/Echo/i18n/eu.json b/Echo/i18n/eu.json
index c59fae87..46d17724 100644
--- a/Echo/i18n/eu.json
+++ b/Echo/i18n/eu.json
@@ -3,39 +3,124 @@
"authors": [
"Subi",
"Xabier Armendaritz",
- "Sator"
+ "Sator",
+ "Mikel Ibaiba"
]
},
"prefs-echo": "Jakinarazpenak",
"prefs-emailsettings": "E-posta aukerak",
"prefs-displaynotifications": "Aukerak erakutsi",
+ "prefs-echosubscriptions": "Gertaera hauen inguruan jakinarazi nazazue",
+ "prefs-echocrosswiki": "Wikien arteko jakinarazpenak",
+ "prefs-newmessageindicator": "Mezu berriaren adierazlea",
+ "echo-pref-send-me": "Bidali niri:",
+ "echo-pref-send-to": "Honi bidali:",
+ "echo-pref-email-format": "Posta-elektronikoaren formatua:",
"echo-pref-web": "Web",
"echo-pref-email": "Posta elektronikoa",
+ "echo-pref-email-frequency-never": "Ez bidali niri inongo jakinarazpen emailik",
+ "echo-pref-email-frequency-immediately": "Bidali banakako jakinarazpenak hauek heldu ahala",
+ "echo-pref-email-frequency-daily": "Jakinarazpenen eguneroko laburpena",
+ "echo-pref-email-frequency-weekly": "Jakinarazpenen asteroko laburpena",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Testu laua",
+ "echo-pref-cross-wiki-notifications": "Erakutsi beste wikietako jakinarazpenak",
+ "echo-pref-new-message-indicator": "Erakutsi eztabaida orrialdearen mezu adierazlea nire tresna-barran",
+ "echo-pref-beta-feature-cross-wiki-message": "Jakinarazpen hobetuak",
"echo-learn-more": "Gehiago ikasi",
"echo-new-messages": "Mezu berriak dituzu",
- "echo-no-agent": "[Inor ez]",
- "echo-no-title": "[Ez dago orririk]",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|mezu}} eztabaida orrian",
+ "echo-category-title-mention": "{{PLURAL:$1|Aipamen|Aipamenak}}",
+ "echo-category-title-other": "{{PLURAL:$1|Beste}}",
+ "echo-category-title-system": "{{PLURAL:$1|Sistema}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Lankide eskubide aldaketa|Lankide eskubide aldaketak}}",
+ "echo-category-title-article-reminder": "Orrialdea {{PLURAL:$1|reminder|reminders}}",
+ "echo-pref-tooltip-edit-user-talk": "Jakinarazi norbaitek mezu bat nire eztabaida orrian jartzen edo erantzuten duenean.",
+ "echo-pref-tooltip-article-linked": "Jakinarazi norbaitek egin dudan artikulu bati beste orri batetik loturen bat egiten duenean.",
+ "echo-pref-tooltip-reverted": "Jakinarazi norbaitek nire ekarpenen bat desegiten atzera botatzen duenean, desegin edo rollback tresnaren bidez.",
+ "echo-pref-tooltip-mention": "Jakinarazi norbaitek nire lankide orrira lotura egiten duenean.",
+ "echo-pref-tooltip-user-rights": "Jakinarazi norbaitek nire lankide eskubideak aldatzean.",
+ "echo-pref-tooltip-emailuser": "Jakinarazi norbaitek niri email bat bidaltzean.",
+ "echo-pref-tooltip-article-reminder": "Artikulu honen inguruko mezuak jaso eskatzen ditudanean.",
"notifications": "Jakinarazpenak",
- "tooltip-pt-notifications": "Zure jakinarazpenak",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Zure}} alertak",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Zure}} mezuak",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Erabiltzaile berriak",
"echo-specialpage": "Jakinarazpenak",
+ "echo-specialpage-section-markread": "Markatu taldea irakurrita bezala",
+ "echo-specialpage-markasread": "Jakinarazpena: Markatu irakurrita bezala",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|jakinarazpen $1|$1 jakinarazpen}}",
+ "echo-specialpage-pagefilters-title": "Azken jarduerak",
+ "echo-specialpage-pagefilters-subtitle": "Irakurri gabeko jakinarazpenak dituzten orriak",
+ "notificationsmarkread-legend": "Markatu jakinarazpena irakurrita bezala",
+ "echo-anon": "Jakinarazpenak jasotzeko, [$1 kontua sortu] edo[$2 saioa hasi].",
"echo-none": "Ez duzu jakinarazpenik.",
"echo-more-info": "Informazio gehiago",
+ "echo-notification-placeholder": "Ez dago jakinarazpenik.",
+ "echo-notification-placeholder-filters": "Ez dago irizpide horiek betetzen dituen jakinarazpenik.",
+ "echo-notification-markasread": "Markatu irakurritzat",
+ "echo-notification-markasunread": "Markatu irakurri gabekotzat",
+ "echo-notification-markasread-tooltip": "Markatu irakurritzat",
+ "echo-notification-more-options-tooltip": "Aukera gehiago",
+ "notification-link-text-expand-all": "Zabaldu",
+ "notification-link-text-expand-alert-count": "Ikusi {{PLURAL:$1|alerta $1|$1 alertak}}",
+ "notification-link-text-expand-notice-count": "Ikus {{PLURAL:$1|mezua $1|$1 mezu}}",
+ "notification-link-text-collapse-all": "Itxi",
"notification-link-text-view-message": "Ikusi mezua",
"notification-link-text-view-mention": "Ikusi aipamena",
- "notification-link-text-view-changes": "Ikusi aldaketak",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Ikus aipamena|Ikus aipamenak}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Ikusi}} aldaketak",
"notification-link-text-view-page": "Orrialdea ikusi",
- "echo-email-batch-body-default": "Jakinarazpen berri bat daukazu.",
- "echo-notification-message": "{{PLURAL:$1|Mezua ($1)|Mezuak ($1)|100=Mezuak (+99)}}",
+ "notification-header-edit-user-talk": "$1(e)k mezu bat {{GENDER:$2|utzi}} dizu <strong>{{GENDER:$3|zure}} eztabaida orrian</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1(e)k mezu bat {{GENDER:$2|utzi}} dizu <strong>{{GENDER:$3|zure}} eztabaida orrian</strong>, \"<strong>$4</strong>\" atalean.",
+ "notification-header-article-reminder": "Orrialde batek {{GENDER:$2|you}} <strong>$3</strong> gogoraraztea eskatu du.",
+ "notification-header-mention-other": "$1(e)k {{GENDER:$2|aipamena}} egin {{GENDER:$3|dizu}} <strong>$4</strong>(e)an \"<strong>$5</strong>\" harian.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|lankideak}} aipatu {{GENDER:$3|zaitu}} <strong>$4</strong> orrian.",
+ "notification-header-mention-user-talkpage-v2": "$1(e)k {{GENDER:$2|aipamena}} egin {{GENDER:$3|dizu}} <strong>$4{{GENDER:$5|ren}} lankide eztabaida orrian</strong>, \"<strong>$6</strong>\" atalean.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|lankideak}} aipatu {{GENDER:$3|zaitu}} <strong>{{GENDER:$5|}}$4</strong> lankidearen eztabaida orrian.",
+ "notification-header-mention-agent-talkpage": "$1(e)k {{GENDER:$2|aipamena}} egin {{GENDER:$3|dizu}} {{GENDER:$2|bere|beraien}} eztabaida orrian</strong> \"<strong>$4</strong>\" atalean.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|lankideak}} aipatu {{GENDER:$3|zaitu}} <strong>{{GENDER:$2|bere}}</strong> eztabaida orrian.",
+ "notification-header-mention-article-talkpage": "$1(e)k {{GENDER:$2|aipamena}} egin {{GENDER:$3|dizu}} <strong>$4</strong>ren eztabaida orrian \"<strong>$5</strong>\" atalean.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|lankideak}} aipatu {{GENDER:$3|zaitu}} <strong>$4</strong> eztabaida orrian.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Lankide izena ez da existitzen:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IPA ezin dira aipatuak izan:</strong> $1",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2(e)k|Aipamena egin dizu}}:</strong> $3",
+ "notification-welcome-linktext": "Ongi etorri",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Zure}} ehungarren aldaketa egin berri {{GENDER:$2|duzu}}; Mila esker!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Zure}} milagarren edizioa egin berri {{GENDER:$2|duzu}}; eskerrak {{GENDER:$2|zuri}} hain lankide oparoa izateagatik!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Zure}} ehunmilagarren edizioa egin berri {{GENDER:$2|duzu}}; Eskerrak {{GENDER:$2|zuri}} egindako ekarpen itzelagatik!",
+ "notification-link-text-view-edit": "Ikusi aldaketa",
+ "notification-link-article-reminder": "Orrialdea ikusi",
+ "notification-header-emailuser": "$1 lankideak email bat {{GENDER:$2|bidali}} dizu.",
+ "notification-edit-talk-page-email-subject2": "$1(e)k mezu bat {{GENDER:$1|utzi}} dizu {{SITENAME}} gunean",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1(e)k mezu bat {{GENDER:$1|utzi}} dizu zure eztabaida orriko ''$2'' atalean.",
+ "notification-reverted-email-subject2": "Zure {{PLURAL:$3|aldaketa {{GENDER:$1|desegina izan da}}|aldaketak {{GENDER:$1|deseginak izan dira}}}} {{SITENAME}} gunean",
+ "notification-mention-email-subject": "$1(e)k {{GENDER:$1|aipatu}} {{GENDER:$2|zaitu}} {{SITENAME}} gunean",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ord}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 eg}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 hil}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 urt}}",
+ "notification-timestamp-today": "Gaur",
+ "notification-timestamp-yesterday": "Atzo",
+ "notification-inbox-filter-read": "Irakurriak",
+ "notification-inbox-filter-unread": "irakurri gabe",
+ "notification-inbox-filter-all": "Denak",
+ "echo-email-body-default": "Jakinarazpen berri bat duzu {{SITENAME}} gunean:\n\n$1",
+ "echo-notification-alert": "{{PLURAL:$1|Alerta ($1)|($1) Alerta|100=Alerta (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Mezu($1)|($1) mezu|100=Mezuak(99+)}}",
"echo-notification-alert-text-only": "Alertak",
- "echo-notification-message-text-only": "Mezuak",
+ "echo-notification-notice-text-only": "Abisuak",
"echo-overlay-link": "Jakinarazpen guztiak",
"echo-overlay-title": "<b>Jakinarazpenak</b>",
"echo-mark-all-as-read": "Markatu denak irakurritzat",
+ "echo-mark-all-as-read-confirmation": "{{PLURAL:$1|Jakinarazpen $1|$1 jakinarazpen}} irakurriak bezala {{PLURAL:$1|markatua|markatuak}}",
+ "echo-mark-wiki-as-read": "Markatu denak irakurriak bezala aukeratutako wikian:$1",
"echo-date-today": "Gaur",
"echo-date-yesterday": "Atzo",
"echo-email-batch-link-text-view-all-notifications": "Jakinarazpen guztiak ikusi",
- "apihelp-query+notifications-example-1": "Zerrendatu jakinarazpenak",
- "apihelp-query+notifications-example-2": "Zerrendatu jakinarazpenak, atalka antolaturik, kontagailuekin"
+ "notification-header-foreign-alert": "Alerta gehiago {{PLURAL:$5|beste wiki batean|beste $5 wikietan}}",
+ "notification-header-foreign-notice": "Mezu gehiago beste {{PLURAL:$5|wikian|$5 wikietan}}",
+ "notification-header-foreign-all": "Jakinarazpenak beste {{PLURAL:$5|beste wiki batean|beste $5 wikietan}}"
}
diff --git a/Echo/i18n/fa.json b/Echo/i18n/fa.json
index 6eba26c4..a683c861 100644
--- a/Echo/i18n/fa.json
+++ b/Echo/i18n/fa.json
@@ -15,127 +15,207 @@
"Bersam",
"Saeidpourbabak",
"Koroğlu",
- "Calak"
+ "Calak",
+ "Americophile",
+ "Hosseinblue",
+ "Huji",
+ "Arian Ar",
+ "Macofe",
+ "Mahdy Saffar",
+ "4nn1l2"
]
},
- "echo-desc": "سامانهٔ آگاه‌سازی‌ها",
- "prefs-echo": "آگاه‌سازی‌ها",
+ "echo-desc": "سامانهٔ آگاه‌سازی کاربران از رویدادها و پیام‌ها",
+ "prefs-echo": "اعلان‌ها",
"prefs-emailsettings": "تنظیمات ایمیل",
"prefs-displaynotifications": "گزینه‌های نمایش",
"prefs-echosubscriptions": "مرا از این رویدادها آگاه کن",
+ "prefs-echocrosswiki": "آگاه‌سازی همه ویکی‌ها",
"prefs-newmessageindicator": "نشانگر پیام تازه",
+ "prefs-blocknotificationslist": "کاربران خاموش‌شده",
"echo-pref-send-me": "برایم فرستاده شود:",
"echo-pref-send-to": "فرستاده‌شود به:",
"echo-pref-email-format": "قالب ایمیل:",
"echo-pref-web": "وب‌گاه",
"echo-pref-email": "ایمیل",
- "echo-pref-email-frequency-never": "ایمیل اعلان برایم فرستاده نشود",
- "echo-pref-email-frequency-immediately": "آگاه‌سازی‌های جداگانه به محض دریافت",
- "echo-pref-email-frequency-daily": "خلاصهٔ روزانهٔ آگاه‌سازی‌‌ها",
- "echo-pref-email-frequency-weekly": "خلاصهٔ هفتگی از آگاه‌سازی‌ها",
+ "echo-pref-email-frequency-never": "ایمیل اعلان‌ها برایم فرستاده نشود",
+ "echo-pref-email-frequency-immediately": "اعلان‌های جداگانه به محض دریافت",
+ "echo-pref-email-frequency-daily": "خلاصهٔ روزانهٔ اعلان‌ها",
+ "echo-pref-email-frequency-weekly": "خلاصهٔ هفتگی اعلان‌ها",
"echo-pref-email-format-html": "اچ‌تی‌ام‌ال",
"echo-pref-email-format-plain-text": "متن ساده",
- "echo-pref-new-message-indicator": "نمایش نشانگر پیام صفحهٔ بحث در نوار ابزار من",
+ "echo-pref-cross-wiki-notifications": "نمایش آگاه‌سازی از ویکی‌های دیگر",
+ "echo-pref-notifications-blacklist": "عدم نمایش آگاه‌سازی برای این کاربران. [[mw:Help:Notifications#mute|برای اطلاعات بیشتر]]",
+ "echo-pref-new-message-indicator": "نشانگر پیام در صفحهٔ بحث در نوار ابزار من نشان داده شود",
+ "echo-pref-beta-feature-cross-wiki-message": "آگاه‌سازی‌های بهبودیافته",
+ "echo-pref-beta-feature-cross-wiki-description": "آسان‌تر آگاه‌سازی‌ها را ببینید و مدیریت کنید. این ویژگی شامل آگاه‌سازی بین ویکی‌هاست که به شما اجازه می‌دهد پیام آگاه‌سازی از سایر ویکی‌ها هم دریافت کنید. (برای دریافت آگاه‌سازی از سایر ویکی‌ها باید نسخهٔ آزمایشی را در آن ویکی فعال کنید).",
"echo-learn-more": "اطلاعات بیشتر",
+ "echo-log": "سیاهه عمومی",
"echo-new-messages": "پیام‌های جدیدی دارید",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|پیام|پیام‌های}} صفحهٔ بحث",
"echo-category-title-article-linked": "{{PLURAL:$1|پیوند|پیوندهای}} صفحه",
"echo-category-title-reverted": "{{PLURAL:$1|واگردانی|واگردانی‌های}} ویرایش",
- "echo-category-title-mention": "{{PLURAL:$1|اشاره}}",
- "echo-category-title-other": "{{PLURAL:$1|دیگر}}",
+ "echo-category-title-mention": "{{PLURAL:$1|اشاره|اشاره‌ها}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|اشاره|اشاره‌های}} ناموفق",
+ "echo-category-title-mention-success": "{{PLURAL:$1|اشاره|اشاره‌های}} موفق",
+ "echo-category-title-other": "{{PLURAL:$1|سایر}}",
"echo-category-title-system": "{{PLURAL:$1|سامانه}}",
- "echo-category-title-user-rights": "{{PLURAL:$1|تغییر دسترسی کاربر|تغییرات دسترسی کاربر}}",
- "echo-pref-tooltip-edit-user-talk": "هنگامی که کسی برای من پیام فرستاد یا جواب پیام مرا در صفحهٔ بحثم داد، مرا آگاه کن.",
- "echo-pref-tooltip-article-linked": "هنگامی که کسی به مقالهٔ ایجادشده توسط من پیوند داد، مرا آگاه کن.",
- "echo-pref-tooltip-reverted": "هنگامی که کسی ویرایشی را که من انجام داده‌ام را با استفاده از ابزار خثنی‌سازی یا واگردانی، خثنی کرد، مرا آگاه کن.",
- "echo-pref-tooltip-mention": "هنگامی که شخصی به صفحهٔ کاربری من در هر صفحه‌ای پیوند ایجاد کرد، مرا آگاه کن.",
- "echo-pref-tooltip-user-rights": "وقتی کسی دسترسی‌های کاربری من را تغییر داد مرا مطلع کن.",
- "echo-no-agent": "[هیچ کس]",
- "echo-no-title": "[بدون عنوان]",
- "echo-error-no-formatter": "هیچ قالب تعریف‌شده‌ای برای آگاه‌سازی وجود ندارد",
- "notifications": "آگاه‌سازی‌ها",
- "tooltip-pt-notifications-alert": "{{GENDER:|هشدارهای}} شما",
- "tooltip-pt-notifications-message": "{{GENDER:|پیام‌های}} شما",
+ "echo-category-title-user-rights": "{{PLURAL:$1|تغییر دسترسی‌های کاربری|تغییرات دسترسی‌های کاربری}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|ایمیل از کاربری دیگر|ایمیل‌هایی از دیگر کاربران}}",
+ "echo-category-title-article-reminder": "صفحهٔ {{PLURAL:$1|یادآوری|یادآوری}}",
+ "echo-pref-tooltip-edit-user-talk": "وقتی کسی برایم پیام فرستاد یا جواب پیام مرا در صفحهٔ بحثم داد، مرا آگاه کن.",
+ "echo-pref-tooltip-article-linked": "وقتی کسی به صفحه‌ای که ایجاد کرده‌ام پیوند داد، مرا آگاه کن.",
+ "echo-pref-tooltip-reverted": "وقتی کسی ویرایش مرا با ابزار خثنی‌سازی یا واگردانی، خثنی کرد، مرا آگاه کن.",
+ "echo-pref-tooltip-mention": "وقتی کسی به صفحهٔ کاربری‌ام پیوند داد، مرا آگاه کن.",
+ "echo-pref-tooltip-mention-failure": "زمانی که اشاره‌کردن به سایر کاربران با خطا مواجه شد به من اطلاع بده.",
+ "echo-pref-tooltip-mention-success": "زمانی که اشاره‌کردن به سایر کاربران با موفقیت انجام شد به من اطلاع بده.",
+ "echo-pref-tooltip-user-rights": "وقتی کسی دسترسی‌های کاربری من را تغییر داد مرا آگاه کن.",
+ "echo-pref-tooltip-emailuser": "وقتی کسی به من ایمیل فرستاد، مرا آگاه کن.",
+ "echo-pref-tooltip-article-reminder": "زمانی که درخواست دادم، دربارهٔ این صفحه مرا آگاه کن.",
+ "echo-error-no-formatter": "هیچ قالبی برای آگاه‌سازی تعریف نشده‌است.",
+ "notifications": "اعلان‌ها",
+ "tooltip-pt-notifications-alert": "هشدارهای {{GENDER:|شما}}",
+ "tooltip-pt-notifications-notice": "آگاهی‌های {{GENDER:|شما}}",
+ "echo-displaynotificationsconfiguration": "نمایش تنظیمات آگاه‌سازی‌ها",
+ "echo-displaynotificationsconfiguration-summary": "این نگاهی اجمالی است برای مشخص کردن اینکه چگونه آگاه‌سازی‌ها برای این ویکی تنظیم می‌شوند.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "آگاه‌سازی‌ها بر پایه رده",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "مرتب‌کردن نوع‌ها",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "در هر بخش هر دسته آگاه‌سازی مرتب شده‌است",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "روش‌های آگاه‌سازی مجاز",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "روش‌های آگاه‌سازی پشتیبانی شده برای هر رده",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "روش آگاه‌سازیی که توسط افزونه آگاه‌سازی پشتیبانی می‌شود؛ فقط قابل تنظیم برای رده‌های پنهانی‌ست که در ترجیحات تنظیم شده‌اند",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "فعال شده به صورت پیش‌فرض",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "کاربرهای موجود",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "کاربران جدید",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "روش‌های آگاه‌سازی مورد نیاز",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "کدام سبک آگاه‌سازی برای هر رده اجباری‌ست",
"echo-specialpage": "آگاه‌سازی‌ها",
- "echo-anon": "برای دریافت آگاه‌سازی‌ها [$1 حسابی بسازید] یا [$2 وارد سامانه شوید] .",
- "echo-none": "شما هیچگونه آگاه‌سازی‌ای ندارید.",
+ "echo-specialpage-section-markread": "علامت‌زدن گروه به عنوان خوانده شده",
+ "echo-specialpage-markasread": "آگاه‌سازی: انتخاب به عنوان خوانده شده",
+ "echo-specialpage-markasread-invalid-id": "شناسهٔ رویداد نامعتبر",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|آگاه‌سازی|آگاه‌سازی}}",
+ "echo-specialpage-pagefilters-title": "فعالیت‌های اخیر",
+ "echo-specialpage-pagefilters-subtitle": "صفحات دارای آگاه‌سازی‌های خوانده‌نشده",
+ "notificationsmarkread-legend": "علامت زدن آگاه‌سازی به عنوان خوانده شده",
+ "echo-anon": "برای دریافت آگاه‌سازی‌ها [$1 حساب بسازید] یا [$2 وارد سامانه شوید].",
+ "echo-none": "آگاه‌سازی ندارید.",
"echo-more-info": "اطلاعات بیشتر",
"echo-feedback": "بازخورد",
+ "echo-popup-footer-special-page-invitation": "<strong>تلاش برای طراحی مجدد صفحهٔ آگاه‌سازی.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "ظاهر و ویژگی‌های جدید.",
"echo-quotation-marks": "«$1»",
+ "echo-api-failure": "ناتوان از دریافت آگاه‌سازی‌ها.",
+ "echo-api-failure-cross-wiki": "اجازهٔ دسترسی به دامنه دور داده نشد.",
+ "echo-notification-placeholder": "آگاه‌سازی ندارید.",
+ "echo-notification-placeholder-filters": "آگاه‌سازی‌ای در مطابقت با این شرایط وجود ندارد.",
+ "echo-notification-loginrequired": "برای دیدن آگاه‌سازی‌هایتان باید به سامانه وارد شوید.",
+ "echo-notification-popup-loginrequired": "لطفاً برای دیدن آگاه‌سازی‌هایتان به سامانه وارد شوید.",
+ "echo-notification-markasread": "علامت‌گذاری به عنوان خوانده‌شده",
+ "echo-notification-markasunread": "علامت‌گذاری به عنوان خوانده‌نشده",
+ "echo-notification-markasread-tooltip": "علامت‌گذاری به عنوان خوانده‌شده",
+ "echo-notification-more-options-tooltip": "گزینه‌های بیشتر",
+ "notification-dynamic-actions-unwatch": "فعالیت‌های تازه در «$1» را پی‌گیری {{GENDER:$3|نکن}}",
+ "notification-dynamic-actions-unwatch-confirmation": "شما دیگر صفحهٔ «$1» را پی‌گیری {{GENDER:$3|نمی‌کنید}}",
+ "notification-dynamic-actions-unwatch-confirmation-description": "شما می‌توانید هر زمان خواستید [$2 این صفحه] را پی‌گیری {{GENDER:$3|کنید}}",
+ "notification-dynamic-actions-watch": "فعالیت‌های تازه در «$1» را دنبال {{GENDER:$3|کن}}",
+ "notification-dynamic-actions-watch-confirmation": "شما حالا صفحهٔ «$1» پی‌گیری {{GENDER:$3|می‌کنید}}",
+ "notification-dynamic-actions-watch-confirmation-description": "شما می‌توانید هر زمان خواستید پی‌گیری [$2 این صفحه] را متوقف {{GENDER:$3|کنید}}.",
+ "notification-link-text-expand-all": "گسترش",
+ "notification-link-text-expand-alert-count": "دیدن {{PLURAL:$1|$1 هشدار|$1 هشدار}}",
+ "notification-link-text-expand-notice-count": "دیدن {{PLURAL:$1|$1 آگاه‌سازی|$1 آگاه‌سازی}}",
+ "notification-link-text-expand-all-count": "دیدن {{PLURAL:$1|$1 آگاه‌سازی|$1 آگاه‌سازی}}",
+ "notification-link-text-collapse-all": "نهفتن",
"notification-link-text-view-message": "نمایش پیام",
- "notification-link-text-view-mention": "مشاهدهٔ تذکر",
- "notification-link-text-view-changes": "نمایش تغییرات",
- "notification-link-text-view-page": "مشاهدهٔ صفحه",
+ "notification-link-text-view-mention": "نمایش اشاره",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|دیدن اشاره|دیدن اشاره}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|نمایش}} تغییرات",
+ "notification-link-text-view-page": "نمایش صفحه",
+ "notification-header-edit-user-talk": "$1 پیامی بر روی صفحهٔ <strong>بحث {{GENDER:$3|شما}}</strong> {{GENDER:$2|گذاشته‌است}}.",
+ "notification-header-edit-user-talk-with-section": "$1 یک پیام در <strong>بحث {{GENDER:$3|شما}}</strong> در <strong>«$4»</strong> {{GENDER:$2|گذاشته‌است}}.",
+ "notification-header-page-linked": "پیوندی از <strong>$4</strong> به <strong>$3</strong> داده شده‌است.",
+ "notification-compact-header-page-linked": "پیوند داده شده از <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "پیوندهای ایجاد شده از {{PLURAL:$5||$5 صفحه|100=بیش از ۹۹ صفحه}} به <strong>$3</strong>.",
+ "notification-header-article-reminder": "صفحه‌ای که {{GENDER:$2|شما}} برای یادآوری درخواست داده بودید در <strong>$3</strong> است",
+ "notification-link-text-what-links-here": "همهٔ پیوندها به این صفحه",
+ "notification-header-mention-other": "$1 به {{GENDER:$3|شما}} در <strong>$4</strong> در </strong>«$5»</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-mention-other-nosection": "$1 به {{GENDER:$3|شما}} در <strong>$4</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-mention-user-talkpage-v2": "$1 به {{GENDER:$3|شما}} در <strong>صفحهٔ {{GENDER:$5|بحث}} $4</strong> در <strong>«$6»</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-mention-user-talkpage-nosection": "$1 به {{GENDER:$3|شما}} در <strong>صفحهٔ {{GENDER:$5|بحث}} $4</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-mention-agent-talkpage": "$1 به {{GENDER:$3|شما}} در <strong>صفحهٔ {{GENDER:$2|بحثش|بحثش|بحثشان}}</strong> در <strong>«$4»</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 به {{GENDER:$3|شما}} در <strong>صفحهٔ {{GENDER:$2|بحثش|بحثش|بحثشان}}</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-mention-article-talkpage": "$1 به {{GENDER:$3|شما}} در صفحهٔ بحث <strong>$4</strong> در <strong>«$5»</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-mention-article-talkpage-nosection": "$1 به {{GENDER:$3|شما}} در صفحهٔ بحث <strong>$4</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-mention-failure-user-unknown": "اشارهٔ {{GENDER:$2|شما}} برای <strong>$3</strong> ارسال نشد چون کاربر یافت نشد.",
+ "notification-header-mention-failure-user-anonymous": "اشارهٔ {{GENDER:$2|شما}} برای <strong>$3</strong> ارسال نشد چون کاربر گمنام است.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|قصد}} آگاه‌سازی بیش از $3 {{PLURAL:$3|کاربر|کاربر}} را داشتید. همهٔ آگاه‌سازی‌هایی که بیش از آن محدودیت باشند ارسال نمی‌شوند.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|اشاره‌ای|$3 اشاره‌ای}} که {{GENDER:$2|شما}} در بحث <strong>$4</strong> ایجاد کردید {{PLURAL:$3|امکان}} ارسالش وجود ندارد.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>نام کاربری وجود ندارد:</strong>$1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>امکان اشاره به آی‌پی نیست:</strong>$1",
+ "notification-header-mention-success": "اشارهٔ {{GENDER:$2|شما}} به <strong>$3</strong> ارسال شد.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|اشاره‌ای|$3 اشاره‌ای}} که {{GENDER:$2|شما}} در بحث <strong>$4</strong> ایجاد کردید {{PLURAL:$3|ارسال}} شد.",
+ "notification-compact-header-mention-success": "{{GENDER:$2|اشاره کردید به}}: $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|یک آگاه‌سازی|$3 آگاه‌سازی}} دربارهٔ {{PLURAL:$3|اشاره‌ای|اشاره‌هایی}} که در صفحهٔ بحث <strong>$4</strong> {{GENDER:$2|انجام دادید}}: {{PLURAL:$5|$5 مورد فرستاده نشد}}، {{PLURAL:$6|$6 مورد فرستاده شد}}.",
+ "notification-header-user-rights-add-only": "دسترسی {{GENDER:$4|شما}} تغییر {{GENDER:$1|کرده‌است}}. اضافه شدید به: $2.",
+ "notification-header-user-rights-remove-only": "دسترسی {{GENDER:$4|شما}} تغییر {{GENDER:$1|کرده‌است}}. دیگر در $2 عضو نیستید.",
+ "notification-header-user-rights-add-and-remove": "دسترسی {{GENDER:$6|شما}} تغییر {{GENDER:$1|کرده‌است}}. اضافه شدید به: $2. دیگر در $4 عضو نیستید.",
+ "notification-header-user-rights-expiry-change": "انقضای عضویت {{GENDER:$4|شما}} در این {{PLURAL:$3|گروه|گروه‌ها}} تغییر {{GENDER:$1|یافته‌است}}: $2",
+ "notification-header-welcome": "$1، به {{SITENAME}} {{GENDER:$2|خوش آمدید}}. خوشحالیم که {{GENDER:$2|شما}} اینجایید.",
+ "notification-welcome-linktext": "خوش‌آمدید",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|شما}} اولین ویرایشتان را {{GENDER:$2|انجام دادید}}؛ {{GENDER:$2|ممنون}}، خوش‌آمدید!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|شما}} دهمین ویرایشتان را {{GENDER:$2|انجام دادید}}؛ {{GENDER:$2|ممنون}}، لطفاً ادامه دهید!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|شما}} صدمین ویرایشتان را {{GENDER:$2|انجام دادید}}؛ {{GENDER:$2|خیلی ممنون}}!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|شما}} هزارمین ویرایشتان را {{GENDER:$2|انجام دادید}}؛ {{GENDER:$2|ممنون}} از بابت اینکه ویرایشگر بزرگی هستید!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|شما}} ده‌هزارمین ویرایشتان را {{GENDER:$2|انجام دادید}}؛ {{GENDER:$2|خیلی ممنون}}!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|شما}} صد هزارمین ویرایشتان را {{GENDER:$2|انجام دادید}}؛ {{GENDER:$2|ممنون}} از بابت اینکه ویرایشگر بزرگی هستید!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|شما}} یک میلیونمین ویرایشتان را {{GENDER:$2|انجام دادید}}؛ {{GENDER:$2|ممنون}} از بابت اینکه ویرایشگر بزرگی هستید!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|ویرایش}} شما",
"notification-link-text-view-edit": "نمایش ویرایش",
- "notification-edit-talk-page2": "[[User:$1|$1]] در صفحه‌‌ٔ بحث شما [[User talk:$2#$3|پیامی]] گذاشته‌است.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] برای شما در صفحهٔ بحث‌تان در «[[User talk:$2#$3|$4]]» پیامی {{GENDER:$1|گذاشت}}.",
- "notification-edit-talk-page-flyout2": "$1 در صفحه‌‌ٔ‌‌‌ بحث شما [[User talk:$2#$3|مطلبی]] گذاشته‌است.",
- "notification-edit-talk-page-flyout-with-section": "$1 یک پیام در بحث شما در «[[User talk:$2#$3|$4]]» {{GENDER:$1|گذاشته‌است}}.",
- "notification-page-linked": "[[:$2]] از [[:$3]] {{GENDER:$1|پیوند گرفته‌است}}. [[Special:WhatLinksHere/$2|همهٔ پیوندها به این صفحه را ببینید]].",
- "notification-page-linked-flyout": "[[:$2]] از [[:$3]] {{GENDER:$1|پیوند گرفته‌است}}.",
- "notification-add-comment2": "[[User:$1|$1]] در «[[$3|$2]]» در صفحه بحث «$4» نظری افزود.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] بخش جدیدی «$2» در [[$3]] ایجاد کرد.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] به شما پیامی فرستاد: «[[$3#$2|$2]]»",
- "notification-add-comment-yours2": "[[User:$1|$1]] در «[[$3#$2|$2]]» در صفحه بحث شما نظری داده است.",
- "notification-mention": "[[User:$1|$1]] به شما در بحث $5 در «[[:$3#$2|$4]]» {{GENDER:$1|اشاره‌کرد}}.",
- "notification-mention-flyout": "$1 در بحث $5 در «[[:$3#$2|$4]]» به شما {{GENDER:$1|اشاره}} کرده‌است.",
- "notification-mention-nosection": "[[User:$1|$1]] در [[:$3|صفحهٔ بحث $2]] به شما {{GENDER:$1|اشاره}} کرده‌ است.",
- "notification-mention-nosection-flyout": "$1 در [[:$3|صفحهٔ بحث $2]] به شما {{GENDER:$1|اشاره}} کرده است.",
- "notification-user-rights": "دسترسی‌های شما توسط [[User:$1|$1]] [[Special:Log/rights/$1|تغییر یافته است]] . $2. [[Special:ListGroupRights|بیشتر بخوانید]]",
- "notification-user-rights-flyout": "دسترسی‌های شما توسط $1 تغییر یافت. $2. [[Special:ListGroupRights|اطلاعات بیشتر]]",
- "notification-user-rights-add": "شما در حال حاضر عضو {{PLURAL:$2| این گروه|این گروه‌ها}} هستید:$1",
- "notification-user-rights-remove": "شما دیگر عضو {{PLURAL:$2|این گروه|این گروه‌ها}} نیستید: $1",
- "notification-new-user": "به {{SITENAME}} خوش‌آمدید، $1! خوشحالیم که شما اینجا هستید.",
- "notification-reverted2": "ویرایش(های) شما در [[:$2]] توسط [[User:$1|$1]] {{PLURAL:$4|خنثی‌سازی|واگردانی}} شده است. $3",
- "notification-reverted-flyout2": "ویرایش(های) شما بر روی $2 توسط $1 {{PLURAL:$4|خنثی‌سازی|واگردانی}} شده است. $3",
+ "notification-link-article-reminder": "مشاهدهٔ صفحه",
+ "notification-header-reverted": "{{PLURAL:$4|ویرایش شما بر روی <strong>$3</strong>|ویرایش‌های شما بر روی <strong>$3</strong>}} {{GENDER:$2|برگردانده شده‌است.}}",
+ "notification-header-emailuser": "$1 به شما ایمیل {{GENDER:$2|زد}}.",
"notification-edit-talk-page-email-subject2": "شما یک پیام تازه از طرف $1 در صفحهٔ بحث {{SITENAME}} دارید.",
- "notification-edit-talk-page-email-batch-body2": "$1 پیامی بر روی صفحهٔ بحثتان {{GENDER:$1|گذاشته‌است}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 یک پیام در بحث شما در «$2» {{GENDER:$1|گذاشته‌است}}.",
"notification-page-linked-email-subject": "صفحه‌ای که شما آغازگر آن بودید در {{SITENAME}} پیوند شد.",
- "notification-page-linked-email-batch-body": "$2 از $3 {{GENDER:$1|پیوند داده شده‌است}}.",
"notification-reverted-email-subject2": "{{PLURAL:$3|ویرایش|ویرایش‌های}} شما در {{SITENAME}} {{GENDER:$1|واگردانی شده‌است}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|ویرایش|ویرایش‌های}} شما در $2 توسط $1 {{GENDER:$1|واگردانی شده است}}.",
- "notification-mention-email-subject": "$1 شما را در {{SITENAME}} {{GENDER:$1|ذکر کرده‌است}}",
- "notification-mention-email-batch-body": "$1 در $4 صفحهٔ بحث «$3» به شما {{GENDER:$1|اشاره کرد}}",
- "notification-mention-nosection-email-batch-body": "$1 در صفحهٔ بحث $2 به‌ شما {{GENDER:$1|اشاره}} کرده است.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|شما}} را در {{SITENAME}} {{GENDER:$1|ذکر کرده‌است}}",
"notification-user-rights-email-subject": "دسترسی‌های شما در {{SITENAME}} تغییر یافته‌است",
- "notification-user-rights-email-batch-body": "دسترسی‌های شما توسط $1 تغییر یافته‌است. $2",
- "echo-email-subject-default": "آگاه‌سازی‌های تازه در {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 ثانیه}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 دقیقه}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ساعت}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 روز}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 ماه}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 سال}}",
+ "notification-timestamp-today": "امروز",
+ "notification-timestamp-yesterday": "دیروز",
+ "notification-inbox-filter-read": "خوانده‌شده",
+ "notification-inbox-filter-unread": "خوانده‌نشده",
+ "notification-inbox-filter-all": "همه",
"echo-email-body-default": "شما در {{SITENAME}} آگاه‌سازی تازه‌ای دارید:\n\n$1",
- "echo-email-batch-body-default": "شما آگاه‌سازی تازه‌ای دارید.",
+ "echo-email-footer-default-html": "برای تنظیم ایمیلی که برای شما فرستاده شده‌است <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">ترجیحاتتان را بررسی کنید</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nبرای کنترل ایمیل‌های ارسالی به شما، ترجیحات‌تان را بررسی کنید:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "برای کنترل اینکه چه ایمیلی به شما بفرستیم، <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">ترجیحاتتان را بررسی کنید</a>.<br />\n$1",
+ "echo-email-plain-footer": "برای تنظیم ایمیل‌هایی که دریافت {{GENDER:$1|می‌کنید}}، تنظیماتتان را بررسی {{GENDER:$1|کنید}}:",
+ "echo-email-html-footer-preference-link-text": "ترجیحاتتان را بررسی {{GENDER:$1|کنید}}",
+ "echo-email-html-footer-with-link": "برای بررسی ایمیل‌هایی که برای شما ارسال {{GENDER:$2|کردیم}}، $1.",
"echo-notification-alert": "{{PLURAL:$1|هشدارها ($1)|هشدارها ($1)|100=هشدارها (۹۹+)}}",
- "echo-notification-message": "{{PLURAL:$1|پیام‌ها ($1)|پیام‌ها ($1)|100=پیام‌ها (۹۹+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|آگاهی‌ها ($1)|آگاهی‌ها ($1)|100=آگاهی‌ها (۹۹+)}}",
"echo-notification-alert-text-only": "هشدارها",
- "echo-notification-message-text-only": "پیام‌ها",
+ "echo-notification-notice-text-only": "آگاهی‌ها",
"echo-overlay-link": "همهٔ آگاه‌سازی‌ها",
"echo-overlay-title": "<b>آگاه‌سازی‌ها</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|آگاه‌سازی‌ها}}</b> (نمایش $1 از $2 خوانده‌نشده)",
"echo-mark-all-as-read": "نشان‌گذاری همه به عنوان خوانده‌شده",
+ "echo-mark-all-as-read-confirmation": "$1 آگاه‌سازی به عنوان خوانده‌شده علامت {{PLURAL:$1|خورد|خوردند}}",
+ "echo-mark-wiki-as-read": "انتخاب همهٔ موارد در ویکی انتخاب شده به عنوان خوانده شده:$1",
"echo-date-today": "امروز",
"echo-date-yesterday": "دیروز",
"echo-load-more-error": "دریافت نتیجه‌های بیشتر با خطا مواجه شده‌است.",
- "notification-edit-talk-page-bundle": "$1 و $3 {{PLURAL:$4|کاربر دیگر}} در صفحهٔ [[User talk:$2|بحث شما]] پیامی گذاشته‌اند.",
- "notification-page-linked-bundle": "$2 بدست $1 از $3 و $4 {{PLURAL:$5|صفحهٔ دیگر}} پیوند داده شده‌است. [[Special:WhatLinksHere/$2|دیدن همهٔ پیوندها به این صفحه]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 و $2 {{PLURAL:$3|شخص دیگر}} پیامی در صفحهٔ بحث شما گذاشته‌اند.",
- "notification-page-linked-email-batch-bundle-body": "$2 از $3 و $4 {{PLURAL:$5|صفحهٔ دیگر}} {{GENDER:$1|پیوند داده شده‌است}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|یک پیام جدید|$1 پیام جدید|100=بیش از ۹۹ پیام جدید}} جدید در <strong>بحث {{GENDER:$3|شما}}</strong> گذاشته‌شده‌است.",
"echo-email-batch-subject-daily": "شما دارای {{PLURAL:$2|یک آگاه‌سازی تازه|آگاه‌سازی‌های تازه‌ای}} در {{SITENAME}} هستید",
"echo-email-batch-subject-weekly": "شما دارای {{PLURAL:$2|یک آگاه‌سازی تازه|آگاه‌سازی‌های تازه‌ای}} در {{SITENAME}} در این هفته هستید",
"echo-email-batch-body-intro-daily": "سلام $1،\nدر اینجا خلاصهٔ فعالیت امروز شما در {{SITENAME}} وجود دارد.",
"echo-email-batch-body-intro-weekly": "سلام $1،\nدر اینجا خلاصهٔ فعالیت این هفتهٔ شما در {{SITENAME}} وجود دارد.",
"echo-email-batch-link-text-view-all-notifications": "دیدن همهٔ آگاه‌سازی‌ها",
- "echo-rev-deleted-text-view": "بازنگری این صفحه متوقف شده‌است.",
- "apihelp-echomarkread-description": "علامت گذاری به عنوان اطلاعیه خوانده شده برای کاربر فعلی",
- "apihelp-echomarkread-param-list": "فهرستی از شناسه های آگاه سازی به عنوان خوانده شده",
- "apihelp-echomarkread-param-all": "اگر تنظیم شود، تمام پیام های آگاه سازی این کاربر به عنوان خوانده شده علامت میخورد",
- "apihelp-echomarkread-param-sections": "فهرستی از شناسه های آگاه سازی به عنوان خوانده شده",
- "apihelp-echomarkread-example-1": "علامت گذاری 8 اعلان آگاه سازی به عنوان خوانده شده",
- "apihelp-echomarkread-example-2": "علامت‌گذاری تمامی اعلان‌ها به عنوان خوانده شده",
- "apihelp-echomarkseen-description": "علامت گذاری به عنوان اطلاعیه خوانده شده برای کاربر فعلی",
- "apihelp-echomarkseen-example-1": "علامت‌گذاری اعلان‌ها به عنوان خوانده شده",
- "apihelp-query+notifications-description": "دریافت اطلاعیه انتظار برای کاربر فعلی است.",
- "apihelp-query+notifications-param-prop": "جزئیات به درخواست.",
- "apihelp-query+notifications-example-1": "فهرست اعلان‌ها",
- "apihelp-query+notifications-example-2": "فهرست اعلان‌ها، بخش بندیش شده، همراه با شمار آن‌ها."
+ "notification-header-foreign-alert": "هشدارهای بیشتر از {{PLURAL:$5|و ویکی دیگر|و $5 ویکی دیگر}}",
+ "notification-header-foreign-notice": "آگاهی‌های بیشتر از {{PLURAL:$5|ویکی دیگر|$5 ویکی دیگر}}",
+ "notification-header-foreign-all": "آگاه‌سازی‌های بیشتر از $5 ویکی دیگر"
}
diff --git a/Echo/i18n/fi.json b/Echo/i18n/fi.json
index 6294772a..cb2c6150 100644
--- a/Echo/i18n/fi.json
+++ b/Echo/i18n/fi.json
@@ -10,15 +10,20 @@
"Silvonen",
"Stryn",
"VezonThunder",
- "Pitke"
+ "Pitke",
+ "McSalama",
+ "Mikahama",
+ "01miki10"
]
},
- "echo-desc": "Järjestelmä ilmoitusten lähettämiseen käyttäjille",
+ "echo-desc": "Järjestelmä jonka avulla käyttäjille voi lähettää ilmoituksia tapahtumista ja viesteistä",
"prefs-echo": "Ilmoitukset",
"prefs-emailsettings": "Sähköpostiasetukset",
"prefs-displaynotifications": "Näyttöasetukset",
"prefs-echosubscriptions": "Ilmoita minulle näistä tapahtumista",
+ "prefs-echocrosswiki": "Wikienväliset ilmoitukset",
"prefs-newmessageindicator": "Uuden viestin ilmaisin",
+ "prefs-blocknotificationslist": "Estolista",
"echo-pref-send-me": "Lähetä minulle:",
"echo-pref-send-to": "Lähetä osoitteeseen:",
"echo-pref-email-format": "Sähköpostin muoto:",
@@ -30,94 +35,161 @@
"echo-pref-email-frequency-weekly": "Viikottainen yhteenveto ilmoituksista",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Pelkkä teksti",
+ "echo-pref-cross-wiki-notifications": "Näytä ilmoituksia muista wikeistä",
"echo-pref-new-message-indicator": "Näytä keskustelusivujen viestistä erillinen ilmoitus työkalurivilläni",
+ "echo-pref-beta-feature-cross-wiki-message": "Kehittyneet ilmoitukset",
+ "echo-pref-beta-feature-cross-wiki-description": "Tee ilmoitusten katselusta ja järjestämisestä helpompaa. Sisältää wikienväliset ilmoitukset, joiden avulla viestit muissa wikeissä eivät jää huomaamatta. (Saat wikienvälisiä ilmoituksia vain niissä wikeissä, joissa betaominaisuus on käytössä.)",
"echo-learn-more": "Lue lisää aiheesta",
+ "echo-log": "Julkinen loki",
"echo-new-messages": "Sinulle on uusia viestejä",
"echo-category-title-edit-user-talk": "Keskustelusivun {{PLURAL:$1|viesti|viestit}}",
"echo-category-title-article-linked": "{{PLURAL:$1|Sivun linkki|Sivujen linkit}}",
"echo-category-title-reverted": "{{PLURAL:$1|Muokkauksen kumoaminen|Muokkausten kumoamiset}}",
"echo-category-title-mention": "{{PLURAL:$1|Maininta|Maininnat}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Epäonnistunut maininta|Epäonnistuneet maininnat}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Onnistunut maininta|Onnistuneet maininnat}}",
"echo-category-title-other": "{{PLURAL:$1|Muu|Muut}}",
"echo-category-title-system": "{{PLURAL:$1|Järjestelmä}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Käyttöoikeusmuutos|Käyttöoikeusmuutokset}}",
- "echo-pref-tooltip-edit-user-talk": "Ilmoita minulle, kun joku kirjoittaa viestin tai vastaa viestiini keskustelusivullani.",
- "echo-pref-tooltip-article-linked": "Ilmoita minulle, kun joku linkittää luomaani sivuun artikkelisivulta.",
- "echo-pref-tooltip-reverted": "Ilmoita minulle, kun joku kumoaa tekemäni muokkauksen käyttäen kumoa/palauta-työkalua.",
- "echo-pref-tooltip-mention": "Ilmoita minulle, kun joku tekee linkin käyttäjäsivulleni joltakin keskustelusivulta.",
- "echo-pref-tooltip-user-rights": "Ilmoita minulle, kun joku muuttaa käyttöoikeuksiani.",
- "echo-no-agent": "[Ei kukaan]",
- "echo-no-title": "[Ei sivua]",
- "echo-error-no-formatter": "Mitään muotoilua ei ole määritelty tälle ilmoitukselle.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Sähköposti toiselta käyttäjältä|Sähköpostia toisilta käyttäjiltä}}",
+ "echo-pref-tooltip-edit-user-talk": "Ilmoita, kun joku kirjoittaa viestin tai vastaa viestiini keskustelusivullani.",
+ "echo-pref-tooltip-article-linked": "Ilmoita, kun joku linkittää luomaani sivuun toiselta sivulta.",
+ "echo-pref-tooltip-reverted": "Ilmoita, kun joku kumoaa tekemäni muokkauksen käyttäen kumoa- tai palauta-työkalua.",
+ "echo-pref-tooltip-mention": "Ilmoita, kun joku tekee linkin käyttäjäsivulleni.",
+ "echo-pref-tooltip-mention-failure": "Ilmoita minulle, kun mainintaa ei voitu lähettää toiselle käyttäjälle.",
+ "echo-pref-tooltip-mention-success": "Ilmoita minulle, kun maininnan lähettäminen toiselle käyttäjälle onnistui.",
+ "echo-pref-tooltip-user-rights": "Ilmoita, kun joku muuttaa käyttöoikeuksiani.",
+ "echo-pref-tooltip-emailuser": "Ilmoita, kun joku lähettää minulle sähköpostia.",
+ "echo-error-no-formatter": "Tälle ilmoitukselle ei ole määritelty esitystapaa.",
"notifications": "Ilmoitukset",
- "tooltip-pt-notifications-alert": "{{GENDER:|Ilmoituksesi}}",
- "tooltip-pt-notifications-message": "{{GENDER:|Viestisi}}",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Hälytyksesi}}",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Ilmoituksesi}}",
+ "echo-displaynotificationsconfiguration": "Ilmoitusasetusten näyttö",
+ "echo-displaynotificationsconfiguration-summary": "Tässä on yleiskatsaus tämän wikin ilmoitusasetuksista.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Ilmoitukset luokittain",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Ilmoitustyyppien luokittelu",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Mihin osioon mikäkin ilmoitustyyppi kuuluu",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Sallitut ilmoitusmenetelmät",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Sallitut ilmoitusmenetelmät luokittain",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Sallitut ilmoitusmenetelmät luokittain. Koskee vain luokkia, jotka on piilotettu asetuksista",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Käytössä oletuksena",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Nykyiset käyttäjät",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Uudet käyttäjät",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Vaaditut ilmoitusmenetelmät",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Mitkä ilmoitusmenetelmät ovat pakollisia millekin luokalle",
"echo-specialpage": "Ilmoitukset",
+ "echo-specialpage-section-markread": "Merkitse tämä ryhmä luetuksi",
+ "echo-specialpage-markasread": "Ilmoitus: Merkitse luetuksi",
+ "echo-specialpage-markasread-invalid-id": "Virheellinen event ID",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|ilmoitus|ilmoitusta}}",
+ "echo-specialpage-pagefilters-title": "Viimeaikainen toiminta",
+ "echo-specialpage-pagefilters-subtitle": "Lukemattomia ilmoituksia sisältävät sivut",
+ "notificationsmarkread-legend": "Merkitse ilmoitus luetuksi",
"echo-anon": "Jos haluat saada ilmoituksia, [$1 luo käyttäjätunnus] tai [$2 kirjaudu sisään].",
"echo-none": "Sinulla ei ole ilmoituksia.",
"echo-more-info": "Lisätietoja",
"echo-feedback": "Palaute",
+ "echo-popup-footer-special-page-invitation": "<strong>Kokeile uusittua Ilmoitukset-sivua.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Täysin uusi ilme ja uusia ominaisuuksia.",
+ "echo-api-failure": "Ilmoitusten hakeminen epäonnistui.",
+ "echo-api-failure-cross-wiki": "Pääsy etäkoneeseen on estetty.",
+ "echo-notification-placeholder": "Ei ilmoituksia.",
+ "echo-notification-placeholder-filters": "Ei hakua vastaavia ilmoituksia.",
+ "echo-notification-loginrequired": "Näet ilmoitukset kirjautumalla sisään.",
+ "echo-notification-popup-loginrequired": "Näe ilmoitukset kirjautumalla sisään.",
+ "echo-notification-markasread": "Merkitse luetuksi",
+ "echo-notification-markasunread": "Merkitse lukemattomaksi",
+ "echo-notification-markasread-tooltip": "Merkitse luetuksi",
+ "echo-notification-more-options-tooltip": "Lisää valintoja",
+ "notification-link-text-expand-all": "Laajenna",
+ "notification-link-text-expand-alert-count": "Näytä {{PLURAL:$1|$1 hälytys|$1 hälytystä}}",
+ "notification-link-text-expand-notice-count": "Näytä {{PLURAL:$1|$1 ilmoitus|$1 ilmoitusta}}",
+ "notification-link-text-expand-all-count": "Näytä {{PLURAL:$1|$1 ilmoitus|$1 ilmoitusta}}",
+ "notification-link-text-collapse-all": "Supista",
"notification-link-text-view-message": "Näytä viesti",
"notification-link-text-view-mention": "Näytä maininta",
- "notification-link-text-view-changes": "Näytä muutokset",
+ "notification-link-text-view-mention-failure": "Näytä {{PLURAL:$1|maininta|maininnat}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Näytä}} muutokset",
"notification-link-text-view-page": "Näytä sivu",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|jätti}} viestin <strong>{{GENDER:$3|keskustelusivullesi}}</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|jätti}} viestin <strong>{{GENDER:$3|keskustelusivullesi}}</strong> osioon <strong>$4</strong>.",
+ "notification-header-page-linked": "Sivulle <strong>$4</strong> lisättiin linkki sivulle <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Linkitetty sivulta <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Sivulle <strong>$3</strong> on tehty linkkejä {{PLURAL:$5||$5 muusta sivusta|100=99+ muusta sivusta}}.",
+ "notification-link-text-what-links-here": "Kaikki tälle sivulle johtavat linkit",
+ "notification-header-mention-other": "$1 {{GENDER:$2|mainitsi}} {{GENDER:$3|sinut}} sivulla <strong>$4</strong> osiossa <strong>$5</strong>.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|mainitsi}} {{GENDER:$3|sinut}} sivulla <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|mainitsi}} {{GENDER:$3|sinut}} <strong>{{GENDER:$5|käyttäjän}} $4 keskustelusivulla</strong> osiossa <strong>$6</strong>.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|mainitsi}} {{GENDER:$3|sinut}} <strong>{{GENDER:$5|käyttäjän}} $4 keskustelusivulla</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|mainitsi}} {{GENDER:$3|sinut}} <strong>{{GENDER:$2|keskustelusivullansa}}</strong> osiossa <strong>$4</strong>.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|mainitsi}} {{GENDER:$3|sinut}} <strong>{{GENDER:$2|keskustelusivullansa}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|mainitsi}} {{GENDER:$3|sinut}} sivun <strong>$4</strong> keskustelusivulla osiossa <strong>$5</strong>.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|mainitsi}} {{GENDER:$3|sinut}} sivun <strong>$4</strong> keskustelusivulla.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Mainintaasi}} käyttäjästä <strong>$3</strong> ei lähetetty, koska käyttäjää ei löydetty.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Mainintaasi}} käyttäjästä <strong>$3</strong> ei lähetetty, koska tunnus on rekisteröimätön.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Yritit}} mainita enemmän kuin $3 {{PLURAL:$3|tunnuksen|tunnusta}}. Kyseisen rajan ylittäneitä mainintoja ei lähetetty.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Maininta, jonka|$3 mainintaa, jotka}} {{GENDER:$2|teit}} keskustelusivulla <strong>$4</strong> ei voitu lähettää.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Tunnus ei ole olemassa:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-osoitetta ei voi mainita:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Tekemäsi}} maininta käyttäjästä <strong>$3</strong> on lähetetty.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Maininta, jonka|$3 mainintaa, jotka}} {{GENDER:$2|teit}} keskustelusivulla <strong>$4</strong> {{PLURAL:$3|lähetettiin}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Mainitsit}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Maininta|$3 mainintaa}} maininnoista, jotka {{GENDER:$2|teit}} keskustelusivulla <strong>$4</strong>: {{PLURAL:$5|$5 ei lähetetty}}, {{PLURAL:$6|$6 lähetetty}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Sinun}} käyttöoikeuksiasi on {{GENDER:$1|muutettu}}. Sinut on lisätty ryhmään: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Sinun}} käyttöoikeuksiasi on {{GENDER:$1|muutettu}}. Sinut on poistettu ryhmistä: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Sinun}} käyttöoikeuksiasi on {{GENDER:$1|muutettu}}. Sinut on lisätty ryhmiin: $2. Sinut on poistettu ryhmistä: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Tervetuloa}} {{GRAMMAR:illative|{{SITENAME}}}}, $1! Olemme iloisia, että {{GENDER:$2|olet}} täällä.",
+ "notification-welcome-linktext": "Tervetuloa",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Teit}} juuri ensimmäisen muokkauksesi. Kiitos ja tervetuloa!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Teit}} juuri kymmenennen muokkauksesi. Kiitos ja jatka muokkaamista!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Teit}} juuri sadannen muokkauksesi. Lämpimät onnittelut!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Teit}} juuri tuhannennen muokkauksesi. Kiitos siitä, että olet tarmokas muokkaaja!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Teit}} juuri kymmenennentuhannennen muokkauksesi. Kiitos erittäin paljon!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Muokkauksesi}}",
"notification-link-text-view-edit": "Näytä muokkaus",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|jätti}} viestin [[User talk:$2#$3|keskustelusivullesi]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|jätti}} viestin keskustelusivullesi osioon \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|jätti}} viestin [[User talk:$2#$3|keskustelusivullesi]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|jätti}} viestin keskustelusivullesi osioon \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Sivulle [[:$2]] {{GENDER:$1|on nyt linkki}} sivulta [[:$3]].[[Special:WhatLinksHere/$2|Katso kaikki kohteeseen viittaavat linkit]].",
- "notification-page-linked-flyout": "Sivulle [[:$2]] {{GENDER:$1|johtaa nyt linkki}} sivulta [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|kommentoi}} aihetta \"[[$3|$2]]\" keskustelusivulla \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|lisäsi}} uuden aiheen \"$2\" sivulle [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|lähetti}} sinulle viestin: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|kommentoi}} aihetta \"[[$3#$2|$2]]\" keskustelusivullasi.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|mainitsi}} sinut kohteen $5 keskustelussa osiossa \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|mainitsi}} sinut kohteen $5 keskustelussa osiossa \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|mainitsi}} sinut [[:$3|$2 keskustelusivulla]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|mainitsi}} sinut [[:$3|$2 keskustelusivulla]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|muutti}}]] käyttöoikeuksiasi. $2. [[Special:ListGroupRights|Lisätietoja]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|muutti}} käyttöoikeuksiasi. $2. [[Special:ListGroupRights|Lisätietoja]]",
- "notification-user-rights-add": "Olet nyt {{PLURAL:$2|tämän ryhmän|näiden ryhmien}} jäsen: $1",
- "notification-user-rights-remove": "Et ole enää {{PLURAL:$2|tämän ryhmän|näiden ryhmien}} jäsen: $1",
- "notification-new-user": "Tervetuloa sivustolle {{SITENAME}}, $1! Olemme iloisia että olet täällä.",
- "notification-reverted2": "[[User:$1|$1]] {{GENDER:$1|kumosi}} {{PLURAL:$4|muokkauksesi}} sivulla [[:$2]]. $3",
- "notification-reverted-flyout2": "Käyttäjä $1 on {{GENDER:$1|kumonnut}} {{PLURAL:$4|muokkauksesi sivulla $2|muokkauksiasi sivulla $2}}. $3",
+ "notification-link-article-reminder": "Näytä sivu",
+ "notification-header-reverted": "{{PLURAL:$4|Tekemäsi muokkaus|Tekemäsi muokkaukset}} sivulla <strong>$3</strong> on {{GENDER:$2|kumottu}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|lähetti}} sinulle sähköpostia.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|jätti}} sinulle viestin sivustolla {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|jätti}} viestin keskustelusivullesi.",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|jätti}} viestin keskustelusivullesi osioon \"$2\".",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|jätti}} viestin keskustelusivullesi osioon ”$2”.",
"notification-page-linked-email-subject": "Luomasi sivu linkitettiin sivustolla {{SITENAME}}",
- "notification-page-linked-email-batch-body": "Sivulle $2 johtava {{GENDER:$1|linkki lisättiin}} sivulta $3.",
"notification-reverted-email-subject2": "Tekemäsi {{PLURAL:$3|muokkaus|muokkaukset}} sivustolla {{SITENAME}} on {{GENDER:$1|kumottu}}.",
- "notification-reverted-email-batch-body2": "Tekemäsi {{PLURAL:$3|muutoksen sivulle $2 on|muutokset sivulle $2 on}} {{GENDER:$1|kumonnut}} $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|mainitsi}} sinut sivustolla {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|mainitsi}} sinut kohteen $4 keskustelussa osiossa \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|mainitsi}} sinut keskustelusivulla $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|mainitsi}} {{GENDER:$2|sinut}} sivustolla {{SITENAME}}",
"notification-user-rights-email-subject": "Käyttöoikeutesi ovat muuttuneet sivustolla {{SITENAME}}",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|muutti}} käyttöoikeuksiasi. $2.",
- "echo-email-subject-default": "Uusi ilmoitus sivustolla {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 t}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 pv}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 kk}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 v}}",
+ "notification-timestamp-today": "Tänään",
+ "notification-timestamp-yesterday": "Eilen",
+ "notification-inbox-filter-read": "Luetut",
+ "notification-inbox-filter-unread": "Lukemattomat",
+ "notification-inbox-filter-all": "Kaikki",
"echo-email-body-default": "Sinulle on uusi ilmoitus sivustolla {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Sinulla on uusi ilmoitus.",
- "echo-email-footer-default": "$2\n\nMäärittele, mitä sähköposteja lähetämme sinulle, tarkistamalla asetuksesi:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Määrittele, mitä sähköpostiviestejä lähetämme sinulle, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">tarkistamalla asetuksesi</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nMääritä, mitä sähköposteja lähetämme sinulle. Voit tehdä sen omissa asetuksissasi:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-html-footer-preference-link-text": "tarkista {{GENDER:$1|asetuksesi}}",
"echo-notification-alert": "{{PLURAL:$1|Hälytysilmoitukset ($1)|100=Hälytysilmoitukset (yli 99)}}",
- "echo-notification-message": "{{PLURAL:$1|Viesti ($1)|Viestit ($1)|100=Viestit (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Ilmoitus ($1)|Ilmoitukset ($1)|100=Ilmoitukset (99+)}}",
"echo-notification-alert-text-only": "Hälytysilmoitukset",
- "echo-notification-message-text-only": "Viestit",
+ "echo-notification-notice-text-only": "Ilmoitukset",
"echo-overlay-link": "Kaikki ilmoitukset",
"echo-overlay-title": "<b>Ilmoitukset</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Ilmoitukset}}</b> (näytetään $1 ($2) lukematonta)",
"echo-mark-all-as-read": "Merkitse kaikki luetuiksi",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|ilmoitus|ilmoitusta}} merkitty luetuksi",
+ "echo-mark-wiki-as-read": "Merkitse kaikki luetuiksi valitsemassasi wikissä: $1",
"echo-date-today": "Tänään",
"echo-date-yesterday": "Eilen",
"echo-load-more-error": "Virhe ilmeni, kun haettiin lisää tuloksia.",
- "notification-edit-talk-page-bundle": "$1 ja {{PLURAL:$4|yksi muu|$3 muuta}} {{GENDER:$1|jättivät}} viestin [[User talk:$2|keskustelusivullesi]].",
- "notification-page-linked-bundle": "Sivulle $2 {{GENDER:$1|on tehty linkki}} sivulta $3 ja {{PLURAL:$5|yhdeltä muulta sivulta|$4 muulta sivulta}}. [[Special:WhatLinksHere/$2|Katso kaikki kohteeseen viittavat linkit]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 ja {{PLURAL:$3|yksi muu jättivät|$2 muuta ovat jättäneet}} viestin keskustelusivullesi.",
- "notification-page-linked-email-batch-bundle-body": "Sivu $2 {{GENDER:$1|linkitettiin}} sivulta $3 ja {{PLURAL:$5|yhdeltä muulta sivulta|$4 muulta sivulta}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Yksi uusi viesti|$1 uutta viestiä|100=yli 99 uutta viestiä}} <strong>{{GENDER:$3|keskustelusivullasi}}</strong>.",
"echo-email-batch-subject-daily": "Sinulle on {{PLURAL:$2|yksi uusi ilmoitus|$2 uutta ilmoitusta}} sivustolla {{SITENAME}}",
"echo-email-batch-subject-weekly": "Sinulle on {{PLURAL:$2|yksi uusi ilmoitus|$2 uutta ilmoitusta}} tällä viikolla sivustolla {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Hei $1.\nTässä on sinulle kooste tämän päivän tapahtumista sivustolla {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Hei $1.\nTässä on sinulle kooste tämän viikon tapahtumista sivustolla {{SITENAME}}.",
- "echo-email-batch-link-text-view-all-notifications": "Katso kaikki ilmoitukset",
- "echo-rev-deleted-text-view": "Tämä versio sivusta on poistettu."
+ "echo-email-batch-link-text-view-all-notifications": "Näytä kaikki ilmoitukset",
+ "notification-header-foreign-alert": "Muita hälytysilmoituksia {{PLURAL:$5|toisesta wikistä|$5 muista wikeistä}}",
+ "notification-header-foreign-notice": "Lisää ilmoituksia {{PLURAL:$5|toisesta wikistä|$5 muusta wikistä}}",
+ "notification-header-foreign-all": "Lisää ilmoituksia {{PLURAL:$5|toisesta wikistä|$5 toisesta wikistä}}"
}
diff --git a/Echo/i18n/fo.json b/Echo/i18n/fo.json
index ddc7c605..8b6dd178 100644
--- a/Echo/i18n/fo.json
+++ b/Echo/i18n/fo.json
@@ -17,7 +17,6 @@
"echo-pref-email-frequency-never": "Ikki senda mær fráboðanir við telduposti",
"echo-no-agent": "[Ongin]",
"echo-no-title": "[Ongin síða]",
- "tooltip-pt-notifications": "Tínar fráboðanir",
"notification-link-text-view-page": "Vís síðu",
"notification-link-text-view-edit": "Vís rætting",
"echo-email-batch-body-default": "Tú hevur nýggj boð.",
diff --git a/Echo/i18n/fr.json b/Echo/i18n/fr.json
index cdf86e9e..d4bfa024 100644
--- a/Echo/i18n/fr.json
+++ b/Echo/i18n/fr.json
@@ -23,139 +23,219 @@
"Mattho69",
"Wladek92",
"Momo50WM",
- "Orlodrim"
+ "Orlodrim",
+ "Jules78120",
+ "Jdforrester",
+ "Thibaut120094",
+ "Ash Crow",
+ "Zebulon84",
+ "PifyZ",
+ "Macofe",
+ "Cedric31",
+ "Trizek",
+ "GeekEmad",
+ "Mattflaschen",
+ "Trizek (WMF)",
+ "Pols12",
+ "Yasten",
+ "Trial",
+ "Tuxxic",
+ "Nemo bis",
+ "The RedBurn"
]
},
- "echo-desc": "Système pour avertir les utilisateurs sur les événements et les messages",
+ "echo-desc": "Système pour avertir les utilisateurs des événements et messages",
"prefs-echo": "Notifications",
"prefs-emailsettings": "Options de courriel",
"prefs-displaynotifications": "Options d'affichage",
"prefs-echosubscriptions": "Me prévenir de ces événements",
+ "prefs-echocrosswiki": "Notifications inter-wikis",
"prefs-newmessageindicator": "Indicateur de nouveau message",
+ "prefs-blocknotificationslist": "Utilisateurs occultés",
"echo-pref-send-me": "M'envoyer :",
"echo-pref-send-to": "Envoyer à :",
"echo-pref-email-format": "Format de courriel :",
"echo-pref-web": "Web",
"echo-pref-email": "Courriel",
"echo-pref-email-frequency-never": "Ne pas m'envoyer de notification par courriel",
- "echo-pref-email-frequency-immediately": "Notifications individuelles au fur et à mesure",
+ "echo-pref-email-frequency-immediately": "Un courriel par notification",
"echo-pref-email-frequency-daily": "Un résumé quotidien des notifications",
"echo-pref-email-frequency-weekly": "Un résumé hebdomadaire des notifications",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Texte brut",
- "echo-pref-new-message-indicator": "Afficher dans ma barre d’outils l’indicateur de nouveau message sur ma page de discussion",
+ "echo-pref-cross-wiki-notifications": "Afficher les notifications d’autres wikis",
+ "echo-pref-notifications-blacklist": "Ne pas afficher les notifications de ces utilisateurs ([[mw:Help:Notifications#mute|en savoir plus]]).",
+ "echo-pref-new-message-indicator": "Afficher dans ma barre d’outils l’indicateur signalant de nouveaux messages sur ma page de discussion",
+ "echo-pref-beta-feature-cross-wiki-message": "Notifications améliorées",
+ "echo-pref-beta-feature-cross-wiki-description": "Afficher et organiser plus facilement les notifications. Inclut les notifications inter-wikis, qui permettent de voir les messages des autres wikis (pour recevoir des notifications inter-wikis sur un wiki donné, vous devez activer la fonctionnalité bêta depuis celui-ci).",
"echo-learn-more": "En savoir plus",
+ "echo-log": "Journal public",
"echo-new-messages": "Vous avez de nouveaux messages",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Message|Messages}} de la page de discussion",
"echo-category-title-article-linked": "{{PLURAL:$1|Article lié|Article liés}}",
"echo-category-title-reverted": "{{PLURAL:$1|Modification annulée|Modifications annulées}}",
"echo-category-title-mention": "{{PLURAL:$1|Mention|Mentions}}",
+ "echo-category-title-mention-failure": "Échec {{PLURAL:$1|de la mention d’un utilisateur|des mentions d’utilisateurs}}",
+ "echo-category-title-mention-success": "Succès {{PLURAL:$1|de la mention d’un utilisateur|des mentions d’utilisateurs}}",
"echo-category-title-other": "{{PLURAL:$1|Autres}}",
"echo-category-title-system": "{{PLURAL:$1|Système}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Modification de droits utilisateur|Modifications de droits utilisateur}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Courriel d’un autre utilisateur|Courriels d’autres utilisateurs}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Rappel de page|Rappels de pages}}",
"echo-pref-tooltip-edit-user-talk": "Me prévenir quand quelqu’un publie un message ou répond sur ma page de discussion.",
- "echo-pref-tooltip-article-linked": "Me prévenir quand quelqu’un fait référence à une page que j’ai créée à partir d’une page d’article.",
- "echo-pref-tooltip-reverted": "Me prévenir quand quelqu’un annule une modification que j’ai faite, en utilisant l’outil annulation ou révocation",
+ "echo-pref-tooltip-article-linked": "Me prévenir quand quelqu’un depuis une autre page fait référence à une page que j’ai créée.",
+ "echo-pref-tooltip-reverted": "Me prévenir quand quelqu’un annule une modification que j’ai faite, en utilisant l’outil d’annulation ou de révocation.",
"echo-pref-tooltip-mention": "Me prévenir quand quelqu’un fait référence à ma page utilisateur.",
+ "echo-pref-tooltip-mention-failure": "M’avertir dans le cas où une mention pourrait n'avoir pas fonctionné.",
+ "echo-pref-tooltip-mention-success": "M’avertir lorsqu’une mention que j’ai effectuée a bien fonctionné.",
"echo-pref-tooltip-user-rights": "Me notifier quand quelqu’un modifie mes droits utilisateur.",
- "echo-no-agent": "[Personne]",
- "echo-no-title": "[Aucune page]",
+ "echo-pref-tooltip-emailuser": "Me notifier quand quelqu’un m’envoie un courriel.",
+ "echo-pref-tooltip-article-reminder": "Me prévenir de cette page quand je le demande.",
"echo-error-no-formatter": "Aucune mise en forme définie pour la notification",
"notifications": "Notifications",
"tooltip-pt-notifications-alert": "Vos alertes",
- "tooltip-pt-notifications-message": "Vos messages",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Vos}} notifications",
+ "echo-displaynotificationsconfiguration": "Configuration d’affichage des notifications",
+ "echo-displaynotificationsconfiguration-summary": "Ceci est un aperçu de comment les notifications sont configurées sur ce wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notifications par catégorie",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Classification des types de notification",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Dans quelle section chaque type de notification est trié",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Méthodes de notification autorisées",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Quelles méthodes de notification sont prises en charge pour chaque catégorie",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Quelles méthodes de notification sont prises en charge pour chaque type ; s’applique seulement aux types dans les catégories qui sont masquées dans les préférences",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Activé par défaut",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Utilisateurs existants",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nouveaux utilisateurs",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Méthodes de notification obligatoires",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Quelles méthodes de notification sont obligatoires pour chaque catégorie",
"echo-specialpage": "Notifications",
+ "echo-specialpage-section-markread": "Marquer la section comme lue",
+ "echo-specialpage-markasread": "Notification : marquer comme lue",
+ "echo-specialpage-markasread-invalid-id": "ID d'événement invalide",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notification|notifications}}",
+ "echo-specialpage-pagefilters-title": "Activité récente",
+ "echo-specialpage-pagefilters-subtitle": "Pages avec des notifications non lues",
+ "notificationsmarkread-legend": "Marquer une notification comme lue",
"echo-anon": "Pour recevoir des notifications, [$1 créez un compte] ou [$2 connectez-vous].",
"echo-none": "Vous n'avez reçu aucune notification.",
"echo-more-info": "Plus d’informations",
"echo-feedback": "Avis",
+ "echo-popup-footer-special-page-invitation": "<strong>Essayez la page des Notifications refaite.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Nouvelles présentation et fonctionnalités.",
"echo-quotation-marks": "« $1 »",
- "echo-api-failure": "Impossible d’obtenir les notifications. Veuillez réessayez. (Erreur $1)",
+ "echo-api-failure": "Impossible de récupérer les notifications.",
+ "echo-api-failure-cross-wiki": "L'accès au domaine distant a été refusé.",
"echo-notification-placeholder": "Il n’y a aucune notification.",
+ "echo-notification-placeholder-filters": "Il n'y a aucune notification correspondant à ces critères.",
+ "echo-notification-loginrequired": "Vous devez vous connecter pour voir vos notifications.",
+ "echo-notification-popup-loginrequired": "Veuillez vous connecter pour voir vos notifications.",
+ "echo-notification-markasread": "Marquer comme lu",
+ "echo-notification-markasunread": "Marquer comme non lu",
+ "echo-notification-markasread-tooltip": "Marquer comme lu",
+ "echo-notification-more-options-tooltip": "Plus d’options",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Arrêter}} de suivre de nouvelles activités sur « $1 »",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Vous}} ne suivez plus la page « $1 »",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Vous}} pouvez suivre [$2 cette page] à nouveau à tout moment.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Suivre}} la nouvelle activité sur «&nbsp;$1&nbsp;»",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Vous}} suivez désormais la page « $1 »",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Vous}} pouvez arrêter de suivre [$2 cette page] à tout moment.",
+ "notification-link-text-expand-all": "Développer",
+ "notification-link-text-expand-alert-count": "Afficher {{PLURAL:$1|$1 alerte|$1 alertes}}",
+ "notification-link-text-expand-notice-count": "Afficher {{PLURAL:$1|$1 notification|$1 notifications}}",
+ "notification-link-text-expand-all-count": "Afficher {{PLURAL:$1|$1 notification|$1 notifications}}",
+ "notification-link-text-collapse-all": "Réduire",
"notification-link-text-view-message": "Afficher le message",
"notification-link-text-view-mention": "Afficher la mention",
- "notification-link-text-view-changes": "Afficher les modifications",
+ "notification-link-text-view-mention-failure": "Afficher l{{PLURAL:$1|a mention|es mentions}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Afficher}} les modifications",
"notification-link-text-view-page": "Afficher la page",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|a laissé}} un message sur <strong>{{GENDER:$3|votre}} page de discussion</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|a laissé}} un message sur <strong>{{GENDER:$3|votre}} page de discussion</strong> dans la section « <strong>$4</strong> ».",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Un lien vers <strong>$3</strong> a été créé sur <strong>$4</strong>.",
+ "notification-compact-header-page-linked": "Lié depuis <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Des liens vers « <strong>$3</strong> » ont été insérés dans {{PLURAL:$5||$5 pages|100=plus de 100 pages}}.",
+ "notification-header-article-reminder": "Une page dont {{GENDER:$2|vous}} avez demandé le rappel est disponible sur <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Tous les liens vers cette page",
+ "notification-header-mention-other": "$1 {{GENDER:$2|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur <strong>$4</strong> dans « <strong>$5</strong> ».",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur la <strong>page de discussion {{GENDER:$5|de}} $4</strong> dans « <strong>$6</strong> ».",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur la <strong>page de discussion {{GENDER:$5|de}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur <strong>{{GENDER:$2|sa|sa|sa}} page de discussion</strong> dans « <strong>$4</strong> ».",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur <strong>sa page de discussion</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur la page de discussion de <strong>$4</strong> dans « <strong> $5</strong> ».",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur la page de discussion de <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Votre}} mention de  <strong>$3</strong> n’a pas été envoyée parce que l’utilisateur n’a pas été trouvé.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Votre}} mention de <strong>$3</strong> n’a pas été envoyée parce que l’utilisateur est anonyme.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|}}Vous avez essayé de mentionner plus de $3 utilisateur{{PLURAL:$3||s}}. Toutes les mentions au-dessus de cette limite ne leur ont pas été notifiées.",
+ "notification-header-mention-failure-bundle": "Concernant {{PLURAL:$3|l’utilisat{{GENDER:$2|eur|rice}} que vous avez mentionné{{GENDER:$2||e}}|les $3 utilisateurs que vous avez mentionnés}} sur la page de discussion <strong>$4</strong>, {{PLURAL:$3|une notification n’a pas pu lui être envoyée|$3 notifications n’ont pas pu leur être envoyées}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Utilisateur inconnu :</strong> « $1 »",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Les adresses IP ne peuvent pas être notifiées :</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Votre}} mention de <strong>$3</strong> a été envoyée.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Une mention|$3 mentions}} {{GENDER:$2|que vous avez faite}}{{PLURAL:$3||s}} sur la page de discussion de <strong>$4</strong> {{PLURAL:$3|a été envoyée|ont été envoyées}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Vous avez mentionné}} :</strong> $3",
+ "notification-header-mention-status-bundle": "Concernant {{PLURAL:$3|l’utilisat{{GENDER:$2|eur|rice}} $2 que vous avez mentionné{{GENDER:$2||e}}|les $3 utilisateurs que vous avez mentionnés}} sur la page de discussion <strong>$4</strong>, {{PLURAL:$5|0=|une notification n’a pas pu lui être envoyée|$5 notifications n’ont pas pu leur être envoyées}}{{PLURAL:$5|0=|{{PLURAL:$6|0=|&#32;et&#32;}}}}{{PLURAL:$6|0=|une notification lui a été envoyée|$6 notifications leur ont été envoyées}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Vos}} droits utilisateurs ont été {{GENDER:$1|modifiés}}. Vous avez été ajouté à : $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Vos}} droits utilisateurs ont été {{GENDER:$1|modifiés}}. Vous n’êtes désormais plus membre de : $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Vos}} droits d’{{GENDER:$2|utilisateur|utilisatrice}} ont été {{GENDER:$1|modifiés}}. Vous avez été ajouté{{GENDER:$2||e}} à : $2. Vous n’êtes désormais plus membre de : $4.",
+ "notification-header-user-rights-expiry-change": "L’expiration de {{GENDER:$4|votre}} appartenance {{PLURAL:$3|au groupe suivant|aux groupes suivants}} a été {{GENDER:$1|modifiée}} : $2.",
+ "notification-header-welcome": "{{GENDER:$2|Bienvenue}} sur {{SITENAME}}, $1 ! Nous sommes heureux que {{GENDER:$2|vous soyez}} ici.",
+ "notification-welcome-linktext": "Bienvenue",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Vous}} venez de faire {{GENDER:$2|votre}} première modification , {{GENDER:$2|}} merci et bienvenue !",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Vous}} venez de faire {{GENDER:$2|votre}} dixième modification, {{GENDER:$2|}} merci, continuez ainsi !",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Vous}} venez de faire {{GENDER:$2|votre}} centième modification , {{GENDER:$2|}} merci beaucoup !",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Vous}} venez de faire {{GENDER:$2|votre}} millième modification ; nous {{GENDER:$2|vous}} remercions d’être {{GENDER:$2|un grand contributeur !|une grande contributrice !}}",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Vous}} venez de faire {{GENDER:$2|votre}} dix-millième modification, un très grand merci à {{GENDER:$2|vous}} !",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Vous}} venez de faire {{GENDER:$2|votre}} cent-millième modification, merci à {{GENDER:$2|vous}} pour votre participation incroyable !",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Vous}} venez de faire {{GENDER:$2|votre}} millionième modification, merci à {{GENDER:$2|vous}} pour votre participation exceptionnelle !",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Votre}} modification",
"notification-link-text-view-edit": "Afficher la modification",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|a laissé}} un message sur votre [[User talk:$2#$3|page de discussion]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] a laissé un message sur votre page de discussion dans la [[User talk:$2#$3|section ''$4'']].",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|a laissé}} un message sur votre [[User talk:$2#$3|page de discussion]].",
- "notification-edit-talk-page-flyout-with-section": "$1 a laissé un message sur votre page de discussion dans la [[User talk:$2#$3|section ''$4'']].",
- "notification-page-linked": "[[:$2]] a été {{GENDER:$1|référencé}} depuis [[:$3]]. [[Special:WhatLinksHere/$2|Voir tous les liens vers cette page]].",
- "notification-page-linked-flyout": "[[:$2]] a été {{GENDER:$1|référencé}} depuis [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|a fait un commentaire}} dans « [[$3|$2]] » sur la page de discussion « $4 »",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|a publié}} un nouveau sujet \"$2\" sur [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] vous {{GENDER:$1|a envoyé}} un message: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|a fait un commentaire}} dans ''[[$3#$2|$2]]'' sur votre page de discussion",
- "notification-mention": "[[User:$1|$1]] vous a mentionné sur la page de discussion de $5 dans la [[:$3#$2|section ''$4'']].",
- "notification-mention-flyout": "$1 vous a mentionné sur la page de discussion de $5 dans la [[:$3#$2|section ''$4'']].",
- "notification-mention-nosection": "[[User:$1|$1]] a fait mention de vous sur la [[:$3|page de discussion de $2]].",
- "notification-mention-nosection-flyout": "$1 a fait mention de vous sur la [[:$3|page de discussion de $2]].",
- "notification-user-rights": "Vos droits d’utilisateur [[Special:Log/rights/$1|ont été modifiés]] par [[User:$1|$1]]. $2. [[Special:ListGroupRights|En savoir plus]]",
- "notification-user-rights-flyout": "Vos droits d’utilisateur {{GENDER:$1|ont été modifiés}} par $1. $2. [[Special:ListGroupRights|En savoir plus]]",
- "notification-user-rights-add": "Vous êtes maintenant membre de {{PLURAL:$2|ce groupe|ces groupes}} : $1",
- "notification-user-rights-remove": "Vous n’êtes plus membre de {{PLURAL:$2|ce groupe|ces groupes}} : $1",
- "notification-new-user": "Bienvenue sur {{SITENAME}}, $1 ! Nous sommes heureux de vous voir ici.",
- "notification-reverted2": "{{PLURAL:$4|Votre modification sur [[:$2]] a|Vos modifications sur [[:$2]] ont}} été annulée{{PLURAL:$4||s}} par [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Votre modification sur $2 a|Vos modifications sur $2 ont}} été annulée{{PLURAL:$4||s}} par $1 $3",
- "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|a laissé}} un message sur votre page de discussion sur {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|a laissé}} un message sur votre page de discussion .",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 a laissé un message sur votre page de discussion dans ''$2''.",
- "notification-page-linked-email-subject": "Une page que vous avez créé a été référencée sur {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 a été {{GENDER:$1|référencé}} depuis $3.",
+ "notification-link-article-reminder": "Afficher la page",
+ "notification-header-reverted": "{{PLURAL:$4|Votre modification sur <strong>$3</strong> a|Vos modifications sur <strong>$3</strong> ont}} été {{GENDER:$2|annulée}}{{PLURAL:$4||s}}.",
+ "notification-header-emailuser": "$1 vous {{GENDER:$2|a envoyé}} un courriel.",
+ "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|a laissé}} un message sur votre page de discussion sur {{SITENAME}}.",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 a laissé un message sur votre page de discussion dans « $2 ».",
+ "notification-page-linked-email-subject": "Un lien vers une page que vous avez créée a été inséré sur {{SITENAME}}",
"notification-reverted-email-subject2": "{{PLURAL:$3|Votre modification a été {{GENDER:$1|annulée}}|Vos modifications ont été {{GENDER:$1|annulées}}}} sur {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Votre modification sur $2 a été annulée|Vos modifications sur $2 ont été annulées}} par $1",
- "notification-mention-email-subject": "$1 vous a mentionné sur {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 vous a mentionné sur la page de discussion de $4 dans ''$3''.",
- "notification-mention-nosection-email-batch-body": "$1 a fait mention de vous sur la page de discussion de $2.",
+ "notification-mention-email-subject": "$1 vous a mentionné{{GENDER:$2||e}} sur {{SITENAME}}",
"notification-user-rights-email-subject": "Vos droits d’utilisateur ont été modifiés sur {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Vos droits d’utilisateur {{GENDER:$1|ont été modifiés}} par $1. $2",
- "echo-email-subject-default": "Nouvelle notification sur {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1mi}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1j}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mo}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1an}}",
+ "notification-timestamp-today": "Aujourd’hui",
+ "notification-timestamp-yesterday": "Hier",
+ "notification-inbox-filter-read": "Lus",
+ "notification-inbox-filter-unread": "Non lus",
+ "notification-inbox-filter-all": "Tous",
"echo-email-body-default": "Vous avez une nouvelle notification sur {{SITENAME}} :\n\n$1",
- "echo-email-batch-body-default": "Vous avez une nouvelle notification",
- "echo-email-footer-default": "$2\n\nPour vérifier quels courriels nous vous envoyons, allez dans vos préférences :\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Pour contrôler les courriels que nous vous envoyons, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">vérifiez vos préférences</a><br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|Alertes ($1)|100=Alertes (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Messages ($1)|100=Messages (99+)}}",
+ "echo-email-footer-default-html": "Pour contrôler les courriels que nous vous envoyons, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">vérifier vos préférences</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPour contrôler quels courriels nous vous envoyons, vérifiez vos préférences :\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Pour choisir quels courriels nous {{GENDER:$1|vous}} envoyons, vérifiez {{GENDER:$1|vos}} préférences :",
+ "echo-email-html-footer-preference-link-text": "vérifiez {{GENDER:$1|vos}} préférences",
+ "echo-email-html-footer-with-link": "Pour contrôler quels courriels nous {{GENDER:$2|vous}} envoyons, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Alerte ($1)|100=Alertes (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notifications ($1)|100=Notifications (100 et plus)}}",
"echo-notification-alert-text-only": "Alertes",
- "echo-notification-message-text-only": "Messages",
+ "echo-notification-notice-text-only": "Notifications",
"echo-overlay-link": "Toutes les notifications",
"echo-overlay-title": "<b>Notifications</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notification|Notifications}}</b> ($1 sur $2 {{PLURAL:$1|non lue affichée|non lues affichées}})",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notification|Notifications}}</b> ($1 {{PLURAL:$1|affichée|affichées}} sur $2 {{PLURAL:$1|non lue|non lues}})",
"echo-mark-all-as-read": "Tout marquer comme lu",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notification marquée comme lue|notifications marquées comme lues}}",
+ "echo-mark-wiki-as-read": "Marquer le tout comme étant lu pour les wiki sélectionnés : $1",
"echo-date-today": "Aujourd’hui",
"echo-date-yesterday": "Hier",
- "echo-load-more-error": "Un erreur s'est produite en analysant davantage de résultats.",
- "notification-edit-talk-page-bundle": "$1 et $3 {{PLURAL:$4|autre|autres}} ont laissé un message sur votre [[User talk:$2|page de discussion]].",
- "notification-page-linked-bundle": "$2 a été {{GENDER:$1|référencé}} depuis $3 et $4 {{PLURAL:$5|autre page|autres pages}}. [[Special:WhatLinksHere/$2|Voir tous les liens vers cette page]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 et $2 {{PLURAL:$3|autre|autres}} ont {{GENDER:$1|laissé}} un message sur votre page de discussion.",
- "notification-page-linked-email-batch-bundle-body": "$2 a été {{GENDER:$1|lié}} depuis $3 et $4 {{PLURAL:$5|autre page|autres pages}}.",
+ "echo-load-more-error": "Une erreur s'est produite en recherchant plus de résultats.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Un nouveau message|$1 nouveaux messages|100=plus de 100 nouveaux messages}} sur <strong>{{GENDER:$3|votre}} page de discussion</strong> .",
"echo-email-batch-subject-daily": "Vous avez {{PLURAL:$2|une nouvelle notification|de nouvelles notifications}} aujourd'hui sur {{SITENAME}}",
"echo-email-batch-subject-weekly": "Vous avez {{PLURAL:$2|une nouvelle notification|de nouvelles notifications}} sur {{SITENAME}} cette semaine",
"echo-email-batch-body-intro-daily": "Bonjour $1,\nVoici pour vous un résumé de l’activité d’aujourd’hui sur {{SITENAME}}",
"echo-email-batch-body-intro-weekly": "Bonjour $1,\nVoici pour vous un résumé de l’activité de la semaine sur {{SITENAME}}",
"echo-email-batch-link-text-view-all-notifications": "Voir toutes les notifications",
- "echo-rev-deleted-text-view": "Cette révision de page a été supprimée",
- "apihelp-echomarkread-description": "Marquer les notifications comme lues pour l’utilisateur actuel.",
- "apihelp-echomarkread-param-list": "Une liste des IDs de notification à marquer comme lues.",
- "apihelp-echomarkread-param-all": "Si défini, marque toutes les notifications de l’utilisateur comme lues.",
- "apihelp-echomarkread-param-sections": "Une liste des sections à marquer comme lues.",
- "apihelp-echomarkread-example-1": "Marquer la notification 8 comme lue",
- "apihelp-echomarkread-example-2": "Marquer toutes les notifications comme lues",
- "apihelp-echomarkseen-description": "Marquer les notifications comme lues pour l’utilisateur actuel.",
- "apihelp-echomarkseen-example-1": "Marquer les notifications de tous types comme lues.",
- "apihelp-echomarkseen-param-type": "Type de notifications à marquer comme vues : 'alert', 'message' ou 'all'.",
- "apihelp-query+notifications-description": "Obtenir les notifications en attente pour l’utilisateur courant.",
- "apihelp-query+notifications-param-prop": "Détails à demander.",
- "apihelp-query+notifications-param-sections": "Les sections de notification de la requête (c'est à dire une combinaison de 'alerte' et 'message').",
- "apihelp-query+notifications-param-groupbysection": "S’il faut grouper les résultats par section. Chaque section est analysée séparément, s’il est défini.",
- "apihelp-query+notifications-param-format": "Si spécifié, les notifications seront renvoyées dans ce format.",
- "apihelp-query+notifications-param-limit": "Le nombre maximal de notifications à renvoyer.",
- "apihelp-query+notifications-param-index": "Si spécifié, une liste ordonnée d’IDs de notification sera renvoyée.",
- "apihelp-query+notifications-param-alertcontinue": "Quand plus d’alertes sont disponibles, utiliser cela pour continuer.",
- "apihelp-query+notifications-param-alertunreadfirst": "S’il faut afficher d’abord les notifications de message non lu.",
- "apihelp-query+notifications-param-messagecontinue": "Quand plus de résultats de message sont disponibles, utiliser cela pour continuer.",
- "apihelp-query+notifications-param-messageunreadfirst": "S’il faut afficher les notifications d’alerte non lues en premier.",
- "apihelp-query+notifications-example-1": "Lister les notifications",
- "apihelp-query+notifications-example-2": "Lister les notifications, groupées par section, avec les compteurs"
+ "notification-header-foreign-alert": "Davantage d’alertes {{PLURAL:$5|d’un autre wiki|de $5 autres wikis}}",
+ "notification-header-foreign-notice": "Davantage de notifications {{PLURAL:$5|d’un autre wiki|de $5 autres wikis}}",
+ "notification-header-foreign-all": "Davantage de notifications {{PLURAL:$5|d’un autre wiki|de $5 autres wikis}}"
}
diff --git a/Echo/i18n/frp.json b/Echo/i18n/frp.json
index e7ecc098..10366195 100644
--- a/Echo/i18n/frp.json
+++ b/Echo/i18n/frp.json
@@ -10,7 +10,8 @@
"echo-no-agent": "[Nion]",
"echo-no-title": "[Niona pâge]",
"notifications": "Notificacions",
- "tooltip-pt-notifications": "Voutres notificacions",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Voutres}} alèrtes",
+ "tooltip-pt-notifications-message": "{{GENDER:|Voutros}} mèssâjos",
"echo-specialpage": "Mes notificacions",
"echo-none": "Vos éd reçu gins de notificacion.",
"notification-new-user": "Benvegnua sur {{SITENAME}}, $1 !",
diff --git a/Echo/i18n/frr.json b/Echo/i18n/frr.json
index 4d2561c7..7fc62718 100644
--- a/Echo/i18n/frr.json
+++ b/Echo/i18n/frr.json
@@ -36,11 +36,9 @@
"echo-pref-tooltip-reverted": "Sai mi beskias, wan diar hoker en feranrang faan mi uun en artiikel turagsaat.",
"echo-pref-tooltip-mention": "Sai mi beskias, wan diar hoker en ferwisang faan en diskuschuunsidj üüb min brükersidj saat.",
"echo-pref-tooltip-user-rights": "Du mi bööd, wan hoker min brükerrochten feranert.",
- "echo-no-agent": "[Näämen]",
- "echo-no-title": "[Nian sidj]",
"echo-error-no-formatter": "Tu detdiar bööd as nian formoot fäästlaanj wurden.",
"notifications": "Bööd",
- "tooltip-pt-notifications": "Din bööd",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Din}} wäärnangen",
"echo-specialpage": "Bööd",
"echo-anon": "Am bööd tu fun, skel dü en [$1 brükerkonto] iinracht of di [$2 uunmelde].",
"echo-none": "Dü heest nian bööd.",
@@ -51,48 +49,17 @@
"notification-link-text-view-changes": "Feranrang/en uunwise",
"notification-link-text-view-page": "Sidj uunwise",
"notification-link-text-view-edit": "Feranrang uunwise",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|hää}} en bööd üüb din [[User talk:$2#$3|brükersidj]] skrewen.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|hää}} en bööd üüb din diskuschuunsidj skrewen auer \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|hää}} en bööd üüb din [[User talk:$2#$3|diskuschuunsidj]] skrewen.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|hää}} en bööd üüb din diskuschuunsidj skrewen auer \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Üüb [[:$2]] as faan [[:$3]] {{GENDER:$1|ferwiset}} wurden. [[Special:WhatLinksHere/$2|Aal a ferwisangen üüb detdiar sidj uunwise]].",
- "notification-page-linked-flyout": "Üüb [[:$2]] as faan [[:$3]] {{GENDER:$1|ferwiset}} wurden.",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|skrääw}} auer \"[[$3|$2]]\" üüb det \"$4\" diskuschuunsidj.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|skrääw}} en nei kirew \"$2\" üüb [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|hää}} di en bööd schüürd: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|skrääw}} auer \"[[$3#$2|$2]]\" üüb din diskuschuunsidj.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|näämd}} di üüb det $5 diskuschuunsidj auer \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|näämd}} di üüb det $5 diskuschuunsidj uun \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|näämd}} di üüb det [[:$3|$2 diskuschuunsidj]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|näämd}} di üüb det [[:$3|$2 diskuschuunsidj]].",
- "notification-user-rights": "Din brükerrochten [[Special:Log/rights/$1|san {{GENDER:$1|feranert}}]] wurden faan [[User:$1|$1]]. $2. [[Special:ListGroupRights|Muar diartu]]",
- "notification-user-rights-flyout": "Din brükerrochten san {{GENDER:$1|feranert}} wurden faan $1. $2. [[Special:ListGroupRights|Muar diartu]]",
- "notification-user-rights-add": "Dü beest nü lasmoot faan {{PLURAL:$2|detdiar brükerskööl|jodiar brükersköölen}}: $1",
- "notification-user-rights-remove": "Dü beest nian lasmoot muar faan {{PLURAL:$2|detdiar brükerskööl|jodiar brükersköölen}}: $1",
- "notification-new-user": "Welkimen tu {{SITENAME}}, $1! Wi san bliis, dat dü diar beest.",
- "notification-reverted2": "Din {{PLURAL:$4|feranrang üüb [[:$2]] as|feranrangen üüb [[:$2]] san}} {{GENDER:$1|turagsaat}} wurden faan [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "Din {{PLURAL:$4|feranrang üüb $2 as|feranrangen üüb $2 san}} {{GENDER:$1|turagsaat}} wurden faan $1. $3",
+ "notification-header-reverted": "Din {{PLURAL:$4|feranrang üüb $3 as|feranrangen üüb $3 san}} {{GENDER:$2|turagsaat}} wurden faan $1.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|hää}} di en bööd schüürd üüb {{SITENAME}}.",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|hää}} en bööd üüb din diskuschuunsidj skrewen.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|hää}} en bööd üüb din diskuschuunsidj skrewen auer \"$2\".",
"notification-page-linked-email-subject": "Üüb ian sidj faan di as faan {{SITENAME}} ferwiset wurden.",
- "notification-page-linked-email-batch-body": "Üüb $2 as faan $3 {{GENDER:$1|ferwiset}} wurden.",
"notification-reverted-email-subject2": "Din {{PLURAL:$3|feranrang as|feranrangen san}} {{GENDER:$1|turagsaat}} wurden üüb {{SITENAME}}.",
- "notification-reverted-email-batch-body2": "Din {{PLURAL:$3|feranrang üüb $2 as|feranrangen üüb $2 san}} faan $1 {{GENDER:$1|turagsaat}} wurden.",
"notification-mention-email-subject": "$1 {{GENDER:$1|näämd}} di üüb {{SITENAME}}.",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|näämd}} di üüb det $4 diskuschuunsidj uun \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|näämd}} di üüb det $2 diskuschuunsidj.",
"notification-user-rights-email-subject": "Din brükerrochten san feranert wurden üüb {{SITENAME}}.",
- "notification-user-rights-email-batch-body": "Din brükerrochten san {{GENDER:$1|feranert}} wurden faan $1. $2.",
- "echo-email-subject-default": "Nei bööd üüb {{SITENAME}}.",
"echo-email-body-default": "Dü heest nei bööd üüb {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Dü heest nei bööd.",
"echo-email-footer-default": "$2\n\nAm iintustelen, hük e-mails tu di schüürd wurd, brük din iinstelangs-sidj:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Am iintustelen, hük e-mails tu di schüürd wurd, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">brük din iinstelangs-sidj</a>.<br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|Ian bööd|$1 bööden|100=99+ bööden}}",
- "echo-notification-message": "{{PLURAL:$1|Ian bööd|$1 bööden|100=99+ bööden}}",
"echo-notification-alert-text-only": "Bööden",
- "echo-notification-message-text-only": "Bööden",
"echo-overlay-link": "Aal din bööd",
"echo-overlay-title": "<b>Bööd</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Bööden}}</b> (Uunwiset wurd $1 faan $2, diar noch ei leesen wurden san)",
@@ -100,35 +67,9 @@
"echo-date-today": "Daalang",
"echo-date-yesterday": "Jister",
"echo-load-more-error": "Bi't ufrepen as wat skiaf gingen.",
- "notification-edit-talk-page-bundle": "$1 an $3 {{PLURAL:$4|brüker muar|muar brükern}} {{GENDER:$1|schüürd}} en bööd tu din [[User talk:$2|diskuschuunsidj]].",
- "notification-page-linked-bundle": "Üüb $2 as faan $3 an $4 {{PLURAL:$5|sidj muar|muar sidjen}} {{GENDER:$1|ferwiset}} wurden. [[Special:WhatLinksHere/$2|Aal a ferwisangen üüb detdiar sidj uunwise]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 an $2 {{PLURAL:$3|brüker muar|muar brükern}} {{GENDER:$1|haa}} en bööd tu din diskuschuunsidj schüürd.",
- "notification-page-linked-email-batch-bundle-body": "Üüb $2 as faan $3 an $4 {{PLURAL:$5|sidj muar|muar sidjen}} {{GENDER:$1|ferwiset}} wurden.",
"echo-email-batch-subject-daily": "Dü heest {{PLURAL:$2|en nei bööd|nei bööden}} üüb {{SITENAME}}.",
"echo-email-batch-subject-weekly": "Dü heest das weg {{PLURAL:$2|ian nei bööd|nei bööden}} üüb {{SITENAME}}.",
"echo-email-batch-body-intro-daily": "Hoi $1,\ndiar as en auersicht för di auer feranrangen üüb {{SITENAME}} faan daalang.",
"echo-email-batch-body-intro-weekly": "Hoi $1,\nDiar as en auersicht för di auer a feranrangen üüb {{SITENAME}} faan das weg.",
- "echo-email-batch-link-text-view-all-notifications": "Aal min bööd uunwise",
- "echo-rev-deleted-text-view": "Detdiar sidjenwerjuun as ferbürgen wurden.",
- "apihelp-echomarkread-description": "Bööden för di uugenblakelk brüker ruad uunwise",
- "apihelp-echomarkread-param-list": "En list faan bööd-IDs ruad uuntuwisin",
- "apihelp-echomarkread-param-all": "Wan det so fäästlaanj as, wurd aal a bööden üs al leesen uunwiset.",
- "apihelp-echomarkread-param-sections": "En list faan kirwer ruad uuntuwisin.",
- "apihelp-echomarkread-example-1": "Bööd 8 üs al leesen uunwise",
- "apihelp-echomarkread-example-2": "Aal a bööden üs al leesen uunwise",
- "apihelp-echomarkseen-description": "Bööden för di uugenblakelk brüker üs uunluket markiare",
- "apihelp-echomarkseen-example-1": "Bööden üs uunluket markiare",
- "apihelp-query+notifications-description": "Bööden för di uugenblakelk brüker haale.",
- "apihelp-query+notifications-param-prop": "Enkelthaiden uuntufraagin.",
- "apihelp-query+notifications-param-sections": "Bööd kirwer uftufraagin",
- "apihelp-query+notifications-param-groupbysection": "Of det resultaat efter kirwer uunwiset woort. Arke kirew woort enkelt haalet, wan det so fäästlaanj as.",
- "apihelp-query+notifications-param-format": "Bööden wurd formatiaret uunwiset, wan det so fäästlaanj as.",
- "apihelp-query+notifications-param-limit": "Det huuchst taal faan uunwiset bööden.",
- "apihelp-query+notifications-param-index": "En list faan bööd-IDs woort efter a rä uunwiset, wan det so fäästlaanj as.",
- "apihelp-query+notifications-param-alertcontinue": "Wann diar muar resultaaten san, brük det heer, am widjer tu maagin.",
- "apihelp-query+notifications-param-alertunreadfirst": "Of diar bööden tuiarst uunwiset wurd skel, diar noch ei leesen wurden san.",
- "apihelp-query+notifications-param-messagecontinue": "Wann diar muar resultaaten san, brük det heer, am widjer tu maagin.",
- "apihelp-query+notifications-param-messageunreadfirst": "Of diar bööden tuiarst uunwiset wurd skel, diar noch ei leesen wurden san.",
- "apihelp-query+notifications-example-1": "List faan din bööden",
- "apihelp-query+notifications-example-2": "List faan din bööden, efter a rä faan a kirwer, mä taalen"
+ "echo-email-batch-link-text-view-all-notifications": "Aal min bööd uunwise"
}
diff --git a/Echo/i18n/fur.json b/Echo/i18n/fur.json
new file mode 100644
index 00000000..5309945e
--- /dev/null
+++ b/Echo/i18n/fur.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Tocaibon"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|I tiei}} avîs",
+ "tooltip-pt-notifications-message": "{{GENDER:|I tiei}} messaçs"
+}
diff --git a/Echo/i18n/fy.json b/Echo/i18n/fy.json
index d5b5dfd7..2d4e067d 100644
--- a/Echo/i18n/fy.json
+++ b/Echo/i18n/fy.json
@@ -1,17 +1,19 @@
{
"@metadata": {
"authors": [
- "Robin0van0der0vliet"
+ "Robin0van0der0vliet",
+ "PiefPafPier",
+ "Robin van der Vliet"
]
},
"prefs-emailsettings": "E-mailynstellingen",
"echo-pref-email": "E-mail",
"echo-pref-email-format-html": "HTML",
"notifications": "Meldingen",
- "tooltip-pt-notifications": "Jo meldingen",
"echo-specialpage": "Meldingen",
"echo-feedback": "Weromkeppeling",
- "echo-notification-message-text-only": "Berjochten",
+ "notification-link-text-expand-all": "Utklappe",
+ "notification-link-text-collapse-all": "Ynklappe",
"echo-overlay-link": "Alle meldingen",
"echo-date-today": "Hjoed",
"echo-date-yesterday": "Juster"
diff --git a/Echo/i18n/gd.json b/Echo/i18n/gd.json
index 0b8a492f..9e5eb48f 100644
--- a/Echo/i18n/gd.json
+++ b/Echo/i18n/gd.json
@@ -1,10 +1,11 @@
{
"@metadata": {
"authors": [
- "GunChleoc"
+ "GunChleoc",
+ "Akerbeltz"
]
},
- "echo-desc": "Siostam nam brathan-naidheachd",
+ "echo-desc": "Siostam gus brathan a chur chan luchd-cleachdaidh mu thachartasan is naidheachdan",
"prefs-echo": "Brathan-naidheachd",
"prefs-emailsettings": "Roghainnean a' phuist-d",
"prefs-displaynotifications": "Roghainnean an t-seallaidh",
@@ -21,7 +22,6 @@
"echo-pref-email-frequency-weekly": "Gearr chunntas dhe bhrathan-naidheachd na seachdaine",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Teacsa lom",
- "echo-pref-notify-show-link": "Seall brathan-naidheachd air a' bhàr-inneal agam",
"echo-pref-new-message-indicator": "Seall taisbeanair airson duilleag na deasbaireachd air a' bhàr-inneal agam",
"echo-learn-more": "Barrachd fiosrachaidh",
"echo-new-messages": "Tha teachdaireachdan ùra agad",
@@ -36,13 +36,9 @@
"echo-pref-tooltip-reverted": "Cuir brath-naidheachd thugam nuair a thilleas cuideigin deasachadh a rinn mi le inneal an neo-dhèanaimh no an tillidh.",
"echo-pref-tooltip-mention": "Cuir brath-naidheachd thugam nuair a cheanglas cuideigin ris duilleag a' chleachdaiche agam o dhuilleag na deasbaireachd sam bith.",
"echo-pref-tooltip-user-rights": "Cuir brath-naidheachd thugam nuair a dh'atharraicheas cuideigin ceadan a' chleachdaiche agam.",
- "echo-no-agent": "[Chan eil duine]",
- "echo-no-title": "[Gun duilleag]",
"echo-error-no-formatter": "Tha deach fòrmatadh a shònrachadh airson a' bhratha-naidheachd.",
- "echo-error-preference": "Mearachd: cha b' urrainn dhuinn roghainn a' chleachdaiche a shuidheachadh.",
- "echo-error-token": "Mearachd: Cha b' urrainn dhuinn tòcan a' chleachdaiche fhaighinn.",
"notifications": "Brathan-naidheachd",
- "tooltip-pt-notifications": "Na brathan-naidheachd agad",
+ "tooltip-pt-notifications-alert": "Na caismeachdan {{GENDER:|agad}}",
"echo-specialpage": "Brathan-naidheachd",
"echo-anon": "[$1 Cruthaich cunntas] no [$2 log a-steach] gus brathan-naidheachd fhaighinn.",
"echo-none": "Chan eil brath-naidheachd agad.",
@@ -51,48 +47,19 @@
"echo-quotation-marks": "\"$1\"",
"notification-link-text-view-message": "Seall an teachdaireachd",
"notification-link-text-view-mention": "Seall an t-iomradh",
- "notification-link-text-view-changes": "Seall na h-atharraichean",
+ "notification-link-text-view-changes": "{{GENDER:$1|Seall}} na h-atharraichean",
"notification-link-text-view-page": "Seall an duilleag",
+ "notification-header-edit-user-talk": "Dh’fhàg $1 teachdaireachd dhut air <strong>an duilleag deasbaireachd agad</strong>.",
"notification-link-text-view-edit": "Seall an deasachadh",
- "notification-edit-talk-page2": "Dh'fhàg [[User:$1|$1]] {{GENDER:$1|}} teachdaireachd air [[User talk:$2#$3|duilleag na deasbaireachd]] agad.",
- "notification-edit-talk-page-with-section": "Dh'fhàg [[User:$1|$1]] {{GENDER:$1|}} teachdaireachd duilleag na deasbaireachd agad ann an \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "Dh'fhàg $1 {{GENDER:$1|}} teachdaireachd air [[User talk:$2#$3|duilleag na deasbaireachd]] agad.",
- "notification-edit-talk-page-flyout-with-section": "Dh'fhàg $1 {{GENDER:$1|}} teachdaireachd duilleag na deasbaireachd agad ann an \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Chaidh [[:$2]] a cheangal {{GENDER:$1|}} o [[:$3]]. [[Special:WhatLinksHere/$2|Seall a h-uile ceangal dhan duilleag seo]].",
- "notification-page-linked-flyout": "Chaidh [[:$2]] a cheangal {{GENDER:$1|}} o [[:$3]].",
- "notification-add-comment2": "Bheachdaich [[User:$1|$1]] {{GENDER:$1|}} air \"[[$3|$2]]\" air duilleag na deasbaireachd \"$4\".",
- "notification-add-talkpage-topic2": "Thòisich [[User:$1|$1]] {{GENDER:$1|}} cuspair ùr \"$2\" air [[$3]].",
- "notification-add-talkpage-topic-yours2": "Chuir [[User:$1|$1]] {{GENDER:$1|}} teachdaireachd thugad: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "Bheachdaich [[User:$1|$1]] {{GENDER:$1|}} air \"[[$3#$2|$2]]\" air duilleag na deasbaireachd agad.",
- "notification-mention": "Thug [[User:$1|$1]] {{GENDER:$1|}} iomradh ort air duilleag na deasbaireachd \"$5\" ann an \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "Thug $1 {{GENDER:$1|}} iomradh ort air duilleag na deasbaireachd \"$5\" ann an \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "Thug [[User:$1|$1]] {{GENDER:$1|}} iomradh ort air [[:$3|$2 duilleag na deasbaireachd]].",
- "notification-mention-nosection-flyout": "Thug $1 {{GENDER:$1|}} iomradh ort air [[:$3|$2 duilleag na deasbaireachd]].",
- "notification-user-rights": "Chaidh ceadan a' chleachdaiche agad [[Special:Log/rights/$1|{{GENDER:$1|atharrachadh}}]] le [[User:$1|$1]]. $2. [[Special:ListGroupRights|Barrachd fiosrachaidh]]",
- "notification-user-rights-flyout": "Chaidh ceadan a' chleachdaiche agad {{GENDER:$1|atharrachadh}} le $1. $2. [[Special:ListGroupRights|Barrachd fiosrachaidh]]",
- "notification-user-rights-add": "Tha thu 'nad bhall {{PLURAL:$2|sa bhuidheann seo|sna buidhnean seo}} a-nis: $1",
- "notification-user-rights-remove": "Chan eil thu 'nad bhall {{PLURAL:$2|sa bhuidheann seo|sna buidhnean seo}} tuilleadh: $1",
- "notification-new-user": "Fàilte gu {{SITENAME}}, $1! Tha sinn toilichte gu bheil thu ann.",
- "notification-reverted2": "Chaidh {{PLURAL:$4|an deasachadh agad air [[:$2]] |na deasachaidhean agad air [[:$2]]}} {{GENDER:$1|a thilleadh}} le [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "Chaidh {{PLURAL:$4|an deasachadh agad air $2 |na deasachaidhean agad air $2}} {{GENDER:$1|a thilleadh}} le $1. $3",
+ "notification-header-reverted": "Chaidh {{PLURAL:$4|an deasachadh agad air <strong>$3</strong> |na deasachaidhean agad air <strong>$3</strong>}} {{GENDER:$2|a thilleadh}}.",
"notification-edit-talk-page-email-subject2": "Dh'fhag $1 {{GENDER:$1|}} teachdaireachd dhut air {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "Dh'fhàg $1 {{GENDER:$1|}} teachdaireachd air duilleag na deasbaireachd agad:",
"notification-edit-talk-page-email-batch-body-with-section": "Dh'fhàg $1 {{GENDER:$1|}} teachdaireachd air duilleag na deasbaireachd agad ann an \"$2\".",
- "notification-page-linked-email-subject": "Chaidh ceangal ris an duilleag agad air {{SITENAME}}",
- "notification-page-linked-email-batch-body": "Chaidh $2 a cheangal {{GENDER:$1|}} o $3.",
+ "notification-page-linked-email-subject": "Chaidh ceangal ri duilleag a chruthaich thu air {{SITENAME}}",
"notification-reverted-email-subject2": "Chaidh {{PLURAL:$3|an deasachadh agad|na deasachaidhean agad}} {{GENDER:$1|a thilleadh}} air {{SITENAME}}",
- "notification-reverted-email-batch-body2": "Chaidh {{PLURAL:$3|an deasachadh agad air $2 |na deasachaidhean agad air $2}} {{GENDER:$1|a thilleadh}} le $1.",
- "notification-mention-email-subject": "Thug $1 {{GENDER:$1|iomradh}} ort air {{SITENAME}}",
- "notification-mention-email-batch-body": "Thug $1 {{GENDER:$1|}} iomradh ort air duilleag na deasbaireachd \"$4\" ann an \"$3\".",
- "notification-mention-nosection-email-batch-body": "Thug $1 {{GENDER:$1|}} iomradh ort air duilleag na deasbaireachd \"$2\".",
+ "notification-mention-email-subject": "Thug $1 {{GENDER:$1|iomradh}} {{GENDER:$2|ort}} air {{SITENAME}}",
"notification-user-rights-email-subject": "Chaidh ceadan a' chleachdaiche agad atharrachadh air {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Chaidh ceadan a' chleachdaiche agad {{GENDER:$1|atharrachadh}} le $1. $2.",
- "echo-notification-count": "$1+",
- "echo-email-subject-default": "Brath-naidheachd ùr air {{SITENAME}}",
"echo-email-body-default": "Tha brath-naidheachd ùr agad air {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Tha brath-naidheachd ùr agad.",
"echo-email-footer-default": "$2\n\nThoir sùil air na roghainnean agad gus taghadh dè na puist-d a chuireas sinn thugad:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "<a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">Thoir sùil air na roghainnean agad</a> gus taghadh dè na puist-d a chuireas sinn thugad.<br />\n$1",
"echo-overlay-link": "A h-uile brath-naidheachd",
"echo-overlay-title": "<b>Brathan-naidheachd</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Brath-naidheachd|Brathan-naidheachd}}</b> (a' sealltainn $1 à $2 gun leughadh)",
@@ -100,15 +67,10 @@
"echo-date-today": "An-diugh",
"echo-date-yesterday": "An-dè",
"echo-load-more-error": "Thachair mearachd nuair a bha sinn a' faighinn barrachd thoraidhean.",
- "notification-edit-talk-page-bundle": "Dh'fhàg $1 agus $3 {{PLURAL:$4|eile}} {{GENDER:$1|}} teachdaireachd air [[User talk:$2|duilleag na deasbaireachd agad]].",
- "notification-page-linked-bundle": "Chaidh $2 a cheangal {{GENDER:$1|}} o $3 agus $4 {{PLURAL:$5|duilleag|duilleagan}} eile. [[Special:WhatLinksHere/$2|Seall a h-uile ceangal dhan duilleag seo]]",
- "notification-edit-user-talk-email-batch-bundle-body": "Dh'fhàg $1 agus $3 {{PLURAL:$4|eile}} {{GENDER:$1|}} teachdaireachd air duilleag na deasbaireachd agad.",
- "notification-page-linked-email-batch-bundle-body": "Chaidh $2 a cheangal {{GENDER:$1|}} o $3 agus $4 {{PLURAL:$5|duilleag|duilleagan}} eile.",
"echo-email-batch-bullet": "•",
"echo-email-batch-subject-daily": "Tha {{PLURAL:$2|bràth-naidheachd ùr|brathan-naidheachd ùra}} agad air {{SITENAME}}",
"echo-email-batch-subject-weekly": "Tha {{PLURAL:$2|bràth-naidheachd ùr|brathan-naidheachd ùra}} agad air {{SITENAME}} an t-seachdain seo",
"echo-email-batch-body-intro-daily": "$1, a charaid,\nSeo gearr-chunntas dhut dhen ghnìomhachd air {{SITENAME}} an-diugh.",
"echo-email-batch-body-intro-weekly": "$1, a charaid,\nSeo gearr-chunntas dhut dhen ghnìomhachd air {{SITENAME}} an t-seachdain seo.",
- "echo-email-batch-link-text-view-all-notifications": "Seall a h-uile brath-naidheachd",
- "echo-rev-deleted-text-view": "Chaidh am mùthadh duilleige seo a mùchadh."
+ "echo-email-batch-link-text-view-all-notifications": "Seall a h-uile brath-naidheachd"
}
diff --git a/Echo/i18n/gl.json b/Echo/i18n/gl.json
index 00c95d94..ff99770f 100644
--- a/Echo/i18n/gl.json
+++ b/Echo/i18n/gl.json
@@ -4,15 +4,18 @@
"Elisardojm",
"Toliño",
"Vivaelcelta",
- "Banjo"
+ "Banjo",
+ "Macofe"
]
},
- "echo-desc": "Sistema para notificar ós usuarios sobre eventos e mensaxes",
+ "echo-desc": "Sistema para notificar aos usuarios sobre eventos e mensaxes",
"prefs-echo": "Notificacións",
"prefs-emailsettings": "Opcións de correo electrónico",
"prefs-displaynotifications": "Opcións de visualización",
"prefs-echosubscriptions": "Notificádeme sobre estes eventos",
+ "prefs-echocrosswiki": "Notificatións entre wikis",
"prefs-newmessageindicator": "Indicador de mensaxe nova",
+ "prefs-blocknotificationslist": "Usuarios ocultados",
"echo-pref-send-me": "Enviádeme:",
"echo-pref-send-to": "Enviar a:",
"echo-pref-email-format": "Formato do correo:",
@@ -24,116 +27,178 @@
"echo-pref-email-frequency-weekly": "Un resumo semanal das notificacións",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Texto simple",
+ "echo-pref-cross-wiki-notifications": "Mostrar as notificacións doutros wikis",
+ "echo-pref-notifications-blacklist": "Non amosar notificacións destes usuarios.\n([[mw:Help:Notifications#mute|Saber máis]])",
"echo-pref-new-message-indicator": "Mostrar o indicador de mensaxe na páxina de conversa na miña barra de ferramentas",
+ "echo-pref-beta-feature-cross-wiki-message": "Notificacións melloradas",
+ "echo-pref-beta-feature-cross-wiki-description": "Ver e organizar as notifiacións máis doadamente. Inclúe as notificacións entre wikis, o que lle permite ver as mensaxes doutros wikis. (Para recibir notificacións desde outros wikis, debe activar a característica beta neses wikis.)",
"echo-learn-more": "Máis información",
+ "echo-log": "Rexistro público",
"echo-new-messages": "Ten mensaxes novas",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mensaxe|Mensaxes}} na páxina de conversa",
"echo-category-title-article-linked": "{{PLURAL:$1|Ligazón|Ligazóns}} a unha páxina",
"echo-category-title-reverted": "{{PLURAL:$1|Reversión|Reversións}} dunha edición",
"echo-category-title-mention": "{{PLURAL:$1|Mención|Mencións}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Mención fallida|Mencións fallidas}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Mención exitosa|Mencións exitosas}}",
"echo-category-title-other": "{{PLURAL:$1|Outra|Outras}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Cambio|Cambios}} nos dereitos de usuario",
- "echo-pref-tooltip-edit-user-talk": "Notificádeme cando alguén deixe unha mensaxe na miña páxina de conversa.",
- "echo-pref-tooltip-article-linked": "Notificádeme cando alguén ligue cunha páxina que creei desde un artigo.",
- "echo-pref-tooltip-reverted": "Notificádeme cando alguén reverta unha edición feita por min usando a ferramenta de reversión ou desfacer.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Correo electrónico doutro usuario|Correos electrónicos doutros usuarios}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Notificación|Notificacións}} de páxinas",
+ "echo-pref-tooltip-edit-user-talk": "Notificádeme cando alguén deixe unha mensaxe ou responda na miña páxina de conversa.",
+ "echo-pref-tooltip-article-linked": "Notificádeme cando alguén engada desde outra páxina unha ligazón cara a unha páxina creada por min.",
+ "echo-pref-tooltip-reverted": "Notificádeme cando alguén reverta unha edición feita por min usando a ferramenta de reversión ou de desfacer.",
"echo-pref-tooltip-mention": "Notificádeme cando alguén ligue cara a miña páxina de usuario.",
+ "echo-pref-tooltip-mention-failure": "Notificádeme cando eu non poida enviar unha mención a alguén.",
+ "echo-pref-tooltip-mention-success": "Notificádeme cando eu envíe unha mención a alguén.",
"echo-pref-tooltip-user-rights": "Notificádeme cando alguén modifique os meus dereitos de usuario.",
- "echo-no-agent": "[Ninguén]",
- "echo-no-title": "[Ningunha páxina]",
+ "echo-pref-tooltip-emailuser": "Notificádeme cando alguén me envíe un correo electrónico.",
+ "echo-pref-tooltip-article-reminder": "Notificarse sobre esta páxina cando pregunte.",
"echo-error-no-formatter": "Non se definiu formato ningún para a notificación",
"notifications": "Notificacións",
"tooltip-pt-notifications-alert": "{{GENDER:|As súas}} alertas",
- "tooltip-pt-notifications-message": "{{GENDER:|As súas}} mensaxes",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Os seus}} avisos",
+ "echo-displaynotificationsconfiguration": "Configuración do visualizador de notificacións",
+ "echo-displaynotificationsconfiguration-summary": "Este é un resumo de como se configuran as notificacións neste wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notificacións por categoría",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Clasificación dos tipos de notificación",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Sección na que se clasifica cada tipo de notificación",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Métodos de notificación permitidos",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Métodos de notificación admitidos para cada categoría",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Métodos de notificación admitidos para cada tipo; só se aplica aos tipos dentro das categorías que están ocultos nas preferencias",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Activadas por defecto",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Usuarios existentes",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Novos usuarios",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Métodos de notificación obrigatorios",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Métodos de notificación obrigatorios para cada categoría",
"echo-specialpage": "Notificacións",
+ "echo-specialpage-section-markread": "Marcar o grupo como lido",
+ "echo-specialpage-markasread": "Notificaciónː Marcar como lida",
+ "echo-specialpage-markasread-invalid-id": "ID de evento incorrecto",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notificación|notificacións}}",
+ "echo-specialpage-pagefilters-title": "Actividade recente",
+ "echo-specialpage-pagefilters-subtitle": "Páxinas con notificacións sen ler",
+ "notificationsmarkread-legend": "Marcar a notificación como lida",
"echo-anon": "Para recibir notificacións, [$1 cree unha conta] ou [$2 acceda ao sistema].",
"echo-none": "Non ten ningunha notificación.",
"echo-more-info": "Máis información",
"echo-feedback": "Comentarios",
+ "echo-popup-footer-special-page-invitation": "<strong>Probar a páxina de notificacións redeseñada.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Aspecto e funcionalidades totalmente novas.",
+ "echo-api-failure": "Erro ao recuperar as notificacións.",
+ "echo-api-failure-cross-wiki": "Denegouse o acceso ao dominio remoto.",
+ "echo-notification-placeholder": "Non hai notificacións.",
+ "echo-notification-placeholder-filters": "Non hai notificacións que coincidan con eses criterios.",
+ "echo-notification-loginrequired": "Debe conectarse para ver as súas notificacións.",
+ "echo-notification-popup-loginrequired": "Por favor, acceda ao sistema para ver as súas notificacións.",
+ "echo-notification-markasread": "Marcar como lida",
+ "echo-notification-markasunread": "Marcar como non lida",
+ "echo-notification-markasread-tooltip": "Marcar como lida",
+ "echo-notification-more-options-tooltip": "Máis opcións",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Deixar}} de vixiar a nova actividade en \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Xa}} non está a vixiar a páxina \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Pode}} vixiar [$2 esta páxina] en calquera momento.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Seguir}} a nova actividade en \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "Agora {{GENDER:$3|está}} vixiando a páxina \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Pode}} deixar de vixiar [$2 esta páxina] en calquera momento.",
+ "notification-link-text-expand-all": "Expandir",
+ "notification-link-text-expand-alert-count": "Ver {{PLURAL:$1|$1 alerta|$1 alertas}}",
+ "notification-link-text-expand-notice-count": "Ver {{PLURAL:$1|$1 aviso|$1 avisos}}",
+ "notification-link-text-expand-all-count": "Ver {{PLURAL:$1|$1 notificación|$1 notificacións}}",
+ "notification-link-text-collapse-all": "Contraer",
"notification-link-text-view-message": "Mostrar a mensaxe",
"notification-link-text-view-mention": "Mostrar a mención",
- "notification-link-text-view-changes": "Mostrar os cambios",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Ver a mención|Ver as mencións}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Ver}} os cambios",
"notification-link-text-view-page": "Mostrar a páxina",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|deixou}} unha mensaxe na <strong>{{GENDER:$3|súa}} páxina de conversa</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|deixou}} unha mensaxe na <strong>{{GENDER:$3|súa}} páxina de conversa</strong> en \"<strong>$4</strong>\".",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Fíxose unha ligazón desde \"<strong>$4</strong>\" a \"<strong>$3</strong>\".",
+ "notification-compact-header-page-linked": "Ligada desde \"<strong>$1</strong>\".",
+ "notification-bundle-header-page-linked": "Fixéronse ligazóns desde {{PLURAL:$5||$5 páxinas|100=máis de 100 páxinas}} cara a \"<strong>$3</strong>\".",
+ "notification-header-article-reminder": "Unha páxina acerca da cal pideu ser {{GENDER:$2|notificado|notificada}} está en <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Todas as ligazóns a esta páxina",
+ "notification-header-mention-other": "$1 {{GENDER:$2|mencionou}}{{GENDER:$3|no|na}} en \"<strong>$4</strong>\" na sección \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|mencionou}}{{GENDER:$3|no|na}} en \"<strong>$4</strong>\".",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|mencionou}}{{GENDER:$3|no|na}} na <strong>páxina de conversa {{GENDER:$5|do usuario|da usuaria}} $4</strong> en \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|mencionou}}{{GENDER:$3|no|na}} na <strong>páxina de conversa {{GENDER:$5|do usuario|da usuaria}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|mencionou}}{{GENDER:$3|no|na}} na <strong>{{GENDER:$2|súa}} páxina de conversa</strong> en \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|mencionou}}{{GENDER:$3|no|na}} na <strong>{{GENDER:$2|súa}} páxina de conversa</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|mencionou}}{{GENDER:$3|no|na}} na sección \"<strong>$5</strong>\" da páxina de conversa de \"<strong>$4</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|mencionou}}{{GENDER:$3|no|na}} na páxina de conversa de \"<strong>$4</strong>\".",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|A súa}} mención de <strong>$3</strong> non se enviou porque non se atopou o usuario.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|A súa}} mención de <strong>$3</strong> non se enviou porque o usuario é anónimo.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Intentou}} mencionar a máis de $3 {{PLURAL:$3|usuario|usuarios}}. Non se enviaron as mencións que superaron ese límite.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Unha mención|$3 mencións}} que {{GENDER:$2|fixo}} na páxina de conversa de <strong>$4</strong> poida que non se {{PLURAL:$3|enviase|enviasen}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>O nome de usuario non existe:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Non se poden mencionar enderezos IP:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|A súa}} mención de <strong>$3</strong> foi enviada.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|A mención|As $3 mencións}} {{GENDER:$2|que fixo}} na páxina de conversa <strong>$4</strong> {{PLURAL:$3|foi enviada|foron enviadas}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Mencionou a}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Unha notificación|$3 notificacións}} sobre mencións {{GENDER:$2|que fixo}} na páxina de conversa <strong>$4</strong>: {{PLURAL:$5|$5 non enviadas}}, {{PLURAL:$6|$6 enviadas}}.",
+ "notification-header-user-rights-add-only": "Os {{GENDER:$4|seus}} dereitos de usuario foron {{GENDER:$1|modificados}}. Pertence agora a: $2.",
+ "notification-header-user-rights-remove-only": "Os {{GENDER:$4|seus}} dereitos de usuario foron {{GENDER:$1|modificados}}. Xa non pertence a: $2.",
+ "notification-header-user-rights-add-and-remove": "Os {{GENDER:$6|seus}} dereitos de usuarios foron {{GENDER:$1|modificados}}. Foi engadido a: $2. Xa non pertence a: $4.",
+ "notification-header-user-rights-expiry-change": "A data de expiración {{GENDER:$4|da}} súa pertenza {{PLURAL:$3|no seguinte grupo|nos seguintes grupos}} foi {{GENDER:$1|modificada}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Benvido|Benvida}} a {{SITENAME}}, $1. Alégranos que esteas aquí.",
+ "notification-welcome-linktext": "Reciba a nosa benvida",
+ "notification-header-thank-you-1-edit": "Acaba de facer {{GENDER:$2|a súa}} primeira edición. Grazas e ¡{{GENDER:$2|benvido|benvida}}!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Acaba}} de facer {{GENDER:$2|a súa}} décima edición en, {{GENDER:$2|grazas}}, e por favor, continúe!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Acaba}} de facer {{GENDER:$2|a súa}} centésima edición, moitas grazas!",
+ "notification-header-thank-you-1000-edit": "Acaba de facer {{GENDER:$2|a súa}} edición número mil. {{GENDER:$2|Grazas}} por ser un gran contribuidor!",
+ "notification-header-thank-you-10000-edit": "Acaba de facer {{GENDER:$2|a súa}} edición número dez mil. Moitísimas {{GENDER:$2|grazas}}!",
+ "notification-header-thank-you-100000-edit": "Acaba de facer {{GENDER:$2|a súa}} edición número cen mil. {{GENDER:$2|Grazas}} pola súa incrible contribución!",
+ "notification-header-thank-you-1000000-edit": "Acaba de facer {{GENDER:$2|a súa}} edición número un millón. {{GENDER:$2|Grazas}} pola súa abraiante contribución!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|A súa}} edición",
"notification-link-text-view-edit": "Mostrar a edición",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|deixou}} unha mensaxe na súa [[User talk:$2#$3|páxina de conversa]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|deixou}} unha mensaxe na súa páxina de conversa na sección \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|deixou}} unha mensaxe na súa [[User talk:$2#$3|páxina de conversa]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|deixou}} unha mensaxe na súa páxina de conversa na sección \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "\"[[:$2]]\" foi {{GENDER:$1|ligada}} desde \"[[:$3]]\". [[Special:WhatLinksHere/$2|Ollar todas as ligazóns cara a esta páxina]].",
- "notification-page-linked-flyout": "\"[[:$2]]\" foi {{GENDER:$1|ligada}} desde \"[[:$3]]\".",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|comentou}} en \"[[$3|$2]]\" na páxina de conversa \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|comezou}} o fío de conversa \"$2\" en \"[[$3]]\"",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|envioulle}} unha mensaxe: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|comentou}} en \"[[$3#$2|$2]]\" na súa páxina de conversa.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|fíxolle}} unha mención na páxina de conversa de \"$5\" na sección \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|fíxolle}} unha mención na páxina de conversa de \"$5\" na sección \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|fíxolle}} unha mención na [[:$3|páxina de conversa de \"$2\"]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|fíxolle}} unha mención na [[:$3|páxina de conversa de \"$2\"]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|mudou}} os seus dereitos de usuario]]. $2. [[Special:ListGroupRights|Máis información]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|mudou}} os seus dereitos de usuario. $2. [[Special:ListGroupRights|Máis información]]",
- "notification-user-rights-add": "Agora pertence a {{PLURAL:$2|este grupo|estes grupos}}: $1",
- "notification-user-rights-remove": "Xa non pertence a {{PLURAL:$2|este grupo|estes grupos}}: $1",
- "notification-new-user": "Dámoslle a benvida a {{SITENAME}}, $1! Alegrámonos de que estea aquí.",
- "notification-reverted2": "[[User:$1|$1]] {{GENDER:$1|reverteu}} {{PLURAL:$4|a súa edición|as súas edicións}} en \"[[:$2]]\" $3",
- "notification-reverted-flyout2": "$1 {{GENDER:$1|reverteu}} {{PLURAL:$4|a súa edición|as súas edicións}} en \"$2\" $3",
+ "notification-link-article-reminder": "Ollar a páxina",
+ "notification-header-reverted": "{{PLURAL:$4|A túa edición en <strong>$3</strong> foi revertida|As túas edicións en <strong>$3</strong> foron {{GENDER:$2|revertidas}}}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|envioulle}} un correo electrónico.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|deixoulle}} unha mensaxe en {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|deixou}} unha mensaxe na súa páxina de conversa.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|deixou}} unha mensaxe na súa páxina de conversa na sección \"$2\"",
"notification-page-linked-email-subject": "Unha páxina creada por vostede foi ligada en {{SITENAME}}",
- "notification-page-linked-email-batch-body": "\"$2\" foi {{GENDER:$1|ligada}} desde \"$3\".",
"notification-reverted-email-subject2": "{{PLURAL:$3|Reverteuse a súa edición|Revertéronse as súas edicións}} {{GENDER:$1|en}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "$1 {{GENDER:$1|reverteu}} {{PLURAL:$3|a súa edición|as súas edicións}} en \"$2\"",
- "notification-mention-email-subject": "$1 {{GENDER:$1|fíxolle}} unha mención en {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|fíxolle}} unha mención na páxina de conversa de \"$4\" na sección \"$3\"",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|fíxolle}} unha mención na páxina de conversa de \"$2\".",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|fíxolle}} unha {{GENDER:$2|mención}} en {{SITENAME}}",
"notification-user-rights-email-subject": "Os seus dereitos de usuario cambiaron en {{SITENAME}}",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|mudou}} os seus dereitos de usuario. $2",
- "echo-email-subject-default": "Nova notificación en {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mes|$1 meses}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 ano|$1 anos}}",
+ "notification-timestamp-today": "Hoxe",
+ "notification-timestamp-yesterday": "Onte",
+ "notification-inbox-filter-read": "Lidas",
+ "notification-inbox-filter-unread": "Non lidas",
+ "notification-inbox-filter-all": "Todas",
"echo-email-body-default": "Ten unha nova notificación en {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Ten unha nova notificación",
+ "echo-email-footer-default-html": "Para controlar que correos electrónicos lle enviamos, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">revise as súas preferenzas</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nPara controlar os correos electrónicos que lle enviamos, comprobe as súas preferencias:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Para controlar os correos electrónicos que lle enviamos, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">comprobe as súas preferencias</a><br />\n$1",
+ "echo-email-plain-footer": "Para controlar os emais que {{GENDER:$1|lle}} mandamos, {{GENDER:$1|revise}} as súas preferenciasː",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|comprobe}} as súas preferencias",
+ "echo-email-html-footer-with-link": "Para controlar que correos electrónicos {{GENDER:$2|lle}} enviamos, $1.",
"echo-notification-alert": "{{PLURAL:$1|Alertas ($1)|100=Alertas (máis de 99)}}",
- "echo-notification-message": "{{PLURAL:$1|Mensaxes ($1)|100=Mensaxes (máis de 99)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Aviso ($1)|Avisos ($1)|100=Avisos (99+)}}",
"echo-notification-alert-text-only": "Alertas",
- "echo-notification-message-text-only": "Mensaxes",
+ "echo-notification-notice-text-only": "Avisos",
"echo-overlay-link": "Todas as notificacións",
"echo-overlay-title": "<b>Notificacións</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificación|Notificacións}}</b> (mostrando $1 de $2 sen ler)",
"echo-mark-all-as-read": "Marcar todo como lido",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notificación marcada como lida|notificacións marcadas como lidas}}",
+ "echo-mark-wiki-as-read": "Marcar todas como lidas na wiki seleccionada: $1",
"echo-date-today": "Hoxe",
"echo-date-yesterday": "Onte",
"echo-load-more-error": "Houbo un erro ao procurar máis resultados.",
- "notification-edit-talk-page-bundle": "$1 e {{PLURAL:$4|outra persoa|$3 persoas máis}} {{GENDER:$1|deixaron}} mensaxes na súa [[User talk:$2|páxina de conversa]].",
- "notification-page-linked-bundle": "\"$2\" foi {{GENDER:$1|ligada}} desde \"$3\" e $4 {{PLURAL:$5|páxina|páxinas}} máis. [[Special:WhatLinksHere/$2|Ollar todas as ligazóns cara a esta páxina]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e {{PLURAL:$3|outra persoa|$2 persoas máis}} {{GENDER:$1|deixaron}} mensaxes na súa páxina de conversa",
- "notification-page-linked-email-batch-bundle-body": "\"$2\" foi {{GENDER:$1|ligada}} desde \"$3\" e {{PLURAL:$5|outra páxina|$4 páxinas máis}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Mensaxe nova|$1 mensaxes novas|100=Máis de 99 mensaxes novas}} na <strong>{{GENDER:$3|súa}} páxina de conversa</strong>.",
"echo-email-batch-subject-daily": "Ten {{PLURAL:$2|unha nova notificación|novas notificacións}} en {{SITENAME}}",
"echo-email-batch-subject-weekly": "Esta semana ten {{PLURAL:$2|unha nova notificación|novas notificacións}} en {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Boas, $1:\nVelaquí ten un resumo da actividade de hoxe en {{SITENAME}}",
"echo-email-batch-body-intro-weekly": "Boas, $1:\nVelaquí ten un resumo da actividade da semana en {{SITENAME}}",
"echo-email-batch-link-text-view-all-notifications": "Ollar todas as notificacións",
- "echo-rev-deleted-text-view": "Eliminouse a revisión da páxina",
- "apihelp-echomarkread-description": "Marcar notificacións coma lidas para o usuario actual.",
- "apihelp-echomarkread-param-list": "Lista de identificadores de notificacións a marcar coma lidas.",
- "apihelp-echomarkread-param-all": "Si se establece, marca todas as notificacións dun usuario como lidas.",
- "apihelp-echomarkread-param-sections": "Unha lista das seccións a marcar como lidas.",
- "apihelp-echomarkread-example-1": "Marcar a notificación 8 coma lida",
- "apihelp-echomarkread-example-2": "Marcar tódalas notificacións como lidas",
- "apihelp-echomarkseen-description": "Marcar notificacións coma lidas para o usuario actual.",
- "apihelp-echomarkseen-example-1": "Marcar notificacións de todos os tipos como lidas",
- "apihelp-echomarkseen-param-type": "Tipo de notificacións para marcar como lidas: 'alert' (alerta), 'message' (mensaxe) ou 'all' (todas).",
- "apihelp-query+notifications-description": "Obter notificacións de espera para o usuario actual.",
- "apihelp-query+notifications-param-prop": "Detalles que solicitar.",
- "apihelp-query+notifications-param-sections": "As seccións de notificación a consultar (p.ex. algunha combinación de 'alerta' e 'mensaxe').",
- "apihelp-query+notifications-param-groupbysection": "Si se agrupan os resultados por sección. Cada sección obtense por separado si así se establece.",
- "apihelp-query+notifications-param-format": "Si se especifica, as notificacións devolveranse neste formato.",
- "apihelp-query+notifications-param-limit": "Número máximo de notificacións a retornar.",
- "apihelp-query+notifications-param-index": "Si se especifica, devolverase unha lista ordenada de identificadores de notificación.",
- "apihelp-query+notifications-param-alertcontinue": "Cando estean dispoñibles alertas adicionais, use esta opción para continuar.",
- "apihelp-query+notifications-param-alertunreadfirst": "Mostra as notificacións de mensaxes sen ler primeiro.",
- "apihelp-query+notifications-param-messagecontinue": "Cando novos mensaxes estean dispoñibles, use esta opción para continuar.",
- "apihelp-query+notifications-param-messageunreadfirst": "Mostra as notificacións de alertas sen ler primeiro.",
- "apihelp-query+notifications-example-1": "Listar notificacións",
- "apihelp-query+notifications-example-2": "Lista de notificacións, agrupadas por sección, incluíndo contadores"
+ "notification-header-foreign-alert": "Máis alertas {{PLURAL:$5|doutro wiki|doutros $5 wikis}}",
+ "notification-header-foreign-notice": "Máis avisos {{PLURAL:$5|doutro wiki|doutros $5 wikis}}",
+ "notification-header-foreign-all": "Máis notificacións {{PLURAL:$5|doutra wiki|doutras $5 wikis}}"
}
diff --git a/Echo/i18n/glk.json b/Echo/i18n/glk.json
new file mode 100644
index 00000000..eadd36b9
--- /dev/null
+++ b/Echo/i18n/glk.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "شیخ"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|شيمي}} واخؤ گۊدنؤن",
+ "tooltip-pt-notifications-message": "{{GENDER:|شيمي}} پىغامؤن"
+}
diff --git a/Echo/i18n/gn.json b/Echo/i18n/gn.json
index eb5d352e..24d187ae 100644
--- a/Echo/i18n/gn.json
+++ b/Echo/i18n/gn.json
@@ -19,7 +19,6 @@
"echo-no-agent": "[Mavave]",
"echo-no-title": "[Ndaipóri Kuatirogue]",
"notifications": "Maranduha",
- "tooltip-pt-notifications": "Nde maranduha",
"echo-specialpage": "Maranduha",
"echo-none": "Nderereko maranduha pyahu.",
"echo-more-info": "Maranduve",
diff --git a/Echo/i18n/gom-deva.json b/Echo/i18n/gom-deva.json
index 30b511f3..978e4085 100644
--- a/Echo/i18n/gom-deva.json
+++ b/Echo/i18n/gom-deva.json
@@ -2,8 +2,13 @@
"@metadata": {
"authors": [
"Darshan kandolkar",
- "The Discoverer"
+ "The Discoverer",
+ "Vaishali Parab"
]
},
- "tooltip-pt-notifications": "तुमच्यो कळवण्यो"
+ "notification-timestamp-today": "आयज",
+ "notification-timestamp-yesterday": "काल",
+ "notification-inbox-filter-read": "वाचचें",
+ "notification-inbox-filter-unread": "वाचूंक नाशिल्ले",
+ "notification-inbox-filter-all": "सगळें"
}
diff --git a/Echo/i18n/gom-latn.json b/Echo/i18n/gom-latn.json
index 4ba9aa7e..c214742f 100644
--- a/Echo/i18n/gom-latn.json
+++ b/Echo/i18n/gom-latn.json
@@ -4,5 +4,11 @@
"The Discoverer"
]
},
- "tooltip-pt-notifications-alert": "{{GENDER:|Tujeo}} chotraio"
+ "tooltip-pt-notifications-alert": "{{GENDER:|Tujeo}} chotraio",
+ "tooltip-pt-notifications-message": "{{GENDER:|Tujeo}} sondex",
+ "notification-timestamp-today": "Aiz",
+ "notification-timestamp-yesterday": "Kal",
+ "notification-inbox-filter-read": "Vach",
+ "notification-inbox-filter-unread": "Vachunk naslele",
+ "notification-inbox-filter-all": "Sogllem"
}
diff --git a/Echo/i18n/gor.json b/Echo/i18n/gor.json
new file mode 100644
index 00000000..89f3b784
--- /dev/null
+++ b/Echo/i18n/gor.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Marwan Mohamad"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "Mopo'ota {{GENDER:|Yi'o}}",
+ "tooltip-pt-notifications-message": "Tahuli {{GENDER:|Yi'o}}"
+}
diff --git a/Echo/i18n/grc.json b/Echo/i18n/grc.json
new file mode 100644
index 00000000..7ddc3f37
--- /dev/null
+++ b/Echo/i18n/grc.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gts-tg"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "Αἴ {{GENDER:|ὐμετέραι}} ἐιδοποιήσεις",
+ "tooltip-pt-notifications-message": "Αἴ {{GENDER:|ὐμέτεραι}} ἀγγέλματα"
+}
diff --git a/Echo/i18n/gsw.json b/Echo/i18n/gsw.json
index 091d0905..24fe4087 100644
--- a/Echo/i18n/gsw.json
+++ b/Echo/i18n/gsw.json
@@ -34,12 +34,9 @@
"echo-pref-tooltip-reverted": "Hiwyse, wen en Änderig vo mir isch rückgängig gmacht oder zrügggsetzt worde.",
"echo-pref-tooltip-mention": "Hiwyse, we öpper e Link uf mys Konto (Benutzersyte) het gschribe.",
"echo-pref-tooltip-user-rights": "Hiwyse, we myni Berächtigunge hei g’änderet.",
- "echo-no-agent": "[Niemer]",
- "echo-no-title": "[Kei Syte]",
"echo-error-no-formatter": "Formatierig füre Hiwys fählt.",
"notifications": "Hiwyse",
"tooltip-pt-notifications-alert": "{{GENDER:|Dyni}} Hiwyse",
- "tooltip-pt-notifications-message": "{{GENDER:|Dyni}} Nachrichte",
"echo-specialpage": "Hiwyse",
"echo-anon": "Für Hiwyse z übercho, muesch di [$1 registrieren] oder [$2 amälde].",
"echo-none": "Du hesch kener Hiwyse.",
@@ -50,48 +47,17 @@
"notification-link-text-view-changes": "Änderigen aluege",
"notification-link-text-view-page": "Syten aluege",
"notification-link-text-view-edit": "Änderig aluege",
- "notification-edit-talk-page2": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het dir e Nachricht gschriben uf [[User talk:$2#$3|dyre Diskussion]].",
- "notification-edit-talk-page-with-section": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het dir uf dyre Diskussion e Nachricht gschribe zum Thema «[[User talk:$2#$3|$4]]».",
- "notification-edit-talk-page-flyout2": "{{GENDER:$1|Der $1|D $1|$1}} het dir e Nachricht gschriben uf [[User talk:$2#$3|dyre Diskussion]].",
- "notification-edit-talk-page-flyout-with-section": "{{GENDER:$1|Der $1|D $1|$1}} het dir uf dyre Diskussion e Nachricht gschribe zum Thema «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "{{GENDER:$1|Der $1|D $1|$1}} het uf [[:$3]] e Link uf dyni Syte [[:$2]] ygfüegt. [[Special:WhatLinksHere/$2|Alli Links uf $2 aluege]].",
- "notification-page-linked-flyout": "{{GENDER:$1|Der $1|D $1|$1}} het uf [[:$3]] e Link uf dyni Syte [[:$2]] ygfüegt.",
- "notification-add-comment2": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het uf der Diskussion vo $4 e Kommentar zum Abschnitt «[[$3|$2]]» gschribe.",
- "notification-add-talkpage-topic2": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het uf der Diskussion vo [[$3]] der Abschnitt «$2» ufta.",
- "notification-add-talkpage-topic-yours2": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het der e Nachricht gschickt: «[[$3#$2|$2]]».",
- "notification-add-comment-yours2": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het uf dyre Diskussion e Kommentar zum Abschnitt «[[$3#$2|$2]]» gschribe.",
- "notification-mention": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het di uf der Diskussion vo $5 im Abschnitt «[[:$3#$2|$4]]» erwähnt.",
- "notification-mention-flyout": "{{GENDER:$1|Der $1|D $1|$1}} het di uf der Diskussion vo «$5» im Abschnitt «[[:$3#$2|$4]]» erwähnt.",
- "notification-mention-nosection": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het di uf der [[:$3|Diskussion vo «$2»]] erwähnt.",
- "notification-mention-nosection-flyout": "{{GENDER:$1|Der $1|D $1|$1}} het di uf der [[:$3|Diskussion vo «$2»]] erwähnt.",
- "notification-user-rights": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het dyni [[Special:Log/rights/$1|Berächtigunge g’änderet]]. $2. [[Special:ListGroupRights|Meh lehre]]",
- "notification-user-rights-flyout": "{{GENDER:$1|Der $1|D $1|$1}} het dyni Berächtigunge g’änderet. $2. [[Special:ListGroupRights|Meh lehre]]",
- "notification-user-rights-add": "Du bisch itz Mitglid {{PLURAL:$2|vor|vo de}} Gruppe $1",
- "notification-user-rights-remove": "Du bisch nümm Mitglid {{PLURAL:$2|vor|vo de}} Gruppe $1",
- "notification-new-user": "{{GENDER:$1|Liebe $1|Liebi $1|Hallo $1}} – willkomme by {{SITENAME}}! Mir fröüen üs, das d’ mitmachsch.",
- "notification-reverted2": "{{GENDER:$1|Der [[User:$1|$1]]|D [[User:$1|$1]]|[[User:$1|$1]]}} het {{PLURAL:$4|dyni Veränderig|dyni Veränderigen}} ar Syte [[:$2]] rückgängig gmacht. $3",
- "notification-reverted-flyout2": "{{GENDER:$1|Der $1|D $1|$1}} het dyni {{PLURAL:$4|Änderig|Änderigen}} ar Syte $2 rückgängig gemacht. $3",
+ "notification-header-reverted": "{{GENDER:$2|Der $1|D $1|$1}} het dyni {{PLURAL:$4|Änderig|Änderigen}} ar Syte $3 rückgängig gemacht.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|Der $1|D $1|$1}} het der e Nachricht uf {{SITENAME}} gschribe",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|Der $1|D $1|$1}} het dir e Nachricht uf dyre Diskussion gschribe.",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Der $1|D $1|$1}} het uf dyre Diskussion e Nachricht über «$2» gschribe.",
"notification-page-linked-email-subject": "E Syte vo dir het uf {{SITENAME}} e Link übercho",
- "notification-page-linked-email-batch-body": "Dyni Syte $2 het {{GENDER:$1|vom $1|vor $1|vo $1}} e Link übercho, und zwar vo $3 uus.",
"notification-reverted-email-subject2": "{{GENDER:$1|Der $1|D $1|$1}} het {{PLURAL:$3|e Veränderig|Veränderige}} vo dir uf {{SITENAME}} rückgängig gmacht",
- "notification-reverted-email-batch-body2": "{{GENDER:$1|Der $1|D $1|$1}} het dyni {{PLURAL:$3|Veränderig|Veränderige}} vo $2 rückgängig gmacht.",
"notification-mention-email-subject": "{{GENDER:$1|Der $1|D $1|$1}} het di uf {{SITENAME}} erwähnt",
- "notification-mention-email-batch-body": "{{GENDER:$1|Der $1|D $1|$1}} het di uf der Diskussion vo $4 im Abschnitt «$3» erwähnt.",
- "notification-mention-nosection-email-batch-body": "{{GENDER:$1|Der $1|D $1|$1}} het di uf der Diskussion vo $2 erwähnt.",
- "notification-user-rights-email-subject": "Dyni Rächt uf {{SITENAME}} hei g’änderet",
- "notification-user-rights-email-batch-body": "{{GENDER:$1|Der $1|D $1|$1}} het dyni Rächt g’änderet. $2.",
- "echo-email-subject-default": "Nöüe Hiwys uf {{SITENAME}}",
+ "notification-user-rights-email-subject": "Dyni Rächt uf {{SITENAME}} hei gänderet",
"echo-email-body-default": "Du hesch e nöüe Hiwys uf {{SITENAME}} übercho:\n\n$1",
- "echo-email-batch-body-default": "Du hesch e nöüe Hiwys übercho.",
"echo-email-footer-default": "$2\n\nDu chasch i dynen Ystellige bestimme, weli Hiwyse das du per E-Mail überchunsch:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Du chasch i dyne <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">Hiwys-Ystellige</a> bestimme, was du für E-Mails überchunsch.<br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|Ei Hiwys|$1 Hiwyse|100=Hiwyse (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Ei Nachricht|$1 Nachrichte|100=Nachrichte (99+)}}",
"echo-notification-alert-text-only": "Hiwyse",
- "echo-notification-message-text-only": "Nachrichte",
"echo-overlay-link": "Alli Hiwyse",
"echo-overlay-title": "<b>Hiwyse</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Hiwys|Hiwyse}}</b> ($1 {{PLURAL:$1|Hiwys vo $2 ungläsnige wird|Hiwyse vo $2 ungläsnige wärden}} azeigt)",
@@ -99,19 +65,9 @@
"echo-date-today": "Hüt",
"echo-date-yesterday": "Gester",
"echo-load-more-error": "Bim Abrüeffe vo de Resultat het’s e Fähler ’gä.",
- "notification-edit-talk-page-bundle": "{{GENDER:$1|Der $1|D $1|$1}} u {{PLURAL:$4|öpper anders|$3 anderi}} hei der e Nachricht uf [[User talk:$2|dyre Diskussion]] gschribe.",
- "notification-page-linked-bundle": "Dyni Syte $2 het {{GENDER:$1|vom $1|vor $1|vo $1}} e Link übercho, und zwar vo $3 und {{PLURAL:$5|eiren andere Syten|$4 andere Syten}} uus. [[Special:WhatLinksHere/$2|Alli Links uf $2 aluege]]",
- "notification-edit-user-talk-email-batch-bundle-body": "{{GENDER:$1|Der $1|D $1|$1}} u {{PLURAL:$3|öpper anders|$2 anderi}} hei der e Nachricht uf dyre Diskussion gschribe.",
- "notification-page-linked-email-batch-bundle-body": "Dyni Syte $2 het {{GENDER:$1|vom $1|vor $1|vo $1}} e Link übercho, und zwar vo $3 und {{PLURAL:$5|eiren andere Syten|$4 andere Syten}} uus.",
"echo-email-batch-subject-daily": "Du hesch {{PLURAL:$2|e nöüe Hiwys|nöüi Hiwysen}} uf {{SITENAME}}",
"echo-email-batch-subject-weekly": "Du hesch {{PLURAL:$2|e nöüe Hiwys|nöüi Hiwysen}} us der letste Wuchen uf {{SITENAME}}",
"echo-email-batch-body-intro-daily": "{{GENDER:$1|Liebe $1|Liebi $1|Hallo $1}}\n\nHie isch e Zämefassig vo den Ereignis hüt uf {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "{{GENDER:$1|Liebe $1|Liebi $1|Hallo $1}}\n\nHie isch e Zämefassig vo den Ereignis die Wuchen uf {{SITENAME}}.",
- "echo-email-batch-link-text-view-all-notifications": "Alli Hiwysen aluege",
- "echo-rev-deleted-text-view": "Die Version isch gsperrt.",
- "apihelp-echomarkread-description": "Hiwyse für das Konto (Benutzerin oder Benutzer) als gläse markiere.",
- "apihelp-echomarkread-param-all": "Falls festgleit, alli Hiwyse vomene Konto (Benutzerin oder Benutzer) als gläse markiere.",
- "apihelp-echomarkread-param-sections": "A Liste vo den Abschnitte, wo als gläse sölle markiert wärde.",
- "apihelp-echomarkread-example-1": "Hiwys 8 als gläse markiere",
- "apihelp-echomarkread-example-2": "Alli Hiwysen als gläse markiere"
+ "echo-email-batch-link-text-view-all-notifications": "Alli Hiwysen aluege"
}
diff --git a/Echo/i18n/gu.json b/Echo/i18n/gu.json
index 6a9d4f1a..a795aafb 100644
--- a/Echo/i18n/gu.json
+++ b/Echo/i18n/gu.json
@@ -4,14 +4,16 @@
"Dsvyas",
"KartikMistry",
"Rangilo Gujarati",
- "NehalDaveND"
+ "NehalDaveND",
+ "Drashti4"
]
},
- "echo-desc": "સૂચના સિસ્ટમ",
+ "echo-desc": "સભ્યોને ઘટનાઓ અને સંદેશાઓનું સૂચન કરતી સેવા",
"prefs-echo": "સૂચનાઓ",
- "prefs-emailsettings": "ઈમેઇલ વિકલ્પો",
+ "prefs-emailsettings": "ઈમેલ વિકલ્પો",
"prefs-displaynotifications": "પ્રદર્શન વિકલ્પો",
"prefs-echosubscriptions": "મને આ ઘટનાઓ વિશે જાણ કરવી",
+ "prefs-echocrosswiki": "આંતર-વિકિ સૂચનાઓ",
"prefs-newmessageindicator": "નવો સંદેશ સૂચક",
"echo-pref-send-me": "મને મોકલો:",
"echo-pref-send-to": "આને મોકલો:",
@@ -24,68 +26,73 @@
"echo-pref-email-frequency-weekly": "સૂચનાઓનો સાપ્તાહિક સારાંશ",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "સાદું લખાણ",
+ "echo-pref-cross-wiki-notifications": "અન્ય વિકિ પરની સૂચનાઓ દર્શાવો",
"echo-pref-new-message-indicator": "ચર્ચા પાનાઓની સૂચનાઓ મારી સાધનપટ્ટીમાં દેખાડવી",
"echo-learn-more": "વધુ જાણો",
+ "echo-log": "જાહેર નોંધ",
"echo-new-messages": "તમારા માટે નવા સંદેશાઓ છે",
"echo-category-title-edit-user-talk": "ચર્ચા પાનું {{PLURAL:$1|સંદેશ|સંદેશાઓ}}",
"echo-category-title-article-linked": "પાનું {{PLURAL:$1|કડી|કડીઓ}}",
- "echo-category-title-reverted": "{{PLURAL:$1|ઉલટાવેલ|ઉલટાવેલા}} ફેરફાર કરો",
+ "echo-category-title-reverted": "{{PLURAL:$1|ઉલટાવેલ|ઉલટાવેલા}} ફેરફાર",
"echo-category-title-mention": "{{PLURAL:$1|ઉલ્લેખ|ઉલ્લેખો}}",
+ "echo-category-title-mention-failure": "અસફળ {{PLURAL:$1|ઉલ્લેખ|ઉલ્લેખો}}",
+ "echo-category-title-mention-success": "સફળ {{PLURAL:$1|ઉલ્લેખ|ઉલ્લેખો}}",
"echo-category-title-other": "{{PLURAL:$1|અન્ય}}",
"echo-category-title-system": "{{PLURAL:$1|સિસ્ટમ}}",
- "echo-pref-tooltip-edit-user-talk": "નવાં સંદેશા કે ચર્ચા પાનાનાં ફેરફાર પર મને સૂચન કરવું.",
- "echo-pref-tooltip-article-linked": "જ્યારે કોઇ મારા દ્વારા બનાવવામાં આવેલ લેખને કોઈ જગ્યાએ જોડવામાં આવે ત્યારે મને જાણ કરવી.",
- "echo-pref-tooltip-reverted": "જ્યારે કોઈ મારું સંપાદન રદ કરે કે કોઈ રોલબેક ઉપકરણ વાપરે ત્યારે મને જાણ કરવી.",
- "echo-pref-tooltip-mention": "મારા સભ્ય પાનાને જ્યારે કોઈ જોડે ત્યારે મને જાણ કરવી.",
- "echo-no-agent": "[કોઈ નહી]",
- "echo-no-title": "[કોઈ પાનું નહી]",
+ "echo-pref-tooltip-edit-user-talk": "જ્યારે કોઇ મારા ચર્ચા પાના પર સંદેશ મૂકે કે જવાબ આપે ત્યારે સૂચના મોકલો.",
+ "echo-pref-tooltip-article-linked": "જ્યારે કોઇ મારા દ્વારા બનાવવામાં આવેલ લેખ સાથે કોઇ કડી કરે ત્યારે સૂચના મોકલો.",
+ "echo-pref-tooltip-reverted": "જ્યારે કોઈ મારું સંપાદન રદ કરે કે કોઈ રોલબેક ઉપકરણ વાપરે ત્યારે મને સૂચના મોકલો.",
+ "echo-pref-tooltip-mention": "મારા સભ્ય પાનાને જ્યારે કોઈ કડી વડે જોડે ત્યારે સૂચના મોકલો.",
"echo-error-no-formatter": "સૂચનાઓ માટે કોઈ માળખું નિયત નથી કર્યું.",
"notifications": "સૂચનાઓ",
"tooltip-pt-notifications-alert": "{{GENDER:|તમારી}} ચેતવણીઓ",
- "tooltip-pt-notifications-message": "{{GENDER:|તમારા}} સંદેશાઓ",
+ "tooltip-pt-notifications-notice": "{{GENDER:|તમારી}} સૂચનાઓ",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "નવા સભ્યો",
"echo-specialpage": "સૂચનાઓ",
"echo-anon": "સૂચનાઓ પ્રાપ્ત કરવા, [$1 નવું ખાતું ખોલો] અથવા [$2 પ્રવેશ કરો].",
"echo-none": "તમારા માટે કોઈ સૂચનાઓ નથી.",
"echo-more-info": "વધારે જાણકારી",
"echo-feedback": "અભિપ્રાય",
+ "echo-notification-placeholder": "કોઇ નવી સૂચનાઓ નથી.",
+ "echo-notification-markasread": "વાંચેલી તરીકે અંકિત કરો",
+ "echo-notification-markasunread": "ન વાંચેલી તરીકે અંકિત કરો",
+ "echo-notification-markasread-tooltip": "વાંચેલી તરીકે અંકિત કરો",
+ "echo-notification-more-options-tooltip": "વધુ વિકલ્પો",
+ "notification-link-text-expand-all": "વિસ્તૃત કરો",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|$1 સૂચના|$1 સૂચનાઓ}} જુઓ",
+ "notification-link-text-collapse-all": "સંકેલો",
"notification-link-text-view-message": "સંદેશ જુઓ",
"notification-link-text-view-mention": "ઉલ્લેખ જુઓ",
- "notification-link-text-view-changes": "ફેરફારો જુઓ",
+ "notification-link-text-view-changes": "ફેરફારો {{GENDER:$1|જુઓ}}",
"notification-link-text-view-page": "પાનું જુઓ",
+ "notification-link-text-what-links-here": "આ પાનાંની બધી કડીઓ",
+ "notification-welcome-linktext": "સ્વાગત",
+ "notification-link-thank-you-edit": "{{GENDER:$1|તમારો}} ફેરફાર",
"notification-link-text-view-edit": "ફેરફાર જુઓ",
- "notification-edit-talk-page2": "[[User:$1|$1]]એ તમારાં [[User talk:$2#$3|ચર્ચા પાનાં]] પર સંદેશો {{GENDER:$1|છોડ્યો}} છે.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]]એ તમારા ચર્ચા પાનાંમાં \"[[User talk:$2#$3|$4]]\" પર સંદેશો {{GENDER:$1|છોડ્યો}} છે.",
- "notification-edit-talk-page-flyout2": "$1એ તમારા [[User talk:$2#$3|ચર્ચા પાનાં]] પર સંદેશો {{GENDER:$1|છોડયો}} છે.",
- "notification-edit-talk-page-flyout-with-section": "$1એ તમારા \"[[User talk:$2#$3|$4]]\" ચર્ચા પાનાં પર સંદેશો {{GENDER:$1|છોડયો}} છે.",
- "notification-page-linked": "{{GENDER:$1|linked}} દ્વારા [[:$2]], [[:$3]] પર જોડવામાં આવેલું. [[Special:WhatLinksHere/$2|આ પાનાંને સમ્બોધતી બધી કડીઓ જુઓ]].",
- "notification-page-linked-flyout": "[[:$2]]ને [[:$3]] સાથે {{GENDER:$1|જોડ્યું છે}}.",
- "notification-add-comment2": "[[User:$1|$1]]એ \"$4\"નાં \"[[$3|$2]]\" પર {{GENDER:$1|સંદેશો છોડ્યો}}.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]]એ [[$3]] પર નવો વિશય \"$2\" {{GENDER:$1|ચાલૂ કર્યો}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]]એ તમને નવો સંદેશો {{GENDER:$1|મોકલ્યો}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]]એ \"[[$3#$2|$2]]\" પર {{GENDER:$1|ટીપ્પણી કરી}}.",
- "notification-mention": "[[User:$1|$1]]એ $5નાં ચર્ચાનાં પાને \"[[:$3#$2|$4]]\"માં તમારો {{GENDER:$1|ઉલ્લેખ કર્યો છે}}.",
- "notification-mention-flyout": "$1એ $5નાં ચર્ચાનાં પાને \"[[:$3#$2|$4]]\"માં તમારો {{GENDER:$1|ઉલ્લેખ કર્યો છે}}.",
- "notification-user-rights-flyout": "તમારા સભ્ય હક્કો $1એ {{GENDER:$1|બદલ્યા}} છે. $2.\n[[Special:ListGroupRights|વધુ જાણો]]",
- "notification-user-rights-add": "તમે હવે {{PLURAL:$2|આ જુથ|આ જુથો}}ના સભ્ય છો: $1",
- "notification-user-rights-remove": "હવે તમે {{PLURAL:$2|આ જુથ|આ જુથો}}ના સભ્ય રહ્યા નથી: $1",
- "notification-new-user": "$1 તમારું {{SITENAME}} પર સ્વાગત છે! તમને અહીં જોઇ અમે આનંદિત થયા છીએ.",
- "notification-reverted2": "{{PLURAL:$4|[[:$2]] પરનો તમારો ફેરફાર|[[:$2]] પરના તમારા ફેરફારો}} [[User:$1|$1]]એ {{GENDER:$1|{{PLURAL|પાછો વાળ્યો|પાછા વાળ્યા}} છે}}. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|$2 પરનો તમારો ફેરફાર|$2 પરના તમારા ફેરફારો}} $1એ {{GENDER:$1|પૂર્વવત્}} કરેલ છે. $3",
- "notification-edit-talk-page-email-subject2": "{{SITENAME}} પર તમારા માટે $1એ {{GENDER:$1|સંદેશો}} મૂક્યો છે.",
- "notification-edit-talk-page-email-batch-body2": "$1એ તમારા ચર્ચાનાં પાને {{GENDER:$1|સંદેશો}} મૂક્યો છે.",
- "notification-edit-talk-page-email-batch-body-with-section": "$1એ તમારા ચર્ચાનાં પાને ''$2'' હેઠળ તમારા માટે {{GENDER:$1|સંદેશો}} મૂક્યો છે.",
+ "notification-link-article-reminder": "પાનું જુઓ",
+ "notification-header-reverted": "{{PLURAL:$4|<strong>$3</strong> પરનો ફેરફાર|<strong>$3</strong> પરના ફેરફારો}} {{GENDER:$2|પૂર્વવત}} કરવામાં આવેલ છે .",
+ "notification-header-emailuser": "$1 તમને ઇમેલ {{GENDER:$2|મોકલ્યો}}.",
+ "notification-edit-talk-page-email-subject2": "{{SITENAME}} પર તમારા માટે $1એ સંદેશ {{GENDER:$1|મૂક્યો}} છે.",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1એ તમારા ચર્ચાનાં પાને ''$2'' હેઠળ તમારા માટે સંદેશો {{GENDER:$1|મૂક્યો}} છે.",
"notification-page-linked-email-subject": "તમારુ પાનાની કડી {{SITENAME}} પર જોડવામાં આવી",
- "notification-page-linked-email-batch-body": "$2ને $3 સાથે {{GENDER:$1|જોડ્યું}} હતું,",
- "notification-reverted-email-subject2": "{{SITENAME}} પર {{PLURAL:$3|તમારો ફેરફાર|તમારા ફેરફારો}} {{GENDER:$1|{{PLURAL|પાછો વાળ્યો|પાછા વાળ્યા}} છે}}.",
- "notification-mention-email-subject": "$1એ {{SITENAME}} પર તમારો {{GENDER:$1|ઉલ્લેખ}} કર્યો છે.",
- "notification-mention-nosection-email-batch-body": "$2 ચર્ચા પાનાં પર $1 એ તમારો {{GENDER:$1|ઉલ્લેખ}} કર્યો.",
- "notification-user-rights-email-subject": "તમારાં {{SITENAME}} પરનાં અધિકારો બદલાયા છે.",
- "notification-user-rights-email-batch-body": "તમારા સભ્ય અધિકારો {{GENDER:$1|દ્વારા}} બદલાવવમાં આવ્યા છે. $2",
- "echo-email-subject-default": "{{SITENAME}} પર નવી સૂચના",
+ "notification-reverted-email-subject2": "{{SITENAME}} પર {{PLURAL:$3|તમારો ફેરફાર|તમારા ફેરફારો}} {{GENDER:$1|પાછો વાળ્યો|પાછા વાળ્યા}} છે.",
+ "notification-mention-email-subject": "$1એ {{SITENAME}} પર {{GENDER:$2|તમારો}} {{GENDER:$1|ઉલ્લેખ}} કર્યો છે",
+ "notification-user-rights-email-subject": "તમારાં {{SITENAME}} પરનાં અધિકારો બદલાયા છે",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1કલાક}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1દિવસ}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mo}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1વર્ષ}}",
+ "notification-timestamp-today": "આજે",
+ "notification-timestamp-yesterday": "ગઈ કાલે",
+ "notification-inbox-filter-read": "વંચાયેલ",
+ "notification-inbox-filter-unread": "ન વંચાયેલ",
+ "notification-inbox-filter-all": "બધું",
"echo-email-body-default": "તમારા માટે {{SITENAME}} પર નવી સૂચના છે:\n\n$1",
- "echo-email-batch-body-default": "તમને નવો સંદેશ આવેલો છે",
- "echo-notification-alert-text-only": "ચેતવણી:",
- "echo-notification-message-text-only": "સંદેશાઓ",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|તમારી}} પસંદગીઓ ચકાસો",
+ "echo-notification-alert-text-only": "ચેતવણીઓ",
+ "echo-notification-notice-text-only": "સૂચનાઓ",
"echo-overlay-link": "બધી સૂચનાઓ",
"echo-overlay-title": "<b>સૂચનાઓ</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|સુચનાઓ}}</b> ($2 પૈકીની નહિવાંચેલી $1 દર્શાવી છે)",
@@ -97,6 +104,5 @@
"echo-email-batch-subject-weekly": "આ અઠવાડીએ {{SITENAME}} પર તમારા માટે {{PLURAL:$2|નવી સુચના|નવી સુચનાઓ}} છે",
"echo-email-batch-body-intro-daily": "નમસ્કાર $1,\n{{SITENAME}} પર તમારી ક્રિયાઓનો આજનો સારાંશ આ પ્રમાણે છે.",
"echo-email-batch-body-intro-weekly": "નમસ્કાર $1,\n{{SITENAME}} પર તમારી ક્રિયાઓનો સાપ્તાહિક સારાંશ આ પ્રમાણે છે.",
- "echo-email-batch-link-text-view-all-notifications": "બધાં સંદેશાઓ જુઓ",
- "echo-rev-deleted-text-view": "આ પાનાંની આવૃત્તિ દબાવી દેવામાં આવી છે."
+ "echo-email-batch-link-text-view-all-notifications": "બધાં સંદેશાઓ જુઓ"
}
diff --git a/Echo/i18n/hak.json b/Echo/i18n/hak.json
new file mode 100644
index 00000000..85e24de2
--- /dev/null
+++ b/Echo/i18n/hak.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hakka"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|ngì ke}} thì-siáng",
+ "tooltip-pt-notifications-message": "{{GENDER:|Ngì ke}} liù-ngièn sêu-sit"
+}
diff --git a/Echo/i18n/haw.json b/Echo/i18n/haw.json
index 23174a12..ae08c7b9 100644
--- a/Echo/i18n/haw.json
+++ b/Echo/i18n/haw.json
@@ -20,7 +20,6 @@
"echo-category-title-edit-user-talk": "{{PLURAL:$1|memo|mau memo}} ‘ao‘ao kūkākūkā",
"echo-category-title-article-linked": "{{PLURAL:$1|loulou|mau loulou}} ‘ao‘ao",
"notifications": "Notikala",
- "tooltip-pt-notifications": "Kāu notikala",
"echo-specialpage": "Notikala",
"echo-none": "‘A‘ohe notikala.",
"echo-more-info": "‘Ike ‘ē a‘e",
diff --git a/Echo/i18n/he.json b/Echo/i18n/he.json
index 3178de35..abda6166 100644
--- a/Echo/i18n/he.json
+++ b/Echo/i18n/he.json
@@ -9,139 +9,203 @@
"Ypnypn",
"דולב",
"חיים",
- "ערן"
+ "ערן",
+ "Ijon",
+ "IKhitron",
+ "Macofe"
]
},
- "echo-desc": "מערכת לשליחת התראות למשתמשים על אירועים ומסרים",
+ "echo-desc": "מערכת לשליחת התראות למשתמשים על אירועים והודעות",
"prefs-echo": "הודעות",
"prefs-emailsettings": "אפשרויות דוא\"ל",
"prefs-displaynotifications": "אפשרויות תצוגה",
"prefs-echosubscriptions": "להודיע לי על האירועים הבאים",
- "prefs-newmessageindicator": "סמן הודעות חדשות",
+ "prefs-echocrosswiki": "הודעות מאתרי ויקי אחרים",
+ "prefs-newmessageindicator": "סמן הודעת דף שיחה חדשה",
+ "prefs-blocknotificationslist": "משתמשים מושתקים",
"echo-pref-send-me": "מה לשלוח לי:",
"echo-pref-send-to": "לשלוח אל:",
"echo-pref-email-format": "תסדיר דוא\"ל:",
"echo-pref-web": "באתר",
"echo-pref-email": "בדוא\"ל",
- "echo-pref-email-frequency-never": "לא לשלוח לי שום התראות בדואר אלקטרוני",
+ "echo-pref-email-frequency-never": "לא לשלוח לי שום הודעות בדואר אלקטרוני",
"echo-pref-email-frequency-immediately": "הודעות בודדות כשהן מגיעות",
- "echo-pref-email-frequency-daily": "סיכום יומי של התראות",
+ "echo-pref-email-frequency-daily": "סיכום יומי של הודעות",
"echo-pref-email-frequency-weekly": "סיכום שבועי של הודעות",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "טקסט רגיל",
+ "echo-pref-cross-wiki-notifications": "הצגת הודעות מאתרי ויקי אחרים",
+ "echo-pref-notifications-blacklist": "לא להציג התראות מהמשתמשים האלה. ([[mw:Help:Notifications#mute|מידע נוסף]])",
"echo-pref-new-message-indicator": "הצגת סמן הודעות דף שיחה בסרגל הכלים שלי",
+ "echo-pref-beta-feature-cross-wiki-message": "הודעות מורחבות",
+ "echo-pref-beta-feature-cross-wiki-description": "הצגה וארגון של הודעות יותר בקלות. כולל הצגת הודעות מאתרי ויקי שונים, שמאפשרת לך לראות הודעות דף שיחה מאתרים אחרים. (כדי לקבל הודעות בוויקי מסוים, יש להפעיל את אפשרות הבטא באותו הוויקי.)",
"echo-learn-more": "מידע נוסף",
+ "echo-log": "יומן ציבורי",
"echo-new-messages": "יש לך הודעות חדשות",
- "echo-category-title-edit-user-talk": "{{PLURAL:$1|הודעה|הודעות}} בדף שיחה",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|הודעה|הודעות}} בדף השיחה",
"echo-category-title-article-linked": "{{PLURAL:$1|קישור לדף|קישורים לדפים}}",
"echo-category-title-reverted": "{{PLURAL:$1|שחזור עריכה|שחזורי עריכות}}",
"echo-category-title-mention": "{{PLURAL:$1|אזכור|אזכורים}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|אזכור שנכשל|אזכורים שנכשלו}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|אזכור שהצליח|אזכורים שהצליחו}}",
"echo-category-title-other": "{{PLURAL:$1|אחר}}",
"echo-category-title-system": "{{PLURAL:$1|מערכת}}",
- "echo-category-title-user-rights": "{{PLURAL:$1|שינוי|שינויים}} בהרשאות משתמש",
- "echo-pref-tooltip-edit-user-talk": "להודיע לי כשמישהו כותב בדף השיחה שלי.",
- "echo-pref-tooltip-article-linked": "להודיע לי כשמישהו מקשר לדף שיצרתי מדף אחר.",
- "echo-pref-tooltip-reverted": "להודיע לי כשמישהו משחזר עריכה שעשיתי, באמצעות כלי הביטול או השחזור.",
+ "echo-category-title-user-rights": "{{PLURAL:$1|שינוי|שינויים}} בהרשאות שלי",
+ "echo-category-title-emailuser": "{{PLURAL:$1|דוא\"ל ממשתמש אחר|דוא\"ל ממשתמשים אחרים}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|תזכורת על דף|תזכורות על דפים}}",
+ "echo-pref-tooltip-edit-user-talk": "להודיע לי כשמישהו שולח הודעה או תגובה בדף השיחה שלי.",
+ "echo-pref-tooltip-article-linked": "להודיע לי כשמישהו מקשר לדף שיצרתי מתוך דף אחר.",
+ "echo-pref-tooltip-reverted": "להודיע לי כשמישהו משחזר עריכה שלי באמצעות כלי השחזור או הביטול.",
"echo-pref-tooltip-mention": "להודיע לי כשמישהו מקשר לדף המשתמש שלי.",
+ "echo-pref-tooltip-mention-failure": "להודיע לי כשעריכות שלי לא מצליחות לשלוח אזכורים למשתמשים.",
+ "echo-pref-tooltip-mention-success": "להודיע לי כשעריכות שלי שולחות אזכורים למשתמשים.",
"echo-pref-tooltip-user-rights": "להודיע לי כשמישהו משנה את הרשאות המשתמש שלי.",
- "echo-no-agent": "[אף אחד]",
- "echo-no-title": "[ללא דף]",
- "echo-error-no-formatter": "לא הוגדר עיצוב להתראות.",
- "notifications": "התראות",
+ "echo-pref-tooltip-emailuser": "להודיע לי כשמישהו שולח לי דואר אלקטרוני.",
+ "echo-pref-tooltip-article-reminder": "להודיע לי על הדף הזה כשאני מבקש.",
+ "echo-error-no-formatter": "לא הוגדר עיצוב להודעה.",
+ "notifications": "הודעות",
"tooltip-pt-notifications-alert": "ההתראות שלך",
- "tooltip-pt-notifications-message": "ההודעות שלך",
+ "tooltip-pt-notifications-notice": "ההודעות {{GENDER:|שלך}}",
+ "echo-displaynotificationsconfiguration": "הצגת הגדרות הודעות",
+ "echo-displaynotificationsconfiguration-summary": "זוהי סקירה כללית של איך שההודעות מוגדרות בוויקי הזה.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "הודעות לפי קטגוריה",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "מיון סוגים",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "לאיזה אזור בתצוגה ממוינת כל הודעה",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "שיטות הודעה מותרות",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "אילו שיטות הודעה נתמכות לכל קטגוריה",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "אילו שיטות הודעה נתמכות לכל סוג; זה חל רק על סוגים בתוך קטגוריות שמוסתרות מהעדפות",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "מופעל כברירת מחדל",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "משתמשים קיימים",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "משתמשים חדשים",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "שיטות הודעה נדרשות",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "אילו שיטות הודעה נדרשות לכל קטגוריה",
"echo-specialpage": "הודעות",
- "echo-anon": "כדי לקבל התראות, [$1 יש ליצור חשבון] או [$2 להיכנס].",
+ "echo-specialpage-section-markread": "סימון כקבוצה שנקראה",
+ "echo-specialpage-markasread": "הודעה: סימון כהודעה שנקראה",
+ "echo-specialpage-markasread-invalid-id": "מזהה אירוע בלתי־תקין",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|הודעה אחת|$1 הודעות}}",
+ "echo-specialpage-pagefilters-title": "פעילות אחרונה",
+ "echo-specialpage-pagefilters-subtitle": "דפים עם הודעות שלא נקראו",
+ "notificationsmarkread-legend": "סימון כהודעה שנקראה",
+ "echo-anon": "כדי לקבל הודעות, יש [$1 ליצור חשבון] או [$2 להיכנס].",
"echo-none": "אין לך הודעות.",
"echo-more-info": "מידע נוסף",
"echo-feedback": "משוב",
- "echo-api-failure": "לא היה אשר לאחזר התראות. נא לנסות שוב. (שגיאה $1)",
- "echo-notification-placeholder": "אין התראות.",
- "notification-link-text-view-message": "הצגת הודעה",
- "notification-link-text-view-mention": "הצגת אזכור",
- "notification-link-text-view-changes": "הצגת שינויים",
- "notification-link-text-view-page": "הצגת דף",
- "notification-link-text-view-edit": "הצגת עריכה",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|כתב|כתבה}} ב[[User talk:$2#$3|דף השיחה]] שלך.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|כתב|כתבה}} בדף השיחה שלך הודעה תחת הכותרת '[[User talk:$2#$3|$4]]'.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|כתב|כתבה}} ב[[User talk:$2#$3|דף השיחה שלך]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|כתב|כתבה}} בדף השיחה שלך הודעה תחת הכותרת '[[User talk:$2#$3|$4]]'.",
- "notification-page-linked": "{{GENDER:$1|נוסף קישור}} אל הדף [[:$2]] מהדף [[:$3]]. [[Special:WhatLinksHere/$2|כל הקישורים אל הדף הזה]].",
- "notification-page-linked-flyout": "{{GENDER:$1|נוסף קישור}} אל הדף [[:$2]] מהדף [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|העיר|העירה}} על הנושא \"[[$3|$2]]\" בדף השיחה של \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|והוסיף|הוסיפה}} את נושא החדש \"$2\" לדף [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|שלח|שלחה}} לך הודעה: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|העיר|העירה}} על הנושא \"[[$3#$2|$2]]\" בדף השיחה שלך",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|הזכיר|הזכירה}} אותך בפסקה \"[[:$3#$2|$4]]\" בדף השיחה של $5.",
- "notification-mention-flyout": "$1 {{GENDER:$1|הזכיר|הזכירה}} אותך בפסקה \"[[:$3#$2|$4]]\" בדף השיחה של $5.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|הזכיר|הזכירה}} אותך ב[[:$3|דף השיחה $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|הזכיר|הזכירה}} אותך ב[[:$3|דף השיחה $2]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|שינה|שינתה}}]] את ההרשאות שלך. $2. [[Special:ListGroupRights|מידע נוסף]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|שינה|שינתה}} את ההרשאות שלך. $2. [[Special:ListGroupRights|מידע נוסף]]",
- "notification-user-rights-add": "צורפת {{PLURAL:$2|לקבוצה הבאה|לקבוצות הבאות}}: $1",
- "notification-user-rights-remove": "נמחקת {{PLURAL:$2|מהקבוצה הבאה|מהקבוצות הבאות}}: $1",
- "notification-new-user": "ברוך בואך ל{{GRAMMAR:תחילית|{{SITENAME}}}}&rlm;, $1! אנחנו שמחים לראות אותך כאן.",
- "notification-reverted2": "[[User:$1|$1]] {{GENDER:$1|ביטל|ביטלה}} {{PLURAL:$4|עריכה שלך|עריכות שלך}} בדף [[:$2]] $3",
- "notification-reverted-flyout2": "$1 {{GENDER:$1|ביטל|ביטלה}} {{PLURAL:$4|עריכה שלך|עריכות שלך}} בדף $2 $3",
- "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|כתב|כתבה}} לך הודעה חדשה באתר {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|כתב|כתבה}} הודעה בדף השיחה שלך.",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|כתב|כתבה}} בדף השיחה שלך הודעה תחת הכותרת '$2'.",
- "notification-page-linked-email-subject": "מישהו קישר לדף שיצרת באתר {{SITENAME}}",
- "notification-page-linked-email-batch-body": "{{GENDER:$1|מישהו קישר|מישהי קישרה}} מהדף $3 אל הדף $2",
- "notification-reverted-email-subject2": "$1 {{GENDER:$1|שחזר|שחזרה}} {{PLURAL:$3|עריכה שלך|עריכות שלך}} באתר {{SITENAME}}",
- "notification-reverted-email-batch-body2": "$1 {{GENDER:$1|שחזר|שחזרה}} {{PLURAL:$3|עריכה שלך|עריכות שלך}} בדף $2",
- "notification-mention-email-subject": "$1 {{GENDER:$1|הזכיר|הזכירה}} אותך באתר {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|הזכיר|הזכירה}} אותך בדיון בדף השיחה של $4 בפסקה '$3'.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|הזכיר|הזכירה}} אותך בדף השיחה $2.",
+ "echo-popup-footer-special-page-invitation": "<strong>{{GENDER:|נסה|נסי|נסו}} את העיצוב החדש של דף ההודעות.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "המראה החדש וכל התכונות החדשות.",
+ "echo-api-failure": "לא ניתן היה לאחזר הודעות.",
+ "echo-api-failure-cross-wiki": "לא ניתנה גישה למתחם המרוחק.",
+ "echo-notification-placeholder": "אין הודעות.",
+ "echo-notification-placeholder-filters": "אין הודעות שמתאימות לסינון הזה.",
+ "echo-notification-loginrequired": "יש להיכנס לחשבון כדי לצפות בהודעות.",
+ "echo-notification-popup-loginrequired": "נא להיכנס לחשבון כדי לצפות בהודעות שלך.",
+ "echo-notification-markasread": "סימון כהודעה שנקראה",
+ "echo-notification-markasunread": "סימון כהודעה שלא נקראה",
+ "echo-notification-markasread-tooltip": "סימון כהודעה שנקראה",
+ "echo-notification-more-options-tooltip": "אפשרויות נוספות",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|הפסקת}} המעקב אחרי פעילות חדשה בדף \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|אתה כבר לא עוקב|את כבר לא עוקבת|אתם כבר לא עוקבים}} יותר אחרי הדף \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|באפשרותך|באפשרותך|באפשרותכם}} לעקוב אחרי [$2 הדף הזה] בכל עת.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|מעקב}} אחרי פעילות חדשה בדף \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|אתה עכשיו עוקב|את עכשיו עוקבת|אתם עכשיו עוקבים}} אחרי הדף \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|באפשרותך|באפשרותך|באפשרותכם}} להפסיק את המעקב אחרי [$2 הדף הזה] בכל עת.",
+ "notification-link-text-expand-all": "הצגה",
+ "notification-link-text-expand-alert-count": "הצגת {{PLURAL:$1|התראה אחת|$1 התראות}}",
+ "notification-link-text-expand-notice-count": "הצגת {{PLURAL:$1|הודעה אחת|$1 הודעות}}",
+ "notification-link-text-expand-all-count": "הצגת {{PLURAL:$1|הודעה אחת|$1 הודעות}}",
+ "notification-link-text-collapse-all": "הסתרה",
+ "notification-link-text-view-message": "הצגת ההודעה",
+ "notification-link-text-view-mention": "הצגת האזכור",
+ "notification-link-text-view-mention-failure": "הצגת {{PLURAL:$1|האזכור|האזכורים}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|הצגת}} שינויים",
+ "notification-link-text-view-page": "הצגת הדף",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|השאיר|השאירה}} הודעה ב<strong>דף השיחה {{GENDER:$3|שלך}}</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|השאיר|השאירה}} הודעה ב<strong>דף השיחה {{GENDER:$3|שלך}}</strong> בפסקה \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "נוצר קישור מהדף <strong>$4</strong> אל הדף <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "קושר מהדף <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "נוצרו קישורים מ{{GRAMMAR:תחילית|{{PLURAL:$5||$5 דפים|100=99+ דפים}}}} אל הדף <strong>$3</strong>.",
+ "notification-header-article-reminder": "שם הדף {{GENDER:$2|שביקשת}} תזכורות עליו הוא <strong>$3</strong>",
+ "notification-link-text-what-links-here": "כל הקישורים לדף הזה",
+ "notification-header-mention-other": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$3|אותך}} בדף <strong>$4</strong> בפסקה \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$3|אותך}} בדף <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$3|אותך}} ב<strong>דף השיחה של {{GENDER:$5|$4}}</strong> בפסקה \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$3|אותך}} ב<strong>דף השיחה של {{GENDER:$5|$4}}</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$3|אותך}} ב<strong>דף השיחה {{GENDER:$2|שלו|שלה}}</strong> בפסקה \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$3|אותך}} ב<strong>דף השיחה {{GENDER:$2|שלו|שלה}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$3|אותך}} בדף השיחה של הדף <strong>$4</strong> בפסקה \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$3|אותך}} בדף השיחה של הדף <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "האזכור ש{{GENDER:$2|עשית}} עבור <strong>$3</strong> לא נשלח כי המשתמש לא נמצא.",
+ "notification-header-mention-failure-user-anonymous": "האזכור {{GENDER:$2|שלך}} לא נשלח אל <strong>$3</strong> כי זה משתמש אלמוני.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|ניסית}} להזכיר יותר {{PLURAL:$3|ממשתמש אחד|מ־$3 משתמשים}}. כל האזכורים מעל המגבלה הזאת לא נשלחו.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|אזכור אחד|$3 אזכורים}} {{GENDER:$2|שעשית}} בדף השיחה <strong>$4</strong> לא {{PLURAL:$3|נשלח|נשלחו}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>משתמש לא קיים:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>לא ניתן לשלוח אזכורים עבור כתובות IP:</strong>&rlm; $1",
+ "notification-header-mention-success": "האזכור ש{{GENDER:$2|עשית}} נשלח ל{{GENDER:$3|משתמש|משתמשת}} <strong>$3</strong>.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|אזכור אחד|$3 אזכורים}} ש{{GENDER:$2|עשית}} בדף השיחה <strong>$4</strong> {{PLURAL:$3|נשלח|נשלחו}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|הזכרת}} את:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|התראה אחת|$3 התראות}} על אזכורים ש{{GENDER:$2|עשית}} בדף השיחה <strong>$4</strong>: {{PLURAL:$5|אזכור אחד לא נשלח|$5 אזכורים לא נשלחו}}, {{PLURAL:$6|אזכור אחד נשלח|$6 אזכורים נשלחו}}.",
+ "notification-header-user-rights-add-only": "הרשאות המשתמש שלך {{GENDER:$1|שונו}}. {{GENDER:$4|נוספת}} ל{{GRAMMAR:תחילית|$2}}.",
+ "notification-header-user-rights-remove-only": "הרשאות המשתמש שלך {{GENDER:$1|שונו}}. {{GENDER:$4|אתה כבר לא חבר|את כבר לא חברה}} ב{{GRAMMAR:תחילית|$2}}.",
+ "notification-header-user-rights-add-and-remove": "הרשאות המשתמש שלך {{GENDER:$1|שונו}}. נוספת ל{{GRAMMAR:תחילית|$2}}. {{GENDER:$6|אתה כבר לא חבר|את כבר לא חברה}} ב{{GRAMMAR:תחילית|$4}}.",
+ "notification-header-user-rights-expiry-change": "תפוגת החברות {{GENDER:$4|שלך}} {{PLURAL:$3|בקבוצה הבאה|בקבוצות הבאות}} {{GENDER:$1|שונתה}}: $2",
+ "notification-header-welcome": "{{GENDER:$2|ברוך הבא|ברוכה הבאה|ברוך בואך}} ל{{GRAMMAR:תחילית|{{SITENAME}}}}&rlm;, $1! אנחנו שמחים {{GENDER:$2|שאתה פה|שאת פה|שבאת}}.",
+ "notification-welcome-linktext": "ברוך בואך",
+ "notification-header-thank-you-1-edit": "זה עתה {{GENDER:$2|עשית}} את העריכה הראשונה שלך; תודה ו{{GENDER:$2|ברוך הבא|ברוכה הבאה|ברוך בואך}}!",
+ "notification-header-thank-you-10-edit": "זה עתה {{GENDER:$2|עשית}} את העריכה העשירית שלך; תודה, {{GENDER:$2|המשך|המשיכי}} כך!",
+ "notification-header-thank-you-100-edit": "זה עתה {{GENDER:$2|עשית}} את העריכה המאה שלך; תודה רבה!",
+ "notification-header-thank-you-1000-edit": "זה עתה {{GENDER:$2|עשית}} את העריכה ה־1,000 שלך; תודה על כך {{GENDER:$2|שאתה תורם כה נפלא|שאת תורמת כה נפלאה}}!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|עשית}} את העריכה העשרת אלפים שלך; תודה רבה־רבה!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|עשית}} את העריכה המאה אלף שלך; תודה על התרומה המדהימה הזאת!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|עשית}} את העריכה המיליון שלך; תודה על התרומה המדהימה הזאת!",
+ "notification-link-thank-you-edit": "עריכה {{GENDER:$1|שלך}}",
+ "notification-link-text-view-edit": "הצגת העריכה",
+ "notification-link-article-reminder": "הצגת הדף",
+ "notification-header-reverted": "{{PLURAL:$4|העריכה {{GENDER:$2|שלך}} בדף <strong>$3</strong> שוחזרה|העריכות שלך בדף <strong>$3</strong> שוחזרו}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|שלח|שלחה}} לך דוא\"ל.",
+ "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|כתב|כתבה}} לך הודעה באתר {{SITENAME}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|השאיר|השאירה}} הודעה בדף השיחה שלך בפסקה \"$2\".",
+ "notification-page-linked-email-subject": "נוצר קישור לדף שיצרת באתר {{SITENAME}}",
+ "notification-reverted-email-subject2": "{{PLURAL:$3|עריכה {{GENDER:$1|שלך}}|עריכות שלך}} באתר {{SITENAME}} {{PLURAL:$3|שוחזרה|שוחזרו}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|הזכיר|הזכירה}} {{GENDER:$2|אותך}} באתר {{SITENAME}}",
"notification-user-rights-email-subject": "ההרשאות שלך באתר {{SITENAME}} שונו",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|שינה|שינתה}} את ההרשאות שלך. $2",
- "echo-notification-count": "יותר מ־$1",
- "echo-email-subject-default": "התראה חדשה באתר {{SITENAME}}",
- "echo-email-body-default": "יש לך התראה חדשה באתר {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "יש לך הודעה חדשה.",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|שנייה|$1 שניות}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|דקה|$1 דקות}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|שעה|שעתיים|$1 שעות}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|יום|יומיים|$1 ימים}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|חודש|חודשיים|$1 חודשים}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|שנה|שנתיים|$1 שנה|$1 שנים}}",
+ "notification-timestamp-today": "היום",
+ "notification-timestamp-yesterday": "אתמול",
+ "notification-inbox-filter-read": "הודעות שנקראו",
+ "notification-inbox-filter-unread": "הודעות שלא נקראו",
+ "notification-inbox-filter-all": "הכול",
+ "echo-email-body-default": "יש לך הודעה חדשה באתר {{SITENAME}}:\n\n$1",
+ "echo-email-footer-default-html": "כדי לשלוט בסוגי המכתבים שאנחנו שולחים לך, <a href=\"$2\" style=\"text-decoration: none; color: #3868B0;\">נא להתאים את ההעדפות שלך</a><br />\n$1",
"echo-email-footer-default": "$2\n\nכדי לבחור אילו מכתבים נשלח לך, אפשר לשנות את ההעדפות שלך:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "כדי לשלוט בסוגי המכתבים שאנחנו שולחים לך <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">נא להתאים את ההעדפות שלך</a><br />\n$1",
+ "echo-email-plain-footer": "כדי לבחור אילו מכתבים נשלח {{GENDER:$1|אליך|אלייך|אליכם}}, אנא {{GENDER:$1|בדוק|בִדקי|בִדקו}} את ההעדפות {{GENDER:$1|שלך|שלך|שלכם}}:",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|בדוק|בִדקי|בִדקו}} את ההעדפות {{GENDER:$1|שלך|שלך|שלכם}}",
+ "echo-email-html-footer-with-link": "כדי לבחור אילו מכתבים נשלח {{GENDER:$2|אליך|אלייך|אליכם}}, אנא $1.",
"echo-notification-alert": "{{PLURAL:$1|התראות ($1)|100=התראות (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|הודעות ($1)|100=הודעות (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|הודעה אחת|הודעות ($1)|100=הודעות (99+)}}",
"echo-notification-alert-text-only": "התראות",
- "echo-notification-message-text-only": "הודעות",
- "echo-overlay-link": "כל ההתראות",
+ "echo-notification-notice-text-only": "הודעות",
+ "echo-overlay-link": "כל ההודעות",
"echo-overlay-title": "<b>הודעות</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|התראה|התראות}}</b> ({{PLURAL:$1|מוצגת אחת|מוצגות $1}} מתוך $2 שלא נקראו)",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|הודעה|הודעות}}</b> ({{PLURAL:$1|מוצגת אחת|מוצגות $1}} מתוך $2 שלא נקראו)",
"echo-mark-all-as-read": "לסמן שהכול נקרא",
+ "echo-mark-all-as-read-confirmation": "{{PLURAL:$1|הודעה אחת סומנה כהודעה שנקראה|$1 הודעות סומנו כהודעות שנקראו}}",
+ "echo-mark-wiki-as-read": "סימון כל ההודעות מאתר הוויקי שנבחר כנקראות: $1",
"echo-date-today": "היום",
"echo-date-yesterday": "אתמול",
"echo-load-more-error": "אירעה שגיאה בעת אחזור תוצאות נוספות.",
- "notification-edit-talk-page-bundle": "$1 ועוד {{PLURAL:$4|אדם אחד|$3 אנשים}} כתבו הודעות ב[[User talk:$2|דף השיחה]] שלך.",
- "notification-page-linked-bundle": "אל הדף $2 {{GENDER:$1|נוסף קישור}} מהדף $3 ומעוד {{PLURAL:$5|דף|$4 דפים אחרים}}. [[Special:WhatLinksHere/$2|כל הקישורים אל הדף הזה]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 ועוד {{PLURAL:$3|אדם אחד|$2 אנשים}} כתבו הודעות בדף השיחה שלך.",
- "notification-page-linked-email-batch-bundle-body": "אל הדף $2 {{GENDER:$1|נוסף קישור}} מהדף $3 ומעוד {{PLURAL:$5|דף|$4 דפים אחרים}}.",
- "echo-email-batch-subject-daily": "קיבלת {{PLURAL:$2|התראה חדשה|התראות חדשות}} באתר {{SITENAME}}",
- "echo-email-batch-subject-weekly": "קיבלת {{PLURAL:$2|התראה חדשה|התראות חדשות}} באתר {{SITENAME}} השבוע",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|הודעה חדשה|$1 הודעות חדשות|100=99+ הודעות חדשות}} ב<strong>דף השיחה {{GENDER:$3|שלך}}</strong>.",
+ "echo-email-batch-subject-daily": "קיבלת {{PLURAL:$2|הודעה חדשה|הודעות חדשות}} באתר {{SITENAME}}",
+ "echo-email-batch-subject-weekly": "יש לך {{PLURAL:$2|הודעה חדשה|הודעות חדשות}} באתר {{SITENAME}} השבוע",
"echo-email-batch-body-intro-daily": "שלום $1,\nלהלן תקציר של פעילויות שקשורות אליך באתר {{SITENAME}} היום.",
"echo-email-batch-body-intro-weekly": "שלום $1,\nלהלן תקציר של פעילויות שקשורות אליך באתר {{SITENAME}} השבוע.",
- "echo-email-batch-link-text-view-all-notifications": "הצגת כל ההתראות",
- "echo-rev-deleted-text-view": "הגרסה הזאת של הדף הועלמה.",
- "apihelp-echomarkread-description": "סימון שכל ההתראות נקראו עבור המשתמש הנוכחי.",
- "apihelp-echomarkread-param-list": "רשימת מזהי התראות שצריך לסמן שהן נקראו.",
- "apihelp-echomarkread-param-all": "אם זה מוגדר, כל ההתראות של המשתמש תסומנה בתור התראות שנקראו.",
- "apihelp-echomarkread-param-sections": "רשימת פסקאות שיש לסמן שהן נקראו.",
- "apihelp-echomarkread-example-1": "לסמן שהתראה 8 נקראה",
- "apihelp-echomarkread-example-2": "לסמן שכל ההתראות נקראו",
- "apihelp-echomarkseen-description": "סימון התראות בהתראות שנראו עבור המשתמש הנוכחי.",
- "apihelp-echomarkseen-example-1": "לסמן שהתראות מכל הסוגים נראו",
- "apihelp-echomarkseen-param-type": "סוג ההתראות לסמן בתור נראות: 'alert'‏, 'message' או 'all'.",
- "apihelp-query+notifications-description": "קבלת התראות שממתינות למשתמש הנוכחי.",
- "apihelp-query+notifications-param-prop": "אילו פרטים לבקש.",
- "apihelp-query+notifications-param-sections": "פסקאות ההתראות שצריך לאחזר (כלומר, שילוב כלשהו של 'alert' ו־'message').",
- "apihelp-query+notifications-param-groupbysection": "האם לקבץ את התוצאות לפי פסקה. כל פסקה מאוחזרת בנפרד אם זה מוגדר.",
- "apihelp-query+notifications-param-format": "אם זה מצוין, ההתראות תוחזרנה עם עיצוב כזה.",
- "apihelp-query+notifications-param-limit": "המספר המרבי של ההתראות להחזיר.",
- "apihelp-query+notifications-param-index": "אם זה מצוין, תוחזר רשימת מזני התראות לפי הסדר.",
- "apihelp-query+notifications-param-alertcontinue": "האם זמינים עוד תוצאות צגים, יש להשתמש בזה כדי להמשיך.",
- "apihelp-query+notifications-param-alertunreadfirst": "האם להציג מונה הודעות שלא נקרא תחילה.",
- "apihelp-query+notifications-param-messagecontinue": "כשזמינות עוד תוצאות הודעות, יש להשתמש בזה כדי להמשיך.",
- "apihelp-query+notifications-param-messageunreadfirst": "האם להציג צג התראות שלא נקראו תחילה.",
- "apihelp-query+notifications-example-1": "רשימת הודעות",
- "apihelp-query+notifications-example-2": "רשימת התראות, מקובצות לפי פסקה, עם מונים"
+ "echo-email-batch-link-text-view-all-notifications": "הצגת כל ההודעות",
+ "notification-header-foreign-alert": "עוד התראות {{PLURAL:$5|מאתר ויקי אחר|מ־$5 אתרי ויקי אחרים}}",
+ "notification-header-foreign-notice": "עוד הודעות {{PLURAL:$5|מאתר ויקי אחר|מ־$5 אתרי ויקי אחרים}}",
+ "notification-header-foreign-all": "עוד הודעות {{PLURAL:$5|מאתר ויקי אחר|מ־$5 אתרי ויקי אחרים}}",
+ "echo-foreign-wiki-lang": "$1 – $2"
}
diff --git a/Echo/i18n/hi.json b/Echo/i18n/hi.json
index a34e5288..5081463f 100644
--- a/Echo/i18n/hi.json
+++ b/Echo/i18n/hi.json
@@ -8,121 +8,166 @@
"Shubhamkanodia",
"Siddhartha Ghai",
"NehalDaveND",
- "राम प्रसाद जोशी"
+ "राम प्रसाद जोशी",
+ "Angpradesh",
+ "Sfic",
+ "चक्रपाणी",
+ "संजीव कुमार",
+ "Shahjad ansari",
+ "Anamdas",
+ "हिंदुस्थान वासी",
+ "Sachinkatiyar"
]
},
"echo-desc": "अधिसूचना प्रणाली",
- "prefs-echo": "अधिसूचनाएँ",
+ "prefs-echo": "सूचनायें",
"prefs-emailsettings": "ईमेल विकल्प",
"prefs-displaynotifications": "प्रदर्शन विकल्प",
"prefs-echosubscriptions": "मुझे इन घटनाओं के बारे में सूचित करें",
+ "prefs-echocrosswiki": "क्रॉस-विकी नोटिफिकेशन",
"prefs-newmessageindicator": "नए संदेश का संकेतक",
+ "prefs-blocknotificationslist": "मूक उपयोगकर्ता",
"echo-pref-send-me": "मुझे भेजिए:",
"echo-pref-send-to": "यहाँ भेजिए:",
"echo-pref-email-format": "ईमेल प्रारूप:",
"echo-pref-web": "वेब",
"echo-pref-email": "ईमेल",
"echo-pref-email-frequency-never": "मुझे कोई भी ईमेल अधिसूचना मत भेजें",
- "echo-pref-email-frequency-immediately": "अधिसूचनाएँ एक-एक कर के, जैसे-जैसे वे प्राप्त होती हैं",
+ "echo-pref-email-frequency-immediately": "सूचना आते साथ प्राप्त होती है।",
"echo-pref-email-frequency-daily": "अधिसूचनाओं का दैनिक सारांश",
"echo-pref-email-frequency-weekly": "अधिसूचनाओं का साप्ताहिक सारांश",
"echo-pref-email-format-html": "एच॰टी॰एम॰एल॰",
"echo-pref-email-format-plain-text": "सादा पाठ",
+ "echo-pref-cross-wiki-notifications": "दूसरे विकीज़ से नोटिफिकेशन दिखाएँ",
"echo-pref-new-message-indicator": "वार्ता पृष्ठ संदेश संकेतक मेरी उपकरण पट्टी में दिखाएँ",
+ "echo-pref-beta-feature-cross-wiki-message": "बढ़ा सूचना",
"echo-learn-more": "अधिक जानिए",
+ "echo-log": "सार्वजनिक लॉग",
"echo-new-messages": "आपके लिए नए संदेश हैं",
"echo-category-title-edit-user-talk": "वार्ता पृष्ठ {{PLURAL:$1| सन्देश}}",
"echo-category-title-article-linked": "पृष्ठ {{PLURAL:$1| कड़ी | कड़ियाँ}}",
"echo-category-title-reverted": "सम्पादन {{PLURAL:$1|पूर्ववत किये जाने की}}",
"echo-category-title-mention": "{{PLURAL:$1|उल्लेख}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|उल्लेख}} विफल रहा",
+ "echo-category-title-mention-success": "{{PLURAL:$1|उल्लेख}} सफल रहा",
"echo-category-title-other": "{{PLURAL:$1|अन्य}}",
"echo-category-title-system": "{{PLURAL:$1|प्रणाली}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|सदस्य अधिकार बदला|सदस्य अधिकार बदले}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|अन्य सदस्य से ईमेल|अन्य सदस्यों से ईमेल}}",
"echo-pref-tooltip-edit-user-talk": "जब कोई मुझे संदेश भेजे या मेरे वार्ता पृष्ठ पर उत्तर दे तो मुझे सूचित करें।",
"echo-pref-tooltip-article-linked": "जब कोई मेरे द्वारा बनाए गए लेख की कड़ी कहीं जोड़े तो मुझे सूचित करें।",
"echo-pref-tooltip-reverted": "जब कोई मेरे किसी सम्पादन को पूर्ववत करे या वापस ले तो मुझे सूचित करें।",
"echo-pref-tooltip-mention": "जब कोई मेरे सदस्य पृष्ठ की कड़ी का किसी वार्ता पृष्ठ पर प्रयोग करे तो मुझे सूचित करें।",
+ "echo-pref-tooltip-mention-failure": "यदि किसी के नाम का उल्लेख न हो तो मुझे सूचित करें।",
+ "echo-pref-tooltip-mention-success": "किसी के नाम का उल्लेख करने पर मुझे सूचित करें।",
"echo-pref-tooltip-user-rights": "यदि कोई मेरे सदस्य अधिकार परिवर्तित करता है तो मुझे सूचित करें।",
- "echo-no-agent": "[कोई नहीं]",
- "echo-no-title": "[कोई पृष्ठ नहीं]",
+ "echo-pref-tooltip-emailuser": "जब मुझे कोई ईमेल करें तो मुझे सूचना दें।",
"echo-error-no-formatter": "अधिसूचना के लिए कोई स्वरूपण परिभाषित नहीं है।",
- "notifications": "अधिसूचनाएँ",
- "tooltip-pt-notifications-message": "{{GENDER:|आप के}} संदेश",
- "echo-specialpage": "अधिसूचनाएँ",
- "echo-anon": "अधिसूचनाएँ पाने के लिये, [$1 खाता बनाएँ] या [$2 लॉग इन करें]।",
+ "notifications": "सूचनायें",
+ "tooltip-pt-notifications-alert": "{{GENDER:|आपका}} जागरूकता संदेश",
+ "tooltip-pt-notifications-notice": "{{GENDER:|आपकी}} सूचना",
+ "echo-displaynotificationsconfiguration": "प्रदर्शन सूचना पसंद",
+ "echo-displaynotificationsconfiguration-summary": "यह इस विकी पर सूचनाएँ कैसे कॉन्फ़िगर किया गया है, इसका अवलोकन है।",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "श्रेणी अनुसार अधिसूचनाएं",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "छंटनी के प्रकार",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "अनुमति प्राप्त सूचना के तरीके",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "मूल रूप से सक्रिय",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "वर्तमान सदस्य",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "नये सदस्य",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "अनिवार्य सूचना पद्धति",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "कौनसा सूचना पद्धति उन श्रेणियों में अनिवार्य है",
+ "echo-specialpage": "सूचनायें",
+ "echo-specialpage-section-markread": "समूह को पढ़ा हुआ चिह्नित करें",
+ "echo-specialpage-markasread": "सूचना: पढ़ा हुआ चिन्हित करें",
+ "echo-specialpage-markasread-invalid-id": "अमान्य आयोजन आईडी",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|सूचना}}",
+ "echo-specialpage-pagefilters-title": "हाल की गतिविधि",
+ "echo-specialpage-pagefilters-subtitle": "न पढ़े सूचना के साथ पन्ने",
+ "notificationsmarkread-legend": "सूचना को पढ़ा हुआ चिन्हित करें",
+ "echo-anon": "सूचना पाने के लिये, [$1 खाता बनाएँ] या [$2 लॉग इन करें]।",
"echo-none": "आपके लिये कोई अधिसूचना नहीं है।",
"echo-more-info": "अधिक जानकारी",
"echo-feedback": "आपके सुझाव",
+ "echo-popup-footer-special-page-invitation": "<strong>सूचना पन्ने का फिर से रूप बनाने का कोशिश करें।</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "सभी नया रूप और विशेषता",
+ "echo-api-failure": "सूचना प्राप्त करने में विफल रहा।",
+ "echo-api-failure-cross-wiki": "रिमोट डोमैन ने जुड़ने से इंकार कर दिया।",
+ "echo-notification-placeholder": "कोई सूचना नहीं है।",
+ "echo-notification-placeholder-filters": "इस मापदंड पर कोई सूचना नहीं दिख रही",
+ "echo-notification-loginrequired": "सूचनाओं को देखने हेतु आपको प्रवेश करना होगा।",
+ "echo-notification-popup-loginrequired": "सूचना देखने हेतु खाते में प्रवेश करें।",
+ "echo-notification-markasread": "पढ़ा गया चिन्हित करें",
+ "echo-notification-markasunread": "न पढ़ा चिन्हित करें",
+ "echo-notification-markasread-tooltip": "पढ़ा गया चिन्हित करें",
+ "echo-notification-more-options-tooltip": "अन्य विकल्प",
+ "notification-dynamic-actions-unwatch": "\"$1\" में नई गतिविधि देखना {{GENDER:$3|बंद}} करें",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|आप}} अब \"$1\" पन्ने को ध्यानसूची से हटा चुके हैं।",
+ "notification-dynamic-actions-watch": "\"$1\" में नई गतिविधि {{GENDER:$3|ध्यान में रखें}}",
+ "notification-dynamic-actions-watch-confirmation": "\"$1\" को {{GENDER:$3|आप}} ध्यान दे रहे हैं।",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|आप}} [$2 इस पृष्ठ] से कभी भी ध्यान देना बंद कर सकते हैं।",
+ "notification-link-text-expand-all": "विस्तार करें",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 सूचना|$1 सूचनाएँ}} देखें",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|$1 सूचना|$1 सूचनाओं को}} देखें",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 सूचना|$1 सूचनाओं को}} देखें",
+ "notification-link-text-collapse-all": "छोटा करें",
"notification-link-text-view-message": "संदेश देखें",
"notification-link-text-view-mention": "उल्लेख देखें",
- "notification-link-text-view-changes": "बदलाव देखें",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|उल्लेख देखें}}",
+ "notification-link-text-view-changes": "बदलाव {{GENDER:$1|देखें}}",
"notification-link-text-view-page": "पृष्ठ देखें",
+ "notification-header-edit-user-talk": "$1 ने <strong>{{GENDER:$3|आपके}} वार्ता पृष्ठ पर</strong> एक संदेश {{GENDER:$2|छोड़ा}} है।",
+ "notification-compact-header-page-linked": "<strong>$1</strong> से जुड़ा",
+ "notification-link-text-what-links-here": "इसी पृष्ठ से जुड़ी सभी कड़ियाँ",
+ "notification-header-mention-other": "<strong>$4</strong> पर \"<strong>$5</strong>\" अनुभाग में $1 जी ने {{GENDER:$3|आपका}} {{GENDER:$2|उल्लेख किया है}}।",
+ "notification-header-mention-other-nosection": "$1 जी ने {{GENDER:$3|आपका}} <strong>$4</strong> में {{GENDER:$2|उल्लेख किया है}}।",
+ "notification-header-mention-user-talkpage-v2": "<strong>$4 {{GENDER:$5|के}} वार्ता पृष्ठ</strong> के \"<strong>$6</strong>\" अनुभाग में $1 जी ने {{GENDER:$3|आपका}} {{GENDER:$2|उल्लेख किया है}}।",
+ "notification-header-mention-user-talkpage-nosection": "$1 जी ने {{GENDER:$3|आपका}} $4 {{GENDER:$5|के}} <strong>सदस्य वार्ता पृष्ठ पर</strong> {{GENDER:$2|उल्लेख किया है}}।",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>सदस्य नाम उपस्थित नहीं है:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>आईपी सदस्यों का उल्लेख नहीं किया जा सकता:</strong> $1",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|आपने उल्लेख किया}}:</strong> $3",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|आपका}} अधिकार {{GENDER:$1|बदला}} गया। अब आपको इसमें जोड़ा गया है: $2",
+ "notification-welcome-linktext": "सुस्वागतम्‌!",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|आपने}} अभी अभी {{GENDER:$2|अपना}} पहला सम्पादन किया है; {{GENDER:$2|आपका}} धन्यवाद, और स्वागत है!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|आपके}} सम्पादन",
"notification-link-text-view-edit": "सम्पादन देखें",
- "notification-edit-talk-page2": "[[User:$1|$1]] ने आपके [[User talk:$2#$3|वार्ता पृष्ठ]] पर एक नया सन्देश {{GENDER:$1|छोड़ा}} है।",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] ने आपके वार्ता पृष्ठ पर \"[[User talk:$2#$3|$4]]\" भाग में एक नया सन्देश {{GENDER:$1|छोड़ा}} है।",
- "notification-edit-talk-page-flyout2": "$1 ने आपके [[User talk:$2#$3|वार्ता पृष्ठ]] पर एक सन्देश {{GENDER:$1|छोड़ा}} है।",
- "notification-edit-talk-page-flyout-with-section": "$1 ने आपके वार्ता पृष्ठ पर \"[[User talk:$2#$3|$4]]\" भाग में एक सन्देश {{GENDER:$1|छोड़ा}} है।",
- "notification-page-linked": "[[:$3]] पर [[:$2]] की कड़ी {{GENDER:$1|जोड़ी}} गयी थी। [[Special:WhatLinksHere/$2|इस पृष्ठ से जुड़ने वाले सभी पृष्ठ देखें]]।",
- "notification-page-linked-flyout": "[[:$3]] पर [[:$2]] की कड़ी {{GENDER:$1|जोड़ी}} गयी।",
- "notification-add-comment2": "[[User:$1|$1]] ने \"$4\" वार्ता पृष्ठ पर \"[[$3|$2]]\" भाग में {{GENDER:$1|टिप्पणी की है}}।",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] ने [[$3]] पर \"$2\" विषय पर चर्चा शुरू {{GENDER:$1|की}} है।",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] ने आपको एक नया सन्देश {{GENDER:$1|भेजा}} है: \"[[$3#$2|$2]]\"।",
- "notification-add-comment-yours2": "[[User:$1|$1]] ने आपके वार्ता पृष्ठ पर \"[[$3#$2|$2]]\" भाग में टिप्पणी की है।",
- "notification-mention": "[[User:$1|$1]] ने $5 के वार्ता पृष्ठ पर \"[[:$3#$2|$4]]\" भाग में आपका उल्लेख {{GENDER:$1|किया}} है।",
- "notification-mention-flyout": "$1 ने $5 के वार्ता पृष्ठ पर \"[[:$3#$2|$4]]\" भाग में आपका उल्लेख {{GENDER:$1|किया}} है।",
- "notification-mention-nosection": "[[User:$1|$1]] ने [[:$3|$2 वार्ता पृष्ठ]] में आपका {{GENDER:$1|उल्लेख}} किया है।",
- "notification-mention-nosection-flyout": "$1 ने [[:$3|$2 वार्ता पृष्ठ]] में आपका {{GENDER:$1|उल्लेख}} किया है।",
- "notification-user-rights": "आपके सदस्य अधिकार [[User:$1|$1]] द्वारा [[Special:Log/rights/$1|{{GENDER:$1|बदले गये}}]]। $2। [[Special:ListGroupRights|अधिक जानिये]]",
- "notification-user-rights-flyout": "आपके सदस्य अधिकार $1 द्वारा {{GENDER:$1|बदले गये}}। $2। [[Special:ListGroupRights|अधिक जानिये]]",
- "notification-user-rights-add": "आप अब {{PLURAL:$2|इस समूह|इन समूहों}} के सदस्य हैं: $1",
- "notification-user-rights-remove": "आप अब {{PLURAL:$2|इस समूह|इन समूहों}} के सदस्य नहीं रहे: $1",
- "notification-new-user": "आपका {{SITENAME}} पर स्वागत है, $1! हमे ख़ुशी है आप यहाँ आये।",
- "notification-reverted2": "[[:$2]] पर आपके {{PLURAL:$4|सम्पादन|सम्पादनों}} को [[User:$1|$1]] द्वारा {{GENDER:$1|पूर्ववत}} कर दिया गया है। $3",
- "notification-reverted-flyout2": "$2 पर आपके {{PLURAL:$4|सम्पादन|सम्पादनों}} को $1 द्वारा {{GENDER:$1|पूर्ववत}} कर दिया गया है। $3",
+ "notification-link-article-reminder": "लेख देखें",
+ "notification-header-reverted": "$3 पर आपके {{PLURAL:$4|सम्पादन|सम्पादनों}} को $1 द्वारा {{GENDER:$2|पूर्ववत}} कर दिया गया है।",
+ "notification-header-emailuser": "$1 ने आपको ईमेल {{GENDER:$2|भेजा}} है।",
"notification-edit-talk-page-email-subject2": "$1 ने आपके लिए {{SITENAME}} पर संदेश {{GENDER:$1|छोड़ा है}}",
- "notification-edit-talk-page-email-batch-body2": "$1 ने आपके वार्ता पृष्ठ पर संदेश {{GENDER:$1|छोड़ा है}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 ने आपके वार्ता पृष्ठ पर \"$2\" भाग में संदेश {{GENDER:$1|छोड़ा है}}।",
"notification-page-linked-email-subject": "आपका पृष्ठ {{SITENAME}} पर लिंक किया गया",
- "notification-page-linked-email-batch-body": "$2 {{GENDER:$1|लिंक किया गया}} $3 से।",
"notification-reverted-email-subject2": "{{SITENAME}} पर आपके {{PLURAL:$3|सम्पादन|सम्पादनों}} को {{GENDER:$1|पूर्ववत}} किया गया।",
- "notification-reverted-email-batch-body2": "$2 पर आपके {{PLURAL:$3|सम्पादन|सम्पादनों}} को $1 द्वारा {{GENDER:$1|पूर्ववत}} किया गया।",
"notification-mention-email-subject": "$1 ने {{SITENAME}} पर आपका {{GENDER:$1|उल्लेख}} किया",
- "notification-mention-email-batch-body": "$1 ने $4 के वार्ता पृष्ठ पर \"$3\" भाग में आपका {{GENDER:$1|उल्लेख}} किया।",
- "notification-mention-nosection-email-batch-body": "$1 ने $2 वार्ता पृष्ठ में आपका {{GENDER:$1|उल्लेख}} किया।",
"notification-user-rights-email-subject": "{{SITENAME}} पर आपके सदस्य अधिकार बदले गए हैं",
- "notification-user-rights-email-batch-body": "आपके सदस्य अधिकार $1 द्वारा {{GENDER:$1|बदले गए}} हैं। $2।",
- "echo-email-subject-default": "{{SITENAME}} पर नई अधिसूचना",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1से}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 मि}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 घ}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 दि}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 मा}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 व}}",
+ "notification-timestamp-today": "आज",
+ "notification-timestamp-yesterday": "कल",
+ "notification-inbox-filter-read": "पढ़ें",
+ "notification-inbox-filter-unread": "बिना पढ़े",
+ "notification-inbox-filter-all": "सभी",
"echo-email-body-default": "आपके लिए {{SITENAME}} पर नई अधिसूचना है:\n\n$1",
- "echo-email-batch-body-default": "आपके लिए नई अधिसूचना है।",
"echo-email-footer-default": "$2\n\nहमारी ओर से भेजे जाने वाले ईमेलों पर नियंत्रण करने के लिये कृपया अपनी पसन्द देखिए:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "हमारी ओर से भेजे जाने वाले ईमेलों पर नियंत्रण करने के लिये <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">अपनी पसन्द देखिए</a>।<br />\n\n$1",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|अपनी}} पसंद देखें",
+ "echo-notification-alert": "{{PLURAL:$1|सूचना ($1)|सूचना ($1)|100=सूचना (99+)}}",
"echo-notification-alert-text-only": "चेतावनी",
- "echo-notification-message-text-only": "संदेश",
- "echo-overlay-link": "सभी अधिसूचनाएँ",
- "echo-overlay-title": "<b>अधिसूचनाएँ</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|अधिसूचनाएँ}}</b>($2 अपठित में से $1 दिखाई जा रही हैं)",
+ "echo-notification-notice-text-only": "सूचना",
+ "echo-overlay-link": "सभी सूचनायें",
+ "echo-overlay-title": "<b>सूचनायें</b>",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|सूचना|सूचनायें}}</b> ($2 अपठित में से $1 दिख रहा)",
"echo-mark-all-as-read": "सभी पढ़ी गयी चिन्हित करें",
+ "echo-mark-wiki-as-read": "चुने विकियों के सभी को पढ़ा चिन्हित करें: $1",
"echo-date-today": "आज",
"echo-date-yesterday": "कल",
"echo-load-more-error": "अधिक परिणाम प्राप्त करते समय एक त्रुटि हुई।",
- "notification-edit-talk-page-bundle": "$1 और $3 {{PLURAL:$4|अन्य}} ने आपके [[User talk:$2|वार्ता पृष्ठ]] पर सन्देश छोड़े हैं।",
- "notification-page-linked-bundle": "$2 की कड़ी $3 और $4 अन्य {{PLURAL:$5|पृष्ठ|पृष्ठों}} पर {{GENDER:$1|जोड़ी}} गयी। [[Special:WhatLinksHere/$2|इस पृष्ठ से जुड़ने वाले सभी पृष्ठ देखें]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 और $2 {{PLURAL:$3|अन्य}} ने आपके वार्ता पृष्ठ पर सन्देश छोड़े हैं।",
- "notification-page-linked-email-batch-bundle-body": "$2 की कड़ी $3 और $4 अन्य {{PLURAL:$5|पृष्ठ|पृष्ठों}} में {{GENDER:$1|जोड़ी}} गयी।",
+ "notification-bundle-header-edit-user-talk-v2": "<strong>{{GENDER:$3|आपके}} वार्ता पृष्ठ</strong> पर {{PLURAL:$1|एक नया संदेश आया है।|$1 नये संदेश आये हैं।|100=99+ नये संदेश आये हैं।}}",
"echo-email-batch-subject-daily": "आपके लिये {{SITENAME}} पर नई {{PLURAL:$2|अधिसूचना है|अधिसूचनाएँ हैं}}।",
"echo-email-batch-subject-weekly": "आपके लिये {{SITENAME}} पर इस सप्ताह नई {{PLURAL:$2|अधिसूचना है|अधिसूचनाएँ हैं}}।",
"echo-email-batch-body-intro-daily": "नमस्कार $1,\n{{SITENAME}} पर आज की गतिविधि का सारांश निम्न है।",
"echo-email-batch-body-intro-weekly": "नमस्कार $1,\n{{SITENAME}} पर इस सप्ताह की गतिविधि का सारांश निम्न है।",
- "echo-email-batch-link-text-view-all-notifications": "सभी अधिसूचनाएँ देखें",
- "echo-rev-deleted-text-view": "यह पृष्ठ अवतरण छिपा दिया गया है।",
- "apihelp-echomarkread-description": "वर्तमान सदस्य की अधिसूचनाओं पढ़ी गई रेखांकित करें।",
- "apihelp-echomarkread-param-list": "अधिसूचनाओं के आई०डी० की सूची जिन्हें पढ़े जाने के तौर पर रेखांकित करना है।",
- "apihelp-echomarkread-param-all": "यदि तय हो, किसी सदस्य की सारे अधिसूचनाओं पढ़े जाने के तौर पर रेखांकित करें।",
- "apihelp-echomarkread-param-sections": "अनुभागों की सूची जिन्हें पढ़े जाने के तौर पर रेखांकित करना है।",
- "apihelp-echomarkread-example-1": "अधिसूचना ८ को पढ़े जाने के तौर पर चिन्हित करें",
- "apihelp-echomarkread-example-2": "सभी अधिसूचनाओं को पढ़े जाने के तौर पर चिन्हित करें",
- "apihelp-echomarkseen-description": "वर्तमान सदस्य की अधिसूचनाओं पढ़ी गई रेखांकित करें।",
- "apihelp-echomarkseen-example-1": "अधिसूचनाओं को देखे जाने के तौर पर चिन्हित करें",
- "apihelp-query+notifications-param-sections": "पूछताछ के अधिसूचना अनुभाग",
- "apihelp-query+notifications-example-1": "अधिसूचनाओं को सूचीबद्ध करें",
- "apihelp-query+notifications-example-2": "अधिसूचनाओं को सूचीबद्ध अनुभाग के अनुसार सम्मिलित करके गिनकर करें"
+ "echo-email-batch-link-text-view-all-notifications": "सभी सूचनायें देखें"
}
diff --git a/Echo/i18n/hif-latn.json b/Echo/i18n/hif-latn.json
new file mode 100644
index 00000000..aea435de
--- /dev/null
+++ b/Echo/i18n/hif-latn.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Abdul Kadir"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Aap ke}} alerts"
+}
diff --git a/Echo/i18n/hr.json b/Echo/i18n/hr.json
index 911e1417..bc66aa73 100644
--- a/Echo/i18n/hr.json
+++ b/Echo/i18n/hr.json
@@ -3,17 +3,22 @@
"authors": [
"Amire80",
"MaGa",
- "Roberta F."
+ "Roberta F.",
+ "Ex13",
+ "Bugoslav",
+ "Wumbolo"
]
},
- "echo-desc": "Sustav obavješćivanja",
+ "echo-desc": "Sustav obavješćivanja suradnika o događajima i porukama",
"prefs-echo": "Obavijesti",
"prefs-emailsettings": "Mogućnosti elektroničke pošte",
"prefs-displaynotifications": "Opcije prikaza",
"prefs-echosubscriptions": "Obavijesti me o događajima",
+ "prefs-echocrosswiki": "Obavijesti s drugih wikija",
"prefs-newmessageindicator": "Pokazivač novih poruka",
+ "prefs-blocknotificationslist": "Suradnici čije obavijesti i vijestice ne želite primati",
"echo-pref-send-me": "Pošalji mi:",
- "echo-pref-send-to": "Pošalji:",
+ "echo-pref-send-to": "Pošalji na:",
"echo-pref-email-format": "Oblik e-poruke:",
"echo-pref-web": "Mreža",
"echo-pref-email": "Elektronička pošta",
@@ -23,74 +28,129 @@
"echo-pref-email-frequency-weekly": "tjedni sažetak obavijesti",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "obični tekst",
- "echo-pref-new-message-indicator": "Prikaži pokazivač poruka na stranici za razgovor na mojoj alatnoj traci",
+ "echo-pref-cross-wiki-notifications": "Prikaži obavijesti s drugih wikija",
+ "echo-pref-notifications-blacklist": "Popis suradnika koji Vam, u većini slučajeva, ne će više moći slati obavijesti i vijestice (nema utjecaja na izmjene na Vašoj razgovornoj stranici; [[mw:Help:Notifications#mute|saznaj više]])",
+ "echo-pref-new-message-indicator": "Prikaži pokazivač poruka uz stranicu za razgovor na mojoj alatnoj traci",
+ "echo-pref-beta-feature-cross-wiki-message": "Poboljšane obavijesti",
+ "echo-pref-beta-feature-cross-wiki-description": "Jednostavniji pregled i organiziranje obavijesti, uključujući i mogućnost pregleda obavijesti s drugih wikija.",
"echo-learn-more": "Saznajte više",
+ "echo-log": "Javni očevidnik",
"echo-new-messages": "Imate nove poruke",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Poruka}} na stranici za razgovor",
- "echo-category-title-article-linked": "{{PLURAL:$1|Poveznica|Poveznice|Poveznica}} na stranicu",
+ "echo-category-title-article-linked": "Stavljanja {{PLURAL:$1|poveznica|poveznice|poveznica}} na stranicu",
"echo-category-title-reverted": "Uklanjanje {{PLURAL:$1|uređivanja}}",
- "echo-category-title-mention": "Spominjanja",
+ "echo-category-title-mention": "{{PLURAL:$1|Spominjanje|Spominjanja}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Neuspješno spominjanje|Neuspješna spominjanja|Neuspješnih spominjanja}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Uspješno spominjanje|Uspješna spominjanja|Uspješnih spominjanja}}",
"echo-category-title-system": "{{PLURAL:$1|Sustav}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Promjena suradničkih prava}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-poruka od drugog suradnika|E-poruke od drugih suradnika}}",
"echo-pref-tooltip-edit-user-talk": "Obavijesti me kad netko snimi poruku ili odgovori na mojoj stranici za razgovor.",
- "echo-pref-tooltip-article-linked": "Obavijesti me kad netko doda poveznicu na stranicu koju sam započeo.",
+ "echo-pref-tooltip-article-linked": "Obavijesti me kad netko doda poveznicu na stranicu koju sam započeo s druge stranice.",
"echo-pref-tooltip-reverted": "Obavijesti me kad netko ukloni moje uređivanje.",
- "echo-pref-tooltip-mention": "Obavijesti me kad netko doda poveznicu prema mojoj suradničkoj stranici s bilo koje razgovorne stranice.",
+ "echo-pref-tooltip-mention": "Obavijesti me kad netko doda poveznicu prema mojoj suradničkoj stranici.",
"echo-pref-tooltip-user-rights": "Obavijesti me kad netko promijeni moja suradnička prava.",
- "echo-no-agent": "[Nitko]",
- "echo-no-title": "[Nema stranice]",
+ "echo-pref-tooltip-emailuser": "Obavijesti me kada mi netko pošalje e-poštu.",
"notifications": "Obavijesti",
- "tooltip-pt-notifications-alert": "Vaše obavijesti",
- "tooltip-pt-notifications-message": "Vaše poruke",
- "echo-specialpage": "Obavijesti",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Vaše}} obavijesti",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Vaše}} vijestice",
+ "echo-specialpage": "Obavijesti i vijestice",
+ "echo-specialpage-section-markread": "Označi grupu kao pročitanu",
+ "echo-specialpage-markasread": "Obavijest: označi kao pročitano",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|obavijest|obavijesti}}",
+ "echo-specialpage-pagefilters-title": "Nedavna aktivnost",
+ "echo-specialpage-pagefilters-subtitle": "Stranice s nepročitanim obavijestima",
"echo-anon": "Da biste primali obavijesti, [$1 otvorite račun] ili se [$2 prijavite].",
"echo-none": "Nemate obavijesti.",
"echo-more-info": "Više informacija",
"echo-feedback": "Povratna informacija",
+ "echo-popup-footer-special-page-invitation": "<strong>Isprobajte redizajniranu stranicu s obavijestima.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Novi izgled i mogućnosti.",
+ "echo-api-failure": "Dobavljanje obavijesti/vijestica nije bilo uspješno!",
+ "echo-notification-placeholder": "Nema obavijesti.",
+ "echo-notification-placeholder-filters": "Nema obavijesti prema zadanom kriteriju.",
+ "echo-notification-loginrequired": "Morate biti prijavljeni da biste vidjeli vaše obavijesti.",
+ "echo-notification-popup-loginrequired": "Da biste vidjeli vaše obavijesti, molimo prijavite se.",
+ "echo-notification-markasread": "Označi kao pročitano",
+ "echo-notification-markasunread": "Označi kao nepročitano",
+ "echo-notification-markasread-tooltip": "Označi kao pročitano",
+ "echo-notification-more-options-tooltip": "Više mogućnosti",
+ "notification-link-text-expand-all": "Proširi",
+ "notification-link-text-expand-alert-count": "Vidi {{PLURAL:$1|$1 obavijest|$1 obavijesti}}",
+ "notification-link-text-expand-notice-count": "Vidi {{PLURAL:$1|$1 vijesticu|$1 vijestice|$1 vijestica}}",
+ "notification-link-text-expand-all-count": "Vidi {{PLURAL:$1|$1 obavijest|$1 obavijesti}}",
+ "notification-link-text-collapse-all": "Sažmi",
"notification-link-text-view-message": "Pogledajte poruku",
"notification-link-text-view-mention": "Pogledaj spominjanja",
- "notification-link-text-view-changes": "Prikaži promjene",
+ "notification-link-text-view-changes": "{{GENDER:$1|Pregled}} promjena",
"notification-link-text-view-page": "Vidi stranicu",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|Vam je ostavio|Vam je ostavila}} poruku na {{GENDER:$3|Vašoj}} stranici za razgovor.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|Vam je ostavio|Vam je ostavila}} poruku na {{GENDER:$3|Vašoj}} stranici za razgovor u odlomku \"$4\".",
+ "notification-header-page-linked": "{{GENDER:$2|Suradnik|Suradnica}} $1 {{GENDER:$2|načinio je|načinila je}} poveznicu na stranici <strong>$4</strong> prema <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Povezano sa stranice <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Stranica $3 je {{GENDER:$2|povezana}} sa stranicom $4 i s još $5 {{PLURAL:$6|stranicom|stranice|stranica}}.",
+ "notification-link-text-what-links-here": "Sve poveznice na ovu stranicu",
+ "notification-header-mention-other": "$1 Vas je {{GENDER:$2|spomenuo|spomenula}} {{GENDER:$3|na}} <strong>$4</strong> u „<strong>$5</strong>”.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>razgovornoj stranici {{GENDER:$5|suradnika|suradnice}} $4</strong> u odlomku »<strong>$6</strong>«.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>razgovornoj stranici {{GENDER:$5|suradnika|suradnice}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na <strong>{{GENDER:$2|svojoj}} razgovornoj stranici</strong> u odlomku »<strong>$4</strong>«.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|Vas}} je {{GENDER:$2|spomenuo|spomenula}} na razgovornoj stranici <strong>$4</strong> u temi \"<strong>$5</strong>\".",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Vaše}} spominjanje suradnika <strong>$3</strong> nije bilo poslano, jer suradničko ime nije bilo moguće pronaći.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Vaše}} spominjanje suradnika <strong>$3</strong> nije poslano, jer je neprijavljeni suradnik anoniman.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Spominjanje koje|$3 spominjanja koja}} ste Vi {{GENDER:$2|poslali|poslala}}, a putem razgovorne stranice <strong>$4</strong>, {{PLURAL:$3|nije bilo isporučeno|nisu bila isporučena}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Suradničko ime nije pronađeno:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Neprijavljeni suradnici ne mogu biti spomenuti:</strong> $1",
+ "notification-header-mention-success": "<strong>$3</strong> je {{GENDER:$3|obaviješten|obaviještena}} da {{GENDER:$2|ste}} {{GENDER:$3|ga|je}} spomenuli.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Spominjanje koje|$3 spominjanja koja}} ste Vi {{GENDER:$2|poslali|poslala}}, a putem razgovorne stranice <strong>$4</strong>, {{PLURAL:$3|bilo je isporučeno|bila su isporučena}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Spomenuo si suradnika|Spomenula si suradnika|Spomenuli ste suradnika}}:</strong> $3",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Vašu}} pripadnost suradničkim skupinama {{GENDER:$1|promijenio|promijenila}} je {{GENDER:$1|suradnik|suradnica}} $1. Sad ste {{GENDER:$4|pripadnikom|pripadnicom}} suradničke skupine: $2.",
+ "notification-welcome-linktext": "Dobro došli",
+ "notification-header-thank-you-1-edit": "Upravo {{GENDER:$2|ste}} načinili {{GENDER:$2|Vaše}} prvo uređivanje, zahvaljujemo {{GENDER:$2|Vam}} i dobro nam došli!",
+ "notification-header-thank-you-10-edit": "Upravo {{GENDER:$2|ste}} načinili {{GENDER:$2|Vaše}} deseto uređivanje, zahvaljujemo {{GENDER:$2|Vam}} i molimo Vas da tako i nastavite!",
+ "notification-header-thank-you-100-edit": "Upravo {{GENDER:$2|ste}} načinili {{GENDER:$2|Vaše}} stoto uređivanje, zahvaljujemo {{GENDER:$2|Vam}} i očekujemo da ćete nastaviti tako i dalje!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Poštovani|Poštovana}}, upravo {{GENDER:$2|ste}} načinili {{GENDER:$2|Vaše}} tisućito uređivanje, zahvaljujemo {{GENDER:$2|Vam}} i molimo Vas da nastavite biti {{GENDER:$2|odličnim doprinositeljom|odličnom doprinositeljicom}}!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Poštovani|Poštovana}}, upravo {{GENDER:$2|ste}} načinili {{GENDER:$2|Vaše}} desettisućito uređivanje, neizmjerno {{GENDER:$2|Vam}} zahvaljujemo i molimo Vas da nastavite biti {{GENDER:$2|izvrsnim doprinositeljom|izvrsnom doprinositeljicom}}!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Poštovani|Poštovana}}, upravo {{GENDER:$2|ste}} načinili {{GENDER:$2|Vaše}} stotisućito uređivanje, zahvaljujemo {{GENDER:$2|Vam}} na iznimnom doprinosu te Vas molimo da nastavite biti {{GENDER:$2|izvanrednim doprinositeljom|izvanrednom doprinositeljicom}}!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Poštovani|Poštovana}}, upravo {{GENDER:$2|ste}} načinili {{GENDER:$2|Vaše}} milijunto uređivanje, zahvaljujemo {{GENDER:$2|Vam}} na tom nevjerojatno zadivljujućem doprinosu!",
"notification-link-text-view-edit": "Prikaži promjene",
- "notification-edit-talk-page2": "[[User:$1|$1]] je {{GENDER:$1|ostavio|ostavila}} poruku na Vašoj [[User talk:$2#$3|razgovornoj stranici]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] je {{GENDER:$1|ostavio|ostavila}} poruku na Vašoj razgovornoj stranici \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 je {{GENDER:$1|ostavio|ostavila}} poruku na Vašoj [[User talk:$2#$3|razgovornoj stranici]].",
- "notification-edit-talk-page-flyout-with-section": "$1 je {{GENDER:$1|ostavio|ostavila}} poruku na Vašoj razgovornoj stranici u \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Članak [[:$2]] je {{GENDER:$1|povezan}} s člankom [[:$3]]. [[Special:WhatLinksHere/$2|Pogledajte što vodi prema ovom članku]].",
- "notification-page-linked-flyout": "Članak [[:$2]] je {{GENDER:$1|povezan}} s člankom [[:$3]].",
- "notification-mention": "[[User:$1|$1]] Vas je {{GENDER:$1|spomenuо|spomenula}} na stranici za razgovor $5, u odlomku [[:$3#$2|$4]].",
- "notification-mention-flyout": "$1 Vas je {{GENDER:$1|spomenuo|spomenula}} na stranici za razgovor $5, u odlomku [[:$3#$2|$4]].",
- "notification-user-rights": "Vaša suradnička prava [[Special:Log/rights/$1|{{GENDER:$1|promijenio|promijenila}}]] je {{GENDER:$1|suradnik|suradnica}} [[User:$1|$1]]. $2. [[Special:ListGroupRights|Saznajte više]]",
- "notification-user-rights-add": "Sada ste član {{PLURAL:$2|sljedeće grupe|sljedećih grupa}}: $1",
- "notification-reverted2": "{{PLURAL:$4|Vaše uređivanje na stranici [[:$2]]|Vaša uređivanja na stranici [[:$2]]}} {{GENDER:$1|uklonio je suradnik|uklonila je suradnica}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Vaše uređivanje na stranici $2|Vaša uređivanja na stranici $2}} {{GENDER:$1|uklonio je suradnik|uklonila je suradnica}} $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Vaše uređivanje na stranici $3|Vaša uređivanja na stranici $3}} {{GENDER:$2|uklonio je suradnik|uklonila je suradnica}} $2.",
+ "notification-header-emailuser": "$1 Vam je {{GENDER:$2|poslao|poslala}} e-poštu.",
"notification-edit-talk-page-email-subject2": "$1 Vam je {{GENDER:$1|ostavio|ostavila}} poruku na projektu {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 Vam je {{GENDER:$1|ostavio|ostavila}} poruku na Vašoj stranici za razgovor:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 je {{GENDER:$1|ostavio|ostavila}} poruku na Vašoj stranici za razgovor u odlomku \"$2\".",
- "notification-page-linked-email-subject": "Na projektu {{SITENAME}} dodana je poveznica na Vaš članak",
- "notification-page-linked-email-batch-body": "Članak $2 je {{GENDER:$1|povezan}} s člankom $3.",
+ "notification-page-linked-email-subject": "Na projektu {{SITENAME}} dodana je poveznica na stranicu koju ste stvorili",
"notification-reverted-email-subject2": "{{PLURAL:$3|Vaša izmjena je {{GENDER:$1|uklonjena}}|Vaše izmjene su {{GENDER:$1|uklonjene}}}} na projektu {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Vaše uređivanje|Vaša uređivanja}} na stranici $2 {{GENDER:$1|uklonio je|uklonila je}} $1.",
- "notification-mention-email-subject": "$1 Vas je {{GENDER:$1|spomenuo|spomenula}} na projektu {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 Vas je {{GENDER:$1|spomenuo|spomenula}} na stranici za razgovor $4, u odlomku $3.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|Vas}} je {{GENDER:$1|spomenuo|spomenula}} na projektu {{SITENAME}}",
"notification-user-rights-email-subject": "Vaša suradnička prava su promijenjena na projektu {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Vaša suradnička prava {{GENDER:$1|promijenio|promijenila}} je $1. $2.",
- "echo-email-batch-body-default": "Imate novu poruku.",
- "echo-email-footer-default": "$2\n\nUkoliko želite prilagoditi primanje e-pošte, prilagodite svoje postavke:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 sek.}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min.}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 sat|$1 sata|$1 sati}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 dan|$1 dana}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mj.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 god.}}",
+ "notification-timestamp-today": "Danas",
+ "notification-timestamp-yesterday": "Jučer",
+ "notification-inbox-filter-read": "Pročitane",
+ "notification-inbox-filter-unread": "Nepročitane",
+ "notification-inbox-filter-all": "Sve",
+ "echo-email-body-default": "Imate novu obavijest na projektu {{SITENAME}}:\n\n$1",
"echo-email-footer-default-html": "Ukoliko želite prilagoditi primanje e-pošte, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">prilagodite svoje postavke</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nUkoliko želite prilagoditi primanje e-pošte, prilagodite svoje postavke:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Da biste prilagodili primanje e-pošte, provjerite postavke:",
"echo-notification-alert": "{{PLURAL:$1|Imate jednu obavijest|Imate $1 obavijesti|100=Imate više od 100 obavijesti}}",
- "echo-notification-message": "{{PLURAL:$1|Imate jednu poruku|Imate $1 poruke|Imate $1 poruka|100=Imate više od 100 poruka}}",
+ "echo-notification-notice": "{{PLURAL:$1|Imate jednu vijesticu|Imate $1 vijestice|Imate $1 vijestica|100=Imate 100 ili više vijestica}}",
"echo-notification-alert-text-only": "Obavijesti",
- "echo-notification-message-text-only": "Poruke",
+ "echo-notification-notice-text-only": "Vijestice",
"echo-overlay-link": "Sve obavijesti",
"echo-overlay-title": "<b>Obavijesti</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Obavijesti}}</b> (prikazano $1 od $2 {{PLURAL:$1|nepročitana|nepročitane|nepročitanih}})",
"echo-mark-all-as-read": "Označi sve pročitanim",
"echo-date-today": "Danas",
"echo-date-yesterday": "Jučer",
- "notification-edit-talk-page-bundle": "$1 i još $3 {{PLURAL:$4|suradnik|suradnika}} {{GENDER:$1|ostavili}} su poruku na Vašoj [[User talk:$2|stranici za razgovor]].",
- "notification-page-linked-bundle": "Članak $2 je {{GENDER:$1|povezan}} s člankom $3 i još $4 {{PLURAL:$5|člankom|članka|članaka}}. [[Special:WhatLinksHere/$2|Pogledajte što vodi prema ovom članku]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 i još $2 {{PLURAL:$3|suradnik|suradnika}} {{GENDER:$1|ostavili}} su poruku na Vašoj stranici za razgovor.",
- "notification-page-linked-email-batch-bundle-body": "Članak $2 je {{GENDER:$1|povezan}} s člankom $3 i još $4 {{PLURAL:$5|člankom|članka|članaka}}.",
- "echo-email-batch-link-text-view-all-notifications": "Prikaži sve obavijesti"
+ "notification-bundle-header-edit-user-talk-v2": "$1 {{PLURAL:$2|nova poruka|nove poruke|novih poruka}} na {{GENDER:$3|Vašoj}} stranici za razgovor.",
+ "echo-email-batch-subject-daily": "Imate {{PLURAL:$2|novu obavijest|nove obavijesti}} na projektu {{SITENAME}}",
+ "echo-email-batch-subject-weekly": "Ovog tjedna imate {{PLURAL:$2|obavijest|obavijesti}} na projektu {{SITENAME}}",
+ "echo-email-batch-link-text-view-all-notifications": "Prikaži sve obavijesti",
+ "notification-header-foreign-alert": "Više obavijesti na {{PLURAL:$5|drugom wikiju|$5 druga wikija|$5 drugih wikija}}",
+ "notification-header-foreign-notice": "Više obavijesti na {{PLURAL:$5|drugom wikiju|$5 druga wikija|$5 drugih wikija}}",
+ "notification-header-foreign-all": "Više obavijesti na {{PLURAL:$5|drugom wikiju|$5 druga wikija|$5 drugih wikija}}"
}
diff --git a/Echo/i18n/hsb.json b/Echo/i18n/hsb.json
index a5d7b4ea..b0bff710 100644
--- a/Echo/i18n/hsb.json
+++ b/Echo/i18n/hsb.json
@@ -1,7 +1,8 @@
{
"@metadata": {
"authors": [
- "Michawiki"
+ "Michawiki",
+ "J budissin"
]
},
"echo-desc": "Zdźělenski system",
@@ -21,7 +22,6 @@
"echo-pref-email-frequency-weekly": "Tydźenski přehlad zdźělenkow",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Luty tekst",
- "echo-pref-notify-show-link": "Zdźělenki w symbolowej lajsće pokazać",
"echo-pref-new-message-indicator": "Powěsćowy indikator diskusijneje strony w symbolowej lajsće pokazać",
"echo-learn-more": "Dalše informacije",
"echo-new-messages": "Maš nowe powěsće",
@@ -35,13 +35,9 @@
"echo-pref-tooltip-article-linked": "Informuj mje, hdyž něchtó na stronu wotkazuje, kotruž sym z nastawka wutworił.",
"echo-pref-tooltip-reverted": "Informuj mje, hdyž něchtó z pomocu cofnjenja abo nastroja změnu anuluje, kotruž sym činił.",
"echo-pref-tooltip-mention": "Informuj mje, hdyž něchtó z někajkeje diskusijneje strony k mojej wužiwarskej stronje wotkazuje.",
- "echo-no-agent": "[Nichtó]",
- "echo-no-title": "[Žana strona]",
"echo-error-no-formatter": "Za zdźělenje njeje so formatowanje definowało.",
- "echo-error-preference": "Zmylk: Wužiwarske nastajenje njeda so stajić.",
- "echo-error-token": "Zmylk: Wužiwarski token njeda so wotwołać.",
"notifications": "Zdźělenki",
- "tooltip-pt-notifications": "Twoje zdźělenki",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Twoje}} powěsće",
"echo-specialpage": "Zdźělenki",
"echo-anon": "Zo by zdźělenki dóstał, dyrbiš [$1 konto załožić] abo [$2 so přizjewić].",
"echo-none": "Nimaš zdźělenki.",
@@ -53,45 +49,15 @@
"notification-link-text-view-changes": "Změny pokazać",
"notification-link-text-view-page": "Stronu pokazać",
"notification-link-text-view-edit": "Změnu pokazać",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|zawostaji}} powěsć na twojej [[User talk:$2#$3|diskusijnej stronje]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|zawostaji}} powěsć na twojej diskusijnej stronje w \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|zawostaji}} powěsć na twojej [[User talk:$2#$3|diskusijnej stronje]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|zawostaji}} powěsć na twojej diskusijnej stronje w \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] je so wot [[:$3]] {{GENDER:$1|wotkazał|wotkazała}}. [[Special:WhatLinksHere/$2|Wšě wotkazy k tutej stronje pokazać]].",
- "notification-page-linked-flyout": "[[:$2]] je so wot [[:$3]] {{GENDER:$1|wotkazał}}.",
- "notification-add-comment2": "[[User:$1|$1]] je na \"[[$3|$2]]\" na diskusijnej stronje \"$4\" {{GENDER:$1|komentował|komentowała}}.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] je nowu temu \"$2\" na [[$3]] {{GENDER:$1|startował|startowała}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] je ći powěsć {{GENDER:$1|pósłał|pósłała}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] je na \"[[$3#$2|$2]]\" na twojej diskusijnej stronje {{GENDER:$1|komentował|komentowała}}.",
- "notification-mention": "[[User:$1|$1]] je će na diskusijnej stronje $5 w \"[[:$3#$2|$4]]\" {{GENDER:$1|naspomnił|naspomniła}}.",
- "notification-mention-flyout": "$1 je će na diskusijnej stronje $5 w \"[[:$3#$2|$4]]\" {{GENDER:$1|naspomnił|naspomniła}}.",
- "notification-mention-nosection": "[[User:$1|$1]] je će na [[:$3|diskusijnej stronje $2]] {{GENDER:$1|naspomnił|naspomniła}}.",
- "notification-mention-nosection-flyout": "$1 je će na [[:$3|diskusijnej stronje $2]] {{GENDER:$1|naspomnił|naspomniła}}.",
- "notification-user-rights": "Twoje wužiwarske prawa [[Special:Log/rights/$1|su so wot [[User:$1|$1]] {{GENDER:$1|změnili}}]] . $2. [[Special:ListGroupRights|Dalše informacije]]",
- "notification-user-rights-flyout": "Twoje wužiwarske prawa su so wot $1 {{GENDER:$1|změnili}}. $2. [[Special:ListGroupRights|Dalše informacije]]",
- "notification-user-rights-add": "Sy nětko čłon {{PLURAL:$2|tuteje skupiny|tuteju skupinow|tutych skupinow}}: $1",
- "notification-user-rights-remove": "Njejsy hižo čłon {{PLURAL:$2|tuteje skupiny|tuteju skupinow|tutych skupinow}}: $1",
- "notification-new-user": "Witaj do {{GRAMMAR:genitiw|{{SITENAME}}}}, $1! Wjeselimy so, zo sy tu.",
- "notification-reverted2": "[[User:$1|$1]] je {{PLURAL:$4|změnu na [[:$2]]|změnje na [[:$2]]|změny na [[:$2]]}} {{GENDER:$1|anulował|anulowała}}. $3",
- "notification-reverted-flyout2": "$1 je {{PLURAL:$4|změnu na $2|změnje na $2|změny na $2}} {{GENDER:$1|anulował|anulowała}}. $3",
+ "notification-header-reverted": "$1 je {{PLURAL:$4|změnu na $3|změnje na $3|změny na $3}} {{GENDER:$2|anulował|anulowała}}.",
"notification-edit-talk-page-email-subject2": "$1 je ći powěsć na {{GRAMMAR:lokatiw|{{SITENAME}}}} {{GENDER:$1|zawostajił|zawostajiła}}",
- "notification-edit-talk-page-email-batch-body2": "$1 je powěsć na twojej diskusijnej stronje {{GENDER:$1|zawostajił|zawostajiła}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 je powěsć wo \"$2\" na twojej diskusijnej stronje {{GENDER:$1|zawostajił|zawostajiła}}.",
"notification-page-linked-email-subject": "Twoja strona je so na {{GRAMMAR:lokatiw|{{SITENAME}}}} wotkazała.",
- "notification-page-linked-email-batch-body": "$2 je so z $3 {{GENDER:$1|wotkazał}}.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Twoja změna je|Twojej změnje stej|Twoje změny su}} so na {{GRAMMAR:lokatiw|{{SITENAME}}}}{{GENDER:$1|{{PLURAL:$3|anulowała|anulowałoj|anulowali}}}}",
- "notification-reverted-email-batch-body2": "$1 je {{PLURAL:$3|twoju změnu na $2|twojej změnje na $2|twoje změny na $2}} {{GENDER:$1|anulował|anulowała}}.",
"notification-mention-email-subject": "$1 je će na {{GRAMMAR:lokatiw|{{SITENAME}}}} {{GENDER:$1|naspomnił|naspomniła}}",
- "notification-mention-email-batch-body": "$1 je će na diskusijnej stronje $4 w \"$3\" {{GENDER:$1|naspomnił|naspomniła}}.",
- "notification-mention-nosection-email-batch-body": "$1 je će na diskusijnej stronje $2 {{GENDER:$1|naspomnił|naspomniła}}.",
"notification-user-rights-email-subject": "Twoje wužiwarske prawa su so na {{GRAMMAR:lokatiw|{{SITENAME}}}} změnili",
- "notification-user-rights-email-batch-body": "Twoje wužiwarske prawa su so wot $1 {{GENDER:$1|změnili}}. $2",
- "echo-notification-count": "$1+",
- "echo-email-subject-default": "Nowa zdźělenka na {{GRAMMAR:lokatiw|{{SITENAME}}}}",
"echo-email-body-default": "Maš nowu zdźělenku na {{GRAMMAR:lokatiw|{{SITENAME}}}}:\n\n$1",
- "echo-email-batch-body-default": "Maš nowu powěsć.",
"echo-email-footer-default": "$2\n\nZo by kontrolował, kotre e-mejle ći sćelemy, přepruwuj swoje nastajenja:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Zo by kontrolował, kotre e-mejle ći sćelemy, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">přepruwuj swoje nastajenja</a>.<br />\n$1",
"echo-overlay-link": "Wšě zdźělenki",
"echo-overlay-title": "<b>Zdźělenki</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Zdźělenka|Zdźělence|Zdźělenki}}</b> ($1 z $2 {{PLURAL:$2|njepřitaneje|njepřečitaneju|njepřečitanych}} so {{PLURAL:$1|pokazuje|pokazujetej|pokazuja|pokazuje}})",
@@ -99,15 +65,10 @@
"echo-date-today": "Dźensa",
"echo-date-yesterday": "Wčera",
"echo-load-more-error": "Při wobstarowanju dalšich wuslědkow je zmylk wustupił.",
- "notification-edit-talk-page-bundle": "$1 a {{PLURAL:$4|dalši wužiwar je|$3 dalšej wužiwarjej stej|$3 dalši wužiwarjo su|$3 dalšich wužiwarjow je}} powěsć na twojej [[User talk:$2|diskusijnej stronje]] {{PLURAL:$4|zawostajił|zawostajiłoj|zawostajili|zawostajiło}}.",
- "notification-page-linked-bundle": "$2 je so z $3 a {{PLURAL:$5|jedneje dalšeje strony|$4 dalšeju stronow|$4 dalšich stronow}} {{GENDER:$1|wotkazał}}. [[Special:WhatLinksHere/$2|Wšě wotkazy k tutej stronje pokazać]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 a {{PLURAL:$3|dalši wužiwar staj|$2 dalšej wužiwarjej su|$2 dalši wužiwarjo su|dalšich wužiwarjow su}} powěsć na twojej diskusijnej stronje {{GENDER:$1|zawostajiłoj|zawostajili}}.",
- "notification-page-linked-email-batch-bundle-body": "$2 je so wot $3 a {{PLURAL:$5|jedneje dalšeje strony|$4 dalšeju stronow|$4 dalšich stronow}} {{GENDER:$1|wotkazał}}.",
"echo-email-batch-bullet": "•",
"echo-email-batch-subject-daily": "Maš {{PLURAL:$2|nowu zdźělenku|nowej zdźělence|nowe zdźělenki}} na {{GRAMMAR:lokatiw|{{SITENAME}}}}",
"echo-email-batch-subject-weekly": "Maš {{PLURAL:$2|nowu zdźělenku|nowej zdźělence|nowe zdźělenki}} na {{GRAMMAR:lokatiw|{{SITENAME}}}} tutón tydźeń",
"echo-email-batch-body-intro-daily": "Witaj $1,\n\ntu je zjeće dźensnišich aktiwitow na {{GRAMMAR:lokatiw|{{SITENAME}}}} za tebje.",
"echo-email-batch-body-intro-weekly": "Witja $1,\n\ntu je zjeće aktiwitow z tutoho tydźenja na {{GRAMMAR:lokatiw|{{SITENAME}}}} za tebje.",
- "echo-email-batch-link-text-view-all-notifications": "Wšě zdźělenki pokazać",
- "echo-rev-deleted-text-view": "Tuta wersija strony je so potłóčiła."
+ "echo-email-batch-link-text-view-all-notifications": "Wšě zdźělenki pokazać"
}
diff --git a/Echo/i18n/hsn.json b/Echo/i18n/hsn.json
new file mode 100644
index 00000000..fe753da3
--- /dev/null
+++ b/Echo/i18n/hsn.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "SolidBlock"
+ ]
+ },
+ "echo-displaynotificationsconfiguration": "显示通知配置",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "嗯类通知",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "杂杂类型搞得的通知方法;只搞得参数设置中藏噶的分类的类型",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "冇港就是开噶",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "现成滴用户",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "新用户"
+}
diff --git a/Echo/i18n/ht.json b/Echo/i18n/ht.json
index c92712e0..8f104252 100644
--- a/Echo/i18n/ht.json
+++ b/Echo/i18n/ht.json
@@ -3,6 +3,5 @@
"authors": [
"Tisave"
]
- },
- "tooltip-pt-notifications": "Alèt ou"
+ }
}
diff --git a/Echo/i18n/hu-formal.json b/Echo/i18n/hu-formal.json
new file mode 100644
index 00000000..c46d6d76
--- /dev/null
+++ b/Echo/i18n/hu-formal.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Futhark1988"
+ ]
+ },
+ "echo-notification-markasunread": "Olvasatlannak jelölés"
+}
diff --git a/Echo/i18n/hu.json b/Echo/i18n/hu.json
index 660645cb..5b0d138b 100644
--- a/Echo/i18n/hu.json
+++ b/Echo/i18n/hu.json
@@ -8,15 +8,21 @@
"Tgr",
"Tacsipacsi",
"Samat",
- "Bináris"
+ "Bináris",
+ "Macofe",
+ "R-Joe",
+ "BanKris",
+ "Bencemac"
]
},
- "echo-desc": "Értesítési rendszer",
+ "echo-desc": "Értesíti a felhasználókat az eseményekről és üzenetekről",
"prefs-echo": "Értesítések",
"prefs-emailsettings": "E-mail beállítások",
"prefs-displaynotifications": "Megjelenítési beállítások",
"prefs-echosubscriptions": "Értesítést kérek ezekről az eseményekről",
+ "prefs-echocrosswiki": "Wikiközi értesítések",
"prefs-newmessageindicator": "Új üzenet jelzése",
+ "prefs-blocknotificationslist": "Lenémított felhasználók",
"echo-pref-send-me": "Gyakoriság:",
"echo-pref-send-to": "Erre a címre:",
"echo-pref-email-format": "A levél formátuma:",
@@ -28,94 +34,170 @@
"echo-pref-email-frequency-weekly": "Küldjön heti összefoglalót az értesítésekről",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Sima szöveg",
+ "echo-pref-cross-wiki-notifications": "Értesítések megjelenítése más wikikről",
+ "echo-pref-notifications-blacklist": "Értesítések megjelenítésének letiltása ezektől a felhasználóktól. ([[mw:Help:Notifications#mute|további információk]])",
"echo-pref-new-message-indicator": "Jelezze a vitalapi üzeneteket a lap tetején lévő menüben",
+ "echo-pref-beta-feature-cross-wiki-message": "Fejlettebb értesítések",
"echo-learn-more": "Tudj meg többet",
+ "echo-log": "Nyilvános napló",
"echo-new-messages": "Új üzeneted van",
"echo-category-title-edit-user-talk": "vitalapi {{PLURAL:$1|üzenet|üzenetek}}",
"echo-category-title-article-linked": "hivatkozott {{PLURAL:$1|lap|lapok}}",
"echo-category-title-reverted": "visszaállított {{PLURAL:$1|szerkesztés|szerkesztések}}",
"echo-category-title-mention": "{{PLURAL:$1|említés|említések}}",
+ "echo-category-title-mention-failure": "Sikertelen {{PLURAL:$1|említés|említések}}",
+ "echo-category-title-mention-success": "Sikeres {{PLURAL:$1|említés|említések}}",
"echo-category-title-other": "{{PLURAL:$1|Más}}",
"echo-category-title-system": "{{PLURAL:$1|rendszerüzenet|rendszerüzenetek}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Felhasználói jogok változása|Felhasználói jogok változásai}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-mail másik szerkesztőtől|E-mailek más szerkesztőktől}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|lapértesítés|lapértesítések}}",
"echo-pref-tooltip-edit-user-talk": "Értesítést kérek, ha valaki üzen vagy válaszol a vitalapomon.",
"echo-pref-tooltip-article-linked": "Értesítést kérek, ha valaki hivatkozik egy általam írt szócikkre egy másik cikkben.",
- "echo-pref-tooltip-reverted": "Értesítést kérek, ha valaki visszaállítja egy szerkesztésemet.",
+ "echo-pref-tooltip-reverted": "Értesítést kérek, ha valaki visszaállítja egy szerkesztésemet a visszavonás vagy a visszaállítás eszközzel.",
"echo-pref-tooltip-mention": "Értesítést kérek, ha valaki hivatkozik a felhasználói lapomra.",
+ "echo-pref-tooltip-mention-failure": "Értesítsen, amikor valakinek nem sikerült említést küldenem.",
+ "echo-pref-tooltip-mention-success": "Értesítsen, amikor említést küldök valakinek.",
"echo-pref-tooltip-user-rights": "Értesítést kérek, ha valaki megváltoztatja a felhasználói jogaimat.",
- "echo-no-agent": "[Senki]",
- "echo-no-title": "[Nincs lap]",
+ "echo-pref-tooltip-emailuser": "Értesítést kérek, ha valaki küld nekem egy e-mailt.",
+ "echo-pref-tooltip-article-reminder": "Értesítést kérek erről a lapról, amikor kérdezek.",
"echo-error-no-formatter": "Nincs értesítési formátum definiálva",
"notifications": "Értesítések",
"tooltip-pt-notifications-alert": "Értesítéseid",
- "tooltip-pt-notifications-message": "Üzeneteid",
+ "tooltip-pt-notifications-notice": "Értesítéseid",
+ "echo-displaynotificationsconfiguration": "Értesítések konfigurációjának megjelenítése",
+ "echo-displaynotificationsconfiguration-summary": "Ez egy áttekintés az Értesítések konfigurációjáról ezen a wikin.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Értesítések kategóriánként",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Típusok beosztása",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Melyik részbe kerülnek az egyes értesítéstípusok",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Engedélyezett értesítési módok",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Melyik értesítési módok támogatottak az egyes kategóriákban",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Alapértelmezetten bekapcsolva",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Létező felhasználóknak",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Új felhasználóknak",
"echo-specialpage": "Értesítések",
+ "echo-specialpage-section-markread": "Csoport megjelölése olvasottként",
+ "echo-specialpage-markasread": "Értesítés: Megjelölés olvasottként",
+ "echo-specialpage-markasread-invalid-id": "Érvénytelen eseményazonosító",
+ "echo-specialpage-pagination-numnotifications": "$1 értesítés",
+ "echo-specialpage-pagefilters-title": "Friss tevékenység",
+ "echo-specialpage-pagefilters-subtitle": "Lapok olvasatlan értesítésekkel",
+ "notificationsmarkread-legend": "Értesítés megjelölése olvasottként",
"echo-anon": "Értesítések fogadásához [$1 hozz létre egy fiókot] vagy [$2 jelentkezz be].",
"echo-none": "Nincsenek értesítéseid.",
"echo-more-info": "További információ",
"echo-feedback": "Visszajelzés",
+ "echo-popup-footer-special-page-invitation": "<strong>Próbáld ki az újratervezett Értesítések lapot.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Teljesen új megjelenés és funkciók.",
+ "echo-api-failure": "Nem sikerült lekérni az értesítéseket.",
+ "echo-api-failure-cross-wiki": "A hozzáférés a távoli tartományhoz elutasítva.",
+ "echo-notification-placeholder": "Nincsenek értesítések.",
+ "echo-notification-placeholder-filters": "Nincs a feltételeknek megfelelő értesítés.",
+ "echo-notification-loginrequired": "Be kell jelentkezned, hogy lásd az értesítéseidet.",
+ "echo-notification-popup-loginrequired": "Az értesítéseid megtekintéséhez jelentkezz be.",
+ "echo-notification-markasread": "Megjelölés olvasottként",
+ "echo-notification-markasunread": "Megjelölés olvasatlanként",
+ "echo-notification-markasread-tooltip": "Megjelölés olvasottként",
+ "echo-notification-more-options-tooltip": "További lehetőségek",
+ "notification-dynamic-actions-unwatch": "Új tevékenységek figyelésének {{GENDER:$3|leállítása}} a(z) „$1” lapon",
+ "notification-dynamic-actions-unwatch-confirmation": "Már nem {{GENDER:$3|figyeled}} a(z) „$1” lapot",
+ "notification-dynamic-actions-unwatch-confirmation-description": "Bármikor újra {{GENDER:$3|figyelheted}} [$2 ezt a lapot].",
+ "notification-dynamic-actions-watch": "Új tevékenységek {{GENDER:$3|figyelése}} a(z) „$1” lapon",
+ "notification-dynamic-actions-watch-confirmation": "Mostantól {{GENDER:$3|figyeled}} a(z) „$1” lapot",
+ "notification-dynamic-actions-watch-confirmation-description": "Bármikor {{GENDER:$3|abbahagyhatod}} [$2 ennek a lapnak] a figyelését.",
+ "notification-link-text-expand-all": "Kibontás",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|egy|$1}} figyelmeztetés megtekintése",
+ "notification-link-text-expand-notice-count": "$1 értesítés megtekintése",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|egy|$1}} értesítés megtekintése",
+ "notification-link-text-collapse-all": "Becsukás",
"notification-link-text-view-message": "Üzenet mutatása",
"notification-link-text-view-mention": "Említés mutatása",
- "notification-link-text-view-changes": "Változások mutatása",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Említés|Említések}} megjelenítése",
+ "notification-link-text-view-changes": "Változások {{GENDER:$1|mutatása}}",
"notification-link-text-view-page": "Lap mutatása",
+ "notification-header-edit-user-talk": "$1 üzenetet {{GENDER:$2|hagyott}} {{GENDER:$3|a <strong>vitalapodon</strong>}}.",
+ "notification-header-edit-user-talk-with-section": "$1 üzenetet {{GENDER:$2|hagyott}} {{GENDER:$3|a <strong>vitalapodon</strong>}} a(z) „<strong>$4</strong>” szakaszban.",
+ "notification-header-page-linked": "A(z) <strong>$3</strong> lapra hivatkoztak a(z) <strong>$4</strong> lapról.",
+ "notification-compact-header-page-linked": "Hivatkozva a(z) <strong>$1</strong> lapról.",
+ "notification-bundle-header-page-linked": "Hivatkozás készült {{PLURAL:$5||$5 lapról|100=99+ lapról}} a(z) <strong>$3</strong> lapra.",
+ "notification-link-text-what-links-here": "Összes hivatkozás erre a lapra",
+ "notification-header-mention-other": "$1 {{GENDER:$2$3|megemlített}} a(z) <strong>$4</strong> lapon a(z) „<strong>$5</strong>” szakaszban.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2$3|megemlített}} a(z) <strong>$4</strong> lapon.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2$3|megemlített}} <strong>$4 {{GENDER:$5|vitalapján}}</strong> a(z) „<strong>$6</strong>” szakaszban.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2$3|megemlített}} <strong>$4 {{GENDER:$5|vitalapján}}</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|megemlített}} a <strong>{{GENDER:$2|vitalapján}}</strong> a(z) „<strong>$4</strong>” szakaszban.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|megemlített}} a <strong>{{GENDER:$2|vitalapján}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2$3|megemlített}} a(z) <strong>$4</strong> vitalapon a(z) „<strong>$5</strong>” szakaszban.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2$3|megemlített}} a(z) <strong>$4</strong> vitalapon.",
+ "notification-header-mention-failure-user-unknown": "<strong>$3</strong> említése nem lett {{GENDER:$2|elküldve}}, mert a felhasználó nem található.",
+ "notification-header-mention-failure-user-anonymous": "<strong>$3</strong> említése nem lett {{GENDER:$2|elküldve}}, mert a felhasználó névtelen.",
+ "notification-header-mention-failure-too-many": "Több mint $3 felhasználót {{GENDER:$2|próbáltál}} megemlíteni. A korlátot túllépő értesítések nem lettek elküldve.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Egy|$3}} {{GENDER:$2|említésedet}} a(z) <strong>$4</strong> vitalapon nem sikerült elküldeni.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>A felhasználónév nem létezik:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-ket nem lehet megemlíteni:</strong> $1",
+ "notification-header-mention-success": "<strong>$3</strong> említése {{GENDER:$2|elküldve}}.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Egy|$3}} {{GENDER:$2|említésed}} a(z) <strong>$4</strong> vitalapról elküldve.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Megemlítetted}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Egy|$3}} értesítés a(z) <strong>$4</strong> vitalapon lévő {{GENDER:$2|említéseidről}}: $5 nincs elküldve, $6 elküldve.",
+ "notification-header-user-rights-add-only": "{{GENDER:$1|Megváltoztak}} a {{GENDER:$4|jogosultságaid}}. Tagja lettél {{PLURAL:$3|ennek a csoportnak|ezeknek a csoportoknak}}: $2",
+ "notification-header-user-rights-remove-only": "{{GENDER:$1|Megváltoztak}} a {{GENDER:$4|jogosultságaid}}. Kikerültél {{PLURAL:$3|ebből a csoportból|ezekből a csoportokból}}: $2",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$1|Megváltoztak}} a {{GENDER:$6|jogosultságaid}}. Tagja lettél {{PLURAL:$3|ennek a csoportnak|ezeknek a csoportoknak}}: $2. Kikerültél {{PLURAL:$5|ebből a csoportból|ezekből a csoportokból}}: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Üdvözlünk}} a(z) {{SITENAME}} wikin, $1! Örülünk, hogy itt {{GENDER:$2|vagy}}.",
+ "notification-welcome-linktext": "Üdvözlet",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Elkészítetted}} az első szerkesztésedet; köszönjük és üdvözlünk!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Elkészítetted}} a tizedik szerkesztésedet; köszönjük és csak így tovább!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Elkészítetted}} a századik szerkesztésedet; nagyon köszönjük!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Elkészítetted}} az ezredik szerkesztésedet; köszönjük, hogy ilyen nagy szerkesztő vagy!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Elkészítetted}} a tízezredik szerkesztésedet; nagyon-nagyon köszönjük!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Elkészítetted}} a százezredik szerkesztésedet; köszönjük ezt az elképesztő hozzájárulást!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Elkészítetted}} a milliomodik szerkesztésedet; köszönjük a megdöbbentő hozzájárulásodat!",
+ "notification-link-thank-you-edit": "A {{GENDER:$1|szerkesztésed}}",
"notification-link-text-view-edit": "Szerkesztés mutatása",
- "notification-edit-talk-page2": "[[User:$1|$1]] üzenetet hagyott [[User talk:$2#$3|a vitalapodon]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] üzenetet hagyott a vitalapodon „[[User talk:$2#$3|$4]]” címmel.",
- "notification-edit-talk-page-flyout2": "$1 üzenetet hagyott [[User talk:$2#$3|a vitalapodon]].",
- "notification-edit-talk-page-flyout-with-section": "$1 üzenetet hagyott a vitalapodon „[[User talk:$2#$3|$4]]” címmel.",
- "notification-page-linked": "A(z) [[:$2]] szócikkedre {{GENDER:$1|hivatkoztak}} a(z) [[:$3]] cikkben. [[Special:WhatLinksHere/$2|Kilistázhatod az összes hivatkozást a szócikkre]].",
- "notification-page-linked-flyout": "A(z) [[:$2]] szócikkedre {{GENDER:$1|hivatkoztak}} a(z) [[:$3]] cikkben.",
- "notification-add-comment2": "[[User:$1|$1]] hozzászólt a(z) „[[$3|$2]]” témához a(z) „$4” vitalapon",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] új témát kezdett „$2” néven a(z) [[$3]] lapon.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] üzenetet küldött neked: „[[$3#$2|$2]]”",
- "notification-add-comment-yours2": "[[User:$1|$1]] hozzászólt a „[[$3#$2|$2]]” témához a vitalapodon",
- "notification-mention": "[[User:$1|$1]] megemlített téged $5 vitalapján a(z) „[[:$3#$2|$4]]” szakaszban.",
- "notification-mention-flyout": "$1 megemlített téged $5 vitalapján a(z) „[[:$3#$2|$4]]” szakaszban.",
- "notification-mention-nosection": "[[User:$1|$1]] megemlített téged [[:$3|$2 vitalapján]].",
- "notification-mention-nosection-flyout": "$1 megemlített téged [[:$3|$2 vitalapján]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|megváltoztatta a jogosultságaidat]]. $2. [[Special:ListGroupRights|Információ a jogosultságokról]]",
- "notification-user-rights-flyout": "$1 megváltoztatta a jogosultságaidat. $2. [[Special:ListGroupRights|Információ a jogosultságokról]]",
- "notification-user-rights-add": "Tagja lettél {{PLURAL:$2|ennek a csoportnak|ezeknek a csoportoknak}}: $1",
- "notification-user-rights-remove": "Kikerültél {{PLURAL:$2|ebből a csoportból|ezekből a csoportokból}}: $1",
- "notification-new-user": "Kedves $1! Üdvözlünk a {{SITENAME}} oldalon. Örülünk, hogy csatlakoztál hozzánk.",
- "notification-reverted2": "[[User:$1|$1]] visszavonta a {{PLURAL:$4|szerkesztésedet|szerkesztéseidet}} a(z) [[:$2]] cikkben. $3",
- "notification-reverted-flyout2": "$1 visszavonta a {{PLURAL:$4|szerkesztésedet|szerkesztéseidet}} a(z) $2 cikkben. $3",
+ "notification-header-reverted": "{{GENDER:$2|Visszavonták}} a {{PLURAL:$4|szerkesztésedet|szerkesztéseidet}} a(z) <strong>$3</strong> cikkben.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|küldött}} neked egy e-mailt",
"notification-edit-talk-page-email-subject2": "$1 üzenetet hagyott neked a(z) {{SITENAME}} wikin",
- "notification-edit-talk-page-email-batch-body2": "$1 üzenetet hagyott a vitalapodon:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 üzenetet hagyott a vitalapodon a(z) „$2” szakaszban.",
"notification-page-linked-email-subject": "Hivatkoztak egy általad létrehozott oldalra a(z) {{SITENAME}} wikin",
- "notification-page-linked-email-batch-body": "A(z) $2 lapra {{GENDER:$1|hivatkoztak}} a(z) $3 lapról.",
"notification-reverted-email-subject2": "Visszavonták a {{PLURAL:$3|szerkesztésedet|szerkesztéseidet}} a(z) {{SITENAME}} wikin",
- "notification-reverted-email-batch-body2": "$1 visszavonta a {{PLURAL:$3|szerkesztésedet|szerkesztéseidet}} a(z) $2 oldalon.",
- "notification-mention-email-subject": "$1 említett téged a(z) {{SITENAME}} wikin",
- "notification-mention-email-batch-body": "$1 említett téged $4 vitalapján a(z) „$3” szakaszban.",
- "notification-mention-nosection-email-batch-body": "$1 megemlített téged $2 vitalapján.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|megemlített}} a(z) {{SITENAME}} wikin",
"notification-user-rights-email-subject": "Megváltoztak a jogosultságaid a(z) {{SITENAME}} wikin",
- "notification-user-rights-email-batch-body": "$1 megváltoztatta a jogosultságaidat. $2",
- "echo-email-subject-default": "Új értesítés a(z) {{SITENAME}} wikin",
+ "notification-timestamp-ago-seconds": "$1 mp",
+ "notification-timestamp-ago-minutes": "$1 p",
+ "notification-timestamp-ago-hours": "$1 ó",
+ "notification-timestamp-ago-days": "$1 n",
+ "notification-timestamp-ago-months": "$1 hó",
+ "notification-timestamp-ago-years": "$1 év",
+ "notification-timestamp-today": "Ma",
+ "notification-timestamp-yesterday": "Tegnap",
+ "notification-inbox-filter-read": "Olvasott",
+ "notification-inbox-filter-unread": "Olvasatlan",
+ "notification-inbox-filter-all": "Mind",
"echo-email-body-default": "Új értesítést kaptál a(z) {{SITENAME}} wikin:\n\n$1",
- "echo-email-batch-body-default": "Új értesítést kaptál.",
+ "echo-email-footer-default-html": "A <a href=\"$2\" style=\"text-decoration:none; color:#3868B0;\">beállításaidnál</a> módosíthatod, mikor küldjünk e-mailt.<br />\n$1",
"echo-email-footer-default": "$2\n\nA beállításaidnál módosíthatod, mikor küldjünk e-mailt:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "<a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">A beállításaidnál</a> módosíthatod, mikor küldjünk e-mailt.<br />\n$1",
+ "echo-email-plain-footer": "A {{GENDER:$1|beállításaidnál}} módosíthatod, mikor küldjünk e-mailt:",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|beállításaidnál}}",
+ "echo-email-html-footer-with-link": "A $1 {{GENDER:$2|módosíthatod}}, mikor küldjünk e-mailt.",
"echo-notification-alert": "Értesítések ({{PLURAL:$1|1|$1|100=99+}})",
- "echo-notification-message": "Üzenetek ({{PLURAL:$1|1|$1|100=99+}})",
+ "echo-notification-notice": "{{PLURAL:$1|Értesítés ($1)|Értesítések ($1)|100=Értesítések (99+)}}",
"echo-notification-alert-text-only": "Értesítések",
- "echo-notification-message-text-only": "Üzenetek",
+ "echo-notification-notice-text-only": "Értesítések",
"echo-overlay-link": "Összes értesítés",
"echo-overlay-title": "<b>Értesítéseim</b>",
"echo-overlay-title-overflow": "<b>Értesítéseim</b> ($2 olvasatlanból $1 mutatva)",
"echo-mark-all-as-read": "Összes olvasottnak jelölése",
+ "echo-mark-all-as-read-confirmation": "$1 értesítés olvasottnak jelölve",
+ "echo-mark-wiki-as-read": "Minden elolvasva a kiválasztott wikin: $1",
"echo-date-today": "Ma",
"echo-date-yesterday": "Tegnap",
"echo-load-more-error": "Hiba történt a további eredmények lekérdezése során.",
- "notification-edit-talk-page-bundle": "$1 és még {{PLURAL:$4|egy|$3}} szerkesztő üzenetet hagyott [[User talk:$2|a vitalapodon]].",
- "notification-page-linked-bundle": "A(z) $2 lapra {{GENDER:$1|hivatkoztak}} a(z) $3 lapról és {{PLURAL:$5|egy|még $4}} másikról. [[Special:WhatLinksHere/$2|Kilistázhatod az összes hivatkozást a szócikkre]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 és {{PLURAL:$3|egy másik|még $2}} szerkesztő üzenetet hagyott a vitalapodon.",
- "notification-page-linked-email-batch-bundle-body": "A(z) $2 lapra {{GENDER:$1|hivatkoztak}} a(z) $3 lapról és {{PLURAL:$5|egy|még $4}} másikról",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Egy|$1|100=99+}} új üzenet a <strong>{{GENDER:$3|vitalapodon}}</strong>",
"echo-email-batch-subject-daily": "Új {{PLURAL:$2|értesítést|értesítéseket}} kaptál a(z) {{SITENAME}} wikin",
"echo-email-batch-subject-weekly": "A héten új {{PLURAL:$2|értesítést|értesítéseket}} kaptál a(z) {{SITENAME}} wikin",
"echo-email-batch-body-intro-daily": "Kedves $1,\nösszefoglaltuk, mi történt ma a(z) {{SITENAME}} wikin.",
"echo-email-batch-body-intro-weekly": "Kedves $1,\nösszefoglaltuk, mi történt a héten a(z) {{SITENAME}} wikin.",
"echo-email-batch-link-text-view-all-notifications": "Nézd meg az összes értesítést",
- "echo-rev-deleted-text-view": "Ezt a lapváltozatot elrejtették."
+ "notification-header-foreign-alert": "További figyelmeztetések {{PLURAL:$5|egy|$5}} másik wikiről",
+ "notification-header-foreign-notice": "További értesítések {{PLURAL:$5|egy|$5}} másik wikiről",
+ "notification-header-foreign-all": "További értesítések {{PLURAL:$5|egy|$5}} másik wikiről"
}
diff --git a/Echo/i18n/hy.json b/Echo/i18n/hy.json
index 572602e4..e6025ae4 100644
--- a/Echo/i18n/hy.json
+++ b/Echo/i18n/hy.json
@@ -8,11 +8,12 @@
"Աշոտ1997"
]
},
- "echo-desc": "Ծանուցումների համակարգ",
+ "echo-desc": "Մասնակիցներին միջոցառումների և հաղորդագրությունների մասին ծանուցող համակարգ",
"prefs-echo": "Ծանուցումներ",
"prefs-emailsettings": "Էլ․ փոստի կարգավորումներ",
"prefs-displaynotifications": "Ցուցադրման կարգավորումներ",
"prefs-echosubscriptions": "Ծանուցել հետևյալ դեպքերում",
+ "prefs-echocrosswiki": "Միջվիքիական հաղորդագրություններ",
"prefs-newmessageindicator": "Նոր ուղերձների ցուցիչ։",
"echo-pref-send-me": "Ուղարկել ինձ․",
"echo-pref-send-to": "Ուղարկել․",
@@ -25,57 +26,130 @@
"echo-pref-email-frequency-weekly": "Ծանուցումների շաբաթական ամփոփում",
"echo-pref-email-format-html": "ԷյչԹիԷմԷլ",
"echo-pref-email-format-plain-text": "Պարզ տեքստ",
+ "echo-pref-cross-wiki-notifications": "Ցույց այլ վիքիների ծանուցումները",
"echo-pref-new-message-indicator": "Ցուցադրել քննարկման էջի հաղորդագրությունների ցուցիչը իմ վահանակում",
+ "echo-pref-beta-feature-cross-wiki-message": "Բարելավված ծանուցումներ",
"echo-learn-more": "Իմանալ ավելին",
+ "echo-log": "Հանրամատչելի գրանցամատյան",
"echo-new-messages": "Դուք նոր ուղերձներ ունեք",
"echo-category-title-edit-user-talk": "Քննարկման էջում {{PLURAL:$1|ուղերձ|ուղերձներ}}",
"echo-category-title-article-linked": "Էջի {{PLURAL:$1|հղում|հղումներ}}",
"echo-category-title-reverted": "{{PLURAL:$1|1=Խմբագրման|Խմբագրումների}} հետ շրջում",
"echo-category-title-mention": "{{PLURAL:$1|Նշում|Նշումներ}}",
+ "echo-category-title-mention-failure": "Ձախողված {{PLURAL:$1|հիշատակում|հիշատակումներ}}",
+ "echo-category-title-mention-success": "Հաջողված {{PLURAL:$1|հիշատակում|հիշատակումներ}}",
"echo-category-title-other": "{{PLURAL:$1|Այլ}}",
"echo-category-title-system": "{{PLURAL:$1|Համակարգ}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Մասնակցի իրավունքի փոփոխություն|Մասնակցի իրավունքի փոփոխություններ}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Էլ. փոստ այլ մասնակցից|Էլ. փոստեր այլ մասնակիցներից}}",
"echo-pref-tooltip-edit-user-talk": "Տեղեկացնել ինձ, երբ ինչ-որ մեկը իմ քննարկման էջում պատասխանում կամ թողնում է հաղորդագրություն:",
- "echo-no-agent": "[Ոչ ոք]",
- "echo-no-title": "[Էջը չկա]",
+ "echo-pref-tooltip-article-linked": "Տեղեկացնել ինձ, երբ ինչ-որ մեկը հղում է կատարում իմ ստեղծած հոդվածին։",
+ "echo-pref-tooltip-reverted": "Տեղեկացնել ինձ, երբ ինչ-որ մեկը հետ է շրջում իմ կատարած խմբագրումը՝ հետ շրջման կամ հետ գլորման գործիքի միջոցով:",
+ "echo-pref-tooltip-mention": "Տեղեկացնել ինձ, երբ ինչ-որ մեկը հղում է կատարում իմ մասնակցային էջին:",
+ "echo-pref-tooltip-user-rights": "Տեղեկացնել ինձ, երբ ինչ-որ մեկը փոխում է իմ մասնակցային իրավունքները:",
+ "echo-pref-tooltip-emailuser": "Տեղեկացնել ինձ, երբ ինչ-որ մեկը ինձ էլ. նամակ է ուղարկում:",
+ "echo-error-no-formatter": "Ծանուցումների համար ֆորմատավորման ձև որոշված չէ:",
"notifications": "Ծանուցումներ",
"tooltip-pt-notifications-alert": "Ձեր ծանուցումները",
- "tooltip-pt-notifications-message": "Ձեր հաղորդագրությունները",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Ձեր}} ծանուցումները",
+ "echo-displaynotificationsconfiguration": "Ցույց տալ ծանուցումների կարգավորումները",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Ծանուցումներ ըստ կատեգորիաների",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Դասավորել ըստ տեսակների",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Թույլատրելի ծանուցման եղանակներ",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Միացված է լռելյայն",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Գոյություն ունեցող մասնակիցներ",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Նոր մասնակիցներ",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Պահանջվող ծանուցման եղանակներ",
"echo-specialpage": "Ծանուցումներ",
+ "echo-specialpage-section-markread": "Խումբը նշել ընթերցված",
+ "echo-specialpage-markasread": "Ծանուցում. նշել որպես ընթերցված",
+ "echo-specialpage-markasread-invalid-id": "Իրադարձության սխալ ID",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|ծանուցում|ծանուցումներ}}",
+ "echo-specialpage-pagefilters-title": "Վերջին ակտիվություն",
+ "echo-specialpage-pagefilters-subtitle": "Էջեր չընթերցված ծանուցումներով",
+ "notificationsmarkread-legend": "Ծանուցումը նշել ընթերցված",
"echo-anon": "Ծանուցումներ ստանալու համար [$1 ստեղծեք հաշիվ] կամ [$2 մուտք գործեք]։",
"echo-none": "Դուք ծանուցումներ չունեք։",
"echo-more-info": "Մանրամասն",
"echo-feedback": "Հետադարձ կապ",
+ "echo-popup-footer-special-page-invitation-link": "Նոր տեսք և ֆունկցիաներ",
+ "echo-api-failure": "Չի հաջողվել ստանալ ծանուցումները:",
+ "echo-notification-placeholder": "Ծանուցումներ չկան",
+ "echo-notification-placeholder-filters": "Այս չափորոշչին համապատասխան ծանուցում չկա",
+ "echo-notification-loginrequired": "Դու պետք է մուտք գործես՝ ծանուցումներդ տեսնելու համար:",
+ "echo-notification-popup-loginrequired": "Մուտք գործիր՝ ծանուցումներդ տեսնելու համար:",
+ "echo-notification-markasread": "Նշել ընթերցված",
+ "echo-notification-markasunread": "Նշել չընթերցված",
+ "echo-notification-markasread-tooltip": "Նշել ընթերցված",
+ "echo-notification-more-options-tooltip": "Այլ կարգավորումներ",
+ "notification-link-text-expand-all": "Բացել",
+ "notification-link-text-expand-alert-count": "Ցույց տալ {{PLURAL:$1|$1 տեղեկացումը|$1 տեղեկացումները}}",
+ "notification-link-text-expand-notice-count": "Ցույց տալ {{PLURAL:$1|$1 ծանուցումը|$1 ծանուցումները}}",
+ "notification-link-text-expand-all-count": "Ցույց տալ {{PLURAL:$1|$1 ծանուցումը|$1 ծանուցումները}}",
+ "notification-link-text-collapse-all": "Ծալել",
"notification-link-text-view-message": "Դիտել ուղերձը",
"notification-link-text-view-mention": "Դիտել հիշատակումը",
- "notification-link-text-view-changes": "Դիտել փոփոխությունները",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Ցույց տալ հիշատակումը|Ցույց տալ հիշատակումները}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Դիտել}} փոփոխությունները",
"notification-link-text-view-page": "Դիտել էջը",
+ "notification-header-edit-user-talk": "$1-ը հաղորդագրություն է {{GENDER:$2|թողել}} <strong>{{GENDER:$3|ձեր}} քննարկման էջում</strong>:",
+ "notification-header-edit-user-talk-with-section": "$1-ը հաղորդագրություն է {{GENDER:$2|թողել}} <strong>{{GENDER:$3|ձեր}} քննարկման էջի</strong> «<strong>$4</strong>» բաժնում:",
+ "notification-header-page-linked": "<strong>$4</strong> էջից հղում է կատարվել <strong>$3</strong>-ին:",
+ "notification-compact-header-page-linked": "Կապված է <strong>$1</strong>-ին:",
+ "notification-bundle-header-page-linked": "<strong>$3</strong>-ը հղվել է {{PLURAL:$5||$5 էջերում|100=99+ էջերում}}:",
+ "notification-link-text-what-links-here": "Այստեղ հղվող էջերը",
+ "notification-header-mention-other": "$1-ը {{GENDER:$2|հիշատակել է}} {{GENDER:$3|քեզ}} <strong>$4</strong> էջի «<strong>$5</strong>» բաժնում:",
+ "notification-header-mention-other-nosection": "$1-ը {{GENDER:$2|հիշատակել է}} {{GENDER:$3|քեզ}} <strong>$4</strong> էջում:",
+ "notification-header-mention-user-talkpage-v2": "$1-ը {{GENDER:$2|հիշատակել է}} {{GENDER:$3|քեզ}} <strong> $4-ի քննարկման էջի</strong> «<strong>$6</strong>» բաժնում:",
+ "notification-header-mention-user-talkpage-nosection": "$1-ը {{GENDER:$2|հիշատակել է}} {{GENDER:$3|քեզ}} <strong> $4-ի քննարկման էջի</strong>:",
+ "notification-header-mention-agent-talkpage": "$1-ը {{GENDER:$2|հիշատակել է}} {{GENDER:$3|քեզ}} <strong> {{GENDER:$2|իր}} քննարկման էջի</strong> «<strong>$4</strong>» բաժնում:",
+ "notification-header-mention-agent-talkpage-nosection": "$1-ը {{GENDER:$2|հիշատակել է}} {{GENDER:$3|քեզ}} <strong> {{GENDER:$2|իր}} քննարկման էջում</strong>:",
+ "notification-header-mention-article-talkpage": "$1-ը {{GENDER:$2|հիշատակել է}} {{GENDER:$3|քեզ}} <strong>$4</strong> քննարկման էջի «<strong>$5</strong>» բաժնում:",
+ "notification-header-mention-article-talkpage-nosection": "$1-ը {{GENDER:$2|հիշատակել է}} {{GENDER:$3|քեզ}} <strong>$4</strong> քննարկման էջում:",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Ձեր}} <strong>$3-ի</strong> հիշատակումը չի ուղարկվել, քանի որ այդպիսի մասնակից գոյություն չունի:",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Ձեր}} <strong>$3-ի</strong> հիշատակումը չի ուղարկվել, քանի որ այս մասնակիցն անանուն է:",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Ձեր}} հիշատակումները չեն ուղարկվել, քանի որ դրանք $3-ից շատ էին։",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Հիշատակումը, որը|$3 հիշատակումները, որոնք}} {{GENDER:$2|դու կատարել ես}} <strong>$4</strong>-ի քննարկման էջում {{PLURAL:$3|չի|չեն}} ուղարկվել:",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Մասնակիցը գոյություն չունի՝</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Ձեր}} <strong>$3-ի</strong> հիշատակումը ուղարկված է։",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Հիշատակումը, որը|$3 հիշատակումները, որոնք}} {{GENDER:$2|դու կատարել ես}} <strong>$4</strong>-ի քննարկման էջում ուղարկվել {{PLURAL:$3|է|են}}:",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Դու նշել ես}}՝</strong> $3",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Ձեր}} մասնակցային իրավունքները {{GENDER:$1|փոփոխվել են}}: Ձեզ ավելացրել են՝ «$2» խմբում:",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Ձեր}} մասնակցային իրավունքները {{GENDER:$1|փոփոխվել են}}: Դուք այլևս $2 խմբում չեք:",
+ "notification-welcome-linktext": "Բարի գալուստ",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Դուք}} հենց նոր արեցիք {{GENDER:$2|Ձեր}} առաջին խմբագրումը: Շատ շնորհակալություն և բարի՛ գալուստ:",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Դուք}} հենց նոր արեցիք {{GENDER:$2|ձեր}} տասներորդ խմբագրումը: Շարունակեք նույն կերպ:",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Դուք}} հենց նոր արեցիք {{GENDER:$2|Ձեր}} հարյուրերորդ խմբագրումը: Շատ շնորհակալություն:",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Դուք}} հենց նոր արեցիք {{GENDER:$2|ձեր}} հազարերորդ խմբագրումը: Շնորհակալություն ձեր հսկայական ներդրման համար:",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Դուք}} հենց նոր արեցիք {{GENDER:$2|ձեր}} տաս հազարերորդ խմբագրումը: Անչափ շնորհակալությո՜ւն:",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Դու}} հենց նոր արեցիր {{GENDER:$2|քո}} հարյուր հազարերորդ խմբագրումը: Շնորհակալություն, այսպիսի հրաշալի խմբագրող լինելու համար:",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Դու}} հենց նոր արեցիր {{GENDER:$2|քո}} միլիոներորդ խմբագրումը: Շնորհակալություն այսպիսի անհավատալի խմբագիր լինելու համար:",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Ձեր}} խմբագրումը",
"notification-link-text-view-edit": "Դիտել խմբագրումը",
- "notification-edit-talk-page2": "[[User:$1|$1]] մասնակիցը հաղորդագրություն է {{GENDER:$1|թողել}} [[User talk:$2#$3|Ձեր քննարկման էջում]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] մասնակիցը հաղորդագրություն է թողել Ձեր քննարկման էջի «[[User talk:$2#$3|$4]]» բաժնում:",
- "notification-edit-talk-page-flyout2": "$1 մասնակիցը հաղորդագրություն է թողել Ձեր [[User talk:$2#$3|քննարկման էջում]]:",
- "notification-edit-talk-page-flyout-with-section": "$1 մասնակիցը հաղորդագրություն է թողել Ձեր քննարկման էջի \"[[User talk:$2#$3|$4]]\" բաժնում:",
- "notification-page-linked": "[[:$2]] {{GENDER:$1|հղվել է}} [[:$3]] հոդվածից: [[Special:WhatLinksHere/$2|Տեսնել այս էջին հղվող բոլոր հոդվածները]].",
- "notification-page-linked-flyout": "[[:$2]] հոդվածը {{GENDER:$1|հղվել է}} [[:$3]] հոդվածում:",
- "notification-add-comment2": "[[User:$1|$1]] մասնակիցը {{GENDER:$1|մեկնաբանել է}} \"$4\" քննարկման էջի \"[[$3|$2]]\" բաժնում:",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] մասնակիցը [[$3]] էջում {{GENDER:$1|ավելացրել է}} \"$2\" անվամբ բաժին:",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] մասնակիցը \"[[$3#$2|$2]]\" բաժնում Ձեզ {{GENDER:$1|ուղարկել է}} նոր հաղորդագրություն:",
- "notification-add-comment-yours2": "[[User:$1|$1]] մասնակիցը {{GENDER:$1|մեկնաբանել}} է ձեր քննարկման էջի «[[$3#$2|$2]]» բաժնում։",
- "notification-mention": "[[User:$1|$1]] մասնակիցը {{GENDER:$1|հիշատակել}} է Ձեզ, $5 էջի «[[:$3#$2|$4]]» բաժնում։",
- "notification-mention-flyout": "$1 մասնակիցը {{GENDER:$1|հիշատակել}} է Ձեզ $5 քննարկման էջի «[[:$3#$2|$4]]» բաժնում։",
- "notification-new-user": "Բարի՛ գալուստ {{SITENAME}}, $1։ Ուրախ ենք տեսնել Ձեզ այստեղ։",
+ "notification-header-reverted": "Քո {{PLURAL:$4|խմբագրումը <strong>$3</strong> էջում|խմբագրումները <strong>$3</strong> էջում}} {{PLURAL:$2|հետ է շրջվել|հետ են շրջվել}}:",
+ "notification-header-emailuser": "$1-ը քեզ {{GENDER:$2|ուղարկել է}} էլ. փոստ:",
+ "notification-edit-talk-page-email-subject2": "$1-ը հաղորդագրություն է {{GENDER:$1|թողել}} {{SITENAME}}-ում:",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1-ը հաղորդագրություն է {{GENDER:$1|թողել}} ձեր մասնակցային էջի «$2» բաժնում:",
"notification-page-linked-email-subject": "Ձեր ստեղծած էջը հղվում է դեպի {{SITENAME}} կայքը",
- "echo-email-subject-default": "Նոր ծանուցումներ {{SITENAME}} կայքից։",
+ "notification-mention-email-subject": "$1 մասնակիցը հիշատակել է {{GENDER:$2|քեզ}} {{SITENAME}} էջում",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 վ}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 ր}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ժ}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 օր}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 ամիս}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 տարի}}",
+ "notification-timestamp-today": "Այսօր",
+ "notification-timestamp-yesterday": "Երեկ",
+ "notification-inbox-filter-read": "Ընթերցված",
+ "notification-inbox-filter-unread": "Չընթերցված",
+ "notification-inbox-filter-all": "Բոլորը",
"echo-email-body-default": "Դուք ունեք նոր ծանուցումներ «{{SITENAME}}» կայքից:\n\n$1",
- "echo-email-batch-body-default": "Դուք ունեք նոր ծանուցում։",
"echo-notification-alert-text-only": "Ծանուցումներ",
- "echo-notification-message-text-only": "Հողորդագրություններ",
+ "echo-notification-notice-text-only": "Ծանուցումներ",
"echo-overlay-link": "Բոլոր ծանուցումները",
"echo-overlay-title": "<b>Ծանուցումներ</b>",
- "echo-mark-all-as-read": "Ամենը ընթերցված նշել",
+ "echo-mark-all-as-read": "Բոլոր նշել որպես ընթերցված",
"echo-date-today": "Այսօր",
"echo-date-yesterday": "Երեկ",
- "notification-edit-talk-page-bundle": "$1 և $3 {{PLURAL:$4|այլ}} մասնկից հաղորդագրություն են {{GENDER:$1|թողել}} Ձեր [[User talk:$2|քննարկման էջում]]։",
- "echo-email-batch-link-text-view-all-notifications": "Դիտել բոլոր ծանուցումները",
- "echo-rev-deleted-text-view": "Էջի այս խմբագրումը թաքցված է։"
+ "echo-email-batch-link-text-view-all-notifications": "Դիտել բոլոր ծանուցումները"
}
diff --git a/Echo/i18n/ia.json b/Echo/i18n/ia.json
index c85a3891..f405c19d 100644
--- a/Echo/i18n/ia.json
+++ b/Echo/i18n/ia.json
@@ -1,10 +1,11 @@
{
"@metadata": {
"authors": [
- "McDutchie"
+ "McDutchie",
+ "Julian Mendez"
]
},
- "echo-desc": "Systema de notificationes",
+ "echo-desc": "Systema pro notificar usatores super eventos e messages",
"prefs-echo": "Notificationes",
"prefs-emailsettings": "Optiones de e-mail",
"prefs-displaynotifications": "Optiones de presentation",
@@ -30,64 +31,38 @@
"echo-category-title-mention": "{{PLURAL:$1|Mention|Mentiones}}",
"echo-category-title-other": "{{PLURAL:$1|Altere|Alteres}}",
"echo-category-title-system": "{{PLURAL:$1|Systema|Systemas}}",
- "echo-pref-tooltip-edit-user-talk": "Notificar me quando alcuno scribe o responde in mi pagina de discussion",
+ "echo-pref-tooltip-edit-user-talk": "Notificar me quando alcuno scribe un message o responsa in mi pagina de discussion",
"echo-pref-tooltip-article-linked": "Notificar me quando alcuno insere in un pagina de articulo un ligamine a un pagina que io ha create.",
- "echo-pref-tooltip-reverted": "Notificar me quando alcuno reverte un modification que io ha facite per medio de \"disfacer\" o \"revocar\".",
- "echo-pref-tooltip-mention": "Notificar me quando alcuno insere un ligamine a mi pagina de usator in alcun pagina de discussion.",
- "echo-no-agent": "[Nemo]",
- "echo-no-title": "[Nulle pagina]",
+ "echo-pref-tooltip-reverted": "Notificar me quando alcuno reverte, per medio de \"disfacer\" o \"revocar\", un modification que io ha facite.",
+ "echo-pref-tooltip-mention": "Notificar me quando alcuno insere un ligamine a mi pagina de usator.",
+ "echo-pref-tooltip-article-reminder": "Notificar me sur iste articulo quando io lo demandava.",
"echo-error-no-formatter": "Nulle formato definite pro notification",
"notifications": "Notificationes",
"tooltip-pt-notifications-alert": "Tu alertas",
- "tooltip-pt-notifications-message": "{{GENDER:|Tu}} messages",
"echo-specialpage": "Notificationes",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notification|notificationes}}",
"echo-anon": "Pro reciper notificationes, [$1 crea un conto] o [$2 aperi session].",
"echo-none": "Tu non ha notificationes.",
"echo-more-info": "Plus info",
"echo-feedback": "Commentario",
+ "echo-notification-placeholder-filters": "Il non ha notificationes correspondente a iste criterios.",
+ "echo-notification-markasunread": "Marcar como non legite",
"notification-link-text-view-message": "Vider message",
"notification-link-text-view-mention": "Vider mention",
- "notification-link-text-view-changes": "Vider modificationes",
+ "notification-link-text-view-changes": "{{GENDER:$1|Vider}} modificationes",
"notification-link-text-view-page": "Vider pagina",
+ "notification-header-article-reminder": "Un articulo del qual {{GENDER:$2|tu}} ha requestate de esser rememorate es a <strong>$3</strong>",
"notification-link-text-view-edit": "Vider modification",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|lassava}} un message in tu [[User talk:$2#$3|pagina de discussion]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] te lassava un message in tu pagina de discussion sub \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 te lassava un message in tu [[User talk:$2#$3|pagina de discussion]].",
- "notification-edit-talk-page-flyout-with-section": "$1 te lassava un message in tu pagina de discussion sub \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Un ligamine a [[:$2]] ha essite {{GENDER:$1|inserite}} in [[:$3]]. [[Special:WhatLinksHere/$2|Vider tote le ligamines a iste pagina]].",
- "notification-page-linked-flyout": "Un ligamine a [[:$2]] ha essite {{GENDER:$1|inserite}} in [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] commentava \"[[$3|$2]]\" in le pagina de discussion \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|ha comenciate}} un nove discussion \"$2\" in [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] te {{GENDER:$1|ha inviate}} un message: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|ha commentate}} \"[[$3#$2|$2]]\" in tu pagina de discussion.",
- "notification-mention": "[[User:$1|$1]] te {{GENDER:$1|ha mentionate}} in le pagina de discussion de $5 in \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 te {{GENDER:$1|ha mentionate}} in le pagina de discussion de $5 in \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] te {{GENDER:$1|mentionava}} in le [[:$3|$2 pagina de discussion]].",
- "notification-mention-nosection-flyout": "$1 te {{GENDER:$1|mentionava}} in le [[:$3|$2 pagina de discussion]].",
- "notification-user-rights": "Tu derectos de usator [[Special:Log/rights/$1|ha essite {{GENDER:$1|cambiate}}]] per [[User:$1|$1]]. $2. [[Special:ListGroupRights|Leger plus]]",
- "notification-user-rights-flyout": "Tu derectos de usator ha essite {{GENDER:$1|cambiate}} per $1. $2. [[Special:ListGroupRights|Leger plus]]",
- "notification-user-rights-add": "Tu es ora membro de iste {{PLURAL:$2|gruppo|gruppos}}: $1",
- "notification-user-rights-remove": "Tu non plus es membro de iste {{PLURAL:$2|gruppo|gruppos}}: $1",
- "notification-new-user": "Benvenite a {{SITENAME}}, $1! Nos es felice de vider te hic.",
- "notification-reverted2": "Tu {{PLURAL:$4|modification|modificationes}} de [[:$2]] ha essite {{GENDER:$1|revertite}} per [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "Tu {{PLURAL:$4|modification|modificationes}} de $2 ha essite {{GENDER:$1|revertite}} per $1. $3",
+ "notification-link-article-reminder": "Vider articulo",
+ "notification-header-reverted": "Tu {{PLURAL:$4|modification|modificationes}} de <strong>$3</strong> ha essite {{GENDER:$2|revertite}}.",
"notification-edit-talk-page-email-subject2": "$1 te {{GENDER:$1|ha lassate}} un message in {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|ha lassate}} un message in tu pagina de discussion:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|ha lassate}} un message in tu pagina de discussion in \"$2\".",
- "notification-page-linked-email-subject": "Un ligamine a tu pagina ha essite inserite in {{SITENAME}}",
- "notification-page-linked-email-batch-body": "Un ligamine a $2 ha essite {{GENDER:$1|inserite}} in $3.",
+ "notification-page-linked-email-subject": "Un pagina create per te ha essite ligate in {{SITENAME}}",
"notification-reverted-email-subject2": "Tu {{PLURAL:$3|modification|modificationes}} ha essite {{GENDER:$1|revertite}} in {{SITENAME}}",
- "notification-reverted-email-batch-body2": "Tu {{PLURAL:$3|modification|modificationes}} de $2 ha essite {{GENDER:$1|revertite}} per $1.",
- "notification-mention-email-subject": "$1 te {{GENDER:$1|ha mentionate}} in {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 te {{GENDER:$1|ha mentionate}} in le pagina de discussion de $4 in \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 te {{GENDER:$1|mentionava}} in le pagina de discussion de $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|te}} {{GENDER:$1|ha mentionate}} in {{SITENAME}}",
"notification-user-rights-email-subject": "Tu derectos de usator ha cambiate in {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Tu derectos de usator ha essite {{GENDER:$1|cambiate}} per $1. $2",
- "echo-email-subject-default": "Nove notification in {{SITENAME}}",
"echo-email-body-default": "Tu ha un nove notification in {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Tu ha un nove notification.",
"echo-email-footer-default": "$2\n\nPro seliger le e-mails que nos te invia, controla tu preferentias:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Pro seliger le e-mails que nos te invia, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">controla tu preferentias</a>.<br />\n$1",
"echo-overlay-link": "Tote le notificationes",
"echo-overlay-title": "<b>Notificationes</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificationes}}</b> ($1 monstrate de $2 non legite)",
@@ -95,14 +70,9 @@
"echo-date-today": "Hodie",
"echo-date-yesterday": "Heri",
"echo-load-more-error": "Un error ha occurrite durante le obtention de altere resultatos.",
- "notification-edit-talk-page-bundle": "$1 e $3 {{PLURAL:$4|altere|alteres}} {{GENDER:$1|ha lassate}} un message in tu [[User talk:$2|pagina de discussion]].",
- "notification-page-linked-bundle": "Ligamines a $2 ha essite {{GENDER:$1|inserite}} in $3 e $4 altere {{PLURAL:$5|pagina|paginas}}. [[Special:WhatLinksHere/$2|Vider tote le ligamines a iste pagina]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e $2 {{PLURAL:$3|altere|alteres}} {{GENDER:$1|ha lassate}} un message in tu pagina de discussion.",
- "notification-page-linked-email-batch-bundle-body": "Un ligamine a $2 ha essite {{GENDER:$1|inserite}} in $3 e $4 altere {{PLURAL:$5|pagina|paginas}}.",
"echo-email-batch-subject-daily": "Tu ha {{PLURAL:$2|un nove notification|nove notificationes}} in {{SITENAME}}",
"echo-email-batch-subject-weekly": "Tu ha {{PLURAL:$2|un nove notification|nove notificationes}} in {{SITENAME}} iste septimana",
"echo-email-batch-body-intro-daily": "Salute $1,\nEcce un summario del activitate de hodie in {{SITENAME}} pro te.",
"echo-email-batch-body-intro-weekly": "Salute $1,\nEcce un summario del activitate de iste septimana in {{SITENAME}} pro te.",
- "echo-email-batch-link-text-view-all-notifications": "Vider tote le notificationes",
- "echo-rev-deleted-text-view": "Iste version del pagina ha essite supprimite."
+ "echo-email-batch-link-text-view-all-notifications": "Vider tote le notificationes"
}
diff --git a/Echo/i18n/id.json b/Echo/i18n/id.json
index 3131a4fd..2f2910b9 100644
--- a/Echo/i18n/id.json
+++ b/Echo/i18n/id.json
@@ -5,14 +5,19 @@
"Farras",
"William Surya Permana",
"පසිඳු කාවින්ද",
- "Bennylin"
+ "Bennylin",
+ "WongKentir",
+ "Mbrt",
+ "Rachmat.Wahidi",
+ "Kenrick95"
]
},
- "echo-desc": "Sistem pemberitahuan",
+ "echo-desc": "Sistem pemberitahuan ke pengguna tentang pesan dan peristiwa",
"prefs-echo": "Pemberitahuan",
"prefs-emailsettings": "Opsi surel",
"prefs-displaynotifications": "Opsi tampilan",
"prefs-echosubscriptions": "Beritahu saya mengenai peristiwa berikut",
+ "prefs-echocrosswiki": "Pemberitahuan antar-wiki",
"prefs-newmessageindicator": "Penanda pesan baru",
"echo-pref-send-me": "Kirimi saya:",
"echo-pref-send-to": "Kirimkan ke:",
@@ -25,8 +30,9 @@
"echo-pref-email-frequency-weekly": "Ringkasan mingguan dari beberapa pemberitahuan",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Teks polos",
- "echo-pref-notify-show-link": "Tampilkan pemberitahuan di bilah alat saya",
+ "echo-pref-cross-wiki-notifications": "Perlihatkan pemberitahuan dari wiki lain",
"echo-pref-new-message-indicator": "Tampilkan penanda pesan halaman pembicaraan pada bilah alat saya",
+ "echo-pref-beta-feature-cross-wiki-message": "Notifikasi tingkat tinggi",
"echo-learn-more": "Pelajari selengkapnya",
"echo-new-messages": "Anda memiliki pesan baru",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Pesan}} halaman pembicaraan",
@@ -41,66 +47,62 @@
"echo-pref-tooltip-reverted": "Beritahu saya saat seseorang membalikkan suntingan yang pernah saya buat, dengan menggunakan alat batalkan atau balikkan.",
"echo-pref-tooltip-mention": "Beritahu saya saat seseorang membuat pranala menuju halaman pengguna saya.",
"echo-pref-tooltip-user-rights": "Beritahu saya saat seseorang mengubah hak pengguna saya.",
- "echo-no-agent": "[Tidak seorang pun]",
- "echo-no-title": "[Tidak ada halaman]",
"echo-error-no-formatter": "Tidak ada pemformatan yang ditetapkan untuk pemberitahuan.",
- "echo-error-preference": "Galat: Tidak dapat menetapkan preferensi pengguna.",
- "echo-error-token": "Galat: Tidak dapat mengambil token pengguna.",
"notifications": "Notifikasi (Pemberitahuan)",
- "tooltip-pt-notifications": "Pemberitahuan Anda",
+ "tooltip-pt-notifications-alert": "Pemberitahuan {{GENDER:|Anda}}",
+ "tooltip-pt-notifications-notice": "Pemberitahuan {{GENDER:|Anda}}",
+ "echo-displaynotificationsconfiguration": "Perlihatkan konfigurasi Pemberitahuan",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Pengguna baru",
"echo-specialpage": "Pemberitahuan",
+ "echo-specialpage-section-markread": "Tandai grup telah dibaca",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|pemberitahuan|pemberitahuan}}",
+ "echo-specialpage-pagefilters-title": "Aktivitas terkini",
+ "echo-specialpage-pagefilters-subtitle": "Halaman dengan pemberitahuan yang belum dibaca",
"echo-anon": "Untuk menerima pemberitahuan, [$1 buat sebuah akun] atau [$2 masuk log].",
"echo-none": "Anda tidak memiliki pemberitahuan.",
"echo-more-info": "Informasi selengkapnya",
"echo-feedback": "Umpan balik",
"echo-quotation-marks": "\"$1\"",
+ "echo-api-failure": "Gagal mengambil pemberitahuan.",
+ "echo-notification-placeholder-filters": "Tidak ada pemberitahuan yang sesuai dengan kriteria ini.",
+ "echo-notification-markasread": "Tandai sudah dibaca",
+ "echo-notification-markasunread": "Tandai belum dibaca",
+ "echo-notification-markasread-tooltip": "Tandai sudah dibaca",
+ "echo-notification-more-options-tooltip": "Opsi lainnya",
+ "notification-link-text-expand-all": "Kembangkan",
+ "notification-link-text-collapse-all": "Ciutkan",
"notification-link-text-view-message": "Lihat pesan",
"notification-link-text-view-mention": "Lihat sebutan",
- "notification-link-text-view-changes": "Lihat perubahan",
+ "notification-link-text-view-changes": "{{GENDER:$1|Lihat}} perubahan",
"notification-link-text-view-page": "Lihat halaman",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|meninggalkan}} sebuah pesan di <strong>halaman pembicaraan {{GENDER:$3|Anda}}</strong>.",
+ "notification-welcome-linktext": "Selamat datang",
+ "notification-link-thank-you-edit": "Suntingan {{GENDER:$1|Anda}}",
"notification-link-text-view-edit": "Lihat suntingan",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|meninggalkan}} sebuah pesan pada [[User talk:$2#$3|halaman pembicaraan]] Anda.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|meninggalkan}} sebuah pesan pada halaman pembicaraan Anda di [[User talk:$2#$3|$4]].",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|meninggalkan}} sebuah pesan pada [[User talk:$2#$3|halaman pembicaraan]] Anda.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|meninggalkan}} sebuah pesan pada halaman pembicaraan Anda di [[User talk:$2#$3|$4]].",
- "notification-page-linked": "Pranala ke [[:$2]] {{GENDER:$1|ditambahkan}} di [[:$3]]. [[Special:WhatLinksHere/$2|Lihat semua pranala balik ke halaman ini]].",
- "notification-page-linked-flyout": "Pranala ke [[:$2]] {{GENDER:$1|ditambahkan}} di [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|mengomentari}} \"[[$3|$2]]\" pada halaman pembicaraan \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|mengirimkan}} sebuah topik baru \"$2\" di [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|mengirimi}} Anda sebuah pesan: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|mengomentari}} \"[[$3#$2|$2]]\" pada halaman pembicaraan Anda.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|menyebut}} Anda di \"[[:$3#$2|$4]]\" pada halaman pembicaraan $5.",
- "notification-mention-flyout": "$1 {{GENDER:$1|menyebut}} Anda di \"[[:$3#$2|$4]]\" pada halaman pembicaraan $5.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|menyebut}} Anda pada [[:$3|halaman pembicaraan $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|menyebut}} Anda pada [[:$3|halaman pembicaraan $2]].",
- "notification-user-rights": "Hak pengguna Anda [[Special:Log/rights/$1|telah {{GENDER:$1|diubah}}]] oleh [[User:$1|$1]]. $2. [[Special:ListGroupRights|Pelajari selengkapnya]]",
- "notification-user-rights-flyout": "Hak pengguna Anda telah {{GENDER:$1|diubah}} oleh $1. $2. [[Special:ListGroupRights|Pelajari selengkapnya]]",
- "notification-user-rights-add": "Anda sekarang adalah anggota dari {{PLURAL:$2|kelompok berikut}}: $1",
- "notification-user-rights-remove": "Anda tidak lagi menjadi anggota dari {{PLURAL:$2|kelompok berikut}}: $1",
- "notification-new-user": "Selamat datang di {{SITENAME}}, $1! Kami senang Anda hadir di sini.",
- "notification-reverted2": "{{PLURAL:$4|Suntingan Anda pada [[:$2]] telah}} {{GENDER:$1|dibalikkan}} oleh [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Suntingan Anda pada $2 telah}} {{GENDER:$1|dibalikkan}} oleh $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Suntingan Anda pada <strong>$3</strong> telah}} {{GENDER:$2|dibalikkan}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|mengirimkan}} Anda sebuah surel.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|meninggalkan}} Anda sebuah pesan di {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|meninggalkan}} sebuah pesan pada halaman pembicaraan Anda:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|meninggalkan}} sebuah pesan di \"$2\" pada halaman pembicaraan Anda.",
- "notification-page-linked-email-subject": "Pranala ke halaman Anda ditambahkan di {{SITENAME}}",
- "notification-page-linked-email-batch-body": "Pranala ke $2 {{GENDER:$1|ditambahkan}} di $3.",
+ "notification-page-linked-email-subject": "Pranala ke halaman yang Anda buat ditambahkan di {{SITENAME}}",
"notification-reverted-email-subject2": "{{PLURAL:$3|Suntingan}} Anda telah {{GENDER:$1|dibalikkan}} di {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|suntingan Anda pada $2 telah}} {{GENDER:$1|dibalikkan}} oleh $1.",
"notification-mention-email-subject": "$1 {{GENDER:$1|menyebut}} Anda di {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|menyebut}} Anda di \"$3\" pada halaman pembicaraan $4.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|menyebut}} Anda pada halaman pembicaraan $2.",
"notification-user-rights-email-subject": "Hak pengguna Anda telah diubah di {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Hak pengguna Anda telah {{GENDER:$1|diubah}} oleh $1. $2.",
- "echo-email-subject-default": "Pemberitahuan baru di {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1j}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1bln}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1thn}}",
+ "notification-timestamp-today": "Hari ini",
+ "notification-timestamp-yesterday": "Kemarin",
+ "notification-inbox-filter-read": "Sudah dibaca",
+ "notification-inbox-filter-unread": "Belum dibaca",
+ "notification-inbox-filter-all": "Semua",
"echo-email-body-default": "Anda memiliki pemberitahuan baru di {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Anda memiliki pemberitahuan baru.",
"echo-email-footer-default": "$2\n\nUntuk mengendalikan surel mana saja yang akan kami kirimkan kepada Anda, periksa preferensi Anda:\n{{canonicalurl: {{#special:Preferences}} #mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Untuk mengendalikan surel mana saja yang akan kami kirimkan kepada Anda, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">periksa preferensi Anda</a>.<br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|Penanda ($1)|100=Penanda (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Pesan ($1)|100=Pesan (99+)}}",
"echo-notification-alert-text-only": "Penanda",
- "echo-notification-message-text-only": "Pesan",
+ "echo-notification-notice-text-only": "Pemberitahuan",
"echo-overlay-link": "Semua pemberitahuan",
"echo-overlay-title": "<b>Pemberitahuan</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Pemberitahuan}}</b> (menampilkan $1 dari $2 yang belum dibaca)",
@@ -108,33 +110,9 @@
"echo-date-today": "Hari ini",
"echo-date-yesterday": "Kemarin",
"echo-load-more-error": "Terjadi galat saat mengambil hasil selengkapnya.",
- "notification-edit-talk-page-bundle": "$1 dan $3 pengguna {{PLURAL:$4|lainnya}} {{GENDER:$1|meninggalkan}} sebuah pesan pada [[User talk:$2|halaman pembicaraan]] Anda.",
- "notification-page-linked-bundle": "Pranala ke $2 {{GENDER:$1|ditambahkan}} di $3 dan $4 {{PLURAL:$5|halaman}} lainnya. [[Special:WhatLinksHere/$2|Lihat semua pranala balik ke halaman ini]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 dan $2 pengguna {{PLURAL:$3|lainnya}} {{GENDER:$1|meninggalkan}} sebuah pesan pada halaman pembicaraan Anda.",
- "notification-page-linked-email-batch-bundle-body": "Pranala ke $2 {{GENDER:$1|ditambahkan}} di $3 dan $4 {{PLURAL:$5|halaman}} lainnya.",
"echo-email-batch-subject-daily": "Anda memiliki {{PLURAL:$2|sebuah|beberapa}} pemberitahuan baru di {{SITENAME}}",
"echo-email-batch-subject-weekly": "Anda memiliki {{PLURAL:$2|sebuah|beberapa}} pemberitahuan baru di {{SITENAME}} pekan ini",
"echo-email-batch-body-intro-daily": "Hai $1,\nIni adalah ringkasan aktivitas kegiatan hari ini di {{SITENAME}} untuk Anda.",
"echo-email-batch-body-intro-weekly": "Hai $1,\nIni adalah ringkasan aktivitas kegiatan pekan ini di {{SITENAME}} untuk Anda.",
- "echo-email-batch-link-text-view-all-notifications": "Tampilkan semua pemberitahuan",
- "echo-rev-deleted-text-view": "Revisi halaman ini telah ditekan.",
- "apihelp-echomarkread-description": "Tandai pemberitahuan dari pengguna ini sebagai telah dibaca.",
- "apihelp-echomarkread-param-list": "Daftar ID pemberitahuan yang ingin ditandai sebagai telah dibaca.",
- "apihelp-echomarkread-param-all": "Jika ditetapkan, menandai semua pemberitahuan pengguna sebagai telah dibaca.",
- "apihelp-echomarkread-param-sections": "Daftar bagian yang ingin ditandai sebagai telah dibaca.",
- "apihelp-echomarkread-example-1": "Tandai pemberitahuan 8 sebagai telah dibaca",
- "apihelp-echomarkread-example-2": "Tandai semua pemberitahuan sebagai telah dibaca",
- "apihelp-query+notifications-description": "Dapatkan penungguan pemberitahuan untuk pengguna ini.",
- "apihelp-query+notifications-param-prop": "Rincian yang diminta.",
- "apihelp-query+notifications-param-sections": "Bagian pemberitahuan yang ingin didapatkan.",
- "apihelp-query+notifications-param-groupbysection": "Menentukan apakah perlu mengelompokkan hasil berdasarkan bagian. Jika ditetapkan, setiap bagian diambil secara terpisah.",
- "apihelp-query+notifications-param-format": "Jika ditetapkan, pemberitahuan akan menghasilkan format seperti ini.",
- "apihelp-query+notifications-param-limit": "Jumlah maksimum pemberitahuan yang dihasilkan.",
- "apihelp-query+notifications-param-index": "Jika ditetapkan, daftar ID pemberitahuan akan dihasilkan, secara berurutan.",
- "apihelp-query+notifications-param-alertcontinue": "Saat ada lebih banyak hasil penanda yang tersedia, gunakan ini untuk melanjutkan.",
- "apihelp-query+notifications-param-alertunreadfirst": "Menentukan apakah harus menampilkan pemberitahuan pesan yang belum dibaca terlebih dahulu.",
- "apihelp-query+notifications-param-messagecontinue": "Saat ada lebih banyak hasil pesan yang tersedia, gunakan ini untuk melanjutkan.",
- "apihelp-query+notifications-param-messageunreadfirst": "Menentukan apakah harus menampilkan pemberitahuan penanda terlebih dahulu.",
- "apihelp-query+notifications-example-1": "Daftar pemberitahuan",
- "apihelp-query+notifications-example-2": "Daftar pemberitahuan, dikelompokkan berdasarkan bagian, dengan jumlah"
+ "echo-email-batch-link-text-view-all-notifications": "Tampilkan semua pemberitahuan"
}
diff --git a/Echo/i18n/ie.json b/Echo/i18n/ie.json
new file mode 100644
index 00000000..6cbd12cb
--- /dev/null
+++ b/Echo/i18n/ie.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Stavanger7"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "Tui notificationes"
+}
diff --git a/Echo/i18n/ilo.json b/Echo/i18n/ilo.json
index a001166c..c0261087 100644
--- a/Echo/i18n/ilo.json
+++ b/Echo/i18n/ilo.json
@@ -15,13 +15,12 @@
"echo-pref-email-format": "Pormat ti esurat:",
"echo-pref-web": "Web",
"echo-pref-email": "Esurat",
- "echo-pref-email-frequency-never": "Saannak a patulodan kadagiti aniaman a pakaammo ti esurat",
+ "echo-pref-email-frequency-never": "Saannak a patulodan kadagiti ania man a pakaammo ti esurat",
"echo-pref-email-frequency-immediately": "Dagiti agmaymaysa a pakaaamo a kas um-umayda",
"echo-pref-email-frequency-daily": "Ti inaldaw a pakapukpukan dagiti pakaammo",
"echo-pref-email-frequency-weekly": "Ti linawas a pakapukpukan dagiti pakaammo",
"echo-pref-email-format-html": "HTML",
- "echo-pref-email-format-plain-text": "Naranas a testo",
- "echo-pref-notify-show-link": "Ipakita dagiti pakaammo iti baras ti ramitko",
+ "echo-pref-email-format-plain-text": "Naranas a teksto",
"echo-pref-new-message-indicator": "Iparang ti panangipakita ti mensahe ti tungtungan a panid iti baras ti ramitko",
"echo-learn-more": "Agadal pay ti adu",
"echo-new-messages": "Adda dagiti baro a mensahem",
@@ -37,13 +36,9 @@
"echo-pref-tooltip-reverted": "Pakaammuannak no adda mangisubli ti inurnosko, babaen ti panag-usar ti ramit ti panagukas wenno panangisubli.",
"echo-pref-tooltip-mention": "Pakaammuannak no adda mangisilpo iti panidko.",
"echo-pref-tooltip-user-rights": "Pakaammuannak no adda mangbaliw ti karkarbengak.",
- "echo-no-agent": "[Awan ti sinoman]",
- "echo-no-title": "[Awan ti panid]",
"echo-error-no-formatter": "Awan ti naipalawag a panagporma para iti pakaammo.",
- "echo-error-preference": "Biddut: Saan a maiyasentar ti kakaykayatan ti agar-aramat.",
- "echo-error-token": "Biddut: Saan a maala ti tandaan ti agar-aramat.",
"notifications": "Dagiti pakaammo",
- "tooltip-pt-notifications": "Dagiti pakaammom",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Dagiti}} pakaammom",
"echo-specialpage": "Dagiti pakaammo",
"echo-anon": "Tapno makaawat kadagiti pakaammo, [$1 agpartuat ti pakabilangan] wenno [$2 sumrek].",
"echo-none": "Awan dagiti pakaammom.",
@@ -54,44 +49,15 @@
"notification-link-text-view-changes": "Kitaen dagiti sinukatan",
"notification-link-text-view-page": "Kitaen ti panid",
"notification-link-text-view-edit": "Kitaen ti inurnos",
- "notification-edit-talk-page2": "Ni [[User:$1|$1]] ket {{GENDER:$1|nangibati}} ti mensahe idiay [[User talk:$2#$3|tungtungam a panid]].",
- "notification-edit-talk-page-with-section": "Ni [[User:$1|$1]] ket {{GENDER:$1|nangibati}} ti mensahe idiay tungtungam a panid idiay \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "Ni $1 ket {{GENDER:$1|nangibati}} ti mensahe a idiay [[User talk:$2#$3|tungtungam a panid]].",
- "notification-edit-talk-page-flyout-with-section": "Ni $1 ket {{GENDER:$1|nangibati}} ti mensahe idiay tungtungam a panid idiay \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Ti [[:$2]] ket {{GENDER:$1|naisilpo}} manipud ti [[:$3]]. [[Special:WhatLinksHere/$2|Kitaen amin dagiti silpo iti daytoy a panid]].",
- "notification-page-linked-flyout": "Ti [[:$2]] ket {{GENDER:$1|naisilpo}} manipud ti [[:$3]].",
- "notification-add-comment2": "Ni [[User:$1|$1]] ket {{GENDER:$1|nagkomentario}} iti \"[[$3|$2]]\" iti tungtungan a panid ti \"$4\".",
- "notification-add-talkpage-topic2": "Ni [[User:$1|$1]] ket {{GENDER:$1|nangipablaak}} ti baro a topiko ti \"$2\" iti [[$3]].",
- "notification-add-talkpage-topic-yours2": "Ni [[User:$1|$1]] ket {{GENDER:$1|pinatulodannaka}} ti mensahe: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "Ni [[User:$1|$1]] ken {{GENDER:$1|nagkomentario}} iti \"[[$3#$2|$2]]\" idiay tungtungam a panid.",
- "notification-mention": "Ni [[User:$1|$1]] ket {{GENDER:$1|inbaganaka}} iti tungtungan a panid ti $5 iti \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "Ni $1 ket {{GENDER:$1|inbaganaka}} iti tungtungan a panid ti $5 iti \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "Ni [[User:$1|$1]] ket {{GENDER:$1|inbaganaka}} idiay [[:$3|$2 a tungtungan a panid]].",
- "notification-mention-nosection-flyout": "Ni $1 ket {{GENDER:$1|inbaganaka}} idiay [[:$3|$2 a tungtungan a panid]].",
- "notification-user-rights": "Dagiti karbengam nga agar-aramat [[Special:Log/rights/$1|ket {{GENDER:$1|binaliwan}}]] babaen ni [[User:$1|$1]]. $2. [[Special:ListGroupRights|Agadal pay ti adu]]",
- "notification-user-rights-flyout": "Dagiti karbengam nga agar-aramat ket {{GENDER:$1|binaliwan}} babaen ni $1. $2. [[Special:ListGroupRights|Agadal pay ti adu]]",
- "notification-user-rights-add": "Kamengka itan {{PLURAL:$2|iti daytoy a grupo|kadagitoy a grupo}}: $1",
- "notification-user-rights-remove": "Saankan a kameng {{PLURAL:$2|iti daytoy a grupo|kadagitoy a grupo}}: $1",
- "notification-new-user": "Naragsak nga isasangbay iti {{SITENAME}}, $1! Maragsakankami nga addaka ditoy.",
- "notification-reverted2": "Ti {{PLURAL:$4|inurnosmo iti [[:$2]] ket|inur-urnosmo iti [[:$2]] ket}} {{GENDER:$1|naisubli}} babaen ni [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "Ti {{PLURAL:$4|inurnosmo iti $2 ket|inur-urnosmo iti $2 ket}} {{GENDER:$1|naisubli}} babaen ni $1. $3",
+ "notification-header-reverted": "Ti {{PLURAL:$4|inurnosmo iti $3 ket|inur-urnosmo iti $3 ket}} {{GENDER:$2|naisubli}} babaen ni $1.",
"notification-edit-talk-page-email-subject2": "Ni $1 ket {{GENDER:$1|nangibati}} kenka ti mensahe idiay {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "Ni $1 ket {{GENDER:$1|nangibati}} ti mensahe idiay tungtungam a panid:",
"notification-edit-talk-page-email-batch-body-with-section": "Ni $1 ket {{GENDER:$1|nangibati}} ti mensahe idiay tungtungam a panid iti \"$2\".",
"notification-page-linked-email-subject": "Ti panidmo ket naisilpo idiay {{SITENAME}}",
- "notification-page-linked-email-batch-body": "Ti $2 ket {{GENDER:$1|naisilpo}} manipud iti $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Ti inurnosmo ket|Dagiti inurnosmo ket}} {{GENDER:$1|naisubli}} idiay {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Ti inurnosmo iti $2 ket|Dagiti inurnosmo iti $2 ket}} {{GENDER:$1|insubli}} babaen ni $1.",
"notification-mention-email-subject": "Ni $1 {{GENDER:$1|inbaganaka}} idiay {{SITENAME}}",
- "notification-mention-email-batch-body": "Ni $1 {{GENDER:$1|inbaganaka}} idiay tungtungan a panid ti $4 iti \"$3\".",
- "notification-mention-nosection-email-batch-body": "Ni $1 ket {{GENDER:$1|inbaganaka}} idiay $2 a tungtungan a panid.",
"notification-user-rights-email-subject": "Dagiti karbengam nga agar-aramat ket nabaliwan idiay {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Dagiti karbengam nga agar-aramat ket {{GENDER:$1|binaliwan}} babaen ni $1. $2.",
- "echo-email-subject-default": "Baro a pakaammo idiay {{SITENAME}}",
"echo-email-body-default": "Adda baro a pakaammom idiay {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Adda baro a pakaammom.",
"echo-email-footer-default": "$2\n\nTi mangtengngel no ania dagiti esurat nga ipatulodmi kenka, kitaem dagiti kakaykayatam:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Ti mangtengngel no ania dagiti esurat nga ipatulodmi kenka, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">kitaem dagiti kakaykayatam</a>.<br />\n$1",
"echo-overlay-link": "Dagiti amin a pakaaammo",
"echo-overlay-title": "<b>Dagiti pakaammo</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Dagiti pakaammo}}</b> (agipakpakita ti $1 iti $2 a saan pay a nabasa)",
@@ -99,14 +65,9 @@
"echo-date-today": "Ita nga aldaw",
"echo-date-yesterday": "Idi kalman",
"echo-load-more-error": "Adda biddut a rimsua bayat nga agal-ala kadagiti ad-adu a resulta.",
- "notification-edit-talk-page-bundle": "Ni $1 ken $3 a {{PLURAL:$4|sabali|sabsabali}} ket {{GENDER:$1|nangibati}} ti mensahe idiay [[User talk:$2|tungtungam a panid]].",
- "notification-page-linked-bundle": "Ti $2 ket {{GENDER:$1|naisilpo}} manipud ti $3 ken ti $4 a sabali a {{PLURAL:$5|panid|pampanid}}. [[Special:WhatLinksHere/$2|Kitaen amin dagiti silpo iti daytoy a panid]]",
- "notification-edit-user-talk-email-batch-bundle-body": "Ni $1 ken $2 a {{PLURAL:$3|sabali|sabsabali}} ket {{GENDER:$1|nangibati}} ti mensahe idiay tungtungam a panid.",
- "notification-page-linked-email-batch-bundle-body": "Ti $2 ket {{GENDER:$1|naisilpo}} manipud ti $3 ken $4 a sabali a {{PLURAL:$5|panid|pampanid}}.",
"echo-email-batch-subject-daily": "Addaanka {{PLURAL:$2|ti baro a pakaammo|kadagiti baro a pakaammo}} idiay {{SITENAME}}",
"echo-email-batch-subject-weekly": "Addaanka {{PLURAL:$2|ti baro a pakaammo|kadagiti baro a pakaammo}} idiay {{SITENAME}} ita a lawas",
"echo-email-batch-body-intro-daily": "Kumusta $1,\nAdda ditoy ti pakapukpukan ti aktibidad ita nga aldaw idiay {{SITENAME}} para kenka.",
"echo-email-batch-body-intro-weekly": "Kumusta $1,\nAdda ditoy ti pakapukpukan ti aktibidad ita a lawas idiay {{SITENAME}} para kenka.",
- "echo-email-batch-link-text-view-all-notifications": "Kitaen amin dagiti pakaammo",
- "echo-rev-deleted-text-view": "Daytoy a panagbaliw ti panid ket napasardengen."
+ "echo-email-batch-link-text-view-all-notifications": "Kitaen amin dagiti pakaammo"
}
diff --git a/Echo/i18n/inh.json b/Echo/i18n/inh.json
new file mode 100644
index 00000000..da1bce6d
--- /dev/null
+++ b/Echo/i18n/inh.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Adam-Yourist"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Хьа}} дӀахейтараш",
+ "tooltip-pt-notifications-message": "{{GENDER:|Хьа}} хоамбараш"
+}
diff --git a/Echo/i18n/io.json b/Echo/i18n/io.json
new file mode 100644
index 00000000..06d359d4
--- /dev/null
+++ b/Echo/i18n/io.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Algentem"
+ ]
+ },
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Vu}} jus facis {{GENDER:$2|vua}} unesma redakto; ni dankas {{GENDER:$2|vu}}, e bonveno!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Vu}} jus facis {{GENDER:$2|vua}} dekesma redakto; ni dankas {{GENDER:$2|vu}}, e voluntez durar!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Vu}} jus facis {{GENDER:$2|vua}} centesma redakto; ni dankas {{GENDER:$2|vu}} tre multe!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Vu}} jus facis {{GENDER:$2|vua}} milesma redakto; ni dankas {{GENDER:$2|vu}} por esar bonega kontributero!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Vu}} jus facis {{GENDER:$2|vua}} dekamilesma redakto; ni dankas {{GENDER:$2|vu}} tre multe!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Vu}} jus facis {{GENDER:$2|vua}} centamilesma redakto; ni dankas {{GENDER:$2|vu}} por astoniva kontributo!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Vu}} jus facis {{GENDER:$2|vua}} milionesma redakto; ni dankas {{GENDER:$2|vu}} por astoniva kontributo!"
+}
diff --git a/Echo/i18n/is.json b/Echo/i18n/is.json
index 048d1039..ce17e38a 100644
--- a/Echo/i18n/is.json
+++ b/Echo/i18n/is.json
@@ -2,7 +2,10 @@
"@metadata": {
"authors": [
"Snævar",
- "පසිඳු කාවින්ද"
+ "පසිඳු කාවින්ද",
+ "Sveinki",
+ "Macofe",
+ "Hjalmtyr"
]
},
"echo-desc": "Kerfi til að tilkynna notendum um viðburði og skilaboð",
@@ -21,6 +24,8 @@
"echo-pref-email-frequency-weekly": "Vikulegt yfirlit yfir tilkynningar",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "óstílfærður texti",
+ "echo-pref-cross-wiki-notifications": "Sýna tilkynningar frá öðrum wiki",
+ "echo-pref-new-message-indicator": "Sýna merki um skilaboð á spjallsíðu í tólastikunni minni",
"echo-new-messages": "Þú hefur ný skilaboð",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Skilaboð}} á spjallsíðu",
"echo-category-title-article-linked": "{{PLURAL:$1|Tengil|Tengla}} á síðum",
@@ -29,63 +34,54 @@
"echo-category-title-other": "{{PLURAL:$1|Annað}}",
"echo-category-title-system": "{{PLURAL:$1|Kerfi}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Réttinda breyting|Réttinda breytingar}}",
- "echo-pref-tooltip-edit-user-talk": "Tilkynntu mig um þegar einhver skilur eftir skilaboð eða svarar skilaboðum á spjallsíðunni minni.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Tölvupóstur frá öðrum notanda|Tölvupóstar frá öðrum notendum}}",
+ "echo-pref-tooltip-edit-user-talk": "Tilkynntu mér um þegar einhver skilur eftir skilaboð eða svarar skilaboðum á spjallsíðunni minni.",
"echo-pref-tooltip-article-linked": "Gefðu mér tilkynningu þegar einhver tengir í síðu, sem ég bjó til, frá annari síðu.",
"echo-pref-tooltip-reverted": "Gefðu mér tilkynningu þegar einhver tekur aftur breytingu sem ég gerði.",
- "echo-pref-tooltip-mention": "Gefðu mér tilkynningu þegar einhver tengir í notendasíðu mína.",
+ "echo-pref-tooltip-mention": "Tilkynntu mér þegar einhver tengir í notendasíðuna mína.",
"echo-pref-tooltip-user-rights": "Tilkynntu mér þegar einhver breytir notendaréttendum mínum.",
- "echo-no-agent": "[Enginn]",
- "echo-no-title": "[Engin síða]",
+ "echo-pref-tooltip-emailuser": "Tilkynntu mér um þegar einhver sendir mér tölvupóst.",
"echo-error-no-formatter": "Engin stílviðmið tilgreind fyrir tilkynningum.",
"notifications": "Tilkynningar",
- "tooltip-pt-notifications": "Þínar tilkynningar",
+ "tooltip-pt-notifications-alert": "Aðvaranir til {{GENDER:|þín}}",
"echo-specialpage": "Tilkynningar",
"echo-anon": "Til þess að fá tilkynningar þarft þú annaðhvort að [$1 búa til aðgang] eða [$2 skrá þig inn].",
"echo-none": "Þú hefur engar tilkynningar.",
"echo-more-info": "Frekari upplýsingar",
"echo-feedback": "Svörun",
+ "echo-notification-placeholder": "Engar tilkynningar.",
+ "echo-notification-markasread": "Merkja sem lesið",
+ "echo-notification-markasunread": "Merkja sem ólesið",
+ "echo-notification-markasread-tooltip": "Merkja sem lesið",
"notification-link-text-view-message": "Sjá skilaboð",
- "notification-link-text-view-changes": "Sjá breytingar",
+ "notification-link-text-view-changes": "{{GENDER:$1|Sjá}} breytingar",
"notification-link-text-view-page": "Skoða síðu",
+ "notification-header-mention-other": "$1 {{GENDER:$2|minntist}} á {{GENDER:$3|þig}} á <strong>$4</strong> undir „<strong>$5</strong>”.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|minntist}} á {{GENDER:$3|þig}} á <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|minntist}} á {{GENDER:$3|þig}} á <strong>notandaspjall síðu {{GENDER:$5|$4}} </strong> undir „<strong>$6</strong>”.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|minntist}} á {{GENDER:$3|þig}} á <strong>notanda spjall síðu {{GENDER:$5|$4}}</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|minntist}} á {{GENDER:$3|þig}} á <strong>spjallsíðu {{GENDER:$2|hans|hennar|þess}}</strong> undir „<strong>$4</strong>”.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|minntist}} á {{GENDER:$3|þig}} á <strong>spjallsíðu {{GENDER:$2|hanns|hennar|þess}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|minntist}} á {{GENDER:$3|þig}} á spjallsíðu <strong>$4</strong> undir „<strong>$5</strong>”.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|minntist}} á {{GENDER:$3|þig}} á spjallsíðu <strong>$4</strong>.",
+ "notification-header-welcome": "{{GENDER:$2|Velkominn|Velkomin|Velkomin(n)}} á {{SITENAME}}, $1! Við erum ánægð með að {{GENDER:$2|þú}} sért hér.",
+ "notification-welcome-linktext": "Velkomin(n)",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Þú}} gerðir {{GENDER:$2|þína}} fyrstu breytingu; takk fyrir og {{GENDER:$2|velkominn|velkomin|velkomin/n}} !",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Þú}} gerðir {{GENDER:$2|þína}} tíundu breytingu; takk fyrir og endilega haltu áfram!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Þú}} gerðir {{GENDER:$2|þína}} hundruðustu breytingu; takk {{GENDER:$2|kærlega}} fyrir!",
+ "notification-link-thank-you-edit": "Breytingin {{GENDER:$1|þín}}",
"notification-link-text-view-edit": "Skoða breytingu",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|skildi}} eftir skilaboð á [[User talk:$2#$3|spjallsíðu þinni]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|skildi}} eftir skilaboð í \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|skildi}} eftir skilaboð á [[User talk:$2#$3|spjallsíðu þinni]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|skildi}} eftir skilaboð á spjallsíðu þinni í \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] var {{GENDER:$1|tengd}} við [[:$3]]. [[Special:WhatLinksHere/$2|Sjá alla tengla sem tengjast hingað]].",
- "notification-page-linked-flyout": "[[:$2]] var {{GENDER:$1|tengd}} við [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|tjáði sig}} um „[[$3|$2]]” á spjallsíðu „$4”.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|skrifaði}} nýtt innlegg um \"$2\" á [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|senti}} þér skilaboð: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|tjáði sig}} í \"[[$3#$2|$2]]\" á spjallsíðu þinni.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|minntist á}} þig á spjallsíðu $5 í „[[:$3#$2|$4]]“.",
- "notification-mention-flyout": "$1 {{GENDER:$1|minntist á}} þig á spjallsíðu $5 í „[[:$3#$2|$4]]“.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|minntist á}} þig á [[:$3|spjallsíðu $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|minntist á}} þig á [[:$3|spjallsíðu $2]].",
- "notification-user-rights": "Notendaréttindum þínum [[Special:Log/rights/$1|var {{GENDER:$1|breytt}}]] af [[User:$1|$1]]. $2. [[Special:ListGroupRights|Læra meira]]",
- "notification-user-rights-flyout": "Notendaréttindum þínum var {{GENDER:$1|breytt}} af $1. $2. [[Special:ListGroupRights|Læra meira]]",
- "notification-user-rights-add": "Þú ert nú meðlimur {{PLURAL:$2|þessa hóps|þessara hópa}}: $1",
- "notification-user-rights-remove": "Þú ert ekki lengur meðlimur {{PLURAL:$2|þessa hóps|þessara hópa}}: $1",
- "notification-new-user": "Velkomin til {{SITENAME}}, $1! Við erum ánægð með að sjá þig hér.",
- "notification-reverted2": "{{PLURAL:$4|Breyting þín|Breytingar þínar}} á [[:$2]] {{PLURAL:$4|hefur verið {{GENDER:$1|tekin aftur}}|hafa verið {{GENDER:$1|teknar aftur}}}} af [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Breyting þín|Breytingar þínar}} á $2 {{PLURAL:$4|hefur verið {{GENDER:$1|tekin aftur}}|hafa verið {{GENDER:$1|teknar aftur}}}} af $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Breyting þín|Breytingar þínar}} á <strong>$3</strong> {{PLURAL:$4|var tekin|voru teknar}} {{GENDER:$2|aftur}}.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|skildi}} eftir skilaboð handa þér á {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|skildi}} eftir skilaboð á spjallsíðu þinni.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|skildi}} eftir skilaboð á spjallsíðu þinni undir \"$2\".",
"notification-page-linked-email-subject": "Tengt var í síðu sem þú bjóst til á {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 var {{GENDER:$1|tengd}} frá $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Breytingin þín var tekin aftur|Breytingarnar þínar voru teknar}} {{GENDER:$1|aftur}} á {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Breytingin þín á $2 hefur verið tekin|Breytingarnar þínar á $2 hafa verið teknar}} {{GENDER:$1|aftur}} af $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|minntist}} á þig á {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|minntist}} á þig í „$3” á spjallsíðu $4.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|minntist}} á þig á spjallsíðu $2.",
- "notification-user-rights-email-subject": "Notendaréttindi þín hafa breyst á {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Notendaréttindunum þínum var {{GENDER:$1|breytt}} af $1. $2.",
- "echo-email-subject-default": "Ný tilkynning á {{SITENAME}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|minntist}} á {{GENDER:$2|þig}} á {{SITENAME}}",
+ "notification-user-rights-email-subject": "Notandaréttindi þín hafa breyst á {{SITENAME}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 klst}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 ár}}",
"echo-notification-alert": "{{PLURAL:$1|$1 áminning|$1 Áminningar|100=Áminningar (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|$1 skilaboð|100=Skilaboð (99+)}}",
"echo-notification-alert-text-only": "Áminningar",
- "echo-notification-message-text-only": "Skilaboð",
"echo-overlay-link": "Allar tilkynningar",
"echo-overlay-title": "<b>Tilkynningar</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Tilkynning|Tilkynningar}}</b> (sýni $1 af $2 ólesnum)",
@@ -93,11 +89,7 @@
"echo-date-today": "Í dag",
"echo-date-yesterday": "Í gær",
"echo-load-more-error": "Villa átti sér stað þegar fleiri niðurstöður voru sóttar.",
- "notification-edit-talk-page-bundle": "$1 og $3 {{PLURAL:$4|annar|aðrir}} {{GENDER:$1|skildi eftir}} skilaboð á [[User talk:$2|spjallsíðu]] þinni.",
- "notification-page-linked-bundle": "$2 var {{GENDER:$1|tengd}} frá $3 og $4 {{PLURAL:$5|annarri síðu|öðrum síðum}}. [[Special:WhatLinksHere/$2|Sjá alla tengla á þessa síðu]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 og $2 {{PLURAL:$3|annar skildi|aðrir skildu}} {{GENDER:$1|eftir}} skilaboð á spjallsíðu þinni.",
- "notification-page-linked-email-batch-bundle-body": "$2 var {{GENDER:$1|tengd}} frá $3 og $4 {{PLURAL:$5|annarri síðu|öðrum síðum}}.",
"echo-email-batch-subject-daily": "Þú hefur {{PLURAL:$2|nýja tilkynningu|nýjar tilkynningar}} á {{SITENAME}}",
"echo-email-batch-subject-weekly": "Þú hefur {{PLURAL:$2|nýja tilkynningu|nýjar tilkynningar}} á {{SITENAME}} í þessari viku",
- "echo-rev-deleted-text-view": "Þessi útgáfa síðunnar hefur verið falin."
+ "notification-header-foreign-all": "Fleiri skilaboð frá {{PLURAL:$5|öðru wiki|$5 öðrum wiki-um}}"
}
diff --git a/Echo/i18n/it.json b/Echo/i18n/it.json
index 2fc7037d..92243e22 100644
--- a/Echo/i18n/it.json
+++ b/Echo/i18n/it.json
@@ -10,7 +10,13 @@
"Raoli",
"Vituzzu",
"Horcrux92",
- "Alexmar983"
+ "Alexmar983",
+ "Fringio",
+ "Catrope",
+ "Macofe",
+ "Matteocng",
+ "Anto",
+ "Pequod76"
]
},
"echo-desc": "Sistema per notificare agli utenti messaggi ed eventi",
@@ -18,7 +24,9 @@
"prefs-emailsettings": "Opzioni email",
"prefs-displaynotifications": "Opzioni di visualizzazione",
"prefs-echosubscriptions": "Inviami una notifica su questi eventi",
- "prefs-newmessageindicator": "Barra dei nuovi messaggi",
+ "prefs-echocrosswiki": "Notifiche cross-wiki",
+ "prefs-newmessageindicator": "Indicatore dei nuovi messaggi",
+ "prefs-blocknotificationslist": "Utenti silenziati",
"echo-pref-send-me": "Inviami:",
"echo-pref-send-to": "Invia a:",
"echo-pref-email-format": "Formato email:",
@@ -30,102 +38,169 @@
"echo-pref-email-frequency-weekly": "Un riepilogo settimanale delle notifiche",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Testo normale",
- "echo-pref-new-message-indicator": "Notificami i nuovi messaggi nella mia pagina di discussione con un avviso nella barra degli strumenti",
+ "echo-pref-cross-wiki-notifications": "Mostra notifiche da altri wiki",
+ "echo-pref-notifications-blacklist": "Non mostrare notifiche di questi utenti. ([[mw:Help:Notifications#mute|ulteriori informazioni]])",
+ "echo-pref-new-message-indicator": "Mostra l'indicatore nella barra degli strumenti, per nuovi messaggi nella mia pagina di discussione",
+ "echo-pref-beta-feature-cross-wiki-message": "Notifiche migliorate",
+ "echo-pref-beta-feature-cross-wiki-description": "Visualizza e organizza le notifiche più facilmente. Include notifiche cross-wiki, che ti permettono di visualizzare i messaggi provenienti da altri wiki. (Per ricevere notifiche cross-wiki su un wiki specifico, devi attivare la funzione beta su quel wiki.)",
"echo-learn-more": "Ulteriori informazioni",
+ "echo-log": "Registro pubblico",
"echo-new-messages": "Hai nuovi messaggi",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Messaggio|Messaggi}} sulla pagina di discussione",
"echo-category-title-article-linked": "{{PLURAL:$1|Collegamento|Collegamenti}} a una pagina",
"echo-category-title-reverted": "{{PLURAL:$1|Modifica annullata|Modifiche annullate}}",
"echo-category-title-mention": "{{PLURAL:$1|Menzione|Menzioni}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Menzione|Menzioni}} in errore",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Menzione corretta|Menzioni corrette}}",
"echo-category-title-other": "{{PLURAL:$1|Altro}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Modifica diritto|Modifiche diritti}} utente",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Email da un altro utente|Email da altri utenti}}",
"echo-pref-tooltip-edit-user-talk": "Avvisami quando qualcuno mi scrive un messaggio o risponde nella mia pagina di discussione.",
- "echo-pref-tooltip-article-linked": "Avvisami quando qualcuno collega, da una voce, una pagina che ho creato.",
+ "echo-pref-tooltip-article-linked": "Avvisami quando qualcuno collega una pagina che ho creato da un'altra pagina.",
"echo-pref-tooltip-reverted": "Avvisami quando qualcuno annulla una modifica che ho fatto, usando le funzioni annulla o rollback.",
"echo-pref-tooltip-mention": "Avvisami quando qualcuno collega la mia pagina utente.",
+ "echo-pref-tooltip-mention-failure": "Avvisami quando non ho potuto inviare una menzione a qualcuno.",
+ "echo-pref-tooltip-mention-success": "Avvisami quando invio una menzione a qualcuno.",
"echo-pref-tooltip-user-rights": "Avvisami quando qualcuno modifica i miei diritti di utente.",
- "echo-no-agent": "[Nessuno]",
- "echo-no-title": "[Nessuna pagina]",
+ "echo-pref-tooltip-emailuser": "Avvisami quando qualcuno mi invia una email.",
"echo-error-no-formatter": "Nessuna formattazione definita per le notifiche",
"notifications": "Notifiche",
"tooltip-pt-notifications-alert": "{{GENDER:|I tuoi}} avvisi",
- "tooltip-pt-notifications-message": "{{GENDER:|I tuoi}} messaggi",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Le tue}} notizie",
+ "echo-displaynotificationsconfiguration": "Visualizza configurazione notifiche",
+ "echo-displaynotificationsconfiguration-summary": "Questa è una panoramica di come le notifiche sono configurate su questo wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notifiche per categoria",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Ordinamento dei tipi",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "In quale sezione ogni tipo di notifica è ordinato",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Metodi di notifica consentiti",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Quali metodi di notifica sono supportati per ogni categoria",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Quali metodi di notifica sono supportati per ogni tipo; si applica solo ai tipi all'interno delle categorie che sono nascosti dalle preferenze",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Abilitato per impostazione predefinita",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Utenti esistenti",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nuovi utenti",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Metodi di notifica richiesti",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Quali metodi di notifica sono obbligatori per ogni categoria",
"echo-specialpage": "Notifiche",
+ "echo-specialpage-section-markread": "Segna gruppo come letto",
+ "echo-specialpage-markasread": "Notifica: segna come letta",
+ "echo-specialpage-markasread-invalid-id": "ID evento non valido",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notifica|notifiche}}",
+ "echo-specialpage-pagefilters-title": "Attività recente",
+ "echo-specialpage-pagefilters-subtitle": "Pagine con notifiche non lette",
+ "notificationsmarkread-legend": "Contrassegna la notifica come letta",
"echo-anon": "Per ricevere le notifiche, [$1 registrati] o [$2 accedi].",
"echo-none": "Non hai notifiche.",
"echo-more-info": "Altre informazioni",
"echo-feedback": "Commenti",
+ "echo-api-failure": "Non è stato possibile recuperare le notifiche.",
+ "echo-api-failure-cross-wiki": "L'accesso al dominio remoto è stato negato.",
+ "echo-notification-placeholder": "Non ci sono notifiche.",
+ "echo-notification-placeholder-filters": "Non ci sono notifiche che corrispondano a questi criteri.",
+ "echo-notification-loginrequired": "Devi effettuare l'accesso per vedere le tue notifiche.",
+ "echo-notification-popup-loginrequired": "Effettua l'accesso per visualizzare le tue notifiche.",
+ "echo-notification-markasread": "Segna come già letto",
+ "echo-notification-markasunread": "Segna come non letto",
+ "echo-notification-markasread-tooltip": "Segna come già letto",
+ "echo-notification-more-options-tooltip": "Altre opzioni",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Rimuovi}} le nuove attività su \"$1\" dagli osservati speciali",
+ "notification-dynamic-actions-unwatch-confirmation": "Non {{GENDER:$3|stai}} più osservando la pagina \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Puoi}} inserire [$2 questa pagina] negli osservati speciali in qualsiasi momento.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Segui}} le nuove attività su \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Stai}} osservando la pagina \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Puoi}} rimuovere [$2 questa pagina] dagli osservati speciali in qualsiasi momento.",
+ "notification-link-text-expand-all": "Espandi",
+ "notification-link-text-expand-alert-count": "Vedi {{PLURAL:$1|$1 avviso|$1 avvisi}}",
+ "notification-link-text-expand-notice-count": "Vedi {{PLURAL:$1|$1 notizia|$1 notizie}}",
+ "notification-link-text-expand-all-count": "Vedi {{PLURAL:$1|$1 notifica|$1 notifiche}}",
+ "notification-link-text-collapse-all": "Comprimi",
"notification-link-text-view-message": "Vedi messaggio",
"notification-link-text-view-mention": "Vedi menzione",
- "notification-link-text-view-changes": "Vedi modifiche",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Vedi menzione|Vedi menzioni}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Vedi}} modifiche",
"notification-link-text-view-page": "Vedi pagina",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|ha lasciato}} un messaggio sulla <strong>{{GENDER:$3|tua}} pagina di discussione</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|ha lasciato}} un messaggio sulla <strong>{{GENDER:$3|tua}} pagina di discussione</strong> in \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "È stato creato un collegamento da <strong>$4</strong> a <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Collegata da <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Sono stati creati i collegamenti da {{PLURAL:$5||$5 pagine|100=più di 99 pagine}} a <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Tutti i collegamenti a questa pagina",
+ "notification-header-mention-other": "$1 {{GENDER:$2|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} su <strong>$4</strong> in \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} su <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} nella <strong>pagina di discussione utente {{GENDER:$5|di}} $4</strong> in \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} nella <strong>pagina di discussione utente {{GENDER:$5|di}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} nella <strong>sua pagina di discussione</strong> in \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} nella <strong>sua pagina di discussione</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} sulla pagina di discussione di <strong>$4</strong> in \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} sulla pagina di discussione di <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|La tua}} menzione di <strong>$3</strong> non è stata inviata perché l'utente non è stato trovato.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|La tua}} menzione di <strong>$3</strong> non è stata inviata perché l'utente è anonimo.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Hai menzionato}} più di $3 {{PLURAL:$3|utente|utenti}}. Tutte le menzioni che hanno superato questo limite non sono state inviate.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Una menzione|$3 menzioni}} che {{GENDER:$2|hai fatto}} nella pagina di discussione <strong>$4</strong> non {{PLURAL:$3|può essere inviata|possono essere inviate}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Il nome utente non esiste:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Non possono essere inviate menzioni ad IP:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|La tua}} menzione di <strong>$3</strong> è stata inviata.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Una menzione|$3 menzioni}} che {{GENDER:$2|hai fatto}} nella pagina di discussione <strong>$4</strong> {{PLURAL:$3|è stata inviata|sono state inviate}}.",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Una notifica|$3 notifiche}} riguardo a menzioni che {{GENDER:$2|hai fatto}} nella pagina di discussione <strong>$4</strong>: $5 non {{PLURAL:$5|inviata|inviate}}, $6 {{PLURAL:$6|inviata|inviate}}.",
+ "notification-header-user-rights-add-only": "I tuoi diritti utente sono stati {{GENDER:$1|modificati}}. Sei {{GENDER:$4|stato aggiunto|stata aggiunta}} a: $2.",
+ "notification-header-user-rights-remove-only": "I {{GENDER:$4|tuoi}} diritti utente sono stati {{GENDER:$1|modificati}}. Non sei più un membro di: $2.",
+ "notification-header-user-rights-add-and-remove": "I tuoi diritti utente sono stati {{GENDER:$1|modificati}}. Sei {{GENDER:$6|stato aggiunto|stata aggiunta}} a: $2. Non sei più un membro di: $4.",
+ "notification-header-user-rights-expiry-change": "La scadenza della {{GENDER:$4|tua}} appartenenza {{PLURAL:$3|al seguente gruppo|ai seguenti gruppi}} è stata {{GENDER:$1|modificata}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Benvenuto|Benvenuta|Benvenuto/a}} su {{SITENAME}}, $1! Siamo lieti che {{GENDER:$2|tu sia}} qui.",
+ "notification-welcome-linktext": "Benvenuto",
+ "notification-header-thank-you-1-edit": "Hai appena fatto la tua prima modifica; grazie e {{GENDER:$2|benvenuto|benvenuta|benvenuto/a}}!",
+ "notification-header-thank-you-10-edit": "Hai appena fatto la tua decima modifica; grazie e {{GENDER:$2|continua}} così!",
+ "notification-header-thank-you-100-edit": "Hai appena fatto la tua centesima modifica; {{GENDER:$2|ti}} ringraziamo molto!",
+ "notification-header-thank-you-1000-edit": "Hai appena fatto la tua millesima modifica; grazie per essere {{GENDER:$2|un grande contributore|una grande contributrice}}!",
+ "notification-header-thank-you-10000-edit": "Hai appena fatto la tua decimillesima modifica; {{GENDER:$2|ti}} ringraziamo molto!",
+ "notification-header-thank-you-100000-edit": "Hai appena fatto la tua centomillesima modifica; grazie per il {{GENDER:$2|tuo}} incredibile contributo!",
+ "notification-header-thank-you-1000000-edit": "Hai appena fatto la tua milionesima modifica; grazie per il {{GENDER:$2|tuo}} strabiliante contributo!",
+ "notification-link-thank-you-edit": "La {{GENDER:$1|tua}} modifica",
"notification-link-text-view-edit": "Vedi modifica",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|ha lasciato}} un messaggio sulla tua [[User talk:$2#$3|pagina di discussione]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|ha lasciato}} un messaggio nella tua pagina di discussione in '[[User talk:$2#$3|$4]]'.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|ha lasciato}} un messaggio sulla tua [[User talk:$2#$3|pagina di discussione]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|ha lasciato}} un messaggio nella tua pagina di discussione in '[[User talk:$2#$3|$4]]'.",
- "notification-page-linked": "[[:$2]] è stata {{GENDER:$1|collegata}} da [[:$3]]. [[Special:WhatLinksHere/$2|Vedi tutti i collegamenti a questa pagina]].",
- "notification-page-linked-flyout": "[[:$2]] è stata {{GENDER:$1|collegata}} da [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|ha lasciato un commento}} riguardo a \"[[$3|$2]]\" nella pagina di discussione di \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|ha aggiunto}} un nuovo argomento \"$2\" su [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] ti {{GENDER:$1|ha inviato}} un messaggio: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|ha lasciato un commento}} riguardo a \"[[$3#$2|$2]]\" nella tua pagina di discussione",
- "notification-mention": "[[User:$1|$1]] ti ha {{GENDER:$1|menzionato|menzionata|menzionato/a}} sulla pagina di discussione di $5 in '[[:$3#$2|$4]]'.",
- "notification-mention-flyout": "$1 ti ha {{GENDER:$1|menzionato|menzionata|menzionato/a}} sulla pagina di discussione di $5 in '[[:$3#$2|$4]]'.",
- "notification-mention-nosection": "[[User:$1|$1]] ti {{GENDER:$1|ha menzionato}} nella [[:$3|pagina di discussione $2]].",
- "notification-mention-nosection-flyout": "$1 ti {{GENDER:$1|ha menzionato}} nella [[:$3|pagina di discussione $2]].",
- "notification-user-rights": "I tuoi diritti utente [[Special:Log/rights/$1|sono stati {{GENDER:$1|modificati}}]] da [[User:$1|$1]]. $2. [[Special:ListGroupRights|Ulteriori informazioni]]",
- "notification-user-rights-flyout": "I tuoi diritti utente sono stati {{GENDER:$1|modificati}} da $1. $2. [[Special:ListGroupRights|Ulteriori informazioni]]",
- "notification-user-rights-add": "Ora sei membro di {{PLURAL:$2|questo gruppo|questi gruppi}}: $1",
- "notification-user-rights-remove": "Non sei più membro di {{PLURAL:$2|questo gruppo|questi gruppi}}: $1",
- "notification-new-user": "Benvenuto su {{SITENAME}}, $1! Siamo felici che tu sia qui.",
- "notification-reverted2": "{{PLURAL:$4|La tua modifica|Le tue modifiche}} su [[:$2]] {{PLURAL:$4|è stata annullata|sono state annullate}} {{GENDER:$1|da}} [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|La tua modifica|Le tue modifiche}} su $2 {{PLURAL:$4|è stata annullata|sono state annullate}} {{GENDER:$1|da}} $1 $3",
+ "notification-header-reverted": "{{PLURAL:$4|La tua modifica|Le tue modifiche}} su <strong>$3</strong> {{PLURAL:$4|è stata annullata|sono state annullate}}{{GENDER:$2|}}",
+ "notification-header-emailuser": "$1 ti {{GENDER:$2|ha inviato}} una email.",
"notification-edit-talk-page-email-subject2": "$1 ti {{GENDER:$1|ha lasciato}} un messaggio in {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|ha lasciato}} un messaggio sulla tua pagina di discussione.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|ha lasciato}} un messaggio sulla tua pagina di discussione in '$2'.",
"notification-page-linked-email-subject": "Una pagina che hai creato è stata collegata su {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 è stata {{GENDER:$1|collegata}} da $3",
"notification-reverted-email-subject2": "{{PLURAL:$3|La tua modifica è stata annullata|Le tue modifiche sono state annullate}} {{GENDER:$1|su}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|La tua modifica|Le tue modifiche}} su $2 {{PLURAL:$3|è stata annullata|sono state annullate}} {{GENDER:$1|da}} $1",
- "notification-mention-email-subject": "$1 ti ha {{GENDER:$1|menzionato|menzionata|menzionato/a}} su {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 ti ha {{GENDER:$1|menzionato|menzionata|menzionato/a}} sulla pagina di discussione di $4 in '$3'.",
- "notification-mention-nosection-email-batch-body": "$1 ti {{GENDER:$1|ha menzionato}} nella pagina di discussione $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|ti}} ha {{GENDER:$2|menzionato|menzionata|menzionato/a}} su {{SITENAME}}",
"notification-user-rights-email-subject": "I tuoi diritti utente sono stati modificati su {{SITENAME}}",
- "notification-user-rights-email-batch-body": "I tuoi diritti utente sono stati {{GENDER:$1|modificati}} da $1. $2",
- "echo-email-subject-default": "Nuova notifica su {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "$1 {{PLURAL:$1|min}}",
+ "notification-timestamp-ago-hours": "$1 {{PLURAL:$1|ora|ore}}",
+ "notification-timestamp-ago-days": "$1 {{PLURAL:$1|g|gg}}",
+ "notification-timestamp-ago-months": "$1 {{PLURAL:$1|mese|mesi}}",
+ "notification-timestamp-ago-years": "$1 {{PLURAL:$1|anno|anni}}",
+ "notification-timestamp-today": "Oggi",
+ "notification-timestamp-yesterday": "Ieri",
+ "notification-inbox-filter-read": "Lette",
+ "notification-inbox-filter-unread": "Non lette",
+ "notification-inbox-filter-all": "Tutte",
"echo-email-body-default": "Hai una nuova notifica su {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Hai una nuova notifica",
- "echo-email-footer-default": "$2\n\nPer controllare quali email ti verranno inviate, controlla le tue preferenze:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Per verificare quali email ti vengono inviate, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">controlla le tue preferenze</a><br />\n$1",
+ "echo-email-footer-default-html": "Per controllare quali email ti vengono inviate, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">verifica le tue preferenze</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPer controllare quali email ti vengono inviate, controlla le tue preferenze:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Per controllare quali email {{GENDER:$1|ti}} vengono inviate, verifica le {{GENDER:$1|tue}} preferenze:",
+ "echo-email-html-footer-preference-link-text": "verifica le {{GENDER:$1|tue}} preferenze",
+ "echo-email-html-footer-with-link": "Per controllare quali email {{GENDER:$2|ti}} vengono inviate, $1.",
"echo-notification-alert": "{{PLURAL:$1|Avviso ($1)|Avvisi ($1)|100=Avvisi (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Messaggio ($1)|Messaggi ($1)|100=Messaggi (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notizia ($1)|Notizie ($1)|100=Notizie (99+)}}",
"echo-notification-alert-text-only": "Avvisi",
- "echo-notification-message-text-only": "Messaggi",
+ "echo-notification-notice-text-only": "Notizie",
"echo-overlay-link": "Tutte le notifiche",
"echo-overlay-title": "<b>Notifiche</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notifica|Notifiche}}</b> (mostrate $1 di $2 non lette)",
"echo-mark-all-as-read": "Segna tutte come lette",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notifica contrassegnata come letta|notifiche contrassegnate come lette}}",
"echo-date-today": "Oggi",
"echo-date-yesterday": "Ieri",
"echo-load-more-error": "Si è verificato un errore nel recupero di ulteriori risultati.",
- "notification-edit-talk-page-bundle": "$1 e {{PLURAL:$4|un altro utente|altri $3 utenti}} {{GENDER:$1|hanno lasciato}} un messaggio nella tua [[User talk:$2|pagina di discussione]].",
- "notification-page-linked-bundle": "$2 è stata {{GENDER:$1|collegata}} da $3 ed {{PLURAL:$5|un'altra pagina|altre $4 pagine}}. [[Special:WhatLinksHere/$2|Vedi tutti i collegamenti a questa pagina]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e {{PLURAL:$3|un altro|altri $2}} {{GENDER:$1|hanno lasciato}} un messaggio sulla tua pagina di discussione",
- "notification-page-linked-email-batch-bundle-body": "$2 è stata {{GENDER:$1|collegata}} da $3 ed {{PLURAL:$5|un'altra pagina|altre $4 pagine}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Un nuovo messaggio|$1 nuovi messaggi|100=Più di 99 nuovi messaggi}} sulla <strong>{{GENDER:$3|tua}} pagina di discussione</strong>.",
"echo-email-batch-subject-daily": "Hai {{PLURAL:$2|una nuova notifica|nuove notifiche}} su {{SITENAME}}",
"echo-email-batch-subject-weekly": "Hai {{PLURAL:$2|una nuova notifica|nuove notifiche}} su {{SITENAME}} questa settimana",
"echo-email-batch-body-intro-daily": "Ciao $1,\neccoti una sintesi delle attività di oggi su {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Ciao $1,\neccoti una sintesi delle attività di questa settimana su {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "Vedi tutte le notifiche",
- "echo-rev-deleted-text-view": "Questa versione della pagina è stata soppressa",
- "apihelp-echomarkread-description": "Contrassegna tutte le notifiche come lette per l'utente attuale.",
- "apihelp-echomarkread-param-list": "Un elenco di ID notifiche da contrassegnare come lette.",
- "apihelp-echomarkread-param-all": "Se impostato, contrassegna tutte le notifiche dell'utente come lette.",
- "apihelp-echomarkread-param-sections": "Un elenco di sezioni da contrassegnare come lette.",
- "apihelp-echomarkread-example-1": "Contrassegna la notifica 8 come letta",
- "apihelp-echomarkread-example-2": "Contrassegna tutte le notifiche come lette",
- "apihelp-query+notifications-example-1": "Elenco notifiche",
- "apihelp-query+notifications-example-2": "Elenco notifiche, raggruppate per sezione, con i conteggi"
+ "notification-header-foreign-alert": "Altri avvisi da {{PLURAL:$5|un altro wiki|altri $5 wiki}}",
+ "notification-header-foreign-notice": "Altre notizie da {{PLURAL:$5|un altro wiki|altri $5 wiki}}",
+ "notification-header-foreign-all": "Altre notifiche da {{PLURAL:$5|un altro wiki|altri $5 wiki}}"
}
diff --git a/Echo/i18n/ja.json b/Echo/i18n/ja.json
index 6132f7d0..68540415 100644
--- a/Echo/i18n/ja.json
+++ b/Echo/i18n/ja.json
@@ -7,7 +7,12 @@
"Penn Station",
"Sujiniku",
"2nd-player",
- "Takot"
+ "Takot",
+ "Otokoume",
+ "Vigorous action",
+ "Thibaut120094",
+ "Marine-Blue",
+ "Translatealcd"
]
},
"echo-desc": "イベントおよびメッセージについて、ユーザーに通知するシステム",
@@ -15,7 +20,9 @@
"prefs-emailsettings": "メールの設定",
"prefs-displaynotifications": "表示の設定",
"prefs-echosubscriptions": "以下の場合に通知を受け取る",
+ "prefs-echocrosswiki": "ウィキ横断通知",
"prefs-newmessageindicator": "新着メッセージの表示",
+ "prefs-blocknotificationslist": "ミュートした利用者",
"echo-pref-send-me": "受け取る頻度:",
"echo-pref-send-to": "送信先:",
"echo-pref-email-format": "メールの形式:",
@@ -27,100 +34,165 @@
"echo-pref-email-frequency-weekly": "通知を1週間ごとに要約",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "プレーンテキスト",
+ "echo-pref-cross-wiki-notifications": "他のウィキからの通知を表示",
+ "echo-pref-notifications-blacklist": "以下の利用者からの通知は表示されません ([[mw:Help:Notifications#mute|詳細]])。",
"echo-pref-new-message-indicator": "トークページのメッセージの未読数をツールバーに表示",
+ "echo-pref-beta-feature-cross-wiki-message": "強化型通知",
+ "echo-pref-beta-feature-cross-wiki-description": "より簡単に通知を閲覧・整理します。ウィキ横断通知により、他のウィキからのメッセージを見れます。(あるウィキでウィキ横断通知を受信するには、そのウィキでベータ版機能を有効化する必要があります。)",
"echo-learn-more": "詳細",
+ "echo-log": "公開記録",
"echo-new-messages": "新着メッセージがあります",
"echo-category-title-edit-user-talk": "トークページヘの{{PLURAL:$1|メッセージ}}",
"echo-category-title-article-linked": "ページへの{{PLURAL:$1|リンク}}",
"echo-category-title-reverted": "編集の{{PLURAL:$1|差し戻し}}",
"echo-category-title-mention": "{{PLURAL:$1|言及}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|言及}}の失敗",
+ "echo-category-title-mention-success": "{{PLURAL:$1|言及}}の成功",
"echo-category-title-other": "{{PLURAL:$1|その他}}",
"echo-category-title-system": "{{PLURAL:$1|システム}}",
"echo-category-title-user-rights": "{{PLURAL:$1|利用者権限の変更}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|他の利用者からのメール}}",
"echo-pref-tooltip-edit-user-talk": "誰かが私のトークページでメッセージの投稿または返信をしたときに通知する。",
- "echo-pref-tooltip-article-linked": "誰かが私が作成したページに記事からリンクしたときに通知する。",
+ "echo-pref-tooltip-article-linked": "誰かが自分の作成したページに記事からリンクしたときに通知する。",
"echo-pref-tooltip-reverted": "誰かが取り消しや巻き戻しの機能で私の編集を差し戻したときに通知する。",
"echo-pref-tooltip-mention": "誰かが私の利用者ページにリンクしたときに通知する。",
+ "echo-pref-tooltip-mention-failure": "利用者への言及に失敗したとき通知する。",
+ "echo-pref-tooltip-mention-success": "利用者へ言及したときに通知する。",
"echo-pref-tooltip-user-rights": "誰かが私の利用者権限を変更したときに通知する。",
- "echo-no-agent": "[送信者なし]",
- "echo-no-title": "[ページなし]",
+ "echo-pref-tooltip-emailuser": "誰かが私にメールを送ったときに通知する。",
"echo-error-no-formatter": "通知の書式が定義されていません。",
"notifications": "通知",
- "tooltip-pt-notifications-alert": "あなたへの通知",
- "tooltip-pt-notifications-message": "あなたへのメッセージ",
+ "tooltip-pt-notifications-alert": "{{GENDER:|あなた}}への通知",
+ "tooltip-pt-notifications-notice": "{{GENDER:|あなた}}への通知",
+ "echo-displaynotificationsconfiguration": "通知の構成状況の表示",
+ "echo-displaynotificationsconfiguration-summary": "こちらは通知機能がこのウィキでどのように構成されているかの概観です。",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "分類別の通知",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "種類ごとの振り分け",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "各々の種類の通知がどのセクションに振り分けられるか",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "許可されている通知方法",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "分類ごとにどの通知方法が許可されているか",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "分類ごとにどの通知方法が許可されているか、個人設定では非表示の分類にのみ適用",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "既定で有効",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "既存利用者",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "新しい利用者",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "必須の通知方法",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "分類ごとに必須の通知方法",
"echo-specialpage": "通知",
+ "echo-specialpage-section-markread": "まとめて既読にする",
+ "echo-specialpage-markasread": "通知: 既読にする",
+ "echo-specialpage-markasread-invalid-id": "無効なイベントID",
+ "echo-specialpage-pagination-numnotifications": "$1件の{{PLURAL:$1|通知}}",
+ "echo-specialpage-pagefilters-title": "最近の通知",
+ "echo-specialpage-pagefilters-subtitle": "未読の通知があるページ",
+ "notificationsmarkread-legend": "通知を既読にする",
"echo-anon": "通知を受け取るには、[$1 アカウント作成]または[$2 ログイン]をしてください。",
"echo-none": "通知はありません。",
"echo-more-info": "詳細情報",
"echo-feedback": "フィードバック",
+ "echo-popup-footer-special-page-invitation": "<strong>再デザインされた通知ページを試す。</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "まったく新しい外観と機能。",
"echo-quotation-marks": "「$1」",
- "echo-api-failure": "通知を取得できませんでした。もう一度、やりなおしてください。(エラー $1)",
- "echo-notification-placeholder": "通知は無し。",
+ "echo-api-failure": "通知を取得できませんでした。",
+ "echo-api-failure-cross-wiki": "リモートドメインへのアクセスが拒否されました。",
+ "echo-notification-placeholder": "通知はありません。",
+ "echo-notification-placeholder-filters": "この条件に一致する通知はありません。",
+ "echo-notification-loginrequired": "通知を表示するにはログインしてください。",
+ "echo-notification-popup-loginrequired": "通知を表示するにはログインしてください。",
+ "echo-notification-markasread": "既読にする",
+ "echo-notification-markasunread": "未読にする",
+ "echo-notification-markasread-tooltip": "既読にする",
+ "echo-notification-more-options-tooltip": "その他の操作",
+ "notification-link-text-expand-all": "展開",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1件のアラート}}を表示",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|$1件の通知}}を見る",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1件の通知}}を表示",
+ "notification-link-text-collapse-all": "折り畳む",
"notification-link-text-view-message": "メッセージを閲覧",
"notification-link-text-view-mention": "言及を閲覧",
- "notification-link-text-view-changes": "差分を閲覧",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|言及を閲覧}}",
+ "notification-link-text-view-changes": "差分を{{GENDER:$1|閲覧}}",
"notification-link-text-view-page": "ページを閲覧",
+ "notification-header-edit-user-talk": "$1 が<strong>{{GENDER:$3|あなたの}}トークページ</strong>にメッセージを{{GENDER:$2|投稿しました}}。",
+ "notification-header-edit-user-talk-with-section": "$1 が<strong>{{GENDER:$3|あなたの}}トークページ</strong>のセクション「<strong>$4</strong>」にメッセージを{{GENDER:$2|投稿しました}}。",
+ "notification-header-page-linked": "<strong>$3</strong> が <strong>$4</strong> からリンクされました。",
+ "notification-compact-header-page-linked": "<strong>$1</strong> からリンクされました。",
+ "notification-bundle-header-page-linked": "<strong>$3</strong> が {{PLURAL:$5||$5件のページ|100=99件以上のページ}}からリンクされました。",
+ "notification-link-text-what-links-here": "このページへリンクしているすべてのページ",
+ "notification-header-mention-other": "$1 が <strong>$4</strong> のセクション「<strong>$5</strong>」で{{GENDER:$3|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-mention-other-nosection": "$1 が <strong>$4</strong> で{{GENDER:$3|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-mention-user-talkpage-v2": "$1 が <strong>$4 {{GENDER:$5|の}}利用者トークページ</strong>のセクション「<strong>$6</strong>」で{{GENDER:$3|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-mention-user-talkpage-nosection": "$1 が <strong>$4 {{GENDER:$5|の}}利用者トークページ</strong>で{{GENDER:$3|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-mention-agent-talkpage": "$1 が<strong>{{GENDER:$2|自分|自分|自分}}のトークページ</strong>のセクション「<strong>$4</strong>」で{{GENDER:$3|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-mention-agent-talkpage-nosection": "$1 が<strong>{{GENDER:$2|自分|自分|自分}}のトークページ</strong>で{{GENDER:$3|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-mention-article-talkpage": "$1 が <strong>$4</strong> のセクション「<strong>$5</strong>」で{{GENDER:$3|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-mention-article-talkpage-nosection": "$1 が <strong>$4</strong> のトークページで{{GENDER:$3|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-mention-failure-user-unknown": "<strong>$3</strong> は存在しない利用者のため、{{GENDER:$2|あなた}}の言及を送信できませんでした。",
+ "notification-header-mention-failure-user-anonymous": "<strong>$3</strong> は匿名利用者のため、{{GENDER:$2|あなた}}の言及を送信できませんでした。",
+ "notification-header-mention-failure-too-many": "$3件を超過して言及することはできないため、{{GENDER:$2|あなた}}の言及を送信できませんでした。",
+ "notification-header-mention-failure-bundle": "<strong>$4</strong> に{{GENDER:$2|送信}}した{{PLURAL:$3|言及|$3件の言及}}を送信{{PLURAL:$3|できませんでした}}。",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>そのような利用者名は存在しません:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP利用者には言及できません:</strong> $1",
+ "notification-header-mention-success": "<strong>$3</strong> に言及を送信{{GENDER:$2|しました}}。",
+ "notification-header-mention-success-bundle": "<strong>$4</strong> のトークページに{{PLURAL:$3|言及|$3件の言及}}を{{GENDER:$2|送信}}しました。",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|言及しました}}:</strong> $3",
+ "notification-header-mention-status-bundle": "<strong>$4</strong> のトークページに{{GENDER:$2|送信}}した言及について{{PLURAL:$3|通知|$3件の通知}}があります: {{PLURAL:$5|$5件が未送信}}、{{PLURAL:$6|$6件が送信済み}}",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|あなたの}}利用者権限が{{GENDER:$1|変更されました}}: $2へ追加されました。",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|あなたの}}利用者権限が{{GENDER:$1|変更されました}}: $2から除外されました。",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|あなたの}}利用者権限が{{GENDER:$1|変更されました}}: $2へ追加され、$4から除外されました。",
+ "notification-header-welcome": "$1 さん、{{SITENAME}} へ{{GENDER:$2|ようこそ}}!{{GENDER:$2|あなた}}の参加を歓迎します。",
+ "notification-welcome-linktext": "ようこそ",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|あなた}}は初めて編集を行いました。寄稿をありがとうございます。そして、ようこそ!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|あなた}}は10回の編集を行いました。これからも頑張りましょう!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|あなた}}は100回の編集を行いました。ありがとうございます!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|あなた}}は1,000回の編集を行いました。たくさんの寄稿をありがとうございます。",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|あなた}}は10,000回の編集を行いました。非常に多くの寄稿をありがとうございます。",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|あなた}}は100,000回の編集を行いました。数えきれないほどの寄稿をありがとうございます。",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|あなた}}は1,000,000回の編集を行いました。莫大な数の寄稿をありがとうございます。",
+ "notification-link-thank-you-edit": "{{GENDER:$1|自身}}の編集",
"notification-link-text-view-edit": "編集内容を閲覧",
- "notification-edit-talk-page2": "[[User:$1|$1]] があなたの[[User talk:$2#$3|トークページ]]にメッセージを{{GENDER:$1|投稿しました}}。",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] があなたのトークページの「[[User talk:$2#$3|$4]]」にメッセージを{{GENDER:$1|投稿しました}}。",
- "notification-edit-talk-page-flyout2": "$1 があなたの[[User talk:$2#$3|トークページ]]にメッセージを{{GENDER:$1|投稿しました}}。",
- "notification-edit-talk-page-flyout-with-section": "$1 があなたのトークページの「[[User talk:$2#$3|$4]]」にメッセージを{{GENDER:$1|投稿しました}}。",
- "notification-page-linked": "[[:$2]] が [[:$3]] から{{GENDER:$1|リンクされました}}。[[Special:WhatLinksHere/$2|このページのリンク元]]",
- "notification-page-linked-flyout": "[[:$2]] が [[:$3]] から{{GENDER:$1|リンクされました}}。",
- "notification-add-comment2": "[[User:$1|$1]] が「$4」のトークページの「[[$3|$2]]」に{{GENDER:$1|コメントしました}}。",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] が [[$3]] に新しい話題「$2」を{{GENDER:$1|投稿しました}}。",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] があなたにメッセージを{{GENDER:$1|送信しました}}:「[[$3#$2|$2]]」",
- "notification-add-comment-yours2": "[[User:$1|$1]] があなたのトークページの「[[$3#$2|$2]]」に{{GENDER:$1|コメントしました}}。",
- "notification-mention": "[[User:$1|$1]] が $5 のトークページの「[[:$3#$2|$4]]」であなたに{{GENDER:$1|言及しました}}。",
- "notification-mention-flyout": "$1 が $5 のトークページの「[[:$3#$2|$4]]」であなたに{{GENDER:$1|言及しました}}。",
- "notification-mention-nosection": "[[User:$1|$1]] が [[:$3|$2 のトークページ]]であなたに{{GENDER:$1|言及しました}}。",
- "notification-mention-nosection-flyout": "$1 が [[:$3|$2 のトークページ]]であなたに{{GENDER:$1|言及しました}}。",
- "notification-user-rights": "あなたの権限を[[User:$1|$1]]が[[Special:Log/rights/$1|{{GENDER:$1|変更しました}}]]。$2。[[Special:ListGroupRights|詳細はこちら]]",
- "notification-user-rights-flyout": "あなたの権限を $1 が{{GENDER:$1|変更しました}}。$2。[[Special:ListGroupRights|詳細はこちら]]",
- "notification-user-rights-add": "あなたは{{PLURAL:$2|以下のグループ}}に所属になりました: $1",
- "notification-user-rights-remove": "あなたは{{PLURAL:$2|以下のグループ}}の所属から外れました: $1",
- "notification-new-user": "$1さん、{{SITENAME}}へようこそおいでくださいました。",
- "notification-reverted2": "{{PLURAL:$4|[[:$2]] でのあなたの編集}}を [[User:$1|$1]] が{{GENDER:$1|差し戻しました}}。$3",
- "notification-reverted-flyout2": "{{PLURAL:$4|$2 でのあなたの編集}}を $1 が{{GENDER:$1|差し戻しました}}。$3",
+ "notification-link-article-reminder": "ページを閲覧",
+ "notification-header-reverted": "{{PLURAL:$4|<strong>$3</strong> でのあなたの編集}}が{{GENDER:$2|差し戻されました}}",
+ "notification-header-emailuser": "$1 があなたに電子メールを{{GENDER:$2|送りました}}。",
"notification-edit-talk-page-email-subject2": "{{SITENAME}}で $1 があなたのトークページにメッセージを{{GENDER:$1|投稿しました}}",
- "notification-edit-talk-page-email-batch-body2": "$1 があなたのトークページにメッセージを{{GENDER:$1|投稿しました}}。",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 があなたのトークページの「$2」にメッセージを{{GENDER:$1|投稿しました}}。",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 があなたのトークページのセクション「$2」にメッセージを{{GENDER:$1|投稿しました}}。",
"notification-page-linked-email-subject": "あなたの作成したページが{{SITENAME}}でリンクされました",
- "notification-page-linked-email-batch-body": "$2 が $3 から{{GENDER:$1|リンクされました}}。",
"notification-reverted-email-subject2": "{{SITENAME}}でのあなたの{{PLURAL:$3|編集}}が{{GENDER:$1|差し戻されました}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|$2 でのあなたの編集}}を $1 が{{GENDER:$1|差し戻しました}}。",
- "notification-mention-email-subject": "$1 が{{SITENAME}}であなたに{{GENDER:$1|言及しました}}",
- "notification-mention-email-batch-body": "$1 が $4 のトークページの「$3」であなたに{{GENDER:$1|言及しました}}。",
- "notification-mention-nosection-email-batch-body": "$1 が $2 のトークページであなたに{{GENDER:$1|言及しました}}。",
+ "notification-mention-email-subject": "$1 が{{SITENAME}}で{{GENDER:$2|あなた}}に{{GENDER:$1|言及しました}}",
"notification-user-rights-email-subject": "{{SITENAME}}での利用者権限が変更されました",
- "notification-user-rights-email-batch-body": "あなたの権限が $1 により{{GENDER:$1|変更されました}}。$2",
- "echo-email-subject-default": "{{SITENAME}}での新しい通知",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1秒前}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1分前}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1時間前}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1日前}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1ヶ月前}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1年前}}",
+ "notification-timestamp-today": "今日",
+ "notification-timestamp-yesterday": "昨日",
+ "notification-inbox-filter-read": "既読",
+ "notification-inbox-filter-unread": "未読",
+ "notification-inbox-filter-all": "すべて",
"echo-email-body-default": "{{SITENAME}}で新しい通知があります:\n\n$1",
- "echo-email-batch-body-default": "新しい通知があります。",
"echo-email-footer-default": "$2\n\n受け取るメールの設定を変更するには、個人設定をご確認ください:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "お送りするメールの設定を変更するには、<a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">個人設定を参照してください</a>。<br />\n$1",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|自分}}の個人設定を確認する",
"echo-notification-alert": "{{PLURAL:$1|アラート ($1)|100=アラート (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|メッセージ ($1)|100=メッセージ (99+)}}",
- "echo-notification-alert-text-only": "アラート",
- "echo-notification-message-text-only": "メッセージ",
+ "echo-notification-notice": "{{PLURAL:$1|通知 ($1件)|100=通知 (99件以上)}}",
+ "echo-notification-alert-text-only": "通知",
+ "echo-notification-notice-text-only": "通知",
"echo-overlay-link": "すべての通知",
"echo-overlay-title": "<b>通知</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|通知}}</b> (未読 $2 件中 $1 件を表示中)",
"echo-mark-all-as-read": "すべて既読にする",
+ "echo-mark-all-as-read-confirmation": "$1件の{{PLURAL:$1|通知}}を既読にしました",
+ "echo-mark-wiki-as-read": "選択したウィキですべて既読にする: $1",
"echo-date-today": "今日",
"echo-date-yesterday": "昨日",
"echo-load-more-error": "結果の続きを取得する際にエラーが発生しました。",
- "notification-edit-talk-page-bundle": "$1 と他 $3 {{PLURAL:$4|人}}があなたの[[User talk:$2|トークページ]]にメッセージを{{GENDER:$1|投稿しました}}。",
- "notification-page-linked-bundle": "$2 が $3 と他 $4 {{PLURAL:$5|件のページ}}から{{GENDER:$1|リンクされました}}。[[Special:WhatLinksHere/$2|このページのリンク元]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 と他 $2 {{PLURAL:$3|人}}があなたのトークページにメッセージを{{GENDER:$1|投稿しました}}。",
- "notification-page-linked-email-batch-bundle-body": "$2 が $3 と他 $4 {{PLURAL:$5|件のページ}}から{{GENDER:$1|リンクされました}}。",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|1件の新しいメッセージ|$1件の新しいメッセージ|100=99件以上の新しいメッセージ}}が<strong>{{GENDER:$3|あなた}}のトークページ</strong>にあります。",
"echo-email-batch-subject-daily": "{{SITENAME}}で{{PLURAL:$2|新たな通知}}が届いています",
"echo-email-batch-subject-weekly": "{{SITENAME}}でこの1週間に{{PLURAL:$2|新たな通知}}が届いています",
"echo-email-batch-body-intro-daily": "こんにちは、$1 さん。\nこれが {{SITENAME}} での今日の出来事をあなたのために要約したものです。",
"echo-email-batch-body-intro-weekly": "こんにちは、$1 さん。\nこれが {{SITENAME}} での今週の出来事をあなたのために要約したものです。",
"echo-email-batch-link-text-view-all-notifications": "すべての通知を閲覧",
- "echo-rev-deleted-text-view": "ページのこの版は秘匿されています。",
- "apihelp-echomarkread-description": "現在のユーザーについては通知を既読にする",
- "apihelp-query+notifications-example-1": "通知を一覧表示する",
- "apihelp-query+notifications-example-2": "通知をセクションによりグループ化し、カウントで一覧表示する"
+ "notification-header-foreign-alert": "{{PLURAL:$5|他のウィキ|$5件のウィキ}}からの通知があります",
+ "notification-header-foreign-notice": "{{PLURAL:$5|他のウィキ|$5件の他のウィキ}}からの通知があります",
+ "notification-header-foreign-all": "{{PLURAL:$5|他のウィキ|$5件の他のウィキ}}からの通知があります"
}
diff --git a/Echo/i18n/jam.json b/Echo/i18n/jam.json
new file mode 100644
index 00000000..fb7765ae
--- /dev/null
+++ b/Echo/i18n/jam.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Katxis"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Fiyu}} aloert‎",
+ "tooltip-pt-notifications-message": "{{GENDER:|Fiyu}} mechiz‎"
+}
diff --git a/Echo/i18n/jut.json b/Echo/i18n/jut.json
new file mode 100644
index 00000000..938661bb
--- /dev/null
+++ b/Echo/i18n/jut.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jyllanj"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Din}} mæljenge",
+ "tooltip-pt-notifications-message": "{{GENDER:|Din}} beskede"
+}
diff --git a/Echo/i18n/jv.json b/Echo/i18n/jv.json
index 4a335e77..2d5dbd31 100644
--- a/Echo/i18n/jv.json
+++ b/Echo/i18n/jv.json
@@ -6,104 +6,185 @@
"NoiX180"
]
},
- "echo-desc": "Sistem pemberitahuan",
+ "echo-desc": "Sistem sing ngabari panganggo ngenani anané layang lan kagiyatan",
"prefs-echo": "Wara-wara",
- "prefs-emailsettings": "Opsi layang elektronik",
- "prefs-displaynotifications": "Duduhna pilihan",
- "prefs-echosubscriptions": "Beritahu saya mengenai peristiwa berikut",
- "prefs-newmessageindicator": "Penanda layang anyar",
- "echo-pref-send-me": "Kirim nang aku:",
- "echo-pref-send-to": "Kirim nang:",
- "echo-pref-email-format": "Format layang elektronik:",
- "echo-pref-web": "Web",
- "echo-pref-email": "Layang èlèktronik",
- "echo-pref-email-frequency-never": "Ora usah ngirimi aku notifikasi",
- "echo-pref-email-frequency-immediately": "Pemberitahuan tunggal setiap suatu peristiwa terjadi",
- "echo-pref-email-frequency-daily": "Ringkasan harian dari beberapa pemberitahuan",
- "echo-pref-email-frequency-weekly": "Ringkasan mingguan dari beberapa pemberitahuan",
+ "prefs-emailsettings": "Opsi layang-èl",
+ "prefs-displaynotifications": "Opsi pitontonan",
+ "prefs-echosubscriptions": "Kabari aku ngenani kagiyatan iki",
+ "prefs-echocrosswiki": "Wara-wara antar-wiki",
+ "prefs-newmessageindicator": "Panengeré layang anyar",
+ "echo-pref-send-me": "Kirimi aku:",
+ "echo-pref-send-to": "Kirim menyang:",
+ "echo-pref-email-format": "Format layang-èl:",
+ "echo-pref-web": "Jaringan",
+ "echo-pref-email": "Layang-èl",
+ "echo-pref-email-frequency-never": "Aja kirimi aku wara-wara lumantar layang-èl",
+ "echo-pref-email-frequency-immediately": "Wara-wara siji saben kabar",
+ "echo-pref-email-frequency-daily": "Ringkesan padinan wara-wara sing mlebu",
+ "echo-pref-email-frequency-weekly": "Ringkesan minggon wara-wara sing mlebu",
"echo-pref-email-format-html": "HTML",
- "echo-pref-email-format-plain-text": "aksara nglegena",
- "echo-pref-notify-show-link": "Tampilkan pemberitahuan di bilah alat saya",
- "echo-pref-new-message-indicator": "Tampilkan penanda pesan halaman pembicaraan pada bilah alat saya",
- "echo-learn-more": "Sinau luwih",
- "echo-new-messages": "Panjenengan olèh pesen-pesen anyar",
- "echo-category-title-edit-user-talk": "{{PLURAL:$1|Pesan}} halaman pembicaraan",
- "echo-category-title-article-linked": "{{PLURAL:$1|Pranala|Pranala}} kaca",
- "echo-category-title-reverted": "{{PLURAL:$1|Balikna|Baliknya}} pangowahan",
- "echo-category-title-mention": "{{PLURAL:$1|Panyebutan|Panyebutan}}",
- "echo-category-title-other": "{{PLURAL:$1|Liyane}}",
+ "echo-pref-email-format-plain-text": "Tèks barès",
+ "echo-pref-cross-wiki-notifications": "Tuduhaké wara-wara saka wiki liya",
+ "echo-pref-new-message-indicator": "Tuduhaké panengeré layang saka kaca-parembugan menyang wilah-pirantiku",
+ "echo-pref-beta-feature-cross-wiki-message": "Wara-wara njlimet",
+ "echo-pref-beta-feature-cross-wiki-description": "Deleng lan tata wara-wara kanthi mayar. Kalebu wara-wara antar-wiki, sing njalari panjenengan bisa ndeleng layang saka wiki-wiki liya. (Supaya bisa nampa wara-wara antar-wiki ing sawijiné wiki, panjenengan kudu ngurubaké fitur béta ing wiki iku.)",
+ "echo-learn-more": "Sinaoni candhaké",
+ "echo-log": "Log umum",
+ "echo-new-messages": "Panjenengan antuk layang anyar",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|Layang}} ing kaca-parembugan",
+ "echo-category-title-article-linked": "{{PLURAL:$1|Pranala}} kaca",
+ "echo-category-title-reverted": "{{PLURAL:$1|Pamulihan}} besutan",
+ "echo-category-title-mention": "{{PLURAL:$1|Panyebutan}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Panyebutan}} sing gagal",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Panyebutan}} sing kasil",
+ "echo-category-title-other": "{{PLURAL:$1|Liyané}}",
"echo-category-title-system": "{{PLURAL:$1|Sistem}}",
- "echo-pref-tooltip-edit-user-talk": "Beritahu saya saat seseorang mengirim pesan atau balasan pada halaman pembicaraan saya.",
- "echo-pref-tooltip-article-linked": "Beritahu saya saat seseorang membuat pranala di halaman artikel ke sebuah halaman yang pernah saya rintis.",
- "echo-pref-tooltip-reverted": "Beritahu saya saat seseorang membalikkan suntingan yang pernah saya buat, dengan menggunakan alat batalkan atau balikkan.",
- "echo-pref-tooltip-mention": "Beritahu saya saat seseorang membuat pranala di halaman pembicaraan apapun ke halaman pengguna saya.",
- "echo-no-agent": "[Dudu sapa-sapa]",
- "echo-no-title": "[Ora ana kaca]",
- "echo-error-no-formatter": "Tidak ada pemformatan yang ditetapkan untuk pemberitahuan.",
- "echo-error-preference": "Galat: Tidak dapat menetapkan preferensi pengguna.",
- "echo-error-token": "Galat: Tidak dapat mengambil token pengguna.",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Owah-owahané haké panganggo}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Layang-èl saka panganggo liya}}",
+ "echo-pref-tooltip-edit-user-talk": "Kabari aku manawa ana sing ngirimi layang utawa mangsuli aku ing kaca-parembuganku.",
+ "echo-pref-tooltip-article-linked": "Kabari aku manawa ana sing nggayutaké kaca artikel nyang kaca sing takgawé.",
+ "echo-pref-tooltip-reverted": "Kabari aku manawa ana sing mbalèkaké besutanku lumantar tombol-balèkaké.",
+ "echo-pref-tooltip-mention": "Kabari aku manawa ana sing nggayut menyang kaca-panganggoku.",
+ "echo-pref-tooltip-mention-failure": "Kabari aku manawa aku ora kasil ngirim panyebutan nyang sawiji wong.",
+ "echo-pref-tooltip-mention-success": "Kabari aku manawa aku kasil ngirim panyebutan marang sawijining wong.",
+ "echo-pref-tooltip-user-rights": "Kabari aku manawa ana sing ngowahi hak-panganggoku.",
+ "echo-pref-tooltip-emailuser": "Kabari aku manawa ana sing ngirimi layang-èl.",
+ "echo-error-no-formatter": "Ora ana format sing dicakaké ing wara-wara.",
"notifications": "Wara-wara",
- "tooltip-pt-notifications": "Pemberitahuan Anda",
+ "tooltip-pt-notifications-alert": "Pangawasané {{GENDER:|panjenengan}}",
+ "tooltip-pt-notifications-notice": "Wara-warané {{GENDER:|panjenengan}}",
+ "echo-displaynotificationsconfiguration": "Tuduhaké pangaturané Wara-wara",
+ "echo-displaynotificationsconfiguration-summary": "Iki ulasan ngenani kepiyé Wara-wara ditata ing wiki iki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Wara-wara miturut kategoriné",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Urutané jinis",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Métodhe wara-wara sing diidinaké",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Urubaké miturut bakuné",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Panganggo sing ana",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Panganggo anyar",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Métodhené wara-wara sing dibutuhaké",
"echo-specialpage": "Wara-wara",
- "echo-anon": "Kanggo nampa wara-wara [$1 gawé akun] utawa [$2 mlebu log].",
- "echo-none": "Sampéyan durung nampa wara-wara apa-apa.",
- "echo-more-info": "Info jangkep",
- "echo-feedback": "Lebon saran",
- "notification-link-text-view-message": "Lihat pesan",
- "notification-link-text-view-mention": "Lihat sebutan",
- "notification-link-text-view-changes": "Tuduhna pangowahan",
- "notification-link-text-view-page": "Tuduhna kaca",
- "notification-link-text-view-edit": "Tuduhna pangowahan",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|meninggalkan}} sebuah pesan pada [[User talk:$2#$3|halaman pembicaraan]] Anda.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|meninggalkan}} sebuah pesan pada halaman pembicaraan Anda di [[User talk:$2#$3|$4]].",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|meninggalkan}} sebuah pesan pada [[User talk:$2#$3|halaman pembicaraan]] Anda.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|meninggalkan}} sebuah pesan pada halaman pembicaraan Anda di [[User talk:$2#$3|$4]].",
- "notification-page-linked": "Pranala ke [[:$2]] {{GENDER:$1|ditambahkan}} di [[:$3]]. [[Special:WhatLinksHere/$2|Lihat semua pranala balik ke halaman ini]].",
- "notification-page-linked-flyout": "Pranala ke [[:$2]] {{GENDER:$1|ditambahkan}} di [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|mengomentari}} \"[[$3|$2]]\" pada halaman pembicaraan \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|mengirimkan}} sebuah topik baru \"$2\" di [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|mengirimi}} Anda sebuah pesan: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|mengomentari}} \"[[$3|$2]]\" pada halaman pembicaraan \"$4\".",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|menyebut}} Anda di \"[[:$3#$2|$4]]\" pada halaman pembicaraan $5.",
- "notification-mention-flyout": "$1 {{GENDER:$1|menyebut}} Anda di \"[[:$3#$2|$4]]\" pada halaman pembicaraan $5.",
- "notification-user-rights": "Hak pengguna Anda [[Special:Log/rights/$1|telah {{GENDER:$1|diubah}}]] oleh [[User:$1|$1]]. $2. [[Special:ListGroupRights|Pelajari selengkapnya]]",
- "notification-user-rights-flyout": "Hak pengguna Anda telah {{GENDER:$1|diubah}} oleh $1. $2. [[Special:ListGroupRights|Pelajari selengkapnya]]",
- "notification-user-rights-add": "Anda sekarang adalah anggota dari {{PLURAL:$2|kelompok berikut}}: $1",
- "notification-user-rights-remove": "Anda tidak lagi menjadi anggota dari {{PLURAL:$2|kelompok berikut}}: $1",
- "notification-new-user": "Selamat datang di {{SITENAME}}, $1! Kami senang Anda hadir di sini.",
- "notification-reverted2": "{{PLURAL:$4|Suntingan Anda pada [[:$2]] telah}} {{GENDER:$1|dibalikkan}} oleh [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Suntingan Anda pada $2 telah}} {{GENDER:$1|dibalikkan}} oleh $1. $3",
- "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|meninggalkan}} Anda sebuah pesan di {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|meninggalkan}} sebuah pesan pada halaman pembicaraan Anda:",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|meninggalkan}} sebuah pesan di \"$2\" pada halaman pembicaraan Anda.",
- "notification-page-linked-email-subject": "Pranala ke halaman Anda ditambahkan di {{SITENAME}}",
- "notification-page-linked-email-batch-body": "Pranala ke $2 {{GENDER:$1|ditambahkan}} di [[:$3]].",
- "notification-reverted-email-subject2": "{{PLURAL:$3|Suntingan}} Anda telah {{GENDER:$1|dibalikkan}} di {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$4|Suntingan Anda pada $2 telah}} {{GENDER:$1|dibalikkan}} oleh $1. $3",
- "notification-mention-email-subject": "$1 {{GENDER:$1|menyebut}} Anda di {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|menyebut}} Anda di \"[[$3#$2|$4]]\" pada halaman pembicaraan $5.",
- "notification-user-rights-email-subject": "Hak pengguna Anda telah diubah di {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Hak pengguna Anda telah {{GENDER:$1|diubah}} oleh $1. $2.",
- "echo-email-subject-default": "Wara-wara anyar nèng {{SITENAME}}",
- "echo-email-body-default": "Sampéyan nduwé wara-wara anyar nèng {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Sampéyan nampa wara-wara anyar.",
- "echo-email-footer-default": "$2\n\nUntuk mengendalikan surel mana saja yang akan kami kirimkan kepada Anda, periksa preferensi Anda:\n{{canonicalurl: {{#special:Preferences}} #mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Untuk mengendalikan surel mana saja yang akan kami kirimkan kepada Anda, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">periksa preferensi Anda</a>.<br />\n$1",
+ "echo-specialpage-section-markread": "Tengeri grup iki yèn wis diwaca",
+ "echo-specialpage-markasread": "Wara-wara: Tengeri yèn wis diwaca",
+ "echo-specialpage-markasread-invalid-id": "ID kagiyatan ora sah",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|wara-wara}}",
+ "echo-specialpage-pagefilters-title": "Kagiyatan mentas waé",
+ "echo-specialpage-pagefilters-subtitle": "Kaca mawa wara-wara sing durung diwaca",
+ "notificationsmarkread-legend": "Tengeri wara-wara yèn wis diwaca",
+ "echo-anon": "Supaya bisa nampa wara-wara, [$1 gawéa akun] utawa [$2 mlebua log].",
+ "echo-none": "Panjenengan durung antuk wara-wara.",
+ "echo-more-info": "Katerangan liyané",
+ "echo-feedback": "Pamrayoga",
+ "echo-popup-footer-special-page-invitation": "<strong>Jajala kaca Wara-wara sing wis dirancang ulang.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Sakèhing sesawangan lan fitur anyar.",
+ "echo-api-failure": "Wurung antuk wara-wara.",
+ "echo-api-failure-cross-wiki": "Aksès menyang dhomain adoh ora diolèhaké.",
+ "echo-notification-placeholder": "Durung ana wara-wara.",
+ "echo-notification-placeholder-filters": "Ora ana wara-wara sing mathuk pathokan iki.",
+ "echo-notification-loginrequired": "Panjenengan kudu mlebu log saperlu maca wara-wara kanggo panjenengan.",
+ "echo-notification-popup-loginrequired": "Mangga mlebua log saperlu maca wara-wara kanggo panjenengan.",
+ "echo-notification-markasread": "Tengeri yèn wis diwaca",
+ "echo-notification-markasunread": "Tengeri yèn durung diwaca",
+ "echo-notification-markasread-tooltip": "Tengeri yèn wis diwaca",
+ "echo-notification-more-options-tooltip": "Pilihan liya",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Endheg}} ngawasi kagiyatan anyar ing \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Panjenengan}} wis ora ngawasi kaca \"$1\" manèh",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Panjenengan}} bisa sawayah-wayah ngawasi [$2 kaca iki].",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Awasi}} kagiyatan anyar ing \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Panjenengan}} saiki ngawasi kaca \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Panjenengan}} bisa sawayah-wayah mandheg ngawasi [$2 kaca iki].",
+ "notification-link-text-expand-all": "Jembarna",
+ "notification-link-text-expand-alert-count": "Deleng {{PLURAL:$1|$1 pangawasan}}",
+ "notification-link-text-expand-notice-count": "Deleng {{PLURAL:$1|$1 wara-wara}}",
+ "notification-link-text-expand-all-count": "Deleng {{PLURAL:$1|$1 wara-wara}}",
+ "notification-link-text-collapse-all": "Ciyutna",
+ "notification-link-text-view-message": "Waca layang",
+ "notification-link-text-view-mention": "Deleng panyebutan",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Deleng panyebutan}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Deleng}} owahan",
+ "notification-link-text-view-page": "Deleng kaca",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|ninggal}} layang ing <strong>kaca parembugané {{GENDER:$3|panjenengan}}</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|ninggal}} layang ing <strong>kaca parembugané {{GENDER:$3|panjenengan}}</strong> ing \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "Sawijining pranala digawé saka <strong>$4</strong> nyang <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Kagayut saka <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Pranala digawé saka {{PLURAL:$5||$5 kaca|100=99+ kaca}} nyang <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Kabèh pranala menyang kaca iki",
+ "notification-header-mention-other": "$1 {{GENDER:$2|nyebut}} {{GENDER:$3|panjenengan}} ing <strong>$4</strong> ing \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|nyebut}} {{GENDER:$3|panjenengan}} ing <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|nyebut}} {{GENDER:$3|panjenengan}} ing <strong>kaca parembugan{{GENDER:$5|é}} $4</strong> ing \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|nyebut}} {{GENDER:$3|panjenengan}} ing <strong>kaca parembugan{{GENDER:$5|é}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|nyebut}} {{GENDER:$3|panjenengan}} ing <strong>kaca perembugan{{GENDER:$2|é}}</strong> ing \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|nyebut}} {{GENDER:$3|panjenengan}} ing <strong>kaca parembugan{{GENDER:$2|é}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|nyebut}} {{GENDER:$3|panjenengan}} ing kaca parembugané <strong>$4</strong> ing \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|nyebut}} {{GENDER:$3|panjenengan}} ing kaca parambugané <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "Panyebuté {{GENDER:$2|panjenengan}} tumrap <strong>$3</strong> ora kakirim amarga wongé ora katemu.",
+ "notification-header-mention-failure-user-anonymous": "Panyebuté {{GENDER:$2|panjenengan}} tumrap <strong>$3</strong> ora kakirim amarga wongé anonim.",
+ "notification-header-mention-failure-too-many": "Panyebuté {{GENDER:$2|panjenengan}} ora kakirim amarga cacahé munjuli watesé panyebutan cacah $3.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Panybutan|$3 panyebutan}} sing {{GENDER:$2|digawé panjenengan}} ing kaca parembugané <strong>$4</strong> ora {{PLURAL:$3|bisa}} dikirim.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Jeneng panganggo ora ana:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Ora bisa nyebut IP:</strong> $1",
+ "notification-header-mention-success": "Panyebuté {{GENDER:$2|panjenengan}} tumrap <strong>$3</strong> wis kakirim.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Panyebutan|$3 panyebutan}} sing {{GENDER:$2|digawé panjenengan}} ing kaca parembugané <strong>$4</strong> {{PLURAL:$3|wis}} kakirim.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Panjenengan nyebut}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Wara-wara|$3 wara-wara}} ngenani panyebutan sing {{GENDER:$2|digawé panjenengan}} ing kaca parembugané <strong>$4</strong>: {{PLURAL:$5|$5 ora kakirim}}, {{PLURAL:$6|$6 kakirim}}.",
+ "notification-header-user-rights-add-only": "Haké {{GENDER:$4|panjenengan}} wis {{GENDER:$1|diowahi}}. Panjenengan wis dilebokaké nyang: $2.",
+ "notification-header-user-rights-remove-only": "Haké {{GENDER:$4|panjenengan}} wis {{GENDER:$1|diowahi}}. Panjenengan wis dudu anggota: $2.",
+ "notification-header-user-rights-add-and-remove": "Haké {{GENDER:$6|panjenengan}} wis {{GENDER:$1|diowahi}}. Panjenengan wis dilebokaké nyang: $2. Panjenengan wis dudu anggota: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Sugeng rawuh}} ing {{SITENAME}}, $1! Kita bungah banget {{GENDER:$2|panjenengan}} wis teka mréné.",
+ "notification-welcome-linktext": "Sugeng rawuh",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Panjenengan}} nembé nggawé besutan sing pisanan; matur nuwun lan sugeng rawuh!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Panjenengan}} nembé nggawé besutan sing kaping sepuluh; matur nuwun lan panggah mbesut, ya!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Panjenengan}} nembé nggawé besutan sing kaping satus; matur nuwun sagedhé-gedhéné, ya!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Panjenengan}} nembé nggawé besutan sing kaping sèwu; matur nuwun panjenengan wis dadi pandharma sing hébat!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Panjenengan}} nembé nggawé besutan sing kaping sepuluh èwu; matur nuwun saakèh-akèhé, ya!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Panjenengan}} nembé nggawé besutan sing kaping sepuluh èwu; matur nuwun wis ndharma kalawan hébat!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Panjenengan}} nembé nggawé besutan sing kaping sayuta; matur nuwun wis ndharma kalawan tulus!",
+ "notification-link-thank-you-edit": "Besutané {{GENDER:$1|panjenengan}}",
+ "notification-link-text-view-edit": "Tuduhaké besutan",
+ "notification-header-reverted": "{{PLURAL:$4|Besutané panjenengan ing <strong>$3</strong>}} {{GENDER:$2|dibalèkaké}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|ngirimi}} panjenengan layang.",
+ "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|ngirimi}} panjenengan layang ing {{SITENAME}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|ndèkèk}} layang ing kaca parembugané panjenengan ing \"$2\".",
+ "notification-page-linked-email-subject": "Kaca sing panjenengan ripta digayutaké menyang {{SITENAME}}",
+ "notification-reverted-email-subject2": "{{PLURAL:$3|Besutané panjenengan}} ing {{SITENAME}} {{GENDER:$1|dibalèkaké}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|nyebut}} {{GENDER:$2|panjenengan}} ing {{SITENAME}}",
+ "notification-user-rights-email-subject": "Haké panjenengan ing {{SITENAME}} wis diowahi",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1dh}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1j}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1w}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1t}}",
+ "notification-timestamp-today": "Dina iki",
+ "notification-timestamp-yesterday": "Wingi",
+ "notification-inbox-filter-read": "Wis diwaca",
+ "notification-inbox-filter-unread": "Durung diwaca",
+ "notification-inbox-filter-all": "Kabèh",
+ "echo-email-body-default": "Panjenengan antuk wara-wara anyar ing {{SITENAME}}:\n\n$1",
+ "echo-email-footer-default-html": "Kanggo ngatur layang-èl endi waé sing kudu kita kirim nyang panjenengan, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">priksa préferènsiné panjenengan</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nKanggo ngatur layang-èl endi waé sing kudu kita kirim nyang panjenengan, priksa préferènsiné panjenengan:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Kanggo ngatur layang-èl endi waé sing kudu kita kirim nyang {{GENDER:$1|panjenengan}}, priksa préferènsiné {{GENDER:$1|panjenengan}}:",
+ "echo-email-html-footer-preference-link-text": "priksa préferènsiné {{GENDER:$1|panjenengan}}",
+ "echo-email-html-footer-with-link": "Kanggo ngatur layang-èl endi waé sing kudu kita kirim nyang {{GENDER:$2|panjenengan}}, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Pangawasan ($1)|100=Pangawasan (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Wara-wara ($1)|100=Wara-wara (99+)}}",
+ "echo-notification-alert-text-only": "Pangawasan",
+ "echo-notification-notice-text-only": "Wara-wara",
"echo-overlay-link": "Kabèh wara-wara",
"echo-overlay-title": "<b>Wara-wara</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Pemberitahuan}}</b> (menampilkan $1 dari $2 yang belum dibaca)",
- "echo-mark-all-as-read": "Tandhai kabèh minangka kawaca",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Wara-wara}}</b> (nuduhaké $1 saka $2 layang sing durung diwaca)",
+ "echo-mark-all-as-read": "Tengeri kabèh yèn wis diwaca",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|wara-wara}} ditengeri yèn wis diwaca",
+ "echo-mark-wiki-as-read": "Tengeri kabèh yèn wis diwaca ing wiki iki: $1",
"echo-date-today": "Dina iki",
"echo-date-yesterday": "Dina wingi",
- "echo-load-more-error": "Ana kasalahan nalika njupuk luwih akèh asil.",
- "notification-edit-talk-page-bundle": "$1 dan $3 pengguna {{PLURAL:$4|lainnya}} {{GENDER:$1|meninggalkan}} sebuah pesan pada [[User talk:$2|halaman pembicaraan]] Anda.",
- "notification-page-linked-bundle": "Pranala ke $2 {{GENDER:$1|ditambahkan}} di $3 dan $4 {{PLURAL:$5|halaman}} lainnya. [[Special:WhatLinksHere/$2|Lihat semua pranala balik ke halaman ini]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 dan $2 pengguna {{PLURAL:$3|lainnya}} {{GENDER:$1|meninggalkan}} sebuah pesan pada halaman pembicaraan Anda.",
- "notification-page-linked-email-batch-bundle-body": "Pranala ke $2 {{GENDER:$1|ditambahkan}} di $3 dan $4 {{PLURAL:$5|halaman}} lainnya.",
- "echo-email-batch-subject-daily": "Anda memiliki {{PLURAL:$2|sebuah|beberapa}} pemberitahuan baru di {{SITENAME}}",
- "echo-email-batch-subject-weekly": "Anda memiliki {{PLURAL:$2|sebuah|beberapa}} pemberitahuan baru di {{SITENAME}} pekan ini",
- "echo-email-batch-body-intro-daily": "Hai $1,\nIni adalah ringkasan aktivitas kegiatan hari ini di {{SITENAME}} untuk Anda.",
- "echo-email-batch-body-intro-weekly": "Hai $1,\nIni adalah ringkasan aktivitas kegiatan pekan ini di {{SITENAME}} untuk Anda.",
- "echo-email-batch-link-text-view-all-notifications": "Tampilkan semua pemberitahuan",
- "echo-rev-deleted-text-view": "Revisi halaman ini telah ditekan."
+ "echo-load-more-error": "Ana masalah nalika njupuk kasilé luwih akèh.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Salayang anyar|$1 layang anyar|100=99+ layang anyar}} ing <strong>kaca parembugané {{GENDER:$3|panjenengan}}</strong>.",
+ "echo-email-batch-subject-daily": "Panjenengan antuk {{PLURAL:$2|wara-wara anyar}} ing {{SITENAME}}",
+ "echo-email-batch-subject-weekly": "Panjenengan antuk {{PLURAL:$2|wara-wara anyar}} ing {{SITENAME}} minggu iki",
+ "echo-email-batch-body-intro-daily": "Halo $1,\nIki ringkesané kagiyatan dina iki ing {{SITENAME}} kanggo panjenengan.",
+ "echo-email-batch-body-intro-weekly": "Halo $1,\nIki ringkesané kagiyatan minggu iki ing {{SITENAME}} kanggo panjenengan.",
+ "echo-email-batch-link-text-view-all-notifications": "Deleng kabèh wara-wara",
+ "notification-header-foreign-alert": "Pangawasan tambahan saka {{PLURAL:$5|wiki liya|$5 wiki liya}}",
+ "notification-header-foreign-notice": "Wara-wara tambahan saka {{PLURAL:$5|wiki liya|$5 wiki liya}}",
+ "notification-header-foreign-all": "Wara-wara tambahan saka {{PLURAL:$5|wiki liya|$5 wiki liya}}"
}
diff --git a/Echo/i18n/ka.json b/Echo/i18n/ka.json
index a14ce4a9..4003c78a 100644
--- a/Echo/i18n/ka.json
+++ b/Echo/i18n/ka.json
@@ -4,14 +4,20 @@
"David1010",
"MIKHEIL",
"Nodar Kherkheulidze",
- "Tokoko"
+ "Tokoko",
+ "Otogi",
+ "BRUTE",
+ "Dawid Deutschland",
+ "Macofe",
+ "Sopopruidze"
]
},
- "echo-desc": "შეტყობინებების სისტემა",
+ "echo-desc": "შეტყობინებებისა და მოვლენების სისტემა",
"prefs-echo": "შეტყობინებები",
"prefs-emailsettings": "ელ-ფოსტის პარამეტრები",
"prefs-displaynotifications": "გამოსახვის პარამეტრები",
"prefs-echosubscriptions": "შემატყობინეთ ამ ღონისძიებების შესახებ",
+ "prefs-echocrosswiki": "კროს-ვიკის შეტყობინებები",
"prefs-newmessageindicator": "ახალი შეტყობინების ინდიკატორი",
"echo-pref-send-me": "გამომიგზავნეთ:",
"echo-pref-send-to": "გასაგზავნი მისამართი:",
@@ -24,50 +30,99 @@
"echo-pref-email-frequency-weekly": "კვირის შემაჯამებელი შეტყობინებები",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "ჩვეულებრივი ტექსტი",
+ "echo-pref-cross-wiki-notifications": "შეტყობინების ჩვენება სხვა ვიკიდან",
"echo-pref-new-message-indicator": "განხილვის გვერდის შეტყობინების ინდიკატორის ჩვენება ხელსაწყოების პანელზე",
+ "echo-pref-beta-feature-cross-wiki-message": "გაზრდილი შეტყობინებები",
+ "echo-pref-beta-feature-cross-wiki-description": "იხილეთ და მოაწესრიგეთ შეტყობინებები უფრო მარტივად. შეგეძლებათ იხილოთ შეტყობინებები, რომლებსაც დაგიტოვებენ სხვა პროექტებში.",
"echo-learn-more": "გაიგეთ მეტი",
"echo-new-messages": "თქვენ გაქვთ ახალი შეტყობინება",
"echo-category-title-edit-user-talk": "განხილვის გვერდის {{PLURAL:$1|შეტყობინება}}",
+ "echo-category-title-article-linked": "გვერდის {{PLURAL:$1|ბმული|ბმულები}}",
+ "echo-category-title-reverted": "{{PLURAL:$1|1=ცვლილების|ცვლილებების}} გაუქმება",
+ "echo-category-title-mention": "{{PLURAL:$1|მონიშვნა|მონიშვნები}}",
+ "echo-category-title-mention-failure": "წარუმატებელი {{PLURAL:$1|მოხსენება|მოხსენებები}}",
+ "echo-category-title-mention-success": "წარმატებული {{PLURAL:$1|მოხსენება|მოხსენებები}}",
+ "echo-category-title-other": "{{PLURAL:$1|სხვა}}",
+ "echo-category-title-system": "{{PLURAL:$1|სისტემა}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|მომხმარებლის უფლებების ცვლილება|მომხმარებლის უფლებების ცვლილებები}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|იმეილი სხვა მომხმარებლისაგან|იმეილი სხვა მომხმარებლებისაგან}}",
"echo-pref-tooltip-edit-user-talk": "შემატყობინე, როდესაც ვინმე დაარედაქტირებს ჩემს განხილვის გვერდს.",
+ "echo-pref-tooltip-article-linked": "შემატყობინე, როდესაც ვინმე უკავშირდება სტატიებს ჩემ მიერ შექმნილ გვერდზე",
"echo-pref-tooltip-reverted": "შემატყობინე, როდესაც ვინმე ჩემს რედაქტირებას გააუქმებს.",
"echo-pref-tooltip-mention": "შემატყობინე, როდესაც ვინმე მომნიშნავს განხილვაში.",
- "echo-no-agent": "[არავინ]",
- "echo-no-title": "[არ არის გვერდი]",
+ "echo-pref-tooltip-mention-failure": "შემატყობინე, როდესაც ვერ შევძლებ გავუგზავნო მოხსენება ვინმეს",
+ "echo-pref-tooltip-mention-success": "შემატყობინე, როდესაც მე ვუგზავნი ვინმეს მოხსენებას",
+ "echo-pref-tooltip-user-rights": "შემატყობინე, როდესაც ვინმე შეცვლის ჩემს მომხმარებლის უფლებებს.",
+ "echo-pref-tooltip-emailuser": "შემატყობინე, როდესაც ვინმე მომწერს ელექტრონულ მეილს.",
+ "echo-error-no-formatter": "შეტყობინებისთვის ფორმატირება განსაზღვრული არ არის.",
"notifications": "შეტყობინებები",
+ "tooltip-pt-notifications-alert": "{{GENDER:|თქვენი}} მოხსენებები",
+ "tooltip-pt-notifications-notice": "თქვენი შეტყობინებები",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "შეტყობინებები კატეგორიების მიხედვით",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "ტიპების დალაგება",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "ახალი მომხმარებლები",
"echo-specialpage": "შეტყობინებები",
+ "echo-specialpage-pagefilters-title": "ბოლო მოქმედებები",
+ "echo-specialpage-pagefilters-subtitle": "გვერდები წაუკითხავი შეტყობინებებით",
"echo-anon": "რომ მიიღოთ შეტყობინებები, [$1 შექმენით ანგარიში] ან [$2 შედით სისტემაში].",
"echo-none": "თქვენ არ გაქვთ შეტყობინება.",
"echo-more-info": "დეტალურად",
"echo-feedback": "შეფასება",
+ "echo-api-failure": "შეტყობინებას ვერ ვპოულობთ. გთხოვთ სცადეთ თავიდან. (შეცდომა $1)",
+ "echo-api-failure-cross-wiki": "მანძილზე მოქმედ დომეინზე წვდომა უარყოფილია.",
+ "echo-notification-placeholder": "ახალი შეტყობინებები არ არის.",
+ "echo-notification-loginrequired": "თქვენი შეტყობინებების სანახავად უნდა გაიაროთ ავტორიზაცია.",
+ "echo-notification-popup-loginrequired": "გთხოვთ გაიარეთ ავტორიზაცია თქვენი შეტყობინებების სანახავად.",
+ "echo-notification-markasread": "მონიშნეთ როგორც წაკითხული",
+ "echo-notification-markasunread": "მონიშნეთ როგორც წაუკითხავი",
+ "echo-notification-markasread-tooltip": "მონიშნეთ როგორც წაკითხული",
+ "echo-notification-more-options-tooltip": "მეტი პარამეტრები",
+ "notification-link-text-expand-all": "განვრცობა",
+ "notification-link-text-expand-all-count": "იხილე {{PLURAL:$1|$1 შეტყობინება|$1 შეტყობინებები}}",
+ "notification-link-text-collapse-all": "ჩაკეცვა",
"notification-link-text-view-message": "შეტყობინების ნახვა",
"notification-link-text-view-mention": "მონიშვნის ნახვა",
- "notification-link-text-view-changes": "ცვლილებების ნახვა",
+ "notification-link-text-view-changes": "ცვლილებების {{GENDER:$1|ნახვა}}",
"notification-link-text-view-page": "გვერდის ნახვა",
+ "notification-header-edit-user-talk": "მომხმარებელმა $1 {{GENDER:$2|დატოვა}} შეტყობინება <strong>{{GENDER:$3|თქვენი}} განხილვის გვერდზე</strong>.",
+ "notification-header-edit-user-talk-with-section": "მომხმარებელმა $1 {{GENDER:$2|}} დატოვა შეტყობინება <strong>{{GENDER:$3|თქვენი}} განხილვის გვერდზე</strong> „<strong>$4</strong>“-ში.",
+ "notification-header-page-linked": "გაკეთდა ბმული <strong>$4</strong>-დან <strong>$3</strong>-ზე.",
+ "notification-compact-header-page-linked": "ბმული <strong>$1</strong>-დან.",
+ "notification-link-text-what-links-here": "ყველა ბმული ამ გვერდზე",
+ "notification-header-mention-other": "მომხარებელმა $1 {{GENDER:$2|მოგიხსენიათ}} {{GENDER:$3|თქვენ}} გვერდზე <strong>$4</strong>, სექციაში „<strong>$5</strong>“.",
+ "notification-header-mention-other-nosection": "$1-მ {{GENDER:$2|მოგიხსენიათ}} {{GENDER:$3|თქვენ}} გვერდზე <strong>$4</strong>.",
+ "notification-welcome-linktext": "კეთილი იყოს თქვენი მობრძანება",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|თქვენ}} ახლახან განახორციელეთ {{GENDER:$2|თქვენი}} პირველი რედაქტირება. მადლობას {{GENDER:$2|გიხდით}} ამისთვის, და კეთილი იყოს თქვენი მობრძანება!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|თქვენ}} ახლახან განახორციელეთ {{GENDER:$2|თქვენი}} მეათე რედაქტირება. მადლობას გიხდით ამისთვის, ასე განაგრძეთ!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|თქვენ}} ახლახან განახორციელეთ {{GENDER:$2|თქვენი}} მეასე რედაქტირება. დიდი მადლობა ამისთვის!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|თქვენ}} ახლახან განახორციელეთ {{GENDER:$2|თქვენი}} მეათასე რედაქტირება; მადლობა {{GENDER:$2|თქვენ}} დიდი წვლილისთვის!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|თქვენ}} ახლახან განახორციელეთ {{GENDER:$2|თქვენი}} მეათასე რედაქტირება; ძალიან დიდი მადლობა!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|თქვენ}} ახლახან განახორციელეთ {{GENDER:$2|თქვენი}} მეასიათასე რედაქტირება; მადლობა {{GENDER:$2|თქვენ}} საოცარი წვლილისთვის!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|თქვენ}} ახლახან განახორციელეთ {{GENDER:$2|თქვენი}} მემილიონე რედაქტირება; მადლობა {{GENDER:$2|თქვენ}} განსაცვიფრებელი წვლილისთვის!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|თქვენი}} რედაქტირება",
"notification-link-text-view-edit": "რედაქტირების ნახვა",
- "notification-edit-talk-page2": "მომხმარებელმა [[User:$1|$1]] {{GENDER:$1|დატოვა}} შეტყობინება თქვენი [[User talk:$2#$3|განხილვის გვერდზე]].",
- "notification-edit-talk-page-with-section": "მომხმარებელმა [[User:$1|$1]] {{GENDER:$1|დატოვა}} შეტყობინება თქვენი განხილვის გვერდზე განყოფილებაში „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "მომხმარებელმა $1 {{GENDER:$1|დატოვა}} შეტყობინება თქვენი [[User talk:$2#$3|განხილვის გვერდზე]].",
- "notification-edit-talk-page-flyout-with-section": "მომხმარებელმა $1 {{GENDER:$1|დატოვა}} შეტყობინება თქვენი განხილვის გვერდზე განყოფილებაში „[[User talk:$2#$3|$4]]“.",
- "notification-page-linked": "[[:$2]] {{GENDER:$1|ბმული}} გაკეთდა სტატიაში [[:$3]]. [[Special:WhatLinksHere/$2|იხილეთ ამ გვერდის ყველა ბმული]].",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|მოგნიშნათ}} განხილვის გვერდზე „$5“ სექციაში „[[:$3#$2|$4]]“.",
- "notification-mention-flyout": "$1 {{GENDER:$1|მოგნიშნათ}} განხილვის გვერდზე „$5“ სექციაში „[[:$3#$2|$4]]“.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|მოგნიშნათ}} [[:$3|$2 განხილვის გვერდზე]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|მოგნიშნათ}} [[:$3|$2 განხილვის გვერდზე]].",
- "notification-user-rights-add": "თქვენ გაწევრიანებული ხართ {{PLURAL:$2|ამ ჯგუფში|ამ ჯგუფებში}}: $1",
- "notification-user-rights-remove": "თქვენ აღარ ხართ გაწევრიანებული {{PLURAL:$2|ამ ჯგუფში|ამ ჯგუფებში}}: $1",
- "notification-new-user": "კეთილი იყოს თქვენი მობრძანება საიტზე {{SITENAME}}, $1! ჩვენ მოხარული ვართ თქვენი აქ ყოფნით.",
- "notification-edit-talk-page-email-batch-body2": "მომხმარებელმა $1 {{GENDER:$1|დატოვა}} შეტყობინება თქვენი განხილვის გვერდზე:",
+ "notification-header-emailuser": "მომხმარებელმა $1 {{GENDER:$2|გამოგიგზავნათ}} ელექტრონული წერილი.",
+ "notification-edit-talk-page-email-subject2": "$1-მ {{GENDER:$1|მოგწერათ}} {{SITENAME}}-ზე",
"notification-edit-talk-page-email-batch-body-with-section": "მომხმარებელმა $1 {{GENDER:$1|დატოვა}} შეტყობინება თქვენი განხილვის გვერდზე განყოფილებაში „$2“.",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|მოგნიშნათ}} განხილვის გვერდზე „$4“ სექციაში „$3“.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|მოგნიშნათ}} $2 განხილვის გვერდზე.",
- "echo-notification-count": "$1+",
- "echo-email-batch-body-default": "თქვენ გაქვთ ახალი შეტყობინება.",
+ "notification-user-rights-email-subject": "თქვენი მომხარებლის უფლებები შეიცვალა {{SITENAME}}-ზე",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 წამ.}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 წუთ.}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 საათ.}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 დღე}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 თვე}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 წელი}}",
+ "notification-timestamp-today": "დღეს",
+ "notification-inbox-filter-read": "კითხვა",
+ "notification-inbox-filter-unread": "წაუკითხავი",
+ "notification-inbox-filter-all": "ყველა",
+ "echo-email-body-default": "თქვენგაქვთ ახალიშეტყობინება {{SITENAME}}-ზე:\n\n$1",
"echo-notification-alert-text-only": "მოხსენება",
- "echo-notification-message-text-only": "შეტყობინება",
+ "echo-notification-notice-text-only": "შეტყობინებები",
"echo-overlay-link": "შეტყობინება",
"echo-overlay-title": "<b>შეტყობინებები</b>",
"echo-mark-all-as-read": "მონიშნეთ ყველა, როგორც წაკითხული",
"echo-date-today": "დღეს",
"echo-date-yesterday": "გუშინ",
- "echo-email-batch-bullet": "•"
+ "echo-email-batch-bullet": "•",
+ "echo-email-batch-link-text-view-all-notifications": "ყველა შეტყობინების ნახვა"
}
diff --git a/Echo/i18n/kab.json b/Echo/i18n/kab.json
new file mode 100644
index 00000000..3563fc2d
--- /dev/null
+++ b/Echo/i18n/kab.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Belkacem77"
+ ]
+ },
+ "prefs-newmessageindicator": "Anammal n yizen amaynut",
+ "echo-new-messages": "Ɣur-k iznan imaynuten",
+ "tooltip-pt-notifications-alert": "Ilɣa-ik",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Iseqdacen imaynuten",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Seḥbes}} aḍfaṛ n irmuden imaynuten di \"$1\"",
+ "notification-link-text-view-message": "Sken izen"
+}
diff --git a/Echo/i18n/kbp.json b/Echo/i18n/kbp.json
new file mode 100644
index 00000000..c646c3c1
--- /dev/null
+++ b/Echo/i18n/kbp.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gnangbade"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "Ño-kubusi",
+ "tooltip-pt-notifications-message": "Ñɔ-tɔm kɩmamatʋ"
+}
diff --git a/Echo/i18n/khw.json b/Echo/i18n/khw.json
index fdcd9ebc..d99291cc 100644
--- a/Echo/i18n/khw.json
+++ b/Echo/i18n/khw.json
@@ -4,5 +4,6 @@
"Rachitrali"
]
},
- "tooltip-pt-notifications": "تہ نوٹیفیکیشن"
+ "tooltip-pt-notifications-alert": "الرٹس",
+ "tooltip-pt-notifications-message": "پیغامات"
}
diff --git a/Echo/i18n/kk-cyrl.json b/Echo/i18n/kk-cyrl.json
index 2460a460..f3643783 100644
--- a/Echo/i18n/kk-cyrl.json
+++ b/Echo/i18n/kk-cyrl.json
@@ -1,7 +1,8 @@
{
"@metadata": {
"authors": [
- "Arystanbek"
+ "Arystanbek",
+ "Macofe"
]
},
"echo-desc": "Оқиғалар мен хабарламалар туралы қатысушыларға ескерту \nжүйесі",
@@ -9,6 +10,7 @@
"prefs-emailsettings": "Е-пошта баптаулары",
"prefs-displaynotifications": "Көрсету бапталымдары",
"prefs-echosubscriptions": "Бұл оқиғалар туралы маған хабарландыр",
+ "prefs-echocrosswiki": "Уикиаралық ескетпелер",
"prefs-newmessageindicator": "Жаңа хабарлама көрсеткіші",
"echo-pref-send-me": "Маған жіберу:",
"echo-pref-send-to": "Жіберу:",
@@ -16,12 +18,17 @@
"echo-pref-web": "Веб",
"echo-pref-email": "Е-поштаңыз",
"echo-pref-email-frequency-never": "Ешбір е-пошта хабарландыруларын маған жіберме",
+ "echo-pref-email-frequency-immediately": "Жеке хабарландырулар олар келіп ретінде",
"echo-pref-email-frequency-daily": "Хабарландырулардың күнделікті түйіндемесі",
"echo-pref-email-frequency-weekly": "Хабарландырулардың апталық түйіндемесі",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Қалыпты мәтін",
+ "echo-pref-cross-wiki-notifications": "Басқа уикилерден ескертпелерді көрсету",
"echo-pref-new-message-indicator": "Құралдар үстелімде талқылау беттегі хабарламалар көрсеткішін көрсету",
+ "echo-pref-beta-feature-cross-wiki-message": "Кеңейтілген хабарландырулар",
+ "echo-pref-beta-feature-cross-wiki-description": "Ескетпелерді қарау және басқару бұрыңғыдан да жеңілірек. Сіз басқа уикилерден хабарламалар көруге мүмкіндік береді, ол уикиаралық хабарландыруларын қамтиды.",
"echo-learn-more": "Көбірек білу",
+ "echo-log": "Барлығы көре алатын журнал",
"echo-new-messages": "Сізге жаңа хабарламалар келді",
"echo-category-title-edit-user-talk": "Талқылау бетіңіздегі {{PLURAL:$1|хабарлама|хабарламалар}}",
"echo-category-title-article-linked": "Бет {{PLURAL:$1|сілтемесі|сілтемелері}}",
@@ -30,69 +37,90 @@
"echo-category-title-other": "{{PLURAL:$1|Басқа}}",
"echo-category-title-system": "{{PLURAL:$1|Жүйе}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Қатысушы құқықтары өзгертуі|Қатысушы құқықтары өзгертулері}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Басқа қатысушыдан келген электрондық хат|Басқа қатысушылардан келген электрондық хаттар}}",
"echo-pref-tooltip-edit-user-talk": "Әлдекім талқылау бетіме хабарлама немесе жауап жазса маған ескерт.",
"echo-pref-tooltip-article-linked": "Әлдекім мен бастаған бетті мақала бетінде сілтеген кезде маған ескерт.",
"echo-pref-tooltip-reverted": "Әлдекім жоққа шығару несесе шегіндіру құралын қолданып мен жасаған өңдемелерді қайтарған кезде маған ескерт.",
"echo-pref-tooltip-mention": "Әлдекім менің қатысушы бетімді сілтеген кезде маған ескерт.",
"echo-pref-tooltip-user-rights": "Әлдекім менің қатысушы құқықтарымды өзгерткен кезде маған ескерт",
- "echo-no-agent": "[Ешкім]",
- "echo-no-title": "[Бет жоқ]",
+ "echo-pref-tooltip-emailuser": "Маған электронды хат жібергенде маған ескерт.",
"echo-error-no-formatter": "Ескертпелер үшін форматтау анықталмайды.",
"notifications": "Хабарландырулар",
"tooltip-pt-notifications-alert": "{{GENDER:|Сіздегі}} дабылдар",
- "tooltip-pt-notifications-message": "Сіздегі хабарламалар",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Жаңа қатысушылар",
"echo-specialpage": "Хабарландырулар",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|$1 ескертпе|$1 ескертпе}}",
+ "notificationsmarkread-legend": "Ескертпені оқылды деп белгілеу",
"echo-anon": "Ескертпелерді қабылдау үшін [$1 тіркеліңіз] немесе [$2 кіріңіз].",
"echo-none": "Сізде ескертпелер жоқ.",
"echo-more-info": "Көбірек ақпарат",
"echo-feedback": "Кері байланыс",
+ "echo-api-failure": "Хабарлама алынбады. Қайталап көріңіз (Қате: $1)",
+ "echo-api-failure-cross-wiki": "Қашықтағы домен қатынастан бас тартты.",
+ "echo-notification-placeholder": "Мұнда ескертпелер жоқ.",
+ "echo-notification-loginrequired": "Ескертпелерді көру үшін кіруіңіз керек.",
+ "echo-notification-popup-loginrequired": "Ескертпелерді көру үшін кіріңіз.",
+ "echo-notification-markasread": "Оқылды деп белгілеу",
+ "echo-notification-markasunread": "Оқылмаған деп белгілеу",
+ "echo-notification-markasread-tooltip": "Оқылды деп белгілеу",
+ "notification-link-text-expand-all": "Барлығын көру",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 Дабылды|$1 Дабылды}} көру",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 ескертпені|$1 ескертпені}} көру",
+ "notification-link-text-collapse-all": "Жиыру",
"notification-link-text-view-message": "Хабарламаны көру",
"notification-link-text-view-mention": "Еске салуды көру",
- "notification-link-text-view-changes": "Өзгерістерді көру",
+ "notification-link-text-view-changes": "Өзгерістерді {{GENDER:$1|көру}}",
"notification-link-text-view-page": "Бетті көру",
+ "notification-header-edit-user-talk": "$1 <strong>талқылау {{GENDER:$3|бетіңізге}}</strong> хабарлама {{GENDER:$2|қалдырды}}.",
+ "notification-header-edit-user-talk-with-section": "$1 <strong>талқылау {{GENDER:$3|бетіңіздегі}}</strong> «<strong>$4</strong>» бөліміне хабарлама {{GENDER:$2|қалдырды}}.",
+ "notification-header-page-linked": "<strong>$4</strong> дегеннен <strong>$3</strong> дегенге сілтеме жасалды.",
+ "notification-bundle-header-page-linked": "<strong>$4</strong> және {{PLURAL:$5|басқа бір беттен|басқа $5 беттен|100=басқа 99+ беттен}} <strong>$3</strong> бетіне сілтеме жасалды.",
+ "notification-link-text-what-links-here": "Бұл бетке сілтенгендер",
+ "notification-header-mention-other": "$1 <strong>$4</strong> бетінің \"<strong>$5</strong>\" бөлімінде {{GENDER:$3|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-mention-other-nosection": "$1 <strong>$4</strong> бетінде {{GENDER:$3|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-mention-user-talkpage-v2": "$1 <strong>$4 қатысушы талқылау {{GENDER:$5|бетінің}}</strong> \"<strong>$6</strong>\" бөлімінде {{GENDER:$3|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-mention-user-talkpage-nosection": "$1 <strong>$4 қатысушы талқылау {{GENDER:$5|бетінде}} {{GENDER:$3|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-mention-agent-talkpage": "$1 <strong>{{GENDER:$2|оның|оның|олардың}} талқылау бетінің</strong> \"<strong>$4</strong>\" бөлімінде {{GENDER:$3|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 <strong>{{GENDER:$2|оның|оның|олардың}} талқылау бетінде {{GENDER:$3|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-mention-article-talkpage": "$1 <strong>$4</strong> талқылау бетінің \"<strong>$5</strong>\" бөлімінде {{GENDER:$3|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-mention-article-talkpage-nosection": "$1 <strong>$4</strong> талқылау бетінде {{GENDER:$3|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Сіздің}} қатысушы құқықтарыңыз {{GENDER:$1|өзгертілді}}. Сіз мына топқа косылдыңыз: $2",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Сіздің}} қатысушы құқықтарыңыз {{GENDER:$1|өзгертілді}}. Сіз осыдан былай мына топқа кірмейсіз: $2",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Сіздің}} қатысушы құқықтарыңыз {{GENDER:$1|өзгертілді}}. Сіз мына топқа косылдыңыз: $2. Сіз осыдан былай мына топқа кірмейсіз: $4",
+ "notification-header-welcome": "{{SITENAME}} жобасына {{GENDER:$2|қош келдіңіз}}, $1! {{GENDER:$2|Сіздің}} осында болғаныңызға қуаныштымыз.",
+ "notification-welcome-linktext": "Қош келдіңіз!",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Сіз}} қазір ғана бірінші {{GENDER:$2|өңдемеңізді}} жасадыңыз; {{GENDER:$2|сізге}} рахмет, сонымен қош келдіңіз!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Оныншы}} {{GENDER:$2|өңдемеңізді}} жасадыңыз; {{GENDER:$2|сізге}} рахмет, ары қарай жалғастыруыңызды сұраймыз!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Жүзінші}} {{GENDER:$2|өңдемеңізді}} жасадыңыз; {{GENDER:$2|сізге}} көп рахмет!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Мыңыншы}} {{GENDER:$2|өңдемеңізді}} жасадыңыз; үлкен үлесіңіз үшін {{GENDER:$2|сізге}} рахмет!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Он мыңыншы}} {{GENDER:$2|өңдемеңізді}} жасадыңыз; сондықтан {{GENDER:$2|сізге}} көп рахмет!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Жүз мыңыншы}} {{GENDER:$2|өңдемеңізді}} жасадыңыз; керемет үлесіңіз үшін {{GENDER:$2|сізге}} рахмет!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Миллионыншы}} {{GENDER:$2|өңдемеңізді}} жасадыңыз; таң қаларлық үлесіңіз үшін {{GENDER:$2|сізге}} рахмет!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Сіздің}} өңдемеңіз",
"notification-link-text-view-edit": "Өңдемені көру",
- "notification-edit-talk-page2": "[[User:$1|$1]] [[User talk:$2#$3|талқылау бетіңізге]] хабарлама {{GENDER:$1|қалдырды}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] талқылау бетіңіздегі «[[User talk:$2#$3|$4]]» бөліміне хабарлама {{GENDER:$1|қалдырды}}.",
- "notification-edit-talk-page-flyout2": "$1 [[User talk:$2#$3|талқылау бетіңізге]] хабарлама {{GENDER:$1|қалдырды}}.",
- "notification-edit-talk-page-flyout-with-section": "$1 талқылау бетіңіздегі «[[User talk:$2#$3|$4]]» бөліміне хабарлама {{GENDER:$1|қалдырды}}.",
- "notification-page-linked": "[[:$2]] [[:$3]] бетінен {{GENDER:$1|сілтенді}}. [[Special:WhatLinksHere/$2|Бұл бетке барлық сілтенгендерді көріңіз]].",
- "notification-page-linked-flyout": "[[:$2]] [[:$3]] дегеннен {{GENDER:$1|сілтенді}}.",
- "notification-add-comment2": "[[User:$1|$1]] \"$4\" талқылау бетіндегі \"[[$3|$2]]\" бөліміне {{GENDER:$1|пікір жазды}}.",
- "notification-add-talkpage-topic2": "[[$3]] бетінде [[User:$1|$1]] \"$2\" деген жаңа тақырып {{GENDER:$1|қосты}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] сізге хабарлама {{GENDER:$1|жіберді}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] талқылау бетіндегі \"[[$3#$2|$2]]\" бөліміне {{GENDER:$1|пікірін білдірді}}.",
- "notification-mention": "[[User:$1|$1]] $5 талқылау бетінің «[[:$3#$2|$4]]» бөлімінде сізді {{GENDER:$1|атап өтті}}.",
- "notification-mention-flyout": "$1 $5 талқылау бетінің «[[:$3#$2|$4]]» бөлімінде сізді {{GENDER:$1|атап өтті}}.",
- "notification-mention-nosection": "[[User:$1|$1]] [[:$3|$2 талқылау бетінде]] сізді {{GENDER:$1|атап өтті}}.",
- "notification-mention-nosection-flyout": "$1 [[:$3|$2 талқылау бетінде]] сізді {{GENDER:$1|атап өтті}}.",
- "notification-user-rights": "Сіздің қатысушы құқықтарыңызды [[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|өзгертті}}]]. $2. [[Special:ListGroupRights|Толығырақ біліңіз]]",
- "notification-user-rights-flyout": "Сіздің қатысушы құқықтарыңызды $1 {{GENDER:$1|өзгертті}}. $2. [[Special:ListGroupRights|Қатысушы құқықтары туралы көбірек біліңіз]]",
- "notification-user-rights-add": "Қазір {{PLURAL:$2|бұл топтың|бұл топтардың}} мүшесісіз: $1",
- "notification-user-rights-remove": "Сіз {{PLURAL:$2|бұл топтың|бұл топтың}} көптен бергі мүшесі емессіз: $1",
- "notification-new-user": "$1 {{SITENAME}} сайтына қош келдіңіз! Сіз осында болғаныңызға біз қуаныштымыз.",
- "notification-reverted2": "Сіздің {{PLURAL:$4|[[:$2]] бетіндегі өңдемеңізді|[[:$2]] бетіндегі өңдемелеріңізді}} [[User:$1|$1]] {{GENDER:$1|жоққа шығарды}}. $3",
- "notification-reverted-flyout2": "Сіздің {{PLURAL:$4|$2 бетіндегі өңдемеңізді|$2 бетіндегі өңдемелеріңізді}} $1 есімді қатысушы {{GENDER:$1|жоққа шығарыды}}. $3",
+ "notification-header-reverted": "Сіздің {{PLURAL:$4|<strong>$3</strong> бетіндегі өңдемеңіз|<strong>$3</strong> бетіндегі өңдемелеріңіз}} {{GENDER:$2|жоққа шығарылды}}.",
+ "notification-header-emailuser": "$1 сізге электронды хат {{GENDER:$2|жіберді}}.",
"notification-edit-talk-page-email-subject2": "$1 {{SITENAME}} сайтында сізге хабарлама {{GENDER:$1|қалдырды}}",
- "notification-edit-talk-page-email-batch-body2": "$1 талқылау бетіңізге хабарлама {{GENDER:$1|қалдырды}}.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 талқылау бетіңіздегі «$2» бөліміне хабарлама {{GENDER:$1|қалдырды}}.",
"notification-page-linked-email-subject": "{{SITENAME}} сайтында сіз бастаған бет сілтенді",
- "notification-page-linked-email-batch-body": "$2 $3 дегеннен {{GENDER:$1|сілтенді}}.",
"notification-reverted-email-subject2": "{{SITENAME}} сайтында сіздің {{PLURAL:$3|өңдемеңіз|өңдемелеріңіз}}{{GENDER:$1|қайтарылды}}",
- "notification-reverted-email-batch-body2": "Сіздің {{PLURAL:$3|$2 бетіндегі өңдемеңізді|$2 бетіндегі өңдемелеріңізді}} $1 есімді қатысушы {{GENDER:$1|жоққа шығарыды}}.",
- "notification-mention-email-subject": "{{SITENAME}} сайтында $1 сізді {{GENDER:$1|атап өтті}}",
- "notification-mention-email-batch-body": "$1 $4 талқылау бетінің «$3» бөлімінде сізді {{GENDER:$1|атап өтті}}.",
- "notification-mention-nosection-email-batch-body": "$1 $2 талқылау бетінде сізді {{GENDER:$1|атап өтті}}.",
+ "notification-mention-email-subject": "{{SITENAME}} сайтында $1 сізді {{GENDER:$2|атап өтті}}",
"notification-user-rights-email-subject": "{{SITENAME}} сайтында сіздің қатысушы құқықтарыңыз өзгерілді.",
- "notification-user-rights-email-batch-body": "Сіздің қатысушы құқықтарыңызды $1 {{GENDER:$1|өзгертті}}. $2.",
- "echo-email-subject-default": "{{SITENAME}} сайтында жаңа ескертпелер",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 м}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 м}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 сағ}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 күн}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 ай}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 жыл}}",
+ "notification-timestamp-today": "Бүгін",
+ "notification-timestamp-yesterday": "Кеше",
+ "notification-inbox-filter-read": "Оқылған",
+ "notification-inbox-filter-unread": "Оқылмаған",
+ "notification-inbox-filter-all": "Барлығы",
"echo-email-body-default": "{{SITENAME}} сайтында сіз жаңа ескертпелер алдыңыз:\n\n$1",
- "echo-email-batch-body-default": "Сізге жаңа ескертпелер келді.",
"echo-email-footer-default": "$2\n\nБақылау э-пошта арқылы жіберілсе, бапталымдарыңызды тексеріп шығыңыз:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Бақылау э-почта арқылы жіберілсе, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">бапталымдарыңызды тексеріңіз</a>.<br />\n\n$1",
"echo-notification-alert": "{{PLURAL:$1|Ескертпе ($1)|Ескертпе ($1)|100=Ескертпе (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Хабарламалар ($1)|Хабарламалар ($1)|100=Хабарламалар (99+)}}",
"echo-notification-alert-text-only": "Дабылдар",
- "echo-notification-message-text-only": "Хабарламалар",
"echo-overlay-link": "Барлық ескертпелер",
"echo-overlay-title": "<b>Ескертпелер</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Ескертпелер}}</b> (оқылмаған $2 ескертпенің $1 ескертпесі көрселуде)",
@@ -100,22 +128,11 @@
"echo-date-today": "Бүгін",
"echo-date-yesterday": "Кеше",
"echo-load-more-error": "Қосымша нәтижелерді алуда қателік кездесті.",
- "notification-edit-talk-page-bundle": "$1 және {{PLURAL:$4|басқа|басқа}} $3 қатысушы [[User talk:$2|талқылау бетіңізге]] хабарлама {{GENDER:$1|қалдырды}}.",
- "notification-page-linked-bundle": "$2 $3 және басқа $4 {{PLURAL:$5|беттен|беттен}} {{GENDER:$1|сілтенді}}. [[Special:WhatLinksHere/$2|Бұл бетке барлық сілтенгендерді көріңіз]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 және {{PLURAL:$3|басқа|басқа}} $2 қатысушы талқылау бетіңізге хабарлама {{GENDER:$1|қалдырды}}.",
- "notification-page-linked-email-batch-bundle-body": "$2 $3 және басқа $4 {{PLURAL:$5|беттен|беттен}} {{GENDER:$1|сілтенді}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{GENDER:$3|Талқылау бетіңіздегі}} {{PLURAL:$1|бір жаңа хабарлама|басқа $1 хабарлама|100=басқа 99+ хабарлама}}.",
"echo-email-batch-subject-daily": "Сізге {{SITENAME}} сайтында {{PLURAL:$2|жаңа ескертпе|жаңа ескертпелер}} келді",
"echo-email-batch-subject-weekly": "Сізге осы аптада {{SITENAME}} сайтында {{PLURAL:$2|жаңа ескертпе|жаңа ескертпелер}} келді",
"echo-email-batch-body-intro-daily": "Сәлем $1, \nБұл {{SITENAME}} жобасындағы бүгінгі сіз үшін іс-әрекеттер түйіндемесі.",
"echo-email-batch-body-intro-weekly": "Сәлем $1, \nБұл {{SITENAME}} жобасындағы осы аптадағы сіз үшін іс-әрекеттер түйіндемесі.",
"echo-email-batch-link-text-view-all-notifications": "Барлық ескертпелерді көру",
- "echo-rev-deleted-text-view": "Бұл бет нұсқасы жасырылған",
- "apihelp-echomarkread-description": "Қазіргі қатысушы үшін ескертпелер оқылған деп белгілеу",
- "apihelp-echomarkread-param-sections": "Бөлімдер тізімін оқылды деп белгілеу.",
- "apihelp-echomarkread-example-1": "8 ескертпені оқылды деп белгілеу",
- "apihelp-echomarkread-example-2": "Барлық ескертпелерді оқылды деп белгілеу",
- "apihelp-echomarkseen-description": "Қазіргі қатысушы үшін ескертпелер көрілген деп белгілеу",
- "apihelp-echomarkseen-example-1": "Ескертпелердің барлық түрін көрдім деп белгілеу",
- "apihelp-query+notifications-example-1": "Ескертпелер тізімі",
- "apihelp-query+notifications-example-2": "Санымен көрсетілген, бөлімі бойынша топталған ескертпелер сан"
+ "notification-header-foreign-alert": "{{PLURAL:$5|Басқа уикиден|Басқа $5 уикиден}} көбірек ескертпелер"
}
diff --git a/Echo/i18n/km.json b/Echo/i18n/km.json
index 2a6e8ae0..c436bf04 100644
--- a/Echo/i18n/km.json
+++ b/Echo/i18n/km.json
@@ -6,6 +6,7 @@
},
"prefs-echo": "ការជូនដំណឹង",
"prefs-emailsettings": "ជម្រើសទាក់ទិននឹងអ៊ីមែល",
+ "prefs-echosubscriptions": "ជូនដំណឹងដល់ខ្ញុំពីព្រឹត្តិការណ៍ខាងក្រោមនេះ",
"echo-pref-send-me": "ផ្ញើមកខ្ញុំនូវ៖",
"echo-pref-send-to": "ផ្ញើទៅកាន់៖",
"echo-pref-email-format": "ទម្រង់អ៊ីមែល៖",
@@ -19,6 +20,7 @@
"echo-learn-more": "ស្វែងយល់បន្ថែម",
"echo-new-messages": "អ្នកមានសារថ្មីៗ",
"notifications": "ការជូនដំណឹង",
+ "tooltip-pt-notifications-alert": "ការជូនដំណឹង{{GENDER:|មកអ្នក}}",
"echo-anon": "ដើម្បីទទួលបានការជូនដំណឺង សូម[$1 បង្កើតគណនី] ឬ [$2 កត់ឈ្មោះចូល]។",
"echo-email-footer-default": "$2\n\nដើម្បីកំណត់អ៊ីមែលដែលយើងត្រូវផ្ញើអោយអ្នក សូមពិនិត្យចំណង់ចំណូលសិត្តរបស់អ្នក៖\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-overlay-link": "ការជូនដំណឹងទាំងអស់"
diff --git a/Echo/i18n/kn.json b/Echo/i18n/kn.json
index f18c8903..3de081ce 100644
--- a/Echo/i18n/kn.json
+++ b/Echo/i18n/kn.json
@@ -23,7 +23,6 @@
"echo-pref-email-frequency-weekly": "ಪ್ರತಿ ವಾರದ ಸೂಚನೆಗಳ ಸಾರಾಂಶ",
"echo-pref-email-format-html": "ಎಚ್‌ಟಿಎಂಎಲ್",
"echo-pref-email-format-plain-text": "ಸಾದಾ ಪಠ್ಯ",
- "echo-pref-notify-show-link": "ನನ್ನ ಸಾಧನಪಟ್ಟಿಯಲ್ಲಿ ಸೂಚನೆಗಳನ್ನು ತೋರಿಸಿ",
"echo-pref-new-message-indicator": "ನನ್ನ ಸಾಧನಪಟ್ಟಿಯಲ್ಲಿ ಚರ್ಚಾಪುಟದ ಸಂದೇಶಸೂಚನೆ ತೋರಿಸಿ",
"echo-learn-more": "ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ",
"echo-new-messages": "ನಿಮಗೆ ಹೊಸ ಸಂದೇಶಗಳಿವೆ",
@@ -37,13 +36,8 @@
"echo-pref-tooltip-article-linked": "ನಾನು ತಯಾರಿಸಿದ ಲೇಖನಪುಟಕ್ಕೆ ಯಾರಾದರೂ ಕೊಂಡಿ ನೀಡಿದರೆ ನನಗೆ ತಿಳಿಸಿ",
"echo-pref-tooltip-reverted": "ನಾನು ಮಾಡಿದ ಸಂಪಾದನೆಯನ್ನು ಯಾರಾದರು ಹಿಂದಿನಂತೆ ಮಾಡಿದರೆ ನನಗೆ ತಿಳಿಸಿ",
"echo-pref-tooltip-mention": "ನನ್ನ ಸದಸ್ಯ ಪುಟಕ್ಕೆ ಯಾರಾದರು ಯಾವುದಾದರು ಚರ್ಚಾಪುಟದಿಂದ ಕೊಂಡಿ ನೀಡಿದರೆ ನನಗೆ ತಿಳಿಸಿ",
- "echo-no-agent": "[ಯಾರೂ ಇಲ್ಲ]",
- "echo-no-title": "[ಯಾವುದೇ ಪುಟ ಇಲ್ಲ]",
"echo-error-no-formatter": "ಸೂಚನೆಗಳಿಗೆ ಯಾವುದೇ ನಮೂನೆ ನಿರ್ಧರಿಸಿಲ್ಲ",
- "echo-error-preference": "ದೋಷ: ಬಳಕೆದಾರ ಪ್ರಾಶಸ್ತ್ಯಗಳನ್ನು ನಿಗದಿ ಮಾಡಲು ಆಗಲಿಲ್ಲ",
- "echo-error-token": "ದೋಷ: ಬಳಕೆದಾರ ಟೋಕನ್ ಮರಳಿ ಪಡೆಯಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ",
"notifications": "ಸೂಚನೆಗಳು",
- "tooltip-pt-notifications": "ನಿಮ್ಮ ಸೂಚನೆಗಳು",
"echo-specialpage": "ಸೂಚನೆಗಳು",
"echo-anon": "ಸೂಚನೆಗಳನ್ನು ಸ್ವೀಕರಿಸಲು [ಖಾತೆ ಸೃಷ್ಟಿಸಿ $1] ಅಥವಾ [ಲಾಗಿನ್ $2]",
"echo-none": "ನಿಮಗೆ ಯಾವುದೇ ಸೂಚನೆಗಳಿಲ್ಲ",
@@ -54,13 +48,9 @@
"notification-link-text-view-changes": "ಬದಲಾವಣೆ ನೋಡಿ",
"notification-link-text-view-page": "ಪುಟ ನೋಡಿ",
"notification-link-text-view-edit": "ಸಂಪಾದನೆ ನೋಡಿ",
- "notification-new-user": "{{SITENAME}} ಕ್ಕೆ ಸುಸ್ವಾಗತ, $1! ನೀವು ಇಲ್ಲಿ ಬಂದಿದ್ದು ಸಂತಸ ತಂದಿತು",
"notification-page-linked-email-subject": "ನಿಮ್ಮ ಪುಟವು {{SITENAME}} ಜಾಲತಾಣಕ್ಕೆ ಸಂಪರ್ಕಿಸಲ್ಪಟ್ಟಿದೆ",
"notification-user-rights-email-subject": "{{SITENAME}} ಜಾಲತಾಣದಲ್ಲಿ ನಿಮ್ಮ ಬಳಕೆದಾರ ಹಕ್ಕುಗಳನ್ನು ಬದಲಿಸಲಾಗಿದೆ",
- "echo-email-subject-default": "{{SITENAME}} ಜಾಲತಾಣದಲ್ಲಿ ಹೊಸ ಸೂಚನೆ ಇದೆ",
"echo-email-body-default": "{{SITENAME}} ಜಾಲತಾಣದಲ್ಲಿ ನಿಮಗೆ ಈ ಸೂಚನೆ ಇದೆ: $1",
- "echo-email-batch-body-default": "ನಿಮಗೆ ಹೊಸ ಸೂಚನೆ ಇದೆ.",
- "echo-email-footer-default-html": "ನಿಮಗೆ ನಾವು ಯಾವ ಇಮೈಲ್‌ಗಳನ್ನು ಕಳುಹಿಸಬಹುದೆಂಬುದನ್ನು ನಿಯಂತ್ರಿಸಲು, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">ನಿಮ್ಮ ಪ್ರಾಶಸ್ತ್ಯಗಳನ್ನು ಪರಿಶೀಲಿಸಿ</a>.<br /> $1",
"echo-overlay-link": "ಎಲ್ಲ ಸೂಚನೆಗಳು",
"echo-overlay-title": "<b>ಸೂಚನೆಗಳು</b>",
"echo-overlay-title-overflow": "<b>ಸೂಚನೆಗಳು</b> ($2 ರಲ್ಲಿ $1 ಓದದವುಗಳನ್ನು ತೋರಿಸಲಾಗುತ್ತಿದೆ)",
@@ -70,6 +60,5 @@
"echo-load-more-error": "ಹೆಚ್ಚು ಫಲಿತಾಂಶಗಳನ್ನು ಪಡೆಯುವಾಗ ದೋಷವೊಂದು ಆಯಿತು",
"echo-email-batch-body-intro-daily": "ನಮಸ್ಕಾರ $1,\n{{SITENAME}} ಜಾಲತಾಣದಲ್ಲಿ ಇಂದು ನಡೆದ ಎಲ್ಲ ಪ್ರಕ್ರಿಯೆಗಳ ಸಾರಾಂಶ ನಿಮಗಾಗಿ ಇಲ್ಲಿದೆ.",
"echo-email-batch-body-intro-weekly": "ನಮಸ್ಕಾರ $1,\n{{SITENAME}} ಜಾಲತಾಣದಲ್ಲಿ ಈ ವಾರ ನಡೆದ ಎಲ್ಲ ಪ್ರಕ್ರಿಯೆಗಳ ಸಾರಾಂಶ ನಿಮಗಾಗಿ ಇಲ್ಲಿದೆ.",
- "echo-email-batch-link-text-view-all-notifications": "ಎಲ್ಲ ಸೂಚನೆಗಳನ್ನು ನೋಡಿ",
- "echo-rev-deleted-text-view": "ಈ ಪುಟದ ಪರಿಷ್ಕರಣೆಯನ್ನು ಹತ್ತಿಕ್ಕಲಾಗಿದೆ"
+ "echo-email-batch-link-text-view-all-notifications": "ಎಲ್ಲ ಸೂಚನೆಗಳನ್ನು ನೋಡಿ"
}
diff --git a/Echo/i18n/ko.json b/Echo/i18n/ko.json
index c590ea89..097d75f6 100644
--- a/Echo/i18n/ko.json
+++ b/Echo/i18n/ko.json
@@ -10,15 +10,23 @@
"아라",
"Revi",
"IRTC1015",
- "Hwangjy9"
+ "Hwangjy9",
+ "HDNua",
+ "Bluemersen",
+ "Ykhwong",
+ "Jonghaya",
+ "Ellif",
+ "렌즈"
]
},
"echo-desc": "이벤트와 메시지를 사용자에게 알리는 시스템",
"prefs-echo": "알림",
- "prefs-emailsettings": "이메일 설정",
- "prefs-displaynotifications": "표시 설정",
- "prefs-echosubscriptions": "다음 경우에 알림",
+ "prefs-emailsettings": "이메일 옵션",
+ "prefs-displaynotifications": "표시 옵션",
+ "prefs-echosubscriptions": "다음의 경우에 내게 알림",
+ "prefs-echocrosswiki": "여러 위키의 알림",
"prefs-newmessageindicator": "새 메시지 표시기",
+ "prefs-blocknotificationslist": "알림에서 제외된 사용자",
"echo-pref-send-me": "다음 방식으로 보내기:",
"echo-pref-send-to": "다음 주소로 보내기:",
"echo-pref-email-format": "이메일 형식:",
@@ -30,96 +38,167 @@
"echo-pref-email-frequency-weekly": "매주 알림 요약",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "일반 텍스트",
+ "echo-pref-cross-wiki-notifications": "다른 위키의 알림을 보기",
+ "echo-pref-notifications-blacklist": "이 사용자들에게서 오는 알림을 표시하지 않습니다. ([[mw:Help:Notifications#mute|더 알아보기]])",
"echo-pref-new-message-indicator": "내 도구 모음에 토론 문서 메시지 표시기 보이기",
+ "echo-pref-beta-feature-cross-wiki-message": "향상된 알림",
+ "echo-pref-beta-feature-cross-wiki-description": "알림을 더 쉽게 확인하고 정리합니다. 위키 간 알림 기능이 포함되어, 다른 위키에서의 메시지를 볼 수 있습니다. (주어진 위키에서 다른 위키의 알림을 받으려면 해당 위키에서 베타 기능을 활성화해야 합니다.)",
"echo-learn-more": "더 알아보기",
+ "echo-log": "공개 기록",
"echo-new-messages": "새 메시지가 있습니다",
"echo-category-title-edit-user-talk": "토론 문서 {{PLURAL:$1|메시지}}",
"echo-category-title-article-linked": "문서 {{PLURAL:$1|링크}}",
"echo-category-title-reverted": "편집이 {{PLURAL:$1|되돌려짐}}",
"echo-category-title-mention": "{{PLURAL:$1|언급}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|언급}} 실패",
+ "echo-category-title-mention-success": "{{PLURAL:$1|언급}} 성공",
"echo-category-title-other": "{{PLURAL:$1|기타}}",
"echo-category-title-system": "{{PLURAL:$1|시스템}}",
- "echo-category-title-user-rights": "{{PLURAL:$1|사용자 권한 변경}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|사용자 권한 바꾸기}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|다른 사용자로부터의 이메일}}",
"echo-pref-tooltip-edit-user-talk": "내 토론 문서에 누군가가 글이나 답글을 남길 때 내게 알립니다.",
- "echo-pref-tooltip-article-linked": "누군가가 어느 문서에서 내가 만든 문서를 링크할 때 내게 알립니다.",
- "echo-pref-tooltip-reverted": "누군가가 편집 취소나 되돌리기 도구를 사용하여 내 편집을 되돌릴 때 내게 알립니다.",
+ "echo-pref-tooltip-article-linked": "누군가가 다른 문서에서 내가 만든 문서를 링크할 때 내게 알립니다.",
+ "echo-pref-tooltip-reverted": "누군가가 편집 취소나 되돌리기 도구를 사용하여 내 편집을 되돌릴 때 내게 알림",
"echo-pref-tooltip-mention": "누군가가 내 사용자 문서를 링크할 때 내게 알립니다.",
- "echo-pref-tooltip-user-rights": "다른 사용자가 내 사용자 권한을 변경하는 경우 알립니다.",
- "echo-no-agent": "[알 수 없는 사용자]",
- "echo-no-title": "[문서 없음]",
+ "echo-pref-tooltip-mention-failure": "내가 누군가에게 언급을 보내지 못하면 내게 알립니다.",
+ "echo-pref-tooltip-mention-success": "내가 누군가에게 언급을 보내면 내게 알립니다.",
+ "echo-pref-tooltip-user-rights": "다른 사용자가 내 사용자 권한을 바꿀 때 내게 알립니다.",
+ "echo-pref-tooltip-emailuser": "누군가 나에게 이메일을 보낼 때 내게 알립니다.",
+ "echo-pref-tooltip-article-reminder": "내가 요청할 때 이 문서를 내게 알립니다.",
"echo-error-no-formatter": "알림에 대해 정의된 형식이 없습니다.",
"notifications": "알림",
- "tooltip-pt-notifications-alert": "{{GENDER:|당신}}의 알림",
- "tooltip-pt-notifications-message": "{{GENDER:|당신}}의 메시지",
+ "tooltip-pt-notifications-alert": "{{GENDER:|당신}}의 경보",
+ "tooltip-pt-notifications-notice": "{{GENDER:|당신의}} 알림",
+ "echo-displaynotificationsconfiguration": "알림 표시 설정",
+ "echo-displaynotificationsconfiguration-summary": "이 위키에서 알림이 어떻게 설정되었는지에 관한 개요입니다.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "분류별 알림",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "허용된 알림 방식",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "기본적으로 활성화됨",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "기존 사용자",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "새 사용자",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "필수 알림 방식",
"echo-specialpage": "알림",
+ "echo-specialpage-section-markread": "그룹을 읽은 것으로 표시",
+ "echo-specialpage-markasread": "알림: 읽은 것으로 표시",
+ "echo-specialpage-markasread-invalid-id": "유효하지 않은 이벤트 ID",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|알림}} $1개",
+ "echo-specialpage-pagefilters-title": "최근 활동",
+ "echo-specialpage-pagefilters-subtitle": "읽지 않은 알림 문서",
+ "notificationsmarkread-legend": "모든 알림을 읽은 것으로 표시",
"echo-anon": "알림을 받으려면 [$1 계정을 만들거나] [$2 로그인]하세요.",
"echo-none": "알림이 없습니다.",
"echo-more-info": "자세한 정보",
"echo-feedback": "피드백 남기기",
+ "echo-popup-footer-special-page-invitation": "<strong>재설계된 알림 문서를 사용해 보세요.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "새로운 모든 모양과 기능.",
+ "echo-api-failure": "알림을 받아올 수 없었습니다.",
+ "echo-api-failure-cross-wiki": "원격 도메인으로의 연결은 거부되었습니다.",
+ "echo-notification-placeholder": "알림이 없습니다.",
+ "echo-notification-placeholder-filters": "이 기준에 맞는 알림이 없습니다.",
+ "echo-notification-loginrequired": "알림을 보려면 로그인해야 합니다.",
+ "echo-notification-popup-loginrequired": "알림을 보려면 로그인하세요.",
+ "echo-notification-markasread": "읽은 것으로 표시",
+ "echo-notification-markasunread": "읽지 않은 것으로 표시",
+ "echo-notification-markasread-tooltip": "읽은 것으로 표시",
+ "echo-notification-more-options-tooltip": "옵션 더 보기",
+ "notification-dynamic-actions-unwatch": "\"$1\"의 새로운 활동 주시를 {{GENDER:$3|해제}}",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|당신은}} 더 이상 \"$1\" 문서를 주시하지 않습니다",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|당신은}} 언제든지 [$2 이 문서]를 주시할 수 있습니다.",
+ "notification-dynamic-actions-watch": "\"$1\"의 새로운 활동을 {{GENDER:$3|팔로우}}",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|당신은}} 지금 \"$1\" 문서를 주시하고 있습니다",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|당신은}} 언제든지 [$2 이 문서]의 주시를 해제할 수 있습니다.",
+ "notification-link-text-expand-all": "펼치기",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|경보 $1개}} 보기",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|공지 $1}}개",
+ "notification-link-text-expand-all-count": "$1개의 알림을 보기",
+ "notification-link-text-collapse-all": "접기",
"notification-link-text-view-message": "메시지 보기",
"notification-link-text-view-mention": "언급된 내용 보기",
- "notification-link-text-view-changes": "차이 보기",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|언급 보기}}",
+ "notification-link-text-view-changes": "차이 {{GENDER:$1|보기}}",
"notification-link-text-view-page": "문서 보기",
+ "notification-header-edit-user-talk": "$1님이 <strong>{{GENDER:$3|당신의}} 토론 문서</strong>에 글을 {{GENDER:$2|남겼습니다}}.",
+ "notification-header-edit-user-talk-with-section": "$1님이 <strong>{{GENDER:$3|당신의}} 토론 문서</strong>의 \"<strong>$4</strong>\" 문단에 글을 {{GENDER:$2|남겼습니다}}.",
+ "notification-header-page-linked": "<strong>$4</strong>에서 <strong>$3</strong>으로 연결되는 링크가 생성되었습니다.",
+ "notification-compact-header-page-linked": "<strong>$1</strong>에서 연결되었습니다.",
+ "notification-bundle-header-page-linked": "<strong>$3</strong> 문서가 {{PLURAL:$5||$5 개의 문서|100=99개 이상의 문서}}에서 링크되었습니다.",
+ "notification-link-text-what-links-here": "이 문서로 향하는 모든 링크",
+ "notification-header-mention-other": "$1님이 <strong>$4</strong>의 \"<strong>$5</strong>\"에서 {{GENDER:$3|당신}}을 {{GENDER:$2|언급했습니다}}.",
+ "notification-header-mention-other-nosection": "$1님이 <strong>$4</strong>에서 {{GENDER:$3|당신을}} {{GENDER:$2|언급했습니다}}.",
+ "notification-header-mention-user-talkpage-v2": "$1님이 <strong>$4{{GENDER:$5|의}} 사용자 토론 문서</strong>의 \"<strong>$6</strong>\"에서 {{GENDER:$3|당신}}을 {{GENDER:$2|언급했습니다}}.",
+ "notification-header-mention-user-talkpage-nosection": "$1님이 <strong>$4{{GENDER:$5|의}} 사용자 토론 문서</strong>에서 {{GENDER:$3|당신}}을 {{GENDER:$2|언급했습니다}}.",
+ "notification-header-mention-agent-talkpage": "$1님이 <strong>$1님 자신의 사용자 토론 문서</strong>의 \"<strong>$4</strong>\"에서 {{GENDER:$3|당신}}을 {{GENDER:$2|언급했습니다}}.",
+ "notification-header-mention-agent-talkpage-nosection": "$1님이 <strong>$1님 자신의 사용자 토론 문서</strong>에서 {{GENDER:$3|당신}}을 {{GENDER:$2|언급했습니다}}.",
+ "notification-header-mention-article-talkpage": "$1님이 $4 토론 문서의 \"<strong>$5</strong>\" 문단에서 {{GENDER:$3|당신을}} {{GENDER:$2|언급했습니다}}.",
+ "notification-header-mention-article-talkpage-nosection": "$1님이 <strong>$4</strong> 토론 문서에서 {{GENDER:$3|당신을}} {{GENDER:$2|언급했습니다}}.",
+ "notification-header-mention-failure-user-unknown": "사용자를 찾을 수 없기 때문에 <strong>$3</strong>에 대한 {{GENDER:$2|당신의}} 언급은 전달되지 않았습니다.",
+ "notification-header-mention-failure-user-anonymous": "사용자가 익명이기 때문에 <strong>$3</strong>에 대한 {{GENDER:$2|당신의}} 언급은 전달되지 않았습니다.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|당신은}} $3명 이상의 {{PLURAL:$3|사용자}}를 언급하려고 했습니다. 제한을 초과한 모든 언급은 전달되지 않았습니다.",
+ "notification-header-mention-failure-bundle": "<strong>$4</strong> 토론 문서에 {{GENDER:$2|당신이 한}} {{PLURAL:$3||$3개의}} 언급은 {{PLURAL:$3|전달되지}} 않았습니다.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>사용자 이름이 존재하지 않습니다:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP는 언급할 수 없습니다:</strong> $1",
+ "notification-header-mention-success": "<strong>$3</strong>님에 대한 {{GENDER:$2|당신의}} 언급이 전달되었습니다.",
+ "notification-header-mention-success-bundle": "<strong>$4</strong> 토론 문서에 {{GENDER:$2|당신이 한}} {{PLURAL:$3|언급|$3개의 언급}}을 보냈습니다.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|언급했습니다}}:</strong> $3",
+ "notification-header-mention-status-bundle": "<strong>$4</strong> 토론 문서에서 {{GENDER:$2|당신이 한}} 언급에 대한 {{PLURAL:$3|한 개의 알림|$3개의 알림}}: {{PLURAL:$5|$5개 보내지 못함}}, {{PLURAL:$6|$6개 보냄}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|당신}}의 사용자 권한이 {{GENDER:$1|바뀌었습니다}}. 당신은 $2 권한을 부여받았습니다.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|당신}}의 사용자 권한이 {{GENDER:$1|바뀌었습니다}}. 당신은 더 이상 $2 권한을 갖고 있지 않습니다.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|당신}}의 사용자 권한이 {{GENDER:$1|바뀌었습니다}}. 당신은 $2 권한을 받았지만, $4 권한은 더 이상 갖고 있지 않습니다.",
+ "notification-header-user-rights-expiry-change": "$2 {{PLURAL:$3|그룹|그룹들}}에서의 {{GENDER:$4|귀하}}의 멤버십 유효기간이 {{GENDER:$1|변경되었습니다}}.",
+ "notification-header-welcome": "{{SITENAME}}에 오신 것을 {{GENDER:$2|환영}}합니다, $1님! 당신을 만나게 되어 기쁩니다.",
+ "notification-welcome-linktext": "환영합니다",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|}}방금 첫 번째 편집을 달성했습니다. 기여에 감사드리며, 환영합니다!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|}}방금 10번째 편집을 달성했습니다. 편집에 감사드리며, 앞으로도 좋은 기여 부탁드립니다!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|}}방금 100번째 편집을 달성했습니다. 진심으로 감사드립니다!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|}}방금 1,000번째 편집을 달성했습니다. 훌륭한 기여자가 되어주셔서 감사합니다!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|}}방금 10,000번째 편집을 달성했습니다. 진심으로 감사드립니다!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|}}방금 100,000번째 편집을 달성했습니다. 상당한 기여에 감사드립니다!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|}}방금 1,000,000번째 편집을 달성했습니다. 놀라울 정도로 대단한 기여에 감사드립니다!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|사용자}}의 편집",
"notification-link-text-view-edit": "편집 보기",
- "notification-edit-talk-page2": "[[User:$1|$1]]님이 당신의 [[User talk:$2#$3|토론 문서]]에 글을 {{GENDER:$1|남겼습니다}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]]님이 당신의 토론 문서의 \"[[User talk:$2#$3|$4]]\" 문단에 글을 {{GENDER:$1|남겼습니다}}.",
- "notification-edit-talk-page-flyout2": "$1님이 당신의 [[User talk:$2#$3|토론 문서]]에 글을 {{GENDER:$1|남겼습니다}}.",
- "notification-edit-talk-page-flyout-with-section": "$1님이 당신의 토론 문서의 \"[[User talk:$2#$3|$4]]\" 문단에 글을 {{GENDER:$1|남겼습니다}}.",
- "notification-page-linked": "[[:$2]] 문서가 [[:$3]]에 {{GENDER:$1|링크되었습니다}}. [[Special:WhatLinksHere/$2|이 문서를 가리키는 모든 링크를 봅니다]].",
- "notification-page-linked-flyout": "[[:$2]] 문서가 [[:$3]]에 {{GENDER:$1|링크되었습니다}}.",
- "notification-add-comment2": "[[User:$1|$1]]님이 \"$4\" 토론 문서의 \"[[$3|$2]]\" 문단에 {{GENDER:$1|댓글을 남겼습니다}}.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]]님이 [[$3]]에 새 주제 \"$2\"을(를) {{GENDER:$1|게시했습니다}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]]님이 당신에게 메시지를 {{GENDER:$1|보냈습니다}}: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]]님이 당신의 토론 문서의 \"[[$3#$2|$2]]\" 문단에 {{GENDER:$1|댓글을 남겼습니다}}.",
- "notification-mention": "[[User:$1|$1]]님이 $5 토론 문서의 \"[[:$3#$2|$4]]\" 문단에서 당신을 {{GENDER:$1|언급했습니다}}.",
- "notification-mention-flyout": "$1님이 $5 토론 문서의 \"[[:$3#$2|$4]]\"에서 당신을 {{GENDER:$1|언급했습니다}}.",
- "notification-mention-nosection": "[[User:$1|$1]]님이 [[:$3|$2 토론 문서]]에서 당신을 언급했습니다.",
- "notification-mention-nosection-flyout": "$1님이 [[:$3|$2 토론 문서]]에서 당신을 언급했습니다.",
- "notification-user-rights": "[[User:$1|$1]]님이 당신의 [[Special:Log/rights/$1|사용자 권한을 {{GENDER:$1|바꾸었습니다}}]]. $2. [[Special:ListGroupRights|더 알아보기]]",
- "notification-user-rights-flyout": "$1님이 당신의 사용자 권한을 {{GENDER:$1|바꾸었습니다}}. $2. [[Special:ListGroupRights|더 알아보기]]",
- "notification-user-rights-add": "당신은 이제 {{PLURAL:$2|다음 권한}}을 갖습니다: $1",
- "notification-user-rights-remove": "당신은 더 이상 {{PLURAL:$2|다음 권한}}을 갖지 않습니다: $1",
- "notification-new-user": "$1님, {{SITENAME}}에 온 것을 환영합니다! 당신이 여기에 오신 걸 매우 기쁘게 생각합니다.",
- "notification-reverted2": "{{PLURAL:$4|[[:$2]]에 대한 내 편집}}을 [[User:$1|$1]]님이 {{GENDER:$1|되돌렸습니다}}. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|$2에 대한 내 편집}}을 $1님이 {{GENDER:$1|되돌렸습니다}}. $3",
+ "notification-link-article-reminder": "문서 보기",
+ "notification-header-reverted": "당신의 {{PLURAL:$4|<strong>$3</strong>에 대한 편집}}이 {{GENDER:$2|되돌려졌습니다}}.",
+ "notification-header-emailuser": "$1님이 당신에게 이메일을 {{GENDER:$2|보냈습니다}}.",
"notification-edit-talk-page-email-subject2": "$1님이 {{SITENAME}}에서 당신에게 글을 {{GENDER:$1|남겼습니다}}",
- "notification-edit-talk-page-email-batch-body2": "$1님이 당신의 토론 문서에 글을 {{GENDER:$1|남겼습니다}}.",
"notification-edit-talk-page-email-batch-body-with-section": "$1님이 당신의 토론 문서의 \"$2\" 문단에 글을 {{GENDER:$1|남겼습니다}}.",
"notification-page-linked-email-subject": "{{SITENAME}}에서 당신이 만든 문서가 링크되었습니다",
- "notification-page-linked-email-batch-body": "$2 문서가 $3에 {{GENDER:$1|링크되었습니다}}",
"notification-reverted-email-subject2": "{{SITENAME}}의 당신의 {{PLURAL:$3|편집}}이 {{GENDER:$1|되돌려졌습니다}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|$2에 대한 내 편집}}을 $1님이 {{GENDER:$1|되돌렸습니다}}.",
- "notification-mention-email-subject": "$1님이 {{SITENAME}}에서 당신을 {{GENDER:$1|언급했습니다}}",
- "notification-mention-email-batch-body": "$1님이 $4 토론 문서의 \"$3\" 문단에서 당신을 {{GENDER:$1|언급했습니다}}.",
- "notification-mention-nosection-email-batch-body": "$1님이 $2 토론 문서에서 당신을 언급했습니다.",
+ "notification-mention-email-subject": "$1님이 {{SITENAME}}에서 {{GENDER:$2|당신을}} {{GENDER:$1|언급했습니다}}",
"notification-user-rights-email-subject": "{{SITENAME}}에서 당신의 사용자 권한이 바뀌었습니다",
- "notification-user-rights-email-batch-body": "$1님이 당신의 사용자 권한을 {{GENDER:$1|바꾸었습니다}}. $2",
- "echo-email-subject-default": "{{SITENAME}}의 새 알림",
+ "notification-timestamp-ago-seconds": "$1초 전",
+ "notification-timestamp-ago-minutes": "$1분 전",
+ "notification-timestamp-ago-hours": "$1시간 전",
+ "notification-timestamp-ago-days": "$1일 전",
+ "notification-timestamp-ago-months": "$1개월 전",
+ "notification-timestamp-ago-years": "$1년 전",
+ "notification-timestamp-today": "오늘",
+ "notification-timestamp-yesterday": "어제",
+ "notification-inbox-filter-read": "읽음",
+ "notification-inbox-filter-unread": "읽지 않음",
+ "notification-inbox-filter-all": "모두",
"echo-email-body-default": "{{SITENAME}}에 새 알림이 있습니다:\n\n$1",
- "echo-email-batch-body-default": "새 알림이 있습니다",
+ "echo-email-footer-default-html": "발송되는 메일을 관리하려면 <a href=\"$2\" style=\"text-decoration:none; color:#3868B0;\">환경 설정을 확인하세요</a>. <br />\n$1",
"echo-email-footer-default": "$2\n\n발송되는 이메일을 관리하려면, 환경 설정을 확인하세요:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "발송되는 이메일을 제어하려면, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">사용자 환경 설정을 확인하세요</a>.<br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|알림 ($1)|알림 ($1)|100=알림 (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|메시지 ($1)|메시지 ($1)|100=메시지 (99+)}}",
- "echo-notification-alert-text-only": "알림",
- "echo-notification-message-text-only": "메시지",
+ "echo-email-html-footer-with-link": "{{GENDER:$2|}}발송되는 메일을 관리하려면, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|경보 ($1)|경보 ($1)|100=경보 (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|알림 ($1)|알림 ($1)|100=알림 (99+)}}",
+ "echo-notification-alert-text-only": "경보",
+ "echo-notification-notice-text-only": "알림",
"echo-overlay-link": "모든 알림",
"echo-overlay-title": "<b>알림</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|알림}}</b> (안 읽은 알림 $2개 중 $1개)",
"echo-mark-all-as-read": "모두 읽은 것으로 표시",
+ "echo-mark-wiki-as-read": "선택한 위키에서 모든 항목을 읽은 것으로 표시: $1",
"echo-date-today": "오늘",
"echo-date-yesterday": "어제",
"echo-load-more-error": "더 많은 결과를 가져오는 동안 오류가 발생했습니다.",
- "notification-edit-talk-page-bundle": "$1님 {{PLURAL:$4|외}} $3명이 당신의 [[User talk:$2|토론 문서]]에 글을 {{GENDER:$1|남겼습니다}}.",
- "notification-page-linked-bundle": "$2 문서가 $3 문서와 다른 $4개 {{PLURAL:$5|문서}}에 {{GENDER:$1|링크되었습니다}}. [[Special:WhatLinksHere/$2|이 문서를 가리키는 모든 링크 보기]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1님과 {{PLURAL:$3|다른}} $2명의 사용자가 당신의 토론 문서에 글을 {{GENDER:$1|남겼습니다}}.",
- "notification-page-linked-email-batch-bundle-body": "$2 문서가 $3 문서와 다른 $4개 {{PLURAL:$5|문서}}에 {{GENDER:$1|링크되었습니다}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{GENDER:$3|당신}}의 토론 문서에 {{PLURAL:$1|1개의 새 메시지|$1개의 새 메시지|100=99+개의 새 메시지}}가 있습니다.",
"echo-email-batch-subject-daily": "{{SITENAME}}에서 {{PLURAL:$2|새 알림}}이 있습니다",
"echo-email-batch-subject-weekly": "이번 주에 {{SITENAME}}에서 {{PLURAL:$2|새 알림}}이 있습니다",
"echo-email-batch-body-intro-daily": "$1님 안녕하세요,\n여기에 {{SITENAME}}에 오늘의 활동 요약이 있습니다.",
"echo-email-batch-body-intro-weekly": "$1님 안녕하세요,\n여기에 {{SITENAME}}에 이번 주의 활동 요약이 있습니다.",
"echo-email-batch-link-text-view-all-notifications": "모든 알림 보기",
- "echo-rev-deleted-text-view": "이 문서의 판은 숨겨져 있습니다.",
- "apihelp-echomarkread-description": "현재 사용자의 알림을 읽은 것으로 표시",
- "apihelp-echomarkread-example-2": "모든 알림을 읽은 것으로 표시"
+ "notification-header-foreign-alert": "{{PLURAL:$5|다른 위키|$5개의 다른 위키}}의 경보 더 보기",
+ "notification-header-foreign-notice": "{{PLURAL:$5|다른 위키|$5개의 다른 위키}}의 더 많은 알림",
+ "notification-header-foreign-all": "$5개의 다른 위키로부터 알림 더 보기"
}
diff --git a/Echo/i18n/krc.json b/Echo/i18n/krc.json
index fc1e7741..ba1d4c47 100644
--- a/Echo/i18n/krc.json
+++ b/Echo/i18n/krc.json
@@ -24,11 +24,13 @@
"echo-pref-email-format-plain-text": "Тюз текст",
"echo-pref-new-message-indicator": "Адырла панелимде сюзюу бетимдеги билдириулени индикаторун кёргюз",
"echo-learn-more": "Кёбюрек бил",
+ "echo-log": "Баш журнал",
"echo-new-messages": "Джангы билдириулеринг барды",
"echo-category-title-edit-user-talk": "Сюзюу бетде {{PLURAL:$1|билдириу|билдириуле}}",
"echo-category-title-article-linked": "Бетлеге {{PLURAL:$1|джибериу|джибериуле}}",
"echo-category-title-reverted": "Тюрлендириулени {{PLURAL:$1|ызына алыу|ызына алыула}}",
"echo-category-title-mention": "{{PLURAL:$1|сагъыныу|сагъыныула}}",
+ "echo-category-title-mention-failure": "Джатишимсиз {{PLURAL:$1|сагъыныу|сагъыныула}}",
"echo-category-title-other": "{{PLURAL:$1|башха}}",
"echo-category-title-system": "{{PLURAL:$1|Система}}",
"echo-category-title-user-rights": "къошулуучуну хакъларын {{PLURAL:$1|тюрлендириу|тюрлендириуле}}",
@@ -37,64 +39,44 @@
"echo-pref-tooltip-reverted": "Ким болса да, ызына алыу неда дженгил къайтарыу функция бла мени тюрлендириуюмю ызына алса, меннге билдир.",
"echo-pref-tooltip-mention": "Ким болса да, къайсы болса да сюзюу бетде мени къошулуучу бетиме джибериу салса, меннге билдир.",
"echo-pref-tooltip-user-rights": "Мени къошулуучу хакъларыма ким болса да тюрлендирсе, билдир",
- "echo-no-agent": "[Киши да]",
- "echo-no-title": "[Бет джокъду]",
"echo-error-no-formatter": "Билдириу ючюн форматланыу белгиленмегенди.",
"notifications": "Билдириуле",
"tooltip-pt-notifications-alert": "{{GENDER:|Билдириуле}}",
- "tooltip-pt-notifications-message": "{{GENDER:|Джазылгъанла}}",
"echo-specialpage": "Билдириуле",
"echo-anon": "Билдириуле алыр ючюн, [$1 тергеу джазыу къурагъыз] неда [$2 системагъа киригиз].",
"echo-none": "Билдириуюгюз болмагъанды.",
"echo-more-info": "Толу билги",
"echo-feedback": "Ызына билдириу",
+ "echo-popup-footer-special-page-invitation": "<strong>Билдириулени джангыргъан бетине багъа бичигиз.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Джангы дизайн эм функцияла.",
"notification-link-text-view-message": "Билдириуню кёр",
"notification-link-text-view-mention": "Сагъыныуну кёр",
"notification-link-text-view-changes": "Тюрлениулени кёр",
"notification-link-text-view-page": "Бетни кёр",
"notification-link-text-view-edit": "Тюрлендириуню кёр",
- "notification-edit-talk-page2": "[[User:$1|$1]], [[User talk:$2#$3|сюзюу бетигизде]] билдириу {{GENDER:$1|къойду}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]], сюзюу бетигизде (\"[[User talk:$2#$3|$4]]\") билдириу {{GENDER:$1|къойду}}.",
- "notification-edit-talk-page-flyout2": "$1, [[User talk:$2#$3|сюзюу бетигизде]] билдириу {{GENDER:$1|къойду}}.",
- "notification-edit-talk-page-flyout-with-section": "$1, сюзюу бетигизде (\"[[User talk:$2#$3|$4]]\") билдириу {{GENDER:$1|къойду}}.",
- "notification-page-linked": "[[:$2]], [[:$3]] бла {{GENDER:$1|байламлы}} эди. [[Special:WhatLinksHere/$2|Бу бетге бары джибериулеге къарагъыз]].",
- "notification-page-linked-flyout": "[[:$2]], [[:$3]] бла {{GENDER:$1|байламлы}} эди.",
- "notification-add-comment2": "[[User:$1|$1]], \"$4\" сюзюу бетдеги \"[[$3|$2]]\" темада комментарий {{GENDER:$1|къойду}}.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]], [[$3]] бетде \"$2\" деген джангы теманы {{GENDER:$1|ачды}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]], сизге билдириу {{GENDER:$1|джиберди}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]], сизни сюзюу бетигиздеги \"[[$3#$2|$2]]\" темада комментарий {{GENDER:$1|къойду}}.",
- "notification-mention": "[[User:$1|$1]], $5 сюзюу бетинде (\"[[:$3#$2|$4]]\") сизни {{GENDER:$1|сагъынды}}.",
- "notification-mention-flyout": "$1, $5 сюзюу бетинде (\"[[:$3#$2|$4]]\") сизни {{GENDER:$1|сагъынды}}.",
- "notification-mention-nosection": "[[User:$1|$1]] сизни [[:$3|сюзюу бетде $2]] {{GENDER:$1|сагъынды}}.",
- "notification-mention-nosection-flyout": "$1 сизни [[:$3|$2 сюзюу бетде]] {{GENDER:$1|сагъынды}}.",
- "notification-user-rights": "Къошулуучу хакъларыгъыз [[User:$1|$1]] джанындан [[Special:Log/rights/$1|{{GENDER:$1|тюрлендирилди}}]]. $2. [[Special:ListGroupRights|Толуракъ билги]]",
- "notification-user-rights-flyout": "Къошулуучу хакъларыгъызны $1 {{GENDER:$1|тюрлендирди}}. $2. [[Special:ListGroupRights|Толуракъ билги]]",
- "notification-user-rights-add": "Энди сиз {{PLURAL:$2|бу къауумгъа|бу къауумлагъа}} киресиз: $1",
- "notification-user-rights-remove": "Энди сиз {{PLURAL:$2|бу къауумгъа|бу къауумлагъа}} кирмейсиз: $1",
- "notification-new-user": "{{SITENAME}} сайтха хош келигиз, $1! Сизни былайгъа келгенигизге къууандыкъ.",
- "notification-reverted2": "[[User:$1|$1]], {{PLURAL:$4|[[:$2]] бетде сизни тюрлендириуюгюзню|[[:$2]] бетде сизни тюрлендириулеригизни}} {{GENDER:$1|ызына алды}}. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|$2 бетде сизни тюрлендириуюгюзню|$2 бетде сизни тюрлендириулеригизни}} $1 {{GENDER:$1|ызына алды}}. $3",
+ "notification-header-reverted": "{{PLURAL:$4|$3 бетде сизни тюрлендириуюгюзню|$3 бетде сизни тюрлендириулеригизни}} $1 {{GENDER:$2|ызына алды}}.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|къошулуучу}} сизге «{{SITENAME}}» сайтда билдириу {{GENDER:$1|къойду}}",
- "notification-edit-talk-page-email-batch-body2": "$1, сюзюу бетигизде билдириу {{GENDER:$1|къойду}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|къошулуучу}}, сюзюу бетигизни «$2» бёлюмюнде (темасында) билдириу {{GENDER:$1|къойду}}.",
"notification-page-linked-email-subject": "«{{SITENAME}}» сайтда сиз къурагъан бетге джибериу салынды",
- "notification-page-linked-email-batch-body": "$1 къошулуучу, $3 бетде $2 бетге джибериу {{GENDER:$1|салды}}.",
"notification-reverted-email-subject2": "{{GENDER:$1|Ким эсе да}}, сизни «{{SITENAME}}» сайтда {{PLURAL:$3|тюрлендириуюгюзню|тюрлендириулеригизни}} ызына алды",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|«$2» бетде сизни тюрлендириуюгюзню|«$2» бетде сизни тюрлендириулеригизни}} $1 {{GENDER:$1|ызына алды}}.",
"notification-mention-email-subject": "$1, {{SITENAME}} сайтда сизни {{GENDER:$1|сагъынды}}",
- "notification-mention-email-batch-body": "$1, $4 сюзюу бетинде (\"$3\") сизни {{GENDER:$1|сагъынды}}.",
- "notification-mention-nosection-email-batch-body": "$1, $2 къошулуучу бетде сизни {{GENDER:$1|сагъанды}}.",
"notification-user-rights-email-subject": "Сизни «{{SITENAME}}» сайтда хакъларыгъыз тюрлендирилдиле",
- "notification-user-rights-email-batch-body": "Къошулуучу хакъларыгъызны $1 {{GENDER:$1|тюрлендирди}}. $2.",
- "echo-email-subject-default": "«{{SITENAME}}» сайтда джангы билдириу",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 с}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 мин}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 са}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 к}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 ай}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 джыл}}",
+ "notification-timestamp-today": "Бюгюн",
+ "notification-timestamp-yesterday": "Тюнене",
+ "notification-inbox-filter-read": "Окъулгъан",
+ "notification-inbox-filter-unread": "Окъулмагъан",
+ "notification-inbox-filter-all": "Барысы да",
"echo-email-body-default": "«{{SITENAME}}» сайтда джангы билдириуюгюз барды:\n\n$1",
- "echo-email-batch-body-default": "Сизни джангы билдириуюгюз барды.",
"echo-email-footer-default": "$2\n\nЭл. почта бла ийилген билдириулени контролда тутар ючюн энчи джарашдырыуларыгъызны тинтигиз:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Эл. почта бла ийилген билдириулени контролда тутар ючюн <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">энчи джарашдырыуларыгъызны тинтигиз</a><br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|Билдириу ($1)|Билдириуле ($1)|100=Билдириуле (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Джазылгъан ($1)|Джазылгъанла ($1)|100=Джазылгъанла (99+)}}",
"echo-notification-alert-text-only": "Билдириуле",
- "echo-notification-message-text-only": "Джазылгъанла",
+ "echo-notification-notice-text-only": "Билдириуле",
"echo-overlay-link": "Бютеу билдириуле",
"echo-overlay-title": "<b>Билдириуле</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Билдириу|Билдириуле}}</b> ($2 {{PLURAL|$2|окъулмагъандан}} $1 саны {{PLURAL|$1|кёргюзюлгенди}})",
@@ -102,28 +84,9 @@
"echo-date-today": "Бюгюн",
"echo-date-yesterday": "Тюнене",
"echo-load-more-error": "Къошакъ эсеблени алгъан сагъатда халат чыкъды.",
- "notification-edit-talk-page-bundle": "$1 бла $3 {{PLURAL:$4|башха къошулуучу|башха къошулуучула}}, [[User talk:$2|сюзюу бетигизде]] билдириу {{GENDER:$1|къойду}}.",
- "notification-page-linked-bundle": "«$2» бетге «$3» бетден эмда башха $4 {{PLURAL:$5|бетден}} {{GENDER:$1|джибериу барды}}. [[Special:WhatLinksHere/$2|Бу бетге бютеу джибериулеге къарагъыз]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 бла $2 {{PLURAL:$3|башха къошулуучу|башха къошулуучула}}, сюзюу бетигизде билдириу {{GENDER:$1|къойду}}.",
- "notification-page-linked-email-batch-bundle-body": "«$2» бетге «$3» бетден эмда башха $4 {{PLURAL:$5|бетден}} {{GENDER:$1|джибериу}} барды.",
"echo-email-batch-subject-daily": "«{{SITENAME}}» проектде сизни {{PLURAL:$2|джангы билдириуюгюз|джангы билдириулеригиз}} барды",
"echo-email-batch-subject-weekly": "«{{SITENAME}}» проектде бу ыйыкъда сизге $2 {{PLURAL:$2|джангы билдириу}} келди.",
"echo-email-batch-body-intro-daily": "Салам, $1!\nСизге {{SITENAME}} сайтда бюгюннгю турумну юсюнден къысха хапар.",
"echo-email-batch-body-intro-weekly": "Салам, $1!\nСизге {{SITENAME}} сайтда турумну юсюнден ыйыкъ сайын къысха хапар.",
- "echo-email-batch-link-text-view-all-notifications": "Бютеу билдириулени кёрюу",
- "echo-rev-deleted-text-view": "Бу бет версия джашырылыбды",
- "apihelp-echomarkread-description": "Бу къошулуучу ючюн билдириулени окъулгъанлача белгиле.",
- "apihelp-echomarkread-param-list": "Окъулгъанлача белгилер ючюн ID'лени билдириулени тизмеси.",
- "apihelp-echomarkread-param-all": "Бегитилген эсе, къошулуучуну бары джазгъанларын да окъулгъанлача белгилейди.",
- "apihelp-echomarkread-param-sections": "Окъулгъанлача белгилер ючюн бёлюмлени тизмеси.",
- "apihelp-echomarkread-example-1": "8'чи билдириуню окъулгъанча белгиле",
- "apihelp-echomarkread-example-2": "Бютеу бары билдириулени да окъулгъанлача белгиле",
- "apihelp-echomarkseen-description": "Бу къошулуучу ючюн билдириулени окъулгъанлача белгиле.",
- "apihelp-echomarkseen-example-1": "Хар тюрлю билдириуню да окъулгъанча белгиле",
- "apihelp-echomarkseen-param-type": "Окъулгъанлача белгилер ючюн билдириулени тюрлюлери: 'билдириу', 'джазылгъан' неда 'бютеу'.",
- "apihelp-query+notifications-description": "Бу къошулуучуну сакълагъан билдириулеге къараб ал.",
- "apihelp-query+notifications-param-prop": "Соруу ючюн деталла.",
- "apihelp-query+notifications-param-sections": "Соруу ючюн билдириу тюрлюлери ('билдириу' бла 'джазылгъан' дегенлени комбинациялары).",
- "apihelp-query+notifications-param-limit": "Къайтарылыучу билдириулени максимал саны.",
- "apihelp-query+notifications-example-1": "Билдириулени тизмеси"
+ "echo-email-batch-link-text-view-all-notifications": "Бютеу билдириулени кёрюу"
}
diff --git a/Echo/i18n/krl.json b/Echo/i18n/krl.json
new file mode 100644
index 00000000..38b97edd
--- /dev/null
+++ b/Echo/i18n/krl.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mashoi7",
+ "Varvana"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Šiun}} hälytykšet",
+ "tooltip-pt-notifications-message": "{{GENDER:|Šiun}} viestit"
+}
diff --git a/Echo/i18n/ks-arab.json b/Echo/i18n/ks-arab.json
new file mode 100644
index 00000000..dabc4767
--- /dev/null
+++ b/Echo/i18n/ks-arab.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Shahwaqar"
+ ]
+ },
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "اَلَگ اَلَگ قٕسٕمن چھانٛٹ دِنۍ"
+}
diff --git a/Echo/i18n/ksh.json b/Echo/i18n/ksh.json
index 33d0a932..ffeabd9a 100644
--- a/Echo/i18n/ksh.json
+++ b/Echo/i18n/ksh.json
@@ -4,26 +4,31 @@
"Purodha"
]
},
- "echo-desc": "Süßtehm för Meddeijlonge aan de Metmaacher övver Nohreeschte un wat paßehrd es.",
- "prefs-echo": "Meddeilonge",
+ "echo-desc": "Süßtehm för de Metmaacher ze benohreeschteje övver wat paßehrd es un övver Meddeijlonge un Nohreeschte.",
+ "prefs-echo": "Benohreeschtejonge",
"prefs-emailsettings": "Enschtällonge för de <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">e-mail</i>",
"prefs-displaynotifications": "Enschtällonge för_t Aanzeije",
"prefs-echosubscriptions": "Donn mesch enfommehre övver:",
- "prefs-newmessageindicator": "„Neu Meddeilonge“ Aanzeije",
+ "prefs-echocrosswiki": "Meddeijlonge uß anndere Wikkis",
+ "prefs-newmessageindicator": "„Neu Meddeijlonge“ Aanzeije",
"echo-pref-send-me": "Scheck mer:",
"echo-pref-send-to": "Scheck aan:",
"echo-pref-email-format": "Dä <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">e-mail</i> iehr Fommahd:",
"echo-pref-web": "Wäb",
"echo-pref-email": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">e-mail</i>",
- "echo-pref-email-frequency-never": "Dom_mer kein ennfommazjuhne pä <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">e-mail</i> schecke.",
+ "echo-pref-email-frequency-never": "Dom_mer kein Ennfommazjuhne pä <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">e-mail</i> schecke.",
"echo-pref-email-frequency-immediately": "Scheck alles esu, wi et kütt",
"echo-pref-email-frequency-daily": "Scheck mer einmohl aam Daach alles zersamme",
"echo-pref-email-frequency-weekly": "Scheck mer einmohl pä Woch alles zersamme",
"echo-pref-email-format-html": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"PHP Hypertext Preprocessor</i>",
"echo-pref-email-format-plain-text": "Eijfache Täx",
- "echo-pref-new-message-indicator": "Donn „Neu Meddeilonge op Dinger Klaafsigg“ en mingem Menüh anzeije",
+ "echo-pref-cross-wiki-notifications": "Donn Meddeijlonge uß anndere Wikkis aanzeije",
+ "echo-pref-new-message-indicator": "Donn „Neu Meddeijlonge op Dinger Klaafsigg“ en mingem Menüh anzeije",
+ "echo-pref-beta-feature-cross-wiki-message": "Bäßer Meddeijlonge",
+ "echo-pref-beta-feature-cross-wiki-description": "Benohreeschtejonge leijschter belohre un ojjannisere, enjeschloße Benohreeschtejonge uß andere Wikkis.",
"echo-learn-more": "Mih lässe",
- "echo-new-messages": "Do häs neu Meddeilonge",
+ "echo-log": "Öffentlesch Logbohch",
+ "echo-new-messages": "Do häs neu Meddeijlonge",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Nohreesch|Nohreeschte|Nohreesch}} op der Klaafsigg",
"echo-category-title-article-linked": "{{PLURAL:$1|Lengk|Lengks|Lenk}} en Sigge",
"echo-category-title-reverted": "Retuhr jenumme {{PLURAL:$1|Ännderong|Ännderonge|Ännderong}}",
@@ -31,109 +36,110 @@
"echo-category-title-other": "{{PLURAL:$1|Söns}}",
"echo-category-title-system": "{{PLURAL:$1|Fum Wikki}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Änderong aan dä Rääschde vun enem Metmaacher|Änderonge aan Rääschde vun Metmaacher|Nix}}",
- "echo-pref-tooltip-edit-user-talk": "Scheck mer em Meddeilong, wann eine op ming Klaafsigg schriiv udder antwoot.",
- "echo-pref-tooltip-article-linked": "Scheck mer em Meddeilong, wann eine ene Lengk op en Sigg uß minge Fädder en ene Atikel deiht.",
- "echo-pref-tooltip-reverted": "Scheck mer em Meddeilong, wann eine mem !FUZZY!!undo or rollback udder Wärkzüsch en Änderong retuur nemmp, di esch jemaat han.",
- "echo-pref-tooltip-mention": "Scheck mer em Meddeilong, wann eine ene Lengk noh minge Klaafsigg säz.",
- "echo-pref-tooltip-user-rights": "Scheck mer em Meddeilong, wann eine ming Rääschde ändert.",
- "echo-no-agent": "[Keine]",
- "echo-no-title": "[Kein Sigg]",
- "echo-error-no-formatter": "Mer künne di Meddeilong nit aanzeije.\nMer weße de Manier nit, wih.",
- "notifications": "Meddeilonge",
- "tooltip-pt-notifications-message": "Ding Nohreeschte{{GENDER:|}}",
- "echo-specialpage": "Meddeilonge",
- "echo-anon": "Do moß Desch [$1 aanmälde] udder [$2 enlogge], öm Meddeilonge krijje ze künne.",
- "echo-none": "De häß kein Meddeilonge.",
+ "echo-category-title-emailuser": "<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">{{PLURAL:$1|e-mail|e-maile|e-mail}}</i> vun anndere Metmaacher",
+ "echo-pref-tooltip-edit-user-talk": "Dom_mesch benohreeschteje, wann eine op ming Klaafsigg schrihv udder doh antwoot.",
+ "echo-pref-tooltip-article-linked": "Dom_mesch benohreeschteje, wann eine ene Lengk op en Sigg uß minge Fädder en ene Atikel deiht.",
+ "echo-pref-tooltip-reverted": "Dom_mesch benohreeschteje, wann eine mem !FUZZY!!undo or rollback udder Wärkzüsch en Änderong retuur nemmp, di esch jemaat han.",
+ "echo-pref-tooltip-mention": "Dom_mesch benohreeschteje, wann eine ene Lengk noh minge Klaafsigg säz.",
+ "echo-pref-tooltip-user-rights": "Dom_mesch benohreeschteje, wann eine ming Rääschde ändert.",
+ "echo-pref-tooltip-emailuser": "Dom_mesch benohreeschteje, wam_mer eijne en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> schek.",
+ "echo-error-no-formatter": "Mer künne di Meddeijlong nit aanzeije.\nMer weße de Manier nit, wih.",
+ "notifications": "Benohreeschtejonge",
+ "tooltip-pt-notifications-alert": "Ding Benohreeschtejonge",
+ "tooltip-pt-notifications-notice": "Ding Benohreeschtejonge{{GENDER:|}}",
+ "echo-displaynotificationsconfiguration": "Zeijsch de Enschtällonge för de Meddeijlonge",
+ "echo-displaynotificationsconfiguration-summary": "Heh küdd en Övversesch, wi de Meddeijlonge en heh däm Wikki enjeschtallt sin.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Meddeijlonge noh Zoote",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Zottehre",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "En wat för ene Afschnedd en Zoot Benohreeschtejong enzotteht weed.",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Zohjelohße Metohde för Meddeijlonge",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Wat för en Mannehre vun Benohreeschtejonge för jehde Jropp müjjelesch sin",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Schtandattmähßesch ennjeschalldt",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Metmaacher, di et jitt",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Neu Metmaacher",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Nühdejje Metohde för Meddeijlonge",
+ "echo-specialpage": "Benohreeschtejonge",
+ "echo-specialpage-section-markread": "Makkehr di Jropp als jelässe",
+ "echo-specialpage-markasread": "Benohreeschtejong: Als jelässe makkehre",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|ein Benohreeschtejong|$1 Benohreeschtejonge|kein Benohreeschtejong}}",
+ "echo-specialpage-pagefilters-title": "Zeläz jedonn",
+ "echo-specialpage-pagefilters-subtitle": "Sigge med onjelässe Meddeijlonge",
+ "notificationsmarkread-legend": "Donn en Meddijlong als jelässe mekkehre",
+ "echo-anon": "Do moß Desch [$1 aanmälde] udder [$2 enlogge], öm Benohreeschtejonge krijje ze künne.",
+ "echo-none": "De häß kein Meddeijlonge.",
"echo-more-info": "Mih Enfommazjuhne",
"echo-feedback": "Rökmäldong",
"echo-quotation-marks": "„$1“",
- "echo-api-failure": "Mer kunne kein Medeijonge affrohfe. Bes esu johd un versöhg et norr_ens. (Fähler $1)",
- "echo-notification-placeholder": "meer han kein neuje Meddeijonge.",
+ "echo-api-failure": "Mer kunne kein Medeijonge affrohfe.",
+ "echo-api-failure-cross-wiki": "Der Zohjreff noh ußerhallef wood nit zohjelohße.",
+ "echo-notification-placeholder": "Mer han kein neuje Meddeijlonge.",
+ "echo-notification-placeholder-filters": "Mer han kein Benohreeschtejonge met dä Eijeschaffte.",
+ "echo-notification-loginrequired": "Mer moß ennlogge, öm sing Nohreeschte belohre ze künne.",
+ "echo-notification-popup-loginrequired": "Donn ennlogge, öm ding Nohreeschte ze belohre.",
+ "echo-notification-markasread": "Als „jelässe“ makehre",
+ "echo-notification-markasunread": "Als „nit jelässe“ makkehre",
+ "echo-notification-markasread-tooltip": "Als „jelässe“ makehre",
+ "echo-notification-more-options-tooltip": "Mih Müjjeleschkeijte",
+ "notification-link-text-expand-all": "Opklappe",
+ "notification-link-text-expand-notice-count": "Belohr {{PLURAL:$1|ein Benohreeschtejong|$1 Benohreeschtejonge|keij Benohreeschtejonge}}",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|Meddejlong|$1 Meddejlong|Nix}} aanzeije",
+ "notification-link-text-collapse-all": "Zohklappe",
"notification-link-text-view-message": "De Nohreesch belohre",
"notification-link-text-view-mention": "De Äwähnong belohre",
- "notification-link-text-view-changes": "De Veränderonge belohre",
+ "notification-link-text-view-changes": "De Veränderonge belohre{{GENDER:$1|}}",
"notification-link-text-view-page": "De Sigg belohre",
+ "notification-header-edit-user-talk": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät jädd op <strong>Ding [[User talk:$3|Klaafsigg]]</strong> jeschrevve.",
+ "notification-header-edit-user-talk-with-section": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hädd em Affschnett „$4“ jädd op Ding Klaafsigg jeschrevve.{{GENDER:$3|}}",
+ "notification-header-page-linked": "Ene Lengk wood jesaz vun <strong>$4</strong> op <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Verlengkt vun <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Et woodte Lengks jemäät {{PLURAL:$5||vun $5 Sigge|100=vun mih wi 99 Sigge}} op <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Alle Lengks op heh di Sigg",
+ "notification-header-welcome": "Wellkomme, $1, {{GRAMMAR:em|{{SITENAME}}}}! Mer sin fruh, dat De derbei beß.{{GENDER:$2|}}",
+ "notification-welcome-linktext": "Wellkumme",
+ "notification-header-thank-you-1-edit": "Do häs jrahd Ding eezte Änderong aam Wikki jemaat.\nDoh freue mer ons drövver.\nWellkumme!{{GENDER:$2|}}",
+ "notification-header-thank-you-10-edit": "Do häs jrahd Ding zehnte Änderong aam Wikki jemaat.\nDoh freue mer ons drövver.{{GENDER:$2|}}",
+ "notification-header-thank-you-100-edit": "Do häs jrahd Ding honertsde Änderong aam Wikki jemaat.\nDoh freue mer ons drövver.{{GENDER:$2|}}",
+ "notification-header-thank-you-1000-edit": "Do häs jrahd Ding dousenste Änderong aam Wikki jemaat.\nDoh freue mer ons drövver.{{GENDER:$2|}}",
+ "notification-link-thank-you-edit": "Ding Änderong{{GENDER:$1|}}",
"notification-link-text-view-edit": "De Veränderong belohre",
- "notification-edit-talk-page2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hädd en Nohreech op Ding [[User talk:$2#$3|Klaafsigg]] jedonn.",
- "notification-edit-talk-page-with-section": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hädd en Nohreech op Ding Klaafsigg en dä Affschnedd „[[User talk:$2#$3|$4]]“ jedonn.",
- "notification-edit-talk-page-flyout2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hädd en Nohreech op Ding [[User talk:$2#$3|Klaafsigg]] jedonn.",
- "notification-edit-talk-page-flyout-with-section": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hädd en Nohreech op Ding Klaafsigg en dä Affschnedd „[[User talk:$2#$3|$4]]“ jedonn.",
- "notification-page-linked": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ häd op dä Sigg „[[:$3]]“ ene Lengk noh „[[:$2]]“ enjebout. De kanns Der [[Special:WhatLinksHere/$2|alle Lengks noh doh]] belohre.",
- "notification-page-linked-flyout": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ häd op dä Sigg „[[:$3]]“ ene Lengk noh „[[:$2]]“ enjebout.",
- "notification-add-comment2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hät jäd en dä Affschnedd „[[$3|$2]]“ op da Klaafsigg vun dä Sigg „$4“ jedonn.",
- "notification-add-talkpage-topic2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hät ene neu Affschnedd met dä Övverschreff „$2“ op di Sigg „[[$3]]“ jedonn.",
- "notification-add-talkpage-topic-yours2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hät Der en Metdeilong jescheck: „[[$3#$2|$2]]“ .",
- "notification-add-comment-yours2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hät op Dinge Klaafsigg jät zoh „[[$3#$2|$2]]“ jeschrevve.",
- "notification-mention": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hät Desch op dä Klaafsigg vun dä Sigg „$5“ em Affschnet „[[:$3#$2|$4]]“ jenannt.",
- "notification-mention-flyout": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Desch op dä Klaafsigg vun dä Sigg „$5“ em Affschnet „[[:$3#$2|$4]]“ jenannt.",
- "notification-mention-nosection": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hät Desch op dä Klaafsigg övver di Sigg „[[:$3|$2]]“ jenannt.",
- "notification-mention-nosection-flyout": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Desch op dä Klaafsigg övver di Sigg „[[:$3|$2]]“ jenannt.",
- "notification-user-rights": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hät [[Special:Log/rights/$1|Ding Rääschde als ene Metmaacher verändert]]. $2. Do kanns [[Special:ListGroupRights|mih övver de einzel Rääschde]] nohlässe.",
- "notification-user-rights-flyout": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Ding Rääschde als ene Metmaacher verändert. $2. Do kanns [[Special:ListGroupRights|mih övver de einzel Rääschde]] nohlässe.",
- "notification-user-rights-add": "Do bes jäz en heh dä {{PLURAL:$2|Jropp|Jroppe|Jropp}}: $1",
- "notification-user-rights-remove": "Do bes jäz nit mih en heh dä {{PLURAL:$2|Jropp|Jroppe|Jropp}}: $1",
- "notification-new-user": "$1, welkumme op {{GENDER:Dative|{{SITENAME}}}}.\nMer freue ons, dat De doh bes!",
- "notification-reverted2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „[[User:$1|$1]]“ hät {{PLURAL:$4|Dinge Beijdraach|Ding Beijdrähsch|keine Beijdraach vun Der}} op dä Sigg „[[:$2]]“ retuhr jemaht. $3",
- "notification-reverted-flyout2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät {{PLURAL:$4|Dinge Beijdraach|Ding Beijdrähsch|keine Beijdraach vun Der}} op dä Sigg „$2“ retuhr jemaht. $3",
+ "notification-header-reverted": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät {{PLURAL:$4|Dinge Beijdraach|Ding Beijdrähsch|keine Beijdraach vun Der}} op dä Sigg „$3“ retuhr jemaht.",
+ "notification-header-emailuser": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Der en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i> jeschek.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Der op {{GENDER:Dative|{{SITENAME}}}} en Metdeilong jeschek.",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Der op en Metdeilong op Ding Klaafsigg jedonn.",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Der op en Metdeilong op Ding Klaafsigg en dä Affschnett „$2“ jedonn.",
"notification-page-linked-email-subject": "Op {{GENDER:Dative|{{SITENAME}}}} wohd ene Lengk op Sigg aanjelaht, di Do aanjalaht hats.",
- "notification-page-linked-email-batch-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ häd op dä Sigg „$3“ ene Lengk noh „$2“ enjebout.",
"notification-reverted-email-subject2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ häd op {{GENDER:Dative|{{SITENAME}}}} {{PLURAL:$3|en Änderong|$3 Änderonge|kein Änderonge}} vun Der retuhr jemaht.",
- "notification-reverted-email-batch-body2": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ häd op {{GENDER:Dative|{{SITENAME}}}} {{PLURAL:$3|en Änderong vun Der|$3 vun Dinge Änderonge|kein vun Dinge Änderonge}} aan dä Sigg „$2“ retuhr jemaht.",
"notification-mention-email-subject": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Desch {{GRAMMAR:em|{{ucfirst:{{SITENAME}}}}}} jenannt.",
- "notification-mention-email-batch-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} hät Desch op dä Sigg „$4“ em Affschnet „$3“ jenannt.",
- "notification-mention-nosection-email-batch-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} hät Desch op dä Sigg „$2“ jenannt.",
"notification-user-rights-email-subject": "Ding Rääschde als Metmaacher {{GRAMMAR:em|{{ucfirst:{{SITENAME}}}}}} sin verändert woode.",
- "notification-user-rights-email-batch-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät Ding Rääschde als Metmaacher verändert. $2.",
- "echo-notification-count": "övver $1",
- "echo-email-subject-default": "En neue Meddeilong op {{GRAMMAR:dative|{{ucfirst:{{SITENAME}}}}}}",
- "echo-email-body-default": "Do häss_en neue Meddeilong op {{GRAMMAR:dative|{{ucfirst:{{SITENAME}}}}}}:\n\n$1",
- "echo-email-batch-body-default": "Do häss_en neuje Meddeilong.",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 Sek.}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 Min.}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 Std.}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 Daach}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 Mon.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|ei&nbsp;Johr|$1&nbsp;Johre|nix}}",
+ "notification-timestamp-today": "Hügg",
+ "notification-timestamp-yesterday": "Jäßtere",
+ "notification-inbox-filter-read": "Jelässe",
+ "notification-inbox-filter-unread": "Nit jelässe",
+ "notification-inbox-filter-all": "All",
+ "echo-email-body-default": "Do häss_en neue Meddeijlong op {{GRAMMAR:dative|{{ucfirst:{{SITENAME}}}}}}:\n\n$1",
"echo-email-footer-default": "$2\n\nDonn op:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\nenschtälle, wat mer Der schecke sulle.\n\n$1",
- "echo-email-footer-default-html": "En Dinge <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">Enschtällonge</a> kanns De faßlähje, wat mer Der jenou scheke sulle.<br />\n$1",
+ "echo-email-html-footer-preference-link-text": "Lohr noh Ding Ennschschtällonge",
"echo-notification-alert": "{{PLURAL:$1|Eine Henwihß|$1 Henwihse|Keine Henwihß|100=Övver 99 Henwihse}}",
- "echo-notification-message": "{{PLURAL:$1|Eine Nohreesch ob ene Klaafsigg|$1 Nohreeschte op Klaafsigge|Keine Nohreesch ob ene Klaafsigg|100=Övver 99 Nohreeschte op Klaafsigge}}",
+ "echo-notification-notice": "{{PLURAL:$1|Benohreeschtejong ($1)|Benohreeschtejonge ($1)|100=Benohreeschtejonge (99+)}}",
"echo-notification-alert-text-only": "Henwihß",
- "echo-notification-message-text-only": "Nohreschte",
- "echo-overlay-link": "Alle Meddeilonge",
- "echo-overlay-title": "<b>Meddeilonge</b>",
- "echo-overlay-title-overflow": "<b>Meddeilonge</b> ($1 vun $2 wähde aanjezeijsch){{PLURAL:$1|}}",
+ "echo-notification-notice-text-only": "Meddeijlonge",
+ "echo-overlay-link": "Alle Meddeijlonge",
+ "echo-overlay-title": "<b>Meddeijlonge</b>",
+ "echo-overlay-title-overflow": "<b>Meddeijlonge</b> ($1 vun $2 wähde aanjezeijsch){{PLURAL:$1|}}",
"echo-mark-all-as-read": "Alle als jelässe makehre",
+ "echo-mark-wiki-as-read": "Makkehr alles als jelässe em usjesöhk Wikki: $1",
"echo-date-today": "Hück",
"echo-date-yesterday": "Jäßtere",
"echo-load-more-error": "Ene Fähler es opjetrodde beim Versohch, mih ze holle vun dämm wadd_erus kohm.",
- "notification-edit-talk-page-bundle": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ un {{PLURAL:$4|eine anndere hät|$3 anndere han|keine söns hät}} en Nohreesch udder Nohreeschte op Ding [[User talk:$2|Klaafsigg]] jeschrevve.",
- "notification-page-linked-bundle": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ häd op dä Sigg „$3“ un {{PLURAL:$5|eine anndere|$4 anndere|söns keine}} ene Lengk noh „$2“ enjebout. De kanns Der [[Special:WhatLinksHere/$2|alle Lengks noh doh]] belohre.",
- "notification-edit-user-talk-email-batch-bundle-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ un {{PLURAL:$3|eine anndere hät|$2 anndere han|keine söns hät}} en Nohreesch udder Nohreeschte op Ding Klaafsigg jeschrevve.",
- "notification-page-linked-email-batch-bundle-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ häd op dä Sigg „$3“ un {{PLURAL:$5|eine anndere|$4 anndere|söns keine}} ene Lengk noh „$2“ enjebout.",
"echo-email-batch-bullet": "•",
- "echo-email-batch-subject-daily": "Do häs {{PLURAL:$2|en neuje Meddeilong|$2 neuje Meddeilong|kein neuje Meddeilonge}} {{GRAMMAR:em|{{ucfirst:{{SITENAME}}}}}}.",
- "echo-email-batch-subject-weekly": "Do häs en dä Woch {{PLURAL:$2|en neuje Meddeilong|$2 neuje Meddeilong|kein neuje Meddeilonge}} {{GRAMMAR:em|{{ucfirst:{{SITENAME}}}}}}.",
+ "echo-email-batch-subject-daily": "Do häs {{PLURAL:$2|en neuje Meddeijlong|$2 neuje Meddeijlong|kein neuje Meddeijlonge}} {{GRAMMAR:em|{{ucfirst:{{SITENAME}}}}}}.",
+ "echo-email-batch-subject-weekly": "Do häs en dä Woch {{PLURAL:$2|en neuje Meddeijlong|$2 neuje Meddeijlong|kein neuje Meddeijlonge}} {{GRAMMAR:em|{{ucfirst:{{SITENAME}}}}}}.",
"echo-email-batch-body-intro-daily": "Daach $1,\nheh küdd en Sammlong vun däm, wadd {{GRAMMAR:em|{{ucfirst:{{SITENAME}}}}}} hück paßehrd es.",
"echo-email-batch-body-intro-weekly": "Daach $1,\nheh küdd en Sammlong vun däm, wadd {{GRAMMAR:em|{{ucfirst:{{SITENAME}}}}}} di Woch paßehrd es.",
- "echo-email-batch-link-text-view-all-notifications": "Alle Meddeilonge belohre",
- "echo-rev-deleted-text-view": "Heh di Väsjohn vun dä Sigg es ongerdrök woode.",
- "apihelp-echomarkread-description": "Makkehr, dat dä aktoälle Metmaacher di Meddeilonge jelässe hät.",
- "apihelp-echomarkread-param-list": "En leß met dä Kännonge för di Meddeilonge, di op „jelässe“ jesaz wähde sulle.",
- "apihelp-echomarkread-param-all": "Wann aanjekleck, dunn all däm Metmaacher singe Meddeilonge op „jelässe“ säze.",
- "apihelp-echomarkread-param-sections": "En Leß met Affschnedde, di op „jelässe“ jesaz wähde sulle.",
- "apihelp-echomarkread-example-1": "Säz de Meddeilong aach op „jelässe“.",
- "apihelp-echomarkread-example-2": "Säz alle Meddeilonge op „jelässe“.",
- "apihelp-echomarkseen-description": "Makkehr, dat dä aktoälle Metmaacher di Meddeilonge jesinn hät.",
- "apihelp-echomarkseen-example-1": "Makehr de Meddeilong als „jesinn“",
- "apihelp-query+notifications-description": "Holl däm aktoälle Metmaacher sing Waadeschlang met Meddeilonge.",
- "apihelp-query+notifications-param-prop": "De Einzelheijte för dernoh ze frohre.",
- "apihelp-query+notifications-param-sections": "De Afschnedde vun de Nohreeschte holle.",
- "apihelp-query+notifications-param-groupbysection": "Of de Leß en Jroppe vun Afschnedde sin sull.\nJehde Affschnedd es för sesch, wann dat aanjeklegg es.",
- "apihelp-query+notifications-param-format": "Wann aanjejovve, wähde de Nohreeschte en dä Manier daajeschtällt.",
- "apihelp-query+notifications-param-limit": "Nit mih, wi esu vill Meddeilonge ußjävve.",
- "apihelp-query+notifications-param-index": "Wann ußjewählt, küdd_en zottehrte Leß met Kännonge för Meddeilonge.",
- "apihelp-query+notifications-param-alertcontinue": "Wann mih Meddeilonge ze holle sin, nemm dat för wigger ze maache.",
- "apihelp-query+notifications-param-alertunreadfirst": "Ov de unjelässe Meddeilonge am Aanfang schtonn sulle.",
- "apihelp-query+notifications-param-messagecontinue": "Wann mih Nohreeschte ze holle sin, nemm dat för wigger ze maache.",
- "apihelp-query+notifications-param-messageunreadfirst": "Ov de unjelässe Nohreeschte övver Meddeilonge am Aanfang schtonn sulle.",
- "apihelp-query+notifications-example-1": "Meddeilonge opleßte",
- "apihelp-query+notifications-example-2": "Meddeilonge opleßte, noh Affschnedde, met der Aanzahl"
+ "echo-email-batch-link-text-view-all-notifications": "Alle Meddeijlonge belohre"
}
diff --git a/Echo/i18n/ku-latn.json b/Echo/i18n/ku-latn.json
index 442620f6..7d7fb75f 100644
--- a/Echo/i18n/ku-latn.json
+++ b/Echo/i18n/ku-latn.json
@@ -2,14 +2,46 @@
"@metadata": {
"authors": [
"George Animal",
- "Bikarhêner"
+ "Bikarhêner",
+ "Ghybu"
]
},
+ "prefs-emailsettings": "Vebijarkên e-nameyê",
+ "echo-pref-web": "Web",
+ "echo-pref-email": "E-name",
"echo-pref-email-format-html": "HTML",
+ "echo-learn-more": "Bêhtir hîn bibe",
"echo-new-messages": "Peyamên nû ji te re hene",
- "tooltip-pt-notifications": "Agahdarîyên te",
- "notification-link-text-view-changes": "Guherandinan bibîne",
+ "echo-category-title-system": "{{PLURAL:$1|Pergal}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Guherandina mafên bikarhêran|Guherandinan mafên bikarhêneran}}",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Agahdariyên}} te",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Bikarhênerên hene",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Bikarhênerên nû",
+ "echo-specialpage-pagefilters-title": "Çalakiya dawî",
+ "echo-notification-placeholder": "Agahdariyên te tine nin.",
+ "echo-notification-markasread": "Wek xwendî nîşan bide",
+ "echo-notification-markasunread": "Wek nexwendî nîşan bide",
+ "echo-notification-markasread-tooltip": "Wek xwendî nîşan bide",
+ "notification-link-text-view-changes": "Guherandinan {{GENDER:$1|bibîne}}",
"notification-link-text-view-page": "Rûpelê bibîne",
+ "notification-link-text-what-links-here": "Hemû girêdanên ber bi vê rûpelê ve",
+ "notification-header-mention-other-nosection": "$1 li ser <strong>$4</strong> {{GENDER:$2|qala}} {{GENDER:$3|te}} kir.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Navê bikarhêner tune ye:</strong> $1",
+ "notification-welcome-linktext": "Tu bi xêr hatî",
+ "notification-header-emailuser": "$1 peyamek ji te re {{GENDER:$2|şand.}}",
+ "notification-user-rights-email-subject": "Mafên te yên bikarhêneriyê li ser {{SITENAME}} hatin guherandin.",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1st}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1r}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1me}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1sl}}",
+ "notification-timestamp-today": "Îro",
+ "notification-timestamp-yesterday": "Doh",
+ "notification-inbox-filter-read": "Bixwîne",
+ "notification-inbox-filter-unread": "Nexwendî",
+ "notification-inbox-filter-all": "Hemû",
+ "echo-mark-all-as-read": "Hemûkan wek xwendî nîşan bide",
"echo-date-today": "Îro",
"echo-date-yesterday": "Doh"
}
diff --git a/Echo/i18n/ky.json b/Echo/i18n/ky.json
index 18d7e718..bcaa4b00 100644
--- a/Echo/i18n/ky.json
+++ b/Echo/i18n/ky.json
@@ -3,6 +3,5 @@
"authors": [
"Janatkg"
]
- },
- "tooltip-pt-notifications": "Билдирүүлөрүңүз"
+ }
}
diff --git a/Echo/i18n/la.json b/Echo/i18n/la.json
index f02643f1..40f819ab 100644
--- a/Echo/i18n/la.json
+++ b/Echo/i18n/la.json
@@ -3,27 +3,28 @@
"authors": [
"Amire80",
"Autokrator",
- "UV"
+ "UV",
+ "Laurentianus"
]
},
"echo-desc": "Modus nuntiorum mittendarum",
"prefs-echo": "Nuntia",
- "prefs-emailsettings": "Praeferentiae litterarum electronicarum",
- "prefs-displaynotifications": "Praeferentiae nuntiorum",
- "prefs-echosubscriptions": "De his actionibus nuntiare",
+ "prefs-emailsettings": "Modi nuntiorum",
+ "prefs-displaynotifications": "Nuntiorum modi",
+ "prefs-echosubscriptions": "Haec indicare",
"prefs-newmessageindicator": "Nova nuntia",
- "echo-pref-send-me": "Mitte mihi:",
- "echo-pref-send-to": "Mittere ad:",
- "echo-pref-email-format": "Modus litterarum electronicarum:",
+ "echo-pref-send-me": "Mihi mittantur:",
+ "echo-pref-send-to": "Mittantur per:",
+ "echo-pref-email-format": "Litterarum modus:",
"echo-pref-web": "Interrete",
"echo-pref-email": "Litterae electronicae",
- "echo-pref-email-frequency-never": "Nullas litteras electronicas mittere",
- "echo-pref-email-frequency-daily": "Summarium cottidianum nuntiorum",
- "echo-pref-email-frequency-weekly": "Summarium hebdomadale nuntiorum",
+ "echo-pref-email-frequency-never": "Nulla nuntia",
+ "echo-pref-email-frequency-immediately": "Singula nuntia",
+ "echo-pref-email-frequency-daily": "Nuntia cottidie congesta",
+ "echo-pref-email-frequency-weekly": "Nuntia hebdomadatim congesta",
"echo-pref-email-format-html": "HTML",
- "echo-pref-email-format-plain-text": "Textus",
- "echo-pref-notify-show-link": "Nuntia in arca ferramentorum monstrare",
- "echo-pref-new-message-indicator": "Monstrare indicatorem paginarum disputationis nuntiorum in arca ferramentorum",
+ "echo-pref-email-format-plain-text": "Textus nudus",
+ "echo-pref-new-message-indicator": "Nova apud te disputata in arca ferramentorum indicare",
"echo-learn-more": "Plura legere",
"echo-new-messages": "Habes nuntia nova",
"echo-category-title-edit-user-talk": "Paginae disputationis {{PLURAL:$1|nuntium|nuntia}}",
@@ -33,13 +34,10 @@
"echo-pref-tooltip-edit-user-talk": "Me certiorem facere si quis nuntium mittat vel in pagina disputationis mea respondat.",
"echo-pref-tooltip-article-linked": "Me certiorem facere si quis paginam quam creavi nectit e quadam pagina commentationis.",
"echo-pref-tooltip-mention": "Me certiorem facere si quis e quacumque pagina disputationis ad paginam usoris meam nectit.",
- "echo-no-agent": "[Nemo]",
- "echo-no-title": "[Nulla pagina]",
- "echo-error-preference": "Error: Praeferentias usoris adaptare non contigit.",
"notifications": "Nuntia",
- "tooltip-pt-notifications": "Nuntia tua",
+ "tooltip-pt-notifications-alert": "Conclamationes ad te pertinentes",
"echo-specialpage": "Nuntia",
- "echo-anon": "Ut nuntia accipias, [$1 rationem crees] aut [$2 conventum aperias] rogamus.",
+ "echo-anon": "Ut nuntia accipere possis, [$1 nomen tibi impones] aut [$2 nomen tuum des] rogamus.",
"echo-none": "Nulla nuntia.",
"echo-more-info": "Plura legere",
"echo-feedback": "Responsa",
@@ -48,18 +46,10 @@
"notification-link-text-view-changes": "Mutata ostendere",
"notification-link-text-view-page": "Vide paginam",
"notification-link-text-view-edit": "Vide recensionem",
- "notification-page-linked-flyout": "[[:$2]] nectum est a pagina [[:$3]].",
- "notification-user-rights-add": "Nunc es sodalis {{PLURAL:$2|eius gregis|eorum gregium}}: $1",
- "notification-user-rights-remove": "Non iam es sodalis {{PLURAL:$2|eius gregis|eorum gregium}}: $1",
- "notification-new-user": "Salve ad {{grammar:accusative|{{SITENAME}}}}, $1!",
"notification-page-linked-email-subject": "Pagina tua annexa est apud {{grammar:accusative|{{SITENAME}}}}",
"notification-mention-email-subject": "$1 tui {{GENDER:$1|mentionem fecit}} apud {{grammar:accusative|{{SITENAME}}}}",
- "notification-mention-email-batch-body": "$1 tui {{GENDER:$1|mentionem fecit}} in $4 in \"$3\"",
- "echo-email-subject-default": "Nova nuntia apud {{grammar:accusative|{{SITENAME}}}}",
"echo-email-body-default": "Habes nova nuntia apud {{grammar:accusative|{{SITENAME}}}}:\n\n$1",
- "echo-email-batch-body-default": "Habes novum nuntium.",
- "echo-email-footer-default": "$2\n\nAd aptandum quales litteras electronicas tibi mittantur praeferentias tuas vide:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Ad aptandum quales litteras electronicas tibi mittantur <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">praeferentias tuas vide</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nAd deligendum, quales litterae electronicae tibi mittantur, vide modos tuos:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-overlay-link": "Omnia nuntia",
"echo-overlay-title": "<b>Nuntia</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Nuntium|Nuntia}}</b> (monstrans $1 de $2 inlectis)",
@@ -67,11 +57,9 @@
"echo-date-today": "Hodie",
"echo-date-yesterday": "Heri",
"echo-load-more-error": "Error in plura eventa quaerendo.",
- "notification-page-linked-bundle": "$2 nectum est a $3 et $4 {{PLURAL:$5|alia pagina|aliis paginis}}. [[Special:WhatLinksHere/$2|Omnes nexus ad hanc paginam spectare]]",
"echo-email-batch-subject-daily": "Habes {{PLURAL:$2|novum nuntium|nova nuntia}} apud {{grammar:accusative|{{SITENAME}}}}",
"echo-email-batch-subject-weekly": "Habes {{PLURAL:$2|novum nuntium|nova nuntia}} apud {{grammar:accusative|{{SITENAME}}}} hac hebdomada",
"echo-email-batch-body-intro-daily": "Salve $1,\nHoc est summarium actionum hodiernarum apud {{grammar:accusative|{{SITENAME}}}}.",
"echo-email-batch-body-intro-weekly": "Salve $1,\nHoc est summarium actionum hebdomadum apud {{grammar:accusative|{{SITENAME}}}}.",
- "echo-email-batch-link-text-view-all-notifications": "Omnia nuntia spectare",
- "echo-rev-deleted-text-view": "Haec emendatio paginae oppressa est."
+ "echo-email-batch-link-text-view-all-notifications": "Omnia nuntia spectare"
}
diff --git a/Echo/i18n/lad.json b/Echo/i18n/lad.json
index a7226e0f..9631fc29 100644
--- a/Echo/i18n/lad.json
+++ b/Echo/i18n/lad.json
@@ -2,13 +2,14 @@
"@metadata": {
"authors": [
"Menachem.Moreira",
- "Universal Life"
+ "Universal Life",
+ "StevenJ81"
]
},
"prefs-emailsettings": "Opsyones del korreo elektroniko",
"echo-pref-email": "Korreo elektroniko",
"echo-pref-email-format-html": "HTML",
- "echo-category-title-article-linked": "Pajina{{PLURAL:$1|enlase|enlases}}",
+ "echo-category-title-article-linked": "Hoja{{PLURAL:$1|enlase|enlases}}",
"notification-link-text-view-changes": "Amostrar los trocamientos",
"notification-link-text-view-page": "Ver la hoja",
"notification-link-text-view-edit": "Ver edisyon"
diff --git a/Echo/i18n/lb.json b/Echo/i18n/lb.json
index 87813b34..4e7b166e 100644
--- a/Echo/i18n/lb.json
+++ b/Echo/i18n/lb.json
@@ -2,7 +2,9 @@
"@metadata": {
"authors": [
"Robby",
- "Soued031"
+ "Soued031",
+ "Macofe",
+ "Les Meloures"
]
},
"echo-desc": "System fir Benotzer iwwer Evenementer a Messagen z'informéieren",
@@ -10,7 +12,9 @@
"prefs-emailsettings": "E-Mail-Astellungen",
"prefs-displaynotifications": "Optioune vum Affichage",
"prefs-echosubscriptions": "Mech iwwer dës Evenementer informéieren",
+ "prefs-echocrosswiki": "Cross-Wiki Notifikatiounen",
"prefs-newmessageindicator": "Indicateur vun neie Messagen",
+ "prefs-blocknotificationslist": "Verstoppt Benotzer",
"echo-pref-send-me": "Mir schécken:",
"echo-pref-send-to": "Schécken un:",
"echo-pref-email-format": "E-Mail-Format:",
@@ -22,99 +26,176 @@
"echo-pref-email-frequency-weekly": "All Woch e Resumé vun den Notifikatiounen",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Kloertext",
+ "echo-pref-cross-wiki-notifications": "Notifikatioune vun anere Wikie weisen",
+ "echo-pref-notifications-blacklist": "Notifikatioune vun dëse Benotzer net weisen.\n([[mw:Help:Notifications#mute|méi gewuer ginn]])",
"echo-pref-new-message-indicator": "Indicateur fir Messagen op menger Diskussiounssäit a menger Geschirläischt weisen",
+ "echo-pref-beta-feature-cross-wiki-message": "Erweidert Notifikatiounen",
+ "echo-pref-beta-feature-cross-wiki-description": "Notifikatioune méi einfach weisen an organiséieren.Inklusiv Cross-Wiki Notifikatiounen, déi Iech Message vun anere Wikie weisen. (Fir Cross-Wiki Notifikatioune vun enger bestëmmter Wiki ze kréie musst dir d'Beta-Funktioun op där Wiki aktivéieren.)",
"echo-learn-more": "Fir méi ze wëssen",
+ "echo-log": "Ëffentlecht Logbuch",
"echo-new-messages": "Dir hutt nei Messagen",
"echo-category-title-edit-user-talk": "Diskussiounssäit {{PLURAL:$1|Message|Messagen}}",
"echo-category-title-article-linked": "{{PLURAL:$1|Säitelink|Säitelinken}}",
- "echo-category-title-reverted": "{{PLURAL:$1|Zréckgesetzung|Zrécksetzungen}} änneren",
+ "echo-category-title-reverted": "{{PLURAL:$1|Zrécksetzung|Zrécksetzungen}} änneren",
"echo-category-title-mention": "{{PLURAL:$1|Mentioun|Mentiounen}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Mentioun|Mentiounen}} ouni Succès",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Mentioun|Mentioune}} mat Succès",
"echo-category-title-other": "{{PLURAL:$1|Aneren|Anerer}}",
"echo-category-title-system": "{{PLURAL:$1|System}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Ännerung vu Benotzerrechter|Ännerunge vu Benotzerrechter}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-Mail vun engem anere Benotzer|E-Maile vun anere Benotzer}}",
+ "echo-category-title-article-reminder": "Säit {{PLURAL:$1|Erënnerung|Erënnerungen}}",
"echo-pref-tooltip-edit-user-talk": "Mech informéiere wann een eppes op meng Diskussiounssäit schreift oder do äntwert.",
- "echo-pref-tooltip-article-linked": "Mech informéiere wann een an engem Artikel op eng Säit verlinkt, déi ech kreéiert hunn.",
- "echo-pref-tooltip-reverted": "Mech informéiere wann ee meng Ännerung zrécksetzt oder andeems hien de 'Rollback'-Tool benotzt.",
+ "echo-pref-tooltip-article-linked": "Mech informéiere wann een an engem Artikel op eng aner Säit verlinkt, déi ech kreéiert hunn.",
+ "echo-pref-tooltip-reverted": "Mech informéiere wann ee meng Ännerung zerécksetzt oder wann de 'Rollback'-Tool benotzt gëtt.",
"echo-pref-tooltip-mention": "Mech informéiere wann een e Link op meng Benotzersäit setzt.",
+ "echo-pref-tooltip-mention-failure": "Mech informéieren wann ech engem eng Mentioun net schécke konnt.",
+ "echo-pref-tooltip-mention-success": "Mech informéieren wann ech engem eng Mentioun geschéckt hunn.",
"echo-pref-tooltip-user-rights": "Mech informéiere wann ee meng Benotzerrechter ännert.",
- "echo-no-agent": "[Keen]",
- "echo-no-title": "[Keng Säit]",
+ "echo-pref-tooltip-emailuser": "Mech informéiere wann ee mir en E-Mail schéckt.",
+ "echo-pref-tooltip-article-reminder": "Mech iwwer dës Säit notifiéieren wann ech froen.",
"echo-error-no-formatter": "Keng Formatéierung fir Notifikatiounen definéiert.",
"notifications": "Notifikatiounen",
"tooltip-pt-notifications-alert": "{{GENDER:|Är}} Warnungen",
- "tooltip-pt-notifications-message": "{{GENDER:|Är}} Messagen",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Är}} Notifikatiounen",
+ "echo-displaynotificationsconfiguration": "Astellunge vun den Notifikatioune weisen",
+ "echo-displaynotificationsconfiguration-summary": "Dëst ass eng Iwwersiicht wéi Notifikatiounen op dëser Wiki agestallt sinn.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notifikatiounen no Kategorie",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Klassifikatioun vun den Typen",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "A Wat fir een Abschnitt all Typ vun Notifikatioun azortéiert gëtt",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Erlaabt Methode fir Notifikatiounen",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Wat fir eng Notifikatunsmethode fir jidder Kategorie ënnerstëtzt ginn",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Wat fir eng Notifikatiounsmethode gi fir jiddwer Typ ënnerstëtzt; bezitt sech nëmmen op Typpe vu Kategorien déi an den Astellunge verstoppt sinn",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Als Standard aktivéiert",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Lëscht vun de Benotzer",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nei Benotzer",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Obligatoresch Notifikatiounsmethoden",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Wat fir eng Notifikatiounsmethode fir jidder Kategorie obligatoresch sinn",
"echo-specialpage": "Notifikatiounen",
+ "echo-specialpage-section-markread": "Grupp als geliest markéieren",
+ "echo-specialpage-markasread": "Notifikatioun: Als geliest markéieren",
+ "echo-specialpage-markasread-invalid-id": "Net valabel ID vun engem Evenement",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|Notifikatioun|Notifikatiounen}}",
+ "echo-specialpage-pagefilters-title": "Rezent Aktivitéit",
+ "echo-specialpage-pagefilters-subtitle": "Säite mat net geliesten Notifikatiounen",
+ "notificationsmarkread-legend": "Notifikatioun als geliest markéieren",
"echo-anon": "Fir Notifikatiounen ze kréien, [$1 maacht e Benotzerkont op] oder [$2 loggt Iech an]",
"echo-none": "Dir hutt keng Notifikatiounen.",
"echo-more-info": "Méi Informatiounen",
"echo-feedback": "Feedback",
- "echo-api-failure": "D'Notifikatioune konnten net ofgeruff ginn.Probéiert nach eng Kéier. (Feeler $1)",
+ "echo-popup-footer-special-page-invitation": "<strong>Probéiert déi nei Notifikatiouns-Säit aus.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Mat neiem Look an neie Funktiounen",
+ "echo-api-failure": "D'Notifikatioune konnten net ofgeruff ginn.",
+ "echo-api-failure-cross-wiki": "Den Zougang op d'Remote-Domain gouf net erlaabt.",
"echo-notification-placeholder": "Et si keng Notifikatiounen do.",
+ "echo-notification-placeholder-filters": "Et gëtt keng Notifikatiounen déi dëse Kritären entspriechen.",
+ "echo-notification-loginrequired": "Dir musst Iech alogge fir Är Notifikatiounen ze gesinn.",
+ "echo-notification-popup-loginrequired": "Loggt Iech w.e.g. a fir Är Notifikatiounen ze gesinn.",
+ "echo-notification-markasread": "Als geliest markéieren",
+ "echo-notification-markasunread": "Als net-geliest markéieren",
+ "echo-notification-markasread-tooltip": "Als gelies markéieren",
+ "echo-notification-more-options-tooltip": "Méi Optiounen",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Ophalen}} nei Aktivitéiten iwwer \"$1\" z'iwwerwaachen",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Dir}} iwwerwaacht d'Säit \"$1\" net méi",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Dir}} kënnt [$2 dës Säit] zu all Ament iwwerwaachen.",
+ "notification-dynamic-actions-watch": "Iwwer nei Aktivitéiten zu \"$1\" {{GENDER:$3|informéiert}} ginn",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Dir}} iwwerwaacht elo d'Säit \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Dir}} kënnt zu all Ament ophalen [$2 dës Säit] z'iwwerwaachen.",
+ "notification-link-text-expand-all": "Opklappen",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|Eng Warnung|$1 Warnunge}} weisen",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|Eng Notifikatioun|$1 Notifikatioune}} weisen",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|Eng Notifikatioun|$1 Notifikatiounen}} weisen",
+ "notification-link-text-collapse-all": "Zesummeklappen",
"notification-link-text-view-message": "Message weisen",
"notification-link-text-view-mention": "Mentioun weisen",
- "notification-link-text-view-changes": "Ännerunge weisen",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Mentioun|Mentioune}} weisen",
+ "notification-link-text-view-changes": "Ännerunge {{GENDER:$1|weisen}}",
"notification-link-text-view-page": "Säit weisen",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|huet}} e Message op <strong>{{GENDER:$3|Är}} Diskussiounssäit</strong> gesat.",
+ "notification-header-edit-user-talk-with-section": "$1 huet {{GENDER:$2|Iech}} e Message op <strong>{{GENDER:$3|Ärer}} Diskussiounssäit</strong> an \"<strong>$4</strong>\" geschriwwen.",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Et gouf e Link vu(n) <strong>$4</strong> op <strong>$3</strong> gemaach.",
+ "notification-compact-header-page-linked": "Vu(n) <strong>$1</strong> verlinkt.",
+ "notification-bundle-header-page-linked": "Linke goufe vun {{PLURAL:$5||$5 Säiten|100=méi wéi 99 anere Säiten}} op <strong>$3</strong> gemaach.",
+ "notification-link-text-what-links-here": "All Linken op dës Säit",
+ "notification-header-mention-other": "$1 huet {{GENDER:$3|Iech}} op <strong>$4</strong> an \"<strong>$5</strong>\" {{GENDER:$2|mentionnéiert}}.",
+ "notification-header-mention-other-nosection": "$1 huet {{GENDER:$3|Iech}} op <strong>$4</strong> {{GENDER:$2|ernimmt}}",
+ "notification-header-mention-user-talkpage-v2": "$1 huet {{GENDER:$3|Iech}} op der <strong>Benotzerdiskussiounssäit {{GENDER:$5|vum}} $4</strong> an \"<strong>$6</strong>\" {{GENDER:$2|mentionnéiert}}.",
+ "notification-header-mention-user-talkpage-nosection": "$1 huet {{GENDER:$3|Iech}} op der <strong>Benotzerdiskusiiounssäit {{GENDER:$5|vum}} $4</strong> {{GENDER:$2|mentionnéiert}}.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|huet}} {{GENDER:$3|Iech}} op <strong>{{GENDER:$2|senger|hirer}} Diskussiounssäit</strong> iwwer ''<strong>$4</strong>'' ernimmt.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 huet {{GENDER:$3|Iech}} op <strong>{{GENDER:$2|senger|hirer|senger}} Diskussiounssäit</strong> {{GENDER:$2|mentionnéiert}}.",
+ "notification-header-mention-article-talkpage": "$1 huet {{GENDER:$3|Iech}} op der Diskussiounssäit <strong>$4</strong> an \"<strong>$5</strong>\" {{GENDER:$2|mentionnéiert}}.",
+ "notification-header-mention-article-talkpage-nosection": "$1 huet {{GENDER:$3|Iech}} op der Diskussiounssäit <strong>$4</strong> {{GENDER:$2|mentionnéiert}}.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Är}} Mentioun vum <strong>$3</strong> gouf net geschéckt well de Benotzer net fonnt gouf.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Är}} Mentioun vum <strong>$3</strong> gouf net geschéckt well de Benotzer anonym ass.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Dir}} hutt probéiert fir méi wéi $3 {{PLURAL:$3|Brnotzer}} z'ernimmen. All Mentiounen iwwer där Limite goufen net geschéckt.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Eng Mentioun|$3 Mentiounen}} déi {{GENDER:$2|Dir}} op der Diskussiounssäit <strong>$4</strong> gemaach hutt {{PLURAL:$3|konnt|konnten}} net geschéckt ginn.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Benotzernumm gëtt et net:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Ip'e kënnen net ernimmt ginn:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Är}} Mentioun vu(n) <strong>$3</strong> gouf geschéckt.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Eng Mentioun|$3 Mentiounen}} déi {{GENDER:$2|Dir}} op der Diskussiounssäit <strong>$4</strong> gemaach hutt {{PLURAL:$3|gouf|goufe}} geschéckt.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Dir}} hutt mentionnéiert:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Eng Notifikatioun|$3 Notifikatioune}} vu Mentiounen déi {{GENDER:$2|Dir}} op der Diskussiounssäit <strong>$4</strong> ge4maach hutt: {{PLURAL:$5|$5 gouf geschéckt|goufe geschéckt}}, {{PLURAL:$6|$6 geschéckt}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Är}} Benotzerrechter goufe {{GENDER:$1|geännert}}. Dir sidd elo Member vun: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Är}} Benotzerrechter goufe {{GENDER:$1|geännert}}. Dir sidd net méi Member vun: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Är}} Benotzerrechter goufe {{GENDER:$1|geännert}}. Dir sidd elo Member vun: $2. Dir sidd net méi Member vun: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Wëllkomm}} op {{SITENAME}}, $1! Mir si frou, datt {{GENDER:$2|Dir}} do sidd.",
+ "notification-welcome-linktext": "Wëllkomm",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Dir}} hutt elo grad {{GENDER:$2|Är}} éischt Ännerung op {{SITENAME}} gemaach; Villmools {{GENDER:$2|Merci}}, a wëllkomm!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Dir}} hutt elo grad {{GENDER:$2|Är}} zéngst Ännerung gemaach; Villmools {{GENDER:$2|Merci}}, a maacht esou weider!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Dir}} hutt elo grad {{GENDER:$2|Är}} honnertst Ännerung gemaach; Villmools {{GENDER:$2|Merci}}!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Dir}} hutt elo grad {{GENDER:$2|Är}} dausendst Ännerung gemaach; Villmools {{GENDER:$2|Merci}}! Dir sidd e gudde Mataarbechter!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Dir}} hutt elo grad {{GENDER:$2|Är}} zengdausendst Ännerung gemaach; Villmools {{GENDER:$2|Merci}}!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Dir}} hutt elo grad {{GENDER:$2|Är}} honnertdausendst Ännerung gemaach; Villmools {{GENDER:$2|Merci}}! Dir sidd e fantastesche Mataarbechter!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Dir}} hutt elo grad {{GENDER:$2|Är}} milliounst Ännerung gemaach; Villmools {{GENDER:$2|Merci}}fir Ären erstaunleche Beitrag!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Är}} Ännerung",
"notification-link-text-view-edit": "Ännerung weisen",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|huet}} op Är [[User talk:$2#$3|Diskussiounssäit]] geschriwwen.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|huet}} e Message op Ärer Diskussiounssäit ënner \"[[User talk:$2#$3|$4]]\" hannerlooss.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|huet}} op Är [[User talk:$2#$3|Diskussiounssäit]] geschriwwen.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|huet}} e Message op Ärer Diskussiounssäit ënner \"[[User talk:$2#$3|$4]]\" hannerlooss.",
- "notification-page-linked": "[[:$2]] gouf vun [[:$3]] {{GENDER:$1|verlinkt}}. [[Special:WhatLinksHere/$2|Kuckt all Linken op dës Säit]].",
- "notification-page-linked-flyout": "[[:$2]] gouf vun der Säit [[:$3]] {{GENDER:$1|verlinkt}}.",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|huet}} eng Bemierkung iwwer \"[[$3|$2]]\" op der \"$4\" Diskussiounssäit geschriwwen.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|huet}} en neit Thema \"$2\" op [[$3]] ugefaang.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|huet}} Iech ee Message geschéckt: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|huet}} op \"[[$3#$2|$2]]\" op Ärer Diskussiounssäit eng Bemierkung gemaach",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|huet}} Iech op der $5 Diskussiounssäit bei \"[[:$3#$2|$4]]\" ernimmt.",
- "notification-mention-flyout": "$1 {{GENDER:$1|huet}} Iech op der $5 Diskussiounssäit bei \"[[:$3#$2|$4]]\" ernimmt.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|huet}} Iech op der [[:$3|$2 Diskussiounssäit]] ernimmt.",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|huet}} Iech op der [[:$3|$2 Diskussiounssäit]] ernimmt.",
- "notification-user-rights": "Är Benotzerrechter [[Special:Log/rights/$1|goufe vum [[User:$1|$1]] {{GENDER:$1|geännert}}]]. $2. [[Special:ListGroupRights|Fir méi ze wëssen]]",
- "notification-user-rights-flyout": "Är Benotzerrechter goufe vum $1 {{GENDER:$1|geännert}}. $2. [[Special:ListGroupRights|Fir méi ze wëssen]]",
- "notification-user-rights-add": "Dir sidd elo Member vun {{PLURAL:$2|dësem Grupp|dëse Gruppen}}: $1",
- "notification-user-rights-remove": "Dir sidd net méi Member vun {{PLURAL:$2|dësem Grupp|dëse Gruppen}}: $1",
- "notification-new-user": "Wëllkomm op {{SITENAME}}, $1! Mir si frou Iech begréissen ze kënnen.",
- "notification-reverted2": "Är {{PLURAL:$4|Ännerung vu(n) [[:$2]] gouf|Ännerunge vu(n) [[:$2]] goufe}} vum [[User:$1|$1]] {{GENDER:$1|zréckgesat}}. $3",
- "notification-reverted-flyout2": "Är {{PLURAL:$4|Ännerung op $2 gouf|Ännerungen op $2 goufe}} vum $1 {{GENDER:$1|zréckgesat}} $3.",
+ "notification-link-article-reminder": "Säit weisen",
+ "notification-header-reverted": "Är {{PLURAL:$4|Ännerung op <strong>$3</strong> gouf|Ännerungen op <strong>$3</strong> goufen}} {{GENDER:$2|zréckgesat}}.",
+ "notification-header-emailuser": "$1 huet {{GENDER:$2|Iech}} eng E-Mail geschéckt.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|huet}} Iech en neie Message op Ärer Diskussiounssäit op {{SITENAME}} hannerlooss",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|huet}} ee Message op Är Diskussiounssäit geschriwwen.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|huet}} ee Message op Är Diskussiounssäit op \"$2\" geschriwwen.",
"notification-page-linked-email-subject": "Eng Säit déi Dir op {{SITENAME}} ugeluecht hutt gouf verlinkt",
- "notification-page-linked-email-batch-body": "$2 gouf vu(n) $3 {{GENDER:$1|verlinkt}}.",
"notification-reverted-email-subject2": "Är {{PLURAL:$3|Ännerung|Ännerungen}} op {{SITENAME}} {{PLURAL:$3|gouf|goufen}} {{GENDER:$1|zréckgesat}}",
- "notification-reverted-email-batch-body2": "Är {{PLURAL:$3|Ännerung vu(n) $2 gouf|Ännerunge vu(n) $2 goufe}} vum $1 {{GENDER:$1|zréckgesat}}.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|huet}} Iech op {{SITENAME}} ernimmt",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|huet}} Iech op der $4 Diskussiounssäit ernimmt bei \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|huet}} Iech op der $2 Diskussiounssäit ernimmt.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|huet}} {{GENDER:$2|Iech}} op {{SITENAME}} ernimmt",
"notification-user-rights-email-subject": "Är Benotzerrechter op {{SITENAME}} hu geännert",
- "notification-user-rights-email-batch-body": "Är Benotzerrechter goufe vum $1 {{GENDER:$1|geännert}}. $2",
- "echo-email-subject-default": "Nei Notifikatioun op {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|En Sekonn|$1 Sekonnen}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|Eng Minutt|$1 Minutten}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|Eng Stonn|$1 Stonnen}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|Een Dag|$1 Deeg}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|Ee Mount|$1 Méint}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|Ee Joer|$1 Joer}}",
+ "notification-timestamp-today": "Haut",
+ "notification-timestamp-yesterday": "Gëschter",
+ "notification-inbox-filter-read": "Geliest",
+ "notification-inbox-filter-unread": "Net geliest",
+ "notification-inbox-filter-all": "All",
"echo-email-body-default": "Dir hutt eng nei Notifikatioun op {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Dir hutt eng Notifikatioun",
+ "echo-email-footer-default-html": "Fir ze kontrolléiere wat fir eng E-Maile mir Iech schécken, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">kuckt an Ären Astellungen</a><br />\n$1",
"echo-email-footer-default": "$2\n\nFir ze kontrolléiere wat fir eng E-Maile mir Iech schécken, kuckt Är Preferenzen no:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Fir ze kontrolléieren, watfir E-Maile mir Iech schécken, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">kuckt Är Astellungen no</a>.<br />\n$1",
+ "echo-email-plain-footer": "Fir ze kontrolléiere wat fir eng E-Mailen mir {{GENDER:$1|Iech}} schécken, kuckt an {{GENDER:$1|Ären}} Astellungen:",
+ "echo-email-html-footer-preference-link-text": "kuckt {{GENDER:$1|Är}} Astellungen no",
+ "echo-email-html-footer-with-link": "Fir ze kontrolléiere wat fir eng E-Mailen mir {{GENDER:$2|Iech}} schécken, $1.",
"echo-notification-alert": "{{PLURAL:$1|Warnung ($1)|Warnungen ($1)|100=Warnungen (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Message ($1)|Messagen ($1)|100=Messagen (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notifikatioun ($1)|Notifikatiounen ($1)|100=Notifikatiounen (méi wéi 99)}}",
"echo-notification-alert-text-only": "Warnungen",
- "echo-notification-message-text-only": "Messagen",
+ "echo-notification-notice-text-only": "Notifikatiounen",
"echo-overlay-link": "All Notifikatiounen",
"echo-overlay-title": "<b>Notifikatiounen</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notifikatioun|Notifikatiounen}}</b> (weist $1 vun $2 net geliesten)",
"echo-mark-all-as-read": "All als geliest markéieren",
+ "echo-mark-all-as-read-confirmation": "{{PLURAL:$1|Eng Notifikatioun|$1 Notifikatiounen}} als geliest markéiert",
+ "echo-mark-wiki-as-read": "An der erausgesichter Wiki all als geliest markéieren: $1",
"echo-date-today": "Haut",
"echo-date-yesterday": "Gëschter",
"echo-load-more-error": "Am Sichen no méi Resultater ass e Feeler geschitt.",
- "notification-edit-talk-page-bundle": "$1 a(n) $3 {{PLURAL:$4|een anere|$3 anerer}} {{GENDER:$1|hunn}} ee Message op Är [[User talk:$2|Diskussiounssäit]] geschriwwen.",
- "notification-page-linked-bundle": "$2 gouf vu(n) $3 an nach {{PLURAL:$5|enger anerer Säit|$4 anere Säite}} {{GENDER:$1|verlinkt}}. [[Special:WhatLinksHere/$2|All Linken op dës Säit weisen]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 a(n) {{PLURAL:$3|een anere|$2 aner}} Benotzer {{GENDER:$1|hunn}} ee Message op Är Diskussiounssäit geschriwwen.",
- "notification-page-linked-email-batch-bundle-body": "$2 gouf vu(n) $3 a(n) {{PLURAL:$5|enger anerer Säit|$4 anere Säite}} {{GENDER:$1|verlinkt}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Een neie Message|$1 nei Messagen|100=méi wéi 99 Messagen}} op <strong>{{GENDER:$3|Ärer}} Diskussiounssäit</strong>.",
"echo-email-batch-subject-daily": "Dir hutt haut {{PLURAL:$2|eng nei Notifikatioun|nei Notifikatiounen}} op {{SITENAME}}",
"echo-email-batch-subject-weekly": "Dir hutt dës Woch {{PLURAL:$2|eng nei Notifikatioun|nei Notifikatiounen}} op {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Salut $1,\n\nHei ass e Resumé vun den Aktivitéite vun haut op {{SITENAME}} fir Iech.",
"echo-email-batch-body-intro-weekly": "Salut $1,\n\nHei ass e Resumé vun den Aktivitéite vun dëser Woch op {{SITENAME}} fir Iech.",
"echo-email-batch-link-text-view-all-notifications": "All Notifikatioune weisen",
- "echo-rev-deleted-text-view": "Dës Versioun vun der Säit gouf geläscht.",
- "apihelp-echomarkread-param-sections": "Eng Lëscht vun den Abschnitter déi als geliest markéiert solle ginn.",
- "apihelp-echomarkseen-description": "Notifikatioune fir den aktuelle Benotzer als geliest markéieren.",
- "apihelp-echomarkseen-example-1": "Notifikatiounen vun all Typ als geliest markéieren",
- "apihelp-query+notifications-param-prop": "Detailer fir unzefroen."
+ "notification-header-foreign-alert": "Méi Warnunge {{PLURAL:$5|vun enger anerer Wiki|vu(n) $5 anere Wikien}}",
+ "notification-header-foreign-notice": "Méi Notifikatiounen aus {{PLURAL:$5|enger anere Wiki|$5 anere Wikien}}",
+ "notification-header-foreign-all": "Méi Notifikatioune {{PLURAL:$5|vun enger anerer Wiki|vu(n) $5 anere Wikien}}"
}
diff --git a/Echo/i18n/lfn.json b/Echo/i18n/lfn.json
new file mode 100644
index 00000000..d654456c
--- /dev/null
+++ b/Echo/i18n/lfn.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cgboeree"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Tua}} avisas"
+}
diff --git a/Echo/i18n/li.json b/Echo/i18n/li.json
new file mode 100644
index 00000000..d75e6642
--- /dev/null
+++ b/Echo/i18n/li.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ooswesthoesbes"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Dien}} meljinge"
+}
diff --git a/Echo/i18n/lij.json b/Echo/i18n/lij.json
new file mode 100644
index 00000000..72bb0b2e
--- /dev/null
+++ b/Echo/i18n/lij.json
@@ -0,0 +1,131 @@
+{
+ "@metadata": {
+ "authors": [
+ "Giromin Cangiaxo"
+ ]
+ },
+ "echo-desc": "Scistema pe notificâ a-i utenti messaggi e eventi",
+ "prefs-echo": "Notiffiche",
+ "prefs-emailsettings": "Opçioin e-mail",
+ "prefs-displaynotifications": "Opçioin de vixualizaçion",
+ "prefs-echosubscriptions": "Mandime 'na notiffica insce questi eventi",
+ "prefs-echocrosswiki": "Notiffiche cross-wiki",
+ "prefs-newmessageindicator": "Indicatô di noeuvi messaggi",
+ "echo-pref-send-me": "Mandime:",
+ "echo-pref-send-to": "Manda a:",
+ "echo-pref-email-format": "Formato e-mail:",
+ "echo-pref-web": "Web",
+ "echo-pref-email": "E-mail",
+ "echo-pref-email-frequency-never": "No inviâme de notiffiche pe e-mail",
+ "echo-pref-email-frequency-immediately": "Notiffiche scingole amanaman ch'arivan",
+ "echo-pref-email-frequency-daily": "Un riepillogo cotidian de notiffiche",
+ "echo-pref-email-frequency-weekly": "Un riepillogo settemanâ de notiffiche",
+ "echo-pref-email-format-html": "HTML",
+ "echo-pref-email-format-plain-text": "Testo normale",
+ "echo-pref-cross-wiki-notifications": "Mostra notiffiche da atri wiki",
+ "echo-pref-new-message-indicator": "Mostra inta bara di strumenti l'indicatô pe-i noeuvi messaggi da mæ paggina de discuscion",
+ "echo-pref-beta-feature-cross-wiki-message": "Notiffiche amegioæ",
+ "echo-pref-beta-feature-cross-wiki-description": "Vixualizza e organizza e notiffiche ciù façilmente. O l'includde e notiffiche cross-wiki, che te permettan de vixualizâ i messaggi da i atri wiki. (Pe riçeive e notiffiche cross-wiki insce 'n dæto wiki, ti devi attivâ a fonçion beta inte quello wiki.)",
+ "echo-learn-more": "Pe saveine de ciu",
+ "echo-log": "Registro pubbrico",
+ "echo-new-messages": "Ti g'hæ di noeuvi messaggi",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|Messaggio|Messaggi}} inta paggina de discuscion",
+ "echo-category-title-article-linked": "{{PLURAL:$1|Ingancio|Inganci}} a 'na paggina",
+ "echo-category-title-reverted": "{{PLURAL:$1|Modiffica annulâ|Modiffiche annulæ}}",
+ "echo-category-title-mention": "{{PLURAL:$1|Mençion|Mençioin}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Mençion|Mençioin}} in erô",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Mençion|Mençioin}} corrette",
+ "echo-category-title-other": "{{PLURAL:$1|Atro}}",
+ "echo-category-title-system": "{{PLURAL:$1|Scistema}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Modiffica|Modiffiche}} driti utente",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-mail da 'n atro utente|E-mail da di atri utenti}}",
+ "echo-pref-tooltip-edit-user-talk": "Notiffichime quande quarchidun me scrive un messaggio ò risponde inta mæ paggina de discuscion.",
+ "echo-pref-tooltip-article-linked": "Avvixime quande quarcun o conliga, da 'na voxe, una paggina che ho creou.",
+ "echo-pref-tooltip-reverted": "Avvixime quande quarcun o l'annulla 'na modiffica ch'ho fatto, doeuviando e fonçioin anulla ò rollback.",
+ "echo-pref-tooltip-mention": "Avixime quande quarcun o l'ingancia a mæ paggina utente.",
+ "echo-pref-tooltip-mention-failure": "Avvixime quande no ho posciuo inviâ 'na mençion a quarchedun.",
+ "echo-pref-tooltip-mention-success": "Avvixime quande invio 'na mençion a quarchedun.",
+ "echo-pref-tooltip-user-rights": "Avvixime quande quarcun o modiffica i mæ driti d'utente.",
+ "echo-pref-tooltip-emailuser": "Avvixime quande quarcun o m'invia 'n'e-mail.",
+ "echo-error-no-formatter": "Nisciun-a formattaçion definia pe-e notiffiche",
+ "notifications": "Notiffiche",
+ "tooltip-pt-notifications-alert": "{{GENDER:|I teu}} avixi",
+ "tooltip-pt-notifications-notice": "{{GENDER:|I teu}} avixi",
+ "echo-displaynotificationsconfiguration": "Mostra a configuaçion de notiffiche",
+ "echo-displaynotificationsconfiguration-summary": "Questa a l'è 'na panorammica de comme e notiffiche son configuæ insce questo wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notiffiche pe categoria",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Ordenamento di tipi",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Inte quæ seçion l'è amerçou ogni tipo de notiffica",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Mettodi de notifica consentii",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Quæ mettodi de notiffica son supportæ pe ogni categoria",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Quæ mettodi de notiffica son supportæ pe ogni tipo; a s'apprica solo a-i tipi che, inte categorie, son nascosti da-e preferençe",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Abilitou pe impostaçion predefinia",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Utenti existenti",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Noeuvi utenti",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Metodi de notiffica obrigatoi",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Quæ mettodi de notiffica son obrigatoi pe ogni categoria",
+ "echo-specialpage": "Notiffiche",
+ "echo-specialpage-section-markread": "Marca groppo comme lezuo",
+ "echo-specialpage-markasread": "Notiffica: marca comme lezua",
+ "echo-specialpage-markasread-invalid-id": "ID evento non vallido",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notiffica|notiffiche}}",
+ "echo-specialpage-pagefilters-title": "Attivitæ reçente",
+ "echo-specialpage-pagefilters-subtitle": "Paggine con notiffiche non lezue",
+ "notificationsmarkread-legend": "Contrasegna a notiffica comme lezua",
+ "echo-anon": "Pe riçeive e notiffiche, [$1 registrite] ò [$2 accedi].",
+ "echo-none": "Notiffiche no ti ghe n'hæ .",
+ "echo-more-info": "Atre informaçioin",
+ "echo-feedback": "Commenti",
+ "echo-popup-footer-special-page-invitation": "<strong>Proeuva a noeuva paggina de notiffiche.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Noeuve presentaçioin e fonçionalitæ.",
+ "echo-api-failure": "No l'è stæto poscibbile recuperâ e notiffiche.",
+ "echo-api-failure-cross-wiki": "L'accesso a-o dominnio remoto o l'è stæto negou.",
+ "echo-notification-placeholder": "Notiffiche no ghe n'è.",
+ "echo-notification-placeholder-filters": "No gh'è de notiffiche che corrispondan a sti critei.",
+ "echo-notification-loginrequired": "Ti devi effettoâ l'accesso pe vedde e to notiffiche.",
+ "echo-notification-popup-loginrequired": "Effettoa l'accesso pe vixualizâ e to notiffiche.",
+ "echo-notification-markasread": "Marca comme zà lezuo",
+ "echo-notification-markasunread": "Marca comme non lezuo",
+ "echo-notification-markasread-tooltip": "Marca comme lezuo",
+ "echo-notification-more-options-tooltip": "Atre opçioin",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Rimoeuvi}} e noeuve attivitæ insce \"$1\" da-i oservæ speciali",
+ "notification-dynamic-actions-unwatch-confirmation": "A paggina \"$1\" no {{GENDER:$3|ti}} l'osservi ciu",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Ti poeu}} insei [$2 sta paggina] inti oservæ speciali in qualunque momento.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Segui}} e noeuve attivitæ insce \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|T'ê}} aproeuvo a oservâ a paggina \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Ti poeu}} levâ [$2 sta paggina] da-i oservæ speciali in qualunque momento.",
+ "notification-link-text-expand-all": "Espandi",
+ "notification-link-text-expand-alert-count": "Amia {{PLURAL:$1|$1 alerta|$1 alerte}}",
+ "notification-link-text-expand-notice-count": "Mostra {{PLURAL:$1|$1 aviso|$1 avixi}}",
+ "notification-link-text-expand-all-count": "Amia {{PLURAL:$1|notiffica|notiffiche}}",
+ "notification-link-text-collapse-all": "Comprimmi",
+ "notification-link-text-view-message": "Amia messaggio",
+ "notification-link-text-view-mention": "Amia mençion",
+ "notification-link-text-view-mention-failure": "Amia {{PLURAL:$1|mençion|mençioin}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Amia}} modiffiche",
+ "notification-link-text-view-page": "Amia a paggina",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|o|a}} l'ha lasciou un messaggio insciâ <strong>{{GENDER:$3|to}} paggina de discuscion</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|o|a}} l'ha lasciou un messaggio inta <strong>{{GENDER:$3|to}} paggina de discuscion</strong> in \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "L'è stæto creou un ingancio da <strong>$4</strong> a <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Conligâ da <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "L'è stæto creou di inganci da {{PLURAL:$5||$5 paggine|100=ciù de 99 pagine}} a <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Tutti i inganci a questa paggina",
+ "notification-header-mention-other": "$1 {{GENDER:$2|o|a}} t'ha {{GENDER:$3|mençunou|mençunâ|mençunou/â}} inte <strong>$4</strong> in \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|o|a}} t'ha {{GENDER:$3|mençunou|mençunâ|mençunou/â}} inte <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|o|a}} t'ha {{GENDER:$3|mençunaou|mençunâ|mençunou/â}} inta <strong>paggina de discuscion utente {{GENDER:$5|de}} $4</strong> in \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|o|a}} t'ha {{GENDER:$3|mençunou|mençunâ|mençunou/â}} inta <strong>paggina de discuscion utente {{GENDER:$5|de}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|o|a}} t'ha {{GENDER:$3|mençunou|mençunâ|mençunou/â}} inta <strong>so pagina de discuscion</strong> in \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|o t'}}ha {{GENDER:$3|mençunou|mençunâ|mençunou/â}} inta <strong>so paggina de discuscion</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|o|a}} t'ha {{GENDER:$3|mençunou|mençunâ|mençunou/â}} inta paggina de discuscion de <strong>$4</strong> in \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|o|a}} t'ha {{GENDER:$3|mençunou|mençunâ|mençunou/â}} inta åaggina de discuscion de <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|A to}} mençion de <strong>$3</strong> a no l'è stæta inviâ perchè l'utente o no l'è stæto trovou.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|A to}} mençion de <strong>$3</strong> a no l'è stæta inviâ perché l'utente o l'è anonnimo.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|E to}} mençioin no son stæte inviæ perché han superou o limmite de $3.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Una mençion|$3 mençioin}} che {{GENDER:$2|t'hæ fæto}} inta paggina de discuscion <strong>$4</strong> {{PLURAL:$3|a no poeu ese inviâ| no poeuan ese inviæ}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>O nomme utente o no l'existe:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>I IP no poeuan ese mençunæ:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|A to}} mençion de <strong>$3</strong> a l'è stæta inviâ.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Una mençion|$3 mençioin}} che {{GENDER:$2|t'hæ fæto}} inta paggina de discuscion <strong>$4</strong> {{PLURAL:$3|a l'è stæta inviâ| son stæte inviæ}}.",
+ "notification-welcome-linktext": "Benvegnuo",
+ "echo-overlay-link": "Tutte e notiffiche"
+}
diff --git a/Echo/i18n/lki.json b/Echo/i18n/lki.json
new file mode 100644
index 00000000..ddfc94f3
--- /dev/null
+++ b/Echo/i18n/lki.json
@@ -0,0 +1,83 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hosseinblue",
+ "Reza1615",
+ "Lakzon"
+ ]
+ },
+ "echo-desc": "سامانهٔ آگاه‌سازی کاربران از رویدادها و پیام‌ها",
+ "prefs-echo": "اعلان‌ها",
+ "prefs-emailsettings": "تنظیمات ایمیل",
+ "prefs-displaynotifications": "گزینه‌های نمایش",
+ "prefs-echosubscriptions": "مرا از این رویدادها آگاه کن",
+ "prefs-newmessageindicator": "نشانگر پیام تازه",
+ "echo-pref-send-me": "برایم فرستاده شود:",
+ "echo-pref-send-to": "فرستاده‌شود به:",
+ "echo-pref-email-format": "قالب ایمیل:",
+ "echo-pref-web": "وب‌گاه",
+ "echo-pref-email": "ایمیل",
+ "echo-pref-email-frequency-never": "ایمیل اعلان‌ها برایم فرستاده نشود",
+ "echo-pref-email-frequency-immediately": "اعلان‌های جداگانه به محض دریافت",
+ "echo-pref-email-frequency-daily": "خلاصهٔ روزانهٔ اعلان‌ها",
+ "echo-pref-email-frequency-weekly": "خلاصهٔ هفتگی اعلان‌ها",
+ "echo-pref-email-format-html": "اچ‌تی‌ام‌ال",
+ "echo-pref-email-format-plain-text": "متن ساده",
+ "echo-pref-new-message-indicator": "نمایش نشانگر پیام صفحهٔ بحث در نوار ابزار من",
+ "echo-learn-more": "اطلاعات بیشتر",
+ "echo-new-messages": "پیام‌های جدیدی دارید",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|پیام|پیام‌های}} وةڵگة گةپ",
+ "echo-category-title-article-linked": "{{PLURAL:$1|پیوند|پیوندهای}} وةڵگة",
+ "echo-category-title-reverted": "{{PLURAL:$1|واگردانی|واگردانی‌های}} ویرایش",
+ "echo-category-title-mention": "{{PLURAL:$1|اشاره|اشاره‌ها}}",
+ "echo-category-title-other": "{{PLURAL:$1|دیگر}}",
+ "echo-category-title-system": "{{PLURAL:$1|سیستم}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|تغییر دسترسی‌های کاربری|تغییرات دسترسی‌های کاربری}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|ایمیل از کابری دیگر|ایمیل‌هایی از دیگر کاربران}}",
+ "echo-pref-tooltip-edit-user-talk": "وقتی کسی برایم پیام فرستاد یا جواب پیام مرا در صفحهٔ بحثم داد، مرا آگاه کن.",
+ "echo-pref-tooltip-article-linked": "وقتی کسی به مقاله‌ای که ایجاد کرده‌ام پیوند داد، مرا آگاه کن.",
+ "echo-pref-tooltip-reverted": "وقتی کسی ویرایش مرا با ابزار خثنی‌سازی یا واگردانی، خثنی کرد، مرا آگاه کن.",
+ "echo-pref-tooltip-mention": "وقتی کسی به صفحهٔ کاربری‌ام پیوند داد، مرا آگاه کن.",
+ "echo-pref-tooltip-user-rights": "وقتی کسی دسترسی‌های کاربری من را تغییر داد مرا آگاه کن.",
+ "echo-pref-tooltip-emailuser": "وقتی کسی به من ایمیل فرستاد، مرا آگاه کن.",
+ "echo-error-no-formatter": "هیچ قالبی برای آگاه‌سازی تعریف نشده‌است.",
+ "notifications": "اعلان‌ها",
+ "tooltip-pt-notifications-alert": "{{GENDER:|هۆمە}} ویردارکرەل(آگاکرەل)",
+ "echo-specialpage": "اعلان‌ها",
+ "echo-anon": "برای دریافت اعلان‌ها [$1 حساب بسازید] یا [$2 وارد سامانه شوید].",
+ "echo-none": "اعلانی ندارید.",
+ "echo-more-info": "اطلاعات بیشتر",
+ "echo-feedback": "بازخورد",
+ "echo-api-failure": "اعلان‌ها بازیابی نشد. لطفاً دوباره سعی کنید. (خطا $1)",
+ "echo-notification-placeholder": "اعلانی ندارید.",
+ "notification-link-text-view-message": "نمایش پیام",
+ "notification-link-text-view-mention": "نمایش اشاره",
+ "notification-link-text-view-changes": "گؤەڕیال(تغییرات) بۆین",
+ "notification-link-text-view-page": "وەڵگە بۆین",
+ "notification-header-welcome": "$1، به {{SITENAME}} {{GENDER:$2|خؤةش هةتین}}. خوشحالیم که {{GENDER:$2|شما}} اینجایید.",
+ "notification-welcome-linktext": "خؤةش هةتین/هاتین",
+ "notification-link-text-view-edit": "نمایش دەسکاری",
+ "notification-header-reverted": "{{PLURAL:$4|ویرایش|ویرایش‌های}}تان بر $3 را $1 {{GENDER:$2|واگردانی}} کرده‌است.",
+ "notification-header-emailuser": "$1 به شما ایمیل {{GENDER:$2|زد}}.",
+ "notification-edit-talk-page-email-subject2": "شما یک پیام تازه از طرف $1 در وةڵگة گةپ {{SITENAME}} دارید.",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 یک پیام در گةپ هؤمة در «$2» {{GENDER:$1|گذاشته‌است}}.",
+ "notification-page-linked-email-subject": "صفحه‌ای که شما آغازگر آن بودید در {{SITENAME}} پیوند شد.",
+ "notification-reverted-email-subject2": "{{PLURAL:$3|ویرایش|ویرایش‌های}} شما در {{SITENAME}} {{GENDER:$1|واگردانی شده‌است}}",
+ "notification-user-rights-email-subject": "دسترسی‌های شما در {{SITENAME}} تغییر یافته‌است",
+ "echo-email-body-default": "شما در {{SITENAME}} آگاه‌سازی تازه‌ای دارید:\n\n$1",
+ "echo-email-footer-default": "$2\n\nبرای کنترل ایمیل‌های ارسالی به شما، ترجیحات‌تان را بررسی کنید:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-notification-alert": "{{PLURAL:$1|هشدار ($1)|هشدارها ($1)|100=هشدارها (۹۹+)}}{{PLURAL:$1|}}",
+ "echo-notification-alert-text-only": "هشدارها",
+ "echo-overlay-link": "همهٔ آگاه‌سازی‌ها",
+ "echo-overlay-title": "<b>آگاه‌سازی‌ها</b>",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|آگاه‌سازی‌ها}}</b> (نمایش $1 از $2 خوانده‌نشده)",
+ "echo-mark-all-as-read": "نشان‌گذاری همه به عنوان خوانده‌شده",
+ "echo-date-today": "ایمڕۆ",
+ "echo-date-yesterday": "دؤئنۀ-دؤۀکۀ",
+ "echo-load-more-error": "دریافت نتیجه‌های بیشتر با خطا مواجه شده‌است.",
+ "echo-email-batch-subject-daily": "شما دارای {{PLURAL:$2|یک آگاه‌سازی تازه|آگاه‌سازی‌های تازه‌ای}} در {{SITENAME}} هستید",
+ "echo-email-batch-subject-weekly": "شما دارای {{PLURAL:$2|یک آگاه‌سازی تازه|آگاه‌سازی‌های تازه‌ای}} در {{SITENAME}} در این هفته هستید",
+ "echo-email-batch-body-intro-daily": "سلام $1،\nدر اینجا خلاصهٔ فعالیت امروز شما در {{SITENAME}} وجود دارد.",
+ "echo-email-batch-body-intro-weekly": "سلام $1،\nدر اینجا خلاصهٔ فعالیت این هفتهٔ شما در {{SITENAME}} وجود دارد.",
+ "echo-email-batch-link-text-view-all-notifications": "دیدن همهٔ آگاه‌سازی‌ها"
+}
diff --git a/Echo/i18n/lrc.json b/Echo/i18n/lrc.json
index 3aeb3b75..296985cd 100644
--- a/Echo/i18n/lrc.json
+++ b/Echo/i18n/lrc.json
@@ -22,7 +22,6 @@
"echo-pref-email-frequency-weekly": "یه گل چکسه هفته ای د وارسیاریا",
"echo-pref-email-format-html": "اچ تی ام ال",
"echo-pref-email-format-plain-text": "متن ساده",
- "echo-pref-notify-show-link": "وارسیاریا نه د نوار اوزار مه نشو بیه",
"echo-pref-new-message-indicator": "نشودیارکن پیغوم نه د اوزارجا بلگه چک چنه نشو بیئه",
"echo-learn-more": "بيشتر يا بيئريت",
"echo-new-messages": "شما پیغومیا تازه داریتو",
@@ -36,10 +35,7 @@
"echo-pref-tooltip-edit-user-talk": "مه نه وختی که یه نفر د بلگه چک چنم پیغوم می نه یا جواو می ئه خوردار کو.",
"echo-pref-tooltip-mention": "هرگاتی که کسی وه بلگه کاریاری مه هوم پیوند بی مه نه وارسیاری بک",
"echo-pref-tooltip-user-rights": "هرگاتی که کسی حقوق کاریاری مه نا آلشت ده مه نه وارسیاری بک.",
- "echo-no-agent": "[هیشکی]",
- "echo-no-title": "[بی بلگه]",
"notifications": "وارسیاریا",
- "tooltip-pt-notifications": "وارسیاریا شما",
"echo-specialpage": "وارسیاریا",
"echo-none": "شما هیژ وارسیاری ناریت.",
"echo-more-info": "دونسمنیا هنی",
@@ -49,49 +45,18 @@
"notification-link-text-view-changes": "دیئن آلشتیا",
"notification-link-text-view-page": "بلگه بوینیت",
"notification-link-text-view-edit": "ویرایشت نه بوینیت",
- "notification-edit-talk-page2": "[[کاریار:$1|$1]] {{GENDER:$1|یه گل پیغوم تازه }} د [[چک چنه کاریاری:$2#$3|بلگه چک چنه]] شما نیا.",
- "notification-edit-talk-page-with-section": "[[کاریار:$1|$1]] {{GENDER:$1|}} یه گل پیغوم د بلگه چک چنه شما نیا د \"[[بلگه چک چنه:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|}}یه گل پیغوم د [[چک چنه کاریار:$2#$3|بلگه چک چنه]]تو نیائه.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|}}یه گل پیغوم د بلگه چک چنه شما نیائه\" د[[چک چنه کاریار:$2#$3|$4]]\".",
- "notification-page-linked-flyout": "[[:$2]] {{GENDER:$1|هوم پیوند دئه }}سی [[:$3]].",
- "notification-add-comment2": "[[کاریار:$1|$1]] {{GENDER:$1|د}}د \"[[$3|$2]]\" د بلگه چک چنه \"$4\" نیا.",
- "notification-add-talkpage-topic-yours2": "[[کاریار:$1|$1]] {{GENDER:$1|}} یه گل پیغوم سی شما کل کرد: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[کاریار:$1|$1]] {{GENDER:$1|د}}د \"[[$3|$2]]\" د بلگه چک چنه \"$4\" نیا.",
- "notification-mention-nosection": "[[کاریار:$1|$1]] {{GENDER:$1|گوته }} د [[:$3|$2 بلگه چک چنه]] شما.$2",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|گوته بیه}} د [[:$3|$2 بلگه چک چنه شما]].",
- "notification-user-rights": "حقوق کاریاری تو [[ویجه:پهرستنومه/حقوق/$1|بیه {{GENDER:$1|آلشت بیه }}]] وا [[کارور:$1|$1]]. $2. [[ویجه:نوم گه حقوق گرو|بیشتر بفئمید]]",
- "notification-user-rights-add": "شما ایسه اندوم{{PLURAL:$2|ای دسه|ای دسه یا}} هیئت: $1",
- "notification-new-user": "خوش اومایت د {{نوم سیل جا}}, $1! ایما خوشالیم که ایسه هایتیت ایچه.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|یه گل پیغوم}} د {{نوم دیارگه}} نیائه.",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|یه گل پیغوم د بلگه چک چنه شما}} نیائه:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|یه گل پیغوم د بلگه چک چنه شما د \"$2\"}} نیائه.",
"notification-page-linked-email-subject": "بلگه شما د {{نوم مالگه}} هوم پیوند بیه",
- "notification-page-linked-email-batch-body": "$2 {{GENDER:$1|هوم پیوند کرده}} سی$3.",
"notification-mention-email-subject": "$1 {{GENDER:$1|گوته}} د {{SITENAME}} شما",
"notification-user-rights-email-subject": "حقوق کاریاری شما د {{نوم دیارگه}} آلشت دئیه بیه",
- "notification-user-rights-email-batch-body": "حقوق کاریاری شما {{GENDER:$1|آلشت بیه}} وه دس $1. $2.",
- "echo-email-subject-default": "یه گل وارسیاری تازه د {{SITENAME}}",
"echo-email-body-default": "شما یه گل وارسیاری تاز د {{SITENAME}} داریتو\n\n$1",
- "echo-email-batch-body-default": "شما یه گل وارسیاری تازه داریت.",
- "echo-notification-message": "{{PLURAL:$1|پیغوم($1)|پیغومیا($1)|100=پیغومیا(99+)}}",
"echo-notification-alert-text-only": "زئناریا",
- "echo-notification-message-text-only": "پيغومیا",
"echo-overlay-link": "همه وارسیاریا",
"echo-overlay-title": "<b>وارسیاریا</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|وارسیاری یا}}</b> (نشو دئه $1 د $2 حنه نبیه)",
"echo-mark-all-as-read": "همه نه د عنوان حنه بیه نشو بیه",
"echo-date-today": "امرو",
"echo-date-yesterday": "دوش،دیرو",
- "echo-email-batch-link-text-view-all-notifications": "همه وارسیاریانه بوینیت",
- "echo-rev-deleted-text-view": "وانئری ای بلگه پاکساگری بیه.",
- "apihelp-echomarkread-description": "نشودار کردن وارسیاریا چی حنه بیه یا سی کاریاری ایسنی.",
- "apihelp-echomarkread-param-sections": "نومجایی د بهرجایایی که چی حنه بیه نشودار بیه.",
- "apihelp-echomarkread-example-1": "هشت گله وارسیاری نه چی حنه بیه یا نشودار بک",
- "apihelp-echomarkread-example-2": "همه وارسیاری یا نه چی حنه بیه یا نشودار بک",
- "apihelp-query+notifications-description": "وارسیاری آهره داری کردن سی کاریار ایسنی نه وه دس بئیرت.",
- "apihelp-query+notifications-param-prop": "جزئیات حاسته بیه.",
- "apihelp-query+notifications-param-sections": "بهرجایا وارسیاری سی پورس کردن.",
- "apihelp-query+notifications-param-limit": "بیشترونه شماره وارسیاریا سی ؤرئشتن",
- "apihelp-query+notifications-param-alertunreadfirst": "آیا اول وارسیاریا پیغومیا نحنه نه نشو بیه.",
- "apihelp-query+notifications-example-1": "نومجا وارسیاریا"
+ "echo-email-batch-link-text-view-all-notifications": "همه وارسیاریانه بوینیت"
}
diff --git a/Echo/i18n/lt.json b/Echo/i18n/lt.json
index 45b2928b..57744400 100644
--- a/Echo/i18n/lt.json
+++ b/Echo/i18n/lt.json
@@ -4,14 +4,17 @@
"Eitvys200",
"Hugo.arg",
"Mantak111",
- "Albertas"
+ "Albertas",
+ "Zygimantus",
+ "Macofe",
+ "Homo"
]
},
"echo-desc": "Sistema, skirta naudotojų informavimui apie įvykius ir žinutes",
"prefs-echo": "Pranešimai",
"prefs-emailsettings": "El. pašto nustatymai",
"prefs-displaynotifications": "Rodymo nuostatos",
- "prefs-echosubscriptions": "Praneškite man apie šiuos įvykius",
+ "prefs-echosubscriptions": "Pranešti man apie šiuos įvykius",
"prefs-newmessageindicator": "Naujų žinučių indikatorius",
"echo-pref-send-me": "Siųskite man:",
"echo-pref-send-to": "Siųsti:",
@@ -24,116 +27,172 @@
"echo-pref-email-frequency-weekly": "Per savaitę gautų pranešimų sąvadas",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Paprastas tekstas",
+ "echo-pref-cross-wiki-notifications": "Rodyti pranešimus iš kitų viki",
"echo-pref-new-message-indicator": "Rodyti ženklą mano įrankių juostoje apie aptarimų puslapyje gautą pranešimą",
+ "echo-pref-beta-feature-cross-wiki-message": "Papildyti pranešimai",
+ "echo-pref-beta-feature-cross-wiki-description": "Peržiūrėkite ir organizuokite pranešimus lengviau. Įeina tarp-vikiniai pranešimai, kurie leidžia matyti žinutes iš kitų vikių.",
"echo-learn-more": "Sužinokite daugiau",
+ "echo-log": "Viešas žurnalas",
"echo-new-messages": "Turite naujų žinučių",
- "echo-category-title-edit-user-talk": "Aptarimo puslapis {{PLURAL:$1|žinutė|žinutės}}",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|Pranešimas|Pranešimai}} aptarimų puslapyje",
"echo-category-title-article-linked": "Puslapio {{PLURAL:$1|nuoroda|nuorodos}}",
- "echo-category-title-reverted": "Redaguoti {{PLURAL:$1|atstatyti|atstatymai}}",
+ "echo-category-title-reverted": "Pakeitimų {{PLURAL:$1|atmetimas|atmetimai}}",
"echo-category-title-mention": "{{PLURAL:$1|Paminėjimas|Paminėjimai}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Nepavykęs paminėjimas|Nepavykę paminėjimai}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Pavykęs paminėjimas|Pavykę paminėjimai}}",
"echo-category-title-other": "{{PLURAL:$1|Kiti}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Naudotojo teisių pakeitimas|Naudotojo teisių pakeitimai}}",
- "echo-pref-tooltip-edit-user-talk": "Tebūnie pranešta, kai kas nors palieka naują žinutę ar atsakymą mano aptarimų puslapyje.",
- "echo-pref-tooltip-article-linked": "Tebūnie pranešta, kai kas nors straipsnyje sukuria nuorodą į mano rašytą straipsnį.",
- "echo-pref-tooltip-reverted": "Tebūnie pranešta, kai kas nors atmeta mano pakeitimus naudodamasis atmetimo ir atšaukimo įrankiais.",
- "echo-pref-tooltip-mention": "Tebūnie pranešta, kai kas nors sukuria nuorodą į mano naudotojo puslapį.",
- "echo-pref-tooltip-user-rights": "Tebūnie pranešta, kai kas nors pakeičia mano naudotojo teises.",
- "echo-no-agent": "[Niekas]",
- "echo-no-title": "[Nėra puslapio]",
+ "echo-category-title-emailuser": "{{PLURAL:$1|El. laiškas iš kito naudotojo|El. laiškai iš kitų naudotojų}}",
+ "echo-category-title-article-reminder": "Puslapio priminimai",
+ "echo-pref-tooltip-edit-user-talk": "Pranešti man, kai kas nors parašo žinutę ar atsako mano aptarimo puslapyje.",
+ "echo-pref-tooltip-article-linked": "Pranešti man, kai kas nors sukuria nuorodą iš straipsnio į mano sukurtą puslapį.",
+ "echo-pref-tooltip-reverted": "Pranešti man, kai kas nors atmeta mano pakeitimus, naudodamasis atmetimo ar atšaukimo įrankiais.",
+ "echo-pref-tooltip-mention": "Pranešti man, kai kas nors sukuria nuorodą į mano naudotojo puslapį.",
+ "echo-pref-tooltip-mention-failure": "Pranešti man, kai aš kažkam negaliu išsiųsti paminėjimo.",
+ "echo-pref-tooltip-mention-success": "Pranešti man, kai aš kažkam išsiunčiu paminėjimą.",
+ "echo-pref-tooltip-user-rights": "Pranešti man, kai kas nors pakeičia mano naudotojo teises.",
+ "echo-pref-tooltip-emailuser": "Pranešti, kai kas nors atsiunčia man el. laišką.",
"echo-error-no-formatter": "Pranešimo formatavimas nėra apibrėžtas.",
"notifications": "Pranešimai",
"tooltip-pt-notifications-alert": "{{GENDER:|Jūsų}} perspėjimai",
- "tooltip-pt-notifications-message": "{{GENDER:|Jūsų}} žinutės",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Jūsų}} pranešimai",
+ "echo-displaynotificationsconfiguration": "Rodyti Pranešimų konfigūraciją",
+ "echo-displaynotificationsconfiguration-summary": "Tai yra Pranešimų konfigūracijos šioje viki apžvalga.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Pranešimai pagal kategoriją",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Tipų rūšiavimas",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Į kurį skyrių kiekvienas pranešimų tipas yra rūšiuojamas",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Leidžiami pranešimo metodai",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Kokie pranešimų metodai yra palaikomi kiekvienai kategorijai",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Kokie pranešimų metodai yra palaikomi kiekvienam tipui; taikoma tik tipams, kurie yra kategorijose, bet paslėpti nuo pasirinkčių",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Įjungta pagal nutylėjimą",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Esami naudotojai",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nauji naudotojai",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Privalomi pranešimų metodai",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Kokie pranešimų metodai yra privalomi kiekvienai kategorijai",
"echo-specialpage": "Pranešimai",
+ "echo-specialpage-section-markread": "Žymėti grupę kaip skaityta",
+ "echo-specialpage-markasread": "Pranešimas: žymėti kaip skaityta",
+ "echo-specialpage-markasread-invalid-id": "Negalimas įvykio ID",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|pranešimas|pranešimai}}",
+ "echo-specialpage-pagefilters-title": "Naujausia veikla",
+ "echo-specialpage-pagefilters-subtitle": "Puslapiai su neskaitytais pranešimais",
+ "notificationsmarkread-legend": "Žymėti pranešimą kaip perskaityta",
"echo-anon": "Norėdami gauti pranešimus [$1 susikurkite paskyrą] arba [$2 prisijunkite].",
"echo-none": "Jūs turite jokių pranešimų.",
"echo-more-info": "Daugiau informacijos",
"echo-feedback": "Atsiliepimas",
+ "echo-popup-footer-special-page-invitation": "<strong>Išbandykite naują Pranešimų puslapį.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Nauja išvaizda ir galimybės.",
+ "echo-api-failure": "Nepavyko gauti pranešimų.",
+ "echo-api-failure-cross-wiki": "Prieiga prie nuotolinio domeno buvo atmesta.",
+ "echo-notification-placeholder": "Pranešimų nėra.",
+ "echo-notification-placeholder-filters": "Nėra pranešimų, kurie atitinka šiuos kriterijus.",
+ "echo-notification-loginrequired": "Turite prisijungti, kad matytumėte pranešimus.",
+ "echo-notification-popup-loginrequired": "Prašome prisijungti, kad peržiūrėtumėte pranešimus.",
+ "echo-notification-markasread": "Žymėti kaip perskaitytą",
+ "echo-notification-markasunread": "Žymėti neskaitytu",
+ "echo-notification-markasread-tooltip": "Žymėti skaitytu",
+ "echo-notification-more-options-tooltip": "Daugiau nustatymų",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Nebesekti}} naujos „$1“ veiklos",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Jūs}} nebesekate puslapio „$1“",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Jūs}} galite sekti [$2 šį puslapį] bet kada.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Sekti}} naują „$1“ veiklą",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Jūs}} dabar sekate puslapį „$1“",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Jūs}} galite nebesekti [$2 šio puslapio] bet kada.",
+ "notification-link-text-expand-all": "Išplėsti",
+ "notification-link-text-expand-alert-count": "Išplėsti {{PLURAL:$1|$1 įspėjimą|$1 įspėjimus}}",
+ "notification-link-text-expand-notice-count": "Peržiūrėti {{PLURAL:$1|$1 pranešimą|$1 pranešimus}}",
+ "notification-link-text-expand-all-count": "Žiūrėti {{PLURAL:$1|$1 pranešimą|$1 pranešimus}}",
+ "notification-link-text-collapse-all": "Suskleisti",
"notification-link-text-view-message": "Peržiūrėti žinutę",
"notification-link-text-view-mention": "Peržiūrėti paminėjimą",
- "notification-link-text-view-changes": "Peržiūrėti pakeitimus",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Žiūrėti paminėjimą|Žiūrėti paminėjimus}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Žiūrėti}} keitimus",
"notification-link-text-view-page": "Peržiūrėti puslapį",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|paliko}} žinutę <strong>{{GENDER:$3|jūsų}} aptarimo puslapyje</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|paliko}} žinutę <strong>{{GENDER:$3|jūsų}} aptarimo puslapyje</strong> \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "Buvo sukurta nuoroda iš <strong>$4</strong> į <strong>$3</strong>.",
+ "notification-bundle-header-page-linked": "$4 ir $5 kiti {{PLURAL:$6|puslapis|puslapiai}} dabar nurodo į $3.",
+ "notification-link-text-what-links-here": "Visos nuorodos į šį puslapį",
+ "notification-header-mention-other": "$1 {{GENDER:$3|jus}} {{GENDER:$2|paminėjo}} <strong>$4</strong>, „<strong>$5</strong>“.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|paminėjo}} {{GENDER:$3|jus}} čia <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|jus}} {{GENDER:$2|paminėjo}} <strong>vartotojo {{GENDER:$5|$4}} aptarimo puslapyje</strong>, „<strong>$6</strong>“.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|jus}} {{GENDER:$2|paminėjo}} <strong>vartotojo {{GENDER:$5|$4}} aptarimo puslapyje</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|jus}} {{GENDER:$2|paminėjo}} <strong>{{GENDER:$2|savo}} aptarimo puslapyje</strong>, „<strong>$4</strong>“.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|jus}} {{GENDER:$2|paminėjo}} <strong>{{GENDER:$2|savo}} aptarimo puslapyje</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|jus}} {{GENDER:$2|paminėjo}} <strong>$4</strong> aptarimo puslapyje, „<strong>$5</strong>“.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|jus}} {{GENDER:$2|paminėjo}} <strong>$4</strong> aptarimo puslapyje.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Jūsų}} <strong>$3</strong> paminėjimas nebuvo išsiųstas, nes vartotojas nebuvo rastas.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Jūsų}} <strong>$3</strong> paminėjimas nebuvo išsiųstas, nes vartotojas yra anonimas.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Jūsų}} paminėjimai nebuvo išsiųsti, nes jie viršija limitą $3.",
+ "notification-header-mention-failure-bundle": "{{GENDER:$2|Jūsų}} {{PLURAL:$3|paminėjimas|$3 paminėjimai}} <strong>$4</strong> aptarimo puslapyje {{PLURAL:$3|nebuvo išsiųstas|nebuvo išsiųsti}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Vartotojo vardas neegzistuoja:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Nepavyko paminėti IP:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Jūsų}} <strong>$3</strong> paminėjimas buvo išsiųstas.",
+ "notification-header-mention-success-bundle": "{{GENDER:$2|Jūsų}} {{PLURAL:$3|paminėjimas|$3 paminėjimai}} <strong>$4</strong> aptarimo puslapyje {{PLURAL:$3|buvo išsiųstas|buvo išsiųsti}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Jūs paminėjote}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Pranešimas|$3 pranešimai}} apie {{GENDER:$2|jūsų}} paminėjimus <strong>$4</strong> aptarimo puslapyje: {{PLURAL:$5|$5 neišsiųstas|$5 neišsiųsti}}, {{PLURAL:$6|$6 išsiųstas|$6 išsiųsti}}",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Jūsų}} vartotojo teisės buvo {{GENDER:$1|pakeistos}}. Buvote pridėtas prie: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Jūsų}} vartotojo teisės buvo {{GENDER:$1|pakeistos}}. Jūs nebeesate šių grupių narys: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Jūsų}} vartotojo teisės buvo {{GENDER:$1|pakeistos}}. Buvote pridėtas prie: $2. Jūs nebeesate šių grupių narys: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Sveiki atvykę}} į {{SITENAME}}, $1! Me džiaugiamės, kad {{GENDER:$2|jūs esate}} čia.",
+ "notification-welcome-linktext": "Sveiki",
+ "notification-header-thank-you-1-edit": "Ką tik atlikote {{GENDER:$2|savo}} pirmąjį pakeitimą; ačiū jums ir sveiki atvykę!",
+ "notification-header-thank-you-10-edit": "Ką tik atlikote {{GENDER:$2|savo}} dešimtąjį pakeitimą; ačiū jums ir prašome nesustoti!",
+ "notification-header-thank-you-100-edit": "Ką tik atlikote {{GENDER:$2|savo}} šimtąjį pakeitimą; labai jums ačiū!",
+ "notification-header-thank-you-1000-edit": "Ką tik atlikote {{GENDER:$2|savo}} tūkstantąjį pakeitimą; ačiū jums, kad esate puikus pagalbininkas!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Jūs}} ką tik atlikote {{GENDER:$2|savo}} dešimt tūkstantąjį pakeitimą, ačiū!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Jūs}} ką tik atlikote {{GENDER:$2|savo}} šimta tūkstantąjį pakeitimą, ačiū už nuostabų įnašą!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Jūs}} ką tik atlikote {{GENDER:$2|savo}} milijoninį pakeitimą, ačiū už neįtikėtiną įnašą!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Jūsų}} pakeitimas",
"notification-link-text-view-edit": "Peržiūrėti redagavimą",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|paliko}} žinutę jūsų [[User talk:$2#$3|aptarimų puslapyje]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|paliko}} žinutę jūsų aptarimų puslapyje \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|paliko}} žinutę jūsų [[User talk:$2#$3|aptarimų puslapyje]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|paliko}} žinutę jūsų aptarimų puslapyje \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] buvo {{GENDER:$1|susietas}} čia [[:$3]]. [[Special:WhatLinksHere/$2|Pamatyti visas nuorodas į šį puslapį]].",
- "notification-page-linked-flyout": "[[:$2]] buvo {{GENDER:$1|susietas}} čia [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|pakomentavo}} \"[[$3|$2]]\" \"$4\" aptarimo puslapyje.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|pateikė}} naują temą \"$2\" čia [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|atsiuntė}} Jums žinutę: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|pakomentavo}} \"[[$3#$2|$2]]\" Jūsų aptarimo puslapyje.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|paminėjo}} Jus $5 aptarimo puslapyje \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|paminėjo}} Jus $5 aptarimo puslapyje \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|paminėjo}} Jus čia [[:$3|$2 aptarimo puslapis]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|paminėjo}} Jus [[:$3|$2 aptarimo puslapyje]].",
- "notification-user-rights": "Jūsų naudotojo teisės [[Special:Log/rights/$1|buvo {{GENDER:$1|pakeistos}}]] naudotojo [[User:$1|$1]]. $2. [[Special:ListGroupRights|Sužinoti daugiau]]",
- "notification-user-rights-flyout": "Jūsų naudotojo teisės buvo {{GENDER:$1|pakeistos}} naudotojo $1. $2. [[Special:ListGroupRights|Sužinoti daugiau]]",
- "notification-user-rights-add": "Jūs dabar esate {{PLURAL:$2|šios grupės|šių grupių}} narys: $1",
- "notification-user-rights-remove": "Jūs nebesate {{PLURAL:$2|šios grupės|šių grupių}} narys: $1",
- "notification-new-user": "Sveiki atvykę į {{SITENAME}}, $1! Džiaugiamės, kad esate čia.",
- "notification-reverted2": "Jūsų {{PLURAL:$4|keitimas puslapyje [[:$2]]|keitimai [[:$2]] puslapyje}} buvo {{PLURAL:$4|atmestas|atmesti}} naudotojo [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "Jūsų {{PLURAL:$4|keitimas puslapyje $2|keitimai $2 puslapyje}} buvo {{PLURAL:$4|atmestas|atmesti}} naudotojo $1. $3",
+ "notification-link-article-reminder": "Žiūrėti puslapį",
+ "notification-header-reverted": "Jūsų {{PLURAL:$4|keitimas <strong>$3</strong>|keitimai <strong>$3</strong> puslapyje}} buvo {{GENDER:$2|atmesti}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|atsiuntė}} jums el. laišką.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|paliko}} žinutę jums svetainėje {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|paliko}} žinutę Jūsų aptarimo puslapyje.",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|paliko}} žinutę Jūsų aptarimo puslapyje \"$2\".",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|paliko}} žinutę jūsų aptarimo puslapyje \"$2\".",
"notification-page-linked-email-subject": "Puslapis, kurį sukūrėte buvo susietas {{SITENAME}} tinklapyje",
- "notification-page-linked-email-batch-body": "$2 buvo {{GENDER:$1|susietas}} $3.",
"notification-reverted-email-subject2": "Jūsų {{PLURAL:$3|pakeitimas buvo|pakeitimai buvo}} {{GENDER:$1|atšaukti}} {{SITENAME}} tinklapyje",
- "notification-reverted-email-batch-body2": "Jūsų {{PLURAL:$3|$2 pakeitimas buvo {{GENDER:$1|atšauktas}}|$2 pakeitimai buvo {{GENDER:$1|atšaukti}}}} naudotojo $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|paminėjo}} Jus {{SITENAME}} tinklapyje",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|paminėjo}} Jus temoje $4 aptarimo puslapyje \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|paminėjo}} Jus $2 aptarimo puslapyje.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|paminėjo}} {{GENDER:$2|jus}} {{SITENAME}}",
"notification-user-rights-email-subject": "Jūsų naudotojo teisės buvo pakeistos {{SITENAME}} tinklapyje",
- "notification-user-rights-email-batch-body": "Jūsų naudotojo teisės buvo {{GENDER:$1|pakeistos}} naudotojo $1. $2.",
- "echo-email-subject-default": "Naujas pranešimas {{SITENAME}} tinklapyje",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}{{PLURAL:$1|}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mėn}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-today": "Šiandien",
+ "notification-timestamp-yesterday": "Vakar",
+ "notification-inbox-filter-read": "Skaitytas",
+ "notification-inbox-filter-unread": "Neskaitytas",
+ "notification-inbox-filter-all": "Visi",
"echo-email-body-default": "Turite naują pranešimą {{SITENAME}} tinklapyje:\n\n$1",
- "echo-email-batch-body-default": "Jūs turite naują pranešimą",
- "echo-email-footer-default": "$2\n\nKontroliuoti, kuriuos el. laiškus Jums siunčiame, galite savo nustatymuose:\n{{canonicalurl:{{#special:Nustatymai}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Kontroliuoti, kuriuos el. laiškus Jums siunčiame, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">galite savo nustatymuose</a>.<br />\n$1",
+ "echo-email-footer-default-html": "Kad valdytumėte kuriuos el. laiškus jums siunčiame, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">patikrinkite savo nustatymus</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nKontroliuoti, kuriuos el. laiškus Jums siunčiame, galite savo nustatymuose:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Kontroliuoti, kuriuos el. laiškus Jums siunčiame, galite savo nustatymuose:",
+ "echo-email-html-footer-preference-link-text": "patikrinkite savo nustatymus",
+ "echo-email-html-footer-with-link": "Kontroliuoti, kuriuos el. laiškus jums siunčiame, $1.",
"echo-notification-alert": "{{PLURAL:$1|Įspėjimas ($1)|Įspėjimai ($1)|100=Įspėjimų (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Žinutė ($1)|Žinutės ($1)|100=Žinučių (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Pranešimas ($1)|Pranešimai ($1)|100=Pranešimai (99+)}}",
"echo-notification-alert-text-only": "Įspėjimai",
- "echo-notification-message-text-only": "Žinutės",
+ "echo-notification-notice-text-only": "Pranešimai",
"echo-overlay-link": "Visi pranešimai",
"echo-overlay-title": "<b>Pranešimai</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Pranešimas|Pranešimai}}</b> (rodoma $1 iš $2 neperskaitytų)",
"echo-mark-all-as-read": "Pažymėti visus kaip skaitytus",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|pranešimas pažymėtas|pranešimai pažymėti}} kaip perskaityti",
+ "echo-mark-wiki-as-read": "Pažymėti visus kaip skaitytus pasirinktoje viki: $1",
"echo-date-today": "Šiandien",
"echo-date-yesterday": "Vakar",
"echo-load-more-error": "Įvyko klaida gaunant daugiau rezultatų.",
- "notification-edit-talk-page-bundle": "$1 ir $3 {{PLURAL:$4|kitas|kiti}} {{GENDER:$1|paliko}} žinutę Jūsų [[User talk:$2|aptarimo puslapyje]].",
- "notification-page-linked-bundle": "$2 buvo {{GENDER:$1|susietas}} $3 puslapyje ir $4 {{PLURAL:$5|kito puslapio|kitų puslapių}}. [[Special:WhatLinksHere/$2|Pamatyti visas nuorodas į šį puslapį]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 ir $2 {{PLURAL:$3|kitas|kiti|kitų}} {{GENDER:$1|paliko}} žinutę jūsų aptarimų puslapyje.",
- "notification-page-linked-email-batch-bundle-body": "$2 buvo {{GENDER:$1|susietas}} $3 puslapyje ir $4 {{PLURAL:$5|kitame puslapyje|kituose puslapiuose}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Vienas naujas pranešimas|$1 nauji pranešimai|100=99+ nauji pranešimai}} <strong>{{PLURAL:$3|jūsų}} aptarimo puslapyje</strong>.",
"echo-email-batch-subject-daily": "Jūs gavote {{PLURAL:$2|naują pranešimą|naujų pranešimų}} {{SITENAME}} tinklapyje",
"echo-email-batch-subject-weekly": "Jūs gavote {{PLURAL:$2|naują pranešimą|naujų pranešimų}} {{SITENAME}} tinklapyje šią savaitę",
"echo-email-batch-body-intro-daily": "Sveiki $1,\nPateikiame Jums šiandienos aktyvumo {{SITENAME}} tinklapyje santrauką.",
"echo-email-batch-body-intro-weekly": "Sveiki $1,\nPateikiame Jums šios savaitės aktyvumo {{SITENAME}} tinklapyje santrauką.",
"echo-email-batch-link-text-view-all-notifications": "Peržiūrėti visus pranešimus",
- "echo-rev-deleted-text-view": "Ši puslapio versija buvo uždrausta.",
- "apihelp-echomarkread-description": "Pažymėti pranešimus kaip perskaitytus dabartinio naudotojo.",
- "apihelp-echomarkread-param-list": "ID sąrašas pranešimų, kuriuos pažymėti kaip perskaitytus.",
- "apihelp-echomarkread-param-all": "Jeigu nustatyta, pažymi visus naudotojo pranešimus kaip perskaitytus.",
- "apihelp-echomarkread-param-sections": "Sąrašas skyrių, kuriuos pažymėti kaip perskaitytus.",
- "apihelp-echomarkread-example-1": "Pažymėti pranešimą 8 kaip perskaitytą",
- "apihelp-echomarkread-example-2": "Pažymėti visus pranešimus kaip perskaitytus",
- "apihelp-echomarkseen-description": "Pažymėti pranešimus kaip peržiūrėtus dabartinio naudotojo.",
- "apihelp-echomarkseen-example-1": "Pažymėti visų tipų pranešimus kaip peržiūrėtus",
- "apihelp-echomarkseen-param-type": "Tipas pranešimų, kuriuos pažymėti kaip peržiūrėtus: 'alert', 'message' arba 'all'.",
- "apihelp-query+notifications-description": "Gauti pranešimus, kurie laukia dabartinio naudotojo.",
- "apihelp-query+notifications-param-prop": "Informacija, kurios prašyti.",
- "apihelp-query+notifications-param-sections": "Pranešimo sekcijos, su kuriomis vykdyti užklausą (t.y. kokia nors kombinacija iš 'alert' ir 'message').",
- "apihelp-query+notifications-param-groupbysection": "Ar grupuoti rezultatus pagal skyrius. Kiekvienas skyrius yra paimamas atskirai, jeigu taip nustatyta.",
- "apihelp-query+notifications-param-format": "Jeigu nustatyta, pranešimai bus grąžinami suformatuoti šiuo būdu.",
- "apihelp-query+notifications-param-limit": "Maksimalus pranešimų skaičius, kurį grąžinti.",
- "apihelp-query+notifications-param-index": "Jeigu nustatyta, bus grąžintas surūšiuotas pranešimų ID sąrašas.",
- "apihelp-query+notifications-param-alertcontinue": "Kai prieinama daugiau įspėjimo rezultatų, tęsimui naudoti tai.",
- "apihelp-query+notifications-param-alertunreadfirst": "Ar pirmiau rodyti neperskaitytų žinučių pranešimus.",
- "apihelp-query+notifications-param-messagecontinue": "Kai prieinama daugiau žinučių rezultatų, tęsimui naudoti tai.",
- "apihelp-query+notifications-param-messageunreadfirst": "Ar pirmiau rodyti neperskaitytus įspėjimų pranešimus.",
- "apihelp-query+notifications-example-1": "Rodyti pranešimus",
- "apihelp-query+notifications-example-2": "Rodyti pranešimus, sugrupuotus pagal skyrius, su kiekiais"
+ "notification-header-foreign-alert": "Daugiau įspėjimų iš {{PLURAL:$5|kitos viki|$5 kitų viki}}",
+ "notification-header-foreign-notice": "Daugiau pranešimų iš {{PLURAL:$5|kitos viki|$5 kitų viki}}",
+ "notification-header-foreign-all": "Daugiau žinučių iš {{PLURAL:$5|kitos viki|$5 kitų viki}}"
}
diff --git a/Echo/i18n/luz.json b/Echo/i18n/luz.json
index 06e617e6..5cbf26ed 100644
--- a/Echo/i18n/luz.json
+++ b/Echo/i18n/luz.json
@@ -3,6 +3,5 @@
"authors": [
"علی ساکی لرستانی"
]
- },
- "tooltip-pt-notifications": "ئیعلانل ئیشا"
+ }
}
diff --git a/Echo/i18n/lv.json b/Echo/i18n/lv.json
index 1b8bc47f..892e5834 100644
--- a/Echo/i18n/lv.json
+++ b/Echo/i18n/lv.json
@@ -3,14 +3,17 @@
"authors": [
"Admresdeserv.",
"Edgars2007",
- "Papuass"
+ "Papuass",
+ "Zuiks",
+ "Silraks"
]
},
- "echo-desc": "Paziņojumu sistēma",
+ "echo-desc": "Sistēma dalībnieku informēšanai par notikumiem un ziņojumiem",
"prefs-echo": "Paziņojumi",
- "prefs-emailsettings": "E-pasta uzstādījumi",
+ "prefs-emailsettings": "E-pasta iestatījumi",
"prefs-displaynotifications": "Attēlošanas uzstādījumi",
"prefs-echosubscriptions": "Paziņot man par šiem notikumiem",
+ "prefs-echocrosswiki": "Starpprojektu paziņojumi",
"prefs-newmessageindicator": "Jauna ziņojuma indikators",
"echo-pref-send-me": "Nosūtīt man:",
"echo-pref-send-to": "Nosūtīt uz:",
@@ -23,9 +26,10 @@
"echo-pref-email-frequency-weekly": "Iknedēļas paziņojumu kopsavilkums",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Vienkāršs teksts",
- "echo-pref-notify-show-link": "Rādīt paziņojumus manā rīkjoslā",
+ "echo-pref-cross-wiki-notifications": "Rādīt paziņojumus no citiem WMF projektiem",
"echo-pref-new-message-indicator": "Rādīt diskusiju lapas ziņojumu indikatoru manā rīkjoslā",
"echo-learn-more": "Uzzināt vairāk",
+ "echo-log": "Publiskais žurnāls",
"echo-new-messages": "tev ir jauni paziņojumi",
"echo-category-title-edit-user-talk": "Diskusiju lapas {{PLURAL:$1|paziņojumi|paziņojums|paziņojumi}}",
"echo-category-title-article-linked": "Lapas {{PLURAL:$1|saites|saite|saites}}",
@@ -33,82 +37,101 @@
"echo-category-title-mention": "{{PLURAL:$1|Pieminēšanas|Pieminēšana|Pieminēšanas}}",
"echo-category-title-other": "{{PLURAL:$1|Citi|Cits|Citi}}",
"echo-category-title-system": "{{PLURAL:$1|Sistēmas paziņojumi|Sistēmas paziņojums|Sistēmas paziņojumi}}",
- "echo-category-title-user-rights": "{{PLURAL:$1|Lietotāja tiesību izmaiņas|Lietotāja tiesības izmaiņas|Lietotāja tiesību izmaiņas}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Dalībnieka tiesību izmaiņas|Dalībnieka tiesības izmaiņas|Dalībnieka tiesību izmaiņas}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-pasti no citiem dalībniekiem|E-pasts no citiem dalībniekiem|E-pasti no citiem dalībniekiem}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Lapu atgādinājumi|Lapas atgādinājums|Lapu atgādinājumi}}",
"echo-pref-tooltip-edit-user-talk": "Paziņot man, kad kāds pievieno ziņojumu vai atbild manā diskusiju lapā.",
"echo-pref-tooltip-article-linked": "Paziņot man, kad kāds izveido saiti uz manis izveidotu lapu.",
"echo-pref-tooltip-reverted": "Paziņot man, kad kāds atceļ manis veiktu labojumu, izmanojot atcelšanas rīku.",
- "echo-pref-tooltip-mention": "Paziņot man, kad kāds izveido saiti uz manu lietotāja lapu.",
- "echo-pref-tooltip-user-rights": "Paziņot man, kad kāds izmaina manas lietotāja tiesības.",
- "echo-no-agent": "[Neviens]",
- "echo-no-title": "[Nav lapas]",
+ "echo-pref-tooltip-mention": "Paziņot man, kad kāds izveido saiti uz manu dalībnieka lapu.",
+ "echo-pref-tooltip-user-rights": "Paziņot man, kad kāds izmaina manas dalībnieka tiesības.",
+ "echo-pref-tooltip-emailuser": "Paziņot man, kad kāds nosūta man e-pastu.",
"echo-error-no-formatter": "Paziņojumam nav norādīts formatējums",
- "echo-error-preference": "Kļūda: Neizdevās uzstādīt lietotāja izvēli",
- "echo-error-token": "Kļūda: Neizdevās iegūt lietotāja identifikatoru",
"notifications": "Paziņojumi",
- "tooltip-pt-notifications": "Jūsu paziņojumi",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Tavi}} brīdinājumi",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Tavi}} paziņojumi",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Paziņojumi pēc kategorijas",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Iespējots pēc noklusējuma",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Esošie dalībnieki",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Jauni dalībnieki",
"echo-specialpage": "Paziņojumi",
- "echo-anon": "Lai saņemtu paziņojumus, [$1 izveidojiet lietotāja kontu] vai [$2 pieslēdzietes].",
+ "echo-specialpage-section-markread": "Atzīmēt grupu kā izlasītu",
+ "echo-specialpage-markasread": "Paziņojums: Atzīmēt kā izlasītu",
+ "echo-specialpage-markasread-invalid-id": "Nederīgs notikuma ID",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|paziņojumi|paziņojums|paziņojumi}}",
+ "echo-specialpage-pagefilters-title": "Nesena aktivitāte",
+ "echo-specialpage-pagefilters-subtitle": "Lapas ar nelasītiem paziņojumiem",
+ "notificationsmarkread-legend": "Atzīmēt paziņojumu kā izlasītu",
+ "echo-anon": "Lai saņemtu paziņojumus, [$1 izveidojiet dalībnieka kontu] vai [$2 pieslēdzietes].",
"echo-none": "Jums nav paziņojumu.",
"echo-more-info": "Vairāk informācijas",
"echo-feedback": "Atsauksmes",
+ "echo-popup-footer-special-page-invitation": "<strong>Izmēģini uzlaboto paziņojumu lapu.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Jauns izskats un iespējas.",
+ "echo-api-failure": "Neizdevās iegūt paziņojumus.",
+ "echo-notification-placeholder": "Nav paziņojumu.",
+ "echo-notification-placeholder-filters": "Nav paziņojumu, kas atbilstu šiem kritērijiem.",
+ "echo-notification-markasread": "Atzīmēt kā lasītu",
+ "echo-notification-markasunread": "Atzīmēt kā nelasītu",
+ "echo-notification-markasread-tooltip": "Atzīmēt kā lasītu",
+ "echo-notification-more-options-tooltip": "Vairāk iespēju",
+ "notification-link-text-expand-all": "Izvērst",
+ "notification-link-text-expand-notice-count": "Apskatīt {{PLURAL:$1|$1 paziņojumus|$1 paziņojumu|$1 paziņojumus}}",
+ "notification-link-text-collapse-all": "Sakļaut",
"notification-link-text-view-message": "Apskatīt ziņojumu",
"notification-link-text-view-mention": "Apskatīt pieminēšanu",
- "notification-link-text-view-changes": "Apskatīt izmaiņas",
+ "notification-link-text-view-changes": "{{GENDER:$1|Apskatīt}} izmaiņas",
"notification-link-text-view-page": "Apskatīt lapu",
+ "notification-link-text-what-links-here": "Visas saites uz šo lapu",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Tu}} mēģināji pieminēt vairāk nekā $3 {{PLURAL:$3|dalībniekus|dalībnieku|dalībniekus}}. Visiem pieminētajiem aiz šīs robežas netika nosūtīts paziņojums.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Dalībnieka vārds nepastāv:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP adreses nevar pieminēt:</strong> $1",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Tu pieminēji}}:</strong> $3",
+ "notification-header-thank-you-1-edit": "Tu nupat veici savu pirmo labojumu; paldies tev un laipni {{GENDER:$2|lūgts|lūgta}}!",
+ "notification-header-thank-you-10-edit": "Tu nupat veici savu desmito labojumu; paldies tev un {{GENDER:$2|lūdzu turpini}}!",
+ "notification-header-thank-you-100-edit": "Tu nupat veici savu simto labojumu; liels paldies {{GENDER:$2|tev}}!",
+ "notification-header-thank-you-1000-edit": "Tu nupat veici savu tūkstošo labojumu; paldies tev kā {{GENDER:$2|lieliskam dalībniekam|lieliskai dalībniecei}}!",
+ "notification-header-thank-you-10000-edit": "Tu nupat veici savu desmittūkstošo labojumu; patiesi liels paldies {{GENDER:$2|tev}}!",
+ "notification-header-thank-you-100000-edit": "Tu nupat veici savu simttūkstošo labojumu; paldies {{GENDER:$2|tev}} par fantastisko devumu!",
+ "notification-header-thank-you-1000000-edit": "Tu nupat veici savu miljono labojumu; paldies {{GENDER:$2|tev}} par nenovērtējamo devumu!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Tavs}} labojums",
"notification-link-text-view-edit": "Apskatīt labojumu",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|atstāja}} paziņojumu jūsu [[User talk:$2#$3|diskusiju lapā]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|atstāja}} paziņojumu jūsu diskusiju lapā \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|atstāja}} paziņojumu jūsu [[User talk:$2#$3|diskusiju lapā]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|atstāja}} paziņojumu tavā diskusiju lapā \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Uz [[:$2]] {{GENDER:$1|tika izveidota saite}} no [[:$3]]. [[Special:WhatLinksHere/$2|Apskatīt visas saites uz šo lapu]].",
- "notification-page-linked-flyout": "Uz [[:$2]] tika {{GENDER:$1|izveidota saite}} no [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|komentēja}} par \"[[$3|$2]]\" \"$4\" diskusiju lapā",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|izveidoja}} jaunu tēmu \"$2\" [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|nosūtīja}} jums paziņojumu: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|komentēja}} par \"[[$3#$2|$2]]\" jūsu diskusiju lapā",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|pieminēja}} tevi $5 diskusiju lapā \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|pieminēja}} jūs $5 diskusiju lapā par \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|pieminēja}} tevi [[:$3|$2 diskusiju lapā]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|pieminēja}} tevi [[:$3|$2 diskusiju lapā]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|nomainīja}}]] tavas lietotāja tiesības. $2. [[Special:ListGroupRights|Skatīt informāciju]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|nomainīja}} tavas lietotāja tiesības. $2. [[Special:ListGroupRights|Skatīt informāciju]]",
- "notification-user-rights-add": "Jūs tagad esat {{PLURAL:$2|šo grupu|šīs grupas|šo grupu}} dalībnieks: $1",
- "notification-user-rights-remove": "Jūs vairs neesat {{PLURAL:$2|šo grupu|šīs grupas|šo grupu}} dalībnieks: $1",
- "notification-new-user": "Laipni lūdzam {{SITENAME}}, $1! Mēs priecājamies jūs te redzēt.",
- "notification-reverted2": "Jūsu {{PLURAL:$4|labojumus lapā [[:$2]]|labojumu lapā [[:$2]]|labojumus lapā [[:$2]]}} {{GENDER:$1|atcēla}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "Jūsu {{PLURAL:$4|labojumus lapā $2|labojumu lapā $2|labojumus lapā $2}} {{GENDER:$1|atcēla}} $1. $3",
+ "notification-link-article-reminder": "Skatīt lapu",
+ "notification-header-reverted": "{{PLURAL:$4|Tavi labojumi lapā <strong>$3</strong> {{GENDER:$2|tika atcelti}}|Tavs labojums lapā <strong>$3</strong> {{GENDER:$2|tika atcelts}}|Tavi labojumi lapā <strong>$3</strong> {{GENDER:$2|tika atcelti}}}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|nosūtīja}} tev e-pastu.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|atstāja}} tev ziņojumu {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|atstāja}} paziņojumu jūsu diskusiju lapā:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|atstāja}} paziņojumu jūsu diskusiju lapā \"$2\".",
"notification-page-linked-email-subject": "Uz jūsu lapu {{SITENAME}} tika izveidota saite",
- "notification-page-linked-email-batch-body": "$3 lapā tika izveidota saite no $2",
"notification-reverted-email-subject2": "Jūsu {{PLURAL:$3|atcelts|labojums tika {{GENDER:$1|atcelts}}|labojumi tika {{GENDER:$1|atcelti}}}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "Jūsu {{PLURAL:$3|labojumus $2|labojumu $2|labojumus $2}} {{GENDER:$1|atcēla}} $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|pieminēja}} tevi {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|pieminēja}} tevi $4 diskusiju lapā \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|pieminēja}} tevi $2 diskusijas lapā.",
- "notification-user-rights-email-subject": "Jūsu lietotāja tiesības tika izmainītas {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Jūsu lietotāja tiesības {{GENDER:$1|izmainīja}} $1. $2.",
- "echo-email-subject-default": "Jauns paziņojums par {{SITENAME}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|pieminēja}} {{GENDER:$2|tevi}} vietnē {{SITENAME}}",
+ "notification-user-rights-email-subject": "Jūsu dalībnieka tiesības tika izmainītas {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mēn}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 gd}}",
+ "notification-timestamp-today": "Šodien",
+ "notification-timestamp-yesterday": "Vakar",
+ "notification-inbox-filter-read": "Izlasītie",
+ "notification-inbox-filter-unread": "Nelasītie",
+ "notification-inbox-filter-all": "Visi",
"echo-email-body-default": "Jums ir jauns paziņojums par {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Jums ir jauns paziņojums.",
"echo-email-footer-default": "$2\n\nLai kontrolētu, kurus e-pastus mēs Jums sūtām, pārbaudiet savus uzstādījumus:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Lai kontrolētu, kurus e-pastus mēs Jums sūtām, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">pārbaudiet savus iestatījumus</a>.<br />\n$1",
+ "echo-email-html-footer-preference-link-text": "pārbaudi {{GENDER:$1|savas}} izvēles",
"echo-notification-alert-text-only": "Brīdinājumi",
- "echo-notification-message-text-only": "Ziņojumi",
+ "echo-notification-notice-text-only": "Paziņojumi",
"echo-overlay-link": "Visi paziņojumi",
"echo-overlay-title": "<b>Paziņojumi</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Paziņojumi|Paziņojums|Paziņojumi}}</b> (rāda $1 no $2 nelasītiem)",
"echo-mark-all-as-read": "Atzīmēt visus kā izlasītus",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|paziņojumi|paziņojums|paziņojumi}} atzīmēti kā izlasīti",
"echo-date-today": "Šodien",
"echo-date-yesterday": "Vakar",
- "echo-load-more-error": "Ielasot vairāk rezultātus notika kļūda.",
- "notification-edit-talk-page-bundle": "$1 un $3 {{PLURAL:$4|citi|cits|citi}} {{GENDER:$1|atstāja}} paziņojumu tavā [[User talk:$2|diskusiju lapā]].",
- "notification-page-linked-email-batch-bundle-body": "{{GENDER:$1|linked}} from $3 un $4 citās {{PLURAL:$5|lapās|lapā|lapās}} tika izveidota saite uz $2.",
+ "echo-load-more-error": "Ielasot vairāk rezultātus, notika kļūda.",
"echo-email-batch-subject-daily": "Jums ir {{PLURAL:$2|jauni paziņojumi|jauns paziņojums|jauni paziņojumi}} par {{SITENAME}}",
"echo-email-batch-subject-weekly": "Jums šonedēļ ir {{PLURAL:$2|jauni paziņojumi|jauns paziņojums|jauni paziņojumi}} par {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Sveiks $1,\nŠis ir šīsdienas {{SITENAME}} aktivitāšu saraksts.",
"echo-email-batch-body-intro-weekly": "Sveiks $1,\nŠis ir šīs nedēļas {{SITENAME}} aktivitāšu saraksts.",
- "echo-email-batch-link-text-view-all-notifications": "Apskatīt visus paziņojumus",
- "apihelp-echomarkread-example-2": "Atzīmēt visus paziņojumus, kā izlasītus"
+ "echo-email-batch-link-text-view-all-notifications": "Apskatīt visus paziņojumus"
}
diff --git a/Echo/i18n/lzh.json b/Echo/i18n/lzh.json
index 0d87ac68..c762faeb 100644
--- a/Echo/i18n/lzh.json
+++ b/Echo/i18n/lzh.json
@@ -2,12 +2,17 @@
"@metadata": {
"authors": [
"Yanteng3",
- "Jason924tw"
+ "Jason924tw",
+ "SolidBlock",
+ "Davidzdh",
+ "LNDDYL"
]
},
+ "prefs-echo": "告示",
"prefs-emailsettings": "傳書",
"prefs-echosubscriptions": "訊事",
- "echo-new-messages": "子有新訊息",
+ "echo-new-messages": "音書新來",
"notifications": "訊",
+ "tooltip-pt-notifications-alert": "{{GENDER:|君}}鳴",
"echo-notification-alert": "{{PLURAL:$1|訊 ($1)|訊 ($1)|100=訊 (九九+)}}"
}
diff --git a/Echo/i18n/mai.json b/Echo/i18n/mai.json
index 272a1fc4..83f9464a 100644
--- a/Echo/i18n/mai.json
+++ b/Echo/i18n/mai.json
@@ -1,8 +1,108 @@
{
"@metadata": {
"authors": [
- "Tulsi Bhagat"
+ "Tulsi Bhagat",
+ "बिप्लब आनन्द"
]
},
- "tooltip-pt-notifications": "आपने के अधिसूचना"
+ "prefs-echo": "सूचनासभ",
+ "prefs-emailsettings": "इमेल विकल्प",
+ "prefs-displaynotifications": "प्रदर्शन विकल्पसभ",
+ "prefs-echosubscriptions": "हमरा ई घटनासभक बारेमे सूचित करी",
+ "prefs-echocrosswiki": "क्रस-विकी सूचना",
+ "prefs-newmessageindicator": "नव सन्देशक सङ्केतक",
+ "echo-pref-send-me": "हमरा भेजी:",
+ "echo-pref-send-to": "यतयँ भेजी:",
+ "echo-pref-email-format": "इमेल प्रारूप:",
+ "echo-pref-web": "वेब",
+ "echo-pref-email": "इमेल",
+ "echo-pref-email-format-plain-text": "सादा पाठ",
+ "echo-pref-cross-wiki-notifications": "दोसर विकिसभक सूचना देखाबी",
+ "echo-pref-new-message-indicator": "वार्ता पृष्ठ सन्देश सङ्केत हमर उपकरण पट्टीमे देखाबी",
+ "echo-learn-more": "अधिक जानी",
+ "echo-log": "सार्वजनिक लग",
+ "echo-new-messages": "अहाँक लेल नव सन्देश अछि",
+ "echo-category-title-edit-user-talk": "वार्ता पृष्ठ {{PLURAL:$1|सन्देश|सन्देशसभ}}",
+ "echo-category-title-article-linked": "पृष्ठ {{PLURAL:$1|लिङ्क|लिङ्कसभ}}",
+ "echo-category-title-reverted": "सम्पादन {{PLURAL:$1|पूर्ववत कएल गेल|पूर्ववत भेल}}",
+ "echo-category-title-mention": "{{PLURAL:$1|उल्लेख|उल्लेख भेल}}",
+ "echo-category-title-other": "{{PLURAL:$1|अन्य}}",
+ "echo-category-title-system": "{{PLURAL:$1|प्रणाली}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|प्रयोगकर्ता अधिकार परिवर्तन|प्रयोगकर्ता अधिकार परिवर्तन भेल}}",
+ "echo-error-no-formatter": "अधिसूचनाक लेल कोनो स्वरूपण परिभाषित नै अछि ।",
+ "notifications": "अधिसूचनासभ",
+ "tooltip-pt-notifications-alert": "{{GENDER:|अहाँक}} सूचना",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "स्वचालित रुपसँ सक्षम करी",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "वर्तमान प्रयोगकर्तासभ",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "नव प्रयोगकर्तासभ",
+ "echo-specialpage": "अधिसूचनासभ",
+ "echo-specialpage-section-markread": "समूहके पढल चिह्नित करी",
+ "echo-specialpage-markasread": "सूचना: पढल गेल चिन्हित करी",
+ "echo-specialpage-markasread-invalid-id": "अमान्य त्रुटी आइडी",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|सूचना|सूचनासभ}}",
+ "echo-specialpage-pagefilters-title": "लगक क्रिया",
+ "echo-none": "अहाँक लेल कोनो अधिसूचना नै अछि।",
+ "echo-more-info": "अधिक जानकारी",
+ "echo-feedback": "अहाँक सुझाव",
+ "echo-api-failure": "अधिसूचना आनैमे असफल।",
+ "echo-api-failure-cross-wiki": "स्वचालित डोमेनक प्रयास विफल।",
+ "echo-notification-placeholder": "कोनो सूचना नै अछि।",
+ "echo-notification-loginrequired": "सूचनासभके देखैक लेल अहाँक सम्प्रवेश करै पडत।",
+ "echo-notification-popup-loginrequired": "सूचनासभके देखैक लेल सम्प्रवेश करी।",
+ "echo-notification-markasread": "पढल गेल चिन्हित करी",
+ "echo-notification-markasunread": "नै पढल चिन्हित करी",
+ "echo-notification-markasread-tooltip": "पढल गेल चिन्हित करी",
+ "echo-notification-more-options-tooltip": "अन्य विकल्प",
+ "notification-link-text-expand-all": "विस्तार करी",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 सूचना|$1 सूचनासभ}} देखी",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 सूचना|$1 सूचनासभ}} देखी",
+ "notification-link-text-collapse-all": "भखडाबी",
+ "notification-link-text-view-message": "सन्देश देखी",
+ "notification-link-text-view-mention": "उल्लेख देखी",
+ "notification-link-text-view-changes": "परिवर्तन {{GENDER:$1|देखी}}",
+ "notification-link-text-view-page": "पृष्ठ देखी",
+ "notification-compact-header-page-linked": "<strong>$1</strong> सँ लिङ्क भेल।",
+ "notification-link-text-what-links-here": "ई पृष्ठ सँ जुड़ल सम्पूर्ण लिङ्कसभ।",
+ "notification-header-welcome": "अहाँक {{SITENAME}} पर {{GENDER:$2|स्वागत}} अछि, $1! हमसभ ख़ुशी छी जे अहाँ {{GENDER:$2|यतयँ}} अएलौ।",
+ "notification-welcome-linktext": "सुस्वागतम्‌!",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|अहाँ}} अखने अखन {{GENDER:$2|अपन}} पहिल सम्पादन केनए छी; {{GENDER:$2|अहाँक}} धन्यवाद, आ स्वागत अछि!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|अहाँ}} अखने अखन {{GENDER:$2|अपन}} दशम सम्पादन केनए छी; {{GENDER:$2|अहाँक}} धन्यवाद, आ अहिने सम्पादन करैत रही!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|अहाँ}} अखने अखन {{GENDER:$2|अपन}} सौटा सम्पादन केनए छी; {{GENDER:$2|अहाँक}} धन्यवाद, आ स्वागत अछि!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|अहाँ}} अखने अखन {{GENDER:$2|अपन}} हजारम सम्पादन केनए छी; {{GENDER:$2|अहाँक}} उत्कृष्ट योगदानक लेल धन्यवाद!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|अहाँ}} अखने अखन {{GENDER:$2|अपन}} दश हजारम सम्पादन केनए छी; {{GENDER:$2|अहाँक}} बहुत बहुत धन्यवाद!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|अहाँ}} अखने अखन {{GENDER:$2|अपन}} एक लाखम सम्पादन केनए छी; {{GENDER:$2|अहाँक}} सराहनीय योगदानक लेल धन्यवाद!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|अहाँ}} अखने अखन {{GENDER:$2|अपन}} दश लाखम सम्पादन केनए छी; {{GENDER:$2|अहाँक}} अति उत्कृष्ट योगदानक लेल धन्यवाद!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|अहाँक}} सम्पादन",
+ "notification-link-text-view-edit": "सम्पादन देखी",
+ "notification-header-reverted": "अहाँक {{PLURAL:$4|<strong>$3</strong>सम्पादन|सम्पादनसभ <strong>$3</strong>के}} {{GENDER:$2|द्वारा पूर्ववत}} करि देल गेल अछि।",
+ "notification-header-emailuser": "$1 अहाँक ईमेल {{GENDER:$2|भेजने}} अछि।",
+ "notification-edit-talk-page-email-subject2": "$1 अहाँक लेल {{SITENAME}}पर सन्देश {{GENDER:$1|छोडलक अछि}}",
+ "notification-reverted-email-subject2": "{{SITENAME}} पर अहाँक {{PLURAL:$3|सम्पादन|सम्पादनसभ}}के {{GENDER:$1|पूर्ववत}} कएल गेल।",
+ "notification-user-rights-email-subject": "{{SITENAME}} पर अहाँक प्रयोगकर्ता अधिकार परिवर्तन कएल गेल",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1सँ}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 मि}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 घ}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 दि}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 मा}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 व}}",
+ "notification-timestamp-today": "आई",
+ "notification-timestamp-yesterday": "काल्हि",
+ "notification-inbox-filter-read": "पढी",
+ "notification-inbox-filter-unread": "नै पढल",
+ "notification-inbox-filter-all": "सभटा",
+ "echo-email-body-default": "अहाँक लेल {{SITENAME}} पर नव अधिसूचना अछि:\n\n$1",
+ "echo-email-html-footer-preference-link-text": "अपन खासमखास जाँच करी",
+ "echo-notification-alert-text-only": "सङ्केतक",
+ "echo-overlay-link": "सब सूचनासभ",
+ "echo-overlay-title": "<b>सूचनासभ</b>",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|सूचना|सूचनासभ}}</b>($2 अपठितमे सँ $1 प्रदर्शित कएल जा रहल अछि)",
+ "echo-mark-all-as-read": "सब पढि लेल गएल चिन्हित करी",
+ "echo-date-today": "आई",
+ "echo-date-yesterday": "काल्हि",
+ "echo-load-more-error": "अधिक परिणाम प्राप्त करैत समय एक त्रुटि भेल।",
+ "echo-email-batch-subject-daily": "अहाँक लेल {{SITENAME}} पर नव {{PLURAL:$2|अधिसूचना अछि|अधिसूचनासभ अछि}}।",
+ "echo-email-batch-subject-weekly": "अहाँक लेल {{SITENAME}} पर ई हप्ता नव {{PLURAL:$2|अधिसूचना अछि|अधिसूचनासभ अछि}}।",
+ "echo-email-batch-body-intro-daily": "नमस्कार $1,\n{{SITENAME}} पर आजुक गतिविधिक सारांश निम्न अछि।",
+ "echo-email-batch-body-intro-weekly": "नमस्कार $1,\n{{SITENAME}} पर ई हप्ताक गतिविधिक सारांश निम्न अछि।",
+ "echo-email-batch-link-text-view-all-notifications": "सभ अधिसूचनासभ देखी"
}
diff --git a/Echo/i18n/mg.json b/Echo/i18n/mg.json
index 4d56314f..77348dbf 100644
--- a/Echo/i18n/mg.json
+++ b/Echo/i18n/mg.json
@@ -21,7 +21,6 @@
"echo-pref-email-frequency-weekly": "Famintinana isan-kerinandron'ny fampilazana",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Soratra tsotra",
- "echo-pref-notify-show-link": "Asehoy ao amin'ny toolbar-ko ny fampilazana",
"echo-pref-new-message-indicator": "Haneho ny mpanondro hafatra ao amin'ny pejin-dresaka ao amin'ny toolbar-ko",
"echo-learn-more": "Fampahalalana fanampiny",
"echo-new-messages": "Misy hafatra vaovao",
@@ -29,10 +28,8 @@
"echo-category-title-article-linked": "{{PLURAL:$1|Rohim-pejy}}",
"echo-pref-tooltip-edit-user-talk": "Ilazao aho raha misy mamela hafatra na mamaly hafatra eo amin'ny pejin-dresaka.",
"echo-pref-tooltip-article-linked": "Ilazao aho raha misy manisy rohy mankany amina pejy noforiko avy amin'ny pejin-dahatsoratra",
- "echo-no-agent": "[Tsy misy]",
- "echo-no-title": "[Tsy misy pejy]",
"notifications": "Fampilazana",
- "tooltip-pt-notifications": "Ny fampilazanao",
+ "tooltip-pt-notifications-alert": "Fanairana anao",
"echo-specialpage": "Fampilazana",
"echo-more-info": "Fampahalalana fanampiny",
"echo-feedback": "Famoahan-kevitra",
@@ -41,20 +38,15 @@
"notification-link-text-view-changes": "Hijery ny fiovana",
"notification-link-text-view-page": "Hijery ny pejy",
"notification-link-text-view-edit": "Hijery ny fanovàna",
- "notification-edit-talk-page2": "Nametraka hafatra teo amin'ny [[User talk:$2#$3|pejin-dresakao]] i [[User:$1|$1]].",
"notification-edit-talk-page-email-subject2": "Nametraka hafatra teo amin'ny pejin-dresakao teo amin'i {{SITENAME}} i $1",
"notification-edit-talk-page-email-batch-body-with-section": "Namela hafatra teo amin'ny pejin-dresakao tanatin'i \"$2\" i $1",
"notification-user-rights-email-subject": "Voaova teo amin'i {{SITENAME}} ny zom-pikambanao",
- "notification-user-rights-email-batch-body": "Voaovan'i $1 ny zom-pikambanao. $2",
- "echo-email-subject-default": "Fampilazana vaovao any amin'i {{SITENAME}}",
"echo-email-body-default": "Manana fampilazana vaovao ianao any amin'i {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Manana fampilazana vaovao ianao.",
"echo-overlay-link": "Fampilazana rehetra",
"echo-overlay-title": "<b>Fampilazana</b>",
"echo-mark-all-as-read": "Marihana ho voavaky",
"echo-date-today": "Androany",
"echo-date-yesterday": "Omaly",
"echo-load-more-error": "Nisy hadisoana nitranga tam-panaovana fetch ny valiny.",
- "echo-email-batch-link-text-view-all-notifications": "Hijery ny fampilazana rehetra",
- "echo-rev-deleted-text-view": "Voafafa ity filazam-pajy ity."
+ "echo-email-batch-link-text-view-all-notifications": "Hijery ny fampilazana rehetra"
}
diff --git a/Echo/i18n/mhr.json b/Echo/i18n/mhr.json
new file mode 100644
index 00000000..4438ce71
--- /dev/null
+++ b/Echo/i18n/mhr.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Санюн Вадик"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "Шижтарымаш-влак тыланда",
+ "tooltip-pt-notifications-notice": "Серыш-влак тыланда"
+}
diff --git a/Echo/i18n/mk.json b/Echo/i18n/mk.json
index 98b2c3cf..2794da90 100644
--- a/Echo/i18n/mk.json
+++ b/Echo/i18n/mk.json
@@ -1,7 +1,8 @@
{
"@metadata": {
"authors": [
- "Bjankuloski06"
+ "Bjankuloski06",
+ "Macofe"
]
},
"echo-desc": "Систем за известување на корисници во врска со настани и пораки",
@@ -9,10 +10,12 @@
"prefs-emailsettings": "Можности за е-пошта",
"prefs-displaynotifications": "Нагодувања на приказот",
"prefs-echosubscriptions": "Известувај ме за следниве настани",
+ "prefs-echocrosswiki": "Известувања од други викија",
"prefs-newmessageindicator": "Показател за нови пораки",
+ "prefs-blocknotificationslist": "Список на блокови",
"echo-pref-send-me": "Испрати ми:",
"echo-pref-send-to": "Испрати на:",
- "echo-pref-email-format": "Формат на е-пошта:",
+ "echo-pref-email-format": "Формат на е-поштата:",
"echo-pref-web": "На вики",
"echo-pref-email": "Е-пошта",
"echo-pref-email-frequency-never": "Не ми праќај известувања на е-пошта",
@@ -21,119 +24,181 @@
"echo-pref-email-frequency-weekly": "Неделен преглед на известувањата",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Прост текст",
+ "echo-pref-cross-wiki-notifications": "Прикажувај известувања од други викија",
+ "echo-pref-notifications-blacklist": "Список на кориснички имиња на црниот список, што значи дека за нив нема да се известува во Ехо (уредувањата на вашата корисничка разговорна страница сепак ќе се известуваат)",
"echo-pref-new-message-indicator": "Прикажувај показател за нови пораки (на стр. за разговор) во алатникот",
+ "echo-pref-beta-feature-cross-wiki-message": "Подобрени известувања",
+ "echo-pref-beta-feature-cross-wiki-description": "Полесно прегледување и организирање на известувањата. Вклучува известувања низ сите викија, што значи дека ќе можете да ја видите пораката од други викија, покрај вашето. (За да добивате известувања низ сите викија на дадено вики, ќе мора да ја вклучите бета-можноста на тоа вики.)",
"echo-learn-more": "Дознајте повеќе",
+ "echo-log": "Јавен дневник",
"echo-new-messages": "Имате нови пораки",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Порака|Пораки}} на стран. за разговор",
"echo-category-title-article-linked": "{{PLURAL:$1|Врска|Врски}} до стран.",
"echo-category-title-reverted": "{{PLURAL:$1|Вратено уредување|Вратени уредувања}}",
"echo-category-title-mention": "{{PLURAL:$1|Споменување|Споменувања}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Неуспешно споменување|Неуспешни споменувања}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Успешно споменување|Успешни споменувања}}",
"echo-category-title-other": "{{PLURAL:$1|Друго}}",
"echo-category-title-system": "{{PLURAL:$1|Систем}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Промена во корисничките права|Промени во корисничките права}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Е-пошта од друг корисник|Е-пошта од други корисници}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Потсетник за страница|Потсетници за страниците}}",
"echo-pref-tooltip-edit-user-talk": "Извести ме кога некој ќе остави порака или ќе одговори на мојата страница за разговор.",
- "echo-pref-tooltip-article-linked": "Извести ме кога некој ќе се повика на статија што ја имам создадено.",
+ "echo-pref-tooltip-article-linked": "Извести ме кога некој ќе се повика на страница што ја имам создадено од друга страница.",
"echo-pref-tooltip-reverted": "Извести ме кога некој ќе откаже уредување што го имам направено користејќи ја алатката за отповикување или враќање.",
- "echo-pref-tooltip-mention": "Извести ме кога некој ќе стави врска до мојата корисничка страница.",
+ "echo-pref-tooltip-mention": "Извести ме кога некој ќе се повика на мојата корисничка страница.",
+ "echo-pref-tooltip-mention-failure": "Извести ме кога нема да успее некому испратеното споменување.",
+ "echo-pref-tooltip-mention-success": "Извести ме кога некому ќе испратам споменување.",
"echo-pref-tooltip-user-rights": "Извести ме кога некој ќе ми ги смени корисничките права.",
- "echo-no-agent": "[Никој]",
- "echo-no-title": "[Нема страница]",
+ "echo-pref-tooltip-emailuser": "Извести ме кога некој ќе ми испрати е-пошта.",
+ "echo-pref-tooltip-article-reminder": "Извести ме за страницава кога ќе побарам.",
"echo-error-no-formatter": "Нема зададено форматирање за ова известување",
"notifications": "Известувања",
"tooltip-pt-notifications-alert": "{{GENDER:|Ваши}} напомени",
- "tooltip-pt-notifications-message": "{{GENDER:|Ваши}} пораки",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Ваши}} известувања",
+ "echo-displaynotificationsconfiguration": "Прикажувај поставки за известувања",
+ "echo-displaynotificationsconfiguration-summary": "Ова е преглед на поставките за известувања на ова вики.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Известувања по категории",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Подредување на видови",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Во кој оддел ќе се подреди секој вид известување",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Допуштени начини на известување",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Кои начини на известување се поддржани за секоја категорија",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Кои начини на известување се поддржани за секој вид; се однесува само на видовите во рамките на категориите кои се скриени од поставките",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Овозможено по основно",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Постоечки корисници",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Нови корисници",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Задолжителни начини на известување",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Кои начини на известување се задолжителни за секоја категорија",
"echo-specialpage": "Известувања",
+ "echo-specialpage-section-markread": "Означи ја групата како прочитана",
+ "echo-specialpage-markasread": "Известување: Означување како прочитано",
+ "echo-specialpage-markasread-invalid-id": "Неважечка назнака на настанот",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|известување|известувања}}",
+ "echo-specialpage-pagination-range": "$1 - $2",
+ "echo-specialpage-pagefilters-title": "Скорешни активности",
+ "echo-specialpage-pagefilters-subtitle": "Страници со непрочитани известувања",
+ "notificationsmarkread-legend": "Означи го известувањето како прочитано",
"echo-anon": "За да добивате известувања, [$1 направете сметка] или [$2 најавете се].",
"echo-none": "Немате известувања.",
"echo-more-info": "Повеќе информации",
"echo-feedback": "Мислења",
+ "echo-popup-footer-special-page-invitation": "<strong>Пробајте ја новопреуредената страница за Известувања.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Нов изглед и нови можности.",
"echo-quotation-marks": "„$1“",
- "echo-api-failure": "Не можев да ги добијам известувањата. Обидете се повторно. (Грешка $1)",
+ "echo-api-failure": "Не успеав да ги добијам известувањата.",
+ "echo-api-failure-cross-wiki": "Пристапот до далечински домен е одбиен.",
"echo-notification-placeholder": "Нема известувања.",
+ "echo-notification-placeholder-filters": "Нема известувања што одговараат на зададеното.",
+ "echo-notification-loginrequired": "Мора да сте најавени за да ги видите известувањата.",
+ "echo-notification-popup-loginrequired": "Најавете се за да ги погледате вашите известувања.",
+ "echo-notification-markasread": "Означи како прочитано",
+ "echo-notification-markasunread": "Означи како непрочитано",
+ "echo-notification-markasread-tooltip": "Означи како прочитано",
+ "echo-notification-more-options-tooltip": "Повеќе можности",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Престани}} со набљудување на новите активности на „$1“",
+ "notification-dynamic-actions-unwatch-confirmation": "Повеќе не {{GENDER:$3|ја набљудувате}} страницата „$1“",
+ "notification-dynamic-actions-unwatch-confirmation-description": "Можете да {{GENDER:$3|ја набљудувате}} [$2 страницава] во секое време.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Следи}} ги новите активности на „$1“",
+ "notification-dynamic-actions-watch-confirmation": "Сега {{GENDER:$3|ја набљудувате}} страницата „$1“",
+ "notification-dynamic-actions-watch-confirmation-description": "Можете {{GENDER:$3|да престанете}} со набљудување на [$2 страницава] во секое време.",
+ "notification-link-text-expand-all": "Прикажи",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 напомена|$1 напомени}}",
+ "notification-link-text-expand-notice-count": "Погл. {{PLURAL:$1|$1 напомена|$1 напомени}}",
+ "notification-link-text-expand-all-count": "Погл. {{PLURAL:$1|$1 известување|$1 известувања}}",
+ "notification-link-text-collapse-all": "Собери",
"notification-link-text-view-message": "Погл. порака",
"notification-link-text-view-mention": "Погл. споменувањето",
- "notification-link-text-view-changes": "Погл. промени",
+ "notification-link-text-view-mention-failure": "Погл. {{PLURAL:$1|споменување|споменувања}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Погл.}} промени",
"notification-link-text-view-page": "Погл. страница",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|остави}} порака на <strong>{{GENDER:$3|вашата}} страница за разговор.</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|остави}} порака на <strong>{{GENDER:$3|вашата}} страница за разговор</strong> на <strong>„$4“.</strong>",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Направена е врска од <strong>$4</strong> до <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Поврзано од <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Направени се врски од {{PLURAL:$5||$5 страници|100=преку 99 страници}} до <strong>$3</strong>.",
+ "notification-header-article-reminder": "На <strong>$3</strong> има страница за која {{GENDER:$2|имате}} побарано потсетник",
+ "notification-link-text-what-links-here": "Сите врски до страницава",
+ "notification-header-mention-other": "$1 {{GENDER:$3|ве}} {{GENDER:$2|спомна}} на <strong>$4</strong> во „<strong>$5</strong>“.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|ве}} {{GENDER:$2|спомна}} на <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|ве}} {{GENDER:$2|спомна}} на <strong>страницата за разговор {{GENDER:$5|на}} $4</strong> во „<strong>$6</strong>“.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|ве}} {{GENDER:$2|спомна}} на <strong>страницата за разговор {{GENDER:$5|на}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|ве}} {{GENDER:$2|спомна}} на <strong>{{GENDER:$2|неговата|нејзината|својата}} страница</strong> за разговор во „<strong>$4</strong>“.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|ве}} {{GENDER:$2|спомна}} на <strong>{{GENDER:$2|неговата|нејзината|својата}} странца за разговор.</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|ве}} {{GENDER:$2|спомна}} во разговорот за <strong>$4</strong> во „<strong>$5</strong>“.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|ве}} {{GENDER:$2|спомна}} во разговорот за <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Вашето}} споменување на <strong>$3</strong> не е испратено бидејќи не можев да го најдам корисникот.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Вашето}} споменување на <strong>$3</strong> не е испратено бидејќи корисникот е анонимен.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Се обидовте}} да споменете повеќе од $3 {{PLURAL:$3|корисник|корисници}}. Сите споменувања што ја надминуваат оваа граница не беа испратени.",
+ "notification-header-mention-failure-bundle": "Не {{PLURAL:$3|е испратено споменувањето|се испратени $3 споменувањата}} {{GENDER:$3|што го {{GENDER:$2|направивте}}|што ги направивте}} на страницата за разговор <strong>$4</strong>.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Корисничкото име не постои:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Не можат да се споменуваат IP-адреси:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Вашето}} споменување на <strong>$3</strong> е испратено.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Испратено е|Испратени се}} {{PLURAL:$3|споменување што го {{GENDER:$2|направивте}}|$3 споменувања што ги направивте}} на страницата за разговор <strong>$4</strong>.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Го споменавте|Ја споменавте}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Известување|$3 известувања}} за споменувања {{GENDER:$2|што ги направивте}} на страницата за разговор <strong>$4</strong>: {{PLURAL:$5|$5 неисправена|$5 неиспратени}}, {{PLURAL:$6|$6 испратена|$6 испратени}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Вашите}} кориснички права се {{GENDER:$1|изменети}}. Додадени сте во: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Вашите}} кориснички права се {{GENDER:$1|изменети}}. Повеќе не членувате во $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Вашите}} кориснички права се {{GENDER:$1|изменети}}. Додадени сте во: $2. Повеќе не членувате во: $4.",
+ "notification-header-user-rights-expiry-change": "{{GENDER:$1|Изменет}} е истекот на {{GENDER:$4|вашето}} членство во {{PLURAL:$3|следнава група|следниве групи}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Добре дојдовте}} на {{SITENAME}}, $1! Драго ни е {{GENDER:$2|што сте}} тука.",
+ "notification-welcome-linktext": "Добре дојдовте",
+ "notification-header-thank-you-1-edit": "Штотуку го {{GENDER:$2|направивте}} {{GENDER:$2|вашето}} прво уредување. {{GENDER:$2|Ви}} благодариме, и добре дојдовте!",
+ "notification-header-thank-you-10-edit": "Штотуку го {{GENDER:$2|направивте}} {{GENDER:$2|вашето}} десетто уредување. {{GENDER:$2|Ви}} благодариме, и продолжете така!",
+ "notification-header-thank-you-100-edit": "Штотуку го {{GENDER:$2|направивте}} {{GENDER:$2|вашето}} стото уредување. Многу {{GENDER:$2|ви}} благодариме!",
+ "notification-header-thank-you-1000-edit": "Штотуку го {{GENDER:$2|направивте}} {{GENDER:$2|вашето}} илјадито уредување. {{GENDER:$2|Ви}} благодариме за големиот придонес!",
+ "notification-header-thank-you-10000-edit": "Штотуку го {{GENDER:$2|направивте}} {{GENDER:$2|вашето}} десетилјадито уредување. Ја {{GENDER:$2|имате}} нашата огромна благодарност!",
+ "notification-header-thank-you-100000-edit": "Штотуку го {{GENDER:$2|направивте}} {{GENDER:$2|вашето}} стоилјадито уредување. {{GENDER:$2|Ви}} благодариме за феноменалниот придонес!",
+ "notification-header-thank-you-1000000-edit": "Штотуку го {{GENDER:$2|направивте}} {{GENDER:$2|вашето}} милионито уредување. {{GENDER:$2|Ви}} благодариме за запрепастувачкиот придонес!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Вашето}} уредување",
"notification-link-text-view-edit": "Погл. уредување",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|остави}} порака на вашата [[User talk:$2#$3|страница за разговор]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|остави}} порака на вашата страница за разговор во „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|остави}} порака на вашата [[User talk:$2#$3|страница за разговор]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|остави}} порака на вашата страница за разговор во „[[User talk:$2#$3|$4]]“.",
- "notification-page-linked": "[[:$2]] е {{GENDER:$1|наведена}} од [[:$3]]. [[Special:WhatLinksHere/$2|Погл. сите врски до страницава]].",
- "notification-page-linked-flyout": "[[:$2]] е {{GENDER:$1|наведена}} на [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|коментираше}} на „[[$3|$2]]“ на страницата за разговор „$4“",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|ја објави}} новата тема „$2“ на [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|ви испрати}} порака: „[[$3#$2|$2]]“",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|коментираше}} на „[[$3#$2|$2]]“ на вашата страница за разговор",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|ве спомна}} во страницата $5 на „[[:$3#$2|$4]]“.",
- "notification-mention-flyout": "$1 {{GENDER:$1|ве спомна}} во страницата $5 на „[[:$3#$2|$4]]“.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|ве спомна}} на [[:$3|страницата за разговор на $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|ве спомна}} во [[:$3|страницата за разговор на $2]].",
- "notification-user-rights": "Вашите кориснички права се [[Special:Log/rights/$1|{{GENDER:$1|изменети}}]] од [[User:$1|$1]]. $2. [[Special:ListGroupRights|Дознајте повеќе]]",
- "notification-user-rights-flyout": "Вашите кориснички права се {{GENDER:$1|изменети}} од $1. $2. [[Special:ListGroupRights|Дознајте повеќе]]",
- "notification-user-rights-add": "Сега членувате во {{PLURAL:$2|оваа група|овие групи}}: $1",
- "notification-user-rights-remove": "Повеќе не членувате во {{PLURAL:$2|оваа група|овие групи}}: $1",
- "notification-new-user": "Добре дојдовте на {{SITENAME}}, $1! Драго ни е што сте тука.",
- "notification-reverted2": "[[User:$1|$1]] {{PLURAL:$4|го|ги}} {{GENDER:$1|врати}} {{PLURAL:$4|вашето уредување на [[:$2]]|вашите уредувања на [[:$2]]}} $3",
- "notification-reverted-flyout2": "$1 {{PLURAL:$4|го|ги}} {{GENDER:$1|врати}} {{PLURAL:$4|вашето уредување на $2|вашите уредувања на $2}} $3",
+ "notification-link-article-reminder": "Погл. страница",
+ "notification-header-reverted": "{{PLURAL:$4|Вашето уредување на <strong>$3</strong> е {{GENDER:$2|отповикано}}|Вашите уредувања на <strong>$3</strong> се {{GENDER:$2|отповикани}}}}",
+ "notification-header-emailuser": "$1 {{GENDER:$2|ви испрати}} е-пошта.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|ви остави}} порака на {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|остави}} порака на вашата страница за разговор.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|остави}} порака на вашата страница за разговор на „$2“.",
"notification-page-linked-email-subject": "Ваша страница беше наведена на {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 е {{GENDER:$1|наведена}} на $3",
"notification-reverted-email-subject2": "{{GENDER:$1|На}} {{SITENAME}} {{PLURAL:$3|е вратено ваше уредување|се вратени ваши уредувања}}",
- "notification-reverted-email-batch-body2": "$1 {{GENDER:$1|врати}} {{PLURAL:$3|ваше уредување на $2|ваши уредувања на $2}}",
- "notification-mention-email-subject": "$1 {{GENDER:$1|ве спомна}} на {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|ве спомна}} во страницата $4 на „$3“.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|ве спомна}} во страницата за разговор на $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|ве}} {{GENDER:$2|спомна}} на {{SITENAME}}",
"notification-user-rights-email-subject": "Вашите кориснички права на {{SITENAME}} се изменети",
- "notification-user-rights-email-batch-body": "Вашите кориснички права се {{GENDER:$1|изменети}} од $1. $2",
- "echo-email-subject-default": "Ново известување на {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 с}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 м}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ч}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 д}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 мес.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 г.}}",
+ "notification-timestamp-today": "Денес",
+ "notification-timestamp-yesterday": "Вчера",
+ "notification-inbox-filter-read": "Прочитани",
+ "notification-inbox-filter-unread": "Непрочитани",
+ "notification-inbox-filter-all": "Сите",
"echo-email-body-default": "Имате ново известување на {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Имате ново известување",
- "echo-email-footer-default": "$2\n\nАко сакате да изберете какви пораки да добивате, појдете на страницата:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}} $1\n\n$1",
- "echo-email-footer-default-html": "За да изберете какви писма да примате од нас, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">појдете во вашите нагодувања</a><br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|Едно известување|$1 известувања|100=99+ известувања}}",
- "echo-notification-message": "{{PLURAL:$1|Една порака|$1 пораки|100=99+ пораки}}",
- "echo-notification-alert-text-only": "Известувања",
- "echo-notification-message-text-only": "Пораки",
+ "echo-email-footer-default-html": "За да одберете каква е-пошта да ви праќаме, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">проверете си ги поставките</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nАко сакате да изберете какви пораки да добивате од нас по е-пошта:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "За да одберете каква е-пошта да {{GENDER:$1|ви}} праќаме, проверете {{GENDER:$1|си}} ги поставките:",
+ "echo-email-html-footer-preference-link-text": "проверете {{GENDER:$1|си}} ги поставките",
+ "echo-email-html-footer-with-link": "За да одберете каква е-пошта да {{GENDER:$2|ви}} праќаме, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Напомена ($1)|Напомени ($1)|100=Напомени (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Напомена ($1)|Напомени ($1)|100=Напомени (99+)}}",
+ "echo-notification-alert-text-only": "Напомени",
+ "echo-notification-notice-text-only": "Напомени",
"echo-overlay-link": "Сите известувања",
"echo-overlay-title": "<b>Известувања</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Известувања}}</b> ({{PLURAL:$1|прикажано|прикажани}} $1 од $2 непрочитани)",
"echo-mark-all-as-read": "Означи ги сите како прочитани",
+ "echo-mark-all-as-read-confirmation": "{{PLURAL:$1|Означено $1 известување|Означени $1 известувања}} како прочитани",
+ "echo-mark-wiki-as-read": "Означи ги сите како прочитани на избраното вики: $1",
"echo-date-today": "Денес",
"echo-date-yesterday": "Вчера",
- "echo-load-more-error": "Се појави грешка при обидот да добијам повеќе резултати.",
- "notification-edit-talk-page-bundle": "$1 и {{PLURAL:$4|уште еден друг|уште $3 други}} {{GENDER:$1|оставија}} порака на вашата [[User talk:$2|страница за разговор]].",
- "notification-page-linked-bundle": "$2 е {{GENDER:$1|наведена}} на $3 и уште $4 {{PLURAL:$5|страница|страници}}. [[Special:WhatLinksHere/$2|Погл. сите врски до страницава]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 и уште {{PLURAL:$3|еден|$2 корисници}} {{GENDER:$1|оставија}} порака на вашата страница за разговор",
- "notification-page-linked-email-batch-bundle-body": "$2 беше {{GENDER:$1|наведена}} од $3 и уште {{PLURAL:$5|една страница|$4 страници}}",
+ "echo-load-more-error": "Се појави грешка при обидот да добијам повеќе ставки.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Една нова порака|$1 нови пораки|100=преку 99 нови пораки}} на <strong>{{GENDER:$3|вашата}} страница за разговор</strong>.",
"echo-email-batch-subject-daily": "Имате {{PLURAL:$2|ново известување|нови известувања}} на {{SITENAME}}",
"echo-email-batch-subject-weekly": "Неделава имате {{PLURAL:$2|ново известување|нови известувања}} на {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Здраво $1,\nВи даваме преглед на денешните збиднувања на {{SITENAME}}",
"echo-email-batch-body-intro-weekly": "Здраво $1,\nВи даваме преглед на збиднувањата на {{SITENAME}} за оваа седмица",
"echo-email-batch-link-text-view-all-notifications": "Погл. сите известувања",
- "echo-rev-deleted-text-view": "Оваа преработка е скриена",
- "apihelp-echomarkread-description": "Означи ги сите известувања како прочитани за тековниот корисник.",
- "apihelp-echomarkread-param-list": "Список на назнаки на известувањата што треба да се означат како прочитани.",
- "apihelp-echomarkread-param-all": "Ако е зададено, ги означува сите известувања на еден корисник како прочитани.",
- "apihelp-echomarkread-param-sections": "Список на поднаслови што треба да се означат како прочитани.",
- "apihelp-echomarkread-example-1": "Означи го известувањето 8 како прочитано",
- "apihelp-echomarkread-example-2": "Означиу ги сите известувања како прочитани",
- "apihelp-echomarkseen-description": "Означи ги известувањата како прочитани за тековниот корисник.",
- "apihelp-echomarkseen-example-1": "Означи ги известувањања од сите видови како прочитани",
- "apihelp-echomarkseen-param-type": "Видови известувања што треба да се означат како видени: „alert“, „message“ или „all“.",
- "apihelp-query+notifications-description": "Дај ги известувањата што го исчекуваат тековниот корисник.",
- "apihelp-query+notifications-param-prop": "Подробности што треба да се побараат.",
- "apihelp-query+notifications-param-sections": "Известителните поднаслови што треба да се побараат (т.е. некоја комбинација од „alert“ и „message“).",
- "apihelp-query+notifications-param-groupbysection": "Дали да се групираат резултатите по поднаслови. Ако е зададено, секој поднаслов се дава посебно.",
- "apihelp-query+notifications-param-format": "Ако е укажано, известувањата ќе се дадат форматирани на овој начин.",
- "apihelp-query+notifications-param-limit": "Максималниот број на известувања што ќе се дадат.",
- "apihelp-query+notifications-param-index": "Ако е укажано, ќе се даде список на назнаки на известувања по редослед.",
- "apihelp-query+notifications-param-alertcontinue": "Употребете го ова за да продолжите кога има повеќе напомени за известувања.",
- "apihelp-query+notifications-param-alertunreadfirst": "Дали прво да се прикажуваат непрочитаните известувања за порака.",
- "apihelp-query+notifications-param-messagecontinue": "Употребете го ова за да продолжите кога има повеќе резултати за пораки.",
- "apihelp-query+notifications-param-messageunreadfirst": "Дали прво да се прикажуваат непрочитаните напомени за известувања.",
- "apihelp-query+notifications-example-1": "Испиши известувања",
- "apihelp-query+notifications-example-2": "Испиши известувања, групирани по поднаслови, со бројност"
+ "notification-header-foreign-alert": "Повеќе напомени од {{PLURAL:$5|друго вики|$5 други викија}}",
+ "notification-header-foreign-notice": "Уште напомени од {{PLURAL:$5|друго вики|$5 други викија}}",
+ "notification-header-foreign-all": "Уште известувања од {{PLURAL:$5|друго вики|$5 други викија}}",
+ "echo-foreign-wiki-lang": "$1 — $2"
}
diff --git a/Echo/i18n/ml.json b/Echo/i18n/ml.json
index 2fac03ae..6b810924 100644
--- a/Echo/i18n/ml.json
+++ b/Echo/i18n/ml.json
@@ -4,7 +4,8 @@
"Praveenp",
"Santhosh.thottingal",
"Sidharthan",
- "Vssun"
+ "Vssun",
+ "Macofe"
]
},
"echo-desc": "സംഭവങ്ങളെക്കുറിച്ചും സന്ദേശങ്ങളെക്കുറിച്ചും ഉപയോക്താക്കളെ അറിയിക്കാനുള്ള സംവിധാനം",
@@ -13,7 +14,7 @@
"prefs-displaynotifications": "പ്രദർശന ഐച്ഛികങ്ങൾ",
"prefs-echosubscriptions": "ഈ സംഭവങ്ങളെക്കുറിച്ച് എന്നെ അറിയിക്കുക",
"prefs-newmessageindicator": "പുതിയ സന്ദേശത്തിന്റെ അടയാളം",
- "echo-pref-send-me": "അയക്കേണ്ട രീതി:",
+ "echo-pref-send-me": "എനിക്ക് അയയ്ക്കുക:",
"echo-pref-send-to": "അയക്കേണ്ട വിലാസം:",
"echo-pref-email-format": "ഇമെയിൽ എഴുത്തുരീതി:",
"echo-pref-web": "വെബ്",
@@ -25,6 +26,8 @@
"echo-pref-email-format-html": "എച്ച്.റ്റി.എം.എൽ.",
"echo-pref-email-format-plain-text": "വെറും എഴുത്ത്",
"echo-pref-new-message-indicator": "എന്റെ സംവാദത്താളിലെ സന്ദേശങ്ങളുടെ സൂചന ടൂൾബാറിൽ പ്രദർശിപ്പിക്കുക",
+ "echo-pref-beta-feature-cross-wiki-message": "മെച്ചപ്പെടുത്തിയ അറിയിപ്പുകൾ",
+ "echo-pref-beta-feature-cross-wiki-description": "അറിയിപ്പുകൾ കൂടുതൽ എളുപ്പത്തിൽ കാണുകയും ക്രമപ്പെടുത്തുകയും ചെയ്യുക. മറ്റ് വിക്കികളിൽ നിന്നുള്ള സന്ദേശങ്ങൾ കാണാനനുവദിക്കുന്ന അന്തർവിക്കി അറിയിപ്പുകൾ ഉൾപ്പടെ.",
"echo-learn-more": "കൂടുതൽ അറിയുക",
"echo-new-messages": "താങ്കൾക്ക് പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്",
"echo-category-title-edit-user-talk": "സംവാദത്താളിലെ {{PLURAL:$1|സന്ദേശം|സന്ദേശങ്ങൾ}}",
@@ -34,69 +37,55 @@
"echo-category-title-other": "{{PLURAL:$1|മറ്റുള്ളവ}}",
"echo-category-title-system": "{{PLURAL:$1|വ്യവസ്ഥ}}",
"echo-category-title-user-rights": "ഉപയോക്തൃ അവകാശ {{PLURAL:$1|മാറ്റം|മാറ്റങ്ങൾ}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|മറ്റൊരു ഉപയോക്താവ് അയച്ച ഇമെയിൽ|മറ്റ് ഉപയോക്താക്കൾ അയച്ച ഇമെയിലുകൾ}}",
"echo-pref-tooltip-edit-user-talk": "ആരെങ്കിലും എന്റെ സംവാദത്താളിൽ ഒരു സന്ദേശമോ മറുപടിയോ ഇട്ടാൽ എന്നെ അറിയിക്കുക.",
"echo-pref-tooltip-article-linked": "ഞാൻ സൃഷ്ടിച്ച ഒരു ലേഖനതാളിൽ ആരെങ്കിലും കണ്ണി ചേർത്താൽ എന്നെ അറിയിക്കുക.",
"echo-pref-tooltip-reverted": "തിരസ്കരണ അല്ലെങ്കിൽ മുൻപ്രാപന ഉപകരണമുപയോഗിച്ച് ആരെങ്കിലും ഞാൻ വരുത്തിയ തിരുത്തൽ ഒഴിവാക്കിയാൽ എന്നെ അറിയിക്കുക.",
"echo-pref-tooltip-mention": "ആരെങ്കിലും എന്റെ ഉപയോക്തൃതാളിലേക്ക് കണ്ണി ചേർത്താൽ എന്നെ അറിയിക്കുക.",
"echo-pref-tooltip-user-rights": "എന്റെ ഉപയോക്തൃ അവകാശങ്ങളിൽ ആരെങ്കിലും മാറ്റം വരുത്തിയാൽ എന്നെ അറിയിക്കുക.",
- "echo-no-agent": "[ആരുമില്ല]",
- "echo-no-title": "[താൾ ഇല്ല]",
+ "echo-pref-tooltip-emailuser": "ആരെങ്കിലും എനിക്ക് ഇമെയിൽ അയച്ചാൽ എന്നെ അറിയിക്കുക.",
"echo-error-no-formatter": "അറിയിപ്പിനായി യാതൊരു രൂപവും നിർവ്വചിച്ചിട്ടില്ല",
"notifications": "അറിയിപ്പുകൾ",
"tooltip-pt-notifications-alert": "{{GENDER:|താങ്കൾക്കുള്ള}} അറിയിപ്പുകൾ",
- "tooltip-pt-notifications-message": "{{GENDER:|താങ്കൾക്കുള്ള}} സന്ദേശങ്ങൾ",
"echo-specialpage": "അറിയിപ്പുകൾ",
"echo-anon": "അറിയിപ്പുകൾ ലഭിക്കാനായി, [$1 അംഗത്വമെടുക്കയോ] [$2 പ്രവേശിക്കുകയോ] ചെയ്യേണ്ടതാണ്.",
"echo-none": "താങ്കൾക്ക് അറിയിപ്പുകളൊന്നുമില്ല.",
"echo-more-info": "കൂടുതൽ വിവരങ്ങൾ",
"echo-feedback": "പ്രതികരണം",
+ "echo-api-failure": "അറിയിപ്പുകൾ എടുക്കാൻ കഴിഞ്ഞില്ല. ദയവായി വീണ്ടും ശ്രമിക്കുക. (പിഴവ് $1)",
+ "echo-api-failure-cross-wiki": "വിദൂര ഡൊമൈന്റെ ലഭ്യത നിരാകരിച്ചിരിക്കുന്നു.",
+ "echo-notification-placeholder": "അറിയിപ്പുകൾ ഒന്നുമില്ല.",
+ "echo-notification-loginrequired": "താങ്കൾക്കുള്ള അറിയിപ്പുകൾ കാണാൻ പ്രവേശിച്ചിരിക്കണം.",
+ "echo-notification-popup-loginrequired": "താങ്കൾക്കുള്ള അറിയിപ്പുകൾ കാണാൻ പ്രവേശിക്കുക.",
+ "notification-link-text-expand-all": "എല്ലാം വികസിപ്പിക്കുക",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|ഒരു ജാഗ്രതാ അറിയിപ്പ്|$1 ജാഗ്രതാ അറിയിപ്പുകൾ}} വികസിപ്പിക്കുക",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|ഒരു അറിയിപ്പ്|$1 അറിയിപ്പുകൾ}} വികസിപ്പിക്കുക",
+ "notification-link-text-collapse-all": "എല്ലാം ചുരുക്കുക",
"notification-link-text-view-message": "സന്ദേശം കാണുക",
"notification-link-text-view-mention": "പരാമർശിച്ചിരിക്കുന്നത് കാണുക",
"notification-link-text-view-changes": "മാറ്റങ്ങൾ കാണുക",
"notification-link-text-view-page": "താൾ കാണുക",
+ "notification-header-edit-user-talk": "{{GENDER:$3|താങ്കളുടെ}} സംവാദത്താളിൽ, $1 ഒരു സന്ദേശം {{GENDER:$2|ചേർത്തിട്ടുണ്ട്}}.",
+ "notification-header-edit-user-talk-with-section": "{{GENDER:$3|താങ്കളുടെ}} സംവാദത്താളിലെ \"$4\" ഭാഗത്ത്, $1 ഒരു സന്ദേശം {{GENDER:$2|ചേർത്തിട്ടുണ്ട്}}.",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "<strong>$4</strong> എന്ന താളിൽ നിന്ന് <strong>$3</strong> എന്ന താളിലേക്ക് ഒരു കണ്ണി സൃഷ്ടിക്കപ്പെട്ടിരിക്കുന്നു.",
+ "notification-bundle-header-page-linked": "$4 എന്ന താളിൽ നിന്നും $5 മറ്റ് {{PLURAL:$6|താളിൽ|താളുകളിൽ}} നിന്നും $3 എന്ന താളിലേക്ക് കണ്ണി ചേർക്കപ്പെട്ടു.",
+ "notification-link-text-what-links-here": "ഈ താളിലേക്കുള്ള കണ്ണികൾ",
+ "notification-header-welcome": "{{SITENAME}} സംരംഭത്തിലേക്ക് {{GENDER:$2|സ്വാഗതം}}, $1! {{GENDER:$2|താങ്കൾ}} ഇവിടെ എത്തിയതിൽ അതിയായി സന്തോഷിക്കുന്നു.",
+ "notification-welcome-linktext": "സ്വാഗതം",
"notification-link-text-view-edit": "തിരുത്ത് കാണുക",
- "notification-edit-talk-page2": "താങ്കളുടെ [[User talk:$2#$3|സംവാദത്താളിൽ]] [[User:$1|$1]] ഒരു സന്ദേശം {{GENDER:$1|ചേർത്തിരിക്കുന്നു}} .",
- "notification-edit-talk-page-with-section": "താങ്കളുടെ സംവാദത്താളിൽ ''[[User talk:$2#$3|$4]]'' എന്ന് [[User:$1|$1]] ഒരു സന്ദേശം {{GENDER:$1|ചേർത്തിരിക്കുന്നു}}.",
- "notification-edit-talk-page-flyout2": "താങ്കളുടെ [[User talk:$2#$3|സംവാദത്താളിൽ]] $1 ഒരു സന്ദേശം {{GENDER:$1|ചേർത്തിരിക്കുന്നു}}.",
- "notification-edit-talk-page-flyout-with-section": "താങ്കളുടെ സംവാദത്താളിൽ ''[[User talk:$2#$3|$4]]'' എന്ന് ഒരു സന്ദേശം $1 {{GENDER:$1|ചേർത്തിരിക്കുന്നു}}.",
- "notification-page-linked": "[[:$2]] എന്ന താളിലേയ്ക്ക് [[:$3]] എന്ന താളിൽ നിന്ന് കണ്ണി {{GENDER:$1|ചേർക്കപ്പെട്ടിരിക്കുന്നു}}: [[Special:WhatLinksHere/$2|ഈ താളിലേയ്ക്കുള്ള എല്ലാ കണ്ണികളും കാണുക]]",
- "notification-page-linked-flyout": "[[:$2]] എന്ന താളിലേയ്ക്ക് [[:$3]] എന്ന താളിൽ നിന്ന് കണ്ണി {{GENDER:$1|ചേർക്കപ്പെട്ടിരിക്കുന്നു}}.",
- "notification-add-comment2": "[[User:$1|$1]] \"$4\" സംവാദത്താളിലെ \"[[$3|$2]]\" എന്നതിൽ {{GENDER:$1|കുറിപ്പിട്ടിരിക്കുന്നു}}",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] [[$3]] എന്ന താളിലെ \"$2\" എന്നതിൽ ഒരു പുതിയ വിഷയം {{GENDER:$1|ചേർത്തു}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] താങ്കൾക്ക് ഒരു സന്ദേശം {{GENDER:$1|അയച്ചിട്ടുണ്ട്}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] താങ്കളുടെ സംവാദത്താളിലെ \"[[$3#$2|$2]]\" എന്നതിൽ {{GENDER:$1|കുറിപ്പിട്ടു}}",
- "notification-mention": "[[User:$1|$1]] താങ്കളെ $5 എന്ന സംവാദത്താളിലെ \"[[:$3#$2|$4]]\" എന്ന ഭാഗത്ത് {{GENDER:$1|പരാമർശിച്ചിരിക്കുന്നു}}.",
- "notification-mention-flyout": "$1 എന്ന ഉപയോക്താവ് താങ്കളെ $5 എന്ന സംവാദത്താളിലെ \"[[:$3#$2|$4]]\" എന്ന ഭാഗത്ത് {{GENDER:$1|പരാമർശിച്ചിരിക്കുന്നു}}.",
- "notification-mention-nosection": "[[:$3|$2 സംവാദത്താളിൽ]] താങ്കളെ [[User:$1|$1]] {{GENDER:$1|പരാമർശിച്ചിരിക്കുന്നു}}.",
- "notification-mention-nosection-flyout": "[[:$3|$2 സംവാദത്താളിൽ]] താങ്കളെ $1 {{GENDER:$1|പരാമർശിച്ചിരിക്കുന്നു}}.",
- "notification-user-rights": "താങ്കളുടെ ഉപയോക്തൃ അവകാശങ്ങൾ [[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|മാറ്റിയിരിക്കുന്നു}}]]. $2 . [[Special:ListGroupRights|കൂടുതലറിയുക]]",
- "notification-user-rights-flyout": "താങ്കളുടെ ഉപയോക്തൃ അവകാശങ്ങൾ $1 {{GENDER:$1|മാറ്റിയിരിക്കുന്നു}}. $2 . [[Special:ListGroupRights|കൂടുതലറിയുക]]",
- "notification-user-rights-add": "താങ്കളിപ്പോൾ {{PLURAL:$2|ഈ സംഘത്തിൽ|ഈ സംഘങ്ങളിൽ}} അംഗമാണ്: $1",
- "notification-user-rights-remove": "താങ്കളിപ്പോൾ {{PLURAL:$2|ഈ സംഘത്തിൽ|ഈ സംഘങ്ങളിൽ}} അംഗമല്ല: $1",
- "notification-new-user": "{{SITENAME}} സംരംഭത്തിലേയ്ക്ക് സ്വാഗതം, $1! താങ്കളിവിടെ എത്തിയതിൽ സന്തോഷമുണ്ട്.",
- "notification-reverted2": "[[:$2]] എന്ന താളിൽ, താങ്കൾ ചെയ്ത {{PLURAL:$4|തിരുത്ത്|തിരുത്തുകൾ}} [[User:$1|$1]] {{GENDER:$1|മുൻപ്രാപനം ചെയ്തിരിക്കുന്നു}}. $3",
- "notification-reverted-flyout2": "$2 എന്ന താളിൽ, താങ്കൾ ചെയ്ത {{PLURAL:$4|തിരുത്ത്|തിരുത്തുകൾ}} $1 {{GENDER:$1|മുൻപ്രാപനം ചെയ്തിരിക്കുന്നു}}. $3",
+ "notification-header-reverted": "താങ്കൾ വരുത്തിയ {{PLURAL:$4|<strong>$3</strong> താളിലെ തിരുത്ത്|<strong>$3</strong> താളിലെ തിരുത്തുകൾ}}{{GENDER:$2|മുൻപ്രാപനം ചെയ്തിരിക്കുന്നു}}",
+ "notification-header-emailuser": "$1 താങ്കൾക്കൊരു ഇമെയിൽ {{GENDER:$2|അയച്ചിട്ടുണ്ട്}}.",
"notification-edit-talk-page-email-subject2": "{{SITENAME}} സംരംഭത്തിൽ, താങ്കൾക്കൊരു സന്ദേശം $1 {{GENDER:$1|ചേർത്തിട്ടുണ്ട്}}",
- "notification-edit-talk-page-email-batch-body2": "താങ്കളുടെ സംവാദത്താളിൽ, ഒരു സന്ദേശം $1 {{GENDER:$1|ചേർത്തിട്ടുണ്ട്}}.",
"notification-edit-talk-page-email-batch-body-with-section": "താങ്കളുടെ സംവാദത്താളിൽ, \"$2\" എന്നതിൽ ഒരു സന്ദേശം $1 {{GENDER:$1|ചേർത്തിട്ടുണ്ട്}}.",
"notification-page-linked-email-subject": "താങ്കൾ സൃഷ്ടിച്ച ഒരു താൾ {{SITENAME}} സംരംഭത്തിൽ കണ്ണിചേർക്കപ്പെട്ടിരിക്കുന്നു",
- "notification-page-linked-email-batch-body": "$2 എന്ന താളിലേയ്ക്ക് $3 എന്ന താളിൽ നിന്ന് കണ്ണി {{GENDER:$1|ചേർക്കപ്പെട്ടിരിക്കുന്നു}}",
"notification-reverted-email-subject2": "{{SITENAME}} സംരംഭത്തിൽ താങ്കൾ വരുത്തിയ {{PLURAL:$3|തിരുത്ത്|തിരുത്തുകൾ}} {{GENDER:$1|മുൻപ്രാപനം ചെയ്തിരിക്കുന്നു}}",
- "notification-reverted-email-batch-body2": "താങ്കൾ വരുത്തിയ {{PLURAL:$3|$2 താളിലെ തിരുത്ത്|$2 താളിലെ തിരുത്തുകൾ}} $1 {{GENDER:$1|മുൻപ്രാപനം ചെയ്തിരിക്കുന്നു}}",
- "notification-mention-email-subject": "$1 താങ്കളെ {{SITENAME}} സംരംഭത്തിൽ {{GENDER:$1|പരാമർശിച്ചിരിക്കുന്നു}}",
- "notification-mention-email-batch-body": "$1 താങ്കളെ $4 സംവാദത്താളിൽ \"$3\" എന്നതിൽ {{GENDER:$1|പരാമർശിച്ചിരിക്കുന്നു}}.",
- "notification-mention-nosection-email-batch-body": "$2 സംവാദത്താളിൽ താങ്കളെ $1 {{GENDER:$1|പരാമർശിച്ചിരിക്കുന്നു}}.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|താങ്കളെ}} {{SITENAME}} സംരംഭത്തിൽ {{GENDER:$1|പരാമർശിച്ചിരിക്കുന്നു}}",
"notification-user-rights-email-subject": "{{SITENAME}} സംരംഭത്തിൽ താങ്കളുടെ അവകാശങ്ങളിൽ മാറ്റമുണ്ടായിരിക്കുന്നു",
- "notification-user-rights-email-batch-body": "താങ്കളുടെ ഉപയോക്തൃ അവകാശങ്ങൾ $1 {{GENDER:$1|മാറ്റിയിരിക്കുന്നു}}. $2",
- "echo-email-subject-default": "{{SITENAME}} സംരംഭത്തിൽ അറിയിപ്പുണ്ട്",
"echo-email-body-default": "{{SITENAME}} സംരംഭത്തിൽ താങ്കൾക്ക് ഒരു അറിയിപ്പുണ്ട്:\n\n$1",
- "echo-email-batch-body-default": "താങ്കൾക്ക് ഒരറിയിപ്പുണ്ട്",
"echo-email-footer-default": "$2\n\nഞങ്ങൾ താങ്കൾക്കയയ്ക്കുന്ന ഇമെയിലുകൾ നിയന്ത്രിക്കാൻ, താങ്കളുടെ ക്രമീകരണങ്ങൾ ഉപയോഗിക്കുക: {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "ഞങ്ങൾ താങ്കൾക്കയയ്ക്കുന്ന ഇമെയിലുകൾ നിയന്ത്രിക്കാൻ, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">താങ്കളുടെ ക്രമീകരണങ്ങൾ പരിശോധിക്കുക</a>.<br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|അറിയിപ്പ് ($1)|അറിയിപ്പുകൾ ($1)|100=അറിയിപ്പുകൾ (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|സന്ദേശം ($1)|സന്ദേശങ്ങൾ ($1)|100=സന്ദേശങ്ങൾ (99+)}}",
+ "echo-notification-alert": "{{PLURAL:$1|ജാഗ്രതാ അറിയിപ്പ് ($1)|ജാഗ്രതാ അറിയിപ്പുകൾ ($1)|100=ജാഗ്രതാ അറിയിപ്പുകൾ (99+)}}",
"echo-notification-alert-text-only": "അറിയിപ്പുകൾ",
- "echo-notification-message-text-only": "സന്ദേശങ്ങൾ",
"echo-overlay-link": "എല്ലാ അറിയിപ്പുകളും",
"echo-overlay-title": "<b>അറിയിപ്പുകൾ</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|അറിയിപ്പുകൾ}}</b> (വായിക്കാത്ത $2 എണ്ണത്തിലെ $1 എണ്ണം കാണിക്കുന്നു)",
@@ -104,36 +93,9 @@
"echo-date-today": "ഇന്ന്",
"echo-date-yesterday": "ഇന്നലെ",
"echo-load-more-error": "കൂടുതൽ ഫലങ്ങൾ എടുക്കുന്നതിനിടെ ഒരു പിഴവുണ്ടായി.",
- "notification-edit-talk-page-bundle": "$1 എന്നയാൾക്കുപുറമേ {{PLURAL:$4|മറ്റൊരാളും|മറ്റ് $3 പേരും}} താങ്കളുടെ [[User talk:$2|സംവാദത്താളിൽ]] സന്ദേശം {{GENDER:$1|ചേർത്തിരിക്കുന്നു}}.",
- "notification-page-linked-bundle": "$2 എന്ന താളിലേയ്ക്ക് $3 എന്ന താളിൽ നിന്നും മറ്റ് $4 {{PLURAL:$5|താളിൽ|താളുകളിൽ}} നിന്നും കണ്ണി {{GENDER:$1|ചേർക്കപ്പെട്ടിരിക്കുന്നു}}. [[Special:WhatLinksHere/$2|ഈ താളിലേയ്ക്കുള്ള എല്ലാ കണ്ണികളും കാണുക]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 എന്ന ഉപയോക്താവും ഒപ്പം {{PLURAL:$3|മറ്റൊരു ഉപയോക്താവും|$2 മറ്റുപയോക്താക്കളും}} താങ്കളുടെ സം‌വാദത്താളിൽ സന്ദേശം {{GENDER:$1|ചേർത്തിരിക്കുന്നു}}.",
- "notification-page-linked-email-batch-bundle-body": "$2 എന്ന താളിലേയ്ക്ക് $3 എന്ന താളിൽ നിന്നും മറ്റ് $4 {{PLURAL:$5|താളിൽ|താളുകളിൽ}} നിന്നും {{GENDER:$1|കണ്ണി ചേർക്കപ്പെട്ടിരിക്കുന്നു}}.",
"echo-email-batch-subject-daily": "താങ്കൾക്ക് {{SITENAME}} സംരംഭത്തിൽ {{PLURAL:$2|ഒരു പുതിയ അറിയിപ്പ്|പുതിയ അറിയിപ്പുകൾ}} ഉണ്ട്",
"echo-email-batch-subject-weekly": "താങ്കൾക്ക് ഈ ആഴ്ച, {{SITENAME}} സംരംഭത്തിൽ {{PLURAL:$2|പുതിയ ഒരറിയിപ്പ്|പുതിയ അറിയിപ്പുകൾ}} ഉണ്ട്",
"echo-email-batch-body-intro-daily": "പ്രിയ $1,\n{{SITENAME}} സംരംഭത്തിൽ, താങ്കളെ ബാധിക്കുന്ന ഇന്നത്തെ പ്രവർത്തനങ്ങളുടെ സംഗ്രഹം ഇതാ.",
"echo-email-batch-body-intro-weekly": "പ്രിയ $1,\n{{SITENAME}} സംരംഭത്തിൽ, താങ്കളെ ബാധിക്കുന്ന ഈ ആഴ്ചയിലെ പ്രവർത്തനങ്ങളുടെ സംഗ്രഹം ഇതാ.",
- "echo-email-batch-link-text-view-all-notifications": "എല്ലാ അറിയിപ്പുകളും കാണുക",
- "echo-rev-deleted-text-view": "താളിന്റെ ഈ നാൾപ്പതിപ്പ് ഒതുക്കിയിരിക്കുന്നു.",
- "apihelp-echomarkread-description": "ഇപ്പോഴത്തെ ഉപയോക്താവിന്റെ അറിയിപ്പുകൾ വായിച്ചതായി അടയാളപ്പെടുത്തുക.",
- "apihelp-echomarkread-param-list": "വായിച്ചതായി അടയാളപ്പെടുത്തേണ്ട അറിയിപ്പ് ഐ.ഡി.കളുടെ പട്ടിക.",
- "apihelp-echomarkread-param-all": "സജ്ജമെങ്കിൽ ഉപയോക്താവിനുള്ള അറിയിപ്പുകളെല്ലാം വായിച്ചതായി അടയാളപ്പെടുത്തുക.",
- "apihelp-echomarkread-param-sections": "വായിച്ചതായി അടയാളപ്പെടുത്തേണ്ട ഭാഗങ്ങളുടെ പട്ടിക.",
- "apihelp-echomarkread-example-1": "അറിയിപ്പ് 8 വായിച്ചതായി അടയാളപ്പെടുത്തുക",
- "apihelp-echomarkread-example-2": "എല്ലാ അറിയിപ്പുകളും വായിച്ചതായി അടയാളപ്പെടുത്തുക",
- "apihelp-echomarkseen-description": "ഇപ്പോഴത്തെ ഉപയോക്താവ് കണ്ടെന്ന് അറിയിപ്പുകളിൽ അടയാളപ്പെടുത്തുക.",
- "apihelp-echomarkseen-example-1": "എല്ലാ തരത്തിലുമുള്ള അറിയിപ്പുകളും കണ്ടെന്ന് അടയാളപ്പെടുത്തുക",
- "apihelp-echomarkseen-param-type": "കണ്ടതായി അടയാളപ്പെടുത്തേണ്ട അറിയിപ്പുകളുടെ തരം: 'അറിയിപ്പ്', 'സന്ദേശം', 'എല്ലാം'.",
- "apihelp-query+notifications-description": "ഇപ്പോഴത്തെ ഉപയോക്താവിനായി കാത്തുനിൽക്കുന്ന അറിയിപ്പുകൾ ലഭ്യമാക്കുക.",
- "apihelp-query+notifications-param-prop": "അഭ്യർത്ഥനയുടെ വിശദാംശങ്ങൾ.",
- "apihelp-query+notifications-param-sections": "ചോദിക്കേണ്ട അറിയിപ്പ് ഭാഗങ്ങൾ (അതായത് 'അറിയിപ്പ്', 'സന്ദേശം' എന്നിവയുടെ മിശ്രണം).",
- "apihelp-query+notifications-param-groupbysection": "ഫലങ്ങൾ വിഭാഗമനുസരിച്ച് വർഗ്ഗീകരിക്കണോ. സജ്ജമെങ്കിൽ ഓരോ ഭാഗവും വ്യത്യസ്തമായിട്ടാവും എടുക്കുക.",
- "apihelp-query+notifications-param-format": "വ്യക്തമാക്കിയിട്ടുണ്ടെങ്കിൽ, അറിയിപ്പുകൾ ഇതുവഴിയായിരിക്കും വിന്യസികുക.",
- "apihelp-query+notifications-param-limit": "എടുക്കേണ്ട അറിയിപ്പുകളുടെ പരമാവധി എണ്ണം.",
- "apihelp-query+notifications-param-index": "വ്യക്തമാക്കിയിട്ടുണ്ടെങ്കിൽ, അറിയിപ്പ് ഐ.ഡി.കളുടെ ഒരു പട്ടിക, ക്രമാനുസരണം, നൽകപ്പെടും.",
- "apihelp-query+notifications-param-alertcontinue": "അധികം അറിയിപ്പ് ഫലങ്ങൾ ലഭ്യമായിരിക്കുമ്പോൾ, തുടരാൻ ഇതുപയോഗിക്കുക.",
- "apihelp-query+notifications-param-alertunreadfirst": "വായിക്കാത്ത സന്ദേശ അറിയിപ്പുകൾ ആദ്യം പ്രദർശിപ്പിക്കണോ.",
- "apihelp-query+notifications-param-messagecontinue": "അധികം സന്ദേശ ഫലങ്ങൾ ലഭ്യമായിരിക്കുമ്പോൾ, തുടരാൻ ഇതുപയോഗിക്കുക.",
- "apihelp-query+notifications-param-messageunreadfirst": "വായിക്കാത്ത വിവരദായക അറിയിപ്പുകൾ ആദ്യം പ്രദർശിപ്പിക്കണോ.",
- "apihelp-query+notifications-example-1": "അറിയിപ്പുകൾ പട്ടികയാക്കുക",
- "apihelp-query+notifications-example-2": "അറിയിപ്പുകൾ വിഭാഗമനുസരിച്ച് എണ്ണം നൽകി വർഗ്ഗീകരിച്ച് പട്ടികയാക്കുക"
+ "echo-email-batch-link-text-view-all-notifications": "എല്ലാ അറിയിപ്പുകളും കാണുക"
}
diff --git a/Echo/i18n/mn.json b/Echo/i18n/mn.json
index d1eef177..e966d34d 100644
--- a/Echo/i18n/mn.json
+++ b/Echo/i18n/mn.json
@@ -1,9 +1,11 @@
{
"@metadata": {
"authors": [
- "Wisdom"
+ "Wisdom",
+ "Munkhzaya.E"
]
},
+ "echo-notification-markasread": "Уншсанаар тэмдэглэх",
"echo-notification-alert": "{{PLURAL:$1|Сануулга ($1)|Сануулга ($1)|100=Сануулга (99+)}}",
"echo-notification-message": "{{PLURAL:$1|Мэдээ ($1)|Мэдээ ($1)|100=Мэдээ (99+)}}"
}
diff --git a/Echo/i18n/mr.json b/Echo/i18n/mr.json
index e37d482c..bc101873 100644
--- a/Echo/i18n/mr.json
+++ b/Echo/i18n/mr.json
@@ -7,14 +7,16 @@
"Prabodh1987",
"Sankoswal",
"V.narsikar",
- "संतोष दहिवळ"
+ "संतोष दहिवळ",
+ "Macofe"
]
},
- "echo-desc": "अधिसूचना प्रणाली",
+ "echo-desc": "सदस्यांना घडामोडी व संदेश देणारी अधिसूचना प्रणाली",
"prefs-echo": "अधिसूचना",
"prefs-emailsettings": "विपत्र ऐच्छिके",
"prefs-displaynotifications": "प्रदर्शित करण्याचे पर्याय",
- "prefs-echosubscriptions": "ह्या उपक्रमाबद्दल कळवावे",
+ "prefs-echosubscriptions": "या उपक्रमाबद्दल कळवावे",
+ "prefs-echocrosswiki": "आंतर-विकि अधिसूचना",
"prefs-newmessageindicator": "नवीन संदेश निर्देशक",
"echo-pref-send-me": "मला पाठवा:",
"echo-pref-send-to": "ला पाठवा:",
@@ -27,85 +29,165 @@
"echo-pref-email-frequency-weekly": "अधिसूचनांचा साप्ताहिक सारांश",
"echo-pref-email-format-html": "एचटीएमएल",
"echo-pref-email-format-plain-text": "साधा मजकूर",
+ "echo-pref-cross-wiki-notifications": "ईतर विकिंवरील अधिसूचना दाखवा",
"echo-pref-new-message-indicator": "चर्चापान संदेश दर्शक माझ्या साधनपेटीत दाखवा",
+ "echo-pref-beta-feature-cross-wiki-message": "वर्धित अधिसूचना",
+ "echo-pref-beta-feature-cross-wiki-description": "सोप्या रितीने अधिसूचना बघा व त्यांना व्यवस्थित लावा.यात आंतरविकि अधिसूचना अंतर्भूत आहेत ज्या, आपणास, इतर विकिंतील अधिसूचना बघणे शक्य करतात.( आंतर विकि अधिसूचना दिलेल्या विकिवर प्राप्त करण्यास, आपण त्या विकिवर बीटा फिचर सक्शम करावयास हवा.)",
"echo-learn-more": "अधिक जाणून घ्या",
+ "echo-log": "सार्वजनिक नोंदी",
"echo-new-messages": "तुमच्यासाठी नवीन संदेश आहेत",
"echo-category-title-edit-user-talk": "चर्चा पान {{PLURAL:$1|संदेश}}",
"echo-category-title-article-linked": "पान {{PLURAL:$1|दुवा|दुवे}}",
"echo-category-title-reverted": "संपादन {{PLURAL:$1|उलटवा}}",
"echo-category-title-mention": "{{PLURAL:$1|उल्लेख}}",
+ "echo-category-title-mention-failure": "अयशस्वी {{PLURAL:$1|उल्लेख}}",
+ "echo-category-title-mention-success": "यशस्वी {{PLURAL:$1|उल्लेख}}",
"echo-category-title-other": "{{PLURAL:$1|इतर}}",
"echo-category-title-system": "{{PLURAL:$1|प्रणाली}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|सदस्य अधिकार बदल}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|दुसऱ्या सदस्यातर्फे विपत्र|दुसऱ्या सदस्यांतर्फे विपत्र}}",
"echo-pref-tooltip-edit-user-talk": "माझ्या चर्चापानावर कोणी संदेश किंवा उत्तर टाकल्यास मला कळवा.",
"echo-pref-tooltip-article-linked": "मी तयार केलेल्या लेख पानाचा दुवा कोणी दुसरऱ्या लेख पानात दिल्यास मला कळवा.",
"echo-pref-tooltip-reverted": "मी केलेले संपादन जर कोणी 'रद्द करा' किंवा रोलबॅक साधन वापरून उलटवित असेल तर मला कळवा.",
- "echo-pref-tooltip-mention": "माझ्या सदस्यपानाचा दुवा जर कोणी इतर कुठल्याही चर्चापानात दिल्यास मला कळवा.",
- "echo-no-agent": "[कोणीच नाही]",
- "echo-no-title": "[कोणतेच पान नाही]",
+ "echo-pref-tooltip-mention": "माझ्या सदस्यपानास जर कोणी दुवा दिला तर मला सुचित करा.",
+ "echo-pref-tooltip-mention-failure": "जेंव्हा माझी संपादने वापरकर्त्यास नमूद करण्यात अयशस्वी होतील तेंव्हा मला कळवा.",
+ "echo-pref-tooltip-mention-success": "जेंव्हा माझी संपादने यशस्वीरित्या सदस्यांचा उल्लेख करतील तेंव्हा मला सूचना द्या.",
+ "echo-pref-tooltip-user-rights": "माझे सदस्याधिकार कोणी बदलविल्यास मला सुचित करा.",
+ "echo-pref-tooltip-emailuser": "जर कोणी मला विपत्र पाठविले तर मला सुचित करा.",
"echo-error-no-formatter": "अधिसूचनेसाठी कोणतेच प्रारुपण निश्चित नाही.",
"notifications": "अधिसूचना",
- "tooltip-pt-notifications-alert": "{{GENDER:|आपले}} जागरुकतेचे संदेश",
- "tooltip-pt-notifications-message": "{{GENDER:|आपले}} संदेश",
+ "tooltip-pt-notifications-alert": "{{GENDER:|आपले}} सजगतेचे संदेश",
+ "tooltip-pt-notifications-notice": "{{GENDER:|आपल्या}} सूचना",
+ "echo-displaynotificationsconfiguration": "अधिसूचनांचे विन्यास दर्शवा",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "वर्गानूसार अधिसूचना",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "प्रकारानुसार निवड",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "प्रत्येक अधिसूचना कोणत्या विभागात निवडल्या जाते",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "परवानगी दिलेल्या अधिसूचना पद्धती",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "प्रत्येक वर्गासाठी कोणती अधिसूचना पद्धती साहाय्यीकृत आहे",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "अविचलरित्या सक्षम",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "सध्याचे सदस्य",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "नविन सदस्य",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "आवश्यक अधिसूचना पद्धत",
"echo-specialpage": "अधिसूचना",
+ "echo-specialpage-section-markread": "गटावर वाचले अशी खूण करा",
+ "echo-specialpage-markasread": "अधिसूचना:वाचल्या म्हणून खूण करा",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|अधिसूचना}}",
+ "echo-specialpage-pagefilters-title": "अलीकडील क्रियाकलाप",
+ "echo-specialpage-pagefilters-subtitle": "न वाचलेल्या अधिसूचनांची पाने",
+ "notificationsmarkread-legend": "अधिसूचना वाचल्यात अशी खूण करा",
"echo-anon": "अधिसूचना मिळण्यास, [$1 create an account] किंवा [$2 log in].",
"echo-none": "आपल्यासाठी काहीच अधिसूचना नाहीत.",
"echo-more-info": "अधिक माहिती",
"echo-feedback": "प्रतिक्रिया",
+ "echo-popup-footer-special-page-invitation": "<strong>पुनर्रचित अधिसूचनेच्या पानावर प्रयत्न करा.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "पूर्णपणे नविन दिखावा व फिचर्स",
+ "echo-quotation-marks": "\"$1\"",
+ "echo-api-failure": "अधिसूचना पुरविण्यात अयशस्वी.",
+ "echo-api-failure-cross-wiki": "दूरवरच्या विदागारास पोहोच नाकारण्यात आली आहे.",
+ "echo-notification-placeholder": "अधिसूचना नाहीत.",
+ "echo-notification-placeholder-filters": "या निकषांंशी जुळणाऱ्या कोणत्याच अधिसूचना नाहीत.",
+ "echo-notification-loginrequired": "आपणास आपली अधिसूचना बघण्यास सनोंद प्रवेशित असावे लागेल.",
+ "echo-notification-popup-loginrequired": "आपल्या अधिसूचना बघण्यास सनोंद प्रवेश करा.",
+ "echo-notification-markasread": "वाचले अशी खूण करा",
+ "echo-notification-markasunread": "न वाचलेले अशी खूण करा",
+ "echo-notification-markasread-tooltip": "वाचले अशी खूण करा",
+ "echo-notification-more-options-tooltip": "अधिक पर्याय",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|आपला}} \"$1\" या पानावर पहारा नाही.",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|आपण}} [$2 या पानावर] पहारा देणे कधीही थांबवू शकता.",
+ "notification-link-text-expand-all": "विस्तार करा",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 इशारा|$1 इशारे}} बघा",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|$1 सूचना}} बघा",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 अधिसूचना}} बघा",
+ "notification-link-text-collapse-all": "निपात करा",
"notification-link-text-view-message": "संदेश बघा",
"notification-link-text-view-mention": "उल्लेख बघा",
- "notification-link-text-view-changes": "बदल बघा",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|उल्लेख बघा}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|बदल}} बघा",
"notification-link-text-view-page": "पान बघा",
+ "notification-header-edit-user-talk": "$1 ने <strong>{{GENDER:$3|आपल्या}} चर्चा पानावर </strong> एक संदेश {{GENDER:$2|टाकला}}.",
+ "notification-header-edit-user-talk-with-section": "$1 ने <strong>{{GENDER:$3|आपल्या}} चर्चा पानावर </strong>\"<strong>$4</strong>\" मध्ये एक संदेश {{GENDER:$2|टाकला}}.",
+ "notification-header-page-linked": "<strong>$4</strong> हून <strong>$3</strong> ला दुवा तयार केल्या गेला.",
+ "notification-compact-header-page-linked": "<strong>$1</strong> शी दुवा जोडला आहे.",
+ "notification-bundle-header-page-linked": "{{PLURAL:$5||$5 पाने|100=99+ पाने}} आता <strong>$3</strong> शी जुळवल्या गेली आहेत.",
+ "notification-link-text-what-links-here": "या पानास असणारे सर्व दुवे",
+ "notification-header-mention-other": "$1 ने <strong>$4</strong> वर \"<strong>$5</strong>\" मध्ये {{GENDER:$3|आपला}} {{GENDER:$2|उल्लेख केला}}.",
+ "notification-header-mention-other-nosection": "$1 ने <strong>$4</strong> वर {{GENDER:$3|आपला}} {{GENDER:$2|उल्लेख केला}}.",
+ "notification-header-mention-user-talkpage-v2": "$1 ने \"<strong>$6</strong>\" मध्ये <strong>$4{{GENDER:$5|च्या}} सदस्य चर्चा पानावर </strong> {{GENDER:$3|आपला}} {{GENDER:$2|उल्लेख केला}}.",
+ "notification-header-mention-user-talkpage-nosection": "$1 ने <strong>$4 {{GENDER:$5|च्या}}सदस्य चर्चा पानावर</strong>{{GENDER:$3|आपला}} {{GENDER:$2|उल्लेख केला}}.",
+ "notification-header-mention-agent-talkpage": "$1 ने \"<strong>$4</strong>\" मध्ये {{GENDER:$2|त्याच्या|तिच्या|त्यांच्या}}<strong> चर्चा पानावर </strong> {{GENDER:$3|आपला}} {{GENDER:$2|उल्लेख केला}}.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 ने <strong>{{GENDER:$2|त्याच्या|तिच्या|त्यांच्या}} चर्चा पानावर </strong>{{GENDER:$3|आपला}}{{GENDER:$2|उल्लेख केला}}.",
+ "notification-header-mention-article-talkpage": "$1 ने <strong>$5</strong> मध्ये \" <strong>$4</strong> चर्चा पानावर\"{{GENDER:$3|आपला}} {{GENDER:$2|उल्लेख केला}}.",
+ "notification-header-mention-article-talkpage-nosection": "$1 ने <strong>$4</strong> चर्चा पानावर {{GENDER:$3|आपला}}{{GENDER:$2|उल्लेख केला}}.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|आपण}} उल्लेख केलेले<strong>$3</strong> पाठविल्या गेले नाही कारण तो सदस्य सापडला नाही.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|आपण}} उल्लेख केलेले<strong>$3</strong> पाठविल्या गेले नाही कारण तो सदस्य अनामिक आहे.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|आपले}} उल्लेखित पाठविल्या गेले नाहीत कारण त्यांनी $3 ची मर्यादा उल्लंघिली.",
+ "notification-header-mention-failure-bundle": "{{GENDER:$2|आपण केलेला/ले}} {{PLURAL:$3|एक उल्लेख|$3 उल्लेख}} <strong>$4</strong> चर्चा पानावर {{PLURAL:$3|पाठविल्या}} गेले नाहीत.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>सदस्यनाव अस्तित्वात नाही:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>अंकपत्ते उल्लेखित केल्या जाऊ शकत नाहीत:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|आपला}}<strong>$3</strong> चा उल्लेख पाठविल्या गेला.",
+ "notification-header-mention-success-bundle": "<strong>$4</strong> चर्चा पानावर {{GENDER:$2|आपण केलेला/ले}}{{PLURAL:$3|एक उल्लेख|$3 उल्लेख}} पाठविल्या {{PLURAL:$3|गेलेत}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|आपण उल्लेख केला}}:</strong> $3",
+ "notification-header-mention-status-bundle": "<strong>$4</strong> चर्चापानावर {{GENDER:$2|आपण केलेल्या}} नमूदीबाबतच्या {{PLURAL:$3|अधिसूचना|$3 अधिसूचना}}: {{PLURAL:$5|$5 पाठविल्या गेल्या नाहीत}}, {{PLURAL:$6|$6 पाठविल्या गेल्यात}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|आपले}} सदस्य अधिकार {{GENDER:$1|बदलल्या गेलेत}}. आपण जोडल्या गेले आहात: $2 शी.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|आपले}} सदस्य अधिकार {{GENDER:$1|बदलल्या गेलेत}}. आपण आता सदस्य नाहीत: $2 चा.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|आपले}} सदस्य अधिकार {{GENDER:$1|बदललेत}}. आपण जोडल्या गेले आहात: $2. आपण सध्या सदस्य नाहीत: $4 चे.",
+ "notification-header-welcome": "{{SITENAME}} वर {{GENDER:$2|आपले स्वागत}}, $1! {{GENDER:$2|आपण}} येथे आल्यामुळे आम्हास आनंद झाला.",
+ "notification-welcome-linktext": "स्वागत",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|आपण}} {{GENDER:$2|आपले}} पहिले संपादन नुकतेच केले आहे;{{GENDER:$2|आपणास}} धन्यवाद व आपले स्वागत आहे!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|आपण}} {{GENDER:$2|आपले}} दहावे संपादन नुकतेच केले आहे;{{GENDER:$2|आपणास}} धन्यवाद व कृपया संपादने सुरु ठेवा!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|आपण}} {{GENDER:$2|आपले}} शंभरावे संपादन नुकतेच केले आहे;{{GENDER:$2|आपणास}} खूप धन्यवाद!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|आपण}} {{GENDER:$2|आपले}} हजारावे संपादन नुकतेच केले आहे;एक महान योगदानकर्ता असण्याबद्दल {{GENDER:$2|आपणास}} धन्यवाद!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|आपण}} {{GENDER:$2|आपले}} दहा हजारावे संपादन नुकतेच केले आहे;{{GENDER:$2|आपणास}} खूप खूप धन्यवाद!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|आपण}} {{GENDER:$2|आपले}} शंभर हजारावे संपादन नुकतेच केले आहे;{{GENDER:$2|आपणास}} योगदानाच्या आपल्या अचाट कामाबद्दल धन्यवाद!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|आपण}} {{GENDER:$2|आपले}} लाखावे संपादन नुकतेच केले आहे;{{GENDER:$2|आपणास}} योगदानाच्या आपल्या आश्चर्यकारक कामाबद्दल धन्यवाद!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|आपले}} संपादन",
"notification-link-text-view-edit": "संपादन बघा",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|ने}} आपल्या [[User talk:$2#$3|चर्चा पानावर]] संदेश टाकला.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|ने}} एक संदेश आपल्या चर्चा पानावर \"[[User talk:$2#$3|$4]]\" या मथळ्याखाली टाकला.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|ने}} आपल्या [[User talk:$2#$3|चर्चा पानावर]] एक संदेश टाकला.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|ने}} ''[[User talk:$2#$3|$4]]'' या मथळ्याखाली आपल्या चर्चा पानावर एक संदेश टाकला.",
- "notification-page-linked": "[[:$2]] ला [[:$3]] वरून {{GENDER:$1|दुवा दिल्या गेला}}. [[Special:WhatLinksHere/$2|या पानाचे सर्व दुवे बघा]].",
- "notification-page-linked-flyout": "[[:$2]] ला [[:$3]] वरुन {{GENDER:$1|दुवा दिल्या गेला}}.",
- "notification-add-comment2": "[[User:$1|$1]] ने \"[[$3|$2]]\" वर, \"$4\" चर्चा पानावर{{GENDER:$1|शेरा टाकला}}.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] ने [[$3]]वर नविन विषय \"$2\" {{GENDER:$1|टाकला}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]]ने आपणास एक संदेश {{GENDER:$1|पाठविला}}:\"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]]ने \"[[$3#$2|$2]]\" बाबत आपल्या चर्चापानावर {{GENDER:$1|शेरा टाकला}}.",
- "notification-mention": "[[User:$1|$1]]ने \"[[:$3#$2|$4]]\" मध्ये $5 चर्चापानावर आपला {{GENDER:$1|उल्लेख केला}}.",
- "notification-mention-flyout": "$1 ने \"[[:$3#$2|$4]]\" मध्ये $5 चर्चापानावर आपला {{GENDER:$1|उल्लेख केला}}",
- "notification-user-rights": "आपले सदस्य अधिकार [[User:$1|$1]]द्वारा [[Special:Log/rights/$1| {{GENDER:$1|बदलविण्यात आले}}]]. $2. [[Special:ListGroupRights|अधिक माहिती घ्या]]",
- "notification-user-rights-flyout": "आपले सदस्य अधिकार $1 द्वारा {{GENDER:$1|बदलविण्यात आले}}.$2. [[Special:ListGroupRights|अधिक माहिती घ्या]]",
- "notification-user-rights-add": "आपण आता {{PLURAL:$2|या गटाचे|या गटांचे}} सदस्य आहात:$1",
- "notification-user-rights-remove": "आपण यापुढे {{PLURAL:$2|या गटाचे|या गटांचे}} सदस्य नाहीत:\n$1",
- "notification-new-user": "$1! या {{SITENAME}}वर आपले स्वागत. आपण येथे आल्यामुळे आम्हास आनंद झाला.",
- "notification-reverted2": "आपले/ली{{PLURAL:$4|संपादन [[:$2]]वर|संपादने [[:$2]]वर}} [[User:$1|$1]]ने {{GENDER:$1|उलटवली}}. $3",
- "notification-reverted-flyout2": "आपले/ली {{PLURAL:$4|$2वरील संपादन|$2वरील संपादने}} $1ने {{GENDER:$1|उलटविलीत}}. $3",
+ "notification-header-reverted": "आपले/ली {{PLURAL:$4|<strong>$3</strong> वरील संपादन|<strong>$3</strong> वरील संपादने}}{{GENDER:$2|उलटवल्या गेलीत}}.",
+ "notification-header-emailuser": "$1 ने आपणास एक विपत्र {{GENDER:$2|पाठविले}}.",
"notification-edit-talk-page-email-subject2": "$1 ने {{SITENAME}}वर आपल्यासाठी एक संदेश {{GENDER:$1|टाकला}}",
- "notification-edit-talk-page-email-batch-body2": "$1 ने आपल्या चर्चा पानावर एक संदेश {{GENDER:$1|टाकला}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 ने \"$2\" मधील आपल्या चर्चा पानावर एक संदेश {{GENDER:$1|टाकला}}.",
- "notification-page-linked-email-subject": "{{SITENAME}}वर आपले पान जोडल्या गेले आहे",
- "notification-page-linked-email-batch-body": "$2 ला $3शी {{GENDER:$1|दुव्याने जोडण्यात आले आहे}}.",
- "notification-reverted-email-subject2": "{{PLURAL:$3|आपले {{SITENAME}} वरील संपादन {{GENDER:$1|उलटविले गेले}}|आपली {{SITENAME}} वरील संपादने {{GENDER:$1|उलटवविली गेली}}}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|आपले $2 वरील संपादन|आपली $2 वरील संपादने}} $1 ने {{GENDER:$1|उलटविली}}.",
- "notification-mention-email-subject": "$1 ने आपला {{SITENAME}} वर {{GENDER:$1|उल्लेख केला}}",
- "notification-mention-email-batch-body": "$1 ने आपला \"$3\" मध्ये $4 चर्चापानावर {{GENDER:$1|उल्लेख केला}}.",
+ "notification-page-linked-email-subject": " आपण तयार केलेले पान {{SITENAME}}वर जोडल्या गेले आहे",
+ "notification-reverted-email-subject2": "आपले {{SITENAME}} वरील {{PLURAL:$3|संपादन|संपादने}}{{GENDER:$1|उलटविले गेले|उलटविल्या गेलीत}}",
+ "notification-mention-email-subject": "$1 ने {{GENDER:$2|आपला}} {{SITENAME}} वर {{GENDER:$1|उल्लेख केला}}",
"notification-user-rights-email-subject": "{{SITENAME}} वर आपले सदस्य अधिकार बदलले आहेत",
- "notification-user-rights-email-batch-body": "$1द्वारा आपले सदस्य अधिकार {{GENDER:$1|बदलविल्या गेलेत}}. $2.",
- "echo-email-subject-default": "{{SITENAME}} वर एक नविन अधिसूचना",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1से}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1मि}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1ता}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1दि}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1म}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1व}}",
+ "notification-timestamp-today": "आज",
+ "notification-timestamp-yesterday": "काल",
+ "notification-inbox-filter-read": "वाचलेले",
+ "notification-inbox-filter-unread": "न वाचलेले",
+ "notification-inbox-filter-all": "सर्व",
"echo-email-body-default": "{{SITENAME}}वर आपणासाठी एक नविन अधिसूचना आहे:\n\n$1",
- "echo-email-batch-body-default": "आपणासाठी एक नविन अधिसूचना आहे.",
+ "echo-email-footer-default-html": "आम्ही आपणास कोणते विपत्र पाठवितो, त्यावर नियंत्रण करण्यास<a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">आपला पसंतीक्रम तपासा</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nआम्ही आपणास पाठविण्याच्या विपत्रांवर नियंत्रणासाठी, आपला पसंतीक्रम तपासा:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "आम्ही आपणास पाठविलेल्या विपत्रांवर नियंत्रणासाठी, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">आपला पसंतीक्रम तपासा</a>.<br />\n$1",
+ "echo-email-plain-footer": "आम्ही आपणास पाठविण्याच्या विपत्रांवर नियंत्रणासाठी, आपला पसंतीक्रम तपासा:",
+ "echo-email-html-footer-preference-link-text": "आपला पसंतीक्रम तपासा",
+ "echo-email-html-footer-with-link": "आम्ही आपणास पाठविण्याच्या विपत्रांवर नियंत्रणासाठी, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|सजगता ($1)|100=(99+)सजगता}}",
+ "echo-notification-notice": "{{PLURAL:$1|सूचना($1)|100=सूचना(99+)}}",
+ "echo-notification-alert-text-only": "सजगता",
+ "echo-notification-notice-text-only": "सूचना",
"echo-overlay-link": "सर्व अधिसूचना",
"echo-overlay-title": "<b>अधिसूचना</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|अधिसूचना}}</b> ($2 पैकी $1 न वाचलेल्या)",
"echo-mark-all-as-read": "वाचले म्हणून खूण करा",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|अधिसूचना}} वाचल्या म्हणून खूण केली",
+ "echo-mark-wiki-as-read": "निवडलेल्या विकित सर्व वाचले अशी खूण करा: $1",
"echo-date-today": "आज",
"echo-date-yesterday": "काल",
- "echo-load-more-error": "अधिक निकाल देण्यापोटी एक त्रूटी घडली.",
- "notification-edit-talk-page-bundle": "$1 व $3 {{PLURAL:$4|इतरानी|इतरांनी}} आपल्या [[User talk:$2|चर्चा पानावर]] एक संदेश {{GENDER:$1|टाकला}}.",
- "notification-page-linked-bundle": "$2 हे पान $3 व $4 यापासून, इतर {{PLURAL:$5|पानाशी|पानांशी}}{{GENDER:$1|जोडल्या गेले}}. [[Special:WhatLinksHere/$2|या पानाशी जोडलेले सर्व दुवे बघा]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 व $2 {{PLURAL:$3|इतरानी|इतरांनी}} आपल्या चर्चा पानावर एक संदेश {{GENDER:$1|टाकला}}.",
- "notification-page-linked-email-batch-bundle-body": "$2ला $3शी व $4 इतर {{PLURAL:$5|पानाशी|पानांशी}} {{GENDER:$1|दुव्याने जोडल्या गेले}}.",
+ "echo-load-more-error": "अधिक निकाल देण्यापोटी एक त्रुटी घडली.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|एक नविन संदेश|$1 नविन संदेश|100=99+ नविन संदेश}} <strong>{{GENDER:$3|आपल्या}} चर्चा पानावर आहेत</strong>.",
+ "echo-email-batch-bullet": "•",
"echo-email-batch-subject-daily": "आपल्यासाठी {{SITENAME}}वर {{PLURAL:$2|एक नविन अधिसूचना आहे|नविन अधिसूचना आहेत}}",
"echo-email-batch-subject-weekly": "आपल्यासाठी या आठवड्यात {{SITENAME}}वर {{PLURAL:$2|एक नविन अधिसूचना आहे|नविन अधिसूचना आहेत}}",
"echo-email-batch-body-intro-daily": "नमस्कार $1,\nआपण {{SITENAME}}वर केलेल्या आजच्या क्रियाकलापांचा सारांश येथे आहे.",
"echo-email-batch-body-intro-weekly": "नमस्कार $1,\nआपण {{SITENAME}}वर केलेल्या या आठवड्याच्या क्रियाकलापांचा सारांश येथे आहे.",
"echo-email-batch-link-text-view-all-notifications": "सर्व अधिसूचना पहा",
- "echo-rev-deleted-text-view": "या पानाची आवृत्ती दाबण्यात आलेली आहे."
+ "notification-header-foreign-alert": "{{PLURAL:$5|दुसऱ्या विकितील|$5 इतर विकिंतील}} अधिक इशारे",
+ "notification-header-foreign-notice": "{{PLURAL:$5|दुसऱ्या विकितील|$5 इतर विकिंतील}} अधिक सूचना",
+ "notification-header-foreign-all": "{{PLURAL:$5|दुसऱ्या विकितील|$5 इतर विकिंतील}} अधिक अधिसूचना"
}
diff --git a/Echo/i18n/ms.json b/Echo/i18n/ms.json
index 9cf4b379..ff45ddd7 100644
--- a/Echo/i18n/ms.json
+++ b/Echo/i18n/ms.json
@@ -3,7 +3,9 @@
"authors": [
"Anakmalaysia",
"Pizza1016",
- "Aviator"
+ "Aviator",
+ "Kurniasan",
+ "Jeluang Terluang"
]
},
"echo-desc": "Sistem pemberitahuan",
@@ -23,7 +25,6 @@
"echo-pref-email-frequency-weekly": "Ringkasan pemberitahuan mingguan",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Teks biasa",
- "echo-pref-notify-show-link": "Paparkan pemberitahuan di palang alat saya",
"echo-pref-new-message-indicator": "Paparkan indikator pesanan dari halaman perbincangan pada palang alat saya",
"echo-learn-more": "Ketahui lebih lanjut",
"echo-new-messages": "Anda mempunyai pesanan baru",
@@ -39,13 +40,9 @@
"echo-pref-tooltip-reverted": "Beritahu saya apabila seseorang mengundurkan suntingan saya dengan menggunakan alat 'batalkan' atau 'undur'.",
"echo-pref-tooltip-mention": "Beritahu saya apaila seseorang membuat pautan ke laman pengguna saya.",
"echo-pref-tooltip-user-rights": "Beritahu saya apabila seseorang mengubah hak-hak pengguna saya.",
- "echo-no-agent": "[Tiada Sesiapa]",
- "echo-no-title": "[Tiada laman]",
"echo-error-no-formatter": "Tiada pemformatan ditetap untuk pemberitahuan.",
- "echo-error-preference": "Ralat: Keutamaan pengguna tidak boleh ditetapkan.",
- "echo-error-token": "Ralat: Token pengguna tidak dapat didapati.",
"notifications": "Pemberitahuan",
- "tooltip-pt-notifications": "Pemberitahuan anda",
+ "tooltip-pt-notifications-alert": "Notis {{GENDER:|anda}}",
"echo-specialpage": "Pemberitahuan",
"echo-anon": "Untuk menerima pemberitahuan, sila [$1 buka akaun] atau [$2 log masuk].",
"echo-none": "Tiada pemberitahuan untuk anda.",
@@ -56,48 +53,17 @@
"notification-link-text-view-changes": "Lihat perubahan",
"notification-link-text-view-page": "Lihat laman",
"notification-link-text-view-edit": "Lihat suntingan",
- "notification-edit-talk-page2": "[[User:$1|$1]] telah {{GENDER:$1|meninggalkan}} sebuah pesanan pada [[User talk:$2#$3|laman perbincangan]] anda.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] telah {{GENDER:$1|meninggalkan}} sebuah pesanan pada laman perbincangan anda di \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 telah {{GENDER:$1|meninggalkan}} sebuah pesanan pada [[User talk:$2#$3|laman perbincangan]] anda.",
- "notification-edit-talk-page-flyout-with-section": "$1 telah {{GENDER:$1|meninggalkan}} sebuah pesanan pada laman perbincangan anda di \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] telah {{GENDER:$1|dipautkan}} dari [[:$3]]. [[Special:WhatLinksHere/$2|Lihat semua pautan ke halaman ini]].",
- "notification-page-linked-flyout": "[[:$2]] telah {{GENDER:$1|dipautkan}} dari [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] telah {{GENDER:$1|mengulas}} tentang \"[[$3|$2]]\" pada laman perbincangan \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] telah mengepos topik baru, \"$2\", di [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] telah {{GENDER:$1|mengirim}} pesanan kepada anda: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] telah {{GENDER:$1|mengulas}} tentang \"[[$3#$2|$2]]\" pada laman perbincangan anda.",
- "notification-mention": "[[User:$1|$1]] telah {{GENDER:$1|menyebut}} anda pada laman perbincangan $5 di \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 telah {{GENDER:$1|menyebut}} anda di laman perbincangan $5 di [[:$3#$2|$4]].",
- "notification-mention-nosection": "[[User:$1|$1]] telah {{GENDER:$1|menyebut}} anda di [[:$3|laman perbincangan $2]].",
- "notification-mention-nosection-flyout": "$1 telah {{GENDER:$1|menyebut}} anda di [[:$3|laman perbincangan $2]].",
- "notification-user-rights": "Hak-hak pengguna anda telah [[Special:Log/rights/$1|{{GENDER:$1|diubah}}]] oleh [[User:$1|$1]]. $2. [[Special:ListGroupRights|Ketahui lebih lanjut]]",
- "notification-user-rights-flyout": "Hak-hak pengguna anda telah {{GENDER:$1|diubah}} oleh \t$1. $2. [[Special:ListGroupRights|Ketahui lebih lanjut]]",
- "notification-user-rights-add": "Anda kini menganggotai {{PLURAL:$2|kumpulan|kumpulan-kumpulan ini:}} $1",
- "notification-user-rights-remove": "Anda tidak lagi menganggotai {{PLURAL:$2|kumpulan|kumpulan-kumpulan ini:}} $1",
- "notification-new-user": "Selamat datang ke {{SITENAME}}, $1! Dengan sukacita kami menyambut kedatangan anda.",
- "notification-reverted2": "{{PLURAL:$4|Suntingan|Suntingan-suntingan}} anda di [[:$2]] telah {{GENDER:$1|dibalikkan}} oleh [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Suntingan|Suntingan-suntingan}} anda di $2 telah {{GENDER:$1|dibalikkan}} oleh $1 $3",
+ "notification-header-reverted": "{{PLURAL:$4|Suntingan|Suntingan-suntingan}} anda di $3 telah {{GENDER:$2|dibalikkan}} oleh $1",
"notification-edit-talk-page-email-subject2": "$1 telah {{GENDER:$1|meninggalkan}} pesanan untuk anda di {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 telah {{GENDER:$1|meninggalkan}} pesanan untuk anda di laman perbincangan anda:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 telah {{GENDER:$1|meninggalkan}} sebuah pesanan pada laman perbincangan anda di \"$2\".",
"notification-page-linked-email-subject": "Laman ciptaan anda telah dipautkan dengan {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 telah {{GENDER:$1|dipautkan}} dari $3",
"notification-reverted-email-subject2": "{{PLURAL:$3|Suntingan|Suntingan-suntingan}} telah {{GENDER:$1|diundurkan}} di {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Suntingan|Suntingan-suntingan}} anda di $2 telah {{GENDER:$1|diundurkan}} oleh $1",
"notification-mention-email-subject": "$1 {{GENDER:$1|menyebut}} anda di {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 telah {{GENDER:$1|menyebut}} anda di laman perbincangan $4 di \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 telah {{GENDER:$1|menyebut}} anda di laman perbincangan $2.",
"notification-user-rights-email-subject": "Hak-hak pengguna anda telah berubah di {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Hak-hak pengguna anda telah {{GENDER:$1|diubah}} oleh $1. $2",
- "echo-email-subject-default": "Pemberitahuan baru di {{SITENAME}}",
"echo-email-body-default": "Anda menerima pemberitahuan baru di {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Anda mempunyai pemberitahuan baru",
"echo-email-footer-default": "$2\n\nUntuk mengubah pesanan-pesanan e-mel yang anda hendak kami hantar, semak keutamaan anda:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Untuk mengawal e-mel yang kami hantar kepada anda, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">semak keutamaan anda</a><br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|Pesanan ($1)|100=Pesanan (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Pesanan ($1)|Pesanan ($1)|100=Pesanan (99+)}}",
"echo-notification-alert-text-only": "Peringatan",
- "echo-notification-message-text-only": "Pesanan",
"echo-overlay-link": "Semua pemberitahuan",
"echo-overlay-title": "<b>Pemberitahuan</b>",
"echo-overlay-title-overflow": "<b>Pemberitahuan</b> (memaparkan $1 daripada $2 yang belum dibaca)",
@@ -105,14 +71,9 @@
"echo-date-today": "Hari ini",
"echo-date-yesterday": "Semalam",
"echo-load-more-error": "Ralat berlaku ketika mengambil lebih banyak hasil.",
- "notification-edit-talk-page-bundle": "$1 dan $3 {{PLURAL:$4|orang lain}} telah {{GENDER:$1|meninggalkan}} sebuah pesanan pada [[User talk:$2|laman perbincangan]] anda.",
- "notification-page-linked-bundle": "$2 telah {{GENDER:$1|dipautkan}} dari $3 dan $4 {{PLURAL:$5|laman}} yang lain. [[Special:WhatLinksHere/$2|Lihat semua pautan ke laman ini]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 dan $2 {{PLURAL:$3|orang lain}} telah {{GENDER:$1|meninggalkan}} sebuah pesanan pada laman perbincangan anda.",
- "notification-page-linked-email-batch-bundle-body": "$2 telah {{GENDER:$1|dipautkan}} dari $3 dan $4 {{PLURAL:$5|laman}} lain.",
"echo-email-batch-subject-daily": "Anda ada {{PLURAL:$2|satu|beberapa}} pemberitahuan baru di {{SITENAME}}",
"echo-email-batch-subject-weekly": "Anda ada {{PLURAL:$2|satu|beberapa}} pemberitahuan baru di {{SITENAME}} minggu ini",
- "echo-email-batch-body-intro-daily": "$1,\nYang berikut adalah ringkasan kegiatan hari ini di {{SITENAME}} untuk rujukan anda",
- "echo-email-batch-body-intro-weekly": "$1,\nYang berikut adalah ringkasan kegiatan minggu ini di {{SITENAME}} untuk rujukan anda",
- "echo-email-batch-link-text-view-all-notifications": "Baca semua pemberitahuan",
- "echo-rev-deleted-text-view": "Semakan halaman ini telah digantung"
+ "echo-email-batch-body-intro-daily": "$1,\nYang berikut ialah ringkasan kegiatan hari ini di {{SITENAME}} untuk rujukan anda.",
+ "echo-email-batch-body-intro-weekly": "$1,\nYang berikut ialah ringkasan kegiatan minggu ini di {{SITENAME}} untuk rujukan anda.",
+ "echo-email-batch-link-text-view-all-notifications": "Baca semua pemberitahuan"
}
diff --git a/Echo/i18n/mt.json b/Echo/i18n/mt.json
index d44177f7..9a03b329 100644
--- a/Echo/i18n/mt.json
+++ b/Echo/i18n/mt.json
@@ -24,7 +24,6 @@
"echo-pref-email-frequency-weekly": "Sommarju ta' kull ġimgħa tan-notifiki",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Test normali",
- "echo-pref-notify-show-link": "Uri n-notifiki fl-iżbarra tal-għodda",
"echo-pref-new-message-indicator": "Uri s-sinjal tal-messaġġi l-ġodda fil-paġna tad-diskussjoni tiegħi fl-iżbarra tal-għodda",
"echo-learn-more": "Aktar tagħrif",
"echo-new-messages": "Għandek messaġġi ġodda",
@@ -38,13 +37,9 @@
"echo-pref-tooltip-article-linked": "Għarrafni meta xi ħadd joħloq ħolqa minn artiklu għal xi paġna li ħlaqt jien.",
"echo-pref-tooltip-reverted": "Għarrafni meta xi ħadd permezz tal-għodda tal-annullament (undo) jew tat-treġġigħ lura (rollback) jannulla xi modifika li għamilt jien.",
"echo-pref-tooltip-mention": "Għarrafni meta xi ħadd joħloq ħolqa minn xi paġna tad-diskussjoni għall-paġna tal-utent tiegħi.",
- "echo-no-agent": "[Ħadd]",
- "echo-no-title": "[L-ebda paġna]",
"echo-error-no-formatter": "L-ebda formattazzjoni definita għan-notifiki",
- "echo-error-preference": "Żball: Il-preferenzi tal-utent ma setgħux jiġu ssettjati.",
- "echo-error-token": "Żball: It-token tal-utent ma setax jiġi rkuprat.",
"notifications": "Notifiki",
- "tooltip-pt-notifications": "In-notifiki tiegħek",
+ "tooltip-pt-notifications-alert": "L-avviżi tiegħek",
"echo-specialpage": "Notifiki",
"echo-anon": "Sabiex tirċievi n-notifiki, [$1 oħloq kont] jew [$2 idħol fil-kont].",
"echo-none": "M'għandek l-ebda notifika",
@@ -55,41 +50,15 @@
"notification-link-text-view-changes": "Ara l-bidliet",
"notification-link-text-view-page": "Ara l-paġna",
"notification-link-text-view-edit": "Ara l-modifika",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|ħalla|ħalliet}} messaġġ fuq il-[[User talk:$2#$3|paġna tal-utent]] tiegħek.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|ħalla|ħalliet}} messaġġ fuq il-paġna tad-diskussjoni tiegħek f'\"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|ħalla|ħalliet}} messaġġ fuq il-[[User talk:$2#$3|paġna tad-diskussjoni]] tiegħek.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|ħalla|ħalliet}} messaġġ fil-paġna tad-diskussjoni tiegħek f' \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] {{GENDER:$1|inħalqitilha}} ħolqa minn [[:$3]]. [[Special:WhatLinksHere/$2|Ara l-ħoloq għal din il-paġna kollha]].",
- "notification-page-linked-flyout": "[[:$2]] {{GENDER:$1|inħalqitilha}} ħolqa minn [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|ħalla|ħalliet}} kumment \"[[$3|$2]]\" fuq il-paġna tad-diskussjoni ta' \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|beda|bdiet}} suġġett ġdid \"$2\" fuq [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|bagħatlek|bagħtitlek}} messaġġ: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|ħalla|ħalliet}} kumment dwar \"[[$3#$2|$2]]\" fuq il-paġna tad-diskussjoni tiegħek.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|semmiek|semmietek}} fuq il-paġna tad-diskussjoni ta' $5 f' \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|semmiek|semmietek}} fuq il-paġna tad-diskussjoni ta' $5 f' \"[[:$3#$2|$4]]\".",
- "notification-user-rights": "Id-drittijiet tiegħek ta' utent [[Special:Log/rights/$1|ġew {{GENDER:$1|modifikati}}]] minn [[User:$1|$1]]. $2. [[Special:ListGroupRights|Ara iżjed]]$1$1",
- "notification-user-rights-flyout": "Id-drittijiet tiegħek ta' utent ġew {{GENDER:$1|modifikati}} minn $1. $2. [[Special:ListGroupRights|Ara iżjed]]",
- "notification-user-rights-add": "Issa int membru ta' {{PLURAL:$2|dan il-grupp|dawn il-gruppi}}: $1",
- "notification-user-rights-remove": "Int m'għadikx membru ta' {{PLURAL:$2|dan il-grupp|dawn il-gruppi}}: $1",
- "notification-new-user": "Merħba fuq {{SITENAME}}, $1! Qed nieħdu gost li ġejt hawn.",
- "notification-reverted2": "Il-{{PLURAL:$4|modifika|modifiki}} fuq [[:$2]] {{PLURAL:$4|ġiet annullata|ġew annullati}} {{GENDER:$1|minn}} [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "Il-{{PLURAL:$4|modifika|modifiki}} tiegħek fuq $2 {{PLURAL:$4|ġiet annullata|ġew annullati}} {{GENDER:$1|minn}} $1. $3",
+ "notification-header-reverted": "Il-{{PLURAL:$4|modifika|modifiki}} tiegħek fuq $3 {{PLURAL:$4|ġiet annullata|ġew annullati}} {{GENDER:$2|minn}} $1.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|ħallielek|ħallietlek}} messaġġ fuq {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|ħalla|ħalliet}} messaġġ fuq il-paġna tad-diskussjoni tiegħek:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|ħalla|ħalliet}} messaġġ fil-paġna tad-diskussjoni tiegħek f' \"$2\".",
"notification-page-linked-email-subject": "Inħolqot ħolqa għall-paġna tiegħek fuq {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 {{GENDER:$1|inħalqitilha}} ħolqa minn $3.",
"notification-reverted-email-subject2": "Il-{{PLURAL:$3|modifika tiegħek ġiet annullata|modifiki tiegħek ġew annullati}} {{GENDER:$1|fuq}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "Il-{{PLURAL:$3|modifika|modifiki}} tiegħek fuq $2 {{PLURAL:$3|ġiet annullata|ġew annullati}} {{GENDER:$1|minn}} $1.",
"notification-mention-email-subject": "$1 {{GENDER:$1|semmiek|semmietek}} fuq {{SITENAME}}$1",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|semmiek|semmietek}} fuq il-paġna tad-diskussjoni ta' $4 f' \"$3\".",
"notification-user-rights-email-subject": "Id-drittijiet tiegħek ta' utent fuq {{SITENAME}} inbidlu.",
- "notification-user-rights-email-batch-body": "Id-drittijiet tiegħek ta' utent {{GENDER:$1|biddilhom|biddlithom}} $1. $2.",
- "echo-email-subject-default": "Notifika ġdida fuq {{SITENAME}}",
"echo-email-body-default": "Għandek notifika ġdida fuq {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Għandek notifika ġdida.",
"echo-email-footer-default": "$2\n\nBiex tkun taf liema posta elettronika tasallek, iċċekkja l-preferenzi tiegħek: \n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Biex tikkontrolla liema posta elettronika nibagħtulek, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">iċċekkja l-preferenzi tiegħek</a>.<br /> \n$1",
"echo-overlay-link": "In-notifiki kollha",
"echo-overlay-title": "<b>Notifiki</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notifiki}}</b> (qegħdin jidhru $1 minn $2 li ma nqrawx)",
@@ -97,14 +66,9 @@
"echo-date-today": "Illum",
"echo-date-yesterday": "Ilbieraħ",
"echo-load-more-error": "Sar żball waqt li kienu qegħdin jinkisbu iktar riżultati.",
- "notification-edit-talk-page-bundle": "$1 u $3 {{PLURAL:$4|ieħor/oħra|oħrajn}} {{GENDER:$1|ħallew}} messaġġ fuq il-[[User talk:$2|paġna tad-diskussjoni]] tiegħek.",
- "notification-page-linked-bundle": "$2 {{GENDER:$1|saritilha ħolqa}} minn $3 u $4 {{PLURAL:$5|paġna|paġni}} oħra. [[Special:WhatLinksHere/$2|Ara l-ħoloq kollha għal din il-paġna]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 u $2 {{PLURAL:$3|ieħor/oħra|oħra}} {{GENDER:$1|ħalla/ħalliet|ħallew}} messaġġ fuq il-paġna tad-diskussjoni tiegħek.",
- "notification-page-linked-email-batch-bundle-body": "$2 saritilha {{GENDER:$1|ħolqa}} minn $3 u $4 {{PLURAL:$5|paġna|paġni}} oħra.",
"echo-email-batch-subject-daily": "Għandek {{PLURAL:$2|notifika ġdida|notifiki ġodda}} fuq {{SITENAME}}",
"echo-email-batch-subject-weekly": "Għandek {{PLURAL:$2|notifika ġdida|notifiki ġodda}} fuq {{SITENAME}} dil-Ġimgħa",
"echo-email-batch-body-intro-daily": "X'hemm $1,\nDan hu s-sommarju tal-attività tal-lum fuq {{SITENAME}} biex tista' tarah.",
"echo-email-batch-body-intro-weekly": "X'hemm $1,\nDan hu s-sommarju tal-attività ta' din il-ġimgħa fuq {{SITENAME}} biex tista' tarah.",
- "echo-email-batch-link-text-view-all-notifications": "Ara n-notifiki kollha",
- "echo-rev-deleted-text-view": "Din ir-reviżjoni tal-paġna ġiet soppressa."
+ "echo-email-batch-link-text-view-all-notifications": "Ara n-notifiki kollha"
}
diff --git a/Echo/i18n/mwl.json b/Echo/i18n/mwl.json
new file mode 100644
index 00000000..5cb31add
--- /dev/null
+++ b/Echo/i18n/mwl.json
@@ -0,0 +1,52 @@
+{
+ "@metadata": {
+ "authors": [
+ "MokaAkashiyaPT"
+ ]
+ },
+ "prefs-echo": "Notificaçones",
+ "prefs-emailsettings": "Oupçones de correio eiletrónico",
+ "prefs-displaynotifications": "Oupçones de bisualizaçon",
+ "prefs-echosubscriptions": "Abisar-me subre estes eibentos",
+ "prefs-echocrosswiki": "Notificaçones d'outras bersones de la Biquipédia",
+ "prefs-newmessageindicator": "Andicador de nuoba mensaige",
+ "prefs-blocknotificationslist": "Lhista de bloqueios",
+ "echo-pref-send-me": "Ambiar-me:",
+ "echo-pref-send-to": "Ambiar pa:",
+ "echo-pref-email-format": "Formato de correio:",
+ "echo-pref-web": "Anternete",
+ "echo-pref-email": "Correio eiletrónico",
+ "echo-pref-email-frequency-never": "Nun me ambiar notificaçones por correio",
+ "echo-pref-email-frequency-immediately": "Notificaçones andebiduales cunforme cheguen",
+ "echo-pref-email-frequency-daily": "Un resumo diairo de notificaçones",
+ "echo-pref-email-frequency-weekly": "Un resumo semanal de notificaçones",
+ "echo-pref-email-format-html": "HTML",
+ "echo-pref-email-format-plain-text": "Testo simples",
+ "echo-pref-cross-wiki-notifications": "Amostrar notificaçones d'outras bersones de la Biquipédia",
+ "echo-pref-notifications-blacklist": "Nun amostrar notificaçones destes outelizadores. ([[mw:Help:Notifications#mute|coincer mais]])",
+ "echo-pref-new-message-indicator": "Amostrar l'andicador de mensaige na páigina de cumbersa na mie barra de ferramientas",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|Mensaige|Mensaiges}} na páigina de cumbersa",
+ "echo-category-title-article-linked": "{{PLURAL:$1|Lhigaçon|Lhigaçones}} pa la páigina",
+ "echo-category-title-reverted": "{{PLURAL:$1|Eidiçon rebertida|Eidiçones rebertidas}}",
+ "echo-category-title-mention": "{{PLURAL:$1|Mençon|Mençones}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Mençon falhada|Mençones falhadas}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Mençon efetuada cun éisito|Mençones efetuadas cun éisito}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Altaraçon de ls prebilégios de outelizador|Altaraçones de ls prebilégios de outelizador}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Correio eiletrónico de outro outelizador|Correios eiletrónicos de outros outelizadores}}",
+ "echo-pref-tooltip-edit-user-talk": "Abisar-me quando alguien publicar na mie páigina de cumbersa.",
+ "echo-pref-tooltip-article-linked": "Abisar-me quando alguien anterlhigar ua páigina criada por mi nua outra.",
+ "echo-pref-tooltip-reverted": "Abisar-me quando alguien reberter ua eidiçon mie, al outelizar la funçon çfazer ó la ferramienta de reberson.",
+ "echo-pref-tooltip-mention": "Abisar-me quando alguien criar ua lhigaçon pa a mie páigina de outelizador.",
+ "echo-pref-tooltip-mention-failure": "Abisar-me quando ocorrer un erro al mencionar alguien.",
+ "echo-pref-tooltip-mention-success": "Abisar-me quando menciono alguien.",
+ "echo-pref-tooltip-user-rights": "Abisar-me quando ls mius prebilégios de outelizador fúren altarados.",
+ "echo-pref-tooltip-emailuser": "Abisar-me quando alguien me ambiar un correio eiletrónico.",
+ "notifications": "Notificaçones",
+ "echo-specialpage": "Notificaçones",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notificaçon|notificaçones}}",
+ "notification-link-text-view-mention": "Ber mençon",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Ber mençon|Ber mençones}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notificaçon ($1)|Notificaçones ($1)|100=Notificaçones (mais de 99)}}",
+ "echo-notification-notice-text-only": "Abisos",
+ "echo-overlay-title": "<b>Notificaçones</b>"
+}
diff --git a/Echo/i18n/my.json b/Echo/i18n/my.json
new file mode 100644
index 00000000..9e3d105f
--- /dev/null
+++ b/Echo/i18n/my.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ninjastrikers",
+ "9.sinistra"
+ ]
+ },
+ "prefs-echo": "အသိပေးချက်များ",
+ "notifications": "အသိပေးချက်များ",
+ "tooltip-pt-notifications-alert": "{{GENDER:|သင်၏}} သတိပေးချက်များ",
+ "echo-specialpage": "အသိပေးချက်များ",
+ "notification-header-edit-user-talk": "<strong>{{GENDER:$3|သင်၏}} ဆွေးနွေးချက် စာမျက်နှာ</strong>တွင် စာလွှာတစ်ခုကို $1 {{GENDER:$2|ချန်ထားခဲ့သည်}}။",
+ "notification-header-edit-user-talk-with-section": "<strong>{{GENDER:$3|သင်၏}} ဆွေးနွေးချက်စာမျက်နှာ</strong>ရှိ \"<strong>$4</strong>\" တွင် စာလွှာတစ်ခုကို $1 {{GENDER:$2|ချန်ထားခဲ့သည်}}။",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|သင့်ရဲ့}} ပထမဆုံး တည်းဖြတ်မှုကို {{GENDER:$2|သင်}} ပြုလုပ်ခဲ့ပါပြီ၊ {{GENDER:$2|ကျေးဇူးတင်ပြီး}} ကြိုဆိုလိုက်ပါတယ်!",
+ "notification-header-reverted": "သင်၏ {{PLURAL:$4|<strong>$3</strong> ပေါ်ရှိ တည်းဖြတ်မှု|<strong>$3</strong> ပေါ်ရှိ တည်းဖြတ်မှုများ}}သည် {{GENDER:$2|နောက်ပြန် ပြန်ပြင်ခံခဲ့ရသည်}}။",
+ "notification-reverted-email-subject2": "{{SITENAME}} ရှိ သင့် {{PLURAL:$3|တည်းဖြတ်မှု|တည်းဖြတ်မှုများ}}ကို {{GENDER:$1|နောက်ပြန်ပြင်ခဲ့သည်}}",
+ "echo-overlay-link": "အသိပေးချက်များ အားလုံး",
+ "echo-email-batch-link-text-view-all-notifications": "အသိပေးချက်များ အားလုံးကို ကြည့်ရန်"
+}
diff --git a/Echo/i18n/nan.json b/Echo/i18n/nan.json
new file mode 100644
index 00000000..a3715650
--- /dev/null
+++ b/Echo/i18n/nan.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Luuva"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Lí ê }} thê-chhíⁿ"
+}
diff --git a/Echo/i18n/nap.json b/Echo/i18n/nap.json
index 5c304310..cf3e0365 100644
--- a/Echo/i18n/nap.json
+++ b/Echo/i18n/nap.json
@@ -2,7 +2,10 @@
"@metadata": {
"authors": [
"C.R.",
- "Chelin"
+ "Chelin",
+ "Macofe",
+ "Catrope",
+ "Nemo bis"
]
},
"echo-desc": "Sistema pe' notificà ll'utente ncopp'a ll'evente e li mmasciate",
@@ -10,6 +13,7 @@
"prefs-emailsettings": "Opziune e-mail",
"prefs-displaynotifications": "Opziune 'e visualizzazione",
"prefs-echosubscriptions": "Famme sapè ncopp'a sti avvenimente",
+ "prefs-echocrosswiki": "Nutifiche cross-wiki",
"prefs-newmessageindicator": "Barra d' 'e mmasciate nove",
"echo-pref-send-me": "Manna a mme:",
"echo-pref-send-to": "Manna a:",
@@ -22,118 +26,172 @@
"echo-pref-email-frequency-weekly": "Nu riepilego a semmana a semmana d' 'e mmasciate",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Testo nurmale",
+ "echo-pref-cross-wiki-notifications": "Fà veré 'e nnutifiche 'e ll'ati wiki",
"echo-pref-new-message-indicator": "Fa verè nnicature d' 'e mmasciate ncopp' 'a paggena 'e chiacchiera cu na mmasciata dint' 'a barra 'e strumiente",
+ "echo-pref-beta-feature-cross-wiki-message": "Notifiche migliurate",
+ "echo-pref-beta-feature-cross-wiki-description": "Vide e sistema notifiche cchiù sempricemente. Chesto ncludesse notifiche cross-wiki, ca ve premmettessero 'e vedé mmasciate 'a n'ati wiki. (Pe' puté ricevere notifiche 'e na wiki data, avite appiccià attive 'e funziune beta ncopp'a chillu wiki.)",
"echo-learn-more": "Mpara 'e cchiù",
+ "echo-log": "Riggistro pubbreco",
"echo-new-messages": "Avite mmasciate nove",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mmasciate}} d' 'a paggena 'e chiacchiere",
"echo-category-title-article-linked": "Paggena {{PLURAL:$1|cullegamiento|cullegamiente}}",
"echo-category-title-reverted": "{{PLURAL:$1|Cagnamiento 'arrepigliato|Cagnamiente 'arrepigliate}}",
"echo-category-title-mention": "{{PLURAL:$1|Menzione|Menziune}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Menzione guasta|Menziune guaste}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Menzione|Menziune}} apposto",
"echo-category-title-other": "{{PLURAL:$1|Ati}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Cagna 'o deritto|Cagna 'e deritte}} utente",
- "echo-pref-tooltip-edit-user-talk": "Famme nu tuzzuleo quanno coccheruno mannasse na mmasciata o rispunnesse ncopp' 'a paggena 'e chiacchiera mia.",
- "echo-pref-tooltip-article-linked": "Famme nu tuzzuleo quanno coccheruno se cullegasse a na paggena ca io avesse criato 'a na voce.",
- "echo-pref-tooltip-reverted": "Famme nu tuzzuleo quanno coccheruno annullasse nu cagnamiento ca io stesso aggio fatto, ausanno 'o strumiento 'e annulla.",
- "echo-pref-tooltip-mention": "Famme nu tuzzuleo quanno coccheruno se cullegasse 'a paggena utente mia.",
- "echo-pref-tooltip-user-rights": "Famme nu tuzzuleo quanno coccheruno cagnasse 'e deritte utente mieie.",
- "echo-no-agent": "[Nisciuno]",
- "echo-no-title": "[Nisciuna paggena]",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Masciata mail 'a n'at'utente|Mmasciate mail 'a ll'at'utente}}",
+ "echo-pref-tooltip-edit-user-talk": "Famme nu tuzzuleo si coccheruno mannasse na mmasciata o rispunnesse ncopp' 'a paggena 'e chiacchiera mia.",
+ "echo-pref-tooltip-article-linked": "Famme nu tuzzuleo si coccheruno se cullegasse a na paggena ca io avesse criato 'a na voce.",
+ "echo-pref-tooltip-reverted": "Famme nu tuzzuleo si coccheruno annullasse nu cagnamiento ca io stesso aggio fatto, ausanno 'o strumiento 'e annulla.",
+ "echo-pref-tooltip-mention": "Famme nu tuzzuleo si coccheruno se cullegasse 'a paggena utente mia.",
+ "echo-pref-tooltip-mention-failure": "Fà 'a notifica si nun putesse mannà fòre na menziona a coccheruno.",
+ "echo-pref-tooltip-mention-success": "Famme 'a notifica si mannasse fòre na menziona a coccheruno.",
+ "echo-pref-tooltip-user-rights": "Famme nu tuzzuleo si coccheruno cagnasse 'e deritte utente mieie.",
+ "echo-pref-tooltip-emailuser": "Famme notifica si coccheruno me mannasse na mail.",
"echo-error-no-formatter": "Nisciuna furmattazione è stata definita p' 'e tuzzulee.",
"notifications": "Mmasciate",
"tooltip-pt-notifications-alert": "L'allerte {{GENDER:|vuoste}}",
- "tooltip-pt-notifications-message": "'E mmasciate {{GENDER:|vuoste}}",
+ "tooltip-pt-notifications-notice": "'E communicaziune {{GENDER:|vuoste}}",
+ "echo-displaynotificationsconfiguration": "Fà veré 'e mpustaziune 'e notifiche",
+ "echo-displaynotificationsconfiguration-summary": "Chest'è na panoramica 'e comm' 'e notifiche so' state configurate ncopp'a stu wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notifiche pe' categurìa",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sistimaziona d' 'e tipe",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Int'a quale seziona ogne tipo 'e cagnamiento fosse sistimato",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Metode 'e notifica cunzentute",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Qualu metodo 'e notifica se suppurtasse p'ogne categurìa",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Quali metodi 'e cagnamiento songo suppurtate p'ogne tipo; s'apprecasse surtanto a 'e tipe 'e ll'interno d' 'e categurìe ca songo annascunnute 'a 'e preferenze",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Appicciato predefinito",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Utente esistente",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Utente nuove",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Metode 'e notifica richieste",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Quali metodi so' obbligatori p'ogne categurìa",
"echo-specialpage": "Mmasciate",
+ "echo-specialpage-section-markread": "Nzegna stu gruppo comme fosse letto",
+ "echo-specialpage-markasread": "Notifica: Nzegna comme fosse letta",
+ "echo-specialpage-markasread-invalid-id": "ID evento nun è buono",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|$1 notifica|$1 notifiche}}",
+ "echo-specialpage-pagefilters-title": "Attività ricente",
+ "echo-specialpage-pagefilters-subtitle": "Paggene cu' notifiche nun liggiute",
+ "notificationsmarkread-legend": "Nzegna 'a notifica comme liggiuta",
"echo-anon": "Pe' ricevere notifiche, <span class=\"plainlinks\">[$1 criate nu cunto] o <span class=\"plainlinks\">[$2 trasite].",
"echo-none": "Nun tiene notifiche.",
"echo-more-info": "Cchiù nfurmaziune",
"echo-feedback": "Commenti",
- "echo-api-failure": "Nun se ponno arrepiglià 'e notifiche. Pe' piacere tentate n'ata vota (Errore $1)",
+ "echo-popup-footer-special-page-invitation": "<strong>Pròva 'a paggena 'e Nutifiche fatta nuova.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Tutt' 'e caratteristiche e nuova faccia.",
+ "echo-api-failure": "Guastaje a arrepiglià notifiche.",
+ "echo-api-failure-cross-wiki": "L'acciesso a 'o dominio remoto è stato negato.",
"echo-notification-placeholder": "Nun ce stanno notifiche.",
+ "echo-notification-placeholder-filters": "Nun ce stanno notifiche ca currispunnessero a sti criterie.",
+ "echo-notification-loginrequired": "Avit'a trasì pe' puté vede' 'e mmasciate voste.",
+ "echo-notification-popup-loginrequired": "Pe' piacere, trasite pe' vedé 'e notifiche vuoste.",
+ "echo-notification-markasread": "Nzegna comme fosse letto",
+ "echo-notification-markasunread": "Nzegna comme fosse nun letto",
+ "echo-notification-markasread-tooltip": "Nzegna comme fosse letto",
+ "echo-notification-more-options-tooltip": "Cchiù opziune",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Ferniscela}} 'e cuntrullà attività nuova ncopp' 'o \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Vedite ca}} nun state cchiù a cuntrullà 'a paggena \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Vuje}} putite cuntrullà e tenite a mmente [$2 sta paggena] dint'a ll'elenco 'e cuntrullate.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Segue}} attività nuova ncopp'a \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Vuje}} mo' state a cuntrullà 'a paggena \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Putite}} fernì 'e cuntrullà [$2 sta paggena] quanno vulite.",
+ "notification-link-text-expand-all": "Spanne",
+ "notification-link-text-expand-alert-count": "Vide {{PLURAL:$1|$1 avviso|$1 avvise}}",
+ "notification-link-text-expand-notice-count": "Vire {{PLURAL:$1|$1 communicazione|$1 communicaziune}}",
+ "notification-link-text-expand-all-count": "Vide {{PLURAL:$1|$1 notifica|$1 notifiche}}",
+ "notification-link-text-collapse-all": "Abarruca",
"notification-link-text-view-message": "Vire mmasciata",
"notification-link-text-view-mention": "Vire menziona",
- "notification-link-text-view-changes": "Vire 'e cagnamiente",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Vide menzione|Vide menziune}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Vire}} 'e cagnamiente",
"notification-link-text-view-page": "Vire 'a paggena",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|lassaje}} na mmasciata dint'a <strong>paggena 'e chiacchiera {{GENDER:$3|vosta}}</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|lassaje}} na mmasciata dint'a <strong>paggena 'e chiacchiera r' 'a {{GENDER:$3|vosta}}</strong> int'a \"<strong>$4</strong>\".",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Nu cullegamento è stato fatto 'a <strong>$4</strong> a <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Cullegata 'a <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "'E cullegamente so' state fatte 'a {{PLURAL:$5||nu $5 paggene|100=99+ paggene}} a <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Tuttuquante 'e cullegamente a sta paggena",
+ "notification-header-mention-other": "$1 {{GENDER:$2|facette 'o nomme}} {{GENDER:$3|vuosto}} ncopp'a <strong>$4</strong> int'a \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|facette 'o nomme}} {{GENDER:$3|vuosto}} ncopp'a <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|facette 'o nome}} {{GENDER:$3|vuosto}} dint'a <strong>paggena 'e chiachiera 'utente {{GENDER:$5|'e}} $4</strong> int'a \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|facette 'o nomme}} {{GENDER:$3|vuosto}} dint'a <strong>paggena 'e chiacchiera 'utente {{GENDER:$5|'e}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|facette 'o nomme}} <strong>{{GENDER:$3|vuosto}} dint'a paggena 'e discussione</strong> 'e \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|facette 'o nomme}} {{GENDER:$3|vuosto}} dint' 'a <strong>paggena 'e chiacchiera {{GENDER:$2|soja}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|facette 'o nomme}} {{GENDER:$3|vuosto}} dint'a <strong>$4</strong> paggena 'e chiachiera 'e \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|ha fatto 'o nomme}} {{GENDER:$3|vuosto}} dint' 'a paggena 'e chiacchiera <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|'A menziona vosta}} 'e <strong>$3</strong> nun è stata mannata pecché l'utente nun se truvava.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|'A menziona vosta}} 'e <strong>$3</strong> nun è stata mannata pecché l'utente era anonimo.",
+ "notification-header-mention-failure-too-many": "'E menziune {{GENDER:$2|voste}} nun s'erano mannate pecché jevano annanz' 'o lémmeto 'e $3.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Na menziona|Nu $3 menziune}} {{GENDER:$2|c'avite fatto}} ncopp' 'a <strong>$4</strong> paggena 'e chiacchiera {{PLURAL:$3|putesse stà bluccata|putessero stà bluccate}} senz' 'e se mannà.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>'O nomme utente nun esiste:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>'E ll'IP nun se pò ffà 'o nomme:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|'A menziona vosta}} 'e <strong>$3</strong> è stata mannata.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Na menziona|Nu $3 menziune}} {{GENDER:$2|c'avite fatto}} ncopp' 'a <strong>$4</strong> paggena 'e chiacchiera {{PLURAL:$3|è stata mannata|se so' mannate}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Avite fatto menziona a}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Na notifica|Nu $3 notifiche}} ncopp' 'e menziune {{GENDER:$2|c'avite fatto}} ncopp' 'a paggena 'e chiacchiera <strong>$4</strong>: {{PLURAL:$5|$5 non mannate}}, {{PLURAL:$6|$6 mannate}}.",
+ "notification-header-user-rights-add-only": "'E deritte 'utente {{GENDER:$4|vuoste}} so' state {{GENDER:$1|cagnate}}. Mo' site mpizzato/a dint'a: $2.",
+ "notification-header-user-rights-remove-only": "'E deritte utente {{GENDER:$4|vuoste}} so' state {{GENDER:$1|cagnate}}. Vuje nun site cchiù nu membro 'e: $2.",
+ "notification-header-user-rights-add-and-remove": "'E deritte utente {{GENDER:$6|vuoste}} so state {{GENDER:$1|cagnate}}. Vuje site mò mpizzato/a dint'a: $2. Vuje nun site cchiù nu membro 'e: $4.",
+ "notification-header-welcome": "{{GENDER:$2|Bemmenuto|Bemmenuta}} ncopp' 'a {{SITENAME}}, $1! Simmo cuntente {{GENDER:$2|ca state}} ccà.",
+ "notification-welcome-linktext": "Bemmenute",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Vuje}} appena avite fatto 'o primmo cagnamiento {{GENDER:$2|r' 'o vuosto}}; ve ringraziamm'assaje, e {{GENDER:$2|bemmenuto|bemmenuta}}!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Vuje}} appena avite fatt' 'o cagnamiento nummero diece {{GENDER:$2|r' 'o vuosto}}; ve ringraziamm'assaje assaje, pe' piacere facite semp'accussì!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Vuje}} avite fatto mò mò nu centenaro 'e cagnamiente; site {{GENDER:$2|nu|na}} mostro, ve ringraziamm'assaje!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Vuje}} appena avite fatto nu migliar' 'e cuntribbute; Chest'è na cosa seria, nc'amma luvà 'o cappiello annanz'a {{GENDER:$2|nu cuntribbutore|na cuntribbutrice}} accussì {{GENDER:$2|gruoss|gross}}.",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Vuje}} avite fatto mò mò ll'edizione {{GENDER:$2|vosta}} nummero diecimila; {{GENDER:$2|ve}} ringraziamm'assaje!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Vuje}} appena avite fatto nu centenar' 'e migliar' 'e cuntribbute; marò, assaje! grazie a {{GENDER:$2|vuje}} pe' nu cuntribbuto accussì gruoss!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Vuje}} appena avite fatto nu melion' 'e cuntribbute; Nu melione! Oh anema ro Priatorio!!! (cit.) grazie a {{GENDER:$2|vuje}}!",
+ "notification-link-thank-you-edit": "'O cagnamiento {{GENDER:$1|vuosto}}",
"notification-link-text-view-edit": "Vire 'o cagnamiento",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|t'ha lassato}} na mmasciata dint' 'a [[User talk:$2#$3|paggena 'e chiacchiera]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|t'ha lassato}} na mmasciata dint'a \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|t'ha lassato}} na mmasciata dint' 'a [[User talk:$2#$3|paggena 'e chiacchiera]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|ha lassato}} na mmasciata int'a paggena 'e chiacchiera d' 'a toja int'a \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] fuje {{GENDER:$1|cullegato}} 'a [[:$3]]. [[Special:WhatLinksHere/$2|Vedite tutt' 'e link a sta paggena]].",
- "notification-page-linked-flyout": "[[:$2]] è stata {{GENDER:$1|cullegata}} a [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|lassaje nu commento}} ncopp'a \"[[$3|$2]]\" dint' 'a \"$4\" paggena 'e chiacchiera.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|ave mannato}} n'argomento nuovo \"$2\" ncopp'a [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|t'a mannato}} na mmasciata: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|lassaje nu commento}} ncopp'a \"[[$3#$2|$2]]\" dint' 'a paggena 'e chiacchiera vosta.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|facette 'o nomme vuosto}} dint' 'a $5 paggena 'e chiacchiera int'a \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|ave fatto 'o nomme}} vuosto dint' 'a $5 paggena 'e chiacchiera 'e \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|ave fatto 'o nomme}} vuoto int' 'a [[:$3|$2 paggena 'e chiacchiera]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|ha fatto 'o nomme}} vuosto dint' 'a [[:$3|$2 paggena 'e chiacchiera]].",
- "notification-user-rights": "'E deritte 'utente [[Special:Log/rights/$1|so' state {{GENDER:$1|cagnate}}]] 'a [[User:$1|$1]]. $2. [[Special:ListGroupRights|Mparate 'e cchiù]]",
- "notification-user-rights-flyout": "'E deritte vuoste so' state {{GENDER:$1|cagnate}} 'a $1. $2. [[Special:ListGroupRights|Mpara 'e cchiù]]",
- "notification-user-rights-add": "Mo' site membre 'e {{PLURAL:$2|stu gruppo|sti gruppe}}: $1",
- "notification-user-rights-remove": "Mo' nun site cchiù membre 'e {{PLURAL:$2|stu gruppo|sti gruppe}}: $1",
- "notification-new-user": "Bemmenuto/a a {{SITENAME}}, $1! Nuje simmo cuntente 'e te veré ccà.",
- "notification-reverted2": "{{PLURAL:$4|'O cagnamiento vuosto ncopp'a [[:$2]] è stato|'E cagnamiente vuoste ncopp' 'a [[:$2]] so' state}} {{GENDER:$1|annullate}} 'a [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|'O cagnamiento ncopp'a $2 vuosto è stato|'E cagnamiente vuoste ncopp' 'a $2 so state}} {{GENDER:$1|annullate}} 'a $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|'O cagnamiento ncopp'a <strong>$3</strong> vuosto è stato|'E cagnamiente vuoste ncopp' 'a <strong>$3</strong> so state}} {{GENDER:$2|annullate}}",
+ "notification-header-emailuser": "$1 {{GENDER:$2|te mannaje}} na mmasciata email.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|t'ha lassato}} na mmasciata {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|lassaje}} na mmasciata dint'a paggena 'e chiacchiera toja.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|lassaje}} na mmasciata dint'a paggena 'e chiacchiera r' 'a vosta \"$2\".",
"notification-page-linked-email-subject": "Na paggena c'avite criato fuje cullegata ncopp'a {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 è stata {{GENDER:$1|cullegata}} 'a $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|'O cangiamento vuosto è stato|'E cangiamiente vuoste so'}} state {{GENDER:$1|annullate}} ncopp'a {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|'O cagnamiento ncopp'a $2 vuosto è stato|'E cagnamiente vuoste ncopp' 'a $2 so state}} {{GENDER:$1|annullate}} 'a $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|facette 'o nomme}} vuosto ncopp'a {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|facette 'o nomme}} vuosto ncopp'a $4 paggena 'e chiacchiera dint'a \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|ha fatto 'o nomme}} vuosto dint' 'a paggena 'e chiacchiera 'e $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|facette 'o nomme}} {{GENDER:$2|vuosto}} ncopp'a {{SITENAME}}",
"notification-user-rights-email-subject": "'E deritte utente vuoste so' state cagnate ncopp'a {{SITENAME}}",
- "notification-user-rights-email-batch-body": "'E deritte utente vuoste so' state {{GENDER:$1|cagnate}} 'a $1. $2.",
- "echo-email-subject-default": "Notifica nova ncopp'a {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "$1 {{PLURAL:$1|ora|ore}}",
+ "notification-timestamp-ago-days": "$1 {{PLURAL:$1|iuorno|gghiuorne}}",
+ "notification-timestamp-ago-months": "$1 {{PLURAL:$1|mese|mise}}",
+ "notification-timestamp-ago-years": "$1 {{PLURAL:$1|anno|anne}}",
+ "notification-timestamp-today": "Ogge",
+ "notification-timestamp-yesterday": "Aiere",
+ "notification-inbox-filter-read": "Liegge",
+ "notification-inbox-filter-unread": "Nun liggiuto",
+ "notification-inbox-filter-all": "Tutte",
"echo-email-body-default": "Avite na notifica nova ncopp'a {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "È arrevata na notifica nova.",
- "echo-email-footer-default": "$2\n\nPe' puté cuntrullà 'e mmasciate mail ca te mannammo, vedite nu poco 'e preferenze vuoste::\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-email-footer-default-html": "Pe' putè cuntrullà le mail ca ve mannammo, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">cuntrullate 'e preferenze voste</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPe' puté cuntrullà 'e mmasciate mail ca te mannammo, vedite nu poco 'e preferenze vuoste::\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Pe' puté cuntrullà quali 'email ve mannammo, cuntrullate 'e preferenze:",
+ "echo-email-html-footer-preference-link-text": "cuntrulate 'e preferenze d' 'e voste",
+ "echo-email-html-footer-with-link": "Pe' puté cuntrullà quali email ve véneno mannate, $1.",
"echo-notification-alert": "{{PLURAL:$1|Avvertemiénto ($1)|Avvertemiénte ($1)|100=Avvertemiénte (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Mmasciata ($1)|Mmasciate ($1)|100=Mmasciate (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Communicazione ($1)|Communicaziune ($1)|100=Communicaziune (99+)}}",
"echo-notification-alert-text-only": "Avvise",
- "echo-notification-message-text-only": "Mmasciate",
+ "echo-notification-notice-text-only": "Notifiche",
"echo-overlay-link": "Tutt' 'e notifiche vuoste",
"echo-overlay-title": "<b>Notifiche</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notifica|Notifiche}}</b> (mmustanno $1 'e $2 nun liggiute)",
"echo-mark-all-as-read": "Nzegna tutte cumme fossero lette",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notifica|nutifiche}} nzegnate comm'a liggiute",
+ "echo-mark-wiki-as-read": "Nzegna comme liggiuta dint'a wiki scigliuta: $1",
"echo-date-today": "Ogge",
"echo-date-yesterday": "Aiere",
"echo-load-more-error": "Ascette n'errore pe' tramente ca s'arrepigliaveno cchiù risultate.",
- "notification-edit-talk-page-bundle": "$1 e $3 {{PLURAL:$4|ati}} {{GENDER:$1|lassajeno}} na mmasciata ncopp' 'a [[User talk:$2|paggena 'e chiacchiere d' 'a toja]].",
- "notification-page-linked-bundle": "$2 fuje {{GENDER:$1|linkato|linkata}} 'a $3 e $4 {{PLURAL:$5|ata paggena|ati paggene}}. [[Special:WhatLinksHere/$2|Vide tutt' 'e link a sta paggena]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e $2 {{PLURAL:$3|ato|ati}} {{GENDER:$1|lassaje|lassajeno}} na mmasciata dint' 'a paggena 'e chiacchiera r' 'a vosta.",
- "notification-page-linked-email-batch-bundle-body": "$2 fuje {{GENDER:$1|linkato|linkata}} 'a $3 e $4 ati {{PLURAL:$5|paggena|paggene}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Na masciata nuova|$1 mmasciate nnove|100=99+ mmasciate nnove}} dint' 'a <strong>paggena 'e chiacchiera {{GENDER:$3|d' 'a toja}}.</strong>",
"echo-email-batch-subject-daily": "Avite {{PLURAL:$2|na notifica nova|d' 'e notifiche nnove}} dint'a {{SITENAME}}",
"echo-email-batch-subject-weekly": "Avite {{PLURAL:$2|na notifica nova|d' 'e notifiche nnove}} dint'a {{SITENAME}} sta semmana",
"echo-email-batch-body-intro-daily": "Cià $1,\nCcà sta nu riepilogo 'e ll'attività d'ogge ncopp'a {{SITENAME}} pe' vuje.",
"echo-email-batch-body-intro-weekly": "Cià $1,\nCcà sta nu riepilogo 'e ll'attività 'e sta semmana ncopp'a {{SITENAME}} pe' vuje.",
"echo-email-batch-link-text-view-all-notifications": "Vide tutte 'e notifiche",
- "echo-rev-deleted-text-view": "Sta verziona d' 'a paggena è stata scancellata.",
- "apihelp-echomarkread-description": "Nzegna tutt' 'e notifiche comm'a fossero liggiute 'a ll'utente.",
- "apihelp-echomarkread-param-list": "N'elenco 'e ll'ID notifiche 'a nzegnare comme fossero lette.",
- "apihelp-echomarkread-param-all": "Si mpustato, contrassegna tutte 'e notifiche 'e ll'utente comme fossero lette.",
- "apihelp-echomarkread-param-sections": "N'elenco d' 'e sezine ca s'avesser'a nzegnà comme liggiute.",
- "apihelp-echomarkread-example-1": "Nzegna 'a notifica 8 comme liggiuta",
- "apihelp-echomarkread-example-2": "Nzegna tutt' 'e notifiche comme fossero liggiute",
- "apihelp-echomarkseen-description": "Nzegna 'e notifiche comme fossero liggiute 'a ll'utente 'e mo'.",
- "apihelp-echomarkseen-example-1": "Nzegna tutte 'e notifiche comme liggiute",
- "apihelp-echomarkseen-param-type": "Tipo 'e notifica pe' nzegnà visto comme: 'allerta', 'mmasciata' o 'tutto'.",
- "apihelp-query+notifications-description": "Piglia 'e notifiche ca stesser'aspettann'a ll'utente.",
- "apihelp-query+notifications-param-prop": "Dettaglie d' 'a richiesta.",
- "apihelp-query+notifications-param-sections": "'E seziune 'e notifica a se ffà 'a query (fossero p'esempio na cumbinazione 'allerta' e 'mmasciata').",
- "apihelp-query+notifications-param-groupbysection": "Si vulite accucchià 'o risultato pe' sezziona. Ogne seziona se pigliasse comme fosse a spartuta si chisto se buò ffà.",
- "apihelp-query+notifications-param-format": "Quanno fosse specificato, 'e notifiche fossero turnate cu stu formato.",
- "apihelp-query+notifications-param-limit": "'O nummero massimo 'e notifiche ca s'avess'a turnà.",
- "apihelp-query+notifications-param-index": "Si specificato, n'elenco 'e ID 'e notifica, ordinato, sarrà turnato.",
- "apihelp-query+notifications-param-alertcontinue": "Quanno stessero cchiù risultate ccà a disposizione, facite stu prucesso pe cuntinuà.",
- "apihelp-query+notifications-param-alertunreadfirst": "Si s'avess'a mmusta na mmasciata nun liggiuta 'e notifiche apprimma.",
- "apihelp-query+notifications-param-messagecontinue": "Quanno cchiù mmasciate sarranno a disposiziona, ausa chesto pe' cuntinuà.",
- "apihelp-query+notifications-param-messageunreadfirst": "Si vulite mmustà notifiche senza lieggere primma.",
- "apihelp-query+notifications-example-1": "Elenca notifiche",
- "apihelp-query+notifications-example-2": "Elenca notifiche, raggruppate pe' seziona, cu 'e cuntegge"
+ "notification-header-foreign-alert": "Ati avvise 'a {{PLURAL:$5|n'atu wiki|$5 ati wiki}}",
+ "notification-header-foreign-notice": "Ati notifiche 'a {{PLURAL:$5|n'atu wiki|$5 ati wiki}}",
+ "notification-header-foreign-all": "Ati notifiche 'a {{PLURAL:$5|n'atu wiki|$5 ati wiki}}"
}
diff --git a/Echo/i18n/nb.json b/Echo/i18n/nb.json
index c48e948b..f24f0000 100644
--- a/Echo/i18n/nb.json
+++ b/Echo/i18n/nb.json
@@ -5,136 +5,203 @@
"Jeblad",
"Laaknor",
"Njardarlogar",
- "Chameleon222"
+ "Chameleon222",
+ "SuperPotato",
+ "Macofe",
+ "Nemo bis",
+ "Jon Harald Søby"
]
},
- "echo-desc": "System for å informere brukere om hendelser og meldinger",
- "prefs-echo": "Varsler",
+ "echo-desc": "System for å gi brukere beskjed om hendelser og meldinger",
+ "prefs-echo": "Beskjeder",
"prefs-emailsettings": "E-postinnstillinger",
"prefs-displaynotifications": "Visningsvalg",
- "prefs-echosubscriptions": "Varsle meg om disse hendelsene",
+ "prefs-echosubscriptions": "Gi meg beskjed om disse hendelsene",
+ "prefs-echocrosswiki": "Interwikivarsler",
"prefs-newmessageindicator": "Indikator for ny melding",
+ "prefs-blocknotificationslist": "Ignorerte brukere",
"echo-pref-send-me": "Send meg:",
"echo-pref-send-to": "Send til:",
"echo-pref-email-format": "Epost-format:",
"echo-pref-web": "Web",
"echo-pref-email": "E-post",
- "echo-pref-email-frequency-never": "Ikke send meg e-postvarsler",
- "echo-pref-email-frequency-immediately": "Individuelle varsler fortløpende",
- "echo-pref-email-frequency-daily": "Daglige sammendrag av varsler",
- "echo-pref-email-frequency-weekly": "Ukentlige sammendrag av varsler",
+ "echo-pref-email-frequency-never": "Ikke send meg beskjed på e-post",
+ "echo-pref-email-frequency-immediately": "Individuelle beskjeder etterhvert som de kommer inn",
+ "echo-pref-email-frequency-daily": "Daglige sammendrag av beskjeder",
+ "echo-pref-email-frequency-weekly": "Ukentlige sammendrag av beskjeder",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Ren tekst",
+ "echo-pref-cross-wiki-notifications": "Vis beskjeder fra andre wikier",
+ "echo-pref-notifications-blacklist": "Ikke vis varsler fra disse brukerne. ([[mw:Help:Notifications#mute|lær mer]])",
"echo-pref-new-message-indicator": "Vis indikator for nye meldinger i verktøylinjen min",
+ "echo-pref-beta-feature-cross-wiki-message": "Utvidete beskjeder",
+ "echo-pref-beta-feature-cross-wiki-description": "Vis og organiser beskjeder på en enklere måte. Inkluder beskjeder fra andre wikier. (For å motta beskjeder fra en gitt wiki må du aktivere betafunksjonen på den wikien.)",
"echo-learn-more": "Lær mer",
+ "echo-log": "Offentlig logg",
"echo-new-messages": "Du har nye meldinger",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Melding|Meldinger}} på diskusjonsside",
"echo-category-title-article-linked": "{{PLURAL:$1|Sidelenke|Sidelenker}}",
"echo-category-title-reverted": "Tilbakestilling av {{PLURAL:$1|redigering|redigeringer}}",
"echo-category-title-mention": "{{PLURAL:$1|Omtale|Omtaler}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Mislykket omtale|Mislykkede omtaler}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Vellykket omtale|Vellykkede omtaler}}",
"echo-category-title-other": "{{PLURAL:$1|Annet}}",
"echo-category-title-system": "{{PLURAL:$1|System}}",
- "echo-category-title-user-rights": "{{PLURAL:$1|Endringer}} i brukerrettigheter",
- "echo-pref-tooltip-edit-user-talk": "Varsle meg når noen skriver en melding eller svarer på diskusjonssiden min.",
- "echo-pref-tooltip-article-linked": "Varsle meg når noen lenker fra en artikkel til en side jeg har opprettet.",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Endring|Endringer}} i brukerrettigheter",
+ "echo-category-title-emailuser": "Epost fra {{PLURAL:$1|annen bruker|andre brukere}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Sidepåminnelse|Sidepåminnelser}}",
+ "echo-pref-tooltip-edit-user-talk": "Gi meg beskjed når noen skriver en melding eller svarer på diskusjonssiden min.",
+ "echo-pref-tooltip-article-linked": "Varsle meg når noen lenker til en side jeg har opprettet fra en annen side.",
"echo-pref-tooltip-reverted": "Gi meg beskjed når noen tilbakestiller en av redigeringene mine.",
- "echo-pref-tooltip-mention": "Varsle meg når noen lenker til brukersiden min.",
- "echo-pref-tooltip-user-rights": "Varsle meg når noen endrer brukerrettighetene mine.",
- "echo-no-agent": "[Ingen]",
- "echo-no-title": "[Ingen side]",
- "echo-error-no-formatter": "Ingen formatering definert for varselet",
- "notifications": "Varsler",
+ "echo-pref-tooltip-mention": "Gi meg beskjed når noen lenker til brukersiden min.",
+ "echo-pref-tooltip-mention-failure": "Gi meg beskjed når omtale jeg forsøker å sende ut ikke blir sendt.",
+ "echo-pref-tooltip-mention-success": "Gi meg beskjed når jeg sender ut omtale til noen.",
+ "echo-pref-tooltip-user-rights": "Gi meg beskjed når noen endrer brukerrettighetene mine.",
+ "echo-pref-tooltip-emailuser": "Gi meg beskjed når noen sender meg en e-post.",
+ "echo-pref-tooltip-article-reminder": "Varsle meg om denne siden når jeg spør.",
+ "echo-error-no-formatter": "Ingen formatering definert for beskjeden.",
+ "notifications": "Beskjeder",
"tooltip-pt-notifications-alert": "{{GENDER:|Dine}} varsler",
- "tooltip-pt-notifications-message": "{{GENDER:|Dine}} meldinger",
- "echo-specialpage": "Varsler",
- "echo-anon": "For å motta varsler, [$1 opprett en konto] eller [$2 logg inn].",
- "echo-none": "Du har ingen varsler.",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Dine}} notiser",
+ "echo-displaynotificationsconfiguration": "Vis konfigurasjon av Beskjeder",
+ "echo-displaynotificationsconfiguration-summary": "Dette er en oversikt over hvordan Beskjeder er konfigurert på denne wikien.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Beskjeder etter kategori",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sortering av typer",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Hvilken seksjon hver beskjedtype er sortert i",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Tillatte beskjedmetoder",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Hvilken beskjedmetoder er støttet for hver kategori",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Hvilken beskjedmetoder er støttet for hver type; gjelder bare typer innen kategorier som er skjult fra innstillinger",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Aktivert som standard",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Eksisterende brukere",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nye brukere",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Obligatoriske beskjedmetoder",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Hvilken beskjedmetoder er nødvendige for hver kategori",
+ "echo-specialpage": "Beskjeder",
+ "echo-specialpage-section-markread": "Merk gruppen som lest",
+ "echo-specialpage-markasread": "Beskjed: Merk som lest",
+ "echo-specialpage-markasread-invalid-id": "Ugyldig hendelses-ID",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|beskjed|beskjeder}}",
+ "echo-specialpage-pagefilters-title": "Nylig aktivitet",
+ "echo-specialpage-pagefilters-subtitle": "Sider med uleste beskjeder",
+ "notificationsmarkread-legend": "Merk beskjed som lest",
+ "echo-anon": "For å motta beskjeder, [$1 opprett en konto] eller [$2 logg inn].",
+ "echo-none": "Du har ingen beskjeder.",
"echo-more-info": "Mer informasjon",
"echo-feedback": "Tilbakemelding",
+ "echo-popup-footer-special-page-invitation": "<strong>Prøv den nye siden for beskjeder.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Nytt utseende og ny funksjonalitet.",
+ "echo-api-failure": "Kunne ikke hente beskjeder på grunn av en feil.",
+ "echo-api-failure-cross-wiki": "Tilgang til det eksterne domenet ble avvist.",
+ "echo-notification-placeholder": "Det er ingen beskjeder.",
+ "echo-notification-placeholder-filters": "Ingen beskjeder oppfyller disse kriteriene.",
+ "echo-notification-loginrequired": "Du må logge inn for å se beskjedene dine.",
+ "echo-notification-popup-loginrequired": "Logg inn for å se beskjedene dine.",
+ "echo-notification-markasread": "Merk som lest",
+ "echo-notification-markasunread": "Merk som ulest",
+ "echo-notification-markasread-tooltip": "Merk som lest",
+ "echo-notification-more-options-tooltip": "Flere valg",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Slutt}} å følge med på ny aktivitet på «$1»",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Du}} overvåker ikke lenger siden «$1»",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Du}} kan når som helst begynne å overvåke [$2 denne siden] igjen.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Følg}} med på ny aktivitet på «$1»",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Du}} overvåker nå siden «$1»",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Du}} kan når som helst slutte å overvåke [$2 denne siden].",
+ "notification-link-text-expand-all": "Utvid",
+ "notification-link-text-expand-alert-count": "Vis {{PLURAL:$1|varsel|$1 varsler}}",
+ "notification-link-text-expand-notice-count": "Vis {{PLURAL:$1|En notis|$1 notiser}}",
+ "notification-link-text-expand-all-count": "Vis {{PLURAL:$1|beskjeden|$1 beskjedene}}",
+ "notification-link-text-collapse-all": "Skjul",
"notification-link-text-view-message": "Vis melding",
"notification-link-text-view-mention": "Vis omtale",
- "notification-link-text-view-changes": "Vis endringer",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Vis omtale|Vis omtaler}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Vis}} endringer",
"notification-link-text-view-page": "Vis side",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|skrev}} en melding på <strong>diskusjonssiden {{GENDER:$3|din}}</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|skrev}} en melding under «<strong>$4</strong>» på <strong>diskusjonssiden {{GENDER:$3|din}}</strong>.",
+ "notification-header-page-linked": "<strong>$3</strong> ble lenket til fra <strong>$4</strong>.",
+ "notification-compact-header-page-linked": "Lenket fra <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "<strong>$3</strong> ble lenket til fra {{PLURAL:$5||$5 sider|100=99+ andre sider}}.",
+ "notification-header-article-reminder": "En side {{GENDER:$2|du}} har bedt om varsler for finnes på <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Alle lenker til denne siden",
+ "notification-header-mention-other": "$1 {{GENDER:$2|omtalte}} {{GENDER:$3|deg}} i «<strong>$5</strong>» på <strong>$4</strong>.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|omtalte}} {{GENDER:$3|deg}} på <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|omtalte}} {{GENDER:$3|deg}} i «<strong>$6</strong>» på <strong>brukerdiskusjonssiden {{GENDER:$5|til}} $4</strong>.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|omtalte}} {{GENDER:$3|deg}} på <strong>brukerdiskusjonssiden {{GENDER:$5|til}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|omtalte}} {{GENDER:$3|deg}} i «<strong>$4</strong>» på <strong>diskusjonssiden {{GENDER:$2|sin}}</strong>.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|omtalte}} {{GENDER:$3|deg}} på <strong>diskusjonssiden {{GENDER:$2|sin}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|omtalte}} {{GENDER:$3|deg}} i «<strong>$5</strong>» på diskusjonssiden til <strong>$4</strong>.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|omtalte}} {{GENDER:$3|deg}} på diskusjonssiden til <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "Omtalen {{GENDER:$2|din}} av <strong>$3</strong> ble ikke sendt fordi brukeren ikke ble funnet.",
+ "notification-header-mention-failure-user-anonymous": "Omtalen {{GENDER:$2|din}} av <strong>$3</strong> ble ikke sendt fordi brukeren er anonym.",
+ "notification-header-mention-failure-too-many": "Omtalene {{GENDER:$2|dine}} ble ikke sendt fordi antallet {{PLURAL:$3|mottakere}} oversteg grensen på $3.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|En omtale|$3 omtaler}} {{GENDER:$2|du gjorde}} på diskusjonssiden <strong>$4</strong> {{PLURAL:$3|kunne}} ikke sendes.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Brukernavnet eksisterer ikke:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-er kan ikke omtales:</strong> $1",
+ "notification-header-mention-success": "Omtalen {{GENDER:$2|din}} av <strong>$3</strong> ble sendt.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|En omtale|$3 omtaler}} {{GENDER:$2|du gjorde}} på diskusjonssiden <strong>$4</strong> {{PLURAL:$3|ble}} sendt.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Du omtalte}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|En beskjed|$3 beskjeder}} om omtaler {{GENDER:$2|du gjorde}} på diskusjonssiden <strong>$4</strong>: {{PLURAL:$5|$5 ble ikke sendt}}, {{PLURAL:$6|$6 ble sendt}}.",
+ "notification-header-user-rights-add-only": "Brukerrettighetene {{GENDER:$4|dine}} har blitt {{GENDER:$1|endret}}. Du er nå medlem av: $2.",
+ "notification-header-user-rights-remove-only": "Brukerrettighetene {{GENDER:$4|dine}} har blitt {{GENDER:$1|endret}}. Du er ikke lengre medlem av: $2.",
+ "notification-header-user-rights-add-and-remove": "Brukerrettighetene {{GENDER:$6|dine}} har blitt {{GENDER:$1|endret}}. Du er nå medlem av: $2. Du er ikke lengre medlem av: $4.",
+ "notification-header-user-rights-expiry-change": "Utløpstiden for medlemskapet {{GENDER:$4|ditt}} i følgende {{PLURAL:$3|gruppe|grupper}} har blitt {{GENDER:$1|endret}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Velkommen}} til {{SITENAME}}, $1! Vi er glade for at {{GENDER:$2|du}} er her.",
+ "notification-welcome-linktext": "Velkommen",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Du}} har gjort {{GENDER:$2|din}} første redigering. {{GENDER:$2|Takk}} – og velkommen hit!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Du}} har gjort {{GENDER:$2|din}} tiende redigering. {{GENDER:$2|Takk}}, fortsett gjerne!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Du}} har gjort {{GENDER:$2|din}} hundrede redigering – {{GENDER:$2|tusen takk}}!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Du}} har gjort {{GENDER:$2|din}} tusende redigering – {{GENDER:$2|takk}} for at du bidrar så mye!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Du}} har gjort {{GENDER:$2|din}} titusende redigering – {{GENDER:$2|tusen takk}}!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Du}} gjorde akkurat {{GENDER:$2|din}} hundretusende redigering – {{GENDER:$2|tusen takk}} for utrolig innsats!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Du}} gjorde akkurat {{GENDER:$2|din}} millionte redigering – {{GENDER:$2|tusen takk}} for forbløffende innsats!",
+ "notification-link-thank-you-edit": "Redigeringen {{GENDER:$1|din}}",
"notification-link-text-view-edit": "Vis redigering",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|skrev}} en melding på [[User talk:$2#$3|diskusjonssiden din]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|skrev}} en melding på diskusjonssiden din under «[[User talk:$2#$3|$4]]».",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|skrev}} en melding på [[User talk:$2#$3|diskusjonssiden din]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|skrev}} en melding på diskusjonssiden din under «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "[[:$2]] ble {{GENDER:$1|lenket til}} fra [[:$3]]. [[Special:WhatLinksHere/$2|Se alle lenker til denne siden]].",
- "notification-page-linked-flyout": "[[:$2]] ble {{GENDER:$1|lenket til}} fra [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|kommenterte}} på ''[[$3|$2]]'' på diskusjonssiden ''$4''",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|postet}} en ny tråd ''$2'' på [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|sendte}} deg en melding: ''[[$3#$2|$2]]''",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|kommenterte}} på ''[[$3#$2|$2]]'' på diskusjonssiden din",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|nevnte}} deg i «[[:$3#$2|$4]]» på diskusjonssiden til $5.",
- "notification-mention-flyout": "$1 {{GENDER:$1|nevnte}} deg i «[[:$3#$2|$4]]» på diskusjonssiden til $5.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|nevnte}} deg på [[:$3|diskusjonssiden til «$2»]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|nevnte}} deg på [[:$3|diskusjonssiden til «$2»]].",
- "notification-user-rights": "Brukerrettighetene dine [[Special:Log/rights/$1|ble {{GENDER:$1|endret}}]] av [[User:$1|$1]]. $2. [[Special:ListGroupRights|Lær mer]]",
- "notification-user-rights-flyout": "Brukerrettighetene dine ble {{GENDER:$1|endret}} av $1. $2. [[Special:ListGroupRights|Lær mer]]",
- "notification-user-rights-add": "Du er nå medlem av {{PLURAL:$2|denne gruppa|disse gruppene}}: $1",
- "notification-user-rights-remove": "Du er ikke lenger medlem av {{PLURAL:$2|denne gruppa|disse gruppene}}: $1",
- "notification-new-user": "Velkommen til {{SITENAME}}, $1! Hyggelig å se deg her.",
- "notification-reverted2": "{{PLURAL:$4|Redigeringen din|Redigeringene dine}} på [[:$2]] har blitt {{GENDER:$1|tilbakestilt}} av [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Redigeringen din|Redigeringene dine}} på $2 har blitt {{GENDER:$1|tilbakestilt}} av $1. $3",
+ "notification-link-article-reminder": "Vis siden",
+ "notification-header-reverted": "{{PLURAL:$4|Redigeringen din|Redigeringene dine}} på <strong>$3</strong> har blitt {{GENDER:$2|tilbakestilt}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|sendte}} deg en epost.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|skrev}} en melding til deg på {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|skrev}} en melding på diskusjonssiden din.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|skrev}} en melding til deg under overskriften «$2» på diskussjonssiden din.",
"notification-page-linked-email-subject": "En side du opprettet ble lenket til på {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 ble {{GENDER:$1|lenket}} til fra $3",
"notification-reverted-email-subject2": "{{PLURAL:$3|Redigeringen din|Redigeringene dine}} på {{SITENAME}} ble {{GENDER:$1|tilbakestilt}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Redigeringen din|Redigeringene dine}} på $2 har blitt {{GENDER:$1|tilbakestilt}} av $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|nevnte}} deg på {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|nevnte}} deg i «$3» på diskusjonssiden til $4.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|nevnte}} deg på diskusjonssiden til «$2».",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|omtalte}} {{GENDER:$2|deg}} på {{SITENAME}}",
"notification-user-rights-email-subject": "Brukerrettighetene dine ble endret på {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Brukerrettighetene dine ble {{GENDER:$1|endret}} av $1. $2",
- "echo-email-subject-default": "Nytt varsel på {{SITENAME}}",
- "echo-email-body-default": "Du har et nytt varsel på {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Du har et nytt varsel",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1t}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mnd}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1år}}",
+ "notification-timestamp-today": "I dag",
+ "notification-timestamp-yesterday": "I går",
+ "notification-inbox-filter-read": "Leste",
+ "notification-inbox-filter-unread": "Uleste",
+ "notification-inbox-filter-all": "Alle",
+ "echo-email-body-default": "Du har en ny beskjed på {{SITENAME}}:\n\n$1",
+ "echo-email-footer-default-html": "Du kan styre hva slags eposter vi sender deg i <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">innstillingene dine</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nFor å styre hva slags e-poster vi sender deg, sjekk innstillingene dine: {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "For å kontrollere hvilke e-poster vi kan sende deg, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">sjekk innstillingene dine</a><br />\n$1",
+ "echo-email-plain-footer": "For å kontrollere hvilke eposter vi sender {{GENDER:$1|deg}}, sjekk innstillingene dine:",
+ "echo-email-html-footer-preference-link-text": "sjekk innstillingene {{GENDER:$1|dine}}",
+ "echo-email-html-footer-with-link": "For å kontrollere hvilke eposter vi sender {{GENDER:$2|deg}}, $1.",
"echo-notification-alert": "{{PLURAL:$1|Varsel ($1)|Varsler ($1)|100=Varsler (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Melding ($1)|Meldinger ($1)|100=Meldinger (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notis ($1)|Notiser ($1)|100=Notiser (99+)}}",
"echo-notification-alert-text-only": "Varsler",
- "echo-notification-message-text-only": "Meldinger",
- "echo-overlay-link": "Alle varsler",
- "echo-overlay-title": "<b>Varslinger</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Varsler}}</b> (viser $1 av $2 uleste)",
+ "echo-notification-notice-text-only": "Notiser",
+ "echo-overlay-link": "Alle beskjeder",
+ "echo-overlay-title": "<b>Beskjeder</b>",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Beskjed|Beskjeder}}</b> (viser $1 av $2 uleste)",
"echo-mark-all-as-read": "Merk alle som leste",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|varsel|varsler}} markert som lest",
+ "echo-mark-wiki-as-read": "Merk alle som lest på den valgte wikien: $1",
"echo-date-today": "I dag",
"echo-date-yesterday": "I går",
"echo-load-more-error": "En feil oppsto under henting av flere resultater.",
- "notification-edit-talk-page-bundle": "$1 og $3 {{PLURAL:$4|annen|andre}} {{GENDER:$1|skrev}} en melding på [[User talk:$2|diskusjonssiden din]].",
- "notification-page-linked-bundle": "$2 ble {{GENDER:$1|lenket til}} fra $3 og $4 {{PLURAL:$5|annen side|andre sider}}. [[Special:WhatLinksHere/$2|Se alle lenker til denne siden]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 og $2 {{PLURAL:$3|annen|andre}} {{GENDER:$1|skrev}} en melding på diskusjonssiden din",
- "notification-page-linked-email-batch-bundle-body": "$2 ble {{GENDER:$1|lenket til}} fra $3 og $4 {{PLURAL:$5|annen side|andre sider}}",
- "echo-email-batch-subject-daily": "Du har {{PLURAL:$2|ett nytt varsel|nye varsler}} på {{SITENAME}} i dag",
- "echo-email-batch-subject-weekly": "Du har {{PLURAL:$2|ett nytt varsel|nye varsler}} på {{SITENAME}} denne uka",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Én ny melding|$1 nye meldinger|100=99+ nye meldinger}} på <strong>diskusjonssiden {{GENDER:$3|din}}</strong>.",
+ "echo-email-batch-subject-daily": "Du har {{PLURAL:$2|en ny beskjed|nye beskjeder}} på {{SITENAME}} i dag",
+ "echo-email-batch-subject-weekly": "Du har {{PLURAL:$2|en ny beskjed|nye beskjeder}} på {{SITENAME}} denne uka",
"echo-email-batch-body-intro-daily": "Hei $1,\nHer er et sammendrag av dagens aktivitet på {{SITENAME}} for deg",
"echo-email-batch-body-intro-weekly": "Hei $1,\nHer er et sammendrag av ukas aktivitet på {{SITENAME}} for deg",
- "echo-email-batch-link-text-view-all-notifications": "Vis alle varsler",
- "echo-rev-deleted-text-view": "Denne siderevisjonen har blitt skjult",
- "apihelp-echomarkread-description": "Merk varsler som leste for den aktuelle brukeren.",
- "apihelp-echomarkread-param-list": "En liste over ID-er for varsler som skal merkes som lest.",
- "apihelp-echomarkread-param-all": "Merk alle brukerens varsler som lest.",
- "apihelp-echomarkread-param-sections": "En liste over seksjoner som skal markeres som leste.",
- "apihelp-echomarkread-example-1": "Merk varsel 8 som lest",
- "apihelp-echomarkread-example-2": "Merk alle varsler som leste",
- "apihelp-echomarkseen-description": "Merk varsler som sett for den aktuelle brukeren.",
- "apihelp-echomarkseen-example-1": "Merk varsler av alle typer som sett",
- "apihelp-echomarkseen-param-type": "Varsler som skal merkes som sett: 'alert', 'message' eller 'all'.",
- "apihelp-query+notifications-description": "Hent ventende varsler for den aktuelle brukeren.",
- "apihelp-query+notifications-param-prop": "Detaljer som skal forespørres.",
- "apihelp-query+notifications-param-sections": "Varselstypene som skal spørres (f.eks. en kombinasjon av 'alert' og 'message').",
- "apihelp-query+notifications-param-groupbysection": "Hvorvidt varslene skal grupperes etter seksjon. Hver seksjon hentes hver for seg hvis gitt.",
- "apihelp-query+notifications-param-format": "Hvis angitt blir varslene formatert på denne måten.",
- "apihelp-query+notifications-param-limit": "Maks antall varsler som skal hentes.",
- "apihelp-query+notifications-param-index": "Hvis angitt, en ordnet liste over ID-er for varsler som skal hentes",
- "apihelp-query+notifications-param-alertcontinue": "Når flere resultater er tilgjengelig, bruk denne for å hente flere.",
- "apihelp-query+notifications-param-alertunreadfirst": "Hvorvidt uleste varsler skal vises først.",
- "apihelp-query+notifications-param-messagecontinue": "Når flere resultater er tilgjengelig, bruk denne for å hente flere.",
- "apihelp-query+notifications-param-messageunreadfirst": "Hvorvidt uleste varsler skal vises først.",
- "apihelp-query+notifications-example-1": "List varsler",
- "apihelp-query+notifications-example-2": "List varsler, gruppert etter seksjon, med antall"
+ "echo-email-batch-link-text-view-all-notifications": "Vis alle beskjeder",
+ "notification-header-foreign-alert": "Flere varsler fra {{PLURAL:$5|én annen wiki|$5 andre wikier}}",
+ "notification-header-foreign-notice": "Flere notiser fra {{PLURAL:$5|en annen wiki|$5 andre wikier}}",
+ "notification-header-foreign-all": "Flere beskjeder fra {{PLURAL:$5|én annen wiki|$5 andre wikier}}"
}
diff --git a/Echo/i18n/nds-nl.json b/Echo/i18n/nds-nl.json
index 19595629..c39410d9 100644
--- a/Echo/i18n/nds-nl.json
+++ b/Echo/i18n/nds-nl.json
@@ -4,11 +4,12 @@
"Servien"
]
},
- "echo-desc": "Meldingssysteem",
+ "echo-desc": "Systeem veur t informeren van gebrukers over evenementen en berichten",
"prefs-echo": "Melding",
"prefs-emailsettings": "Netpostinstellingen",
"prefs-displaynotifications": "Weergave-instellingen",
"prefs-echosubscriptions": "Stel mien op de heugte van disse gebeurtenissen",
+ "prefs-echocrosswiki": "Meldingen van aandere wiki's",
"prefs-newmessageindicator": "Melding nieje berichten",
"echo-pref-send-me": "Stuur mien:",
"echo-pref-send-to": "Sturen naor:",
@@ -21,9 +22,10 @@
"echo-pref-email-frequency-weekly": "n Wekelikse samenvatting van meldingen",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Tekste zonder opmaak",
- "echo-pref-notify-show-link": "Laot melding in mien warkbalke zien",
+ "echo-pref-cross-wiki-notifications": "Meldingen van aandere wiki's laoten zien",
"echo-pref-new-message-indicator": "Laot meldingen over berichten op mien overlegzied in mien warkbalke zien",
"echo-learn-more": "Meer lezen",
+ "echo-log": "Openbaor logboek",
"echo-new-messages": "Je hebben nieje berichten",
"echo-category-title-edit-user-talk": "Bericht{{PLURAL:$1||en}} op mien overlegzied",
"echo-category-title-article-linked": "Ziedverwiezing{{PLURAL:$1||en}}",
@@ -35,58 +37,59 @@
"echo-pref-tooltip-article-linked": "Stuur m'n n melding as der ene n verwiezing maakt naor n zied die'k an-emaakt hebbe.",
"echo-pref-tooltip-reverted": "Stuur m'n n melding as der ene n bewarking die'k an-ebröcht hebbe weerummedreit mit de funksie ongedaonmaken of weerummedreien.",
"echo-pref-tooltip-mention": "Stuur m'n n melding as der ene n verwiezing maakt naor mien gebrukerszied vanaof n overlegzied.",
- "echo-no-agent": "[Gien ene]",
- "echo-no-title": "[Gien zied]",
"echo-error-no-formatter": "Der is gien opmaak in-esteld veur de melding.",
- "echo-error-preference": "Fout: de gebrukersinstelling kon niet in-esteld wörden",
- "echo-error-token": "Fout: t gebrukerstoken kon niet op-ehaold wörden",
"notifications": "Meldingen",
- "tooltip-pt-notifications": "Joew meldingen",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Oew}} meldingen",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Joew}} mededelingen",
"echo-specialpage": "Meldingen",
+ "echo-specialpage-pagefilters-title": "Leste aktiviteit",
+ "echo-specialpage-pagefilters-subtitle": "Ziejen mit meldingen die niet elezen bin",
+ "notificationsmarkread-legend": "Markeer melding as elezen",
"echo-anon": "[$1 Maak n gebrukerskonto n] of [$2 meld je eigen an] a'j meldingen ontvangen willen.",
"echo-none": "Je hebben gien meldingen.",
"echo-more-info": "Meer informasie",
"echo-feedback": "Kommentaar",
+ "echo-popup-footer-special-page-invitation": "<strong>Probeer de herontwörpen meldingenzied.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "n Niej uterlik en nieje funksies.",
+ "echo-api-failure": "Kan meldingen niet ophaolen.",
+ "echo-notification-placeholder": "Der bin gien berichten.",
+ "echo-notification-markasread": "Markeer as elezen",
+ "echo-notification-markasunread": "Markeer as niet elezen",
+ "echo-notification-markasread-tooltip": "Markeer as elezen",
+ "echo-notification-more-options-tooltip": "Meer opsies",
+ "notification-link-text-expand-all": "Uutklappen",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 melding|$1 meldingen}} bekieken",
+ "notification-link-text-expand-notice-count": "Bekiek {{PLURAL:$1|$1 mededeling|$1 mededelingen}}",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 melding|$1 meldingen}} bekieken",
+ "notification-link-text-collapse-all": "Inklappen",
"notification-link-text-view-message": "Bericht bekieken",
"notification-link-text-view-mention": "Vermelding bekieken",
"notification-link-text-view-changes": "Verschil bekieken",
"notification-link-text-view-page": "Zied bekieken",
+ "notification-welcome-linktext": "Welkom",
"notification-link-text-view-edit": "Bewarking bekieken",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|hef n bericht achtereleuten}} op joew [[User talk:$2#$3|overlegzied]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|hef}} n bericht op joew overlegzied achtereleuten in t onderwarp \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|hef n bericht achtereleuten}} op joew [[User talk:$2#$3|overlegzied]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|hef}} n bericht op joew overlegzied achtereleuten in t onderwarp \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] is {{GENDER:$1|ekoppeld}} vanaof [[:$3]]:[[Special:WhatLinksHere/$2|alle verwiezingen naor disse zied bekieken]].",
- "notification-page-linked-flyout": "[[:$2]] is {{GENDER:$1|ekoppeld}} vanaof [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|hef ereageerd}} op \"[[$3|$2]]\" op de overlegzied \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|hef}} n niej onderwarp \"$2\" op [[$3]] ezet.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|hef}} joe n bericht estuurd: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|hef ereageerd}} op \"[[$3#$2|$2]]\" op joew overlegzied",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|hef}} joe eneumd op de overlegzied van $5 in \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|hef}} joe eneumd op de overlegzied van $5 in \"[[:$3#$2|$4]]\".",
- "notification-user-rights": "[[Special:Log/rights/$1|Joew gebrukersrechten]] bin {{GENDER:$1|ewiezigd}} deur [[User:$1|$1]]. $2. [[Special:ListGroupRights|Meer informasie]]",
- "notification-user-rights-flyout": "Joew gebrukersrechten bin {{GENDER:$1|ewiezigd}} deur $1. $2. [[Special:ListGroupRights|Meer informasie]]",
- "notification-user-rights-add": "Je bin noen lid van disse groep{{PLURAL:$2||en}}: $1",
- "notification-user-rights-remove": "Je bin noen gien lid meer van disse groep{{PLURAL:$2||en}}: $1",
- "notification-new-user": "Welkom op {{SITENAME}}, $1! Goed da'j der bin.",
- "notification-reverted2": "Joew {{PLURAL:$4|bewarking op [[:$2]] is|bewarkingen op [[:$2]] bin}} {{GENDER:$1|weerummedreid}} deur [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "Joew {{PLURAL:$4|bewarking op $2 is|bewarkingen op $2 bin}} {{GENDER:$1|weerummedreid}} deur $1 $3",
+ "notification-header-reverted": "Joew {{PLURAL:$4|bewarking op $3 is|bewarkingen op $3 bin}} {{GENDER:$2|weerummedreid}} deur $1",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|hef}} n bericht veur joe achtereleuten op {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|hef}} n bericht achtereleuten op joew overlegzied:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|hef}} n bericht achtereleuten op joew overlegzied in \"$2\".",
"notification-page-linked-email-subject": "n Zied die'j an-emaakt hebbe is ekoppeld op {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 is {{GENDER:$1|ekoppeld}} vanaof $3.",
"notification-reverted-email-subject2": "Joew {{PLURAL:$3|bewarking op {{SITENAME}} is|bewarkingen op {{SITENAME}} bin}} {{GENDER:$1|weerummedreid}}",
- "notification-reverted-email-batch-body2": "Joew {{PLURAL:$3|bewarking op $2 is|bewarkingen op $2 bin}} {{GENDER:$1|weerummedreid}} deur $1",
"notification-mention-email-subject": "$1 {{GENDER:$1|hef}} joe eneumd op {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|hef}} joe eneumd op de overlegzied van $4 in \"$3\"",
"notification-user-rights-email-subject": "Joew gebrukersrechten op {{SITENAME}} bin ewiezigd",
- "notification-user-rights-email-batch-body": "Joew gebrukersrechten bin {{GENDER:$1|ewiezigd}} deur $1. $2",
- "echo-email-subject-default": "Nieje melding op {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1u}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mnd}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1jr}}",
+ "notification-timestamp-today": "Vandage",
+ "notification-timestamp-yesterday": "Gisteren",
+ "notification-inbox-filter-read": "Elezen",
+ "notification-inbox-filter-unread": "Niet elezen",
+ "notification-inbox-filter-all": "Alles",
"echo-email-body-default": "Je hebben n nieje melding op {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Je hebben n nieje melding.",
"echo-email-footer-default": "$2\n\nVolg de volgende verwiezing um te bepaolen hokken netberichten wie joe sturen:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Gao naor <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">mien veurkeuren</a> um te bepaolen hokken netberichten wie joe sturen.<br />\n$1",
+ "echo-notification-alert-text-only": "Meldingen",
+ "echo-notification-notice-text-only": "Mededelingen",
"echo-overlay-link": "Alle meldingen",
"echo-overlay-title": "<b>Meldingen</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Meldingen}}</b> ($1 van $2 he'j nog niet elezen)",
@@ -94,14 +97,9 @@
"echo-date-today": "Vandage",
"echo-date-yesterday": "Gisteren",
"echo-load-more-error": "Der is wat mis egaon bie t ophaolen van meer resultaoten.",
- "notification-edit-talk-page-bundle": "$1 en $3 {{PLURAL:$4|aandere gebruker|aandere gebrukers}} hebben n bericht {{GENDER:$1|achtereleuten}} op joew [[User talk:$2|overlegzied]].",
- "notification-page-linked-bundle": "$2 is {{GENDER:$1|ekoppeld}} vanaof $3 en $4 aandere {{PLURAL:$5|zied|ziejen}}. [[Special:WhatLinksHere/$2|Alle verwiezingen naor disse zied bekieken]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 en $2 {{PLURAL:$3|aandere gebruker|aandere gebrukers}} {{GENDER:$1|hebben}} n bericht op joew overlegzied achtereleuten.",
- "notification-page-linked-email-batch-bundle-body": "$2 is {{GENDER:$1|ekoppeld}} vanaof $3 en $4 aandere {{PLURAL:$5|zied|ziejen}}",
"echo-email-batch-subject-daily": "Je hebben {{PLURAL:$2|n nieje melding|nieje meldingen}} op {{SITENAME}}",
"echo-email-batch-subject-weekly": "Je hebben disse weke {{PLURAL:$2|n nieje melding|nieje meldingen}} op {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Huj $1,\nHier he'j n samenvatting van de aktiviteiten op {{SITENAME}} van vandage",
"echo-email-batch-body-intro-weekly": "Huj $1,\nHier he'j n samenvatting van de aktiviteiten op {{SITENAME}} van disse weke.",
- "echo-email-batch-link-text-view-all-notifications": "Alle mededelingen bekieken",
- "echo-rev-deleted-text-view": "Disse ziedversie is onderdrokt."
+ "echo-email-batch-link-text-view-all-notifications": "Alle mededelingen bekieken"
}
diff --git a/Echo/i18n/nds.json b/Echo/i18n/nds.json
index e8ea73b2..ddbeb258 100644
--- a/Echo/i18n/nds.json
+++ b/Echo/i18n/nds.json
@@ -1,10 +1,14 @@
{
"@metadata": {
"authors": [
- "Joachim Mos"
+ "Joachim Mos",
+ "Servien"
]
},
"echo-pref-web": "Web",
"echo-pref-email": "E-Mail",
- "echo-category-title-other": "Annere"
+ "echo-category-title-other": "Annere",
+ "echo-notification-placeholder": "Dat gifft keen Benarichtigungen.",
+ "echo-notification-alert-text-only": "Meldungen",
+ "echo-overlay-link": "Alle Benarichtigungen"
}
diff --git a/Echo/i18n/ne.json b/Echo/i18n/ne.json
index 179fc3bc..c175e424 100644
--- a/Echo/i18n/ne.json
+++ b/Echo/i18n/ne.json
@@ -4,12 +4,14 @@
"सरोज कुमार ढकाल",
"Nirjal stha",
"NehalDaveND",
- "राम प्रसाद जोशी"
+ "राम प्रसाद जोशी",
+ "बिप्लब आनन्द",
+ "जनक राज भट्ट"
]
},
- "echo-desc": "जानकारी प्रणाली",
+ "echo-desc": "प्रयोगकर्तालाई सम्मेलन तथा सन्देश सूचना दिने जानकारी प्रणाली",
"prefs-echo": "जानकारीहरू",
- "prefs-emailsettings": "इमेल विकल्पहरु",
+ "prefs-emailsettings": "इमेल विकल्पहरू",
"prefs-displaynotifications": "प्रदर्शन विकल्पहरू",
"prefs-echosubscriptions": "निम्न घटनाहरूबारे मलाई जानकारी गराउने",
"prefs-newmessageindicator": "नयाँ जानकारी सुचक",
@@ -31,82 +33,53 @@
"echo-category-title-article-linked": "पृष्ठ {{PLURAL:$1|लिङ्क|लिङ्कहरू}}",
"echo-category-title-reverted": "सम्पादन {{PLURAL:$1|रिभर्ट|रिभर्टहरू}}",
"echo-category-title-mention": "{{PLURAL:$1|नाम लिइयो|नामहरू लिइयो}}",
- "echo-category-title-other": "{{PLURAL:$1|अरु}}",
+ "echo-category-title-other": "{{PLURAL:$1|अन्य}}",
"echo-category-title-system": "{{PLURAL:$1|प्रणाली}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|प्रयोगकर्ता अधिकार परिवर्तन|प्रयोगकर्ता अधिकारहरू परिवर्तन}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|अन्य प्रयोगकर्ताबाट इमेल|अन्य प्रयोगकर्ताहरूबाट इमेल}}",
"echo-pref-tooltip-edit-user-talk": "कसैले मेरो वार्तालाप पृष्ठमा सन्देश छोडेमा जानकारी गराउनुहोस् ।",
"echo-pref-tooltip-article-linked": "कसैले मैले सिर्जना गरेको पृष्ठमा लिङ्क जोडेमा जानकारी गराउनुहोस ।",
"echo-pref-tooltip-reverted": "जब कसैले मैले बनाएको सम्पादन उल्ट्याउँदछ मलाई जानकारी गराउनुहोस्, अनडु र रोलब्याक उपकरण प्रयोग गरेर।",
"echo-pref-tooltip-mention": "जब कसैले मेरो प्रयोगकर्ता पृष्ठलाई कुनै पनि वार्ता पृष्ठबाट लिङ्क गर्छ मलाई जानकारी गराउनुहोस्।",
- "echo-no-agent": "[कोही पनि हैन]",
- "echo-no-title": "[कुनै पनि पृष्ठ हैन]",
"echo-error-no-formatter": "जानकारीको लागि कुनै पनि ढाँचा खुलाइएको छैन ।",
"notifications": "जानकारीहरू",
- "tooltip-pt-notifications-message": "{{GENDER:|तपाईंका}} संदेशहरू",
+ "tooltip-pt-notifications-alert": "{{GENDER:|तपाईंको}} जानकारीहरू",
"echo-specialpage": "जानकारीहरू",
"echo-anon": "जानकारीहरू प्राप्त गर्न, [$1 एउटा खाता खोल्नुहोस्] वा [$2 प्रवेश गर्नुहोस्]",
- "echo-none": "तपाईँको लागि नयाँ जानकारी छैन ।",
+ "echo-none": "तपाईंको लागि कुनै नयाँ जानकारी छैन ।",
"echo-more-info": "थप जानकारी",
"echo-feedback": "प्रतिक्रिया",
+ "echo-notification-placeholder": "तपाईंको लागि कुनै सूचना छैन ।",
+ "echo-notification-markasread": "पढेकोमा चिह्नित गर्ने",
"notification-link-text-view-message": "सन्देश हेर्ने",
"notification-link-text-view-mention": "नाम लिइएको हेर्ने",
"notification-link-text-view-changes": "परिवर्तन हेर्ने",
"notification-link-text-view-page": "पृष्ठ हेर्ने",
"notification-link-text-view-edit": "सम्पादन हेर्ने",
- "notification-edit-talk-page2": "[[User:$1|$1]] ले तपाईँको [[User talk:$2#$3|वार्ता पृष्ठ]]मा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}}।",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] ले तपाईँको वार्ता पृष्ठमा \"[[User talk:$2#$3|$4]]\"मा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}}।",
- "notification-edit-talk-page-flyout2": "$1ले तपाईँको [[User talk:$2#$3|वार्ता पृष्ठ]]मा सन्देश {{GENDER:$1|छोड्नुभएको छ}} ।",
- "notification-edit-talk-page-flyout-with-section": "$1 ले तपाईँको वार्ता पृष्ठमा \"[[User talk:$2#$3|$4]]\" मा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}}।",
- "notification-page-linked": "[[:$2]] [[:$3]] बाट {{GENDER:$1|लिङ्क भयो}}। [[Special:WhatLinksHere/$2|यस पृष्ठसँग भएको सबै लिङ्कहरू हेर्नुहोस्]]।",
- "notification-page-linked-flyout": "[[:$3]] मा [[:$2]] {{GENDER:$1|जोडियो }}",
- "notification-add-comment2": "[[User:$1|$1]] ले \"[[$3|$2]]\" मा \"$4\" वार्तालाप पृष्ठमा {{GENDER:$1|टिप्पणी गर्नुभयो}}।",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] ले [[$3]] मा एउटा नयाँ विषय \"$2\" {{GENDER:$1|पोस्ट गर्नुभयो}}।",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] ले तपाईँलाई एउटा सन्देश: \"[[$3#$2|$2]]\" {{GENDER:$1|पठाउनुभयो}}।",
- "notification-add-comment-yours2": "[[User:$1|$1]] ले \"[[$3#$2|$2]]\" मा तपाईँको वार्तालाप पृष्ठमा {{GENDER:$1|टिप्पणी गर्नुभयो}}।",
- "notification-mention": "[[User:$1|$1]] ले \"[[:$3#$2|$4]]\" मा $5 वार्ता पृष्ठमा तपाईँलाई {{GENDER:$1|उल्लेख गर्नुभयो}}।",
- "notification-mention-flyout": "$1 ले तपाईँलाई $5 वार्ता पृष्ठमा \"[[:$3#$2|$4]]\" मा {{GENDER:$1|उल्लेख गर्नुभयो}}।",
- "notification-mention-nosection": "[[User:$1|$1]] ले तपाईँलाई [[:$3|$2 वार्ता पृष्ठ]] मा {{GENDER:$1|उल्लेख गर्नुभयो}}।",
- "notification-mention-nosection-flyout": "$1 ले तपाईँलाई [[:$3|$2 वार्ता पृष्ठ]] मा {{GENDER:$1|उल्लेख गर्नुभयो}}।",
- "notification-user-rights": "तपाईँको प्रयोगकर्ता अधिकारहरू [[Special:Log/rights/$1| [[User:$1|$1]] द्वारा {{GENDER:$1|परिवर्तन गरियो}}]]। $2. [[Special:ListGroupRights|थप जानकारी]]",
- "notification-user-rights-flyout": "तपाईँको प्रयोगकर्ता अधिकारहरू $1 द्वारा {{GENDER:$1|परिवर्तन गरियो}}। $2. [[Special:ListGroupRights|थप जानकारी]]",
- "notification-user-rights-add": "अब तपाईँ {{PLURAL:$2|यो समूह|यी समूहहरू}}: $1 को एउटा सदस्य हुनुहुन्छ।",
- "notification-user-rights-remove": "अब तपाईँ {{PLURAL:$2|यो समूह|यी समूहहरू}}: $1 को सदस्य हुनुहुन्न।",
- "notification-new-user": "{{SITENAME}} मा स्वागत, $1! तपाईँ यहाँ हुनुहुन्छ हामी खुसी छौँ।",
- "notification-reverted2": "तपाईँको {{PLURAL:$4|सम्पादन [[:$2]] मा |सम्पादनहरू [[:$2]] मा}} [[User:$1|$1]] द्वारा {{GENDER:$1|उल्ट्याइएको छ}}। $3",
- "notification-reverted-flyout2": "तपाईँको {{PLURAL:$4|सम्पादन $2 मा |सम्पादनहरू $2 मा}} $1 द्वारा {{GENDER:$1|उल्ट्याइएको छ}}। $3",
- "notification-edit-talk-page-email-subject2": "$1 ले तपाईँलाई {{SITENAME}} मा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}}",
- "notification-edit-talk-page-email-batch-body2": "$1 तपाईँको वार्ता पृष्ठमा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}}:",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 तपाईँको वार्ता पृष्ठमा \"$2\" मा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}} ।",
- "notification-page-linked-email-subject": "तपाईँको पृष्ठ {{SITENAME}} मा जोडियो",
- "notification-page-linked-email-batch-body": "$2 $3 बाट {{GENDER:$1|जोडियो}}।",
- "notification-reverted-email-subject2": "तपाईँको {{PLURAL:$3|सम्पादन |सम्पादनहरू}} {{SITENAME}} मा {{GENDER:$1|उल्ट्याइयो}}",
- "notification-reverted-email-batch-body2": "तपाईँको {{PLURAL:$3|सम्पादन $2 मा |सम्पादन $2 मा}} $1 द्वारा {{GENDER:$1|उल्ट्याइयो}}।",
- "notification-mention-email-subject": "$1 ले तपाईँलाई {{SITENAME}} मा {{GENDER:$1|उल्लेख गर्नुभयो}}",
- "notification-mention-email-batch-body": "$1 ले तपाईँलाई $4 वार्ता पृष्ठमा \"$3\" मा {{GENDER:$1|उल्लेख गर्नुभयो}}।",
- "notification-mention-nosection-email-batch-body": "$1 ले तपाईँलाई वार्ता पृष्ठमा $2 मा {{GENDER:$1|उल्लेख गर्नुभयो}}।",
- "notification-user-rights-email-subject": "तपाईँको प्रयोगकर्ता अधिकारहरू {{SITENAME}} मा परिवर्तन भएका छन्।",
- "notification-user-rights-email-batch-body": "तपाईँको प्रयोगकर्ता अधिकारहरू $1 द्वारा {{GENDER:$1|परिवर्तन गरियो}}। $2.",
- "echo-email-subject-default": " {{SITENAME}} मा नयाँ सूचनाहरू",
+ "notification-header-reverted": "तपाईंको {{PLURAL:$4|सम्पादन $3 मा |सम्पादनहरू $3}} द्वारा {{GENDER:$2|उल्ट्याइएको छ}}।",
+ "notification-header-emailuser": "$1 {{GENDER:$2|ले}} इमेल पठाउनुभएको छ",
+ "notification-edit-talk-page-email-subject2": "$1 ले तपाईंलाई {{SITENAME}} मा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 तपाईंको वार्ता पृष्ठमा \"$2\" मा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}} ।",
+ "notification-page-linked-email-subject": "तपाईँद्वारा निर्माण गरिएको पृष्ठ {{SITENAME}}मा जोडियो",
+ "notification-reverted-email-subject2": "तपाईंको {{PLURAL:$3|सम्पादन |सम्पादनहरू}} {{SITENAME}} मा {{GENDER:$1|उल्ट्याइयो}}",
+ "notification-mention-email-subject": "$1 ले {{GENDER:$2|तपाईंलाई}} {{SITENAME}} मा {{GENDER:$1|उल्लेख गर्नुभयो}}",
+ "notification-user-rights-email-subject": "तपाईंको प्रयोगकर्ता अधिकारहरू {{SITENAME}} मा परिवर्तन भएका छन्।",
+ "notification-inbox-filter-read": "पढिएका",
+ "notification-inbox-filter-unread": "नपढिएका",
+ "notification-inbox-filter-all": "सबै",
"echo-email-body-default": "तपाईँका लागि {{SITENAME}} मा नयाँ सूचनाहरू छन्:\n\n$1",
- "echo-email-batch-body-default": "तपाईँको लागि नयाँ सूचना छ ।",
- "echo-email-footer-default": "$2\n\nहामीले तपाईँलाई कुन इमेलहरू पठाउने नियन्त्रण गर्न, आफ्नो प्राथमिकताहरू जाँच्नुहोस्:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "हामीले तपाईँलाई कुन इमेलहरू पठाउने नियन्त्रण गर्न, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">check your preferences</a>.<br />\n$1",
- "echo-notification-message-text-only": "सन्देशहरू",
- "echo-overlay-link": "सबै जानकारीहरु",
+ "echo-email-footer-default": "$2\n\nहामीले तपाईंलाई कुन इमेलहरू पठाउने भन्नेमा नियन्त्रण गर्न, आफ्नो प्राथमिकताहरू जाँच्नुहोस्:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-notification-alert-text-only": "सुचनाहरू",
+ "echo-overlay-link": "सबै जानकारीहरू",
"echo-overlay-title": "<b>जानकारीहरू</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|जानकारीहरू}}</b> ($2 मध्येका $1 नहेरिएका जानकारीहरू )",
"echo-mark-all-as-read": "सबै पढिएको भनि चिनो लगाउने",
"echo-date-today": "आज",
"echo-date-yesterday": "हिजो",
"echo-load-more-error": "थप नतिजाहरू प्राप्त गर्दा त्रुटि हुन गयो ।",
- "notification-edit-talk-page-bundle": "$1 र $3 {{PLURAL:$4|अन्य}} ले तपाईँको [[User talk:$2|वार्ता पृष्ठ]] मा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}}।",
- "notification-page-linked-bundle": "$2 $3 र $4 अन्य {{PLURAL:$5|पृष्ठ|पृष्ठहरू}}बाट {{GENDER:$1|जोडियो}}। [[Special:WhatLinksHere/$2|यस पृष्ठसँग जोडिएका सबै हेर्नुहोस्]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 र $2 {{PLURAL:$3|अन्य}} ले तपाईँको वार्ता पृष्ठमा एउटा सन्देश {{GENDER:$1|छोड्नुभएको छ}}।",
- "notification-page-linked-email-batch-bundle-body": "$2 $3 र $4 अन्य {{PLURAL:$5|पृष्ठ|पृष्ठहरू}} बाट {{GENDER:$1|जोडियो}}।",
"echo-email-batch-subject-daily": "तपाईँसँग {{SITENAME}} मा {{PLURAL:$2|नयाँ सूचना|नयाँ सूचनाहरू}} छ",
"echo-email-batch-subject-weekly": "तपाईँसँग {{SITENAME}} मा यो हप्ता {{PLURAL:$2|नयाँ सूचना|नयाँ सूचनाहरू}} छ",
- "echo-email-batch-body-intro-daily": "नमस्ते $1,\nयहाँ तपाईँको लागि {{SITENAME}} मा आजको गतिविधिको एउटा सारांश छ।",
- "echo-email-batch-body-intro-weekly": "नमस्ते $1,\nयहाँ तपाईँको लागि {{SITENAME}} मा यो हप्ताको गतिविधिको एउटा सारांश छ।",
- "echo-email-batch-link-text-view-all-notifications": "सबै सूचनाहरू हेर्नुहोस्",
- "echo-rev-deleted-text-view": "यो पृष्ठको पुनरावलोकन दबाइएको छ ।",
- "apihelp-echomarkseen-example-1": "सूचनालाई हेरेको भनि चिन्ह लगाउने"
+ "echo-email-batch-body-intro-daily": "नमस्ते $1,\nयहाँ तपाईंको लागि {{SITENAME}}मा आजको गतिविधिको एउटा सारांश छ।",
+ "echo-email-batch-body-intro-weekly": "नमस्ते $1,\nयहाँ तपाईंको लागि {{SITENAME}} मा यो हप्ताको गतिविधिको निम्नानुशार सारांश छ।",
+ "echo-email-batch-link-text-view-all-notifications": "सबै सूचनाहरू हेर्नुहोस्"
}
diff --git a/Echo/i18n/nl-informal.json b/Echo/i18n/nl-informal.json
index 2a12dc1d..fc569dd8 100644
--- a/Echo/i18n/nl-informal.json
+++ b/Echo/i18n/nl-informal.json
@@ -4,7 +4,6 @@
"Siebrand"
]
},
- "tooltip-pt-notifications": "Jouw meldingen",
"echo-none": "Je hebt geen meldingen.",
"echo-email-body-default": "Je hebt een nieuwe melding op {{SITENAME}}:\n\n$1",
"echo-email-footer-default": "$2\n\nVolg de volgende koppeling om je e-mailvoorkeuren te wijzigen of om je uit te schrijven:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
diff --git a/Echo/i18n/nl.json b/Echo/i18n/nl.json
index fa4e024d..7f113018 100644
--- a/Echo/i18n/nl.json
+++ b/Echo/i18n/nl.json
@@ -16,135 +16,206 @@
"Sjoerddebruin",
"Mar(c)",
"Esketti",
- "HanV"
+ "HanV",
+ "Valhallasw",
+ "Macofe",
+ "Mbch331",
+ "Dinosaur918",
+ "Catrope",
+ "MrLeopold",
+ "Mainframe98"
]
},
- "echo-desc": "Meldingensysteem",
+ "echo-desc": "Systeem voor het informeren van gebruikers over evenementen en berichten",
"prefs-echo": "Meldingen",
"prefs-emailsettings": "E-mailinstellingen",
"prefs-displaynotifications": "Weergaveopties",
"prefs-echosubscriptions": "Informeer mij over deze gebeurtenissen",
+ "prefs-echocrosswiki": "Meldingen van andere wiki's",
"prefs-newmessageindicator": "Melding nieuwe berichten",
- "echo-pref-send-me": "Wanneer verzenden:",
+ "prefs-blocknotificationslist": "Genegeerde gebruikers",
+ "echo-pref-send-me": "Stuur mij:",
"echo-pref-send-to": "Verzenden naar:",
"echo-pref-email-format": "E-mailopmaak:",
"echo-pref-web": "Web",
"echo-pref-email": "E-mail",
- "echo-pref-email-frequency-never": "U geen meldingen via e-mail sturen",
+ "echo-pref-email-frequency-never": "Stuur mij geen meldingen per e-mail",
"echo-pref-email-frequency-immediately": "Individuele meldingen wanneer ze binnenkomen",
"echo-pref-email-frequency-daily": "Een dagelijkse samenvatting van meldingen",
"echo-pref-email-frequency-weekly": "Een wekelijkse samenvatting van meldingen",
"echo-pref-email-format-html": "HTML",
- "echo-pref-email-format-plain-text": "Platte tekst",
+ "echo-pref-email-format-plain-text": "Tekst zonder opmaak",
+ "echo-pref-cross-wiki-notifications": "Meldingen van andere wiki's weergeven",
+ "echo-pref-notifications-blacklist": "Toon geen meldingen van deze gebruikers. ([[mw:Help:Notifications#mute|Meer lezen]])",
"echo-pref-new-message-indicator": "Overlegpaginaberichtenindicator in mijn werkbalk weergeven",
+ "echo-pref-beta-feature-cross-wiki-message": "Uitgebreide meldingen",
+ "echo-pref-beta-feature-cross-wiki-description": "Bekijk en organiseer uw meldingen efficiënter. U ziet ook meldingen over andere wiki's. (Om meldingen van andere wiki's te ontvangen op een gegeven wiki, moet u de beta-functie op de desbetreffende wiki aanzetten.)",
"echo-learn-more": "Meer lezen",
- "echo-new-messages": "U heeft nieuwe berichten",
- "echo-category-title-edit-user-talk": "Bericht{{PLURAL:$1||en}} op mijn overlegpagina",
+ "echo-log": "Openbaar logboek",
+ "echo-new-messages": "U hebt nieuwe berichten",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|Bericht|Berichten}} op mijn overlegpagina",
"echo-category-title-article-linked": "Paginakoppeling{{PLURAL:$1||en}}",
"echo-category-title-reverted": "Bewerking{{PLURAL:$1||en}} teruggedraaid",
"echo-category-title-mention": "{{PLURAL:$1|Genoemd}}",
+ "echo-category-title-mention-failure": "Mislukte vermelding{{PLURAL:$1||en}}",
+ "echo-category-title-mention-success": "Succesvolle vermelding{{PLURAL:$1||en}}",
"echo-category-title-other": "{{PLURAL:$1|Overige}}",
"echo-category-title-system": "{{PLURAL:$1|Systeem}}",
- "echo-category-title-user-rights": "Gebruikersrechtenwijziging{{PLURAL:$1||en}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Gebruikersrechtenwijziging|Gebruikersrechtenwijzigingen}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-mail van een andere gebruiker|E-mails van andere gebruikers}}",
+ "echo-category-title-article-reminder": "Pagina {{PLURAL:$1|herinnering|herinneringen}}",
"echo-pref-tooltip-edit-user-talk": "Informeer mij wanneer iemand een bericht of antwoord op mijn overlegpagina plaatst.",
- "echo-pref-tooltip-article-linked": "Informeer mij wanneer iemand in een artikel een link aanbrengt naar een pagina die ik heb aangemaakt.",
+ "echo-pref-tooltip-article-linked": "Informeer mij wanneer iemand een koppeling aanbrengt naar een pagina die ik heb aangemaakt.",
"echo-pref-tooltip-reverted": "Informeer mij wanneer iemand een bewerking van mij terugdraait met behulp van \"ongedaan maken\" of \"terugdraaien\".",
"echo-pref-tooltip-mention": "Informeer mij wanneer iemand een koppeling naar mijn gebruikerspagina plaatst.",
+ "echo-pref-tooltip-mention-failure": "Houd me op de hoogte wanneer ik iemand niet kon vermelden.",
+ "echo-pref-tooltip-mention-success": "Houd me op de hoogte wanneer ik iemand vermeld.",
"echo-pref-tooltip-user-rights": "Informeer mij wanneer iemand mijn gebruikersrechten wijzigt.",
- "echo-no-agent": "[Niemand]",
- "echo-no-title": "[Geen pagina]",
+ "echo-pref-tooltip-emailuser": "Informeer mij wanneer iemand mij een e-mail stuurt.",
+ "echo-pref-tooltip-article-reminder": "Herinner me aan deze pagina wanneer ik er om vraag.",
"echo-error-no-formatter": "Er is geen opmaak ingesteld voor deze melding.",
"notifications": "Meldingen",
- "tooltip-pt-notifications-alert": "{{GENDER:|Uw}} waarschuwingen",
- "tooltip-pt-notifications-message": "{{GENDER:|Uw}} berichten",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Uw}} meldingen",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Uw}} notificaties",
+ "echo-displaynotificationsconfiguration": "Toon meldingsconfiguratie",
+ "echo-displaynotificationsconfiguration-summary": "Dit overzicht geeft aan hoe meldingen zijn geconfigureerd op deze wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Meldingen per categorie",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Hoe types gesorteerd zijn",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "In welke sectie elk type geplaatst wordt",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Toegestane meldingsmethoden",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Welke meldingsmethoden ondersteund worden per categorie",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Welke meldingsmethoden ondersteund worden per type; alleen van toepassing op meldingstypes in categorieën die niet zichtbaar zijn in het voorkeurenscherm.",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Standaard ingeschakeld",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Bestaande gebruikers",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nieuwe gebruikers",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Verplichte meldingsmethodes",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Welke meldingsmethodes verplicht zijn (niet kunnen worden uitgeschakeld) per categorie",
"echo-specialpage": "Meldingen",
- "echo-anon": "[$1 Maak een gebruiker aan] of [$2 meld u aan] als u meldingen wilt ontvangen.",
+ "echo-specialpage-section-markread": "Markeer groep als gelezen",
+ "echo-specialpage-markasread": "Notificatie: Markeer als gelezen",
+ "echo-specialpage-markasread-invalid-id": "Ongeldige gebeurtenis-ID",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|melding|meldingen}}",
+ "echo-specialpage-pagefilters-title": "Recente activiteit",
+ "echo-specialpage-pagefilters-subtitle": "Pagina's met ongelezen meldingen",
+ "notificationsmarkread-legend": "Markeer notificatie als gelezen",
+ "echo-anon": "[$1 Maak een account aan] of [$2 meld u aan] als u meldingen wilt ontvangen.",
"echo-none": "U hebt geen meldingen.",
"echo-more-info": "Meer info",
"echo-feedback": "Terugkoppeling",
+ "echo-popup-footer-special-page-invitation": "<strong>Probeer de herontworpen meldingenpagina.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Een compleet nieuw uiterlijk en nieuwe functies.",
+ "echo-api-failure": "Kan meldingen niet ophalen.",
+ "echo-api-failure-cross-wiki": "Toegang tot het externe domein is geweigerd.",
+ "echo-notification-placeholder": "Er zijn geen meldingen.",
+ "echo-notification-placeholder-filters": "Er zijn geen meldingen binnen deze criteria.",
+ "echo-notification-loginrequired": "U moet zich aanmelden om uw meldingen te bekijken.",
+ "echo-notification-popup-loginrequired": "Meld u aan om uw notificaties te weergeven.",
+ "echo-notification-markasread": "Als gelezen markeren",
+ "echo-notification-markasunread": "Als ongelezen markeren",
+ "echo-notification-markasread-tooltip": "Als gelezen markeren",
+ "echo-notification-more-options-tooltip": "Meer opties",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Stop}} met het volgen van nieuwe activiteit op \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|U}} volgt de pagina \"$1\" niet meer",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|U}} kunt [$2 deze pagina] op elk moment volgen.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Volg}} nieuwe gebeurtenissen op \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|U}} volgt nu de pagina \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|U}} kunt op elk moment stoppen met het volgen van [$2 deze pagina].",
+ "notification-link-text-expand-all": "Uitvouwen",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 melding|$1 meldingen}} weergeven",
+ "notification-link-text-expand-notice-count": "Toon {{PLURAL:$1|$1 notificatie|$1 notificaties}}",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 melding|$1 meldingen}} weergeven",
+ "notification-link-text-collapse-all": "Samenvouwen",
"notification-link-text-view-message": "Bericht bekijken",
"notification-link-text-view-mention": "Vermelding bekijken",
- "notification-link-text-view-changes": "Wijzigingen bekijken",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Toon vermelding|Toon vermeldingen}}",
+ "notification-link-text-view-changes": "Wijzigingen {{GENDER:$1|bekijken}}",
"notification-link-text-view-page": "Pagina bekijken",
+ "notification-header-edit-user-talk": "$1 heeft een bericht {{GENDER:$2|achtergelaten}} op <strong>{{GENDER:$3|uw}} overlegpagina</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|heeft}} een bericht op <strong>{{GENDER:$3|uw}} overlegpagina</strong> achtergelaten onder \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "Er is een koppeling gemaakt van <strong>$4</strong> naar <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Koppeling van <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Er zijn koppelingen gemaakt {{PLURAL:$5|één andere pagina|$5 andere pagina's|100=99+ andere pagina's}} naar <strong>$3</strong>.",
+ "notification-header-article-reminder": "Een pagina waarvoor {{GENDER:$2|u}} hebt verzocht te worden herinnerd is op <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Alle links naar deze pagina",
+ "notification-header-mention-other": "$1 heeft {{GENDER:$3|u}} {{GENDER:$2|genoemd}} op <strong>$4</strong> onder \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 heeft {{GENDER:$3|u}} {{GENDER:$2|genoemd}} op <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 heeft {{GENDER:$3|u}} {{GENDER:$2|genoemd}} op de <strong>overlegpagina {{GENDER:$5|van}} $4</strong> onder \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 heeft {{GENDER:$3|u}} {{GENDER:$2|genoemd}} op de <strong>overlegpagina {{GENDER:$5|van}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 heeft {{GENDER:$3|u}} {{GENDER:$2|genoemd}} op <strong>{{GENDER:$2|zijn|haar|zijn/haar}} overlegpagina</strong> onder \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 heeft {{GENDER:$3|u}} {{GENDER:$2|genoemd}} op <strong>{{GENDER:$2|zijn|haar|zijn/haar}} overlegpagina</strong>.",
+ "notification-header-mention-article-talkpage": "$1 heeft {{GENDER:$3|u}} {{GENDER:$2|genoemd}} op de <strong>overlegpagina van $4</strong> onder \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 heeft {{GENDER:$3|u}} {{GENDER:$2|genoemd}} op de overlegpagina van <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Uw}} vermelding van <strong>$3</strong> werd niet verzonden, omdat de gebruiker niet gevonden werd.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Uw}} vermelding van <strong>$3</strong> werd niet verzonden, omdat de gebruiker anoniem is.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|U}} probeerde meer dan $3 {{PLURAL:$3|gebruiker|gebruikers}} te vermelden. Alle vermeldingen boven de limiet zijn niet verzonden.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Een vermelding|$3 vermeldingen}} die {{GENDER:$2|u hebt gemaakt}} op de <strong>$4</strong> overlegpagina {{PLURAL:$3|kon}} niet worden verzonden.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Gebruikersnaam bestaat niet:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IPs kan niet worden genoemd:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Uw}} vermelding van <strong>$3</strong> is verzonden.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Een vermelding|$3 vermeldingen}} die {{GENDER:$2|u maakte}} op de overlegpagina van <strong>$4</strong> {{PLURAL:$3|zijn}} verzonden.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|U noemde}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Een melding|$3 meldingen}} over vermeldingen die {{GENDER:$2|u hebt gemaakt}} op de <strong>$4</strong> overlegpagina: {{PLURAL:$5|$5 niet verstuurd}}, {{PLURAL:$6|verstuurd}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Uw}} gebruikersrechten zijn {{GENDER:$1|veranderd}}. U bent lid van $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Uw}} gebruikersrechten zijn {{GENDER:$1|veranderd}}. U bent niet langer lid meer van $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Uw}} gebruikersrechten zijn {{GENDER:$1|veranderd}}. U bent nu lid van $2 en niet langer meer lid van $4.",
+ "notification-header-user-rights-expiry-change": "De verlooptijd van {{GENDER:$4|uw}} lidmaatschap in de volgende {{PLURAL:$3|groep|groepen}} is {{GENDER:$1|gewijzigd}}: $2",
+ "notification-header-welcome": "{{GENDER:$2|Welkom}} op {{SITENAME}}, $1! We zijn blij dat {{GENDER:$2|u}} er bent.",
+ "notification-welcome-linktext": "Welkom",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|U}} hebt uw eerste bewerking gemaakt; dankuwel, en welkom!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|U}} hebt uw tiende bewerking gemaakt; dankuwel, en ga door!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|U}} hebt uw honderdste bewerking gemaakt; hartelijk bedankt!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|U}} hebt uw duizendste bewerking gemaakt; dank u voor uw geweldige bijdrage!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|U}} hebt uw tienduizendste bewerking gemaakt; heel erg bedankt!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|U}} hebt uw honderdduizendste bewerking gemaakt; dank u voor uw fantastische bijdrage!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|U}} hebt uw miljoenste bewerking gemaakt; dank u voor uw schitterende bijdrage!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Uw}} bewerking",
"notification-link-text-view-edit": "Bewerking bekijken",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|heeft een bericht geplaatst}} op uw [[User talk:$2#$3|overlegpagina]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|heeft}} een bericht achtergelaten op uw overlegpagina in het onderwerp \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|heeft een bericht geplaatst}} op uw [[User talk:$2#$3|overlegpagina]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|heeft}} een bericht achtergelaten op uw overlegpagina onder het kopje \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] is {{GENDER:$1|gekoppeld}} vanaf [[:$3]]. [[Special:WhatLinksHere/$2|Alle koppelingen naar deze pagina bekijken]].",
- "notification-page-linked-flyout": "[[:$2]] is {{GENDER:$1|gekoppeld}} vanaf [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|heeft gereageerd}} op \"[[$3|$2]]\" op de overlegpagina \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|heeft}} een nieuw onderwerp \"$2\" geplaatst op [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|heeft}} u een bericht gezonden: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|heeft gereageerd}} op \"[[$3#$2|$2]]\" op uw overlegpagina",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|heeft}} u genoemd op de overlegpagina van $5 onder \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|heeft}} u genoemd op de overlegpagina van $5 onder \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] heeft u {{GENDER:$1|genoemd}} op de [[:$3|overlegpagina van $2]].",
- "notification-mention-nosection-flyout": "$1 heeft u {{GENDER:$1|genoemd}} op de [[:$3|overlegpagina van $2]].",
- "notification-user-rights": "[[Special:Log/rights/$1|Uw gebruikersrechten]] zijn {{GENDER:$1|gewijzigd}} door [[User:$1|$1]]. $2. [[Special:ListGroupRights|Meer informatie]]",
- "notification-user-rights-flyout": "Uw gebruikersrechten zijn {{GENDER:$1|gewijzigd}} door $1. $2. [[Special:ListGroupRights|Meer informatie]]",
- "notification-user-rights-add": "U bent nu lid van deze groep{{PLURAL:$2||en}}: $1",
- "notification-user-rights-remove": "U bent niet langer lid van deze groep{{PLURAL:$2||en}}: $1",
- "notification-new-user": "Welkom op {{SITENAME}}, $1! We zijn blij dat u er bent.",
- "notification-reverted2": "Uw {{PLURAL:$4|bewerking op [[:$2]] is|bewerkingen op [[:$2]] zijn}} {{GENDER:$1|teruggedraaid}} door [[User:$1|$1]]: $3",
- "notification-reverted-flyout2": "Uw {{PLURAL:$4|bewerking op $2 is|bewerkingen op $2 zijn}} {{GENDER:$1|teruggedraaid}} door $1 $3",
+ "notification-link-article-reminder": "Pagina bekijken",
+ "notification-header-reverted": "Uw {{PLURAL:$4|bewerking op <strong>$3</strong> is|bewerkingen op <strong>$3</strong> zijn}} {{GENDER:$2|teruggedraaid}}.",
+ "notification-header-emailuser": "$1 heeft u een e-mail {{GENDER:$2|gestuurd}}.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|heeft}} een bericht voor u achtergelaten op {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|heeft}} een bericht geplaatst op uw overlegpagina.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|heeft}} een bericht achtergelaten op uw overlegpagina onder \"$2\".",
"notification-page-linked-email-subject": "Er is een verwijzing gemaakt op {{SITENAME}} naar een pagina die u hebt gemaakt",
- "notification-page-linked-email-batch-body": "$2 is {{GENDER:$1|gekoppeld}} vanaf $3",
"notification-reverted-email-subject2": "Uw {{PLURAL:$3|bewerking op {{SITENAME}} is|bewerkingen op {{SITENAME}} zijn}} {{GENDER:$1|teruggedraaid}}",
- "notification-reverted-email-batch-body2": "Uw {{PLURAL:$3|bewerking op $2 is|bewerkingen op $2 zijn}} {{GENDER:$1|teruggedraaid}} door $1",
- "notification-mention-email-subject": "$1 {{GENDER:$1|heeft}} u genoemd op {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|heeft}} u genoemd op de overlegpagina van $4 onder \"$3\"",
- "notification-mention-nosection-email-batch-body": "$1 heeft u {{GENDER:$1|genoemd}} op de overlegpagina van $2.",
+ "notification-mention-email-subject": "$1 heeft {{GENDER:$2|u}} {{GENDER:$1|genoemd}} op {{SITENAME}}",
"notification-user-rights-email-subject": "Uw gebruikersrechten op {{SITENAME}} zijn gewijzigd",
- "notification-user-rights-email-batch-body": "Uw gebruikersrechten zijn {{GENDER:$1|gewijzigd}} door $1. $2",
- "echo-email-subject-default": "Nieuwe melding op {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1u}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mnd}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1jr}}",
+ "notification-timestamp-today": "Vandaag",
+ "notification-timestamp-yesterday": "Gisteren",
+ "notification-inbox-filter-read": "Gelezen",
+ "notification-inbox-filter-unread": "Ongelezen",
+ "notification-inbox-filter-all": "Alle",
"echo-email-body-default": "U hebt een nieuwe melding op {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "U hebt een nieuwe melding",
- "echo-email-footer-default": "$2\n\nVolg de volgende koppeling om te bepalen welke e-mails wij u zenden:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Ga naar <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">uw voorkeuren</a> om te bepalen welke e-mails wij u zenden.<br />\n$1",
+ "echo-email-footer-default-html": "Open <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">uw voorkeuren</a> om te bepalen welke e-mails wij u versturen.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nOm te bepalen welke e-mails wij u zenden, controleert u uw voorkeuren:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Controleer {{GENDER:$1|uw}} voorkeuren om te bepalen welke e-mails wij {{GENDER:$1|u}} sturen:",
+ "echo-email-html-footer-preference-link-text": "controleer {{GENDER:$1|uw}} voorkeuren",
+ "echo-email-html-footer-with-link": "Om te bepalen welke e-mails we {{GENDER:$2|u}} sturen, $1.",
"echo-notification-alert": "{{PLURAL:$1|Melding ($1)|Meldingen ($1)|100=Meldingen (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Bericht ($1)|Berichten ($1)|100=Berichten (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Melding ($1)|Meldingen ($1)|100=Meldingen (99+)}}",
"echo-notification-alert-text-only": "Meldingen",
- "echo-notification-message-text-only": "Berichten",
+ "echo-notification-notice-text-only": "Notificaties",
"echo-overlay-link": "Alle meldingen",
"echo-overlay-title": "<b>Meldingen</b>",
- "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Meldingen}}</b> ($1 van $2 ongelezen)",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Melding|Meldingen}}</b> ($1 van $2 ongelezen)",
"echo-mark-all-as-read": "Alles als gelezen markeren",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|melding|meldingen}} gemarkeerd als gelezen",
+ "echo-mark-wiki-as-read": "Markeer alles als gelezen in de geselecteerde wiki: $1",
"echo-date-today": "Vandaag",
"echo-date-yesterday": "Gisteren",
"echo-load-more-error": "Er is een fout opgetreden tijdens het ophalen van meer resultaten.",
- "notification-edit-talk-page-bundle": "$1 en $3 {{PLURAL:$4|andere|anderen}} hebben een bericht {{GENDER:$1|geplaatst}} op uw [[User talk:$2|overlegpagina]].",
- "notification-page-linked-bundle": "$2 is {{GENDER:$1|gekoppeld}} vanaf $3 en $4 andere pagina{{PLURAL:$5||'s}}. [[Special:WhatLinksHere/$2|Alle koppelingen naar deze pagina bekijken]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 and $2 {{PLURAL:$3|andere gebruiker|andere gebruikers}} {{GENDER:$1|hebben}} een bericht op uw overlegpagina geplaatst",
- "notification-page-linked-email-batch-bundle-body": "$2 is {{GENDER:$1|gekoppeld}} vanaf $3 en $4 andere pagina{{PLURAL:$5||'s}}",
- "echo-email-batch-subject-daily": "U heeft vandaag {{PLURAL:$2|0=geen nieuwe meldingen|een nieuwe melding|nieuwe meldingen}} op {{SITENAME}}",
- "echo-email-batch-subject-weekly": "U heeft deze week {{PLURAL:$2|0=geen nieuwe meldingen|een nieuwe melding|nieuwe meldingen}} op {{SITENAME}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|één nieuw bericht|$1 nieuwe berichten|100=99+ nieuwe berichten}} op <strong>{{GENDER:$3|uw}} overlegpagina</strong>.",
+ "echo-email-batch-subject-daily": "U heeft vandaag {{PLURAL:$2|een nieuwe melding|nieuwe meldingen}} op {{SITENAME}} ontvangen",
+ "echo-email-batch-subject-weekly": "U heeft deze week {{PLURAL:$2|een nieuwe melding|nieuwe meldingen}} op {{SITENAME}} ontvangen",
"echo-email-batch-body-intro-daily": "Hallo $1,\nHier is een samenvatting voor u van de activiteiten van vandaag op {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Hallo $1,\nHier is een samenvatting voor u van de activiteiten van deze week op {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "Alle mededelingen bekijken",
- "echo-rev-deleted-text-view": "Deze paginaversie is onderdrukt.",
- "apihelp-echomarkread-description": "Mark meldingen lezen voor de huidige gebruiker.",
- "apihelp-echomarkread-param-list": "Een lijst van de kennisgeving Id ' s te markeren als gelezen.",
- "apihelp-echomarkread-param-all": "Als dit is ingesteld, markeert alle van een gebruiker van de meldingen lezen.",
- "apihelp-echomarkread-param-sections": "Een lijst van de secties te markeren als gelezen.",
- "apihelp-echomarkread-example-1": "Notificatie 8 als gelezen markeren",
- "apihelp-echomarkread-example-2": "Markeer alle meldingen als gelezen",
- "apihelp-echomarkseen-description": "Mark meldingen gezien voor de huidige gebruiker.",
- "apihelp-echomarkseen-example-1": "Mark meldingen gezien",
- "apihelp-query+notifications-description": "Ontvang meldingen te wachten voor de huidige gebruiker.",
- "apihelp-query+notifications-param-prop": "Details op aanvraag.",
- "apihelp-query+notifications-param-sections": "De kennisgeving van secties query.",
- "apihelp-query+notifications-param-groupbysection": "Of de groep in het resultaat door de sectie. Elke sectie wordt opgehaald apart instellen.",
- "apihelp-query+notifications-param-format": "Indien opgegeven, meldingen zullen worden geretourneerd op deze manier geformatteerd.",
- "apihelp-query+notifications-param-limit": "Het maximum aantal meldingen terug te keren.",
- "apihelp-query+notifications-param-index": "Indien opgegeven, een lijst van de kennisgeving Id ' s, in volgorde, zal worden teruggegeven.",
- "apihelp-query+notifications-param-alertcontinue": "Wanneer er meer alert resultaten beschikbaar zijn, gebruik deze om verder te gaan.",
- "apihelp-query+notifications-param-alertunreadfirst": "Of het nu om de ongelezen berichten eerst.",
- "apihelp-query+notifications-param-messagecontinue": "Wanneer meer bericht resultaten beschikbaar zijn, gebruik deze om verder te gaan.",
- "apihelp-query+notifications-param-messageunreadfirst": "Of ongelezen meldingen eerste.",
- "apihelp-query+notifications-example-1": "Lijst meldingen",
- "apihelp-query+notifications-example-2": "Lijst van meldingen, gegroepeerd per paragraaf, met graven"
+ "notification-header-foreign-alert": "Meer meldingen van {{PLURAL:$5|een andere wiki|$5 andere wiki's}}",
+ "notification-header-foreign-notice": "Meer notificaties van {{PLURAL:$5|een andere wiki|$5 andere wiki's}}",
+ "notification-header-foreign-all": "Meer meldingen van {{PLURAL:$5|een andere wiki|$5 andere wiki's}}"
}
diff --git a/Echo/i18n/nn.json b/Echo/i18n/nn.json
index ffaf9dc3..e8339e50 100644
--- a/Echo/i18n/nn.json
+++ b/Echo/i18n/nn.json
@@ -2,11 +2,12 @@
"@metadata": {
"authors": [
"Amire80",
- "Njardarlogar"
+ "Njardarlogar",
+ "Jon Harald Søby"
]
},
"echo-desc": "Meldingssystem",
- "prefs-echo": "Meldingar",
+ "prefs-echo": "Meldingar og varsel",
"prefs-emailsettings": "E-postval",
"prefs-displaynotifications": "Visingsval",
"prefs-echosubscriptions": "Meld meg om desse hendingane",
@@ -18,8 +19,8 @@
"echo-pref-email": "E-post",
"echo-pref-email-frequency-never": "Ikkje send meg e-postmeldingar",
"echo-pref-email-frequency-immediately": "Einkskilde meldingar etter kvart som dei kjem inn",
- "echo-pref-email-frequency-daily": "Eit dagleg samandrag av meldingar",
- "echo-pref-email-frequency-weekly": "Eit vekentleg samandrag av meldingar",
+ "echo-pref-email-frequency-daily": "Eit dagleg samandrag av meldingar og varsel",
+ "echo-pref-email-frequency-weekly": "Eit vekentleg samandrag av meldingar og varsel",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Rein tekst",
"echo-pref-new-message-indicator": "Vis indikatoren for diskusjonssidemeldingar på verktøylina mi",
@@ -32,80 +33,85 @@
"echo-category-title-other": "{{PLURAL:$1|Anna}}",
"echo-category-title-system": "{{PLURAL:$1|System}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Endring}} av brukarrettar",
+ "echo-category-title-emailuser": "Epost frå {{PLURAL:$1|annan brukar|andre brukarar}}",
"echo-pref-tooltip-edit-user-talk": "Meld meg når nokon skriv ei melding eller svarar på diskusjonssida mi.",
- "echo-pref-tooltip-article-linked": "Meld meg når nokon lenkjar frå ein artikkel til ei side eg har oppretta.",
+ "echo-pref-tooltip-article-linked": "Meld meg når nokon lenkjar til ei side eg har oppretta frå ei anna side.",
"echo-pref-tooltip-reverted": "Meld meg når nokon fjernar ei endring eg gjorde ved bruk av angre- eller attenderullingsverktøyet.",
"echo-pref-tooltip-mention": "Meld meg når nokon lenkjar til brukarsida mi.",
"echo-pref-tooltip-user-rights": "Meld meg når nokon endrar brukarrettane mine.",
- "echo-no-agent": "[Ingen]",
- "echo-no-title": "[Inga side]",
"echo-error-no-formatter": "Inga formatering definert for meldinga.",
- "notifications": "Meldingar",
+ "notifications": "Meldingar og varsel",
"tooltip-pt-notifications-alert": "Varsla {{GENDER:|dine}}",
- "tooltip-pt-notifications-message": "Meldingane {{GENDER:|dine}}",
- "echo-specialpage": "Merksamgjeringar",
- "echo-anon": "For å få meldingar, [$1 opprett ein konto] eller [$2 logg inn].",
- "echo-none": "Du har ingen merksamgjeringar.",
+ "tooltip-pt-notifications-notice": "Notisane {{GENDER:|dine}}",
+ "echo-specialpage": "Meldingar og varsel",
+ "echo-specialpage-section-markread": "Merk gruppa som lesen",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|éin notis eller eitt varsel|$1 notisar og varsel}}",
+ "echo-specialpage-pagefilters-title": "Nyleg aktivitet",
+ "echo-specialpage-pagefilters-subtitle": "Sider med ulesne notisar eller varsel",
+ "echo-anon": "For å få meldingar og varsel, [$1 opprett ein konto] eller [$2 logg inn].",
+ "echo-none": "Du har ingen meldingar eller varsel.",
"echo-more-info": "Meir info",
"echo-feedback": "Attendemelding",
+ "echo-notification-placeholder": "Det er ingen meldingar eller varsel.",
+ "echo-notification-placeholder-filters": "Ingen varsel eller notisar passar med desse kriteria.",
+ "echo-notification-markasread": "Merk som lese(n)",
+ "echo-notification-markasunread": "Merk som ulese(n)",
"notification-link-text-view-message": "Sjå melding",
"notification-link-text-view-mention": "Sjå omtale",
- "notification-link-text-view-changes": "Sjå endringar",
+ "notification-link-text-view-changes": "{{GENDER:$1|Sjå}} endringar",
"notification-link-text-view-page": "Sjå side",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|la att}} ei melding på <strong>diskusjonssida</strong> {{GENDER:$3|di}}.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|la att}} ei melding på <strong>diskusjonssida</strong> {{GENDER:$3|di}} under «<strong>$4</strong>».",
+ "notification-header-page-linked": "Ei lenkje vart oppretta frå <strong>$4</strong> til <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Lenkja frå <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Det vart oppretta lenkjer frå {{PLURAL:$5||$5 sider|100=meir enn 99 sider}} til <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Alle lenkjer til sida",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Du nemnde}}:</strong> $3",
+ "notification-welcome-linktext": "Velkomen",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Du}} gjorde nettopp di fyrste endring; takk og velkomen!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Du}} gjorde nettopp di tiande endring; takk, fortsett slik!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Du}} gjorde nettopp di hundrede endring; tusen takk!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Du gjorde nettopp di tusande endring; takk for at du er ein flott bidragsytar!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Du}} gjorde nettopp di titusende endring; ti tusen takk!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Du}} gjorde nettopp di hundretusende endring; takk for ein fantastisk innsats!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Du}} gjorde nettopp di endring nr. éin million; takk for ditt eneståande bidrag!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Di}} endring",
"notification-link-text-view-edit": "Sjå endring",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|la att}} ei melding på [[User talk:$2#$3|diskusjonssida]] di.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|la att}} ei melding på diskusjonssida di under bolken «[[User talk:$2#$3|$4]]».",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|la att}} ei melding på [[User talk:$2#$3|diskusjonssida]] di.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|la att}} ei melding på diskusjonssida di under bolken «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "[[:$2]] vart {{GENDER:$1|lenkja}} til frå [[:$3]]. [[Special:WhatLinksHere/$2|Sjå alle lenkjene til sida]].",
- "notification-page-linked-flyout": "[[:$2]] vart {{GENDER:$1|lenkja}} til frå [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|kommenterte}} emnet «[[$3|$2]]» på diskusjonssida «$4».",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|la inn}} det nye emnet «$2» på [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|sende}} deg ei melding: «[[$3#$2|$2]]».",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|kommenterte}} emnet «[[$3#$2|$2]]» på diskusjonssida di.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|nemnde}} deg på diskusjonssida til $5 under bolken «[[:$3#$2|$4]]».",
- "notification-mention-flyout": "$1 {{GENDER:$1|nemnde}} deg på diskusjonssida til $5 under bolken «[[:$3#$2|$4]]».",
- "notification-user-rights": "Brukarrettane dine [[Special:Log/rights/$1|vart {{GENDER:$1|endra}}]] av [[User:$1|$1]]. $2. [[Special:ListGroupRights|Lær meir]]",
- "notification-user-rights-flyout": "Brukarrettane dine vart {{GENDER:$1|endra}} av $1. $2. [[Special:ListGroupRights|Lær meir]]",
- "notification-user-rights-add": "Du er no ein medlem av {{PLURAL:$2|denne gruppa|desse gruppene}}: $1",
- "notification-user-rights-remove": "Du er ikkje lenger medlem av {{PLURAL:$2|denne gruppa|desse gruppene}}: $1",
- "notification-new-user": "Velkomen til {{SITENAME}}, $1! Me er glade for at du er her.",
- "notification-reverted2": "{{PLURAL:$4|Endringa di|Endringane dine}} på [[:$2]] vart {{GENDER:$1|fjerna}} av [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Endringa di|Endringane dine}} på $2 vart {{GENDER:$1|fjerna}} av $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Endringa di|Endringane dine}} på <strong>$3</strong> vart {{GENDER:$2|fjerna}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|sendte}} deg ein e-post",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|la att}} ei melding til deg på {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|la att}} ei melding på diskusjonssida di.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|la att}} ei melding på diskusjonssida di under «$2».",
"notification-page-linked-email-subject": "Ei side du oppretta vart lenkja til på {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 vart {{GENDER:$1|lenkja til}} frå $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Endringa di|Endringane dine}} vart {{GENDER:$1|fjerna}} på {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Endringa di|Endringane dine}} på $2 vart {{GENDER:$1|fjerna}} av $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|nemnde}} deg på {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|nemnde}} deg på diskusjonssida til $4 under bolken «$3».",
- "notification-user-rights-email-subject": "Brukarrettane dine har endra seg på {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Brukarrettane dine vart {{GENDER:$1|endra}} av $1. $2.",
- "echo-email-subject-default": "Ny melding på {{SITENAME}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|nemnde}} {{GENDER:$2|deg}} på {{SITENAME}}",
+ "notification-user-rights-email-subject": "Brukarrettane dine på {{SITENAME}} har vorte endra",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 sek.}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min.}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 t.}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 d.}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mnd.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 år}}",
+ "notification-timestamp-today": "I dag",
+ "notification-timestamp-yesterday": "I går",
+ "notification-inbox-filter-read": "Lesne",
+ "notification-inbox-filter-unread": "Ulesne",
+ "notification-inbox-filter-all": "Alle",
"echo-email-body-default": "Du har ei ny melding på {{SITENAME}}: $1",
- "echo-email-batch-body-default": "Du har ei ny melding.",
"echo-email-footer-default": "$2\n\nFor å styra kva for e-postar me sender til deg, sjå til innstillingane dine:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "For å styra kva for e-postar me sender til deg, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">sjå til innstillingane dine</a>.<br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|Varsel ($1)|100=Varsel (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notis ($1)|Notisar ($1)|100=Notisar (99+)}}",
"echo-notification-alert-text-only": "Varsel",
- "echo-notification-message-text-only": "Meldingar",
- "echo-overlay-link": "Alle merksamgjeringar",
- "echo-overlay-title": "<b>Meldingar</b>",
+ "echo-notification-notice-text-only": "Notisar",
+ "echo-overlay-link": "Alle meldingar og varsel",
+ "echo-overlay-title": "<b>Meldingar og varsel</b>",
"echo-overlay-title-overflow": "<b>Meldingar</b> (viser $1 av $2 ulesne)",
"echo-mark-all-as-read": "Merk alle som lesne",
"echo-date-today": "I dag",
"echo-date-yesterday": "I går",
"echo-load-more-error": "Det oppstod ein feil under henting av fleire resultat.",
- "notification-edit-talk-page-bundle": "$1 og {{PLURAL:$4|ein annan|$3 andre}} {{GENDER:$1|la att}} ei melding til deg på [[User talk:$2|diskusjonssida]] di.",
- "notification-page-linked-bundle": "$2 vart {{GENDER:$1|lenkja til}} frå $3 og {{PLURAL:$5|ei anna side|$4 andre sider}}. [[Special:WhatLinksHere/$2|Sjå alle lenkjene til sida]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 og {{PLURAL:$3|ein annan|$2 andre}} {{GENDER:$1|la att}} ei melding på diskusjonssida di.",
- "notification-page-linked-email-batch-bundle-body": "$2 vart {{GENDER:$1|lenkja til}} frå $3 og {{PLURAL:$5|ei anna side|$4 andre sider}}.",
"echo-email-batch-subject-daily": "Du har {{PLURAL:$2|ei ny melding|nye meldingar}} på {{SITENAME}}",
"echo-email-batch-subject-weekly": "Du har {{PLURAL:$2|ei ny melding|nye meldingar}} på {{SITENAME}} denne veka",
"echo-email-batch-body-intro-daily": "Hei $1.\nHer er eit samandrag av aktiviteten i dag på {{SITENAME}} for deg.",
"echo-email-batch-body-intro-weekly": "Hei $1.\nHer er eit samandrag av aktiviteten denne veka på {{SITENAME}} for deg.",
- "echo-email-batch-link-text-view-all-notifications": "Sjå alle meldingane",
- "echo-rev-deleted-text-view": "Denne sideversjonen er vorten løynd."
+ "echo-email-batch-link-text-view-all-notifications": "Sjå alle meldingar og varsel"
}
diff --git a/Echo/i18n/oc.json b/Echo/i18n/oc.json
index 4723cb23..f720b093 100644
--- a/Echo/i18n/oc.json
+++ b/Echo/i18n/oc.json
@@ -1,10 +1,12 @@
{
"@metadata": {
"authors": [
- "Cedric31"
+ "Cedric31",
+ "Nicolas Eynaud",
+ "Vriullop"
]
},
- "echo-desc": "Sistèma de notificacions",
+ "echo-desc": "Sistèma per avertir los utilizaires dels eveniments e messatges",
"prefs-echo": "Notificacions",
"prefs-emailsettings": "Opcions del corrièr electronic",
"prefs-displaynotifications": "Opcions d'afichatge",
@@ -21,7 +23,7 @@
"echo-pref-email-frequency-weekly": "Un resumit setmanièr de las notificacions",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Tèxte brut",
- "echo-pref-notify-show-link": "Afichar las notificacions dins ma barra d'aisinas",
+ "echo-pref-cross-wiki-notifications": "Afichar las notificacions d’autres wikis",
"echo-pref-new-message-indicator": "Afichar l’indicador de messatge sus la pagina de discussion dins ma barra d’aisinas",
"echo-learn-more": "Ne saber mai",
"echo-new-messages": "Avètz de messatges novèls",
@@ -29,79 +31,98 @@
"echo-category-title-article-linked": "{{PLURAL:$1|Article ligat|Articles ligats}}",
"echo-category-title-reverted": "{{PLURAL:$1|Modificacion anullada|Modificacions anulladas}}",
"echo-category-title-mention": "{{PLURAL:$1|Mencion|Mencions}}",
+ "echo-category-title-mention-failure": "Fracàs {{PLURAL:$1|de la mencion|de las mencions}}",
+ "echo-category-title-mention-success": "Succès {{PLURAL:$1|de la mencion|de las mencions}}",
"echo-category-title-other": "{{PLURAL:$1|Autres}}",
"echo-category-title-system": "{{PLURAL:$1|Sistèma}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Modificacion de dreits utilizaire|Modificacions de dreits utilizaire}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Corrièr electronic d’un autre utilizaire|Corrièrs electronics d’autres utilizaires}}",
"echo-pref-tooltip-edit-user-talk": "M'avisar quand qualqu’un publica un messatge o respond sus ma pagina de discussion.",
- "echo-pref-tooltip-article-linked": "M'avisar quand qualqu’un fa referéncia a una pagina qu’ai creada a partir d’una pagina d’article.",
- "echo-pref-tooltip-reverted": "M'avisar quand qualqu’un anulla una modificacion qu’ai facha, en utilizant l’aisina anullacion o retorn arrièr",
+ "echo-pref-tooltip-article-linked": "M'avisar quand qualqu’un fa referéncia a una pagina qu’ai creada dempuèi una pagina d’article.",
+ "echo-pref-tooltip-reverted": "M'avisar quand qualqu’un anulla una modificacion qu’ai faita, en utilizant l’aisina anullacion o de revocacion.",
"echo-pref-tooltip-mention": "M'avisar quand qualqu’un fa referéncia a ma pagina d'utilizaire.",
- "echo-no-agent": "[Pas degun]",
- "echo-no-title": "[Pas cap de pagina]",
+ "echo-pref-tooltip-emailuser": "Me notificar quand qualqu’un me manda un corrièr electronic.",
"echo-error-no-formatter": "Cap de mesa en forma pas definida per la notificacion",
- "echo-error-preference": "Error : Impossible de definir la preferéncia d'utilizaire",
- "echo-error-token": "Error : Impossible de recuperar lo geton de l’utilizaire",
"notifications": "Notificacions",
- "tooltip-pt-notifications": "Vòstras notificacions",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Vòstras}} alèrtas",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Vòstras}} notificacions",
"echo-specialpage": "Notificacions",
+ "echo-specialpage-section-markread": "Marcar la seccion coma legida",
+ "echo-specialpage-markasread": "Notificacion : marcar coma legida",
+ "echo-specialpage-pagefilters-subtitle": "Paginas amb de notificacions pas legidas",
"echo-anon": "Per recebre de notificacions, [$1 creatz un compte] o [$2 connectatz-vos].",
"echo-none": "Avètz pas recebut cap de notificacion.",
"echo-more-info": "Mai d'informacion",
"echo-feedback": "Vejaires",
+ "echo-notification-placeholder": "I a pas cap de notificacion.",
+ "echo-notification-markasread": "Marcar coma legit",
+ "echo-notification-markasunread": "Marcar coma pas legit",
+ "echo-notification-markasread-tooltip": "Marcar coma legit",
+ "echo-notification-more-options-tooltip": "Mai d'opcions",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Podètz}} seguir [$2 aquesta pagina] a tot moment.",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Podètz}} arrestar de seguir [$2 aquesta pagina] a tot moment.",
"notification-link-text-view-message": "Afichar lo messatge",
"notification-link-text-view-mention": "Afichar la mencion",
- "notification-link-text-view-changes": "Afichar las modificacions",
+ "notification-link-text-view-changes": "{{GENDER:$1|Afichar}} las modificacions",
"notification-link-text-view-page": "Afichar la pagina",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|a daissat}} un messatge sus <strong>{{GENDER:$3|vòstra}} pagina de discussion</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|a daissat}} un messatge sus <strong>{{GENDER:$3|vòstra}} pagina de discussion</strong> dins la seccion « <strong>$4</strong> ».",
+ "notification-header-mention-other": "$1 {{GENDER:$2|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus <strong>$4</strong> dins « <strong>$5</strong> ».",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus la <strong>pagina de discussion {{GENDER:$5|de}} $4</strong> dins « <strong>$6</strong> ».",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus la <strong>pagina de discussion {{GENDER:$5|de}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus <strong>{{GENDER:$2|sa|sa|sa}} pagina de discussion</strong> dins « <strong>$4</strong> ».",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus <strong>sa pagina de discussion</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus la pagina de discussion de <strong>$4</strong> dins « <strong> $5</strong> ».",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus la pagina de discussion de <strong>$4</strong>.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Una mencion|$3 mencions}} {{GENDER:$2|qu'avètz faita}}{{PLURAL:$3||s}} sus la pagina de discussion de <strong>$4</strong> {{PLURAL:$3|a|an}} pas pogut èsser mandada{{PLURAL:$3||s}}.",
+ "notification-header-mention-success": "{{GENDER:$2|Vòstra}} mencion de <strong>$3</strong> es estada mandada.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Avètz mencionat}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Demest las notificacions|$3 notificacions}} qu'{{GENDER:$2|avètz faita}}{{PLURAL:$3||s}} sus la pagina de discussion <strong>$4</strong>, $5 {{PLURAL:$5|es pas estada mandada|son pas estadas mandadas}} e $6 {{PLURAL:$6|es estada mandada|son estadas mandadas}}.",
+ "notification-welcome-linktext": "Benvenguda",
"notification-link-text-view-edit": "Afichar la modificacion",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|a daissat}} un messatge sus vòstra [[User talk:$2#$3|pagina de discussion]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] a daissat un messatge sus vòstra pagina de discussion dins la [[User talk:$2#$3|seccion ''$4'']].",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|a daissat}} un messatge sus vòstra [[User talk:$2#$3|pagina de discussion]].",
- "notification-edit-talk-page-flyout-with-section": "$1 a daissat un messatge sus vòstra pagina de discussion dins la [[User talk:$2#$3|seccion ''$4'']].",
- "notification-page-linked": "[[:$2]] es estat {{GENDER:$1|referenciat}} dempuèi [[:$3]]. [[Special:WhatLinksHere/$2|Veire totes los ligams cap a aquesta pagina]].",
- "notification-page-linked-flyout": "[[:$2]] es estat {{GENDER:$1|referenciat}} dempuèi [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|a fach un comentari}} dins « [[$3|$2]] » sus la pagina de discussion « $4 »",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|a publicat}} un subjècte novèl \"$2\" sus [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] vos {{GENDER:$1|a mandat}} un messatge : \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|a fach un comentari}} dins ''[[$3#$2|$2]]'' sus vòstra pagina de discussion",
- "notification-mention": "[[User:$1|$1]] vos {{GENDER:$1|a mencionat|a mencionada}} sus la pagina de discussion de $5 dins la [[:$3#$2|seccion ''$4'']].",
- "notification-mention-flyout": "$1 vos {{GENDER:$1|a mencionat|a mencionada}} sus la pagina de discussion de $5 dins la [[:$3#$2|seccion ''$4'']].",
- "notification-user-rights": "Vòstres dreches d’utilizaire [[Special:Log/rights/$1|son estats {{GENDER:$1|modificats}}]] per [[User:$1|$1]]. $2. [[Special:ListGroupRights|Ne saber mai]]",
- "notification-user-rights-flyout": "Vòstres dreches d’utilizaire {{GENDER:$1|son estats modificats}} per $1. $2. [[Special:ListGroupRights|Ne saber mai]]",
- "notification-user-rights-add": "Ara sètz membre d'{{PLURAL:$2|aqueste grop|aquestes gropes}} : $1",
- "notification-user-rights-remove": "Sètz pas mai membre d'{{PLURAL:$2|aqueste grop|aquestes gropes}} : $1",
- "notification-new-user": "Benvenguda sus {{SITENAME}}, $1 ! Sèm uroses de vos veire aicí.",
- "notification-reverted2": "{{PLURAL:$4|Vòstra modificacion sus [[:$2]] es estada|Vòstras modificacions sus [[:$2]] son estadas}} {{GENDER:$1|anullada}}{{PLURAL:$4||s}} per [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Vòstra modificacion sus $2 es estada|Vòstras modificacions sus $2 son estadas}} {{GENDER:$1|anullada}}{{PLURAL:$4||s}} per $1 $3",
+ "notification-header-reverted": "{{PLURAL:$4|Vòstra modificacion sus <strong>$3</strong> es estada|Vòstras modificacions sus <strong>$3</strong> son estadas}} {{GENDER:$2|anullada}}{{PLURAL:$4||s}}",
+ "notification-header-emailuser": "$1 vos {{GENDER:$2|a mandat}} un corrièr electronic.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|a daissat}} un messatge sus vòstra pagina de discussion sus {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|a daissat}} un messatge sus vòstra pagina de discussion :",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 a daissat un messatge sus vòstra pagina de discussion dins ''$2''.",
- "notification-page-linked-email-subject": "Vòstra pagina es estada referenciada sus {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 es estat {{GENDER:$1|referenciat}} dempuèi $3",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 a daissat un messatge sus vòstra pagina de discussion dins « $2 ».",
+ "notification-page-linked-email-subject": "Un ligam cap a una pagina qu'avètz creada es estada inserida sus {{SITENAME}}",
"notification-reverted-email-subject2": "{{PLURAL:$3|Vòstra modificacion es estada anullada|Vòstras modificacions son estadas anulladas}} {{GENDER:$1|}} sus {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Vòstra modification sus $2 es estada anullada|Vòstras modificacions sus $2 son estadas anulladas}} {{GENDER:$1|}} per $1",
- "notification-mention-email-subject": "$1 vos {{GENDER:$1|a mencionat|a mencionada}} sus {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 vos {{GENDER:$1|a mencionat|a mencionada}} sus la pagina de discussion de $4 dins ''$3''.",
- "notification-user-rights-email-subject": "Vòstres dreches d’utilizaire son estats modificats sus {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Vòstres dreches d’utilizaire {{GENDER:$1|son estats modificats}} per $1. $2",
- "echo-email-subject-default": "Novèla notificacion sus {{SITENAME}}",
+ "notification-mention-email-subject": "$1 vos {{GENDER:$2|a mencionat|a mencionada}} sus {{SITENAME}}",
+ "notification-user-rights-email-subject": "Vòstres dreits d’utilizaire son estats modificats sus {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 j}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mes|$1 meses}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 an|$1 ans}}",
+ "notification-timestamp-today": "Uèi",
+ "notification-timestamp-yesterday": "Ièr",
+ "notification-inbox-filter-read": "Legidas",
+ "notification-inbox-filter-unread": "Pas legidas",
+ "notification-inbox-filter-all": "Totes",
"echo-email-body-default": "Avètz una novèla notificacion sus {{SITENAME}} :\n\n$1",
- "echo-email-batch-body-default": "Avètz una novèla notificacion",
- "echo-email-footer-default": "$2\n\nPer verificar quines corrièrs electronics vos mandam, anatz dins vòstras preferéncias :\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Per contrarotlar los corrièrs electronics que vos mandam, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">verificatz vòstras preferéncias</a><br />\n$1",
+ "echo-email-footer-default": "$2\n\nPer contrarotlar quines corrièrs electronics vos mandam, verificatz vòstras preferéncias :\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-html-footer-with-link": "Per contrarotlar quines corrièrs electronics {{GENDER:$2|vos}} mandam, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Alèrta ($1)|100=Alèrtas (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notificacions ($1)|100=Notificacions (100 e mai)}}",
+ "echo-notification-alert-text-only": "Alèrtas",
+ "echo-notification-notice-text-only": "Notificacions",
"echo-overlay-link": "Totas las notificacions",
"echo-overlay-title": "<b>Notificacions</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificacion|Notificacions}}</b> ($1 sus $2 {{PLURAL:$1|pas legida d'afichada|pas legidas d'afichadas}})",
"echo-mark-all-as-read": "Marcar tot coma legit",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notificacion marcada coma legida|notificacions marcadas coma legidas}}",
+ "echo-mark-wiki-as-read": "Marcar tot coma essent legit pels wiki seleccionats : $1",
"echo-date-today": "Uèi",
"echo-date-yesterday": "Ièr",
- "echo-load-more-error": "Una error s'es producha en analisant mai de resultats.",
- "notification-edit-talk-page-bundle": "$1 e $3 {{PLURAL:$4|autre|autres}} {{GENDER:$1|an daissat}} un messatge sus vòstra [[User talk:$2|pagina de discussion]].",
- "notification-page-linked-bundle": "$2 es estat {{GENDER:$1|referenciat}} dempuèi $3 e $4 {{PLURAL:$5|autra pagina|autras paginas}}. [[Special:WhatLinksHere/$2|Veire totes los ligams cap a aquesta pagina]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e $2 {{PLURAL:$3|autre|autres}} an {{GENDER:$1|daissat}} un messatge sus vòstra pagina de discussion.",
- "notification-page-linked-email-batch-bundle-body": "$2 a été {{GENDER:$1|ligat}} dempuèi $3 e $4 {{PLURAL:$5|autra pagina|autras paginas}}",
+ "echo-load-more-error": "Una error s'es produita en analisant mai de resultats.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Un novèl messatge|$1 novèls messatges|100=mai de 100 novèls messatges}} sur <strong>{{GENDER:$3|vòstra}} pagina de discussion</strong> .",
"echo-email-batch-subject-daily": "Avètz {{PLURAL:$2|una novèla notificacion|de novèlas notificacions}} uèi sus {{SITENAME}}",
"echo-email-batch-subject-weekly": "Avètz {{PLURAL:$2|una novèla notificacion|de novèlas notificacions}} sus {{SITENAME}} aquesta setmana",
"echo-email-batch-body-intro-daily": "Bonjorn $1,\nAquí per vos un resumit de l’activitat d’uèi sus {{SITENAME}}",
"echo-email-batch-body-intro-weekly": "Bonjorn $1,\nAquí per vos un resumit de l’activitat de la setmana sus {{SITENAME}}",
"echo-email-batch-link-text-view-all-notifications": "Veire totas las notificacions",
- "echo-rev-deleted-text-view": "Aquesta revision de pagina es estada suprimida"
+ "notification-header-foreign-alert": "Mai d’alèrtas {{PLURAL:$5|d’un autre wiki|de $5 autres wikis}}",
+ "notification-header-foreign-notice": "Mai de notificacions {{PLURAL:$5|d’un autre wiki|de $5 autres wikis}}",
+ "notification-header-foreign-all": "Mai de notificacions {{PLURAL:$5|d’un autre wiki|de $5 autres wikis}}"
}
diff --git a/Echo/i18n/olo.json b/Echo/i18n/olo.json
index 3407419d..64d37e91 100644
--- a/Echo/i18n/olo.json
+++ b/Echo/i18n/olo.json
@@ -1,31 +1,41 @@
{
"@metadata": {
"authors": [
- "Mashoi7"
+ "Mashoi7",
+ "Ilja.mos",
+ "Macofe"
]
},
"echo-pref-send-me": "Työnnä minule:",
"echo-pref-send-to": "Työnnä adressah:",
+ "echo-pref-email-format": "Sähköpoštan formuattu:",
+ "echo-pref-web": "Verko",
"echo-pref-email": "Sähköpoštu",
"echo-pref-email-frequency-never": "Älä työnnä minule sähköpoštuilmoituksii",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Perustekstu",
"echo-new-messages": "Sinul on uuzii viestilöi",
+ "echo-category-title-article-linked": "{{PLURAL:$1|Sivun linku|Sivuloin linkat}}",
"echo-category-title-other": "{{PLURAL:$1|Muu|Muut}}",
- "echo-no-agent": "[Niken]",
- "echo-no-title": "[Ei sivuu]",
+ "echo-category-title-system": "{{PLURAL:$1|Sistiemu}}",
"tooltip-pt-notifications-alert": "{{GENDER:|Sinun}} hälytykset",
- "tooltip-pt-notifications-message": "{{GENDER:|Sinun}} viestit",
+ "echo-more-info": "Ližätieduo",
"echo-feedback": "Työndö",
"notification-link-text-view-message": "Ozuta viesti",
+ "notification-link-text-view-changes": "{{GENDER:$1|Ozuta}} muutokset",
"notification-link-text-view-page": "Ozuta sivu",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|kirjutti}} viestin [[User talk:$2#$3|sinun paginsivule]].",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|kirjutti}} viestin [[User talk:$2#$3|sinun paginsivule]].",
- "notification-new-user": "Tule terveh sivule {{SITENAME}}, $1! Olemmo hyväs mieles ku olet tiä.",
+ "notification-link-text-view-edit": "Ozuta kohendus",
+ "notification-header-reverted": "{{PLURAL:$4|Sinun kohendus|Sinun kohendukset}} sivul <strong>$3</strong> {{GENDER:$2|{{PLURAL:$4|on kumottu|oldih kumottu}}}}",
+ "notification-header-emailuser": "$1 {{GENDER:$2|työndi}} sinule sähköpoštan.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|kirjutti}} sinule viestin sivul {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|kirjutti}} viestin sinun paginsivule.",
- "echo-notification-message-text-only": "Viestit",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|jätti}} viestin sinun paginsivule sektah \"$2\".",
+ "notification-page-linked-email-subject": "Sinun luajittu sivu linkitettih saital {{SITENAME}}",
+ "notification-reverted-email-subject2": "Sinun {{PLURAL:$3|luajittu kohendus|luajitut kohendukset}} saital {{SITENAME}} on {{GENDER:$1|kumattu}}.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|mainičči}} {{GENDER:$2|sinuu}} saital {{SITENAME}}",
+ "notification-user-rights-email-subject": "Sinun käyttöoigevuot ollah muutunnuot saital {{SITENAME}}",
"echo-mark-all-as-read": "Merkiče kai luvettuloikse",
"echo-date-today": "Tänäpäi",
- "echo-date-yesterday": "Egläi"
+ "echo-date-yesterday": "Egläi",
+ "echo-email-batch-body-intro-daily": "Terveh $1.\nTäs on sinule yhtehvedo tämän päivän tapahtumis saital {{SITENAME}}.",
+ "echo-email-batch-body-intro-weekly": "Terveh $1.\nTäs on sinule yhtehvedo tämän nedälin tapahtumis saital {{SITENAME}}."
}
diff --git a/Echo/i18n/or.json b/Echo/i18n/or.json
index 0ed9a548..666ae374 100644
--- a/Echo/i18n/or.json
+++ b/Echo/i18n/or.json
@@ -2,7 +2,8 @@
"@metadata": {
"authors": [
"MKar",
- "Psubhashish"
+ "Psubhashish",
+ "DareDevil"
]
},
"echo-desc": "ସୂଚନା ପ୍ରଣାଳି",
@@ -10,7 +11,7 @@
"prefs-emailsettings": "ଇମେଲ ବିକଳ୍ପ",
"prefs-displaynotifications": "ଦେଖଣା ବିକଳ୍ପ",
"prefs-echosubscriptions": "ଏହି ଘଟଣା ସଂପର୍କରେ ମତେ ସୂଚନା ଦିଅନ୍ତୁ",
- "prefs-newmessageindicator": "ନୂଆ ବାର୍ତ୍ତା ସୂଚକ",
+ "prefs-newmessageindicator": "ନୂଆ ସନ୍ଦେଶ ସୂଚକ",
"echo-pref-send-me": "ମୋ ପାଖକୁ ପଠାନ୍ତୁ",
"echo-pref-send-to": "ଏହାଙ୍କ ପାଖକୁ ପଠାନ୍ତୁ",
"echo-pref-email-format": "ଇମେଲ ଶୈଳୀ",
@@ -22,11 +23,10 @@
"echo-pref-email-frequency-weekly": "ସୂଚନାର ସାପ୍ତାହିକ ସାରମର୍ମ",
"echo-pref-email-format-html": "ଏଚଟିଏମଏଲ",
"echo-pref-email-format-plain-text": "ସାଦା ଲେଖା",
- "echo-pref-notify-show-link": "ମୋ ଟୁଲବାରରେ ସୂଚନା ସବୁ ଦେଖାନ୍ତୁ",
"echo-pref-new-message-indicator": "ମୋ ଟୁଲବାରରେ ଆଲୋଚନା ପୃଷ୍ଠା ବାର୍ତ୍ତ ସୂଚକ ଦେଖାନ୍ତୁ",
"echo-learn-more": "ଅଧିକ ଶିଖନ୍ତୁ",
- "echo-new-messages": "ଆପଣଙ୍କ ପାଇଁ ଏକ ନୂଆ ବାର୍ତ୍ତା ଅଛି",
- "echo-category-title-edit-user-talk": "ଆଲୋଚନା ପୃଷ୍ଠା {{PLURAL:$1|ବାର୍ତ୍ତା|ଏକାଧିକ ବାର୍ତ୍ତା}}",
+ "echo-new-messages": "ଆପଣଙ୍କ ପାଖକୁ ନୂଆ ସନ୍ଦେଶ ଆସିଛି",
+ "echo-category-title-edit-user-talk": "ଆଲୋଚନା ପୃଷ୍ଠା {{PLURAL:$1|ସନ୍ଦେଶ|ଏକାଧିକ ସନ୍ଦେଶÍ}}",
"echo-category-title-article-linked": "ପୃଷ୍ଠା {{PLURAL:$1|ଲିଙ୍କ|ଏକାଧିକ ଲିଙ୍କ}}",
"echo-category-title-reverted": "ସଂପାଦନା {{PLURAL:$1|ପଶ୍ଚାତକରଣ|ଏକାଧିକ ପଶ୍ଚାତକରଣ}}",
"echo-category-title-other": "{{PLURAL:$1|ଅନ୍ୟାନ୍ୟ}}",
@@ -35,35 +35,28 @@
"echo-pref-tooltip-article-linked": "ମୁଁ ତିଆରି କରିଥିବା ପୃଷ୍ଠାକୁ କେହି ପ୍ରସଙ୍ଗ ପୃଷ୍ଠାରେ ସଂଯୋଗ କଲେ ମୋତେ ସୂଚିତ କରନ୍ତୁ",
"echo-pref-tooltip-reverted": "ମୋର ସଂପାଦନାକୁ କେହି ରୋଲବ୍ୟାକ ଟୁଲ ବା ପଛକୁ ଫେରାଇବା ଟୁଲ ବ୍ୟବହାର କରି ପଶ୍ଚାତକରଣ କଲେ ମୋତେ ସୂଚନା ଦିଅନ୍ତୁ",
"echo-pref-tooltip-mention": "ମୋର ବ୍ୟବହାରକାରୀ ପୃଷ୍ଠାକୁ କେହି ଜଣେ କୌଣସି ଆଲୋଚନା ପୃଷ୍ଠାରୁ ସଂଯୋଗ କଲେ ମୋତେ ସୂଚୀତ କରନ୍ତୁ",
- "echo-no-agent": "[କେହି ନୁହେଁ]",
- "echo-no-title": "[କୌଣସି ପୃଷ୍ଠା ନାହିଁ]",
"echo-error-no-formatter": "ସୂଚନା ନିମନ୍ତେ କୌଣସି ନିର୍ଦ୍ଦିଷ୍ଟ ଶୈଳୀ ନାହିଁ",
- "echo-error-preference": "ତୃଟି:ବ୍ୟବହାରକାରୀ ପସନ୍ଦ ସ୍ଥାପନ କରାଯାଇପାରିଲା ନାହିଁ",
- "echo-error-token": "ତୃଟି:ବ୍ୟବହାରକାରୀ ଟୋକନ ଅଣାଯାଇ ପାରିଲା ନାହିଁ",
"notifications": "ସୂଚନା",
- "tooltip-pt-notifications": "ଆପଣଙ୍କ ପାଇଁ ସୂଚନା",
+ "tooltip-pt-notifications-alert": "{{GENDER:|ଆପଣଙ୍କ}} ପାଇଁ ସୂଚନା",
"echo-specialpage": "ସୂଚନା",
"echo-anon": "ସୂଚନା ପ୍ରାପ୍ତି ନିମନ୍ତେ, [$1 ନୂଆ ଖାତା ଖୋଲନ୍ତୁ] କିମ୍ବା [$2 ଲଗ ଇନ କରନ୍ତୁ].",
"echo-none": "ଆପଣଙ୍କ ନିମନ୍ତେ କୌଣସି ସୂଚନା ନାହିଁ",
"echo-more-info": "ଅଧିକ ତଥ୍ୟ",
"echo-feedback": "ମତାମତ",
- "notification-link-text-view-message": "ବାର୍ତ୍ତା ଦେଖନ୍ତୁ",
+ "notification-link-text-view-message": "ସନ୍ଦେଶ ଦେଖନ୍ତୁ",
"notification-link-text-view-mention": "ସୂଚିତ ହୋଇଥିବା ପୃଷ୍ଠା ଦେଖନ୍ତୁ",
"notification-link-text-view-changes": "ସମସ୍ତ ବଦଳ ଦେଖନ୍ତୁ",
"notification-link-text-view-page": "ପୃଷ୍ଠା ଦେଖନ୍ତୁ",
"notification-link-text-view-edit": "ସମ୍ପାଦନା ଦେଖନ୍ତୁ",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|left}} ଆପଣଙ୍କ ପାଇଁ ଗୋଟିଏ ବାର୍ତ୍ତ ଅଛି [[User talk:$2#$3|ଆଲୋଚନା ପୃଷ୍ଠାରେ]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|left}} ଆପଣଙ୍କ ପାଇଁ ଗୋଟିଏ ବାର୍ତ୍ତା ଅଛି ଆପଣଙ୍କ ଆଲୋଚନା ପୃଷ୍ଠାରେ \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|left}} ଗୋଟିଏ ବାର୍ତ୍ତ ଆପଣଙ୍କ [[User talk:$2#$3|ଆଲୋଚନା ପୃଷ୍ଠା]]ରେ.",
+ "echo-notification-notice-text-only": "ଘୋଷଣା",
"echo-overlay-link": "ସମସ୍ତ ସୂଚନା",
"echo-overlay-title": "<b>ସୂଚନାବଳୀ</b>",
"echo-mark-all-as-read": "ସବୁ ପଢ଼ା ସରିଛି ବୋଲି ଚିହ୍ନ ଦିଅନ୍ତୁ",
"echo-date-today": "ଆଜି",
"echo-date-yesterday": "ଗତ କାଲି",
"echo-load-more-error": "ଅଧିକ ଫଳଗୁଡ଼ିକୁ ଖୋଜୁଥିବା ବେଳେ କିଛିଗୋଟେ ଅସୁବିଧା ହେଲା ।",
- "echo-email-batch-subject-weekly": "ଆପଣଙ୍କ ପାଇଁ {{SITENAME}}ରେ ଚଳିତ ସପ୍ତାହର {{PLURAL:$2|ଗୋଟିଏ ନୂଆ ବାର୍ତ୍ତ|ଏକାଧିକ ନୂଆ ବାର୍ତ୍ତା}} ଅଛି",
+ "echo-email-batch-subject-weekly": "ଆପଣଙ୍କ ପାଖକୁ {{SITENAME}}ରେ ଚଳିତ ସପ୍ତାହର {{PLURAL:$2|ନୂଆ ସନ୍ଦେଶଟିଏ|ଏକାଧିକ ନୂଆ ସନ୍ଦେଶ}} ଆସିଛି",
"echo-email-batch-body-intro-daily": "ନମସ୍କାର $1,\nଆପଣଙ୍କ ପାଇଁ ଏହା ହେଉଛି {{SITENAME}}ରେ ଚଳିତ ସପ୍ତାହର କାର୍ଯ୍ୟାବଳୀର ସାରମର୍ମ",
"echo-email-batch-body-intro-weekly": "ନମସ୍କାର $1,\nଆପଣଙ୍କ ପାଇଁ ଏହା ହେଉଛି {{SITENAME}}ରେ ଏହି ସପ୍ତାହର କାର୍ଯ୍ୟାବଳୀର ସାରମର୍ମ",
- "echo-email-batch-link-text-view-all-notifications": "ସମସ୍ତ ସୂଚନା ଦେଖନ୍ତୁ",
- "echo-rev-deleted-text-view": "ଏହି ପୃଷ୍ଠାର ପୁନରାବୃତି ଇତିହାସ ଉହ୍ୟ କରିଦିଆଯାଇଛି"
+ "echo-email-batch-link-text-view-all-notifications": "ସମସ୍ତ ସୂଚନା ଦେଖନ୍ତୁ"
}
diff --git a/Echo/i18n/pa.json b/Echo/i18n/pa.json
index 6ecacdcd..5a135f69 100644
--- a/Echo/i18n/pa.json
+++ b/Echo/i18n/pa.json
@@ -2,7 +2,10 @@
"@metadata": {
"authors": [
"Satdeep gill",
- "Babanwalia"
+ "Babanwalia",
+ "ਪ੍ਰਚਾਰਕ",
+ "Jimidar",
+ "Tow"
]
},
"echo-desc": "ਸੂਚਨਾ ਪ੍ਰਣਾਲੀ",
@@ -22,7 +25,6 @@
"echo-pref-email-frequency-weekly": "ਸੂਚਨਾਵਾਂ ਦਾ ਹਫਤਾਵਰ ਸਾਰ",
"echo-pref-email-format-html": "ਐਚ.ਟੀ.ਮੈਲ.ਐਲ.",
"echo-pref-email-format-plain-text": "ਸਰਲ ਟੈਕਸਟ",
- "echo-pref-notify-show-link": "ਮੇਰੀ ਟੂਲਬਾਰ ਵਿੱਚ ਸੂਚਨਾਵਾਂ ਵਿਖਾਓ",
"echo-pref-new-message-indicator": "ਮੇਰੀ ਟੂਲਬਾਰ ਵਿੱਚ ਗੱਲ-ਬਾਤ ਪੰਨਾ ਸੂਚਕ ਵਿਖਾਓ",
"echo-learn-more": "ਹੋਰ ਜਾਣੋ",
"echo-new-messages": "ਤੁਹਾਡੇ ਲਈ ਨਵੇਂ ਸੁਨੇਹੇ ਹਨ।",
@@ -36,60 +38,45 @@
"echo-pref-tooltip-article-linked": "ਜਦ ਕੋਈ ਉਸ ਪੰਨੇ ਨਾਲ ਜੁੜਦਾ ਹੈ ਜੋ ਮੈਂ ਕਿਸੇ ਲੇਖ ਦੇ ਪੰਨੇ ਤੋਂ ਬਣਾਇਆ ਸੀ ਤਾਂ ਮੈਨੂੰ ਸੂਚਨਾ ਦੇਵੋ।",
"echo-pref-tooltip-reverted": "ਜਦ ਕੋਈ ਮੇਰੀ ਕੀਤੀ ਸੋਧ ਨੂੰ, ਕੋਈ ਟੂਲ ਵਰਤ ਕੇ ਰੱਦ ਕਰ ਦਿੰਦਾ ਹੈ ਤਾਂ ਮੈਨੂੰ ਸੂਚਨਾ ਦੇਵੋ।",
"echo-pref-tooltip-mention": "ਜਦ ਕੋਈ ਕਿਸੇ ਗੱਲ-ਬਾਤ ਪੰਨੇ ਤੋਂ ਮੇਰੇ ਵਰਤੋਂਕਾਰ ਪੰਨੇ ਤੇ ਜੁੜਦਾ ਹੈ ਤਾਂ ਮੈਨੂੰ ਸੂਚਨਾ ਦੇਵੋ।",
- "echo-no-agent": "[ਕੋਈ ਨਹੀਂ]",
- "echo-no-title": "[ਕੋਈ ਪੰਨਾ ਨਹੀਂ]",
"echo-error-no-formatter": "ਸੂਚਨਾ ਲਈ ਕੋਈ ਫਾਰਮੈਟ ਨਹੀਂ ਹੈ।",
- "echo-error-preference": "ਭੁੱਲ: ਵਰਤੋਂਕਾਰ ਤਰਜੀਹ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ।",
- "echo-error-token": "ਭੁੱਲ: ਵਰਤੋਂਕਾਰ ਪਛਾਣ ਲੱਭੀ ਨਹੀਂ ਜਾ ਸਕੀ।",
"notifications": "ਸੂਚਨਾਵਾਂ",
- "tooltip-pt-notifications": "ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ",
+ "tooltip-pt-notifications-alert": "ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "ਨਵੇਂ ਵਰਤੋਂਕਾਰ",
"echo-specialpage": "ਸੂਚਨਾਵਾਂ",
"echo-anon": "ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, [$1 ਖਾਤਾ ਬਣਾਉ] ਜਾਂ [$2 ਲਾਗ ਇਨ ਕਰੋ]।",
"echo-none": "ਤੁਹਾਡੇ ਲਈ ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ ਹੈ।",
"echo-more-info": "ਹੋਰ ਜਾਣਕਾਰੀ",
"echo-feedback": "ਫ਼ੀਡਬੈਕ",
+ "notification-link-text-expand-all": "ਫੈਲਾਓ",
+ "notification-link-text-collapse-all": "ਸਮੇਟੋ",
"notification-link-text-view-message": "ਸੁਨੇਹਾ ਵੇਖੋ",
"notification-link-text-view-mention": "ਜ਼ਿਕਰ ਦੇਖੋ",
"notification-link-text-view-changes": "ਤਬਦੀਲੀਆਂ ਵੇਖੋ",
"notification-link-text-view-page": "ਪੰਨਾ ਦੇਖੋ",
+ "notification-link-text-what-links-here": "ਇਸ ਸਫੇ ਨੂੰ ਸਾਰੀਆੰ ਕੜੀਆੰ",
+ "notification-welcome-linktext": "ਜੀ ਆਇਆਂ ਨੂੰ",
+ "notification-link-thank-you-edit": "{{GENDER:$1|ਤੁਹਾਡਾ}} ਸੋਧ",
"notification-link-text-view-edit": "ਸੋਧ ਦੇਖੋ",
- "notification-edit-talk-page2": "[[User:$1|$1]] ਨੇ ਤੁਹਾਡੇ [[User talk:$2#$3|ਗੱਲ-ਬਾਤ ਸਫ਼ੇ]] 'ਤੇ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ}} ਹੈ।",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] ਨੇ \"[[User talk:$2#$3|$4]]\" ਵਿਚਲੇ ਤੁਹਾਡੇ ਗੱਲ-ਬਾਤ ਸਫ਼ੇ 'ਤੇ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ}} ਹੈ।",
- "notification-edit-talk-page-flyout2": "$1 ਨੇ ਤੁਹਾਡੇ [[User talk:$2#$3|ਗੱਲਬਾਤ ਸਫ਼ੇ]] ਉੱਤੇ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ ਹੈ}}।",
- "notification-edit-talk-page-flyout-with-section": "$1 ਨੇ \"[[User talk:$2#$3|$4]]\" ਵਿਚਲੇ ਤੁਹਾਡੇ ਗੱਲ-ਬਾਤ ਸਫ਼ੇ ਉੱਤੇ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ ਹੈ}}।",
- "notification-page-linked": "[[:$2]] ਨੂੰ [[:$3]] ਤੋਂ {{GENDER:$1|ਜੋੜਿਆ}} ਸੀ। [[Special:WhatLinksHere/$2|ਇਸ ਪੰਨੇ ਨਾਲ ਜੁੜਦੇ ਸਾਰੇ ਲਿੰਕ ਵੇਖੋ]]।",
- "notification-page-linked-flyout": "[[:$2]] ਨੂੰ [[:$3]] ਤੋਂ {{GENDER:$1|ਜੋੜਿਆ}} ਸੀ।",
- "notification-add-comment2": "[[User:$1|$1]] ਨੇ \"$4\" ਗੱਲ-ਬਾਤ ਪੰਨੇ ਉੱਤੇ \"[[$3|$2]]\" ਉੱਤੇ {{GENDER:$1|ਟਿੱਪਣੀ ਕੀਤੀ}}।",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] ਨੇ [[$3]] ਉੱਤੇ ਇੱਕ ਨਵਾਂ ਵਿਸ਼ਾ \"$2\" {{GENDER:$1|ਪਾਇਆ}}",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] ਨੇ ਤੁਹਾਨੂੰ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਭੇਜਿਆ ਹੈ}}: \"[[$3#$2|$2]]\"।",
- "notification-add-comment-yours2": "[[User:$1|$1]] ਨੇ ਤੁਹਾਡੇ ਗੱਲ-ਬਾਤ ਪੰਨੇ ਉੱਤੇ \"[[$3#$2|$2]]\" ਉੱਤੇ {{GENDER:$1|ਟਿੱਪਣੀ ਕੀਤੀ ਹੈ}}।",
- "notification-mention": "[[User:$1|$1]] ਨੇ \"[[:$3#$2|$4]]\" ਵਿੱਚ $5 ਗੱਲ-ਬਾਤ ਸਫ਼ੇ ਉੱਤੇ ਤੁਹਾਡਾ {{GENDER:$1|ਜ਼ਿਕਰ ਕੀਤਾ ਹੈ}}",
- "notification-mention-flyout": "$1 ਨੇ \"[[:$3#$2|$4]]\" ਵਿੱਚ $5 ਗੱਲ-ਬਾਤ ਸਫ਼ੇ ਉੱਤੇ ਤੁਹਾਡਾ {{GENDER:$1|ਜ਼ਿਕਰ ਕੀਤਾ ਹੈ}}",
- "notification-user-rights": "ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ ਅਧਿਕਾਰ [[User:$1|$1]] ਦੁਆਰਾ [[Special:Log/rights/$1|{{GENDER:$1|ਬਦਲ ਦਿੱਤੇ ਗਏ ਸਨ}}]]। $2। [[Special:ListGroupRights|ਹੋਰ ਜਾਣੋ]]",
- "notification-user-rights-flyout": "ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ ਅਧਿਕਾਰ $1 ਦੁਆਰਾ {{GENDER:$1|ਬਦਲ ਦਿੱਤੇ ਗਏ}} ਸਨ। $2।[[Special:ListGroupRights|ਹੋਰ ਜਾਣੋ]]",
- "notification-user-rights-add": "ਹੁਣ ਤੁਸੀਂ {{PLURAL:$2|ਇਸ ਸਮੂਹ|ਇਨ੍ਹਾਂ ਸਮੂਹਾਂ}} ਦੇ ਮੈਂਬਰ ਹੋ: $1",
- "notification-user-rights-remove": "ਹੁਣ ਤੁਸੀਂ {{PLURAL:$2|ਇਸ ਸਮੂਹ|ਇਨ੍ਹਾਂ ਸਮੂਹਾਂ}} ਦੇ ਮੈਂਬਰ ਨਹੀਂ ਹੋ: $1",
- "notification-new-user": "{{SITENAME}} ਉੱਤੇ ਤੁਹਾਡਾ ਸਵਾਗਤ ਹੈ, $1! ਤੁਹਾਡੇ ਇਥੇ ਆਉਣ ਉੱਤੇ ਸਾਨੂੰ ਖੁਸ਼ੀ ਹੋਈ।",
- "notification-reverted2": "ਤੁਹਾਡੀ {{PLURAL:$4|[[:$2]] ਉੱਤੇ ਸੋਧ|[[:$2]] ਉੱਤੇ ਸੋਧਾਂ}} ਨੂੰ [[User:$1|$1]] ਨੇ {{GENDER:$1|ਰੱਦ ਕਰ ਦਿੱਤਾ}} ਹੈ। $3",
- "notification-reverted-flyout2": "ਤੁਹਾਡੀ {{PLURAL:$4|$2 ਉੱਤੇ ਸੋਧ|$2 ਉੱਤੇ ਸੋਧਾਂ}} ਨੂੰ $1 ਨੇ {{GENDER:$1|ਰੱਦ ਕਰ ਦਿੱਤਾ}} ਹੈ। $3",
+ "notification-header-reverted": "ਤੁਹਾਡੀ {{PLURAL:$4|$3 ਉੱਤੇ ਸੋਧ|$3 ਉੱਤੇ ਸੋਧਾਂ}} ਨੂੰ $1 ਨੇ {{GENDER:$2|ਰੱਦ ਕਰ ਦਿੱਤਾ}} ਹੈ।",
"notification-edit-talk-page-email-subject2": "$1 ਨੇ {{SITENAME}} ਉੱਤੇ ਤੁਹਾਡੇ ਲਈ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ ਹੈ}}",
- "notification-edit-talk-page-email-batch-body2": "$1 ਨੇ ਤੁਹਾਡੇ ਗੱਲ-ਬਾਤ ਸਫ਼ੇ ਉੱਤੇ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ}} ਹੈ:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 ਨੇ ਤੁਹਾਡੇ \"$2\" ਵਿਚਲੇ ਗੱਲ-ਬਾਤ ਸਫ਼ੇ ਉੱਤੇ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ}} ਹੈ।",
"notification-page-linked-email-subject": "{{SITENAME}} ਉੱਤੇ ਤੁਹਾਡਾ ਪੰਨਾ ਜੁੜਦਾ ਹੈ",
- "notification-page-linked-email-batch-body": "$2 ਨੂੰ $3 ਤੋਂ {{GENDER:$1|ਜੋੜਿਆ ਗਿਆ}}।",
"notification-reverted-email-subject2": "ਤੁਹਾਡੀ {{SITENAME}} ਉੱਤੇ {{PLURAL:$3|ਸੋਧ|ਸੋਧਾਂ}} ਨੂੰ {{GENDER:$1|ਰੱਦ ਕਰ ਦਿੱਤਾ}} ਸੀ।",
- "notification-reverted-email-batch-body2": "ਤੁਹਾਡੀ {{PLURAL:$3|$2 ਉੱਤੇ ਸੋਧ|$2 ਉੱਤੇ ਸੋਧਾਂ}} ਨੂੰ $1 ਨੇ {{GENDER:$1|ਰੱਦ ਕਰ ਦਿੱਤਾ}} ਹੈ।",
"notification-mention-email-subject": "$1 ਨੇ {{SITENAME}} ਉੱਤੇ ਤੁਹਾਡਾ {{GENDER:$1|ਜ਼ਿਕਰ ਕੀਤਾ ਹੈ}}",
- "notification-mention-email-batch-body": "$1 ਨੇ \"$3\" ਵਿੱਚ $4 ਗੱਲ-ਬਾਤ ਪੰਨੇ ਉੱਤੇ ਤੁਹਾਡਾ {{GENDER:$1|ਜ਼ਿਕਰ ਕੀਤਾ ਹੈ}}",
"notification-user-rights-email-subject": "{{SITENAME}} ਉੱਤੇ ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ ਅਧਿਕਾਰ ਬਦਲ ਗਏ ਹਨ",
- "notification-user-rights-email-batch-body": "ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ ਅਧਿਕਾਰ $1. $2 ਦੁਆਰਾ {{GENDER:$1|ਬਦਲੇ ਗਏ}}।",
- "echo-email-subject-default": "{{SITENAME}} ਉੱਤੇ ਨਵੀਂ ਸੂਚਨਾ",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mo}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1yr}}",
+ "notification-timestamp-today": "ਅੱਜ",
+ "notification-timestamp-yesterday": "ਕੱਲ੍ਹ",
+ "notification-inbox-filter-read": "ਪੜ੍ਹੇ ਹੋਏ",
+ "notification-inbox-filter-all": "ਸੱਭ",
"echo-email-body-default": "ਤੁਹਾਡੇ ਲਈ {{SITENAME}} ਉੱਤੇ ਨਵੀਂ ਸੂਚਨਾ ਹੈ:\n\n$1",
- "echo-email-batch-body-default": "ਤੁਹਾਡੇ ਲਈ ਇੱਕ ਨਵੀਂ ਸੂਚਨਾ ਹੈ।",
"echo-email-footer-default": "$2\n\nਅਸੀਂ ਤੁਹਾਨੂੰ ਕਿਹੜੇ ਈ-ਮੇਲ ਭੇਜਦੇ ਹਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਆਪਣੀਆਂ ਤਰਜੀਹਾਂ ਵੇਖੋ:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "ਅਸੀਂ ਤੁਹਾਨੂੰ ਕਿਹੜੇ ਈ-ਮੇਲ ਭੇਜਦੇ ਹਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਲਈ <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">ਆਪਣੀਆਂ ਤਰਜੀਹਾਂ ਵੇਖੋ</a>.<br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|ਚੌਕਸੀ ($1)|ਚੌਕਸੀਆਂ ($1)|100=ਚੌਕਸੀਆਂ (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|ਸੁਨੇਹਾ ($1)|ਸੁਨੇਹੇ ($1)|100=ਸੁਨੇਹੇ (99+)}}",
"echo-overlay-link": "ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ",
"echo-overlay-title": "<b>ਸੂਚਨਾਵਾਂ</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|ਸੂਚਨਾ|ਸੂਚਨਾਵਾਂ}}</b> ($2 ਨਾ-ਪੜ੍ਹੀਆਂ 'ਚੋਂ $1 ਵਿਖਾ ਰਿਹਾ ਹੈ)",
@@ -97,14 +84,9 @@
"echo-date-today": "ਅੱਜ",
"echo-date-yesterday": "ਬੀਤੀ ਕੱਲ",
"echo-load-more-error": "ਹੋਰ ਨਤੀਜੇ ਖੋਜਣ ਦੌਰਾਨ ਇੱਕ ਭੁੱਲ ਹੋ ਗਈ।",
- "notification-edit-talk-page-bundle": "$1 ਅਤੇ $3 {{PLURAL:$4|ਹੋਰ|ਹੋਰਾਂ}} ਨੇ ਤੁਹਾਡੇ [[User talk:$2|ਗੱਲ-ਬਾਤ ਸਫ਼ੇ]] ਉੱਤੇ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ}} ਹੈ।",
- "notification-page-linked-bundle": "$2 ਨੂੰ $3 ਅਤੇ $4 ਹੋਰ {{PLURAL:$5|ਪੰਨਾ|ਪੰਨੇ}} ਤੋਂ {{GENDER:$1|ਜੋੜਿਆ}} ਸੀ।\n[[Special:WhatLinksHere/$2|ਇਸ ਪੰਨੇ ਉੱਤੇ ਜੁੜਦੇ ਸਾਰੇ ਲਿੰਕ ਵੇਖੋ]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 ਅਤੇ $2 {{PLURAL:$3|ਹੋਰ|ਹੋਰਾਂ}} ਨੇ ਤੁਹਾਡੇ ਗੱਲ-ਬਾਤ ਸਫ਼ੇ ਉੱਤੇ ਇੱਕ ਸੁਨੇਹਾ {{GENDER:$1|ਛੱਡਿਆ}} ਹੈ।",
- "notification-page-linked-email-batch-bundle-body": "$2 ਨੂੰ $3 ਅਤੇ $4 ਹੋਰ {{PLURAL:$5|ਪੰਨਾ|ਪੰਨੇ}} ਤੋਂ {{GENDER:$1|ਜੋੜਿਆ}} ਸੀ।",
"echo-email-batch-subject-daily": "ਤੁਹਾਡੇ ਲਈ {{SITENAME}} ਉੱਤੇ {{PLURAL:$2|ਇੱਕ ਨਵੀਂ ਸੂਚਨਾ|ਨਵੀਆਂ ਸੂਚਨਾਵਾਂ}} ਹਨ।",
"echo-email-batch-subject-weekly": "ਤੁਹਾਡੇ ਲਈ {{SITENAME}} ਉੱਤੇ ਇਸ ਹਫਤੇ {{PLURAL:$2|ਇੱਕ ਨਵੀਂ ਸੂਚਨਾ|ਨਵੀਆਂ ਸੂਚਨਾਵਾਂ}} ਹਨ।",
"echo-email-batch-body-intro-daily": "ਸਤਿ ਸ਼੍ਰੀ ਅਕਾਲ $1,\nਤੁਹਾਡੇ ਲਈ {{SITENAME}} ਉੱਤੇ ਅੱਜ ਦੀ ਸਰਗਰਮੀ ਦਾ ਸਾਰ।",
"echo-email-batch-body-intro-weekly": "ਸਤਿ ਸ਼੍ਰੀ ਅਕਾਲ $1,\nਤੁਹਾਡੇ ਲਈ {{SITENAME}} ਉੱਤੇ ਹਫਤਾਵਰ ਸਰਗਰਮੀ ਦਾ ਸਾਰ।",
- "echo-email-batch-link-text-view-all-notifications": "ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖੋ",
- "echo-rev-deleted-text-view": "ਇਸ ਪੰਨੇ ਦੀ ਸੁਧਾਈ ਨੂੰ ਰੋਕ ਦਿੱਤਾ ਗਿਆ ਹੈ।"
+ "echo-email-batch-link-text-view-all-notifications": "ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖੋ"
}
diff --git a/Echo/i18n/pam.json b/Echo/i18n/pam.json
new file mode 100644
index 00000000..6e2b15c1
--- /dev/null
+++ b/Echo/i18n/pam.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Leeheonjin",
+ "Amiel Guanlao"
+ ]
+ },
+ "echo-notification-loginrequired": "Dapot kang mibuklat ba mong akit ding pakiwari keka.",
+ "notification-welcome-linktext": "Malawus ko pu"
+}
diff --git a/Echo/i18n/pfl.json b/Echo/i18n/pfl.json
index 58d2173f..2e41e363 100644
--- a/Echo/i18n/pfl.json
+++ b/Echo/i18n/pfl.json
@@ -3,6 +3,5 @@
"authors": [
"Manuae"
]
- },
- "tooltip-pt-notifications": "Doi Bnochrischdigunge"
+ }
}
diff --git a/Echo/i18n/pl.json b/Echo/i18n/pl.json
index 4437e570..71cf7005 100644
--- a/Echo/i18n/pl.json
+++ b/Echo/i18n/pl.json
@@ -16,15 +16,20 @@
"Tsca",
"Peter Bowman",
"The Polish",
- "Rzuwig"
+ "Rzuwig",
+ "Sethakill",
+ "PiotrekD",
+ "InternerowyGołąb"
]
},
- "echo-desc": "System powiadomień użytkowników o wydarzeniach i komunikatach",
+ "echo-desc": "System powiadomień użytkowników o zdarzeniach i komunikatach",
"prefs-echo": "Powiadomienia",
"prefs-emailsettings": "Opcje e-maila",
"prefs-displaynotifications": "Opcje wyświetlania",
"prefs-echosubscriptions": "Powiadom mnie o tych zdarzeniach",
+ "prefs-echocrosswiki": "Powiadomienia z innych projektów",
"prefs-newmessageindicator": "Informacje o nowych wiadomościach",
+ "prefs-blocknotificationslist": "Ignorowanie od użytkowników",
"echo-pref-send-me": "Wysyłaj mi:",
"echo-pref-send-to": "Wyślij na adres:",
"echo-pref-email-format": "Format e-maila:",
@@ -32,107 +37,180 @@
"echo-pref-email": "Przez e‐mail",
"echo-pref-email-frequency-never": "Nie wysyłaj powiadomień e-mailem",
"echo-pref-email-frequency-immediately": "Każde powiadomienie osobno",
- "echo-pref-email-frequency-daily": "Dzienne podsumowanie",
- "echo-pref-email-frequency-weekly": "Tygodniowe podsumowanie",
+ "echo-pref-email-frequency-daily": "Podsumowanie dzienne",
+ "echo-pref-email-frequency-weekly": "Podsumowanie tygodniowe",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Zwykły tekst",
+ "echo-pref-cross-wiki-notifications": "Pokazuj powiadomienia z innych wiki",
+ "echo-pref-notifications-blacklist": "Nie wyświetlaj powiadomień od tych użytkowników. ([[mw:Help:Notifications#mute|dowiedz się więcej]])",
"echo-pref-new-message-indicator": "Pokazuj informację o nowej wiadomości w pasku osobistym",
+ "echo-pref-beta-feature-cross-wiki-message": "Rozbudowane powiadomienia",
+ "echo-pref-beta-feature-cross-wiki-description": "Łatwiej wyświetlaj i organizuj powiadomienia. Funkcja obejmuje powiadomienia ''cross-wiki'', dzięki którym widzisz powiadomienia z innych wiki. (Aby otrzymywać powiadomienia cross-wiki na danej wiki, należy włączyć funkcją eksperymentalną na tej wiki)",
"echo-learn-more": "Dowiedz się więcej",
+ "echo-log": "Rejestr publiczny",
"echo-new-messages": "Masz nowe wiadomości",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Wpis|Wpisy}} w dyskusji",
"echo-category-title-article-linked": "{{PLURAL:$1|Link|Linki}} do moich artykułów",
"echo-category-title-reverted": "{{PLURAL:$1|Rewert|Rewerty}} edycji",
"echo-category-title-mention": "{{PLURAL:$1|Wzmianka|Wzmianki}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Nieudana wzmianka|Nieudane wzmianki}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Udana wzmianka|Udane wzmianki}}",
"echo-category-title-other": "{{PLURAL:$1|Inne zdarzenie|Inne zdarzenia}}",
"echo-category-title-system": "{{PLURAL:$1|Zdarzenie systemowe|Zdarzenia systemowe}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Zmiana uprawnień|Zmiany uprawnień}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-mail od innego użytkownika|E-maile od innych użytkowników}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Przypomnienie|Przypomnienia}} o stronach",
"echo-pref-tooltip-edit-user-talk": "Powiadom mnie, kiedy ktoś napisze nową wiadomość albo odpowie na mojej stronie dyskusji.",
- "echo-pref-tooltip-article-linked": "Powiadom mnie, kiedy ktoś umieści w artykule link do strony utworzonej przeze mnie.",
+ "echo-pref-tooltip-article-linked": "Powiadom mnie, kiedy ktoś umieści na innej stronie link do strony utworzonej przeze mnie.",
"echo-pref-tooltip-reverted": "Powiadom mnie, kiedy ktoś wycofa moją edycję korzystając z narzędzia „anuluj” albo „cofnij”.",
"echo-pref-tooltip-mention": "Powiadom mnie, kiedy ktoś umieści link do mojej strony użytkownika.",
+ "echo-pref-tooltip-mention-failure": "Powiadom mnie, kiedy nie udało się wysłać do kogoś informacji o wzmiance.",
+ "echo-pref-tooltip-mention-success": "Powiadom mnie, kiedy wyślę do kogoś informacje o wzmiance.",
"echo-pref-tooltip-user-rights": "Powiadamiaj mnie, gdy ktoś zmieni moje uprawnienia.",
- "echo-no-agent": "[Nikt]",
- "echo-no-title": "[Brak strony]",
+ "echo-pref-tooltip-emailuser": "Powiadom mnie, gdy ktoś wyśle mi e-mail.",
+ "echo-pref-tooltip-article-reminder": "Powiadom mnie o tej stronie, gdy zapytam.",
"echo-error-no-formatter": "Nie określono formatowania dla powiadomień",
"notifications": "Powiadomienia",
- "tooltip-pt-notifications-alert": "Twoje powiadomienia",
- "tooltip-pt-notifications-message": "Twoje wiadomości",
+ "tooltip-pt-notifications-alert": "Moje powiadomienia",
+ "tooltip-pt-notifications-notice": "Moje komunikaty",
+ "echo-displaynotificationsconfiguration": "Wyświetl konfigurację Powiadomień",
+ "echo-displaynotificationsconfiguration-summary": "To jest przegląd tego, jak Powiadomienia są skonfigurowane na tej wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Powiadomienia według kategorii",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sortowanie według typu",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Do której sekcji każdy rodzaj powiadomienia jest przydzielany",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Akceptowane sposoby powiadamiania",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Jakie metody powiadamiania są obsługiwane dla każdej z kategorii",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Jakie metody powiadamiania są obsługiwane dla każdego z rodzajów; ma tylko zastosowanie do rodzajów zawartych w kategoriach, które są ukryte z preferencji.",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Domyślnie włączone",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Istniejący użytkownicy",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nowi użytkownicy",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Wymagane sposoby powiadamiania",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Które metody powiadamiania są obowiązkowe dla każdej z kategorii",
"echo-specialpage": "Powiadomienia",
+ "echo-specialpage-section-markread": "Oznacz grupę jako przeczytaną",
+ "echo-specialpage-markasread": "Powiadomienie: Oznacz jako przeczytane",
+ "echo-specialpage-markasread-invalid-id": "Nieprawidłowy identyfikator zdarzenia",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|$1 powiadomienie|$1 powiadomienia|$1 powiadomień}}",
+ "echo-specialpage-pagefilters-title": "Ostatnia aktywność",
+ "echo-specialpage-pagefilters-subtitle": "Strony z nieodczytanymi powiadomieniami",
+ "notificationsmarkread-legend": "Oznacz powiadomienie jako przeczytane",
"echo-anon": "Aby otrzymywać powiadomienia, [$1 załóż konto] lub [$2 zaloguj się].",
"echo-none": "Nie masz żadnych powiadomień.",
"echo-more-info": "Więcej informacji",
"echo-feedback": "Opinie",
- "echo-api-failure": "Nie udało się pobrać powiadomień. Spróbuj ponownie. (Błąd $1)",
+ "echo-popup-footer-special-page-invitation": "<strong>Wypróbuj przebudowaną stronę powiadomień.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Całkowicie nowy wygląd i możliwości.",
+ "echo-api-failure": "Nie udało się pobrać powiadomień.",
+ "echo-api-failure-cross-wiki": "Dostęp do zdalnej domeny jest zabroniony.",
"echo-notification-placeholder": "Nie ma powiadomień.",
+ "echo-notification-placeholder-filters": "Nie ma powiadomień, które spełniają te kryteria.",
+ "echo-notification-loginrequired": "Aby zobaczyć powiadomienia, musisz się zalogować.",
+ "echo-notification-popup-loginrequired": "Zaloguj się, aby zobaczyć swoje powiadomienia.",
+ "echo-notification-markasread": "Oznacz jako przeczytane",
+ "echo-notification-markasunread": "Oznacz jako nieprzeczytane",
+ "echo-notification-markasread-tooltip": "Oznacz jako przeczytane",
+ "echo-notification-more-options-tooltip": "Więcej opcji",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Zatrzymaj}} obserwowanie nowej aktywności na \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Przestałeś|Przestałaś}} obserwować stronę „$1”",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Możesz}} wznowić obserwowanie [$2 tej strony] w dowolnym momencie.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Śledź}} nową aktywność na \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Zacząłeś|Zaczęłaś}} obserwować stronę „$1”",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Możesz}} przestać obserwować [$2 tę stronę] w dowolnym momencie.",
+ "notification-link-text-expand-all": "Rozwiń",
+ "notification-link-text-expand-alert-count": "Pokaż {{PLURAL:$1|$1 powiadomienie|$1 powiadomienia|$1 powiadomień}}",
+ "notification-link-text-expand-notice-count": "Zobacz {{PLURAL:$1|$1 powiadomienie|$1 powiadomień}}",
+ "notification-link-text-expand-all-count": "Pokaż {{PLURAL:$1|$1 powiadomienie|$1 powiadomienia|$1 powiadomień}}",
+ "notification-link-text-collapse-all": "Zwiń",
"notification-link-text-view-message": "Zobacz wiadomość",
"notification-link-text-view-mention": "Zobacz wzmiankę",
- "notification-link-text-view-changes": "Zobacz zmiany",
+ "notification-link-text-view-mention-failure": "Zobacz {{PLURAL:$1|wzmiankę|wzmianki}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Zobacz}} zmiany",
"notification-link-text-view-page": "Zobacz stronę",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|zostawił|zostawiła|zostawił(a)}} wiadomość na <strong>{{GENDER:$3|twojej}} stronie dyskusji</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|zostawił|zostawiła|zostawił(a)}} wiadomość na <strong>{{GENDER:$3|twojej}} stronie dyskusji</strong> w „<strong>$4</strong>”.",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Utworzono link z <strong>$4</strong> do <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Linkowana z <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Utworzono linki z {{PLURAL:$5||$5 stron|100=99+ stron}} do <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Wszystkie linki do tej strony",
+ "notification-header-mention-other": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$3|tobie}} na stronie <strong>$4</strong> w wątku „<strong>$5</strong>”.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$3|Tobie}} na stronie <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$3|tobie}} na <strong>stronie dyskusji {{GENDER:$5|użytkownika|użytkowniczki}} $4</strong> w wątku „<strong>$6</strong>”.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$3|tobie}} na <strong>stronie dyskusji {{GENDER:$5|użytkownika|użytkowniczki}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$3|tobie}} na <strong>{{GENDER:$2|swojej}} stronie dyskusji</strong> w wątku „<strong>$4</strong>”.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$3|tobie}} na <strong>{{GENDER:$2|swojej}} stronie dyskusji</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$3|tobie}} na stronie dyskusji strony <strong>$4</strong> w wątku „<strong>$5</strong>”.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$3|Tobie}} na stronie dyskusji strony <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Twoja}} wzmianka o <strong>$3</strong> nie została wysłana, ponieważ ten użytkownik nie został znaleziony.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Twoja}} wzmianka o <strong>$3</strong> nie została wysłana, ponieważ jest to użytkownik anonimowy.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Próbowałeś|Próbowałaś}} wspomnieć o więcej niż $3 {{PLURAL:$3|użytkowniku|użytkowników}}. Wzmianki powyżej tego limitu nie zostaną wysłane.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Wzmianka|$3 wzmianki|$3 wzmianek}}, których {{GENDER:$2|dokonałeś|dokonałaś}} na stronie dyskusji <strong>$4</strong> nie {{PLURAL:$3|mogła|mogły|mogło}} zostać wysłanych.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Nazwa użytkownika nie istnieje:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Nie można wspominać o adresach IP:</strong> „$1”",
+ "notification-header-mention-success": "{{GENDER:$2|Twoje}} wzmiankowanie o <strong>$3</strong> zostało wysłane.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Wzmianka|$3 wzmianki|$3 wzmianek}}, których {{GENDER:$2|dokonałeś|dokonałaś}} na stronie dyskusji <strong>$4</strong> {{PLURAL:$3|została|zostały}} wysłane.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Wspomniałeś|Wspomniałaś}} o:</strong> $3",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Twoje}} uprawnienia zostały {{GENDER:$1|zmienione}}. {{GENDER:$4|Zostałeś dodany|Zostałaś dodana}} do: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Twoje}} uprawnienia zostały {{GENDER:$1|zmienione}}. Nie należysz już do: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Twoje}} uprawnienia zostały {{GENDER:$1|zmienione}}. {{GENDER:$6|Zostałeś dodany|Zostałaś dodana}} do: $2. Nie należysz już do: $4.",
+ "notification-header-user-rights-expiry-change": "{{GENDER:$1|Zmieniono}} czas wygaśnięcia {{GENDER:$4|Twojego}} członkostwa w {{PLURAL:$3|następującej grupie|następujących grupach}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Witaj}} w {{GRAMMAR:MS.lp|{{SITENAME}}}}, $1! Cieszymy się, że {{GENDER:$2|jesteś}} tutaj.",
+ "notification-welcome-linktext": "Witaj",
+ "notification-header-thank-you-1-edit": "Właśnie {{GENDER:$2|dokonałeś|dokonałaś}} swojej pierwszej edycji; dziękujemy Ci i zapraszamy!",
+ "notification-header-thank-you-10-edit": "Właśnie {{GENDER:$2|dokonałeś|dokonałaś}} swojej dziesiątej edycji; dziękujemy Ci i tak trzymaj!",
+ "notification-header-thank-you-100-edit": "Właśnie {{GENDER:$2|dokonałeś|dokonałaś}} swojej setnej edycji; bardzo Ci dziękujemy!",
+ "notification-header-thank-you-1000-edit": "Właśnie {{GENDER:$2|dokonałeś|dokonałaś}} swojej tysięcznej edycji; dziękujemy Ci za bycie świetnym współpracownikiem!",
+ "notification-header-thank-you-10000-edit": "Właśnie {{GENDER:$2|dokonałeś|dokonałaś}} swojej dziesięciotysięcznej edycji; jesteśmy Ci ogromnie wdzięczni!",
+ "notification-header-thank-you-100000-edit": "Właśnie {{GENDER:$2|dokonałeś|dokonałaś}} swojej stutysięcznej edycji; dziękujemy Ci za niesamowity wkład!",
+ "notification-header-thank-you-1000000-edit": "Właśnie {{GENDER:$2|dokonałeś|dokonałaś}} swojej milionowej edycji; dziękujemy Ci za Twój zadziwiający wkład!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Twoja}} edycja",
"notification-link-text-view-edit": "Zobacz edycję",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|napisał|napisała}} do ciebie na twojej [[User talk:$2#$3|stronie dyskusji]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|napisał|napisała}} do Ciebie na Twojej stronie dyskusji, w wątku „[[User talk:$2#$3|$4]]”.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|napisał|napisała}} do ciebie na twojej [[User talk:$2#$3|stronie dyskusji]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|napisał|napisała}} do Ciebie na Twojej stronie dyskusji, w wątku „[[User talk:$2#$3|$4]]”.",
- "notification-page-linked": "W artykule [[:$3]] {{GENDER:$1|umieszczono}} link do artykułu [[:$2]]. [[Special:WhatLinksHere/$2|Pokaż wszystkie linkujące do artykułu $2]].",
- "notification-page-linked-flyout": "W artykule [[:$3]] {{GENDER:$1|umieszczono}} link do artykułu [[:$2]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|umieścił|umieściła}} komentarz do „[[$3|$2]]” na stronie dyskusji „$4”",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|umieścił|umieściła}} komentarz w nowym wątku „$2” na stronie [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|wysłał|wysłała}} ci wiadomość: „[[$3#$2|$2]]”",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|umieścił|umieściła}} komentarz do „[[$3#$2|$2]]” na twojej stronie dyskusji",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|wspomniał|wspomniała}} o Tobie na stronie $5 w wątku „[[:$3#$2|$4]]”.",
- "notification-mention-flyout": "$1 {{GENDER:$1|wspomniał|wspomniała}} o Tobie w wątku „[[:$3#$2|$4]]” na stronie $5.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|wspomniał|wspomniała}} o Tobie na [[:$3|stronie $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|wspomniał|wspomniała}} o Tobie na [[:$3|stronie $2]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|zmienił|zmieniła}}]] twoje uprawnienia. $2. [[Special:ListGroupRights|Dowiedz się więcej]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|zmienił|zmieniła}} twoje uprawnienia. $2. [[Special:ListGroupRights|Dowiedz się więcej]]",
- "notification-user-rights-add": "Należysz teraz do {{PLURAL:$2|tej grupy|tych grup}}: $1",
- "notification-user-rights-remove": "Od teraz nie należysz już do {{PLURAL:$2|tej grupy|tych grup}}: $1",
- "notification-new-user": "Witaj w {{grammar:MS.lp|{{SITENAME}}}}, $1! Cieszymy się, że tu jesteś.",
- "notification-reverted2": "[[User:$1|$1]] {{GENDER:$1|wycofał|wycofała}} {{PLURAL:$4|Twoją edycję|Twoje edycje}} na stronie [[:$2]] $3",
- "notification-reverted-flyout2": "$1 {{GENDER:$1|wycofał|wycofała}} {{PLURAL:$4|Twoją edycję|Twoje edycje}} na stronie $2 $3",
- "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|napisał|napisała}} do Ciebie w {{grammar:MS.lp|{{SITENAME}}}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|napisał|napisała}} do ciebie na twojej stronie dyskusji.",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|napisał|napisała}} do Ciebie na Twojej stronie dyskusji w wątku „$2”.",
+ "notification-link-article-reminder": "Zobacz stronę",
+ "notification-header-reverted": "{{GENDER:$2|Wycofano}} {{PLURAL:$4|twoją edycję|twoje edycje}} na stronie <strong>$3</strong>.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|wysłał|wysłała|wysłał(a)}} Ci e-mail.",
+ "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|napisał|napisała}} do Ciebie w projekcie {{SITENAME}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|napisał|napisała|napisał}} do ciebie na twojej stronie dyskusji w wątku „$2”.",
"notification-page-linked-email-subject": "Na stronie {{SITENAME}} pojawił się link do utworzonej przez Ciebie strony",
- "notification-page-linked-email-batch-body": "Na stronie $3 {{GENDER:$1|umieszczono}} link do strony $2",
- "notification-reverted-email-subject2": "$1 {{GENDER:$1|wycofał|wycofała}} {{PLURAL:$3|twoją edycję|twoje edycje}} w {{grammar:MS.lp|{{SITENAME}}}}",
- "notification-reverted-email-batch-body2": "$1 {{GENDER:$1|wycofał|wycofała}} {{PLURAL:$3|Twoją edycję|Twoje edycje}} na stronie $2",
- "notification-mention-email-subject": "$1 {{GENDER:$1|wspomniał|wspomniała}} o Tobie w {{grammar:MS.lp|{{SITENAME}}}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|wspomniał|wspomniała}} o Tobie na stronie $4 w wątku „$3”.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|wspomniał|wspomniała}} o Tobie na stronie $2.",
+ "notification-reverted-email-subject2": "$1 {{GENDER:$1|wycofał|wycofała}} {{PLURAL:$3|Twoją edycję|Twoje edycje}} w {{grammar:MS.lp|{{SITENAME}}}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$2|Tobie}} w {{grammar:MS.lp|{{SITENAME}}}}",
"notification-user-rights-email-subject": "W {{grammar:MS.lp|{{SITENAME}}}} zostały zmienione twoje uprawnienia",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|zmienił|zmieniła}} twoje uprawnienia. $2",
- "echo-notification-count": "$1+",
- "echo-email-subject-default": "Nowe powiadomienie w {{grammar:MS.lp|{{SITENAME}}}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 godz.}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 dzień|$1 dni}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mies.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 rok|$1 lata|$1 lat}}",
+ "notification-timestamp-today": "Dzisiaj",
+ "notification-timestamp-yesterday": "Wczoraj",
+ "notification-inbox-filter-read": "Przeczytane",
+ "notification-inbox-filter-unread": "Nieprzeczytane",
+ "notification-inbox-filter-all": "Wszystkie",
"echo-email-body-default": "Masz nowe powiadomienie w {{grammar:MS.lp|{{SITENAME}}}}:\n\n$1",
- "echo-email-batch-body-default": "Masz nowe powiadomienie",
+ "echo-email-footer-default-html": "Aby określić, jakie e-maile wysyłamy do Ciebie, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">sprawdź swoje preferencje</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nMożesz wybrać, jakie e-maile chcesz otrzymywać, w swoich preferencjach: {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Możesz wybrać, jakie e-maile chcesz otrzymywać <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">w swoich preferencjach</a>.<br />\n$1",
+ "echo-email-plain-footer": "Aby kontrolować e-maile, które wysyłamy do {{GENDER:$1|Ciebie}}, sprawdź swoje ustawienia:",
+ "echo-email-html-footer-preference-link-text": "sprawdź {{GENDER:$1|swoje}} preferencje",
+ "echo-email-html-footer-with-link": "Aby kontrolować, jakie e-maile wysyłamy do {{GENDER:$2|Ciebie}}, $1.",
"echo-notification-alert": "{{PLURAL:$1|Powiadomienie ($1)|Powiadomienia ($1)|100=Powiadomienia (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Wiadomość ($1)|Wiadomości ($1)|100=Wiadomości (ponad 99)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Powiadomienie ($1)|Powiadomienia ($1)|100=Powiadomień (99+)}}",
"echo-notification-alert-text-only": "Powiadomienia",
- "echo-notification-message-text-only": "Wiadomości",
+ "echo-notification-notice-text-only": "Komunikaty",
"echo-overlay-link": "Wszystkie powiadomienia",
"echo-overlay-title": "<b>Powiadomienia</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Powiadomienie|Powiadomienia}}</b> (wyświetlono $1 z $2 nieprzeczytanych)",
"echo-mark-all-as-read": "Oznacz wszystkie jako przeczytane",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|powiadomienie oznaczone|powiadomienia oznaczone|powiadomień oznaczonych}} jako przeczytane",
+ "echo-mark-wiki-as-read": "Oznacz wszystko jako przeczytane w wybranej wiki: $1",
"echo-date-today": "Dzisiaj",
"echo-date-yesterday": "Wczoraj",
"echo-load-more-error": "Wystąpił błąd przy pobieraniu kolejnych wyników.",
- "notification-edit-talk-page-bundle": "$1 i {{PLURAL:$4|ktoś inny|$3 inni|$3 innych}} napisali do Ciebie na Twojej [[User talk:$2|stronie dyskusji]].",
- "notification-page-linked-bundle": "Na stronie $3 i na {{PLURAL:$5|innej stronie|$4 innych stronach}} {{GENDER:$1|umieszczono}} link do strony $2: [[Special:WhatLinksHere/$2|pokaż wszystkie linkujące do tej strony]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 i {{PLURAL:$3|ktoś inny|$2 inni|$2 innych}} {{GENDER:$1|napisali}} do Ciebie na Twojej stronie dyskusji.",
- "notification-page-linked-email-batch-bundle-body": "Na stronie $3 i na {{PLURAL:$5|innej stronie|$4 innych stronach}} {{GENDER:$1|umieszczono}} link do strony $2",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Jedna nowa wiadomość|$1 nowe wiadomości|$1 nowych wiadomości|100=99+ nowych wiadomości}} na <strong>{{GENDER:$3|twojej}} stronie dyskusji</strong>.",
"echo-email-batch-subject-daily": "Masz {{PLURAL:$2|nowe powiadomienie|nowe powiadomienia}} w {{grammar:MS.lp|{{SITENAME}}}}",
"echo-email-batch-subject-weekly": "Masz {{PLURAL:$2|nowe powiadomienie|nowe powiadomienia}} w {{grammar:MS.lp|{{SITENAME}}}} z tego tygodnia",
"echo-email-batch-body-intro-daily": "Cześć, $1!\nW {{grammar:MS.lp|{{SITENAME}}}} czeka na ciebie dzisiejsze podsumowanie powiadomień.",
"echo-email-batch-body-intro-weekly": "Cześć, $1!\nW {{grammar:MS.lp|{{SITENAME}}}} czeka na ciebie podsumowanie powiadomień z ostatniego tygodnia.",
"echo-email-batch-link-text-view-all-notifications": "Zobacz wszystkie powiadomienia",
- "echo-rev-deleted-text-view": "Ta wersja strony została ukryta",
- "apihelp-echomarkread-description": "Oznacz powiadomienia jako przeczytane dla bieżącego użytkownika.",
- "apihelp-echomarkread-param-sections": "Lista sekcji do oznaczania jako przeczytane.",
- "apihelp-echomarkread-example-2": "Oznacz wszystkie powiadomienia jako przeczytane",
- "apihelp-echomarkseen-example-1": "Oznacz powiadomienia wszystkich typów jako przeczytane",
- "apihelp-query+notifications-param-limit": "Maksymalna liczba zwracanych powiadomień.",
- "apihelp-query+notifications-example-1": "Spis powiadomień"
+ "notification-header-foreign-alert": "Więcej powiadomień z {{PLURAL:$5|innej wiki|$5 innych wiki}}",
+ "notification-header-foreign-notice": "Więcej powiadomień z {{PLURAL:$5|innej wiki|$5 innych wiki}}",
+ "notification-header-foreign-all": "Więcej powiadomień z {{PLURAL:$5|innej wiki|$5 innych wiki}}"
}
diff --git a/Echo/i18n/pms.json b/Echo/i18n/pms.json
index d68c3448..cc837f13 100644
--- a/Echo/i18n/pms.json
+++ b/Echo/i18n/pms.json
@@ -37,12 +37,9 @@
"echo-pref-tooltip-reverted": "Aviseme cand cheidun a anula na modìfica che mi i l'hai fàit, an dovrand l'utiss d'anulament o d'artorn andaré.",
"echo-pref-tooltip-mention": "Aviseme cand cheidun a buta na liura vers mia pàgina d'utent.",
"echo-pref-tooltip-user-rights": "Aviseme cand cheidun a modìfica ij mè drit d'utent.",
- "echo-no-agent": "[Gnun]",
- "echo-no-title": "[Gnun-a pàgina]",
"echo-error-no-formatter": "Gnun formà definì për la notìfica",
"notifications": "Notìfiche",
"tooltip-pt-notifications-alert": "{{GENDER:|Soe}} alerte",
- "tooltip-pt-notifications-message": "{{GENDER:|Sò}} mëssagi",
"echo-specialpage": "Notìfiche",
"echo-anon": "Për arseive dle notìfiche, <span class=\"plainlinks\">[$1 ch'a crea un cont] o <span class=\"plainlinks\">[$2 ch'a intra ant ël sistema].",
"echo-none": "A l'ha gnun-e notìfiche.",
@@ -53,48 +50,17 @@
"notification-link-text-view-changes": "Smon-e le modìfiche",
"notification-link-text-view-page": "Smon-e la pàgina",
"notification-link-text-view-edit": "Smon-e la modìfica",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|a l'ha lassà}} un mëssagi dzora a soa [[User talk:$2#$3|pàgina ëd ciaciarade]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|a l'ha lassà}} un mëssagi an soa pàgina ëd ciaciarade an «[[User talk:$2#$3|$4]]».",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|a l'ha lassà}} un mëssagi dzora soa [[User talk:$2#$3|pàgina ëd ciaciarade]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|a l'ha lassà}} un mëssagi su soa pàgina ëd ciaciarade an «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "[[:$2]] a l'é stàit {{GENDER:$1|colegà}} da [[:$3]]. [[Special:WhatLinksHere/$2|Vëdde tute le liure a costa pàgina]].",
- "notification-page-linked-flyout": "[[:$2]] a l'é stàit {{GENDER:$1|colegà}} da [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|a l'ha comentà}} su «[[$3|$2]]» an sla pàgina ëd discussion «$4»",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|a l'ha publicà}} n'argoment neuv «$2» dzor [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|a l'ha manda}}te un mëssagi: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|a l'ha comentà}} dzor «[[$3#$2|$2]]» su soa pàgina ëd ciaciarade",
- "notification-mention": "[[User:$1|$1]] a l'ha {{GENDER:$1|massionalo|massionala}} an sla pàgina ëd ciaciarade ëd $5 an «[[:$3#$2|$4]]».",
- "notification-mention-flyout": "$1 {{GENDER:$1|a l'ha massionalo|a l'ha massionala}} ant la pàgina ëd discussion ëd $5 an «[[:$3#$2|$4]]».",
- "notification-mention-nosection": "[[User:$1|$1]] a l'ha {{GENDER:$1|massionalo|massional}} ant la [[:$3|pàgina ëd discussion ëd $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|a l'ha massionalo|a l'ha massionala}} an sla [[:$3|pàgina ëd discussion ëd $2]].",
- "notification-user-rights": "Ij sò drit d'utent [[Special:Log/rights/$1|a son ëstàit {{GENDER:$1|modificà}}]] da [[User:$1|$1]]. $2. [[Special:ListGroupRights|Savèjne ëd pi]]",
- "notification-user-rights-flyout": "Ij sò drit d'utent a son ëstàit {{GENDER:$1|modificà}} da $1. $2. [[Special:ListGroupRights|Savèjne ëd pi]]",
- "notification-user-rights-add": "Adess a l'é mèmber ëd {{PLURAL:$2|costa partìa|coste partìe}}: $1",
- "notification-user-rights-remove": "A l'é pi nen mèmber ëd {{PLURAL:$2|costa partìa|coste partìe}}: $1",
- "notification-new-user": "Bin-ëvnù su {{SITENAME}}, $1! I soma content ch'a l'é ambelessì.",
- "notification-reverted2": "{{PLURAL:$4|Soa modìfica dzor [[:$2]] a l'é stàita|Soe modìfiche dzor [[:$2]] a son stàite}} {{GENDER:$1|ripristinà}} da [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Soa modìfica dzor $2 a l'é stàita|Soe modìfiche dzor $2 a son stàite}} {{GENDER:$1|ripristinà}} da $1 $3",
+ "notification-header-reverted": "{{PLURAL:$4|Soa modìfica dzor $3 a l'é stàita|Soe modìfiche dzor $3 a son stàite}} {{GENDER:$2|ripristinà}} da $1",
"notification-edit-talk-page-email-subject2": "$1 a l'ha {{GENDER:$1|lassaje}} un mëssagi su {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|a l'ha lassà}} un mëssadi dzora soa pàgina ëd ciaciarade:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|a l'ha lassà}} un mëssagi su soa pàgina ëd discussion an «$2».",
"notification-page-linked-email-subject": "Soa pàgina a l'é stàita sità su {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 a l'é stàit {{GENDER:$1|sità}} da $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Soa modìfica a l'é stàita|Soe modìfiche a son ëstàite}} {{GENDER:$1|anulà}} su {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Soa modìfica a $2 a l'é stàita|Soe modìfiche a $2 a son stàite}} {{GENDER:$1|anulà}} da $1.",
"notification-mention-email-subject": "$1 a l'ha {{GENDER:$1|massionalo|massionala}} su {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 a l'ha {{GENDER:$1|massionalo|massionala}} ant lapàgina ëd discussion ëd $4 an «$3».",
- "notification-mention-nosection-email-batch-body": "$1 a l'ha {{GENDER:$1|massionalo|massionala}} ant la pàgina ëd discussion ëd $2.",
"notification-user-rights-email-subject": "Ij sò drit d'utent a son ëstàit modificà su {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Ij sò drit d'utent a son ëstàit {{GENDER:$1|modificà}} da $1. $2.",
- "echo-email-subject-default": "Notìfiche neuve a {{SITENAME}}",
"echo-email-body-default": "It l'has na notìfica neuva a {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "A l'ha na neuva notìfica.",
"echo-email-footer-default": "$2\n\nPër controlé che mëssagi i-j mandoma, ch'a contròla ij sò gust:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Për controlé che mëssagi i-j mandoma, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">ch'a contròla ij sò gust</a>.<br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|Avis ($1)|100=Avis (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Mëssagi ($1)|100=Mëssagi (99+)}}",
"echo-notification-alert-text-only": "Avis",
- "echo-notification-message-text-only": "Mëssagi",
"echo-overlay-link": "Tute le notìfiche",
"echo-overlay-title": "<b>Notìfiche</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notìfiche}}</b> (as na mostro $1 ëd $2 nen lesùe)",
@@ -102,33 +68,9 @@
"echo-date-today": "Ancheuj",
"echo-date-yesterday": "Jer",
"echo-load-more-error": "A l'é capitaje n'eror an recuperand pi d'arzultà.",
- "notification-edit-talk-page-bundle": "$1 e $3 {{PLURAL:$4|àutr a l'ha|àutri a l'han}} {{GENDER:$1|lassà}} un mëssagi su soa [[User talk:$2|pàgina dle ciaciarade]].",
- "notification-page-linked-bundle": "$2 a l'é stàit {{GENDER:$1|colegà}} da $3 e $4 {{PLURAL:$5|àutra pàgina|àutre pàgine}}. [[Special:WhatLinksHere/$2|Vëdde tute le liure a costa pàgina]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e $2 {{PLURAL:$3|àutr|àutri}} a l'han {{GENDER:$1|lassà}} un mëssagi su soa pàgina dle ciaciarade.",
- "notification-page-linked-email-batch-bundle-body": "$2 a l'é stàit {{GENDER:$1|colegà}} da $3 e $4 {{PLURAL:$5|àutra pàgina|àutre pàgine}}.",
"echo-email-batch-subject-daily": "A l'ha {{PLURAL:$2|na notìfica neuva|dle notìfiche neuve}} su {{SITENAME}}",
"echo-email-batch-subject-weekly": "A l'ha {{PLURAL:$2|na notìfica neuva|dle notìfiche neuve}} su {{SITENAME}} sta sman-a",
"echo-email-batch-body-intro-daily": "Cerea $1\nValà un resumé dl'atività d'ancheuj su {{SITENAME}} për chiel.",
"echo-email-batch-body-intro-weekly": "Cerea $1,\nValà un resumé dl'atività dë sta sman-a su {{SITENAME}} për chiel.",
- "echo-email-batch-link-text-view-all-notifications": "Vëdde tute le notìfiche",
- "echo-rev-deleted-text-view": "Costa revision ëd pàgina a l'é stàita scancelà.",
- "apihelp-echomarkread-description": "Marché le notìfiche coma lesùe për l'utent atual.",
- "apihelp-echomarkread-param-list": "Na lista d'ID ëd notìfica da marché coma lesù.",
- "apihelp-echomarkread-param-all": "Si definì, a marca tute le notìfiche ëd n'utent coma lesùe.",
- "apihelp-echomarkread-param-sections": "Na lista ëd session da marché coma lesùe.",
- "apihelp-echomarkread-example-1": "Marché la notìtica 8 coma lesùa",
- "apihelp-echomarkread-example-2": "Marché tute le notìfiche coma lesùe",
- "apihelp-query+notifications-description": "Oten-e le notìfiche an atèisa për l'utent atual.",
- "apihelp-query+notifications-param-prop": "Detaj da ciamé.",
- "apihelp-query+notifications-param-sections": "Le session ëd notìfica da ciamé.",
- "apihelp-query+notifications-param-groupbysection": "S'a venta argropé j'arzultà për session. Minca na session a l'é analisà për sò cont s'a l'é definì.",
- "apihelp-query+notifications-param-format": "Si spessificà, le notìfiche a sarà mandà ant ës formà.",
- "apihelp-query+notifications-param-limit": "Ël nùmer màssim ëd notìfiche da mandé.",
- "apihelp-query+notifications-param-index": "Si spessificà, na lista d'ID ëd notìfica, an órdin, a sarà smonùa.",
- "apihelp-query+notifications-param-alertcontinue": "Cand a son disponìbij vàire arzultà d'alerta, dovré sòn për andé anans.",
- "apihelp-query+notifications-param-alertunreadfirst": "S'a venta smon-e prima le notìfiche dij mëssagi nen lesù.",
- "apihelp-query+notifications-param-messagecontinue": "Cand vàire arzultà ëd mëssagi a son disponìbij, dovré sòn për andé anans.",
- "apihelp-query+notifications-param-messageunreadfirst": "S'a venta smon-e prima le notìfiche d'alerta nen lesùe.",
- "apihelp-query+notifications-example-1": "Listé le modìfiche",
- "apihelp-query+notifications-example-2": "Lista dle notìfiche, argropà për session, con ij conteur"
+ "echo-email-batch-link-text-view-all-notifications": "Vëdde tute le notìfiche"
}
diff --git a/Echo/i18n/pnb.json b/Echo/i18n/pnb.json
index 9ae409cb..88f0bd51 100644
--- a/Echo/i18n/pnb.json
+++ b/Echo/i18n/pnb.json
@@ -1,8 +1,10 @@
{
"@metadata": {
"authors": [
- "Khalid Mahmood"
+ "Khalid Mahmood",
+ "Saanvel",
+ "Abbas dhothar"
]
},
- "tooltip-pt-notifications": "تواڈیاں دساں"
+ "tooltip-pt-notifications-alert": "{{GENDER:|Your}} الرٹس"
}
diff --git a/Echo/i18n/ps.json b/Echo/i18n/ps.json
index 970f97f8..b3245fd1 100644
--- a/Echo/i18n/ps.json
+++ b/Echo/i18n/ps.json
@@ -21,49 +21,66 @@
"echo-pref-email-frequency-weekly": "د يادگيرنو يو اونيز لنډيز",
"echo-pref-email-format-html": "اچ ټي ام اېل",
"echo-pref-email-format-plain-text": "ساده متن",
+ "echo-pref-cross-wiki-notifications": "له نورو ويکي گانو څخه خبرونې ښکاره کول",
"echo-pref-new-message-indicator": "زما په توکپټه کې د خبرو اترو پيغام ښودونکی ښکاره کول",
+ "echo-pref-beta-feature-cross-wiki-message": "پرمختللې خبرونې",
"echo-learn-more": "نور څه زده کول",
"echo-new-messages": "تاسې نوي پيغامونه لرئ",
"echo-category-title-edit-user-talk": "خبرو اترو مخ {{PLURAL:$1|پيغام|پيغامونه}}",
"echo-category-title-article-linked": "مخ {{PLURAL:$1|تړنه|تړنې}}",
"echo-category-title-other": "{{PLURAL:$1|نور}}",
"echo-category-title-system": "{{PLURAL:$1|غونډال}}",
- "echo-no-agent": "[هېڅوک]",
- "echo-no-title": "[هېڅ مخ]",
+ "echo-category-title-user-rights": "{{PLURAL:$1|کارن رښتې بدلون|کارن رښتو بدلونونه}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|له بل کارن څخه برېښليک اخيستل|له نورو کارنانو څخه برېښليکونه اخيستل}}",
"notifications": "يادگيرنې",
"tooltip-pt-notifications-alert": "{{GENDER:|ستاسې}} خبرونې",
- "tooltip-pt-notifications-message": "{{GENDER:|ستاسې}} پيغامونه",
+ "tooltip-pt-notifications-notice": "{{GENDER:|ستاسې}} خبرونې",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "نوي کارنان",
"echo-specialpage": "يادگيرنې",
+ "echo-specialpage-markasread": "خبرېدنه: د لوستلي په توگه په نخښه کول",
"echo-anon": "د يادگيرنو اخيستلو لپاره، [$1 يو گڼون جوړ کړئ] او يا هم [$2 ورننوځئ].",
"echo-none": "تاسې هېڅ يادگيرنې نه لرئ.",
"echo-more-info": "نور مالومات",
"echo-feedback": "غبرگون",
+ "echo-notification-placeholder": "کومې خبرونې نشته.",
+ "echo-notification-markasread": "ټول لوستی په نخښه کول",
+ "echo-notification-markasread-tooltip": "لوستی په نخښه کول",
+ "echo-notification-more-options-tooltip": "نورې خوښنې",
+ "notification-link-text-expand-all": "غځول",
+ "notification-link-text-collapse-all": "پرځول",
"notification-link-text-view-message": "پيغام کتل",
"notification-link-text-view-mention": "يادگيرنه کتل",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|يادگيرنه کتل|يادگيرنې کتل}}",
"notification-link-text-view-changes": "بدلونونه کتل",
"notification-link-text-view-page": "مخ کتل",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$3|ستاسې}} د خبرو اترو په مخ يو پيغام {{GENDER:$2|پرېښوده}}.",
+ "notification-link-text-what-links-here": "همدې مخ سره ټولې تړنې",
+ "notification-header-mention-success": "{{GENDER:$2|ستاسې}} يادونه د $3 ولېږل شوه.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|تاسې ياد کړی}}:</strong> $3",
+ "notification-welcome-linktext": "ښه راغلئ",
"notification-link-text-view-edit": "سمون کتل",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] ستاسې د خبرو اترو پر مخ يو پيغام په \"[[User talk:$2#$3|$4]]\" کې {{GENDER:$1|پرېښوده}} .",
- "notification-edit-talk-page-flyout-with-section": "$1 ستاسې د خبرو اترو پر مخ يو پيغام په \"[[User talk:$2#$3|$4]]\" کې {{GENDER:$1|پرېښود}}.",
- "notification-page-linked": "[[:$2]] له [[:$3]] سره {{GENDER:$1|تړل شوی}}. [[Special:WhatLinksHere/$2|دې مخ سره ټولې تړنې وگورئ]].",
- "notification-page-linked-flyout": "[[:$2]] له [[:$3]] سره {{GENDER:$1|وتړل شو}}.",
- "notification-new-user": "$1 {{SITENAME}} ته ښه راغلې!، موږ خوښ يو چې تاسې دلته ياست.",
- "notification-edit-talk-page-email-batch-body2": "$1 ستاسې د خبرو اترو په مخ يو پيغام {{GENDER:$1|پرېښوده}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 ستاسې د خبرو اترو پر مخ يو پيغام په \"$2\" کې {{GENDER:$1|پرېښود}}.",
"notification-page-linked-email-subject": "يو مخ چې تاسې جوړ کړی، په {{SITENAME}} يې تړنه جوړه شوه",
- "notification-page-linked-email-batch-body": "[[:$2]] له [[:$3]] سره {{GENDER:$1|تړل شوی}}.",
- "echo-email-subject-default": "په {{SITENAME}} باندې نوې يادگيرنه",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1د}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1گ}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1و}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1م}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1ک}}",
+ "notification-timestamp-today": "نن",
+ "notification-timestamp-yesterday": "پرون",
+ "notification-inbox-filter-read": "لوستل",
+ "notification-inbox-filter-unread": "نالوستل",
+ "notification-inbox-filter-all": "ټول",
"echo-email-body-default": "تاسې په {{SITENAME}} باندې يوه نوې يادگيرنه لرئ:\n\n$1",
- "echo-email-batch-body-default": "تاسې يوه نوې يادگيرنه لرئ.",
- "echo-notification-message": "{{PLURAL:$1|پيغام ($1)|پيغامونه ($1)|100=پيغامونه (99+)}}",
+ "echo-email-html-footer-preference-link-text": "خپل غوره توبونه وڅارئ",
+ "echo-notification-notice": "{{PLURAL:$1|يادښت ($1)|يادښتونه ($1)|100=يادښتونه (99+)}}",
"echo-notification-alert-text-only": "خبرونې",
- "echo-notification-message-text-only": "پيغامونه",
+ "echo-notification-notice-text-only": "يادښتونه",
"echo-overlay-link": "ټولې يادگيرنې",
"echo-overlay-title": "<b>يادگيرنې</b>",
"echo-overlay-title-overflow": "<b>يادگيرنې</b> (د$2 څخه $1 نالوستلي ښکاره کول)",
"echo-mark-all-as-read": "ټول لوستی په نخښه کول",
"echo-date-today": "نن",
"echo-date-yesterday": "پرون",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 او $2 {{PLURAL:$3|نور|نورو}} يو پيغام ستاسې د خبرو اترو په مخ {{GENDER:$1|پرېښوده}}.",
"echo-email-batch-link-text-view-all-notifications": "ټولې يادگيرنې کتل"
}
diff --git a/Echo/i18n/pt-br.json b/Echo/i18n/pt-br.json
index 540528f5..5203fcae 100644
--- a/Echo/i18n/pt-br.json
+++ b/Echo/i18n/pt-br.json
@@ -9,112 +9,215 @@
"TheGabrielZaum",
"Rodrigo codignoli",
"Dianakc",
- "He7d3r"
+ "He7d3r",
+ "Almondega",
+ "TheEduGobi",
+ "Macofe",
+ "Luk3",
+ "Anderson Costa",
+ "Peter Fernando",
+ "Cristofer Alves",
+ "Hamilton Abreu",
+ "Felipe L. Ewald"
]
},
- "echo-desc": "Sistema de notificações",
+ "echo-desc": "Sistema para notificar usuários sobre eventos e mensagens",
"prefs-echo": "Notificações",
- "prefs-emailsettings": "Opções de email",
+ "prefs-emailsettings": "Opções de e-mail",
"prefs-displaynotifications": "Opções de exibição",
- "prefs-echosubscriptions": "Notifique-me sobre esses eventos",
+ "prefs-echosubscriptions": "Notificar-me sobre estes eventos",
+ "prefs-echocrosswiki": "Notificações entre-wikis",
"prefs-newmessageindicator": "Indicador de nova mensagem",
+ "prefs-blocknotificationslist": "Lista de bloqueios",
"echo-pref-send-me": "Envie-me:",
"echo-pref-send-to": "Envie para:",
- "echo-pref-email-format": "Formato do email:",
+ "echo-pref-email-format": "Formato de e-mail:",
"echo-pref-web": "Web",
- "echo-pref-email": "Email",
- "echo-pref-email-frequency-never": "Não me envie notificações por email",
+ "echo-pref-email": "E-mail",
+ "echo-pref-email-frequency-never": "Não me envie notificações por e-mail",
"echo-pref-email-frequency-immediately": "Notificações individuais conforme cheguem",
"echo-pref-email-frequency-daily": "Um resumo diário das notificações",
"echo-pref-email-frequency-weekly": "Um resumo semanal das notificações",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Texto simples",
- "echo-pref-notify-show-link": "Exibir notificações na minha barra de ferramentas",
+ "echo-pref-cross-wiki-notifications": "Mostrar notificações de outras wikis",
+ "echo-pref-notifications-blacklist": "Lista de nomes de usuários que estão na lista negra de ativar a maioria das notificações do Echo (as edições na página de conversa do usuário ainda serão acionadas para notificações)",
"echo-pref-new-message-indicator": "Exibir indicador de mensagem na página de discussão em minha barra de ferramentas",
+ "echo-pref-beta-feature-cross-wiki-message": "Notificações aprimoradas",
+ "echo-pref-beta-feature-cross-wiki-description": "Confira e organize as suas notificações mais facilmente. Inclui notificações globais, o que lhe permite verificar as suas mensagens provenientes de outras wikis. (Para receber notificações globais em uma wiki específica deverá ativar a funcionalidade beta na respetiva wiki.)",
"echo-learn-more": "Saiba mais",
+ "echo-log": "Registro Público",
"echo-new-messages": "Você tem novas mensagens",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mensagem|Mensagens}} na página de discussão",
- "echo-category-title-article-linked": "{{PLURAL:$1|Link|Links}} para a página",
+ "echo-category-title-article-linked": "{{PLURAL:$1|Ligação|Ligações}} para a página",
"echo-category-title-reverted": "{{PLURAL:$1|Edição revertida|Edições revertidas}}",
"echo-category-title-mention": "{{PLURAL:$1|Menção|Menções}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Mensão falhou|Menções falharam}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Mensão realizada|Menções realizadas}}",
"echo-category-title-other": "{{PLURAL:$1|Outro|Outros}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema|Sistemas}}",
- "echo-pref-tooltip-edit-user-talk": "Notifique-me quando alguém publicar ou responder em minha página de discussão.",
- "echo-pref-tooltip-article-linked": "Notifique-me quando alguém criar um link através de artigo para uma página criada por mim.",
- "echo-pref-tooltip-reverted": "Notifique-me quando alguém reverter uma edição minha utilizando a função desfazer ou a ferramenta de reversão.",
- "echo-pref-tooltip-mention": "Notifique-me quando alguém criar ligações à minha página de usuário em qualquer página de discussão.",
- "echo-no-agent": "[Ninguém]",
- "echo-no-title": "[Nenhuma página]",
- "echo-error-no-formatter": "Nenhum formato definido para notificações",
- "echo-error-preference": "Erro: Não foi possível configurar as preferências do usuário.",
- "echo-error-token": "Erro: Não foi possível receber token do usuário.",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Alteração de permissões de usuário|Alterações de permissões de usuário}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-mail de outro usuário|E-mails de outros usuários}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Lembrete|Lembretes}} de página",
+ "echo-pref-tooltip-edit-user-talk": "Notifique-me quando alguém publicar uma mensagem ou respostas na minha página de discussão.",
+ "echo-pref-tooltip-article-linked": "Notifique-me quando alguém criar um link para uma página que criei a partir de uma página de artigo.",
+ "echo-pref-tooltip-reverted": "Notifique-me quando alguém reverter uma edição que fiz usando desfazer ou a ferramenta de reversão.",
+ "echo-pref-tooltip-mention": "Notificar-me quando alguém criar links para a minha página de usuário.",
+ "echo-pref-tooltip-mention-failure": "Avise-me quando eu não puder enviar uma menção a alguém.",
+ "echo-pref-tooltip-mention-success": "Notifique me quando eu enviar uma menção para alguém.",
+ "echo-pref-tooltip-user-rights": "Notificar-me quando alguém alterar minhas permissões de usuário.",
+ "echo-pref-tooltip-emailuser": "Notificar-me quando alguém me enviar um email.",
+ "echo-pref-tooltip-article-reminder": "Avise-me sobre esta página quando eu perguntar.",
+ "echo-error-no-formatter": "Nenhum formato definido para notificações.",
"notifications": "Notificações",
- "tooltip-pt-notifications": "Suas notificações",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Seus}} alertas",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Suas}} notificações",
+ "echo-displaynotificationsconfiguration": "Configuração de notificações de exibição",
+ "echo-displaynotificationsconfiguration-summary": "Esta é uma visão geral de como as Notificações são configuradas nesta wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notificações por categoria",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Classificação de tipos",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Qual seção cada tipo de notificação é classificada em",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Métodos de notificação permitidos",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Quais os métodos de notificação são suportados para cada categoria",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Quais métodos de notificação são suportados para cada tipo; Aplica-se apenas a tipos dentro de categorias escondidas das preferências",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Habilitado por padrão",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Usuários existentes",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Novos usuários",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Métodos de notificação necessários",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Quais os métodos de notificação são obrigatórios para cada categoria",
"echo-specialpage": "Notificações",
+ "echo-specialpage-section-markread": "Marcar como grupo como lido",
+ "echo-specialpage-markasread": "Notificação: Marcar como lida",
+ "echo-specialpage-markasread-invalid-id": "ID do evento inválido",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notificação|notificações}}",
+ "echo-specialpage-pagination-range": "$1 - $2",
+ "echo-specialpage-pagefilters-title": "Atividades recentes",
+ "echo-specialpage-pagefilters-subtitle": "Páginas com notificações não lidas",
+ "notificationsmarkread-legend": "Marcar a notificação como lida",
"echo-anon": "Para receber notificações, [$1 crie uma conta] ou [$2 registre-se].",
"echo-none": "Você não tem notificações.",
"echo-more-info": "Mais informações",
"echo-feedback": "Comentários",
+ "echo-popup-footer-special-page-invitation": "<strong>Experimente a página de Notificações redesenhada.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Todos os novos looks e recursos.",
+ "echo-quotation-marks": "\"$1\"",
+ "echo-api-failure": "Não foi possível recuperar as notificações.",
+ "echo-api-failure-cross-wiki": "O acesso ao domínio remoto foi negado.",
+ "echo-notification-placeholder": "Não há notificações.",
+ "echo-notification-placeholder-filters": "Não há notificações que correspondam a esses critérios.",
+ "echo-notification-loginrequired": "Você deve autenticar-se para ver suas notificações.",
+ "echo-notification-popup-loginrequired": "Autentique-se para ver suas notificações.",
+ "echo-notification-markasread": "Marcar como lida",
+ "echo-notification-markasunread": "Marcar como não lida",
+ "echo-notification-markasread-tooltip": "Marcar como lida",
+ "echo-notification-more-options-tooltip": "Mais opções",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Parar}} de vigiar nova atividade em \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Você}} não está mais vigiando a página \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Você}} pode vigiar [$2 esta página] a qualquer momento.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Siga}} novas atividades em \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Você}} agora estão vigiando a página \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Você}} pode parar de vigiar [$2 essta página] a qualquer momento.",
+ "notification-link-text-expand-all": "Expandir",
+ "notification-link-text-expand-alert-count": "Ver {{PLURAL:$1|$1 alerta|$1 alertas}}",
+ "notification-link-text-expand-notice-count": "Ver {{PLURAL:$1|$1 notificação|$1 notificações}}",
+ "notification-link-text-expand-all-count": "Ver {{PLURAL:$1|$1 notificação|$1 notificações}}",
+ "notification-link-text-collapse-all": "Recolher",
"notification-link-text-view-message": "Ver mensagem",
"notification-link-text-view-mention": "Ver menção",
- "notification-link-text-view-changes": "Ver mudanças",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Ver menção|Ver menções}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Ver}} mudanças",
"notification-link-text-view-page": "Ver página",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|deixou}} uma mensagem na '''{{GENDER:$3|sua}} página de discussão'''.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|deixou}} uma mensagem na <strong>{{GENDER:$3|sua}} página de discussão</strong> em “<strong>$4</strong>”.",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Uma ligação foi criada de <strong>$4</strong> para <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Vinculado de <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Ligações foram criadas de {{PLURAL:$5||$5 páginas|100=99+ páginas}} para <strong>$3</strong>.",
+ "notification-header-article-reminder": "Uma página que {{GENDER:$2|você}} pediu para se lembrar sobre está em <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Todas as ligações para esta página",
+ "notification-header-mention-other": "$1 {{GENDER:$2|mencionou}} {{GENDER:$3|você}} em <strong>$4</strong>, \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|mencionou}} {{GENDER:$3|você}} em <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|mencionou}} {{GENDER:$3|você}} <strong>na página de discussão {{GENDER:$5|do|da}} $4</strong> em \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|mencionou}} {{GENDER:$3|você}} <strong>na página de discussão {{GENDER:$5|do|da}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|mencionou}} {{GENDER:$3|você}} <strong>na página de discussão {{GENDER:$2|dele|dela}}</strong> em \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|mencionou}} {{GENDER:$3|você}} <strong>na página de discussão {{GENDER:$2|dele|dela}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|mencionou}} {{GENDER:$3|você}} na página de discussão <strong>$4</strong> em \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|mencionou}} {{GENDER:$3|você}} na página de discussão <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Sua}} menção de <strong>$3</strong> não foi enviada porque o usuário não foi encontrado.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Sua}} menção de <strong>$3</strong> não foi enviada porque o usuário é anônimo.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Você}} tentou mencionar mais de $3{{PLURAL:$3|usuário|usuários}}. Todas as menções acima desse limite não foram enviadas.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Uma menção|$3 menções}} {{GENDER:$2|que você fez}} na página de discussão de <strong>$4</strong> {{PLURAL: $3|não pode ser enviada|não puderam ser enviadas}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Nome de usuário não existe:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IPs não podem ser mencionados:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Sua}} menção de <strong>$3</strong> foi enviada.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Uma menção|$3 menções}} {{GENDER:$2|que você fez}} na página de discussão de <strong>$4</strong> {{PLURAL: $3|foi enviada|foram enviadas}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Você mencionou}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Uma notificação|$3 notificações}} sobre menções {{GENDER:$2|que você fez}} na página de discussão de <strong>$4</strong>: {{PLURAL:$5|$5 não enviada}}, {{PLURAL:$6|$6 enviada}}.",
+ "notification-header-user-rights-add-only": "Os seus direitos de {{GENDER:$4|usuário|usuária}} foram {{GENDER:$1|alterados}}. Você foi adicionado a: $2.",
+ "notification-header-user-rights-remove-only": "Os {{GENDER:$4|seus}} privilégios foram {{GENDER:$1|alterados}}. Não pertence mais a: $2.",
+ "notification-header-user-rights-add-and-remove": "Os {{GENDER:$6|seus}} privilégios foram {{GENDER:$1|alterados}}. Foi {{GENDER:$6|adicionado|adicionada|adicionado(a)}} a: $2. Não pertence mais a: $4.",
+ "notification-header-user-rights-expiry-change": "A expiração de {{GENDER:$4|sua}} associação {{PLURAL:$3|no seguinte grupo|nos seguintes grupos}} foi {{GENDER:$1|modificado|modificada}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Bem-vindo|Bem-vinda}} ao site {{SITENAME}}, $1! Estamos contentes por ter {{GENDER:$2|você}} aqui.",
+ "notification-welcome-linktext": "Bem-vindo(a)",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Você}} acaba de fez {{GENDER:$2|sua}} primeira edição; {{GENDER:$2|Obrigado e seja bem-vindo!|Obrigada e seja bem-vinda!}}",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Você}} acaba de fez {{GENDER:$2|sua}} décima edição; {{GENDER:$2|Obrigado|Obrigada}} e continue por aí!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Você}} acaba de fez {{GENDER:$2|sua}} centésima edição; Agradeço {{GENDER:$2|Muito obrigado!|Muito obrigada!}}",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Você}} acaba de fez {{GENDER:$2|sua}} milésima edição; {{GENDER:$2|Muito obrigado por ser um grande contribuidor!|Muito obrigada por ser uma grande contribuidora!}}",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Você}} acaba de fez {{GENDER:$2|sua}} décima milésima edição; {{GENDER:$2|Muito obrigado!|Muito obrigada!}}",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Você}} acaba de fez {{GENDER:$2|sua}} centésima milésima edição; {{GENDER:$2|Muito obrigado|Muito obrigada}} por uma incrível contribuição!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Você}} acaba de fez {{GENDER:$2|sua}} milionésima edição; {{GENDER:$2|Muito obrigado|Muito obrigada}} por uma contribuição surpreendente!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Sua}} edição",
"notification-link-text-view-edit": "Ver edição",
- "notification-edit-talk-page2": "[[User:$1|$1]] deixou uma mensagem em sua [[User talk:$2#$3|página de discussão]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] deixou uma mensagem em sua página de discussão em \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 deixou uma mensagem em sua [[User talk:$2#$3|página de discussão]].",
- "notification-edit-talk-page-flyout-with-section": "$1 deixou uma mensagem em sua página de discussão em \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Foi criado um {{GENDER:$1|link}} à página [[:$2]] a partir de [[:$3]]. [[Special:WhatLinksHere/$2|Veja todos os links para esta página]].",
- "notification-page-linked-flyout": "Foi criada uma {{GENDER:$1|ligação}} à página [[:$2]] a partir de [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] comentou em \"[[$3|$2]]\" na página de discussão \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] adicionou um novo tópico \"$2\" em [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] enviou-lhe uma mensagem: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] comentou em \"[[$3#$2|$2]]\" na sua página de discussão.",
- "notification-mention": "[[User:$1|$1]] mencionou você na página de discussão $5 em \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 mencionou você na página de discussão $5 em \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] mencionou você na [[:$3|página de discussão de $2]].",
- "notification-mention-nosection-flyout": "$1 mencionou você na [[:$3|página de discussão de $2]].",
- "notification-user-rights": "Seus direitos de usuário [[Special:Log/rights/$1|foram alterados]] {{GENDER:$1|pelo|pela|por}} [[User:$1|$1]]. $2. [[Special:ListGroupRights|Saiba mais]]",
- "notification-user-rights-flyout": "Seus direitos de usuário foram alterados {{GENDER:$1|pelo|pela|por}} $1. $2. [[Special:ListGroupRights|Saiba mais]]",
- "notification-user-rights-add": "Você agora é membro {{PLURAL:$2|deste grupo|destes grupos}}: $1",
- "notification-user-rights-remove": "Você não é mais membro {{PLURAL:$2|deste grupo|destes grupos}}: $1",
- "notification-new-user": "Bem-vindo(a) ao site {{SITENAME}}, $1! Estamos felizes por você estar aqui.",
- "notification-reverted2": "{{PLURAL:$4|Sua edição em [[:$2]] foi revertida|Suas edições em [[:$2]] foram revertidas}} {{GENDER:$1|pelo|pela|por}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Sua edição em $2 foi revertida|Suas edições em $2 foram revertidas}} {{GENDER:$1|pelo|pela|por}} $1. $3",
- "notification-edit-talk-page-email-subject2": "$1 deixou uma mensagem para você em {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 deixou uma mensagem na sua página de discussão:",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 deixou uma mensagem na sua página de discussão em \"$2\".",
+ "notification-link-article-reminder": "Ver página",
+ "notification-header-reverted": "{{PLURAL:$4|Sua edição em <strong>$3</strong> foi {{GENDER:$2|revertida}}|Suas edições em <strong>$3</strong> foram {{GENDER:$2|revertidas}}}}.",
+ "notification-body-reverted": "$1",
+ "notification-header-emailuser": "$1 {{GENDER:$2|enviou}} um e-mail para você.",
+ "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|deixou}} uma mensagem para você em {{SITENAME}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|ldeixou}} uma mensagem na sua página de discussão em \"$2\".",
"notification-page-linked-email-subject": "A pagina que você criou foi lincada em {{SITENAME}}",
- "notification-page-linked-email-batch-body": "A página $2 foi {{GENDER:$1|ligada}} a partir de $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Sua edição foi revertida|Suas edições foram revertidas}} {{GENDER:$1|em}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Sua edição em $2 foi revertida|Suas edições em $2 foram revertidas}} {{GENDER:$1|pelo|pela|por}} $1.",
- "notification-mention-email-subject": "$1 mencionou você em {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 mencionou você na página de discussão de $4 em \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 mencionou você na página de discussão de $2.",
- "notification-user-rights-email-subject": "Seus direitos de usuários mudaram na {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Seus direitos de usuário foram alterados por $1. $2.",
- "echo-email-subject-default": "Nova notificação em {{SITENAME}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|mencionou}} {{GENDER:$2|você}} em {{SITENAME}}",
+ "notification-user-rights-email-subject": "Seus direitos de usuários mudaram em {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1a}}",
+ "notification-timestamp-today": "Hoje",
+ "notification-timestamp-yesterday": "Ontem",
+ "notification-inbox-filter-read": "Ler",
+ "notification-inbox-filter-unread": "Não lidas",
+ "notification-inbox-filter-all": "Todas",
"echo-email-body-default": "Você tem uma nova notificação em {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Você tem uma nova notificação.",
- "echo-email-footer-default": "$2\n\nPara controlar quais emails enviamos a você, confira suas preferências: {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Para controlar quais emails enviamos a você, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">confira suas preferências</a>.<br /> $1",
+ "echo-email-footer-default-html": "Para controlar quais os e-mails que lhe enviamos, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">verifique suas preferências</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPara controlar quais emails enviamos a você, confira suas preferências: \n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Para controlar quais e-mails enviamos para {{GENDER:$1|você}}, verifique {{GENDER:$1|suas}} preferências:",
+ "echo-email-html-footer-preference-link-text": "verifique {{GENDER:$1|suas}} preferências",
+ "echo-email-html-footer-with-link": "Para controlar quais e-mails enviamos {{GENDER:$2|você}}, $1.",
"echo-notification-alert": "{{PLURAL:$1|Alerta ($1)|Alertas ($1)|100=Alertas (+99)}}",
- "echo-notification-message": "{{PLURAL:$1|Mensagem ($1)|Mensagens ($1)|100=Mensagens (+99)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Aviso ($1)|Avisos ($1)|100=Avisos (99+)}}",
+ "echo-notification-alert-text-only": "Alertas",
+ "echo-notification-notice-text-only": "Avisos",
"echo-overlay-link": "Todas as notificações",
"echo-overlay-title": "<b>Notificações</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificação|Notificações}}</b> (exibindo $1 de $2 não lidas)",
"echo-mark-all-as-read": "Marcas todas como lidas",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notificação marcada como lida|notificações marcadas como lidas}}",
+ "echo-mark-wiki-as-read": "Marcar tudo como lido na wiki selecionada: $1 \\",
"echo-date-today": "Hoje",
"echo-date-yesterday": "Ontem",
"echo-load-more-error": "Um erro ocorreu ao carregar mais resultados.",
- "notification-edit-talk-page-bundle": "$1 e $3 {{PLURAL:$4|outro|outros}} deixaram uma mensagem em sua [[User talk:$2|página de discussão]].",
- "notification-page-linked-bundle": "Foram criados {{GENDER:$1|links}} à página $2 em $3 e $4 {{PLURAL:$5|outra página|outras páginas}}. [[Special:WhatLinksHere/$2|Veja todos os links para esta página]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e $2 {{PLURAL:$3|outro|outros}} deixaram uma mensagem em sua página de discussão.",
- "notification-page-linked-email-batch-bundle-body": "Foram criados {{GENDER:$1|links}} à página $2 em $3 e $4 {{PLURAL:$5|outra página|outras páginas}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Uma nova mensagem|$1 novas mensagens|100=mais de 99 novas mensagens}} em <strong>{{GENDER:$3|sua}} página de discussão</strong>.",
+ "echo-email-batch-bullet": "•",
"echo-email-batch-subject-daily": "Você tem {{PLURAL:$2|uma nova notificação|novas notificações}} em {{SITENAME}}",
"echo-email-batch-subject-weekly": "Você tem {{PLURAL:$2|uma nova notificação|novas notificações}} em {{SITENAME}} esta semana",
"echo-email-batch-body-intro-daily": "Olá $1,\nAqui está um resumo diário de atividades em {{SITENAME}} para você.",
"echo-email-batch-body-intro-weekly": "Olá $1,\nAqui está um resumo semanal de atividades em {{SITENAME}} para você.",
"echo-email-batch-link-text-view-all-notifications": "Ver todas as notificações",
- "echo-rev-deleted-text-view": "Esta revisão foi ocultada."
+ "notification-header-foreign-alert": "Mais alertas de {{PLURAL:$5|outra wiki|$5 outras wikis}}",
+ "notification-header-foreign-notice": "Mais notificações de {{PLURAL:$5|outra wiki|$5 outras wikis}}",
+ "notification-header-foreign-all": "Mais notificações de {{PLURAL:$5|outra wiki|$5 outras wikis}}",
+ "echo-foreign-wiki-lang": "$1 - $2",
+ "echo-badge-count": "{{PLURAL:$1|$1|100=99+}}"
}
diff --git a/Echo/i18n/pt.json b/Echo/i18n/pt.json
index 74cd4b1a..8d0753ea 100644
--- a/Echo/i18n/pt.json
+++ b/Echo/i18n/pt.json
@@ -10,116 +10,205 @@
"Vitorvicentevalente",
"He7d3r",
"Fúlvio",
- "Jkb8"
+ "Jkb8",
+ "Macofe",
+ "Önni",
+ "Diniscoelho",
+ "Gato Preto",
+ "Mansil",
+ "Hamilton Abreu"
]
},
- "echo-desc": "Sistema de notificações sobre eventos e mensagens para utilizadores",
+ "echo-desc": "Sistema de notificações a utilizadores sobre eventos e mensagens",
"prefs-echo": "Notificações",
- "prefs-emailsettings": "Opções de e-mail",
+ "prefs-emailsettings": "Opções de correio eletrónico",
"prefs-displaynotifications": "Opções de visualização",
- "prefs-echosubscriptions": "Notifique-me sobre estes eventos",
+ "prefs-echosubscriptions": "Notificar-me sobre estes eventos",
+ "prefs-echocrosswiki": "Notificações interwikis",
"prefs-newmessageindicator": "Indicador de nova mensagem",
- "echo-pref-send-me": "Envie-me:",
- "echo-pref-send-to": "Envie para:",
- "echo-pref-email-format": "Formato de e-mail:",
+ "prefs-blocknotificationslist": "Lista de bloqueios",
+ "echo-pref-send-me": "Enviar-me:",
+ "echo-pref-send-to": "Enviar para:",
+ "echo-pref-email-format": "Formato de correio:",
"echo-pref-web": "Web",
- "echo-pref-email": "E-mail",
- "echo-pref-email-frequency-never": "Não me envie notificações por e-mail",
+ "echo-pref-email": "Correio eletrónico",
+ "echo-pref-email-frequency-never": "Não me enviar notificações por correio",
"echo-pref-email-frequency-immediately": "Notificações individuais conforme cheguem",
"echo-pref-email-frequency-daily": "Um resumo diário de notificações",
"echo-pref-email-frequency-weekly": "Um resumo semanal de notificações",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Texto simples",
+ "echo-pref-cross-wiki-notifications": "Mostrar notificações de outras wikis",
+ "echo-pref-notifications-blacklist": "Lista de nomes de utilizador que não podem desencadear a maioria das notificações Echo (as edições da sua página de discussão continuarão a desencadear notificações)",
"echo-pref-new-message-indicator": "Mostrar indicador de mensagem na página de discussão na minha barra de ferramentas",
+ "echo-pref-beta-feature-cross-wiki-message": "Notificações melhoradas",
+ "echo-pref-beta-feature-cross-wiki-description": "Veja e organize as suas notificações mais facilmente. Inclui notificações interwikis, o que lhe permite ver as mensagens provenientes de outras wikis. (Para receber notificações interwikis deverá ativar a funcionalidade beta na respetiva wiki.)",
"echo-learn-more": "Saiba mais",
+ "echo-log": "Registo público",
"echo-new-messages": "Tem novas mensagens",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mensagem|Mensagens}} na página de discussão",
"echo-category-title-article-linked": "{{PLURAL:$1|Ligação|Ligações}} para a página",
"echo-category-title-reverted": "{{PLURAL:$1|Edição revertida|Edições revertidas}}",
"echo-category-title-mention": "{{PLURAL:$1|Menção|Menções}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Menção falhada|Menções falhadas}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Menção efetuada com êxito|Menções efetuadas com êxito}}",
"echo-category-title-other": "{{PLURAL:$1|Outro|Outros}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema|Sistemas}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Alteração de privilégios de utilizador|Alterações de privilégios de utilizador}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Correio eletrónico de outro utilizador|Correio eletrónico de outros utilizadores}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Notificação|Notificações}} de páginas",
"echo-pref-tooltip-edit-user-talk": "Notificar-me quando alguém publicar na minha página de discussão.",
"echo-pref-tooltip-article-linked": "Notificar-me quando alguém interligar uma página criada por mim numa outra.",
"echo-pref-tooltip-reverted": "Notificar-me quando alguém reverter uma edição minha, ao utilizar a função desfazer ou a ferramenta de reversão.",
- "echo-pref-tooltip-mention": "Notificar-me quando alguém mencionar a minha página de utilizador.",
+ "echo-pref-tooltip-mention": "Notificar-me quando alguém criar uma ligação para a minha página de utilizador.",
+ "echo-pref-tooltip-mention-failure": "Notificar-me quando ocorrer um erro ao mencionar alguém.",
+ "echo-pref-tooltip-mention-success": "Notificar-me quando menciono alguém.",
"echo-pref-tooltip-user-rights": "Notificar-me quando os meus privilégios de utilizador forem alterados.",
- "echo-no-agent": "[Ninguém]",
- "echo-no-title": "[Nenhuma página]",
- "echo-error-no-formatter": "Sem formato definido para notificações",
+ "echo-pref-tooltip-emailuser": "Notificar-me quando alguém me enviar um correio.",
+ "echo-pref-tooltip-article-reminder": "Notificar-me acerca desta página a meu pedido.",
+ "echo-error-no-formatter": "Sem formato definido para notificações.",
"notifications": "Notificações",
"tooltip-pt-notifications-alert": "Os {{GENDER:|seus}} alertas",
- "tooltip-pt-notifications-message": "As {{GENDER:|suas}} mensagens",
+ "tooltip-pt-notifications-notice": "As {{GENDER:|suas}} notificações",
+ "echo-displaynotificationsconfiguration": "Mostrar a configuração de notificações",
+ "echo-displaynotificationsconfiguration-summary": "Esta é uma visão geral de como as notificações são configuradas nesta wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notificações por categoria",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Classificação dos tipos de notificação",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Em que secção é classificado cada tipo de notificação",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Métodos de notificação permitidos",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Que métodos de notificação são suportadas para cada categoria",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Que métodos de notificação são suportados para cada tipo; só se aplica a tipos dentro das categorias que estão escondidas nas preferências",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Ativado por padrão",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Utilizadores existentes",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Novos utilizadores",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Métodos de notificação obrigatórios",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Que métodos de notificação são obrigatórios para cada categoria",
"echo-specialpage": "Notificações",
+ "echo-specialpage-section-markread": "Marcar grupo como lido",
+ "echo-specialpage-markasread": "Notificação: Marcar como lida",
+ "echo-specialpage-markasread-invalid-id": "ID de evento inválido",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|notificação|notificações}}",
+ "echo-specialpage-pagefilters-title": "Atividade recente",
+ "echo-specialpage-pagefilters-subtitle": "Páginas com notificações não lidas",
+ "notificationsmarkread-legend": "Marcar notificação como lida",
"echo-anon": "Para receber notificações, [$1 crie uma conta] ou [$2 entre] na sua.",
"echo-none": "Não tem notificações.",
"echo-more-info": "Mais informações",
"echo-feedback": "Comentários",
- "echo-api-failure": "Não foi possível recuperar as notificações. Por favor tente novamente. (Erro $1)",
+ "echo-popup-footer-special-page-invitation": "<strong>Experimente a página redesenhada de notificações.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Aspeto e funcionalidades totalmente novas.",
+ "echo-api-failure": "Não foi possível obter as notificações.",
+ "echo-api-failure-cross-wiki": "O acesso ao domínio remoto foi negado.",
"echo-notification-placeholder": "Não há notificações.",
+ "echo-notification-placeholder-filters": "Não existem notificações correspondentes a estes critérios.",
+ "echo-notification-loginrequired": "Deve iniciar sessão para ver as suas notificações.",
+ "echo-notification-popup-loginrequired": "Inicie sessão para ver as suas notificações.",
+ "echo-notification-markasread": "Marcar como lida",
+ "echo-notification-markasunread": "Marcar como não lida",
+ "echo-notification-markasread-tooltip": "Marcar como lida",
+ "echo-notification-more-options-tooltip": "Mais opções",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Parar}} de vigiar a nova atividade em \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Parou}} de vigiar a página \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Pode}} vigiar [$2 esta página] a qualquer momento.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Seguir}} a nova atividade em \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Está}} agora a vigiar a página \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Pode}} parar de vigiar [$2 esta página] a qualquer momento.",
+ "notification-link-text-expand-all": "Expandir",
+ "notification-link-text-expand-alert-count": "Ver {{PLURAL:$1|$1 alerta|$1 alertas}}",
+ "notification-link-text-expand-notice-count": "Ver {{PLURAL:$1|$1 notificação|$1 notificações}}",
+ "notification-link-text-expand-all-count": "Ver {{PLURAL:$1|$1 notificação|$1 notificações}}",
+ "notification-link-text-collapse-all": "Ocultar",
"notification-link-text-view-message": "Ver mensagem",
"notification-link-text-view-mention": "Ver menção",
- "notification-link-text-view-changes": "Ver mudanças",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Ver menção|Ver menções}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Ver}} alterações",
"notification-link-text-view-page": "Ver página",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|deixou}} uma mensagem na <strong>{{GENDER:$3|sua}} página de discussão</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|deixou}} uma mensagem na <strong>{{GENDER:$3|sua}} página de discussão</strong>, na secção \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "Foi feita ligação em <strong>$4</strong> para <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Feita ligação a partir de <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Foram feitas ligações para <strong>$3</strong> em {{PLURAL:$5||$5 outras páginas|100=mais de 99 outras páginas}}.",
+ "notification-header-article-reminder": "Uma página acerca da qual pediu para ser {{GENDER:$2|recordado|recordada}} está em <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Todas as páginas afluentes desta",
+ "notification-header-mention-other": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$3|o|a|o(a)}} em <strong>$4</strong>, na secção \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$3|o|a|o(a)}} em <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$3|o|a|o(a)}} na <strong>página de discussão {{GENDER:$5|de}} $4</strong> em \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$3|o|a|o(a)}} na <strong>página de discussão {{GENDER:$5|de}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$3|o|a|o(a)}} <strong>na página de discussão {{GENDER:$2|dele|dela}}</strong> em \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$3|o|a|o(a)}} na <strong>página de discussão {{GENDER:$2|dele|dela}}</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$3|o|a|o(a)}} na página de discussão {{GENDER:$5|de}} <strong>$4</strong> em \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$3|o|a|o(a)}} na página de discussão de <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "A {{GENDER:$2|sua}} menção de <strong>$3</strong> não foi enviada porque o utilizador não foi encontrado.",
+ "notification-header-mention-failure-user-anonymous": "A {{GENDER:$2|sua}} menção de <strong>$3</strong> não foi enviada porque se trata de um utilizador anónimo.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Tentaste}} mencionar mais de $3 {{PLURAL:$3|utilizador|utilizadores}}. Todas as menções acima desse limite não foram enviadas.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|A menção|As $3 menções}} {{GENDER:$2|que fez}} na página de discussão \"<strong>$4</strong>\" não {{PLURAL:$3|foi enviada|foram enviadas}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Utilizador inexistente:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP não podem ser mencionados:</strong> $1",
+ "notification-header-mention-success": "A {{GENDER:$2|sua}} menção de <strong>$3</strong> foi enviada.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|A menção|As $3 menções}} {{GENDER:$2|que fez}} na página de discussão \"<strong>$4</strong>\" {{PLURAL:$3|foi enviada|foram enviadas}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Mencionou}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Uma notificação|$3 notificações}} sobre menções {{GENDER:$2|que fez}} na página de discussão \"<strong>$4</strong>\": {{PLURAL:$5|$5 não enviadas}}, {{PLURAL:$6|$6 enviadas}}.",
+ "notification-header-user-rights-add-only": "Os {{GENDER:$4|seus}} privilégios foram {{GENDER:$1|alterados}}. Foi {{GENDER:$4|adicionado|adicionada|adicionado(a)}} a: $2.",
+ "notification-header-user-rights-remove-only": "Os {{GENDER:$4|seus}} privilégios foram {{GENDER:$1|alterados}}. Deixou de pertencer a: $2.",
+ "notification-header-user-rights-add-and-remove": "Os {{GENDER:$6|seus}} privilégios foram {{GENDER:$1|alterados}}. Foi {{GENDER:$6|adicionado|adicionada|adicionado(a)}} a: $2. Deixou de pertencer a: $4.",
+ "notification-header-user-rights-expiry-change": "A expiração de {{GENDER:$4|sua}} associação {{PLURAL:$3|no seguinte grupo|nos seguintes grupos}} foi {{GENDER:$1|alterada}}: $2",
+ "notification-header-welcome": "{{GENDER:$2|Bem-vindo|Bem-vinda|Bem-vindo(a)}} à wiki {{SITENAME}}, $1! Ficamos satisfeitos por {{GENDER:$2|tê-lo|tê-la|tê-lo(a)}} aqui.",
+ "notification-welcome-linktext": "Bem-vindo(a)!",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Acabou}} de fazer a {{GENDER:$2|sua}} primeira edição; obrigado, e seja {{GENDER:$2|bem-vindo|bem-vinda|bem-vindo(a)}}!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Acabou}} de fazer a {{GENDER:$2|sua}} décima edição; obrigado e, por favor, continue!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Acabou}} de fazer a {{GENDER:$2|sua}} centésima edição; muito obrigado!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Acabou}} de fazer a {{GENDER:$2|sua}} milésima edição; obrigado por colaborar tão arduamente!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Acabou}} de fazer a {{GENDER:$2|sua}} milésima edição; muito obrigado!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Acabou}} de fazer a {{GENDER:$2|sua}} edição número cem mil; obrigado por colaborar tão arduamente!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Acabou}} de fazer a {{GENDER:$2|sua}} milionésima edição; obrigado pela sua surpreendente contribuição!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|A sua}} edição",
"notification-link-text-view-edit": "Ver edição",
- "notification-edit-talk-page2": "[[User:$1|$1]] deixou uma mensagem na sua [[User talk:$2#$3|página de discussão]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] deixou uma mensagem na sua página de discussão na secção \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 deixou uma mensagem na sua [[User talk:$2#$3|página de discussão]].",
- "notification-edit-talk-page-flyout-with-section": "$1 deixou uma mensagem na sua página de discussão na secção \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] foi {{GENDER:$1|ligada}} a partir de [[:$3]]. [[Special:WhatLinksHere/$2|Ver todas as páginas afluentes a esta]].",
- "notification-page-linked-flyout": "[[:$2]] foi {{GENDER:$1|ligada}} a partir de [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] comentou em \"[[$3|$2]]\" na página de discussão de \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] criou o novo tópico \"$2\" em [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] enviou-lhe uma mensagem: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] comentou na secção \"[[$3#$2|$2]]\" na sua página de discussão.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|mencionou}} você na página de discussão $5, na secção \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|mencionou}} você na página de discussão $5, na secção \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|mencionou}} você na [[:$3|página de discussão de $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|mencionou}} você na [[:$3|página de discussão de $2]].",
- "notification-user-rights": "Os seus privilégios de {{GENDER:$1|utilizador}} [[Special:Log/rights/$1|foram]] alterados por [[User:$1|$1]]. $2. [[Special:ListGroupRights|Saiba mais]]",
- "notification-user-rights-flyout": "Os seus privilégios de {{GENDER:$1|utilizador|utilizadora}} foram alterados por $1. $2. [[Special:ListGroupRights|Saiba mais]]",
- "notification-user-rights-add": "É agora membro {{PLURAL:$2|deste grupo|destes grupos}}: $1",
- "notification-user-rights-remove": "Já não é membro {{PLURAL:$2|deste grupo|destes grupos}}: $1",
- "notification-new-user": "Bem-vindo(a) a {{SITENAME}}, $1! Estamos contentes por se ter juntado a nós.",
- "notification-reverted2": "{{PLURAL:$4|A sua edição em [[:$2]] foi revertida|As suas edições em [[:$2]] foram revertidas}} por [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|A sua edição em $2 foi revertida|As suas edições em $2 foram revertidas}} {{GENDER:$1|pelo|pela|por}} $1. $3",
- "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|deixou-lhe}} uma mensagem em {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 deixou-lhe uma mensagem {{GENDER:$1|na}} {{SITENAME}}.",
+ "notification-link-article-reminder": "Ver página",
+ "notification-header-reverted": "{{PLURAL:$4|A sua edição em <strong>$3</strong> foi revertida|As suas edições em <strong>$3</strong> foram {{GENDER:$2|revertidas}}}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|enviou-lhe}} uma mensagem de correio.",
+ "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|deixou-lhe}} uma mensagem na wiki {{SITENAME}}",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|deixou-lhe}} uma mensagem na sua página de discussão na secção \"$2\".",
- "notification-page-linked-email-subject": "A página que criou foi ligada em {{SITENAME}}",
- "notification-page-linked-email-batch-body": "A página $2 foi {{GENDER:$1|ligada}} a partir de $3.",
- "notification-reverted-email-subject2": "{{PLURAL:$3|A sua edição foi revertida|As suas edições foram revertidas}} {{GENDER:$1|}} em {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|A sua edição em $2 foi revertida|As suas edições em $2 foram revertidas}} por $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|mencionou}} você em {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|mencionou}} você na página de discussão $4, na secção \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|mencionou}} você na página de discussão $2.",
- "notification-user-rights-email-subject": "Os seus privilégios de utilizador foram alterados em {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Os seus privilégios de utilizador foram {{GENDER:$1|alterados}} por $1. $2.",
- "echo-email-subject-default": "Nova notificação em {{SITENAME}}",
- "echo-email-body-default": "Tem uma nova notificação em {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Tem uma nova notificação.",
- "echo-email-footer-default": "$2\n\nPara controlar quais os e-mails que deseja receber, consulte as suas preferências: {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Para controlar quais os e-mails que deseja receber, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">consulte as suas preferências</a>.<br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|Alerta ($1)|Alertas ($1)|100=Alertas (+99)}}",
- "echo-notification-message": "{{PLURAL:$1|Mensagem ($1)|Mensagens ($1)|100=Mensagens (+99)}}",
+ "notification-page-linked-email-subject": "Foi criada uma ligação para uma página que criou na wiki {{SITENAME}}",
+ "notification-reverted-email-subject2": "{{PLURAL:$3|A sua edição foi revertida|As suas edições foram revertidas}}{{GENDER:$1|}} na wiki {{SITENAME}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|mencionou-}}{{GENDER:$2|o|a|o(a)}} na wiki {{SITENAME}}",
+ "notification-user-rights-email-subject": "Os seus privilégios de utilizador foram alterados na wiki {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mês|$1 meses}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 ano|$1 anos}}",
+ "notification-timestamp-today": "Hoje",
+ "notification-timestamp-yesterday": "Ontem",
+ "notification-inbox-filter-read": "Lidas",
+ "notification-inbox-filter-unread": "Não lidas",
+ "notification-inbox-filter-all": "Todas",
+ "echo-email-body-default": "Tem uma nova notificação na wiki {{SITENAME}}:\n\n$1",
+ "echo-email-footer-default-html": "Para controlar as mensagens eletrónicas que lhe são enviadas, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">verifique as suas preferências</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPara controlar quais as mensagens eletrónicas que deseja receber, consulte as suas preferências:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Para controlar as mensagens eletrónicas que {{GENDER:$1|lhe}} são enviadas, verifique as {{GENDER:$1|suas}} preferências:",
+ "echo-email-html-footer-preference-link-text": "verifique as {{GENDER:$1|suas}} preferências",
+ "echo-email-html-footer-with-link": "Para controlar as mensagens eletrónicas que {{GENDER:$2|lhe}} são enviadas, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Alerta ($1)|Alertas ($1)|100=Alertas (mais de 99)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notificação ($1)|Notificações ($1)|100=Notificações (mais de 99)}}",
"echo-notification-alert-text-only": "Alertas",
- "echo-notification-message-text-only": "Mensagens",
+ "echo-notification-notice-text-only": "Notificações",
"echo-overlay-link": "Todas as notificações",
"echo-overlay-title": "<b>Notificações</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificações}}</b> (a mostrar $1 de $2 não lidas)",
"echo-mark-all-as-read": "Marcar todas como lidas",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|notificação marcada como lida|notificações marcadas como lidas}}",
+ "echo-mark-wiki-as-read": "Marcar tudo como lido na wiki selecionada: $1",
"echo-date-today": "Hoje",
"echo-date-yesterday": "Ontem",
"echo-load-more-error": "Ocorreu um erro ao carregar mais resultados.",
- "notification-edit-talk-page-bundle": "$1 e $3 {{PLURAL:$4|outro|outros}} {{GENDER:$1|deixaram}} uma mensagem na sua [[User talk:$2|página de discussão]].",
- "notification-page-linked-bundle": "$2 foi {{GENDER:$1|ligada}} a partir de $3 e $4 {{PLURAL:$5|outra página|outras páginas}}. [[Special:WhatLinksHere/$2|Veja todas as páginas ligadas a esta]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e $2 {{PLURAL:$3|outro|outros}} {{GENDER:$1|deixaram}} uma mensagem na sua página de discussão.",
- "notification-page-linked-email-batch-bundle-body": "$2 foi {{GENDER:$1|ligada}} a partir de $3 e $4 para {{PLURAL:$5|outra página|outras páginas}}.",
- "echo-email-batch-subject-daily": "Tem {{PLURAL:$2|uma nova notificação|novas notificações}} em {{SITENAME}}",
- "echo-email-batch-subject-weekly": "Tem {{PLURAL:$2|uma nova notificação|novas notificações}} em {{SITENAME}} esta semana",
- "echo-email-batch-body-intro-daily": "Olá $1,\nAqui está um resumo da actividade de hoje em {{SITENAME}} para si.",
- "echo-email-batch-body-intro-weekly": "Olá $1,\nAqui está um resumo da actividade desta semana em {{SITENAME}} para si.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Uma nova mensagem|$1 novas mensagens|100=Mais de 99 novas mensagens}} na <strong>{{GENDER:$3|sua}} página de discussão</strong>.",
+ "echo-email-batch-subject-daily": "Tem {{PLURAL:$2|uma nova notificação|novas notificações}} na wiki {{SITENAME}}",
+ "echo-email-batch-subject-weekly": "Tem {{PLURAL:$2|uma nova notificação|novas notificações}} na wiki {{SITENAME}} esta semana",
+ "echo-email-batch-body-intro-daily": "Olá $1,\nAqui tem um resumo da atividade de hoje na wiki {{SITENAME}}.",
+ "echo-email-batch-body-intro-weekly": "Olá $1,\nAqui tem um resumo da atividade desta semana na wiki {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "Ver todas as notificações",
- "echo-rev-deleted-text-view": "A revisão desta página foi suprimida."
+ "notification-header-foreign-alert": "Mais alertas de {{PLURAL:$5|uma outra wiki|$5 outras wikis}}",
+ "notification-header-foreign-notice": "Mais notificações de {{PLURAL:$5|outra wiki|$5 outras wikis}}",
+ "notification-header-foreign-all": "Mais notificações de {{PLURAL:$5|uma outra wiki|$5 outras wikis}}"
}
diff --git a/Echo/i18n/qqq.json b/Echo/i18n/qqq.json
index 81996963..cb66f3e6 100644
--- a/Echo/i18n/qqq.json
+++ b/Echo/i18n/qqq.json
@@ -22,7 +22,13 @@
"రహ్మానుద్దీన్",
"Liuxinyu970226",
"Purodha",
- "Umherirrender"
+ "Umherirrender",
+ "Mattflaschen",
+ "Trizek (WMF)",
+ "Matěj Suchánek",
+ "McDutchie",
+ "Ans",
+ "Verdy p"
]
},
"echo-desc": "{{desc|name=Echo|url=https://www.mediawiki.org/wiki/Extension:Echo}} The [https://www.mediawiki.org/wiki/Help:Notifications Mediawiki help] page gives notes on the terminology in this extension.",
@@ -30,7 +36,9 @@
"prefs-emailsettings": "Header for the section of preferences that deals with how often notification emails are sent out and what address they are sent to.\n{{Identical|E-mail option}}",
"prefs-displaynotifications": "Header for the section of preferences that deals with how notifications are displayed",
"prefs-echosubscriptions": "Header for the section of preferences that deals with which notifications the user receives",
+ "prefs-echocrosswiki": "Header for the section of preferences that deals with notifications from other wikis",
"prefs-newmessageindicator": "Header for the section of preferences that deals with talk page message alerts",
+ "prefs-blocknotificationslist": "Header for the section of preferences that deals with blocking notifications from certain users",
"echo-pref-send-me": "Label for the following email delivery options:\n* {{msg-mw|Echo-pref-email-frequency-never}}\n* {{msg-mw|Echo-pref-email-frequency-immediately}} (default)\n* {{msg-mw|Echo-pref-email-frequency-daily}}\n* {{msg-mw|Echo-pref-email-frequency-weekly}}",
"echo-pref-send-to": "Label for the address to send email notifications to.",
"echo-pref-email-format": "Label for individual email notification format, the label will be updated once HTML email is ready for email digest.\n\nUsed as label for the select box which has the following options:\n* {{msg-mw|Echo-pref-email-format-html}}\n* {{msg-mw|Echo-pref-email-format-plain-text}}",
@@ -42,122 +50,190 @@
"echo-pref-email-frequency-weekly": "Option for users who want to receive a weekly digest of email notifications",
"echo-pref-email-format-html": "Option for users who want to receive HTML email notification.\n\nSee also:\n* {{msg-mw|Echo-pref-email-format}}\n{{Identical|HTML}}",
"echo-pref-email-format-plain-text": "Option for users who want to receive plain text email notification.\n\nSee also:\n* {{msg-mw|Echo-pref-email-format}}\n{{Identical|Plain text}}",
+ "echo-pref-cross-wiki-notifications": "Label for a preference which enables notifications from other wikis. Only used if {{msg-mw|echo-pref-beta-feature-cross-wiki-message}} is not used.",
+ "echo-pref-notifications-blacklist": "Label for a preference which allows a user to block notifications from certain users.\n\nNote that the translatewiki.net tool may warn, if you alter the link to use an existing translated version linked from the English page at [[mw:Help:Notifications#mute]], such as [[mw:Help:Notifications/fr#mute]] for the French version.",
"echo-pref-new-message-indicator": "Label for a preference which enables the new talk page message alert",
+ "echo-pref-beta-feature-cross-wiki-message": "Label for the cross-wiki notifications Beta Feature. Only used if {{msg-mw|echo-pref-cross-wiki-notifications}} is not used.",
+ "echo-pref-beta-feature-cross-wiki-description": "Description for the cross-wiki notifications Beta Feature, describing the feature that will be enabled. Only used if {{msg-mw|echo-pref-cross-wiki-notifications}} is not used.",
"echo-learn-more": "Text for link to more information about a topic.\n{{Identical|Learn more}}",
+ "echo-log": "Text for link to go to Special:Log",
"echo-new-messages": "Message to let the user know that they have new talk page messages, displayed in the personal menu (top-right corner on Vector and Monobook).\n\nKeep this message short. It '''should not''' end in a full stop.",
"echo-category-title-edit-user-talk": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}",
"echo-category-title-article-linked": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}",
"echo-category-title-reverted": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}",
"echo-category-title-mention": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}\n{{Identical|Mention}}",
+ "echo-category-title-mention-failure": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n{{Related|Echo-category-title}}",
+ "echo-category-title-mention-success": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n{{Related|Echo-category-title}}",
"echo-category-title-other": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}\n{{Identical|Other}}",
"echo-category-title-system": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}\n{{Identical|System}}",
"echo-category-title-user-rights": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}",
+ "echo-category-title-emailuser": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}",
+ "echo-category-title-article-reminder": "This is a short title for notification category.\n\nUsed in a list of options under the heading {{msg-mw|Prefs-echosubscriptions}} in Special:Preferences. As far as I can see this always needs to be a plural for an unspecified number.\n\nIt used to be used as <code>$1</code> in {{msg-mw|Echo-dismiss-message}}, but this message is no longer used, apparently.\n\nParameters:\n* $1 - number of messages, for PLURAL support\n{{Related|Echo-category-title}}",
"echo-pref-tooltip-edit-user-talk": "This is a short description of the edit-user-talk notification category.\n{{Related|Echo-pref-tooltip}}",
"echo-pref-tooltip-article-linked": "This is a short description of the article-linked notification category.\n{{Related|Echo-pref-tooltip}}",
"echo-pref-tooltip-reverted": "This is a short description of the tooltip-reverted notification category.\n{{Related|Echo-pref-tooltip}}",
"echo-pref-tooltip-mention": "This is a short description of the mention notification category.\n{{Related|Echo-pref-tooltip}}",
+ "echo-pref-tooltip-mention-failure": "This is a short description of the mention failure notification category.\n{{Related|Echo-pref-tooltip}}",
+ "echo-pref-tooltip-mention-success": "This is a short description of the mention success notification category.\n{{Related|Echo-pref-tooltip}}",
"echo-pref-tooltip-user-rights": "This is a short description of the user rights changes notification category\n{{Related|Echo-pref-tooltip}}",
- "echo-no-agent": "Shown in place of a username in a notification\n\tif the notification has no specified user.",
- "echo-no-title": "Shown in place of a page title in a notification if the notification has no specified page title.",
+ "echo-pref-tooltip-emailuser": "This is a short description of the user email notification category\n{{Related|Echo-pref-tooltip}}",
+ "echo-pref-tooltip-article-reminder": "This is a short description of the article reminder user notification category\n{{Related|Echo-pref-tooltip}}",
"echo-error-no-formatter": "Error message displayed when no formatting has been defined for a notification. In other words, the extension doesn't know how to properly display the notification.",
"notifications": "{{doc-special|Notifications}}\n{{Identical|Notification}}",
"tooltip-pt-notifications-alert": "This is used for the title (mouseover text) of the alert notifications user tool.",
- "tooltip-pt-notifications-message": "This is used for the title (mouseover text) of the message notifications user tool.",
+ "tooltip-pt-notifications-notice": "This is used for the title (mouseover text) of the notice notifications user tool.",
+ "echo-displaynotificationsconfiguration": "{{doc-special|DisplayNotificationsConfiguration}}\n\nThis could be rephrased as \"Display the configuration of Notifications\".",
+ "echo-displaynotificationsconfiguration-summary": "Summary of the DisplayNotificationsConfiguration special page",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Header on DisplayNotificationsConfiguration for a list of which notifications are in each category",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Header on [[Special:DisplayNotificationsConfiguration]] for a table of which section (alert/message) each type is in",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Legend on DisplayNotificationsConfiguration for a table of which section (alert/message) each type is in",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Header on DisplayNotificationsConfiguration for section regarding methods the user can use to receive different kinds of notifications",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Explanatory text on DisplayNotificationsConfiguration regarding which notification methods are available for each category",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Explanatory text on DisplayNotificationsConfiguration regarding which notification methods are available for each type",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Header on DisplayNotificationsConfiguration for section about which categories are enabled by default",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Explanatory text on DisplayNotificationsConfiguration regarding which notification methods for each category are enabled by default, for existing users",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Explanatory text on DisplayNotificationsConfiguration regarding which notification methods for each category are enabled by default, for new users\n{{Identical|New user}}",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Header on DisplayNotificationsConfiguration for section about which notification methods are required",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Explanatory text on DisplayNotificationsConfiguration regarding which notification methods are mandatory for each category",
"echo-specialpage": "Special page title for Special:Notifications.\n{{Identical|Notification}}",
+ "echo-specialpage-section-markread": "Label for the button to mark notifications in the given section as read in [[Special:Notifications]]",
+ "echo-specialpage-markasread": "Special page title for Special:NotificationsMarkRead for marking specific notification as read.",
+ "echo-specialpage-markasread-invalid-id": "Error message shown to users who try to mark a notification as read with an invalid event ID.",
+ "echo-specialpage-pagination-numnotifications": "Label noting the number of notifications displayed in the page. This only appears if there is a single page of results.\n\nParameters:\n* $1 - Number of notifications in the page.\n{{Identical|Notification}}",
+ "echo-specialpage-pagination-range": "Label noting the range of the notifications displayed in the page. This only appears if there are multiple pages of results available.\n\nParameters:\n* $1 - Number of the first item.\n* $2 - Number of the last item.",
+ "echo-specialpage-pagefilters-title": "Title of the page filter box in Special:Notifications page.",
+ "echo-specialpage-pagefilters-subtitle": "Subtitle of the page filter box in Special:Notifications page.",
+ "notificationsmarkread-legend": "Title for the form that marks a notification as read in [[Special:NotificationsMarkAsRead]]",
"echo-anon": "Error message shown to users who try to visit [[Special:Notifications]] as an anon.\n\nParameters:\n* $1 - URL of signup page, with returnto pointing to Special:Notifications\n* $2 - URL of login page, with returnto pointing to Special:Notifications",
"echo-none": "Message shown to users who have no notifications. Also shown in the overlay.",
"echo-more-info": "This is used for the title (mouseover text) of an icon that links to a page with more information about the Echo extension.\n{{Identical|More information}}",
"echo-feedback": "Text for a link that goes to a feedback survey shown at [[Special:Notifications]].\n{{Identical|Feedback}}",
+ "echo-popup-footer-special-page-invitation": "Text inviting the user to try the new [[Special:Notifications]] page, displayed at the bottom of the notifications popup.\n\nParameters:\n* $1 - Text of the link ({{msg-mw|echo-popup-footer-special-page-invitation-link}}).\n* $2 - URL of the link to Special:Notifications.",
+ "echo-popup-footer-special-page-invitation-link": "Text for the link in {{msg-mw|echo-popup-footer-special-page-invitation}}.",
"echo-quotation-marks": "Unused at this time.\n\n{{optional}}\nPuts the edit summary in quotation marks. Only translate if different than English.\n\nParameters:\n* $1 - ...",
- "echo-api-failure": "Label for the text that notes an error in retrieving notifications for the Echo popup.\n$1 - The api error code.",
+ "echo-api-failure": "Label for the text that notes an error in retrieving notifications for the Echo popup.",
+ "echo-api-failure-cross-wiki": "Label for the api failure text for a failure to fetch cross-wiki notifications, but the remote server is not granted access.",
"echo-notification-placeholder": "Label for the text that appears if there are no notifications in the Echo popup.",
+ "echo-notification-placeholder-filters": "Label for the text that appears if there are no notifications in the Special:Notifications page with filters selected.",
+ "echo-notification-loginrequired": "Message that displays when an anonymous user attempts to view notifications and gets redirect to the login page.",
+ "echo-notification-popup-loginrequired": "Message that displays when an anonymous user attempts to view notifications in their popup after a session expired.",
+ "echo-notification-markasread": "Label for the button to mark the notification as read.",
+ "echo-notification-markasunread": "Label for the button to mark the notification as unread.",
+ "echo-notification-markasread-tooltip": "Tooltip for the button to mark the notification as read.",
+ "echo-notification-more-options-tooltip": "Tooltip for the button to show the hidden secondary actions.",
+ "notification-dynamic-actions-unwatch": "Text for the action offering the user to unwatch a page from within a notification.\n\nParameters:\n* $1 - Page name\n* $2 - Page URL\n* $3 - Current user name for gender purposes\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-unwatch-confirmation": "Title for the confirmation text for unwatching a page from within a notification.\n\nParameters:\n* $1 - Page name\n* $2 - Page URL\n* $3 - Current user name for gender purposes\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-unwatch-confirmation-description": "Description for the confirmation text for unwatching a page from within a notification.\n\nParameters:\n* $1 - Page name\n* $2 - Page URL\n* $3 - Current user name for gender purposes\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-watch": "Text for the action offering the user to watch a page from within a notification.\n\nParameters:\n* $1 - Page name\n* $2 - Page URL\n* $3 - Current user name for gender purposes\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-watch-confirmation": "Title for the confirmation text for watching a page from within a notification.\n\nParameters:\n* $1 - Page name\n* $2 - Page URL\n* $3 - Current user name for gender purposes\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-watch-confirmation-description": "Description for the confirmation text for watching a page from within a notification.\n\nParameters:\n* $1 - Page name\n* $2 - Page URL\n* $3 - Current user name for gender purposes\n\n{{related|Notification-dynamic}}",
+ "notification-link-text-expand-all": "Label for the button that expands a bundled notification.\n{{Identical|Expand}}",
+ "notification-link-text-expand-alert-count": "Label for the button that expands a bundled alert notification.\n\nParameters:\n* $1 - The count of messages that the bundle holds.\n{{Identical|View alert}}",
+ "notification-link-text-expand-notice-count": "Label for the button that expands a bundled notice notification.\n\nParameters:\n* $1 - The count of messages that the bundle holds.",
+ "notification-link-text-expand-all-count": "Label for the button that expands a bundled notification.\n\nParameters:\n* $1 - The count of messages that the bundle holds.\n{{Identical|View notification}}",
+ "notification-link-text-collapse-all": "Label for the button that collapses a bundled notification.\n{{Identical|Collapse}}",
"notification-link-text-view-message": "Label for button that links to a message on your talk page.\n{{Identical|View message}}",
"notification-link-text-view-mention": "Label for button that links to a discussion where you were mentioned.",
- "notification-link-text-view-changes": "Label for button that links to a \"diff\" view showing changes made to a page. This is an alternative to the wording in {{msg-mw|notification-link-text-view-edit}}, which serves essentially the same function.\n{{Identical|View changes}}",
+ "notification-link-text-view-mention-failure": "Label for button that links to a discussion where your mentions failed.\n* $1 - The number of failed mentions; uses standard number formatting and used for PLURAL",
+ "notification-link-text-view-changes": "Label for button that links to a \"diff\" view showing changes made to a page. Paramters:\n* $1 - name of the user viewing the notification, can be used for GENDER.\n{{Identical|View changes}}",
"notification-link-text-view-page": "Label for button that links to a page.\n{{Identical|View page}}",
+ "notification-header-edit-user-talk": "Flyout-specific format for displaying notification header of a user talk page being edited.\n\nParameters:\n* $1 - the formatted username of the person who edited.\n* $2 - the username for GENDER\n* $3 - username of the current user, can be used for GENDER",
+ "notification-header-edit-user-talk-with-section": "Flyout-specific format for displaying notification header of a user talk page being edited with a new section or new comment.\n\nParameters:\n* $1 - the formatted username of the person who edited.\n* $2 - the username for GENDER\n* $3 - username of the current user, can be used for GENDER\n* $4 - the raw section title text",
+ "notification-body-edit-user-talk-with-section": "{{optional}}\nFlyout-specific format for displaying notification body of a user talk page being edited with a new section or new comment.\n\nParameters:\n* $1 - comment left on the user talk page.",
+ "notification-header-page-linked": "Notification header message for articles being linked.\n\nParameters:\n* $1 - the formatted username of the person who linked the page. \n* $2 - the username for GENDER\n* $3 - the page being linked\n* $4 - the page linked from\nSee also:\n* {{msg-mw|Notification-page-linked-email-subject}}",
+ "notification-compact-header-page-linked": "Notification compact header message for articles being linked.\n\nParameters:\n* $1 - the page linked from.\nSee also:\n* {{msg-mw|Notification-page-linked-email-subject}}",
+ "notification-bundle-header-page-linked": "Bundled message for page-linked notification. Parameters:\n* $1 - the formatted username of the person who linked the page. \n* $2 - the username for GENDER\n* $3 - the page title\n* $4 - the page linked from\n* $5 - The number of other pages that link to this page, except that if the count is greater than 99, this value will be 100; uses standard number formatting and used for PLURAL\n* $6 - Unused\nSee also:\n* {{msg-mw|Notification-page-linked-email-subject}}\n{{Related|Notification-bundle}}",
+ "notification-header-article-reminder": "Message for page-reminder notification. Parameters:\n* $1 - the formatted username of the user who requested the reminder. \n* $2 - the username for GENDER\n* $3 - the formatted page title of the article the user requested.",
+ "notification-link-text-what-links-here": "Label for link to the WhatLinksHere special page for the page being linked in this notification.",
+ "notification-body-mention": "{{notranslate}}",
+ "notification-header-mention-other": "Header text for a notification when you are mentioned by another user in a section on a page that is not an article talk page or a user talk page.\n* $1 - user's name (not suitable for GENDER).\n* $2 - user's name for use in GENDER.\n* $3 - name of the user viewing the notification, can be used for GENDER\n* $4 - name of the page they were mentioned in (with namespace).\n* $5 - name of the section they were mentioned in",
+ "notification-header-mention-other-nosection": "Header text for a notification when you are mentioned by another user on a page that is not an article talk page or a user talk page.\n* $1 - user's name (not suitable for GENDER).\n* $2 - user's name for use in GENDER.\n* $3 - name of the user viewing the notification, can be used for GENDER\n* $4 - name of the page they were mentioned in (with namespace)",
+ "notification-header-mention-user-talkpage-v2": "Header text for a notification when you are mentioned by another user in a section on a user talk page.\n* $1 - user's name (not suitable for GENDER).\n* $2 - user's name for use in GENDER.\n* $3 - name of the user viewing the notification, can be used for GENDER\n* $4 - formatted name of the user whose talk page you are mentioned in.\n* $5 - name of the user whose talk page you are mentioned in, can be used for GENDER\n* $6 - name of the section they were mentioned in",
+ "notification-header-mention-user-talkpage-nosection": "Header text for a notification when you are mentioned by another user on a user talk page.\n* $1 - user's name (not suitable for GENDER).\n* $2 - user's name for use in GENDER.\n* $3 - name of the user viewing the notification, can be used for GENDER\n* $4 - name of the user whose talk page you are mentioned in\n* $5 - name of the user whose talk page you are mentioned in, can be used for GENDER",
+ "notification-header-mention-agent-talkpage": "{{doc-singularthey}}\nHeader text for a notification when you are mentioned by another user in a section on their talk page.\n* $1 - user's name (not suitable for GENDER).\n* $2 - user's name for use in GENDER.\n* $3 - name of the user viewing the notification, can be used for GENDER\n* $4 - name of the section they were mentioned in",
+ "notification-header-mention-agent-talkpage-nosection": "{{doc-singularthey}}\nHeader text for a notification when you are mentioned by another user on their talk page.\n* $1 - user's name (not suitable for GENDER).\n* $2 - user's name for use in GENDER.\n* $3 - name of the user viewing the notification, can be used for GENDER",
+ "notification-header-mention-article-talkpage": "Header text for a notification when you are mentioned by another user in a section on an article talk page.\n* $1 - user's name (not suitable for GENDER).\n* $2 - user's name for use in GENDER.\n* $3 - name of the user viewing the notification, can be used for GENDER\n* $4 - name of the article whose talk page you are mentioned in (without namespace).\n* $5 - name of the section they were mentioned in",
+ "notification-header-mention-article-talkpage-nosection": "Header text for a notification when you are mentioned by another user on an article talk page.\n* $1 - user's name (not suitable for GENDER).\n* $2 - user's name for use in GENDER.\n* $3 - name of the user viewing the notification, can be used for GENDER\n* $4 - name of the article whose talk page you are mentioned in (without namespace)",
+ "notification-header-mention-failure-user-unknown": "Header text for a notification when your mention has failed because the user was not found.\n* $2 - user's name for use in GENDER.\n* $3 - username that was not found.",
+ "notification-header-mention-failure-user-anonymous": "Header text for a notification when your mention has failed because the user is an anonymous IP.\n* $2 - user's name for use in GENDER.\n* $3 - username that is anonymous.",
+ "notification-header-mention-failure-too-many": "Header text for a notification when your mention has failed because you tried to mention too many users.\n* $2 - user's name for use in GENDER.<br /> (not clear: is it \"you\" or the mentioned user when there's only one?)</strong>\n* $3 - max number of mentions allowed; uses standard number formatting",
+ "notification-header-mention-failure-bundle": "Header text for a bundled notification when multiple mentions failed.\n* $2 - user's name for use in GENDER. <strong><br /> (not clear: is it \"you\" or the mentioned user when there's only one?)</strong>\n* $3 - number of mentions; uses standard number formatting and used for PLURAL.\n* $4 - talk page title.",
+ "notification-compact-header-mention-failure-user-unknown": "Compact header text for a notification when your mention has failed because the user was not found.\n* $1 - username that was not found.",
+ "notification-compact-header-mention-failure-user-anonymous": "Compact header text for a notification when your mention has failed because the user is an anonymous IP.\n* $1 - username that is anonymous.",
+ "notification-header-mention-success": "Header text for a notification when your mention was successful.\n* $2 - user's name for use in GENDER.\n* $3 - username that was mentioned, can be used for GENDER.",
+ "notification-header-mention-success-bundle": "Header text for a bundled notification when multiple mentions succeeded.\n* $2 - user's name for use in GENDER.\n* $3 - number of mentions; uses standard number formatting and used for PLURAL.\n* $4 - talk page title.",
+ "notification-compact-header-mention-success": "Compact header text for a notification when your mention was successful.\n* $2 - user's name for use in GENDER.\n* $3 - username that was mentioned.",
+ "notification-header-mention-status-bundle": "Header text for a bundled notification when some mentions failed and some succeeded.\n* $2 - user's name for use in GENDER.\n* $3 - number of mentions; uses standard number formatting and used for PLURAL.\n* $4 - talk page title.\n* $5 - number of failed mentions; uses standard number formatting and used for PLURAL.\n* $6 - number of successful mentions; uses standard number formatting and used for PLURAL.",
+ "notification-header-user-rights-add-only": "Notifications header message when a user is added to groups. Parameters:\n* $1 - the raw username of the person who made the user rights change, can be used for GENDER support\n* $2 - a localized list of the groups that were added\n* $3 - the number of groups that were added, can be used for PLURAL\n* $4 - name of the user viewing the notification, can be used for GENDER",
+ "notification-header-user-rights-remove-only": "Notifications header message when a user is removed from groups. Parameters:\n* $1 - the raw username of the person who made the user rights change, can be used for GENDER support\n* $2 - a localized list of the groups that were removed\n* $3 - the number of groups that were removed, can be used for PLURAL\n* $4 - name of the user viewing the notification, can be used for GENDER",
+ "notification-header-user-rights-add-and-remove": "Notifications header message when a user is added to groups and removed from groups. Parameters:\n* $1 - the raw username of the person who made the user rights change, can be used for GENDER support\n* $2 - a localized list of the groups that were added\n* $4 - a localized list of the groups that were removed\n* $6 - name of the user viewing the notification, can be used for GENDER",
+ "notification-header-user-rights-expiry-change": "Notifications header message when a user's group membership is extended or reduced in duration. Parameters:\n* $1 - the raw username of the person who made the user rights change, can be used for GENDER support\n* $2 - a localized list of the groups for which the expiry was changed\n* $3 - the number of groups that were changed, can be used for PLURAL\n* $4 - name of the user viewing the notification, can be used for GENDER",
+ "notification-body-user-rights": "{{notranslate}}",
+ "notification-header-welcome": "Text of the welcome notification. Parameters:\n* $1 - the name of the new user.\nSee also:\n* {{msg-mw|Guidedtour-tour-gettingstarted-start-title}}",
+ "notification-welcome-link": "{{notranslate}}",
+ "notification-welcome-linktext": "Link text for link to the wiki's welcome or introduction page.\n{{Identical|Welcome}}",
+ "notification-header-thank-you-1-edit": "Text of the editor welcome notification for their first edit.\nParameters:\n* $1 - the formatted username of the new user\n* $2 - the username for gender purposes",
+ "notification-header-thank-you-10-edit": "Text of the editor welcome notification for their tenth edit.\nParameters:\n* $1 - the formatted username of the new user\n* $2 - the username for gender purposes",
+ "notification-header-thank-you-100-edit": "Text of the editor welcome notification for their hundredth edit.\nParameters:\n* $1 - the formatted username of the new user\n* $2 - the username for gender purposes",
+ "notification-header-thank-you-1000-edit": "Text of the editor welcome notification for their thousandth edit.\nParameters:\n* $1 - the formatted username of the new user\n* $2 - the username for gender purposes",
+ "notification-header-thank-you-10000-edit": "Text of the editor welcome notification for their ten thousandth edit.\nParameters:\n* $1 - the formatted username of the new user\n* $2 - the username for gender purposes",
+ "notification-header-thank-you-100000-edit": "Text of the editor welcome notification for their hundred thousandth edit.\nParameters:\n* $1 - the formatted username of the new user\n* $2 - the username for gender purposes",
+ "notification-header-thank-you-1000000-edit": "Text of the editor welcome notification for their millionth edit.\nParameters:\n* $1 - the formatted username of the new user\n* $2 - the username for gender purposes",
+ "notification-link-thank-you-edit": "Label for the link to the user's edit which triggered a threshold congratulations message.\nParameters:\n* $1 - the username for gender purposes",
"notification-link-text-view-edit": "Label for button that links to a \"diff\" view showing an edit made to a page. This is an alternative to the wording in {{msg-mw|notification-link-text-view-changes}}, which serves essentially the same function.",
- "notification-edit-talk-page2": "Format for displaying notifications of a user talk page being edited. Parameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER.\n* $2 - the current user's name, used in the link to their talk page\n* $3 - the section title of the discussion, if any, used in the link to their talk page\nSee also:\n* {{msg-mw|Notification-edit-talk-page-flyout2}}\n* {{msg-mw|Notification-add-talkpage-topic2}}\n* left is for verb left.",
- "notification-edit-talk-page-with-section": "Format for displaying notifications of a user talk page being edited with a new section or new comment.\n\nParameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER.\n* $2 - the username of current user, used in the link to their talk page\n* $3 - the section title of the discussion, if any, used in the link to their talk page\n* $4 - the raw section title text",
- "notification-edit-talk-page-flyout2": "Flyout-specific format for displaying notifications of a user talk page being edited.\n\nParameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER.\n* $2 - the current user's name, used in the link to their talk page\n* $3 - the section title of the discussion, if any, used in the link to their talk page\nSee also:\n* {{msg-mw|Notification-edit-talk-page2}}\n* {{msg-mw|Notification-add-talkpage-topic2}}",
- "notification-edit-talk-page-flyout-with-section": "Flyout-specific format for displaying notifications of a user talk page being edited with a new section or new comment.\n\nParameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER.\n* $2 - the username of current user, used in the link to their talk page\n* $3 - the section title of the discussion, if any, used in the link to their talk page\n* $4 - the raw section title text",
- "notification-page-linked": "Format for displaying notifications of articles being linked. Parameters:\n* $1 - the username of the person who linked the page, plain text. Can be used for GENDER.\n* $2 - the page being linked\n* $3 - the page linked from\nSee also:\n* {{msg-mw|Notification-page-linked-flyout}}\n* {{msg-mw|Notification-page-linked-email-batch-body}}\n* {{msg-mw|Notification-page-linked-email-subject}}",
- "notification-page-linked-flyout": "Flyout-specific format for displaying notifications of articles being linked.\n\nParameters:\n* $1 - the username of the person who linked the page, plain text. Can be used for GENDER.\n* $2 - the page being linked\n* $3 - the page linked from\nSee also:\n* {{msg-mw|Notification-page-linked}}\n* {{msg-mw|Notification-page-linked-email-batch-body}}\n* {{msg-mw|Notification-page-linked-email-subject}}",
- "notification-add-comment2": "Format for displaying notifications of a comment being added to an existing discussion.\n\nParameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER.\n* $2 - the section title of the discussion\n* $3 - a link to a page and section\n* $4 - the page on which the discussion exists, plain text\nSee also:\n* {{msg-mw|Notification-add-comment-yours2}}",
- "notification-add-talkpage-topic2": "Format for displaying notifications of a new discussion being added. Parameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER.\n* $2 - the section title of the discussion\n* $3 - the page on which the discussion was added, plain text\nSee also:\n* {{msg-mw|Notification-edit-talk-page2}}\n* {{msg-mw|Notification-edit-talk-page-flyout2}}",
- "notification-add-talkpage-topic-yours2": "Parameters:\n* $1 - a username, plain text. Can be used for GENDER.\n* $2 - a page section\n* $3 - a page title",
- "notification-add-comment-yours2": "Parameters:\n* $1 - a username, plain text; can be used for GENDER\n* $2 - discussion name\n* $3 - link to user talk page\nSee also:\n* {{msg-mw|Notification-add-comment2}}",
- "notification-mention": "Format for displaying notifications of a comment in a specific section including a link to another user's user page.\n\nParameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER\n* $2 - the section title of the discussion\n* $3 - the page title of the discussion\n* $4 - the raw section title text\n* $5 - the title text without namespace (a page title in any namespace)",
- "notification-mention-flyout": "Flyout-specific format for displaying notifications of a comment in a specific section.\nParameters:\n* $1 - the username of the person who mentioned you, plain text. Can be used for GENDER.\n* $2 - the section title of the discussion\n* $3 - the page title of the discussion\n* $4 - the raw section title text\n* $5 - the title text without namespace (a page title in any namespace)",
- "notification-mention-nosection": "Format for displaying notifications of a comment including a link to another user's user page. Parameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER\n* $2 - the title text without namespace (a page title in any namespace)\n* $3 - the page title of the discussion",
- "notification-mention-nosection-flyout": "Flyout-specific format for displaying notifications of a comment.\nParameters:\n* $1 - the username of the person who edited, plain text. Can be used for GENDER\n* $2 - the title text without namespace (a page title in any namespace)\n* $3 - the page title of the discussion",
- "notification-user-rights": "Format for displaying notifications of a user right change in notification page.\n\nParameters:\n* $1 - the username of the person who made the user right change. Can be used for GENDER support.\n* $2 - a semicolon separated list of {{msg-mw|Notification-user-rights-add}}, {{msg-mw|Notification-user-rights-remove}}",
- "notification-user-rights-flyout": "Format for displaying notifications of a user right change in notification flyout. Parameters:\n* $1 - the username of the person who made the user right change. Can be used for GENDER support\n* $2 - a semicolon separated list of {{msg-mw|notification-user-rights-add}}, {{msg-mw|notification-user-rights-remove}}",
- "notification-user-rights-add": "Message indicating that a user was added to a user group. Parameters:\n* $1 - a comma separated list of user group names\n* $2 - the number of user groups, this is used for PLURAL support\nSee also:\n* {{msg-mw|Notification-user-rights-remove}}",
- "notification-user-rights-remove": "Message indicating that a user was removed from a user group. Parameters:\n* $1 - a comma separated list of user group names\n* $2 - the number of user groups, this is used for PLURAL support\nSee also:\n* {{msg-mw|Notification-user-rights-add}}",
- "notification-new-user": "Text of the welcome notification. Parameters:\n* $1 - the name of the new user\nSee also:\n* {{msg-mw|Guidedtour-tour-gettingstarted-start-title}}",
- "notification-reverted2": "Format for displaying notifications of a user's edit being reverted. Parameters:\n* $1 - the username of the person who reverted, plain text. Can be used for GENDER.\n* $2 - the page that was reverted, formatted\n* $3 - a diff link which is labeled {{msg-mw|Showdiff}}\n* $4 - the number of edits that were reverted. NOTE: This will only be set to 1 or 2, with 2 actually meaning 'an unknown number greater than 0'.\n* $5 - Page for reverting user.\nUser page if logged in, or user's contributions page if logged out.\n{{Related|Notification-reverted}}",
- "notification-reverted-flyout2": "Flyout-specific format for displaying notifications of a user's edit being reverted.\n\nParameters:\n* $1 - the username of the person who reverted, plain text. Can be used for GENDER.\n* $2 - the page that was reverted, formatted\n* $3 - a diff link which is labeled {{msg-mw|Showdiff}}\n* $4 - the number of edits that were reverted. NOTE: This will only be set to 1 or 2, with 2 actually meaning \"an unknown number greater than 0\".\n{{Related|Notification-reverted}}",
+ "notification-link-article-reminder": "Label for the link to the article the user requested to be reminded about",
+ "notification-header-reverted": "Notification header of a user's edit being reverted.\n\nParameters:\n* $2 - the username for GENDER\n* $3 - the page that was reverted, formatted\n* $4 - the number of edits that were reverted. NOTE: This will only be set to 1 or 2, with 2 actually meaning \"an unknown number greater than 0\".\n{{Related|Notification-reverted}}",
+ "notification-body-reverted": "{{notranslate}}",
+ "notification-header-emailuser": "Flyout-specific format for displaying notifications of user has sent an email to another user.\n\nParameters:\n* $1 - the formatted username of the person who sent the email.\n* $2 - the username for GENDER.",
+ "notification-body-emailuser": "{{notranslate}}",
"notification-edit-talk-page-email-subject2": "Email subject. Parameters:\n* $1 - a username which can be used for gender support",
- "notification-edit-talk-page-email-batch-body2": "First line of the email notification for a talk page edit. The following line completes it with the description of the message in question, that is its edit summary.\n\nParameters:\n* $1 - a username (which also links to the userpage of the user in question, in the HTML version)\nSee also:\n* {{msg-mw|Notification-edit-talk-page2}}\n* {{msg-mw|Notification-edit-talk-page-email-subject2}}\n* {{msg-mw|Notification-edit-talk-page-flyout2}}",
"notification-edit-talk-page-email-batch-body-with-section": "Email notification for talk page edit with new section or new comment. Parameters:\n* $1 - a username\n* $2 - the raw section title text",
- "notification-page-linked-email-subject": "E-mail subject.\nSee also:\n* {{msg-mw|Notification-page-linked}}\n* {{msg-mw|Notification-page-linked-flyout}}\n* {{msg-mw|Notification-page-linked-email-batch-body}}",
- "notification-page-linked-email-batch-body": "Email notification for page being linked. Parameters:\n* $1 - the username of the person who linked the page, plain text. Can be used for GENDER.\n* $2 - the page being linked\n* $3 - the page linked from\nSee also:\n* {{msg-mw|Notification-page-linked}}\n* {{msg-mw|Notification-page-linked-flyout}}\n* {{msg-mw|Notification-page-linked-email-subject}}",
+ "notification-page-linked-email-subject": "E-mail subject.\nSee also:\n* {{msg-mw|Notification-page-linked-flyout}}",
"notification-reverted-email-subject2": "Email subject. Parameters:\n* $1 - a username\n* $2 - (Unused) a page title\n* $3 - the number of reverts\n{{Related|Notification-reverted}}",
- "notification-reverted-email-batch-body2": "Email notification for page revert. Parameters:\n* $1 - a username\n* $2 - a page title\n* $3 - the number of revert\n{{Related|Notification-reverted}}",
- "notification-mention-email-subject": "Email subject. Parameters:\n* $1 - a username\nSee also:\n* {{msg-mw|Notification-mention}}\n* {{msg-mw|Notification-mention-flyout}}\n* {{msg-mw|Notification-mention-email-batch-body}}",
- "notification-mention-email-batch-body": "E-mail notification batch body. Parameters:\n* $1 - a username, plaintext. Can be used for gender support\n* $2 - (Unused) talk page title\n* $3 - the raw section title text\n* $4 - the title text without namespace (a page title in any namespace)\n\nSee also:\n* {{msg-mw|Notification-mention}}\n* {{msg-mw|Notification-mention-flyout}}\n* {{msg-mw|Notification-mention-email-subject}}",
- "notification-mention-nosection-email-batch-body": "E-mail notification batch body. Parameters:\n* $1 - a username, plaintext. Can be used for gender support\n* $2 - the title text without namespace (a page title in any namespace)\n\nSee also:\n* {{msg-mw|Notification-mention-nosection}}\n* {{msg-mw|Notification-mention-nosection-flyout}}\n* {{msg-mw|Notification-mention-email-subject}}",
- "notification-user-rights-email-subject": "E-mail subject for user rights notification\n\nSee also:\n* {{msg-mw|Notification-user-rights}}\n* {{msg-mw|Notification-user-rights-flyout}}\n* {{msg-mw|Notification-user-rights-email-batch-body}}",
- "notification-user-rights-email-batch-body": "Email notification batch body. Parameters:\n* $1 - a user name, plaintext. Can be used for gender support.\n* $2 - a semicolon separated list of {{msg-mw|notification-user-rights-add}}, {{msg-mw|notification-user-rights-remove}}",
- "echo-notification-count": "{{optional}}\nThe new notification count next to notification link, for example: 99+\n\nParameters:\n* $1 - the count",
- "echo-email-subject-default": "Default subject for Echo e-mail notifications",
+ "notification-mention-email-subject": "Email subject. Parameters:\n* $1 - a username\n* $2 - name of the user viewing the notification, can be used for GENDER\nSee also:\n* {{msg-mw|Notification-mention-flyout}}",
+ "notification-user-rights-email-subject": "E-mail subject for user rights notification\n\nSee also:\n* {{msg-mw|Notification-user-rights}}",
+ "notification-timestamp-ago-seconds": "Label for the amount of time since a notification has arrived in the case where it is under a minute. This should be a very short string. $1 - Number of seconds",
+ "notification-timestamp-ago-minutes": "Label for the amount of time since a notification has arrived in the case where it is in order of minutes. This should be a very short string. $1 - Number of minutes",
+ "notification-timestamp-ago-hours": "Label for the amount of time since a notification has arrived in the case where it is in order of hours. This should be a very short string. $1 - Number of hours",
+ "notification-timestamp-ago-days": "Label for the amount of time since a notification has arrived in the case where it is in order of days. This should be a very short string. $1 - Number of days",
+ "notification-timestamp-ago-months": "Label for the amount of time since a notification has arrived in the case where it is in order of months. This should be a very short string. $1 - Number of months",
+ "notification-timestamp-ago-years": "Label for the amount of time since a notification has arrived in the case where it is in order of years. This should be a very short string. $1 - Number of years",
+ "notification-timestamp-today": "Label for a group of notifications that arrived today.\n{{Identical|Today}}",
+ "notification-timestamp-yesterday": "Label for a group of notifications that arrived yesterday.\n{{Identical|Yesterday}}",
+ "notification-inbox-filter-read": "Label for the button that shows only read notification.\n{{Identical|Read}}",
+ "notification-inbox-filter-unread": "Label for the button that shows only unread notification.\n{{Identical|Unread}}",
+ "notification-inbox-filter-all": "Label for the button that shows all notification.\n{{Identical|All}}",
"echo-email-body-default": "Default message content for Echo email notifications. Parameters:\n* $1 - a plain text description of the notification",
- "echo-email-batch-body-default": "Default message for Echo e-mail digest notifications",
- "echo-email-footer-default": "Default footer content for Echo text e-mail notifications. Parameters:\n* $1 - the address of the organization that sent the email\n* $2 - \"-------...\" ({{msg-mw|echo-email-batch-separator}})\n\nFor HTML version, see {{msg-mw|echo-email-footer-default-html}}.",
"echo-email-footer-default-html": "Default footer content for Echo html e-mail notifications. Parameters:\n* $1 - the address of the organization that sent the email\n* $2 - the URL to the notification preference page\nFor plain-text version, see {{msg-mw|Echo-email-footer-default}}.",
- "echo-notification-alert": "Label for alert notifications (= non discussion notifications) tab in Echo overlay. Parameters:\n* $1 - the number of unread alerts. The number cannot be higher than 100.\nSee also:\n* {{msg-mw|Echo-notification-message}}\n{{Identical|Alert}}",
- "echo-notification-message": "Label for message notifications (= discussion notifications) tab in Echo overlay. Parameters:\n* $1 - the number of unread messages. The number cannot be higher than 100.\nSee also:\n* {{msg-mw|Echo-notification-alert}}\n{{Identical|Message}}",
+ "echo-email-footer-default": "Default footer content for Echo text e-mail notifications. Parameters:\n* $1 - the address of the organization that sent the email\n* $2 - \"-------...\" ({{msg-mw|echo-email-batch-separator}})\n\nFor HTML version, see {{msg-mw|echo-email-footer-default-html}}.",
+ "echo-email-plain-footer": "Footer content for Echo text e-mail notifications. Parameters:\n* $1 - the name of the user being addressed, used for GENDER\n\nFor HTML version, see {{msg-mw|echo-email-html-footer}}.",
+ "echo-email-html-footer-preference-link-text": "Text of link to the preference page in the footer of HTML emails. Parameters:\n* $1 - the name of the user being addressed, used for GENDER",
+ "echo-email-html-footer-with-link": "Footer content of the HTML email. Parameters:\n* $1 - complete HTML link to the preference page. $2 - the name of the user being addressed, used for GENDER\n\nSee {{msg-mw|echo-email-html-footer-preference-link-text}} for the text of the link.",
+ "echo-notification-alert": "Label for alert notifications (= non discussion notifications) tab in Echo overlay. Parameters:\n* $1 - the number of unread alerts. The number cannot be higher than 100.\nSee also:\n* {{msg-mw|Echo-notification-notice}}\n{{Identical|Alert}}",
+ "echo-notification-notice": "Label for notice notifications tab in Echo overlay. Parameters:\n* $1 - the number of unread notices. The number cannot be higher than 100.\nSee also:\n* {{msg-mw|Echo-notification-notice}}\n{{Identical|Notice}}",
"echo-notification-alert-text-only": "Label for alert notifications (= non discussion notifications) tab in Echo overlay without alert notification count next to it\n{{Identical|Alert}}",
- "echo-notification-message-text-only": "Label for message notifications (= discussion notifications) tab in Echo overlay without message notification count next to it\n{{Identical|Message}}",
+ "echo-notification-notice-text-only": "Label for notice notifications tab in Echo overlay without notice notification count next to it. That label groups all notifications less important than the ones displayed in \"alerts\".\n{{Identical|Notice}}",
"echo-overlay-link": "Link to \"all notifications\" at the bottom of the overlay.\n{{Identical|All notifications}}",
"echo-overlay-title": "Title at the top of the notifications overlay. Should include bold tags.\n{{Identical|Notification}}",
"echo-overlay-title-overflow": "Title at the top of the notifications overlay when there are additional unread notifications that are not being shown.\n\nParameters:\n* $1 - the number of unread notifications being shown\n* $2 - the total number of unread notifications that exist",
- "echo-mark-all-as-read": "Text for button that marks all unread notifications as read. Keep this short as possible.\n{{Identical|Mark all as read}}",
+ "echo-mark-all-as-read": "Text for button that marks all unread notifications as read. Keep this as short as possible.\n{{Identical|Mark all as read}}",
+ "echo-mark-all-as-read-confirmation": "Text for the confirmation message that appers after the user marks all unread notifications as read. Keep this as short as possible\n\nParameters:\n* $1 - The number of notifications that were marked as read",
+ "echo-mark-wiki-as-read": "Text for button that marks all unread notifications as read in a specific wiki. Keep this as short as possible.\n\nParameters:\n* $1 - The human readable name of the selected wiki",
"echo-date-today": "The header text for today's notification section.\n{{Identical|Today}}",
"echo-date-yesterday": "The header text for yesterday's notification section.\n{{Identical|Yesterday}}",
"echo-load-more-error": "Error message for errors in loading more notifications",
- "notification-edit-talk-page-bundle": "Bundled message for edit-user-talk notification. Parameters:\n* $1 - the name of the user who performed the action, which can be used for gender support\n* $2 - the name of the user being addressed\n* $3 - the count of other action performers, could be a number or {{msg-mw|Echo-notification-count}}. e.g. \"7\" or \"99+\"\n* $4 - a number used for plural support relating to $3 (likely identical to $3 it that is a number, and 100 otherwise)\nSee also:\n* {{msg-mw|Notification-edit-talk-page2}}\n* {{msg-mw|Notification-edit-talk-page-email-batch-body2}}\n* {{msg-mw|Notification-edit-talk-page-email-subject2}}",
- "notification-page-linked-bundle": "Bundled message for page-linked notification. Parameters:\n* $1 - the username who performs the action, which can be used for gender support\n* $2 - the page title\n* $3 - the page linked from\n* $4 - the count of other action performers, could be number or {{msg-mw|Echo-notification-count}}. e.g. 7 others or 99+ others\n* $5 - a number used for plural support (numeric version of $4)\nSee also:\n* {{msg-mw|Notification-page-linked}}\n* {{msg-mw|Notification-page-linked-flyout}}\n* {{msg-mw|Notification-page-linked-email-batch-body}}\n* {{msg-mw|Notification-page-linked-email-subject}}",
- "notification-edit-user-talk-email-batch-bundle-body": "Bundled message for edit-user-talk email digest notification. Parameters:\n* $1 - the username who performs the action, which can be used for gender support\n* $2 - the count of other action performers, could be number or {{msg-mw|echo-notification-count}}\n* $3 - a number used for plural support\n\nSee also:\n* {{msg-mw|Notification-edit-talk-page2}}\n* {{msg-mw|Notification-edit-talk-page-flyout2}}\n* {{msg-mw|Notification-edit-talk-page-email-batch-body2}}\n* {{msg-mw|Notification-edit-talk-page-email-subject2}}",
- "notification-page-linked-email-batch-bundle-body": "Bundled message for page-linked email digest notification. Parameters:\n* $1 - the username who performs the action, which can be used for gender support\n* $2 - the link-to page title\n* $3 - the link-from page title\n* $4 - the count of other link-from page title, can be number or {{msg-mw|echo-notification-count}}\n* $5 - a number used for plural support (numeric version of $4)\n\nSee also:\n* {{msg-mw|Notification-page-linked}}\n* {{msg-mw|Notification-page-linked-flyout}}\n* {{msg-mw|Notification-page-linked-email-batch-body}}\n* {{msg-mw|Notification-page-linked-email-subject}}",
+ "notification-bundle-header-edit-user-talk-v2": "Bundled header message for edit-user-talk notification. Parameters:\n* $1 - the number of new messages, except that if the count is greater than 99, this value will be 100; uses standard number formatting and used for PLURAL\n* $2 - Unused\n* $3 - the name of the user being addressed, can be used for GENDER\n{{Related|Notification-bundle}}",
"echo-email-batch-separator": "{{optional}}\nEmail batch content separator",
"echo-email-batch-bullet": "{{optional}}",
- "echo-email-batch-subject-daily": "Daily email batch subject.\n* $1 - (Unused) could be a numeric count or \"10+\". See also: {{msg-mw|Echo-notification-count|optional message}}.\n* $2 - a numeric count, this is used for plural support\nSee also:\n* {{msg-mw|Echo-email-batch-subject-weekly}}",
- "echo-email-batch-subject-weekly": "Weekly email batch subject. Parameters:\n* $1 - (Unused) could be a numeric count or \"10+\". See also: {{msg-mw|Echo-notification-count|optional message|notext=1}}\n* $2 - a numeric count, this is used for plural support\nSee also:\n* {{msg-mw|Echo-email-batch-subject-daily}}",
+ "echo-email-batch-subject-daily": "Daily email batch subject.\n* $1 - (Unused, Compatibility) Same as $2. \n* $2 - a numeric count, this is used for plural support\nSee also:\n* {{msg-mw|Echo-email-batch-subject-weekly}}",
+ "echo-email-batch-subject-weekly": "Weekly email batch subject. Parameters:\n* $1 - (Unused, Compatibility) Same as $2\n* $2 - a numeric count, this is used for plural support\nSee also:\n* {{msg-mw|Echo-email-batch-subject-daily}}",
"echo-email-batch-body-intro-daily": "Introduction text for daily email digest. Parameters:\n* $1 - a username\nSee also:\n* {{msg-mw|Echo-email-batch-body-intro-weekly}}",
"echo-email-batch-body-intro-weekly": "Introduction text for weekly email digest. Parameters:\n* $1 - a username\nSee also:\n* {{msg-mw|Echo-email-batch-body-intro-daily}}",
"echo-email-batch-link-text-view-all-notifications": "The link text for the primary action in daily and weekly email digest",
- "echo-rev-deleted-text-view": "Short message displayed instead of edit content when revision text is suppressed.",
- "apihelp-echomarkread-description": "{{doc-apihelp-description|echomarkread}}",
- "apihelp-echomarkread-param-list": "{{doc-apihelp-param|echomarkread|list}}",
- "apihelp-echomarkread-param-all": "{{doc-apihelp-param|echomarkread|all}}",
- "apihelp-echomarkread-param-sections": "{{doc-apihelp-param|echomarkread|sections}}",
- "apihelp-echomarkread-example-1": "{{doc-apihelp-example|echomarkread}}",
- "apihelp-echomarkread-example-2": "{{doc-apihelp-example|echomarkread}}",
- "apihelp-echomarkseen-description": "{{doc-apihelp-description|echomarkseen}}",
- "apihelp-echomarkseen-example-1": "{{doc-apihelp-example|echomarkseen}}",
- "apihelp-echomarkseen-param-type": "{{doc-apihelp-param|query+notifications|type}}",
- "apihelp-query+notifications-description": "{{doc-apihelp-description|query+notifications}}",
- "apihelp-query+notifications-param-prop": "{{doc-apihelp-param|query+notifications|prop}}",
- "apihelp-query+notifications-param-sections": "{{doc-apihelp-param|query+notifications|sections}}",
- "apihelp-query+notifications-param-groupbysection": "{{doc-apihelp-param|query+notifications|groupbysection}}",
- "apihelp-query+notifications-param-format": "{{doc-apihelp-param|query+notifications|format}}",
- "apihelp-query+notifications-param-limit": "{{doc-apihelp-param|query+notifications|limit}}",
- "apihelp-query+notifications-param-index": "{{doc-apihelp-param|query+notifications|index}}",
- "apihelp-query+notifications-param-alertcontinue": "{{doc-apihelp-param|query+notifications|alertcontinue}}",
- "apihelp-query+notifications-param-alertunreadfirst": "{{doc-apihelp-param|query+notifications|alertunreadfirst}}",
- "apihelp-query+notifications-param-messagecontinue": "{{doc-apihelp-param|query+notifications|messagecontinue}}",
- "apihelp-query+notifications-param-messageunreadfirst": "{{doc-apihelp-param|query+notifications|messageunreadfirst}}",
- "apihelp-query+notifications-example-1": "{{doc-apihelp-example|query+notifications}}",
- "apihelp-query+notifications-example-2": "{{doc-apihelp-example|query+notifications}}"
+ "notification-header-foreign-alert": "Flyout-specific format for displaying notification header of having alert notifications on foreign wikis.\n\nParameters:\n* $1 - the formatted username of the current user.\n* $2 - the username for GENDER\n* $3 (deprecated) - 1 of the foreign wikis you have notifications on\n* $4 (deprecated) - the number of remaining other wikis you have notifications on\n*$5 - the number of other wikis you have notifications on",
+ "notification-header-foreign-notice": "Flyout-specific format for displaying notification header of having notice notifications on foreign wikis.\n\nParameters:\n* $1 - the formatted username of the current user.\n* $2 - the username for GENDER\n* $3 (deprecated) - 1 of the foreign wikis you have notifications on\n* $4 (deprecated) - the number of remaining other wikis you have notifications on\n*$5 - the number of other wikis you have notifications on",
+ "notification-header-foreign-all": "Flyout-specific format for displaying notification header of having notifications (combined alerts and messages) on foreign wikis.\n\nParameters:\n* $1 - the formatted username of the current user.\n* $2 - the username for GENDER\n* $3 (deprecated) - 1 of the foreign wikis you have notifications on\n* $4 (deprecated) - the number of remaining other wikis you have notifications on\n*$5 - the number of other wikis you have notifications on",
+ "notification-body-foreign": "{{notranslate}}",
+ "echo-foreign-wiki-lang": "Title of the wiki for which you're seeing foreign notifications:\n\nParameters:\n* $1 - the name of the site (e.g. 'Wikipedia', 'Wikiversity', ...)\n* $2 - the language of the website (e.g. 'English', 'Deutsch', ...)",
+ "echo-badge-count": "Used only for the two Echo badges shown on the personal toolbar.\nParameters:\n* $1 - Formatted notification count. However, for 100 or greater, 100 will be passed."
}
diff --git a/Echo/i18n/qu.json b/Echo/i18n/qu.json
index efde9770..c15e8902 100644
--- a/Echo/i18n/qu.json
+++ b/Echo/i18n/qu.json
@@ -12,23 +12,20 @@
"echo-learn-more": "Astawan yachay",
"echo-new-messages": "Musuq willaykunam qhawanayki kachkan",
"notifications": "Willaykuykuna",
- "tooltip-pt-notifications": "Qampaq willaykuna",
+ "tooltip-pt-notifications-alert": "{{GENDER:|}}Ch'itiyayniykikuna",
+ "tooltip-pt-notifications-message": "{{GENDER:|}}Willayniykikuna",
"echo-specialpage": "Willaykuykuna",
"notification-link-text-view-message": "Willasqata qhaway",
"notification-link-text-view-changes": "Hukchasqakunata qhaway",
"notification-edit-talk-page2": "[[User:$1|$1]] sutiyuq ruraqqa qampaq {{GENDER:$1|willaynintam}} [[User talk:$2#$3|rimanakuy p'anqaykipi]] saqisurqanki.",
"notification-edit-talk-page-with-section": "[[User:$1|$1]] sutiyuq ruraqqa qampaq {{GENDER:$1|willaynintam}} rimanakuy p'anqaykipi [[User talk:$2#$3|$4]]-pi saqisurqanki.",
- "notification-edit-talk-page-flyout2": "$1 qampaq {{GENDER:$1|willaynintam}} [[User talk:$2#$3|rimanakuy p'anqaykipi]] saqisurqanki.",
- "notification-edit-talk-page-flyout-with-section": "$1 qampaq {{GENDER:$1|willaynintam}} rimanakuy p'anqaykipi [[User talk:$2#$3|$4]]-pi saqisurqanki.",
"notification-mention": "[[User:$1|$1]] qammanta rimaspa {{GENDER:$1|qillqarqan}} $5 rimanakuy p'anqapi \"[[:$3#$2|$4]]\" nisqapim.",
- "notification-mention-flyout": "$1 qammanta rimaspa {{GENDER:$1|qillqarqan}} $5 rimanakuy p'anqapi \"[[:$3#$2|$4]]\" nisqapim.",
- "notification-reverted2": "[[User:$1|$1]] sutiyuq ruraqqa [[:$2]] nisqapi qampa {{PLURAL:$4|llamk'apusqaykita|llamk'apusqaykikunata}} {{GENDER:$1|kutichirqanmi}}. $3",
- "notification-reverted-flyout2": "$1 sutiyuq ruraqqa $2 nisqapi qampa {{PLURAL:$4|llamk'apusqaykita|llamk'apusqaykikunata}} {{GENDER:$1|kutichirqanmi}}. $3",
+ "notification-reverted2": "[[$5|$1]] sutiyuq ruraqqa [[:$2]] nisqapi qampa {{PLURAL:$4|llamk'apusqaykita|llamk'apusqaykikunata}} {{GENDER:$1|kutichirqanmi}}. $3",
+ "notification-header-reverted": "$1 sutiyuq ruraqqa $3 nisqapi qampa {{PLURAL:$4|llamk'apusqaykita|llamk'apusqaykikunata}} {{GENDER:$2|kutichirqanmi}}.",
"notification-edit-talk-page-email-subject2": "$1 sutiyuq {{GENDER:$1|ruraqqa}} willasqantam saqisurqanki {{SITENAME}} nisqapi.",
"notification-edit-talk-page-email-batch-body2": "$1 sutiyuq {{GENDER:$1|ruraqqa}} rimanakuy p'anqaykipi willasqantam saqirqan:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 sutiyuq {{GENDER:$1|ruraqqa}} rimanakuy p'anqaykipi willasqantam saqisurqanki \"$2\" nisqapi.",
"echo-email-footer-default": "$2\n\nKachasunayku e-chaski qillqakunata kamachinaykipaqqa, allinkachinaykikunata llanchiy:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Kachasunayku e-chaski qillqakunata kamachinaykipaqqa, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">allinkachinaykikunata llanchiy</a>.<br />\n$1",
"echo-overlay-link": "Tukuy qampaq willaykuykuna",
"echo-overlay-title": "<b>Willaykuykuna</b>",
"notification-edit-talk-page-bundle": "$1, $3 {{PLURAL:$4|wakinpas|wakinkunapas}} qampaq {{GENDER:$1|willaynintam}} [[User talk:$2|rimanakuy p'anqaykipi]] saqisurqanki.",
diff --git a/Echo/i18n/rm.json b/Echo/i18n/rm.json
index 58855ec4..1e2909c3 100644
--- a/Echo/i18n/rm.json
+++ b/Echo/i18n/rm.json
@@ -1,8 +1,10 @@
{
"@metadata": {
"authors": [
- "Kazu89"
+ "Kazu89",
+ "Terfili"
]
},
- "echo-new-messages": "Ti has novs messadis"
+ "echo-new-messages": "Ti has novs messadis",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Tias}} notificaziuns"
}
diff --git a/Echo/i18n/ro.json b/Echo/i18n/ro.json
index e1e58ed3..4a6265cb 100644
--- a/Echo/i18n/ro.json
+++ b/Echo/i18n/ro.json
@@ -5,7 +5,10 @@
"Minisarm",
"Reception123",
"Stelistcristi",
- "ImGelu"
+ "ImGelu",
+ "Wintereu",
+ "Macofe",
+ "Strainu"
]
},
"echo-desc": "Sistem de notificare a utilizatorilor cu privire la evenimente și mesaje",
@@ -13,6 +16,7 @@
"prefs-emailsettings": "Setări pentru e-mail",
"prefs-displaynotifications": "Opțiuni de afișare",
"prefs-echosubscriptions": "Notifică-mă despre aceste evenimente",
+ "prefs-echocrosswiki": "Notificări inter-wiki",
"prefs-newmessageindicator": "Indicator de mesaj nou",
"echo-pref-send-me": "Trimite-mi:",
"echo-pref-send-to": "Trimite la:",
@@ -25,8 +29,12 @@
"echo-pref-email-frequency-weekly": "Un rezumat săptămânal al notificărilor",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Text brut",
+ "echo-pref-cross-wiki-notifications": "Arată notificări de la alte wikiuri",
"echo-pref-new-message-indicator": "Arată indicator pentru mesajele din pagina de discuții în bara mea de instrumente",
+ "echo-pref-beta-feature-cross-wiki-message": "Notificări îmbunătățite",
+ "echo-pref-beta-feature-cross-wiki-description": "Vizualizați și gestionați notificările mai ușor. Include notificări inter-wiki, care vă permit să vizualizați mesajele de la alte wikiuri.",
"echo-learn-more": "Aflați mai multe",
+ "echo-log": "Jurnal public",
"echo-new-messages": "Aveți mesaje noi",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Mesaj|Mesaje}} în pagina de discuții",
"echo-category-title-article-linked": "{{PLURAL:$1|Legătură|Legături}} către pagină",
@@ -35,68 +43,80 @@
"echo-category-title-other": "{{PLURAL:$1|Altele}}",
"echo-category-title-system": "{{PLURAL:$1|Sistem}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Schimbare a drepturilor de utilizator|Schimbări ale drepturilor de utilizator}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-mail de la un alt utilizator|E-mailuri de la alți utilizatori}}",
"echo-pref-tooltip-edit-user-talk": "Notifică-mă când cineva publică un mesaj sau răspunde pe pagina mea de discuții.",
"echo-pref-tooltip-article-linked": "Notifică-mă atunci când cineva introduce într-un articol o legătură către una din paginile pe care le-am creat.",
"echo-pref-tooltip-reverted": "Notifică-mă atunci când cineva, folosind uneltele de anulare sau revenire, revine asupra unei modificări făcută de mine.",
"echo-pref-tooltip-mention": "Notifică-mă când cineva face referire la pagina mea de utilizator.",
- "echo-pref-tooltip-user-rights": "Anunță-mă când cineva îmi schimbă drepturile de autor.",
- "echo-no-agent": "[Nimeni]",
- "echo-no-title": "[Nicio pagină]",
+ "echo-pref-tooltip-user-rights": "Anunță-mă când cineva îmi schimbă drepturile de utilizator.",
+ "echo-pref-tooltip-emailuser": "Anunță-mă când cineva îmi trimite un e-mail.",
"echo-error-no-formatter": "Nicio formatare definită pentru această notificare.",
"notifications": "Notificări",
- "tooltip-pt-notifications": "Notificările dumneavoastră",
+ "tooltip-pt-notifications-alert": "Alertele {{GENDER:|dumneavoastră}}",
+ "echo-displaynotificationsconfiguration": "Configurare Afișare notificări",
+ "echo-displaynotificationsconfiguration-summary": "Acesta este un rezumat al modului în care Notificări a fost configurată pe acest wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Notificări după categorie",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sortare tipuri",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Metode permise de notificare",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Activat în mod implicit",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Utilizatori existenți",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Utilizatori noi",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Metode obligatorii de notificare",
"echo-specialpage": "Notificări",
+ "echo-specialpage-section-markread": "Marchează secțiunea ca citită",
+ "echo-specialpage-markasread": "Notificare: Marcare ca citită",
+ "echo-specialpage-markasread-invalid-id": "ID de eveniment nevalid",
+ "notificationsmarkread-legend": "Marchează notificarea ca citită",
"echo-anon": "Pentru a primi notificări, [$1 creați-vă un cont] sau [$2 autentificați-vă].",
"echo-none": "Nu aveți nicio notificare.",
"echo-more-info": "Mai multe informații",
"echo-feedback": "Reacții",
+ "echo-api-failure": "Imposibil de obținut notificările.",
+ "echo-notification-placeholder": "Nu există notificări.",
+ "echo-notification-loginrequired": "Trebuie să vă autentificați pentru a vedea notificările.",
+ "echo-notification-popup-loginrequired": "Autentificați-vă pentru a vedea notificările.",
+ "echo-notification-markasread": "Marchează ca citită",
+ "echo-notification-markasunread": "Marchează ca necitită",
+ "echo-notification-markasread-tooltip": "Marchează ca citită",
+ "echo-notification-more-options-tooltip": "Mai multe opțiuni",
+ "notification-link-text-expand-all": "Extinde",
+ "notification-link-text-expand-alert-count": "Arată {{PLURAL:$1|$1 alertă|$1 alerte|$1 de alerte}}",
+ "notification-link-text-expand-all-count": "Arată {{PLURAL:$1|$1 notificare|$1 notificări|$1 de notificări}}",
+ "notification-link-text-collapse-all": "Restrânge",
"notification-link-text-view-message": "Vezi mesajul",
"notification-link-text-view-mention": "Vezi menționarea",
- "notification-link-text-view-changes": "Vezi schimbările",
+ "notification-link-text-view-changes": "{{GENDER:$1|Vezi}} schimbările",
"notification-link-text-view-page": "Vezi pagina",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|a lăsat}} un mesaj pe <strong>pagina {{GENDER:$3|dumnevoastră}} de discuții</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|a lăsat}} un mesaj pe <strong>pagina {{GENDER:$3|dumneavoastră}} de discuții</strong>, în cadrul secțiunii „<strong>$4</strong>”.",
+ "notification-header-page-linked": "A fost creată o legătură de la <strong>$4</strong> către <strong>$3</strong>.",
+ "notification-bundle-header-page-linked": "Au fost create legături de la <strong>$4</strong> și {{PLURAL:$5|încă o pagină|încă alte $5 pagini|încă alte $5 de pagini|100=alte 99+ pagini}} către <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Toate legăturile către această pagină",
+ "notification-header-welcome": "{{GENDER:$2|Bun venit}} la {{SITENAME}}, $1! Ne bucurăm să {{GENDER:$2|vă avem}} printre noi.",
+ "notification-welcome-linktext": "Bun venit",
+ "notification-link-thank-you-edit": "Modificarea {{GENDER:$1|dumnevoastră}}",
"notification-link-text-view-edit": "Vezi modificarea",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|a lăsat}} un mesaj pe [[User talk:$2#$3|pagina dumneavoastră de discuții]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|a lăsat}} un mesaj pe pagina dumneavoastră de discuții, în cadrul secțiunii „[[User talk:$2#$3|$4]]”.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|a lăsat}} un mesaj pe [[User talk:$2#$3|pagina dumneavoastră de discuții]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|a lăsat}} un mesaj pe pagina dumneavoastră de discuții, în cadrul secțiunii „[[User talk:$2#$3|$4]]”.",
- "notification-page-linked": "[[:$2]] a fost {{GENDER:$1|menționată}} în [[:$3]]: [[Special:WhatLinksHere/$2|Vedeți toate legăturile către această pagină]].",
- "notification-page-linked-flyout": "[[:$2]] a fost {{GENDER:$1|menționată}} în [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|a comentat}} subiectul „[[$3|$2]]” din pagina de discuție „$4”.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|a pornit}} un nou subiect („$2”) pe [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|v-a trimis}} un mesaj: „[[$3#$2|$2]]”.",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|a comentat}} subiectul „[[$3#$2|$2]]” de pe pagina dumneavoastră de discuții.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|v-a menționat}} pe pagina de discuții a paginii $5, în cadrul secțiunii „[[:$3#$2|$4]]”.",
- "notification-mention-flyout": "$1 {{GENDER:$1|v-a menționat}} pe pagina de discuții a paginii $5, în cadrul secțiunii „[[:$3#$2|$4]]”.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|v-a menționat}} pe [[:$3|pagina de discuție a paginii $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|v-a menționat}} pe [[:$3|pagina de discuție a paginii $2]].",
- "notification-user-rights": "Drepturile dumneavoastră de utilizator [[Special:Log/rights/$1|au fost {{GENDER:$1|schimbate}}]] de către [[User:$1|$1]]. $2. [[Special:ListGroupRights|Aflați mai multe]]",
- "notification-user-rights-flyout": "Drepturile dumneavoastră de utilizator au fost {{GENDER:$1|schimbate}} de către $1. $2. [[Special:ListGroupRights|Aflați mai multe]]",
- "notification-user-rights-add": "Sunteți acum membru al {{PLURAL:$2|acestui grup|acestor grupuri}}: $1",
- "notification-user-rights-remove": "Nu mai sunteți membru al {{PLURAL:$2|acestui grup|acestor grupuri}}: $1",
- "notification-new-user": "Bine ați venit la {{SITENAME}}, $1! Ne bucurăm că sunteți aici.",
- "notification-reverted2": "{{PLURAL:$4|Modificarea dumneavoastră asupra paginii [[:$2]] a|Modificările dumneavoastră asupra paginii [[:$2]] au}} fost {{GENDER:$1|înlăturat}}{{PLURAL:$4|ă|e}} de către [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Modificarea dumneavoastră asupra paginii $2 a|Modificările dumneavoastră asupra paginii $2 au}} fost {{GENDER:$1|înlăturat}}{{PLURAL:$4|ă|e}} de către $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Modificarea dumneavoastră asupra paginii <strong>$3</strong> a|Modificările dumneavoastră asupra paginii <strong>$3</strong> au}} fost {{GENDER:$2|înlăturat}}{{PLURAL:$4|ă|e}}",
+ "notification-header-emailuser": "$1 {{GENDER:$2|v-a trimis}} un e-mail.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|v-a lăsat}} un mesaj la {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|a lăsat}} un mesaj pe pagina dumneavoastră de discuții.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|a lăsat}} un mesaj pe pagina dumneavoastră de discuții, în cadrul secțiunii „$2”.",
"notification-page-linked-email-subject": "O pagină creată de dumnevoastră a fost menționată la {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 a fost {{GENDER:$1|menționată}} în $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Modificarea dumneavoastră a fost|Modificările dumneavoastră au fost}} {{GENDER:$1|înlăturat}}{{PLURAL:$3|ă|e}} la {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Modificarea dumneavoastră asupra paginii $2 a fost|Modificările dumneavoastră asupra paginii $2 au fost}} {{GENDER:$1|înlăturat}}{{PLURAL:$3|ă|e}} de către $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|v-a menționat}} la {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|v-a menționat}} pe pagina de discuții a paginii $4, în secțiunea „$3”.",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|v-a menționat}} pe pagina de discuție a paginii $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|v}}{{GENDER:$1|-a menționat}} la {{SITENAME}}",
"notification-user-rights-email-subject": "Drepturile dumneavoastră de utilizator s-au schimbat la {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Drepturile dumneavoastră de utilizator au fost {{GENDER:$1|schimbate}} de către $1. $2",
- "echo-email-subject-default": "Notificare nouă la {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 z}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 l}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 an|$1 ani}}",
"echo-email-body-default": "Aveți o notificare nouă la {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Aveți o notificare nouă.",
- "echo-email-footer-default": "$2\n\nPentru a avea controlul asupra tipurilor de e-mailuri pe care vi le trimitem, verificați-vă preferințele:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Pentru a controla e-mailurile pe care vi le trimitem, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">verificați-vă preferințele</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPentru a avea controlul asupra e-mailurilor pe care vi le trimitem, verificați-vă preferințele:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Pentru a avea controlul asupra e-mailurilor pe care vi le trimitem, verificați-vă preferințele:",
+ "echo-email-html-footer-preference-link-text": "verificați-vă preferințele",
+ "echo-email-html-footer-with-link": "Pentru a avea controlul asupra e-mailurilor pe care vi le trimitem, $1.",
"echo-notification-alert": "{{PLURAL:$1|Alertă ($1)|Alerte ($1)|100=Alerte (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Mesaj ($1)|Mesaje ($1)|100=Mesaje (99+)}}",
"echo-notification-alert-text-only": "Alerte",
- "echo-notification-message-text-only": "Mesaje",
"echo-overlay-link": "Toate notificările",
"echo-overlay-title": "<b>Notificări</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notificări}}</b> (se afișează $1 din $2 necitite)",
@@ -104,14 +124,9 @@
"echo-date-today": "Astăzi",
"echo-date-yesterday": "Ieri",
"echo-load-more-error": "A apărut o eroare în timpul obținerii mai multor rezultate.",
- "notification-edit-talk-page-bundle": "$1 și încă {{PLURAL:$4|altcineva|alți $3}} {{GENDER:$1|au lăsat}} un mesaj pe [[User talk:$2|pagina dumneavoastră de discuții]].",
- "notification-page-linked-bundle": "$2 a fost {{GENDER:$1|menționată}} în $3 și încă {{PLURAL:$5|o pagină|alte $4 pagini}}. [[Special:WhatLinksHere/$2|Vedeți toate legăturile către această pagină]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 și încă {{PLURAL:$3|altcineva|alți $2}} {{GENDER:$1|au lăsat}} un mesaj pe pagina dumneavoastră de discuții.",
- "notification-page-linked-email-batch-bundle-body": "$2 a fost {{GENDER:$1|menționată}} în $3 și încă {{PLURAL:$5|o pagină|alte $4 pagini}}.",
"echo-email-batch-subject-daily": "Aveți {{PLURAL:$2|o notificare nouă|notificări noi}} la {{SITENAME}}",
"echo-email-batch-subject-weekly": "Aveți {{PLURAL:$2|o notificare nouă|notificări noi}} la {{SITENAME}} în această săptămână",
"echo-email-batch-body-intro-daily": "Bună ziua $1,\nAveți aici un rezumat al activității de astăzi la {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Bună ziua $1,\nAveți aici un rezumat al activității din această săptămână la {{SITENAME}}.",
- "echo-email-batch-link-text-view-all-notifications": "Vezi toate notificările",
- "echo-rev-deleted-text-view": "Această versiune a paginii a fost suprimată."
+ "echo-email-batch-link-text-view-all-notifications": "Vezi toate notificările"
}
diff --git a/Echo/i18n/roa-tara.json b/Echo/i18n/roa-tara.json
index 24a0b02b..f4a63d00 100644
--- a/Echo/i18n/roa-tara.json
+++ b/Echo/i18n/roa-tara.json
@@ -11,6 +11,7 @@
"prefs-displaynotifications": "Opziune de visualizzazzione",
"prefs-echosubscriptions": "Notificame sus a ste avveneminde",
"prefs-newmessageindicator": "Indicatore de messàgge nuève",
+ "prefs-blocknotificationslist": "Utinde citte da sotte",
"echo-pref-send-me": "Manne a me:",
"echo-pref-send-to": "Manne a:",
"echo-pref-email-format": "Formate de l'email:",
@@ -32,64 +33,48 @@
"echo-category-title-other": "{{PLURAL:$1|Otre}}",
"echo-category-title-system": "{{PLURAL:$1|Sisteme}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Cangiamende|Cangiaminde}} de le deritte de l'utende",
- "echo-pref-tooltip-edit-user-talk": "Notificame quacche quacchedune manne 'nu messàgge o responne sus 'a pàgene de le 'ngazzaminde meje.",
- "echo-pref-tooltip-article-linked": "Notificame quacche quacchedune se colleghe a 'na pàgene ca ije agghie ccrejate da 'na vôsce.",
- "echo-pref-tooltip-reverted": "Notificame quanne quacchedune annulle 'nu cangiamende ca agghie fatte ije, ausanne 'u strumende de annullamende.",
- "echo-pref-tooltip-mention": "Notificame quanne quacchedune se colleghe a pàgena utende meje.",
- "echo-pref-tooltip-user-rights": "Notificame quanne quacchedune cange le deritte de utende meje.",
- "echo-no-agent": "[Nisciune]",
- "echo-no-title": "[Nisciuna vôsce]",
+ "echo-pref-tooltip-edit-user-talk": "Avvisame quacche quacchedune manne 'nu messàgge o responne sus 'a pàgene de le 'ngazzaminde meje.",
+ "echo-pref-tooltip-article-linked": "Avvisame quacche quacchedune se colleghe a 'na pàgene ca ije agghie ccrejate da 'n'otra vôsce.",
+ "echo-pref-tooltip-reverted": "Avvisame quanne quacchedune annulle 'nu cangiamende ca agghie fatte ije, ausanne 'u strumende de annullamende.",
+ "echo-pref-tooltip-mention": "Avvisame quanne quacchedune se colleghe a pàgena utende meje.",
+ "echo-pref-tooltip-user-rights": "Avvisame quanne quacchedune cange le deritte de utende meje.",
+ "echo-pref-tooltip-emailuser": "Avvisame quanne quacchedune manne 'na mail.",
"echo-error-no-formatter": "Nisciune formattazzione ha state definite pa notifiche",
"notifications": "Notificaziune",
"tooltip-pt-notifications-alert": "Avvise {{GENDER:|tune}}",
- "tooltip-pt-notifications-message": "Messàgge {{GENDER:|tune}}",
+ "tooltip-pt-notifications-notice": "Le notizie {{GENDER:|tune}}",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Utinde nuève",
"echo-specialpage": "Notificaziune",
"echo-anon": "Pe ricevere notifiche, <span class=\"plainlinks\">[$1 ccreje 'nu cunde] o <span class=\"plainlinks\">[$2 tràse].",
"echo-none": "Non ge tìne notifiche.",
"echo-more-info": "Cchiù 'mbormaziune",
"echo-feedback": "Segnalazione",
+ "echo-api-failure": "Non ge riesche a pigghià le notifiche.",
+ "echo-notification-placeholder": "Non ge stonne notifiche.",
+ "echo-notification-markasread": "Signe cumme lette",
+ "echo-notification-markasunread": "Signe cumme non lette",
+ "echo-notification-markasread-tooltip": "Signe cumme lette",
+ "echo-notification-more-options-tooltip": "Cchiù opziune",
+ "notification-link-text-expand-all": "Spanne",
+ "notification-link-text-expand-alert-count": "'Ndruche le {{PLURAL:$1|$1 avvise}}",
+ "notification-link-text-expand-notice-count": "'Ndruche {{PLURAL:$1|'a $1|le $1}} notizie",
+ "notification-link-text-collapse-all": "Scunne",
"notification-link-text-view-message": "'Ndruche 'u messàgge",
"notification-link-text-view-mention": "'Ndruche 'a menzione",
- "notification-link-text-view-changes": "'Ndruche le cangiaminde",
+ "notification-link-text-view-changes": "{{GENDER:$1|'Ndruche}} le cangiaminde",
"notification-link-text-view-page": "'Ndruche 'a pàgene",
+ "notification-link-text-what-links-here": "Tutte le collegaminde a sta pàgene",
"notification-link-text-view-edit": "'Ndruche 'u cangiamende",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|ha lassate}} 'nu messàgge sus 'a [[User talk:$2#$3|pàgene de le 'ngazzaminde]] tune.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|ave lassate}} 'nu messàgge sus 'a pàgene de le 'ngazzaminde toje jndr'à \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|ha lassate}} 'nu messàgge sus 'a [[User talk:$2#$3|pàgene de le 'ngazzaminde]] tune.",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|ave lassate}} 'nu messàgge sus 'a pàgene de le 'ngazzaminde toje jndr'à \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] ha state {{GENDER:$1|appundate}} da [[:$3]]. [[Special:WhatLinksHere/$2|'Ndruche tutte le collegaminde a sta pàgene]].",
- "notification-page-linked-flyout": "[[:$2]] ere {{GENDER:$1|appondate}} da [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|ave commendate}} sus a \"[[$3|$2]]\" sus a pàgene de le 'ngazzaminde \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|ave mannate}} 'n'argomende nuève \"$2\" sus a [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|t'ha mannate}} 'nu messàgge: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|ave commendate}} sus a \"[[$3#$2|$2]]\" sus 'a pàgene de le 'ngazzaminde tune",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|t'ave menzionate}} sus a pàgene de le 'ngazzaminde $5 jndr'à \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|t'ave menzionate}} sus a pàgene de le 'ngazzaminde $5 jndr'à \"[[:$3#$2|$4]]\".",
- "notification-user-rights": "Le deritte de l'utende [[Special:Log/rights/$1|onne state {{GENDER:$1|cangiate}}]] da [[User:$1|$1]]. $2. [[Special:ListGroupRights|'Mbare de cchiù]]",
- "notification-user-rights-flyout": "Le deritte tune onne state {{GENDER:$1|cangiate}} da $1. $2. [[Special:ListGroupRights|'Mbare de cchiù]]",
- "notification-user-rights-add": "Tu mò si nu memenre de {{PLURAL:$2|stu gruppe|ste gruppe}}: $1",
- "notification-user-rights-remove": "No ge sì cchiù 'nu membre de {{PLURAL:$2|stu gruppe|ste gruppe}}: $1",
- "notification-new-user": "Bovègne jndr'à {{SITENAME}}, $1! Nuje sime cundende ca ste aqquà.",
- "notification-reverted2": "{{PLURAL:$4|'U cangiamende tune sus a [[:$2]] ha|Le cangiaminde sus a [[:$2]] onne}} state {{GENDER:$1|annullate}} da [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "Your {{PLURAL:$4|'U cangiamende tune sus a $2 ha|Le cangiaminde tune sus a $2 onne}} state {{GENDER:$1|annullate}} by $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|'U cangiamende tune sus a $3 ave|Le cangiaminde tune sus a $3 onne}} state {{GENDER:$2|annullate}}.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|t'ha lassate}} 'nu messàgge sus a {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|t'ha lassate}} 'nu messàgge sus 'a pàgene de le 'ngazzaminde tune.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|t'ha lassate}} 'nu messàgge sus 'a pàgene de le 'ngazzaminde tune jndr'à \"$2\".",
"notification-page-linked-email-subject": "'Na pàgene ca tu è ccrejate ha state collagate sus a {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 ere {{GENDER:$1|collegate}} da $3",
"notification-reverted-email-subject2": "{{PLURAL:$3|'U cangiamende tune ha state|Le cangiaminde tune onne}} state {{GENDER:$1|annullate}} sus a {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|'U cangiamende tune sus a $2 ha state|Le cangiaminde tune sus a $2 onne}} state {{GENDER:$1|annullate}} da $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|t'ave menzionate}} sus a {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|'ave menzionate}} sus a pàgene de le 'ngazzaminde $4 jndr'à \"$3\".",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|t'ave}} {{GENDER:$1|menzionate}} sus a {{SITENAME}}",
"notification-user-rights-email-subject": "Le deritte utende tune onne state cangiate sus a {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Le deritte utende tune onne state {{GENDER:$1|cangiate}} da $1. $2.",
- "echo-email-subject-default": "Notifica nove sus a {{SITENAME}}",
"echo-email-body-default": "Tu è 'na notifica nove sus a {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Tu è 'na notifica nove",
- "echo-email-footer-default": "$2\n\nPe condrollà quale email t'amme mannate, verifiche le prefenze tune:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Pe condrollà quale email t'amme mannate, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">condrolle le preferenze tune</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nPe condrollà ce email t'amme mannate, verifiche le prefenze tune:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-notification-alert-text-only": "Avvise",
- "echo-notification-message-text-only": "Messàgge",
"echo-overlay-link": "Tutte le notificaziune",
"echo-overlay-title": "<b>Notifiche</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Notifiche}}</b> (face 'ndrucà $1 de $2 non lette)",
@@ -97,15 +82,9 @@
"echo-date-today": "Osce",
"echo-date-yesterday": "Ajere",
"echo-load-more-error": "Ha assute 'n'errore mendre analizzave le resultate.",
- "notification-edit-talk-page-bundle": "$1 e $3 {{PLURAL:$4|otre}} {{GENDER:$1|t'onne lassate}} 'nu messàgge sus a toje [[User talk:$2|pàgene de le 'ngazzaminde]].",
- "notification-page-linked-bundle": "$2 ha state {{GENDER:$1|appundate}} da $3 e $4 otre {{PLURAL:$5|pàgene|pàggene}}. [[Special:WhatLinksHere/$2|'Ndruche tutte le collegaminde a sta pàgene]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e $2 {{PLURAL:$3|otre}} {{GENDER:$1|t'onne lassate}} 'nu messàgge sus 'a pàgene de le 'ngazzaminde toje.",
- "notification-page-linked-email-batch-bundle-body": "$2 ha state {{GENDER:$1|appundate}} da $3 e $4 otre {{PLURAL:$5|pàgene|pàggene}}.",
"echo-email-batch-subject-daily": "Tu è {{PLURAL:$2|'na notifica|notifiche}} nove sus a {{SITENAME}}",
"echo-email-batch-subject-weekly": "Tu è {{PLURAL:$2|'na notifica|notifiche}} nove STA SUMàNE sus a {{SITENAME}}",
"echo-email-batch-body-intro-daily": "Cià $1,\nAqquà ste 'u rieploghe de l'attività de osce sus a {{SITENAME}} pe te.",
"echo-email-batch-body-intro-weekly": "Cià $1,\nAqquà ste 'u rieploghe de l'attività d'a sumàne sus a {{SITENAME}} pe te.",
- "echo-email-batch-link-text-view-all-notifications": "'Ndruche tutte le notifiche",
- "echo-rev-deleted-text-view": "Sta revisione d'a pàgene ha state accise",
- "apihelp-query+notifications-example-1": "Elenghe de le notifiche"
+ "echo-email-batch-link-text-view-all-notifications": "'Ndruche tutte le notifiche"
}
diff --git a/Echo/i18n/ru.json b/Echo/i18n/ru.json
index 2b187c74..d946f2dc 100644
--- a/Echo/i18n/ru.json
+++ b/Echo/i18n/ru.json
@@ -17,7 +17,26 @@
"Sunpriat",
"Чаховіч Уладзіслаў",
"Doff",
- "Marina Melik-Adamyan"
+ "Marina Melik-Adamyan",
+ "INS Pirat",
+ "Macofe",
+ "Iniquity",
+ "MaxBioHazard",
+ "Sealle",
+ "Исмаил Садуев",
+ "Putnik",
+ "Ole Yves",
+ "Лилиә",
+ "Alexandr Efremov",
+ "Jack who built the house",
+ "Mailman",
+ "Умар",
+ "Trizek (WMF)",
+ "Gamliel Fishkin",
+ "Alex Great",
+ "Facenapalm",
+ "ЛосЯш",
+ "DevilishSkull"
]
},
"echo-desc": "Система уведомления участников о событиях и сообщениях",
@@ -25,9 +44,11 @@
"prefs-emailsettings": "Настройки эл. почты",
"prefs-displaynotifications": "Настройки отображения",
"prefs-echosubscriptions": "Сообщать мне об этих событиях",
+ "prefs-echocrosswiki": "Уведомления из нескольких вики-проектов («кросс-вики»)",
"prefs-newmessageindicator": "Индикатор нового сообщения",
+ "prefs-blocknotificationslist": "Чёрный список",
"echo-pref-send-me": "Присылать мне:",
- "echo-pref-send-to": "Отправлять в:",
+ "echo-pref-send-to": "Отправлять на адрес:",
"echo-pref-email-format": "Формат писем:",
"echo-pref-web": "Веб",
"echo-pref-email": "Эл. почта",
@@ -37,113 +58,178 @@
"echo-pref-email-frequency-weekly": "Еженедельная сводка уведомлений",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Простой текст",
+ "echo-pref-cross-wiki-notifications": "Показывать уведомления с других вики",
"echo-pref-new-message-indicator": "Показать в моей панели инструментов индикатор сообщений на странице обсуждения",
+ "echo-pref-beta-feature-cross-wiki-message": "Улучшенные уведомления",
+ "echo-pref-beta-feature-cross-wiki-description": "Упрощает просмотр и организацию уведомлений. Включает «кросс-вики» уведомления, которые позволяют видеть сообщения из других вики. (Чтобы получать такие уведомления в этом вики-проекте, вы должны активировать здесь соответствующую бета-функцию.)",
"echo-learn-more": "Узнать больше",
+ "echo-log": "Общедоступный журнал",
"echo-new-messages": "У вас есть новые сообщения",
- "echo-category-title-edit-user-talk": "{{PLURAL:$1|1=сообщение|сообщения}} на странице обсуждения",
- "echo-category-title-article-linked": "{{PLURAL:$1|1=ссылка|ссылки}} на страницы",
- "echo-category-title-reverted": "{{PLURAL:$1|1=отмена|отмены}} правок",
- "echo-category-title-mention": "{{PLURAL:$1|1=упоминание|упоминания}}",
- "echo-category-title-other": "{{PLURAL:$1|1=прочее|прочие}}",
- "echo-category-title-system": "{{PLURAL:$1|1=системное|системные}}",
- "echo-category-title-user-rights": "{{PLURAL:$1|изменение|изменения}} прав участника",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|1=Сообщение|Сообщения}} на странице обсуждения",
+ "echo-category-title-article-linked": "{{PLURAL:$1|1=Ссылка на странице|Ссылки на страницах}}",
+ "echo-category-title-reverted": "{{PLURAL:$1|1=Отмена|Отмены}} правок",
+ "echo-category-title-mention": "{{PLURAL:$1|1=Упоминание|Упоминания}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Неудачное упоминание|Неудачные упоминания}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Успешное упоминание|Успешные упоминания}}",
+ "echo-category-title-other": "{{PLURAL:$1|1=Прочее|Прочие}}",
+ "echo-category-title-system": "{{PLURAL:$1|1=Системное|Системные}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Изменение|Изменения}} прав участника",
+ "echo-category-title-emailuser": "Электронная почта от {{PLURAL:$1|другого участника|других участников}}",
"echo-pref-tooltip-edit-user-talk": "Сообщать мне, когда кто-то посылает сообщение или отвечает на моей странице обсуждения.",
- "echo-pref-tooltip-article-linked": "Сообщать мне, когда кто-то ссылается в статьях на созданную мной страницу",
+ "echo-pref-tooltip-article-linked": "Сообщать мне, когда на созданную мной страницу кто-то ссылается с другой страницы.",
"echo-pref-tooltip-reverted": "Сообщать мне, когда кто-то отменил мою правку, используя функцию отмены или отката.",
"echo-pref-tooltip-mention": "Сообщать мне, когда кто-то ссылается на мою страницу участника.",
+ "echo-pref-tooltip-mention-failure": "Уведомлять меня, когда я не могу отправить упоминание кому-либо.",
+ "echo-pref-tooltip-mention-success": "Уведомлять меня, когда я отправляю упоминание кому-либо.",
"echo-pref-tooltip-user-rights": "Сообщать мне, когда кто-то изменяет мои права участника.",
- "echo-no-agent": "[Никто]",
- "echo-no-title": "[Нет страницы]",
+ "echo-pref-tooltip-emailuser": "Сообщать мне, когда кто-то присылает мне письмо по электронной почте.",
+ "echo-pref-tooltip-article-reminder": "Сообщите мне об этой странице, когда я попрошу.",
"echo-error-no-formatter": "Форматирование не определено для уведомления",
"notifications": "Уведомления",
"tooltip-pt-notifications-alert": "{{GENDER:|Ваши}} оповещения",
- "tooltip-pt-notifications-message": "{{GENDER:|Ваши}} сообщения",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Ваши}} уведомления",
+ "echo-displaynotificationsconfiguration": "Показать настройки уведомлений",
+ "echo-displaynotificationsconfiguration-summary": "Это обзор настроек уведомлений на этом вики-сайте.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Уведомления по категориям",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Сортировка по типам",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "В какие секции отсортирован каждый тип уведомлений",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Разрешенные способы уведомления",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Какие способы уведомления поддерживаются в каждой категории",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Какие методы уведомления поддерживаются для каждого типа; применяется только к типам в категориях, скрытых из настроек",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Включено по умолчанию",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Существующие участники",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Новые участники",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Требуемые способы уведомления",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Какие способы уведомления обязательны для каждой категории",
"echo-specialpage": "Уведомления",
+ "echo-specialpage-section-markread": "Пометить группу как прочитанную",
+ "echo-specialpage-markasread": "Уведомление: пометить как прочитанное",
+ "echo-specialpage-markasread-invalid-id": "Неверный идентификатор события",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|уведомление|уведомления|уведомлений}}",
+ "echo-specialpage-pagefilters-title": "Недавние действия",
+ "echo-specialpage-pagefilters-subtitle": "Страницы с непрочтёнными уведомлениями",
+ "notificationsmarkread-legend": "Пометить уведомление как прочитанное",
"echo-anon": "Чтобы получать уведомления, [$1 создайте учётную запись] или [$2 представьтесь].",
"echo-none": "Вы не получали уведомлений.",
"echo-more-info": "Подробнее",
"echo-feedback": "Обратная связь",
+ "echo-popup-footer-special-page-invitation": "<strong>Оцените обновлённую страницу уведомлений.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Новый дизайн и функции.",
"echo-quotation-marks": "«$1»",
+ "echo-api-failure": "Не удалось получить уведомления.",
+ "echo-api-failure-cross-wiki": "В доступе к удаленному домену было отказано.",
+ "echo-notification-placeholder": "Уведомлений нет.",
+ "echo-notification-placeholder-filters": "Нет уведомлений, соответствующих заданным критериям.",
+ "echo-notification-loginrequired": "Вы должны войти, чтобы посмотреть уведомления.",
+ "echo-notification-popup-loginrequired": "Пожалуйста, войдите, чтобы просмотреть уведомления.",
+ "echo-notification-markasread": "Пометить как прочитанное",
+ "echo-notification-markasunread": "Пометить как непрочитанное",
+ "echo-notification-markasread-tooltip": "Отметить как прочитанное",
+ "echo-notification-more-options-tooltip": "Больше возможностей",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Прекратить}} отслеживание новых изменений страницы «$1»",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Вы}} больше не следите за изменениями страницы «$1»",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Вы}} можете возобновить отслеживание [$2 этой страницы] в любой момент.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Отслеживать}} новые изменения страницы «$1»",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Вы}} начали следить за изменениями страницы «$1»",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Вы}} можете прекратить отслеживание [$2 этой страницы] в любой момент.",
+ "notification-link-text-expand-all": "Развернуть",
+ "notification-link-text-expand-alert-count": "Показать {{PLURAL:$1|$1 оповещение|$1 оповещения|$1 оповещений}}",
+ "notification-link-text-expand-notice-count": "Показать {{PLURAL:$1|$1 сообщение|$1 сообщения|$1 сообщений}}",
+ "notification-link-text-expand-all-count": "Показать {{PLURAL:$1|$1 уведомление|$1 уведомления|$1 уведомлений}}",
+ "notification-link-text-collapse-all": "Свернуть",
"notification-link-text-view-message": "Просмотр сообщения",
"notification-link-text-view-mention": "Просмотр упоминания",
- "notification-link-text-view-changes": "Просмотр изменений",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Посмотреть упоминание|Посмотреть упоминания}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Просмотр}} изменений",
"notification-link-text-view-page": "Просмотр страницы",
+ "notification-header-edit-user-talk": "$1 оставил{{GENDER:$2||а}} сообщение на <strong>{{GENDER:$3|вашей}} странице обсуждения</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 оставил{{GENDER:$2||а}} сообщение на <strong>{{GENDER:$3|вашей}} странице обсуждения</strong> в разделе «<strong>$4</strong>».",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "Была сделана ссылка с <strong>$4</strong> на <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Связано с $1",
+ "notification-bundle-header-page-linked": "Были сделаны ссылки с {{PLURAL:$5||$5 страниц|100=99+ других страниц}} на <strong>$3</strong>.",
+ "notification-header-article-reminder": "Страница, о которой {{GENDER:$2|вы}} попросили напоминать, <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Все ссылки на эту страницу",
+ "notification-header-mention-other": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$3|вас}} на странице <strong>$4</strong> в разделе «<strong>$5</strong>».",
+ "notification-header-mention-other-nosection": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$3|вас}} на странице <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$3|вас}} на <strong>странице обсуждения {{GENDER:$5|$4}}</strong> в разделе «<strong>$6</strong>».",
+ "notification-header-mention-user-talkpage-nosection": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$3|вас}} на <strong>странице обсуждения {{GENDER:$5|$4}}</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$3|вас}} на <strong>{{GENDER:$2|своей}} странице обсуждения</strong> в разделе «<strong>$4</strong>».",
+ "notification-header-mention-agent-talkpage-nosection": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$3|вас}} на <strong>{{GENDER:$2|своей}} странице обсуждения</strong>.",
+ "notification-header-mention-article-talkpage": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$3|вас}} на странице обсуждения «<strong>$4</strong>» в разделе «<strong>$5</strong>».",
+ "notification-header-mention-article-talkpage-nosection": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$3|вас}} на странице обсуждения «$4».",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Ваше}} упоминание <strong>$3</strong> не было отправлено поскольку этот участник не найден.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Ваше}} упоминание <strong>$3</strong> не было отправлено поскольку этот участник аноним.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Вы}} попытались упомянуть более $3 {{PLURAL:$3|участника|участников}}. Все упоминания выше этого лимита не были разосланы.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Упоминание|$3 упоминания|$3 упоминаний}} {{PLURAL:$3|сделанное|сделанные|сделанных}} {{GENDER:$2|вами}} на странице обсуждений <strong>$4</strong> не {{PLURAL:$3|может|могут}} быть отправлены.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Имя участника не существует:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-адреса не могут быть упомянуты:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Ваше}} упоминание участника <strong>$3</strong> было отправлено.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Упоминание, сделанное|$3 упоминания, сделанные|$3 упоминаний, сделанных}} {{GENDER:$2|вами}} на странице обсуждения <strong>$4</strong>, отправлен{{PLURAL:$3|о|ы}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Вы упомянули}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Уведомление|$3 уведомления|$3 уведомлений}} об упоминании {{PLURAL:$3|сделанное|сделанные|сделанных}} {{GENDER:$2|вами}} на странице обсуждений <strong>$4</strong>: {{PLURAL:$5|$5 не отправлено|$5 не отправлены}}, {{PLURAL:$6|$6 отправлено|$6 отправлены}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Ваши}} права пользователя были {{GENDER:$1|изменены}}. Вы добавлены в группу: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Ваши}} права пользователя были {{GENDER:$1|изменены}}. Вы больше не входите в группу: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Ваши}} права участника были {{GENDER:$1|изменены}}. Вы были добавлены в: $2. Вы больше не входите в: $4.",
+ "notification-header-user-rights-expiry-change": "Время истечения {{GENDER:$4|вашего}} членства в {{PLURAL:$3|следующей группе|следующих группах}} {{GENDER:$1|изменено}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Добро пожаловать}} на сайт {{SITENAME}}, $1! Мы рады приветствовать {{GENDER:$2|вас}} здесь.",
+ "notification-welcome-linktext": "Добро пожаловать!",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Вы}} только что сделали {{GENDER:$2|вашу}} первую правку. Благодарим {{GENDER:$2|вас}} за это, и добро пожаловать!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Вы}} только что сделали {{GENDER:$2|вашу}} десятую правку. Благодарим {{GENDER:$2|вас}} за это, продолжайте в том же духе!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Вы}} только что сделали {{GENDER:$2|вашу}} сотую правку. Большое спасибо за это!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Вы}} только что сделали {{GENDER:$2|свою}} тысячную правку; спасибо {{GENDER:$2|вам}} за большой вклад!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Вы}} только что сделали {{GENDER:$2|свою}} десятитысячную правку; огромное {{GENDER:$2|вам}} спасибо!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Вы}} только что сделали {{GENDER:$2|свою}} стотысячную правку; спасибо {{GENDER:$2|вам}} за удивительный вклад!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Вы}} только что сделали {{GENDER:$2|свою}} миллионную правку; спасибо {{GENDER:$2|вам}} за умопомрачительный вклад!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Ваша}} правка",
"notification-link-text-view-edit": "Просмотр правки",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|оставил|оставила}} сообщение на вашей [[User talk:$2#$3|странице обсуждения]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|оставил|оставила}} сообщение на вашей странице обсуждения \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|оставил|оставила}} сообщение на вашей [[User talk:$2#$3|странице обсуждения]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|оставил|оставила}} сообщение на вашей странице обсуждения \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "На [[:$2]] {{GENDER:$1|сослались}} из [[:$3]]. [[Special:WhatLinksHere/$2|См. все ссылки на эту страницу]].",
- "notification-page-linked-flyout": "[[:$2]] была {{GENDER:$1|связана}} с [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|прокомментировал|прокомментировала}} тему \"[[$3|$2]]\" на странице обсуждения \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|добавил|добавила}} новую тему \"$2\" на странице [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|отправил|отправила}} вам сообщение: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|прокомментировал|прокомментировала}} тему \"[[$3#$2|$2]]\" на вашей странице обсуждения.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|упомянул|упомянула}} вас на странице обсуждения $5 в разделе \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|упомянул|упомянула}} вас на странице обсуждения $5 в разделе \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] упомянул{{GENDER:$1||а}} вас на [[:$3|странице обсуждения $2]].",
- "notification-mention-nosection-flyout": "$1 упомянул{{GENDER:$1||а}} вас на [[:$3|странице обсуждения $2]].",
- "notification-user-rights": "Ваши права пользователя [[Special:Log/rights/$1|{{GENDER:$1|изменил|изменила}}]] [[User:$1|$1]]. $2. [[Special:ListGroupRights|Подробнее]]",
- "notification-user-rights-flyout": "Права пользователя {{GENDER:$1|изменил|изменила}} $1. $2. [[Special:ListGroupRights|Подробнее]]",
- "notification-user-rights-add": "Теперь вы входите в {{PLURAL:$2|1=следующую группу|следующие группы}}: $1",
- "notification-user-rights-remove": "Вы больше не входите в {{PLURAL:$2|1=следующую группу|следующие группы}}: $1",
- "notification-new-user": "Добро пожаловать в {{SITENAME}}, $1! Мы рады, что вы здесь.",
- "notification-reverted2": "{{PLURAL:$4|1=Вашу правку|Ваши правки}} на странице [[:$2]] {{GENDER:$1|отменил|отменила}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|1=Вашу правку|Ваши правки}} на странице $2 {{GENDER:$1|отменил|отменила}} $1. $3",
+ "notification-link-article-reminder": "Просмотр страницы",
+ "notification-header-reverted": "{{PLURAL:$4|Ваша правка|Ваши правки}} на странице <strong>$3</strong> {{GENDER:$2|{{PLURAL:$4|была отменена|были отменены}}}}.",
+ "notification-header-emailuser": "$1 отправил{{GENDER:$2||а}} вам письмо.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|Участник|Участница}} $1 {{GENDER:$1|оставил|оставила}} вам сообщение на сайте «{{SITENAME}}»",
- "notification-edit-talk-page-email-batch-body2": "Участни{{GENDER:$1|к|ца}} $1 оставил{{GENDER:$1||а}} сообщение на вашей странице обсуждения.",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Участник|Участница}} $1 {{GENDER:$1|оставил|оставила}} вам сообщение на вашей странице обсуждения в разделе (теме) «$2»",
"notification-page-linked-email-subject": "На сайте «{{SITENAME}}» появилась ссылка на созданную вами страницу",
- "notification-page-linked-email-batch-body": "{{GENDER:$1|Участник|участница}} $1 {{GENDER:$1|сослался|сослалась}} на $2 из $3",
"notification-reverted-email-subject2": "{{GENDER:$1|Кто-то}} отменил {{PLURAL:$3|1=вашу правку|ваши правки}} на сайте «{{SITENAME}}»",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|1=Ваша правка на странице «$2» была отменена|Ваши правки на странице «$2» были отменены}} {{GENDER:$1|участником|участницей}} $1.",
- "notification-mention-email-subject": "{{GENDER:$1|Участник|Участница}} $1 {{GENDER:$1|упомянул|упомянула}} вас на сайте «{{SITENAME}}»",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|упомянул|упомянула}} Вас на странице обсуждения $4 в разделе «$3».",
- "notification-mention-nosection-email-batch-body": "$1 упомянул{{GENDER:$1||а}} вас на странице обсуждения $2.",
+ "notification-mention-email-subject": "$1 упомянул{{GENDER:$1||а}} {{GENDER:$2|вас}} на сайте «{{SITENAME}}»",
"notification-user-rights-email-subject": "Ваши права на сайте «{{SITENAME}}» были изменены",
- "notification-user-rights-email-batch-body": "Ваши права были изменены {{GENDER:$1|участником|участницей}} $1. $2.",
- "echo-notification-count": "$1+",
- "echo-email-subject-default": "Новые уведомления на сайте «{{SITENAME}}»",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 с}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 мин}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ч}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 д.}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 мес.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 г.|$1 г.|$1 л.}}",
+ "notification-timestamp-today": "Сегодня",
+ "notification-timestamp-yesterday": "Вчера",
+ "notification-inbox-filter-read": "Прочитанные",
+ "notification-inbox-filter-unread": "Непрочитанные",
+ "notification-inbox-filter-all": "Все",
"echo-email-body-default": "У вас есть новое уведомление на сайте «{{SITENAME}}»:\n\n$1",
- "echo-email-batch-body-default": "У вас есть новое уведомление",
- "echo-email-footer-default": "$2\n\nДля контроля за тем, какие сообщения отправляются вам по эл. почте, проверьте свои персональные настройки:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Для контроля за тем, какие сообщения отправляются вам по эл. почте, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">проверьте свои персональные настройки</a><br />\n$1",
+ "echo-email-footer-default-html": "Чтобы контролировать, какие письма мы посылаем вам, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">проверьте ваши настройки</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nДля контроля за тем, какие сообщения отправляются вам по эл. почте, проверьте свои настройки:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Чтобы контролировать, какие сообщения мы отправляем {{GENDER:$1|вам}}, проверьте {{GENDER:$1|свои}} настройки:",
+ "echo-email-html-footer-preference-link-text": "проверьте {{GENDER:$1|свои}} настройки",
+ "echo-email-html-footer-with-link": "Чтобы контролировать, какие письма мы посылаем {{GENDER:$2|вам}}, $1.",
"echo-notification-alert": "{{PLURAL:$1|Оповещение ($1)|Оповещения ($1)|100=Оповещения (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Сообщение ($1)|Сообщения ($1)|100=Сообщения (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Уведомление ($1)|Уведомления ($1)|100=Уведомления (99+)}}",
"echo-notification-alert-text-only": "Оповещения",
- "echo-notification-message-text-only": "Сообщения",
+ "echo-notification-notice-text-only": "Уведомления",
"echo-overlay-link": "Все уведомления",
"echo-overlay-title": "<b>Уведомления</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Уведомления}}</b> ({{PLURAL:$1|показано|показаны}} $1 из $2 {{PLURAL:$2|непрочитанного|непрочитанных}})",
- "echo-mark-all-as-read": "Отметить всё прочтённым",
+ "echo-mark-all-as-read": "Отметить все как прочитанные",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|уведомление помечено как прочитанное|уведомлений помечены как прочитанные|уведомления помечены как прочитанные}}",
+ "echo-mark-wiki-as-read": "Пометить все как прочитанные в выбранной вики: $1",
"echo-date-today": "Сегодня",
"echo-date-yesterday": "Вчера",
"echo-load-more-error": "Произошла ошибка при получении дополнительных результатов.",
- "notification-edit-talk-page-bundle": "$1 и $3 {{PLURAL:$4|1=другой участник|других участников|других участника}} оставили сообщение на вашей [[User talk:$2|странице обсуждения]].",
- "notification-page-linked-bundle": "На страницу «$2» есть {{GENDER:$1|ссылка}} со страницы «$3» и ещё $4 {{PLURAL:$5|страницы|страниц}}. [[Special:WhatLinksHere/$2|См. все ссылки на эту страницу]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 и $2 {{PLURAL:$3|другой участник|других участникa|других участников}} оставили сообщения на вашей странице обсуждения.",
- "notification-page-linked-email-batch-bundle-body": "На страницу «$2» есть {{GENDER:$1|ссылка}} со страницы «$3» и ещё {{PLURAL:$5|$4 страницы|$4 страниц|1=одной страницы}}",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|новое сообщение|$1 новых сообщений|100=99+ новых сообщения|100=99+ новых сообщений}} на <strong>{{GENDER:$3|вашей}} странице обсуждения</strong>.",
"echo-email-batch-bullet": "•",
"echo-email-batch-subject-daily": "Вы получили {{PLURAL:$2|$2 новое уведомление|$2 новых уведомления|$2 новых уведомлений|1=новое уведомление}} в проекте «{{SITENAME}}»",
"echo-email-batch-subject-weekly": "На этой неделе вы получили {{PLURAL:$2|$2 новое уведомление|$2 новых уведомления|$2 новых уведомлений|1=новое уведомление}} в проекте «{{SITENAME}}»",
"echo-email-batch-body-intro-daily": "Привет, $1!\nВот краткий обзор сегодняшней деятельности в {{SITENAME}} для вас.",
"echo-email-batch-body-intro-weekly": "Привет, $1!\nВот краткий недельный обзор деятельности в {{SITENAME}} для вас.",
"echo-email-batch-link-text-view-all-notifications": "Посмотреть все уведомления",
- "echo-rev-deleted-text-view": "Эта версия страницы была скрыта",
- "apihelp-echomarkread-description": "Отметить уведомления как прочитанные для текущего пользователя.",
- "apihelp-echomarkread-param-list": "Список ID уведомлений для отметки прочитанными.",
- "apihelp-echomarkread-param-all": "Если задано, отметает все уведомления пользователя как прочитанные.",
- "apihelp-echomarkread-param-sections": "Список разделов для пометки как прочитанных.",
- "apihelp-echomarkread-example-1": "Пометить уведомление 8 как прочитанное",
- "apihelp-echomarkread-example-2": "Отметить все уведомления как прочитанные",
- "apihelp-echomarkseen-description": "Отметить уведомления как прочитанные для данного пользователя.",
- "apihelp-echomarkseen-example-1": "Отметить уведомления всех типов как прочитанные",
- "apihelp-query+notifications-param-prop": "Подробности для запроса.",
- "apihelp-query+notifications-param-groupbysection": "Следует ли группировать результат по разделам. Если задано, каждый раздел извлекается отдельно.",
- "apihelp-query+notifications-param-format": "Если определено, уведомления будут возвращены отформатированными таким образом.",
- "apihelp-query+notifications-param-limit": "Максимальное количество возвращаемых уведомлений.",
- "apihelp-query+notifications-param-alertunreadfirst": "Нужно ли показывать непрочитанные уведомления о сообщениях в первую очередь.",
- "apihelp-query+notifications-param-messageunreadfirst": "Нужно ли показывать непрочитанные уведомления о оповещениях в первую очередь.",
- "apihelp-query+notifications-example-1": "Список уведомлений",
- "apihelp-query+notifications-example-2": "Список уведомлений, сгруппированных по разделам, с указанием количества"
+ "notification-header-foreign-alert": "Больше уведомлений из {{PLURAL:$5|другой вики|$5 других вики}}",
+ "notification-header-foreign-notice": "Больше уведомлений из {{PLURAL:$5|другой вики|$5 других вики}}",
+ "notification-header-foreign-all": "Больше уведомлений из {{PLURAL:$5|другой вики|$5 других вики}}"
}
diff --git a/Echo/i18n/rue.json b/Echo/i18n/rue.json
index 36e515fe..43cb98aa 100644
--- a/Echo/i18n/rue.json
+++ b/Echo/i18n/rue.json
@@ -3,6 +3,5 @@
"authors": [
"Dicto23456"
]
- },
- "tooltip-pt-notifications": "Ваші сповіщення"
+ }
}
diff --git a/Echo/i18n/sa.json b/Echo/i18n/sa.json
index 4f31d93e..09817fb1 100644
--- a/Echo/i18n/sa.json
+++ b/Echo/i18n/sa.json
@@ -37,11 +37,9 @@
"echo-pref-tooltip-article-linked": "मया निर्मितेन पुटेन सह यदि अन्येन सम्पर्कतन्तुः योज्यते तर्हि मां सूचयन्तु |",
"echo-pref-tooltip-reverted": "मया कृतं सम्पादनं यदि अन्यः पूर्ववत् परिवर्तयेत् तर्हि सूच्यताम् |",
"echo-pref-tooltip-mention": "कस्यचित् चर्चापुटस्य सम्पर्कतन्तुः मम योजकपुटेन सह योज्यते चेत् सूच्यताम् |",
- "echo-no-agent": "[कोपि नास्ति]",
- "echo-no-title": "[न किञ्चित् पृष्ठं विद्यते]",
"echo-error-no-formatter": "सूचनानां प्रारूपः न रचितः |",
"notifications": "सूचनाः",
- "tooltip-pt-notifications": "भवतः सूचनाः",
+ "tooltip-pt-notifications-alert": "{{GENDER:|भवतः/भवत्याः}} जागरूकतासन्देशाः",
"echo-specialpage": "सूचनाः",
"echo-none": "भवते सूचनाः न विद्यन्ते |",
"echo-more-info": "अधिकं विवरणम्",
@@ -50,7 +48,6 @@
"notification-link-text-view-changes": "परिवर्तनानि दृश्यन्ताम्",
"notification-link-text-view-page": "पृष्ठं दृश्यताम्",
"notification-link-text-view-edit": "सम्पादनं दृश्यताम्",
- "echo-notification-message-text-only": "संदेशाः",
"echo-overlay-link": "सर्वाः सूचनाः",
"echo-overlay-title": "<b>सूचनाः</b>",
"echo-date-today": "अद्य",
diff --git a/Echo/i18n/sah.json b/Echo/i18n/sah.json
index 4935ef97..00ef8d0c 100644
--- a/Echo/i18n/sah.json
+++ b/Echo/i18n/sah.json
@@ -2,12 +2,103 @@
"@metadata": {
"authors": [
"Kaganer",
- "HalanTul"
+ "HalanTul",
+ "София",
+ "Марианна",
+ "Туллук"
]
},
- "tooltip-pt-notifications": "Эйиэхэ биллэриилэр",
- "notification-reverted2": "{{PLURAL:$4|1=Эн көннөрүүгүн|Эн көннөрүүлэргин}} [[:$2]] сирэйгэ [[User:$1|$1]] {{GENDER:$1|көтүрбүт}}. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|1=Эн көннөрүүгүн|Эн көннөрүүлэргин}} $2 сирэйгэ $1 {{GENDER:$1|көтүрбүт}}. $3",
+ "echo-desc": "Иһитиннэриилэр уонна түбэлтэлэр тустарынан кыттааччыларга биллэрэр систиэмэ",
+ "prefs-echo": "Биллэриилэр",
+ "prefs-emailsettings": "Email туруоруулара",
+ "prefs-displaynotifications": "Туруоруулары көрдөр",
+ "prefs-echosubscriptions": "Бу түбэлтэлэр тустарынан миэхэ биллэрэн ис",
+ "prefs-echocrosswiki": "Кросс-вики биллэрии",
+ "prefs-newmessageindicator": "Саҥа сурук кэллэҕинэ көстөр",
+ "echo-pref-send-me": "Миэхэ манна ыыт:",
+ "echo-pref-send-to": "Манна ыыт:",
+ "echo-pref-email-format": "Сурук формаата",
+ "echo-pref-web": "Ситим",
+ "echo-pref-email": "Почта",
+ "echo-pref-email-frequency-never": "Миэхэ биллэриилэри ыытымаҥ",
+ "echo-pref-email-frequency-immediately": "Биллэриилэр киирбит кэмнэринэн наардаммыта",
+ "echo-pref-email-frequency-daily": "Биллэрии күннээҕи сводката",
+ "echo-pref-email-frequency-weekly": "Биллэриилэр нэдиэлэтээҕи сводкалара",
+ "echo-pref-email-format-html": "HTML",
+ "echo-pref-email-format-plain-text": "Көннөрү тиэкис",
+ "echo-pref-cross-wiki-notifications": "Атын биики биллэриилэрин эмиэ көрдөр",
+ "echo-pref-beta-feature-cross-wiki-message": "Тупсарыллыбыт биллэриилэр",
+ "echo-learn-more": "Эбии билии",
+ "echo-log": "Аһаҕас сурунаал",
+ "echo-new-messages": "Эйиэхэ саҥа сурук кэлбит",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|}} биллэриилэр",
+ "echo-category-title-article-linked": "{{PLURAL:$1|сигэлээх}}",
+ "echo-category-title-reverted": "{{PLURAL:$1|төннөрүү}}",
+ "echo-category-title-mention": "{{PLURAL:$1|Ахтыы|Ахтыылар}}",
+ "echo-category-title-other": "{{PLURAL:$1|Атын}}",
+ "echo-category-title-system": "{{PLURAL:$1|Систиэмнэй}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Кыттааччы быраабын уларытыы}}",
+ "echo-pref-tooltip-user-rights": "Ким эмит кыттааччы быһыытынан бырааппын уларытар буоллаҕына миэхэ биллэр.",
+ "echo-pref-tooltip-emailuser": "Электроннай почтабар ким эмит сурук ыытар буоллаҕына миэхэ биллэр.",
+ "notifications": "Биллэриилэр",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Эйиэхэ}} биллэриилэр",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Биллэрии көрүҥүнэн наардаммыта",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Көрүҥүнэн наардааһын",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Биллэрии көҥүллэммит ньымалара",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Баар кыттааччылар",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Саҥа кыттааччылар",
+ "echo-specialpage": "Биллэриилэр",
+ "echo-specialpage-section-markread": "Бөлөҕү ааҕыллыбыт курдук бэлиэтээ",
+ "echo-specialpage-markasread": "Биллэрии: Ааҕыллыбыт курдук бэлиэтээ",
+ "notificationsmarkread-legend": "Биллэриини ааҕыллыбыт курдук бэлиэтээ",
+ "echo-none": "Эн биллэриини тута иликкин.",
+ "echo-more-info": "Сиһилии",
+ "echo-feedback": "Ситимнэһии",
+ "echo-api-failure": "Биллэриилэри тутар табыллыбата.",
+ "echo-notification-placeholder": "Биллэрии суох.",
+ "echo-notification-loginrequired": "Биллэриилэри көрөргө бастаан киир.",
+ "echo-notification-popup-loginrequired": "Биллэриилэри көрөргө бастаан киириэхтээххин.",
+ "echo-notification-markasread": "Ааҕыллыбыт курдук бэлиэтээ",
+ "echo-notification-markasunread": "Ааҕыллыбатах курдук бэлиэтээ",
+ "echo-notification-markasread-tooltip": "Ааҕыллыбыт курдук бэлиэтээ",
+ "echo-notification-more-options-tooltip": "Эбии туруоруулар",
+ "notification-dynamic-actions-unwatch": "\"$1\" сирэй саҥа уларыйыыларын маныырын {{GENDER:$3|тохтот}}",
+ "notification-dynamic-actions-unwatch-confirmation": "\"$1\" сирэй уларыйыыларын {{GENDER:$3|эн}} манаан бүппүтүн",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Эн}}бу [$2 this page] сирэйи көрөргүн хаһан баҕар салҕыаххын сөп",
+ "notification-dynamic-actions-watch": " \"$1\" сирэй саҥа уларыйыыларын {{GENDER:$3|манаа}}",
+ "notification-dynamic-actions-watch-confirmation": "\"$1\" сирэй уларыйыыларын {{GENDER:$3|эн}} манаан бүппүтүн",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Эн}}бу [$2 this page] сирэйи көрөргүн хаһан баҕар салҕыаххын сөп",
+ "notification-link-text-expand-all": "Барытын көрүү",
+ "notification-link-text-expand-alert-count": "Көрдөр {{PLURAL:$1|$1 биллэрии|$1 биллэрии|$1 биллэрии}}",
+ "notification-link-text-collapse-all": "Сабыы",
+ "notification-link-text-view-message": "Суругу көр",
+ "notification-link-text-view-mention": "Өйдөтүүнү көр",
+ "notification-link-text-view-changes": "Уларытыылары {{GENDER:$1|көрүү}}",
+ "notification-link-text-view-page": "Сирэйи көрүү",
+ "notification-header-page-linked": "Сигэ мантан <strong>$4</strong> манна <strong>$3</strong> оҥоһулунна.",
+ "notification-link-text-what-links-here": "Сигэлэри барытын бу сирэйгэ",
+ "notification-welcome-linktext": "Нөрүөн-нөргүй",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Эн}} уларытыыҥ",
+ "notification-link-text-view-edit": "Көннөрүүнү көр",
+ "notification-header-reverted": "<strong>$3</strong> сирэйгэ оҥорбут {{PLURAL:$4|1=Эн көннөрүүҥ|Эн көннөрүүлэриҥ}} {{GENDER:$2|{{PLURAL:$4|ууратылынна|ууратылыннылар}}}}",
+ "notification-header-emailuser": "$1 {{GENDER:$2|sent}} эйиэхэ сурук ыытта.",
"notification-reverted-email-subject2": "{{GENDER:$1|Ким эрэ}} {{PLURAL:$3|1=эн көннөрүүгүн|эн көннөрүүлэргин}} «{{SITENAME}}» ситим-сиргэ көтүрбүт",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|1=Эн көннөрүүҥ «$2» сирэйгэ|Эн көннөрүүлэриҥ «$2» сирэйгэ}} $1 кыттааччынан {{PLURAL:$3|1=көтүрүллүбүтэ|көтүрүллүбүттэрэ}}."
+ "notification-user-rights-email-subject": "{{SITENAME}} сайтка эhиги быраапкыт уларыйда",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|Систиэмнэй}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 мүн}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ч}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 с.}}",
+ "notification-timestamp-today": "Бүгүн",
+ "notification-timestamp-yesterday": "Бэҕэһээ",
+ "notification-inbox-filter-read": "Ааҕыы",
+ "notification-inbox-filter-unread": "Ааҕылла илик",
+ "notification-inbox-filter-all": "Бары (барыта)",
+ "echo-email-html-footer-preference-link-text": "Ордоруубун бэрэбиэркэлээ",
+ "echo-notification-alert-text-only": "биллэрии",
+ "echo-overlay-link": "Биллэрии барыта",
+ "echo-overlay-title": "<b>Биллэриилэр</b>",
+ "echo-mark-all-as-read": "Барытын ааҕыллыбыт курдук бэлиэтээ",
+ "echo-date-today": "Бүгүн",
+ "echo-date-yesterday": "Бэҕэһээ",
+ "echo-email-batch-link-text-view-all-notifications": "Биллэриилэри барытын көр"
}
diff --git a/Echo/i18n/sat.json b/Echo/i18n/sat.json
new file mode 100644
index 00000000..4846c0dc
--- /dev/null
+++ b/Echo/i18n/sat.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Albinus"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Amaḱ}} baḍaejoṅ",
+ "tooltip-pt-notifications-message": "{{GENDER:|Amaḱ}} kathako"
+}
diff --git a/Echo/i18n/scn.json b/Echo/i18n/scn.json
index 738a60f8..24824aef 100644
--- a/Echo/i18n/scn.json
+++ b/Echo/i18n/scn.json
@@ -36,12 +36,9 @@
"echo-pref-tooltip-article-linked": "Abbìsami quannu quarcunu cullèga, di na vuci, na pàggina ca criai.",
"echo-pref-tooltip-reverted": "Abbìsami quannu quarcunu annulla nu canciamentu ca fici, usannu li funzioni annulla o rollback.",
"echo-pref-tooltip-mention": "Avvìsami quannu quarchidunu crea un culligamentu â mè pàggina d'utenti.",
- "echo-no-agent": "[Nuddu]",
- "echo-no-title": "[Nudda pàggina]",
"echo-error-no-formatter": "Nudda furnattazzioni difinuta pê nutìfichi",
"notifications": "Nutìfichi",
"tooltip-pt-notifications-alert": "Li {{GENDER:|tò}} avvisi",
- "tooltip-pt-notifications-message": "Li {{GENDER:|to}} missaggi",
"echo-specialpage": "Nutìfichi",
"echo-anon": "Pi arriciviri li nutìfichi, [$1 arriggistrati] o [$2 trasi].",
"echo-none": "Nun arricivistru nutìfichi",
@@ -52,56 +49,25 @@
"notification-link-text-view-changes": "Talìa li canciamenti",
"notification-link-text-view-page": "Talìa la pàggina",
"notification-link-text-view-edit": "Talìa lu canciamentu",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|lasssau}} nu missaggiu supra la tò [[User talk:$2#$3|pàggina di discussioni]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|lassau}} nu missaggiu ntâ tò pàggina di discussioni n '[[User talk:$2#$3|$4]]'.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|lassau}} nu missaggiu supra la tò [[User talk:$2#$3|pàggina di discussioni]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|lassau}} nu missaggiu ntâ tò pàggina di discussioni n '[[User talk:$2#$3|$4]]'.",
- "notification-page-linked": "[[:$2]] fu {{GENDER:$1|culligata}} di [[:$3]]. [[Special:WhatLinksHere/$2|Talìa tutti li liami a sta pàggina]].",
- "notification-page-linked-flyout": "[[:$2]] fu {{GENDER:$1|culligata}} di [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|lassau nu cummentu}} arriguardu a \"[[$3|$2]]\" ntâ pàggina di discussioni di \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|juncìu}} n'argumentu novu \"$2\" supra [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] ti {{GENDER:$1|mannàu}} nu missaggiu: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|lassau nu cummentu}} arriguardu a \"[[$3#$2|$2]]\" ntâ tò pàggina di discussioni",
- "notification-mention": "[[User:$1|$1]] ti {{GENDER:$1|mintuviau}} supra la pàggina di discussioni di $5 n '[[:$3#$2|$4]]'.",
- "notification-mention-flyout": "$1 ti {{GENDER:$1|mintuviàu}} supra la pàggina di discussioni di $5 n '[[:$3#$2|$4]]'.",
- "notification-user-rights": "Li tò diritti utenti [[Special:Log/rights/$1|foru {{GENDER:$1|canciati}}]] di [[User:$1|$1]]. $2. [[Special:ListGroupRights|Pi sapìrinni cchiossai]]",
- "notification-user-rights-flyout": "Li tò diritti utenti foru {{GENDER:$1|canciati}} di $1. $2. [[Special:ListGroupRights|Pi sapìrinni cchiossai]]",
- "notification-user-rights-add": "Ora si membru di {{PLURAL:$2|stu gruppu|sti gruppa}}: $1",
- "notification-user-rights-remove": "Nun si cchiù membru di {{PLURAL:$2|stu gruppu|sti gruppa}}: $1",
- "notification-new-user": "Bimminutu/a supra {{SITENAME}}, $1! Semu filici ca tu si ccà.",
- "notification-reverted2": "{{PLURAL:$4|Lu tò canciamentu|Li tò canciamenti}} supra [[:$2]] {{PLURAL:$4|fu annullatu|foru annullati}} {{GENDER:$1|di}} [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Lu tò canciamentu|Li tò canciamenti}} supra $2 {{PLURAL:$4|fu annullatu|foru annullati}} {{GENDER:$1|di}} $1 $3",
+ "notification-header-reverted": "{{PLURAL:$4|Lu tò canciamentu|Li tò canciamenti}} supra $3 {{PLURAL:$4|fu annullatu|foru annullati}} {{GENDER:$2|di}} $1",
"notification-edit-talk-page-email-subject2": "$1 ti {{GENDER:$1|lassau}} nu missaggiu n {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|lassau}} nu missaggiu supra la tò pàggina di discussioni:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|lassau}} nu missaggiu supra la tò pàggina di discussioni n $2.",
"notification-page-linked-email-subject": "Na pàggina chi criasti fu liata nta {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 fu {{GENDER:$1|culligata}} di $3",
"notification-reverted-email-subject2": "{{PLURAL:$3|Lu tò canciamentu fu annullatu|Li tò canciamenti foru annullati}} {{GENDER:$1|supra}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Lu tò canciamentu supra $2 fu annullatu|Li tò canciamenti supra $2 foru annullati}} {{GENDER:$1|di}} $1 $3",
- "notification-mention-email-subject": "$1 ti {{GENDER:$1|mintuviàu}} su {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 ti {{GENDER:$1|mintuviàu}} supra la pàggina di discussioni di $4 n '$3'.",
+ "notification-mention-email-subject": "$1 ti {{GENDER:$1|mintuviau}} supra {{SITENAME}}",
"notification-user-rights-email-subject": "Li tò diritti utenti foru canciati supra {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Li tò dirirtti utenti foru {{GENDER:$1|canciati}} di $1. $2",
- "echo-email-subject-default": "Nutìfica nova supra {{SITENAME}}",
"echo-email-body-default": "Vossìa havi na nutìfica nova supra {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Vossìa havi na nutìfica nova",
"echo-email-footer-default": "$2\n\nPi cuntrullari quali email ti vènunu mannati, cuntrolla li tò prifirenzi:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Pi virificari quali email ti sunu mannati, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">cuntrolla li tò prifirenzi</a><br />\n$1",
"echo-overlay-link": "Tutti li nutìfichi",
"echo-overlay-title": "<b>Nutìfichi</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Nutifica|Nutìfichi}}</b> (ammusciati $1 di $2 nunu ligghiuti)",
"echo-mark-all-as-read": "Sinna tutti comu ligghiuti",
- "echo-date-today": "Ogghi",
- "echo-date-yesterday": "Ieri",
- "echo-load-more-error": "Si virificau n'erruri ntô ricùpiru di àutri risurtati.",
- "notification-edit-talk-page-bundle": "$1 e {{PLURAL:$4|n'autru utenti|àutri $3 utenti}} {{GENDER:$1|lassaru}} nu missaggiu ntâ tò [[User talk:$2|pàggina di discussioni]].",
- "notification-page-linked-bundle": "$2 fu {{GENDER:$1|culligata}} di $3 e {{PLURAL:$5|n'àutra pàggina|àutri $4 pàggini}}. [[Special:WhatLinksHere/$2|Talìa tutti li culligamenti a sta pàggina]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 e {{PLURAL:$3|n'àutru|àutri $2}} {{GENDER:$1|lassaru}} nu missaggiu supra la tò pàggina di discussioni",
- "notification-page-linked-email-batch-bundle-body": "$2 fu {{GENDER:$1|culligata}} di $3 e {{PLURAL:$5|n'àutra pàggina|àutri $4 pàggini}}",
+ "echo-date-today": "Oi",
+ "echo-date-yesterday": "Aieri",
+ "echo-load-more-error": "Si virificau n'erruri ntô ricùpiru d'àutri risurtati.",
"echo-email-batch-subject-daily": "Vossia havi {{PLURAL:$2|na nutìfica nova|nutìfichi novi}} supra {{SITENAME}}",
"echo-email-batch-subject-weekly": "Vossia havi {{PLURAL:$2|na nutìfica nova|nutìfichi novi}} supra {{SITENAME}} sta simana",
- "echo-email-batch-body-intro-daily": "Sabbinirica $1,\neccu na sìntisi di l'attivitati di ogghi supra {{SITENAME}} pi vossia",
+ "echo-email-batch-body-intro-daily": "Assabbinidica $1,\neccu na sìntisi di l'attivitati d'oi supra {{SITENAME}} pi vossìa",
"echo-email-batch-body-intro-weekly": "Sabbinirica $1,\neccu na sìntisi di l'attivitati di sta siamana supra {{SITENAME}} pi Vossia",
- "echo-email-batch-link-text-view-all-notifications": "Talìa tutti li canciamenti",
- "echo-rev-deleted-text-view": "Sta virsioni dâ pàggina fu supprimuta"
+ "echo-email-batch-link-text-view-all-notifications": "Talìa tutti li canciamenti"
}
diff --git a/Echo/i18n/sco.json b/Echo/i18n/sco.json
index 4cad82ed..b258fe0e 100644
--- a/Echo/i18n/sco.json
+++ b/Echo/i18n/sco.json
@@ -4,5 +4,6 @@
"AmaryllisGardener"
]
},
- "tooltip-pt-notifications": "Yer notifications"
+ "tooltip-pt-notifications-alert": "{{GENDER:|Yer}} alerts",
+ "echo-specialpage-pagefilters-subtitle": "Pages wi unread notifications"
}
diff --git a/Echo/i18n/sd.json b/Echo/i18n/sd.json
new file mode 100644
index 00000000..0f68d4f8
--- /dev/null
+++ b/Echo/i18n/sd.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aursani",
+ "Mehtab ahmed"
+ ]
+ },
+ "prefs-echo": "اطلاع",
+ "notifications": "اطلاع",
+ "tooltip-pt-notifications-alert": "{{GENDER:|توهانجون}} خبرون",
+ "echo-specialpage": "اطلاع",
+ "echo-specialpage-section-markread": "گروھ کي پڙھيل طور نشان لڳايو",
+ "echo-specialpage-markasread": "اطلاع:پڙھيل طور نشان لڳايو",
+ "notificationsmarkread-legend": "اطلاع کي پڙھيل طور نشان لڳايو",
+ "echo-notification-markasread": "پڙھيل طور نشان لڳايو",
+ "echo-notification-markasunread": "نه-پڙھيل طور نشان لڳايو",
+ "echo-notification-markasread-tooltip": "پڙھيل طور نشان لڳايو",
+ "notification-link-text-view-changes": "تبديليون {{GENDER:$1|ڏيکاريو}}",
+ "notification-header-edit-user-talk": "$1 <strong>{{GENDER:$3|توھان جي}} بحث صفحي</strong> تي ھڪ پيغام {{GENDER:$2|ڇڏيو}}.",
+ "notification-header-edit-user-talk-with-section": "$1 <strong>{{GENDER:$3|توھان جي}} بحث صفحي</strong> تي ھڪ پيغام \"<strong>$4</strong>\" ۾ {{GENDER:$2|ڇڏيو}}.",
+ "notification-header-page-linked": "<strong>$4</strong> کان ھڪ ڳنڍڻو <strong>$3</strong> ڏانھن ٺاھيو ويو.",
+ "notification-link-text-what-links-here": "ھن صفحي ڏانھن سڀ ڳنڍڻا",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|توھان کي}} <strong>$4</strong> بحث صفحي تي {{GENDER:$2|بيان ڪيو}}.",
+ "notification-welcome-linktext": "ڀليڪار",
+ "notification-header-emailuser": "$1 توھان ڏانھن ھڪ ايميل {{GENDER:$2|موڪلي}}.",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 توھان جي بحث صفحي \"$2\" تي پيغام {{GENDER:$1|ڇڏيو}}.",
+ "notification-inbox-filter-read": "پڙھيل",
+ "notification-inbox-filter-unread": "اڻپڙھيل",
+ "notification-inbox-filter-all": "سڀ",
+ "echo-notification-alert-text-only": "پيغام",
+ "echo-notification-notice-text-only": "اطلاع",
+ "echo-overlay-link": "سڀ اطلاع",
+ "echo-mark-all-as-read": "سڀ پڙھيل طور نشان لڳايو"
+}
diff --git a/Echo/i18n/sgs.json b/Echo/i18n/sgs.json
index b3fe7419..f3e476c3 100644
--- a/Echo/i18n/sgs.json
+++ b/Echo/i18n/sgs.json
@@ -4,5 +4,14 @@
"Hugo.arg"
]
},
- "tooltip-pt-notifications": "mona pranešėmā"
+ "prefs-echo": "Žėnotės",
+ "prefs-echosubscriptions": "Monē pasakīkėt, kap būs padėrbtė tėi dāktā:",
+ "tooltip-pt-notifications-alert": "Pertarėmā Tamstā",
+ "echo-specialpage": "Žėnotės",
+ "echo-notification-placeholder": "Žėnotiu nie.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|parašė}} žėnotė <strong>{{GENDER:$3|Tamstas}} aptarėmu poslapie, </strong> prī skėrsnelė „<strong>$4</strong>“.",
+ "echo-notification-alert": "{{PLURAL:$1|Pertarėms ($1)|Pertarėmā ($1)|100=Pertarėmā (99+)}}",
+ "echo-notification-alert-text-only": "Pertarėmā",
+ "echo-overlay-link": "Vėsas žėnotės",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|naujė žėnotė|$1 naujės žėnotės|$1 naujū žėnotiu|100=99+ naujū žėnotiu}} <strong>{{GENDER:$3|Tamstas}} aptarėmu poslapie</strong>."
}
diff --git a/Echo/i18n/sh.json b/Echo/i18n/sh.json
index c22749aa..4f23ab9b 100644
--- a/Echo/i18n/sh.json
+++ b/Echo/i18n/sh.json
@@ -1,7 +1,8 @@
{
"@metadata": {
"authors": [
- "Kolega2357"
+ "Kolega2357",
+ "OC Ripper"
]
},
"echo-desc": "Obavještajni sistem",
@@ -21,7 +22,6 @@
"echo-pref-email-frequency-weekly": "Nedeljni sažetak obavještenja",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Obični tekst",
- "echo-pref-notify-show-link": "Pokaži obavještenja u mojoj alatnoj traci",
"echo-pref-new-message-indicator": "Pokaži indikator da je dobijena poruka na stranici za razgovor u mojoj alatnoj traci",
"echo-learn-more": "Saznajte više",
"echo-new-messages": "Imate nove poruke.",
@@ -35,13 +35,9 @@
"echo-pref-tooltip-article-linked": "Obavijesti me kada neko linkuje na stranicu koju sam napravio od stranice članaka.",
"echo-pref-tooltip-reverted": "Obavijesti me kada neko vrati uređivanje koje sam napravio/la, korištenjem naredbe undo ili alatom za vraćanje.",
"echo-pref-tooltip-mention": "Obavijesti me kada me neko spomene na nekoj stranici za razgovor.",
- "echo-no-agent": "[Niko]",
- "echo-no-title": "[Nema stranice]",
"echo-error-no-formatter": "Nema formatiranja određenog za obavještavanje.",
- "echo-error-preference": "Greška: Nemoguće odrediti korisničke postavke.",
- "echo-error-token": "Greška: Nemoguće ponovo pronaći korisničku oznaku.",
"notifications": "Obavještenja",
- "tooltip-pt-notifications": "Vaša obavještenja",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Vaša}} obavještenja",
"echo-specialpage": "Obavještenja",
"echo-anon": "Da biste primili obaveštenja, morate se [[Special:UserLogin|prijaviti]] ili [[Special:Userlogin/signup|napraviti račun]].",
"echo-none": "Nemate obavještenja",
@@ -52,41 +48,15 @@
"notification-link-text-view-changes": "Pogledaj izmjene",
"notification-link-text-view-page": "Pogledaj stranicu",
"notification-link-text-view-edit": "Pogledaj uređivanje",
- "notification-edit-talk-page2": "[[User:$1|$1]] vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj [[User talk:$2#$3|stranici za razgovor]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj [[User talk:$2#$3|stranici za razgovor]].",
- "notification-edit-talk-page-flyout-with-section": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "Stranica [[:$2]] je {{GENDER:$1|povezana}} sa stranicom [[:$3]]. [[Special:WhatLinksHere/$2|Pogledajte sve veze prema ovoj stranici]].",
- "notification-page-linked-flyout": "[[:$2]] je {{GENDER:$1|povezana}} sa [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] je {{GENDER:$1|ostavio|ostavila}} komentar na \"[[$3|$2]]\" na \"$4\" stranici za razgovor.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] je {{GENDER:$1|postavio|postavila}} novu temu \"$2\" na [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] vam je {{GENDER:$1|poslao|poslala}} poruku: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] je {{GENDER:$1|komentarisao|komentarisala}} temu \"[[$3#$2|$2]]\" na vašoj stranici za razgovor.",
- "notification-mention": "[[User:$1|$1]] vas je {{GENDER:$1|spomenuо|spomenula}} na stranici za razgovor $5 u \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 vas je {{GENDER:$1|spomenuо|spomenula}} na stranici za razgovor $5 u \"[[:$3#$2|$4]]\".",
- "notification-user-rights": "Vaša korisnička prava [[Special:Log/rights/$1|su bila {{GENDER:$1|izmijenjena}}]] od strane [[User:$1|$1]]. $2. [[Special:ListGroupRights|Saznajte više]]",
- "notification-user-rights-flyout": "Vaša korisnička prava su bila {{GENDER:$1|izmijenjena}} od strane $1. $2. [[Special:ListGroupRights|Saznajte više]]",
- "notification-user-rights-add": "Od sada ste član {{PLURAL:$2|ove grupe|ovih grupa}}: $1",
- "notification-user-rights-remove": "Više niste član {{PLURAL:$2|ove grupe|ovih grupa}}: $1",
- "notification-new-user": "$1, dobro došli na {{SITENAME}}! Drago nam je što ste ovdje.",
- "notification-reverted2": "{{PLURAL:$4|Vaša izmjena na [[:$2]] je poništena|Vaše izmjene na [[:$2]] su vraćene}} {{GENDER:$1|od}} strane [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Vaša izmjena na $2 je poništena|Vaše izmjene na $2 su vraćene}} {{GENDER:$1|od}} strane $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Vaša izmjena na $3 je poništena|Vaše izmjene na $3 su vraćene}} {{GENDER:$2|od}} strane $1.",
"notification-edit-talk-page-email-subject2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u \"$2\".",
"notification-page-linked-email-subject": "Vaša stranica je povezana na {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 je {{GENDER:$1|povezana}} sa $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Vaša izmjena je {{GENDER:$1|poništena}}|Vaše izmjene su {{GENDER:$1|poništene}}}} na {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Vaša izmjena na $2 je poništena|Vaše izmjene na $2 su vraćene}} {{GENDER:$1|od}} strane $1.",
"notification-mention-email-subject": "$1 vas je {{GENDER:$1|spomenuо|spomenula}} na {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 vas je {{GENDER:$1|spomenuо|spomenula}} na stranici za razgovor $4 u \"$3\".",
"notification-user-rights-email-subject": "Vaša korisnička prava su se promijenila na {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Vaša korisnička prava su {{GENDER:$1|promjenjena}} od strane $1. $2",
- "echo-email-subject-default": "Novo obavještenje na {{SITENAME}}",
"echo-email-body-default": "Imate novo obavještenje na {{SITENAME}}: \n\n$1",
- "echo-email-batch-body-default": "Imate novo obavještenje.",
"echo-email-footer-default": "$2\n\nDa kontrolišete koje vam email poruke šaljemo, provjerite svoje postavke:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Da kontrolišete koje vam email poruke šaljemo, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">provjerite vaše postavke</a>.<br />\n$1",
"echo-overlay-link": "Sva obavještenja",
"echo-overlay-title": "<b>Obavještenja</b>",
"echo-overlay-title-overflow": "<b>Obavještenja</b> (prikaz $1 od $2 nepročitanih)\n<b>Obavještenja</b> (prikaz $1 od $2 nepročitanih)",
@@ -94,14 +64,9 @@
"echo-date-today": "Danas",
"echo-date-yesterday": "Juče",
"echo-load-more-error": "Greška se pojavila za vrijeme dobavljanja više rezultata.",
- "notification-edit-talk-page-bundle": "$1 i $3 {{PLURAL:$4|ostali|ostale}} {{GENDER:$1|ostavili}} su poruku na vašoj [[User talk:$2|stranici za razgovor]].",
- "notification-page-linked-bundle": "$2 je {{GENDER:$1|povezana}} sa $3 i $4 {{PLURAL:$5|druge stranice|drugih stranica}}. [[Special:WhatLinksHere/$2|Pogledaj sve linkove na ovu stranicu]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 i $2 {{PLURAL:$3|ostali|ostalih}} {{GENDER:$1|ostavili}} su poruku na vašoj stranici za razgovor.",
- "notification-page-linked-email-batch-bundle-body": "Stranica $2 je {{GENDER:$1|povezana}} sa $3 i $4 {{PLURAL:$5|druge stranice|drugih stranica}}.",
"echo-email-batch-subject-daily": "Imate {{PLURAL:$2|novo obavještenje|nova obavještenja}} na {{SITENAME}}",
"echo-email-batch-subject-weekly": "Imate {{PLURAL:$2|novo obavještenje|nova obavještenja}} na {{SITENAME}} ove nedelje",
"echo-email-batch-body-intro-daily": "Zdravo $1,\nOvo je sažetak današnjih aktivnosti na {{SITENAME}} za Vas.",
"echo-email-batch-body-intro-weekly": "Zdravo $1,\nOvo je sažetak nedeljnih aktivnosti na {{SITENAME}} za Vas.",
- "echo-email-batch-link-text-view-all-notifications": "Vidi sve notifikacije",
- "echo-rev-deleted-text-view": "Revizija ove stranice je zabranjena."
+ "echo-email-batch-link-text-view-all-notifications": "Vidi sve notifikacije"
}
diff --git a/Echo/i18n/shn.json b/Echo/i18n/shn.json
index cbedab53..a8aeb273 100644
--- a/Echo/i18n/shn.json
+++ b/Echo/i18n/shn.json
@@ -1,8 +1,9 @@
{
"@metadata": {
"authors": [
- "Saosukham"
+ "Saosukham",
+ "Saimawnkham"
]
},
- "tooltip-pt-notifications": "ၶေႃႈၾၢင်ႉ ၸဝ်ႈၵဝ်ႇ"
+ "tooltip-pt-notifications-alert": "{{GENDER:|ၸဝ်ႈၵဝ်ႇ}} ဢၼ်ၽၢင်ႉ"
}
diff --git a/Echo/i18n/si.json b/Echo/i18n/si.json
index 261cfb7d..386be4f2 100644
--- a/Echo/i18n/si.json
+++ b/Echo/i18n/si.json
@@ -1,7 +1,10 @@
{
"@metadata": {
"authors": [
- "පසිඳු කාවින්ද"
+ "පසිඳු කාවින්ද",
+ "Susith Chandira Gts",
+ "SusithCM",
+ "හරිත"
]
},
"echo-desc": "නිවේදන පද්ධතිය",
@@ -15,11 +18,18 @@
"echo-no-title": "[පිටුවක් නොමැත]",
"echo-error-no-formatter": "නිවේදනය සඳහා කිසිදු ආකෘතියක් දක්වා නොමැත",
"notifications": "නිවේදන",
- "tooltip-pt-notifications": "ඔබේ නිවේදන",
+ "tooltip-pt-notifications-alert": "{{GENDER:|ඔබේ}} දැනුම්දීම්",
+ "tooltip-pt-notifications-message": "{{GENDER:|ඔබේ}} පණිවිඩ",
"echo-specialpage": "නිවේදන",
"echo-anon": "නිවේදන ලබා ගැනීම සඳහා, [$1 ගිණුමක් තනන්න] හෝ [$2 ප්‍රවිෂ්ට වන්න].",
"echo-none": "ඔබට නිවේදන කිසිවක් නොමැත.",
+ "notification-edit-talk-page2": "[[User:$1|$1]] විසින් ඔබේ [[User talk:$2#$3|සාකච්ඡා පිටුවෙහි]] පණිවුඩයක් {{GENDER:$1|තබා ඇත}}.",
+ "notification-edit-talk-page-flyout-with-section": "$1 විසින් ඔබේ සාකච්ඡා පිටුවෙහි \"[[User talk:$2#$3|$4]]\" කොටසෙහි පණිවුඩයක් {{GENDER:$1|තබා ඇත}}.",
"notification-new-user": "{{SITENAME}} වෙත පිළිගනිමු, $1!",
+ "notification-edit-talk-page-email-subject2": "$1 විසින් ඔබ හට {{SITENAME}} හි පණිවුඩයක් {{GENDER:$1|තබා ඇත}}.",
+ "notification-edit-talk-page-email-batch-body2": "$1 විසින් ඔබ හට ඔබේ සාකච්ඡා පිටුවෙහි පණිවුඩයක් {{GENDER:$1|තබා ඇත}}.",
+ "notification-mention-email-subject": "$1 විසින් ඔබව {{SITENAME}} හි {{GENDER:$1|සඳහන් කර}} ඇත.",
+ "echo-notification-count": "$1+",
"echo-email-subject-default": "{{SITENAME}} හී නව නිවේදනයක්",
"echo-email-body-default": "ඔබට {{SITENAME}} හීදී නව නිවේදනයක් ඇත:\n\n$1",
"echo-overlay-link": "සියලුම නිවේදන",
diff --git a/Echo/i18n/sk.json b/Echo/i18n/sk.json
index bccc9efd..d1cc6a8b 100644
--- a/Echo/i18n/sk.json
+++ b/Echo/i18n/sk.json
@@ -2,7 +2,10 @@
"@metadata": {
"authors": [
"Sudo77(new)",
- "Teslaton"
+ "Teslaton",
+ "Macofe",
+ "Urbanecm",
+ "Martin Urbanec"
]
},
"echo-desc": "Notifikačný systém",
@@ -10,6 +13,7 @@
"prefs-emailsettings": "Možnosti e-mailu",
"prefs-displaynotifications": "Možnosti zobrazenia",
"prefs-echosubscriptions": "Upozornite ma na tieto udalosti",
+ "prefs-echocrosswiki": "Upozornenia medzi projektami",
"prefs-newmessageindicator": "Indikátor nových správ",
"echo-pref-send-me": "Posielajte mi:",
"echo-pref-send-to": "Posielať na:",
@@ -22,94 +26,130 @@
"echo-pref-email-frequency-weekly": "Týždenný súhrn upozornení",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Obyčajný text",
+ "echo-pref-cross-wiki-notifications": "Zobrazovať upozornenia z iných wiki",
"echo-pref-new-message-indicator": "Zobraziť indikátor diskusných správ v mojom paneli nástrojov",
+ "echo-pref-beta-feature-cross-wiki-message": "Vylepšené upozornenia",
+ "echo-pref-beta-feature-cross-wiki-description": "Prezerajte si a organizujte upozornenia jednoduchšie. Zahŕňa upozornenia naprieč wikiprojektami, čo vám umožní vidieť správy z iných wiki.",
"echo-learn-more": "Ďalšie informácie",
+ "echo-log": "Verejný záznam",
"echo-new-messages": "Máte nové správy",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|správu|správy}} v diskusii",
"echo-category-title-article-linked": "{{PLURAL:$1|odkaz|odkazy}} na stránku",
"echo-category-title-reverted": "{{PLURAL:$1|vrátenú úpravu|vrátené úpravy}}",
"echo-category-title-mention": "{{PLURAL:$1|zmienku|zmienky}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|neúspešnú zmienku|neúspešné zmienky}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|úspešnú zmienku|úspešné zmienky}}",
"echo-category-title-other": "{{PLURAL:$1|inú udalosť|iné udalosti}}",
"echo-category-title-system": "{{PLURAL:$1|systémovú udalosť|systémové udalosti}}",
"echo-category-title-user-rights": "{{PLURAL:$1|zmenu|zmeny}} používateľských práv",
+ "echo-category-title-emailuser": "{{PLURAL:$1|e-mail od iného používateľa|e-maily od ostatných používateľov}}",
"echo-pref-tooltip-edit-user-talk": "Upozornite ma, keď mi niekto na mojej diskusnej stránke napíše správu alebo odpovie.",
"echo-pref-tooltip-article-linked": "Upozornite ma, keď niekto na stránku, ktorú som založil, odkáže z článku.",
"echo-pref-tooltip-reverted": "Upozornite ma, keď niekto vráti úpravu, ktorú som urobil, pomocou nástrojov vrátiť alebo rollback.",
"echo-pref-tooltip-mention": "Upozornite ma, keď v akejkoľvek diskusii niekto odkáže na moju redaktorskú stránku.",
+ "echo-pref-tooltip-mention-failure": "Upozornite ma, keď sa nepodarí odoslať moju zmienku niekomu.",
+ "echo-pref-tooltip-mention-success": "Upozornite ma, keď niekomu odošlem zmienku.",
"echo-pref-tooltip-user-rights": "Upozornite ma, keď niekto zmení moje používateľské práva.",
- "echo-no-agent": "[Nikto]",
- "echo-no-title": "[Žiadna stránka]",
+ "echo-pref-tooltip-emailuser": "Upozornite ma, keď mi niekto pošle e-mail.",
"echo-error-no-formatter": "Upozornenie nemá definované formátovanie",
"notifications": "Upozornenia",
"tooltip-pt-notifications-alert": "{{GENDER:|Vaše}} upozornenia",
- "tooltip-pt-notifications-message": "{{GENDER:|Vaše}} správy",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Vaše}} oznámenia",
"echo-specialpage": "Upozornenia",
+ "echo-specialpage-section-markread": "Označiť skupinu ako prečítanú",
+ "echo-specialpage-markasread": "Oznámenie: Označiť ako prečítané",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|upozornenie|upozornenia|upozornení}}",
+ "echo-specialpage-pagefilters-title": "Nedávna aktivita",
+ "echo-specialpage-pagefilters-subtitle": "Stránky s neprečítanými upozorneniami",
+ "notificationsmarkread-legend": "Označiť oznámenie ako prečítané",
"echo-anon": "Ak chcete dostávať upozornenia, musíte si [$1 vytvoriť účet] alebo [$2 sa prihlásiť].",
"echo-none": "Nemáte žiadne upozornenia.",
"echo-more-info": "Viac informácií",
"echo-feedback": "Spätná väzba",
+ "echo-popup-footer-special-page-invitation": "<strong>Vyskúšajte prepracovanú stránku s upozorneniami.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "S novým vizuálom aj funkciami.",
+ "echo-api-failure": "Nepodarilo sa načítať upozornenia. Skúste to prosím znovu. (Chyba $1)",
+ "echo-notification-placeholder": "Nemáte žiadne upozornenia.",
+ "echo-notification-markasread": "Označiť ako prečítané",
+ "echo-notification-markasunread": "Označiť ako neprečítané",
+ "echo-notification-markasread-tooltip": "Označiť ako prečítané",
+ "echo-notification-more-options-tooltip": "Viac možností",
+ "notification-link-text-expand-all": "Rozbaliť",
+ "notification-link-text-expand-alert-count": "Zobraziť $1 {{PLURAL:$1|upozornenie|upozornenia|upozornení}}",
+ "notification-link-text-expand-notice-count": "Zobraziť $1 {{PLURAL:$1|oznámenie|oznámenia|oznámení}}",
+ "notification-link-text-expand-all-count": "Zobraziť $1 {{PLURAL:$1|oznámenie|oznámenia|oznámení}}",
+ "notification-link-text-collapse-all": "Zbaliť",
"notification-link-text-view-message": "Zobraziť správu",
"notification-link-text-view-mention": "Zobraziť zmienku",
- "notification-link-text-view-changes": "Zobraziť zmeny",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Zobraziť zmienku|Zobraziť zmienky}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Zobraziť}} zmeny",
"notification-link-text-view-page": "Zobraziť stránku",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$3|vám}} {{GENDER:$2|napísal|napísala}} na vašu diskusnú stránku.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$3|vám}} {{GENDER:$2|napísal|napísala}} na vašu diskusnú stránku v sekcii „$4“.",
+ "notification-header-page-linked": "Zo stránky <strong>$4</strong> bol vytvorený odkaz na stránku <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Zo stránky <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Zo stránky $4 a $5 {{PLURAL:$6|ďalšej|ďalších}} boli vytvorené odkazy na stránku $3.",
+ "notification-link-text-what-links-here": "Všetky odkazy na túto stránku",
+ "notification-header-mention-other": "$1 {{GENDER:$3|vás}} {{GENDER:$2|spomenul|spomenula}} v diskusii <strong>$4</strong> v sekcii „$5“.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|vás}} {{GENDER:$2|spomenul|spomenula}} v diskusii <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|vás}} {{GENDER:$2|spomenul|spomenula}} v diskusii {{GENDER:$5|používateľa|používateľky}} '''$4''' v sekcii „$6“.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|vás}} {{GENDER:$2|spomenul|spomenula}} v diskusii {{GENDER:$5|používateľa|používateľky}} '''$4'''.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|vás}} {{GENDER:$2|spomenul|spomenula}} na svojej diskusnej stránke v sekcii „$4“.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|vás}} {{GENDER:$2|spomenul|spomenula}} na svojej diskusnej stránke.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|vás}} {{GENDER:$2|spomenul|spomenula}} v diskusii k článku <strong>$4</strong> v sekcii „$5“.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|vás}} {{GENDER:$2|spomenul|spomenula}} v diskusii k článku <strong>$4</strong>.",
+ "notification-header-user-rights-add-only": "Vaše používateľské práva boli {{GENDER:$1|zmenené}}: Stali ste sa {{GENDER:$4|členom|členkou}} {{PLURAL:$3|skupiny|skupín}} $2.",
+ "notification-header-user-rights-remove-only": "Vaše používateľské práva boli {{GENDER:$1|zmenené}}: Už nie ste {{GENDER:$4|členom|členkou}} {{PLURAL:$3|skupiny|skupín}} $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Vaše}} používateľské práva boli {{GENDER:$1|zmenené}}: Stali ste sa {{GENDER:$6|členom|členkou}} {{PLURAL:$3|skupiny|skupín}} $2 a už nie ste {{GENDER:$6|členom|členkou}} {{PLURAL:$5|skupiny|skupín}} $4.",
+ "notification-header-welcome": "Vitajte na {{GRAMMAR:6sg|{{SITENAME}}}}, {{GENDER:$2|$1}}! Teší nás, že ste tu.",
+ "notification-welcome-linktext": "Vitajte",
+ "notification-header-thank-you-1-edit": "Práve ste {{GENDER:$2|vykonal|vykonala}} svoju prvú úpravu. Vďaka a vitajte!",
+ "notification-header-thank-you-10-edit": "Práve ste {{GENDER:$2|vykonal|vykonala}} svoju desiatu úpravu. Vďaka a len tak ďalej!",
+ "notification-header-thank-you-100-edit": "Práve ste {{GENDER:$2|vykonal|vykonala}} svoju stú úpravu. Veľká vďaka!",
+ "notification-header-thank-you-1000-edit": "Práve ste {{GENDER:$2|vykonal|vykonala}} svoju tisícu úpravu. Vďaka, ste {{GENDER:$2|skvelý prispievatel|skvelá prispievateľka}}!",
+ "notification-header-thank-you-10000-edit": "Práve ste {{GENDER:$2|vykonal|vykonala}} svoju desaťtisícu úpravu. Obrovská vďaka!",
+ "notification-header-thank-you-100000-edit": "Práve ste {{GENDER:$2|vykonal|vykonala}} svoju stotisícu úpravu. Vďaka za váš vynikajúci príspevok!",
+ "notification-header-thank-you-1000000-edit": "Práve ste {{GENDER:$2|vykonal|vykonala}} svoju milióntu úpravu. Vďaka za váš ohromujúci príspevok!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Vaša}} úprava",
"notification-link-text-view-edit": "Zobraziť úpravu",
- "notification-edit-talk-page2": "[[User:$1|$1]] vám {{GENDER:$1|napísal|napísala}} na [[User talk:$2#$3|vašu diskusnú stránku]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] vám {{GENDER:$1|napísal|napísala}} na vašu diskusnú stránku v sekcii „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "$1 vám {{GENDER:$1|napísal|napísala}} na [[User talk:$2#$3|vašu diskusnú stránku]].",
- "notification-edit-talk-page-flyout-with-section": "$1 vám {{GENDER:$1|napísal|napísala}} na vašu diskusnú stránku v sekcii „[[User talk:$2#$3|$4]]“.",
- "notification-page-linked": "Na stránku [[:$3]] {{GENDER:$1|bol pridaný}} odkaz na stránku [[:$2]]. [[Special:WhatLinksHere/$2|Zobraziť všetky odkazy na túto stránku]].",
- "notification-page-linked-flyout": "Na stránku [[:$3]] {{GENDER:$1|bol pridaný}} odkaz na stránku [[:$2]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|pridal|pridala}} komentár k „[[$3|$2]]“ na stránke „$4“",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|pridal|pridala}} komentár na novú tému „$2“ na stránke „[[$3]]“",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] vám {{GENDER:$1|poslal|poslala}} správu: „[[$3#$2|$2]]“",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|pridal|pridala}} komentár k „[[$3#$2|$2]]“ na vašej diskusnej stránke",
- "notification-mention": "[[User:$1|$1]] vás {{GENDER:$1|spomenul|spomenula}} v diskusii {{GENDER:$5|redaktora|redaktorky}} $5 v sekcii „[[:$3#$2|$4]]“.",
- "notification-mention-flyout": "$1 vás {{GENDER:$1|spomenul|spomenula}} v diskusii {{GENDER:$5|redaktora|redaktorky}} $5 v sekcii „[[:$3#$2|$4]]“.",
- "notification-mention-nosection": "[[User:$1|$1]] vás {{GENDER:$1|spomenul|spomenula}} v [[:$3|diskusii ku stránke $2]].",
- "notification-mention-nosection-flyout": "$1 vás {{GENDER:$1|spomenul|spomenula}} v [[:$3|diskusii ku stránke $2]].",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|{{GENDER:$1|zmenil|zmenila}}]] vaše používateľské práva. $2. [[Special:ListGroupRights|Podrobnosti]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1|zmenil|zmenila}} vaše používateľské práva. $2. [[Special:ListGroupRights|Podrobnosti]]",
- "notification-user-rights-add": "Patríte teraz do {{PLURAL:$2|tejto skupiny|týchto skupín}}: $1",
- "notification-user-rights-remove": "Naďalej už nie ste členom {{PLURAL:$2|tejto skupiny|týchto skupín}}: $1",
- "notification-new-user": "Vitajte na {{grammar:6sg|{{SITENAME}}}}, $1! Teší nás, že ste tu.",
- "notification-reverted2": "[[User:$1|$1]] {{GENDER:$1|vrátil|vrátila}} {{PLURAL:$4|vašu úpravu|vaše úpravy}} stránky [[:$2]] $3",
- "notification-reverted-flyout2": "$1 {{GENDER:$1|vrátil|vrátila}} {{PLURAL:$4|vašu úpravu|vaše úpravy}} stránky $2 $3",
+ "notification-header-reverted": "$1 {{GENDER:$2|vrátil|vrátila}} {{PLURAL:$4|vašu úpravu|vaše úpravy}} stránky $3",
+ "notification-header-emailuser": "$1 vám {{GENDER:$2|poslal|poslala}} e-mail.",
"notification-edit-talk-page-email-subject2": "$1 vám na {{grammar:6sg|{{SITENAME}}}} {{GENDER:$1|napísal|napísla}} správu.",
- "notification-edit-talk-page-email-batch-body2": "$1 vám {{GENDER:$1|napísal|napísala}} na vašu diskusnú stránku:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 vám {{GENDER:$1|napísal|napísala}} na vašu diskusnú stránku k sekcii „$2“.",
"notification-page-linked-email-subject": "Na {{grammar:6sg|{{SITENAME}}}} niekto odkázal na vašu stránku.",
- "notification-page-linked-email-batch-body": "Na stránku $3 {{GENDER:$1|bol pridaný}} odkaz na stránku $2",
"notification-reverted-email-subject2": "$1 {{GENDER:$1|revertoval|revertovala}} {{PLURAL:$3|vašu úpravu|vaše úpravy}} na {{grammar:6sg|{{SITENAME}}}}",
- "notification-reverted-email-batch-body2": "$1 {{GENDER:$1|revertoval|revertovala}} {{PLURAL:$3|vašu úpravu|vaše úpravy}} stránky $2.",
"notification-mention-email-subject": "$1 vás {{GENDER:$1|spomenul|spomenula}} na {{grammar:6sg|{{SITENAME}}}}",
- "notification-mention-email-batch-body": "$1 vás {{GENDER:$1|spomenul|spomenula}} v diskusii {{GENDER:$4|redaktora|redaktorky}} $4 v sekcii „$3“.",
- "notification-mention-nosection-email-batch-body": "$1 vás {{GENDER:$1|spomenul|spomenula}} v diskusii ku stránke $2.",
"notification-user-rights-email-subject": "Na {{grammar:6sg|{{SITENAME}}}} boli zmenené vaše redaktorské práva",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1|zmenil|zmenila}} vaše redaktorské práva. $2",
- "echo-email-subject-default": "Nové upozornenie na {{grammar:6sg|{{SITENAME}}}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mes.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 r}}",
+ "notification-timestamp-today": "Dnes",
+ "notification-timestamp-yesterday": "Včera",
+ "notification-inbox-filter-read": "Prečítané",
+ "notification-inbox-filter-unread": "Neprečítané",
+ "notification-inbox-filter-all": "Všetky",
"echo-email-body-default": "Na {{grammar:6sg|{{SITENAME}}}} máte nové upozornenie:\n\n$1",
- "echo-email-batch-body-default": "Máte nové upozornenie",
"echo-email-footer-default": "$2\n\nPosielanie e-mailov si môžete prispôsobiť v nastaveniach:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Posielanie e-mailov si môžete prispôsobiť <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">v nastaveniach</a>.<br />\n$1",
"echo-notification-alert": "{{PLURAL:$1|Upozornenie ($1)|Upozornenia ($1)|100=Upozornenia (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Správa ($1)|Správy ($1)|100=Správy (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Oznámenie ($1)|Oznámenia ($1)|100=Oznámení (99+)}}",
"echo-notification-alert-text-only": "Upozornenia",
- "echo-notification-message-text-only": "Správy",
+ "echo-notification-notice-text-only": "Oznámenia",
"echo-overlay-link": "Všetky upozornenia",
"echo-overlay-title": "<b>Upozornenia</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Upozornenie|Upozornenia}}</b> (zobrazuje sa $1 z $2 {{PLURAL:$1|neprečítaného|neprečítaných}})",
"echo-mark-all-as-read": "Označiť všetko ako prečítané",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|upozornenie označené|upozornenia označené|upozornení označených}} ako prečítané",
+ "echo-mark-wiki-as-read": "Označiť všetko ako prečítané vo zvolenej wiki: $1",
"echo-date-today": "Dnes",
"echo-date-yesterday": "Včera",
"echo-load-more-error": "Pri načítaní ďalších výsledkov došlo k chybe.",
- "notification-edit-talk-page-bundle": "$1 a $3 {{PLURAL:$4|ďalší}} vám napsali na [[User talk:$2|vašu diskusnú stránku]].",
- "notification-page-linked-bundle": "Do stránky $3 a $4 {{PLURAL:$5|ďalšej stránky|ďalších stránok}} {{GENDER:$1|boli vložené}} odkazy na stránku $2. [[Special:WhatLinksHere/$2|Zobraziť všetky odkazy na túto stránku]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 a $2 {{PLURAL:$3|další|další|dalších}} vám napísali na vašu diskusnú stránku",
- "notification-page-linked-email-batch-bundle-body": "Do stránky $3 a $4 {{PLURAL:$5|ďalšej stránky|ďalších stránok}} {{GENDER:$1|boli vložené}} odkazy na stránku $2.",
+ "notification-bundle-header-edit-user-talk-v2": "$1 {{PLURAL:$2|nová správa|nové správy|nových správ}} na {{GENDER:$3|vašej}} diskusnej stránke.",
"echo-email-batch-subject-daily": "Na {{grammar:6sg|{{SITENAME}}}} dnes máte {{PLURAL:$2|nové|nové|nových}} upozornení",
"echo-email-batch-subject-weekly": "Na {{grammar:6sg|{{SITENAME}}}} máte tento týždeň {{PLURAL:$2|nové|nové|nových}} upozornení",
"echo-email-batch-body-intro-daily": "Ahoj $1,\n\npripájame zhrnutie dnešnej aktivity na {{grammar:6sg|{{SITENAME}}}}.",
"echo-email-batch-body-intro-weekly": "Ahoj $1,\n\npripájame zhrnutie aktivity na {{grammar:6sg|{{SITENAME}}}} za posledný týždeň.",
- "echo-email-batch-link-text-view-all-notifications": "Zobraziť všetky upozornenia",
- "echo-rev-deleted-text-view": "Táto revízia stránky bola skrytá."
+ "echo-email-batch-link-text-view-all-notifications": "Zobraziť všetky upozornenia"
}
diff --git a/Echo/i18n/skr-arab.json b/Echo/i18n/skr-arab.json
new file mode 100644
index 00000000..3c15c80a
--- /dev/null
+++ b/Echo/i18n/skr-arab.json
@@ -0,0 +1,61 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saraiki"
+ ]
+ },
+ "prefs-echo": "اطلاع نامے",
+ "prefs-emailsettings": "ای میل دے آپشن",
+ "prefs-displaynotifications": "آپشن ݙکھاؤ",
+ "echo-pref-send-me": "میکوں بھیجو:",
+ "echo-pref-send-to": "جیکوں بھیجو:",
+ "echo-pref-email-format": "ای میل فارمیٹ",
+ "echo-pref-web": "ویب",
+ "echo-pref-email": "ای میل",
+ "echo-pref-email-format-html": "ایچ ٹی ایم ایل",
+ "echo-pref-email-format-plain-text": "سادہ متن",
+ "echo-learn-more": "ٻیا سِکھو",
+ "echo-log": "عوامی لاگ",
+ "echo-new-messages": "تہاݙے کیتے نویں سنیہے ہن",
+ "echo-category-title-other": "{{PLURAL:$1|ٻیا}}",
+ "echo-category-title-system": "{{PLURAL:$1|نظام}}",
+ "notifications": "اطلاع نامے",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Your}} الرٹس",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "موجودہ ورتݨ آلے",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "نویں ورتݨ آلے",
+ "echo-specialpage": "اطلاع نامے",
+ "echo-specialpage-pagefilters-title": "حالیہ سرگرمی",
+ "echo-more-info": "ٻیاں معلومات",
+ "echo-feedback": "تہاڈی رائے",
+ "echo-notification-markasread": "نشان لاؤ جو پڑھ گھدے",
+ "echo-notification-markasunread": "نشان لاؤ جو کائنی پڑھا",
+ "echo-notification-markasread-tooltip": "نشان لاؤ جو پڑھ گھدے",
+ "echo-notification-more-options-tooltip": "ٻئے اختیار",
+ "notification-link-text-expand-all": "ودھاؤ",
+ "notification-link-text-collapse-all": "لکاؤ",
+ "notification-link-text-view-message": "سنیہا ݙیکھو",
+ "notification-link-text-view-mention": "تذکرہ ݙیکھو",
+ "notification-link-text-view-page": "ورقہ ݙیکھو",
+ "notification-welcome-linktext": "ست بسم اللہ",
+ "notification-link-text-view-edit": "تبدیلی ݙیکھو",
+ "notification-link-article-reminder": "ورقہ ݙیکھو",
+ "notification-timestamp-ago-seconds": "\n{{PLURAL:$1|$1s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mo}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1yr}}",
+ "notification-timestamp-today": "اڄ",
+ "notification-timestamp-yesterday": "کل",
+ "notification-inbox-filter-read": "پڑھو",
+ "notification-inbox-filter-unread": "کائنی پڑھا",
+ "notification-inbox-filter-all": "یکے",
+ "echo-notification-alert-text-only": "الرٹ",
+ "echo-notification-notice-text-only": "اطلاعات",
+ "echo-overlay-link": "جملہ اطلاعاں",
+ "echo-overlay-title": "<b>اطلاعات</b>",
+ "echo-mark-all-as-read": "نشان لاؤ جو سارا پڑھ گھدے",
+ "echo-date-today": "اڄ",
+ "echo-date-yesterday": "کل",
+ "echo-email-batch-link-text-view-all-notifications": "سارے اطلاع نامے ݙیکھو"
+}
diff --git a/Echo/i18n/sl.json b/Echo/i18n/sl.json
index d56860e3..fd5944a9 100644
--- a/Echo/i18n/sl.json
+++ b/Echo/i18n/sl.json
@@ -5,7 +5,9 @@
"Eleassar",
"Matej1234",
"Pinky sl",
- "Yerpo"
+ "Yerpo",
+ "Macofe",
+ "Janezdrilc"
]
},
"echo-desc": "Sistem za obveščanje uporabnikov o dogodkih in sporočilih",
@@ -13,6 +15,7 @@
"prefs-emailsettings": "Možnosti e-pošte",
"prefs-displaynotifications": "Možnosti prikaza",
"prefs-echosubscriptions": "Obvesti me o naslednjih dogodkih",
+ "prefs-echocrosswiki": "Obveščanje med wikiji",
"prefs-newmessageindicator": "Kazalnik novih sporočil",
"echo-pref-send-me": "Pošlji mi:",
"echo-pref-send-to": "Pošlji:",
@@ -25,89 +28,172 @@
"echo-pref-email-frequency-weekly": "Tedenski povzetek obvestil",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Neoblikovano besedilo",
+ "echo-pref-cross-wiki-notifications": "Prikaži obvestila iz drugih wikijev",
"echo-pref-new-message-indicator": "V orodni vrstici prikaži kazalnik sporočil na pogovornih straneh",
+ "echo-pref-beta-feature-cross-wiki-message": "Napredna obvestila",
+ "echo-pref-beta-feature-cross-wiki-description": "Poglej in razporedi obvestila bolj pregledno. Vključuje obveščanje med wikiji. (Za prejemanj obvestil na poljubnem wikiju, moraš na njem vklopiti beta funkcijo.)",
"echo-learn-more": "Več o tem",
- "echo-new-messages": "Imate nova sporočila",
- "echo-category-title-edit-user-talk": "{{PLURAL:$1|Sporočilo|Sporočila}} na pogovornih straneh",
- "echo-category-title-article-linked": "{{PLURAL:$1|Povezava|Povezave}} na pogovornih straneh",
- "echo-category-title-reverted": "{{PLURAL:$1|Vračanje|Vračanja}} urejanj",
- "echo-category-title-mention": "{{PLURAL:$1|Omemba|Omembe}}",
+ "echo-log": "Dnevnik",
+ "echo-new-messages": "Prejel si nova sporočila",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|Sporočilo|Sporočili|Sporočila}} na pogovornih straneh",
+ "echo-category-title-article-linked": "{{PLURAL:$1|Povezava|Povezavi|Povezave}} na pogovornih straneh",
+ "echo-category-title-reverted": "{{PLURAL:$1|Vračanje urejanja|Vračanje urejanj}}",
+ "echo-category-title-mention": "{{PLURAL:$1|Omemba|Omembi|Omembe|Omemb}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|neuspela omemba|neuspeli omembi|neuspele omembe|neuspelih omemb}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|uspela omemba|uspeli omembi|uspele omembe|uspelih omemb}}",
"echo-category-title-other": "{{PLURAL:$1|Drugo}}",
"echo-category-title-system": "{{PLURAL:$1|Sistem}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Sprememba|Spremembi|Spremembe}} uporabniških pravic",
+ "echo-category-title-emailuser": "{{PLURAL:$1|e-pošta od drugega uporabnika|e-pošti od drugih uporabnikov|e-pošte od drugih uporabnikov|e-pošt od drugih uporabnikov}}",
"echo-pref-tooltip-edit-user-talk": "Obvesti me, ko nekdo na moji pogovorni strani objavi sporočilo ali odgovori.",
"echo-pref-tooltip-article-linked": "Obvesti me, ko nekdo doda povezavo na stran, ki sem jo ustvaril.",
"echo-pref-tooltip-reverted": "Obvesti me, ko nekdo z orodjem za razveljavitev ali vrnitev vrne urejanje, ki sem ga napravil.",
"echo-pref-tooltip-mention": "Obvesti me, ko nekdo doda povezavo na mojo uporabniško stran.",
+ "echo-pref-tooltip-mention-failure": "Obvesti me, ko ne uspem poslati omembe nekoga.",
+ "echo-pref-tooltip-mention-success": "Obvesti me, ko pošljem omembo nekoga.",
"echo-pref-tooltip-user-rights": "Obvesti me, ko nekdo spremeni moje uporabniške pravice.",
- "echo-no-agent": "[Nihče]",
- "echo-no-title": "[Nobena stran]",
+ "echo-pref-tooltip-emailuser": "Obvesti me ob prejemu e-pošte.",
"echo-error-no-formatter": "Za obvestilo ni določeno nobeno oblikovanje.",
"notifications": "Obvestila",
- "tooltip-pt-notifications": "Vaša obvestila",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Tvoji}} opomniki",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Tvoja}} obvestila",
+ "echo-displaynotificationsconfiguration": "Prikaži nastavitve za obvestila",
+ "echo-displaynotificationsconfiguration-summary": "To je pregled nastavitev tvojih obvestil na tem wikiju.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Obvestila po kategoriji",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sortiranje tipov",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "v kateri del je uvrščena vrsta obvestila",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Ustrezni načini obveščanja",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Kateri načini obveščanja so podprti za posamezno kategorijo",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Kateri načini obveščanja so podprti za katero vrsto; nanaša se samo na vrste v kategorijah, ki so skrite v nastavitvah",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Vključeno v prednastavitvah",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Obstoječi uporabniki",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Novi uporabniki",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Zahtevani načini za obveščanje",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Kateri načini obveščanja so obvezni za posamezno kategorijo",
"echo-specialpage": "Obvestila",
- "echo-anon": "Za prejemanje obvestil [$1 si ustvarite račun] ali [$2 se prijavite].",
- "echo-none": "Nimate obvestil.",
+ "echo-specialpage-section-markread": "Označi skupino za prebrano",
+ "echo-specialpage-markasread": "Obvestilo: Označi za prebrano",
+ "echo-specialpage-markasread-invalid-id": "Neuspešna določitev dejanja",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|obvestilo|obvestili|obvestila|obvestil}}",
+ "echo-specialpage-pagefilters-title": "Trenutna dejavnost",
+ "echo-specialpage-pagefilters-subtitle": "Strani z neprebranimi obvestili",
+ "notificationsmarkread-legend": "Označi obvestilo za prebrano",
+ "echo-anon": "Za prejemanje obvestil [$1 si moraš ustvariti račun] ali [$2 se prijaviti].",
+ "echo-none": "Ni obvestil.",
"echo-more-info": "Več informacij",
"echo-feedback": "Povratne informacije",
+ "echo-popup-footer-special-page-invitation": "<strong>Preizkusi prenovljeno stran obvestil.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Novi izgled in funkcije.",
+ "echo-api-failure": "Pri izpisu obvestil je prišlo do napake.",
+ "echo-api-failure-cross-wiki": "Dostop do oddaljene domene je bil zavrnjen.",
+ "echo-notification-placeholder": "Ni obvestil.",
+ "echo-notification-placeholder-filters": "Ni obvestil, ki bi se ujemale s temi kriteriji.",
+ "echo-notification-loginrequired": "Za pregled sporočil se moraš prijaviti.",
+ "echo-notification-popup-loginrequired": "Za ogled svojih obvestil se prosim prijavi.",
+ "echo-notification-markasread": "Označi za prebrano",
+ "echo-notification-markasunread": "Označi za neprebrano",
+ "echo-notification-markasread-tooltip": "Označi za prebrano",
+ "echo-notification-more-options-tooltip": "Dodatne možnosti",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Ne glej}} več novih dejavnosti na \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Ne gledaš}} več strani \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "Kadarkoli lahko {{GENDER:$3|pogledaš}} [$2 to stran].",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Preveri}} novo dejavnost na \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "Trenutno {{GENDER:$3|gledaš}} stran \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "Kadarkoli lahko {{GENDER:$3|prenehaš}} z ogledom [$2 te strani].",
+ "notification-link-text-expand-all": "Odpri",
+ "notification-link-text-expand-alert-count": "Poglej {{PLURAL:$1|$1 opomnik|$1 opomnika|$1 opomnike|$1 opomnikov}}",
+ "notification-link-text-expand-notice-count": "Poglej {{PLURAL:$1|$1 obvestilo|$1 obvestili|$1 obvestila|$1 obvestil}}",
+ "notification-link-text-expand-all-count": "Poglej {{PLURAL:$1|$1 obvestilo|$1 obvestili|$1 obvestila|$1 obvestil}}",
+ "notification-link-text-collapse-all": "Zapri",
"notification-link-text-view-message": "Ogled sporočila",
"notification-link-text-view-mention": "Ogled omembe",
- "notification-link-text-view-changes": "Ogled sprememb",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Poglej obvestilo|Poglej obvestili|Poglej obvestila}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Ogled}} sprememb",
"notification-link-text-view-page": "Ogled strani",
+ "notification-header-edit-user-talk": "$1 je na <strong>{{GENDER:$3|tvoji}} pogovorni strani</strong> {{GENDER:$2|pustil|pustila}} sporočilo.",
+ "notification-header-edit-user-talk-with-section": "$1 ti je {{GENDER:$2|pustil|pustila}} sporočilo na <strong>{{GENDER:$3|tvoji}} pogovorni strani</strong> v razdelku »<strong>$4</strong>«.",
+ "notification-header-page-linked": "V članku <strong>$4</strong> je bila narejena notranja povezava na članek <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Povezava narejena iz <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Narejene so bile povezave iz {{PLURAL:$5|$5 stran|$5 strani|100=99+ strani}} na <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Vse povezave na to stran",
+ "notification-header-mention-other": "$1 {{GENDER:$3|te}} je {{GENDER:$2|omenil|omenila}} na strani <strong>$4</strong> v razdelku »<strong>$5</strong>«.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$3|te}} je {{GENDER:$2|omenil|omenila}} na strani <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$3|te}} je {{GENDER:$2|omenil|omenila}} na <strong>pogovorni strani {{GENDER:$5|uporabnika|uporabnice}} $4</strong> v razdelku »<strong>$6</strong>«.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|te}} je {{GENDER:$2|omenil|omenila}} na <strong>pogovorni strani {{GENDER:$5|uporabnika|uporabnice}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$3|te}} {{GENDER:$2|je omenil}} na <strong>{{GENDER:$2|svoji}} pogovorni strani</strong> v razdelku \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$3|te}} je {{GENDER:$2|omenil|omenila}} na <strong>{{GENDER:$2|svoji}} pogovorni strani</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$3|te}} je {{GENDER:$2|omenil|omenila}} na pogovorni strani članka <strong>$4</strong> v razdelku »<strong>$5</strong>«.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|te}} je {{GENDER:$2|omenil|omenila}} na pogovorni strani članka <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Tvoja}} omemba uporabnika <strong>$3</strong> ni bila poslana, saj uporabnik ni bil najden.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Tvoja}} omemba uporabnika <strong>$3</strong> ni bila poslana, saj je uporabnik anonimen.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Poskusil si|Poskusila si|Poskusili ste}} omeniti več kot $3 {{PLURAL:$3|uporabnika|uporabnika|uporabnike|uporabnikov}}. Vseh omemb nad to mejo nismo poslali.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Omemba|$3 omembi|$3 omembe|$3 omemb}}, ki si jih {{GENDER:$2|naredil}} na uporabniški strani <strong>$4</strong> {{PLURAL:$3|niso}} niso bile poslane.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Uporabniško ime ne obstaja:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-je ni mogoče omenjati:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Tvoja}} omemba uporabnika <strong>$3</strong> je bila poslana.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Omemba|$3 omembi|$3 omembe|$3 omemb}}, ki si jih {{GENDER:$2|naredil}} na uporabniškem pogovoru <strong>$4</strong> {{PLURAL:$3|je bila poslana|sta bili poslani|so bile poslane|je bilo poslanih}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Omenil si}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Obvestilo|$3 obvestili|$3 obvestila|$3 obvestil}} o omembah, ki si jih {{GENDER:$2|naredil}} na uporabniškem pogovoru <strong>$4</strong>: {{PLURAL:$5|$5 neposlano|$5 neposlani|$5 neposlana|$5 neposlanih}}, {{PLURAL:$6|$6 poslano|$6 poslani|$6 poslana|$6 poslanih}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Tvoje}} uporabniške pravice so bile {{GENDER:$1|spremenjene}}. Dodan si bil k skupini: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Tvoje}} Uporabniške pravice {{GENDER:$1|so bile spremenjene}}. Odslej nisi več v skupini: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Tvoje}} uporabniške pravice {{GENDER:$1|so bile spremenjene}}. Postal si del skupine: $2. Nisi več v skupini: $4.",
+ "notification-header-user-rights-expiry-change": "Čas poteka {{GENDER:$4|tvojega}} tvojega članstva v naslednjih {{PLURAL:$3|skupini|skupinama|skupinah}} je bil {{GENDER:$1|spremenjen}}: $2.",
+ "notification-header-welcome": "{{GENDER:|Dobrodošel|Dobrodošla}} na {{SITENAME}}, $1! Veseli smo {{GENDER:$2|tvojega}} obiska.",
+ "notification-welcome-linktext": "{{GENDER:|Dobrodošel|Dobrodošla}}",
+ "notification-header-thank-you-1-edit": "Pravkar si {{GENDER:$2|naredil|naredila}} svoje prvo urejanje. Hvala {{GENDER:$2|ti}} in {{GENDER:$2|dobrodošel|dobrodošla}} še naprej!",
+ "notification-header-thank-you-10-edit": "Pravkar si {{GENDER:$2|naredil|naredila}} {{GENDER:$2|svoje}} deseto urejanje. Hvala {{GENDER:$2|ti}} in le tako naprej!",
+ "notification-header-thank-you-100-edit": "Pravkar si {{GENDER:$2|naredil|naredila}} {{GENDER:$2|svoje}} stoto urejanje. Hvala ti za {{GENDER:$2|tvoj}} doprinos!",
+ "notification-header-thank-you-1000-edit": "Pravkar si {{GENDER:$2|naredil|naredila}} {{GENDER:$2|svoje}} tisoče urejanje. Hvala ti za {{GENDER:$2|tvojo}} vztrajnost pri tem velikem delu!",
+ "notification-header-thank-you-10000-edit": "Pravkar si {{GENDER:$2|naredil|naredila}} {{GENDER:$2|svoje}} desettisoče urejanje. Hvala ti za {{GENDER:$2|tvojo}} veliko prostovoljsko vnemo!",
+ "notification-header-thank-you-100000-edit": "Pravkar si {{GENDER:$2|naredil|naredila}} {{GENDER:$2|svoje}} stotisoče urejanje. Hvala ti za {{GENDER:$2|tvoj}} neverjetni doprinos!",
+ "notification-header-thank-you-1000000-edit": "Pravkar si {{GENDER:$2|naredil|naredila}} {{GENDER:$2|svoje}} milijonto urejanje. Hvala ti za {{GENDER:$2|tvoj}} naravnost osupljiv doprinos!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Tvoje}} urejanje",
"notification-link-text-view-edit": "Ogled urejanja",
- "notification-edit-talk-page2": "[[User:$1|$1]] je na vaši [[User talk:$2#$3|pogovorni strani]] {{GENDER:$1|pustil|pustila}} sporočilo.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] je {{GENDER:$1|pustil|pustila}} sporočilo na vaši pogovorni strani v razdelku »[[User talk:$2#$3|$4]]«.",
- "notification-edit-talk-page-flyout2": "$1 je na vaši [[User talk:$2#$3|pogovorni strani]]{{GENDER:$1|pustil|pustila}} sporočilo.",
- "notification-edit-talk-page-flyout-with-section": "$1 je {{GENDER:$1|pustil|pustila}} sporočilo na vaši pogovorni strani v razdelku »[[User talk:$2#$3|$4]]«.",
- "notification-page-linked": "Na strani »[[:$3]]« je bila {{GENDER:$1|dodana}} povezava na stran »[[:$2]]«. [[Special:WhatLinksHere/$2|Ogled vseh povezav na to stran]].",
- "notification-page-linked-flyout": "Na strani »[[:$3]]« je bila {{GENDER:$1|dodana povezava}} na stran »[[:$2]]«.",
- "notification-add-comment2": "[[User:$1|$1]] je o »[[$3|$2]]« {{GENDER:$1|komentiral|komentirala}} na pogovorni strani »$4«.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] je na strani »[[$3]]« {{GENDER:$1|objavil|objavila}} novo temo »$2«.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] vam je {{GENDER:$1|poslal|poslala}} sporočilo: »[[$3#$2|$2]]«.",
- "notification-add-comment-yours2": "[[User:$1|$1]] je na vaši pogovorni strani {{GENDER:$1|komentiral|komentirala}} o temi »[[$3#$2|$2]]«.",
- "notification-mention": "[[User:$1|$1]] vas je {{GENDER:$1|omenil|omenila}} na pogovorni strani strani »$5« v razdelku »[[:$3#$2|$4]]«.",
- "notification-mention-flyout": "$1 vas je {{GENDER:$1|omenil|omenila}} v razdelku »[[:$3#$2|$4]]« na pogovorni strani uporabnika »$5«.",
- "notification-mention-nosection": "[[User:$1|$1]] vas je {{GENDER:$1|omenil|omenila|omenil(-a)}} na [[:$3|pogovorni strani $2]].",
- "notification-mention-nosection-flyout": "$1 vas je {{GENDER:$1|omenil|omenila|omenil(-a)}} na [[:$3|pogovorni strani $2]].",
- "notification-user-rights": "Vaše uporabniške pravice [[Special:Log/rights/$1|je {{GENDER:$1|spremenil|spremenila}}]] {{GENDER:$1|uporabnik|uporabnica}} [[User:$1|$1]]. $2. [[Special:ListGroupRights|Več o tem]].",
- "notification-user-rights-flyout": "Vaše uporabniške pravice je {{GENDER:$1|spremenil|spremenila}} {{GENDER:$1|uporabnik|uporabnica}} $1. $2. [[Special:ListGroupRights|Več o tem]].",
- "notification-user-rights-add": "Odslej ste član {{PLURAL:$2|naslednje skupine|naslednjih skupin}}: $1",
- "notification-user-rights-remove": "Niste več član {{PLURAL:$2|naslednje skupine|naslednjih skupin}}: $1",
- "notification-new-user": "Pozdravljeni v {{GRAMMAR:dajalnik|{{SITENAME}}}}, $1! Veseli smo, da ste tu.",
- "notification-reverted2": "{{PLURAL:$4|Vaše urejanje strani »[[:$2]]« je|Vaša urejanja strani »[[:$2]]« je}} {{GENDER:$1|uporabnik|uporabnica}} [[User:$1|$1]] {{GENDER:$1|vrnil|vrnila}}. $3.",
- "notification-reverted-flyout2": "{{PLURAL:$4|Vaše urejanje strani »$2«|Vaša urejanja strani »$2«}} je {{GENDER:$1|vrnil|vrnila}} {{GENDER:$1|uporabnik|uporabnica}} $1. $3.",
- "notification-edit-talk-page-email-subject2": "V projektu {{SITENAME}} vam je {{GENDER:$1|uporabnik|uporabnica}} {{GENDER:$1|pustil|pustila}} sporočilo.",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|Uporabnik|Uporabnica}} vam je na pogovorni strani {{GENDER:$1|pustil|pustila}} sporočilo.",
- "notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Uporabnik|Uporabnica}} vam je {{GENDER:$1|pustil|pustila}} sporočilo na pogovorni strani v razdelku »$2«.",
- "notification-page-linked-email-subject": "Stran, ki ste jo ustvarili, je na projektu {{SITENAME}} dobila povezavo nanjo",
- "notification-page-linked-email-batch-body": "Stran »$2« je bila {{GENDER:$1|povezana}} s strani »$3«.",
- "notification-reverted-email-subject2": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} {{PLURAL:$3|je bilo|so bila}} {{PLURAL:$3|vaše urejanje|vaša urejanja}} {{GENDER:$1|{{PLURAL:$3|vrnjeno|vrnjena}}}}.",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Vaše urejanje|Vaša urejanja}} v {{GRAMMAR:mestnik|$2}} je {{GENER:$1|vrnil|vrnila}} $1.",
- "notification-mention-email-subject": "V projektu {{SITENAME}} vas je {{GENDER:$1|omenil|omenila}} $1.",
- "notification-mention-email-batch-body": "V razdelku »$3« na pogovorni strani {{GENDER:$4|uporabnika|uporabnice}} vas je {{GENDER:$1|omenil|omenila}} $1.",
- "notification-mention-nosection-email-batch-body": "$1 vas je {{GENDER:$1|omenil|omenila|omenil(-a)}} na pogovorni strani $2.",
- "notification-user-rights-email-subject": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} so bile spremenjene vaše uporabniške pravice.",
- "notification-user-rights-email-batch-body": "Vaše uporabniške pravice je {{GENDER:$1|spremenil|spremenila}} $1. $2.",
- "echo-email-subject-default": "Novo obvestilo v {{GRAMMAR:dajalnik|{{SITENAME}}}}",
- "echo-email-body-default": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} imate novo obvestilo:\n\n$1",
- "echo-email-batch-body-default": "Imate novo obvestilo.",
+ "notification-header-reverted": "{{PLURAL:$4|Tvoje urejanje strani <strong>$3</strong> je bilo {{GENDER:$2|vrnjeno}}|Tvoji urejanji strani <strong>$3</strong> sta bili vrnjeni|Tvoja urejanja strani <strong>$3</strong> so bila vrnjena}}.",
+ "notification-header-emailuser": "$1 ti {{GENDER:$2|je poslal|je poslala}} e-pošto.",
+ "notification-edit-talk-page-email-subject2": "V projektu {{SITENAME}} ti je {{GENDER:$1|uporabnik|uporabnica}} {{GENDER:$1|pustil|pustila}} sporočilo.",
+ "notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Uporabnik|Uporabnica}} ti je {{GENDER:$1|pustil|pustila}} sporočilo na pogovorni strani v razdelku »$2«.",
+ "notification-page-linked-email-subject": "Stran, ki si jo {{GENDER:|ustvaril|ustvarila}}, je dobila povezavo na projektu {{SITENAME}}",
+ "notification-reverted-email-subject2": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} {{PLURAL:$3|je bilo|sta bili|so bila}} {{PLURAL:$3|vaše urejanje|vaši urejanji|vaša urejanja}} {{GENDER:$1|{{PLURAL:$3|vrnjeno|vrnjeni|vrnjena}}}}.",
+ "notification-mention-email-subject": "V projektu {{SITENAME}} {{GENDER:$2|te}} je {{GENDER:$1|omenil|omenila}} $1.",
+ "notification-user-rights-email-subject": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} so bile spremenjene tvoje uporabniške pravice.",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 sekunda|$1 sekundi|$1 sekunde|$1 sekund}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 minuta|$1 minuti|$1 minute|$1 minut}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 ura|$1 uri|$1 ure|$1 ur}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 dan|$1 dni}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 mesec|$1 meseca|$1 meseci|$1 mesecev}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 leto|$1 leti|$1 leta|$1 let}}",
+ "notification-timestamp-today": "Danes",
+ "notification-timestamp-yesterday": "Včeraj",
+ "notification-inbox-filter-read": "Prebrana",
+ "notification-inbox-filter-unread": "Neprebrana",
+ "notification-inbox-filter-all": "Vsa",
+ "echo-email-body-default": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} te čaka novo obvestilo:\n\n$1",
+ "echo-email-footer-default-html": "Prejemanje e-pošte si lahko nastaviš v <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">svojih nastavitvah</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nZa izbiro e-poštnih sporočil, ki jih želite prejemati, prilagodite svoje nastavitve:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Za izbiro e-poštnih sporočil, ki naj vam jih pošiljamo, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">preverite svoje nastavitve</a>.<br />\n$1",
+ "echo-email-plain-footer": "Za izbor vrst sporočil, ki jih {{GENDER:$1|prejemaš}}, preveri svoje nastavitve:",
+ "echo-email-html-footer-preference-link-text": "preveri {{GENDER:$1|svoje}} nastavitve",
+ "echo-email-html-footer-with-link": "Za določitev, katere vrste e-pošte naj {{GENDER:$2|ti}} pošiljamo, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Opomnik ($1)|Opomnika ($1)|Opomniki ($1)|Opomnikov ($1)|100=Opomniki (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Obvestilo ($1)|Obvestili ($1)|Obvestila ($1)|Obvestil ($1)|100=Obvestila (99+)}}",
+ "echo-notification-alert-text-only": "Opomniki",
+ "echo-notification-notice-text-only": "Obvestila",
"echo-overlay-link": "Vsa obvestila",
"echo-overlay-title": "<b>Obvestila</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Obvestila}}</b> ({{PLURAL:$1|prikazano|prikazani|prikazana|prikazanih}} $1 od $2 {{PLURAL:$2|neprebranega|neprebranih}})",
- "echo-mark-all-as-read": "Označi vsa sporočila kot prebrana",
+ "echo-mark-all-as-read": "Označi vsa sporočila za prebrana",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|obvestilo označeno za prebrano|obvestili označeni za prebrani|obvestila označena za prebrana|obvestil označenih za prebrane}}",
+ "echo-mark-wiki-as-read": "Označi vsa za prebrana v izbranem wikiju: $1",
"echo-date-today": "Danes",
"echo-date-yesterday": "Včeraj",
"echo-load-more-error": "Pri pridobivanju dodatnih rezultatov je prišlo do napake.",
- "notification-edit-talk-page-bundle": "$1 in $3 {{PLURAL:$4|drug|druga|drugih}} vam je na vaši [[User talk:$2|uporabniški strani]] {{GENDER:$1|pustilo}} sporočilo.",
- "notification-page-linked-bundle": "Stran »$2« je bila »{{GENDER:$1|povezan|povezana}}« s strani »$3« in $4 {{PLURAL:$5|druge strani|drugih strani}}. [[Special:WhatLinksHere/$2|Ogled vseh povezav na to stran]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 in $2 {{PLURAL:$3|drug|druga|drugih}} vam je na pogovorni strani {{GENDER:$1|pustilo}} sporočilo.",
- "notification-page-linked-email-batch-bundle-body": "Stran »$2« je bila {{GENDER:$1|povezan|povezana}} s strani »$3« in $4 {{PLURAL:$5|druge strani|drugih strani}}.",
- "echo-email-batch-subject-daily": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} imate {{PLURAL:$2|novo sporočilo|nova sporočila}}.",
- "echo-email-batch-subject-weekly": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} imate ta teden {{PLURAL:$2|eno novo sporočilo|nova sporočila}}.",
- "echo-email-batch-body-intro-daily": "Pozdravljeni, $1,\ntu je za vas povzetek današnje aktivnosti v {{GRAMMAR:dajalnik|{{SITENAME}}}}.",
- "echo-email-batch-body-intro-weekly": "Pozdravljeni, $1,\ntu je za vas povzetek aktivnosti preteklega tedna v {{GRAMMAR:dajalnik|{{SITENAME}}}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Eno novo sporočilo|$1 novi sporočili|$1 nova sporočila|$1 novih sporočil|100=99+ novih sporočil}} na <strong>{{GENDER:$3|tvoji}} pogovorni strani</strong>.",
+ "echo-email-batch-subject-daily": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} te {{PLURAL:$2|čaka novo sporočilo|čakata novi sporočili|čakajo nova sporočila}}.",
+ "echo-email-batch-subject-weekly": "V {{GRAMMAR:dajalnik|{{SITENAME}}}} te ta teden čaka {{PLURAL:$2|eno novo sporočilo|dve novi sporočili|nova sporočila}}.",
+ "echo-email-batch-body-intro-daily": "{{GENDER:|Pozdravljen|Pozdravljena}}, $1.\n\nTu je povzetek tvoje današnje dejavnosti v {{GRAMMAR:dajalnik|{{SITENAME}}}}.",
+ "echo-email-batch-body-intro-weekly": "{{GENDER:|Pozdravljen|Pozdravljena}}, $1.\n\nTu je povzetek tvojih dejavnosti v preteklem tednu v {{GRAMMAR:dajalnik|{{SITENAME}}}}.",
"echo-email-batch-link-text-view-all-notifications": "Ogled vseh obvestil",
- "echo-rev-deleted-text-view": "Ta redakcija strani je bila izbrisana."
+ "notification-header-foreign-alert": "Več opomnikov iz {{PLURAL:$5|drugega wikija|$5 drugih wikijev}}",
+ "notification-header-foreign-notice": "Več obvestil iz {{PLURAL:$5|drugega wikija|$5 drugih wikijev}}",
+ "notification-header-foreign-all": "Več obvestil iz {{PLURAL:$5|drugega wikija|$5 drugih wikijev}}"
}
diff --git a/Echo/i18n/so.json b/Echo/i18n/so.json
index 228a9464..3f6cc64b 100644
--- a/Echo/i18n/so.json
+++ b/Echo/i18n/so.json
@@ -4,36 +4,42 @@
"Abshirdheere"
]
},
- "prefs-echo": "Wargelinada",
+ "prefs-echo": "Wargelinnada",
+ "prefs-emailsettings": "Dooqyada e-mail-ka",
+ "prefs-echosubscriptions": "Iisoo dir arrimaha ku saabsan dhacdooyinkaan",
+ "prefs-echocrosswiki": "Wargelinno kuu tallabinaya wikiga",
+ "prefs-newmessageindicator": "Tusaha farriimaha cusub",
+ "echo-pref-email-frequency-never": "Waxba ha iiga soo dirin ku saabsan wargelinnada e-mailka",
+ "echo-pref-email-frequency-immediately": "Wargelinnada kalida ah ee marka ay soo dhacaan.",
+ "echo-pref-email-frequency-daily": "Dulmar maalmeed wargelineed",
+ "echo-pref-email-frequency-weekly": "Dulmar toddobaadle wargelinneed",
+ "echo-learn-more": "Ogaansho dheeraad ah",
"echo-new-messages": "Farriin cusub baa kuu taal",
- "notifications": "Wargelinada",
- "tooltip-pt-notifications": "Wargelinadaada",
+ "notifications": "Wargelinnada",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Baraarujin}} taada",
"echo-specialpage": "Wargelin",
+ "echo-specialpage-pagefilters-title": "Dhaqdhaqaaqyada cusub",
+ "echo-specialpage-pagefilters-subtitle": "Bogag leh wargelinno ee aan la aqrin",
"echo-none": "Malahan wax wargelin ah.",
"echo-more-info": "Dheeraad",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|kuugu reebay|kuugu reebtay}} farriin [[User talk:$2#$3|bogga wadahadalka]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] kuugu {{GENDER:$1|dhaafay|dhaaftay}} farriin boggada wadahadalka ee \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|kuu dhigay|kuu dhigtay}} farriin [[User talk:$2#$3|bogga wadahadalka]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|wuxuu kuugu dhaafay|waxay kuu dhaaftay}} farriin boggaada wadahadalka taasoo ah \"[[User talk:$2#$3|$4]]\".",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|xusid}} kugula sameeyey $5 bogaa wadahadalka ee \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|xusid}} kugula sameeyey $5 bogga wadahadalka \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|xusid}} kugula sameeyey [[:$3|$2 bogga wadahadalka]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|xusid}} kugula sameeyay [[:$3|$2 bogga wadahadalka]].",
- "notification-user-rights": "Xuquuqaha isticmaalahaada [[Special:Log/rights/$1|waa la {{GENDER:$1|bedelay}}]] waxaana bedelay [[User:$1|$1]]. $2. [[Special:ListGroupRights|wax dheeraad ah ka ogoow]]",
- "notification-user-rights-flyout": "Xuquuqda isticmaalahaada waa la {{GENDER:$1|bedelay}} waxaana bedelay $1. $2. [[Special:ListGroupRights|wax dheeraad ah ka sii ogoow]]",
- "notification-user-rights-add": "Hadda waxaad ka midtahay xubin ka mid ah {{PLURAL:$2|kooxdaan|kooxahaan}}: $1",
- "notification-new-user": "Ku soo dhowoow {{SITENAME}}, $1! Waan ku faraxsan-nahay inaad halkaan joogto.",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|ayaa kuugu dhaafay|ayaa kuugu dhaaftay}} farriin boggada wadahadalka:",
+ "echo-popup-footer-special-page-invitation": "<strong>Isku day bogga wargelinnada ee lagu soo celceliyo qaabaynteedda.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Dhammaan astaamaha iyo bandhigyada cusub.",
+ "echo-notification-placeholder": "Ma lahan wargelin.",
+ "echo-notification-placeholder-filters": "Ma jiraan wargelinno isleh ee xulshadaan kooban",
+ "notification-link-text-view-changes": "{{GENDER:$1|Itus}} isbedelka",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|kuugu dhaafay|kuugu dhaaftay}} farriin boggaada wadahadalka ee \"$2\".",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|xusid}} kugula sameeyey $4 bogga wadahadalka ee \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|xusid}} kugula sameeyey $2 bogga wadahadalka.",
- "notification-user-rights-email-batch-body": "Xuquuqda isticmaalahaada wax baa laga {{GENDER:$1|bedelay}} waxaana bedelay $1. $2.",
- "echo-overlay-link": "Dhammaan wargelinada",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 daqiiqo}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1bil}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1sano}}",
+ "notification-inbox-filter-read": "La aqriyay",
+ "notification-inbox-filter-unread": "Aan la aqrin",
+ "notification-inbox-filter-all": "Dhammaan",
+ "echo-notification-alert-text-only": "Baraarujin",
+ "echo-notification-notice-text-only": "Wargelinnada",
+ "echo-overlay-link": "Dhammaan wargelinnada",
"echo-overlay-title": "<b>Wargelinada</b>",
"echo-mark-all-as-read": "Ka dhig dhammaan wax la aqriyey",
"echo-date-today": "Maanta",
"echo-date-yesterday": "Shalay",
- "notification-edit-talk-page-bundle": "$1 iyo $3 {{PLURAL:$4|mid kale|kuwa kale}} {{GENDER:$1|kuugu daafay|kuugu dhaaftay}} farriin boggaada [[User talk:$2|wadahadalka]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 iyo $2 {{PLURAL:$3|mid kale|kuwa kale}} {{GENDER:$1|kuugu dhaafay|kuugu dhaaftay}} farriin boggada wadahadalka.",
"echo-email-batch-link-text-view-all-notifications": "Dhamaan eeg waegelinada"
}
diff --git a/Echo/i18n/sq.json b/Echo/i18n/sq.json
index 624376d8..1bbb78a4 100644
--- a/Echo/i18n/sq.json
+++ b/Echo/i18n/sq.json
@@ -2,12 +2,14 @@
"@metadata": {
"authors": [
"Euriditi",
- "Olsi"
+ "Olsi",
+ "Kosovastar",
+ "Liridon"
]
},
"echo-desc": "Sistemi i njoftimeve",
"prefs-echo": "Njoftimet",
- "prefs-emailsettings": "Opsionet e e-mailit",
+ "prefs-emailsettings": "Opsionet e emailit",
"prefs-displaynotifications": "Shfaq opsionet",
"prefs-echosubscriptions": "Më njofto për këto raste",
"prefs-newmessageindicator": "Brezi i mesazhit të ri",
@@ -35,11 +37,9 @@
"echo-pref-tooltip-article-linked": "Më njofto kur dikush lidh, një faqe, me një faqe që kam krijuar unë.",
"echo-pref-tooltip-reverted": "Më njofto kur dikush kthen një ndryshim që kam bërë unë, duke përdorur funksionet zhbëj ose riktheje.",
"echo-pref-tooltip-mention": "Më njofto kur dikush lidh faqen time të përdoruesit me cilëndo faqe diskutimi.",
- "echo-no-agent": "[Asnjeri]",
- "echo-no-title": "[Asnjë faqe]",
"echo-error-no-formatter": "Asnjë përcaktim mbi formatimimin e njoftimeve.",
"notifications": "Njoftimet",
- "tooltip-pt-notifications-alert": "Njoftimet tuaja",
+ "tooltip-pt-notifications-alert": "Njoftimet e tua",
"echo-specialpage": "Njoftimet",
"echo-anon": "Për të marrë njoftime, [$1 regjistrohuni] ose [$2 hyni].",
"echo-none": "Nuk keni njoftime.",
@@ -49,42 +49,17 @@
"notification-link-text-view-mention": "Shiko përmëndjen",
"notification-link-text-view-changes": "Shiko ndryshimet",
"notification-link-text-view-page": "Shiko faqen",
+ "notification-header-welcome": "{{GENDER:$2|Mirë se erdhët}} në {{SITENAME}}, $1! Jemi të lumtur që {{GENDER:$2|ju}} kemi këtu.",
"notification-link-text-view-edit": "Shiko redaktimin",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|iu la}} një mesazh në [[User talk:$2#$3|faqen tuaj të diskutimeve]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|iu la}} një mesazh në faqen tuaj të diskutimeve në seksionin '[[User talk:$2#$3|$4]]'.",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|iu la}} një mesazh në [[User talk:$2#$3|faqen tuaj të diskutimeve]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|iu la}} një mesazh në faqen tuaj të diskutimeve në seksionin '[[User talk:$2#$3|$4]]'.",
- "notification-page-linked": "[[:$2]] u {{GENDER:$1|lidh}} nga [[:$3]]. [[Special:WhatLinksHere/$2|Shiko të gjitha lidhjet me këtë faqe]].",
- "notification-page-linked-flyout": "[[:$2]] u {{GENDER:$1|lidh}} nga [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|la një koment}} në lidhje me \"[[$3|$2]]\" në faqen e diskutimeve të \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|postoi}} një temë të re \"$2\" në [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] të {{GENDER:$1|dërgoi}} një mesazh: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|la një koment}} në lidhje me \"[[$3#$2|$2]]\" në faqen tuaj të diskutimeve.",
- "notification-mention": "[[User:$1|$1]] iu {{GENDER:$1|përmëndi}} në faqen e diskutimeve $5 në '[[:$3#$2|$4]]'.",
- "notification-mention-flyout": "$1 iu {{GENDER:$1|përmëndi}} në faqen e diskutimeve $5 në '[[:$3#$2|$4]]'.",
- "notification-user-rights": "Të drejtat e tua të përdoruesit [[Special:Log/rights/$1|u {{GENDER:$1|ndryshuan}}]] nga [[User:$1|$1]]. $2. [[Special:ListGroupRights|Mëso më tepër]]",
- "notification-user-rights-flyout": "Të drejtat e tua të përdoruesit u {{GENDER:$1|ndryshuan}} nga $1. $2. [[Special:ListGroupRights|Më tepër informacion]]",
- "notification-user-rights-add": "Tashmë je anëtar i {{PLURAL:$2|këtij grupi|këtyre grupeve}}: $1",
- "notification-user-rights-remove": "Ju nuk jeni më anëtar i {{PLURAL:$2|këtij grupi|këtyre grupeve}}: $1",
- "notification-new-user": "Mirësevini në {{SITENAME}}, $1! Jemi të lumtur që ti je këtu.",
- "notification-reverted2": "{{PLURAL:$4|Redaktimi juaj|Redaktimet e tua}} në [[:$2]] {{PLURAL:$4|u kthye|u kthyen}} {{GENDER:$1|nga}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Redaktimi juaj|Redaktimet e tua}} në $2 {{PLURAL:$4|u kthye|u kthyen}} {{GENDER:$1|nga}} $1. $3",
+ "notification-header-reverted": "{{PLURAL:$4|Redaktimi i juaj|Redaktimet e tua}} në $3 {{PLURAL:$4|u kthye|u kthyen}} {{GENDER:$2|nga}} $1.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|iu la}} një mesazh në {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|iu la}} një mesazh në faqen tuaj të diskutimeve:",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|iu la}} një mesazh në faqen tuaj të diskutimeve në \"$2\".",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|të la}} një mesazh në faqen tënde të diskutimeve në \"$2\".",
"notification-page-linked-email-subject": "Një faqe që keni krijuar u lidh në {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 u {{GENDER:$1|lidh}} nga $3",
"notification-reverted-email-subject2": "{{PLURAL:$3|Redaktimi juaj|Redaktimet tuaja}} {{GENDER:$1|u kthyen}} në {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Redaktimi juaj|Redaktimet e tua}} në $2 {{PLURAL:$3|u kthye|u kthyen}} {{GENDER:$1|nga}} $1",
"notification-mention-email-subject": "$1 të {{GENDER:$1|përmëndi}} në {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 të {{GENDER:$1|përmëndi}} në faqen e diskutimeve të $4 në seksionin '$3'.",
"notification-user-rights-email-subject": "Të drejtat e tua të përdoruesit u ndryshuan në {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Të drejtat e tua të përdoruesit u {{GENDER:$1|ndyshuan}} nga $1. $2",
- "echo-email-subject-default": "Njoftim i ri në {{SITENAME}}",
"echo-email-body-default": "Keni një njoftim të ri në {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Keni një njoftim të ri.",
"echo-email-footer-default": "$2\n\nPër të kontrolluar se cili email do t'iu dërgohet, kontrolloni parapëlqimet tuaja:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Për të kontrolluar se cili email do t'iu dërgohet, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">kontrolloni parapëlqimet tuaja</a>.<br />\n$1",
"echo-overlay-link": "Të gjitha njoftimet",
"echo-overlay-title": "<b>Njoftimet</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Njoftime}}</b> (duke shfaqur $1 nga $2 të pa lexuara)",
@@ -92,14 +67,9 @@
"echo-date-today": "Sot",
"echo-date-yesterday": "Dje",
"echo-load-more-error": "Pati një gabim në ngarkimin e rezultateve shtesë.",
- "notification-edit-talk-page-bundle": "$1 dhe {{PLURAL:$4|një përdorues tjetër|$3 përdorues të tjerë}} {{GENDER:$1|iu lanë}} një mesazh në [[User talk:$2|faqen tuaj të diskutimeve]].",
- "notification-page-linked-bundle": "$2 u {{GENDER:$1|lidh}} nga $3 dhe {{PLURAL:$5|një faqe tjetër|$4 faqe të tjera}}. [[Special:WhatLinksHere/$2|Shfaq të gjitha lidhjet me këtë faqe]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 dhe {{PLURAL:$3|një tjetër|$2 të tjerë}} {{GENDER:$1|lanë}} një mesazh në faqen tuaj të diskutimeve",
- "notification-page-linked-email-batch-bundle-body": "$2 u {{GENDER:$1|lidh}} nga $3 dhe {{PLURAL:$5|një tjetër faqe|$4 faqe të tjera}}",
"echo-email-batch-subject-daily": "Keni {{PLURAL:$2|një njoftim të ri|njoftime të reja}} në {{SITENAME}}",
"echo-email-batch-subject-weekly": "Keni {{PLURAL:$2|një njoftim të ri|njoftime të reja}} në {{SITENAME}} gjatë kësaj jave.",
"echo-email-batch-body-intro-daily": "Përshëndetje $1,\nkëtu është përmbledhja e aktivitetit të sotëm në {{SITENAME}} për ju.",
"echo-email-batch-body-intro-weekly": "Përshëndetje $1,\nkëtu është përmbledhja e aktivitetit javor në {{SITENAME}} për ju.",
- "echo-email-batch-link-text-view-all-notifications": "Shfaq të gjitha njoftimet",
- "echo-rev-deleted-text-view": "Ky version i faqes është fshirë."
+ "echo-email-batch-link-text-view-all-notifications": "Shfaq të gjitha njoftimet"
}
diff --git a/Echo/i18n/sr-ec.json b/Echo/i18n/sr-ec.json
index 1a8bfc54..00de9048 100644
--- a/Echo/i18n/sr-ec.json
+++ b/Echo/i18n/sr-ec.json
@@ -3,115 +3,162 @@
"authors": [
"Milicevic01",
"Rancher",
- "Михајло Анђелковић"
+ "Михајло Анђелковић",
+ "Сербијана",
+ "Macofe",
+ "Srdjan m",
+ "Dungodung",
+ "Obsuser"
]
},
"echo-desc": "Систем за обавештавање корисника о дешавањима и порукама",
"prefs-echo": "Обавештења",
- "prefs-emailsettings": "Поставке е-поште",
+ "prefs-emailsettings": "Поставке имејла",
"prefs-displaynotifications": "Поставке приказа",
- "prefs-echosubscriptions": "Обавести ме о следећим догађајима.",
+ "prefs-echosubscriptions": "Обавести ме о овим догађајима",
+ "prefs-echocrosswiki": "Међувики обавештења",
"prefs-newmessageindicator": "Индикатор за нове поруке",
+ "prefs-blocknotificationslist": "Игнорисани корисници",
"echo-pref-send-me": "Пошаљи ми:",
"echo-pref-send-to": "Пошаљи на:",
- "echo-pref-email-format": "Формат е-поште:",
+ "echo-pref-email-format": "Формат имејла:",
"echo-pref-web": "Веб",
- "echo-pref-email": "На е-пошту",
- "echo-pref-email-frequency-never": "Не шаљи ми обавештења на е-пошту",
+ "echo-pref-email": "Имејл",
+ "echo-pref-email-frequency-never": "Не шаљи ми обавештења на имејл",
"echo-pref-email-frequency-immediately": "Појединачна обавештења чим се појаве",
"echo-pref-email-frequency-daily": "Дневни сажетак обавештења",
"echo-pref-email-frequency-weekly": "Седмични сажетак обавештења",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Чист текст",
+ "echo-pref-cross-wiki-notifications": "Прикажи обавештења са других викија",
+ "echo-pref-notifications-blacklist": "Не приказуј обавештења од ових корисника. ([[mw:Help:Notifications#mute|сазнај више]])",
"echo-pref-new-message-indicator": "Прикажи индикатор када добијем поруку на страници за разговор",
"echo-learn-more": "Сазнајте више",
+ "echo-log": "Дневници",
"echo-new-messages": "Имате нове поруке",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Поруке}} на страници за разговор",
"echo-category-title-article-linked": "{{PLURAL:$1|Повезивање страница}}",
"echo-category-title-reverted": "Поништене {{PLURAL:$1|измене}}",
"echo-category-title-mention": "{{PLURAL:$1|Спомињања}}",
+ "echo-category-title-mention-failure": "Неуспешна {{PLURAL:$1|спомињања}}",
+ "echo-category-title-mention-success": "Успешна {{PLURAL:$1|спомињања}}",
"echo-category-title-other": "{{PLURAL:$1|Остало}}",
"echo-category-title-system": "{{PLURAL:$1|Систем}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Промена корисничких права}}",
- "echo-pref-tooltip-edit-user-talk": "Обавештава вас када неко остави поруку на вашој страници за разговор.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Имејлови од других корисника}}",
+ "echo-pref-tooltip-edit-user-talk": "Обавештава вас када неко остави поруку или реплицира на вашој страници за разговор.",
"echo-pref-tooltip-article-linked": "Обавештава вас када неко повеже чланак који сте ви направили са неком другом страницом.",
- "echo-pref-tooltip-reverted": "Обавештава вас када неко поништи измену коју сте ви начинили.",
+ "echo-pref-tooltip-reverted": "Обавештава вас када неко поништи измену коју сте направили, било коришћењем опције поништи или опције за враћање.",
"echo-pref-tooltip-mention": "Обавештава вас кад вас неко спомене.",
+ "echo-pref-tooltip-mention-failure": "Обавештава вас када неко не добије обавештење након што га споменете.",
+ "echo-pref-tooltip-mention-success": "Обавештава вас када неко добије обавештење након што га споменете.",
"echo-pref-tooltip-user-rights": "Обавештава вас када неко промени ваша корисничка права.",
- "echo-no-agent": "[Нико]",
- "echo-no-title": "[Нема странице]",
+ "echo-pref-tooltip-emailuser": "Обавештава вас када вам неко пошаље имејл.",
"echo-error-no-formatter": "Није задато обликовање за обавештења",
"notifications": "Обавештења",
"tooltip-pt-notifications-alert": "{{GENDER:|Ваша}} обавештења",
- "tooltip-pt-notifications-message": "{{GENDER:|Ваше}} поруке",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Ваша}} обавештења",
"echo-specialpage": "Обавештења",
+ "echo-specialpage-section-markread": "Означи групу као прочитану",
+ "echo-specialpage-pagination-numnotifications": "{{PLURAL:$1|Обавештења}}: $1",
+ "echo-specialpage-pagefilters-title": "Скорашње активности",
+ "echo-specialpage-pagefilters-subtitle": "Странице с непрочитаним обавештењима",
+ "notificationsmarkread-legend": "Означи обавештење прочитаним",
"echo-anon": "Да бисте приступили овој страници морате се [$2 пријавити] или [$1 отворити налог].",
"echo-none": "Немате обавештења",
"echo-more-info": "Више информација",
"echo-feedback": "Повратне информације",
+ "echo-api-failure": "Добављање обавештења није успело.",
+ "echo-notification-placeholder": "Немате обавештења.",
+ "echo-notification-placeholder-filters": "Нема обавештења по задатим критеријумима.",
+ "echo-notification-loginrequired": "Морате се пријавити да би видели обавештења.",
+ "echo-notification-popup-loginrequired": "Пријавите се да видите Ваша обавештења.",
+ "echo-notification-markasread": "Означи као прочитано",
+ "echo-notification-markasunread": "Означи као непрочитано",
+ "echo-notification-markasread-tooltip": "Означи као прочитано",
+ "echo-notification-more-options-tooltip": "Више опција",
+ "notification-link-text-expand-all": "Прошири",
+ "notification-link-text-expand-alert-count": "Прикажи {{PLURAL:$1|обавештења}} ($1)",
+ "notification-link-text-expand-all-count": "Прикажи {{PLURAL:$1|обавештења}} ($1)",
+ "notification-link-text-collapse-all": "Сакриј све",
"notification-link-text-view-message": "Погледај поруку",
- "notification-link-text-view-mention": "Види спомињање",
- "notification-link-text-view-changes": "Погледај измене",
+ "notification-link-text-view-mention": "Види помињање",
+ "notification-link-text-view-changes": "{{GENDER:$1|Погледај}} измене",
"notification-link-text-view-page": "Погледај страницу",
+ "notification-header-edit-user-talk": "$1 Вам је {{GENDER:$2|оставио|оставила}} поруку {{GENDER:$3|на}} <strong>Вашој страници за разговор</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 Вам је {{GENDER:$2|оставио|оставила}} поруку на <strong>{{GENDER:$3|Вашој}} страници за разговор</strong> у „<strong>$4</strong>“.",
+ "notification-header-page-linked": "Страница <strong>$3</strong> је повезана са <strong>$4</strong>.",
+ "notification-compact-header-page-linked": "Повезана са <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Направљене су везе до <strong>$3</strong> са {{PLURAL:$5||$5 странице|$5 страница|100=>&thinsp;99 страница}}.",
+ "notification-link-text-what-links-here": "Све везе ка овој страници",
+ "notification-header-mention-other": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$3|на}} <strong>$4</strong> у „<strong>$5</strong>“.",
+ "notification-header-mention-other-nosection": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$3|на}} <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$3|на}} <strong>страници за разговор {{GENDER:$5|корисника|кориснице}} $4</strong> у „<strong>$6</strong>“.",
+ "notification-header-mention-user-talkpage-nosection": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$3|на}} <strong>страници за разговор {{GENDER:$5|корисника|кориснице}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$3|на}} <strong>својој страници за разговор</strong> у „<strong>$4</strong>“.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$3|на}} <strong>својој страници за разговор</strong>.",
+ "notification-header-mention-article-talkpage": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$3|на}} страници за разговор <strong>$4</strong> у „<strong>$5</strong>“.",
+ "notification-header-mention-article-talkpage-nosection": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$3|на}} страници за разговор <strong>$4</strong>.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Покушали сте}} да поменете више од $3 {{PLURAL:$3|корисника}}. Сва помињања изнад лимита нису послата.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Корисничко име не постоји:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Не можете спомињати ИП адресе:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Ваше}} спомињање {{GENDER:$3|корисника|кориснице|корисника}} <strong>$3</strong> је послато.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Споменули сте}}:</strong> $3",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Ваша}} корисничка права су {{GENDER:$1|промењена}}. Сада сте члан следећих група: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Ваша}} корисничка права су {{GENDER:$1|промењена}}. Више нисте члан следећих група: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Ваша}} корисничка права су {{GENDER:$1|промењена}}. Додати сте у $2 а уклоњени из $4.",
+ "notification-header-user-rights-expiry-change": "Истек {{GENDER:$4|Вашег}} чланства у {{PLURAL:$3|следећој групи|следећим групама}} је {{GENDER:$1|промењен}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Добро дошли}} на {{SITENAME}}, $1! Драго нам {{GENDER:$2|је}} што сте овде.",
+ "notification-welcome-linktext": "Добро дошли",
+ "notification-header-thank-you-1-edit": "Управо {{GENDER:$2|сте}} направили прву измену, хвала {{GENDER:$2|Вам}} и добро дошли!",
+ "notification-header-thank-you-10-edit": "Управо {{GENDER:$2|сте}} направили {{GENDER:$2|своју}} десету измену; хвала {{GENDER:$2|Вам}} и само тако наставите!",
+ "notification-header-thank-you-100-edit": "Управо {{GENDER:$2|сте}} направили {{GENDER:$2|своју}} стоту измену; пуно {{GENDER:$2|Вам}} хвала!",
+ "notification-header-thank-you-1000-edit": "Управо {{GENDER:$2|сте}} направили хиљадиту измену; хвала {{GENDER:$2|Вам}} на фантастичном доприносу!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Ваша}} измена",
"notification-link-text-view-edit": "Погледај измену",
- "notification-edit-talk-page2": "[[User:$1|$1]] вам је {{GENDER:$1|оставио|оставила}} поруку на вашој [[User talk:$2#$3|страници за разговор]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] вам је {{GENDER:$1|оставио|оставила}} поруку на вашој страници за разговор у „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "$1 вам је {{GENDER:$1|оставио|оставила}} поруку на вашој [[User talk:$2#$3|страници за разговор]].",
- "notification-edit-talk-page-flyout-with-section": "$1 вам је {{GENDER:$1|оставио|оставила}} поруку на вашој страници за разговор у „[[User talk:$2#$3|$4]]“.",
- "notification-page-linked": "Страница [[:$2]] је {{GENDER:$1|повезана}} са страницом [[:$3]]. [[Special:WhatLinksHere/$2|Погледајте све везе према овој страници]].",
- "notification-page-linked-flyout": "[[:$2]] је {{GENDER:$1|повезана}} са [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] је {{GENDER:$1|прокоментарисао|прокоментарисала}} тему „[[$3|$2]]“ на страници за разговор „$4“.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] је {{GENDER:$1|поставио|поставила}} нову тему „$2“ на [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] вам је {{GENDER:$1|послао|послала}} поруку: „[[$3#$2|$2]]“.",
- "notification-add-comment-yours2": "[[User:$1|$1]] је {{GENDER:$1|прокоментарисао|прокоментарисала}} тему „[[$3#$2|$2]]“ на вашој страници за разговор.",
- "notification-mention": "[[User:$1|$1]] вас је {{GENDER:$1|спомену|споменула}} на страници за разговор $5 у „[[:$3#$2|$4]]“.",
- "notification-mention-flyout": "$1 вас је {{GENDER:$1|споменуо|споменула}} на страници за разговор $5 у „[[:$3#$2|$4]]“.",
- "notification-mention-nosection": "[[User:$1|$1]] вас је {{GENDER:$1|споменуо|споменула}} на [[:$3|страници за разговор $2]].",
- "notification-mention-nosection-flyout": "$1 вас је {{GENDER:$1|споменуо|споменула}} на [[:$3|страници за разговор $2]].",
- "notification-user-rights": "[[User:$1|$1]] је [[Special:Log/rights/$1|{{GENDER:$1|променио|променила}}]] ваша корисничка права. $2. [[Special:ListGroupRights|Сазнајте више]]",
- "notification-user-rights-flyout": "$1 је {{GENDER:$1|променио|променила}} ваша корисничка права. $2. [[Special:ListGroupRights|Сазнајте више]]",
- "notification-user-rights-add": "Од сада сте члан {{PLURAL:$2|следеће групе|следећих група}}: $1",
- "notification-user-rights-remove": "Више нисте члан {{PLURAL:$2|следеће групе|следећих група}}: $1",
- "notification-new-user": "$1, добро дошли на пројекат {{SITENAME}}! Драго нам је што сте овде.",
- "notification-reverted2": "{{PLURAL:$4|Ваша измена на страници [[:$2]] је поништена|Ваше измене на страници [[:$2]] су поништене}} од стране {{GENDER:$1|корисника|кориснице}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Ваша измена на страници $2 је поништена|Ваше измене на страници $2 су поништене}} од стране {{GENDER:$1|корисника|кориснице}} $1. $3",
- "notification-edit-talk-page-email-subject2": "$1 вам је {{GENDER:$1|оставио|оставила}} поруку на пројекту {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 вам је {{GENDER:$1|оставио|оставила}} поруку на вашој страници за разговор.",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 вам је {{GENDER:$1|оставио|оставила}} поруку на вашој страници за разговор у „$2“.",
+ "notification-header-reverted": "{{PLURAL:$4|Ваша измена на страници <strong>$3</strong> је поништена|Ваше измене на {{GENDER:$2|страници}} <strong>$3</strong> су поништене}}.",
+ "notification-header-emailuser": "$1 Вам је {{GENDER:$2|послао|послала}} имејл.",
+ "notification-edit-talk-page-email-subject2": "$1 Вам је {{GENDER:$1|оставио|оставила}} поруку на пројекту {{SITENAME}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 Вам је {{GENDER:$1|оставио|оставила}} поруку на Вашој страници за разговор у „$2“.",
"notification-page-linked-email-subject": "Ваша страница је повезана на пројекту {{SITENAME}}",
- "notification-page-linked-email-batch-body": "Страница $2 је {{GENDER:$1|повезана}} са $3.",
"notification-reverted-email-subject2": "{{GENDER:$1|{{PLURAL:$3|Ваша измена је поништена|Ваше измене су поништене}}}} на пројекту {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Ваша измена на страници $2 је поништена|Ваше измене на страници $2 су поништене}} од стране {{GENDER:$1|корисника|кориснице}} $1.",
- "notification-mention-email-subject": "$1 вас је {{GENDER:$1|споменуо|споменула}} на {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 вас је {{GENDER:$1|споменуо|споменула}} на страници за разговор $4 у „$3“.",
- "notification-mention-nosection-email-batch-body": "$1 вас је {{GENDER:$1|споменуо|споменула}} на страници за разговор $2.",
+ "notification-mention-email-subject": "$1 Вас је {{GENDER:$1|поменуо|поменула}} {{GENDER:$2|на}} {{SITENAME}}",
"notification-user-rights-email-subject": "Ваша корисничка права на пројекту {{SITENAME}} су промењена.",
- "notification-user-rights-email-batch-body": "$1 је {{GENDER:$1|променио|променила}} ваша корисничка права. $2.",
- "echo-email-subject-default": "Ново обавештење на {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 сек.}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 мин.}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 д.}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 мес.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 год.}}",
+ "notification-timestamp-today": "Данас",
+ "notification-timestamp-yesterday": "Јуче",
+ "notification-inbox-filter-read": "Прочитано",
+ "notification-inbox-filter-unread": "Непрочитано",
+ "notification-inbox-filter-all": "Све",
"echo-email-body-default": "Имате ново обавештење на пројекту {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Имате ново обавештење.",
- "echo-email-footer-default": "$2\n\nДа бисте променили које поруке примате од нас идите у подешавања:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-email-footer-default-html": "Да бисте променили које поруке примате од нас идите у <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">подешавања</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nДа бисте променили које поруке примате од нас идите у подешавања:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Да бисте променили које поруке примате {{GENDER:$1|од}} нас идите у подешавања.",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|Ваша}} подешавања",
+ "echo-email-html-footer-with-link": "Да бисте променили које поруке примате {{GENDER:$2|од}} нас идите у $1.",
"echo-notification-alert": "{{PLURAL:$1|Обавештење ($1)|Обавештања ($1)|100=Обавештања (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Порука ($1)|Поруке ($1)|100=Поруке (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Обавештење ($1)|Обавештења ($1)|100=Обавештења (99+)}}",
"echo-notification-alert-text-only": "Обавештења",
- "echo-notification-message-text-only": "Поруке",
+ "echo-notification-notice-text-only": "Обавештења",
"echo-overlay-link": "Сва обавештења",
"echo-overlay-title": "<b>Обавештења</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Обавештења}}</b> (приказ $1 од $2 непрочитаних)",
"echo-mark-all-as-read": "Означи све прочитаним",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|1=обавештење|обавештења}} као прочитано",
+ "echo-mark-wiki-as-read": "Означи све као прочитано у изабраном викију: $1",
"echo-date-today": "Данас",
"echo-date-yesterday": "Јуче",
"echo-load-more-error": "Дошло је до грешке при добављању више резултата.",
- "notification-edit-talk-page-bundle": "$1 и још $3 {{PLURAL:$4|корисник|корисника}} {{GENDER:$1|оставили}} су поруке на вашој [[User talk:$2|страници за разговор]].",
- "notification-page-linked-bundle": "Страница $2 је {{GENDER:$1|повезана}} са $3 и $4 {{PLURAL:$5|друге странице|других страница}}. [[Special:WhatLinksHere/$2|Погледајте све везе према овој страници]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 и још $2 {{PLURAL:$3|1=један корисник|корисника}} {{GENDER:$1|оставили}} су поруке на вашој страници за разговор.",
- "notification-page-linked-email-batch-bundle-body": "Страница $2 је {{GENDER:$1|повезана}} са $3 и $4 {{PLURAL:$5|друге странице|других страница}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Једна нова порука|$1 нове поруке|$1 нових порука|100=≥100 нових порука}} на <strong>{{GENDER:$3|Вашој}} страници за разговор</strong>.",
"echo-email-batch-subject-daily": "Имате {{PLURAL:$2|ново обавештење|нова обавештења}} на пројекту {{SITENAME}}",
"echo-email-batch-subject-weekly": "Имате {{PLURAL:$2|ново обавештење|нова обавештења}} на пројекту {{SITENAME}} ове седмице",
"echo-email-batch-body-intro-daily": "Здраво $1,\nОво је дневни сажетак данашњих активности на пројекту {{SITENAME}} за вас.",
"echo-email-batch-body-intro-weekly": "Здраво $1,\nОво је недељни сажетак активности на пројекту {{SITENAME}} за вас.",
"echo-email-batch-link-text-view-all-notifications": "Погледај сва обавештења",
- "echo-rev-deleted-text-view": "Ова ревизија странице је потиснута.",
- "apihelp-echomarkread-example-2": "Означи сва обавештења прочитаним"
+ "notification-header-foreign-notice": "Још обавештења са {{PLURAL:$5|другог викија|$5 друга викија|$5 других викија}}"
}
diff --git a/Echo/i18n/sr-el.json b/Echo/i18n/sr-el.json
index 04b63dde..2b693ecc 100644
--- a/Echo/i18n/sr-el.json
+++ b/Echo/i18n/sr-el.json
@@ -2,26 +2,33 @@
"@metadata": {
"authors": [
"Milicevic01",
- "Srdjan m"
+ "Srdjan m",
+ "Macofe",
+ "Сербијана",
+ "Obsuser"
]
},
"echo-desc": "Sistem za obaveštavanje korisnika o dešavanjima i porukama",
"prefs-echo": "Obaveštenja",
- "prefs-emailsettings": "Postavke e-pošte",
+ "prefs-emailsettings": "Postavke imejla",
"prefs-displaynotifications": "Postavke prikaza",
- "prefs-echosubscriptions": "Obavesti me o sledećim događajima.",
+ "prefs-echosubscriptions": "Obavesti me o ovim događajima",
+ "prefs-echocrosswiki": "Međuviki obaveštenja",
"prefs-newmessageindicator": "Indikator za nove poruke",
+ "prefs-blocknotificationslist": "Ignorisani korisnici",
"echo-pref-send-me": "Pošalji mi:",
"echo-pref-send-to": "Pošalji na:",
- "echo-pref-email-format": "Format e-pošte:",
+ "echo-pref-email-format": "Format imejla:",
"echo-pref-web": "Veb",
- "echo-pref-email": "Na e-poštu",
- "echo-pref-email-frequency-never": "Ne šalji mi obaveštenja na e-poštu",
+ "echo-pref-email": "Imejl",
+ "echo-pref-email-frequency-never": "Ne šalji mi obaveštenja na imejl",
"echo-pref-email-frequency-immediately": "Pojedinačna obaveštenja čim se pojave",
"echo-pref-email-frequency-daily": "Dnevni sažetak obaveštenja",
"echo-pref-email-frequency-weekly": "Sedmični sažetak obaveštenja",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Čist tekst",
+ "echo-pref-cross-wiki-notifications": "Prikaži obaveštenja sa drugih vikija",
+ "echo-pref-notifications-blacklist": "Ne prikazuj obaveštenja od ovih korisnika. ([[mw:Help:Notifications#mute|saznaj više]])",
"echo-pref-new-message-indicator": "Prikaži indikator kada dobijem poruku na stranici za razgovor",
"echo-learn-more": "Saznajte više",
"echo-new-messages": "Imate nove poruke",
@@ -29,72 +36,75 @@
"echo-category-title-article-linked": "{{PLURAL:$1|Povezivanje stranica}}",
"echo-category-title-reverted": "Poništene {{PLURAL:$1|izmene}}",
"echo-category-title-mention": "{{PLURAL:$1|Spominjanja}}",
+ "echo-category-title-mention-failure": "Neuspešna {{PLURAL:$1|spominjanja}}",
+ "echo-category-title-mention-success": "Uspešna {{PLURAL:$1|spominjanja}}",
"echo-category-title-other": "{{PLURAL:$1|Ostalo}}",
"echo-category-title-system": "{{PLURAL:$1|Sistem}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Promena korisničkih prava}}",
- "echo-pref-tooltip-edit-user-talk": "Obaveštava vas kada neko ostavi poruku na vašoj stranici za razgovor.",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Imejlovi od drugih korisnika}}",
+ "echo-pref-tooltip-edit-user-talk": "Obaveštava vas kada neko ostavi poruku ili replicira na vašoj stranici za razgovor.",
"echo-pref-tooltip-article-linked": "Obaveštava vas kada neko poveže članak koji ste vi napravili sa nekom drugom stranicom.",
- "echo-pref-tooltip-reverted": "Obaveštava vas kada neko poništi izmenu koju ste vi načinili.",
+ "echo-pref-tooltip-reverted": "Obaveštava vas kada neko poništi izmenu koju ste napravili, bilo korišćenjem opcije poništi ili opcije za vraćanje.",
"echo-pref-tooltip-mention": "Obaveštava vas kad vas neko spomene.",
+ "echo-pref-tooltip-mention-failure": "Obaveštava vas kada neko ne dobije obaveštenje nakon što ga spomenete.",
+ "echo-pref-tooltip-mention-success": "Obaveštava vas kada neko dobije obaveštenje nakon što ga spomenete.",
"echo-pref-tooltip-user-rights": "Obaveštava vas kada neko promeni vaša korisnička prava.",
- "echo-no-agent": "[Niko]",
- "echo-no-title": "[Nema stranice]",
+ "echo-pref-tooltip-emailuser": "Obaveštava vas kada vam neko pošalje imejl.",
"echo-error-no-formatter": "Nije zadato oblikovanje za obaveštenja",
"notifications": "Obaveštenja",
"tooltip-pt-notifications-alert": "{{GENDER:|Vaša}} obaveštenja",
- "tooltip-pt-notifications-message": "{{GENDER:|Vaše}} poruke",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Vaša}} obaveštenja",
"echo-specialpage": "Obaveštenja",
"echo-anon": "Da biste pristupili ovoj stranici morate se [$2 prijaviti] ili [$1 otvoriti nalog].",
"echo-none": "Nemate obaveštenja",
"echo-more-info": "Više informacija",
"echo-feedback": "Povratne informacije",
+ "echo-api-failure": "Dobavljanje obaveštenja nije uspelo.",
+ "echo-notification-placeholder": "Nemate obaveštenja.",
+ "echo-notification-loginrequired": "Morate se prijaviti da bi videli obaveštenja.",
+ "echo-notification-popup-loginrequired": "Prijavite se da vidite Vaša obaveštenja.",
+ "notification-link-text-expand-all": "Prikaži sve",
+ "notification-link-text-expand-alert-count": "Prikaži {{PLURAL:$1|obaveštenja}} ($1)",
+ "notification-link-text-collapse-all": "Sakrij sve",
"notification-link-text-view-message": "Pogledaj poruku",
"notification-link-text-view-mention": "Vidi spominjanje",
- "notification-link-text-view-changes": "Pogledaj izmene",
+ "notification-link-text-view-changes": "{{GENDER:$1|Pogledaj}} izmene",
"notification-link-text-view-page": "Pogledaj stranicu",
+ "notification-header-edit-user-talk": "$1 Vam je {{GENDER:$2|ostavio|ostavila}} poruku {{GENDER:$3|na}} <strong>Vašoj stranici za razgovor</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 Vam je {{GENDER:$2|ostavio|ostavila}} poruku na <strong>{{GENDER:$3|Vašoj}} stranici za razgovor</strong> u „<strong>$4</strong>“.",
+ "notification-header-page-linked": "Stranica <strong>$3</strong> je povezana sa <strong>$4</strong>.",
+ "notification-bundle-header-page-linked": "Stranica '''$3''' je povezana sa '''$4''' i još $5 {{PLURAL:$6|1=stranicom|stranice|stranica}}.",
+ "notification-link-text-what-links-here": "Sve veze ka ovoj stranici",
+ "notification-header-mention-other": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$3|na}} <strong>$4</strong> u „<strong>$5</strong>“.",
+ "notification-header-mention-other-nosection": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$3|na}} <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$3|na}} <strong>stranici za razgovor {{GENDER:$5|korisnika|korisnice}} $4</strong> u „<strong>$6</strong>“.",
+ "notification-header-mention-user-talkpage-nosection": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$3|na}} <strong>stranici za razgovor {{GENDER:$5|korisnika|korisnice}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$3|na}} <strong>svojoj stranici za razgovor</strong> u „<strong>$4</strong>“.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$3|na}} <strong>svojoj stranici za razgovor</strong>.",
+ "notification-header-mention-article-talkpage": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$3|na}} stranici za razgovor <strong>$4</strong> u „<strong>$5</strong>“.",
+ "notification-header-mention-article-talkpage-nosection": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$3|na}} stranici za razgovor <strong>$4</strong>.",
+ "notification-header-mention-success": "{{GENDER:$2|Vaše}} spominjanje {{GENDER:$3|korisnika|korisnice|korisnika}} <strong>$3</strong> je poslato.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Vaša}} korisnička prava su {{GENDER:$1|promenjena}}. Više niste član sledećih grupa: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Dobro došli}} na {{SITENAME}}, $1! Drago nam {{GENDER:$2|je}} što ste ovde.",
+ "notification-welcome-linktext": "Dobro došli",
+ "notification-header-thank-you-1-edit": "Upravo {{GENDER:$2|ste}} napravili prvu izmenu, hvala {{GENDER:$2|Vam}} i dobro došli!",
"notification-link-text-view-edit": "Pogledaj izmenu",
- "notification-edit-talk-page2": "[[User:$1|$1]] vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj [[User talk:$2#$3|stranici za razgovor]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u „[[User talk:$2#$3|$4]]“.",
- "notification-edit-talk-page-flyout2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj [[User talk:$2#$3|stranici za razgovor]].",
- "notification-edit-talk-page-flyout-with-section": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u „[[User talk:$2#$3|$4]]“.",
- "notification-page-linked": "Stranica [[:$2]] je {{GENDER:$1|povezana}} sa stranicom [[:$3]]. [[Special:WhatLinksHere/$2|Pogledajte sve veze prema ovoj stranici]].",
- "notification-page-linked-flyout": "[[:$2]] je {{GENDER:$1|povezana}} sa [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] je {{GENDER:$1|prokomentarisao|prokomentarisala}} temu „[[$3|$2]]“ na stranici za razgovor „$4“.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] je {{GENDER:$1|postavio|postavila}} novu temu „$2“ na [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] vam je {{GENDER:$1|poslao|poslala}} poruku: „[[$3#$2|$2]]“.",
- "notification-add-comment-yours2": "[[User:$1|$1]] je {{GENDER:$1|prokomentarisao|prokomentarisala}} temu „[[$3#$2|$2]]“ na vašoj stranici za razgovor.",
- "notification-mention": "[[User:$1|$1]] vas je {{GENDER:$1|spomenuo|spomenula}} na stranici za razgovor $5 u „[[:$3#$2|$4]]“.",
- "notification-mention-flyout": "$1 vas je {{GENDER:$1|spomenuo|spomenula}} na stranici za razgovor $5 u „[[:$3#$2|$4]]“.",
- "notification-mention-nosection": "[[User:$1|$1]] vas je {{GENDER:$1|spomenuo|spomenula}} na [[:$3|stranici za razgovor $2]].",
- "notification-mention-nosection-flyout": "$1 vas je {{GENDER:$1|spomenuo|spomenula}} na [[:$3|stranici za razgovor $2]].",
- "notification-user-rights": "[[User:$1|$1]] je [[Special:Log/rights/$1|{{GENDER:$1|promenio|promenila}}]] vaša korisnička prava. $2. [[Special:ListGroupRights|Saznajte više]]",
- "notification-user-rights-flyout": "$1 je {{GENDER:$1|promenio|promenila}} vaša korisnička prava. $2. [[Special:ListGroupRights|Saznajte više]]",
- "notification-user-rights-add": "Od sada ste član {{PLURAL:$2|sledeće grupe|sledećih grupa}}: $1",
- "notification-user-rights-remove": "Više niste član {{PLURAL:$2|sledeće grupe|sledećih grupa}}: $1",
- "notification-new-user": "$1, dobro došli na projekat {{SITENAME}}! Drago nam je što ste ovde.",
- "notification-reverted2": "{{PLURAL:$4|Vaša izmena na stranici [[:$2]] je poništena|Vaše izmene na stranici [[:$2]] su poništene}} od strane {{GENDER:$1|korisnika|korisnice}} [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Vaša izmena na stranici $2 je poništena|Vaše izmene na stranici $2 su poništene}} od strane {{GENDER:$1|korisnika|korisnice}} $1. $3",
- "notification-edit-talk-page-email-subject2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor:",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 vam je {{GENDER:$1|ostavio|ostavila}} poruku na vašoj stranici za razgovor u „$2“.",
+ "notification-header-reverted": "{{PLURAL:$4|Vaša izmena na stranici <strong>$3</strong> je poništena|Vaše izmene na {{GENDER:$2|stranici}} <strong>$3</strong> su poništene}}.",
+ "notification-header-emailuser": "$1 Vam je {{GENDER:$2|poslao|poslala}} imejl.",
+ "notification-edit-talk-page-email-subject2": "$1 Vam je {{GENDER:$1|ostavio|ostavila}} poruku na projektu {{SITENAME}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 Vam je {{GENDER:$1|ostavio|ostavila}} poruku na Vašoj stranici za razgovor u „$2“.",
"notification-page-linked-email-subject": "Vaša stranica je povezana na projektu {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 je {{GENDER:$1|povezana}} sa $3.",
"notification-reverted-email-subject2": "{{GENDER:$1|{{PLURAL:$3|Vaša izmena je poništena|Vaše izmene su poništene}}}} na projektu {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Vaša izmena na stranici $2 je poništena|Vaše izmene na stranici $2 su poništene}} od strane {{GENDER:$1|korisnika|korisnice}} $1.",
- "notification-mention-email-subject": "$1 vas je {{GENDER:$1|spomenuо|spomenula}} na {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 vas je {{GENDER:$1|spomenuо|spomenula}} na stranici za razgovor $4 u „$3“.",
- "notification-mention-nosection-email-batch-body": "$1 vas je {{GENDER:$1|spomenuo|spomenula}} na stranici za razgovor $2.",
+ "notification-mention-email-subject": "$1 Vas je {{GENDER:$1|pomenuo|pomenula}} {{GENDER:$2|na}} {{SITENAME}}",
"notification-user-rights-email-subject": "Vaša korisnička prava na projektu {{SITENAME}} su promenjena.",
- "notification-user-rights-email-batch-body": "$1 je {{GENDER:$1|promenio|promenila}} vaša korisnička prava. $2.",
- "echo-email-subject-default": "Novo obaveštenje na {{SITENAME}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 min.}}",
"echo-email-body-default": "Imate novo obaveštenje na {{SITENAME}}: \n\n$1",
- "echo-email-batch-body-default": "Imate novo obaveštenje.",
"echo-email-footer-default": "$2\n\nDa biste promenili koje poruke primate od nas idite u podešavanja:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Da biste promenili koje poruke primate od nas idite u <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">podešavanja</a>.<br />\n$1",
+ "echo-email-plain-footer": "Da biste promenili koje poruke primate {{GENDER:$1|od}} nas idite u podešavanja.",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|Vaša}} podešavanja",
+ "echo-email-html-footer-with-link": "Da biste promenili koje poruke primate {{GENDER:$2|od}} nas idite u $1.",
"echo-notification-alert": "{{PLURAL:$1|Obaveštenje ($1)|Obaveštanja ($1)|100=Obaveštanja (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Poruka ($1)|Poruke ($1)|100=Poruke (99+)}}",
"echo-notification-alert-text-only": "Obaveštenja",
- "echo-notification-message-text-only": "Poruke",
"echo-overlay-link": "Sva obaveštenja",
"echo-overlay-title": "<b>Obaveštenja</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Obaveštenja}}</b> (prikaz $1 od $2 nepročitanih)",
@@ -102,14 +112,10 @@
"echo-date-today": "Danas",
"echo-date-yesterday": "Juče",
"echo-load-more-error": "Došlo je do greške pri dobavljanju više rezultata.",
- "notification-edit-talk-page-bundle": "$1 i još $3 {{PLURAL:$4|korisnik|korisnika}} {{GENDER:$1|ostavili}} su poruke na vašoj [[User talk:$2|stranici za razgovor]].",
- "notification-page-linked-bundle": "Stranica $2 je {{GENDER:$1|povezana}} sa $3 i $4 {{PLURAL:$5|druge stranice|drugih stranica}}. [[Special:WhatLinksHere/$2|Pogledajte sve veze prema ovoj stranici]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 i još $2 {{PLURAL:$3|1=jedan korisnik|korisnika}} {{GENDER:$1|ostavili}} su poruke na vašoj stranici za razgovor.",
- "notification-page-linked-email-batch-bundle-body": "Stranica $2 je {{GENDER:$1|povezana}} sa $3 i $4 {{PLURAL:$5|druge stranice|drugih stranica}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Jedna nova poruka|$1 nove poruke|$1 novih poruka|100=≥100 novih poruka}} na <strong>{{GENDER:$3|Vašoj}} stranici za razgovor</strong>.",
"echo-email-batch-subject-daily": "Imate {{PLURAL:$2|novo obaveštenje|nova obaveštenja}} na {{SITENAME}}",
"echo-email-batch-subject-weekly": "Imate {{PLURAL:$2|novo obaveštenje|nova obaveštenja}} na projektu {{SITENAME}} ove sedmice",
"echo-email-batch-body-intro-daily": "Zdravo $1,\nOvo je dnevni sažetak današnjih aktivnosti na projektu {{SITENAME}} za vas.",
"echo-email-batch-body-intro-weekly": "Zdravo $1,\nOvo je nedeljni sažetak aktivnosti na projektu {{SITENAME}} za vas.",
- "echo-email-batch-link-text-view-all-notifications": "Pogledaj sva obaveštenja",
- "echo-rev-deleted-text-view": "Ova revizija stranice je potisnuta."
+ "echo-email-batch-link-text-view-all-notifications": "Pogledaj sva obaveštenja"
}
diff --git a/Echo/i18n/sty.json b/Echo/i18n/sty.json
new file mode 100644
index 00000000..eb820067
--- /dev/null
+++ b/Echo/i18n/sty.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Khanmarat"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Сеснең}} ҡәбәрләшеүләр"
+}
diff --git a/Echo/i18n/su.json b/Echo/i18n/su.json
index 3b7411d8..4525751e 100644
--- a/Echo/i18n/su.json
+++ b/Echo/i18n/su.json
@@ -1,8 +1,11 @@
{
"@metadata": {
"authors": [
- "Kandar"
+ "Kandar",
+ "Uchup19"
]
},
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|nulis}} surat dina kaca obrolan anjeun."
+ "tooltip-pt-notifications-alert": "Iber {{GENDER:|anjeun}}",
+ "notification-timestamp-yesterday": "Kamari",
+ "echo-date-yesterday": "Kamari"
}
diff --git a/Echo/i18n/sv.json b/Echo/i18n/sv.json
index dd72c9a0..88a486f9 100644
--- a/Echo/i18n/sv.json
+++ b/Echo/i18n/sv.json
@@ -13,7 +13,11 @@
"MagnusA",
"Paracel63",
"Hangsna",
- "NH"
+ "NH",
+ "Frisko",
+ "Macofe",
+ "Nemo bis",
+ "Umeaboy"
]
},
"echo-desc": "System för att meddela användare om händelser och meddelanden",
@@ -21,7 +25,9 @@
"prefs-emailsettings": "E-postinställningar",
"prefs-displaynotifications": "Visningsalternativ",
"prefs-echosubscriptions": "Meddela mig om dessa händelser",
+ "prefs-echocrosswiki": "Interwikiaviseringar",
"prefs-newmessageindicator": "Indikator för nya meddelanden",
+ "prefs-blocknotificationslist": "Ignorerade användare",
"echo-pref-send-me": "Skicka mig:",
"echo-pref-send-to": "Skicka till:",
"echo-pref-email-format": "E-postformat:",
@@ -33,115 +39,177 @@
"echo-pref-email-frequency-weekly": "En veckovis sammanställning av aviseringar",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Oformaterad text",
+ "echo-pref-cross-wiki-notifications": "Visa aviseringar från andra wikis",
+ "echo-pref-notifications-blacklist": "Visa inte aviseringar från dessa användare. ([[mw:Help:Notifications#mute|läs mer]])",
"echo-pref-new-message-indicator": "Visa symbolen för diskussionssidemeddelanden i min verktygsrad",
+ "echo-pref-beta-feature-cross-wiki-message": "Förbättrade aviseringar",
+ "echo-pref-beta-feature-cross-wiki-description": "Visa och organisera aviseringar mer lättare. Innehåller aviseringar som låter dig se meddelanden från andra wikis. (För att få interwikiaviseringar på en wiki måste du aktivera betafunktionen på wikin.)",
"echo-learn-more": "Läs mer",
+ "echo-log": "Offentlig logg",
"echo-new-messages": "Du har nya meddelanden",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Diskussionssidemeddelande|Diskussionssidemeddelanden}}",
"echo-category-title-article-linked": "Sid{{PLURAL:$1|länk|länkar}}",
"echo-category-title-reverted": "Redigerings{{PLURAL:$1|återställning|återställningar}}",
"echo-category-title-mention": "{{PLURAL:$1|Omnämning|Omnämningar}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Misslyckat omnämnande|Misslyckade omnämnanden}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Genomfört omnämnande|Genomförda omnämnanden}}",
"echo-category-title-other": "{{PLURAL:$1|Annan|Andra}}",
"echo-category-title-system": "{{PLURAL:$1|System}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Användarrättighetsförändring|Användarrättighetsförändringar}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|E-post från annan användare|E-post från andra användare}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Sidpåminnelse|Sidpåminnelser}}",
"echo-pref-tooltip-edit-user-talk": "Meddela mig när någon lämnar ett meddelande eller svarar på min diskussionssida.",
- "echo-pref-tooltip-article-linked": "Meddela mig när någon länkar till en sida som jag skapat från en artikelsida.",
+ "echo-pref-tooltip-article-linked": "Meddela mig när någon länkar till en sida som jag skapat från en annan sida.",
"echo-pref-tooltip-reverted": "Meddela mig när någon återställer en ändring som jag gjort, med hjälp av verktygen \"gör ogjord\" eller \"rulla tillbaka\".",
"echo-pref-tooltip-mention": "Meddela mig när någon länkar till min användarsida.",
+ "echo-pref-tooltip-mention-failure": "Meddela mig när jag inte kan skicka ett omnämnande till någon.",
+ "echo-pref-tooltip-mention-success": "Meddela mig när jag skickar ett omnämnande till någon.",
"echo-pref-tooltip-user-rights": "Meddela mig när någon ändrar mina användarrättigheter.",
- "echo-no-agent": "[Ingen]",
- "echo-no-title": "[Ingen sida]",
+ "echo-pref-tooltip-emailuser": "Meddela mig när någon skickar mig ett e-post.",
+ "echo-pref-tooltip-article-reminder": "Meddela mig om denna sida när jag frågar.",
"echo-error-no-formatter": "Ingen formatering definierad för avisering.",
"notifications": "Aviseringar",
- "tooltip-pt-notifications-alert": "{{GENDER:|Dina}} notifieringar",
- "tooltip-pt-notifications-message": "{{GENDER:|Dina}} meddelanden",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Dina}} systemmeddelanden",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Dina}} notiser",
+ "echo-displaynotificationsconfiguration": "Visa aviseringskonfiguration",
+ "echo-displaynotificationsconfiguration-summary": "Detta är en översikt av hur aviseringar är konfigurerade på denna wiki.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Aviseringar efter kategori",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sortering av typer",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Vilket avsnitt varje aviseringstyp sorteras i",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Tillåtna aviseringsmetoder",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Vilka aviseringsmetoder som stöds för varje kategori",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Vilka aviseringsmetoder som varje typ stöder; gäller endast typer inom kategorier som döljs i inställningarna",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Aktiverad som standard",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Befintliga användare",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Nya användare",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Nödvändiga aviseringsmetoder",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Vilka aviseringsmetoder som är obligatoriska för varje kategori",
"echo-specialpage": "Aviseringar",
+ "echo-specialpage-section-markread": "Markera grupp som läst",
+ "echo-specialpage-markasread": "Avisering: Markera som läst",
+ "echo-specialpage-markasread-invalid-id": "Ogiltigt händelse-ID",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|avisering|aviseringar}}",
+ "echo-specialpage-pagefilters-title": "Senaste aktivitet",
+ "echo-specialpage-pagefilters-subtitle": "Sidor med olästa aviseringar",
+ "notificationsmarkread-legend": "Markera avisering som läst",
"echo-anon": "För att ta emot aviseringar, [$1 skapa ett konto] eller [$2 logga in].",
"echo-none": "Du har inga aviseringar.",
"echo-more-info": "Mer information",
"echo-feedback": "Feedback",
+ "echo-popup-footer-special-page-invitation": "<strong>Prova den omgjorda sidan för aviseringar.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Alla nya utseenden och funktioner.",
+ "echo-api-failure": "Kunde inte hämta aviseringar.",
+ "echo-api-failure-cross-wiki": "Åtkomst till fjärrdomänen nekades.",
+ "echo-notification-placeholder": "Det finns inga meddelanden.",
+ "echo-notification-placeholder-filters": "Det finns inga meddelanden som matchar dessa kriterier.",
+ "echo-notification-loginrequired": "Du måste logga in för att se dina aviseringar.",
+ "echo-notification-popup-loginrequired": "Logga in för att se dina aviseringar.",
+ "echo-notification-markasread": "Markera som läst",
+ "echo-notification-markasunread": "Markera som oläst",
+ "echo-notification-markasread-tooltip": "Markera som läst",
+ "echo-notification-more-options-tooltip": "Fler alternativ",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Sluta}} bevaka ny aktivitet på \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Du}} bevakar inte längre sidan \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Du}} kan bevaka [$2 denna sida] när som helst.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Följ}} ny aktivitet på \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|Du}} bevakar nu sidan \"$1\"",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Du}} kan sluta bevaka [$2 denna sida] när som helst.",
+ "notification-link-text-expand-all": "Expandera",
+ "notification-link-text-expand-alert-count": "Visa {{PLURAL:$1|$1 systemmeddelande|$1 systemmeddelanden}}",
+ "notification-link-text-expand-notice-count": "Visa {{PLURAL:$1|$1 notis|$1 notiser}}",
+ "notification-link-text-expand-all-count": "Visa {{PLURAL:$1|$1 avisering|$1 aviseringar}}",
+ "notification-link-text-collapse-all": "Dölj",
"notification-link-text-view-message": "Visa meddelande",
"notification-link-text-view-mention": "Visa omnämnande",
- "notification-link-text-view-changes": "Visa ändringar",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Visa omnämnande|Visa omnämnanden}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Visa}} ändringar",
"notification-link-text-view-page": "Visa sida",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|lämnade}} ett meddelande på <strong>{{GENDER:$3|din}} diskussionssida</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|lämnade}} ett meddelande på <strong>{{GENDER:$3|din}} diskussionssida</strong> i \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "En länkning gjordes från <strong>$4</strong> till <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Länkades från <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Länkar skapades från {{PLURAL:$5||$5 sidor|100=99+ sidor}} till <strong>$3</strong>.",
+ "notification-header-article-reminder": "En sida som {{GENDER:$2|du}} har begärt att påminnas om finns på <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Alla länkar till denna sida",
+ "notification-header-mention-other": "$1 {{GENDER:$2|nämnde}} {{GENDER:$3|dig}} på <strong>$4</strong> i \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|nämnde}} {{GENDER:$3|dig}} på <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|nämnde}} {{GENDER:$3|dig}} på <strong>användardiskussionssidan {{GENDER:$5|för}} $4</strong> i \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|nämnde}} {{GENDER:$3|dig}} på <strong>användardiskussionssidan {{GENDER:$5|för}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|nämnde}} {{GENDER:$3|dig}} på <strong>{{GENDER:$2|sin}} diskussionssida</strong> i \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|nämnde}} {{GENDER:$3|dig}} på <strong>{{GENDER:$2|sin}} diskussionssida</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|nämnde}} {{GENDER:$3|dig}} på diskussionssidan <strong>$4</strong> i \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|nämnde}} {{GENDER:$3|dig}} på diskussionssidan <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Ditt}} omnämnande av <strong>$3</strong> skickades inte eftersom användaren inte hittades.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Ditt}} omnämnande av <strong>$3</strong> skickades inte eftersom användaren är anonym.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Du}} försökte nämna fler än $3 {{PLURAL:$3|användare}}. Alla omnämnanden ovanför gränsen skickades inte.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Ett omnämnande|$3 omnämnanden}} {{GENDER:$2|du gjorde}} på diskussionssidan <strong>$4</strong> kunde inte skickas.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Användarnamnet finns inte:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP-adresser kan inte nämnas:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Ditt}} omnämnande av <strong>$3</strong> skickades.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Ett omnämnande|$3 omnämnanden}} {{GENDER:$2|du gjorde}} på diskussionssidan <strong>$4</strong> skickades.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Du nämnde}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|En avisering|$3 aviseringar}} om omnämningar {{GENDER:$2|du gjorde}} på diskussionssidan <strong>$4</strong>: {{PLURAL:$5|$5 skickades inte}}, {{PLURAL:$6|$6 skickades}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Dina}} användarrättigheter har {{GENDER:$1|ändrats}}. Du har lagts till i: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Dina}} användarrättigheter har {{GENDER:$1|ändrats}}. Du är inte längre medlem i: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Dina}} användarrättigheter har {{GENDER:$1|ändrats}}. Du har lagts till i: $2. Du är inte längre medlem i: $4.",
+ "notification-header-user-rights-expiry-change": "Utgången för {{GENDER:$4|ditt}} medlemskap i följande {{PLURAL:$3|grupp|grupper}} har {{GENDER:$1|ändrats}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Välkommen}} till {{SITENAME}}, $1! Vi är glada över att {{GENDER:$2|du är}} här.",
+ "notification-welcome-linktext": "Välkommen",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Du}} gjorde precis {{GENDER:$2|din}} första redigering; {{GENDER:$2|tack}} och välkommen!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Du}} gjorde precis {{GENDER:$2|din}} tionde redigering; {{GENDER:$2|tack}} och fortsätt i samma takt!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Du}} gjorde precis {{GENDER:$2|din}} hundrade redigering; {{GENDER:$2|tack}} så mycket!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Du}} gjorde precis {{GENDER:$2|din}} tusende redigering; {{GENDER:$2|tack}} för att du är en så bra bidragsgivare!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Du}} gjorde precis {{GENDER:$2|din}} tiotusende redigering; {{GENDER:$2|tack}} så jättemycket!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Du}} gjorde precis {{GENDER:$2|din}} hundratusende redigering; {{GENDER:$2|tack}} för ditt fantastiska bidrag!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Du}} gjorde precis {{GENDER:$2|din}} miljonte redigering; {{GENDER:$2|tack}} för ditt häpnadsväckande bidrag!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Din}} redigering",
"notification-link-text-view-edit": "Visa redigering",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|lämnade}} ett meddelande på din [[User talk:$2#$3|diskussionssida]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|lämnade}} ett meddelande på din diskussionssida i \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|lämnade}} ett meddelande på din [[User talk:$2#$3|diskussionssida]].",
- "notification-edit-talk-page-flyout-with-section": "$1 lämnade ett meddelande på din diskussionsida i \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] {{GENDER:$1|länkades}} från [[:$3]]. [[Special:WhatLinksHere/$2|Se alla länkar till denna sida]].",
- "notification-page-linked-flyout": "[[:$2]] {{GENDER:$1|länkades}} från [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|kommenterade}} \"[[$3|$2]]\" på diskussionssidan för \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|la in}} ett nytt ämne \"$2\" på [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|skickade}} ett meddelande till dig: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|kommenterade}} om \"[[$3#$2|$2]]\" på din diskussionssida.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|nämnde}} dig på $5 i avsnittet \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "$1 {{GENDER:$1|nämnde}} dig på $5 i avsnittet \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|nämnde}} dig på [[:$3|$2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|nämnde}} dig på [[:$3|$2]].",
- "notification-user-rights": "Dina användarrättigheter [[Special:Log/rights/$1|{{GENDER:$1|ändrades}}]] av [[User:$1|$1]]. $2. [[Special:ListGroupRights|Läs mer]]",
- "notification-user-rights-flyout": "Dina användarrättigheter {{GENDER:$1|ändrades}} av $1. $2. [[Special:ListGroupRights|Läs mer]]",
- "notification-user-rights-add": "Du är nu medlem i {{PLURAL:$2|denna grupp|dessa grupper}}: $1",
- "notification-user-rights-remove": "Du är inte längre medlem i {{PLURAL:$2|denna grupp|dessa grupper}}: $1",
- "notification-new-user": "Välkommen till {{SITENAME}}, $1! Vi är glada att du är här.",
- "notification-reverted2": "{{PLURAL:$4|Din redigering|Dina redigeringar}} på [[:$2]] har {{GENDER:$1|återställts}} av [[User:$1|$1]]. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|Din redigering|Dina redigeringar}} på $2 har {{GENDER:$1|återställts}} av $1. $3",
+ "notification-link-article-reminder": "Visa sida",
+ "notification-header-reverted": "{{PLURAL:$4|Din redigering|Dina redigeringar}} på <strong>$3</strong> har {{GENDER:$2|återställts}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|skickade}} e-post till dig.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|lämnade}} ett meddelande till dig på {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|lämnade}} ett meddelande på din diskussionssida.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|lämnade}} ett meddelande på din diskussionssida i \"$2\".",
"notification-page-linked-email-subject": "En sida du skapade länkades till på {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 {{GENDER:$1|länkades}} från $3.",
"notification-reverted-email-subject2": "{{PLURAL:$3|Din redigering blev {{GENDER:$1|återställd}}|Dina redigeringar blev {{GENDER:$1|återställda}}}} på {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|Din redigering|Dina redigeringar}} på $2 har återställts av $1.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|nämnde}} dig på {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|nämnde}} dig på diskussionssidan för $4 i \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|nämnde}} dig på diskussionssidan för $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|nämnde}} {{GENDER:$2|dig}} på {{SITENAME}}",
"notification-user-rights-email-subject": "Dina användarrättigheter har ändrats på {{SITENAME}}",
- "notification-user-rights-email-batch-body": "Dina användarrättigheter har {{GENDER:$1|ändrats}} av $1. $2.",
- "echo-email-subject-default": "Ny avisering på {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1mo}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1yr}}",
+ "notification-timestamp-today": "Idag",
+ "notification-timestamp-yesterday": "Igår",
+ "notification-inbox-filter-read": "Lästa",
+ "notification-inbox-filter-unread": "Olästa",
+ "notification-inbox-filter-all": "Alla",
"echo-email-body-default": "Du har en ny avisering på {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Du har en ny avisering.",
+ "echo-email-footer-default-html": "För att hantera vilka meddelanden vi e-postar till dig, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">kontrollera dina inställningar</a>.<br />\n$1",
"echo-email-footer-default": "$2\n\nFör att hantera vilken e-post vi skickar dig, kontrollera dina inställningar:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "För att kontrollera vilka meddelanden vi e-postar till dig, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">kontrollera dina inställningar</a>.<br />\n$1",
+ "echo-email-plain-footer": "För att kontrollera vilka e-postmeddelanden vi skickar till {{GENDER:$1|dig}}, gå till {{GENDER:$1|dina}} inställningar:",
+ "echo-email-html-footer-preference-link-text": "kontrollera {{GENDER:$1|dina}} inställningar",
+ "echo-email-html-footer-with-link": "För att hantera vilken e-post vi skickar till {{GENDER:$2|dig}}, $1.",
"echo-notification-alert": "{{PLURAL:$1|Systemmeddelande ($1)|100=Systemmeddelande (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Meddelande ($1)|Meddelanden ($1)|100=Meddelande (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Notis ($1)|Notiser ($1)|100=Notiser (99+)}}",
"echo-notification-alert-text-only": "Systemmeddelanden",
- "echo-notification-message-text-only": "Meddelanden",
+ "echo-notification-notice-text-only": "Notiser",
"echo-overlay-link": "Alla aviseringar",
"echo-overlay-title": "<b>Aviseringar</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Avisering|Aviseringar}}</b> (visar $1 av $2 {{PLURAL:$2|oläst|olästa}})",
"echo-mark-all-as-read": "Markera alla som lästa",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|avisering markerad som läst|aviseringar markerade som lästa}}",
+ "echo-mark-wiki-as-read": "Markera alla som lästa på vald wiki: $1",
"echo-date-today": "Idag",
"echo-date-yesterday": "Igår",
"echo-load-more-error": "Ett fel uppstod när fler resultat skulle hämtas.",
- "notification-edit-talk-page-bundle": "$1 och $3 {{PLURAL:$4|andra}} {{GENDER:$1|lämnade}} ett meddelande på din [[User talk:$2|diskussionssida]].",
- "notification-page-linked-bundle": "$2 {{GENDER:$1|länkades}} från $3 och $4 {{PLURAL:$5|annan sida|andra sidor}}. [[Special:WhatLinksHere/$2|Se alla länkar till denna sida]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 och $2 {{PLURAL:$3|annan|andra}} {{GENDER:$1|lämnade}} ett meddelande på din diskussionssida.",
- "notification-page-linked-email-batch-bundle-body": "$2 {{GENDER:$1|länkades}} från $3 och $4 {{PLURAL:$5|annan sida|andra sidor}}.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Ett nytt meddelande|$1 nya meddelanden|100=99+ nya meddelanden}} på <strong>{{GENDER:$3|din}} diskussionssida</strong>.",
"echo-email-batch-subject-daily": "Du har {{PLURAL:$2|en ny avisering|nya aviseringar}} på {{SITENAME}}",
"echo-email-batch-subject-weekly": "Du har {{PLURAL:$2|en ny avisering|nya aviseringar}} på {{SITENAME}} den här veckan",
"echo-email-batch-body-intro-daily": "Hej $1,\nHär är en sammanfattning av dagens aktivitet på {{SITENAME}} för dig.",
"echo-email-batch-body-intro-weekly": "Hej $1,\nHär är en sammanfattning av veckans aktivitet på {{SITENAME}} för dig.",
"echo-email-batch-link-text-view-all-notifications": "Visa alla aviseringar",
- "echo-rev-deleted-text-view": "Denna sidversion har dolts.",
- "apihelp-echomarkread-description": "Markera aviseringar som lästa för den aktuella användaren.",
- "apihelp-echomarkread-param-list": "En lista över aviserings-ID att markera som lästa.",
- "apihelp-echomarkread-param-all": "Om angiven, markerar en användares alla aviseringar som lästa.",
- "apihelp-echomarkread-param-sections": "En lista över avsnitt att markera som lästa.",
- "apihelp-echomarkread-example-1": "Markera avisering 8 som läst",
- "apihelp-echomarkread-example-2": "Markera alla aviseringar som lästa",
- "apihelp-echomarkseen-description": "Märk aviseringar som lästa för aktuell användare.",
- "apihelp-echomarkseen-example-1": "Märk aviseringar som lästa",
- "apihelp-query+notifications-description": "Hämta aviseringar som väntar på aktuell användare.",
- "apihelp-query+notifications-param-prop": "Detaljer som ska begäras.",
- "apihelp-query+notifications-param-sections": "De aviseringsavsnitt som ska undersökas.",
- "apihelp-query+notifications-param-groupbysection": "Om resultaten ska grupperas efter avsnitt. Om angivet hämtas vart avsnitt separat.",
- "apihelp-query+notifications-param-format": "Om angivet, returneras aviseringar formaterade på detta sätt.",
- "apihelp-query+notifications-param-limit": "Det maximala antalet aviseringar som ska returneras.",
- "apihelp-query+notifications-param-index": "Om angivet, en lista över aviserings-ID, i ordning, kommer att returneras.",
- "apihelp-query+notifications-param-alertcontinue": "När fler resultat finns för systemmeddelande, använd detta för att fortsätta.",
- "apihelp-query+notifications-param-alertunreadfirst": "Om du vill visa olästa meddelandeaviseringar först.",
- "apihelp-query+notifications-param-messagecontinue": "När fler meddelanden finns tillgängliga, använd detta för att fortsätta.",
- "apihelp-query+notifications-param-messageunreadfirst": "Om du vill visa olästa systemmeddelandeaviseringar först.",
- "apihelp-query+notifications-example-1": "Lista aviseringar",
- "apihelp-query+notifications-example-2": "Listan aviseringar grupperade efter avsnitt, med antal"
+ "notification-header-foreign-alert": "Fler systemmeddelanden från {{PLURAL:$5|en annan wiki|$5 andra wikis|0=}}",
+ "notification-header-foreign-notice": "Flera notiser från {{PLURAL:$5|en annan wiki|$5 andra wikis}}",
+ "notification-header-foreign-all": "Fler aviseringar från {{PLURAL:$5|en annan wiki|$5 andra wikis}}"
}
diff --git a/Echo/i18n/szl.json b/Echo/i18n/szl.json
index 0d150e01..ccec01ff 100644
--- a/Echo/i18n/szl.json
+++ b/Echo/i18n/szl.json
@@ -3,6 +3,5 @@
"authors": [
"Krol111"
]
- },
- "tooltip-pt-notifications": "Twoje nowiny"
+ }
}
diff --git a/Echo/i18n/ta.json b/Echo/i18n/ta.json
index 228c6fed..48cfdbe3 100644
--- a/Echo/i18n/ta.json
+++ b/Echo/i18n/ta.json
@@ -5,7 +5,9 @@
"Karthi.dr",
"Shanmugamp7",
"மதனாஹரன்",
- "ElangoRamanujam"
+ "ElangoRamanujam",
+ "தமிழ்க்குரிசில்",
+ "Rakeshonwiki"
]
},
"echo-desc": "அறிவிப்பு முறைமை",
@@ -25,7 +27,6 @@
"echo-pref-email-frequency-weekly": "அறிவிப்புகளின் இவ்வார சுறுக்கம்",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "வெற்று உரை",
- "echo-pref-notify-show-link": "என் கருவிப்பட்டியில் அறிவிப்புகளை காட்டு",
"echo-pref-new-message-indicator": "என் கருவிப்பட்டியில் பேச்சு பக்க செய்திகளின் குறிகாட்டியினை காட்டு",
"echo-learn-more": "மேலும் அறிய",
"echo-new-messages": "உங்களுக்கு புதிய செய்திகள் உள்ளன",
@@ -36,43 +37,32 @@
"echo-pref-tooltip-article-linked": "நான் உருவாக்கிய கட்டுரை பக்கத்துக்கு வேறு ஒரு பக்கத்திலிருந்து யாராவது இணைப்புகள் இட்டால் எனக்கு தெரிவி.",
"echo-pref-tooltip-reverted": "நான் செய்த தொகுப்புகளை யாராவது மீளமை அல்லது முன்நிலையாக்குக கருவி கொண்டு மீளமைத்தால் எனக்கு தெரிவி.",
"echo-pref-tooltip-mention": "என் பயனர் பக்கத்துக்கு யாராவது இணைப்புகள் இட்டால் எனக்குத் தெரிவிக்கவும்.",
- "echo-no-agent": "[யாருமில்லை]",
- "echo-no-title": "[கட்டுரை இல்லை]",
"echo-error-no-formatter": "அறிவிப்புகளுக்கு எந்த வடிவமைப்பும் வரையறுக்கப்படவில்லை.",
- "echo-error-preference": "பிழை: பயனர் விருப்ப தேர்வுகளை சேமிக்க இயவில்லை.",
"notifications": "அறிவிப்புகள்",
- "tooltip-pt-notifications": "உங்கள் அறிவிப்புகள்",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Your}} அறிவிப்புகள்",
"echo-specialpage": "அறிவிப்புகள்",
"echo-anon": "அறிவிப்புகளைப் பெறுவதற்கு [$1 ஒரு கணக்கை உருவாக்குங்கள்] அல்லது [$2 உள்நுழையுங்கள்].",
"echo-none": "உங்களுக்கு அறிவிப்பு ஏதும் இல்லை.",
"echo-more-info": "மேலதிக தகவல்",
"echo-feedback": "கருத்து",
+ "notification-dynamic-actions-unwatch": "புதிய செயபட்டை பர்ப்பதை \"$1\" இல் {{GENDER:$3|நிறுத்தவும்}}",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|You}} இந்த பக்கத்தை பார்ப்பதில்லை \"$1\"",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|You}}, [$2 this page] ஐ எப்போது வேண்டுமானாலும் பார்க்கலாம்.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Follow}} புதிய செயல்பாடு \"$1\"",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|You}} இந்த பக்கத்தை பார்க்கிறார் \"$1",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|You}}, [$2 this page] ஐ பார்ப்பதை எப்போது வேண்டுமானாலும் நிறுத்தலாம்",
"notification-link-text-view-message": "செய்தியினை பார்",
"notification-link-text-view-mention": "குறித்திருப்பதைக்காண்க",
"notification-link-text-view-changes": "மாற்றக்களை பார்",
"notification-link-text-view-page": "பக்கத்தை பார்",
"notification-link-text-view-edit": "தொகுப்பை பார்",
- "notification-edit-talk-page2": "[[User:$1|$1]] உங்களுக்கு ஒரு செய்தியினை உங்களின் [[User talk:$2#$3|பேச்சுப்பக்கத்தில்]] {{GENDER:$1|விட்டுச்சென்றுள்ளார்}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] உங்களுக்கு ஒரு செய்தியினை உங்களின் பேச்சுப்பக்கத்தின் \"[[User talk:$2#$3|$4]]இல்\" {{GENDER:$1|விட்டுச்சென்றுள்ளார்}}.",
- "notification-edit-talk-page-flyout2": "$1 ஒரு செய்தியினை உங்களின் [[User talk:$2#$3|பேச்சுப்பக்கத்தில்]] {{GENDER:$1|விட்டுச்சென்றுள்ளார்}}.",
- "notification-edit-talk-page-flyout-with-section": "$1 ஒரு செய்தியினை உங்களின் பேச்சுப்பக்கத்தின் \"[[User talk:$2#$3|$4]]இல்\" {{GENDER:$1|விட்டுச்சென்றுள்ளார்}}.",
- "notification-page-linked": "[[:$2]] [[:$3]]இல் இருந்து {{GENDER:$1|இணைக்கப்பட்டுள்ளது}}. [[Special:WhatLinksHere/$2|இந்த பக்கத்துக்கான அனைத்து இணைப்புகளையும் பார்க்கவும்]].",
- "notification-new-user": "$1 {{SITENAME}}க்கு உங்களை வரவேற்கிறோம்! உங்களின் வருகை எங்களுக்கு மகிழ்ச்சியளிக்கிறது.",
- "notification-reverted2": "உங்களால் {{PLURAL:$4|[[:$2]]இல் செய்யப்பட்ட தொகுப்பு|[[:$2]]இல் செய்யப்பட்ட தொகுப்புகள்}} [[User:$1|$1]]ஆல் {{GENDER:$1|மீளமைக்கப்பட்டுள்ளது}}. $3",
- "notification-reverted-flyout2": "உங்களால் {{PLURAL:$4|$2 இல் செய்யப்பட்ட தொகுப்பு|$2இல் செய்யப்பட்ட தொகுப்புகள்}} $1ஆல் {{GENDER:$1|மீளமைக்கப்பட்டுள்ளது}}. $3",
+ "notification-header-reverted": "உங்களால் {{PLURAL:$4|$3 இல் செய்யப்பட்ட தொகுப்பு|$3இல் செய்யப்பட்ட தொகுப்புகள்}} $1ஆல் {{GENDER:$2|மீளமைக்கப்பட்டுள்ளது}}.",
"notification-edit-talk-page-email-subject2": "$1 {{SITENAME}}இல் உங்களுக்கு ஒரு புதிய செய்தியினை விட்டுச்சென்றுள்ளார்",
- "notification-edit-talk-page-email-batch-body2": "$1 உங்களின் பேச்சுப்பக்கத்தில் ஒரு செய்தியினை விட்டுச்சென்றுள்ளார்:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 உங்களின் பேச்சுப்பக்கத்தில் ஒரு செய்தியினை விட்டுச்சென்றுள்ளார் \"$2\".",
"notification-page-linked-email-subject": "{{SITENAME}}இல் உங்கள் பக்கம் இணைக்கப்பட்டுள்ளது",
- "notification-page-linked-email-batch-body": "$2 $3இல் {{GENDER:$1|lஇணைக்கப்பட்டுள்ளது}}.",
"notification-reverted-email-subject2": "உங்களின் {{PLURAL:$3|தொகுப்பு|தொகுப்புகள்}} {{SITENAME}}இல் {{GENDER:$1|மீளமைக்கப்பட்டுள்ளது}}",
- "notification-reverted-email-batch-body2": "உங்களால் {{PLURAL:$3|$2இல் செய்யப்பட்ட தொகுப்பு|$2இல் செய்யப்பட்ட தொகுப்புகள்}} $1ஆல் {{GENDER:$1|மீளமைக்கப்பட்டுள்ளது}}",
"notification-mention-email-subject": "$1 உங்களை {{SITENAME}}இல் குறிப்பிட்டுள்ளார்",
- "notification-mention-email-batch-body": "$1 உங்களை $4இன் பேச்சுப்பக்கத்தில் \"$3\" பகுதியில் குறிப்பிட்டுள்ளார்.",
- "echo-email-subject-default": "{{SITENAME}}இல் புதிய அறிவிப்புகள்",
"echo-email-body-default": "{{SITENAME}} இல் உங்களுக்கு ஒரு புதிய அறிவிப்பு உள்ளது:\n\n$1",
- "echo-email-batch-body-default": "உங்களுக்கு ஒரு புதிய அறிவிப்பு உள்ளது",
- "echo-notification-message-text-only": "தகவல்கள்",
"echo-overlay-link": "எல்லா அறிவிப்புகள்",
"echo-overlay-title": "<b>அறிவிப்புகள்</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|அறிவிப்புகள்}}</b> ($2இல் பார்க்கப்படாத $1 காட்டப்படுகின்றது)",
@@ -80,12 +70,9 @@
"echo-date-today": "இன்று",
"echo-date-yesterday": "நேற்று",
"echo-load-more-error": "மேலும் முடிவுகளைப் பெறும்போது பிழை ஏற்பட்டுள்ளது.",
- "notification-page-linked-bundle": "$2 $3 மற்றும் $4 பிற {{PLURAL:$5|பக்கத்தில்|பக்கங்களில்}} {{GENDER:$1|இணைக்கப்பட்டுள்ளது}}. [[Special:WhatLinksHere/$2|இந்த பக்கத்துக்கான அனைத்து இணைப்புகளையும் பார்க்கவும்]]",
- "notification-page-linked-email-batch-bundle-body": "$2 $3 மற்றும் $4 பிற {{PLURAL:$5|பக்கத்தில்|பக்கங்களில்}} {{GENDER:$1|இணைக்கப்பட்டுள்ளது}}.",
"echo-email-batch-subject-daily": "{{SITENAME}}இல் உங்களுக்கு {{PLURAL:$2|ஒரு புதிய செய்தி|புதிய செய்திகள்}} உள்ளன",
"echo-email-batch-subject-weekly": "இவ்வாரம் {{SITENAME}}இல் உங்களுக்கு {{PLURAL:$2|ஒரு புதிய செய்தி|புதிய செய்திகள்}} உள்ளன",
"echo-email-batch-body-intro-daily": "$1,\n{{SITENAME}}இல் உங்களுக்காக இன்றைய செயல்பாடுகளின் சுருக்கம் இதோ.",
"echo-email-batch-body-intro-weekly": "$1,\n{{SITENAME}}இல் உங்களுக்காக இந்த வார செயல்பாடுகளின் சுருக்கம் இதோ.",
- "echo-email-batch-link-text-view-all-notifications": "எல்லா அறிவிப்புகளையும் பார்",
- "echo-rev-deleted-text-view": "பக்கத்தின் இந்த திருத்தம் மறைக்கப்பட்டுள்ளது."
+ "echo-email-batch-link-text-view-all-notifications": "எல்லா அறிவிப்புகளையும் பார்"
}
diff --git a/Echo/i18n/tay.json b/Echo/i18n/tay.json
new file mode 100644
index 00000000..8eff8d61
--- /dev/null
+++ b/Echo/i18n/tay.json
@@ -0,0 +1,37 @@
+{
+ "@metadata": {
+ "authors": [
+ "Translatealcd",
+ "Akamycoco",
+ "Hitaypayan"
+ ]
+ },
+ "prefs-echo": "Ssbaq",
+ "prefs-emailsettings": "Zyusyo na e-meyo’ bruwiy",
+ "prefs-newmessageindicator": "Kaikay na ppsbaq sa giqas na zayzyuwaw",
+ "echo-pref-web": "Wangye’",
+ "echo-pref-email-frequency-daily": "Sbbaq ’pinkr’tung kkayal krayrax",
+ "echo-pref-email-frequency-weekly": "Sbbaq ’pinkr’tung kkayal qutux qutux rihay",
+ "echo-pref-email-format-plain-text": "Biru’ mlmlux",
+ "echo-pref-beta-feature-cross-wiki-message": "Twangiy kinlawkah na smbbaq",
+ "notifications": "Ssbaq",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Rwa su’}}gmrhuw kmayal",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Sbbaq sa lalu’ kwara’ gluw na mmtnaq",
+ "echo-specialpage": "Ssbaq",
+ "echo-specialpage-markasread-invalid-id": "Ungat zyuwaw nquw sinbbaq na ID qaniy",
+ "echo-notification-placeholder": "ungat ana nanu’ sinbbaq.",
+ "echo-notification-markasread": "Sinbbaq sa wayal lpgun",
+ "echo-notification-markasunread": "Sinbbaq sa ini’ lpgiy na’",
+ "echo-notification-markasread-tooltip": "Sinbbaq sa wayal lpgun",
+ "notification-link-text-expand-all": "Psglabang",
+ "notification-link-text-collapse-all": "Qmuzyup",
+ "notification-timestamp-today": "Sawni’",
+ "notification-timestamp-yesterday": "Shira’",
+ "notification-inbox-filter-read": "Lpgun",
+ "notification-inbox-filter-unread": "Ini’ lpgiy na’",
+ "notification-inbox-filter-all": "Kwara’",
+ "echo-notification-alert-text-only": "Kmayal",
+ "echo-notification-notice-text-only": "Ssbaq na kwara’ na",
+ "echo-date-today": "Sawni’",
+ "echo-date-yesterday": "Shira’"
+}
diff --git a/Echo/i18n/tcy.json b/Echo/i18n/tcy.json
index 16c31982..a07b59a9 100644
--- a/Echo/i18n/tcy.json
+++ b/Echo/i18n/tcy.json
@@ -1,8 +1,17 @@
{
"@metadata": {
"authors": [
- "VASANTH S.N."
+ "VASANTH S.N.",
+ "Vishwanatha Badikana",
+ "BHARATHESHA ALASANDEMAJALU",
+ "Kiranpoojary"
]
},
- "tooltip-pt-notifications": "ಈರೆನೆ ಸೂಚನೆಲು"
+ "prefs-echo": "ಸೂಚನೆಲು",
+ "notifications": "ಸೂಚನೆಲು",
+ "tooltip-pt-notifications-alert": "{{GENDER:|ಈರೆನ}} ಎಚ್ಚರಿಕೆ ಸಂದೇಸೊಲು",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "ಅಸ್ತಿತ್ವೋಡು ಉಪ್ಪಿ ಗಳಸುನಾರ್",
+ "echo-notification-markasread-tooltip": "ಓದುತೆಂದು ಗುರ್ತ ಪಾಡ್ಲೆ",
+ "echo-notification-more-options-tooltip": "ಮಸ್ತ್ ಆಯ್ಕೆಲೂ",
+ "notification-link-article-reminder": "ಲೇಕನೊ ತೂಲೆ"
}
diff --git a/Echo/i18n/te.json b/Echo/i18n/te.json
index c874137b..ac4eae68 100644
--- a/Echo/i18n/te.json
+++ b/Echo/i18n/te.json
@@ -26,7 +26,6 @@
"echo-pref-email-frequency-weekly": "వారం మొత్తం మీద సూచనల సారాంశం",
"echo-pref-email-format-html": "హెచ్.టి.ఎం.ఎల్",
"echo-pref-email-format-plain-text": "సాదా పాఠ్యం",
- "echo-pref-notify-show-link": "నా టూల్‌బార్‌లో సూచనలను చూపించు",
"echo-pref-new-message-indicator": "నా టూల్‌బార్‌లో చర్చా పేజీ సందేశ-సూచికను చూపించు",
"echo-learn-more": "మరింత తెలుసుకోండి",
"echo-new-messages": "మీకు కొత్త సందేశాలు ఉన్నాయి",
@@ -40,13 +39,9 @@
"echo-pref-tooltip-article-linked": "నేను వ్యాసపు పేజీ నుండి సృష్టించిన పేజీని ఎవరయినా లంకె వేస్తే నాకు తెలియపరుచు.",
"echo-pref-tooltip-reverted": "నా మార్పును ఎవరయినా రద్దు చేసినా లేదా రోల్ బ్యాక్ పరికరం వాడి వెనక్కు మళ్ళించినా, నాకు తెలియపరుచు.",
"echo-pref-tooltip-mention": "ఎవరయినా నా వాడుకరి పేజీకి ఏదయినా చర్చా పేజీలో లంకె వేస్తే నాకు తెలియపరుచు.",
- "echo-no-agent": "[ఎవరూ లేరు]",
- "echo-no-title": "[ఏ పేజీ లేదు]",
"echo-error-no-formatter": "సూచనకు ఎలాంటి ఆకృతి నిర్దేశించబడలేదు.",
- "echo-error-preference": "దోషం: వాడుకరి అభిరుచులు అమర్చడం కుదరలేదు.",
- "echo-error-token": "దోషం: వాడుకరి చిహ్నం తిరిగితేవటం కుదరలేదు.",
"notifications": "సూచనలు",
- "tooltip-pt-notifications": "మీకు సూచనలు",
+ "tooltip-pt-notifications-alert": "{{GENDER:|మీ}} సూచనలు",
"echo-specialpage": "సూచనలు",
"echo-anon": "సూచనలు పొందటానికి [$1 ఖాతా తెరవండి] లేదా [$2 లోనికి రండి]",
"echo-none": "మీకు ఏ సూచనలు లేవు",
@@ -56,43 +51,20 @@
"notification-link-text-view-mention": "పేరెన్నికను చూడు",
"notification-link-text-view-changes": "మార్పులు చూడు",
"notification-link-text-view-page": "పేజీని చూడు",
+ "notification-header-mention-failure-user-unknown": "$3 గురించిన {{GENDER:$2|మీ}} ప్రస్తావనను, ఆ వాడుకరి కనబడనందువలన పంపించలేదు.",
+ "notification-header-mention-failure-user-anonymous": "$3 గురించిన {{GENDER:$2|మీ}} ప్రస్తావనను, వారు అజ్ఞాతంగా ఉన్నందున పంపించలేకపోయాం.",
+ "notification-header-mention-success": "$3 గురించిన {{GENDER:$2|మీ}} ప్రస్తావనను పంపించాం.",
+ "notification-welcome-linktext": "స్వాగతం",
"notification-link-text-view-edit": "మార్పును చూడు",
- "notification-edit-talk-page2": "[[User:$1|$1]] మీ [[User talk:$2#$3|చర్చా పేజీ]]పై సందేశం {{GENDER:$1|చేర్చారు}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] మీ చర్చా పేజీపై \"[[User talk:$2#$3|$4]]\" వద్ద ఒక సందేశాన్ని {{GENDER:$1|చేర్చారు}}.",
- "notification-edit-talk-page-flyout2": "$1 మీ [[User talk:$2#$3|చర్చాపేజీ]] పై ఒక సందేశం {{GENDER:$1|చేర్చారు}}.",
- "notification-edit-talk-page-flyout-with-section": "$1 మీ చర్చా పేజీలో \"[[User talk:$2#$3|$4]]\" వద్ద ఒక సందేశాన్ని {{GENDER:$1|చేర్చారు}}.",
- "notification-page-linked": "[[:$3]] నుండి [[:$2]]కి {{GENDER:$1|లంకె వేసారు}}.\n[[Special:WhatLinksHere/$2|ఈ పేజీకి చేరుకోవటానికున్న అన్ని లంకెలను చూడు]].",
- "notification-page-linked-flyout": "[[:$3]] నుండి [[:$2]] కి {{GENDER:$1|లంకె వేశారు}}.",
- "notification-add-comment2": "[[User:$1|$1]] \"$4\" చర్చా పేజీలో \"[[$3|$2]]\" పై {{GENDER:$1|వ్యాఖ్యానించారు}}.",
- "notification-add-talkpage-topic2": " [[User:$1|$1]] [[$3]] పై \"$2\" అనే ఒక కొత్త విషయాన్ని {{GENDER:$1|చేర్చారు}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] మీకు {{GENDER:$1|పంపిన సందేశం}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] మీ చర్చాపేజీలో \"[[$3#$2|$2]]\" వద్ద {{GENDER:$1|వ్యాఖ్యానించారు}}.",
- "notification-mention": "[[User:$1|$1]] మిమ్మల్ని $5 చర్చా పేజీ పై \"[[:$3#$2|$4]]\"వద్ద {{GENDER:$1|పేర్కొన్నారు}}.",
- "notification-mention-flyout": "$1 మిమ్మల్ని $5 చర్చా పేజీపై \"[[:$3#$2|$4]]\" వద్ద{{GENDER:$1|పేర్కొన్నారు}}.",
- "notification-user-rights": "మీ [[Special:Log/rights/$1|వాడుకరి హక్కులు ]] [[User:$1|$1]].$2 ద్వారా {{GENDER:$1|మార్చబడ్డాయి}}. [[Special:ListGroupRights|మరింత తెలుసుకోండి]]",
- "notification-user-rights-flyout": "మీ వాడుకరి హక్కులను $1($2) {{GENDER:$1|మార్చారు}}. [[Special:ListGroupRights|మరింత తెలుసుకోండి]]",
- "notification-user-rights-add": "మీరిప్పుడు {{PLURAL:$2|ఈ సమూహం|ఈ సమూహాలలో}} సభ్యులు:$1",
- "notification-user-rights-remove": "మీరికపై {{PLURAL:$2|ఈ సమూహం|ఈ సమూహాలలో}} సభ్యులు కారు:$1",
- "notification-new-user": "{{SITENAME}}కు స్వాగతం, $1! మీ రాక మాకెంతో సంతోషం సుమండీ.",
- "notification-reverted2": "{{PLURAL:$4|[[:$2]] పై మీరు చేసిన మార్పు|[[:$2]] పై మీరు చేసిన మార్పులు}} [[User:$1|$1]] ద్వారా {{GENDER:$1|రద్దు చేయబడ్డాయి}}.$3",
- "notification-reverted-flyout2": "{{PLURAL:$4|$2 పై మీ మార్పు|$2 పై మీ మార్పులు}} $1 ద్వారా {{GENDER:$1|రద్దు చేయబడ్డాయి}}. $3",
+ "notification-header-reverted": "{{PLURAL:$4|$3 పై మీ మార్పు|$3 పై మీ మార్పులు}} $1 ద్వారా {{GENDER:$2|రద్దు చేయబడ్డాయి}}.",
"notification-edit-talk-page-email-subject2": "$1 {{SITENAME}} వద్ద మీకొక సందేశం {{GENDER:$1|రాశారు}}.",
- "notification-edit-talk-page-email-batch-body2": "$1 మీ చర్చా పేజీ పై ఒక సందేశాన్ని {{GENDER:$1|రాసారు}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 మీ చర్చా పేజీలోని \"$2\" పై ఒక సందేశం {{GENDER:$1|రాసారు}}.",
"notification-page-linked-email-subject": "మీ పేజీకి {{SITENAME}}లో లింకు ఇవ్వబడింది",
- "notification-page-linked-email-batch-body": "$3 వద్ద నుండి $2 {{GENDER:$1|లింకు చేయబడ్డారు}}",
"notification-reverted-email-subject2": "{{SITENAME}} వద్ద మీ {{PLURAL:$3|మార్పు|మార్పులు}} {{GENDER:$1|వెనక్కి మళ్ళించ}} {{PLURAL:$3|బడింది|బడ్డాయి}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|$2 పై మీ మార్పు|$2 పై మీ మార్పులు}} $1 ద్వారా {{GENDER:$1|రద్దు చేయబడ్డాయి}}.",
"notification-mention-email-subject": "$1 మిమ్మల్ని {{SITENAME}} లో {{GENDER:$1|పేర్కొన్నారు}}.",
- "notification-mention-email-batch-body": "$1 మిమ్మల్ని $4 చర్చా పేజీలో \"$3\" వద్ద {{GENDER:$1|పేర్కొన్నారు}}.",
"notification-user-rights-email-subject": "{{SITENAME}}లో మీ వాడుకరి హక్కులు మారినవి",
- "notification-user-rights-email-batch-body": "మీ వాడుకరి హక్కులను $1.$2 {{GENDER:$1|మార్చారు}}.",
- "echo-email-subject-default": "{{SITENAME}} వద్ద కొత్త సూచన",
"echo-email-body-default": "{{SITENAME}} వద్ద మీకొక కొత్త సూచన ఉన్నది : \n\n$1",
- "echo-email-batch-body-default": "మీకొక కొత్త సూచన ఉంది.",
"echo-email-footer-default": "$2\n\nమీకు ఏ ఏ ఈ-మెయిళ్లు పంపించాలో నియంత్రించడానికి, మీ అభిరుచులను చూడండి:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "మీకు మేము ఏ ఏ ఈ-మెయిళ్లు పంపించాలో నియంత్రించడానికి, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">మీ అభిరుచులను చూడండి</a>.<br />\n$1",
- "echo-notification-message-text-only": "సందేశాలు",
"echo-overlay-link": "అన్ని సూచనలు",
"echo-overlay-title": "<b>సూచనలు</b>",
"echo-overlay-title-overflow": "<b> {{PLURAL:$1|సూచనలు}}</b> (చదవని $2 లో $1 వది)",
@@ -100,14 +72,9 @@
"echo-date-today": "ఈరోజు",
"echo-date-yesterday": "నిన్న",
"echo-load-more-error": "మరిన్ని ఫలితాలు తెచ్చి చూపడంలో దోషం జరిగింది.",
- "notification-edit-talk-page-bundle": "$1 మరియు మరో $3 {{PLURAL:$4|వ్యక్తి|వ్యక్తులు}} మీ [[User talk:$2|వాడుకరి చర్చా పేజీ]]లో సందేశం {{GENDER:$1| చేర్చారు}}.",
- "notification-page-linked-bundle": "$3 మరియు $4 ఇతర {{PLURAL:$5|పేజీ|పేజీల}} నుండి $2 {{GENDER:$1|లింకు చేయబడ్డారు}}. [[Special:WhatLinksHere/$2|ఈ పేజీకి చేర్చే అన్ని లింకులను చూడు]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 మరియు $2 {{PLURAL:$3|ఇతర వ్యక్తి|ఇతరులు}} మీ చర్చా పేజీలో ఒక సందేశం {{GENDER:$1|రాసారు}}.",
- "notification-page-linked-email-batch-bundle-body": "$3 మరియు $4 ఇతర {{PLURAL:$5|పేజీ|పేజీల}} నుండి $2కు {{GENDER:$1|లింకు వేశారు}}",
"echo-email-batch-subject-daily": "మీకు {{SITENAME}} వద్ద {{PLURAL:$2|కొత్త సూచన ఉంది|కొత్త సందేశాలు ఉన్నాయి}}",
"echo-email-batch-subject-weekly": "మీకు ఈ వారం {{SITENAME}} లో {{PLURAL:$2|కొత్త సూచన ఉంది|కొత్త సూచనలుఉన్నాయి}}",
"echo-email-batch-body-intro-daily": "నమస్కారం $1 గారూ,\nమీ కోసం {{SITENAME}}లో ఈ రోజు జరిగిన సంగతుల యొక్క సారాంశం ఇక్కడ సమకూరుస్తున్నాం.",
"echo-email-batch-body-intro-weekly": "నమస్కారం $1 గారూ,\nమీ కోసం {{SITENAME}}లో ఈ వారం జరిగిన సంగతుల యొక్క సారాంశం ఇక్కడ సమకూరుస్తున్నాం.",
- "echo-email-batch-link-text-view-all-notifications": "అన్ని సూచనలు చూడు",
- "echo-rev-deleted-text-view": "ఈ పేజీ మార్పు అణచబడింది"
+ "echo-email-batch-link-text-view-all-notifications": "అన్ని సూచనలు చూడు"
}
diff --git a/Echo/i18n/tg-cyrl.json b/Echo/i18n/tg-cyrl.json
new file mode 100644
index 00000000..22c76bc8
--- /dev/null
+++ b/Echo/i18n/tg-cyrl.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "AryanSogd",
+ "ToJack"
+ ]
+ },
+ "echo-new-messages": "Шумо паёми нав доред.",
+ "tooltip-pt-notifications-alert": "Огоҳии шумо",
+ "notification-timestamp-today": "Имрӯз",
+ "notification-timestamp-yesterday": "Дирӯз",
+ "notification-inbox-filter-read": "Хондан",
+ "notification-inbox-filter-unread": "Хонданашуда",
+ "notification-inbox-filter-all": "Ҳама",
+ "echo-email-body-default": "Шумо дар сомонаи {{SITENAME}} паёми огаҳсозии нав доред:\n\n$1"
+}
diff --git a/Echo/i18n/th.json b/Echo/i18n/th.json
index adc423c8..280b7975 100644
--- a/Echo/i18n/th.json
+++ b/Echo/i18n/th.json
@@ -3,14 +3,17 @@
"authors": [
"Nullzero",
"Supasate",
- "Horus"
+ "Horus",
+ "Bluegram",
+ "Ans"
]
},
- "echo-desc": "ระบบแจ้งเตือน",
+ "echo-desc": "ระบบสำหรับแจ้งผู้ใช้เกี่ยวกับเหตุการณ์และสาร",
"prefs-echo": "การแจ้งเตือน",
"prefs-emailsettings": "ตัวเลือกอีเมล",
"prefs-displaynotifications": "ตัวเลือกการแสดงผล",
"prefs-echosubscriptions": "แจ้งให้ฉันทราบเกี่ยวกับเหตุการณ์เหล่านี้",
+ "prefs-echocrosswiki": "การแจ้งเตือนข้ามวิกิ",
"prefs-newmessageindicator": "ตัวบ่งชี้ข้อความใหม่",
"echo-pref-send-me": "ส่งหาฉัน:",
"echo-pref-send-to": "ส่งถึง:",
@@ -23,79 +26,82 @@
"echo-pref-email-frequency-weekly": "การแจ้งเตือนแบบสรุปรายสัปดาห์",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "ข้อความล้วน",
+ "echo-pref-cross-wiki-notifications": "แสดงการแจ้งเตือนจากวิกิอื่นๆ",
"echo-pref-new-message-indicator": "แสดงตัวบ่งชี้ข้อความในหน้าพูดคุยในแถบเครื่องมือของฉัน",
"echo-learn-more": "เรียนรู้เพิ่มเติม",
"echo-new-messages": "คุณมีข้อความใหม่",
- "echo-category-title-edit-user-talk": "ข้อความหน้าพูดคุย",
+ "echo-category-title-edit-user-talk": "สารหน้าพูดคุย",
"echo-category-title-article-linked": "การโยงหน้า",
"echo-category-title-reverted": "การย้อนการแก้ไข",
- "echo-category-title-mention": "การกล่าวถึง",
+ "echo-category-title-mention": "{{PLURAL:$1|การกล่าวถึง}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|การกล่าวถึง}}ที่ไม่ประสบผลสำเร็จ",
+ "echo-category-title-mention-success": "{{PLURAL:$1|การกล่าวถึง}}ที่ประสบผลสำเร็จ",
"echo-category-title-other": "อื่น ๆ",
"echo-category-title-system": "{{PLURAL:$1|ระบบ}}",
"echo-category-title-user-rights": "การเปลี่ยนแปลงสิทธิผู้ใช้",
+ "echo-category-title-emailuser": "อีเมลจากผู้ใช้อื่น",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|ตัวแจ้งเตือน}}หน้า",
"echo-pref-tooltip-edit-user-talk": "แจ้งเตือนเมื่อมีคนโพสต์ข้อความหรือตอบในหน้าพูดคุยของฉัน",
"echo-pref-tooltip-article-linked": "แจ้งเตือนฉันเมื่อมีคนโยงจากหน้าบทความถึงหน้าที่ฉันสร้าง",
"echo-pref-tooltip-reverted": "แจ้งเตือนฉันเมื่อมีคนย้อนการแก้ไขของฉัน โดยใช้เครื่องมือทำกลับหรือย้อนกลับการแก้ไข",
"echo-pref-tooltip-mention": "แจ้งเตือนฉันเมื่อมีผู้โยงหาหน้าผู้ใช้ของฉัน",
"echo-pref-tooltip-user-rights": "แจ้งเตือนฉันเมื่อมีผู้เปลี่ยนแปลงสิทธิผู้ใช้ของฉัน",
- "echo-no-agent": "[ไม่มีผู้ใด]",
- "echo-no-title": "[ไม่มีหน้าใด]",
+ "echo-pref-tooltip-emailuser": "แจ้งฉันเมื่อมีผู้ส่งอีเมลหาฉัน",
"echo-error-no-formatter": "ไม่มีการกำหนดรูปแบบสำหรับการแจ้งเตือน",
"notifications": "การแจ้งเตือน",
"tooltip-pt-notifications-alert": "การแจ้งเตือนของคุณ",
- "tooltip-pt-notifications-message": "สารของคุณ",
"echo-specialpage": "การแจ้งเตือน",
"echo-anon": "เพื่อรับการแจ้งเตือน [$1 สร้างบัญชี] หรือ [$2 ล็อกอิน]",
"echo-none": "คุณไม่มีการแจ้งเตือน",
"echo-more-info": "ข้อมูลเพิ่มเติม",
"echo-feedback": "ผลป้อนกลับ",
+ "echo-api-failure": "ไม่สามารถดึงการแจ้ง กรุณาลองอีกครั้ง (ข้อผิดพลาด $1)",
+ "echo-notification-placeholder": "ไม่มีการแจ้งเตือน",
+ "echo-notification-loginrequired": "คุณต้องล็อกอินเพื่อดูการแจ้งของคุณ",
+ "echo-notification-popup-loginrequired": "กรุณาล็อกอินเพื่อดูการแจ้งของคุณ",
+ "notification-link-text-expand-all": "ขยายทั้งหมด",
+ "notification-link-text-expand-alert-count": "ขยาย $1 การเตือน",
+ "notification-link-text-expand-all-count": "ขยาย $1 การแจ้ง",
+ "notification-link-text-collapse-all": "ยุบทั้งหมด",
"notification-link-text-view-message": "ดูข้อความ",
"notification-link-text-view-mention": "ดูการกล่าวถึง",
"notification-link-text-view-changes": "ดูความเปลี่ยนแปลง",
"notification-link-text-view-page": "ดูหน้า",
+ "notification-header-edit-user-talk": "$1 ส่งสารบนหน้าพูดคุยของคุณ",
+ "notification-header-edit-user-talk-with-section": "$1 ส่งสารบนหน้าพูดคุยของคุณใน \"$4\"",
+ "notification-header-page-linked": "$3 ถูกโยงจาก $4",
+ "notification-bundle-header-page-linked": "$3 ถูกโยงจาก $4 และหน้าอื่นอีก $5 หน้า",
+ "notification-link-text-what-links-here": "ดูการโยงมาหน้านี้ทั้งหมด",
+ "notification-header-welcome": "ยินดีต้อนรับสู่{{SITENAME}} $1 เรายินดีที่คุณอยู่ที่นี่",
+ "notification-welcome-linktext": "ยินดีต้อนรับ",
"notification-link-text-view-edit": "ดูการแก้ไข",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|ฝาก}}ข้อความไว้บน[[User talk:$2#$3|หน้าพูดคุย]]ของคุณ",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|ฝาก}}ข้อความบนหน้าพูดคุยของคุณที่ \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 ฝากข้อความไว้ใน[[User talk:$2#$3|หน้าพูดคุย]]ของคุณ",
- "notification-edit-talk-page-flyout-with-section": "$1 ฝากข้อความไว้ในหน้าพูดคุยของคุณใน \"[[User talk:$2#$3|$4]]\"",
- "notification-page-linked": "[[:$2]] ถูกโยงจาก [[:$3]] [[Special:WhatLinksHere/$2|ดูการโยงมายังหน้านี้ทั้งหมด]]",
- "notification-page-linked-flyout": "[[:$2]] ถูกโยงจาก [[:$3]]",
- "notification-add-comment2": "[[User:$1|$1]] ออกความเห็นใน \"[[$3|$2]]\" ในหน้าพูดคุย \"$4\"",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] โพสต์หัวข้อใหม่ \"$2\" ใน [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] ส่งข้อความหาคุณ: \"[[$3#$2|$2]]\"",
- "notification-add-comment-yours2": "[[User:$1|$1]] ออกความเห็นบน \"[[$3#$2|$2]]\" ในหน้าพูดคุยของคุณ",
- "notification-mention": "[[User:$1|$1]] กล่าวถึงคุณในหน้าพูดคุย $5 ใน \"[[:$3#$2|$4]]\"",
- "notification-mention-flyout": "$1 กล่าวถึงคุณในหน้าพูดคุย $5 ใน \"[[:$3#$2|$4]]\"",
- "notification-mention-nosection": "[[User:$1|$1]] กล่าวถึงคุณใน[[:$3|หน้าพูดคุย $2]]",
- "notification-mention-nosection-flyout": "$1 กล่าวถึงคุณใน[[:$3|หน้าพูดคุย $2]]",
- "notification-user-rights": "[[User:$1|$1]] [[Special:Log/rights/$1|เปลี่ยน]]สิทธิถูกใช้ของคุณ $2 [[Special:ListGroupRights|เรียนรู้เพิ่มเติม]]",
- "notification-user-rights-flyout": "$1 เปลี่ยนสิทธิผู้ใช้ของคุณ $2 [[Special:ListGroupRights|เรียนรู้เพิ่มเติม]]",
- "notification-user-rights-add": "ขณะนี้คุณเป็นสมาชิก{{PLURAL:$2|กลุ่มนี้|กลุ่มเหล่านี้}}: $1",
- "notification-user-rights-remove": "คุณไม่ได้เป็นสมาชิก{{PLURAL:$2|กลุ่มนี้|กลุ่มเหล่านี้}}อีก: $1",
- "notification-new-user": "ยินดีต้อนรับสู่ {{SITENAME}} $1! เรายินดีที่คุณอยู่ที่นี่",
- "notification-reverted2": "การแก้ไขใน [[:$2]] ของคุณถูกย้อนโดย [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "การแก้ไขใน $2 ของคุณถูกย้อนโดย $1 $3",
+ "notification-header-reverted": "$1 ย้อนการแก้ไขใน $3 ของคุณ",
+ "notification-header-emailuser": "$1 ส่งอีเมลถึงคุณ",
"notification-edit-talk-page-email-subject2": "$1 ส่งข้อความถึงคุณบน {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 ส่งข้อความบนหน้าคุยกับผู้ใช้ของคุณ:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 ส่งข้อความบนหน้าคุยกับผู้ใช้ของคุณใน \"$2\":",
- "notification-page-linked-email-subject": "หน้าของคุณถูกโยงบน {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 ถูกโยงจาก $3",
+ "notification-page-linked-email-subject": "หน้าที่คุณสร้างถูกโยงบน {{SITENAME}}",
"notification-reverted-email-subject2": "การแก้ไขของคุณถูกย้อนใน {{SITENAME}}",
- "notification-reverted-email-batch-body2": "การแก้ไขของคุณใน $2 ถูกย้อนโดย $1",
"notification-mention-email-subject": "$1 กล่าวถึงคุณบน {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 กล่าวถึงคุณในหน้าอภิปราย $4 ใน \"$3\"",
- "notification-mention-nosection-email-batch-body": "$1 กล่าวถึงคุณในหน้าอภิปราย $2",
"notification-user-rights-email-subject": "สิทธิผู้ใช้ของคุณถูกเปลี่ยนบน {{SITENAME}}",
- "notification-user-rights-email-batch-body": "สิทธิผู้ใช้ของคุณถูกเปลี่ยนโดย $1 $2",
- "echo-email-subject-default": "การแจ้งเตือนใหม่ที่ {{SITENAME}}",
+ "notification-timestamp-today": "วันนี้",
+ "notification-timestamp-yesterday": "เมื่อวานนี้",
+ "notification-inbox-filter-read": "อ่านแล้ว",
+ "notification-inbox-filter-unread": "ยังไม่ได้อ่าน",
+ "notification-inbox-filter-all": "ทั้งหมด",
"echo-email-body-default": "คุณมีการแจ้งเตือนใหม่ที่ {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "คุณมีการแจ้งเตือนใหม่",
+ "echo-email-footer-default": "$2\n\nในการควบคุมว่าจะให้เราส่งอีเมลใดถึงคุณ ให้ตรวจสอบการตั้งค่าของคุณ:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-notification-alert": "{{PLURAL:$1|การเตือน ($1)|100=การเตือน (99+)}}",
+ "echo-notification-alert-text-only": "การเตือน",
"echo-overlay-link": "การแจ้งเตือนทั้งหมด",
"echo-overlay-title": "<b>การแจ้งเตือน</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|การแจ้งเตือน}}</b> (กำลังแสดงที่ยังไม่ได้อ่าน $1 จาก $2 การแจ้งเตือน)",
"echo-mark-all-as-read": "ทำเครื่องหมายทั้งหมดว่าอ่านแล้ว",
"echo-date-today": "วันนี้",
"echo-date-yesterday": "เมื่อวานนี้",
- "echo-email-batch-link-text-view-all-notifications": "ดูการแจ้งเตือนทั้งหมด",
- "echo-rev-deleted-text-view": "รุ่นหน้านี้ถูกระงับ"
+ "echo-load-more-error": "เกิดข้อผิดพลาดขณะไปนำผลลัพธ์มาเพิ่ม",
+ "echo-email-batch-subject-daily": "คุณมีการแจ้งใหม่ที่{{SITENAME}}",
+ "echo-email-batch-subject-weekly": "คุณมีการแจ้งใหม่ที่{{SITENAME}}สัปดาห์นี้",
+ "echo-email-batch-body-intro-daily": "สวัสดี $1\nนี่คือสรุปกิจกรรมของวันนี้ใน{{SITENAME}}สำหรับคุณ",
+ "echo-email-batch-body-intro-weekly": "สวัสดี $1\nนี่คือสรุปกิจกรรมของสัปดาห์นี้ใน{{SITENAME}}สำหรับคุณ",
+ "echo-email-batch-link-text-view-all-notifications": "ดูการแจ้งเตือนทั้งหมด"
}
diff --git a/Echo/i18n/tl.json b/Echo/i18n/tl.json
index d884920f..8d948ce4 100644
--- a/Echo/i18n/tl.json
+++ b/Echo/i18n/tl.json
@@ -4,7 +4,9 @@
"AnakngAraw",
"Sky Harbor",
"TheSleepyhollow02",
- "Jojit fb"
+ "Jojit fb",
+ "Leeheonjin",
+ "Emem.calist"
]
},
"echo-desc": "Sistema ng pagpapabatid",
@@ -24,7 +26,6 @@
"echo-pref-email-frequency-weekly": "Isang lingguhang buod ng mga pabatid",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Purong teksto",
- "echo-pref-notify-show-link": "Ipakita ang mga pabatid sa aking toolbar",
"echo-pref-new-message-indicator": "Ipakita ang indikador ng mga mensaheng pampahinang usapan sa aking toolbar",
"echo-learn-more": "Matuto pa",
"echo-new-messages": "Mayroon kang mga bagong mensahe",
@@ -36,62 +37,38 @@
"echo-pref-tooltip-edit-user-talk": "Ipabatid sa akin kung may nagpaskil ng mensahe o may tumugon sa aking pahinang usapan.",
"echo-pref-tooltip-article-linked": "Ipabatid sa akin kung may kumawing sa pahinang inilika ko mula sa isang pahina ng artikulo.",
"echo-pref-tooltip-mention": "Ipabatid sa aking kung may kumawing sa aking pahina ng tagagamit mula sa anumang pahinang usapan.",
- "echo-no-agent": "[Wala sinuman]",
- "echo-no-title": "[Walang pahina]",
+ "echo-pref-tooltip-article-reminder": "PakiTawag-Pansin mo ako kapag ito ay naitanong.",
"echo-error-no-formatter": "Walang itinakdang anyo para sa pabatid.",
- "echo-error-preference": "Kamalian: Hindi maitakda ang kagustuhan ng tagagamit.",
"notifications": "Mga pagpapabatid",
- "tooltip-pt-notifications": "Mga pabatid mo",
"echo-specialpage": "Mga pabatid",
"echo-anon": "Upang makatanggap ng mga pagpapabatid, [$1 lumikha ng isang account] o [$2 lumagdang papasok].",
"echo-none": "Wala kang mga pabatid.",
"echo-more-info": "Karagdagang impormasyon",
"echo-feedback": "Komentaryo",
+ "echo-notification-loginrequired": "Kailangan mong lumagda (login) upang makita ang iyong mga pabatid (notipikasyon)",
"notification-link-text-view-message": "Ipakita ang mensahe",
"notification-link-text-view-mention": "Ipakita ang pagbanggit",
"notification-link-text-view-changes": "Ipakita ang pagbabago",
"notification-link-text-view-page": "Ipakita ang pahina",
+ "notification-link-text-what-links-here": "Tingnan ang lahat ng mga kawing sa pahinang ito",
+ "notification-header-welcome": "{{GENDER:$2|Maligayang pagdating}} sa {{SITENAME}}, $1! Ikinalulugod naming {{GENDER:$2|ikaw ay}} narito.",
+ "notification-welcome-linktext": "Maligayang pagdating",
"notification-link-text-view-edit": "Ipakita ang pagbabago",
- "notification-edit-talk-page2": "{{GENDER:$1|Nag-iwan}} si [[User:$1|$1]] ng mensahe sa iyong [[User talk:$2#$3|pahinang usapan]].",
- "notification-edit-talk-page-with-section": "{{GENDER:$1|Nag-iwan}} si [[User:$1|$1]] ng mensahe sa iyong pahinang usapan sa seksiyong \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "{{GENDER:$1|Nag-iwan}} si $1 ng mensahe sa iyong [[User talk:$2#$3|pahinang usapan]].",
- "notification-edit-talk-page-flyout-with-section": "{{GENDER:$1|Nag-iwan}} si $1 ng mensahe sa iyong pahinang usapan sa seksiyong \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "{{GENDER:$1|Ikinawing}} ang [[:$2]] mula sa [[:$3]]. [[Special:WhatLinksHere/$2|Tingnan ang lahat ng kawing patungo sa pahinang ito.]]",
- "notification-page-linked-flyout": "{{GENDER:$1|Ikinawing}} ang [[:$2]] mula sa [[:$3]].",
- "notification-add-comment2": "{{GENDER:$1|Nagkomento}} si [[User:$1|$1]] sa seksiyong \"[[$3|$2]]\" ng pahinang usapan ng \"$4\".",
- "notification-add-talkpage-topic-yours2": "{{GENDER:$1|Ipinadala}} ka ni [[User:$1|$1]] ng mensahe: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "{{GENDER:$1|Nagkomento}} si [[User:$1|$1]] sa seksiyong \"[[$3#$2|$2]]\" sa iyong pahinang usapan.",
- "notification-mention": "{{GENDER:$1|Binanggit}} ka ni [[User:$1|$1]] sa pahinang usapan ng $5 sa seksiyong \"[[:$3#$2|$4]]\".",
- "notification-mention-flyout": "{{GENDER:$1|Binanggit}} ka ni $1 sa pahinang usapan ng $5 sa seksiyong \"[[:$3#$2|$4]]\".",
- "notification-user-rights": "[[Special:Log/rights/$1|{{GENDER:$1|Binago}}]] ni [[User:$1|$1]] ang iyong mga karapatang pantagagamit. $2. [[Special:ListGroupRights|Matuto pa]]",
- "notification-user-rights-flyout": "{{GENDER:$1|Binago}} ni $1 ang iyong mga karapatang pantagagamit. $2. [[Special:ListGroupRights|Matuto pa]]",
- "notification-user-rights-add": "Kasapi ka na ng {{PLURAL:$2|grupong ito|mga grupong ito}}: $1",
- "notification-user-rights-remove": "Hindi ka na kasapi ng {{PLURAL:$2|grupong ito|mga grupong ito}}: $1",
- "notification-new-user": "Maligayang pagdating sa {{SITENAME}}, $1! Masaya kami na nandito ka.",
+ "notification-link-article-reminder": "Paki-Lathala ang pahina",
+ "notification-header-reverted": "Ang iyong {{PLURAL:$4|edit noong $3 ay|mga edit noong $3 ay}} {{GENDER:$2|ipinanumbalik}} ni $1.",
"notification-edit-talk-page-email-subject2": "{{GENDER:$1|Nag-iwan}} si $1 ng mensahe para sa iyo sa {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|Nag-iwan}} si $1 ng mensahe sa iyong pahinang usapan:",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Nag-iwan}} si $1 ng mensahe sa iyong pahinang usapan sa \"$2\".",
"notification-page-linked-email-subject": "Ikinawing ang pahina mo sa {{SITENAME}}",
- "notification-page-linked-email-batch-body": "{{GENDER:$1|Ikinawing}} ang $2 mula sa $3.",
"notification-mention-email-subject": "{{GENDER:$1|Binanggit}} ka ni $1 sa {{SITENAME}}",
- "notification-mention-email-batch-body": "{{GENDER:$1|Binanggit}} ka ni $1 sa pahinang usapan ng $4 sa seksiyong \"$3\".",
"notification-user-rights-email-subject": "Nagbago ang iyong mga karapatang pantagagamit sa {{SITENAME}}",
- "notification-user-rights-email-batch-body": "{{GENDER:$1|Binago}} ni $1 ang iyong karapatang pantagagamit. $2.",
- "echo-email-subject-default": "Bagong pabatid sa {{SITENAME}}",
"echo-email-body-default": "Mayroon kang isang bagong pagpapabatid doon sa {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "May bago kang pabatid.",
"echo-email-footer-default": "$2\n\nUpang makontrol mo ang mga e-liham na ipinapadala namin sa iyo, tingnan ang iyong mga kagustuhan: {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Upang makontrol mo ang mga e-liham na ipinapadala namin sa iyo, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">tingnan ang iyong mga kagustuhan</a>.<br />\n$1",
"echo-overlay-link": "Lahat ng mga pabatid",
"echo-overlay-title": "<b>Mga pabatid</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Mga pabatid}}</b> (ipinapakita ang $1 ng $2 hindi pa nababasa)",
"echo-mark-all-as-read": "Tatakan ang lahat bilang nabasa na",
"echo-date-today": "Ngayon",
"echo-date-yesterday": "Kahapon",
- "notification-edit-talk-page-bundle": "{{GENDER:$1|Nag-iwan}} sina $1 at $3 {{PLURAL:$4|iba pa}} ng mensahe sa iyong [[User talk:$2|pahinang usapan]].",
- "notification-page-linked-bundle": "{{GENDER:$1|Ikinawing}} ang $2 mula sa $3 at $4 ibang {{PLURAL:$5|pahina}}. [[Special:WhatLinksHere/$2|Tingnan ang lahat ng kawing patungo sa pahinang ito]]",
- "notification-edit-user-talk-email-batch-bundle-body": "{{GENDER:$1|Nag-iwan}} sina $1 at $2 {{PLURAL:$3|iba pa}} ng mensahe sa iyong pahinang usapan.",
- "notification-page-linked-email-batch-bundle-body": "{{GENDER:$1|Ikinawing}} ang $2 mula sa $3 at $4 ibang {{PLURAL:$5|pahina}}.",
"echo-email-batch-subject-daily": "May {{PLURAL:$2|bago kang pabatid|mga bago kang pabatid}} sa {{SITENAME}}",
"echo-email-batch-subject-weekly": "May {{PLURAL:$2|bago kang pabatid|mga bago kang pabatid}} sa {{SITENAME}} ngayong linggo",
"echo-email-batch-body-intro-daily": "Magandang araw $1,\nIto ang buod ng mga gawain ngayon sa {{SITENAME}} para sa iyo.",
diff --git a/Echo/i18n/tr.json b/Echo/i18n/tr.json
index ff213b12..df24acca 100644
--- a/Echo/i18n/tr.json
+++ b/Echo/i18n/tr.json
@@ -11,14 +11,23 @@
"Arystanbek",
"Stultiwikia",
"KorkmazO",
- "McAang"
+ "McAang",
+ "HakanIST",
+ "Macofe",
+ "Sadrettin",
+ "MrSchipunov",
+ "Nemo bis",
+ "Serkanland",
+ "Ece Alpdeniz",
+ "Kumkumuk"
]
},
"echo-desc": "Kullanıcıları olaylar ve mesajlar hakkında bilgilendiren sistem",
"prefs-echo": "Bildirimler",
"prefs-emailsettings": "E-posta seçenekleri",
"prefs-displaynotifications": "Görüntüleme seçenekleri",
- "prefs-echosubscriptions": "Bu olaylar hakkında beni bilgilendir",
+ "prefs-echosubscriptions": "Bu olaylar hakkında bana bildirim gönder",
+ "prefs-echocrosswiki": "Vikilerarası bildirimler",
"prefs-newmessageindicator": "Yeni ileti göstergesi",
"echo-pref-send-me": "E-posta bildirim tercihi:",
"echo-pref-send-to": "Şuraya gönder:",
@@ -31,79 +40,136 @@
"echo-pref-email-frequency-weekly": "Bildirimlerin haftalık özetini gönder",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Düz metin",
+ "echo-pref-cross-wiki-notifications": "Diğer vikilerden bildirimleri göster",
"echo-pref-new-message-indicator": "Mesaj göstergesini araç çubuğumda göster",
+ "echo-pref-beta-feature-cross-wiki-message": "Gelişmiş bildirimler",
+ "echo-pref-beta-feature-cross-wiki-description": "Bildirimleri daha kolay görüntüleyin ve düzenleyin. Diğer vikilerdeki mesajlarınızı görmenize imkan veren vikilerarası bildirimleri destekler. (Vikilerarası bildirimleri almak için, bulunduğunuz vikide beta özelliği etkinleştirmeniz gerekir.)",
"echo-learn-more": "Daha fazla bilgi",
+ "echo-log": "Genel günlük",
"echo-new-messages": "Yeni mesajınız var",
"echo-category-title-edit-user-talk": "Tartışma sayfası {{PLURAL:$1|mesajı|mesajları}}",
"echo-category-title-article-linked": "Sayfa {{PLURAL:$1|bağlantısı|bağlantıları}}",
"echo-category-title-reverted": "Değişiklik {{PLURAL:$1|iptali|iptalleri}}",
"echo-category-title-mention": "{{PLURAL:$1|Bahsetme|Bahsetmeler}}",
+ "echo-category-title-mention-failure": "Başarısız {{PLURAL:$1|bahsetme|bahsetme}}",
+ "echo-category-title-mention-success": "Başarılı {{PLURAL:$1|bahsetme|bahsetmeler}}",
"echo-category-title-other": "{{PLURAL:$1|Diğer}}",
"echo-category-title-system": "{{PLURAL:$1|Sistem}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Kullanıcı hakları değişikliği|Kullanıcı hakları değişiklikleri}}",
- "echo-pref-tooltip-edit-user-talk": "Bir kullanıcı mesaj sayfamı değiştirdiğinde bunu bana bildir.",
- "echo-pref-tooltip-article-linked": "Oluşturduğum sayfalarda değişiklik yapıldığında bana bildir.",
- "echo-pref-tooltip-reverted": "Düzenleme yapıldıktan sonra geri alındığı takdirde bu durumu bana bildir.",
- "echo-pref-tooltip-mention": "Kullanıcı adıma bağlantı verildiğinde bunu bana bildir.",
- "echo-pref-tooltip-user-rights": "Kullanıcı haklarım değiştirildiğinde bunu bana bildir.",
- "echo-no-agent": "[Kimse]",
- "echo-no-title": "[Sayfa yok]",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Diğer kullanıcıdan gelen e-posta|Diğer kullanıcılardan gelen e-postalar}}",
+ "echo-pref-tooltip-edit-user-talk": "Bir kullanıcı mesaj sayfamı değiştirdiğinde bana bildirim gönder.",
+ "echo-pref-tooltip-article-linked": "Bir kullanıcı, bir maddeden benim oluşturduğum bir sayfaya bağlantı verdiğinde bana bildirim gönder.",
+ "echo-pref-tooltip-reverted": "Yaptığım bir değişiklik geri alındığı takdirde bana bildirim gönder.",
+ "echo-pref-tooltip-mention": "Kullanıcı sayfama bağlantı verildiğinde bana bildirim gönder.",
+ "echo-pref-tooltip-mention-failure": "Kullanıcılardan bahsetmelerim başarısız olduğunda bana bildirim gönder.",
+ "echo-pref-tooltip-mention-success": "Bir kullanıcıdan bahsettiğimde bana bildirim gönder.",
+ "echo-pref-tooltip-user-rights": "Bir kullanıcı, benim kullanıcı haklarımı değiştirirse bana bildirim gönder.",
+ "echo-pref-tooltip-emailuser": "Bir kullanıcı tarafıma e-posta gönderirse bana bildirim gönder.",
"echo-error-no-formatter": "Hiçbir bildirim için biçim tanımlanmamış.",
"notifications": "Bildirimler",
"tooltip-pt-notifications-alert": "{{GENDER:|Uyarılarınız}}",
- "tooltip-pt-notifications-message": "{{GENDER:|Mesajlarınız}}",
+ "tooltip-pt-notifications-notice": "Bildirimleriniz",
+ "echo-displaynotificationsconfiguration": "Bildirim ayarlarını görüntüle",
+ "echo-displaynotificationsconfiguration-summary": "Bu, bildirimlerin bu vikide nasıl yapılandırıldığına bir genel bakıştır.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Kategorilerine göre bildirimler",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Türleri belirleme",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Hangi bildirim türü hangi bölümde listelenecek",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "İzin verilen bildirim yöntemleri",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Her kategori için hangi bilidirim yöntemleri desteklenecek",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Hangi bildirim yöntemleri her tür için desteklenecek; sadece tercihlerde gizlenmiş kategorilerdeki türlere uygulanır.",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Varsayılan olarak etkin",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Mevcut kullanıcılar",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Yeni kullanıcılar",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Zorunlu bildirim yöntemleri",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Hangi bildirim yöntemleri ilgili kategori için zorunlu olacak",
"echo-specialpage": "Bildirimler",
+ "echo-specialpage-section-markread": "Grubu okunmuş olarak işaretle",
+ "echo-specialpage-markasread": "Bildirim: Okundu olarak İşaretle",
+ "echo-specialpage-markasread-invalid-id": "Geçersiz olay kimliği",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|bildirim|bildirim}}",
+ "echo-specialpage-pagefilters-title": "Son hareketler",
+ "echo-specialpage-pagefilters-subtitle": "Okunmamış bildirim bulunan sayfalar",
+ "notificationsmarkread-legend": "Bilidirimi okunmuş olarak işaretle",
"echo-anon": "Bildirimlere ulaşabilmek için, [$1 hesap oluşturun] ya da [$2 giriş yapın].",
"echo-none": "Bildiriminiz bulunmuyor.",
"echo-more-info": "Daha fazla bilgi",
"echo-feedback": "Geri bildirim",
+ "echo-popup-footer-special-page-invitation": "<strong>Yenilenen Bildirimler sayfasını deneyin.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Tamamen yeni görünüm ve özellikler.",
+ "echo-api-failure": "Bildirimler getirilemedi.",
+ "echo-api-failure-cross-wiki": "Uzak etki alanı için erişim engellendi.",
+ "echo-notification-placeholder": "Hiçbir bildirim yok.",
+ "echo-notification-placeholder-filters": "Bu kriterlere uyan herhangi bir bildirim yok.",
+ "echo-notification-loginrequired": "Bildirimlerinizi görmek için giriş yapmalısınız.",
+ "echo-notification-popup-loginrequired": "Bildirimlerinizi görmek için lütfen oturum açın.",
+ "echo-notification-markasread": "Okundu olarak işaretle",
+ "echo-notification-markasunread": "Okunmamış olarak işaretle",
+ "echo-notification-markasread-tooltip": "Okunmuş olarak işaretle",
+ "echo-notification-more-options-tooltip": "Daha fazla seçenek",
+ "notification-link-text-expand-all": "Genişlet",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 uyarı|$1 uyarı}} göster",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|$1 bildirim|$1 bildirim}} göster",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 bildirimi|$1 bildirimi}} görüntüle",
+ "notification-link-text-collapse-all": "Daralt",
"notification-link-text-view-message": "Mesajı görüntüle",
"notification-link-text-view-mention": "Bahsi görüntüle",
- "notification-link-text-view-changes": "Değişiklikleri görüntüle",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Bahsetmeyi göster|Bahsetmeleri göster}}",
+ "notification-link-text-view-changes": "Değişiklikleri {{GENDER:$1|görüntüle}}",
"notification-link-text-view-page": "Sayfayı görüntüle",
+ "notification-header-edit-user-talk": "$1, <strong>mesaj {{GENDER:$3|sayfanıza}}</strong> bir mesaj {{GENDER:$2|bıraktı}}.",
+ "notification-header-edit-user-talk-with-section": "$1, <strong>mesaj {{GENDER:$3|sayfanızdaki}}</strong> \"<strong>$4</strong>\" başlığına bir mesaj {{GENDER:$2|bıraktı}}.",
+ "notification-header-page-linked": "<strong>$4</strong> sayfasından <strong>$3</strong> sayfasına bağlantı verildi.",
+ "notification-compact-header-page-linked": "<strong>$1</strong> bağlantılı.",
+ "notification-bundle-header-page-linked": "'''$4''' ve $5 diğer {{ÇOĞUL:$6|sayfadan|sayfadan}}, '''$3''' sayfasına bağlantı verildi.",
+ "notification-link-text-what-links-here": "Bu sayfaya verilen tüm bağlantılar",
+ "notification-header-mention-other": "$1, <strong>$4</strong> sayfasının \"<strong>$5</strong>\" başlığında {{GENDER:$3|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-header-mention-other-nosection": "$1, <strong>$4</strong> sayfasıda {{GENDER:$3|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-header-mention-user-talkpage-v2": "$1, '''$4 {{GENDER:$5|kulanıcısının}} mesaj sayfasının''' \"'''$6'''\" başlığında {{GENDER:$3|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-header-mention-user-talkpage-nosection": "$1, '''$4 {{GENDER:$5|kulanıcısının}} mesaj sayfasında''' {{GENDER:$3|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-header-mention-agent-talkpage": "$1, <strong>$2 kullanıcısının mesaj sayfasındaki</strong> \"<strong>$4</strong>\" başlığında {{GENDER:$3|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-header-mention-agent-talkpage-nosection": "$1, <strong>{{GENDER:$2|kendi mesaj sayfasında}}</strong> {{GENDER:$3|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-header-mention-article-talkpage": "$1, <strong>$4</strong> tartışma sayfasının \"<strong>$5</strong>\" başlığında {{GENDER:$3|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-header-mention-article-talkpage-nosection": "$1, <strong>$4</strong> sayfasının tartışmasında {{GENDER:$3|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Kullanıcı adı mevcut değil:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP'lerden bahsedilemez:</strong> $1",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Kullanıcı}} haklarınız {{GENDER:$1|değiştirildi}}. Eklendiğiniz yer: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Kullanıcı}} haklarınız {{GENDER:$1|değiştirildi}}. Çıkarıldığınız yer: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Kullanıcı}} haklarınız {{GENDER:$1|değiştirildi}}. Eklendiğiniz yer: $2. Çıkarıldığınız yer: $4.",
+ "notification-header-welcome": "{{SITENAME}}'ye {{GENDER:$2|hoş geldin}} $1! Burada olmandan çok memnunuz.",
+ "notification-welcome-linktext": "Hoş geldiniz",
+ "notification-header-thank-you-1-edit": "İlk {{GENDER:$2|değişikliğinizi}} {{GENDER:$2|yaptınız}}; teşekkürler ve hoş geldiniz!",
+ "notification-header-thank-you-10-edit": "Onuncu {{GENDER:$2|değişikliğinizi}} {{GENDER:$2|yaptınız}}; teşekkürler, lütfen devam edin!",
+ "notification-header-thank-you-100-edit": "Yüzüncü {{GENDER:$2|değişikliğinizi}} {{GENDER:$2|yaptınız}}; çok teşekkürler!",
+ "notification-header-thank-you-1000-edit": "Bininci {{GENDER:$2|değişikliğinizi}} {{GENDER:$2|yaptınız}}; büyük katkınız için çok teşekkürler!",
+ "notification-header-thank-you-10000-edit": "On bininci {{GENDER:$2|değişikliğinizi}} {{GENDER:$2|yaptınız}}; çok çok teşekkürler!",
+ "notification-header-thank-you-100000-edit": "Yüz bininci {{GENDER:$2|değişikliğinizi}} {{GENDER:$2|yaptınız}}; inanılmaz katkınız için teşekkürler!",
+ "notification-header-thank-you-1000000-edit": "Bir milyonuncu {{GENDER:$2|değişikliğinizi}} {{GENDER:$2|yaptınız}}; ağızları açık bırakan katkınız için teşekkürler!",
"notification-link-text-view-edit": "Değişikliği görüntüle",
- "notification-edit-talk-page2": "[[User:$1|$1]], [[User talk:$2#$3|mesaj sayfanıza]] yeni bir mesaj {{GENDER:$1|bıraktı}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]], mesaj sayfanızın \"[[User talk:$2#$3|$4]]\" başlığına bir mesaj {{GENDER:$1|bıraktı}}.",
- "notification-edit-talk-page-flyout2": "$1, [[User talk:$2#$3|mesaj sayfanıza]] bir mesaj {{GENDER:$1|bıraktı}}.",
- "notification-edit-talk-page-flyout-with-section": "$1, mesaj sayfanızdaki \"[[User talk:$2#$3|$4]]\" başlığına bir mesaj {{GENDER:$1|bıraktı}}.",
- "notification-page-linked": "[[:$2]] sayfasına [[:$3]] sayfasından {{GENDER:$1|bağlantı verildi}}. [[Special:WhatLinksHere/$2|Bu sayfaya bağlantı veren tüm sayfaları görüntüleyin]].",
- "notification-page-linked-flyout": "[[:$2]] sayfasına [[:$3]] sayfasından {{GENDER:$1|bağlantı verildi}}.",
- "notification-add-comment2": "[[User:$1|$1]], \"$4\" mesaj sayfasındaki \"[[$3|$2]]\" bölümüne {{GENDER:$1|yorum yaptı}}.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{CİNSİYET:$1|yayınlanan}} yeni bir konu,\"$2\" [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] size bir mesaj {{GENDER:$1|gönderdi}}: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]], mesaj sayfanızdaki \"[[$3#$2|$2]]\" konusuna {{GENDER:$1|yorum yaptı}}.",
- "notification-mention": "[[User:$1|$1]], $5 sayfasının tartışma sayfasının \"[[:$3#$2|$4]]\" başlığında sizden {{GENDER:$1|bahsetti}}.",
- "notification-mention-flyout": "$1, $5 sayfasının tartışma sayfasının \"[[:$3#$2|$4]]\" başlığında sizden {{GENDER:$1|bahsetti}}.",
- "notification-mention-nosection": "[[User:$1|$1]] {{CİNSİYET:$1|söz}} [[:$3|$2 tartışma sayfası]].",
- "notification-mention-nosection-flyout": "$1, [[:$3|$2 başlıklı tartışma sayfasında]] sizden {{GENDER:$1|bahsetti}}.",
- "notification-user-rights": "Kullanıcı haklarınız [[User:$1|$1]] tarafından [[Special:Log/rights/$1|{{GENDER:$1|değiştirildi}}]]. $2. [[Special:ListGroupRights|Daha fazla bilgi]]",
- "notification-user-rights-flyout": "Kullanıcı haklarınız $1 tarafından {{GENDER:$1|değiştirildi}}. $2. [[Special:ListGroupRights|Daha fazla bilgi alın]]",
- "notification-user-rights-add": "Artık {{PLURAL:$2|bu grubun|bu grupların}} üyesisiniz: $1",
- "notification-user-rights-remove": "Artık {{PLURAL:$2|bu grubun|bu grupların}} üyesi değilsiniz: $1",
- "notification-new-user": "Hoş geldin $1! Sizi burada görmekten memnun olduk.",
- "notification-reverted2": "{{PLURAL:$4|[[:$2]] sayfasındaki değişikliğiniz|[[:$2]] sayfasındaki değişiklikleriniz}} [[User:$1|$1]] tarafından {{GENDER:$1|geri alındı}}. $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|$2 sayfasındaki değişikliğiniz|$2 sayfasındaki değişiklikleriniz}}, $1 tarafından {{GENDER:$1|geri alındı}}. $3",
+ "notification-header-reverted": "{{PLURAL:$4|$3 sayfasındaki değişikliğiniz|$3 sayfasındaki değişiklikleriniz}}, $1 tarafından {{GENDER:$2|geri alındı}}.",
+ "notification-header-emailuser": "$1 size bir e-posta {{GENDER:$2|gönderdi}}.",
"notification-edit-talk-page-email-subject2": "$1, {{SITENAME}} sayfasında size bir mesaj {{GENDER:$1|bıraktı}}",
- "notification-edit-talk-page-email-batch-body2": "$1, mesaj sayfanıza bir mesaj {{GENDER:$1|bıraktı}}.",
"notification-edit-talk-page-email-batch-body-with-section": "$1, mesaj sayfanızın \"$2\" başlığında bir mesaj {{GENDER:$1|bıraktı}}.",
"notification-page-linked-email-subject": "Sayfanıza {{SITENAME}} sitesinde bağlantı verildi",
- "notification-page-linked-email-batch-body": "$2 sayfasına $3 sayfasından {{GENDER:$1|bağlantı verildi}}.",
"notification-reverted-email-subject2": "Eğer {{ÇOĞUL:$3|Düzenle|düzenleme yapıldı}} {{CİNSİYET:$1|döndürüldü}} {{SITENAME}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|$2 sayfasındaki değişikliğiniz|$2 sayfasındaki $3 değişikliğiniz}} $1 tarafından geri alındı.",
- "notification-mention-email-subject": "$1, {{SITENAME}} sitesinde sizden {{GENDER:$1|bahsetti}}",
- "notification-mention-email-batch-body": "$1, $4 sayfasının tartışma sayfasının \"$3\" başlığında sizden {{GENDER:$1|bahsetti}}.",
- "notification-mention-nosection-email-batch-body": "$1 {{CİNSİYET:$1|söz}} tarihinde $2 mesaj sayfası.",
+ "notification-mention-email-subject": "$1, {{SITENAME}} sitesinde {{GENDER:$2|sizden}} {{GENDER:$1|bahsetti}}",
"notification-user-rights-email-subject": "{{SITENAME}} için kullanıcı hakları değişmiştir",
- "notification-user-rights-email-batch-body": "Kullanıcı haklarınız $1 tarafından {{GENDER:$1|değiştirildi}}. $2",
- "echo-email-subject-default": "{{SITENAME}} için yeni bildirim",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1d}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1sa}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1g}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1ay}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1yıl}}",
+ "notification-timestamp-today": "Bugün",
+ "notification-timestamp-yesterday": "Dün",
+ "notification-inbox-filter-read": "Okunan",
+ "notification-inbox-filter-unread": "Okunmamış",
+ "notification-inbox-filter-all": "Tümü",
"echo-email-body-default": "{{SITENAME}} için yeni bildiriminiz var:\n\n$1",
- "echo-email-batch-body-default": "Yeni bir bildiriminiz var",
"echo-email-footer-default": "$2\n\nSize gönderdiğimiz e-postaları kontrol etmek için, tercihlerinizi kontrol edin:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Size gönderdiğimiz e-postaları kontrol etmek için, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">tercihlerinizi kontrol edin</a>.<br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|Uayrı ($1)|Uyarılar ($1)|100=Uyarılar (99+)}}",
- "echo-notification-message": "{{ÇOĞUL:$1|Mesaj ($1)|Mesaj ($1)|100=Mesajlar (99+)}}",
+ "echo-email-html-footer-preference-link-text": "tercihlerinizi kontrol edin",
+ "echo-notification-alert": "{{PLURAL:$1|Uyarı ($1)|Uyarılar ($1)|100=Uyarılar (99+)}}",
"echo-notification-alert-text-only": "Uyarılar",
- "echo-notification-message-text-only": "İletiler",
+ "echo-notification-notice-text-only": "Bildirimler",
"echo-overlay-link": "Bütün bildirimler",
"echo-overlay-title": "<b>Bildirimler</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Bildirimler}}</b> ($2 okunmayandan $1 adeti gösteriliyor)",
@@ -111,36 +177,12 @@
"echo-date-today": "Bugün",
"echo-date-yesterday": "Dün",
"echo-load-more-error": "Daha fazla sonuç oluşturma esnasında bir hata oluştu.",
- "notification-edit-talk-page-bundle": "$1 ve diğer $3 {{PLURAL:$4|kullanıcı}}, [[User talk:$2|mesaj sayfanıza]] bir mesaj {{GENDER:$1|bıraktı}}.",
- "notification-page-linked-bundle": "$2 sayfasına $3 sayfası ve diğer $4 {{PLURAL:$5|sayfadan|sayfadan}} {{GENDER:$1|bağlantı verildi}}. [[Special:WhatLinksHere/$2|Bu sayfaya bağlantı veren tüm sayfaları görüntüleyin]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 ve diğer $2 {{PLURAL:$3|kullanıcı}}, mesaj sayfanıza bir mesaj {{GENDER:$1|bıraktı}}.",
- "notification-page-linked-email-batch-bundle-body": "$2 sayfasına $3 sayfası ve diğer $4 {{PLURAL:$5|sayfadan|sayfadan}} {{GENDER:$1|bağlantı verildi}}.",
+ "notification-bundle-header-edit-user-talk-v2": "Mesaj {{GENDER:$3|sayfanızda}} $1 yeni {{PLURAL:$2|mesaj|mesaj}} var.",
"echo-email-batch-subject-daily": "{{SITENAME}} sitesinde {{PLURAL:$2|yeni bir bildiriminiz|yeni bildirimleriniz}} var",
"echo-email-batch-subject-weekly": "Bu hafta {{SITENAME}} sitesinde {{PLURAL:$2|yeni bir bildiriminiz|yeni bildirimleriniz}} var",
"echo-email-batch-body-intro-daily": "Merhaba $1,\nBurada {{SITENAME}} için bu günün etkinlik özetini bulabilirsiniz.",
"echo-email-batch-body-intro-weekly": "Merhaba $1,\nBurada {{SITENAME}} için bu haftaki etkinlik özetini bulabilirsiniz.",
"echo-email-batch-link-text-view-all-notifications": "Tüm bildirimleri göster",
- "echo-rev-deleted-text-view": "Bu sayfa sürümü kaldırıldı.",
- "apihelp-echomarkread-description": "Geçerli kullanıcı için okundu olarak işaretle bildirimleri.",
- "apihelp-echomarkread-param-list": "Okundu olarak işaretlemek için bildirim Kimliklerinin bir listesini.",
- "apihelp-echomarkread-param-all": "Set, okumak gibi bir kullanıcı Bildirimleri tüm işaretler.",
- "apihelp-echomarkread-param-sections": "Okundu olarak işaretlemek için bölümler bir listesini.",
- "apihelp-echomarkread-example-1": "Mark bildirim 8 gibi okumak",
- "apihelp-echomarkread-example-2": "Tüm bildirimleri okunmuş olarak işaretle",
- "apihelp-echomarkseen-description": "Geçerli kullanıcı için görüldüğü gibi Mark bildirimleri.",
- "apihelp-echomarkseen-example-1": "Her tür bildirimi okundu olarak işaretle",
- "apihelp-echomarkseen-param-type": "'Uyarı', 'mesaj' ya da 'tümü' olarak işaretlemek için bildirimlerin türü.",
- "apihelp-query+notifications-description": "Bildirimler, geçerli kullanıcı için bekliyor.",
- "apihelp-query+notifications-param-prop": "İstek detayları.",
- "apihelp-query+notifications-param-sections": "Sorgu için bildirim bölümleri (örneğin bazı 'uyarı' ve 'mesaj'kombinasyonu)",
- "apihelp-query+notifications-param-groupbysection": "Olsun bölüm sonuç grup için. Her bölüm set halinde ayrı ayrı getirildi.",
- "apihelp-query+notifications-param-format": "Belirtilmişse, bildirimleri biçimlendirilmiş bu şekilde iade edilecektir.",
- "apihelp-query+notifications-param-limit": "Gösterilebilecek azami bildirim sayısı.",
- "apihelp-query+notifications-param-index": "Belirtilmişse, bildirim listesi Kimlikleri, sipariş, iade edilecektir.",
- "apihelp-query+notifications-param-alertcontinue": "Daha uyanık sonuçlar mevcut olduğunda, bu devam etmek için kullanın.",
- "apihelp-query+notifications-param-alertunreadfirst": "İster okunmamış mesaj bildirimlerini göstermek.",
- "apihelp-query+notifications-param-messagecontinue": "Daha fazla ileti sonuçlar mevcut olduğunda, bu devam etmek için kullanın.",
- "apihelp-query+notifications-param-messageunreadfirst": "İster okunmamış uyarı bildirimleri göstermek.",
- "apihelp-query+notifications-example-1": "Liste bildirimleri",
- "apihelp-query+notifications-example-2": "{{delete}}\nBildirimler, bölüm tarafından gruplandırılmış, sayıları ile listesi"
+ "notification-header-foreign-alert": "{{PLURAL:$5|$5 diğer Viki projesinden}} uyarınız var",
+ "notification-header-foreign-notice": "{{PLURAL:$5|diğer viki|$5 diğer viki}}den daha fazla sonuç"
}
diff --git a/Echo/i18n/tt-cyrl.json b/Echo/i18n/tt-cyrl.json
index 29d015c2..157f543a 100644
--- a/Echo/i18n/tt-cyrl.json
+++ b/Echo/i18n/tt-cyrl.json
@@ -2,27 +2,97 @@
"@metadata": {
"authors": [
"Ilnur efende",
- "Ильнар"
+ "Ильнар",
+ "Macofe"
]
},
- "prefs-echo": "Яңалыклар",
- "notifications": "Яңалыклар",
+ "prefs-echo": "Белдерүләр",
+ "prefs-emailsettings": "E-mail көйләнмәләре",
+ "prefs-displaynotifications": "Күрсәтү көйләнмәләре",
+ "prefs-echosubscriptions": "Миңа бу вакыйгалар турында хәбәр итәргә",
+ "prefs-echocrosswiki": "Кросс-вики белдерүләр",
+ "prefs-newmessageindicator": "Яңа хатлар белдерүе",
+ "echo-pref-send-me": "Миңа җибәрү:",
+ "echo-pref-send-to": "Җибәрер өчен:",
+ "echo-pref-email-format": "Хатлар төре:",
+ "echo-pref-web": "Веб",
+ "echo-pref-email": "Электрон почта",
+ "echo-pref-email-format-html": "HTML",
+ "echo-pref-email-format-plain-text": "Гади текст",
+ "echo-pref-cross-wiki-notifications": "Бүтән викилардагы белдерүләрне күрсәтергә",
+ "echo-pref-new-message-indicator": "Бәхәс битемдә хатлар килуе турында белдерүне кораллар өлгесендә күрсәтү",
+ "echo-pref-beta-feature-cross-wiki-message": "Киңәйтелгән белдерүләр",
+ "echo-learn-more": "Күбрәк белү",
+ "echo-log": "Гомуми көндәлек",
+ "echo-new-messages": "Сезнең яңа хатларыгыз бар",
+ "echo-category-title-edit-user-talk": "Бәхәс битендә {{PLURAL:$1|хат}}",
+ "echo-category-title-article-linked": "Битләргә {{PLURAL:$1|сылтама}}",
+ "echo-category-title-reverted": "Үзгәртүләрне {{PLURAL:$1|кире кагу}}",
+ "echo-category-title-mention": "{{PLURAL:$1|1=Искәртмә|Искәртмәләр}}",
+ "echo-category-title-other": "{{PLURAL:$1|Башкалар}}",
+ "echo-category-title-system": "{{PLURAL:$1|Системалы}}",
+ "echo-category-title-user-rights": "Кулланучы хокукларын {{PLURAL:$1|үзгәртү}}",
+ "echo-category-title-emailuser": "Башка {{PLURAL:$1|кулланучыдан|кулланучылардан}} электрон хат",
+ "notifications": "Белдерүләр",
"tooltip-pt-notifications-alert": "{{GENDER:|Сезнең}} искәртүләр",
- "tooltip-pt-notifications-message": "{{GENDER:|Сезнең}} хатлар",
- "echo-specialpage": "Яңалыклар",
- "notification-link-text-view-changes": "Үзгәртүләрне карау",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Сезнең}} белдерүләр",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Яңа кулланучылар",
+ "echo-specialpage": "Белдерүләр",
+ "echo-specialpage-section-markread": "Төркемне укылган дип санарга",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|белдерү}}",
+ "echo-specialpage-pagefilters-title": "Соңгы гамәлләр",
+ "echo-specialpage-pagefilters-subtitle": "Каралмаган белдерүле битләр",
+ "notificationsmarkread-legend": "Белдерүләрне укылган дип билгеләү",
+ "echo-none": "Сез белдерүләр алмагансыз.",
+ "echo-more-info": "Тулырак",
+ "echo-feedback": "Аралашу",
+ "echo-notification-placeholder": "Белдерүләр юк.",
+ "echo-notification-placeholder-filters": "Критерийларга туры килүче билдерүләр юк.",
+ "echo-notification-markasread": "Укылган итеп билгеләү",
+ "echo-notification-markasunread": "Укылмаган дип билгеләү",
+ "echo-notification-markasread-tooltip": "Укылган итеп билгеләү",
+ "echo-notification-more-options-tooltip": "Өстәмә гамәлләр",
+ "notification-link-text-expand-all": "Ачу",
+ "notification-link-text-expand-alert-count": "{{PLURAL:$1|$1 искәртүне}} карау",
+ "notification-link-text-expand-notice-count": "{{PLURAL:$1|$1 белдерүне}} карау",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 белдерүне}} карау",
+ "notification-link-text-collapse-all": "Төрү",
+ "notification-link-text-view-message": "Хатны карау",
+ "notification-link-text-view-mention": "Искәртүне карау",
+ "notification-link-text-view-changes": "Үзгәртүләрне {{GENDER:$1|карау}}",
+ "notification-link-text-view-page": "Битне карау",
+ "notification-header-edit-user-talk": "$1 <strong>{{GENDER:$3|сезнең}} бәхәс битегездә</strong> хат {{GENDER:$2|калдырды}}.",
+ "notification-header-edit-user-talk-with-section": "$1 <strong>{{GENDER:$3|сезнең}} бәхәс битегездә</strong> «<strong>$4</strong>» хат {{GENDER:$2|калдырды}}.",
+ "notification-header-mention-other": "$1 {{GENDER:$3|сезне}} <strong>$4</strong> битендәге «<strong>$5</strong>» бүлегендә {{GENDER:$2|телгә}} алды.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$3|сезне}} <strong>{{GENDER:$5|$4}} бәхәс битендә</strong> {{GENDER:$2|телгә}} алды.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$3|сезне}} «$4» бәхәс битендә {{GENDER:$2|телгә}} алды.",
+ "notification-welcome-linktext": "Рәхим итегез!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Сезнең}} төзәтмә",
"notification-link-text-view-edit": "Үзгәртүне карау",
- "notification-edit-talk-page2": "[[User:$1|$1]] сезнең [[User talk:$2#$3|бәхәс битегездә]] хат {{GENDER:$1|калдырды}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] сезнең бәхәс битегездә \"[[User talk:$2#$3|$4]]\" хат {{GENDER:$1|калдырды}}.",
- "notification-edit-talk-page-flyout2": "$1 сезнең [[User talk:$2#$3|бәхәс битегездә]] хат {{GENDER:$1|калдырды}}.",
- "notification-edit-talk-page-flyout-with-section": "$1 сезнең бәхәс битегездә \"[[User talk:$2#$3|$4]]\" хат {{GENDER:$1|калдырды}}.",
- "notification-mention": "[[User:$1|$1]] $5 бәхәс битенең \"[[:$3#$2|$4]]\" бүлегендә сезне искә алды.",
- "notification-mention-flyout": "[[User:$1|$1]] $5 бәхәс битенең \"[[:$3#$2|$4]]\" бүлегендә сезне искә алды.",
- "notification-mention-nosection": "[[User:$1|$1]] сезне [[:$3|$2 бәхәс битендә]] искә алды.",
- "notification-mention-nosection-flyout": "$1 сезне [[:$3| $2 бәхәс битендә]] искә алды.",
- "notification-edit-talk-page-email-batch-body2": "{{GENDER:$1|Кулланучы}} $1 сезнең бәхәс битегездә хат {{GENDER:$1|калдырды}}.",
+ "notification-header-reverted": "Сезнең <strong>$3</strong> битендә ясалган {{PLURAL:$4|1=төзәтмәләгез|төзәтмәләрегез}} {{GENDER:$2|{{PLURAL:$4|кире кагылды}}}}.",
"notification-edit-talk-page-email-batch-body-with-section": "{{GENDER:$1|Кулланучы}} $1 сезгә «$2» темасының бәхәс битендә хат {{GENDER:$1|калдырды}}",
- "notification-mention-nosection-email-batch-body": "$1 сезне $2 бәхәс битендә искә алды.",
+ "notification-mention-email-subject": "$1 {{GENDER:$2|сезне}} на сайте «{{SITENAME}}» сәхтфәсендә {{GENDER:$1|искә алды}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 с}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 мин}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 сәг}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 көн}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 ай}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 ел}}",
+ "notification-timestamp-today": "Бүген",
+ "notification-timestamp-yesterday": "Кичә",
+ "notification-inbox-filter-read": "Укылган",
+ "notification-inbox-filter-unread": "Укылмаган",
+ "notification-inbox-filter-all": "Барысы",
+ "echo-email-body-default": "Сезнең «{{SITENAME}}» сайтында яңа белдерү бар:\n\n$1",
+ "echo-notification-alert": "{{PLURAL:$1|Искәртү ($1)|Искәртүләр ($1)|100=Искәртүләр (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Белдерү ($1)|Белдерүләр ($1)|100=Белдерүләр (99+)}}",
+ "echo-notification-alert-text-only": "Искәртүләр",
+ "echo-notification-notice-text-only": "Белдерүләр",
+ "echo-overlay-link": "Барлык белдерүләр",
+ "echo-overlay-title": "<b>Белдерүләр</b>",
+ "echo-mark-all-as-read": "Барсын да укылган итеп билгеләү",
+ "echo-date-today": "Бүген",
"echo-date-yesterday": "Кичә",
- "notification-edit-talk-page-bundle": "$1 һәм тагын $3 кулланучы сезнең [[User talk:$2|бәхәс битендә]] хәбәр калдырганнар."
+ "notification-bundle-header-edit-user-talk-v2": "<strong>{{GENDER:$3|Сезнең}} бәхәс битегездә</strong> {{PLURAL:$1|яңа хат|$1 яңа хат|100=99+ яңа хат}}.",
+ "echo-email-batch-link-text-view-all-notifications": "Барлык белдерүләрне карау"
}
diff --git a/Echo/i18n/tt-latn.json b/Echo/i18n/tt-latn.json
new file mode 100644
index 00000000..36a97b55
--- /dev/null
+++ b/Echo/i18n/tt-latn.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Frhdkazan"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "{{GENDER:|Sezneñ}} belderüläregez",
+ "tooltip-pt-notifications-message": "{{GENDER:|Sezneñ}} xatlarığız"
+}
diff --git a/Echo/i18n/udm.json b/Echo/i18n/udm.json
index d5fdd254..3cba93c6 100644
--- a/Echo/i18n/udm.json
+++ b/Echo/i18n/udm.json
@@ -1,9 +1,11 @@
{
"@metadata": {
"authors": [
- "AlnashPiyash2"
+ "AlnashPiyash2",
+ "Kaganer",
+ "Wadorgurt"
]
},
- "notification-edit-talk-page2": "[[User:$1|$1]] гожтӥз тӥляд [[User talk:$2#$3|вераськон бамады]].",
- "notification-page-linked-flyout": "[[:$2]] вал {{GENDER:$1|герӟамын}} [[:$3]]."
+ "tooltip-pt-notifications-alert": "{{GENDER:|Тӥляд}} ивортонъёсты",
+ "notification-inbox-filter-all": "Ваньзэ"
}
diff --git a/Echo/i18n/ug-arab.json b/Echo/i18n/ug-arab.json
index 960fd0ba..013e9fe3 100644
--- a/Echo/i18n/ug-arab.json
+++ b/Echo/i18n/ug-arab.json
@@ -1,12 +1,14 @@
{
"@metadata": {
"authors": [
- "Sahran"
+ "Sahran",
+ "Uzdil"
]
},
"prefs-echo": "ئۇقتۇرۇشلار",
"prefs-displaynotifications": "كۆرسىتىش تاللانما",
"notifications": "ئۇقتۇرۇشلار",
+ "tooltip-pt-notifications-alert": "{{GENDER:|سىزنىڭ}} ئەسكەرتىشىڭىز",
"echo-date-today": "بۈگۈن",
"echo-date-yesterday": "تۈنۈگۈن"
}
diff --git a/Echo/i18n/uk.json b/Echo/i18n/uk.json
index bdb2319a..0d3f0e4c 100644
--- a/Echo/i18n/uk.json
+++ b/Echo/i18n/uk.json
@@ -9,7 +9,14 @@
"Steve.rusyn",
"SteveR",
"Ата",
- "Piramidion"
+ "Piramidion",
+ "NickK",
+ "Lxlalexlxl",
+ "Максим Підліснюк",
+ "Macofe",
+ "Green Zero",
+ "Amire80",
+ "SimondR"
]
},
"echo-desc": "Система сповіщення користувачів про події і повідомлення",
@@ -17,7 +24,9 @@
"prefs-emailsettings": "Параметри електронної пошти",
"prefs-displaynotifications": "Опції відображення",
"prefs-echosubscriptions": "Повідомляти мене про ці події",
+ "prefs-echocrosswiki": "Крос-вікі сповіщення",
"prefs-newmessageindicator": "Індикатор нових повідомлень",
+ "prefs-blocknotificationslist": "Ігноровані користувачі",
"echo-pref-send-me": "Надіслати мені:",
"echo-pref-send-to": "Надіслати до:",
"echo-pref-email-format": "Формат листів:",
@@ -29,115 +38,178 @@
"echo-pref-email-frequency-weekly": "Щомісячна збірка сповіщень",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Простий текст",
+ "echo-pref-cross-wiki-notifications": "Показувати сповіщення з інших вікі",
+ "echo-pref-notifications-blacklist": "Не показувати сповіщень від цих користувачів. ([[mw:Help:Notifications#mute|дізнайтесь більше]])",
"echo-pref-new-message-indicator": "Показувати індикатор повідомлень на сторінці обговорення у моїй панелі інструментів",
+ "echo-pref-beta-feature-cross-wiki-message": "Розширені сповіщення",
+ "echo-pref-beta-feature-cross-wiki-description": "Переглядайте і сортуйте сповіщення простіше. Містить крос-вікі сповіщення, які дають змогу бачити повідомлення з інших вікі. (Щоб отримувати крос-вікі сповіщення у певній вікі, Ви маєте активувати бета-функцію у цій вікі).",
"echo-learn-more": "Дізнатися більше",
+ "echo-log": "Публічний журнал",
"echo-new-messages": "У Вас є нові повідомлення",
"echo-category-title-edit-user-talk": "{{PLURAL:$1|Повідомлення|Повідомлення|Повідомлень}} на сторінці обговорення",
- "echo-category-title-article-linked": "{{PLURAL:$1|посилання}} на сторінку",
- "echo-category-title-reverted": "{{PLURAL:$1|скасування|скасування|скасувань}} редагувань",
- "echo-category-title-mention": "{{PLURAL:$1|згадування}}",
+ "echo-category-title-article-linked": "{{PLURAL:$1|Посилання}} на сторінку",
+ "echo-category-title-reverted": "Скасування {{PLURAL:$1|редагування|редагувань}}",
+ "echo-category-title-mention": "{{PLURAL:$1|Згадування}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Невдале згадування|Невдалі згадування}}",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Успішне згадування|Успішні згадування}}",
"echo-category-title-other": "{{PLURAL:$1|інше}}",
"echo-category-title-system": "{{PLURAL:$1|системне}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Зміна прав користувача|Зміни прав користувача}}",
- "echo-pref-tooltip-edit-user-talk": "Повідомляти мене, коли хтось надіслав повідомлення або відповів на моїй сторінці обговорення.",
- "echo-pref-tooltip-article-linked": "Повідомляти мене, коли хтось зробив посилання на створену мною сторінку.",
- "echo-pref-tooltip-reverted": "Повідомляти мене, коли хтось відкинув моє редагування з допомогою скасування чи відкату.",
- "echo-pref-tooltip-mention": "Повідомляти мене, коли хтось зробив посилання на мою сторінку користувача.",
- "echo-pref-tooltip-user-rights": "Сповіщати мене, коли хтось змінює мої права користувача.",
- "echo-no-agent": "[Ніхто]",
- "echo-no-title": "[Нема сторінки]",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Електронний лист від іншого користувача|Електронні листи від інших користувачів}}",
+ "echo-category-title-article-reminder": "{{PLURAL:$1|Нагадування}} про сторінки",
+ "echo-pref-tooltip-edit-user-talk": "Повідомляти мене, коли хтось надсилає повідомлення або відповідає на моїй сторінці обговорення.",
+ "echo-pref-tooltip-article-linked": "Повідомляти мене, коли хтось додає на іншу сторінку посилання на створену мною сторінку.",
+ "echo-pref-tooltip-reverted": "Повідомляти мене, коли хтось відхиляє моє редагування за допомогою скасування чи відкату.",
+ "echo-pref-tooltip-mention": "Повідомляти мене, коли хтось посилається на мою сторінку користувача.",
+ "echo-pref-tooltip-mention-failure": "Повідомити мене, коли мені не вдалося відправити згадку кого-небудь.",
+ "echo-pref-tooltip-mention-success": "Повідомляти мене, коли я надсилаю згадку кого-небудь.",
+ "echo-pref-tooltip-user-rights": "Повідомляти мене, коли хтось змінює мої права користувача.",
+ "echo-pref-tooltip-emailuser": "Повідомляти мене, коли хтось надсилає мені електронного листа.",
+ "echo-pref-tooltip-article-reminder": "Повідомити мене про цю сторінку, коли я попрошу.",
"echo-error-no-formatter": "Не визначено формату сповіщень",
"notifications": "Сповіщення",
- "tooltip-pt-notifications-alert": "{{GENDER:|Ваші}} сповіщення",
- "tooltip-pt-notifications-message": "{{GENDER:|Ваші}} повідомлення",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Ваші}} звістки",
+ "tooltip-pt-notifications-notice": "{{GENDER:|Ваші}} сповіщення",
+ "echo-displaynotificationsconfiguration": "Показати налаштування сповіщень",
+ "echo-displaynotificationsconfiguration-summary": "Це огляд налаштувань сповіщень у цій вікі.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Сповіщення за категоріями",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Сортування типів",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Куди стортується кожен тип сповіщень",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Дозволені способи сповіщення",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Які способи сповіщення підтримуються для кожної категорії",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Які способи сповіщення підтримуються для кожного типу; застосовується тільки для типів у межах категорій, які приховані з налаштувань",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Увімкнено за замовчуванням",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Наявні користувачі",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Нові користувачі",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Обов'язкові методи сповіщення",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Які способи сповіщення є обов'язковими для кожної категорії",
"echo-specialpage": "Сповіщення",
+ "echo-specialpage-section-markread": "Позначити групу прочитаною",
+ "echo-specialpage-markasread": "Сповіщення: позначити прочитаним",
+ "echo-specialpage-markasread-invalid-id": "Неправильний ідентифікатор події",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|сповіщення|сповіщення|сповіщень}}",
+ "echo-specialpage-pagefilters-title": "Нещодавня активність",
+ "echo-specialpage-pagefilters-subtitle": "Сторінки з непрочитаними сповіщеннями",
+ "notificationsmarkread-legend": "Позначити сповіщення прочитаним",
"echo-anon": "Для отримання сповіщень [$1 створіть обліковий запис] або [$2 увійдіть].",
"echo-none": "У Вас немає сповіщень.",
"echo-more-info": "Детальніше",
"echo-feedback": "Зворотний зв'язок",
+ "echo-popup-footer-special-page-invitation": "<strong>Випробуйте оновлену сторінку сповіщень.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Всі нові оновлення вигляду та функції.",
+ "echo-api-failure": "Не вдалося отримати сповіщення.",
+ "echo-api-failure-cross-wiki": "Відмовлено в доступі до віддаленого домену.",
+ "echo-notification-placeholder": "Сповіщень немає.",
+ "echo-notification-placeholder-filters": "Немає сповіщень, що відповідають цим критеріям.",
+ "echo-notification-loginrequired": "Ви повинні увійти, щоб подивитися повідомлення.",
+ "echo-notification-popup-loginrequired": "Будь ласка, увійдіть в систему, щоб переглянути свої сповіщення.",
+ "echo-notification-markasread": "Позначити як прочитане",
+ "echo-notification-markasunread": "Позначити як непрочитане",
+ "echo-notification-markasread-tooltip": "Позначити як прочитане",
+ "echo-notification-more-options-tooltip": "Більше параметрів",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|Не}} спостерігати за новою діяльністю на «$1»",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|Ви}} більше не спостерігаєте за сторінкою «$1»",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|Ви}} можете додати [$2 цю сторінку] до списку спостереження будь-коли.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|Спостерігати}} за новою діяльністю на «$1»",
+ "notification-dynamic-actions-watch-confirmation": "Тепер {{GENDER:$3|Ви}} спостерігаєте за сторінкою «$1»",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|Ви}} можете вилучити [$2 цю сторінку] зі списку спостереження будь-коли.",
+ "notification-link-text-expand-all": "Розгорнути",
+ "notification-link-text-expand-alert-count": "Переглянути {{PLURAL:$1|$1 звістку|$1 звістки|$1 звісток}}",
+ "notification-link-text-expand-notice-count": "Дивитися {{PLURAL:$1|$1 сповіщення|$1 сповіщення|$1 сповіщень}}",
+ "notification-link-text-expand-all-count": "Переглянути {{PLURAL:$1|$1 сповіщення|$1 сповіщення|$1 сповіщень}}",
+ "notification-link-text-collapse-all": "Згорнути",
"notification-link-text-view-message": "Переглянути повідомлення",
"notification-link-text-view-mention": "Переглянути згадку",
- "notification-link-text-view-changes": "Переглянути зміни",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Переглянути згадку|Переглянути згадки}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Переглянути}} зміни",
"notification-link-text-view-page": "Переглянути сторінку",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|залишив|залишила}} повідомлення на <strong>{{GENDER:$3|Вашій}} сторінці обговорення</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|залишив|залишила}} повідомлення на <strong>{{GENDER:$3|Вашій}} сторінці обговорення</strong> у «<strong>$4</strong>».",
+ "notification-body-edit-user-talk-with-section": "$1",
+ "notification-header-page-linked": "На сторінку <strong>$4</strong> додано посилання на <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Посилання з <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "З {{PLURAL:$5||$5 сторінок|100=99+ сторінок}} було додано посилання на <strong>$3</strong>.",
+ "notification-header-article-reminder": "Сторінка, про яку {{GENDER:$2|Ви}} просили Вам нагадати — <strong>$3</strong>",
+ "notification-link-text-what-links-here": "Усі посилання на цю сторінку",
+ "notification-header-mention-other": "$1 згада{{GENDER:$2|в|ла}} {{GENDER:$3|Вас}} на сторінці <strong>$4</strong> у «<strong>$5</strong>».",
+ "notification-header-mention-other-nosection": "$1 згада{{GENDER:$2|в|ла}} {{GENDER:$3|Вас}} на сторінці <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 згада{{GENDER:$2|в|ла}} {{GENDER:$3|Вас}} на <strong>сторінці обговорення користувач{{GENDER:$5|а|ки}} $4</strong> у «<strong>$6</strong>».",
+ "notification-header-mention-user-talkpage-nosection": "$1 згада{{GENDER:$2|в|ла}} {{GENDER:$3|Вас}} на <strong>сторінці обговорення користувач{{GENDER:$5|а|ки}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 згада{{GENDER:$2|в|ла}} {{GENDER:$3|Вас}} на <strong>{{GENDER:$2|своїй}} сторінці обговорення</strong> у «<strong>$4</strong>».",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|згадав|згадала}} {{GENDER:$3|Вас}} на <strong>{{GENDER:$2|своїй}} сторінці обговорення</strong>.",
+ "notification-header-mention-article-talkpage": "$1 згада{{GENDER:$2|в|ла}} {{GENDER:$3|Вас}} на сторінці обговорення <strong>$4</strong> у «<strong>$5</strong>».",
+ "notification-header-mention-article-talkpage-nosection": "$1 згада{{GENDER:$2|в|ла}} {{GENDER:$3|Вас}} на сторінці обговорення <strong>$4</strong> .",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Вашу}} згадку <strong>$3</strong> не надіслано, бо не знайдено такого користувача.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Вашу}} згадку <strong>$3</strong> не надіслано, бо користувач — анонім.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Ви}} спробували згадати понад $3 {{PLURAL:$3|користувача|користувачі|користувачів}}. Усі згадки вище понад цей ліміт не було надіслано.",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|Згадка, яку|$3 згадки, які|$3 згадок, які}} {{GENDER:$2|Ви зробили}} на сторінці обговорення <strong>$4</strong>, {{PLURAL:$3|не вдалося}} надіслати.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Ім'я користувача не існує:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Не можна зробити згадку IP:</strong> $1",
+ "notification-header-mention-success": "{{GENDER:$2|Вашу}} згадку <strong>$3</strong> надіслано.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Згадка, здійснена|$3 згадки, здійснені}} {{GENDER:$2|Вами}} на сторінці обговорення <strong>$4</strong>, {{PLURAL:$3|було надіслано}}.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Ви згадали}}:</strong> $3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|Сповіщення|$3 сповіщення|$3 сповіщень}} про згадки, здійснені {{GENDER:$2|Вами}} на сторінці обговорення <strong>$4</strong>: {{PLURAL:$5|$5 не відправлено}}, {{PLURAL:$6|$6 відправлено}}.",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|Ваші}} права користувача {{GENDER:$1|змінилися}}. Вас будо додано до: $2.",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|Ваші}} права користувача {{GENDER:$1|змінилися}}. Ви більше не належите до: $2.",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|Ваші}} права користувача {{GENDER:$1|змінилися}}. Вас було додано до: $2. Ви більше не належите до: $4.",
+ "notification-header-user-rights-expiry-change": "Термін завершення {{GENDER:$4|Вашого}} членства у {{PLURAL:$3|поданій групі|поданих групах}} {{GENDER:$1|змінено}}: $2.",
+ "notification-header-welcome": "{{GENDER:$2|Ласкаво просимо}} до {{GRAMMAR:genitive|{{SITENAME}}}}, $1! Ми раді бачити {{GENDER:$2|Вас}} тут.",
+ "notification-welcome-linktext": "Ласкаво просимо!",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|Ви}} щойно зробили {{GENDER:$2|своє}} перше редагування; дякуємо {{GENDER:$2|Вам}} і ласкаво просимо!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|Ви}} щойно зробили {{GENDER:$2|своє}} десяте редагування; дякуємо {{GENDER:$2|Вам}}, продовжуйте!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|Ви}} щойно зробили {{GENDER:$2|своє}} соте редагування; дуже {{GENDER:$2|Вам}} дякуємо!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|Ви}} щойно зробили {{GENDER:$2|своє}} тисячне редагування; дякуємо {{GENDER:$2|Вам}} за великий внесок!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|Ви}} щойно зробили {{GENDER:$2|своє}} десятитисячне редагування; дуже {{GENDER:$2|Вам}} дякуємо!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|Ви}} щойно зробили {{GENDER:$2|своє}} стотисячне редагування; дякуємо {{GENDER:$2|Вам}} за дивовижний внесок!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|Ви}} щойно зробили {{GENDER:$2|своє}} мільйонне редагування; дякуємо {{GENDER:$2|Вам}} за неймовірний внесок!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|Ваше}} редагування",
"notification-link-text-view-edit": "Переглянути редагування",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|залишив|залишила}} повідомлення на Вашій [[User talk:$2#$3|сторінці обговорення]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|залишив|залишила}} повідомлення на Вашій сторінці обговорення у «[[User talk:$2#$3|$4]]».",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|залишив|залишила}} повідомлення на Вашій [[User talk:$2#$3|сторінці обговорення]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|залишив|залишила}} повідомлення на Вашій сторінці обговорення у «[[User talk:$2#$3|$4]]».",
- "notification-page-linked": "На [[:$3]] $1 {{GENDER:$1|додав|додала}} посилання на [[:$2]]. [[Special:WhatLinksHere/$2|Див. усі посилання на цю сторінку]]",
- "notification-page-linked-flyout": "На [[:$3]] $1 {{GENDER:$1|додав|додала}} посилання на [[:$2]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|прокоментував|прокоментувала}} \"[[$3|$2]]\" на сторінці обговорення \"$4\".",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] {{GENDER:$1|створив|створила}} нову тему \"$2\" на [[$3]].",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|надіслав|надіслала}} Вам повідомлення: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|прокоментував|прокоментувала}} \"[[$3#$2|$2]]\" на Вашій сторінці обговорення.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|згадав|згадала}} Вас на сторінці обговорення $5 у «[[:$3#$2|$4]]».",
- "notification-mention-flyout": "$1 {{GENDER:$1|згадав|згадала}} Вас на сторінці обговорення $5 у «[[:$3#$2|$4]]».",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|згадав|згадала}} вас на [[:$3|сторінці обговорення $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|згадав|згадала}} вас на [[:$3|сторінці обговорення $2]].",
- "notification-user-rights": "Ваші права користувача [[Special:Log/rights/$1|було змінено]] {{GENDER:$1|користувачем|користувачкою}} [[User:$1|$1]]. $2. [[Special:ListGroupRights|Дізнатися більше]]",
- "notification-user-rights-flyout": "Ваші права користувача було змінено {{GENDER:$1|користувачем|користувачкою}} $1. $2. [[Special:ListGroupRights|Дізнатися більше]]",
- "notification-user-rights-add": "Зараз Ви член {{PLURAL:$2|1=такої групи|таких груп}}: $1",
- "notification-user-rights-remove": "Ви більше не є членом {{PLURAL:$2|1=цієї групи|таких груп}}: $1",
- "notification-new-user": "Ласкаво просимо до {{GRAMMAR:Genitive|{{SITENAME}}}}, $1! Ми раді, що Ви тут.",
- "notification-reverted2": "{{PLURAL:$4|1=Ваше редагування|Ваші редагування}} сторінки [[:$2]] було {{GENDER:$1|скасовано}} {{GENDER:$1|користувачем|користувачкою}} [[User:$1|$1]] $3",
- "notification-reverted-flyout2": "{{PLURAL:$4|1=Ваше редагування|Ваші редагування}} сторінки $2 було {{GENDER:$1|скасовано}} {{GENDER:$1|користувачем|користувачкою}} $1 $3",
+ "notification-link-article-reminder": "Переглянути сторінку",
+ "notification-header-reverted": "{{PLURAL:$4|1=Ваше редагування|Ваші редагування}} сторінки <strong>$3</strong> було {{GENDER:$2|скасовано}}",
+ "notification-header-emailuser": "$1 {{GENDER:$2|надіслав|надіслала}} Вам листа.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|залишив|залишила}} Вам повідомлення на сайті {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|залишив|залишила}} повідомлення на Вашій сторінці обговорення.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|залишив|залишила}} повідомлення на Вашій сторінці обговорення у «$2».",
"notification-page-linked-email-subject": "На сайті {{SITENAME}} з'явилось посилання на сторінку, яку Ви створили",
- "notification-page-linked-email-batch-body": "На «$3» $1 {{GENDER:$1|зробив|зробила}} посилання на «$2»",
"notification-reverted-email-subject2": "{{PLURAL:$3|1=Ваше редагування|Ваші редагування}} на сайті {{SITENAME}} було {{GENDER:$1|скасовано}}",
- "notification-reverted-email-batch-body2": "{{PLURAL:$3|1=Ваше редагування|Ваші редагування}} сторінки $2 було {{GENDER:$1|скасовано}} {{GENDER:$1|користувачем|користувачкою}} $1",
- "notification-mention-email-subject": "$1 {{GENDER:$1|згадав|згадала}} Вас на {{GRAMMAR:locative|{{SITENAME}}}}.",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|згадав|згадала}} Вас на сторінці обговорення {{GENDER:$4|користувача|користувачки}} $4 у «$3».",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|згадав|згадала}} вас на сторінці обговорення $2.",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|згадав|згадала}} {{GENDER:$2|Вас}} на сайті «{{SITENAME}}».",
"notification-user-rights-email-subject": "Змінились Ваші права користувача на {{GRAMMAR:locative|{{SITENAME}}}}.",
- "notification-user-rights-email-batch-body": "Ваші права користувача було змінено {{GENDER:$1|користувачем|користувачкою}} $1. $2.",
- "echo-email-subject-default": "Нові сповіщення на {{GRAMMAR:locative|{{SITENAME}}}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1с}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1хв}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1год}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1д.}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1міс.}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1р.|$1рр.}}",
+ "notification-timestamp-today": "Сьогодні",
+ "notification-timestamp-yesterday": "Вчора",
+ "notification-inbox-filter-read": "Прочитане",
+ "notification-inbox-filter-unread": "Непрочитане",
+ "notification-inbox-filter-all": "Усе",
"echo-email-body-default": "У Вас є нове сповіщення на {{GRAMMAR:locative|{{SITENAME}}}}:\n\n$1",
- "echo-email-batch-body-default": "У Вас нове сповіщення.",
- "echo-email-footer-default": "$2\n\nЩоб контролювати, які листи ми Вам надсилаємо, перевірте свої налаштування:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Щоб проконтролювати, які листи ми вам надсилаємо, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">перевірте свої налаштування</a>.<br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|Попередження ($1)|Попереджень ($1)|100=Попереджень (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Повідомлення ($1)|100=Повідомлення (99+)}}",
- "echo-notification-alert-text-only": "Сповіщення",
- "echo-notification-message-text-only": "Повідомлення",
+ "echo-email-footer-default-html": "Для контролю того, які листи ми Вам надсилаємо, <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">перевірте свої налаштування</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nДля контролю того, які листи ми Вам надсилаємо, перевірте свої налаштування:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Щоб визначити, які повідомлення ми {{GENDER:$1|Вам}} надсилаємо, перевірте свої налаштування:",
+ "echo-email-html-footer-preference-link-text": "перевірте {{GENDER:$1|свої}} налаштування",
+ "echo-email-html-footer-with-link": "Щоб контролювати, які листи ми {{GENDER:$2|Вам}} надсилаємо, $1.",
+ "echo-notification-alert": "{{PLURAL:$1|Звістка ($1)|Звістки ($1)|100=Звістки (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|1=Сповіщення ($1)|Сповіщення ($1)|100=Сповіщення (99+)}}",
+ "echo-notification-alert-text-only": "Звістки",
+ "echo-notification-notice-text-only": "Сповіщення",
"echo-overlay-link": "Усі сповіщення",
"echo-overlay-title": "<b>Сповіщення</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Сповіщення|Сповіщення|Сповіщень}}</b> (показано $1 з $2 непрочитаних)",
"echo-mark-all-as-read": "Позначити всі як прочитані",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|сповіщення позначено як прочитане|сповіщення позначені як прочитані|сповіщень позначені як прочитані}}",
+ "echo-mark-wiki-as-read": "Позначити все як прочитане в обраній вікі: $1",
"echo-date-today": "Сьогодні",
"echo-date-yesterday": "Вчора",
"echo-load-more-error": "Під час отримання додаткових результатів сталася помилка.",
- "notification-edit-talk-page-bundle": "$1 та $3 {{PLURAL:$4|інший користувач|інші користувачі|інших користувачів}} {{GENDER:$1|залишили}} повідомлення на Вашій [[User talk:$2|сторінці обговорення]].",
- "notification-page-linked-bundle": "На $3 та $4 {{PLURAL:$5|1=іншій сторінці|інших сторінках}} $1 {{GENDER:$1|додав|додала}} посилання на $2. [[Special:WhatLinksHere/$2|Див. усі посилання на цю сторінку]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 та $2 {{PLURAL:$3|інший користувач|інші користувачі|інших користувачів}} {{GENDER:$1|залишили}} повідомлення на Вашій сторінці обговорення",
- "notification-page-linked-email-batch-bundle-body": "На $3 та $4 {{PLURAL:$5|1=іншій сторінці|інших сторінках}} $1 {{GENDER:$1|додав|додала}} посилання на $2.",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|$1 нове повідомлення|$1 нові повідомлення|$1 нових повідомлень|1=Одне нове повідомлення|100=99+ нових повідомлень}} на <strong>{{GENDER:$3|Вашій}} сторінці обговорення</strong>.",
"echo-email-batch-subject-daily": "У Вас {{PLURAL:$2|нове сповіщення|нові сповіщення|нових сповіщень}} на сайті {{SITENAME}}",
"echo-email-batch-subject-weekly": "У Вас {{PLURAL:$2|нове сповіщення|нові сповіщення|нових сповіщень}} на сайті {{SITENAME}} цього тижня",
"echo-email-batch-body-intro-daily": "Привіт $1!\nОсь підсумок денної активності на сайті {{SITENAME}} для вас.",
"echo-email-batch-body-intro-weekly": "Привіт $1!\nОсь підсумок тижневої активності на сайті {{SITENAME}} для вас.",
"echo-email-batch-link-text-view-all-notifications": "Переглянути усі сповіщення",
- "echo-rev-deleted-text-view": "Цю версію сторінки було приховано.",
- "apihelp-echomarkread-description": "Позначити для поточного користувача сповіщення як прочитані.",
- "apihelp-echomarkread-param-list": "Список ідентифікаторів сповіщень, які позначити як прочитані.",
- "apihelp-echomarkread-param-all": "Якщо встановлено, позначає всі сповіщення користувача прочитаними.",
- "apihelp-echomarkread-param-sections": "Список розділів, які позначити як прочитані.",
- "apihelp-echomarkread-example-1": "Позначити сповіщення 8 як прочитане.",
- "apihelp-echomarkread-example-2": "Позначити всі сповіщення як прочитані",
- "apihelp-echomarkseen-description": "Позначити всі сповіщення як прочитані для поточного користувача.",
- "apihelp-echomarkseen-example-1": "Позначити сповіщення як переглянуті",
- "apihelp-query+notifications-description": "Отримати сповіщення, які чекають поточного користувача.",
- "apihelp-query+notifications-param-prop": "Деталі запиту.",
- "apihelp-query+notifications-param-sections": "Розділи сповіщень для запиту.",
- "apihelp-query+notifications-param-groupbysection": "Чи групувати результати за розділами. Кожен розділ буде отримуватись окремо якщо встановлено.",
- "apihelp-query+notifications-param-format": "Якщо вказано, сповіщення буде отримано форматованими таким чином.",
- "apihelp-query+notifications-param-limit": "Максимальне число сповіщень для повернення.",
- "apihelp-query+notifications-param-index": "Якщо вказано, буде повернено список ідентифікаторів сповіщень у порядку.",
- "apihelp-query+notifications-param-alertcontinue": "Коли доступно більше попереджень, використовуйте це, щоб продовжити.",
- "apihelp-query+notifications-param-alertunreadfirst": "Чи показувати спершу непрочитані сповіщення про повідомлення.",
- "apihelp-query+notifications-param-messagecontinue": "Коли доступно більше повідомлень, використовуйте це, щоб продовжити.",
- "apihelp-query+notifications-param-messageunreadfirst": "Чи показувати спершу непрочитані сповіщення.",
- "apihelp-query+notifications-example-1": "Список сповіщень",
- "apihelp-query+notifications-example-2": "Список сповіщень, згрупованих за розділами, із зазначенням кількостей"
+ "notification-header-foreign-alert": "Більше звісток з {{PLURAL:$5|$5 іншої вікі|$5 інших вікі}}",
+ "notification-header-foreign-notice": "Більше сповіщень з {{PLURAL:$5|іншої вікі|$5 інших вікі}}",
+ "notification-header-foreign-all": "Більше сповіщень з {{PLURAL:$5|$5 іншої вікі|$5 інших вікі}}"
}
diff --git a/Echo/i18n/ur.json b/Echo/i18n/ur.json
index f36cb44c..da47d964 100644
--- a/Echo/i18n/ur.json
+++ b/Echo/i18n/ur.json
@@ -5,22 +5,117 @@
"පසිඳු කාවින්ද",
"Amire80",
"Fauzan",
- "عثمان خان شاہ"
+ "عثمان خان شاہ",
+ "Muhammad Shuaib",
+ "Obaid Raza",
+ "Hindustanilanguage",
+ "امین اکبر"
]
},
+ "echo-desc": "نظام برائے اطلاع صارفین دربارہ تقریبات و پیغامات",
"prefs-echo": "اطلاعات",
+ "prefs-emailsettings": "برقی خط کے اختیارات",
+ "prefs-displaynotifications": "اختیارات دکھائیں",
+ "prefs-echosubscriptions": "ان احوال کے متعلق مجھے آگاہ کریں",
+ "prefs-echocrosswiki": "دیگر ویکیوں کے اطلاع نامے",
+ "prefs-newmessageindicator": "نئے پیغام کا اشارہ نما",
+ "echo-pref-send-me": "مجھے ارسال کریں:",
+ "echo-pref-send-to": "مرسل الیہ:",
+ "echo-pref-email-format": "برقی ڈاک فارمیٹ",
+ "echo-pref-web": "ویب",
+ "echo-pref-email": "برقی خط",
+ "echo-pref-email-frequency-never": "برقی خط کے ذریعہ کوئی اطلاع نامہ ارسال نہ کریں",
+ "echo-pref-email-frequency-immediately": "انفرادی اطلاع نامے جیسے ہی وہ موصول ہوں",
+ "echo-pref-email-frequency-daily": "اطلاع ناموں کا یومیہ خلاصہ",
+ "echo-pref-email-frequency-weekly": "اطلاع ناموں کا ہفتہ واری خلاصہ",
+ "echo-pref-email-format-html": "ایچ ٹی ایم ایل",
+ "echo-pref-email-format-plain-text": "سادہ متن",
+ "echo-pref-cross-wiki-notifications": "دیگر ویکیوں کے اطلاع نامے دکھائیں",
+ "echo-pref-new-message-indicator": "میرے خانہ آلات میں تبادلۂ خیال صفحے کے پیغامات کا اشارہ نما فعال کریں",
+ "echo-learn-more": "مزید معلومات حاصل کریں",
+ "echo-log": "عوامی نوشتہ",
"echo-new-messages": "آپ کے لیے نئے پیغامات",
- "echo-category-title-other": "دیگر",
+ "echo-category-title-edit-user-talk": "تبادلۂ خیال صفحہ {{PLURAL:$1|کا پیغام|کے پیغامات}}",
+ "echo-category-title-article-linked": "صفحہ {{PLURAL:$1|کا ربط|کے روابط}}",
+ "echo-category-title-reverted": "رد {{PLURAL:$1|ترمیم|ترامیم}}",
+ "echo-category-title-mention": "{{PLURAL:$1|تذکرہ|تذکرے}}",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|تذکرہ|تذکرے}} ناکام",
+ "echo-category-title-mention-success": "{{PLURAL:$1|تذکرہ|تذکرے}} کامیاب",
+ "echo-category-title-other": "{{PLURAL:$1|دیگر}}",
+ "echo-category-title-user-rights": "{{PLURAL:$1|اختیارات صارف کی تبدیلی|اختیارات صارف کی تبدیلیاں}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|دوسرے صارف کا برقی خط|دیگر صارفین کے برقی خطوط}}",
+ "echo-pref-tooltip-edit-user-talk": "جب کوئی شخص میرے تبادلۂ خیال صفحہ پر پیغام لکھے یا کسی پیغام کا جواب دے تو مجھے آگاہ کریں۔",
+ "echo-pref-tooltip-article-linked": "جب کسی مضمون میں میرے تخلیق کردہ کسی صفحہ کا ربط دیا جائے تو مجھے آگاہ کریں۔",
+ "echo-pref-tooltip-reverted": "جب کوئی شخص میری ترمیم کو رد یا استرجع کرے تو مجھے آگاہ کریں۔",
+ "echo-pref-tooltip-mention": "جب کوئی شخص میرے صارف صفحے کا ربط کہیں درج کرے تو مجھے آگاہ کریں۔",
+ "echo-pref-tooltip-mention-failure": "جب میں کسی شخص کا تذکرہ نہ کر سکوں تو مجھے آگاہ کریں۔",
+ "echo-pref-tooltip-mention-success": "جب میں کسی کا تذکرہ کروں تو مجھے آگاہ کریں۔",
+ "echo-pref-tooltip-user-rights": "جب کوئی شخص میرے اختیارات میں تبدیلی کرے تو مجھے آگاہ کریں۔",
+ "echo-pref-tooltip-emailuser": "جب کوئی شخص مجھے برقی خط بھیجے تو مجھے آگاہ کریں۔",
"notifications": "اطلاعات",
- "tooltip-pt-notifications": "آپ کے نوٹیفیکیشن",
- "echo-specialpage": "میری اطلاعات",
+ "tooltip-pt-notifications-alert": "{{GENDER:|آپ}}کی اطلاعات",
+ "echo-specialpage": "اطلاعات",
+ "echo-specialpage-pagefilters-title": "حالیہ سرگرمی",
+ "echo-specialpage-pagefilters-subtitle": "صفحات جن کی اطلاعات نہیں پڑھی گئیں",
"echo-feedback": "آپ کی رائے",
- "notification-user-rights-flyout": "آپ کے صارفانہ حقوق ہوگئے {{GENDER:$1| تبدیل}} <b> $1 </b>کے ذریعے ۔ $2. [[Special:ListGroupRights|مزید دیکھیں]]",
- "echo-notification-message-text-only": "پیغامات",
- "echo-overlay-link": "سب اطلاعات...",
+ "echo-api-failure": "اطلاعات حاصل کرنے میں ناکامی، دوبارہ کوشش کریں!",
+ "echo-notification-placeholder": "کوئی اطلاع موجود نہیں۔",
+ "echo-notification-markasread": "بطور خواندہ شدہ نشان زد کریں",
+ "echo-notification-markasunread": "بطور ناخواندہ شدہ نشان زد کریں",
+ "echo-notification-markasread-tooltip": "بطور خواندہ شدہ نشان زد کریں",
+ "echo-notification-more-options-tooltip": "مزید اختیارات",
+ "notification-link-text-expand-all": "پورا دکھائیں",
+ "notification-link-text-expand-all-count": "{{PLURAL:$1|$1 اطلاع نامہ|$1 اطلاع نامے}} دیکھیں",
+ "notification-link-text-collapse-all": "چھپائیں",
+ "notification-link-text-view-message": "پیغام دیکھیں",
+ "notification-link-text-view-mention": "تذکرہ دیکھیں",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|تذکرہ دیکھیں|تذکرے دیکھیں}}",
+ "notification-link-text-view-changes": "تبدیلیاں {{GENDER:$1|دیکھیں}}",
+ "notification-link-text-view-page": "صفحہ دیکھیں",
+ "notification-header-edit-user-talk": "$1 نے <strong>{{GENDER:$3|آپ کے}} تبادلۂ خیال پر </strong> {{GENDER:$2|ایک}} پیغام دیا۔",
+ "notification-header-page-linked": "صفحہ <strong>$3</strong> کا ربط صفحہ <strong>$4</strong> میں شامل کیا گیا ہے۔",
+ "notification-compact-header-page-linked": "<strong>$1</strong> سے مربوط ہوا۔",
+ "notification-bundle-header-page-linked": "صفحہ <strong>$3</strong> میں {{PLURAL:$5||$5 صفحات|100=99+ صفحات}} کے روابط شامل کیے گیے۔",
+ "notification-link-text-what-links-here": "اس صفحے سے مربوط تمام روابط",
+ "notification-header-mention-agent-talkpage": "$1 نے {{GENDER:$3|آپ}} کا {{GENDER:$2|تذکرہ}} <strong>{{GENDER:$2|کے|کے|کے}} تبادلۂ خیال صفحہ</strong> پر \"<strong>$4</strong>\" میں کیا۔",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|آپ کے}} صارفی حقوق {{GENDER:$1|تبدیل}} کر کے آپ کو $2 گروہ صارفین میں شامل کر دیا گیا ہے۔",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|آپ کے}} صارفی حقوق {{GENDER:$1|تبدیل}} کر کے آپ کو $2 میں شامل کر دیا گیا ہے۔ اب آپ $4 کے ایک رکن ہیں۔",
+ "notification-welcome-linktext": "خوش آمدید",
+ "notification-link-text-view-edit": "ترمیم دیکھیں",
+ "notification-link-article-reminder": "صفحہ دیکھیں",
+ "notification-header-reverted": "{{PLURAL:$4| <strong>$3</strong> پر آپ کی ترمیم| <strong>$3</strong> پر آپ کی ترامیم}} {{GENDER:$2|نے رد کر دی ہے}}",
+ "notification-header-emailuser": "$1 نے آپ کو برقی ڈاک {{GENDER:$2|بھیجی ہے}}۔",
+ "notification-edit-talk-page-email-subject2": "{{SITENAME}} پر $1 نے آپ کو پیغام {{GENDER:$1|بھیجا ہے}}",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 نے آپ کے تبادلہ خیال صفحے پر قطعہ \"$2\" کے تحت آپ کو پیغام {{GENDER:$1|بھیجا ہے}}۔",
+ "notification-page-linked-email-subject": "{{SITENAME}} پر آپ کا تخلیق کردہ صفحہ مربوط ہوا",
+ "notification-user-rights-email-subject": "{{SITENAME}} پر آپ کے صارفی اختیارات میں تبدیلی کی گئی ہے",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 سیکنڈ}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 منٹ}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 گھنٹہ}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 دن}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 مہینہ}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 سال}}",
+ "notification-timestamp-today": "آج",
+ "notification-timestamp-yesterday": "گزشتہ کل",
+ "notification-inbox-filter-read": "پڑھیں",
+ "notification-inbox-filter-unread": "غیرمطالعہ شدہ",
+ "notification-inbox-filter-all": "تمام",
+ "echo-email-body-default": "آپ کے لیے {{SITENAME}} پر نیا اطلاع نامہ موجود ہے:\n\n$1",
+ "echo-email-footer-default": "$2\n\nآپ کو ارسال کردہ برقی خطوط کی ترتیب و تنظیم کے لیے اپنی ترجیحات ملاحظہ کریں:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "{{GENDER:$1|آپ کو}} ارسال کردہ برقی خطوط کی ترتیب و تنظیم کے لیے {{GENDER:$1|اپنی}} ترجیحات ملاحظہ کریں:",
+ "echo-email-html-footer-preference-link-text": "{{GENDER:$1|اپنی}} ترجیحات ملاحظہ کریں",
+ "echo-email-html-footer-with-link": "{{GENDER:$2|آپ}} کو ہم سے مرسلہ ای میلوں پر گرفت کے لیے",
+ "echo-notification-alert": "{{PLURAL:$1|انتباہ ($1)|انتباہات ($1)|100=انتباہات (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|اطلاع ($1)|اطلاعات($1)|100=اطلاعات(99+)}}",
+ "echo-notification-alert-text-only": "انتباہات",
+ "echo-notification-notice-text-only": "اطلاعات",
+ "echo-overlay-link": "جملہ اطلاعات",
"echo-overlay-title": "<b>اطلاعات</b>",
- "echo-overlay-title-overflow": "<b>اطلاعات</b> (دکھا رہا ہے $1 کے $2 غیر مطلع)",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|طلاع|اطلاعات}}</b> ($2 ناخواندہ پیغامات میں سے $1 زیر مشاہدہ)",
"echo-mark-all-as-read": "جملہ اطلاعات کو خواندہ نشانزد کریں",
"echo-date-today": "آج",
- "echo-date-yesterday": "گذشتہ کل"
+ "echo-date-yesterday": "گذشتہ کل",
+ "echo-email-batch-link-text-view-all-notifications": "تمام اطلاع نامے دیکھیں",
+ "notification-header-foreign-alert": "{{PLURAL:$5|دوسری ویکی|$5 دیگر ویکیوں}} کی مزید اطلاعات",
+ "notification-header-foreign-all": "{{PLURAL:$5|دوسری ویکی|$5 دیگر ویکیوں}} کے مزید اطلاع نامے"
}
diff --git a/Echo/i18n/uz.json b/Echo/i18n/uz.json
index 23876020..d6d15b98 100644
--- a/Echo/i18n/uz.json
+++ b/Echo/i18n/uz.json
@@ -14,7 +14,7 @@
"prefs-newmessageindicator": "Yangi xabar indikatori",
"echo-pref-send-me": "Menga joʻnatilsin:",
"echo-pref-send-to": "Joʻnatilsin:",
- "echo-pref-email-format": "Elektron xat formati",
+ "echo-pref-email-format": "Xatlar formati:",
"echo-pref-web": "Veb",
"echo-pref-email": "Elektron pochta",
"echo-pref-email-frequency-never": "Menga elektron pochta orqali xabarlar joʻnatilmasin",
@@ -23,7 +23,6 @@
"echo-pref-email-frequency-weekly": "Xabarlar haqida haftalik maʼlumot",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Quruq matn",
- "echo-pref-notify-show-link": "Asboblar panelimda xabarlar koʻrsatilsin",
"echo-pref-new-message-indicator": "Asboblar panelida munozara sahifasidagi xabarlar indikatori koʻrsatilsin",
"echo-learn-more": "Batafsil maʼlumot",
"echo-new-messages": "Sizda yangi xabarlar bor",
@@ -34,17 +33,12 @@
"echo-category-title-other": "{{PLURAL:$1|1=boshqa|boshqalar}}",
"echo-category-title-system": "{{PLURAL:$1|Tuzum}}",
"echo-category-title-user-rights": "{{PLURAL:$1|Foydalanuvchi huquqlarim oʻzgartirildi}}",
- "echo-pref-tooltip-edit-user-talk": "Birorta xat yuborsa yoki munozara sahifamda javob yozsa xabar berilsin",
+ "echo-pref-tooltip-edit-user-talk": "Kimdur menga xat yuborsa yoki munozara sahifamda javob yozsa xabar berilsin",
"echo-pref-tooltip-article-linked": "Maqolalarda men yaratgan biror-bir sahifaga link qoldirilsa xabar berilsin",
"echo-pref-tooltip-reverted": "Kimdir men qilgan tahrirni bekor qilsa, menga xabar berilsin.",
"echo-pref-tooltip-mention": "Biror foydalanuvchi har qanday munozarada sahifamga havola bergani haqida xabar qilinsin",
- "echo-no-agent": "[Hech kim]",
- "echo-no-title": "[Sahifa yoʻq]",
"echo-error-no-formatter": "Xabarlar uchun format belgilanmagan.",
- "echo-error-preference": "Xato: Foydalanuvchi moslamalarini tayinlab boʻlmadi.",
- "echo-error-token": "Xato: Foydalanuvchi markerini olib boʻlmadi (user token).",
"notifications": "Xabarlar",
- "tooltip-pt-notifications": "Sizning xabarlaringiz",
"echo-specialpage": "Xabarlar",
"echo-anon": "Xabarlar olib turish uchun [$1 hisob yarating] yoki [$2 tizimga kiring].",
"echo-none": "Siz xabar olmadingiz.",
@@ -55,44 +49,15 @@
"notification-link-text-view-changes": "Oʻzgarishlarni koʻrish",
"notification-link-text-view-page": "Sahifani koʻrish",
"notification-link-text-view-edit": "Tahrirni koʻrish",
- "notification-edit-talk-page2": "[[User:$1|$1]] sizning [[User talk:$2#$3|munozara sahifangizda]] xat {{GENDER:$1|qoldirdi}}.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] sizning munozara sahifangizda „[[User talk:$2#$3|$4]]“ mavzusida xat {{GENDER:$1|qoldirdi}}.",
- "notification-edit-talk-page-flyout2": "$1 sizning [[User talk:$2#$3|munozara sahifangizda]] xat {{GENDER:$1|qoldirdi}}.",
- "notification-edit-talk-page-flyout-with-section": "$1 sizning munozara sahifangizda „[[User talk:$2#$3|$4]]“ mavzusida xat {{GENDER:$1|qoldirdi}}.",
- "notification-page-linked": "[[:$2]] [[:$3]]dan {{GENDER:$1|bogʻlandi}}. [[Special:WhatLinksHere/$2|Bu sahifaga ulangan barcha linklarni koʻring]].",
- "notification-page-linked-flyout": "[[:$2]] sahifasi [[:$3]] sahifasi bilan {{GENDER:$1|bogʻlandi}}.",
- "notification-add-comment2": "[[User:$1|$1]] „$4“ munozara sahifasida „[[$3|$2]]“ mavzusida {{GENDER:$1|sharh qoldirdi}}.",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] [[$3]] sahifasida yangi „$2“ mavzusini {{GENDER:$1|qoʻshdi}}.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] sizga xabar {{GENDER:$1|joʻnatdi}}: „[[$3#$2|$2]]“.",
- "notification-add-comment-yours2": "[[User:$1|$1]] sizning munozara sahifangizda „[[$3#$2|$2]]“ mavzusida {{GENDER:$1|sharh qoldirdi}}.",
- "notification-mention": "[[User:$1|$1]] $5 munozara sahifasidagi „[[:$3#$2|$4]]“ boʻlimida sizni {{GENDER:$1|tilga oldi}}.",
- "notification-mention-flyout": "$5 sahifasi munozarasidagi „[[:$3#$2|$4]]“ boʻlimida $1 sizni {{GENDER:$1|tilga oldi}}.",
- "notification-mention-nosection": "[[User:$1|$1]] [[:$3|$2 munozara sahifasida]] sizni {{GENDER:$1|tilga oldi}}.",
- "notification-mention-nosection-flyout": "$1 [[:$3|$2 munozara sahifasida]] sizni {{GENDER:$1|tilga oldi}}.",
- "notification-user-rights": "Sizning foydalanuvchi huquqlaringiz [[User:$1|$1]] tomonidan [[Special:Log/rights/$1|{{GENDER:$1|oʻzgartirildi}}]]. $2. [[Special:ListGroupRights|Batafsil]]",
- "notification-user-rights-flyout": "Sizning foydalanuvchi huquqlaringiz $1 tomonidan [[Special:Log/rights/$1|{{GENDER:$1|oʻzgartirildi}}]]. $2. [[Special:ListGroupRights|Batafsil]]",
- "notification-user-rights-add": "Siz endi {{PLURAL:$2|1=quyidagi guruh|quyidagi guruhlar}} aʼzosisiz: $1",
- "notification-user-rights-remove": "Siz endi {{PLURAL:$2|1=quyidagi guruh|quyidagi guruhlar}} aʼzosi emassiz: $1",
- "notification-new-user": "{{SITENAME}}ga xush kelibsiz!, $1! Siz bu yerdaligingizdan mamnunmiz.",
- "notification-reverted2": "[[:$2]] sahifasidagi {{PLURAL:$4|1=tahriringizni|tahrirlaringizni}} [[User:$1|$1]] {{GENDER:$1|bekor qildi}}. $3",
- "notification-reverted-flyout2": "$2 sahifasidagi {{PLURAL:$4|1=tahriringizni|tahrirlaringizni}} $1 {{GENDER:$1|bekor qildi}}. $3",
+ "notification-header-reverted": "$3 sahifasidagi {{PLURAL:$4|1=tahriringizni|tahrirlaringizni}} $1 {{GENDER:$2|bekor qildi}}.",
"notification-edit-talk-page-email-subject2": "$1 {{SITENAME}}da sizga xabar {{GENDER:$1|qoldirdi}}.",
- "notification-edit-talk-page-email-batch-body2": "$1 munozara sahifangizda xabar {{GENDER:$1|qoldirdi}}:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 munozara sahifangizdagi „$2“ boʻlimida xabar {{GENDER:$1|qoldirdi}}:",
"notification-page-linked-email-subject": "{{SITENAME}} saytida siz yaratgan sahifaga havola paydo boʻldi.",
- "notification-page-linked-email-batch-body": "$2 $3dan {{GENDER:$1|bogʻlandi}}.",
"notification-reverted-email-subject2": "{{GENDER:$1|Кimdir}} {{SITENAME}} saytida sizning {{PLURAL:$3|1=tahriringizni|tahrirlaringizni}} bekor qildi.",
- "notification-reverted-email-batch-body2": "$2 sahifasidagi {{PLURAL:$4|1=tahriringizni|tahrirlaringizni}} $1 {{GENDER:$1|bekor qildi}}.",
"notification-mention-email-subject": "$1 sizni {{SITENAME}} saytida {{GENDER:$1|tilga oldi}}.",
- "notification-mention-email-batch-body": "$4 sahifasining munozarasidagi „$3“ boʻlimida $1 sizni {{GENDER:$1|tilga oldi}}.",
- "notification-mention-nosection-email-batch-body": "„$2 sahifasi munozarasida $1 sizni {{GENDER:$1|tilga oldi}}.",
"notification-user-rights-email-subject": "{{SITENAME}} saytidagi huquqlaringiz oʻzgartirildi.",
- "notification-user-rights-email-batch-body": "Sizning huquqlaringiz $1 tomonidan {{GENDER:$1|oʻzgartirildi}}. $2.",
- "echo-email-subject-default": "{{SITENAME}} saytida yangi xabarlar",
"echo-email-body-default": "{{SITENAME}} saytida sizda yangi xabar bor:\n\n$1",
- "echo-email-batch-body-default": "Sizda yangi xabar bor.",
"echo-email-footer-default": "$2 \n\nSizga qanday elektron xabarlarni joʻnatishimizni boshqarish uchun shaxsiy moslamalaringizni koʻrib chiqing: {{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "Sizga qanday elektron xabarlarni joʻnatishimizni boshqarish uchun <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">shaxsiy moslamalaringizni koʻrib chiqing</a>.<br />",
"echo-overlay-link": "Barcha xabarlar",
"echo-overlay-title": "<b>Xabarlar</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Xabarlar}}</b> $2 ta oʻqilmagandan $1 tasi koʻrsatilyapti",
@@ -100,14 +65,9 @@
"echo-date-today": "Bugun",
"echo-date-yesterday": "Kecha",
"echo-load-more-error": "Qoʻshimcha natijalar olinayotganda xato roʻy berdi.",
- "notification-edit-talk-page-bundle": "$1 va $3 {{PLURAL:$4|1=boshqa foydalanuvchi|boshqa foydalanuvchilar}} [[User talk:$2|munozara sahifangizda]] xabar {{GENDER:$1|qoldirdi}}.",
- "notification-page-linked-bundle": "$2 ga $3 va $4 boshqa {{PLURAL:$5|sahifada|sahifalarda}} havola {{GENDER:$1|qoldirildi}}. [[Special:WhatLinksHere/$2|Bu sahifaga ulangan barcha linklarni koʻrib chiqing]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 va $2 {{PLURAL:$3|boshqa|boshqalar}} munozara sahigangizda xabar {{GENDER:$1|qoldirdi}}.",
- "notification-page-linked-email-batch-bundle-body": "$2ga $3da va $4 boshqa {{PLURAL:$5|sahifada|sahifada}} havola {{GENDER:$1|qoldirildi}}.",
"echo-email-batch-subject-daily": "{{SITENAME}} saytida sizda {{PLURAL:$2|yangi xabar|yangi xabar}} bor.",
"echo-email-batch-subject-weekly": "Bu hafta {{SITENAME}} saytida sizda {{PLURAL:$2|yangi xabar|yangi xabar}} bor.",
"echo-email-batch-body-intro-daily": "Salom $1,\nMana siz uchun {{SITENAME}} saytidagi bugungi faoliyat haʻqida qisqa maʼlumot.",
"echo-email-batch-body-intro-weekly": "Salom $1,\nMana siz uchun {{SITENAME}} saytidagi bir haftalik faoliyat haʻqida qisqa maʼlumot.",
- "echo-email-batch-link-text-view-all-notifications": "Barcha xabarlarni koʻrib chiqish",
- "echo-rev-deleted-text-view": "Sahifaning mazkur versiyasi yashirilgan"
+ "echo-email-batch-link-text-view-all-notifications": "Barcha xabarlarni koʻrib chiqish"
}
diff --git a/Echo/i18n/vec.json b/Echo/i18n/vec.json
index c6f32136..ff328221 100644
--- a/Echo/i18n/vec.json
+++ b/Echo/i18n/vec.json
@@ -5,23 +5,123 @@
"Candalua"
]
},
+ "prefs-echo": "Avisi",
+ "prefs-emailsettings": "Preferense e-mail",
+ "prefs-displaynotifications": "Preferense de visualixassion",
+ "prefs-echosubscriptions": "Màndeme un aviso su de sti eventi",
+ "prefs-echocrosswiki": "Avisi tra na wiki e n'altra",
+ "prefs-newmessageindicator": "Indicador de i mesaji novi",
"echo-pref-send-me": "Màndeme:",
"echo-pref-send-to": "Manda a:",
"echo-pref-email-format": "Formato email:",
"echo-pref-web": "Web",
"echo-pref-email": "Email",
"echo-pref-email-frequency-never": "No sta mandarme nissuna notifica par email",
+ "echo-pref-email-frequency-immediately": "Un aviso par olta",
+ "echo-pref-email-frequency-daily": "Un riasunto zorno par zorno de i avisi",
+ "echo-pref-email-frequency-weekly": "Un riasunto dei avisi de la stimana",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Testo normal",
+ "echo-pref-cross-wiki-notifications": "Fà védar anca i avisi de chealtre wiki",
+ "echo-pref-new-message-indicator": "Fà védar l'indicador in tea bara dei strumenti, par i mesaji novi in te la me pagina de discusion",
+ "echo-pref-beta-feature-cross-wiki-message": "Avisi fati mejo",
+ "echo-learn-more": "Par saverghine de pì",
+ "echo-log": "Rejistro pùblico",
"echo-new-messages": "Te ghè dei messagi novi",
+ "echo-category-title-edit-user-talk": "{{PLURAL:$1|Mesajo|Mesaji}} in tea pagina de discusion",
+ "echo-category-title-article-linked": "{{PLURAL:$1|Colegamento|Colegamenti}} a na pagina",
+ "echo-category-title-reverted": "{{PLURAL:$1|Canbiamento desfà|Canbiamenti desfài}}",
+ "echo-category-title-mention": "{{PLURAL:$1|I te ga nomenà}}",
"echo-category-title-other": "{{PLURAL:$1|Altro}}",
"echo-category-title-system": "{{PLURAL:$1|Sistema}}",
- "echo-no-agent": "[Nissun]",
- "echo-no-title": "[Nissuna pagina]",
+ "echo-category-title-user-rights": "{{PLURAL:$1|Canbiamento|Canbiamenti}} de i diriti de l'utente",
+ "echo-category-title-emailuser": "{{PLURAL:$1|Email da n'altro utente|Email da de i altri utenti}}",
+ "echo-pref-tooltip-edit-user-talk": "Dime co che qualchidun me scrive un mesajo o me risponde in te a me pagina de discusion.",
+ "echo-pref-tooltip-article-linked": "Dime co che qualchidun, da na pagina qualunque, el ghe taca un ligame su na pagina de quele che go fato mi.",
+ "echo-pref-tooltip-reverted": "Dime co che qualchedun el desfa un canbiamento che go fato mi, strucando \"anula\" o \"torna indrio\".",
+ "echo-pref-tooltip-mention": "Dime co che qualchidun el taca un ligame verso la me pagina utente",
+ "notifications": "Avisi",
"tooltip-pt-notifications-alert": "{{GENDER:|I to}} avisi",
- "tooltip-pt-notifications-message": "{{GENDER:|I to}} messaji",
+ "tooltip-pt-notifications-notice": "{{GENDER:|I to}} avisi",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Avisi par categoria",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Utenti che gh'è za",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Utenti novi",
+ "echo-specialpage": "Avisi",
+ "echo-specialpage-section-markread": "Segna sto grupo come za lèto",
+ "echo-specialpage-markasread": "Aviso: segna come za lèto",
+ "echo-specialpage-markasread-invalid-id": "ID evento mia valido",
+ "echo-specialpage-pagination-numnotifications": "$1 {{PLURAL:$1|aviso|avisi}}",
+ "echo-specialpage-pagefilters-title": "Atività de poco fa",
+ "echo-specialpage-pagefilters-subtitle": "Pagine con avisi mia lèti gnancora",
+ "notificationsmarkread-legend": "Segna sto aviso come za lèto",
+ "echo-notification-markasread": "Ségnelo come zà lèto",
+ "echo-notification-markasunread": "Ségnelo come gnancora lèto",
+ "echo-notification-markasread-tooltip": "Ségnelo come zà lèto",
+ "echo-notification-more-options-tooltip": "Altre posibilità",
+ "notification-link-text-expand-all": "Slarga",
+ "notification-link-text-expand-alert-count": "Varda {{PLURAL:$1|$1 aviso|$1 avisi}}",
+ "notification-link-text-expand-notice-count": "Varda {{PLURAL:$1|$1 notisia|$1 notisie}}",
+ "notification-link-text-expand-all-count": "Varda $1 {{PLURAL:$1|aviso|avisi}}",
+ "notification-link-text-collapse-all": "Strenzi",
"notification-link-text-view-message": "Varda messajo",
+ "notification-link-text-view-mention": "Varda dove i te gà nomenà",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Varda dove i te gà nomenà}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|Varda}} i canbiamenti",
+ "notification-link-text-view-page": "Varda la pagina",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|el|la}} te gà lassà un mesajo in te la <strong>{{GENDER:$3|to}} pagina de discusion</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|el|la}} te gà lassà un mesajo in te la <strong>{{GENDER:$3|to}} pagina de discusion</strong> su \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "Xe stà tacà un ligame da <strong>$4</strong> a <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Ligà da <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Xe stà ligà {{PLURAL:$5||$5 pagine|100=piassè de 99 pagine}} a <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Tuti i ligami verso de sta pagina",
+ "notification-header-mention-other": "$1 {{GENDER:$2|el|la}} te gà {{GENDER:$3|nomenà}} su <strong>$4</strong> in \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|el|la}} te gà {{GENDER:$3|nomenà}} su <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|el|la}} te gà {{GENDER:$3|nomenà}} in te la <strong>pagina de discusion {{GENDER:$5|de}} $4</strong> in \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|el|la}} te gà {{GENDER:$3|nomenà}} in te la <strong>pagina de discusion {{GENDER:$5|de}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|el|la}} te gà {{GENDER:$3|nomenà}} in te la <strong>so pagina de discusion</strong> in \"<strong>$4</strong>\".",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2|el|la}} te gà {{GENDER:$3|nomenà}} in te la <strong>so pagina de discusion</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2|el|la}} te gà {{GENDER:$3|nomenà}} in te la pagina de discusion de <strong>$4</strong> in \"<strong>$5</strong>\".",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2|el|la}} te gà {{GENDER:$3|nomenà}} in te la pagina de discusion de <strong>$4</strong>.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Sto nome utente no'l gh'è mia:</strong> $1",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|Te ghè nomenà}}:</strong> $3",
+ "notification-welcome-linktext": "Benvegnù!",
+ "notification-header-thank-you-1-edit": "Te gh'è 'pena fato el to primo canbiamento; grasie e {{GENDER:$2|benvegnùo|benvegnùa|benvegnùo/a}}!",
+ "notification-header-thank-you-10-edit": "Te sì 'pena rivà a diese canbiamenti; grasie e {{GENDER:$2|va vanti cussì}}!",
+ "notification-header-thank-you-100-edit": "Te sì 'pena rivà a sento canbiamenti; {{GENDER:$2|tante grasie}}!",
+ "notification-header-thank-you-1000-edit": "Te sì 'pena rivà a mile canbiamenti; {{GENDER:$2|grasie de sto gran laoro}}!",
+ "notification-header-thank-you-10000-edit": "Te sì 'pena rivà a diesemila canbiamenti; {{GENDER:$2|grasie de sto gran laoro}}!",
+ "notification-header-thank-you-100000-edit": "Te sì 'pena rivà a sentomila canbiamenti; {{GENDER:$2|grasie de sto gran laoro}}!",
+ "notification-header-thank-you-1000000-edit": "Te sì 'pena rivà a un milion de canbiamenti; {{GENDER:$2|grasie de sto gran laoro}}!",
+ "notification-link-thank-you-edit": "El {{GENDER:$1|to}} canbiamento",
+ "notification-link-text-view-edit": "Varda el canbiamento",
+ "notification-header-reverted": "{{PLURAL:$4|El to canbiamento|I to canbiamenti}} su <strong>$3</strong> {{PLURAL:$4|el xe stà desfà|i xe stà desfài}}{{GENDER:$2|}}",
+ "notification-header-emailuser": "$1 {{GENDER:$2|el|la}} te gà mandà na email.",
+ "notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|el|la}} te gà lassà un mesajo su {{SITENAME}}.",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|el|la}} te gà lassà un mesajo su la to pagina de discusion in \"$2\".",
+ "notification-page-linked-email-subject": "Na pagina fata da ti la xe stà ligà su {{SITENAME}}",
+ "notification-reverted-email-subject2": "{{PLURAL:$3|El to canbiamento el xe stà desfà|I to canbiamenti i xe stà desfài}} {{GENDER:$1|su}} {{SITENAME}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|el|la}} te gà {{GENDER:$2|nomenà}} su {{SITENAME}}",
+ "notification-user-rights-email-subject": "I to diriti utente su {{SITENAME}} i xe stà canbià",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1 s}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 m}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1 h}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1 d}}",
+ "notification-timestamp-ago-months": "$1 {{PLURAL:$1|mese|mesi}}",
+ "notification-timestamp-ago-years": "$1 {{PLURAL:$1|ano|ani}}",
+ "notification-timestamp-today": "Uncuò",
+ "notification-timestamp-yesterday": "Jèri",
+ "notification-inbox-filter-read": "Za lèti",
+ "notification-inbox-filter-unread": "Da lèzar",
+ "notification-inbox-filter-all": "Tuti",
+ "echo-email-body-default": "Te gh'è n'aviso novo su {{SITENAME}}:\n\n$1",
+ "echo-notification-alert": "{{PLURAL:$1|Aviso ($1)|Avisi ($1)|100=Avisi (99+)}}",
+ "echo-notification-alert-text-only": "Avisi",
+ "echo-notification-notice-text-only": "Notisie",
+ "echo-overlay-link": "Tuti i avisi",
+ "echo-overlay-title": "<b>Avisi</b>",
+ "echo-overlay-title-overflow": "<b>{{PLURAL:$1|Aviso|Avisi}}</b> (mostra $1 de $2 mia lèti)",
"echo-mark-all-as-read": "Segna tuto come zà lèto",
+ "echo-mark-all-as-read-confirmation": "$1 {{PLURAL:$1|aviso segnà come leto|avisi segnà come leti}}",
"echo-date-today": "Uncuò",
"echo-date-yesterday": "Jeri"
}
diff --git a/Echo/i18n/vep.json b/Echo/i18n/vep.json
new file mode 100644
index 00000000..a3871bce
--- /dev/null
+++ b/Echo/i18n/vep.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sebranik"
+ ]
+ },
+ "tooltip-pt-notifications-alert": "Teiden tedotamižed",
+ "tooltip-pt-notifications-message": "Teiden tedotused"
+}
diff --git a/Echo/i18n/vi.json b/Echo/i18n/vi.json
index bdf9f814..6c9e5f2d 100644
--- a/Echo/i18n/vi.json
+++ b/Echo/i18n/vi.json
@@ -4,7 +4,9 @@
"Baonguyen21022003",
"Minh Nguyen",
"Trần Nguyễn Minh Huy",
- "Max20091"
+ "Max20091",
+ "Nguyên Lê",
+ "Quenhitran"
]
},
"echo-desc": "Hệ thống thông báo cho người dùng về các sự kiện và thay đổi quan trọng",
@@ -12,6 +14,7 @@
"prefs-emailsettings": "Tùy chọn thư điện tử",
"prefs-displaynotifications": "Tùy chọn hiển thị",
"prefs-echosubscriptions": "Báo cho tôi biết về những sự kiện này",
+ "prefs-echocrosswiki": "Thông báo liên wiki",
"prefs-newmessageindicator": "Đèn tin nhắn mới",
"echo-pref-send-me": "Gửi thư cho tôi:",
"echo-pref-send-to": "Gửi đến:",
@@ -24,99 +27,172 @@
"echo-pref-email-frequency-weekly": "Tóm lược các thông báo hàng tuần",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "Văn bản thuần",
+ "echo-pref-cross-wiki-notifications": "Hiển thị thông báo từ wiki khác",
"echo-pref-new-message-indicator": "Hiển thị đèn tin nhắn trên thanh công cụ của tôi",
+ "echo-pref-beta-feature-cross-wiki-message": "Thông báo được cải tiến",
+ "echo-pref-beta-feature-cross-wiki-description": "Xem và quản lý các thông báo dễ dàng hơn. Bao gồm các thông báo liên wiki, cho phép bạn xem tin nhắn từ các wiki khác. (Để nhận thông báo liên wiki trên một wiki nào đó, bạn phải kích hoạt tính năng beta trên wiki đó.)",
"echo-learn-more": "Tìm hiểu thêm",
+ "echo-log": "Nhật trình công khai",
"echo-new-messages": "Bạn có tin nhắn mới",
"echo-category-title-edit-user-talk": "{{PLURAL:$1}}Lời tin nhắn",
"echo-category-title-article-linked": "{{PLURAL:$1}}Liên kết đến trang",
"echo-category-title-reverted": "{{PLURAL:$1}}Lùi sửa",
"echo-category-title-mention": "{{PLURAL:$1}}Lời nói đến",
+ "echo-category-title-mention-failure": "{{PLURAL:$1|Lời nhắc đến|Các lời nhắc đến}} thất bại",
+ "echo-category-title-mention-success": "{{PLURAL:$1|Lời nhắc đến|Các lời nhắc đến}} thành công",
"echo-category-title-other": "{{PLURAL:$1}}Khác",
"echo-category-title-system": "{{PLURAL:$1}}Hệ thống",
"echo-category-title-user-rights": "{{PLURAL:$1|Các thay đổi|Thay đổi}} về quyền người dùng",
+ "echo-category-title-emailuser": "Thư điện tử nhận từ {{PLURAL:$1|người dùng|những người dùng}} khác",
"echo-pref-tooltip-edit-user-talk": "Báo cho tôi biết khi nào người ta nhắn tin hoặc trả lời trên trang thảo luận của tôi.",
"echo-pref-tooltip-article-linked": "Báo cho tôi biết khi nào người ta đặt liên kết từ một bài đến một trang do tôi tạo ra.",
"echo-pref-tooltip-reverted": "Báo cho tôi khi nào người ta lùi lại một sửa đổi của tôi dùng chức năng Lùi sửa hoặc Lùi tất cả.",
"echo-pref-tooltip-mention": "Báo cho tôi biết khi có người đặt liên kết đến trang thành viên của tôi.",
- "echo-pref-tooltip-user-rights": "Thông báo cho tôi khi nào các quyền người dùng của tôi được thay đổi.",
- "echo-no-agent": "[Không ai]",
- "echo-no-title": "[Không có trang]",
+ "echo-pref-tooltip-mention-failure": "Báo cho tôi biết khi tôi không thể nhắc đến người khác.",
+ "echo-pref-tooltip-mention-success": "Báo cho tôi khi tôi nhắc đến người khác.",
+ "echo-pref-tooltip-user-rights": "Báo cho tôi biết khi có người thay đổi quyền người dùng của tôi.",
+ "echo-pref-tooltip-emailuser": "Báo cho tôi biết khi có người gửi thư cho tôi.",
"echo-error-no-formatter": "Thông báo không có định rõ định dạng",
"notifications": "Thông báo",
- "tooltip-pt-notifications-alert": "Thông báo cho bạn",
- "tooltip-pt-notifications-message": "Tin nhắn cho bạn",
+ "tooltip-pt-notifications-alert": "Tin nhắn cho bạn",
+ "tooltip-pt-notifications-notice": "Thông báo cho bạn",
+ "echo-displaynotificationsconfiguration": "Cấu hình hiển thị thông báo",
+ "echo-displaynotificationsconfiguration-summary": "Đây là cấu hình hiển thị thông báo trên wiki này.",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "Thông báo theo lý do",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "Sắp xếp loại",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "Loại thông báo nào được sắp xếp vào phần nào",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "Các phương thức thông báo cho phép",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "Các phương thức thông báo được hỗ trợ cho từng loại thông báo",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "Phương thức thông báo nào được hỗ trợ cho từng loại; chỉ có liên quan đến các loại thông báo vì các lý do được ẩn trong tùy chọn",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "Kích hoạt theo mặc định",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "Người dùng đã tồn tại",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "Người dùng mới",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "Phương thức thông báo bắt buộc",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "Phương thức thông báo nào là bắt buộc cho từng lý do",
"echo-specialpage": "Thông báo",
+ "echo-specialpage-section-markread": "Đánh dấu cả phần là đã đọc",
+ "echo-specialpage-markasread": "Thông báo: Đánh dấu là đã đọc",
+ "echo-specialpage-markasread-invalid-id": "ID sự kiện không hợp lệ",
+ "echo-specialpage-pagination-numnotifications": "$1 thông báo",
+ "echo-specialpage-pagefilters-title": "Hoạt động gần đây",
+ "echo-specialpage-pagefilters-subtitle": "Trang có thông báo chưa đọc",
+ "notificationsmarkread-legend": "Đánh dấu thông báo là đã đọc",
"echo-anon": "Để nhận thông báo, hãy [$1 mở tài khoản] hoặc [$2 đăng nhập].",
"echo-none": "Bạn không có thông báo.",
"echo-more-info": "Thêm thông tin",
"echo-feedback": "Phản hồi",
+ "echo-popup-footer-special-page-invitation": "<strong>Hãy thử trang Thông báo được sửa sang.</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "Có thiết kế và chức năng mới.",
"echo-quotation-marks": "“$1”",
+ "echo-api-failure": "Thất bại khi lấy thông báo.",
+ "echo-api-failure-cross-wiki": "Truy cập tới tên miền từ xa bị từ chối.",
+ "echo-notification-placeholder": "Không có thông báo.",
+ "echo-notification-placeholder-filters": "Không có thông báo khớp với các bộ lọc này.",
+ "echo-notification-loginrequired": "Bạn phải đăng nhập để xem các thông báo của mình.",
+ "echo-notification-popup-loginrequired": "Xin hãy đăng nhập để xem các thông báo của bạn.",
+ "echo-notification-markasread": "Đánh dấu là đã đọc",
+ "echo-notification-markasunread": "Đánh dấu là chưa đọc",
+ "echo-notification-markasread-tooltip": "Đánh dấu là đã đọc",
+ "echo-notification-more-options-tooltip": "Thêm tùy chọn",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3}}Ngừng theo dõi hoạt động mới tại “$1”",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3}}Bạn không còn theo dõi trang “$1”",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3}}Bạn có thể theo dõi [$2 trang này] bất cứ lúc nào.",
+ "notification-dynamic-actions-watch": "{{GENDER:$3}}Theo dõi hoạt động mới tại “$1”",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3}}Bạn hiện đang theo dõi trang “$1”",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3}}Bạn có thể ngừng theo dõi [$2 trang này] bất cứ lúc nào.",
+ "notification-link-text-expand-all": "Mở rộng",
+ "notification-link-text-expand-alert-count": "Xem $1 thông báo",
+ "notification-link-text-expand-notice-count": "Xem $1 thông báo",
+ "notification-link-text-expand-all-count": "Xem $1 thông báo",
+ "notification-link-text-collapse-all": "Thu gọn",
"notification-link-text-view-message": "Xem thông điệp",
"notification-link-text-view-mention": "Xem lời nói đến bạn",
- "notification-link-text-view-changes": "Xem các thay đổi",
+ "notification-link-text-view-mention-failure": "Xem {{PLURAL:$1|lời nhắc đến|các lời nhắc đến}}",
+ "notification-link-text-view-changes": "{{GENDER:$1}}Xem các thay đổi",
"notification-link-text-view-page": "Xem trang",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2}}đã để lại một tin nhắn trên <strong>trang thảo luận {{GENDER:$3}}của bạn</strong>.",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2}}đã để lại một tin nhắn trên <strong>trang thảo luận {{GENDER:$3}}của bạn</strong> trong “<strong>$4</strong>”.",
+ "notification-header-page-linked": "Một liên kết đã được tạo từ <strong>$4</strong> tới <strong>$3</strong>.",
+ "notification-compact-header-page-linked": "Liên kết từ <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "Các liên kết đã được tạo từ {{PLURAL:$5|một trang|$5 trang|100=99+ trang}} tới <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "Mọi liên kết đến trang này",
+ "notification-header-mention-other": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$3}}bạn tại trang <strong>$4</strong> trong “<strong>$5</strong>”.",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|đã nhắc đến}} {{GENDER:$3|bạn}} tại trang <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$3}}bạn tại <strong>trang thảo luận thành viên của {{GENDER:$5}}$4</strong> trong “<strong>$6</strong>”.",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$3}}bạn tại <strong>trang thảo luận của {{GENDER:$5}}$4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$3}}bạn tại <strong>trang thảo luận của họ</strong> trong “<strong>$4</strong>”.",
+ "notification-header-mention-agent-talkpage-nosection": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$3}}bạn tại <strong>trang thảo luận của họ</strong>.",
+ "notification-header-mention-article-talkpage": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$3}}bạn tại trang thảo luận của <strong>$4</strong> trong “<strong>$5</strong>”.",
+ "notification-header-mention-article-talkpage-nosection": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$3}}bạn tại trang thảo luận của <strong>$4</strong>.",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2}}Bạn đã nhắc đến <strong>$3</strong> nhưng người dùng này không tồn tại.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2}}Bạn đã nhắc đến <strong>$3</strong> nhưng người dùng vô danh không nhận được thông báo về lời nhắc đến này.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2}}Bạn đã nhắc đến người dùng nhưng họ sẽ không nhận được thông báo vì bạn đã vượt quá hạn chế $3 người dùng.",
+ "notification-header-mention-failure-bundle": "{{GENDER:$2}}Bạn đã nhắc đến {{PLURAL:$3|một người dùng|$3 người dùng}} trong trang thảo luận <strong>$4</strong> nhưng họ không nhận được thông báo.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Tên người dùng không tồn tại:</strong> $1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Không thể thông báo địa chỉ IP về lời nhắc đến:</strong> $1",
+ "notification-header-mention-success": "<strong>$3</strong> đã được thông báo rằng {{GENDER:$2}}bạn đã nhắc đến họ.",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|Một người dùng|$3 người dùng}} đã được thông báo rằng {{GENDER:$2}}bạn đã nhắc đến họ trong trang thảo luận <strong>$4</strong>.",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2}}Bạn đã nhắc đến:</strong> $3",
+ "notification-header-mention-status-bundle": "Trong số $3 người mà {{GENDER:$2}}bạn đã nhắc đến trong trang thảo luận <strong>$4</strong>, $6 người đã nhận thông báo, còn $5 người không nhận được thông báo.",
+ "notification-header-user-rights-add-only": "Các quyền người dùng của {{GENDER:$4}}bạn đã được {{GENDER:$1}}thay đổi. Bạn đã được thêm vào: $2.",
+ "notification-header-user-rights-remove-only": "Các quyền người dùng của {{GENDER:$4}}bạn đã được {{GENDER:$1}}thay đổi. Bạn không còn là thành viên của: $2.",
+ "notification-header-user-rights-add-and-remove": "Các quyền người dùng của {{GENDER:$6}}bạn đã được {{GENDER:$1}}thay đổi. Bạn đã được thêm vào: $2. Bạn không còn là thành viên của: $4.",
+ "notification-header-welcome": "{{GENDER:$2}}Chào mừng $1 đã đến với {{SITENAME}}! Chúng tôi rất vui vì bạn đã tham gia.",
+ "notification-welcome-linktext": "Chào mừng",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2}}Bạn vừa thực hiện sửa đổi đầu tiên; cảm ơn và chào mừng!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2}}Bạn vừa thực hiện sửa đổi lần thứ 10; cảm ơn và xin hãy tiếp tục!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2}}Bạn vừa thực hiện sửa đổi lần thứ 100; rất cảm ơn bạn!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2}}Bạn vừa thực hiện sửa đổi lần thứ một ngàn; cảm ơn bạn vì các đóng góp to lớn!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2}}Bạn đã thực hiện sửa đổi lần thứ 10.000; chân thành cảm ơn bạn!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2}}Bạn vừa thực hiện sửa đổi lần thứ 100.000; cảm ơn bạn vì lượng đóng góp đáng khen!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2}}Bạn vừa thực hiện sửa đổi lần thứ một triệu; cảm ơn bạn vì lượng đóng góp anh hùng!",
+ "notification-link-thank-you-edit": "{{GENDER:$1}}Sửa đổi của bạn",
"notification-link-text-view-edit": "Xem sửa đổi",
- "notification-edit-talk-page2": "[[User:$1|$1]] đã nhắn tin vào [[User talk:$2#$3|trang thảo luận]] của bạn.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] đã {{GENDER:$1}}nhắn tin cho bạn trong “[[User talk:$2#$3|$4]]”.",
- "notification-edit-talk-page-flyout2": "$1 đã nhắn tin vào [[User talk:$2#$3|trang thảo luận]] của bạn.",
- "notification-edit-talk-page-flyout-with-section": "$1 đã {{GENDER:$1}}nhắn tin cho bạn trong “[[User talk:$2#$3|$4]]”.",
- "notification-page-linked": "[[:$3]] mới {{GENDER:$1}}có liên kết đến [[:$2]]. [[Special:WhatLinksHere/$2|Xem tất cả các liên kết đến trang này]].",
- "notification-page-linked-flyout": "[[:$3]] mới {{GENDER:$1}}có liên kết đến [[:$2]]",
- "notification-add-comment2": "[[User:$1|$1]] đã bình luận về “[[$3|$2]]” tại trang thảo luận “$4”",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] đã bắt đầu cuộc thảo luận mới về “$2” tại [[$3]]",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] đã nhắn tin cho bạn: “[[$3#$2|$2]]”",
- "notification-add-comment-yours2": "[[User:$1|$1]] đã bình luận về “[[$3#$2|$2]]” tại trang thảo luận của bạn",
- "notification-mention": "[[User:$1|$1]] đã nói đến bạn trên trang tin nhắn của $5 trong “[[:$3#$2|$4]]”.",
- "notification-mention-flyout": "$1 đã nói đến bạn trên trang tin nhắn của $5 trong “[[:$3#$2|$4]]”.",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1}}đã nói đến bạn trên [[:$3|trang thảo luận $2]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1}}đã nói đến bạn trên [[:$3|trang thảo luận $2]].",
- "notification-user-rights": "[[User:$1|$1]] {{GENDER:$1}}đã [[Special:Log/rights/$1|thay đổi]] các quyền người dùng của bạn. $2. [[Special:ListGroupRights|Tìm hiểu thêm]]",
- "notification-user-rights-flyout": "$1 {{GENDER:$1}}đã thay đổi các quyền người dùng của bạn. $2. [[Special:ListGroupRights|Tìm hiểu thêm]]",
- "notification-user-rights-add": "Bạn mới là thành viên của {{PLURAL:$2|nhóm|các nhóm}} này: $1",
- "notification-user-rights-remove": "Bạn không còn là thành viên của {{PLURAL:$2|nhóm|các nhóm}} này: $1",
- "notification-new-user": "Chào mừng $1 đã đến với {{SITENAME}}!",
- "notification-reverted2": "[[User:$1|$1]] đã lùi lại {{PLURAL:$4|sửa đổi|các sửa đổi}} của bạn tại [[:$2]] $3",
- "notification-reverted-flyout2": "$1 đã lùi lại {{PLURAL:$4|sửa đổi|các sửa đổi}} của bạn tại $2 $3",
+ "notification-header-reverted": "{{PLURAL:$4|Sửa đổi|Các sửa đổi}} của bạn tại <strong>$3</strong> đã bị {{GENDER:$2}}lùi lại.",
+ "notification-header-emailuser": "$1 {{GENDER:$2}}đã gửi bạn bức thư điện tử.",
"notification-edit-talk-page-email-subject2": "$1 đã {{GENDER:$1}}nhắn tin cho bạn trên {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 đã nhắn tin vào trang thảo luận của bạn.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 đã {{GENDER:$1}}nhắn tin cho bạn trong “$2”.",
"notification-page-linked-email-subject": "Có liên kết mới đến một trang do bạn tạo ra tại {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$3 mới {{GENDER:$1}}có liên kết đến $2",
"notification-reverted-email-subject2": "{{PLURAL:$3|Sửa đổi|Các sửa đổi}} của bạn đã bị {{GENDER:$1}}lùi lại trên {{SITENAME}}",
- "notification-reverted-email-batch-body2": "$1 đã lùi lại {{PLURAL:$3|sửa đổi|các sửa đổi}} của bạn tại $2",
- "notification-mention-email-subject": "$1 đã nói đến bạn tại {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 đã nói đến bạn trên trang tin nhắn của $4 trong “$3”",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1}}đã nói đến bạn trên trang thảo luận $2.",
+ "notification-mention-email-subject": "$1 đã nói đến {{GENDER:$2}}bạn tại {{SITENAME}}",
"notification-user-rights-email-subject": "Các quyền người dùng của bạn đã thay đổi tại {{SITENAME}}",
- "notification-user-rights-email-batch-body": "$1 {{GENDER:$1}}đã thay đổi các quyền người dùng của bạn. $2",
- "echo-email-subject-default": "Thông báo mới tại {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "$1gi",
+ "notification-timestamp-ago-minutes": "$1ph́",
+ "notification-timestamp-ago-hours": "$1g̀",
+ "notification-timestamp-ago-days": "$1ng̀",
+ "notification-timestamp-ago-months": "$1th́",
+ "notification-timestamp-ago-years": "$1n",
+ "notification-timestamp-today": "Hôm nay",
+ "notification-timestamp-yesterday": "Hôm qua",
+ "notification-inbox-filter-read": "Đọc",
+ "notification-inbox-filter-unread": "Chưa đọc",
+ "notification-inbox-filter-all": "Tất cả",
"echo-email-body-default": "Bạn có thông báo mới tại {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "Bạn có thông báo mới",
- "echo-email-footer-default": "$2\n\nĐể cấu hình hoặc tắt các thông báo qua thư điện tử, hãy xem tùy chọn của bạn:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-email-footer-default-html": "Để kiểm soát các thư điện tử mà chúng tôi gửi cho bạn, hãy <a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">kiểm tra tùy chọn của bạn</a>.<br />\n$1",
+ "echo-email-footer-default": "$2\n\nĐể cấu hình hoặc tắt các thông báo qua thư điện tử, hãy xem tùy chọn của bạn:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "Để kiểm soát các thư điện tử mà chúng tôi gửi cho bạn, hãy kiểm tra tùy chọn của bạn:",
+ "echo-email-html-footer-preference-link-text": "kiểm tra tùy chọn của bạn",
+ "echo-email-html-footer-with-link": "Để kiểm soát các thư điện tử mà chúng tôi gửi cho bạn, hãy $1.",
"echo-notification-alert": "{{PLURAL:$1|Tin nhắn ($1)|100=Tin nhắn (99+)}}",
- "echo-notification-message": "{{PLURAL:$1|Thông điệp ($1)|100=Thông điệp (99+)}}",
+ "echo-notification-notice": "{{PLURAL:$1|Thông báo ($1)|100=Thông báo (99+)}}",
"echo-notification-alert-text-only": "Tin nhắn",
- "echo-notification-message-text-only": "Thông điệp",
+ "echo-notification-notice-text-only": "Thông báo",
"echo-overlay-link": "Tất cả các thông báo",
"echo-overlay-title": "<b>Thông báo</b>",
"echo-overlay-title-overflow": "<b>Tin nhắn</b> (đang xem $1 trên $2 chưa đọc)",
"echo-mark-all-as-read": "Đánh dấu tất cả là đã đọc",
+ "echo-mark-all-as-read-confirmation": "$1 thông báo được đánh dấu là đã đọc",
+ "echo-mark-wiki-as-read": "Đánh dấu tất cả là đã đọc trong wiki được chọn: $1",
"echo-date-today": "Hôm nay",
"echo-date-yesterday": "Hôm qua",
"echo-load-more-error": "Lỗi đã xảy ra khi lấy thêm kết quả.",
- "notification-edit-talk-page-bundle": "$1 và $3 {{PLURAL:$4}}người khác đã {{GENDER:$1}}nhắn tin vào [[User talk:$2|trang thảo luận]] của bạn.",
- "notification-page-linked-bundle": "$3 và $4 {{PLURAL:$5}}trang khác mới {{GENDER:$1}}có liên kết đến $2. [[Special:WhatLinksHere/$2|Xem tất cả các liên kết đến trang này]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 và $2 {{PLURAL:$3}}người khác {{GENDER:$1}}đã nhắn tin vào trang thảo luận của bạn",
- "notification-page-linked-email-batch-bundle-body": "$3 và $4 {{PLURAL:$5}}trang khác {{GENDER:$1}}mới có liên kết đến $2",
+ "notification-bundle-header-edit-user-talk-v2": "{{PLURAL:$1|Một tin nhắn|$1 tin nhắn|100=99+ tin nhắn}} mới tại <strong>trang thảo luận của {{GENDER:$3}}bạn</strong>.",
"echo-email-batch-subject-daily": "Bạn có {{PLURAL:$2|một tin nhắn|các tin nhắn}} mới hôm nay trên {{SITENAME}}",
"echo-email-batch-subject-weekly": "Bạn có {{PLURAL:$2|thông báo|các thông báo}} mới trên {{SITENAME}} tuần này",
"echo-email-batch-body-intro-daily": "Chào $1,\nĐây là bản tóm tắt các chuyện xảy ra hôm nay trên {{SITENAME}}.",
"echo-email-batch-body-intro-weekly": "Chào $1,\nĐây là bản tóm tắt các chuyện xảy ra vào tuần này trên {{SITENAME}}.",
"echo-email-batch-link-text-view-all-notifications": "Xem tất cả thông báo",
- "echo-rev-deleted-text-view": "Phiên bản trang này đã bị ẩn",
- "apihelp-echomarkread-param-list": "Danh sách các ID thông báo để đánh dấu là đã đọc.",
- "apihelp-echomarkread-example-2": "Đánh dấu tất cả thông báo là đã đọc",
- "apihelp-query+notifications-param-prop": "Chi tiết để yêu cầu.",
- "apihelp-query+notifications-example-1": "Danh sách thông báo"
+ "notification-header-foreign-alert": "Thêm thông báo từ {{PLURAL:$5|một wiki|$5 wiki}} khác",
+ "notification-header-foreign-notice": "Thêm thông báo từ {{PLURAL:$5|một wiki nữa|$5 wiki nữa}}",
+ "notification-header-foreign-all": "Thêm thông báo từ {{PLURAL:$5|một wiki|$5 wiki}} khác"
}
diff --git a/Echo/i18n/vro.json b/Echo/i18n/vro.json
index 920aebca..f43611f5 100644
--- a/Echo/i18n/vro.json
+++ b/Echo/i18n/vro.json
@@ -4,5 +4,5 @@
"Võrok"
]
},
- "tooltip-pt-notifications": "Suq teedüseq"
+ "tooltip-pt-notifications-alert": "{{GENDER:|Muq märgoandõq}}"
}
diff --git a/Echo/i18n/wa.json b/Echo/i18n/wa.json
new file mode 100644
index 00000000..6fd705c7
--- /dev/null
+++ b/Echo/i18n/wa.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Srtxg"
+ ]
+ },
+ "prefs-echo": "Notifiaedjes",
+ "tooltip-pt-notifications-alert": "Vos abranles",
+ "tooltip-pt-notifications-message": "Vos messaedjes"
+}
diff --git a/Echo/i18n/war.json b/Echo/i18n/war.json
index e30f62fb..07de6e2e 100644
--- a/Echo/i18n/war.json
+++ b/Echo/i18n/war.json
@@ -4,5 +4,9 @@
"JinJian"
]
},
- "tooltip-pt-notifications": "Imo mga pasabot"
+ "echo-pref-web": "Web",
+ "echo-pref-email": "Email",
+ "echo-pref-email-format-html": "HTML",
+ "tooltip-pt-notifications-alert": "{{GENDER:|Your}} mga alerto",
+ "tooltip-pt-notifications-message": "{{GENDER:|Imo}} mga mensahe"
}
diff --git a/Echo/i18n/wuu.json b/Echo/i18n/wuu.json
index 53f232f5..56b613c9 100644
--- a/Echo/i18n/wuu.json
+++ b/Echo/i18n/wuu.json
@@ -1,8 +1,12 @@
{
"@metadata": {
"authors": [
- "Poiuyt"
+ "Poiuyt",
+ "飞舞回堂前"
]
},
- "tooltip-pt-notifications": "侬个通知"
+ "echo-pref-send-me": "发畀我:",
+ "echo-pref-send-to": "发送到:",
+ "tooltip-pt-notifications-alert": "{{GENDER:|侬}}个提示",
+ "tooltip-pt-notifications-message": "{{GENDER:|侬个}}通知"
}
diff --git a/Echo/i18n/xmf.json b/Echo/i18n/xmf.json
index 0a29e80c..6a5f1822 100644
--- a/Echo/i18n/xmf.json
+++ b/Echo/i18n/xmf.json
@@ -4,5 +4,8 @@
"Silovan"
]
},
- "tooltip-pt-notifications": "თქვან ოგინაფუეფი"
+ "tooltip-pt-notifications-alert": "{{GENDER:|თქვანი}} მოშინუეფი",
+ "tooltip-pt-notifications-message": "{{GENDER:|თქვანი}} გინაფეფი",
+ "echo-notification-markasread": "უკითხირო შანუა",
+ "echo-email-html-footer-preference-link-text": "გეგნაჯინით თქვანი პარამეტრეფს"
}
diff --git a/Echo/i18n/yi.json b/Echo/i18n/yi.json
index e2c90323..e57c6bfc 100644
--- a/Echo/i18n/yi.json
+++ b/Echo/i18n/yi.json
@@ -1,7 +1,9 @@
{
"@metadata": {
"authors": [
- "פוילישער"
+ "פוילישער",
+ "Macofe",
+ "Har-wradim"
]
},
"echo-desc": "סיסטעם פאר נאטיפֿיצירן באניצער וועגן פאסירונגען און מעלדונגען",
@@ -9,6 +11,7 @@
"prefs-emailsettings": "ע־פאסט אפציעס",
"prefs-displaynotifications": "ווײַזן אפציעס",
"prefs-echosubscriptions": "זיי מיך מודיע וועגן די דאזיקע געשעענישן",
+ "prefs-echocrosswiki": "איבערוויקי הודעות",
"prefs-newmessageindicator": "נייער אנזאג ווייזער",
"echo-pref-send-me": "שיקט מיר:",
"echo-pref-send-to": "שיקט צו:",
@@ -16,13 +19,16 @@
"echo-pref-web": "וועב",
"echo-pref-email": "ע-פאסט",
"echo-pref-email-frequency-never": "שיקט מיר נישט קיין ע־פאסט אנזאגן",
- "echo-pref-email-frequency-immediately": "איינציקע אנזאגן ווען זיי קו מען אן",
+ "echo-pref-email-frequency-immediately": "איינציקע אנזאגן ווען זיי קומען אן",
"echo-pref-email-frequency-daily": "א טעגליכע רעזומע פון אנזאגן",
"echo-pref-email-frequency-weekly": "א וועכנטלעכע רעזומע פון אנזאגן",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "פשוטער טעקסט",
+ "echo-pref-cross-wiki-notifications": "ווייזן מודעות פון אנדערע וויקיס",
"echo-pref-new-message-indicator": "ווײַזן רעדן־בלאט מעלדונג סימן אין מײַן געצייג פאס",
+ "echo-pref-beta-feature-cross-wiki-message": "דערברייטערטע מודעות",
"echo-learn-more": "לערנען נאך",
+ "echo-log": "עפֿנטלעך לאגבוך",
"echo-new-messages": "איר האט נייע מעלדונגען",
"echo-category-title-edit-user-talk": "שמועס בלאט {{PLURAL:$1|מעלדונג|מעלדונגען}}",
"echo-category-title-article-linked": "בלאט {{PLURAL:$1|לינק|לינקען}}",
@@ -31,59 +37,101 @@
"echo-category-title-other": "{{PLURAL:$1|אנדערע}}",
"echo-category-title-system": "{{PLURAL:$1|סיסטעם}}",
"echo-category-title-user-rights": "{{PLURAL:$1|באניצער־רעכטן ענדערונג|באניצער־רעכטן ענדערונגען}}",
- "echo-pref-tooltip-edit-user-talk": "זיי מיך מודיע ווען עמעצער שיקט א מעלדונג אדער ענטפערט אויף מיין שמועס בלאט.",
- "echo-pref-tooltip-article-linked": "מים מודיע זײַן ווען איינער פארבינדט זיך צו א בלאט וואס איך האב געשאפן פון אן ארטיקל בלאט.",
- "echo-pref-tooltip-mention": "מיך מודיע זײַן ווען איינער פארבינדט זיך צו מײַן באניצער־בלאט.",
- "echo-no-agent": "[קיינער]",
- "echo-no-title": "[קיין בלאט]",
+ "echo-category-title-emailuser": "{{PLURAL:$1|בליצבריוו פון אנדער באניצער|בליצבריוו פון אנדערע באניצער}}",
+ "echo-pref-tooltip-edit-user-talk": "זיי מיר מודיע ווען עמעצער שיקט אַ מעלדונג אָדער ענטפערט אויף מיין שמועס בלאַט.",
+ "echo-pref-tooltip-article-linked": "זיי מיך מודיע ווען איינער פארבינדט זיך צו א בלאט וואס איך האב געשאפן פון אן אנדער בלאט.",
+ "echo-pref-tooltip-reverted": "זיי מיר מודיע ווען עמעצער שטעלט צוריק אַ רעדאַקטירונג וואָס איך האָב געמאַכט, ניצנדיק דעם אַנולירן אָדער ווידערשטעלן מכשיר.",
+ "echo-pref-tooltip-mention": "זיי מיר מודיע ווען עמעצער פאַרבינדט זיך צו מיין באַניצער־בלאַט.",
+ "echo-pref-tooltip-user-rights": "זיי מיר מודיע ווען עמעצער ענדערט מיינע באַניצער־רעכטן.",
+ "echo-pref-tooltip-emailuser": "זיי מיר מודיע ווען עמעצער שיקט מיר אַ בליצבריוו.",
"echo-error-no-formatter": "קיין פארמאטירונג נישט דעפינירט פאר דער הודעה.",
"notifications": "אנזאגן",
"tooltip-pt-notifications-alert": "{{GENDER:|אייערע}} אויפדערוואכן",
- "tooltip-pt-notifications-message": "{{GENDER:|אייערע}} מעלדונגען",
+ "tooltip-pt-notifications-notice": "{{GENDER:|אייערע}} מעלדונגען",
+ "echo-displaynotificationsconfiguration": "װײזן מודעות־קאנפֿיגוראַציע",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "מודעות לויט קאטעגאריע",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "סארטירן פון טיפן",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "עקזיסטירנדע באניצער",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "נײַע באַניצער",
"echo-specialpage": "אנזאגן",
+ "echo-specialpage-section-markread": "מארקירן גרופע געליינט",
+ "echo-specialpage-markasread": "מודעה: מאַרקירן װי געליינט",
+ "echo-specialpage-markasread-invalid-id": "אומגילטיגער געשעעניש אידענדיפֿיצירער",
+ "echo-specialpage-pagination-numnotifications": " {{PLURAL:$1|אײן מודעה|$1 מודעות}}",
+ "echo-specialpage-pagefilters-title": "לעצטע אקטיוויטעט",
+ "echo-specialpage-pagefilters-subtitle": "בלעטער מיט מודעות וואס מ׳האט נאך נישט געלייענט",
+ "notificationsmarkread-legend": "מארקירן מודעה געליינט",
"echo-anon": "כדי צו באקומען הודעות, [$1 שאפט א קאנטע] אדער [$2 לאגירט אריין].",
"echo-none": "איר האט נישט קיין אנזאגן.",
"echo-more-info": "נאך אינפארמאציע",
"echo-feedback": "פֿידבעק",
+ "echo-popup-footer-special-page-invitation-link": "ניי אױסזען און נייע פֿונקציעס.",
+ "echo-api-failure": "נישט געווען מעגלעך באקומען אנזאגן.",
+ "echo-notification-placeholder": "נישט פאראן קיין אנזאגן.",
+ "echo-notification-placeholder-filters": "קיין מודעות צוגעפאסט צו די קריטעריע.",
+ "echo-notification-loginrequired": "איר דארפט אריינלאגירן כדי זען אייערע אנזאגן.",
+ "echo-notification-popup-loginrequired": "זייט אזוי גיט ארײַנלאגירן צו זען אייערע מודעות.",
+ "echo-notification-markasread": "מאַרקירן געליינט",
+ "echo-notification-markasunread": "מאַרקירן נישט געליינט",
+ "echo-notification-markasread-tooltip": "מאַרקירן געליינט",
+ "echo-notification-more-options-tooltip": "נאך אפציעס",
+ "notification-link-text-expand-all": "פֿאַרברייטערן",
+ "notification-link-text-expand-alert-count": "באַקוקן {{PLURAL:$1|אײן מעלדונג|$1 מעלדונגען}}",
+ "notification-link-text-expand-notice-count": "באקוקן {{PLURAL:$1|איין מעלדונג|$1 מעלדונגען}}",
+ "notification-link-text-expand-all-count": "באַקוקן {{PLURAL:$1|אײן מודעה|$1 מודעות}}",
+ "notification-link-text-collapse-all": "אײַנציען",
"notification-link-text-view-message": "באקוקן מעלדונג",
- "notification-link-text-view-changes": "באקוקן ענדערונגען",
+ "notification-link-text-view-mention": "ווײַזן ציטאט",
+ "notification-link-text-view-changes": "{{GENDER:$1|באקוקן}} ענדערונגען",
"notification-link-text-view-page": "באקוקן בלאט",
+ "notification-header-edit-user-talk": "$1 {{GENDER:$2|האט געלאזט}} א מעלדונג אין <strong>{{GENDER:$3|אײַער}} רעדן בלאַט</strong>",
+ "notification-header-edit-user-talk-with-section": "$1 {{GENDER:$2|האט געלאזט}} א מעלדונג אויף <strong>{{GENDER:$3|אייער}} רעדן בלאַט</strong> אין \"<strong>$4</strong>\".",
+ "notification-header-page-linked": "א לינק איז געווארן געמאכט פון <strong>$3</strong> צו <strong>$4</strong>.",
+ "notification-compact-header-page-linked": "פֿארלינקט פֿון <strong>$1</strong>.",
+ "notification-bundle-header-page-linked": "לינקען זענען געשאפן געווארן פון {{PLURAL:$5|$5 בלעטער |100=99+ בלעטער}} צו <strong>$3</strong>.",
+ "notification-link-text-what-links-here": "אלע לינקען צו דעם דאזיקן בלאט",
+ "notification-header-mention-other": "$1 {{GENDER:$2|האט דערמאנט}} {{GENDER:$3|אייך}} אויף <strong>$4</strong> אין \"<strong>$5</strong>\".",
+ "notification-header-mention-other-nosection": "$1 {{GENDER:$2|האט דערמאנט}} {{GENDER:$3|אייך}} אויף <strong>$4</strong>.",
+ "notification-header-mention-user-talkpage-v2": "$1 {{GENDER:$2|האט}} {{GENDER:$3|אײך}} דארמאַנט אױפֿן <strong>באַניצער רעדן־בלאַט {{GENDER:$5|פֿון}} $4</strong> אין \"<strong>$6</strong>\".",
+ "notification-header-mention-user-talkpage-nosection": "$1 {{GENDER:$2|האט דערמאנט}} {{GENDER:$3|אייך}} אויפֿן <strong>באניצער שמועס בלאט{{GENDER:$5|פֿון}} $4</strong>.",
+ "notification-header-mention-agent-talkpage": "$1 {{GENDER:$2|האט דערמאנט}} {{GENDER:$3|אייך}} אויף <strong>{{GENDER:$2|זיין|איר|זייער}} שמועס בלאט</strong> אין \"<strong>$4</strong>\".",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>באניצער־נאמען עקזיסטירט נישט:</strong> $1",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|איר האט דערמאנט}}:</strong> $3",
+ "notification-header-welcome": "{{GENDER:$2|ברוך הבא}} צו {{SITENAME}}, $1! מיר פֿרייען זיך אז {{GENDER:$2|איר}} זענט דא.",
+ "notification-welcome-linktext": "ברוך הבא!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|אייער}} רעדאקטירונג",
"notification-link-text-view-edit": "באקוקן רעדאקטירונג",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|האט געלאזט}} א מעלדונג אויף אײַער [[User talk:$2#$3|שמועס בלאט]].",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|האט געלאזט}} א מעלדונג אויף אייער שמועס בלאט ביי \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|האט געלאזט}} א מעלדונג אויף אײַער [[User talk:$2#$3|שמועס בלאט]].",
- "notification-edit-talk-page-flyout-with-section": "$1 {{GENDER:$1|האט געלאזט}} א מעלדונג אויף אייער שמועס בלאט ביי \"[[User talk:$2#$3|$4]]\".",
- "notification-page-linked": "[[:$2]] איז געווארן {{GENDER:$1|פארלינקט}} פון [[:$3]]. [[Special:WhatLinksHere/$2|זען אלע לינקען צו דעם בלאט]].",
- "notification-page-linked-flyout": "[[:$2]] איז געווארן {{GENDER:$1|פֿאַרלינקט}} פֿון [[:$3]].",
- "notification-add-comment2": "[[User:$1|$1]] {{GENDER:$1|האט געלאזט א הערה}} וועגן \"[[$3|$2]]\" אויפן \"$4\" רעדן בלאט.",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] {{GENDER:$1|האט}} אײַך געשיקט אן אנזאג: \"[[$3#$2|$2]]\".",
- "notification-add-comment-yours2": "[[User:$1|$1]] {{GENDER:$1|האט געלאזט א הערה}} וועגן \"[[$3#$2|$2]]\" אויף אײַער רעדן בלאט.",
- "notification-mention": "[[User:$1|$1]] {{GENDER:$1|האט אײַך דערמאנט}} אויפן $5 רעדן בלאט אין \"[[:$3#$2|$4]]\".",
- "notification-mention-nosection": "[[User:$1|$1]] {{GENDER:$1|האט אײַך דערמאנט}} אויפן [[:$3|$2 רעדן בלאט]].",
- "notification-mention-nosection-flyout": "$1 {{GENDER:$1|האט אײַך דערמאנט}} אויפן [[:$3|$2 רעדן בלאט]].",
- "notification-user-rights-add": "איר זענט יעצט א מיטגליד פון {{PLURAL:$2|די גרופע |די גרופעס}}: $1",
- "notification-reverted2": " {{PLURAL:$4|אייער רעדאקטירונג אויף [[:$2]] |אייערע רעדאקטירונגען אויף [[:$2]] }} האט [[User:$1|$1]] {{GENDER:$1|צוריקגעדרייט}}. $3",
+ "notification-header-reverted": " {{PLURAL:$4|אייער רעדאקטירונג אויף <strong>$3</strong> איז|אייערע רעדאקטירונגען אויף <strong>$3</strong> זענען}} געווארן {{GENDER:$2|צוריקגעשטעלט}}.",
+ "notification-header-emailuser": "$1 {{GENDER:$2|האט אייך געשיקט}} א בליצבריוו.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|האט אייך געשריבן}} א נייע מעלדונג אינעם {{SITENAME}} וועבזייטל",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|האט געשריבן}} א מעלדונג אין אײַער רעדן בלאַט.",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|האט געלאזט}} א מעלדונג אין אײַער רעדן בלאַט אין \"$2\".",
"notification-page-linked-email-subject": "א בלאט איר האט געשאפן איז געווארן פֿאַרלינקט אויף {{SITENAME}}",
- "notification-page-linked-email-batch-body": "$2 איז געווארן {{GENDER:$1| פֿאַרלינקט}} פֿון $3.",
- "notification-mention-email-subject": "$1 {{GENDER:$1|האט אײַך דערמאנט}} אויף {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|האט אײַך דערמאנט}} אויפן $4 רעדן בלאט אין \"$3\".",
+ "notification-reverted-email-subject2": "Your {{PLURAL:$3|אייער רעדאקטירונג איז|אייערע רעדאקטירונגען זענען}} געווארן {{GENDER:$1|צוריקגעשטעלט}} אויף {{SITENAME}}",
+ "notification-mention-email-subject": "$1 {{GENDER:$1|האט {{GENDER:$2|אײַך}} דערמאנט}} אויף {{SITENAME}}",
"notification-user-rights-email-subject": "אײַערע באניצער־רעכטן זענען געווארן געענדערט אויף {{SITENAME}}",
- "echo-email-subject-default": "נײַער אנזאג בײַ {{SITENAME}}",
+ "notification-timestamp-ago-seconds": "{{PLURAL:איין סעקונדע1|$1 סעקונדעס}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1 מינוט}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|א שעה|$1 שעה׳ן}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|איין טאג|$1 טעג}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1 מאנאט}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1 יאר}}",
+ "notification-timestamp-today": "הײנט",
+ "notification-timestamp-yesterday": "נעכטן",
+ "notification-inbox-filter-read": "לייענען",
+ "notification-inbox-filter-unread": "נישט געליינט",
+ "notification-inbox-filter-all": "אַלע",
"echo-email-body-default": "איר האט א נײַעם אנזאג בײַ {{SITENAME}}:\n\n$1",
- "echo-email-batch-body-default": "איר האט א נײַעם אנזאג.",
- "echo-notification-message-text-only": "מעלדונגען",
+ "echo-email-html-footer-preference-link-text": "קאנטראלירן {{GENDER:$1|אייערע}} פרעפֿערענצן",
+ "echo-notification-alert": "{{PLURAL:$1|מעלדונג ($1)|מעלדונגען ($1)|100=מעלדונגען (99+)}}",
+ "echo-notification-alert-text-only": "מעלדונגען",
+ "echo-notification-notice-text-only": "נאטיצן",
"echo-overlay-link": "אלע הודעות",
"echo-overlay-title": "<b>הודעות</b>",
"echo-mark-all-as-read": "מאַרקירן אַלע געליינט",
+ "echo-mark-wiki-as-read": "מאַרקירן אַלע געליינט אין אױסגעקליבענע װיקי: $1",
"echo-date-today": "הײַנט",
"echo-date-yesterday": "נעכטן",
- "notification-edit-talk-page-bundle": "$1 און $3 {{PLURAL:$4|אנדערער|אנדערע}} {{GENDER:$1|האבן געלאזט}} אן אנזאג אויף אייער [[User talk:$2|רעדן בלאט]].",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 און $2 {{PLURAL:$3|אנדערער|אנדערע}} {{GENDER:$1|האבן געלאזט}} אן אנזאג אויף אייער רעדן בלאט.",
- "notification-page-linked-email-batch-bundle-body": "$2 איז געווארן {{GENDER:$1|געלינקט}} פון $3 און $4 {{PLURAL:$5|אנדער בלאט|אנדערע בלעטער}}.",
"echo-email-batch-link-text-view-all-notifications": "ווײַזן אלע אנזאגן",
- "echo-rev-deleted-text-view": "די בלאט־ווערסיע איז געווארן אונטערדרוקט.",
- "apihelp-echomarkread-param-sections": "א ליסטע פון אפטיילונגען צו מארקירן געלייענט."
+ "notification-header-foreign-alert": "נאך מעלדונגען פֿון {{PLURAL:$5|אַן אַנדער װיקי|$5 אַנדערע װיקיס}}",
+ "notification-header-foreign-all": "נאך מודעות פֿון {{PLURAL:$5|אַן אַנדער װיקי|$5 אַנדערע װיקיס}}"
}
diff --git a/Echo/i18n/yo.json b/Echo/i18n/yo.json
index 2c3acb48..f248ec86 100644
--- a/Echo/i18n/yo.json
+++ b/Echo/i18n/yo.json
@@ -1,11 +1,12 @@
{
"@metadata": {
"authors": [
- "Demmy"
+ "Demmy",
+ "Wikicology"
]
},
- "notifications": "Àwọn ìdálákìíyèsí",
- "tooltip-pt-notifications": "Àwọn ìdálákìíyèsí yín",
+ "notifications": "Àwọn ìfitólétí",
+ "tooltip-pt-notifications-alert": "Àwọn ìtaníjí rẹ",
"echo-specialpage": "Àwọn ìdálákìíyèsí",
"echo-none": "Ẹ kò ní ìdálákìíyèsí kankan.",
"notification-link-text-view-message": "Ìgbéwò ìránṣẹ́",
@@ -13,18 +14,14 @@
"notification-link-text-view-changes": "Ìgbéwò àwọn àtúnṣe tuntun",
"notification-link-text-view-page": "Ìgbéwò ojúewé",
"notification-link-text-view-edit": "Ìgbéwò àtúnṣe",
- "notification-edit-talk-page2": "[[User:$1|$1]] {{GENDER:$1|fi}} ìránṣẹ́ s'órí [[User talk:$2#$3|ojúewé ọ̀rọ̀]] yín.",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] {{GENDER:$1|fi}} ìránṣẹ́ s'órí ojúewé ọ̀rọ̀ yín ní \"[[User talk:$2#$3|$4]]\".",
- "notification-edit-talk-page-flyout2": "$1 {{GENDER:$1|fi}} ìránṣẹ́ sí [[User talk:$2#$3|ojúewé ọ̀rọ̀]] yín.",
"notification-edit-talk-page-email-subject2": "$1 {{GENDER:$1|fi}} ìránṣẹ́ fún yín lórí {{SITENAME}}",
- "notification-edit-talk-page-email-batch-body2": "$1 {{GENDER:$1|fi}} ìránṣẹ́ s'órí ojúewé ọ̀rọ̀ yín:",
"notification-edit-talk-page-email-batch-body-with-section": "$1 {{GENDER:$1|fi}} ìránṣẹ́ s'órí ojúewé ọ̀rọ̀ yín ní \"$2\".",
"notification-mention-email-subject": "$1 {{GENDER:$1|dárúkọ}} yín lórí {{SITENAME}}",
- "notification-mention-email-batch-body": "$1 {{GENDER:$1|dárúkọ}} yín lórí ojúewé ọ̀rọ̀ $4 nínú \"$3\".",
- "notification-mention-nosection-email-batch-body": "$1 {{GENDER:$1|dárúkọ}} yín lórí ojúewé ọ̀rọ̀ $2.",
- "echo-email-subject-default": "Ìdálákìíyèsí tuntun wà ní {{SITENAME}}",
+ "notification-timestamp-today": "Òní",
+ "notification-inbox-filter-read": "Àwòkà",
+ "notification-inbox-filter-unread": "Àìtíìgbéwò",
+ "notification-inbox-filter-all": "Gbogbo wọn",
"echo-email-body-default": "Ẹ ní ìdálákìíyèsí tuntun ní {{SITENAME}}:\n\n\n$1",
- "echo-email-batch-body-default": "Ẹ ní ìdálákìíyèsí tuntun.",
"echo-overlay-link": "Gbogbo ìdálákìíyèsí",
"echo-overlay-title": "<b>Àwọn ìdálákìíyèsí</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|Àwọn ìdálákìíyèsí}}</b> (ìhàn $1 nínú $2 àìtíìkà)",
diff --git a/Echo/i18n/yua.json b/Echo/i18n/yua.json
new file mode 100644
index 00000000..4602d73e
--- /dev/null
+++ b/Echo/i18n/yua.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lorenzoitza"
+ ]
+ },
+ "echo-category-title-mention-failure": "K'aschaji {{PLURAL:$1|mention|mentions}}",
+ "echo-pref-tooltip-mention-failure": "A'aten le ken k'exa'ak a'alakten men maax ma' patal tin k'exi'",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|Il maax ku t'aan yóolal|Il maax t'anik}}",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|Your}} a tuxt'aan \"$3\" ma' ta tuuxtabi' tumene le maaxo' ma' kaxta'abi'.",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|Your}} t'aana'ab tumen \"$3\" ma' tuuxta'ab tumen ma' oojletan máax tuuxtik.",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|Your}} a tuuxt'an ma'tuuxtabi' tumen maan u $3.",
+ "notification-header-mention-failure-bundle": "$3 t'aano'ob {{GENDER:$2|you made}} ichil <strong>$4</strong> u waalil t'aan tu'ux ma' tuuxtabi'.",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>Ma' ojeeltáan maaxi':</strong> \"$1\"",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>Ma' ojeelta'an maaxi':</strong> \"$1\""
+}
diff --git a/Echo/i18n/yue.json b/Echo/i18n/yue.json
index ef90224c..22f2b4af 100644
--- a/Echo/i18n/yue.json
+++ b/Echo/i18n/yue.json
@@ -2,7 +2,8 @@
"@metadata": {
"authors": [
"William915",
- "Wong128hk"
+ "Wong128hk",
+ "Ktchankt"
]
},
"echo-desc": "通知系統",
@@ -22,7 +23,6 @@
"echo-pref-email-frequency-weekly": "一個禮拜出一次",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "純文字",
- "echo-pref-notify-show-link": "喺工具列道出通知",
"echo-pref-new-message-indicator": "喺工具列道出新留言提示",
"echo-learn-more": "了解多啲",
"echo-new-messages": "你有新信",
@@ -37,10 +37,8 @@
"echo-pref-tooltip-reverted": "有人將我嘅修改打回頭,話我知。",
"echo-pref-tooltip-mention": "有人喺任何傾偈頁提及我嘅用戶頁,話我知。",
"echo-error-no-formatter": "無預定通知格式",
- "echo-error-preference": "出錯︰設定唔到用戶喜好。",
- "echo-error-token": "出錯︰攞唔到用戶保安編碼。",
"notifications": "通知",
- "tooltip-pt-notifications": "你嘅通知",
+ "tooltip-pt-notifications-alert": "{{GENDER:|你}}嘅提示",
"echo-specialpage": "通知",
"echo-anon": "要收到通知嘅話,就[$1 開戶]或者[$2 簽到]啦。",
"echo-none": "爾家無通知畀你",
@@ -51,17 +49,12 @@
"notification-link-text-view-changes": "去睇改咗啲乜",
"notification-link-text-view-page": "去睇嗰頁",
"notification-link-text-view-edit": "去睇改咗啲乜",
- "notification-edit-talk-page2": "[[User:$1|$1]]喺你[[User talk:$2#$3|傾偈版]]道{{GENDER:$1|留}}咗個訊息。",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]]喺你傾偈版小節「[[User talk:$2#$3|$4]]」道{{GENDER:$1|留}}咗個訊息。",
- "notification-edit-talk-page-flyout2": "$1喺你[[User talk:$2#$3|傾偈版]]道{{GENDER:$1|留}}咗個訊息。",
- "notification-edit-talk-page-flyout-with-section": "$1喺你傾偈版小節「[[User talk:$2#$3|$4]]」道{{GENDER:$1|留}}咗個訊息。",
- "notification-page-linked": "[[:$3]]道有連結{{GENDER:$1|連}}過去[[:$2]]。 [[Special:WhatLinksHere/$2|睇嗮有乜連過去]]",
- "notification-page-linked-flyout": "[[:$3]]道有連結{{GENDER:$1|連}}過去[[:$2]]。",
- "notification-add-comment2": "[[User:$1|$1]]喺「$4」傾偈頁小節「[[$3|$2]]」道{{GENDER:$1|發}}咗個意見。",
- "notification-add-talkpage-topic2": "[[User:$1|$1]]喺[[$3]]道{{GENDER:$1|開}}咗個小節「$2」。",
- "echo-email-batch-body-default": "你有新通知",
+ "echo-notification-alert-text-only": "提示",
+ "echo-notification-notice-text-only": "通知",
+ "echo-overlay-link": "所有通知",
+ "echo-overlay-title": "<b>通知</b>",
"echo-mark-all-as-read": "全部標做讀過",
"echo-date-today": "今日",
"echo-date-yesterday": "尋日",
- "echo-rev-deleted-text-view": "爾次修改收埋咗"
+ "echo-email-batch-link-text-view-all-notifications": "睇所有通知"
}
diff --git a/Echo/i18n/zgh.json b/Echo/i18n/zgh.json
new file mode 100644
index 00000000..808f8cbd
--- /dev/null
+++ b/Echo/i18n/zgh.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amara-Amaziɣ",
+ "Aslmad mohamed belarhzali"
+ ]
+ },
+ "tooltip-pt-notifications-message": "ⵜⵓⵣⵉⵏⵉⵏ {{GENDER:|ⵏⵏⴽ|ⵏⵏⵎ}}",
+ "notification-timestamp-today": "ⴰⵙⵙⴰ",
+ "notification-inbox-filter-read": "ⵖⵔ"
+}
diff --git a/Echo/i18n/zh-hans.json b/Echo/i18n/zh-hans.json
index 756fd851..641cac6e 100644
--- a/Echo/i18n/zh-hans.json
+++ b/Echo/i18n/zh-hans.json
@@ -26,7 +26,13 @@
"乌拉跨氪",
"Mywood",
"Impersonator 1",
- "EagerLin"
+ "EagerLin",
+ "范",
+ "Apflu",
+ "Cosine02",
+ "LNDDYL",
+ "飞舞回堂前",
+ "WhitePhosphorus"
]
},
"echo-desc": "用于通知用户有关活动和消息的系统",
@@ -34,7 +40,9 @@
"prefs-emailsettings": "电子邮件选项",
"prefs-displaynotifications": "显示选项",
"prefs-echosubscriptions": "通知我这些事件",
+ "prefs-echocrosswiki": "跨wiki通知",
"prefs-newmessageindicator": "新消息提示器",
+ "prefs-blocknotificationslist": "禁言用户",
"echo-pref-send-me": "给我发送:",
"echo-pref-send-to": "发送至:",
"echo-pref-email-format": "电子邮件格式:",
@@ -46,119 +54,178 @@
"echo-pref-email-frequency-weekly": "每周一次通知摘要",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "纯文本",
+ "echo-pref-cross-wiki-notifications": "显示来自其他wiki的通知",
+ "echo-pref-notifications-blacklist": "不显示来自这些用户的通知([[mw:Help:Notifications#mute|了解更多]])",
"echo-pref-new-message-indicator": "在我的工具栏中显示讨论页留言提示器",
+ "echo-pref-beta-feature-cross-wiki-message": "增强通知",
+ "echo-pref-beta-feature-cross-wiki-description": "使查看与组织通知更加容易。包括跨wiki通知,这将让您看到来自其他wiki的消息。(要接收在指定wiki上的跨wiki通知,您必须在那个wiki激活测试功能。)",
"echo-learn-more": "了解详情",
- "echo-new-messages": "您有新留言",
+ "echo-log": "公共日志",
+ "echo-new-messages": "您有新消息",
"echo-category-title-edit-user-talk": "讨论页{{PLURAL:$1|留言}}",
"echo-category-title-article-linked": "页面{{PLURAL:$1|链接}}",
"echo-category-title-reverted": "编辑{{PLURAL:$1|还原}}",
"echo-category-title-mention": "{{PLURAL:$1|提及}}",
+ "echo-category-title-mention-failure": "失败{{PLURAL:$1|提及}}",
+ "echo-category-title-mention-success": "成功{{PLURAL:$1|提及}}",
"echo-category-title-other": "{{PLURAL:$1|其他}}",
"echo-category-title-system": "{{PLURAL:$1|系统}}",
"echo-category-title-user-rights": "{{PLURAL:$1|用户权限更改}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|来自其他用户的电子邮件}}",
+ "echo-category-title-article-reminder": "页面{{PLURAL:$1|提示}}",
"echo-pref-tooltip-edit-user-talk": "当有人在我的讨论页上留言或回复时通知我。",
- "echo-pref-tooltip-article-linked": "当有人在条目中链接了我创建的页面时通知我。",
- "echo-pref-tooltip-reverted": "当有人用撤销或回退工具还原了我的编辑时通知我。",
+ "echo-pref-tooltip-article-linked": "当有人链接到我从另一页面创建的页面时通知我。",
+ "echo-pref-tooltip-reverted": "当有人用撤销或回退工具来还原我的编辑时通知我。",
"echo-pref-tooltip-mention": "当有人链接我的用户页时通知我。",
+ "echo-pref-tooltip-mention-failure": "当我不能向某人发送提及时通知我。",
+ "echo-pref-tooltip-mention-success": "当我向某人发送提及时通知我。",
"echo-pref-tooltip-user-rights": "当有人更新我的用户权限时通知我。",
- "echo-no-agent": "[匿名]",
- "echo-no-title": "[无页面]",
- "echo-error-no-formatter": "未指定通知格式",
+ "echo-pref-tooltip-emailuser": "当有人向我发送电子邮件时通知我。",
+ "echo-pref-tooltip-article-reminder": "当我请求时,通知我有关该页面的消息。",
+ "echo-error-no-formatter": "未指定通知格式。",
"notifications": "通知",
"tooltip-pt-notifications-alert": "{{GENDER:|您的}}提醒",
- "tooltip-pt-notifications-message": "{{GENDER:|您的}}留言消息",
+ "tooltip-pt-notifications-notice": "{{GENDER:|您的}}一般通知",
+ "echo-displaynotificationsconfiguration": "显示通知配置",
+ "echo-displaynotificationsconfiguration-summary": "这是此wiki上通知配置情况的概述。",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "按分类通知",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "排序类型",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "每种通知类型分为哪几部分",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "允许的通知方法",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "每种分类支持的通知方法",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "每种类型支持的通知方法;只应用于参数设置中隐藏的分类中的类型",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "默认启用",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "现有用户",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "新用户",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "需要通知方法",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "每个分类强制使用的通知方法",
"echo-specialpage": "通知",
+ "echo-specialpage-section-markread": "将组标记为已读",
+ "echo-specialpage-markasread": "通知:标记为已读",
+ "echo-specialpage-markasread-invalid-id": "无效的活动ID",
+ "echo-specialpage-pagination-numnotifications": "$1条{{PLURAL:$1|通知}}",
+ "echo-specialpage-pagefilters-title": "最近活动",
+ "echo-specialpage-pagefilters-subtitle": "有未读通知的页面",
+ "notificationsmarkread-legend": "标记通知为已读",
"echo-anon": "想要接收通知,请[$1 创建账户]或[$2 登录]。",
"echo-none": "您没有通知。",
"echo-more-info": "更多信息",
"echo-feedback": "反馈",
+ "echo-popup-footer-special-page-invitation": "<strong>尝试重新设计的通知页面。</strong>[$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "所有新外观和功能。",
"echo-quotation-marks": "“$1”",
- "echo-api-failure": "无法检索通知。请重试。(错误$1)",
+ "echo-api-failure": "检索通知失败。",
+ "echo-api-failure-cross-wiki": "对远程域名的访问已拒绝。",
"echo-notification-placeholder": "这里没有通知。",
- "notification-link-text-view-message": "查看留言",
+ "echo-notification-placeholder-filters": "没有通知匹配这些标准。",
+ "echo-notification-loginrequired": "您必须登录才能查看您的通知。",
+ "echo-notification-popup-loginrequired": "请登录来查看您的通知。",
+ "echo-notification-markasread": "标记为已读",
+ "echo-notification-markasunread": "标记为未读",
+ "echo-notification-markasread-tooltip": "标记为已读",
+ "echo-notification-more-options-tooltip": "更多选项",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|停止}}关注“$1”上的新活动",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|您}}已不再监视页面“$1”",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|您}}可以随时监视[$2 此页面]。",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|跟踪}}“$1”上的新活动",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|您}}现已监视页面“$1”",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|您}}可以随时停止监视[$2 此页面]。",
+ "notification-link-text-expand-all": "展开",
+ "notification-link-text-expand-alert-count": "查看{{PLURAL:$1|$1条提醒}}",
+ "notification-link-text-expand-notice-count": "查看{{PLURAL:$1|$1条一般通知}}",
+ "notification-link-text-expand-all-count": "查看{{PLURAL:$1|$1次通知}}",
+ "notification-link-text-collapse-all": "折叠",
+ "notification-link-text-view-message": "查看消息",
"notification-link-text-view-mention": "查看提及",
- "notification-link-text-view-changes": "查看更改",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|查看提及}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|查看}}更改",
"notification-link-text-view-page": "查看页面",
+ "notification-header-edit-user-talk": "$1在<strong>{{GENDER:$3|您}}的讨论页</strong>{{GENDER:$2|留言}}了。",
+ "notification-header-edit-user-talk-with-section": "$1在<strong>{{GENDER:$3|您}}的讨论页</strong>的“<strong>$4</strong>”段落{{GENDER:$2|留言}}了。",
+ "notification-header-page-linked": "有人在<strong>$4</strong>中加入了<strong>$3</strong>的链接。",
+ "notification-compact-header-page-linked": "链接自<strong>$1</strong>。",
+ "notification-bundle-header-page-linked": "有人在{{PLURAL:$5||$5个页面|100=超过99个页面}}中加入了指向<strong>$3</strong>的链接。",
+ "notification-header-article-reminder": "{{GENDER:$2|您}}请求提醒的页面位于<strong>$3</strong>",
+ "notification-link-text-what-links-here": "所有链入页面",
+ "notification-header-mention-other": "$1在<strong>$4</strong>中的“<strong>$5</strong>”{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-other-nosection": "$1在<strong>$4</strong>{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-user-talkpage-v2": "$1在<strong>$4{{GENDER:$5|的}}用户讨论页</strong>的“<strong>$6</strong>”中{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-user-talkpage-nosection": "$1在<strong>$4{{GENDER:$5|的}}用户讨论页</strong>{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-agent-talkpage": "$1在<strong>{{GENDER:$2|他|她|他}}的讨论页</strong>的“<strong>$4</strong>”里{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-agent-talkpage-nosection": "$1在<strong>{{GENDER:$2|他|她|他}}的讨论页</strong>{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-article-talkpage": "$1在<strong>$4</strong>的讨论页的“<strong>$5</strong>”段落{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-article-talkpage-nosection": "$1在<strong>$4</strong>的讨论页{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-failure-user-unknown": "{{GENDER:$2|您}}对<strong>$3</strong>的提及未被发送,因为找不到用户。",
+ "notification-header-mention-failure-user-anonymous": "{{GENDER:$2|您}}对<strong>$3</strong>的提及未被发送,因为用户为匿名用户。",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|您}}尝试提及了超过$3个{{PLURAL:$3|用户}}。上述所有超限的提及未发送。",
+ "notification-header-mention-failure-bundle": "{{GENDER:$2|您}}在<strong>$4</strong>讨论页做出的{{PLURAL:$3|$3次提及}}不能被发送。",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>用户名不存在:</strong>$1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP不能被提及:</strong>$1",
+ "notification-header-mention-success": "{{GENDER:$2|您}}对<strong>$3</strong>的提及被发送。",
+ "notification-header-mention-success-bundle": "{{GENDER:$2|您}}在<strong>$4</strong>讨论页做出的{{PLURAL:$3|$3次提及}}已发送。",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|您提及了}}:</strong>$3",
+ "notification-header-mention-status-bundle": "{{PLURAL:$3|$3条}}有关{{GENDER:$2|您}}在<strong>$4</strong>讨论页做出提及的通知:{{PLURAL:$5|$5条未发送}},{{PLURAL:$6|$6条已发送}}。",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|您}}的用户权限已{{GENDER:$1|更改}}。您已被添加至:$2。",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|您}}的用户权限已{{GENDER:$1|更改}}。您不再属于以下用户组的成员:$2。",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|您}}的用户权限已{{GENDER:$1|更改}}。您已被添加至:$2。您不再属于以下用户组的成员:$4。",
+ "notification-header-user-rights-expiry-change": "{{GENDER:$4|您}}的以下{{PLURAL:$3|用户组}}的成员逾期时间已被{{GENDER:$1|更改}}:$2。",
+ "notification-header-welcome": "{{GENDER:$2|欢迎}}来到{{SITENAME}},$1!我们很高兴{{GENDER:$2|您}}来到这里。",
+ "notification-welcome-linktext": "欢迎",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|您}}刚刚作出了{{GENDER:$2|您}}的第一次编辑;感谢{{GENDER:$2|您}},并欢迎您!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|您}}刚刚作出了{{GENDER:$2|您}}的第10次编辑;感谢{{GENDER:$2|您}},请继续保持!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|您}}刚刚作出了{{GENDER:$2|您}}的第100次编辑;非常感谢{{GENDER:$2|您}}!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|您}}刚刚作出了{{GENDER:$2|您}}的第1000次编辑;感谢{{GENDER:$2|您}}成为一个伟大的编辑者!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|您}}刚刚作出了{{GENDER:$2|您}}的第1万次编辑;非常非常感谢{{GENDER:$2|您}}!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|您}}刚刚作出了{{GENDER:$2|您}}的第10万次编辑;感谢{{GENDER:$2|您}}惊人的贡献!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|您}}刚刚作出了{{GENDER:$2|您}}的第100万次编辑;感谢{{GENDER:$2|您}}令人惊讶的贡献!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|您}}的编辑",
"notification-link-text-view-edit": "查看编辑",
- "notification-edit-talk-page2": "[[User:$1|$1]]在您的[[User talk:$2#$3|讨论页]]留言了。",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]]在您的讨论页的“[[User talk:$2#$3|$4]]”段落{{GENDER:$1|留言}}了。",
- "notification-edit-talk-page-flyout2": "$1在您的[[User talk:$2#$3|讨论页]]{{GENDER:$1|留言}}了。",
- "notification-edit-talk-page-flyout-with-section": "$1在您的讨论页的“[[User talk:$2#$3|$4]]”段落{{GENDER:$1|留言}}了。",
- "notification-page-linked": "[[:$3]]{{GENDER:$1|链接}}了[[:$2]]。[[Special:WhatLinksHere/$2|查看所有链至该页的页面]]。",
- "notification-page-linked-flyout": "[[:$2]]被[[:$3]]{{GENDER:$1|链接}}。",
- "notification-add-comment2": "[[User:$1|$1]]在“$4”的讨论页面的“[[$3|$2]]”段落{{GENDER:$1|发表意见}}。",
- "notification-add-talkpage-topic2": "[[User:$1|$1]]在[[$3]]上发起了新话题“$2”",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]]给您发来一则信息:“[[$3#$2|$2]]”。",
- "notification-add-comment-yours2": "[[User:$1|$1]]在您的讨论页的“[[$3#$2|$2]]”段落{{GENDER:$1|发表意见}}。",
- "notification-mention": "[[User:$1|$1]]在$5的讨论页的“[[:$3#$2|$4]]”段落{{GENDER:$1|提到}}了您。",
- "notification-mention-flyout": "$1在$5的讨论页的“[[:$3#$2|$4]]”段落{{GENDER:$1|提到}}了您。",
- "notification-mention-nosection": "[[User:$1|$1]]在[[:$3|$2的讨论页]]提到了您。",
- "notification-mention-nosection-flyout": "$1在[[:$3|$2的讨论页]]提到了您。",
- "notification-user-rights": "您的用户权限被[[User:$1|$1]][[Special:Log/rights/$1|更改了]]。$2。[[Special:ListGroupRights|了解更多]]",
- "notification-user-rights-flyout": "您的用户权限被$1{{GENDER:$1|更改了}}。$2。[[Special:ListGroupRights|了解更多]]",
- "notification-user-rights-add": "您被添加至该{{PLURAL:$2|用户组}}:$1",
- "notification-user-rights-remove": "您被从该{{PLURAL:$2|用户组}}中移除:$1",
- "notification-new-user": "欢迎来到{{SITENAME}},$1!",
- "notification-reverted2": "您对[[:$2]]的{{PLURAL:$4|编辑}}被[[User:$1|$1]]{{GENDER:$1|还原了}}。$3",
- "notification-reverted-flyout2": "您对$2的{{PLURAL:$4|编辑}}被$1{{GENDER:$1|还原了}}。$3",
+ "notification-link-article-reminder": "查看页面",
+ "notification-header-reverted": "有人{{GENDER:$2|回退}}了您{{PLURAL:$4|对<strong>$3</strong>所作出的编辑}}。",
+ "notification-header-emailuser": "$1向您{{GENDER:$2|发送}}了电子邮件。",
"notification-edit-talk-page-email-subject2": "$1在{{SITENAME}}给您{{GENDER:$1|留言}}了",
- "notification-edit-talk-page-email-batch-body2": "$1在您的讨论页{{GENDER:$1|留言}}了。",
"notification-edit-talk-page-email-batch-body-with-section": "$1在您的讨论页的“$2”段落{{GENDER:$1|留言}}了。",
"notification-page-linked-email-subject": "您创建的一个页面在{{SITENAME}}被链接",
- "notification-page-linked-email-batch-body": "$2被$3{{GENDER:$1|链接}}。",
- "notification-reverted-email-subject2": "你在{{SITENAME}}的{{PLURAL:$3|编辑}}被{{GENDER:$1|还原了}}",
- "notification-reverted-email-batch-body2": "你{{PLURAL:$3|对$2的编辑}}被$1{{GENDER:$1|还原了}}。",
- "notification-mention-email-subject": "$1在{{SITENAME}}{{GENDER:$1|提到}}了您",
- "notification-mention-email-batch-body": "$1在$4的讨论页的“$3”段落{{GENDER:$1|提到}}了您。",
- "notification-mention-nosection-email-batch-body": "$1在$2的讨论页提到了您。",
+ "notification-reverted-email-subject2": "有人{{GENDER:$1|还原了}}您在{{SITENAME}}上的{{PLURAL:$3|编辑}}",
+ "notification-mention-email-subject": "$1在{{SITENAME}}上{{GENDER:$1|提到了}}{{GENDER:$2|您}}",
"notification-user-rights-email-subject": "您在{{SITENAME}}的用户权限已被更改",
- "notification-user-rights-email-batch-body": "您的用户权限被$1{{GENDER:$1|更改}}。$2。",
- "echo-email-subject-default": "{{SITENAME}}的新通知",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1秒}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1分钟}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1小时}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1天}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1个月}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1年}}",
+ "notification-timestamp-today": "今天",
+ "notification-timestamp-yesterday": "昨天",
+ "notification-inbox-filter-read": "已读",
+ "notification-inbox-filter-unread": "未读",
+ "notification-inbox-filter-all": "全部",
"echo-email-body-default": "您在{{SITENAME}}有新通知:\n\n$1",
- "echo-email-batch-body-default": "您有新的通知。",
- "echo-email-footer-default": "$2\n\n要管理我们给您发送的电子邮件,请更改您的设置:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
- "echo-email-footer-default-html": "要管理我们给您发送的电子邮件,请<a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">更改您的设置</a>。<br />\n$1",
- "echo-notification-alert": "{{PLURAL:$1|提醒 ($1则)|100=提醒 (99+则)}}",
- "echo-notification-message": "{{PLURAL:$1|留言消息($1则)|100=留言消息(99+则)}}",
+ "echo-email-footer-default-html": "要管理我们给您发送的电子邮件,请<a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">更改您的设置</a>。<br />$1",
+ "echo-email-footer-default": "$2\n\n要管理我们给您发送的电子邮件,请更改您的设置:{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "要控制我们向{{GENDER:$1|您}}发送的电子邮件,请检查{{GENDER:$1|您}}的参数设置:",
+ "echo-email-html-footer-preference-link-text": "检查{{GENDER:$1|您}}的参数设置",
+ "echo-email-html-footer-with-link": "要控制我们给{{GENDER:$2|您}}发送的电子邮件,请$1。",
+ "echo-notification-alert": "{{PLURAL:$1|提醒 ($1条)|100=提醒 (99+条)}}",
+ "echo-notification-notice": "{{PLURAL:$1|一般通知 ($1条)|100=一般通知 (99+条)}}",
"echo-notification-alert-text-only": "提醒",
- "echo-notification-message-text-only": "消息",
+ "echo-notification-notice-text-only": "一般通知",
"echo-overlay-link": "所有通知",
"echo-overlay-title": "<b>通知</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|通知}}</b>(显示$2条未读通知中的$1条)",
"echo-mark-all-as-read": "标记所有为已读",
+ "echo-mark-all-as-read-confirmation": "已标记$1条{{PLURAL:$1|通知}}为已读",
+ "echo-mark-wiki-as-read": "在选定的wiki上标记所有为已读:$1",
"echo-date-today": "今天",
"echo-date-yesterday": "昨天",
"echo-load-more-error": "获取更多结果时出错。",
- "notification-edit-talk-page-bundle": "$1及{{PLURAL:$4|另外}}$3位用户在您的[[User talk:$2|讨论页]]{{GENDER:$1|留言}}了。",
- "notification-page-linked-bundle": "$2被$3和另外$4个{{PLURAL:$5|页面}}{{GENDER:$1|链接}}。[[Special:WhatLinksHere/$2|查看链至该页的所有页面]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1和{{PLURAL:$3|另外}}$2位用户在您的讨论页{{GENDER:$1|留言}}了。",
- "notification-page-linked-email-batch-bundle-body": "$2被$3和另外$4个{{PLURAL:$5|页面}}{{GENDER:$1|链接}}。",
+ "notification-bundle-header-edit-user-talk-v2": "<strong>{{GENDER:$3|您}}的讨论页</strong>上有{{PLURAL:$1|$1条|100=超过99条}}新消息。",
"echo-email-batch-subject-daily": "您在{{SITENAME}}有{{PLURAL:$2|新通知}}",
"echo-email-batch-subject-weekly": "您本周在{{SITENAME}}有{{PLURAL:$2|新通知}}",
- "echo-email-batch-body-intro-daily": "嗨,$1,\n这是今天您在{{SITENAME}}的通知摘要。",
- "echo-email-batch-body-intro-weekly": "$1,\n这是本周您在{{SITENAME}}的通知摘要。",
+ "echo-email-batch-body-intro-daily": "您好,$1\n这是今天您在{{SITENAME}}的通知摘要。",
+ "echo-email-batch-body-intro-weekly": "您好,$1\n这是本周您在{{SITENAME}}的通知摘要。",
"echo-email-batch-link-text-view-all-notifications": "查看所有通知",
- "echo-rev-deleted-text-view": "此页面版本已被隐藏。",
- "apihelp-echomarkread-description": "对当前用户标记通知为已读。",
- "apihelp-echomarkread-param-list": "要标记已读的通知ID列表。",
- "apihelp-echomarkread-param-all": "如果设置,标记一位用户的所有通知为已读。",
- "apihelp-echomarkread-param-sections": "要标记为已读的部分列表。",
- "apihelp-echomarkread-example-1": "标记通知8为已读",
- "apihelp-echomarkread-example-2": "标记所有通知为已读",
- "apihelp-echomarkseen-description": "对当前用户标记通知为已读。",
- "apihelp-echomarkseen-example-1": "标记所有类型的通知为已读",
- "apihelp-echomarkseen-param-type": "要标记为已读的通知类型:“alert”、“message”或“all”。",
- "apihelp-query+notifications-description": "获取当前用户等待的通知。",
- "apihelp-query+notifications-param-prop": "请求的细节。",
- "apihelp-query+notifications-param-sections": "要查询的通知部分(也就是说“alert”和“message”的一些结合)。",
- "apihelp-query+notifications-param-groupbysection": "是否按章节分组结果。如果设置,将分别获取每个章节。",
- "apihelp-query+notifications-param-format": "如果指定,通知将以此格式返回。",
- "apihelp-query+notifications-param-limit": "返回通知的最大数量。",
- "apihelp-query+notifications-param-index": "如果指定,将返回一个按顺序的通知ID列表。",
- "apihelp-query+notifications-param-alertcontinue": "当更多提醒结果可用时,使用这个继续。",
- "apihelp-query+notifications-param-alertunreadfirst": "是否首先显示未读的消息通知。",
- "apihelp-query+notifications-param-messagecontinue": "当更多消息结果可用时,使用这个继续。",
- "apihelp-query+notifications-param-messageunreadfirst": "是否首先显示未读的警告通知。",
- "apihelp-query+notifications-example-1": "通知列表",
- "apihelp-query+notifications-example-2": "列出通知,按节分组,带有数量"
+ "notification-header-foreign-alert": "来自{{PLURAL:$5|另一个wiki|另外$5个wiki}}上的更多提醒",
+ "notification-header-foreign-notice": "来自{{PLURAL:$5|另一个wiki|另外$5个wiki}}上的更多一般通知",
+ "notification-header-foreign-all": "来自{{PLURAL:$5|其他wiki|$5个其他wiki}}的更多通知"
}
diff --git a/Echo/i18n/zh-hant.json b/Echo/i18n/zh-hant.json
index 40e2a7ec..b49bad2a 100644
--- a/Echo/i18n/zh-hant.json
+++ b/Echo/i18n/zh-hant.json
@@ -16,7 +16,14 @@
"LNDDYL",
"Cwlin0416",
"EagerLin",
- "Shizhao"
+ "Shizhao",
+ "Bowleerin",
+ "Macofe",
+ "一個正常人",
+ "Winstonyin",
+ "逆襲的天邪鬼",
+ "Wehwei",
+ "A2093064"
]
},
"echo-desc": "用來通知使用者事件及訊息的系統",
@@ -24,129 +31,186 @@
"prefs-emailsettings": "電子郵件選項",
"prefs-displaynotifications": "顯示選項",
"prefs-echosubscriptions": "通知我這些事件",
+ "prefs-echocrosswiki": "跨 wiki 通知",
"prefs-newmessageindicator": "新訊息指示器",
+ "prefs-blocknotificationslist": "禁言用戶",
"echo-pref-send-me": "傳送給我:",
"echo-pref-send-to": "傳送至:",
"echo-pref-email-format": "電子郵件格式:",
"echo-pref-web": "網頁",
- "echo-pref-email": "Email",
+ "echo-pref-email": "電子郵件",
"echo-pref-email-frequency-never": "不要傳送任何信件通知",
"echo-pref-email-frequency-immediately": "個別通知發生事件時的訊息",
"echo-pref-email-frequency-daily": "每日通知摘要",
"echo-pref-email-frequency-weekly": "每週通知摘要",
"echo-pref-email-format-html": "HTML",
"echo-pref-email-format-plain-text": "純文字",
+ "echo-pref-cross-wiki-notifications": "顯示來自其他 wiki 的通知",
+ "echo-pref-notifications-blacklist": "不顯示來自這些用戶的通知([[mw:Help:Notifications#mute|了解更多]])",
"echo-pref-new-message-indicator": "在工具列中顯示對話頁面訊息提示工具",
+ "echo-pref-beta-feature-cross-wiki-message": "增強通知功能",
+ "echo-pref-beta-feature-cross-wiki-description": "更容易地檢視與組織通知。此功能包含跨維基通知功能,令使用者可以檢視來自其他維基的訊息。(要在某維基上接收跨維基通知,須在該維基上啟用測試功能。)",
"echo-learn-more": "瞭解更多",
+ "echo-log": "公共日誌",
"echo-new-messages": "您有新訊息",
"echo-category-title-edit-user-talk": "對話頁面{{PLURAL:$1|訊息}}",
"echo-category-title-article-linked": "頁面{{PLURAL:$1|連結}}",
"echo-category-title-reverted": "編輯{{PLURAL:$1|還原}}",
- "echo-category-title-mention": "{{PLURAL:$1|提到}}",
+ "echo-category-title-mention": "{{PLURAL:$1|提及}}",
+ "echo-category-title-mention-failure": "失敗{{PLURAL:$1|提及}}",
+ "echo-category-title-mention-success": "成功{{PLURAL:$1|提及}}",
"echo-category-title-other": "{{PLURAL:$1|其他}}",
"echo-category-title-system": "{{PLURAL:$1|系統}}",
- "echo-category-title-user-rights": "{{PLURAL:$1|使用者權限更改}}",
- "echo-pref-tooltip-edit-user-talk": "有人在我的對話頁面上留下訊息或是回覆留言時,請通知我。",
- "echo-pref-tooltip-article-linked": "有人從文章頁面連結到我建立的頁面時,請通知我。",
- "echo-pref-tooltip-reverted": "有人使用還原或取消功能來還原我的編輯時,請通知我。",
+ "echo-category-title-user-rights": "{{PLURAL:$1|使用者權限變更}}",
+ "echo-category-title-emailuser": "{{PLURAL:$1|來自其他使用者的郵件}}",
+ "echo-pref-tooltip-edit-user-talk": "當有人在我的對話頁面上留下訊息或是回覆留言時通知我。",
+ "echo-pref-tooltip-article-linked": "當有人從另一頁面連結到我建立的頁面時通知我。",
+ "echo-pref-tooltip-reverted": "當有人使用還原或取消功能來還原我的編輯時通知我。",
"echo-pref-tooltip-mention": "當有人連結我的使用者頁面時通知我。",
+ "echo-pref-tooltip-mention-failure": "當我提及用戶失敗時通知我。",
+ "echo-pref-tooltip-mention-success": "當我提及某用戶時通知我。",
"echo-pref-tooltip-user-rights": "當有人更改我的使用者權限時通知我。",
- "echo-no-agent": "[無使用者]",
- "echo-no-title": "[無頁面]",
- "echo-error-no-formatter": "沒有定義通知的格式。",
+ "echo-pref-tooltip-emailuser": "當有人向我傳送郵件時通知我。",
+ "echo-error-no-formatter": "尚未定義通知格式。",
"notifications": "通知",
"tooltip-pt-notifications-alert": "{{GENDER:|您的}}提醒",
- "tooltip-pt-notifications-message": "{{GENDER:|您的}}留言訊息",
+ "tooltip-pt-notifications-notice": "{{GENDER:|您的}}一般通知",
+ "echo-displaynotificationsconfiguration": "顯示通知設定",
+ "echo-displaynotificationsconfiguration-summary": "本頁概述此 wiki 上的通知設定。",
+ "echo-displaynotificationsconfiguration-notifications-by-category-header": "各類別的通知",
+ "echo-displaynotificationsconfiguration-sorting-by-section-header": "通知歸類",
+ "echo-displaynotificationsconfiguration-sorting-by-section-legend": "每種通知所歸入的類別",
+ "echo-displaynotificationsconfiguration-available-notification-methods-header": "允許的通知方式",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend": "每種通知可用的通知方式",
+ "echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend": "每種通知可用的通知方式;只適用於設定中隱藏的通知類別",
+ "echo-displaynotificationsconfiguration-enabled-default-header": "預設開啟",
+ "echo-displaynotificationsconfiguration-enabled-default-existing-users-legend": "現有使用者",
+ "echo-displaynotificationsconfiguration-enabled-default-new-users-legend": "新使用者",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-header": "必要的通知方式",
+ "echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend": "每種通知必須使用的通知方式",
"echo-specialpage": "通知",
- "echo-anon": "要接收通知,請先 [$1 註冊帳號] 或是 [$2 登入]。",
+ "echo-specialpage-section-markread": "將群組標記為已讀取",
+ "echo-specialpage-markasread": "通知:標記為已讀",
+ "echo-specialpage-markasread-invalid-id": "事件ID無效",
+ "echo-specialpage-pagination-numnotifications": "$1 則{{PLURAL:$1|通知}}",
+ "echo-specialpage-pagefilters-title": "最近活動",
+ "echo-specialpage-pagefilters-subtitle": "含未讀取通知的頁面",
+ "notificationsmarkread-legend": "將通知標記為已讀",
+ "echo-anon": "要接收通知,請先[$1 註冊帳號]或[$2 登入]。",
"echo-none": "您沒有任何通知。",
"echo-more-info": "更多資訊",
"echo-feedback": "意見回饋",
- "echo-notification-placeholder": "無通知。",
+ "echo-popup-footer-special-page-invitation": "<strong>試試新設計的通知頁面。</strong> [$2 $1]",
+ "echo-popup-footer-special-page-invitation-link": "全新的外觀及功能。",
+ "echo-api-failure": "擷取通知失敗。",
+ "echo-api-failure-cross-wiki": "對遠端網域的存取被拒絕。",
+ "echo-notification-placeholder": "無任何通知。",
+ "echo-notification-placeholder-filters": "沒有任何符合這些條件的通知。",
+ "echo-notification-loginrequired": "您必須登入方可查閱通知。",
+ "echo-notification-popup-loginrequired": "請登入以檢視您的通知。",
+ "echo-notification-markasread": "標記為已讀取",
+ "echo-notification-markasunread": "標記為未讀取",
+ "echo-notification-markasread-tooltip": "標記為已讀取",
+ "echo-notification-more-options-tooltip": "更多選項",
+ "notification-dynamic-actions-unwatch": "{{GENDER:$3|停止}}監視「$1」上的新動態",
+ "notification-dynamic-actions-unwatch-confirmation": "{{GENDER:$3|您}}已不再監視「$1」",
+ "notification-dynamic-actions-unwatch-confirmation-description": "{{GENDER:$3|您}}可以隨時監視[$2 此頁]。",
+ "notification-dynamic-actions-watch": "{{GENDER:$3|追蹤}}「$1」上的新動態",
+ "notification-dynamic-actions-watch-confirmation": "{{GENDER:$3|您}}現已監視頁面「$1」",
+ "notification-dynamic-actions-watch-confirmation-description": "{{GENDER:$3|您}}可以隨時停止監視[$2 此頁]。",
+ "notification-link-text-expand-all": "展開",
+ "notification-link-text-expand-alert-count": "檢視 {{PLURAL:$1|$1 則提醒}}",
+ "notification-link-text-expand-notice-count": "檢視 {{PLURAL:$1|$1 則通知}}",
+ "notification-link-text-expand-all-count": "檢視 {{PLURAL:$1|$1 則通知}}",
+ "notification-link-text-collapse-all": "摺疊",
"notification-link-text-view-message": "檢視訊息",
- "notification-link-text-view-mention": "檢視提到",
- "notification-link-text-view-changes": "檢視變更",
+ "notification-link-text-view-mention": "檢視提及",
+ "notification-link-text-view-mention-failure": "{{PLURAL:$1|查看提及}}",
+ "notification-link-text-view-changes": "{{GENDER:$1|檢視}}變更",
"notification-link-text-view-page": "檢視頁面",
+ "notification-header-edit-user-talk": "$1 在<strong>{{GENDER:$3|您}}的使用者對話頁面</strong>{{GENDER:$2|留下了}}一則訊息。",
+ "notification-header-edit-user-talk-with-section": "$1 在<strong>{{GENDER:$3|您}}的使用者對話頁面</strong>中的「<strong>$4</strong>」{{GENDER:$2|留下了}}一則訊息。",
+ "notification-header-page-linked": "有人在「<strong>$4</strong>」中加入了「<strong>$3</strong>」的連結。",
+ "notification-compact-header-page-linked": "<strong>$1</strong>連結至本頁。",
+ "notification-bundle-header-page-linked": "有人在 {{PLURAL:$5||$5 個頁面|100=99+ 個頁面}}中加入了指向「<strong>$3</strong>」的連結。",
+ "notification-link-text-what-links-here": "連結至本頁的所有頁面",
+ "notification-header-mention-other": "$1在「<strong>$4</strong>」中的「<strong>$5</strong>」{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-other-nosection": "$1在「<strong>$4</strong>」中{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-user-talkpage-v2": "$1在<strong>$4{{GENDER:$5|的}}使用者對話頁</strong>上的「<strong>$6</strong>」{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-user-talkpage-nosection": "$1在<strong>$4{{GENDER:$5|的}}使用者對話頁</strong>上{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-agent-talkpage": "$1在<strong>{{GENDER:$2|他|她|他}}對話頁</strong>上的「<strong>$4</strong>」{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-agent-talkpage-nosection": "$1在<strong>{{GENDER:$2|他|她|他}}的對話頁</strong>上{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-article-talkpage": "$1在<strong>$4</strong>討論頁上的「<strong>$5</strong>」{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-article-talkpage-nosection": "$1在<strong>$4</strong>的討論頁上{{GENDER:$2|提到}}了{{GENDER:$3|您}}。",
+ "notification-header-mention-failure-user-unknown": "無法發送{{GENDER:$2|您}}對<strong>$3</strong>的提及,因為找不到該使用者。",
+ "notification-header-mention-failure-user-anonymous": "無法發送{{GENDER:$2|您}}對<strong>$3</strong>的提及,因為該使用者為匿名使用者。",
+ "notification-header-mention-failure-too-many": "{{GENDER:$2|您}}試著提及超過 $3 位的{{PLURAL:$3|用戶}},但所有超過上限的提及,都不會發送。",
+ "notification-header-mention-failure-bundle": "{{PLURAL:$3|無法}}發送{{GENDER:$2|您}}在<strong>$4</strong>討論頁上的{{PLURAL:$3|提及|$3個提及}}。",
+ "notification-compact-header-mention-failure-user-unknown": "<strong>使用者名稱不存在:</strong>$1",
+ "notification-compact-header-mention-failure-user-anonymous": "<strong>IP是不能被提及的:</strong>$1",
+ "notification-header-mention-success": "已發出{{GENDER:$2|您}}對<strong>$3</strong>的提及。",
+ "notification-header-mention-success-bundle": "{{PLURAL:$3|已發出}}{{GENDER:$2|您}}在<strong>$4</strong>討論頁上的{{PLURAL:$3|提及|$3個提及}}。",
+ "notification-compact-header-mention-success": "<strong>{{GENDER:$2|您提及了}}:</strong>$3",
+ "notification-header-mention-status-bundle": "有{{PLURAL:$3|$3條}}有關{{GENDER:$2|您}}在<strong>$4</strong>討論頁上所作提及的通知:{{PLURAL:$5|$5條未發送}},{{PLURAL:$6|$6條已發送}}。",
+ "notification-header-user-rights-add-only": "{{GENDER:$4|您的}}使用者權限已被{{GENDER:$1|更改}}。您已被添加至:$2。",
+ "notification-header-user-rights-remove-only": "{{GENDER:$4|您的}}使用者權限已被{{GENDER:$1|更改}}。您已不再是$2的成員。",
+ "notification-header-user-rights-add-and-remove": "{{GENDER:$6|您的}}使用者權限已被{{GENDER:$1|更改}}。您已被添加至:$2。您已不再是$4的成員。",
+ "notification-header-welcome": "$1,{{GENDER:$2|歡迎}}來到{{SITENAME}}!很高興在這裡見到{{GENDER:$2|您}}。",
+ "notification-welcome-linktext": "歡迎",
+ "notification-header-thank-you-1-edit": "{{GENDER:$2|您}}剛剛作出了{{GENDER:$2|您的}}第一次編輯。謝謝您,歡迎{{GENDER:$2|您}}!",
+ "notification-header-thank-you-10-edit": "{{GENDER:$2|您}}剛剛作出了{{GENDER:$2|您的}}第十次編輯。謝謝您,請繼續努力!",
+ "notification-header-thank-you-100-edit": "{{GENDER:$2|您}}剛剛作出了{{GENDER:$2|您的}}第一百次編輯。謝謝{{GENDER:$2|您}}!",
+ "notification-header-thank-you-1000-edit": "{{GENDER:$2|您}}剛剛作出了{{GENDER:$2|您的}}第一千次編輯。很感謝{{GENDER:$2|您}}的貢獻!",
+ "notification-header-thank-you-10000-edit": "{{GENDER:$2|您}}剛剛作出了{{GENDER:$2|您的}}第一萬次編輯。謝謝{{GENDER:$2|您}}!",
+ "notification-header-thank-you-100000-edit": "{{GENDER:$2|您}}剛剛作出了{{GENDER:$2|您的}}第十萬次編輯。很感謝{{GENDER:$2|您}}了不起的貢獻!",
+ "notification-header-thank-you-1000000-edit": "{{GENDER:$2|您}}剛剛作出了{{GENDER:$2|您的}}第一百萬次編輯。很感謝{{GENDER:$2|您}}驚人的貢獻!",
+ "notification-link-thank-you-edit": "{{GENDER:$1|您的}}編輯",
"notification-link-text-view-edit": "檢視編輯",
- "notification-edit-talk-page2": "[[User:$1|$1]] 在您的[[User talk:$2#$3|對話頁面]]中{{GENDER:$1|留下了}}一則訊息。",
- "notification-edit-talk-page-with-section": "[[User:$1|$1]] 在您的對話頁面段落 \"[[User talk:$2#$3|$4]]\" 中{{GENDER:$1|留下了}}一則訊息。",
- "notification-edit-talk-page-flyout2": "$1 在您的[[User talk:$2#$3|對話頁面]]中{{GENDER:$1|留下了}}一則訊息。",
- "notification-edit-talk-page-flyout-with-section": "$1 在您的對話頁面段落 \"[[User talk:$2#$3|$4]]\" 中{{GENDER:$1|留下了}}一則訊息。",
- "notification-page-linked": "[[:$2]] 已從 [[:$3]] 頁面{{GENDER:$1|連入了}}。詳情請見[[Special:WhatLinksHere/$2|此頁面的所有連結]]。",
- "notification-page-linked-flyout": "[[:$2]] 已從 [[:$3]] 頁面{{GENDER:$1|連入了}}。",
- "notification-add-comment2": "[[User:$1|$1]] 在 \"$4\" 對話頁面段落 \"[[$3|$2]]\" 中{{GENDER:$1|發表了意見}}。",
- "notification-add-talkpage-topic2": "[[User:$1|$1]] 在 [[$3]] 的頁面中{{GENDER:$1|張貼了}}新主題 \"$2\"。",
- "notification-add-talkpage-topic-yours2": "[[User:$1|$1]] 傳送了一則訊息給您:\"[[$3#$2|$2]]\"。",
- "notification-add-comment-yours2": "[[User:$1|$1]] 在您的對話頁面段落 \"[[$3#$2|$2]]\" 中{{GENDER:$1|發表了意見}}。",
- "notification-mention": "[[User:$1|$1]] 在 $5 的對話頁面段落 \"[[:$3#$2|$4]]\" 中{{GENDER:$1|提到了}}您。",
- "notification-mention-flyout": "$1 在 $5 對話頁面段落 \"[[:$3#$2|$4]]\" 中{{GENDER:$1|提到了}}您。",
- "notification-mention-nosection": "[[User:$1|$1]] 於 [[:$3|$2 對話頁面]] 中提到了您。",
- "notification-mention-nosection-flyout": "$1 於 [[:$3|$2 對話頁面]] 中提到了您。",
- "notification-user-rights": "您的使用者權限已由 [[User:$1|$1]] [[Special:Log/rights/$1|變更]],$2。[[Special:ListGroupRights|瞭解更多]]",
- "notification-user-rights-flyout": "您的使用者權限已由 $1 {{GENDER:$1|變更}},$2。[[Special:ListGroupRights|瞭解更多]]",
- "notification-user-rights-add": "您現在已成為{{PLURAL:$2|這個群組|這些群組}}的成員:$1",
- "notification-user-rights-remove": "你不再是{{PLURAL:$2|這個群組|這些群組}}的成員:$1",
- "notification-new-user": "歡迎來到 {{SITENAME}},$1! 我們很歡迎您的蒞臨。",
- "notification-reverted2": "您{{PLURAL:$4|在 [[:$2]] 頁面的編輯}}已由 [[User:$1|$1]] {{GENDER:$1|還原了}}。$3",
- "notification-reverted-flyout2": "您{{PLURAL:$4|在 $2 頁面的編輯}}已由 $1 給還原了。 $3",
+ "notification-header-reverted": "有人{{GENDER:$2|還原}}了您{{PLURAL:$4|對<strong>$3</strong>所作出的編輯}}。",
+ "notification-header-emailuser": "$1 向您{{GENDER:$2|傳送了}}一封郵件。",
"notification-edit-talk-page-email-subject2": "$1 在 {{SITENAME}} {{GENDER:$1|留下了}}一則訊息給您。",
- "notification-edit-talk-page-email-batch-body2": "$1 在您的對話頁面中{{GENDER:$1|留下了}}一則訊息。",
- "notification-edit-talk-page-email-batch-body-with-section": "$1 在您的對話頁面 \"$2\" 中{{GENDER:$1|留下了}}一則訊息。",
+ "notification-edit-talk-page-email-batch-body-with-section": "$1 在您對話頁面上的「$2」中{{GENDER:$1|留下了}}一則訊息。",
"notification-page-linked-email-subject": "您在 {{SITENAME}} 建立的頁面已被連結",
- "notification-page-linked-email-batch-body": "$2 頁面已被 $3 頁面{{GENDER:$1|連結}}。",
- "notification-reverted-email-subject2": "您在 {{SITENAME}} 的{{PLURAL:$3|編輯}}已{{GENDER:$1|還原了}}",
- "notification-reverted-email-batch-body2": "您在 {{PLURAL:$3|$2 頁面的編輯}}已由 $1 {{GENDER:$1|還原了}}。",
- "notification-mention-email-subject": "$1 在 {{SITENAME}} {{GENDER:$1|提到了}}您",
- "notification-mention-email-batch-body": "$1 在 $4 的對話頁面段落 \"$3\" 中{{GENDER:$1|提到了}}您。",
- "notification-mention-nosection-email-batch-body": "$1 於 $2 對話頁面提到了您。",
+ "notification-reverted-email-subject2": "有人{{GENDER:$1|還原了}}您在{{SITENAME}}上的{{PLURAL:$3|編輯}}",
+ "notification-mention-email-subject": "$1在{{SITENAME}}上{{GENDER:$1|提到了}}{{GENDER:$2|您}}",
"notification-user-rights-email-subject": "您在 {{SITENAME}} 的使用者權限已變更",
- "notification-user-rights-email-batch-body": "$1 已修改你的使用者權限。$2",
- "echo-email-subject-default": "{{SITENAME}} 的新通知",
+ "notification-timestamp-ago-seconds": "{{PLURAL:$1|$1秒}}",
+ "notification-timestamp-ago-minutes": "{{PLURAL:$1|$1分鐘}}",
+ "notification-timestamp-ago-hours": "{{PLURAL:$1|$1小時}}",
+ "notification-timestamp-ago-days": "{{PLURAL:$1|$1天}}",
+ "notification-timestamp-ago-months": "{{PLURAL:$1|$1個月}}",
+ "notification-timestamp-ago-years": "{{PLURAL:$1|$1年}}",
+ "notification-timestamp-today": "今日",
+ "notification-timestamp-yesterday": "昨日",
+ "notification-inbox-filter-read": "已讀取",
+ "notification-inbox-filter-unread": "未讀取",
+ "notification-inbox-filter-all": "所有",
"echo-email-body-default": "你在 {{SITENAME}} 有一則新訊息:\n\n\n$1",
- "echo-email-batch-body-default": "你有一則新通知訊息。",
- "echo-email-footer-default": "$2\n\n如要調整我們寄給您的電子郵件,請檢查您的偏好設定:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
"echo-email-footer-default-html": "如要調整我們寄給您的電子郵件,<a href=\"$2\" style=\"text-decoration:none; color: #3868B0;\">請檢查您的偏好設定</a>。<br />\n$1",
+ "echo-email-footer-default": "$2\n\n如要調整我們寄給您的電子郵件,請檢查您的偏好設定:\n{{canonicalurl:{{#special:Preferences}}#mw-prefsection-echo}}\n\n$1",
+ "echo-email-plain-footer": "如要調整我們寄給您的電子郵件,請檢查{{GENDER:$1|您}}的偏好設定:",
+ "echo-email-html-footer-preference-link-text": "檢查{{GENDER:$1|您}}的偏好設定",
+ "echo-email-html-footer-with-link": "如要調整我們寄給{{GENDER:$2|您}}的電子郵件,$1:",
"echo-notification-alert": "{{PLURAL:$1|提醒 ($1則)|100=提醒 (99+則)}}",
- "echo-notification-message": "{{PLURAL:$1|留言訊息($1則)|100=留言訊息(99+則)}}",
+ "echo-notification-notice": "{{PLURAL:$1|一般通知 ($1)|一般通知 ($1)|100=一般通知 (99+)}}",
"echo-notification-alert-text-only": "提醒",
- "echo-notification-message-text-only": "訊息",
+ "echo-notification-notice-text-only": "一般通知",
"echo-overlay-link": "所有通知",
"echo-overlay-title": "<b>通知</b>",
"echo-overlay-title-overflow": "<b>{{PLURAL:$1|通知}}</b> (顯示 $2 則未讀訊息中的 $1 則)",
"echo-mark-all-as-read": "標記所有為已讀",
+ "echo-mark-all-as-read-confirmation": "已標記$1則{{PLURAL:$1|通知}}為已讀",
+ "echo-mark-wiki-as-read": "在選定的wiki上標記所有為已讀:$1",
"echo-date-today": "今日",
"echo-date-yesterday": "昨日",
"echo-load-more-error": "擷取更多結果的時候發生錯誤。",
- "notification-edit-talk-page-bundle": "$1 與{{PLURAL:$4|另外}} $3 位使用者在您的[[User talk:$2|對話頁面]]裡面{{GENDER:$1|留下了}}一則訊息。",
- "notification-page-linked-bundle": "$2 已由 $3 及另外 $4 個{{PLURAL:$5|頁面}}{{GENDER:$1|連入}}了。詳情請見[[Special:WhatLinksHere/$2|所有的連入頁面]]",
- "notification-edit-user-talk-email-batch-bundle-body": "$1 與{{PLURAL:$3|另外}} $2 位使用者在您的對話頁面裡面{{GENDER:$1|留下了}}訊息。",
- "notification-page-linked-email-batch-bundle-body": "$2 已由 $3 頁面及另外 $4 個{{PLURAL:$5|頁面}}{{GENDER:$1|連入了}}。",
+ "notification-bundle-header-edit-user-talk-v2": "<strong>{{GENDER:$3|您}}的對話頁面</strong>裡有 {{PLURAL:$1|1 則|$1 則|100=99 則以上}}新訊息。",
"echo-email-batch-subject-daily": "您在 {{SITENAME}} 有{{PLURAL:$2|一則新通知}}",
"echo-email-batch-subject-weekly": "本週您在 {{SITENAME}} 有{{PLURAL:$2|一則新通知}}",
"echo-email-batch-body-intro-daily": "$1 您好,\n這是您在 {{SITENAME}} 的今日活動記錄摘要。",
"echo-email-batch-body-intro-weekly": "$1 您好,\n這是您在 {{SITENAME}} 的本週活動記錄摘要。",
"echo-email-batch-link-text-view-all-notifications": "檢視所有通知",
- "echo-rev-deleted-text-view": "該頁面修訂已禁止使用。",
- "apihelp-echomarkread-description": "標記目前使用者的通知為已讀。",
- "apihelp-echomarkread-param-list": "要標記為已讀的通知 ID 清單。",
- "apihelp-echomarkread-param-all": "若設定,標記所有某個使用者的通知為已讀。",
- "apihelp-echomarkread-param-sections": "要標記為已讀的章節清單。",
- "apihelp-echomarkread-example-1": "標記通知 8 為已讀",
- "apihelp-echomarkread-example-2": "標記所有通知為已讀",
- "apihelp-echomarkseen-description": "標記目前使用者的通知為已讀",
- "apihelp-echomarkseen-example-1": "標記所有類型的通知為已讀",
- "apihelp-echomarkseen-param-type": "標記為已讀的通知類型:'alert'、'message' 或 'all'。",
- "apihelp-query+notifications-description": "取得目前使用者等待的通知。",
- "apihelp-query+notifications-param-prop": "請求的詳細資料。",
- "apihelp-query+notifications-param-sections": "要查詢的通知章節 (例如部份 'alert' 與 'message' 的組合)。",
- "apihelp-query+notifications-param-groupbysection": "是否要依據章節來分類查詢結果。 若開啟此功能會各別取得每個章節。",
- "apihelp-query+notifications-param-format": "若有指定,通知將會以此指定的格式回傳結果。",
- "apihelp-query+notifications-param-limit": "要回傳的通知數量上限。",
- "apihelp-query+notifications-param-index": "若有指定,將會回傳有排序的通知 ID 清單。",
- "apihelp-query+notifications-param-alertcontinue": "當有多個警告的結果時,使用此參數來繼續。",
- "apihelp-query+notifications-param-alertunreadfirst": "是否要先顯示未讀的訊息通知。",
- "apihelp-query+notifications-param-messagecontinue": "當有更多訊息結果時,使用此參數來繼續。",
- "apihelp-query+notifications-param-messageunreadfirst": "是否先顯示未讀的警告通知。",
- "apihelp-query+notifications-example-1": "通知清單",
- "apihelp-query+notifications-example-2": "依章節分類通知清單並顯示總數"
+ "notification-header-foreign-alert": "來自{{PLURAL:$5|另一個 wiki|其他 $5 個 wiki}} 的更多通知",
+ "notification-header-foreign-notice": "來自{{PLURAL:$5|另一個 wiki|其他 $5 個 wiki}} 的更多一般通知",
+ "notification-header-foreign-all": "來自 {{PLURAL:$5|其他 wiki| $5 個其他 wiki}} 的更多通知"
}
diff --git a/Echo/images/betafeatures-icon-notifications-ltr.svg b/Echo/images/betafeatures-icon-notifications-ltr.svg
new file mode 100644
index 00000000..2a55cd92
--- /dev/null
+++ b/Echo/images/betafeatures-icon-notifications-ltr.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="264" height="162" viewBox="0 0 264 162" id="svg2">
+ <defs id="defs78">
+ <clipPath id="jagged-edge">
+ <path id="path5121" d="M0 0v152l12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10V0z"/>
+ </clipPath>
+ </defs>
+ <g id="screenshot" clip-path="url(#jagged-edge)">
+ <path fill="#fff" d="M263.5 162.25l-263-.5V.5h263z" id="background"/>
+ <path fill="#e5e5e5" d="M252 162.496V29H48v133.496z" id="article"/>
+ <path fill="#e5e5e5" d="M11 22c0-7.732 6.268-14 14-14s14 6.268 14 14-6.268 14-14 14-14-6.268-14-14z" id="logo"/>
+ <path fill="#e5e5e5" d="M38 163.807V58H13v105.807h25z" id="sidebar"/>
+ <g fill="#e5e5e5" id="personal-tools">
+ <path id="path5129" d="M233 5h26v6h-26V5zm-24 0h22v6h-22zm-24 0h22v6h-22zm-23 0h13v6h-13zm15 0h6v6h-6zm-23 0h6v6h-6z"/>
+ </g>
+ <g fill="#e5e5e5" id="search">
+ <path d="M258 16v4h-92v-4h92m1-1h-94v6h94v-6z" id="path5717"/>
+ <path d="M168 17h2v2h-2z" id="icon"/>
+ </g>
+ <path fill="#e5e5e5" d="M38 45v-5H13v5h25z" id="sitename"/>
+ <path fill="#e5e5e5" id="border" d="M0 0v162h264V0zm1 1h262v150.533l-11 9.166-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-11-9.168z"/>
+ <path id="path14" d="M177.02 5h6v6h-6z" fill="#36c"/>
+ <rect id="rect16" y="18.566" x="140.812" ry=".099" rx=".106" height="93.208" width="78.835" fill="#36c"/>
+ <path id="path18" d="M175.692 19l4.537-6 4.536 6" fill="#36c"/>
+ <path id="path20" d="M180.23 44.254c-7.437 0-12.783 4.648-12.783 11.62v11.62c0 4.648 0 6.972-4.648 6.972v2.324h34.86v-2.324c-4.65 0-4.65-2.324-4.65-6.972v-11.62c0-6.972-5.344-11.62-12.78-11.62zm-6.973 37.184c0 2.324 3.72 4.648 6.972 4.648 3.253 0 6.97-2.324 6.97-4.648h-13.943z" fill="#fff"/>
+ </g>
+</svg>
diff --git a/Echo/images/betafeatures-icon-notifications-rtl.svg b/Echo/images/betafeatures-icon-notifications-rtl.svg
new file mode 100644
index 00000000..e6d2be7a
--- /dev/null
+++ b/Echo/images/betafeatures-icon-notifications-rtl.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="264" height="162" viewBox="0 0 264 162" id="svg2">
+ <defs id="defs78">
+ <clipPath id="jagged-edge">
+ <path id="path5121" d="M0 0v152l12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10V0z"/>
+ </clipPath>
+ </defs>
+ <g transform="matrix(-1 0 0 1 264 0)" id="screenshot" clip-path="url(#jagged-edge)">
+ <path d="M263.5 162.25l-263-.5V.5h263z" id="background" fill="#fff"/>
+ <path d="M252 162.496V29H48v133.496z" id="article" fill="#e5e5e5"/>
+ <path d="M11 22c0-7.732 6.268-14 14-14s14 6.268 14 14-6.268 14-14 14-14-6.268-14-14z" id="logo" fill="#e5e5e5"/>
+ <path d="M38 163.807V58H13v105.807h25z" id="sidebar" fill="#e5e5e5"/>
+ <g id="personal-tools" fill="#e5e5e5">
+ <path id="path5129" d="M233 5h26v6h-26V5zm-24 0h22v6h-22zm-24 0h22v6h-22zm-23 0h13v6h-13zm15 0h6v6h-6zm-23 0h6v6h-6z"/>
+ </g>
+ <g id="search" fill="#e5e5e5">
+ <path d="M258 16v4h-92v-4h92m1-1h-94v6h94v-6z" id="path5717"/>
+ <path d="M168 17h2v2h-2z" id="icon"/>
+ </g>
+ <path d="M38 45v-5H13v5h25z" id="sitename" fill="#e5e5e5"/>
+ <path id="border" d="M0 0v162h264V0zm1 1h262v150.533l-11 9.166-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-11-9.168z" fill="#e5e5e5"/>
+ <path id="path14" d="M177.02 5h6v6h-6z" fill="#36c"/>
+ <rect id="rect16" y="18.566" x="140.812" ry=".099" rx=".106" height="93.208" width="78.835" fill="#36c"/>
+ <path id="path18" d="M175.692 19l4.537-6 4.536 6" fill="#36c"/>
+ <path id="path20" d="M180.23 44.254c-7.437 0-12.783 4.648-12.783 11.62v11.62c0 4.648 0 6.972-4.648 6.972v2.324h34.86v-2.324c-4.65 0-4.65-2.324-4.65-6.972v-11.62c0-6.972-5.344-11.62-12.78-11.62zm-6.973 37.184c0 2.324 3.72 4.648 6.972 4.648 3.253 0 6.97-2.324 6.97-4.648h-13.943z" fill="#fff"/>
+ </g>
+</svg>
diff --git a/Echo/images/pending.gif b/Echo/images/pending.gif
new file mode 100644
index 00000000..1194eed2
--- /dev/null
+++ b/Echo/images/pending.gif
Binary files differ
diff --git a/Echo/includes/AttributeManager.php b/Echo/includes/AttributeManager.php
index 312e0d62..d918f196 100644
--- a/Echo/includes/AttributeManager.php
+++ b/Echo/includes/AttributeManager.php
@@ -17,20 +17,48 @@ class EchoAttributeManager {
protected $categories;
/**
+ * @var array
+ */
+ protected $defaultNotifyTypeAvailability;
+
+ /**
+ * @var array
+ */
+ protected $notifyTypeAvailabilityByCategory;
+
+ /**
+ * @var array
+ */
+ protected $dismissabilityByCategory;
+
+ /**
+ * @var array
+ */
+ protected $notifiers;
+
+ /**
* Notification section constant
*/
const ALERT = 'alert';
const MESSAGE = 'message';
const ALL = 'all';
+ protected static $DEFAULT_SECTION = self::ALERT;
+
/**
* Notifications are broken down to two sections, default is alert
* @var array
*/
- public static $sections = array (
+ public static $sections = [
self::ALERT,
self::MESSAGE
- );
+ ];
+
+ /**
+ * Names for keys in $wgEchoNotifications notification config
+ */
+ const ATTR_LOCATORS = 'user-locators';
+ const ATTR_FILTERS = 'user-filters';
/**
* An EchoAttributeManager instance created from global variables
@@ -39,13 +67,27 @@ class EchoAttributeManager {
protected static $globalVarInstance = null;
/**
- * @param array $notifications notification attributes
- * @param array $categories notification categories
+ * @param array $notifications Notification attributes
+ * @param array $categories Notification categories
+ * @param array $defaultNotifyTypeAvailability Associative array with output
+ * formats as keys and whether they are available as boolean values.
+ * @param array $notifyTypeAvailabilityByCategory Associative array with
+ * categories as keys and value an associative array as with
+ * $defaultNotifyTypeAvailability.
+ * @param array $notifiers Associative array mapping notify types to notifier
+ * that handles them
*/
- public function __construct( array $notifications, array $categories ) {
+ public function __construct( array $notifications, array $categories, array $defaultNotifyTypeAvailability, array $notifyTypeAvailabilityByCategory, array $notifiers ) {
// Extensions can define their own notifications and categories
$this->notifications = $notifications;
$this->categories = $categories;
+
+ $this->defaultNotifyTypeAvailability = $defaultNotifyTypeAvailability;
+ $this->notifyTypeAvailabilityByCategory = $notifyTypeAvailabilityByCategory;
+
+ $this->dismissabilityByCategory = null;
+
+ $this->notifiers = $notifiers;
}
/**
@@ -53,52 +95,57 @@ class EchoAttributeManager {
* @return EchoAttributeManager
*/
public static function newFromGlobalVars() {
- global $wgEchoNotifications, $wgEchoNotificationCategories;
+ global $wgEchoNotifications, $wgEchoNotificationCategories, $wgDefaultNotifyTypeAvailability, $wgNotifyTypeAvailabilityByCategory, $wgEchoNotifiers;
// Unit test may alter the global data for test purpose
- if ( defined( 'MW_PHPUNIT_TEST' ) && MW_PHPUNIT_TEST ) {
- return new self( $wgEchoNotifications, $wgEchoNotificationCategories );
+ if ( defined( 'MW_PHPUNIT_TEST' ) ) {
+ return new self( $wgEchoNotifications, $wgEchoNotificationCategories, $wgDefaultNotifyTypeAvailability, $wgNotifyTypeAvailabilityByCategory, $wgEchoNotifiers );
}
if ( self::$globalVarInstance === null ) {
self::$globalVarInstance = new self(
$wgEchoNotifications,
- $wgEchoNotificationCategories
+ $wgEchoNotificationCategories,
+ $wgDefaultNotifyTypeAvailability,
+ $wgNotifyTypeAvailabilityByCategory,
+ $wgEchoNotifiers
);
}
+
return self::$globalVarInstance;
}
/**
- * Get the user-locators related to the provided event type
+ * Get the user-locators|user-filters related to the provided event type
*
* @param string $type
+ * @param string $locator Either self::ATTR_LOCATORS or self::ATTR_FILTERS
* @return array
*/
- public function getUserLocators( $type ) {
- if ( isset( $this->notifications[$type]['user-locators'] ) ) {
- return (array)$this->notifications[$type]['user-locators'];
+ public function getUserCallable( $type, $locator = self::ATTR_LOCATORS ) {
+ if ( isset( $this->notifications[$type][$locator] ) ) {
+ return (array)$this->notifications[$type][$locator];
} else {
- return array();
+ return [];
}
}
/**
* Get the enabled events for a user, which excludes user-dismissed events
* from the general enabled events
- * @param User
- * @param string web/email
+ * @param User $user
+ * @param string $notifyType Either "web" or "email".
* @return string[]
*/
- public function getUserEnabledEvents( User $user, $outputFormat ) {
+ public function getUserEnabledEvents( User $user, $notifyType ) {
$eventTypesToLoad = $this->notifications;
foreach ( $eventTypesToLoad as $eventType => $eventData ) {
$category = $this->getNotificationCategory( $eventType );
- // Make sure the user is eligible to recieve this type of notification
+ // Make sure the user is eligible to receive this type of notification
if ( !$this->getCategoryEligibility( $user, $category ) ) {
unset( $eventTypesToLoad[$eventType] );
}
- if ( !$user->getOption( 'echo-subscriptions-' . $outputFormat . '-' . $category ) ) {
+ if ( !$user->getOption( 'echo-subscriptions-' . $notifyType . '-' . $category ) ) {
unset( $eventTypesToLoad[$eventType] );
}
}
@@ -108,71 +155,79 @@ class EchoAttributeManager {
}
/**
- * Get the uesr enabled events for the specified sections
- * @param User
- * @param string
- * @param string[]
+ * Get the user enabled events for the specified sections
+ * @param User $user
+ * @param string $notifyType Either "web" or "email".
+ * @param string[] $sections
* @return string[]
*/
- public function getUserEnabledEventsbySections( User $user, $outputFormat, array $sections ) {
- $events = array();
+ public function getUserEnabledEventsbySections( User $user, $notifyType, array $sections ) {
+ $events = [];
foreach ( $sections as $section ) {
$events = array_merge(
$events,
- call_user_func(
- array( $this, 'get' . ucfirst( $section ) . 'Events' )
- )
+ $this->getEventsForSection( $section )
);
}
+
return array_intersect(
- $this->getUserEnabledEvents( $user, $outputFormat ),
+ $this->getUserEnabledEvents( $user, $notifyType ),
$events
);
}
/**
- * Get alert notification event. Notifications without a section attributes
- * default to section alert
- * @return array
+ * Gets events (notification types) for a given section
+ *
+ * @param string $section Internal section name, one of the values from self::$sections
+ *
+ * @return array Array of notification types in this section
*/
- public function getAlertEvents() {
- $events = array();
+ public function getEventsForSection( $section ) {
+ $events = [];
+
+ $isDefault = ( $section === self::$DEFAULT_SECTION );
+
foreach ( $this->notifications as $event => $attribs ) {
if (
- !isset( $attribs['section'] )
- || !in_array( $attribs['section'], self::$sections )
- || $attribs['section'] === 'alert'
+ (
+ isset( $attribs['section'] ) &&
+ $attribs['section'] === $section
+ ) ||
+ (
+ $isDefault &&
+ (
+ !isset( $attribs['section'] ) ||
+
+ // Invalid section
+ !in_array( $attribs['section'], self::$sections )
+ )
+ )
+
) {
$events[] = $event;
}
}
+
return $events;
}
/**
- * Get message notification event
- * @return array
+ * Gets array of internal category names
+ *
+ * @return array All internal names
*/
- public function getMessageEvents() {
- $events = array();
- foreach ( $this->notifications as $event => $attribs ) {
- if (
- isset( $attribs['section'] )
- && $attribs['section'] === 'message'
- ) {
- $events[] = $event;
- }
- }
- return $events;
+ public function getInternalCategoryNames() {
+ return array_keys( $this->categories );
}
/**
- * See if a user is eligible to recieve a certain type of notification
+ * See if a user is eligible to receive a certain type of notification
* (based on user groups, not user preferences)
*
- * @param User
- * @param string A notification category defined in $wgEchoNotificationCategories
- * @return boolean
+ * @param User $user
+ * @param string $category A notification category defined in $wgEchoNotificationCategories
+ * @return bool
*/
public function getCategoryEligibility( $user, $category ) {
$usersGroups = $user->getGroups();
@@ -182,25 +237,27 @@ class EchoAttributeManager {
return false;
}
}
+
return true;
}
/**
* Get the priority for a specific notification type
*
- * @param string A notification type defined in $wgEchoNotifications
- * @return integer From 1 to 10 (10 is default)
+ * @param string $notificationType A notification type defined in $wgEchoNotifications
+ * @return int From 1 to 10 (10 is default)
*/
public function getNotificationPriority( $notificationType ) {
$category = $this->getNotificationCategory( $notificationType );
+
return $this->getCategoryPriority( $category );
}
/**
* Get the priority for a notification category
*
- * @param string A notification category defined in $wgEchoNotificationCategories
- * @return integer From 1 to 10 (10 is default)
+ * @param string $category A notification category defined in $wgEchoNotificationCategories
+ * @return int From 1 to 10 (10 is default)
*/
public function getCategoryPriority( $category ) {
if ( isset( $this->categories[$category]['priority'] ) ) {
@@ -209,13 +266,14 @@ class EchoAttributeManager {
return $priority;
}
}
+
return 10;
}
/**
* Get the notification category for a notification type
*
- * @param string A notification type defined in $wgEchoNotifications
+ * @param string $notificationType A notification type defined in $wgEchoNotifications
* @return string The name of the notification category or 'other' if no
* category is explicitly assigned.
*/
@@ -226,19 +284,99 @@ class EchoAttributeManager {
return $category;
}
}
+
return 'other';
}
/**
+ * Gets an associative array mapping categories to the notification types in
+ * the category
+ *
+ * @return array Associative array with category as key
+ */
+ public function getEventsByCategory() {
+ $eventsByCategory = [];
+
+ foreach ( $this->categories as $category => $categoryDetails ) {
+ $eventsByCategory[$category] = [];
+ }
+
+ foreach ( $this->notifications as $notificationType => $notificationDetails ) {
+ $category = $notificationDetails['category'];
+ if ( isset( $eventsByCategory[$category] ) ) {
+ // Only real categories. Currently, this excludes the 'foreign'
+ // psuedo-category.
+ $eventsByCategory[$category][] = $notificationType;
+ }
+ }
+
+ return $eventsByCategory;
+ }
+
+ /**
+ * Checks whether the specified notify type is available for the specified
+ * category.
+ *
+ * This means whether users *can* turn notifications for this category and format
+ * on, regardless of the default or a particular user's preferences.
+ *
+ * @param string $category Category name
+ * @param string $notifyType notify type, e.g. email/web.
+ * @return bool
+ */
+ public function isNotifyTypeAvailableForCategory( $category, $notifyType ) {
+ if ( isset( $this->notifyTypeAvailabilityByCategory[$category][$notifyType] ) ) {
+ return $this->notifyTypeAvailabilityByCategory[$category][$notifyType];
+ } else {
+ return $this->defaultNotifyTypeAvailability[$notifyType];
+ }
+ }
+
+ /**
+ * Checks whether category is displayed in preferences
+ *
+ * @param string $category Category name
+ * @return bool
+ */
+ public function isCategoryDisplayedInPreferences( $category ) {
+ return !(
+ isset( $this->categories[$category]['no-dismiss'] ) &&
+ in_array( 'all', $this->categories[$category]['no-dismiss'] )
+ );
+ }
+
+ /**
+ * Checks whether the specified notify type is dismissable for the specified
+ * category.
+ *
+ * This means whether the user is allowed to opt out of receiving notifications
+ * for this category and format.
+ *
+ * @param string $category Name of category
+ * @param string $notifyType notify type, e.g. email/web.
+ * @return bool
+ */
+ public function isNotifyTypeDismissableForCategory( $category, $notifyType ) {
+ return !(
+ isset( $this->categories[$category]['no-dismiss'] ) &&
+ (
+ in_array( 'all', $this->categories[$category]['no-dismiss'] ) ||
+ in_array( $notifyType, $this->categories[$category]['no-dismiss'] )
+ )
+ );
+ }
+
+ /**
* Get notification section for a notification type
* @todo add a unit test case
- * @parm string
+ * @param string $notificationType
* @return string
*/
public function getNotificationSection( $notificationType ) {
if ( isset( $this->notifications[$notificationType]['section'] ) ) {
return $this->notifications[$notificationType]['section'];
}
+
return 'alert';
}
diff --git a/Echo/includes/BatchRowUpdate.php b/Echo/includes/BatchRowUpdate.php
deleted file mode 100644
index 45f0e1a5..00000000
--- a/Echo/includes/BatchRowUpdate.php
+++ /dev/null
@@ -1,454 +0,0 @@
-<?php
-/**
- * Provides components to update a tables rows via a batching process
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- */
-
-/**
- * Ties together the batch update components to provide a composable method
- * of batch updating rows in a database. To use create a class implementing
- * the EchoRowUpdateGenerator interface and configure the EchoBatchRowIterator and
- * EchoBatchRowWriter for access to the correct table. The components will
- * handle reading, writing, and waiting for slaves while the generator implementation
- * handles generating update arrays for singular rows.
- *
- * Instantiate:
- * $updater = new EchoBatchRowUpdate(
- * new EchoBatchRowIterator( $dbr, 'some_table', 'primary_key_column', 500 ),
- * new EchoBatchRowWriter( $dbw, 'some_table', 'clusterName' ),
- * new MyImplementationOfEchoRowUpdateGenerator
- * );
- *
- * Run:
- * $updater->execute();
- *
- * An example maintenance script utilizing the EchoBatchRowUpdate can be located in the Echo
- * extension file maintenance/updateSchema.php
- *
- * @ingroup Maintenance
- */
-class EchoBatchRowUpdate {
- /**
- * @var EchoBatchRowIterator $reader Iterator that returns an array of database rows
- */
- protected $reader;
-
- /**
- * @var EchoBatchRowWriter $writer Writer capable of pushing row updates to the database
- */
- protected $writer;
-
- /**
- * @var EchoRowUpdateGenerator $generator Generates single row updates based on the rows content
- */
- protected $generator;
-
- /**
- * @var callable $output Output callback
- */
- protected $output;
-
- /**
- * @param EchoBatchRowIterator $reader Iterator that returns an array of database rows
- * @param EchoBatchRowWriter $writer Writer capable of pushing row updates to the database
- * @param EchoRowUpdateGenerator $generator Generates single row updates based on the rows content
- */
- public function __construct( EchoBatchRowIterator $reader, EchoBatchRowWriter $writer, EchoRowUpdateGenerator $generator ) {
- $this->reader = $reader;
- $this->writer = $writer;
- $this->generator = $generator;
- $this->output = function() {
- }; // nop
- }
-
- /**
- * Runs the batch update process
- */
- public function execute() {
- foreach ( $this->reader as $rows ) {
- $updates = array();
- foreach ( $rows as $row ) {
- $update = $this->generator->update( $row );
- if ( $update ) {
- $updates[] = array(
- 'primaryKey' => $this->reader->extractPrimaryKeys( $row ),
- 'changes' => $update,
- );
- }
- }
-
- if ( $updates ) {
- $this->output( "Processing " . count( $updates ) . " rows\n" );
- $this->writer->write( $updates );
- }
- }
-
- $this->output( "Completed\n" );
- }
-
- /**
- * Accepts a callable which will receive a single parameter containing
- * string status updates
- *
- * @param callable $output A callback taking a single string parameter to output
- *
- * @throws MWException
- */
- public function setOutput( $output ) {
- if ( !is_callable( $output ) ) {
- throw new MWException( 'Provided $output param is required to be callable.' );
- }
- $this->output = $output;
- }
-
- /**
- * Write out a status update
- *
- * @param string $text The value to print
- */
- protected function output( $text ) {
- call_user_func( $this->output, $text );
- }
-}
-
-/**
- * Interface for generating updates to single rows in the database.
- *
- * @ingroup Maintenance
- */
-interface EchoRowUpdateGenerator {
-
- /**
- * Given a database row, generates an array mapping column names to updated value within the database row
- *
- * Sample Response:
- * return array(
- * 'some_col' => 'new value',
- * 'other_col' => 99,
- * );
- *
- * @param stdClass $row A row from the database
- * @return array Map of column names to updated value within the database row. When no update is required
- * returns an empty array.
- */
- public function update( $row );
-}
-
-/**
- * Updates database rows by primary key in batches. There are two options for writing to tables
- * with a composite primary key.
- *
- * @ingroup Maintenance
- */
-class EchoBatchRowWriter {
- /**
- * @var DatabaseBase $db The database to write to
- */
- protected $db;
-
- /**
- * @var string $table The name of the table to update
- */
- protected $table;
-
- /**
- * @var string $clusterName A cluster name valid for use with LBFactory
- */
- protected $clusterName;
-
- /**
- * @param DatabaseBase $db The database to write to
- * @param string $table The name of the table to update
- * @param string|bool $clusterName A cluster name valid for use with LBFactory
- */
- public function __construct( DatabaseBase $db, $table, $clusterName = false ) {
- $this->db = $db;
- $this->table = $table;
- $this->clusterName = $clusterName;
- }
-
- /**
- * @param array $updates Array of arrays each containing two keys, 'primaryKey' and 'changes'.
- * primaryKey must contain a map of column names to values sufficient to uniquely identify the row
- * changes must contain a map of column names to update values to apply to the row
- */
- public function write( array $updates ) {
- $this->db->begin();
-
- foreach ( $updates as $update ) {
- //echo "Updating: ";var_dump( $update['primaryKey'] );
- //echo "With values: ";var_dump( $update['changes'] );
- $this->db->update(
- $this->table,
- $update['changes'],
- $update['primaryKey'],
- __METHOD__
- );
- }
-
- $this->db->commit();
- wfWaitForSlaves( false, false, $this->clusterName );
- }
-}
-
-/**
- * Fetches rows batched into groups from the database in ascending order of the primary key(s).
- *
- * @ingroup Maintenance
- */
-class EchoBatchRowIterator implements RecursiveIterator {
-
- /**
- * @var DatabaseBase $db The database to read from
- */
- protected $db;
-
- /**
- * @var string $table The name of the table to read from
- */
- protected $table;
-
- /**
- * @var array $primaryKey The name of the primary key(s)
- */
- protected $primaryKey;
-
- /**
- * @var integer $batchSize The number of rows to fetch per iteration
- */
- protected $batchSize;
-
- /**
- * @var array $conditions Array of strings containing SQL conditions to add to the query
- */
- protected $conditions = array();
-
- /**
- * @var array $joinConditions
- */
- protected $joinConditions = array();
-
- /**
- * @var array $fetchColumns List of column names to select from the table suitable for use with DatabaseBase::select()
- */
- protected $fetchColumns;
-
- /**
- * @var string $orderBy SQL Order by condition generated from $this->primaryKey
- */
- protected $orderBy;
-
- /**
- * @var array $current The current iterator value
- */
- private $current = array();
-
- /**
- * @var integer key 0-indexed number of pages fetched since self::reset()
- */
- private $key;
-
- /**
- * @param DatabaseBase $db The database to read from
- * @param string $table The name of the table to read from
- * @param string|array $primaryKey The name or names of the primary key columns
- * @param integer $batchSize The number of rows to fetch per iteration
- *
- * @throws MWException
- */
- public function __construct( DatabaseBase $db, $table, $primaryKey, $batchSize ) {
- if ( $batchSize < 1 ) {
- throw new MWException( 'Batch size must be at least 1 row.' );
- }
- $this->db = $db;
- $this->table = $table;
- $this->primaryKey = (array) $primaryKey;
- $this->fetchColumns = $this->primaryKey;
- $this->orderBy = implode( ' ASC,', $this->primaryKey ) . ' ASC';
- $this->batchSize = $batchSize;
- }
-
- /**
- * @param string $condition Query conditions suitable for use with DatabaseBase::select
- */
- public function addConditions( array $conditions ) {
- $this->conditions = array_merge( $this->conditions, $conditions );
- }
-
- public function addJoinConditions( array $conditions ) {
- $this->joinConditions = array_merge( $this->joinConditions, $conditions );
- }
-
- /**
- * @param array $columns List of column names to select from the table suitable for use with DatabaseBase::select()
- */
- public function setFetchColumns( array $columns ) {
- // If it's not the all column selector merge in the primary keys we need
- if ( count( $columns ) === 1 && reset( $columns ) === '*' ) {
- $this->fetchColumns = $columns;
- } else {
- $this->fetchColumns = array_unique( array_merge( $this->primaryKey, $columns ) );
- }
- }
-
- /**
- * Extracts the primary key(s) from a database row.
- *
- * @param stdClass $row An individual database row from this iterator
- * @return array Map of primary key column to value within the row
- */
- public function extractPrimaryKeys( $row ) {
- $pk = array();
- foreach ( $this->primaryKey as $column ) {
- $pk[$column] = $row->$column;
- }
- return $pk;
- }
-
- /**
- * @return array The most recently fetched set of rows from the database
- */
- public function current() {
- return $this->current;
- }
-
- /**
- * @return integer 0-indexed count of the page number fetched
- */
- public function key() {
- return $this->key;
- }
-
- /**
- * Reset the iterator to the begining of the table.
- */
- public function rewind() {
- $this->key = -1; // self::next() will turn this into 0
- $this->current = array();
- $this->next();
- }
-
- /**
- * @return boolean True when the iterator is in a valid state
- */
- public function valid() {
- return (bool) $this->current;
- }
-
- /**
- * @return boolean True when this result set has rows
- */
- public function hasChildren() {
- return $this->current && count( $this->current );
- }
-
- /**
- * @return RecursiveIterator
- */
- public function getChildren() {
- return new EchoNotRecursiveIterator( new ArrayIterator( $this->current ) );
- }
-
- /**
- * Fetch the next set of rows from the database.
- */
- public function next() {
- $res = $this->db->select(
- $this->table,
- $this->fetchColumns,
- $this->buildConditions(),
- __METHOD__,
- array(
- 'LIMIT' => $this->batchSize,
- 'ORDER BY' => $this->orderBy,
- ),
- $this->joinConditions
- );
-
- // The iterator is converted to an array because in addition to returning it
- // in self::current() we need to use the end value in self::buildConditions()
- $this->current = iterator_to_array( $res );
- $this->key++;
- }
-
- /**
- * Uses the primary key list and the maximal result row from the previous iteration to build
- * an SQL condition sufficient for selecting the next page of results. All except the final
- * key use `=` conditions while the final key uses a `>` condition
- *
- * Example output:
- * array( '( foo = 42 AND bar > 7 ) OR ( foo > 42 )' )
- *
- * @return array The SQL conditions necessary to select the next set of rows in the batched query
- */
- protected function buildConditions() {
- if ( !$this->current ) {
- return $this->conditions;
- }
-
- $maxRow = end( $this->current );
- $maximumValues = array();
- foreach ( $this->primaryKey as $column ) {
- $maximumValues[$column] = $this->db->addQuotes( $maxRow->$column );
- }
-
- $pkConditions = array();
- // For example: If we have 3 primary keys
- // first run through will generate
- // col1 = 4 AND col2 = 7 AND col3 > 1
- // second run through will generate
- // col1 = 4 AND col2 > 7
- // and the final run through will generate
- // col1 > 4
- while ( $maximumValues ) {
- $pkConditions[] = $this->buildGreaterThanCondition( $maximumValues );
- array_pop( $maximumValues );
- }
-
- $conditions = $this->conditions;
- $conditions[] = sprintf( '( %s )', implode( ' ) OR ( ', $pkConditions ) );
-
- return $conditions;
- }
-
- /**
- * Given an array of column names and their maximum value generate an SQL
- * condition where all keys except the last match $quotedMaximumValues
- * exactly and the last column is greater than the matching value in $quotedMaximumValues
- *
- * @param array $quotedMaximumValues The maximum values quoted with $this->db->addQuotes()
- * @return string An SQL condition that will select rows where all columns match the
- * maximum value exactly except the last column which must be greater than the provided
- * maximum value
- */
- protected function buildGreaterThanCondition( array $quotedMaximumValues ) {
- $keys = array_keys( $quotedMaximumValues );
- $lastColumn = end( $keys );
- $lastValue = array_pop( $quotedMaximumValues );
- $conditions = array();
- foreach ( $quotedMaximumValues as $column => $value ) {
- $conditions[] = "$column = $value";
- }
- $conditions[] = "$lastColumn > $lastValue";
-
- return implode( ' AND ', $conditions );
- }
-}
-
diff --git a/Echo/includes/Bundleable.php b/Echo/includes/Bundleable.php
new file mode 100644
index 00000000..2469027f
--- /dev/null
+++ b/Echo/includes/Bundleable.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * Interface Bundleable
+ *
+ * Indicates that an object can be bundled.
+ */
+interface Bundleable {
+
+ /**
+ * @return bool Whether this object can be bundled.
+ */
+ public function canBeBundled();
+
+ /**
+ * @return string objects with the same bundling key can be bundled together
+ */
+ public function getBundlingKey();
+
+ /**
+ * @param Bundleable[] $bundleables other object that have been bundled with this one
+ */
+ public function setBundledElements( $bundleables );
+
+ /**
+ * @return mixed the key by which this object should be sorted during the bundling process
+ */
+ public function getSortingKey();
+}
diff --git a/Echo/includes/Bundler.php b/Echo/includes/Bundler.php
new file mode 100644
index 00000000..5c162687
--- /dev/null
+++ b/Echo/includes/Bundler.php
@@ -0,0 +1,48 @@
+<?php
+
+class Bundler {
+
+ private function sort( &$array ) {
+ // We have to ignore the error here (use @usort)
+ // otherwise this code fails when executed by unit tests
+ // See: https://bugs.php.net/bug.php?id=50688
+
+ // @codingStandardsIgnoreStart
+ @usort( $array, function( Bundleable $a, Bundleable $b ) {
+ return strcmp( $b->getSortingKey(), $a->getSortingKey() );
+ } );
+ // @codingStandardsIgnoreEnd
+ }
+
+ /**
+ * Bundle bundleable elements that can be bundled by their bundling keys
+ *
+ * @param Bundleable[] $bundleables
+ * @return Bundleable[] Grouped notifications sorted by timestamp DESC
+ */
+ public function bundle( $bundleables ) {
+ $groups = [];
+ $bundled = [];
+
+ /** @var Bundleable $element */
+ foreach ( $bundleables as $element ) {
+ if ( $element->canBeBundled() && $element->getBundlingKey() ) {
+ $groups[ $element->getBundlingKey() ][] = $element;
+ } else {
+ $bundled[] = $element;
+ }
+ }
+
+ foreach ( $groups as $bundlingKey => $group ) {
+ $this->sort( $group );
+ /** @var Bundleable $base */
+ $base = array_shift( $group );
+ $base->setBundledElements( $group );
+ $bundled[] = $base;
+ }
+
+ $this->sort( $bundled );
+ return $bundled;
+ }
+
+}
diff --git a/Echo/includes/ContainmentSet.php b/Echo/includes/ContainmentSet.php
index 95c1c8af..4b6ce1f8 100644
--- a/Echo/includes/ContainmentSet.php
+++ b/Echo/includes/ContainmentSet.php
@@ -22,9 +22,10 @@ interface EchoContainmentList {
* from multiple sources like global variables, wiki pages, etc.
*
* Initialize:
+ * $cache = ObjectCache::getLocalClusterIntance();
* $set = new EchoContainmentSet;
* $set->addArray( $wgSomeGlobalParameter );
- * $set->addOnWiki( NS_USER, 'Foo/bar-baz', $wgMemc, 'some_user_specific_cache_key' );
+ * $set->addOnWiki( NS_USER, 'Foo/bar-baz', $cache, 'some_user_specific_cache_key' );
*
* Usage:
* if ( $set->contains( 'SomeUser' ) ) {
@@ -33,14 +34,23 @@ interface EchoContainmentList {
*/
class EchoContainmentSet {
/**
- * @var $lists array of EchoContainmentList objects
+ * @var EchoContainmentList[]
*/
- protected $lists = array();
+ protected $lists = [];
+
+ /**
+ * @var User
+ */
+ protected $recipient;
+
+ public function __construct( User $recipient ) {
+ $this->recipient = $recipient;
+ }
/**
* Add an EchoContainmentList to the set of lists checked by self::contains()
*
- * @param $list EchoContainmentList
+ * @param EchoContainmentList $list
*/
public function add( EchoContainmentList $list ) {
$this->lists[] = $list;
@@ -49,21 +59,36 @@ class EchoContainmentSet {
/**
* Add a php array to the set of lists checked by self::contains()
*
- * @param $list array
+ * @param array $list
*/
public function addArray( array $list ) {
$this->add( new EchoArrayList( $list ) );
}
/**
+ * Add a list from a user preference to the set of lists checked by self::contains().
+ *
+ * @param string $preferenceName
+ */
+ public function addFromUserOption( $preferenceName ) {
+ $preference = $this->recipient->getOption( $preferenceName );
+
+ if ( $preference ) {
+ $items = explode( "\n", $preference );
+
+ $this->addArray( $items );
+ }
+ }
+
+ /**
* Add a list from a wiki page to the set of lists checked by self::contains(). Data
* from wiki pages is cached via the BagOStuff. Caching is disabled when passing a null
* $cache object.
*
- * @param $namespace integer An NS_* constant representing the mediawiki namespace of the page containing the list.
- * @param $title string The title of the page containing the list.
- * @param $cache BagOStuff An object to cache the page with or null for no cache.
- * @param $cacheKeyPrefix string A prefix to be combined with the pages latest revision id and used as a cache key.
+ * @param int $namespace An NS_* constant representing the mediawiki namespace of the page containing the list.
+ * @param string $title The title of the page containing the list.
+ * @param BagOStuff $cache An object to cache the page with or null for no cache.
+ * @param string $cacheKeyPrefix A prefix to be combined with the pages latest revision id and used as a cache key.
*
* @throws MWException
*/
@@ -81,8 +106,8 @@ class EchoContainmentSet {
/**
* Test the wrapped lists for existence of $value
*
- * @param $value mixed The value to look for
- * @return boolean True when the set contains the provided value
+ * @param mixed $value The value to look for
+ * @return bool True when the set contains the provided value
*/
public function contains( $value ) {
foreach ( $this->lists as $list ) {
@@ -102,26 +127,26 @@ class EchoContainmentSet {
*/
class EchoArrayList implements EchoContainmentList {
/**
- * @param $list array
+ * @var array
*/
protected $list;
/**
- * @param $list array
+ * @param array $list
*/
public function __construct( array $list ) {
$this->list = $list;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getValues() {
return $this->list;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getCacheKey() {
return '';
@@ -134,14 +159,14 @@ class EchoArrayList implements EchoContainmentList {
*/
class EchoOnWikiList implements EchoContainmentList {
/**
- * @var $title Title|null A title object representing the page to source the list from,
+ * @var Title|null A title object representing the page to source the list from,
* or null if the page does not exist.
*/
protected $title;
/**
- * @param $titleNs integer An NS_* constant representing the mediawiki namespace of the page
- * @param $titleString string String portion of the wiki page title
+ * @param int $titleNs An NS_* constant representing the mediawiki namespace of the page
+ * @param string $titleString String portion of the wiki page title
*/
public function __construct( $titleNs, $titleString ) {
$title = Title::newFromText( $titleString, $titleNs );
@@ -151,23 +176,26 @@ class EchoOnWikiList implements EchoContainmentList {
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getValues() {
if ( !$this->title ) {
- return array();
+ return [];
}
$article = WikiPage::newFromID( $this->title->getArticleId() );
if ( $article === null || !$article->exists() ) {
- return array();
+ return [];
}
-
- return array_filter( array_map( 'trim', explode( "\n", $article->getText() ) ) );
+ $text = ContentHandler::getContentText( $article->getContent() );
+ if ( $text === null ) {
+ return [];
+ }
+ return array_filter( array_map( 'trim', explode( "\n", $text ) ) );
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getCacheKey() {
if ( !$this->title ) {
@@ -193,11 +221,11 @@ class EchoCachedList implements EchoContainmentList {
private $result;
/**
- * @param $cache BagOStuff Bag to stored cached data in.
- * @param $partialCacheKey string Partial cache key, $nestedList->getCacheKey() will be appended to this
- * to construct the cache key used.
- * @param $nestedList EchoContainmentList The nested EchoContainmentList to cache the result of.
- * @param $timeout integer How long in seconds to cache the nested list, defaults to 1 week.
+ * @param BagOStuff $cache Bag to stored cached data in.
+ * @param string $partialCacheKey Partial cache key, $nestedList->getCacheKey() will be appended
+ * to this to construct the cache key used.
+ * @param EchoContainmentList $nestedList The nested EchoContainmentList to cache the result of.
+ * @param int $timeout How long in seconds to cache the nested list, defaults to 1 week.
*/
public function __construct( BagOStuff $cache, $partialCacheKey, EchoContainmentList $nestedList, $timeout = self::ONE_WEEK ) {
$this->cache = $cache;
@@ -207,7 +235,7 @@ class EchoCachedList implements EchoContainmentList {
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getValues() {
if ( $this->result ) {
@@ -234,7 +262,7 @@ class EchoCachedList implements EchoContainmentList {
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function getCacheKey() {
return $this->partialCacheKey . '_' . $this->nestedList->getCacheKey();
diff --git a/Echo/includes/DataOutputFormatter.php b/Echo/includes/DataOutputFormatter.php
index b7519c94..58eec3a1 100644
--- a/Echo/includes/DataOutputFormatter.php
+++ b/Echo/includes/DataOutputFormatter.php
@@ -6,25 +6,42 @@
class EchoDataOutputFormatter {
/**
+ * @var array type => class
+ */
+ protected static $formatters = [
+ 'flyout' => 'EchoFlyoutFormatter',
+ 'model' => 'EchoModelFormatter',
+ 'special' => 'SpecialNotificationsFormatter',
+ 'html' => 'SpecialNotificationsFormatter',
+ ];
+
+ /**
* Format a notification for a user in the format specified
*
* @param EchoNotification $notification
- * @param string|bool $format specifify output format, false to not format any notifications
- * @param User|null $user the target user viewing the notification
- * @return array
+ * @param string|bool $format output format, false to not format any notifications
+ * @param User $user the target user viewing the notification
+ * @param Language $lang Language to format the notification in
+ * @return array|bool false if it could not be formatted
*/
- public static function formatOutput( EchoNotification $notification, $format = false, User $user = null ) {
+ public static function formatOutput( EchoNotification $notification, $format = false, User $user, Language $lang ) {
$event = $notification->getEvent();
$timestamp = $notification->getTimestamp();
+ $utcTimestampIso8601 = wfTimestamp( TS_ISO_8601, $timestamp );
$utcTimestampUnix = wfTimestamp( TS_UNIX, $timestamp );
-
- // Default to notification user if user is not specified
- if ( !$user ) {
- $user = $notification->getUser();
- }
-
- if ( $notification->getBundleBase() && $notification->getBundleDisplayHash() ) {
- $event->setBundleHash( $notification->getBundleDisplayHash() );
+ $utcTimestampMW = wfTimestamp( TS_MW, $timestamp );
+ $bundledIds = null;
+
+ $bundledNotifs = $notification->getBundledNotifications();
+ if ( $bundledNotifs ) {
+ $bundledEvents = array_map( function ( EchoNotification $notif ) {
+ return $notif->getEvent();
+ }, $bundledNotifs );
+ $event->setBundledEvents( $bundledEvents );
+
+ $bundledIds = array_map( function ( $event ) {
+ return (int)$event->getId();
+ }, $bundledEvents );
}
$timestampMw = self::getUserLocalTime( $user, $timestamp );
@@ -48,18 +65,28 @@ class EchoDataOutputFormatter {
}
// End creating date section header
- $output = array(
+ $output = [
+ 'wiki' => wfWikiID(),
'id' => $event->getId(),
'type' => $event->getType(),
'category' => $event->getCategory(),
- 'timestamp' => array(
+ 'timestamp' => [
+ // ISO 8601 is supposed to be the *only* format used for
+ // date output, but back-compat...
+ 'utciso8601' => $utcTimestampIso8601,
+
// UTC timestamp in UNIX format used for loading more notification
'utcunix' => $utcTimestampUnix,
'unix' => self::getUserLocalTime( $user, $timestamp, TS_UNIX ),
+ 'utcmw' => $utcTimestampMW,
'mw' => $timestampMw,
'date' => $date
- ),
- );
+ ],
+ ];
+
+ if ( $bundledIds ) {
+ $output['bundledIds'] = $bundledIds;
+ }
if ( $event->getVariant() ) {
$output['variant'] = $event->getVariant();
@@ -67,23 +94,23 @@ class EchoDataOutputFormatter {
$title = $event->getTitle();
if ( $title ) {
- $output['title'] = array(
+ $output['title'] = [
'full' => $title->getPrefixedText(),
'namespace' => $title->getNSText(),
- 'namespace-key' =>$title->getNamespace(),
+ 'namespace-key' => $title->getNamespace(),
'text' => $title->getText(),
- );
+ ];
}
$agent = $event->getAgent();
if ( $agent ) {
if ( $event->userCan( Revision::DELETED_USER, $user ) ) {
- $output['agent'] = array(
+ $output['agent'] = [
'id' => $agent->getId(),
'name' => $agent->getName(),
- );
+ ];
} else {
- $output['agent'] = array( 'userhidden' => '' );
+ $output['agent'] = [ 'userhidden' => '' ];
}
}
@@ -97,8 +124,8 @@ class EchoDataOutputFormatter {
// This is only meant for unread notifications, if a notification has a target
// page, then it shouldn't be auto marked as read unless the user visits
- // the target page or a user marks it as read manully ( coming soon )
- $output['targetpages'] = array();
+ // the target page or a user marks it as read manually ( coming soon )
+ $output['targetpages'] = [];
if ( $notification->getTargetPages() ) {
foreach ( $notification->getTargetPages() as $targetPage ) {
$output['targetpages'][] = $targetPage->getPageId();
@@ -106,13 +133,48 @@ class EchoDataOutputFormatter {
}
if ( $format ) {
- $output['*'] = EchoNotificationController::formatNotification( $event, $user, $format );
+ $formatted = self::formatNotification( $event, $user, $format, $lang );
+ if ( $formatted === false ) {
+ // Can't display it, so mark it as read
+ EchoDeferredMarkAsDeletedUpdate::add( $event );
+ return false;
+ }
+ $output['*'] = $formatted;
+
+ if ( $notification->getBundledNotifications() && self::isBundleExpandable( $event->getType() ) ) {
+ $output['bundledNotifications'] = array_values( array_filter( array_map( function ( EchoNotification $notification ) use ( $format, $user, $lang ) {
+ // remove nested notifications to
+ // - ensure they are formatted as single notifications (not bundled)
+ // - prevent further re-entrance on the current notification
+ $notification->setBundledNotifications( [] );
+ $notification->getEvent()->setBundledEvents( [] );
+ return self::formatOutput( $notification, $format, $user, $lang );
+ }, array_merge( [ $notification ], $notification->getBundledNotifications() ) ) ) );
+ }
}
return $output;
}
/**
+ * @param EchoEvent $event
+ * @param User $user
+ * @param string $format
+ * @param Language $lang
+ * @return string|bool false if it could not be formatted
+ */
+ protected static function formatNotification( EchoEvent $event, User $user, $format, $lang ) {
+ if ( isset( self::$formatters[$format] ) ) {
+ $class = self::$formatters[$format];
+ /** @var EchoEventFormatter $formatter */
+ $formatter = new $class( $user, $lang );
+ return $formatter->format( $event );
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Get the date header in user's format, 'May 10' or '10 May', depending
* on user's date format preference
* @param User $user
@@ -122,6 +184,7 @@ class EchoDataOutputFormatter {
protected static function getDateHeader( User $user, $timestampMw ) {
$lang = RequestContext::getMain()->getLanguage();
$dateFormat = $lang->getDateFormatString( 'pretty', $user->getDatePreference() ?: 'default' );
+
return $lang->sprintfDate( $dateFormat, $timestampMw );
}
@@ -130,14 +193,24 @@ class EchoDataOutputFormatter {
*
* @param User
* @param string
- * @param int output format
+ * @param int $format output format
*
* @return string
*/
public static function getUserLocalTime( User $user, $ts, $format = TS_MW ) {
$timestamp = new MWTimestamp( $ts );
$timestamp->offsetForUser( $user );
+
return $timestamp->getTimestamp( $format );
}
+ /**
+ * @param string $type
+ * @return bool Whether a notification type can be an expandable bundle
+ */
+ public static function isBundleExpandable( $type ) {
+ global $wgEchoNotifications;
+ return isset( $wgEchoNotifications[$type]['bundle']['expandable'] ) && $wgEchoNotifications[$type]['bundle']['expandable'];
+ }
+
}
diff --git a/Echo/includes/DeferredMarkAsDeletedUpdate.php b/Echo/includes/DeferredMarkAsDeletedUpdate.php
new file mode 100644
index 00000000..3a384466
--- /dev/null
+++ b/Echo/includes/DeferredMarkAsDeletedUpdate.php
@@ -0,0 +1,72 @@
+<?php
+use MediaWiki\Logger\LoggerFactory;
+
+/**
+ * Mark event notifications as deleted at the end of a request. Used to queue up
+ * individual events to mark due to formatting failures.
+ */
+class EchoDeferredMarkAsDeletedUpdate implements DeferrableUpdate {
+ /**
+ * @var array
+ */
+ protected $events = [];
+
+ /**
+ * @param EchoEvent $event
+ */
+ public static function add( EchoEvent $event ) {
+ static $update;
+ if ( $update === null ) {
+ $update = new self();
+ DeferredUpdates::addUpdate( $update );
+ }
+ $update->addInternal( $event );
+ }
+
+ /**
+ * @param EchoEvent $event
+ */
+ private function addInternal( EchoEvent $event ) {
+ $this->events[] = $event;
+ }
+
+ private function filterEventsWithTitleDbLag() {
+ return array_filter(
+ $this->events,
+ function ( EchoEvent $event ) {
+ if ( !$event->getTitle() && $event->getTitle( true ) ) {
+ // It is very likely this event was found
+ // unreaderable because of slave lag.
+ // Do not moderate it at this time.
+ LoggerFactory::getInstance( 'Echo' )->debug(
+ 'EchoDeferredMarkAsDeletedUpdate: Event {eventId} was found unrenderable but its associated title exists on Master. Skipping.',
+ [
+ 'eventId' => $event->getId(),
+ 'title' => $event->getTitle()->getPrefixedText(),
+ ]
+ );
+ return false;
+ }
+ return true;
+ }
+ );
+ }
+
+ /**
+ * Marks all queued notifications as read.
+ * Satisfies DeferrableUpdate interface
+ */
+ public function doUpdate() {
+ $events = $this->filterEventsWithTitleDbLag();
+
+ $eventIds = array_map(
+ function ( EchoEvent $event ) {
+ return $event->getId();
+ },
+ $events
+ );
+
+ EchoModerationController::moderate( $eventIds, true );
+ $this->events = [];
+ }
+}
diff --git a/Echo/includes/DeferredMarkAsReadUpdate.php b/Echo/includes/DeferredMarkAsReadUpdate.php
deleted file mode 100644
index 9b02e8cc..00000000
--- a/Echo/includes/DeferredMarkAsReadUpdate.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-/**
- * Mark event notifications as read at the end of a request. Used to queue up
- * individual events to mark due to formatting failures or other uses.
- */
-class EchoDeferredMarkAsReadUpdate implements DeferrableUpdate {
- /**
- * @var array
- */
- protected $events = array();
-
- /**
- * @param EchoEvent $event
- * @param User $user
- */
- public function add( EchoEvent $event, User $user ) {
- $uid = $user->getId();
- if ( isset( $this->events[$uid] ) ) {
- $this->events[$uid]['eventIds'][] = $event->getId();
- } else {
- $this->events[$uid] = array(
- 'user' => $user,
- 'eventIds' => array( $event->getId() ),
- );
- }
- }
-
- /**
- * Mark's all queue'd notifications as read.
- * Satisfies DeferrableUpdate interface
- */
- public function doUpdate() {
- foreach ( $this->events as $data ) {
- MWEchoNotifUser::newFromUser( $data['user'] )->markRead( $data['eventIds'] );
- }
- $this->events = array();
- }
-}
diff --git a/Echo/includes/DiffParser.php b/Echo/includes/DiffParser.php
index d18035c1..7b70fae6 100644
--- a/Echo/includes/DiffParser.php
+++ b/Echo/includes/DiffParser.php
@@ -26,13 +26,13 @@
* Calculates the individual sets of differences between two pieces of text
* as individual groupings of add, subtract, and change actions. Internally
* uses 0-indexing for positions. All results from the class are 1 indexed
- * to stay consistent with the origional diff output and the previous diff
+ * to stay consistent with the original diff output and the previous diff
* parsing code.
*/
class EchoDiffParser {
/**
- * @var integer $prefixLength The number of characters the diff prefixes a line with
+ * @var int $prefixLength The number of characters the diff prefixes a line with
*/
protected $prefixLength = 1;
@@ -42,7 +42,7 @@ class EchoDiffParser {
protected $left;
/**
- * @var integer $leftPos The current position within the left text
+ * @var int $leftPos The current position within the left text
*/
protected $leftPos;
@@ -52,7 +52,7 @@ class EchoDiffParser {
protected $right;
/**
- * @var integer $rightPos The current position within the right text
+ * @var int $rightPos The current position within the right text
*/
protected $rightPos;
@@ -77,25 +77,55 @@ class EchoDiffParser {
* 'left_pos' and 'right_pos' (in 1-indexed lines) of the change.
*/
public function getChangeSet( $leftText, $rightText ) {
- $left = trim( $leftText ) . "\n";
- $right = trim( $rightText ) . "\n";
- $diff = wfDiff( $left, $right, '-u -w' );
+ $left = trim( $leftText );
+ $right = trim( $rightText );
+
+ if ( $left === '' ) {
+ // fixes T155998
+ return $this->getChangeSetFromEmptyLeft( $right );
+ }
+
+ $diffs = new Diff( explode( "\n", $left ), explode( "\n", $right ) );
+ $format = new UnifiedDiffFormatter();
+ $diff = $format->format( $diffs );
return $this->parse( $diff, $left, $right );
}
/**
+ * If we add content to an empty page the changeSet can be composed straightaway
+ *
+ * @param string $right
+ * @return array[] see getChangeSet()
+ */
+ private function getChangeSetFromEmptyLeft( $right ) {
+ $rightLines = explode( "\n", $right );
+
+ return [
+ '_info' => [
+ 'lhs-length' => 1,
+ 'rhs-length' => count( $rightLines ),
+ 'lhs' => [ '' ],
+ 'rhs' => $rightLines
+ ],
+ [
+ 'right-pos' => 1,
+ 'left-pos' => 1,
+ 'action' => 'add',
+ 'content' => $right,
+ ]
+ ];
+ }
+
+ /**
* Duplicates the check from the global wfDiff function to determine
* if we are using internal or external diff utilities
+ *
+ * @deprecated since 1.29, the internal diff parser is always used
+ * @return bool
*/
- static protected function usingInternalDiff() {
- global $wgDiff;
-
- wfSuppressWarnings();
- $haveDiff = $wgDiff && file_exists( $wgDiff );
- wfRestoreWarnings();
-
- return !$haveDiff;
+ protected static function usingInternalDiff() {
+ return true;
}
/**
@@ -114,14 +144,14 @@ class EchoDiffParser {
$this->leftPos = 0;
$this->rightPos = 0;
- $this->changeSet = array(
- '_info' => array(
+ $this->changeSet = [
+ '_info' => [
'lhs-length' => count( $this->left ),
'rhs-length' => count( $this->right ),
'lhs' => $this->left,
'rhs' => $this->right,
- ),
- );
+ ],
+ ];
$change = null;
foreach ( $diff as $line ) {
@@ -151,59 +181,59 @@ class EchoDiffParser {
} else {
$line = '';
}
- } else {
+ } else {
$op = ' ';
}
- switch( $op ) {
- case '@': // metadata
- if ( $change !== null ) {
- $this->changeSet = array_merge( $this->changeSet, $change->getChangeSet() );
- $change = null;
- }
- // @@ -start,numLines +start,numLines @@
- list( , $left, $right ) = explode( ' ', $line );
- list( $this->leftPos ) = explode( ',', substr( $left, 1 ) );
- list( $this->rightPos ) = explode( ',', substr( $right, 1 ) );
-
- // -1 because diff is 1 indexed and we are 0 indexed
- $this->leftPos--;
- $this->rightPos--;
- break;
-
- case ' ': // No changes
- if ( $change !== null ) {
- $this->changeSet = array_merge( $this->changeSet, $change->getChangeSet() );
- $change = null;
- }
- $this->leftPos++;
- $this->rightPos++;
- break;
-
- case '-': // subtract
- if ( $this->left[$this->leftPos] !== $line ) {
- throw new MWException( 'Positional error: left' );
- }
- if ( $change === null ) {
- $change = new EchoDiffGroup( $this->leftPos, $this->rightPos );
- }
- $change->subtract( $line );
- $this->leftPos++;
- break;
-
- case '+': // add
- if ( $this->right[$this->rightPos] !== $line ) {
- throw new MWException( 'Positional error: right' );
- }
- if ( $change === null ) {
- $change = new EchoDiffGroup( $this->leftPos, $this->rightPos );
- }
- $change->add( $line );
- $this->rightPos++;
- break;
-
- default:
- throw new MWException( 'Unknown Diff Operation: ' . $op );
+ switch ( $op ) {
+ case '@': // metadata
+ if ( $change !== null ) {
+ $this->changeSet = array_merge( $this->changeSet, $change->getChangeSet() );
+ $change = null;
+ }
+ // @@ -start,numLines +start,numLines @@
+ list( , $left, $right ) = explode( ' ', $line );
+ list( $this->leftPos ) = explode( ',', substr( $left, 1 ) );
+ list( $this->rightPos ) = explode( ',', substr( $right, 1 ) );
+
+ // -1 because diff is 1 indexed and we are 0 indexed
+ $this->leftPos--;
+ $this->rightPos--;
+ break;
+
+ case ' ': // No changes
+ if ( $change !== null ) {
+ $this->changeSet = array_merge( $this->changeSet, $change->getChangeSet() );
+ $change = null;
+ }
+ $this->leftPos++;
+ $this->rightPos++;
+ break;
+
+ case '-': // subtract
+ if ( $this->left[$this->leftPos] !== $line ) {
+ throw new MWException( 'Positional error: left' );
+ }
+ if ( $change === null ) {
+ $change = new EchoDiffGroup( $this->leftPos, $this->rightPos );
+ }
+ $change->subtract( $line );
+ $this->leftPos++;
+ break;
+
+ case '+': // add
+ if ( $this->right[$this->rightPos] !== $line ) {
+ throw new MWException( 'Positional error: right' );
+ }
+ if ( $change === null ) {
+ $change = new EchoDiffGroup( $this->leftPos, $this->rightPos );
+ }
+ $change->add( $line );
+ $this->rightPos++;
+ break;
+
+ default:
+ throw new MWException( 'Unknown Diff Operation: ' . $op );
}
return $change;
@@ -222,23 +252,23 @@ class EchoDiffGroup {
/**
* @var array The lines that have been added
*/
- protected $new = array();
+ protected $new = [];
/**
* @var array The lines that have been removed
*/
- protected $old = array();
+ protected $old = [];
/**
- * @param integer $leftPos The starting line number in the left text
- * @param integer $rightPos The starting line number in the right text
+ * @param int $leftPos The starting line number in the left text
+ * @param int $rightPos The starting line number in the right text
*/
public function __construct( $leftPos, $rightPos ) {
// +1 due to the origional code use 1 indexing for this result
- $this->position = array(
+ $this->position = [
'right-pos' => $rightPos + 1,
'left-pos' => $leftPos + 1,
- );
+ ];
}
/**
@@ -270,17 +300,17 @@ class EchoDiffGroup {
$old = implode( "\n", $this->old );
$new = implode( "\n", $this->new );
$position = $this->position;
- $changeSet = array();
+ $changeSet = [];
// The implodes must come first because we consider array( '' ) to also be false
// meaning a blank link replaced with content is an addition
if ( $old && $new ) {
$min = min( count( $this->old ), count( $this->new ) );
- $changeSet[] = $position + array(
+ $changeSet[] = $position + [
'action' => 'change',
'old_content' => implode( "\n", array_slice( $this->old, 0, $min ) ),
'new_content' => implode( "\n", array_slice( $this->new, 0, $min ) ),
- );
+ ];
$position['left-pos'] += $min;
$position['right-pos'] += $min;
$old = implode( "\n", array_slice( $this->old, $min ) );
@@ -288,15 +318,15 @@ class EchoDiffGroup {
}
if ( $new ) {
- $changeSet[] = $position + array(
+ $changeSet[] = $position + [
'action' => 'add',
'content' => $new,
- );
+ ];
} elseif ( $old ) {
- $changeSet[] = $position + array(
+ $changeSet[] = $position + [
'action' => 'subtract',
'content' => $old,
- );
+ ];
}
return $changeSet;
diff --git a/Echo/includes/DiscussionParser.php b/Echo/includes/DiscussionParser.php
index a5dab307..11d5e7fe 100644
--- a/Echo/includes/DiscussionParser.php
+++ b/Echo/includes/DiscussionParser.php
@@ -1,21 +1,24 @@
<?php
+use MediaWiki\MediaWikiServices;
+
abstract class EchoDiscussionParser {
const HEADER_REGEX = '^(==+)\s*([^=].*)\s*\1$';
static protected $timestampRegex;
- static protected $revisionInterpretationCache = array();
+ static protected $revisionInterpretationCache = [];
static protected $diffParser;
/**
* Given a Revision object, generates EchoEvent objects for
* the discussion-related actions that occurred in that Revision.
*
- * @param $revision Revision object
+ * @param Revision $revision
* @return null
*/
- static function generateEventsForRevision( $revision ) {
- $interpretation = self::getChangeInterpretationForRevision( $revision );
+ static function generateEventsForRevision( Revision $revision ) {
+ global $wgEchoMentionsOnMultipleSectionEdits;
+ global $wgEchoMentionOnChanges;
// use slave database if there is a previous revision
if ( $revision->getPrevious() ) {
@@ -30,6 +33,8 @@ abstract class EchoDiscussionParser {
return;
}
+ $interpretation = self::getChangeInterpretationForRevision( $revision );
+
$userID = $revision->getUser();
$userName = $revision->getUserText();
$user = $userID != 0 ? User::newFromId( $userID ) : User::newFromName( $userName, false );
@@ -38,11 +43,28 @@ abstract class EchoDiscussionParser {
if ( $action['type'] == 'add-comment' ) {
$fullSection = $action['full-section'];
$header = self::extractHeader( $fullSection );
- self::generateMentionEvents( $header, $action['content'], $revision, $user );
+ $userLinks = self::getUserLinks( $action['content'], $title );
+ self::generateMentionEvents( $header, $userLinks, $action['content'], $revision, $user );
} elseif ( $action['type'] == 'new-section-with-comment' ) {
$content = $action['content'];
$header = self::extractHeader( $content );
- self::generateMentionEvents( $header, $content, $revision, $user );
+ $userLinks = self::getUserLinks( $content, $title );
+ self::generateMentionEvents( $header, $userLinks, $content, $revision, $user );
+ } elseif ( $action['type'] == 'add-section-multiple' && $wgEchoMentionsOnMultipleSectionEdits ) {
+ $content = self::stripHeader( $action['content'] );
+ $content = self::stripSignature( $content );
+ $userLinks = self::getUserLinks( $content, $title );
+ self::generateMentionEvents( $action['header'], $userLinks, $content, $revision, $user );
+ } elseif ( $action['type'] === 'unknown-signed-change' ) {
+ $userLinks = array_diff_key(
+ self::getUserLinks( $action['new_content'], $title ) ?: [],
+ self::getUserLinks( $action['old_content'], $title ) ?: []
+ );
+ $header = self::extractHeader( $action['full-section'] );
+
+ if ( $wgEchoMentionOnChanges ) {
+ self::generateMentionEvents( $header, $userLinks, $action['new_content'], $revision, $user );
+ }
}
}
@@ -50,24 +72,26 @@ abstract class EchoDiscussionParser {
$notifyUser = User::newFromName( $title->getText() );
// If the recipient is a valid non-anonymous user and hasn't turned
// off their notifications, generate a talk page post Echo notification.
- if ( $notifyUser && $notifyUser->getID() ) {
- // if this is a minor edit, only notify if the agent doesn't have talk page minor edit notification blocked
+ if ( $notifyUser && $notifyUser->getId() ) {
+ // If this is a minor edit, only notify if the agent doesn't have talk page minor
+ // edit notification blocked
if ( !$revision->isMinor() || !$user->isAllowed( 'nominornewtalk' ) ) {
$section = self::detectSectionTitleAndText( $interpretation, $title );
if ( $section['section-text'] === '' ) {
$section['section-text'] = $revision->getComment();
}
- EchoEvent::create( array(
+ EchoEvent::create( [
'type' => 'edit-user-talk',
'title' => $title,
- 'extra' => array(
- 'revid' => $revision->getID(),
+ 'extra' => [
+ 'revid' => $revision->getId(),
'minoredit' => $revision->isMinor(),
'section-title' => $section['section-title'],
- 'section-text' => $section['section-text']
- ),
+ 'section-text' => $section['section-text'],
+ 'target-page' => $title->getArticleID(),
+ ],
'agent' => $user,
- ) );
+ ] );
}
}
}
@@ -76,7 +100,7 @@ abstract class EchoDiscussionParser {
/**
* Attempts to determine what section title the edit was performed under (if any)
*
- * @param $interpretation array Results of self::getChangeInterpretationForRevision
+ * @param array $interpretation Results of self::getChangeInterpretationForRevision
* @return array Array containing section title and text
* @param Title $title
*/
@@ -85,21 +109,25 @@ abstract class EchoDiscussionParser {
$header = $snippet = '';
$found = false;
+ StubObject::unstub( $wgLang );
+
foreach ( $interpretation as $action ) {
- switch( $action['type'] ) {
+ switch ( $action['type'] ) {
case 'add-comment':
- $header = self::extractHeader( $action['full-section'] );
+ $header = self::extractHeader( $action['full-section'] );
$snippet = self::getTextSnippet(
- self::stripSignature( self::stripHeader( $action['content'] ), $title ),
- $wgLang,
- 150 );
+ self::stripSignature( self::stripHeader( $action['content'] ), $title ),
+ $wgLang,
+ 150,
+ $title );
break;
case 'new-section-with-comment':
- $header = self::extractHeader( $action['content'] );
+ $header = self::extractHeader( $action['content'] );
$snippet = self::getTextSnippet(
- self::stripSignature( self::stripHeader( $action['content'] ), $title ),
- $wgLang,
- 150 );
+ self::stripSignature( self::stripHeader( $action['content'] ), $title ),
+ $wgLang,
+ 150,
+ $title );
break;
}
if ( $header ) {
@@ -113,72 +141,230 @@ abstract class EchoDiscussionParser {
}
}
if ( $found === false ) {
- return array( 'section-title' => '', 'section-text' => '' );
+ return [ 'section-title' => '', 'section-text' => '' ];
}
- return array( 'section-title' => $header, 'section-text' => $snippet );
+
+ return [ 'section-title' => $header, 'section-text' => $snippet ];
}
/**
* For an action taken on a talk page, notify users whose user pages
* are linked.
- * @param $header string The subject line for the discussion.
- * @param $content string The content of the post, as a wikitext string.
- * @param $revision Revision object.
- * @param $agent User The user who made the comment.
+ * @param string $header The subject line for the discussion.
+ * @param array $userLinks
+ * @param string $content The content of the post, as a wikitext string.
+ * @param Revision $revision
+ * @param User $agent The user who made the comment.
*/
- public static function generateMentionEvents( $header, $content, $revision, $agent ) {
+ public static function generateMentionEvents(
+ $header,
+ $userLinks,
+ $content,
+ Revision $revision,
+ User $agent
+ ) {
+ global $wgEchoMaxMentionsCount, $wgEchoMentionStatusNotifications;
+
$title = $revision->getTitle();
if ( !$title ) {
return;
}
+ $content = self::stripHeader( $content );
+ $content = self::stripSignature( $content, $title );
- $output = self::parseNonEditWikitext( $content, new Article( $title ) );
- $links = $output->getLinks();
+ if ( !$userLinks ) {
+ return;
+ }
- if ( !isset( $links[NS_USER] ) || !is_array( $links[NS_USER] ) ) {
+ $userMentions = self::getUserMentions( $title, $revision->getUser( Revision::RAW ), $userLinks );
+ $overallMentionsCount = self::getOverallUserMentionsCount( $userMentions );
+ if ( $overallMentionsCount === 0 ) {
return;
}
- $mentionedUsers = array();
+
+ $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
+
+ if ( $overallMentionsCount > $wgEchoMaxMentionsCount ) {
+ if ( $wgEchoMentionStatusNotifications ) {
+ EchoEvent::create( [
+ 'type' => 'mention-failure-too-many',
+ 'title' => $title,
+ 'extra' => [
+ 'max-mentions' => $wgEchoMaxMentionsCount,
+ 'section-title' => $header,
+ 'notifyAgent' => true
+ ],
+ 'agent' => $agent,
+ ] );
+ $stats->increment( 'echo.event.mention.notification.failure-too-many' );
+ }
+ return;
+ }
+
+ if ( $userMentions['validMentions'] ) {
+ EchoEvent::create( [
+ 'type' => 'mention',
+ 'title' => $title,
+ 'extra' => [
+ 'content' => $content,
+ 'section-title' => $header,
+ 'revid' => $revision->getId(),
+ 'mentioned-users' => $userMentions['validMentions'],
+ ],
+ 'agent' => $agent,
+ ] );
+ }
+
+ if ( $wgEchoMentionStatusNotifications ) {
+ // TODO batch?
+ foreach ( $userMentions['validMentions'] as $mentionedUserId ) {
+ EchoEvent::create( [
+ 'type' => 'mention-success',
+ 'title' => $title,
+ 'extra' => [
+ 'subject-name' => User::newFromId( $mentionedUserId )->getName(),
+ 'section-title' => $header,
+ 'revid' => $revision->getId(),
+ 'notifyAgent' => true
+ ],
+ 'agent' => $agent,
+ ] );
+ $stats->increment( 'echo.event.mention.notification.success' );
+ }
+
+ // TODO batch?
+ foreach ( $userMentions['anonymousUsers'] as $anonymousUser ) {
+ EchoEvent::create( [
+ 'type' => 'mention-failure',
+ 'title' => $title,
+ 'extra' => [
+ 'failure-type' => 'user-anonymous',
+ 'subject-name' => $anonymousUser,
+ 'section-title' => $header,
+ 'revid' => $revision->getId(),
+ 'notifyAgent' => true
+ ],
+ 'agent' => $agent,
+ ] );
+ $stats->increment( 'echo.event.mention.notification.failure-user-anonymous' );
+ }
+
+ // TODO batch?
+ foreach ( $userMentions['unknownUsers'] as $unknownUser ) {
+ EchoEvent::create( [
+ 'type' => 'mention-failure',
+ 'title' => $title,
+ 'extra' => [
+ 'failure-type' => 'user-unknown',
+ 'subject-name' => $unknownUser,
+ 'section-title' => $header,
+ 'revid' => $revision->getId(),
+ 'notifyAgent' => true
+ ],
+ 'agent' => $agent,
+ ] );
+ $stats->increment( 'echo.event.mention.notification.failure-user-unknown' );
+ }
+ }
+ }
+
+ private static function getOverallUserMentionsCount( $userMentions ) {
+ return count( $userMentions, COUNT_RECURSIVE ) - count( $userMentions );
+ }
+
+ /**
+ * @return array[]
+ * Set of arrays containing valid mentions and possible intended but failed mentions.
+ * - [validMentions]: An array of valid users to mention with ID => ID.
+ * - [unknownUsers]: An array of DBKey strings representing unknown users.
+ * - [anonymousUsers]: An array of DBKey strings representing anonymous IP users.
+ */
+ private static function getUserMentions( Title $title, $revisionUserId, array $userLinks ) {
+ global $wgEchoMaxMentionsCount;
+ $userMentions = [
+ 'validMentions' => [],
+ 'unknownUsers' => [],
+ 'anonymousUsers' => [],
+ ];
+
$count = 0;
+ $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
- foreach ( $links[NS_USER] as $dbk => $page_id ) {
- $user = User::newFromName( $dbk );
+ foreach ( $userLinks as $dbk => $page_id ) {
+ // If more users are being pinged this is likely a spam/attack vector
+ // Don't send any mention notifications.
+ if ( $count > $wgEchoMaxMentionsCount ) {
+ $stats->increment( 'echo.event.mention.error.tooMany' );
+ break;
+ }
// we should not add user to 'mention' notification list if
- // 1. the user name is not valid
- // 2. the user mentions themselves
- // 3. the user is the owner of the talk page
- // 4. user is anonymous
- if (
- !$user || $user->isAnon() || $user->getId() == $revision->getUser() ||
- ( $title->getNamespace() === NS_USER_TALK && $title->getDBkey() === $dbk )
- ) {
+ // 1. the user link links to a subpage
+ if ( self::hasSubpage( $dbk ) ) {
continue;
}
- $mentionedUsers[$user->getId()] = $user->getId();
- $count++;
- // If more than 50 users are being pinged this is likely a spam/attack vector
- // Don't send any mention notifications.
- if ( $count > 50 ) {
- return;
+
+ // 2. user is an anonymous IP
+ if ( User::isIP( $dbk ) ) {
+ $userMentions['anonymousUsers'][] = $dbk;
+ $count++;
+ $stats->increment( 'echo.event.mention.error.anonUser' );
+ continue;
+ }
+
+ $user = User::newFromName( $dbk );
+ // 3. the user name is not valid
+ if ( !$user ) {
+ $userMentions['unknownUsers'][] = str_replace( '_', ' ', $dbk );
+ $count++;
+ $stats->increment( 'echo.event.mention.error.invalidUser' );
+ continue;
+ }
+
+ // 4. the user mentions themselves
+ if ( $user->getId() === $revisionUserId ) {
+ $stats->increment( 'echo.event.mention.error.sameUser' );
+ continue;
+ }
+
+ // 5. the user is the owner of the talk page
+ if ( $title->getNamespace() === NS_USER_TALK && $title->getDBkey() === $dbk ) {
+ $stats->increment( 'echo.event.mention.error.ownPage' );
+ continue;
}
+
+ // 6. user does not exist
+ if ( $user->getId() === 0 ) {
+ $userMentions['unknownUsers'][] = str_replace( '_', ' ', $dbk );
+ $count++;
+ $stats->increment( 'echo.event.mention.error.unknownUser' );
+ continue;
+ }
+
+ $userMentions['validMentions'][$user->getId()] = $user->getId();
+ $count++;
}
- if ( !$mentionedUsers ) {
- return;
+ return $userMentions;
+ }
+
+ /**
+ * @return bool|array
+ * Array of links in the user namespace with DBKey => ID.
+ */
+ private static function getUserLinks( $content, Title $title ) {
+ $output = self::parseNonEditWikitext( $content, new Article( $title ) );
+ $links = $output->getLinks();
+
+ if ( !isset( $links[NS_USER] ) || !is_array( $links[NS_USER] ) ) {
+ return false;
}
- EchoEvent::create( array(
- 'type' => 'mention',
- 'title' => $title,
- 'extra' => array(
- 'content' => $content,
- 'section-title' => $header,
- 'revid' => $revision->getId(),
- 'mentioned-users' => $mentionedUsers,
- ),
- 'agent' => $agent,
- ) );
+ return $links[NS_USER];
+ }
+
+ private static function hasSubpage( $dbk ) {
+ return strpos( $dbk, '/' ) !== false;
}
/**
@@ -186,13 +372,13 @@ abstract class EchoDiscussionParser {
* but not for editing (old wikitext usually)
* Stolen from AbuseFilterVariableHolder
*
- * @param $wikitext String
- * @param $article Article
+ * @param string $wikitext
+ * @param Article $article
*
* @return ParserOutput
*/
- static function parseNonEditWikitext( $wikitext, $article ) {
- static $cache = array();
+ static function parseNonEditWikitext( $wikitext, Article $article ) {
+ static $cache = [];
$cacheKey = md5( $wikitext ) . ':' . $article->getTitle()->getPrefixedText();
@@ -213,13 +399,13 @@ abstract class EchoDiscussionParser {
* Given a Revision object, returns a talk-page-centric interpretation
* of the changes made in it.
*
- * @param $revision Revision object
+ * @param Revision $revision
* @see EchoDiscussionParser::interpretDiff
- * @return Array, see interpretDiff for details.
+ * @return array see interpretDiff for details.
*/
- static function getChangeInterpretationForRevision( $revision ) {
- if ( $revision->getID() && isset( self::$revisionInterpretationCache[$revision->getID()] ) ) {
- return self::$revisionInterpretationCache[$revision->getID()];
+ static function getChangeInterpretationForRevision( Revision $revision ) {
+ if ( $revision->getId() && isset( self::$revisionInterpretationCache[$revision->getId()] ) ) {
+ return self::$revisionInterpretationCache[$revision->getId()];
}
$userID = $revision->getUser();
@@ -229,14 +415,18 @@ abstract class EchoDiscussionParser {
if ( $revision->getParentId() ) {
$prevRevision = Revision::newFromId( $revision->getParentId() );
if ( $prevRevision ) {
- $prevText = $prevRevision->getText();
+ $prevText = ContentHandler::getContentText( $prevRevision->getContent() );
}
}
- $changes = self::getMachineReadableDiff( $prevText, $revision->getText() );
+ $changes = self::getMachineReadableDiff(
+ $prevText,
+ ContentHandler::getContentText( $revision->getContent() )
+ );
$output = self::interpretDiff( $changes, $user->getName(), $revision->getTitle() );
- self::$revisionInterpretationCache[$revision->getID()] = $output;
+ self::$revisionInterpretationCache[$revision->getId()] = $output;
+
return $output;
}
@@ -245,10 +435,12 @@ abstract class EchoDiscussionParser {
* in terms of discussion page actions
*
* @todo Expand recognisable actions.
+ *
* @param array $changes Output of EchoEvent::getMachineReadableDiff
- * @param string $user Username
+ * @param string $username Username
* @param Title $title
- * @return Array of associative arrays.
+ * @return array[] Array of associative arrays.
+ *
* Each entry represents an action, which is classified in the 'action' field.
* All types contain a 'content' field except 'unknown'
* (which instead passes through the machine-readable diff in 'details')
@@ -258,9 +450,8 @@ abstract class EchoDiscussionParser {
* existing section.
* - new-section-with-comment: A new section is added, containing
* a single comment signed by the user in question.
- * - unknown-signed-addition: Some signed content is added, but it
- * includes section headers, is signed by another user or
- * otherwise confuses the interpretation engine.
+ * - add-section-multiple: A new section or additions to a section
+ * while editing multiple sections at once.
* - unknown-multi-signed-addition: Some signed content is added,
* but it contains multiple signatures.
* - unknown-unsigned-addition: Some content is added, but it is
@@ -268,12 +459,15 @@ abstract class EchoDiscussionParser {
* - unknown-subtraction: Some content was removed. These actions are
* not currently analysed.
* - unknown-change: Some content was replaced with other content.
- * These actions are not currently analysed.
+ * - unknown-signed-change: Same as unknown-change, but signed.
+ * - unknown-multi-signed-change: Same as unknown-change,
+ * but it contains multiple signatures.
* - unknown: Unrecognised change type.
*/
- static function interpretDiff( $changes, $user, Title $title = null ) {
+ static function interpretDiff( $changes, $username, Title $title = null ) {
// One extra item in $changes for _info
- $actions = array();
+ $actions = [];
+ $signedSections = [];
foreach ( $changes as $index => $change ) {
if ( !is_numeric( $index ) ) {
@@ -287,8 +481,8 @@ abstract class EchoDiscussionParser {
if ( $change['action'] == 'add' ) {
$content = trim( $change['content'] );
- // The \A means the regex must match at the begining of the string.
- // This is slightly different than ^ which matches begining of each
+ // The \A means the regex must match at the beginning of the string.
+ // This is slightly different than ^ which matches beginning of each
// line in multiline mode.
$startSection = preg_match( "/\A" . self::HEADER_REGEX . '/um', $content );
$sectionCount = self::getSectionCount( $content );
@@ -296,112 +490,214 @@ abstract class EchoDiscussionParser {
if (
count( $signedUsers ) == 1 &&
- in_array( $user, $signedUsers )
+ in_array( $username, $signedUsers )
) {
if ( $sectionCount === 0 ) {
+ $signedSections[] = self::getSectionSpan( $change['right-pos'], $changes['_info']['rhs'] );
$fullSection = self::getFullSection( $changes['_info']['rhs'], $change['right-pos'] );
- $actions[] = array(
+ $actions[] = [
'type' => 'add-comment',
'content' => $content,
'full-section' => $fullSection,
- );
+ ];
} elseif ( $startSection && $sectionCount === 1 ) {
- $actions[] = array(
+ $signedSections[] = self::getSectionSpan( $change['right-pos'], $changes['_info']['rhs'] );
+ $actions[] = [
'type' => 'new-section-with-comment',
'content' => $content,
- );
+ ];
} else {
- $actions[] = array(
- 'type' => 'unknown-signed-addition',
- 'content' => $content,
- );
+ $nextSectionStart = $change['right-pos'];
+ $sectionData = self::extractSections( $content );
+ foreach ( $sectionData as $section ) {
+ $sectionSpan = self::getSectionSpan( $nextSectionStart, $changes['_info']['rhs'] );
+ $nextSectionStart = $sectionSpan[1] + 1;
+ $sectionSignedUsers = self::extractSignatures( $section['content'], $title );
+ if ( !empty( $sectionSignedUsers ) ) {
+ $signedSections[] = $sectionSpan;
+ if ( !$section['header'] ) {
+ $fullSection = self::getFullSection( $changes['_info']['rhs'], $change['right-pos'] );
+ $section['header'] = self::extractHeader( $fullSection );
+ }
+ $actions[] = [
+ 'type' => 'add-section-multiple',
+ 'content' => $section['content'],
+ 'header' => $section['header'],
+ ];
+ } else {
+ $actions[] = [
+ 'type' => 'unknown-unsigned-addition',
+ 'content' => $section['content'],
+ ];
+ }
+ }
}
} elseif ( count( $signedUsers ) >= 1 ) {
- $actions[] = array(
+ $actions[] = [
'type' => 'unknown-multi-signed-addition',
'content' => $content,
- );
+ ];
} else {
- $actions[] = array(
+ $actions[] = [
'type' => 'unknown-unsigned-addition',
'content' => $content,
- );
+ ];
}
} elseif ( $change['action'] == 'subtract' ) {
- $actions[] = array(
+ $actions[] = [
'type' => 'unknown-subtraction',
'content' => $change['content'],
- );
+ ];
} elseif ( $change['action'] == 'change' ) {
- $actions[] = array(
+ $actions[] = [
'type' => 'unknown-change',
'old_content' => $change['old_content'],
'new_content' => $change['new_content'],
- );
+ 'right-pos' => $change['right-pos'],
+ 'full-section' => self::getFullSection( $changes['_info']['rhs'], $change['right-pos'] ),
+ ];
+
+ if ( self::hasNewSignature(
+ $change['old_content'],
+ $change['new_content'],
+ $username,
+ $title
+ ) ) {
+ $signedSections[] = self::getSectionSpan( $change['right-pos'], $changes['_info']['rhs'] );
+ }
} else {
- $actions[] = array(
+ $actions[] = [
'type' => 'unknown',
'details' => $change,
- );
+ ];
}
}
- // $actions['_diff'] = $changes;
- // unset( $actions['_diff']['_info'] );
+ if ( !empty( $signedSections ) ) {
+ $actions = self::convertToUnknownSignedChanges( $signedSections, $actions );
+ }
return $actions;
}
+ static function getSignedUsers( $content, $title ) {
+ return array_keys( self::extractSignatures( $content, $title ) );
+ }
+
+ static function hasNewSignature( $oldContent, $newContent, $username, $title ) {
+ $oldSignedUsers = self::getSignedUsers( $oldContent, $title );
+ $newSignedUsers = self::getSignedUsers( $newContent, $title );
+
+ return !in_array( $username, $oldSignedUsers ) && in_array( $username, $newSignedUsers );
+ }
+
+ /**
+ * Converts actions of type "unknown-change" to "unknown-signed-change" if the change is in a signed section.
+ *
+ * @param array $signedSections Array of arrays containing first and last line number of signed sections
+ * @param array $actions
+ * @return array converted actions
+ */
+ static function convertToUnknownSignedChanges( $signedSections, $actions ) {
+ return array_map( function ( $action ) use( $signedSections ) {
+ if (
+ $action['type'] === 'unknown-change' &&
+ self::isInSignedSection( $action['right-pos'], $signedSections )
+ ) {
+ $signedUsers = self::getSignedUsers( $action['new_content'], null );
+ if ( count( $signedUsers ) === 1 ) {
+ $action['type'] = 'unknown-signed-change';
+ } else {
+ $action['type'] = 'unknown-multi-signed-change';
+ }
+ }
+
+ return $action;
+ }, $actions );
+ }
+
+ static function isInSignedSection( $line, $signedSections ) {
+ foreach ( $signedSections as $section ) {
+ if ( $line > $section[0] && $line <= $section[1] ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Finds the section that a given line is in.
*
- * @param $lines Array of lines in the page.
- * @param $offset int The line to find the full section for.
+ * @param array $lines of lines in the page.
+ * @param int $offset The line to find the full section for.
* @return string Content of the section.
*/
- static function getFullSection( $lines, $offset ) {
- $content = $lines[$offset - 1];
- $headerRegex = '/' . self::HEADER_REGEX . '/um';
-
- // Expand backwards...
- $continue = !preg_match( $headerRegex, $lines[$offset - 1] );
- $i = $offset - 1;
- while ( $continue && $i > 0 ) {
- --$i;
- $line = $lines[$i];
- $content = "$line\n$content";
- if ( preg_match( $headerRegex, $line ) ) {
- $continue = false;
+ static function getFullSection( array $lines, $offset ) {
+ $start = self::getSectionStartIndex( $offset, $lines );
+ $end = self::getSectionEndIndex( $offset, $lines );
+ $content = implode( "\n", array_slice( $lines, $start, $end - $start ) );
+
+ return trim( $content, "\n" );
+ }
+
+ /**
+ * Given a line number and a text, find the first and last line of the section the line number is in.
+ * If there are subsections, the last line index will be the line before the beginning of the first subsection.
+ * @param $offset line number
+ * @param $lines
+ * @return array tuple [$firstLine, $lastLine]
+ */
+ static function getSectionSpan( $offset, $lines ) {
+ return [
+ self::getSectionStartIndex( $offset, $lines ),
+ self::getSectionEndIndex( $offset, $lines )
+ ];
+ }
+
+ /**
+ * Finds the line number of the start of the section that $offset is in.
+ * @param int $offset
+ * @param array $lines
+ * @return int
+ */
+ static function getSectionStartIndex( $offset, array $lines ) {
+ for ( $i = $offset - 1; $i >= 0; $i-- ) {
+ if ( self::getSectionCount( $lines[$i] ) ) {
+ break;
}
}
- // And then forwards...
+ return $i;
+ }
- $continue = true;
- $i = $offset - 1;
- while ( $continue && $i < count( $lines ) - 1 ) {
- ++$i;
- $line = $lines[$i];
- if ( preg_match( $headerRegex, $line ) ) {
- $continue = false;
- } else {
- $content .= "\n$line";
+ /**
+ * Finds the line number of the end of the section that $offset is in.
+ * @param int $offset
+ * @param array $lines
+ * @return int
+ */
+ static function getSectionEndIndex( $offset, array $lines ) {
+ $lastLine = count( $lines );
+ for ( $i = $offset; $i < $lastLine; $i++ ) {
+ if ( self::getSectionCount( $lines[$i] ) ) {
+ break;
}
}
- return trim( $content, "\n" );
+ return $i;
}
/**
* Gets the number of section headers in a string.
*
- * @param $text string The text.
+ * @param string $text The text.
* @return int Number of section headers found.
*/
static function getSectionCount( $text ) {
$text = trim( $text );
- $matches = array();
+ $matches = [];
preg_match_all( '/' . self::HEADER_REGEX . '/um', $text, $matches );
return count( $matches[0] );
@@ -410,13 +706,13 @@ abstract class EchoDiscussionParser {
/**
* Gets the title of a section or sub section
*
- * @param $text string The text of the section.
- * @return string The title of the section.
+ * @param string $text The text of the section.
+ * @return string|false The title of the section or false if not found
*/
static function extractHeader( $text ) {
$text = trim( $text );
- $matches = array();
+ $matches = [];
if ( !preg_match_all( '/' . self::HEADER_REGEX . '/um', $text, $matches ) ) {
return false;
@@ -426,9 +722,52 @@ abstract class EchoDiscussionParser {
}
/**
+ * Extracts sections and their contents from text.
+ *
+ * @param string $text The text to parse.
+ * @return array[]
+ * Array of arrays containing sections with header and content.
+ * - [header]: The full header string of the section or false if there is preceding text without header.
+ * - [content]: The content of the section including the header string.
+ */
+ private static function extractSections( $text ) {
+ $matches = [];
+
+ if ( !preg_match_all( '/' . self::HEADER_REGEX . '/um', $text, $matches, PREG_OFFSET_CAPTURE ) ) {
+ return [ [
+ 'header' => false,
+ 'content' => $text
+ ] ];
+ }
+
+ $sectionNum = count( $matches[0] );
+ $sections = [];
+
+ if ( $matches[0][0][1] > 1 ) { // is there text before the first headline?
+ $sections[] = [
+ 'header' => false,
+ 'content' => substr( $text, 0, $matches[0][0][1] - 1 )
+ ];
+ }
+ for ( $i = 0; $i < $sectionNum; $i++ ) {
+ if ( $i + 1 < $sectionNum ) {
+ $content = substr( $text, $matches[0][$i][1], $matches[0][$i + 1][1] - $matches[0][$i][1] );
+ } else {
+ $content = substr( $text, $matches[0][$i][1] );
+ }
+ $sections[] = [
+ 'header' => self::extractHeader( $matches[0][$i][0] ),
+ 'content' => trim( $content )
+ ];
+ }
+
+ return $sections;
+ }
+
+ /**
* Strips out a signature if possible.
*
- * @param $text string The wikitext to strip
+ * @param string $text The wikitext to strip
* @param Title $title
* @return string
*/
@@ -436,41 +775,21 @@ abstract class EchoDiscussionParser {
$output = self::getUserFromLine( $text, $title );
if ( $output === false ) {
$timestampPos = self::getTimestampPosition( $text );
+
return substr( $text, 0, $timestampPos );
}
// Use truncate() instead of truncateHTML() because truncateHTML()
// would not strip signature if the text contains < or &
global $wgContLang;
- return $wgContLang->truncate( $text, $output[0], '' );
- }
-
- /**
- * Strips unnecessary indentation and so on from comments
- *
- * @param $text string The text to strip from
- * @return string Stripped wikitext
- */
- static function stripIndents( $text ) {
- // First strip all indentation from the beginning of lines
- $text = preg_replace( '/^\s*\:+/m', '', $text );
-
- // Now if there is only one list item, strip that too
- $listRegex = '/^\s*(?:[\:#*]\s*)*[#*]/m';
- $matches = array();
- if ( preg_match_all( $listRegex, $text, $matches ) ) {
- if ( count( $matches ) == 1 ) {
- $text = preg_replace( $listRegex, '', $text );
- }
- }
- return $text;
+ return $wgContLang->truncate( $text, $output[0], '' );
}
/**
* Strips out a section header
- * @param $text string The text to strip out the section header from.
- * @return string: The same text, with the section header stripped out.
+ * @param string $text The text to strip out the section header from.
+ * @return string The same text, with the section header stripped out.
*/
static function stripHeader( $text ) {
$text = preg_replace( '/' . self::HEADER_REGEX . '/um', '', $text );
@@ -481,11 +800,11 @@ abstract class EchoDiscussionParser {
/**
* Determines whether the input is a signed comment.
*
- * @param $text string The text to check.
- * @param $user User|bool If set, will only return true if the comment is
+ * @param string $text The text to check.
+ * @param User|bool $user If set, will only return true if the comment is
* signed by this user.
* @param Title $title
- * @return bool: true or false.
+ * @return bool
*/
static function isSignedComment( $text, $user = false, Title $title = null ) {
$userData = self::getUserFromLine( $text, $title );
@@ -504,13 +823,13 @@ abstract class EchoDiscussionParser {
/**
* Finds the start position, if any, of the timestamp on a line
*
- * @param $line string The line to search for a signature on
+ * @param string $line The line to search for a signature on
* @return int|bool Integer position
*/
static function getTimestampPosition( $line ) {
$timestampRegex = self::getTimestampRegex();
$endOfLine = self::getLineEndingRegex();
- $tsMatches = array();
+ $tsMatches = [];
if ( !preg_match(
"/$timestampRegex$endOfLine/mu",
$line,
@@ -527,10 +846,10 @@ abstract class EchoDiscussionParser {
* Finds differences between $oldText and $newText
* and returns the result in a machine-readable format.
*
- * @param $oldText string The "left hand side" of the diff.
- * @param $newText string The "right hand side" of the diff.
+ * @param string $oldText The "left hand side" of the diff.
+ * @param string $newText The "right hand side" of the diff.
* @throws MWException
- * @return Array of changes.
+ * @return array of changes.
* Each change consists of:
* * An 'action', one of:
* - add
@@ -544,21 +863,22 @@ abstract class EchoDiscussionParser {
if ( !isset( self::$diffParser ) ) {
self::$diffParser = new EchoDiffParser;
}
+
return self::$diffParser->getChangeSet( $oldText, $newText );
}
/**
* Finds and extracts signatures in $text
*
- * @param $text string The text in which to look for signed comments.
+ * @param string $text The text in which to look for signed comments.
* @param Title $title
- * @return array. Associative array, the key is the username, the value
+ * @return array Associative array, the key is the username, the value
* is the last signature that was found.
*/
static function extractSignatures( $text, Title $title = null ) {
$lines = explode( "\n", $text );
- $output = array();
+ $output = [];
$lineNumber = 0;
@@ -588,23 +908,22 @@ abstract class EchoDiscussionParser {
*
* @param string $line Line of text potentially including linked user, user talk,
* and contribution pages
- * @return array Array of users; empty array for none detected
+ * @return array of usernames, empty array for none detected
*/
- static public function extractUsersFromLine( $line ) {
+ public static function extractUsersFromLine( $line ) {
/*
* Signatures can look like anything (as defined by i18n messages
* "signature" & "signature-anon").
* A signature can, e.g., be both a link to user & user-talk page.
- *
*/
// match all title-like excerpts in this line
if ( !preg_match_all( '/\[\[([^\[]+)\]\]/', $line, $matches ) ) {
- return array();
+ return [];
}
$matches = $matches[1];
- $usernames = array();
+ $usernames = [];
foreach ( $matches as $match ) {
/*
@@ -619,7 +938,10 @@ abstract class EchoDiscussionParser {
$title = Title::newFromText( $match[0] );
// figure out if we the link is related to a user
- if ( $title && ( $title->getNamespace() === NS_USER || $title->getNamespace() === NS_USER_TALK ) ) {
+ if (
+ $title &&
+ ( $title->getNamespace() === NS_USER || $title->getNamespace() === NS_USER_TALK )
+ ) {
$usernames[] = $title->getText();
} elseif ( $title && $title->isSpecial( 'Contributions' ) ) {
$parts = explode( '/', $title->getText(), 2 );
@@ -643,7 +965,7 @@ abstract class EchoDiscussionParser {
* - First element is the position of the signature.
* - Second element is the normalised user name.
*/
- static public function getUserFromLine( $line, Title $title = null ) {
+ public static function getUserFromLine( $line, Title $title = null ) {
global $wgParser;
/*
@@ -659,14 +981,18 @@ abstract class EchoDiscussionParser {
// discovered the signature from
// don't validate the username - anon (IP) is fine!
$user = User::newFromName( $username, false );
- $sig = $wgParser->preSaveTransform( '~~~', $title ?: Title::newMainPage(), $user, new ParserOptions() );
+ $sig = $wgParser->preSaveTransform(
+ '~~~',
+ $title ?: Title::newMainPage(),
+ $user,
+ new ParserOptions()
+ );
// see if we can find this user's generated signature in the content
$pos = strrpos( $line, $sig );
if ( $pos !== false ) {
- return array( $pos, $username );
+ return [ $pos, $username ];
}
-
// couldn't find sig, move on to next link excerpt and try there
}
@@ -677,10 +1003,10 @@ abstract class EchoDiscussionParser {
/**
* Find the last link beginning with a given prefix on a line.
*
- * @param $line string The line to search.
- * @param $linkPrefix string The prefix to search for.
- * @param $failureOffset bool
- * @return bool false for failure, array for success.
+ * @param string $line The line to search.
+ * @param string $linkPrefix The prefix to search for.
+ * @param bool $failureOffset
+ * @return array|bool false for failure, array for success.
* - First element is the string offset of the link.
* - Second element is the user the link refers to.
*/
@@ -711,22 +1037,22 @@ abstract class EchoDiscussionParser {
// Look for another place.
return self::getLinkFromLine( $line, $linkPrefix, $linkPos );
} else {
- return array( $linkPos, $linkUser );
+ return [ $linkPos, $linkUser ];
}
}
/**
* Given text including a link, gives the user that that link refers to
*
- * @param $text string The text to extract from.
- * @param $prefix string The link prefix that was used to find the link.
- * @param $offset int Optionally, the offset of the start of the link.
+ * @param string $text The text to extract from.
+ * @param string $prefix The link prefix that was used to find the link.
+ * @param int $offset Optionally, the offset of the start of the link.
* @return bool|string Type description
*/
static function extractUserFromLink( $text, $prefix, $offset = 0 ) {
$userPart = substr( $text, strlen( $prefix ) + $offset );
- $userMatches = array();
+ $userMatches = [];
if ( !preg_match(
'/^[^\|\]\#]+/u',
$userPart,
@@ -756,16 +1082,16 @@ abstract class EchoDiscussionParser {
* Gets a regular expression fragmentmatching characters that
* can appear in a line after the signature.
*
- * @return String regular expression fragment.
+ * @return string regular expression fragment.
*/
static function getLineEndingRegex() {
- $ignoredEndings = array(
+ $ignoredEndings = [
'\s*',
preg_quote( '}' ),
preg_quote( '{' ),
'\<[^\>]+\>',
preg_quote( '{{' ) . '[^}]+' . preg_quote( '}}' ),
- );
+ ];
$regex = '(?:' . implode( '|', $ignoredEndings ) . ')*';
@@ -777,7 +1103,7 @@ abstract class EchoDiscussionParser {
* timestamps as given by ~~~~.
*
* @throws MWException
- * @return String regular expression fragment.
+ * @return string regular expression fragment.
*/
static function getTimestampRegex() {
if ( self::$timestampRegex !== null ) {
@@ -797,7 +1123,7 @@ abstract class EchoDiscussionParser {
// Trim off the timezone to replace at the end
$output = $exemplarTimestamp;
$tzRegex = '/\s*\(\w+\)\s*$/';
- $tzMatches = array();
+ $tzMatches = [];
if ( preg_match( $tzRegex, $output, $tzMatches ) ) {
$output = preg_replace( $tzRegex, '', $output );
}
@@ -819,49 +1145,45 @@ abstract class EchoDiscussionParser {
}
/**
- * This function returns plain text snippet, it also removes html tag,
- * template from text content
- * @param $text string
+ * Parse wikitext into truncated plain text.
+ * @param string $text
* @param Language $lang
- * @param $length int default 150
+ * @param int $length default 150
+ * @param Title|null $title Page from which the text snippet is being extracted
* @return string
*/
- static function getTextSnippet( $text, Language $lang, $length = 150 ) {
- $text = strip_tags( $text );
- $attempt = 0;
-
- // 10 attempts at most, the logic here is to find the first }} and
- // find the matching {{ for that }}
- while ( $attempt < 10 ) {
- $closeCurPos = strpos( $text, '}}' );
-
- if ( $closeCurPos === false ) {
- break;
- }
- $tempStr = substr( $text, 0, $closeCurPos + 2 );
-
- $openCurPos = strrpos( $tempStr, '{{' );
- if ( $openCurPos === false ) {
- $text = substr_replace( $text, '', $closeCurPos, 2 );
- } else {
- $text = substr_replace( $text, '', $openCurPos, $closeCurPos - $openCurPos + 2 );
- }
- $attempt++;
- }
-
- // See Parser::parse() function, &#160; is replaced specifically, replace it back here
- // with a space as this html entity won't be handled by htmlspecialchars_decode()
- $text = str_replace( '&#160;', ' ', MessageCache::singleton()->parse( $text )->getText() );
- $text = trim( strip_tags( htmlspecialchars_decode( $text ) ) );
- // strip out non-useful data for snippet
- $text = str_replace( array( '{', '}' ), '', $text );
- $text = $lang->truncate( $text, $length );
+ static function getTextSnippet( $text, Language $lang, $length = 150, $title = null ) {
+ // Parse wikitext
+ $html = MessageCache::singleton()->parse( $text, $title )->getText();
+ $plaintext = trim( Sanitizer::stripAllTags( $html ) );
+ return $lang->truncate( $plaintext, $length );
+ }
- // Return empty string if there is undecoded char left
- if ( strpos( $text, '&#' ) !== false ) {
- $text = '';
- }
+ /**
+ * Parse an edit summary into truncated plain text.
+ * @param string $text
+ * @param Language $lang
+ * @param int $length default 150
+ * @return string
+ */
+ static function getTextSnippetFromSummary( $text, Language $lang, $length = 150 ) {
+ // Parse wikitext with summary parser
+ $html = Linker::formatLinksInComment( Sanitizer::escapeHtmlAllowEntities( $text ) );
+ $plaintext = trim( Sanitizer::stripAllTags( $html ) );
+ return $lang->truncate( $plaintext, $length );
+ }
- return $text;
+ /**
+ * Extract an edit excerpt from a revision
+ *
+ * @param Revision $revision
+ * @param Language $lang
+ * @param int $length
+ * @return string
+ */
+ public static function getEditExcerpt( Revision $revision, Language $lang, $length = 150 ) {
+ $interpretation = self::getChangeInterpretationForRevision( $revision );
+ $section = self::detectSectionTitleAndText( $interpretation );
+ return $lang->truncate( $section['section-title'] . ' ' . $section['section-text'], $length );
}
}
diff --git a/Echo/includes/EchoDbFactory.php b/Echo/includes/EchoDbFactory.php
index e908e658..12012632 100644
--- a/Echo/includes/EchoDbFactory.php
+++ b/Echo/includes/EchoDbFactory.php
@@ -1,4 +1,5 @@
<?php
+use MediaWiki\MediaWikiServices;
/**
* Database factory class, this will determine whether to use the main database
@@ -7,24 +8,24 @@
class MWEchoDbFactory {
/**
- * The wiki to access the database for
- * @var string|bool
- */
- protected $wiki;
-
- /**
* The cluster for the database
* @var string|bool
*/
- protected $cluster;
+ private $cluster;
+
+ private $shared;
+
+ private $sharedCluster;
/**
- * @param string|bool
- * @param string|bool
+ * @param string|bool $cluster
+ * @param string|bool $shared
+ * @param string|bool $sharedCluster
*/
- public function __construct( $cluster = false, $wiki = false ) {
+ public function __construct( $cluster = false, $shared = false, $sharedCluster = false ) {
$this->cluster = $cluster;
- $this->wiki = $wiki;
+ $this->shared = $shared;
+ $this->sharedCluster = $sharedCluster;
}
/**
@@ -35,21 +36,34 @@ class MWEchoDbFactory {
* @return MWEchoDbFactory
*/
public static function newFromDefault() {
- global $wgEchoCluster;
- return new self( $wgEchoCluster );
+ global $wgEchoCluster, $wgEchoSharedTrackingDB, $wgEchoSharedTrackingCluster;
+
+ return new self( $wgEchoCluster, $wgEchoSharedTrackingDB, $wgEchoSharedTrackingCluster );
}
/**
* Get the database load balancer
- * @param $wiki string|bool The wiki ID, or false for the current wiki
* @return LoadBalancer
*/
protected function getLB() {
// Use the external db defined for Echo
if ( $this->cluster ) {
- $lb = wfGetLBFactory()->getExternalLB( $this->cluster, $this->wiki );
+ $lb = MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->getExternalLB( $this->cluster );
+ } else {
+ $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
+ }
+
+ return $lb;
+ }
+
+ /**
+ * @return LoadBalancer
+ */
+ protected function getSharedLB() {
+ if ( $this->sharedCluster ) {
+ $lb = MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->getExternalLB( $this->sharedCluster );
} else {
- $lb = wfGetLB( $this->wiki );
+ $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
}
return $lb;
@@ -59,10 +73,23 @@ class MWEchoDbFactory {
* Get the database connection for Echo
* @param $db int Index of the connection to get
* @param $groups mixed Query groups.
- * @return DatabaseBase
+ * @return IDatabase
+ */
+ public function getEchoDb( $db, $groups = [] ) {
+ return $this->getLB()->getConnection( $db, $groups );
+ }
+
+ /**
+ * @param $db int Index of the connection to get
+ * @param array $groups Query groups
+ * @return bool|IDatabase false if no shared db is configured
*/
- public function getEchoDb( $db, $groups = array() ) {
- return $this->getLB()->getConnection( $db, $groups, $this->wiki );
+ public function getSharedDb( $db, $groups = [] ) {
+ if ( !$this->shared ) {
+ return false;
+ }
+
+ return $this->getSharedLB()->getConnection( $db, $groups, $this->shared );
}
/**
@@ -75,20 +102,25 @@ class MWEchoDbFactory {
* @param $db int Index of the connection to get
* @param $groups mixed Query groups.
* @param $wiki string|bool The wiki ID, or false for the current wiki
- * @return DatabaseBase
+ * @return IDatabase
*/
- public static function getDB( $db, $groups = array(), $wiki = false ) {
+ public static function getDB( $db, $groups = [], $wiki = false ) {
global $wgEchoCluster;
+ $services = MediaWikiServices::getInstance();
+
// Use the external db defined for Echo
if ( $wgEchoCluster ) {
- $lb = wfGetLBFactory()->getExternalLB( $wgEchoCluster, $wiki );
+ $lb = $services->getDBLoadBalancerFactory()->getExternalLB( $wgEchoCluster, $wiki );
} else {
- $lb = wfGetLB( $wiki );
+ if ( $wiki === false ) {
+ $lb = $services->getDBLoadBalancer();
+ } else {
+ $lb = $services->getDBLoadBalancerFactory()->getMainLB( $wiki );
+ }
}
return $lb->getConnection( $db, $groups, $wiki );
-
}
/**
@@ -105,11 +137,11 @@ class MWEchoDbFactory {
* @return array
*/
public function getMasterPosition() {
- $position = array(
+ $position = [
'wikiDb' => false,
'echoDb' => false,
- );
- $lb = wfGetLB();
+ ];
+ $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
if ( $lb->getServerCount() > 1 ) {
$position['wikiDb'] = $lb->getMasterPos();
};
@@ -125,7 +157,7 @@ class MWEchoDbFactory {
}
/**
- * Recieves the output of self::getMasterPosition. Waits
+ * Receives the output of self::getMasterPosition. Waits
* for slaves to catch up to the master position at that
* point.
*
@@ -133,10 +165,18 @@ class MWEchoDbFactory {
*/
public function waitFor( array $position ) {
if ( $position['wikiDb'] ) {
- wfGetLB()->waitFor( $position['wikiDb'] );
+ MediaWikiServices::getInstance()->getDBLoadBalancer()->waitFor( $position['wikiDb'] );
}
if ( $position['echoDb'] ) {
$this->getLB()->waitFor( $position['echoDb'] );
}
}
+
+ /**
+ * Check whether it makes sense to retry a failed lookup on the master.
+ * @return bool True if there are multiple servers and changes were made in this request; false otherwise
+ */
+ public function canRetryMaster() {
+ return $this->getLB()->getServerCount() > 1 && $this->getLB()->hasOrMadeRecentMasterChanges();
+ }
}
diff --git a/Echo/includes/EmailBatch.php b/Echo/includes/EmailBatch.php
index 1802ece8..7947fda0 100644
--- a/Echo/includes/EmailBatch.php
+++ b/Echo/includes/EmailBatch.php
@@ -5,25 +5,43 @@
*/
class MWEchoEmailBatch {
- // the user to be notified
+ /**
+ * @var User the user to be notified
+ */
protected $mUser;
- // list of email content
- protected $content = array();
- // the last notification event of this batch
+ /**
+ * @var Language
+ */
+ protected $language;
+
+ /**
+ * @var EchoEvent[] events included in this email
+ */
+ protected $events = [];
+
+ /**
+ * @var EchoEvent the last notification event of this batch
+ */
protected $lastEvent;
- // the event count, this count is supported up to self::$displaySize + 1
+
+ /**
+ * @var int the event count, this count is supported up to self::$displaySize + 1
+ */
protected $count = 0;
- // number of bundle events to include in an email, we couldn't include
- // all events in a batch email
+ /**
+ * @var int number of bundle events to include in an email,
+ * we cannot include all events in a batch email
+ */
protected static $displaySize = 20;
/**
- * @param $user User
+ * @param User $user
*/
public function __construct( User $user ) {
$this->mUser = $user;
+ $this->language = wfGetLangObj( $this->mUser->getOption( 'language' ) );
}
/**
@@ -34,8 +52,8 @@ class MWEchoEmailBatch {
* 0 - instant
* 1 - once everyday
* 7 - once every 7 days
- * @param $userId int
- * @param $enforceFrequency boolean Whether or not email sending frequency should
+ * @param int $userId
+ * @param bool $enforceFrequency Whether or not email sending frequency should
* be enforced.
*
* When true, today's notifications won't be returned if they are
@@ -53,6 +71,7 @@ class MWEchoEmailBatch {
if ( $userEmailSetting == -1 ) {
$emailBatch = new self( $user );
$emailBatch->clearProcessedEvent();
+
return false;
}
@@ -97,15 +116,22 @@ class MWEchoEmailBatch {
$events = $this->getEvents();
if ( $events ) {
- foreach( $events as $row ) {
+ foreach ( $events as $row ) {
$this->count++;
if ( $this->count > self::$displaySize ) {
break;
}
$event = EchoEvent::newFromRow( $row );
- $this->appendContent( $event, $row->eeb_event_hash );
+ if ( !$event ) {
+ continue;
+ }
+ $event->setBundleHash( $row->eeb_event_hash );
+ $this->events[] = $event;
}
+ $bundler = new Bundler();
+ $this->events = $bundler->bundle( $this->events );
+
$this->sendEmail();
}
@@ -122,14 +148,15 @@ class MWEchoEmailBatch {
protected function setLastEvent() {
$dbr = MWEchoDbFactory::getDB( DB_SLAVE );
$res = $dbr->selectField(
- array( 'echo_email_batch' ),
- array( 'MAX( eeb_event_id )' ),
- array( 'eeb_user_id' => $this->mUser->getId() ),
+ [ 'echo_email_batch' ],
+ [ 'MAX( eeb_event_id )' ],
+ [ 'eeb_user_id' => $this->mUser->getId() ],
__METHOD__
);
if ( $res ) {
$this->lastEvent = $res;
+
return true;
} else {
return false;
@@ -152,7 +179,7 @@ class MWEchoEmailBatch {
protected function getEvents() {
global $wgEchoNotifications;
- $events = array();
+ $events = [];
$validEvents = array_keys( $wgEchoNotifications );
@@ -163,11 +190,11 @@ class MWEchoEmailBatch {
if ( $validEvents ) {
$dbr = MWEchoDbFactory::getDB( DB_SLAVE );
- $conds = array(
+ $conds = [
'eeb_user_id' => $this->mUser->getId(),
'event_id = eeb_event_id',
'event_type' => $validEvents
- );
+ ];
// See setLastEvent() for more detail for this variable
if ( $this->lastEvent ) {
@@ -175,15 +202,14 @@ class MWEchoEmailBatch {
}
$res = $dbr->select(
- array( 'echo_email_batch', 'echo_event' ),
- array( '*' ),
+ [ 'echo_email_batch', 'echo_event' ],
+ [ '*' ],
$conds,
__METHOD__,
- array(
+ [
'ORDER BY' => 'eeb_event_priority',
'LIMIT' => self::$displaySize + 1,
- 'GROUP BY' => 'eeb_event_hash'
- )
+ ]
);
foreach ( $res as $row ) {
@@ -199,37 +225,21 @@ class MWEchoEmailBatch {
}
/**
- * Add individual event template to the big email content
- *
- * @param EchoEvent $event
- * @param string $hash
- */
- protected function appendContent( EchoEvent $event, $hash ) {
- // get the category for this event
- $category = $event->getCategory();
- $event->setBundleHash( $hash );
- $email = EchoNotificationController::formatNotification( $event, $this->mUser, 'email', 'emaildigest' );
-
- $this->content[$category][] = $email;
- }
-
- /**
* Clear "processed" events in the queue, processed could be: email sent, invalid, users do not want to receive emails
*/
public function clearProcessedEvent() {
- $conds = array( 'eeb_user_id' => $this->mUser->getId() );
+ $conds = [ 'eeb_user_id' => $this->mUser->getId() ];
// there is a processed cutoff point
if ( $this->lastEvent ) {
$conds[] = 'eeb_event_id <= ' . intval( $this->lastEvent );
}
- $dbw = MWEchoDbFactory::getDB( DB_MASTER );
+ $dbw = MWEchoDbFactory::newFromDefault()->getEchoDb( DB_MASTER );
$dbw->delete(
'echo_email_batch',
$conds,
- __METHOD__,
- array()
+ __METHOD__
);
}
@@ -239,8 +249,7 @@ class MWEchoEmailBatch {
public function sendEmail() {
global $wgNotificationSender, $wgNotificationReplyName;
- // @Todo - replace them with the CONSTANT in 33810 once it is merged
- if ( $this->mUser->getOption( 'echo-email-frequency' ) == 7 ) {
+ if ( $this->mUser->getOption( 'echo-email-frequency' ) == EchoEmailFrequency::WEEKLY_DIGEST ) {
$frequency = 'weekly';
$emailDeliveryMode = 'weekly_digest';
} else {
@@ -248,52 +257,44 @@ class MWEchoEmailBatch {
$emailDeliveryMode = 'daily_digest';
}
- // Echo digest email mode
- $emailDigest = new EchoEmailDigest( $this->mUser, $this->content, $frequency );
-
- $textEmailFormatter = new EchoTextEmailFormatter( $emailDigest );
-
- $body = $textEmailFormatter->formatEmail();
+ $textEmailDigestFormatter = new EchoPlainTextDigestEmailFormatter( $this->mUser, $this->language, $frequency );
+ $content = $textEmailDigestFormatter->format( $this->events, 'email' );
- $format = MWEchoNotifUser::newFromUser( $this->mUser )->getEmailFormat();
- if ( $format == EchoHooks::EMAIL_FORMAT_HTML ) {
- $htmlEmailFormatter = new EchoHTMLEmailFormatter( $emailDigest );
- $body = array(
- 'text' => $body,
- 'html' => $htmlEmailFormatter->formatEmail()
- );
+ if ( !$content ) {
+ // no event could be formatted
+ return;
}
- // email subject
- if ( $this->count > self::$displaySize ) {
- $count = wfMessage( 'echo-notification-count' )
- ->inLanguage( $this->mUser->getOption( 'language' ) )
- ->params( self::$displaySize )->text();
- } else {
- $count = $this->count;
+ $format = MWEchoNotifUser::newFromUser( $this->mUser )->getEmailFormat();
+ if ( $format == EchoEmailFormat::HTML ) {
+ $htmlEmailDigestFormatter = new EchoHtmlDigestEmailFormatter( $this->mUser, $this->language, $frequency );
+ $htmlContent = $htmlEmailDigestFormatter->format( $this->events, 'email' );
+
+ $content = [
+ 'body' => [
+ 'text' => $content['body'],
+ 'html' => $htmlContent['body'],
+ ],
+ 'subject' => $htmlContent['subject'],
+ ];
}
- // Give grep a chance to find the usages:
- // echo-email-batch-subject-daily, echo-email-batch-subject-weekly
- $subject = wfMessage( 'echo-email-batch-subject-' . $frequency )
- ->inLanguage( $this->mUser->getOption( 'language' ) )
- ->params( $count, $this->count )->text();
$toAddress = MailAddress::newFromUser( $this->mUser );
$fromAddress = new MailAddress( $wgNotificationSender, EchoHooks::getNotificationSenderName() );
- $replyAddress = new MailAddress( $wgNotificationSender, $wgNotificationReplyName );
+ $replyTo = new MailAddress( $wgNotificationSender, $wgNotificationReplyName );
// @Todo Push the email to job queue or just send it out directly?
- UserMailer::send( $toAddress, $fromAddress, $subject, $body, $replyAddress );
+ UserMailer::send( $toAddress, $fromAddress, $content['subject'], $content['body'], [ 'replyTo' => $replyTo ] );
MWEchoEventLogging::logSchemaEchoMail( $this->mUser, $emailDeliveryMode );
}
/**
* Insert notification event into email queue
*
- * @param $userId int
- * @param $eventId int
- * @param $priority int
- * @param $hash string
+ * @param int $userId
+ * @param int $eventId
+ * @param int $priority
+ * @param string $hash
*
* @throws MWException
*/
@@ -304,32 +305,26 @@ class MWEchoEmailBatch {
$dbw = MWEchoDbFactory::getDB( DB_MASTER );
- $row = array(
+ $row = [
'eeb_user_id' => $userId,
'eeb_event_id' => $eventId,
'eeb_event_priority' => $priority,
'eeb_event_hash' => $hash
- );
-
- $id = $dbw->nextSequenceValue( 'echo_email_batch_eeb_id' );
-
- if ( $id ) {
- $row['eeb_id'] = $id;
- }
+ ];
$dbw->insert(
'echo_email_batch',
$row,
__METHOD__,
- array( 'IGNORE' )
+ [ 'IGNORE' ]
);
}
/**
* Get a list of users to be notified for the batch
*
- * @param $startUserId int
- * @param $batchSize int
+ * @param int $startUserId
+ * @param int $batchSize
*
* @throws MWException
* @return ResultWrapper|bool
@@ -337,11 +332,11 @@ class MWEchoEmailBatch {
public static function getUsersToNotify( $startUserId, $batchSize ) {
$dbr = MWEchoDbFactory::getDB( DB_SLAVE );
$res = $dbr->select(
- array( 'echo_email_batch' ),
- array( 'eeb_user_id' ),
- array( 'eeb_user_id > ' . intval( $startUserId ) ),
+ [ 'echo_email_batch' ],
+ [ 'eeb_user_id' ],
+ [ 'eeb_user_id > ' . intval( $startUserId ) ],
__METHOD__,
- array( 'ORDER BY' => 'eeb_user_id', 'LIMIT' => $batchSize )
+ [ 'ORDER BY' => 'eeb_user_id', 'LIMIT' => $batchSize ]
);
return $res;
diff --git a/Echo/includes/EmailBundler.php b/Echo/includes/EmailBundler.php
deleted file mode 100644
index 7360498d..00000000
--- a/Echo/includes/EmailBundler.php
+++ /dev/null
@@ -1,303 +0,0 @@
-<?php
-
-/**
- * This class handles email bundling, it has only two public interfacing entries:
- *
- * 1. a single notification is triggered which calls self::addToEmailBatch()
- * (a) cycle is null/reset, send single notification, schedule a bundle job for next notification
- * (b) cycle is in bundle mode, add the notification to the queue
- *
- * 2. a job is popped off the queue which calls self::processBundleEmail()
- *
- */
-class MWEchoEmailBundler {
-
- /**
- * @var User
- */
- protected $mUser;
-
- /**
- * @var string
- */
- protected $bundleHash;
-
- /**
- * @var string
- *
- * The timestamp of email being sent
- */
- protected $timestamp;
-
- /**
- * @var EchoEvent
- */
- protected $baseEvent;
-
- /**
- * @var int
- *
- * seconds between sending batch email for a bundle notification
- * this only applies to a bundle type
- */
- protected $emailInterval;
-
- /**
- * Protected constructor so subclasses can call it
- */
- protected function __construct( $user, $hash ) {
- global $wgEchoBundleEmailInterval;
-
- $this->mUser = $user;
- $this->bundleHash = $hash;
- $this->emailInterval = $wgEchoBundleEmailInterval;
-
- if ( $this->emailInterval < 0 ) {
- $this->emailInterval = 0;
- }
- }
-
- /**
- * Factory method
- */
- public static function newFromUserHash( User $user, $hash ) {
- if ( !$user->getId() ) {
- return false;
- }
- if ( !$hash || !preg_match( '/^[a-f0-9]{32}$/', $hash ) ) {
- return false;
- }
- return new self( $user, $hash );
- }
-
- /**
- * Check if a new notification should be added to the batch queue
- * true - added to the queue for bundling email
- * false - not added, the client should send single email
- *
- * @param int $eventId
- * @param int $eventPriority
- *
- * @return bool
- */
- public function addToEmailBatch( $eventId, $eventPriority ) {
- $this->retrieveLastEmailTimestamp();
- $this->retrieveBaseEvent();
-
- // send instant single notification email if there is no base event in the batch queue
- // and the email is ready to send, otherwiase, add the email to batch and schedule
- // a delayed job
- if ( !$this->baseEvent && $this->shouldSendEmailNow() ) {
- $this->timestamp = wfTimestampNow();
- $this->updateEmailMetadata();
- return false;
- } else {
- // add to email batch queue
- MWEchoEmailBatch::addToQueue(
- $this->mUser->getId(),
- $eventId,
- $eventPriority,
- $this->bundleHash
- );
-
- // always push the job to job queue in case the previous job
- // was lost, job queue will ignore duplicate
- $this->pushToJobQueue( $this->getDelayTime() );
- return true;
- }
- }
-
- /**
- * Get the time diff since last email
- */
- protected function timeSinceLastEmail() {
- // if there is no timestamp, next email should be sent right away
- // set the time diff longer than the email interval
- if ( !$this->timestamp ) {
- return $this->emailInterval + 600;
- }
-
- $now = wfTimestamp( TS_UNIX );
-
- return $now - wfTimestamp( TS_UNIX, $this->timestamp );
- }
-
- /**
- * Check if an email should be sent right away
- * @return bool
- */
- protected function shouldSendEmailNow() {
- if ( $this->timeSinceLastEmail() > $this->emailInterval ) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Get the delay time
- * @return int
- */
- protected function getDelayTime() {
- $delay = $this->emailInterval - $this->timeSinceLastEmail();
- if ( $delay <= 0 ) {
- $delay = 0;
- }
- return $delay;
- }
-
- /**
- * Get the timestamp of last email
- */
- protected function retrieveLastEmailTimestamp() {
- global $wgMemc;
-
- $data = $wgMemc->get( $this->getMemcacheKey() );
- if ( $data !== false ) {
- $this->timestamp = $data['timestamp'];
- }
- }
-
- /**
- * Get the memcache key
- * @return string
- */
- protected function getMemcacheKey() {
- return wfMemcKey( 'echo', 'email_bundle_status', $this->mUser->getId(), $this->bundleHash );
- }
-
- /**
- * Retrieve the base event for email bundling, the one with the largest eeb_id
- * @return bool
- */
- protected function retrieveBaseEvent() {
- $dbr = MWEchoDbFactory::getDB( DB_SLAVE );
- $res = $dbr->selectRow(
- array( 'echo_email_batch' ),
- array( 'eeb_event_id' ),
- array(
- 'eeb_user_id' => $this->mUser->getId(),
- 'eeb_event_hash' => $this->bundleHash
- ),
- __METHOD__,
- array( 'ORDER BY' => 'eeb_event_priority DESC, eeb_id DESC', 'LIMIT' => 1 )
- );
- if ( !$res ) {
- return false;
- }
- $this->baseEvent = EchoEvent::newFromId( $res->eeb_event_id );
- return true;
- }
-
- /**
- * Push the latest bundle data to the queue
- * @param $delay int To delay the job in $delay seconds
- */
- public function pushToJobQueue( $delay = 0 ) {
- $title = Title::newMainPage();
- $job = new MWEchoNotificationEmailBundleJob(
- $title,
- array(
- 'user_id' => $this->mUser->getId(),
- 'bundle_hash' => $this->bundleHash,
- 'jobReleaseTimestamp' => wfTimestamp( TS_MW, wfTimestamp( TS_UNIX ) + $delay )
- )
- );
- JobQueueGroup::singleton()->push( $job );
- }
-
- /**
- * Main function for processinig bundle email
- */
- public function processBundleEmail() {
- $emailSetting = intval( $this->mUser->getOption( 'echo-email-frequency' ) );
-
- // User has switched to email digest or decided not to receive email,
- // the daily cron will handle events left in the queue
- if ( $emailSetting != 0 ) {
- throw new MWException( "User has switched to email digest/no email option!" );
- }
-
- // If there is nothing in the queue, do not update timestamp so next
- // email would be just an instant email
- if ( $this->retrieveBaseEvent() ) {
- $this->timestamp = wfTimestampNow();
- $this->updateEmailMetadata();
- $this->sendEmail();
- $this->clearProcessedEvent();
- } else {
- throw new MWException( "There is no bundle notification to process!" );
- }
- }
-
- /**
- * Send the bundle email
- */
- protected function sendEmail() {
- $content = $this->generateEmailContent();
-
- if ( !isset( $content['subject'] ) || !isset( $content['body'] ) ) {
- throw new MWException( "Fail to create bundle email content!" );
- }
-
- global $wgNotificationSender, $wgNotificationReplyName;
-
- $toAddress = MailAddress::newFromUser( $this->mUser );
- $fromAddress = new MailAddress( $wgNotificationSender, EchoHooks::getNotificationSenderName() );
- $replyAddress = new MailAddress( $wgNotificationSender, $wgNotificationReplyName );
-
- // Schedule a email job or just send the email directly?
- UserMailer::send( $toAddress, $fromAddress, $content['subject'], $content['body'], $replyAddress );
- MWEchoEventLogging::logSchemaEchoMail( $this->mUser, 'bundle' );
- }
-
- /**
- * Generate the content for bundle email
- * @return string
- */
- protected function generateEmailContent() {
- if ( !$this->baseEvent ) {
- return '';
- }
- $this->baseEvent->setBundleHash( $this->bundleHash );
- return EchoNotificationController::formatNotification( $this->baseEvent, $this->mUser, 'email', 'email' );
- }
-
- /**
- * Update bundle email metadata for user/hash pair
- */
- protected function updateEmailMetadata() {
- global $wgMemc;
-
- $key = $this->getMemcacheKey();
-
- // Store new data and make it expire in 7 days
- $wgMemc->set(
- $key,
- array(
- 'timestamp' => $this->timestamp
- ),
- 3600 * 24 * 7
- );
- }
-
- /**
- * clear processed event in the queue
- */
- protected function clearProcessedEvent() {
- if ( !$this->baseEvent ) {
- return;
- }
- $conds = array( 'eeb_user_id' => $this->mUser->getId(), 'eeb_event_hash' => $this->bundleHash );
-
- $conds[] = 'eeb_event_id <= ' . intval( $this->baseEvent->getId() );
-
- $dbw = MWEchoDbFactory::getDB( DB_MASTER );
- $dbw->delete(
- 'echo_email_batch',
- $conds,
- __METHOD__,
- array()
- );
- }
-}
diff --git a/Echo/includes/EmailFormat.php b/Echo/includes/EmailFormat.php
new file mode 100644
index 00000000..582ece97
--- /dev/null
+++ b/Echo/includes/EmailFormat.php
@@ -0,0 +1,6 @@
+<?php
+
+class EchoEmailFormat {
+ const HTML = 'html';
+ const PLAIN_TEXT = 'plain-text';
+}
diff --git a/Echo/includes/EmailFormatter.php b/Echo/includes/EmailFormatter.php
deleted file mode 100644
index aa359485..00000000
--- a/Echo/includes/EmailFormatter.php
+++ /dev/null
@@ -1,858 +0,0 @@
-<?php
-
-/**
- * Abstract class for formatting email notifications
- */
-abstract class EchoEmailFormatter {
-
- /**
- * @var EchoEmailMode
- */
- protected $emailMode;
-
- /**
- * @param $emailMode EchoEmailMode
- */
- public function __construct( EchoEmailMode $emailMode ) {
- $this->emailMode = $emailMode;
- }
-
- /**
- * Abstract method for formatting email
- * @return string
- */
- abstract public function formatEmail();
-}
-
-/**
- * Formatter class for formatting text email notification
- */
-class EchoTextEmailFormatter extends EchoEmailFormatter {
-
- /**
- * @param $emailMode EchoEmailMode
- */
- public function __construct( EchoEmailMode $emailMode ) {
- parent::__construct( $emailMode );
- $this->emailMode->attachDecorator( new EchoTextEmailDecorator() );
- }
-
- /**
- * {@inheritDoc}
- */
- public function formatEmail() {
- $template = $this->emailMode->getTextTemplate();
-
- foreach ( $this->emailMode->getComponent() as $val ) {
- $func = 'build' . ucfirst( $val );
- $template = str_replace( "%%$val%%", $this->emailMode->$func(), $template );
- }
-
- // Remove redundant newline characters
- return $this->removeExtraNewLine( $template );
- }
-
- /**
- * Remove extra newline from a text content
- * @param $text string
- * @return string
- */
- protected function removeExtraNewLine( $text ) {
- return preg_replace( "/\n{3,}/", "\n\n", $text );
- }
-
-}
-
-/**
- * Formatter class for formatting HTML email notification
- */
-class EchoHTMLEmailFormatter extends EchoEmailFormatter {
-
- /**
- * @param $emailMode EchoEmailMode
- */
- public function __construct( EchoEmailMode $emailMode ) {
- parent::__construct( $emailMode );
- $this->emailMode->attachDecorator( new EchoHTMLEmailDecorator() );
- }
-
- /**
- * {@inheritDoc}
- */
- public function formatEmail() {
- $template = $this->emailMode->getHTMLTemplate();
-
- foreach ( $this->emailMode->getComponent() as $val ) {
- $func = 'build' . ucfirst( $val );
- $template = str_replace( "%%$val%%", $this->emailMode->$func(), $template );
- }
-
- return $template;
- }
-}
-
-/**
- * Abstract entity that represents an email delivery mode
- */
-abstract class EchoEmailMode {
-
- /**
- * @var array
- * Email components
- */
- protected $component;
-
- /**
- * @var User
- * The user who receives email notifications
- */
- protected $user;
-
- /**
- * @var EchoEmailDecorator
- * Email decorator
- */
- protected $decorator;
-
- /**
- * @var Language
- * The language object for the user language
- */
- protected $lang;
-
- /**
- * @param $user User
- * @param $component array
- */
- public function __construct( User $user, array $component ) {
- $this->user = $user;
- // All email delivery mode share the same footer
- $this->component = array_merge( $component, array( 'footer' ) );
- // Initialize with a text decorator, the decorator can be altered
- // via attachDecorator() based on text/html emails
- $this->decorator = new EchoTextEmailDecorator();
- $this->lang = Language::factory( $user->getOption( 'language' ) );
- }
-
- /**
- * Get text email template
- * @return string
- */
- abstract public function getTextTemplate();
-
- /**
- * Get html email template
- * @return string
- */
- abstract public function getHTMLTemplate();
-
- /**
- * Get the footer component
- * @return string
- */
- public function buildFooter() {
- global $wgEchoEmailFooterAddress;
- return $this->decorator->decorateFooter( $wgEchoEmailFooterAddress, $this->user );
- }
-
- /**
- * Getter method for email template component
- * @return array
- */
- public function getComponent() {
- return $this->component;
- }
-
- /**
- * Get the notification icon path
- * @param $icon string
- * @return string
- */
- public static function getNotifIcon( $icon ) {
- global $wgLang;
-
- $iconUrl = EchoNotificationFormatter::getIconUrl( $icon, $wgLang->getDir() );
-
- return wfExpandUrl( $iconUrl, PROTO_CANONICAL );
- }
-
- /**
- * Attach an email decorator to the email mode object
- * @param $decorator EchoEmailDecorator
- */
- public function attachDecorator( EchoEmailDecorator $decorator ) {
- $this->decorator = $decorator;
- }
-
- /**
- * Format the message in the user's language
- * @param $message string
- * @param $user User
- * @return Message
- */
- public static function message( $message, User $user ) {
- return wfMessage( $message )->inLanguage( $user->getOption( 'language' ) );
- }
-
-}
-
-/**
- * Entity that represents a single email delivery mode
- */
-class EchoEmailSingle extends EchoEmailMode {
-
- /**
- * @var EchoBasicFormatter
- */
- protected $notifFormatter;
-
- /**
- * @var EchoEvent
- */
- protected $event;
-
- /**
- * @param $notifFormatter EchoBasicFormatter
- * @param $event EchoEvent
- * @param $user User
- */
- public function __construct( EchoBasicFormatter $notifFormatter, EchoEvent $event, User $user ) {
- parent::__construct( $user, array ( 'emailIcon', 'intro', 'summary', 'action' ) );
- $this->notifFormatter = $notifFormatter;
- $this->event = $event;
- }
-
- /**
- * Build the intro component
- * @return string
- */
- public function buildIntro() {
- $bundle = $this->notifFormatter->getValue( 'bundleData' );
- $email = $this->notifFormatter->getValue( 'email' );
-
- if ( $bundle['use-bundle'] && $email['batch-bundle-body']['message'] ) {
- $detail = $email['batch-bundle-body'];
- } else {
- $detail = $email['batch-body'];
- }
-
- $message = $this->notifFormatter->formatFragment(
- $detail,
- $this->event,
- $this->user
- );
-
- return $this->decorator->decorateIntro( $message );
- }
-
- /**
- * Build the summary component
- * @return string
- */
- public function buildSummary() {
- return $this->decorator->decorateRevisionSnippet(
- $this->notifFormatter->getRevisionSnippet(
- $this->event,
- $this->user
- )
- );
- }
-
- /**
- * Build the action component
- * @return string
- */
- public function buildAction() {
- $link = array();
- $ranks = array( 'primary', 'secondary' );
-
- foreach ( $ranks as $rank ) {
- $message = $this->event->getLinkMessage( $rank );
-
- // Valid call to action should have link text
- if ( !$message ) {
- continue;
- }
-
- $link[] = $this->decorator->decorateSingleAction(
- $this->notifFormatter,
- $this->event,
- $this->user,
- $rank,
- $message
- );
- }
-
- // Add some spacing between the two action links
- $spacing = $this->decorator->getActionLinkSeparator();
- return implode( $spacing . $spacing, $link );
- }
-
- /**
- * Build the email icon component
- * @return string
- */
- public function buildEmailIcon() {
- return EchoEmailMode::getNotifIcon( $this->notifFormatter->getValue( 'icon' ) );
- }
-
- /**
- * {@inheritDoc}
- */
- public function getTextTemplate() {
- return <<< EOF
-%%intro%%
-
-%%summary%%
-
-%%action%%
-
-%%footer%%
-EOF;
- }
-
- /**
- * {@inheritDoc}
- */
- public function getHTMLTemplate() {
- $alignStart = $this->lang->alignStart();
- return <<< EOF
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <style>
- @media only screen and (max-width: 480px){
- table[id="email-container"]{max-width:600px !important; width:100% !important;}
- }
- </style>
-</head><body>
-<table cellspacing="0" cellpadding="0" border="0" width="100%" align="center" lang="{$this->lang->getCode()}" dir="{$this->lang->getDir()}">
-<tr>
- <td bgcolor="#E6E7E8"><center>
- <br /><br />
- <table cellspacing="0" cellpadding="0" border="0" width="600" id="email-container">
- <tr>
- <td bgcolor="#FFFFFF" width="5%">&nbsp;</td>
- <td bgcolor="#FFFFFF" width="10%">&nbsp;</td>
- <td bgcolor="#FFFFFF" width="80%" style="line-height:40px;">&nbsp;</td>
- <td bgcolor="#FFFFFF" width="5%">&nbsp;</td>
- </tr><tr>
- <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
- <td bgcolor="#FFFFFF" align="center" valign="top" rowspan="2"><img src="%%emailIcon%%" alt="" height="30" width="30"></td>
- <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:13px; line-height:20px; color:#6D6E70;">%%intro%%</td>
- <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
- </tr><tr>
- <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; line-height: 20px; font-weight: 600;">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; padding-top: 8px; font-size:13px; font-weight: bold; color: #58585B;">
- %%summary%%
- </td>
- </tr>
- </table>
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:14px; padding-top: 25px;">
- %%action%%
- </td>
- </tr>
- </table>
- </td>
- </tr><tr>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- <td bgcolor="#FFFFFF" style="line-height:40px;">&nbsp;</td>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- </tr><tr>
- <td>&nbsp;</td>
- <td>&nbsp;</td>
- <td align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:10px; line-height:13px; color:#6D6E70; padding:10px 20px;"><br />
- %%footer%%
- <br /><br />
- </td>
- <td>&nbsp;</td>
- </tr><tr>
- <td colspan="4">&nbsp;</td>
- </tr>
- </table>
- <br><br></center>
- </td>
-</tr>
-</table>
-</body></html>
-EOF;
- }
-
-}
-
-/**
- * Class that represents email digest delivery mode
- */
-class EchoEmailDigest extends EchoEmailMode {
-
- /**
- * @var string
- * The mode of email digest, 'weekly' or 'daily'
- */
- protected $digestMode;
-
- /**
- * @var array
- * Raw email digest list
- */
- protected $rawDigestList;
-
- /**
- * @param $user User
- * @param $rawDigestList array the raw notification event list
- * @param $digestMode string 'daily'/'weekly'
- */
- public function __construct( User $user, array $rawDigestList, $digestMode = 'daily' ) {
- parent::__construct( $user, array( 'intro', 'digestList', 'action' ) );
- // Some data validation
- if ( !in_array( $digestMode, array( 'daily', 'weekly' ) ) ) {
- $digestMode = 'daily';
- }
- $this->digestMode = $digestMode;
- $this->rawDigestList = $rawDigestList;
- }
-
- /**
- * Build the intro component
- * @return string
- */
- public function buildIntro() {
- // Give grep a chance to find the usages:
- // echo-email-batch-body-intro-daily, echo-email-batch-body-intro-weekly
- $message = EchoEmailMode::message(
- 'echo-email-batch-body-intro-' . $this->digestMode, $this->user
- )->params( $this->user->getName() );
-
- return $this->decorator->decorateIntro( $message );
- }
-
- /**
- * Build the digestList component
- * @return string
- */
- public function buildDigestList() {
- if ( !$this->rawDigestList ) {
- return '';
- }
-
- return $this->decorator->decorateDigestList( $this->rawDigestList, $this->user );
- }
-
- /**
- * Build the action component
- * @return string
- */
- public function buildAction() {
- $title = SpecialPage::getTitleFor( 'Notifications' );
-
- return $this->decorator->decorateDigestAction( $title, $this->user );
- }
-
- /**
- * {@inheritDoc}
- */
- public function getTextTemplate() {
- return <<< EOF
-%%intro%%
-
-%%digestList%%
-
-%%action%%
-
-%%footer%%
-
-EOF;
- }
-
- /**
- * {@inheritDoc}
- */
- public function getHTMLTemplate() {
- $alignStart = $this->lang->alignStart();
- return <<< EOF
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <style>
- @media only screen and (max-width: 480px){
- table[id="email-container"]{max-width:600px !important; width:100% !important;}
- }
- </style>
-</head><body>
-<table cellspacing="0" cellpadding="0" border="0" width="100%" align="center" lang="{$this->lang->getCode()}" dir="{$this->lang->getDir()}">
-<tr>
- <td bgcolor="#E6E7E8"><center>
- <br /><br />
- <table cellspacing="0" cellpadding="0" border="0" width="600" id="email-container">
- <tr>
- <td bgcolor="#FFFFFF" width="5%">&nbsp;</td>
- <td bgcolor="#FFFFFF" width="6%">&nbsp;</td>
- <td bgcolor="#FFFFFF" width="79%" style="line-height:40px;">&nbsp;</td>
- <td bgcolor="#FFFFFF" width="10%">&nbsp;</td>
- </tr>
- <tr>
- <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
- <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
- <td bgcolor="#FFFFFF" align="center" style="font-family: Arial, Helvetica, sans-serif; font-size:13px; line-height:20px; color:#6D6E70; text-align: center;">%%intro%%</td>
- <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
- </tr>
- <tr>
- <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; line-height: 20px; font-weight: 600;">
- <table cellspacing="0" cellpadding="0" border="0" width="100%">
- <tr>
- <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:13px; color: #58585B; padding-top: 25px;">
- %%digestList%%
- </td>
- </tr>
- </table>
- <br /><br />
- </td>
- </tr>
- <tr>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- <td bgcolor="#FFFFFF" style="line-height:60px;" align="center">%%action%%</td>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- </tr>
- <tr>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- <td bgcolor="#FFFFFF" style="line-height:40px;">&nbsp;</td>
- <td bgcolor="#FFFFFF">&nbsp;</td>
- </tr>
- <tr>
- <td>&nbsp;</td>
- <td>&nbsp;</td>
- <td align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:10px; line-height:13px; color:#6D6E70; padding: 10px 20px;"><br />
- %%footer%%
- <br /><br />
- </td>
- <td>&nbsp;</td>
- </tr>
- <tr>
- <td colspan="4">&nbsp;</td>
- </tr>
- </table>
- <br><br></center>
- </td>
-</tr>
-</table>
-</body></html>
-EOF;
- }
-
-}
-
-/**
- * Email decorator interface
- */
-interface EchoEmailDecorator {
- /**
- * Decorate the intro for all modes
- * @param $message Message the intro message object
- * @return string
- */
- public function decorateIntro( $message );
-
- /**
- * Decorate the digest list for digest mode
- * @param $digestList array
- * @param $user User
- * @return string
- */
- public function decorateDigestList( $digestList, User $user );
-
- /**
- * Decorate the primary action for digest mode
- * @param $title Title
- * @param $user User
- * @return string
- */
- public function decorateDigestAction( $title, User $user );
-
- /**
- * Decorate the footer for all mode
- * @param $address string
- * @param $user User
- * @return string
- */
- public function decorateFooter( $address, User $user );
-
- /**
- * Decorate the actions for single mode
- * @param $notifFormatter EchoBasicFormatter
- * @param $event EchoEvent
- * @param $user User
- * @param $rank string
- * @param $message string
- * @return string
- */
- public function decorateSingleAction( $notifFormatter, EchoEvent $event, User $user, $rank, $message );
-
- /**
- * Decorate a revision snippet
- * @param string $snippet the raw revision snippet
- * @return string
- */
- public function decorateRevisionSnippet( $snippet );
-
- /**
- * Get the spacing for between action links
- * @return string
- */
- public function getActionLinkSeparator();
-}
-
-/**
- * Text email decorator
- */
-class EchoTextEmailDecorator implements EchoEmailDecorator {
-
- /**
- * {@inheritDoc}
- */
- public function decorateIntro( $message ) {
- return $message->text();
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateDigestList( $digestList, User $user ) {
- $result = array();
-
- // build the text section for each category
- foreach( $digestList as $category => $notifs ) {
- $output = EchoEmailMode::message( 'echo-category-title-' . $category, $user )->numParams( count( $notifs ) )->text()
- . EchoEmailMode::message( 'colon-separator', $user )->text() . "\n";
-
- foreach( $notifs as $notif ) {
- $output .= "\n " . EchoEmailMode::message( 'echo-email-batch-bullet', $user )->text() . ' ' . $notif['batch-body'];
- }
- $result[] = $output;
- }
-
- // for prepending and appending 'echo-email-batch-separator'
- $result = array_merge( array( '' ), $result, array( '' ) );
-
- return trim(
- implode(
- "\n\n" . EchoEmailMode::message( 'echo-email-batch-separator', $user )->text() . "\n\n",
- $result
- )
- );
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateDigestAction( $title, User $user ) {
- return EchoEmailMode::message( 'echo-email-batch-link-text-view-all-notifications', $user )->text()
- . EchoEmailMode::message( 'colon-separator', $user )->text()
- . '<'
- . $title->getFullURL( '', false, PROTO_CANONICAL )
- . '>';
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateFooter( $address, User $user ) {
- return EchoEmailMode::message( 'echo-email-footer-default', $user )
- ->params(
- $address,
- EchoEmailMode::message( 'echo-email-batch-separator', $user )->text()
- )
- ->text();
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateSingleAction( $notifFormatter, EchoEvent $event, User $user, $rank, $message ) {
- $url = $notifFormatter->getLink( $event, $user, $rank, false, true );
-
- return EchoEmailMode::message( $message, $user )->text()
- . EchoEmailMode::message( 'colon-separator', $user )->text()
- . '<'
- . $notifFormatter->sanitizeEmailLink( $url )
- . '>';
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateRevisionSnippet( $snippet ) {
- // Doing nothing now, but there is a potential to wrap the text
- // around snippet with quote in plain text email
- return $snippet;
- }
-
- /**
- * {@inheritDoc}
- */
- public function getActionLinkSeparator() {
- return "\n";
- }
-}
-
-/**
- * HTML email decorator
- */
-class EchoHTMLEmailDecorator implements EchoEmailDecorator {
-
- /**
- * {@inheritDoc}
- */
- public function decorateIntro( $message ) {
- return nl2br( $message->parse() );
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateDigestList( $digestList, User $user ) {
- $result = array();
- // build the html section for each category
- foreach( $digestList as $category => $notifs ) {
- $output = $this->applyStyleToCategory(
- EchoEmailMode::message( 'echo-category-title-' . $category, $user )
- ->numParams( count( $notifs ) )
- ->escaped()
- );
- foreach( $notifs as $notif ) {
- $output .= "\n" . $this->applyStyleToEvent( $notif );
- }
- $result[] = '<table border="0" width="100%">' . $output . '</table>';
- }
-
- return trim( implode( "\n", $result ) );
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateDigestAction( $title, User $user ) {
- /*
- * Linker::link() will try to figure out if $title already exists
- * (Title::isKnown) and alter the link depending on the outcome
- * (&action=edit&redlink=1)
- * Notifications are usually triggered by new content, so we better
- * make damn sure that slave lag doesn't mess that up. Especially
- * in emails, which we can't rerender once they've been sent.
- * I'll force the status for this $title to be read from master, so
- * Linker::link is guaranteed to get the correct exists() result.
- */
- $title->exists( wfGetLB()->hasOrMadeRecentMasterChanges() ? Title::GAID_FOR_UPDATE : 0 );
-
- return Linker::link(
- $title,
- EchoEmailMode::message( 'echo-email-batch-link-text-view-all-notifications', $user )->escaped(),
- array( 'style' => $this->getPrimaryLinkCSS() ),
- array(),
- array( 'https' )
- );
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateFooter( $address, User $user ) {
- $title = SpecialPage::getTitleFor( 'Preferences' );
- $title->setFragment( "#mw-prefsection-echo" );
- return EchoEmailMode::message( 'echo-email-footer-default-html', $user )
- ->params( $address )
- ->rawParams( $title->getFullURL( '', false, PROTO_HTTPS ) )
- ->text();
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateSingleAction( $notifFormatter, EchoEvent $event, User $user, $rank, $message ) {
- if ( $rank === 'primary' ) {
- $style = $this->getPrimaryLinkCSS();
- } else {
- $style = $this->getSecondaryLinkCSS();
- }
-
- return $notifFormatter->getLink( $event, $user, $rank, false, false, $style );
- }
-
- /**
- * {@inheritDoc}
- */
- public function decorateRevisionSnippet( $snippet ) {
- return htmlspecialchars( $snippet );
- }
-
- /**
- * {@inheritDoc}
- */
- public function getActionLinkSeparator() {
- return "&nbsp;";
- }
-
- /**
- * The style for primary link
- * @return string
- */
- protected function getPrimaryLinkCSS() {
- return 'cursor:pointer; text-align:center; text-decoration:none; padding:.45em 1.2em .45em;
- color:#D9EEF7; background:#3366BB; font-family: Arial, Helvetica, sans-serif;font-size: 13px;';
- }
-
- /**
- * The style for secondary link
- * @return string
- */
- protected function getSecondaryLinkCSS() {
- return 'text-decoration: none;font-size: 10px;font-family: Arial, Helvetica, sans-serif; color: #808184';
- }
-
- /**
- * Apply style to notification category header
- * @param $category string
- * @return string
- */
- protected function applyStyleToCategory( $category ) {
- return <<< EOF
-<tr>
- <td colspan="2" style="color: #A87B4F; font-weight: normal; font-size: 13px; padding-top: 15px;">
- $category <br />
- <hr style="background-color:#FFFFFF; color:#FFFFFF; border: 1px solid #F2F2F2;" />
- </td>
-</tr>
-EOF;
- }
-
- /**
- * Apply style to individual notification event
- * @param $notif array an array containts keys: icon, batch-body, batch-body-html
- * @return string
- */
- protected function applyStyletoEvent( $notif ) {
- // notification icon
- $icon = EchoEmailMode::getNotifIcon( $notif['icon'] );
- // notification text
- $text = $notif['batch-body-html'];
-
- return <<< EOF
-<tr>
- <td width="30">
- <img src="$icon" width="30" height="30" style="vertical-align:middle;">
- </td>
- <td style="font-family: Arial, Helvetica, sans-serif; font-size:13px; color: #58585B;">
- $text
- </td>
-</tr>
-EOF;
- }
-
-}
-
diff --git a/Echo/includes/EmailFrequency.php b/Echo/includes/EmailFrequency.php
new file mode 100644
index 00000000..1dd1ba8b
--- /dev/null
+++ b/Echo/includes/EmailFrequency.php
@@ -0,0 +1,8 @@
+<?php
+
+class EchoEmailFrequency {
+ const NEVER = -1; // Never send email notifications
+ const IMMEDIATELY = 0; // Send email notifications immediately as they come in
+ const DAILY_DIGEST = 1; // Send daily email digests
+ const WEEKLY_DIGEST = 7; // Send weekly email digests
+}
diff --git a/Echo/includes/EventLogging.php b/Echo/includes/EventLogging.php
index 753b9a92..c7f0ba52 100644
--- a/Echo/includes/EventLogging.php
+++ b/Echo/includes/EventLogging.php
@@ -7,27 +7,34 @@ class MWEchoEventLogging {
/**
* This is the only function that interacts with EventLogging
- * @param $schema string
- * @param $data array
+ *
+ * Adds common fields, and logs if logging is enabled for the given $schema.
+ *
+ * @param string $schema
+ * @param array $data
*/
- public static function actuallyLogTheEvent( $schema, $data ) {
- global $wgEchoConfig;
+ protected static function logEvent( $schema, array $data ) {
+ global $wgEchoEventLoggingSchemas, $wgEchoEventLoggingVersion;
- EventLogging::logEvent( $schema, $wgEchoConfig['eventlogging'][$schema]['revision'], $data );
+ $schemaConfig = $wgEchoEventLoggingSchemas[$schema];
+ if ( !$schemaConfig['enabled'] ) {
+ // If logging for this schema is disabled, it's a no-op.
+ return;
+ }
+
+ $data['version'] = $wgEchoEventLoggingVersion;
+
+ EventLogging::logEvent( $schema, $schemaConfig['revision'], $data );
}
/**
* Function for logging the event for Schema:Echo
- * @param $user User being notified.
- * @param $event EchoEvent to log detail about.
- * @param $deliveryMethod string containing either 'web' or 'email'
+ * @param User $user User being notified.
+ * @param EchoEvent $event Event to log detail about.
+ * @param string $deliveryMethod 'web' or 'email'
*/
public static function logSchemaEcho( User $user, EchoEvent $event, $deliveryMethod ) {
- global $wgEchoConfig, $wgEchoNotifications;
- if ( !$wgEchoConfig['eventlogging']['Echo']['enabled'] ) {
- // Only attempt event logging if Echo schema is enabled
- return;
- }
+ global $wgEchoNotifications;
// Notifications under system category should have -1 as sender id
if ( $event->getCategory() === 'system' ) {
@@ -46,21 +53,20 @@ class MWEchoEventLogging {
} else {
$group = 'neutral';
}
- $data = array (
- 'version' => $wgEchoConfig['version'],
- 'eventId' => $event->getId(),
+ $data = [
+ 'eventId' => (int)$event->getId(),
'notificationType' => $event->getType(),
'notificationGroup' => $group,
'sender' => (string)$sender,
'recipientUserId' => $user->getId(),
'recipientEditCount' => (int)$user->getEditCount()
- );
+ ];
// Add the source if it exists. (This is mostly for the Thanks extension.)
$extra = $event->getExtra();
if ( isset( $extra['source'] ) ) {
$data['eventSource'] = (string)$extra['source'];
}
- if( $deliveryMethod == 'email' ) {
+ if ( $deliveryMethod == 'email' ) {
$data['deliveryMethod'] = 'email';
} else {
// whitelist valid delivery methods so it is always valid
@@ -72,29 +78,40 @@ class MWEchoEventLogging {
$data['revisionId'] = $rev->getId();
}
- self::actuallyLogTheEvent( 'Echo', $data );
+ self::logEvent( 'Echo', $data );
}
/**
* Function for logging the event for Schema:EchoEmail
- * @param $user User
- * @param $emailDeliveryMode string
+ * @param User $user
+ * @param string $emailDeliveryMode 'single' (default), 'daily_digest', or 'weekly_digest'
*/
public static function logSchemaEchoMail( User $user, $emailDeliveryMode = 'single' ) {
- global $wgEchoConfig;
-
- if ( !$wgEchoConfig['eventlogging']['EchoMail']['enabled'] ) {
- // Only attempt event logging if EchoMail schema is enabled
- return;
- }
-
- $data = array (
- 'version' => $wgEchoConfig['version'],
+ $data = [
'recipientUserId' => $user->getId(),
'emailDeliveryMode' => $emailDeliveryMode
- );
+ ];
+
+ self::logEvent( 'EchoMail', $data );
+ }
- self::actuallyLogTheEvent( 'EchoMail', $data );
+ /**
+ * @param User $user
+ * @param string $skinName
+ */
+ public static function logSpecialPageVisit( User $user, $skinName ) {
+ self::logEvent(
+ 'EchoInteraction',
+ [
+ 'context' => 'archive',
+ 'action' => 'special-page-visit',
+ 'userId' => (int)$user->getId(),
+ 'editCount' => (int)$user->getEditCount(),
+ 'notifWiki' => wfWikiID(),
+ // Hack: Figure out if we are in the mobile skin
+ 'mobile' => $skinName === 'minerva',
+ ]
+ );
}
}
diff --git a/Echo/includes/ForeignNotifications.php b/Echo/includes/ForeignNotifications.php
new file mode 100644
index 00000000..9b3846ac
--- /dev/null
+++ b/Echo/includes/ForeignNotifications.php
@@ -0,0 +1,254 @@
+<?php
+
+/**
+ * Caches the result of EchoUnreadWikis::getUnreadCounts() and interprets the results in various useful ways.
+ *
+ * If the user has disabled cross-wiki notifications in their preferences (see isEnabledByUser()), this class
+ * won't do anything and will behave as if the user has no foreign notifications. For example, getCount() will
+ * return 0. If you need to get foreign notification information for a user even though they may not have
+ * enabled the preference, set $forceEnable=true in the constructor.
+ */
+class EchoForeignNotifications {
+ /**
+ * @var User
+ */
+ protected $user;
+
+ /**
+ * @var bool
+ */
+ protected $enabled = false;
+
+ /**
+ * @var array [(str) section => (int) count, ...]
+ */
+ protected $counts = [ EchoAttributeManager::ALERT => 0, EchoAttributeManager::MESSAGE => 0 ];
+
+ /**
+ * @var array [(str) section => (string[]) wikis, ...]
+ */
+ protected $wikis = [ EchoAttributeManager::ALERT => [], EchoAttributeManager::MESSAGE => [] ];
+
+ /**
+ * @var array [(str) section => (MWTimestamp) timestamp, ...]
+ */
+ protected $timestamps = [ EchoAttributeManager::ALERT => false, EchoAttributeManager::MESSAGE => false ];
+
+ /**
+ * @var array [(str) wiki => [ (str) section => (MWTimestamp) timestamp, ...], ...]
+ */
+ protected $wikiTimestamps = [];
+
+ /**
+ * @var bool
+ */
+ protected $populated = false;
+
+ /**
+ * @param User $user
+ * @param bool $forceEnable Ignore the user's preferences and act as if they've enabled cross-wiki notifications
+ */
+ public function __construct( User $user, $forceEnable = false ) {
+ $this->user = $user;
+ $this->enabled = $forceEnable || $this->isEnabledByUser();
+ }
+
+ /**
+ * Whether the user has enabled cross-wiki notifications.
+ * @return bool
+ */
+ public function isEnabledByUser() {
+ return (bool)$this->user->getOption( 'echo-cross-wiki-notifications' );
+ }
+
+ /**
+ * @param string $section Name of section
+ * @return int
+ */
+ public function getCount( $section = EchoAttributeManager::ALL ) {
+ $this->populate();
+
+ if ( $section === EchoAttributeManager::ALL ) {
+ $count = array_sum( $this->counts );
+ } else {
+ $count = isset( $this->counts[$section] ) ? $this->counts[$section] : 0;
+ }
+
+ return MWEchoNotifUser::capNotificationCount( $count );
+ }
+
+ /**
+ * @param string $section Name of section
+ * @return MWTimestamp|false
+ */
+ public function getTimestamp( $section = EchoAttributeManager::ALL ) {
+ $this->populate();
+
+ if ( $section === EchoAttributeManager::ALL ) {
+ $max = false;
+ /** @var MWTimestamp $timestamp */
+ foreach ( $this->timestamps as $timestamp ) {
+ // $timestamp < $max = invert 0
+ // $timestamp > $max = invert 1
+ if ( $timestamp !== false && ( $max === false || $timestamp->diff( $max )->invert === 1 ) ) {
+ $max = $timestamp;
+ }
+ }
+
+ return $max;
+ }
+
+ return isset( $this->timestamps[$section] ) ? $this->timestamps[$section] : false;
+ }
+
+ /**
+ * @param string $section Name of section
+ * @return string[]
+ */
+ public function getWikis( $section = EchoAttributeManager::ALL ) {
+ $this->populate();
+
+ if ( $section === EchoAttributeManager::ALL ) {
+ $all = [];
+ foreach ( $this->wikis as $wikis ) {
+ $all = array_merge( $all, $wikis );
+ }
+
+ return array_unique( $all );
+ }
+
+ return isset( $this->wikis[$section] ) ? $this->wikis[$section] : [];
+ }
+
+ public function getWikiTimestamp( $wiki, $section = EchoAttributeManager::ALL ) {
+ $this->populate();
+ if ( !isset( $this->wikiTimestamps[$wiki] ) ) {
+ return false;
+ }
+ if ( $section === EchoAttributeManager::ALL ) {
+ $max = false;
+ foreach ( $this->wikiTimestamps[$wiki] as $section => $ts ) {
+ // $ts < $max = invert 0
+ // $ts > $max = invert 1
+ if ( $max === false || $ts->diff( $max )->invert === 1 ) {
+ $max = $ts;
+ }
+ }
+ return $max;
+ }
+ return isset( $this->wikiTimestamps[$wiki][$section] ) ? $this->wikiTimestamps[$wiki][$section] : false;
+ }
+
+ protected function populate() {
+ if ( $this->populated ) {
+ return;
+ }
+
+ if ( !$this->enabled ) {
+ return;
+ }
+
+ $unreadWikis = EchoUnreadWikis::newFromUser( $this->user );
+ if ( !$unreadWikis ) {
+ return;
+ }
+ $unreadCounts = $unreadWikis->getUnreadCounts();
+ if ( !$unreadCounts ) {
+ return;
+ }
+
+ foreach ( $unreadCounts as $wiki => $sections ) {
+ // exclude current wiki
+ if ( $wiki === wfWikiID() ) {
+ continue;
+ }
+
+ foreach ( $sections as $section => $data ) {
+ if ( $data['count'] > 0 ) {
+ $this->counts[$section] += $data['count'];
+ $this->wikis[$section][] = $wiki;
+
+ $timestamp = new MWTimestamp( $data['ts'] );
+ $this->wikiTimestamps[$wiki][$section] = $timestamp;
+
+ // We need $this->timestamp[$section] to be the max timestamp
+ // across all wikis.
+ // $timestamp < $this->timestamps[$section] = invert 0
+ // $timestamp > $this->timestamps[$section] = invert 1
+ if (
+ $this->timestamps[$section] === false ||
+ $timestamp->diff( $this->timestamps[$section] )->invert === 1
+ ) {
+ $this->timestamps[$section] = new MWTimestamp( $data['ts'] );
+ }
+
+ }
+ }
+ }
+
+ $this->populated = true;
+ }
+
+ /**
+ * @param string[] $wikis
+ * @return array[] [(string) wiki => (array) data]
+ */
+ public static function getApiEndpoints( array $wikis ) {
+ global $wgConf;
+ $wgConf->loadFullData();
+
+ $data = [];
+ foreach ( $wikis as $wiki ) {
+ $siteFromDB = $wgConf->siteFromDB( $wiki );
+ list( $major, $minor ) = $siteFromDB;
+ $server = $wgConf->get( 'wgServer', $wiki, $major, [ 'lang' => $minor, 'site' => $major ] );
+ $scriptPath = $wgConf->get( 'wgScriptPath', $wiki, $major, [ 'lang' => $minor, 'site' => $major ] );
+ $articlePath = $wgConf->get( 'wgArticlePath', $wiki, $major, [ 'lang' => $minor, 'site' => $major ] );
+
+ $data[$wiki] = [
+ 'title' => static::getWikiTitle( $wiki, $siteFromDB ),
+ 'url' => wfExpandUrl( $server . $scriptPath . '/api.php', PROTO_INTERNAL ),
+ // We need this to link to Special:Notifications page
+ 'base' => wfExpandUrl( $server . $articlePath, PROTO_INTERNAL ),
+ ];
+ }
+
+ return $data;
+ }
+
+ /**
+ * @param string $wikiId
+ * @param array $siteFromDB $wgConf->siteFromDB( $wikiId ) result
+ * @return mixed|string
+ */
+ protected static function getWikiTitle( $wikiId, array $siteFromDB = null ) {
+ global $wgConf, $wgLang;
+
+ $msg = wfMessage( 'project-localized-name-'.$wikiId );
+ // check if WikimediaMessages localized project names are available
+ if ( $msg->exists() ) {
+ return $msg->text();
+ } else {
+ // don't fetch $site, $langCode if known already
+ if ( $siteFromDB === null ) {
+ $siteFromDB = $wgConf->siteFromDB( $wikiId );
+ }
+ list( $site, $langCode ) = $siteFromDB;
+
+ // try to fetch site name for this specific wiki, or fallback to the
+ // general project's sitename if there is no override
+ $wikiName = $wgConf->get( 'wgSitename', $wikiId ) ?: $wgConf->get( 'wgSitename', $site );
+ $langName = Language::fetchLanguageName( $langCode, $wgLang->getCode() );
+
+ if ( !$langName ) {
+ // if we can't find a language name (in language-agnostic
+ // project like mediawikiwiki), including the language name
+ // doesn't make much sense
+ return $wikiName;
+ }
+
+ // ... or use generic fallback
+ return wfMessage( 'echo-foreign-wiki-lang', $wikiName, $langName )->text();
+ }
+ }
+}
diff --git a/Echo/includes/ForeignWikiRequest.php b/Echo/includes/ForeignWikiRequest.php
new file mode 100644
index 00000000..c79ccdd7
--- /dev/null
+++ b/Echo/includes/ForeignWikiRequest.php
@@ -0,0 +1,164 @@
+<?php
+
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\Session\SessionManager;
+
+class EchoForeignWikiRequest {
+
+ /**
+ * @param User $user User object
+ * @param array $params Request parameters
+ * @param array $wikis Wikis to send the request to
+ * @param string $wikiParam Parameter name to set to the name of the wiki
+ */
+ public function __construct( User $user, array $params, array $wikis, $wikiParam = null ) {
+ $this->user = $user;
+ $this->params = $params;
+ $this->wikis = $wikis;
+ $this->wikiParam = $wikiParam;
+ }
+
+ /**
+ * Execute the request
+ * @return array [ wiki => result ]
+ */
+ public function execute() {
+ if ( !$this->canUseCentralAuth() ) {
+ return [];
+ }
+
+ $reqs = $this->getRequestParams();
+ return $this->doRequests( $reqs );
+ }
+
+ protected function getCentralId( $user ) {
+ $lookup = CentralIdLookup::factory();
+ $id = $lookup->centralIdFromLocalUser( $user, CentralIdLookup::AUDIENCE_RAW );
+ return $id;
+ }
+
+ protected function canUseCentralAuth() {
+ global $wgFullyInitialised, $wgUser;
+
+ return $wgFullyInitialised &&
+ $wgUser->isSafeToLoad() &&
+ $this->user->isSafeToLoad() &&
+ SessionManager::getGlobalSession()->getProvider() instanceof CentralAuthSessionProvider &&
+ $this->getCentralId( $this->user ) !== 0;
+ }
+
+ /**
+ * Returns CentralAuth token, or null on failure.
+ *
+ * @param User $user
+ * @return string|null
+ */
+ protected function getCentralAuthToken( User $user ) {
+ $context = new RequestContext;
+ $context->setRequest( new FauxRequest( [ 'action' => 'centralauthtoken' ] ) );
+ $context->setUser( $user );
+
+ $api = new ApiMain( $context );
+
+ try {
+ $api->execute();
+
+ return $api->getResult()->getResultData( [ 'centralauthtoken', 'centralauthtoken' ] );
+ } catch ( Exception $ex ) {
+ LoggerFactory::getInstance( 'Echo' )->debug(
+ 'Exception when fetching CentralAuth token: wiki: {wiki}, userName: {userName}, userId: {userId}, centralId: {centralId}, exception: {exception}',
+ [
+ 'wiki' => wfWikiID(),
+ 'userName' => $user->getName(),
+ 'userId' => $user->getId(),
+ 'centralId' => $this->getCentralId( $user ),
+ 'exception' => $ex,
+ ]
+ );
+
+ MWExceptionHandler::logException( $ex );
+
+ return null;
+ }
+ }
+
+ /**
+ * @return array
+ */
+ protected function getRequestParams() {
+ $apis = EchoForeignNotifications::getApiEndpoints( $this->wikis );
+ if ( !$apis ) {
+ return [];
+ }
+
+ $reqs = [];
+ foreach ( $apis as $wiki => $api ) {
+ $reqs[$wiki] = [
+ 'method' => 'GET',
+ 'url' => $api['url'],
+ 'query' => $this->getQueryParams( $wiki ),
+ ];
+ }
+
+ return $reqs;
+ }
+
+ /**
+ * @param string $wiki Wiki name
+ * @return array
+ */
+ protected function getQueryParams( $wiki ) {
+ $extraParams = [];
+ if ( $this->wikiParam ) {
+ // Only request data from that specific wiki, or they'd all spawn
+ // cross-wiki api requests...
+ $extraParams[$this->wikiParam] = $wiki;
+ }
+
+ return [
+ 'centralauthtoken' => $this->getCentralAuthToken( $this->user ),
+ // once all the results are gathered & merged, they'll be output in the
+ // user requested format
+ // but this is going to be an internal request & we don't want those
+ // results in the format the user requested but in a fixed format that
+ // we can interpret here
+ 'format' => 'json',
+ ] + $extraParams + $this->params;
+ }
+
+ /**
+ * @param array $reqs API request params
+ * @return array
+ * @throws Exception
+ */
+ protected function doRequests( array $reqs ) {
+ $http = new MultiHttpClient( [] );
+ $responses = $http->runMulti( $reqs );
+
+ $results = [];
+ foreach ( $responses as $wiki => $response ) {
+ $statusCode = $response['response']['code'];
+
+ if ( $statusCode >= 200 && $statusCode <= 299 ) {
+ $parsed = json_decode( $response['response']['body'], true );
+ if ( $parsed ) {
+ $results[$wiki] = $parsed;
+ }
+ }
+
+ if ( !isset( $results[$wiki] ) ) {
+ LoggerFactory::getInstance( 'Echo' )->warning(
+ 'Failed to fetch API response from {wiki}. Error code {code}',
+ [
+ 'wiki' => $wiki,
+ 'code' => $response['response']['code'],
+ 'response' => $response['response']['body'],
+ 'request' => $reqs[$wiki],
+ ]
+ );
+ }
+ }
+
+ return $results;
+ }
+}
diff --git a/Echo/includes/NotifUser.php b/Echo/includes/NotifUser.php
index 722376d5..d55207c1 100644
--- a/Echo/includes/NotifUser.php
+++ b/Echo/includes/NotifUser.php
@@ -1,4 +1,5 @@
<?php
+use MediaWiki\MediaWikiServices;
/**
* Entity that represents a notification target user
@@ -13,7 +14,7 @@ class MWEchoNotifUser {
/**
* Object cache
- * @var BagOStuff
+ * @var WANObjectCache
*/
private $cache;
@@ -36,17 +37,41 @@ class MWEchoNotifUser {
private $targetPageMapper;
/**
+ * @var EchoForeignNotifications
+ */
+ private $foreignNotifications = null;
+
+ /**
+ * @var array
+ */
+ private $cached;
+
+ /**
+ * @var array|null
+ */
+ private $mForeignData = null;
+
+ // The max notification count shown in badge
+
+ // The max number shown in bundled message, eg, <user> and 99+ others <action>.
+ // This is really a totally separate thing, and could be its own constant.
+
+ // WARNING: If you change this, you should also change all references in the
+ // i18n messages (100 and 99) in all repositories using Echo.
+ const MAX_BADGE_COUNT = 99;
+
+ /**
* Usually client code doesn't need to initialize the object directly
* because it could be obtained from factory method newFromUser()
* @param User $user
- * @param BagOStuff $cache
+ * @param WANObjectCache $cache
* @param EchoUserNotificationGateway $userNotifGateway
* @param EchoNotificationMapper $notifMapper
* @param EchoTargetPageMapper $targetPageMapper
*/
public function __construct(
User $user,
- BagOStuff $cache,
+ WANObjectCache $cache,
EchoUserNotificationGateway $userNotifGateway,
EchoNotificationMapper $notifMapper,
EchoTargetPageMapper $targetPageMapper
@@ -60,7 +85,7 @@ class MWEchoNotifUser {
/**
* Factory method
- * @param $user User
+ * @param User $user
* @throws MWException
* @return MWEchoNotifUser
*/
@@ -68,9 +93,10 @@ class MWEchoNotifUser {
if ( $user->isAnon() ) {
throw new MWException( 'User must be logged in to view notification!' );
}
- global $wgMemc;
+
return new MWEchoNotifUser(
- $user, $wgMemc,
+ $user,
+ MediaWikiServices::getInstance()->getMainWANObjectCache(),
new EchoUserNotificationGateway( $user, MWEchoDbFactory::newFromDefault() ),
new EchoNotificationMapper(),
new EchoTargetPageMapper()
@@ -120,11 +146,11 @@ class MWEchoNotifUser {
/**
* Memcache key for talk notification
+ * @return string
*/
public function getTalkNotificationCacheKey() {
- global $wgEchoConfig;
-
- return wfMemcKey( 'echo-new-talk-notification', $this->mUser->getId(), $wgEchoConfig['version'] );
+ global $wgEchoCacheVersion;
+ return wfMemcKey( 'echo-new-talk-notification', $this->mUser->getId(), $wgEchoCacheVersion );
}
/**
@@ -132,9 +158,7 @@ class MWEchoNotifUser {
* @return bool
*/
public function notifCountHasReachedMax() {
- global $wgEchoMaxNotificationCount;
-
- if ( $this->getNotificationCount() > $wgEchoMaxNotificationCount ) {
+ if ( $this->getLocalNotificationCount() >= self::MAX_BADGE_COUNT ) {
return true;
} else {
return false;
@@ -144,7 +168,7 @@ class MWEchoNotifUser {
/**
* Get message count for this user.
*
- * @param boolean $cached Set to false to bypass the cache. (Optional. Defaults to true)
+ * @param bool $cached Set to false to bypass the cache. (Optional. Defaults to true)
* @param int $dbSource Use master or slave database to pull count (Optional. Defaults to DB_SLAVE)
* @return int
*/
@@ -155,7 +179,7 @@ class MWEchoNotifUser {
/**
* Get alert count for this user.
*
- * @param boolean $cached Set to false to bypass the cache. (Optional. Defaults to true)
+ * @param bool $cached Set to false to bypass the cache. (Optional. Defaults to true)
* @param int $dbSource Use master or slave database to pull count (Optional. Defaults to DB_SLAVE)
* @return int
*/
@@ -163,75 +187,40 @@ class MWEchoNotifUser {
return $this->getNotificationCount( $cached, $dbSource, EchoAttributeManager::ALERT );
}
- /**
- * Get the memcache key for 'has ever had messages' value
- * @return string
- */
- private function getHasMessagesKey() {
- global $wgEchoConfig;
- return wfMemcKey( 'echo', 'user', 'had', 'messages', $this->mUser->getId(), $wgEchoConfig['version'] );
- }
-
- /**
- * Check whether the user has ever had messages.
- *
- * @param boolean $cached Set to false to bypass the cache. (Optional. Defaults to true)
- * @return boolean User has received messages
- */
- public function hasMessages( $cached = true ) {
- global $wgEchoConfig;
- $section = EchoAttributeManager::MESSAGE;
-
- $memcKey = $this->getHasMessagesKey();
- if ( $cached ) {
- $data = $this->cache->get( $memcKey );
- if ( $data !== false && $data !== null ) {
- return (bool)$data;
- }
- }
- $attributeManager = EchoAttributeManager::newFromGlobalVars();
- $eventTypesToLoad = $attributeManager->getUserEnabledEventsbySections( $this->mUser, 'web', array( $section ) );
-
- $count = count( $this->notifMapper->fetchByUser( $this->mUser, 1, 0, $eventTypesToLoad ) );
-
- $result = (int)( $count > 0 );
- $this->cache->set( $memcKey, $result, 86400 );
-
- return (bool)$result;
- }
-
- /**
- * Cache the fact that the user has messages.
- * This is used after the user receives a message, making the system skip the actual test
- * of whether they have messages against the database at all.
- */
- public function cacheHasMessages() {
- $this->cache->set( $this->getHasMessagesKey(), 1, 86400 );
+ public function getLocalNotificationCount( $cached = true, $dbSource = DB_SLAVE, $section = EchoAttributeManager::ALL ) {
+ return $this->getNotificationCount( $cached, $dbSource, $section, false );
}
/**
* Retrieves number of unread notifications that a user has, would return
- * $wgEchoMaxNotificationCount + 1 at most
+ * MWEchoNotifUser::MAX_BADGE_COUNT + 1 at most.
+ *
+ * If $wgEchoCrossWikiNotifications is disabled, the $global parameter is ignored.
*
- * @param boolean $cached Set to false to bypass the cache. (Optional. Defaults to true)
+ * @param bool $cached Set to false to bypass the cache. (Optional. Defaults to true)
* @param int $dbSource Use master or slave database to pull count (Optional. Defaults to DB_SLAVE)
* @param string $section Notification section
+ * @param bool|string $global Whether to include foreign notifications. If set to 'preference', uses the user's preference.
* @return int
*/
- public function getNotificationCount( $cached = true, $dbSource = DB_SLAVE, $section = EchoAttributeManager::ALL ) {
- global $wgEchoConfig;
-
+ public function getNotificationCount( $cached = true, $dbSource = DB_SLAVE, $section = EchoAttributeManager::ALL, $global = 'preference' ) {
if ( $this->mUser->isAnon() ) {
return 0;
}
- $memcKey = wfMemcKey(
- 'echo-notification-count' . ( $section === EchoAttributeManager::ALL ? '' : ( '-' . $section ) ),
- $this->mUser->getId(),
- $wgEchoConfig['version']
- );
+ global $wgEchoCrossWikiNotifications;
+ if ( !$wgEchoCrossWikiNotifications ) {
+ // Ignore the $global parameter
+ $global = false;
+ }
+
+ if ( $global === 'preference' ) {
+ $global = $this->getForeignNotifications()->isEnabledByUser();
+ }
+
+ $memcKey = $this->getMemcKey( 'echo-notification-count' . ( $section === EchoAttributeManager::ALL ? '' : ( '-' . $section ) ), $global );
if ( $cached ) {
- $data = $this->cache->get( $memcKey );
+ $data = $this->getFromCache( $memcKey );
if ( $data !== false && $data !== null ) {
return (int)$data;
}
@@ -241,32 +230,36 @@ class MWEchoNotifUser {
if ( $section === EchoAttributeManager::ALL ) {
$eventTypesToLoad = $attributeManager->getUserEnabledEvents( $this->mUser, 'web' );
} else {
- $eventTypesToLoad = $attributeManager->getUserEnabledEventsbySections( $this->mUser, 'web', array( $section ) );
+ $eventTypesToLoad = $attributeManager->getUserEnabledEventsbySections( $this->mUser, 'web', [ $section ] );
}
- $count = $this->userNotifGateway->getNotificationCount( $dbSource, $eventTypesToLoad );
- $this->cache->set( $memcKey, $count, 86400 );
+ $count = (int)$this->userNotifGateway->getCappedNotificationCount( $dbSource, $eventTypesToLoad, self::MAX_BADGE_COUNT + 1 );
- return (int)$count;
+ if ( $global ) {
+ $count = self::capNotificationCount( $count + $this->getForeignCount( $section ) );
+ }
+
+ $this->setInCache( $memcKey, $count, 86400 );
+ return $count;
}
/**
- * Get the unread timestamp of the latest alert
+ * Get the timestamp of the latest unread alert
*
- * @param boolean $cached Set to false to bypass the cache. (Optional. Defaults to true)
+ * @param bool $cached Set to false to bypass the cache. (Optional. Defaults to true)
* @param int $dbSource Use master or slave database to pull count (Optional. Defaults to DB_SLAVE)
- * @return int
+ * @return bool|MWTimestamp Timestamp of latest unread alert, or false if there are no unread alerts.
*/
public function getLastUnreadAlertTime( $cached = true, $dbSource = DB_SLAVE ) {
return $this->getLastUnreadNotificationTime( $cached, $dbSource, EchoAttributeManager::ALERT );
}
/**
- * Get the unread timestamp of the latest message
+ * Get the timestamp of the latest unread message
*
- * @param boolean $cached Set to false to bypass the cache. (Optional. Defaults to true)
+ * @param bool $cached Set to false to bypass the cache. (Optional. Defaults to true)
* @param int $dbSource Use master or slave database to pull count (Optional. Defaults to DB_SLAVE)
- * @return int
+ * @return bool|MWTimestamp
*/
public function getLastUnreadMessageTime( $cached = true, $dbSource = DB_SLAVE ) {
return $this->getLastUnreadNotificationTime( $cached, $dbSource, EchoAttributeManager::MESSAGE );
@@ -275,56 +268,89 @@ class MWEchoNotifUser {
/**
* Returns the timestamp of the last unread notification.
*
- * @param boolean $cached Set to false to bypass the cache. (Optional. Defaults to true)
+ * If $wgEchoCrossWikiNotifications is disabled, the $global parameter is ignored.
+ *
+ * @param bool $cached Set to false to bypass the cache. (Optional. Defaults to true)
* @param int $dbSource Use master or slave database to pull count (Optional. Defaults to DB_SLAVE)
* @param string $section Notification section
- * @return bool|MWTimestamp Timestamp of last notification, or false if there is none
+ * @param bool|string $global Whether to include foreign notifications. If set to 'preference', uses the user's preference.
+ * @return bool|MWTimestamp Timestamp of latest unread message, or false if there are no unread messages.
*/
- public function getLastUnreadNotificationTime( $cached = true, $dbSource = DB_SLAVE, $section = EchoAttributeManager::ALL ) {
- global $wgEchoConfig;
-
+ public function getLastUnreadNotificationTime( $cached = true, $dbSource = DB_SLAVE, $section = EchoAttributeManager::ALL, $global = 'preference' ) {
if ( $this->mUser->isAnon() ) {
return false;
}
- $memcKey = wfMemcKey(
- 'echo-notification-timestamp' . ( $section === EchoAttributeManager::ALL ? '' : ( '-' . $section ) ),
- $this->mUser->getId(),
- $wgEchoConfig['version']
- );
+ global $wgEchoCrossWikiNotifications;
+ if ( !$wgEchoCrossWikiNotifications ) {
+ // Ignore the $global parameter
+ $global = false;
+ }
+
+ if ( $global === 'preference' ) {
+ $global = $this->getForeignNotifications()->isEnabledByUser();
+ }
+
+ $memcKey = $this->getMemcKey( 'echo-notification-timestamp' . ( $section === EchoAttributeManager::ALL ? '' : ( '-' . $section ) ), $global );
// read from cache, if allowed
if ( $cached ) {
- $timestamp = $this->cache->get( $memcKey );
- if ( $timestamp !== false ) {
+ $timestamp = $this->getFromCache( $memcKey );
+ if ( $timestamp === -1 ) {
+ // -1 means the user has no notifications
+ return false;
+ } elseif ( $timestamp !== false ) {
return new MWTimestamp( $timestamp );
}
+ // else cache miss
}
+ $timestamp = false;
+
+ // Get timestamp of most recent local notification, if there is one
$attributeManager = EchoAttributeManager::newFromGlobalVars();
if ( $section === EchoAttributeManager::ALL ) {
$eventTypesToLoad = $attributeManager->getUserEnabledEvents( $this->mUser, 'web' );
} else {
- $eventTypesToLoad = $attributeManager->getUserEnabledEventsbySections( $this->mUser, 'web', array( $section ) );
+ $eventTypesToLoad = $attributeManager->getUserEnabledEventsbySections( $this->mUser, 'web', [ $section ] );
}
-
- $notifications = $this->notifMapper->fetchUnreadByUser( $this->mUser, 1, $eventTypesToLoad, $dbSource );
+ $notifications = $this->notifMapper->fetchUnreadByUser( $this->mUser, 1, null, $eventTypesToLoad, null, $dbSource );
if ( $notifications ) {
$notification = reset( $notifications );
- $timestamp = $notification->getTimestamp();
+ $timestamp = new MWTimestamp( $notification->getTimestamp() );
+ }
+
+ // Use timestamp of most recent foreign notification, if it's more recent
+ if ( $global ) {
+ $foreignTime = $this->getForeignTimestamp( $section );
+
+ if (
+ $foreignTime !== false &&
+ // $foreignTime < $timestamp = invert 0
+ // $foreignTime > $timestamp = invert 1
+ ( $timestamp === false || $foreignTime->diff( $timestamp )->invert === 1 )
+ ) {
+ $timestamp = $foreignTime;
+ }
+ }
- // store to cache & return
- $this->cache->set($memcKey, $timestamp, 86400);
- return new MWTimestamp( $timestamp );
+ if ( $timestamp === false ) {
+ // No notifications, so no timestamp
+ $returnValue = false;
+ $cacheValue = -1;
+ } else {
+ $returnValue = $timestamp;
+ $cacheValue = $timestamp->getTimestamp( TS_MW );
}
- return false;
+ $this->setInCache( $memcKey, $cacheValue, 86400 );
+ return $returnValue;
}
/**
* Mark one or more notifications read for a user.
- * @param $eventIds Array of event IDs to mark read
- * @return boolean
+ * @param array $eventIds Array of event IDs to mark read
+ * @return bool
*/
public function markRead( $eventIds ) {
$eventIds = array_filter( (array)$eventIds, 'is_numeric' );
@@ -334,20 +360,54 @@ class MWEchoNotifUser {
$res = $this->userNotifGateway->markRead( $eventIds );
if ( $res ) {
- // Delete records from echo_target_page
- $this->targetPageMapper->deleteByUserEvents( $this->mUser, $eventIds );
// Update notification count in cache
$this->resetNotificationCount( DB_MASTER );
// After this 'mark read', is there any unread edit-user-talk
// remaining? If not, we should clear the newtalk flag.
if ( $this->mUser->getNewtalk() ) {
- $unreadEditUserTalk = $this->notifMapper->fetchUnreadByUser( $this->mUser, 1, array( 'edit-user-talk' ), DB_MASTER );
+ $attributeManager = EchoAttributeManager::newFromGlobalVars();
+ $categoryMap = $attributeManager->getEventsByCategory();
+ $usertalkTypes = $categoryMap['edit-user-talk'];
+ $unreadEditUserTalk = $this->notifMapper->fetchUnreadByUser( $this->mUser, 1, null, $usertalkTypes, null, DB_MASTER );
if ( count( $unreadEditUserTalk ) === 0 ) {
$this->mUser->setNewtalk( false );
}
}
}
+
+ return $res;
+ }
+
+ /**
+ * Mark one or more notifications unread for a user.
+ * @param array $eventIds Array of event IDs to mark unread
+ * @return bool
+ */
+ public function markUnRead( $eventIds ) {
+ $eventIds = array_filter( (array)$eventIds, 'is_numeric' );
+ if ( !$eventIds || wfReadOnly() ) {
+ return false;
+ }
+
+ $res = $this->userNotifGateway->markUnRead( $eventIds );
+ if ( $res ) {
+ // Update notification count in cache
+ $this->resetNotificationCount( DB_MASTER );
+
+ // After this 'mark unread', is there any unread edit-user-talk?
+ // If so, we should add the edit-user-talk flag
+ if ( !$this->mUser->getNewtalk() ) {
+ $attributeManager = EchoAttributeManager::newFromGlobalVars();
+ $categoryMap = $attributeManager->getEventsByCategory();
+ $usertalkTypes = $categoryMap['edit-user-talk'];
+ $unreadEditUserTalk = $this->notifMapper->fetchUnreadByUser( $this->mUser, 1, null, $usertalkTypes, null, DB_MASTER );
+ if ( count( $unreadEditUserTalk ) > 0 ) {
+ $this->mUser->setNewtalk( true );
+ }
+ }
+ }
+
return $res;
}
@@ -359,9 +419,9 @@ class MWEchoNotifUser {
* across multiple tables, we would visit this later
*
* @param string[] $sections
- * @return boolean
+ * @return bool
*/
- public function markAllRead( array $sections = array( EchoAttributeManager::ALL ) ) {
+ public function markAllRead( array $sections = [ EchoAttributeManager::ALL ] ) {
if ( wfReadOnly() ) {
return false;
}
@@ -376,10 +436,10 @@ class MWEchoNotifUser {
$attributeManager = EchoAttributeManager::newFromGlobalVars();
$eventTypes = $attributeManager->getUserEnabledEventsbySections( $this->mUser, 'web', $sections );
- $notifs = $this->notifMapper->fetchUnreadByUser( $this->mUser, $wgEchoMaxUpdateCount, $eventTypes );
+ $notifs = $this->notifMapper->fetchUnreadByUser( $this->mUser, $wgEchoMaxUpdateCount, null, $eventTypes );
$eventIds = array_filter(
- array_map( function( EchoNotification $notif ) {
+ array_map( function ( EchoNotification $notif ) {
// This should not happen at all, but use 0 in
// such case so to keep the code running
if ( $notif->getEvent() ) {
@@ -393,42 +453,78 @@ class MWEchoNotifUser {
$res = $this->markRead( $eventIds );
if ( $res ) {
// Delete records from echo_target_page
- $this->targetPageMapper->deleteByUserEvents( $this->mUser, $eventIds );
+ /**
+ * Keep the 'echo_target_page' records so they can be used for moderation.
+ */
+ // $this->targetPageMapper->deleteByUserEvents( $this->mUser, $eventIds );
if ( count( $notifs ) < $wgEchoMaxUpdateCount ) {
$this->flagCacheWithNoTalkNotification();
}
}
+
return $res;
}
/**
- * Recalculates the number of notifications that a user has.
- * @param $dbSource int use master or slave database to pull count
+ * Invalidate cache and update echo_unread_wikis if x-wiki notifications is enabled
+ * NOTE: Consider calling this function from a deferred update since it may access the db
+ *
+ * @param int $dbSource Use master or replica database to pull count
*/
- public function resetNotificationCount( $dbSource = DB_SLAVE ) {
- // Reset notification count for all sections as well
- $this->getNotificationCount( false, $dbSource, EchoAttributeManager::ALL );
- $this->getNotificationCount( false, $dbSource, EchoAttributeManager::ALERT );
- $this->getNotificationCount( false, $dbSource, EchoAttributeManager::MESSAGE );
- // when notification count needs to be updated, last notification may have
- // changed too, so we need to invalidate that cache too
- $this->getLastUnreadNotificationTime( false, $dbSource, EchoAttributeManager::ALL );
- $this->getLastUnreadNotificationTime( false, $dbSource, EchoAttributeManager::ALERT );
- $this->getLastUnreadNotificationTime( false, $dbSource, EchoAttributeManager::MESSAGE );
- $this->mUser->invalidateCache();
+ public function resetNotificationCount( $dbSource = DB_REPLICA ) {
+ global $wgEchoCrossWikiNotifications;
+ if ( $wgEchoCrossWikiNotifications ) {
+ // Schedule an update to the echo_unread_wikis table
+ $uw = EchoUnreadWikis::newFromUser( $this->mUser );
+ if ( $uw ) {
+ $alertCount = $this->getNotificationCount( false, $dbSource, EchoAttributeManager::ALERT, false );
+ $msgCount = $this->getNotificationCount( false, $dbSource, EchoAttributeManager::MESSAGE, false );
+ $alertUnread = $this->getLastUnreadNotificationTime( false, $dbSource, EchoAttributeManager::ALERT, false );
+ $msgUnread = $this->getLastUnreadNotificationTime( false, $dbSource, EchoAttributeManager::MESSAGE, false );
+ $uw->updateCount( wfWikiID(), $alertCount, $alertUnread, $msgCount, $msgUnread );
+ }
+ }
+
+ $this->invalidateCache();
}
/**
- * Retrieves formatted number of unread notifications that a user has.
- * @param boolean $cached Set to false to bypass the cache. (Optional. Defaults to true)
- * @param int $dbSource Use master or slave database to pull count (Optional. Defaults to DB_SLAVE)
- * @param string $section
- * @return string
+ * Get the timestamp of the last time the global notification counts/timestamps were updated, if available.
+ *
+ * If the timestamp of the last update is not known, this will return the current timestamp.
+ * If the user is not attached, this will return false.
+ *
+ * @return string|false MW timestamp of the last update, or false if the user is not attached
*/
- public function getFormattedNotificationCount( $cached = true, $dbSource = DB_SLAVE, $section = EchoAttributeManager::ALL ) {
- return EchoNotificationController::formatNotificationCount(
- $this->getNotificationCount( $cached, $dbSource, $section )
- );
+ public function getGlobalUpdateTime() {
+ $key = $this->getGlobalMemcKey( 'echo-notification-updated' );
+ if ( $key === false ) {
+ return false;
+ }
+ return wfTimestamp( TS_MW, $this->cache->getCheckKeyTime( $key ) );
+ }
+
+ /**
+ * Invalidate user caches related to notification counts/timestamps.
+ *
+ * This bumps the local user's touched timestamp as well as the timestamp returned by getGlobalUpdateTime().
+ */
+ protected function invalidateCache() {
+ // Update the user touched timestamp for the local user
+ $this->mUser->invalidateCache();
+
+ $this->deleteFromCache( $this->getLocalKeys() );
+
+ global $wgEchoCrossWikiNotifications;
+ if ( $wgEchoCrossWikiNotifications ) {
+ $this->deleteFromCache( $this->getGlobalKeys() );
+
+ // Update the global touched timestamp
+ $key = $this->getGlobalMemcKey( 'echo-notification-updated' );
+ if ( $key ) {
+ $this->cache->touchCheckKey( $key );
+ }
+ }
}
/**
@@ -441,8 +537,259 @@ class MWEchoNotifUser {
if ( $wgAllowHTMLEmail ) {
return $this->mUser->getOption( 'echo-email-format' );
} else {
- return EchoHooks::EMAIL_FORMAT_PLAIN_TEXT;
+ return EchoEmailFormat::PLAIN_TEXT;
+ }
+ }
+
+ /**
+ * Get a cache entry from the cache, using a preloaded instance cache.
+ * @param string|false $memcKey Cache key returned by getMemcKey()
+ * @return mixed Cache value
+ */
+ protected function getFromCache( $memcKey ) {
+ // getMemcKey() can return false
+ if ( $memcKey === false ) {
+ return false;
+ }
+
+ // Populate the instance cache
+ if ( $this->cached === null ) {
+ $keys = $this->getPreloadKeys();
+ $this->cached = $this->cache->getMulti( $keys );
+ // also keep track of cache values that couldn't be found (getMulti
+ // omits them...)
+ $this->cached += array_fill_keys( $keys, false );
+ }
+
+ if ( isset( $this->cached[$memcKey] ) ) {
+ return $this->cached[$memcKey];
+ }
+
+ return $this->cache->get( $memcKey );
+ }
+
+ /**
+ * Set a cache entry both in the cache and in the instance cache.
+ * Use this to write to keys that were loaded with getFromCache().
+ * @param string|false $memcKey Cache key returned by getMemcKey()
+ * @param mixed $value Cache value to set
+ * @param int $expiry Expiry, see BagOStuff::set()
+ */
+ protected function setInCache( $memcKey, $value, $expiry ) {
+ // getMemcKey() can return false
+ if ( $memcKey === false ) {
+ return;
+ }
+
+ // Update the instance cache if it's already been populated
+ if ( $this->cached !== null ) {
+ $this->cached[$memcKey] = $value;
+ }
+
+ $this->cache->set( $memcKey, $value, $expiry );
+ }
+
+ protected function deleteFromCache( $keys ) {
+ foreach ( $keys as $key ) {
+ // Update the instance cache if it's already been populated
+ if ( $this->cached !== null ) {
+ unset( $this->cached[$key] );
+ }
+ $this->cache->delete( $key );
+ }
+ }
+
+ /**
+ * Array of memcached keys to load at once.
+ *
+ * @return array
+ */
+ protected function getPreloadKeys() {
+ return array_merge(
+ $this->getLocalKeys(),
+ $this->getGlobalKeys()
+ );
+ }
+
+ protected function getLocalKeys() {
+ return array_filter( array_map( [ $this, 'getMemcKey' ], $this->getKeySeeds() ) );
+ }
+
+ protected function getGlobalKeys() {
+ return array_filter( array_map( [ $this, 'getGlobalMemcKey' ], $this->getKeySeeds() ) );
+ }
+
+ protected function getKeySeeds() {
+ return [
+ 'echo-notification-timestamp',
+ 'echo-notification-timestamp-' . EchoAttributeManager::MESSAGE,
+ 'echo-notification-timestamp-' . EchoAttributeManager::ALERT,
+ 'echo-notification-count',
+ 'echo-notification-count-' . EchoAttributeManager::MESSAGE,
+ 'echo-notification-count-' . EchoAttributeManager::ALERT,
+ ];
+ }
+
+ /**
+ * Build a memcached key.
+ * @param string $key Key, typically prefixed with echo-notification-
+ * @param bool $global If true, return a global memc key; if false, return one local to this wiki
+ * @return string|false Memcached key, or false if one could not be generated
+ */
+ protected function getMemcKey( $key, $global = false ) {
+ global $wgEchoCacheVersion;
+ if ( !$global ) {
+ return wfMemcKey( $key, $this->mUser->getId(), $wgEchoCacheVersion );
+ }
+
+ $lookup = CentralIdLookup::factory();
+ $globalId = $lookup->centralIdFromLocalUser( $this->mUser, CentralIdLookup::AUDIENCE_RAW );
+ if ( !$globalId ) {
+ return false;
+ }
+ return wfGlobalCacheKey( $key, $globalId, $wgEchoCacheVersion );
+ }
+
+ protected function getGlobalMemcKey( $key ) {
+ return $this->getMemcKey( $key, true );
+ }
+
+ /**
+ * Lazy-construct an EchoForeignNotifications instance. This instance is force-enabled, so it
+ * returns information about cross-wiki notifications even if the user has them disabled.
+ * @return EchoForeignNotifications
+ */
+ protected function getForeignNotifications() {
+ if ( !$this->foreignNotifications ) {
+ $this->foreignNotifications = new EchoForeignNotifications( $this->mUser, true );
+ }
+ return $this->foreignNotifications;
+ }
+
+ /**
+ * Get data about foreign notifications from the foreign wikis' APIs.
+ *
+ * This is used when $wgEchoSectionTransition or $wgEchoBundleTransition is enabled,
+ * to deal with untrustworthy echo_unread_wikis entries. This method fetches the list of
+ * wikis that have any unread notifications at all from the echo_unread_wikis table, then
+ * queries their APIs to find the per-section counts and timestamps for those wikis.
+ *
+ * The results of this function are cached in the NotifUser object.
+ * @return array [ (str) wiki => [ (str) section => [ 'count' => (int) count, 'timestamp' => (str) ts ] ] ]
+ */
+ protected function getForeignData() {
+ if ( $this->mForeignData ) {
+ return $this->mForeignData;
+ }
+
+ $potentialWikis = $this->getForeignNotifications()->getWikis( EchoAttributeManager::ALL );
+ $foreignReq = new EchoForeignWikiRequest(
+ $this->mUser,
+ [
+ 'action' => 'query',
+ 'meta' => 'notifications',
+ 'notprop' => 'count|list',
+ 'notgroupbysection' => '1',
+ 'notunreadfirst' => '1',
+ ],
+ $potentialWikis,
+ 'notwikis'
+ );
+ $foreignResults = $foreignReq->execute();
+
+ $this->mForeignData = [];
+ foreach ( $foreignResults as $wiki => $result ) {
+ if ( !isset( $result['query']['notifications'] ) ) {
+ continue;
+ }
+ $data = $result['query']['notifications'];
+ foreach ( EchoAttributeManager::$sections as $section ) {
+ if ( isset( $data[$section]['rawcount'] ) ) {
+ $this->mForeignData[$wiki][$section]['count'] = $data[$section]['rawcount'];
+ }
+ if ( isset( $data[$section]['list'][0] ) ) {
+ $this->mForeignData[$wiki][$section]['timestamp'] = $data[$section]['list'][0]['timestamp']['mw'];
+ }
+ }
+ }
+ return $this->mForeignData;
+ }
+
+ protected function getForeignCount( $section = EchoAttributeManager::ALL ) {
+ global $wgEchoSectionTransition, $wgEchoBundleTransition;
+ $count = 0;
+ if (
+ // In section transition mode, we don't trust the individual echo_unread_wikis rows
+ // but we do trust that alert+message=all. In bundle transition mode, we don't trust
+ // that either, but we do trust that wikis with rows in the table have unread notifications
+ // and wikis without rows in the table don't.
+ ( $wgEchoSectionTransition && $section !== EchoAttributeManager::ALL ) ||
+ $wgEchoBundleTransition
+ ) {
+ $foreignData = $this->getForeignData();
+ foreach ( $foreignData as $data ) {
+ if ( $section === EchoAttributeManager::ALL ) {
+ foreach ( $data as $subData ) {
+ if ( isset( $subData['count'] ) ) {
+ $count += $subData['count'];
+ }
+ }
+ } elseif ( isset( $data[$section]['count'] ) ) {
+ $count += $data[$section]['count'];
+ }
+ }
+ } else {
+ $count += $this->getForeignNotifications()->getCount( $section );
+ }
+ return self::capNotificationCount( $count );
+ }
+
+ protected function getForeignTimestamp( $section = EchoAttributeManager::ALL ) {
+ global $wgEchoSectionTransition, $wgEchoBundleTransition;
+
+ if (
+ // In section transition mode, we don't trust the individual echo_unread_wikis rows
+ // but we do trust that alert+message=all. In bundle transition mode, we don't trust
+ // that either, but we do trust that wikis with rows in the table have unread notifications
+ // and wikis without rows in the table don't.
+ ( $wgEchoSectionTransition && $section !== EchoAttributeManager::ALL ) ||
+ $wgEchoBundleTransition
+ ) {
+ $foreignTime = false;
+ $foreignData = $this->getForeignData();
+ foreach ( $foreignData as $data ) {
+ if ( $section === EchoAttributeManager::ALL ) {
+ foreach ( $data as $subData ) {
+ if ( isset( $subData['timestamp'] ) ) {
+ $wikiTime = new MWTimestamp( $data[$section]['timestamp'] );
+ // $wikiTime > $foreignTime = invert 1
+ if ( $foreignTime === false || $wikiTime->diff( $foreignTime )->invert === 1 ) {
+ $foreignTime = $wikiTime;
+ }
+ }
+ }
+ } elseif ( isset( $data[$section]['timestamp'] ) ) {
+ $wikiTime = new MWTimestamp( $data[$section]['timestamp'] );
+ // $wikiTime > $foreignTime = invert 1
+ if ( $foreignTime === false || $wikiTime->diff( $foreignTime )->invert === 1 ) {
+ $foreignTime = $wikiTime;
+ }
+ }
+ }
+ } else {
+ $foreignTime = $this->getForeignNotifications()->getTimestamp( $section );
}
+ return $foreignTime;
}
+ /**
+ * Helper function to produce the capped number of notifications
+ * based on the value of MWEchoNotifUser::MAX_BADGE_COUNT
+ *
+ * @param int $number Raw notification count to cap
+ * @return int Capped notification count
+ */
+ public static function capNotificationCount( $number ) {
+ return min( $number, self::MAX_BADGE_COUNT + 1 );
+ }
}
diff --git a/Echo/includes/Notifier.php b/Echo/includes/Notifier.php
new file mode 100644
index 00000000..6a05dcab
--- /dev/null
+++ b/Echo/includes/Notifier.php
@@ -0,0 +1,135 @@
+<?php
+
+// @todo Fill in
+class EchoNotifier {
+ /**
+ * Record an EchoNotification for an EchoEvent
+ * Currently used for web-based notifications.
+ *
+ * @param User $user User to notify.
+ * @param EchoEvent $event EchoEvent to notify about.
+ */
+ public static function notifyWithNotification( $user, $event ) {
+ // Only create the notification if the user wants to receive that type
+ // of notification and they are eligible to receive it. See bug 47664.
+ $attributeManager = EchoAttributeManager::newFromGlobalVars();
+ $userWebNotifications = $attributeManager->getUserEnabledEvents( $user, 'web' );
+ if ( !in_array( $event->getType(), $userWebNotifications ) ) {
+ return;
+ }
+
+ EchoNotification::create( [ 'user' => $user, 'event' => $event ] );
+
+ MWEchoEventLogging::logSchemaEcho( $user, $event, 'web' );
+ }
+
+ /**
+ * Send a Notification to a user by email
+ *
+ * @param User $user User to notify.
+ * @param EchoEvent $event EchoEvent to notify about.
+ * @return bool
+ */
+ public static function notifyWithEmail( $user, $event ) {
+ global $wgEnableEmail, $wgBlockDisablesLogin;
+
+ if (
+ // Email is globally disabled
+ !$wgEnableEmail ||
+ // User does not have a valid and confirmed email address
+ !$user->isEmailConfirmed() ||
+ // User has disabled Echo emails
+ $user->getOption( 'echo-email-frequency' ) < 0 ||
+ // User is blocked and cannot log in (T199993)
+ ( $wgBlockDisablesLogin && $user->isBlocked() )
+ ) {
+ return false;
+ }
+
+ // Final check on whether to send email for this user & event
+ if ( !Hooks::run( 'EchoAbortEmailNotification', [ $user, $event ] ) ) {
+ return false;
+ }
+
+ $attributeManager = EchoAttributeManager::newFromGlobalVars();
+ $userEmailNotifications = $attributeManager->getUserEnabledEvents( $user, 'email' );
+ // See if the user wants to receive emails for this category or the user is eligible to receive this email
+ if ( in_array( $event->getType(), $userEmailNotifications ) ) {
+ global $wgEchoEnableEmailBatch, $wgEchoNotifications, $wgNotificationSender, $wgNotificationReplyName;
+
+ $priority = $attributeManager->getNotificationPriority( $event->getType() );
+
+ $bundleString = $bundleHash = '';
+
+ // We should have bundling for email digest as long as either web or email bundling is on, for example, talk page
+ // email bundling is off, but if a user decides to receive email digest, we should bundle those messages
+ if ( !empty( $wgEchoNotifications[$event->getType()]['bundle']['web'] ) || !empty( $wgEchoNotifications[$event->getType()]['bundle']['email'] ) ) {
+ Hooks::run( 'EchoGetBundleRules', [ $event, &$bundleString ] );
+ }
+ if ( $bundleString ) {
+ $bundleHash = md5( $bundleString );
+ }
+
+ MWEchoEventLogging::logSchemaEcho( $user, $event, 'email' );
+
+ // email digest notification ( weekly or daily )
+ if ( $wgEchoEnableEmailBatch && $user->getOption( 'echo-email-frequency' ) > 0 ) {
+ // always create a unique event hash for those events don't support bundling
+ // this is mainly for group by
+ if ( !$bundleHash ) {
+ $bundleHash = md5( $event->getType() . '-' . $event->getId() );
+ }
+ MWEchoEmailBatch::addToQueue( $user->getId(), $event->getId(), $priority, $bundleHash );
+
+ return true;
+ }
+
+ // instant email notification
+ $toAddress = MailAddress::newFromUser( $user );
+ $fromAddress = new MailAddress( $wgNotificationSender, EchoHooks::getNotificationSenderName() );
+ $replyAddress = new MailAddress( $wgNotificationSender, $wgNotificationReplyName );
+ // Since we are sending a single email, should set the bundle hash to null
+ // if it is set with a value from somewhere else
+ $event->setBundleHash( null );
+ $email = self::generateEmail( $event, $user );
+ if ( !$email ) {
+ return false;
+ }
+ $subject = $email['subject'];
+ $body = $email['body'];
+ $options = [ 'replyTo' => $replyAddress ];
+
+ UserMailer::send( $toAddress, $fromAddress, $subject, $body, $options );
+ MWEchoEventLogging::logSchemaEchoMail( $user, 'single' );
+ }
+
+ return true;
+ }
+
+ /**
+ * @param EchoEvent $event
+ * @param User $user
+ * @return bool|array An array of 'subject' and 'body', or false if things went wrong
+ */
+ private static function generateEmail( EchoEvent $event, User $user ) {
+ $emailFormat = MWEchoNotifUser::newFromUser( $user )->getEmailFormat();
+ $lang = wfGetLangObj( $user->getOption( 'language' ) );
+ $formatter = new EchoPlainTextEmailFormatter( $user, $lang );
+ $content = $formatter->format( $event );
+ if ( !$content ) {
+ return false;
+ }
+
+ if ( $emailFormat === EchoEmailFormat::HTML ) {
+ $htmlEmailFormatter = new EchoHtmlEmailFormatter( $user, $lang );
+ $htmlContent = $htmlEmailFormatter->format( $event );
+ $multipartBody = [
+ 'text' => $content['body'],
+ 'html' => $htmlContent['body']
+ ];
+ $content['body'] = $multipartBody;
+ }
+
+ return $content;
+ }
+}
diff --git a/Echo/includes/ResourceLoaderEchoImageModule.php b/Echo/includes/ResourceLoaderEchoImageModule.php
new file mode 100644
index 00000000..c0b103a4
--- /dev/null
+++ b/Echo/includes/ResourceLoaderEchoImageModule.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * A sibling of secret special sauce.
+ * @see ResourceLoaderOOUIImageModule for familial resemblence
+ */
+class ResourceLoaderEchoImageModule extends ResourceLoaderImageModule {
+ protected function loadFromDefinition() {
+ if ( $this->definition === null ) {
+ return;
+ }
+
+ // Check to make sure icons are set
+ if ( !isset( $this->definition['icons'] ) ) {
+ throw new MWException( 'Icons must be set.' );
+ }
+
+ $images = [];
+ foreach ( $this->definition['icons'] as $iconName => $definition ) {
+ // FIXME: We also have a 'site' icon which is "magical"
+ // and uses witchcraft and should be handled specifically
+ if ( isset( $definition[ 'path' ] ) ) {
+ if ( is_array( $definition[ 'path' ] ) ) {
+ $paths = [];
+ foreach ( $definition[ 'path' ] as $dir => $p ) {
+ // Has both rtl and ltr definitions
+ $paths[ $dir ] = $p;
+ }
+ } else {
+ $paths = $definition[ 'path' ];
+ }
+
+ if ( !empty( $paths ) ) {
+ $images[ $iconName ][ 'file' ] = $paths;
+ }
+ }
+ }
+
+ $this->definition[ 'images' ] = $images;
+ $this->definition[ 'selector' ] = '.oo-ui-icon-{name}';
+ // Parent
+ parent::loadFromDefinition();
+ }
+}
diff --git a/Echo/includes/SeenTime.php b/Echo/includes/SeenTime.php
index b0134a68..3d521112 100644
--- a/Echo/includes/SeenTime.php
+++ b/Echo/includes/SeenTime.php
@@ -10,7 +10,7 @@ class EchoSeenTime {
* Allowed notification types
* @var array
*/
- private static $allowedTypes = array( 'alert', 'message' );
+ private static $allowedTypes = [ 'alert', 'message' ];
/**
* @var User
@@ -18,16 +18,10 @@ class EchoSeenTime {
private $user;
/**
- * @var BagOStuff
- */
- private $cache;
-
- /**
* @param User $user A logged in user
*/
private function __construct( User $user ) {
$this->user = $user;
- $this->cache = ObjectCache::getInstance( 'db-replicated' );
}
/**
@@ -39,42 +33,90 @@ class EchoSeenTime {
}
/**
- * @param int $flags BagOStuff::READ_LATEST to use the master
- * @return string|bool false if no stored time
+ * Hold onto a cache for our operations. Static so it can reuse the same
+ * in-process cache in different instances.
+ *
+ * @return BagOStuff
+ */
+ private static function cache() {
+ static $c = null;
+
+ // Use main stash for persistent storage, and
+ // wrap it with CachedBagOStuff for an in-process
+ // cache. (T144534)
+ if ( $c === null ) {
+ $c = new CachedBagOStuff(
+ ObjectCache::getMainStashInstance()
+ );
+ }
+
+ return $c;
+ }
+
+ /**
+ * @param string $type Type of seen time to get
+ * @param int $format Format to return time in, defaults to TS_MW
+ * @return string|bool Timestamp in specified format, or false if no stored time
*/
- public function getTime( $type = 'all', $flags = 0 ) {
- $vals = array();
+ public function getTime( $type = 'all', $format = TS_MW ) {
+ $vals = [];
if ( $type === 'all' ) {
foreach ( self::$allowedTypes as $allowed ) {
- $vals[] = $this->getTime( $allowed );
+ // Use TS_MW, then convert later, so max works properly for
+ // all formats.
+ $vals[] = $this->getTime( $allowed, TS_MW );
}
- return max( $vals );
+
+ return wfTimestamp( $format, min( $vals ) );
}
- if ( $this->validateType( $type ) ) {
- $key = wfMemcKey( 'echo', 'seen', $type, 'time', $this->user->getId() );
- $cas = 0; // Unused, but we have to pass something by reference
- $data = $this->cache->get( $key, $cas, $flags );
- if ( $data === false ) {
- // Check if the user still has it set in their preferences
- $data = $this->user->getOption( 'echo-seen-time', false );
- }
+ if ( !$this->validateType( $type ) ) {
+ return false;
}
- return $data;
+ $data = self::cache()->get( $this->getMemcKey( $type ) );
+
+ if ( $data === false ) {
+ // Check if the user still has it set in their preferences
+ $data = $this->user->getOption( 'echo-seen-time', false );
+ }
+
+ if ( $data === false ) {
+ // There is still no time set, so set time to the UNIX epoch.
+ // We can't remember their real seen time, so reset everything to
+ // unseen.
+ $data = wfTimestamp( TS_MW, 1 );
+ $this->setTime( $data, $type );
+ }
+ return wfTimestamp( $format, $data );
}
+ /**
+ * Sets the seen time
+ *
+ * @param string $time Time, in TS_MW format
+ * @param string $type Type of seen time to set
+ */
public function setTime( $time, $type = 'all' ) {
if ( $type === 'all' ) {
foreach ( self::$allowedTypes as $allowed ) {
$this->setTime( $time, $allowed );
}
- } else {
- if ( $this->validateType( $type ) ) {
- $key = wfMemcKey( 'echo', 'seen', $type, 'time', $this->user->getId() );
- return $this->cache->set( $key, $time );
- }
+ return;
+ }
+
+ if ( !$this->validateType( $type ) ) {
+ return;
}
+
+ // Write to the in-memory cache immediately, and defer writing to
+ // the real cache
+ $key = $this->getMemcKey( $type );
+ $cache = self::cache();
+ $cache->set( $key, $time, 0, BagOStuff::WRITE_CACHE_ONLY );
+ DeferredUpdates::addCallableUpdate( function () use ( $key, $time, $cache ) {
+ $cache->set( $key, $time );
+ } );
}
/**
@@ -86,4 +128,27 @@ class EchoSeenTime {
private function validateType( $type ) {
return in_array( $type, self::$allowedTypes );
}
+
+ /**
+ * Build a memcached key.
+ *
+ * @param string $type Given notification type
+ * @return string Memcached key
+ */
+ protected function getMemcKey( $type = 'all' ) {
+ $localKey = wfMemcKey( 'echo', 'seen', $type, 'time', $this->user->getId() );
+
+ if ( !$this->user->getOption( 'echo-cross-wiki-notifications' ) ) {
+ return $localKey;
+ }
+
+ $lookup = CentralIdLookup::factory();
+ $globalId = $lookup->centralIdFromLocalUser( $this->user, CentralIdLookup::AUDIENCE_RAW );
+
+ if ( !$globalId ) {
+ return $localKey;
+ }
+
+ return wfGlobalCacheKey( 'echo', 'seen', $type, 'time', $globalId );
+ }
}
diff --git a/Echo/includes/UnreadWikis.php b/Echo/includes/UnreadWikis.php
new file mode 100644
index 00000000..e5151187
--- /dev/null
+++ b/Echo/includes/UnreadWikis.php
@@ -0,0 +1,144 @@
+<?php
+
+/**
+ * Manages what wikis a user has unread notifications on
+ */
+class EchoUnreadWikis {
+ /**
+ * @var string
+ */
+ const DEFAULT_TS = '00000000000000';
+
+ /**
+ * @var int
+ */
+ private $id;
+
+ /**
+ * @var MWEchoDbFactory
+ */
+ private $dbFactory;
+
+ /**
+ * @param int $id Central user id
+ */
+ public function __construct( $id ) {
+ $this->id = $id;
+ $this->dbFactory = MWEchoDbFactory::newFromDefault();
+ }
+
+ /**
+ * Use the user id provided by the CentralIdLookup
+ *
+ * @param User $user
+ * @return EchoUnreadWikis|bool
+ */
+ public static function newFromUser( User $user ) {
+ $lookup = CentralIdLookup::factory();
+ $id = $lookup->centralIdFromLocalUser( $user, CentralIdLookup::AUDIENCE_RAW );
+ if ( !$id ) {
+ return false;
+ }
+
+ return new self( $id );
+ }
+
+ /**
+ * @param int $index DB_* constant
+ * @return bool|DatabaseBase
+ */
+ private function getDB( $index ) {
+ return $this->dbFactory->getSharedDb( $index );
+ }
+
+ /**
+ * @return array
+ */
+ public function getUnreadCounts() {
+ $dbr = $this->getDB( DB_SLAVE );
+ if ( $dbr === false ) {
+ return [];
+ }
+
+ $rows = $dbr->select(
+ 'echo_unread_wikis',
+ [
+ 'euw_wiki',
+ 'euw_alerts', 'euw_alerts_ts',
+ 'euw_messages', 'euw_messages_ts',
+ ],
+ [ 'euw_user' => $this->id ],
+ __METHOD__
+ );
+
+ $wikis = [];
+ foreach ( $rows as $row ) {
+ if ( !$row->euw_alerts && !$row->euw_messages ) {
+ // This shouldn't happen, but lets be safe...
+ continue;
+ }
+ $wikis[$row->euw_wiki] = [
+ EchoAttributeManager::ALERT => [
+ 'count' => $row->euw_alerts,
+ 'ts' => $row->euw_alerts_ts,
+ ],
+ EchoAttributeManager::MESSAGE => [
+ 'count' => $row->euw_messages,
+ 'ts' => $row->euw_messages_ts,
+ ],
+ ];
+ }
+
+ return $wikis;
+ }
+
+ /**
+ * @param string $wiki Wiki code
+ * @param int $alertCount Number of alerts
+ * @param MWTimestamp|bool $alertTime Timestamp of most recent unread alert, or
+ * false meaning no timestamp because there are no unread alerts.
+ * @param int $msgCount Number of messages
+ * @param MWTimestamp|bool $msgTime Timestamp of most recent message, or
+ * false meaning no timestamp because there are no unread messages.
+ */
+ public function updateCount( $wiki, $alertCount, $alertTime, $msgCount, $msgTime ) {
+ $dbw = $this->getDB( DB_MASTER );
+ if ( $dbw === false ) {
+ return;
+ }
+
+ $conditions = [
+ 'euw_user' => $this->id,
+ 'euw_wiki' => $wiki,
+ ];
+
+ if ( $alertCount || $msgCount ) {
+ $values = [
+ 'euw_alerts' => $alertCount,
+ 'euw_alerts_ts' => $alertCount
+ ? $alertTime->getTimestamp( TS_MW )
+ : static::DEFAULT_TS,
+ 'euw_messages' => $msgCount,
+ 'euw_messages_ts' => $msgCount
+ ? $msgTime->getTimestamp( TS_MW )
+ : static::DEFAULT_TS,
+ ];
+
+ // when there is unread alert(s) and/or message(s), upsert the row
+ $dbw->upsert(
+ 'echo_unread_wikis',
+ $conditions + $values,
+ [ 'euw_user', 'euw_wiki' ],
+ $values,
+ __METHOD__
+ );
+ } else {
+ // No unread notifications, delete the row
+ $dbw->delete(
+ 'echo_unread_wikis',
+ $conditions,
+ __METHOD__
+ );
+ }
+ }
+}
diff --git a/Echo/includes/UserLocator.php b/Echo/includes/UserLocator.php
index 45f2b905..afe9a3d1 100644
--- a/Echo/includes/UserLocator.php
+++ b/Echo/includes/UserLocator.php
@@ -8,30 +8,31 @@ class EchoUserLocator {
* heavily watched pages when this is used.
*
* @param EchoEvent $event
+ * @param int $batchSize
* @return User[]
*/
public static function locateUsersWatchingTitle( EchoEvent $event, $batchSize = 500 ) {
$title = $event->getTitle();
if ( !$title ) {
- return array();
+ return [];
}
- $it = new EchoBatchRowIterator(
+ $it = new BatchRowIterator(
wfGetDB( DB_SLAVE, 'watchlist' ),
/* $table = */ 'watchlist',
- /* $primaryKeys = */ array( 'wl_user' ),
+ /* $primaryKeys = */ [ 'wl_user' ],
$batchSize
);
- $it->addConditions( array(
+ $it->addConditions( [
'wl_namespace' => $title->getNamespace(),
'wl_title' => $title->getDBkey(),
- ) );
+ ] );
// flatten the result into a stream of rows
$it = new RecursiveIteratorIterator( $it );
// add callback to convert user id to user objects
- $it = new EchoCallbackIterator( $it, function( $row ) {
+ $it = new EchoCallbackIterator( $it, function ( $row ) {
return User::newFromId( $row->wl_user );
} );
@@ -48,14 +49,14 @@ class EchoUserLocator {
public static function locateTalkPageOwner( EchoEvent $event ) {
$title = $event->getTitle();
if ( !$title || $title->getNamespace() !== NS_USER_TALK ) {
- return array();
+ return [];
}
$user = User::newFromName( $title->getDBkey() );
if ( $user && !$user->isAnon() ) {
- return array( $user->getId() => $user );
+ return [ $user->getId() => $user ];
} else {
- return array();
+ return [];
}
}
@@ -68,9 +69,9 @@ class EchoUserLocator {
public static function locateEventAgent( EchoEvent $event ) {
$agent = $event->getAgent();
if ( $agent && !$agent->isAnon() ) {
- return array( $agent->getId() => $agent );
+ return [ $agent->getId() => $agent ];
} else {
- return array();
+ return [];
}
}
@@ -78,7 +79,7 @@ class EchoUserLocator {
* Return the user that created the first revision of the
* associated title.
*
- * @param EchoEvent $evnet
+ * @param EchoEvent $event
* @return User[]
*/
public static function locateArticleCreator( EchoEvent $event ) {
@@ -86,30 +87,30 @@ class EchoUserLocator {
$title = $event->getTitle();
if ( !$title || $title->getArticleID() <= 0 ) {
- return array();
+ return [];
}
// why?
if ( !$agent ) {
- return array();
+ return [];
}
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->selectRow(
- array( 'revision' ),
- array( 'rev_user' ),
- array( 'rev_page' => $title->getArticleID() ),
+ [ 'revision' ],
+ [ 'rev_user' ],
+ [ 'rev_page' => $title->getArticleID() ],
__METHOD__,
- array( 'LIMIT' => 1, 'ORDER BY' => 'rev_timestamp, rev_id' )
+ [ 'LIMIT' => 1, 'ORDER BY' => 'rev_timestamp, rev_id' ]
);
if ( !$res || !$res->rev_user ) {
- return array();
+ return [];
}
$user = User::newFromId( $res->rev_user );
if ( $user ) {
- return array( $user->getId() => $user );
+ return [ $user->getId() => $user ];
} else {
- return array();
+ return [];
}
}
@@ -128,13 +129,13 @@ class EchoUserLocator {
* @return User[]
*/
public static function locateFromEventExtra( EchoEvent $event, array $keys ) {
- $users = array();
+ $users = [];
foreach ( $keys as $key ) {
$userIds = $event->getExtraParam( $key );
if ( !$userIds ) {
continue;
} elseif ( !is_array( $userIds ) ) {
- $userIds = array( $userIds );
+ $userIds = [ $userIds ];
}
foreach ( $userIds as $userId ) {
// we shouldn't receive User instances, but allow
diff --git a/Echo/includes/api/ApiCrossWikiBase.php b/Echo/includes/api/ApiCrossWikiBase.php
new file mode 100644
index 00000000..b9184da2
--- /dev/null
+++ b/Echo/includes/api/ApiCrossWikiBase.php
@@ -0,0 +1,126 @@
+<?php
+
+use MediaWiki\Logger\LoggerFactory;
+
+abstract class ApiCrossWikiBase extends ApiQueryBase {
+ /**
+ * @var EchoForeignNotifications
+ */
+ protected $foreignNotifications;
+
+ /**
+ * @param ApiQuery $queryModule
+ * @param string $moduleName
+ * @param string $paramPrefix
+ */
+ public function __construct( ApiQuery $queryModule, $moduleName, $paramPrefix = '' ) {
+ parent::__construct( $queryModule, $moduleName, $paramPrefix );
+
+ $this->foreignNotifications = new EchoForeignNotifications( $this->getUser() );
+ }
+
+ /**
+ * This will turn the current API call (with all of it's params) and execute
+ * it on all foreign wikis, returning an array of results per wiki.
+ *
+ * @param array $wikis List of wikis to query. Defaults to the result of getRequestedForeignWikis().
+ * @param array $paramOverrides Request parameter overrides
+ * @return array
+ * @throws Exception
+ */
+ protected function getFromForeign( $wikis = null, array $paramOverrides = [] ) {
+ $foreignReq = new EchoForeignWikiRequest(
+ $this->getUser(),
+ $paramOverrides + $this->getForeignQueryParams(),
+ $wikis !== null ? $wikis : $this->getRequestedForeignWikis(),
+ $this->getModulePrefix() . 'wikis'
+ );
+ return $foreignReq->execute();
+ }
+
+ /**
+ * Get the query parameters to use for the foreign API requests.
+ * Subclasses should override this if they need to customize the
+ * parameters.
+ * @return array Query parameters
+ */
+ protected function getForeignQueryParams() {
+ return $this->getRequest()->getValues();
+ }
+
+ /**
+ * @return bool
+ */
+ protected function allowCrossWikiNotifications() {
+ global $wgEchoCrossWikiNotifications;
+ return $wgEchoCrossWikiNotifications;
+ }
+
+ /**
+ * This is basically equivalent to $params['wikis'], but some added checks:
+ * - `*` will expand to "all wikis with unread notifications"
+ * - if `$wgEchoCrossWikiNotifications` is off, foreign wikis will be excluded
+ *
+ * @return array
+ */
+ protected function getRequestedWikis() {
+ $params = $this->extractRequestParams();
+
+ // if wiki is omitted from params, that's because crosswiki is/was not
+ // available, and it'll default to current wiki
+ $wikis = isset( $params['wikis'] ) ? $params['wikis'] : [ wfWikiID() ];
+
+ if ( array_search( '*', $wikis ) !== false ) {
+ // expand `*` to all foreign wikis with unread notifications + local
+ $wikis = array_merge(
+ [ wfWikiID() ],
+ $this->getForeignWikisWithUnreadNotifications()
+ );
+ }
+
+ if ( !$this->allowCrossWikiNotifications() ) {
+ // exclude foreign wikis if x-wiki is not enabled
+ $wikis = array_intersect_key( [ wfWikiID() ], $wikis );
+ }
+
+ return $wikis;
+ }
+
+ /**
+ * @return array Wiki names
+ */
+ protected function getRequestedForeignWikis() {
+ return array_diff( $this->getRequestedWikis(), [ wfWikiID() ] );
+ }
+
+ /**
+ * @return array Wiki names
+ */
+ protected function getForeignWikisWithUnreadNotifications() {
+ return $this->foreignNotifications->getWikis();
+ }
+
+ /**
+ * @return array
+ */
+ public function getAllowedParams() {
+ global $wgConf;
+
+ $params = [];
+
+ if ( $this->allowCrossWikiNotifications() ) {
+ $params += [
+ // fetch notifications from multiple wikis
+ 'wikis' => [
+ ApiBase::PARAM_ISMULTI => true,
+ ApiBase::PARAM_DFLT => wfWikiID(),
+ // `*` will let you immediately fetch from all wikis that have
+ // unread notifications, without having to look them up first
+ ApiBase::PARAM_TYPE => array_unique( array_merge( $wgConf->wikis, [ wfWikiID(), '*' ] ) ),
+ ],
+ ];
+ }
+
+ return $params;
+ }
+}
diff --git a/Echo/includes/api/ApiEchoArticleReminder.php b/Echo/includes/api/ApiEchoArticleReminder.php
new file mode 100644
index 00000000..5ed26794
--- /dev/null
+++ b/Echo/includes/api/ApiEchoArticleReminder.php
@@ -0,0 +1,112 @@
+<?php
+
+class ApiEchoArticleReminder extends ApiBase {
+
+ public function execute() {
+ $this->getMain()->setCacheMode( 'private' );
+ $user = $this->getUser();
+ if ( $user->isAnon() ) {
+ $this->dieWithError( 'apierror-mustbeloggedin-generic', 'login-required' );
+ }
+
+ $params = $this->extractRequestParams();
+ $result = [];
+ $userTimestamp = new MWTimestamp( $params['timestamp'] );
+ $nowTimestamp = new MWTimestamp();
+ // We need $params['timestamp'] to be a future timestamp:
+ // $userTimestamp < $nowTimestamp = invert 0
+ // $userTimestamp > $nowTimestamp = invert 1
+ if ( $userTimestamp->diff( $nowTimestamp )->invert === 0 ) {
+ $this->dieWithError( [ 'apierror-badparameter', 'timestamp' ], 'timestamp-not-in-future', null, 400 );
+ }
+
+ $eventCreation = EchoEvent::create( [
+ 'type' => 'article-reminder',
+ 'agent' => $user,
+ 'title' => $this->getTitleFromTitleOrPageId( $params ),
+ 'extra' => [
+ 'notifyAgent' => true,
+ 'comment' => $params['comment'],
+ ],
+ ] );
+
+ if ( !$eventCreation ) {
+ $this->dieWithError( 'apierror-echo-event-creation-failed', null, null, 500 );
+ }
+
+ /* Temp - removing the delay just for now:
+ $job = new JobSpecification(
+ 'articleReminder',
+ [
+ 'userId' => $user->getId(),
+ 'timestamp' => $params['timestamp'],
+ 'comment' => $params['comment'],
+ ],
+ [ 'removeDuplicates' => true ],
+ Title::newFromID( $params['pageid'] )
+ );
+ JobQueueGroup::singleton()->push( $job );*/
+ $result += [
+ 'result' => 'success'
+ ];
+ $this->getResult()->addValue( 'query', $this->getModuleName(), $result );
+ }
+
+ public function getAllowedParams() {
+ return [
+ 'pageid' => [
+ ApiBase::PARAM_TYPE => 'integer',
+ ],
+ 'title' => [
+ ApiBase::PARAM_TYPE => 'string',
+ ],
+ 'comment' => [
+ ApiBase::PARAM_TYPE => 'string',
+ ],
+ 'timestamp' => [
+ ApiBase::PARAM_REQUIRED => true,
+ ApiBase::PARAM_TYPE => 'timestamp',
+ ],
+ 'token' => [
+ ApiBase::PARAM_REQUIRED => true,
+ ],
+ ];
+ }
+
+ public function needsToken() {
+ return 'csrf';
+ }
+
+ public function getTokenSalt() {
+ return '';
+ }
+
+ public function mustBePosted() {
+ return true;
+ }
+
+ public function isWriteMode() {
+ return true;
+ }
+
+ /**
+ * @see ApiBase::getExamplesMessages()
+ */
+ protected function getExamplesMessages() {
+ $todayDate = new DateTime();
+ $oneDay = new DateInterval( 'P1D' );
+ $tomorrowDate = $todayDate->add( $oneDay );
+ $tomorrowDateTimestamp = new MWTimestamp( $tomorrowDate );
+ $tomorrowTimestampStr = $tomorrowDateTimestamp->getTimestamp( TS_ISO_8601 );
+ return [
+ "action=echoarticlereminder&pageid=1&timestamp=$tomorrowTimestampStr&comment=example"
+ => 'apihelp-echoarticlereminder-example-1',
+ "action=echoarticlereminder&title=Main_Page&timestamp=$tomorrowTimestampStr"
+ => 'apihelp-echoarticlereminder-example-2',
+ ];
+ }
+
+ public function getHelpUrls() {
+ return 'https://www.mediawiki.org/wiki/Echo_(Notifications)/API';
+ }
+}
diff --git a/Echo/includes/api/ApiEchoMarkRead.php b/Echo/includes/api/ApiEchoMarkRead.php
index 13e069e1..551c183e 100644
--- a/Echo/includes/api/ApiEchoMarkRead.php
+++ b/Echo/includes/api/ApiEchoMarkRead.php
@@ -8,7 +8,7 @@ class ApiEchoMarkRead extends ApiBase {
$user = $this->getUser();
if ( $user->isAnon() ) {
- $this->dieUsage( 'Login is required', 'login-required' );
+ $this->dieWithError( 'apierror-mustbeloggedin-generic', 'login-required' );
}
$notifUser = MWEchoNotifUser::newFromUser( $user );
@@ -16,7 +16,7 @@ class ApiEchoMarkRead extends ApiBase {
$params = $this->extractRequestParams();
// There is no need to trigger markRead if all notifications are read
- if ( $notifUser->getNotificationCount() > 0 ) {
+ if ( $notifUser->getLocalNotificationCount() > 0 ) {
if ( count( $params['list'] ) ) {
// Make sure there is a limit to the update
$notifUser->markRead( array_slice( $params['list'], 0, ApiBase::LIMIT_SML2 ) );
@@ -29,9 +29,15 @@ class ApiEchoMarkRead extends ApiBase {
}
}
- $result = array(
+ // Mark as unread
+ if ( count( $params['unreadlist'] ) > 0 ) {
+ // Make sure there is a limit to the update
+ $notifUser->markUnRead( array_slice( $params['unreadlist'], 0, ApiBase::LIMIT_SML2 ) );
+ }
+
+ $result = [
'result' => 'success'
- );
+ ];
$rawCount = 0;
foreach ( EchoAttributeManager::$sections as $section ) {
$rawSectionCount = $notifUser->getNotificationCount( /* $tryCache = */true, DB_SLAVE, $section );
@@ -40,42 +46,33 @@ class ApiEchoMarkRead extends ApiBase {
$rawCount += $rawSectionCount;
}
- $result += array(
+ $result += [
'rawcount' => $rawCount,
'count' => EchoNotificationController::formatNotificationCount( $rawCount ),
- );
+ ];
$this->getResult()->addValue( 'query', $this->getModuleName(), $result );
}
public function getAllowedParams() {
- return array(
- 'list' => array(
+ return [
+ 'list' => [
ApiBase::PARAM_ISMULTI => true,
- ),
- 'all' => array(
+ ],
+ 'unreadlist' => [
+ ApiBase::PARAM_ISMULTI => true,
+ ],
+ 'all' => [
ApiBase::PARAM_REQUIRED => false,
ApiBase::PARAM_TYPE => 'boolean'
- ),
- 'sections' => array(
+ ],
+ 'sections' => [
ApiBase::PARAM_TYPE => EchoAttributeManager::$sections,
ApiBase::PARAM_ISMULTI => true,
- ),
- 'token' => array(
+ ],
+ 'token' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'list' => 'A list of notification IDs to mark as read',
- 'all' => "If set to true, marks all of a user's notifications as read",
- 'sections' => 'A list of sections to mark as read',
- 'token' => 'edit token',
- );
+ ],
+ ];
}
public function needsToken() {
@@ -95,32 +92,17 @@ class ApiEchoMarkRead extends ApiBase {
}
/**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Mark notifications as read for the current user';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=echomarkread&list=8',
- 'api.php?action=echomarkread&all=true'
- );
- }
-
- /**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=echomarkread&list=8'
=> 'apihelp-echomarkread-example-1',
'action=echomarkread&all=true'
=> 'apihelp-echomarkread-example-2',
- );
+ 'action=echomarkread&unreadlist=1'
+ => 'apihelp-echomarkread-example-3',
+ ];
}
public function getHelpUrls() {
diff --git a/Echo/includes/api/ApiEchoMarkSeen.php b/Echo/includes/api/ApiEchoMarkSeen.php
index ce4e4422..d06852ac 100644
--- a/Echo/includes/api/ApiEchoMarkSeen.php
+++ b/Echo/includes/api/ApiEchoMarkSeen.php
@@ -8,7 +8,7 @@ class ApiEchoMarkSeen extends ApiBase {
$user = $this->getUser();
if ( $user->isAnon() ) {
- $this->dieUsage( 'Login is required', 'login-required' );
+ $this->dieWithError( 'apierror-mustbeloggedin-generic', 'login-required' );
}
$params = $this->extractRequestParams();
@@ -16,31 +16,36 @@ class ApiEchoMarkSeen extends ApiBase {
$seenTime = EchoSeenTime::newFromUser( $user );
$seenTime->setTime( $timestamp, $params['type'] );
- $this->getResult()->addValue( 'query', $this->getModuleName(), array(
+ if ( $params['timestampFormat'] === 'ISO_8601' ) {
+ $outputTimestamp = wfTimestamp( TS_ISO_8601, $timestamp );
+ } else {
+ // MW
+ $this->addDeprecation( 'apiwarn-echo-deprecation-timestampformat', 'action=echomarkseen&timestampFormat=MW' );
+
+ $outputTimestamp = $timestamp;
+ }
+
+ $this->getResult()->addValue( 'query', $this->getModuleName(), [
'result' => 'success',
- 'timestamp' => $timestamp,
- ) );
+ 'timestamp' => $outputTimestamp,
+ ] );
}
public function getAllowedParams() {
- return array(
- 'token' => array(
+ return [
+ 'token' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'type' => array(
+ ],
+ 'type' => [
ApiBase::PARAM_REQUIRED => true,
- ApiBase::PARAM_TYPE => array( 'alert', 'message', 'all' ),
- )
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'token' => 'edit token',
- );
+ ApiBase::PARAM_TYPE => [ 'alert', 'message', 'all' ],
+ ],
+ 'timestampFormat' => [
+ // Not using the TS constants, since clients can't.
+ ApiBase::PARAM_DFLT => 'MW',
+ ApiBase::PARAM_TYPE => [ 'ISO_8601', 'MW' ],
+ ],
+ ];
}
public function needsToken() {
@@ -60,28 +65,12 @@ class ApiEchoMarkSeen extends ApiBase {
}
/**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Mark notifications as seen for the current user';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=echomarkseen',
- );
- }
-
- /**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=echomarkseen&type=all' => 'apihelp-echomarkseen-example-1',
- );
+ ];
}
public function getHelpUrls() {
diff --git a/Echo/includes/api/ApiEchoNotifications.php b/Echo/includes/api/ApiEchoNotifications.php
index 278e5cf4..121499c3 100644
--- a/Echo/includes/api/ApiEchoNotifications.php
+++ b/Echo/includes/api/ApiEchoNotifications.php
@@ -1,6 +1,10 @@
<?php
-class ApiEchoNotifications extends ApiQueryBase {
+class ApiEchoNotifications extends ApiCrossWikiBase {
+ /**
+ * @var bool
+ */
+ protected $crossWikiSummary = false;
public function __construct( $query, $moduleName ) {
parent::__construct( $query, $moduleName, 'not' );
@@ -10,88 +14,153 @@ class ApiEchoNotifications extends ApiQueryBase {
// To avoid API warning, register the parameter used to bust browser cache
$this->getMain()->getVal( '_' );
- $user = $this->getUser();
- if ( $user->isAnon() ) {
- $this->dieUsage( 'Login is required', 'login-required' );
+ if ( $this->getUser()->isAnon() ) {
+ $this->dieWithError( 'apierror-mustbeloggedin-generic', 'login-required' );
}
$params = $this->extractRequestParams();
+
+ /* @deprecated */
+ if ( $params['format'] === 'flyout' ) {
+ $this->addDeprecation( 'apiwarn-echo-deprecation-flyout', 'action=query&meta=notifications&notformat=flyout' );
+ } elseif ( $params['format'] === 'html' ) {
+ $this->addDeprecation( 'apiwarn-echo-deprecation-html', 'action=query&meta=notifications&notformat=html' );
+ }
+
+ if ( $this->allowCrossWikiNotifications() ) {
+ $this->crossWikiSummary = $params['crosswikisummary'];
+ }
+
+ $results = [];
+ if ( in_array( wfWikiID(), $this->getRequestedWikis() ) ) {
+ $results[wfWikiID()] = $this->getLocalNotifications( $params );
+ }
+
+ if ( $this->getRequestedForeignWikis() ) {
+ $foreignResults = $this->getFromForeign();
+ foreach ( $foreignResults as $wiki => $result ) {
+ if ( isset( $result['query']['notifications'] ) ) {
+ $results[$wiki] = $result['query']['notifications'];
+ }
+ }
+ }
+
+ // after getting local & foreign results, merge them all together
+ $result = $this->mergeResults( $results, $params );
+ if ( $params['groupbysection'] ) {
+ foreach ( $params['sections'] as $section ) {
+ if ( in_array( 'list', $params['prop'] ) ) {
+ $this->getResult()->setIndexedTagName( $result[$section]['list'], 'notification' );
+ }
+ }
+ } else {
+ if ( in_array( 'list', $params['prop'] ) ) {
+ $this->getResult()->setIndexedTagName( $result['list'], 'notification' );
+ }
+ }
+ $this->getResult()->addValue( 'query', $this->getModuleName(), $result );
+ }
+
+ /**
+ * @param array $params
+ * @return array
+ */
+ protected function getLocalNotifications( array $params ) {
+ $user = $this->getUser();
$prop = $params['prop'];
+ $titles = null;
+ if ( $params['titles'] ) {
+ $titles = array_values( array_filter( array_map( 'Title::newFromText', $params['titles'] ) ) );
+ if ( in_array( '[]', $params['titles'] ) ) {
+ $titles[] = null;
+ }
+ }
- $result = array();
+ $result = [];
if ( in_array( 'list', $prop ) ) {
// Group notification results by section
if ( $params['groupbysection'] ) {
- wfProfileIn( __METHOD__ . '-group-by-section' );
foreach ( $params['sections'] as $section ) {
$result[$section] = $this->getSectionPropList(
- $user, $section, $params['limit'],
- $params[$section . 'continue'], $params['format'], $params[$section . 'unreadfirst']
+ $user, $section, $params['filter'], $params['limit'],
+ $params[$section . 'continue'], $params['format'],
+ $titles, $params[$section . 'unreadfirst'], $params['bundle']
);
- $this->getResult()->setIndexedTagName( $result[$section]['list'], 'notification' );
- // 'index' is built on top of 'list'
- if ( in_array( 'index', $prop ) ) {
- $result[$section]['index'] = $this->getPropIndex( $result[$section]['list'] );
- $this->getResult()->setIndexedTagName( $result[$section]['index'], 'id' );
+
+ if ( $this->crossWikiSummary ) {
+ // insert fake notification for foreign notifications
+ $foreignNotification = $this->makeForeignNotification( $user, $params['format'], $section );
+ if ( $foreignNotification ) {
+ array_unshift( $result[$section]['list'], $foreignNotification );
+ }
}
}
- wfProfileOut( __METHOD__ . '-group-by-section' );
} else {
- wfProfileIn( __METHOD__ . '-group-by-none' );
$attributeManager = EchoAttributeManager::newFromGlobalVars();
$result = $this->getPropList(
$user,
$attributeManager->getUserEnabledEventsbySections( $user, 'web', $params['sections'] ),
- $params['limit'], $params['continue'], $params['format']
+ $params['filter'], $params['limit'], $params['continue'], $params['format'],
+ $titles, $params['unreadfirst'], $params['bundle']
);
- $this->getResult()->setIndexedTagName( $result['list'], 'notification' );
- // 'index' is built on top of 'list'
- if ( in_array( 'index', $prop ) ) {
- $result['index'] = $this->getPropIndex( $result['list'] );
- $this->getResult()->setIndexedTagName( $result['index'], 'id' );
+
+ // if exactly 1 section is specified, we consider only that section, otherwise
+ // we pass ALL to consider all foreign notifications
+ $section = count( $params['sections'] ) === 1 ? reset( $params['sections'] ) : EchoAttributeManager::ALL;
+ if ( $this->crossWikiSummary ) {
+ $foreignNotification = $this->makeForeignNotification( $user, $params['format'], $section );
+ if ( $foreignNotification ) {
+ array_unshift( $result['list'], $foreignNotification );
+ }
}
- wfProfileOut( __METHOD__ . '-group-by-none' );
}
}
if ( in_array( 'count', $prop ) ) {
- wfProfileIn( __METHOD__ . '-count' );
$result = array_merge_recursive(
$result,
- $this->getPropcount( $user, $params['sections'], $params['groupbysection'] )
+ $this->getPropCount( $user, $params['sections'], $params['groupbysection'] )
);
- wfProfileOut( __METHOD__ . '-count' );
}
- $this->getResult()->setIndexedTagName( $result, 'notification' );
- $this->getResult()->addValue( 'query', $this->getModuleName(), $result );
+ if ( in_array( 'seenTime', $prop ) ) {
+ $result = array_merge_recursive(
+ $result,
+ $this->getPropSeenTime( $user, $params['sections'], $params['groupbysection'] )
+ );
+ }
+
+ return $result;
}
/**
* Internal method for getting the property 'list' data for individual section
* @param User $user
* @param string $section 'alert' or 'message'
+ * @param string $filter 'all', 'read' or 'unread'
* @param int $limit
* @param string $continue
* @param string $format
- * @param boolean $unreadFirst
+ * @param Title[] $titles
+ * @param bool $unreadFirst
+ * @param bool $bundle
* @return array
*/
- protected function getSectionPropList( User $user, $section, $limit, $continue, $format, $unreadFirst = false ) {
- $notifUser = MWEchoNotifUser::newFromUser( $user );
+ protected function getSectionPropList( User $user, $section, $filter, $limit, $continue, $format, array $titles = null, $unreadFirst = false, $bundle = false ) {
$attributeManager = EchoAttributeManager::newFromGlobalVars();
- $sectionEvents = $attributeManager->getUserEnabledEventsbySections( $user, 'web', array( $section ) );
+ $sectionEvents = $attributeManager->getUserEnabledEventsbySections( $user, 'web', [ $section ] );
if ( !$sectionEvents ) {
- $result = array(
- 'list' => array(),
+ $result = [
+ 'list' => [],
'continue' => null
- );
+ ];
} else {
$result = $this->getPropList(
- $user, $sectionEvents, $limit, $continue, $format, $unreadFirst
+ $user, $sectionEvents, $filter, $limit, $continue, $format, $titles, $unreadFirst, $bundle
);
}
+
return $result;
}
@@ -101,60 +170,114 @@ class ApiEchoNotifications extends ApiQueryBase {
* of a set of sections or a single section
* @param User $user
* @param string[] $eventTypes
+ * @param string $filter 'all', 'read' or 'unread'
* @param int $limit
* @param string $continue
* @param string $format
- * @param boolean $unreadFirst
+ * @param Title[] $titles
+ * @param bool $unreadFirst
+ * @param bool $bundle
* @return array
*/
- protected function getPropList( User $user, array $eventTypes, $limit, $continue, $format, $unreadFirst = false ) {
- $result = array(
- 'list' => array(),
+ protected function getPropList( User $user, array $eventTypes, $filter, $limit, $continue, $format, array $titles = null, $unreadFirst = false, $bundle = false ) {
+ $result = [
+ 'list' => [],
'continue' => null
- );
+ ];
$notifMapper = new EchoNotificationMapper();
- // Prefer unread notifications. We don't care about next offset in this case
- if ( $unreadFirst ) {
- wfProfileIn( __METHOD__ . '-fetch-data-unread-first' );
- $notifs = $notifMapper->fetchUnreadByUser( $user, $limit, $eventTypes );
- // If there are less unread notifications than we requested,
- // then fill the result with some read notifications
- $count = count( $notifs );
- if ( $count < $limit ) {
- // Query planner should be smart enough that passing a short list of ids to exclude
- // will only visit at most that number of extra rows.
- $mixedNotifs = $notifMapper->fetchByUser(
- $user,
- $limit - $count,
- null,
- $eventTypes,
- array_keys( $notifs )
- );
- foreach ( $mixedNotifs as $notif ) {
- $notifs[$notif->getEvent()->getId()] = $notif;
+ // check if we want both read & unread...
+ if ( in_array( 'read', $filter ) && in_array( '!read', $filter ) ) {
+ // Prefer unread notifications. We don't care about next offset in this case
+ if ( $unreadFirst ) {
+ // query for unread notifications past 'continue' (offset)
+ $notifs = $notifMapper->fetchUnreadByUser( $user, $limit + 1, $continue, $eventTypes, $titles );
+
+ /*
+ * 'continue' has a timestamp & id (to start with, in case
+ * there would be multiple events with that same timestamp)
+ * Unread notifications should always load first, but may be
+ * older than read ones, but we can work with current
+ * 'continue' format:
+ * * if there's no continue, first load unread notifications
+ * * if there's a continue, fetch unread notifications first
+ * * if there are no unread ones, continue must've been
+ * about read notifications: fetch 'em
+ * * if there are unread ones but first one doesn't match
+ * continue id, it must've been about read notifications:
+ * discard unread & fetch read
+ */
+ if ( $notifs && $continue ) {
+ /** @var EchoNotification $first */
+ $first = reset( $notifs );
+ $continueId = intval( trim( strrchr( $continue, '|' ), '|' ) );
+ if ( $first->getEvent()->getID() !== $continueId ) {
+ // notification doesn't match continue id, it must've been
+ // about read notifications: discard all unread ones
+ $notifs = [];
+ }
+ }
+
+ // If there are less unread notifications than we requested,
+ // then fill the result with some read notifications
+ $count = count( $notifs );
+ // we need 1 more than $limit, so we can respond 'continue'
+ if ( $count <= $limit ) {
+ // Query planner should be smart enough that passing a short list of ids to exclude
+ // will only visit at most that number of extra rows.
+ $mixedNotifs = $notifMapper->fetchByUser(
+ $user,
+ $limit - $count + 1,
+ // if there were unread notifications, 'continue' was for
+ // unread notifications and we should start fetching read
+ // notifications from start
+ $count > 0 ? null : $continue,
+ $eventTypes,
+ array_keys( $notifs ),
+ $titles
+ );
+ foreach ( $mixedNotifs as $notif ) {
+ $notifs[$notif->getEvent()->getId()] = $notif;
+ }
}
+ } else {
+ $notifs = $notifMapper->fetchByUser( $user, $limit + 1, $continue, $eventTypes, [], $titles );
}
- wfProfileOut( __METHOD__ . '-fetch-data-unread-first' );
- } else {
- wfProfileIn( __METHOD__ . '-fetch-data' );
- $notifs = $notifMapper->fetchByUser( $user, $limit + 1, $continue, $eventTypes );
- wfProfileOut( __METHOD__ . '-fetch-data' );
+ } elseif ( in_array( 'read', $filter ) ) {
+ $notifs = $notifMapper->fetchReadByUser( $user, $limit + 1, $continue, $eventTypes, $titles );
+ } else { // = if ( in_array( '!read', $filter ) ) {
+ $notifs = $notifMapper->fetchUnreadByUser( $user, $limit + 1, $continue, $eventTypes, $titles );
+ }
+
+ // get $overfetchedItem before bundling and rendering so that it is not affected by filtering
+ /** @var EchoNotification $overfetchedItem */
+ $overfetchedItem = count( $notifs ) > $limit ? array_pop( $notifs ) : null;
+
+ if ( $bundle ) {
+ $bundler = new Bundler();
+ $notifs = $bundler->bundle( $notifs );
}
- wfProfileIn( __METHOD__ . '-formatting' );
- foreach ( $notifs as $notif ) {
- $result['list'][$notif->getEvent()->getID()] = EchoDataOutputFormatter::formatOutput( $notif, $format, $user );
+ while ( count( $notifs ) ) {
+ /** @var EchoNotification $notif */
+ $notif = array_shift( $notifs );
+ $output = EchoDataOutputFormatter::formatOutput( $notif, $format, $user, $this->getLanguage() );
+ if ( $output !== false ) {
+ $result['list'][] = $output;
+ } elseif ( $bundle && $notif->getBundledNotifications() ) {
+ // when the bundle_base gets filtered out, bundled notifications
+ // have to be re-bundled and formatted
+ $notifs = array_merge( $bundler->bundle( $notif->getBundledNotifications() ), $notifs );
+ }
}
- wfProfileOut( __METHOD__ . '-formatting' );
// Generate offset if necessary
- if ( !$unreadFirst ) {
- if ( count( $result['list'] ) > $limit ) {
- $lastItem = array_pop( $result['list'] );
- $result['continue'] = $lastItem['timestamp']['utcunix'] . '|' . $lastItem['id'];
- }
+ if ( $overfetchedItem ) {
+ // @todo: what to do with this when fetching from multiple wikis?
+ $timestamp = wfTimestamp( TS_UNIX, $overfetchedItem->getTimestamp() );
+ $id = $overfetchedItem->getEvent()->getId();
+ $result['continue'] = $timestamp . '|' . $id;
}
return $result;
@@ -164,140 +287,359 @@ class ApiEchoNotifications extends ApiQueryBase {
* Internal helper method for getting property 'count' data
* @param User $user
* @param string[] $sections
- * @param boolean $groupBySection
+ * @param bool $groupBySection
* @return array
*/
protected function getPropCount( User $user, array $sections, $groupBySection ) {
- $result = array();
+ $result = [];
$notifUser = MWEchoNotifUser::newFromUser( $user );
- // Always get total count
- $rawCount = $notifUser->getNotificationCount();
- $result['rawcount'] = $rawCount;
- $result['count'] = EchoNotificationController::formatNotificationCount( $rawCount );
+ $global = $this->crossWikiSummary ? 'preference' : false;
- if ( $groupBySection ) {
- foreach ( $sections as $section ) {
- $rawCount = $notifUser->getNotificationCount( /* $tryCache = */true, DB_SLAVE, $section );
+ $totalRawCount = 0;
+ foreach ( $sections as $section ) {
+ $rawCount = $notifUser->getNotificationCount( /* $tryCache = */true, DB_SLAVE, $section, $global );
+ if ( $groupBySection ) {
$result[$section]['rawcount'] = $rawCount;
$result[$section]['count'] = EchoNotificationController::formatNotificationCount( $rawCount );
}
+ $totalRawCount += $rawCount;
}
+ $result['rawcount'] = $totalRawCount;
+ $result['count'] = EchoNotificationController::formatNotificationCount( $totalRawCount );
+
return $result;
}
/**
- * Internal helper method for getting property 'index' data
- * @param array $list
+ * Internal helper method for getting property 'seenTime' data
+ * @param User $user
+ * @param string[] $sections
+ * @param bool $groupBySection
* @return array
*/
- protected function getPropIndex( $list ) {
- $result = array();
- foreach ( array_keys( $list ) as $key ) {
- // Don't include the XML tag name ('_element' key)
- if ( $key != '_element' ) {
- $result[] = $key;
+ protected function getPropSeenTime( User $user, array $sections, $groupBySection ) {
+ $result = [];
+ $seenTimeHelper = EchoSeenTime::newFromUser( $user );
+
+ if ( $groupBySection ) {
+ foreach ( $sections as $section ) {
+ $result[$section]['seenTime'] = $seenTimeHelper->getTime( $section, TS_ISO_8601 );
+ }
+ } else {
+ $result['seenTime'] = [];
+ foreach ( $sections as $section ) {
+ $result['seenTime'][$section] = $seenTimeHelper->getTime( $section, TS_ISO_8601 );
}
}
+
return $result;
}
+ /**
+ * Build and format a "fake" notification to represent foreign notifications.
+ * @param User $user
+ * @param string $format
+ * @param string $section
+ * @return array|false A formatted notification, or false if there are no foreign notifications
+ */
+ protected function makeForeignNotification( User $user, $format, $section = EchoAttributeManager::ALL ) {
+ global $wgEchoSectionTransition, $wgEchoBundleTransition;
+ if (
+ ( $wgEchoSectionTransition && $section !== EchoAttributeManager::ALL ) ||
+ $wgEchoBundleTransition
+ ) {
+ // In section transition mode we trust that echo_unread_wikis is accurate for the total of alerts+messages,
+ // but not for each section individually (i.e. we don't trust that notifications won't be misclassified).
+ // We get all wikis that have any notifications at all according to the euw table,
+ // and query them to find out what's really there.
+ // In bundle transition mode, we trust that notifications are classified correctly, but we don't
+ // trust the counts in the table.
+ $potentialWikis = $this->foreignNotifications->getWikis( $wgEchoSectionTransition ? EchoAttributeManager::ALL : $section );
+ if ( !$potentialWikis ) {
+ return false;
+ }
+ $foreignResults = $this->getFromForeign( $potentialWikis, [ $this->getModulePrefix() . 'filter' => '!read' ] );
+
+ $countsByWiki = [];
+ $timestampsByWiki = [];
+ foreach ( $foreignResults as $wiki => $result ) {
+ if ( isset( $result['query']['notifications']['list'] ) ) {
+ $notifs = $result['query']['notifications']['list'];
+ $countsByWiki[$wiki] = intval( $result['query']['notifications']['count'] );
+ } elseif ( isset( $result['query']['notifications'][$section]['list'] ) ) {
+ $notifs = $result['query']['notifications'][$section]['list'];
+ $countsByWiki[$wiki] = intval( $result['query']['notifications'][$section]['count'] );
+ } else {
+ $notifs = false;
+ $countsByWiki[$wiki] = 0;
+ }
+ if ( $notifs ) {
+ $timestamps = array_filter( array_map( function ( $n ) {
+ return $n['timestamp']['mw'];
+ }, $notifs ) );
+ $timestampsByWiki[$wiki] = $timestamps ? max( $timestamps ) : 0;
+ }
+ }
+
+ $wikis = array_keys( $timestampsByWiki );
+ $count = array_sum( $countsByWiki );
+ $maxTimestamp = new MWTimestamp( $timestampsByWiki ? max( $timestampsByWiki ) : 0 );
+ $timestampsByWiki = array_map( function ( $ts ) {
+ return new MWTimestamp( $ts );
+ }, $timestampsByWiki );
+ } else {
+ // In non-transition mode, or when querying all sections, we can trust the euw table
+ $wikis = $this->foreignNotifications->getWikis( $section );
+ $count = $this->foreignNotifications->getCount( $section );
+ $maxTimestamp = $this->foreignNotifications->getTimestamp( $section );
+ $timestampsByWiki = [];
+ foreach ( $wikis as $wiki ) {
+ $timestampsByWiki[$wiki] = $this->foreignNotifications->getWikiTimestamp( $wiki, $section );
+ }
+ }
+
+ if ( $count === 0 || count( $wikis ) === 0 ) {
+ return false;
+ }
+
+ // Sort wikis by timestamp, in descending order (newest first)
+ usort( $wikis, function ( $a, $b ) use ( $section, $timestampsByWiki ) {
+ return $timestampsByWiki[$b]->getTimestamp( TS_UNIX ) - $timestampsByWiki[$a]->getTimestamp( TS_UNIX );
+ } );
+
+ $row = new StdClass;
+ $row->event_id = -1;
+ $row->event_type = 'foreign';
+ $row->event_variant = null;
+ $row->event_agent_id = $user->getId();
+ $row->event_agent_ip = null;
+ $row->event_page_id = null;
+ $row->event_page_namespace = null;
+ $row->event_page_title = null;
+ $row->event_extra = serialize( [
+ 'section' => $section ?: 'all',
+ 'wikis' => $wikis,
+ 'count' => $count
+ ] );
+ $row->event_deleted = 0;
+
+ $row->notification_user = $user->getId();
+ $row->notification_timestamp = $maxTimestamp;
+ $row->notification_read_timestamp = null;
+ $row->notification_bundle_base = 1;
+ $row->notification_bundle_hash = md5( 'bogus' );
+ $row->notification_bundle_display_hash = md5( 'also-bogus' );
+
+ // Format output like any other notification
+ $notif = EchoNotification::newFromRow( $row );
+ $output = EchoDataOutputFormatter::formatOutput( $notif, $format, $user, $this->getLanguage() );
+
+ // Add cross-wiki-specific data
+ $output['section'] = $section ?: 'all';
+ $output['count'] = $count;
+ $output['sources'] = EchoForeignNotifications::getApiEndpoints( $wikis );
+ // Add timestamp information
+ foreach ( $output['sources'] as $wiki => &$data ) {
+ $data['ts'] = $timestampsByWiki[$wiki]->getTimestamp( TS_ISO_8601 );
+ }
+ return $output;
+ }
+
+ protected function getForeignQueryParams() {
+ $params = parent::getForeignQueryParams();
+
+ // don't request cross-wiki notification summaries
+ unset( $params['notcrosswikisummary'] );
+
+ return $params;
+ }
+
+ /**
+ * @param array $results
+ * @param array $params
+ * @return mixed
+ */
+ protected function mergeResults( array $results, array $params ) {
+ $master = array_shift( $results );
+ if ( !$master ) {
+ $master = [];
+ }
+
+ if ( in_array( 'list', $params['prop'] ) ) {
+ $master = $this->mergeList( $master, $results, $params['groupbysection'] );
+ }
+
+ if ( in_array( 'count', $params['prop'] ) && !$this->crossWikiSummary ) {
+ // if crosswiki data was requested, the count in $master
+ // is accurate already
+ // otherwise, we'll want to combine counts for all wikis
+ $master = $this->mergeCount( $master, $results, $params['groupbysection'] );
+ }
+
+ return $master;
+ }
+
+ /**
+ * @param array $master
+ * @param array $results
+ * @param bool $groupBySection
+ * @return array
+ */
+ protected function mergeList( array $master, array $results, $groupBySection ) {
+ // sort all notifications by timestamp: most recent first
+ $sort = function ( $a, $b ) {
+ return $a['timestamp']['utcunix'] - $b['timestamp']['utcunix'];
+ };
+
+ if ( $groupBySection ) {
+ foreach ( EchoAttributeManager::$sections as $section ) {
+ if ( !isset( $master[$section]['list'] ) ) {
+ $master[$section]['list'] = [];
+ }
+ foreach ( $results as $result ) {
+ $master[$section]['list'] = array_merge( $master[$section]['list'], $result[$section]['list'] );
+ }
+ usort( $master[$section]['list'], $sort );
+ }
+ } else {
+ if ( !isset( $master['list'] ) || !is_array( $master['list'] ) ) {
+ $master['list'] = [];
+ }
+ foreach ( $results as $result ) {
+ $master['list'] = array_merge( $master['list'], $result['list'] );
+ }
+ usort( $master['list'], $sort );
+ }
+
+ return $master;
+ }
+
+ /**
+ * @param array $master
+ * @param array $results
+ * @param bool $groupBySection
+ * @return array
+ */
+ protected function mergeCount( array $master, array $results, $groupBySection ) {
+ if ( $groupBySection ) {
+ foreach ( EchoAttributeManager::$sections as $section ) {
+ if ( !isset( $master[$section]['rawcount'] ) ) {
+ $master[$section]['rawcount'] = 0;
+ }
+ foreach ( $results as $result ) {
+ $master[$section]['rawcount'] += $result[$section]['rawcount'];
+ }
+ $master[$section]['count'] = EchoNotificationController::formatNotificationCount( $master[$section]['rawcount'] );
+ }
+ }
+
+ if ( !isset( $master['rawcount'] ) ) {
+ $master['rawcount'] = 0;
+ }
+ foreach ( $results as $result ) {
+ // regardless of groupbysection, totals are always included
+ $master['rawcount'] += $result['rawcount'];
+ }
+ $master['count'] = EchoNotificationController::formatNotificationCount( $master['rawcount'] );
+
+ return $master;
+ }
+
public function getAllowedParams() {
$sections = EchoAttributeManager::$sections;
- $params = array(
- 'prop' => array(
+
+ $params = parent::getAllowedParams();
+ $params += [
+ 'filter' => [
+ ApiBase::PARAM_ISMULTI => true,
+ ApiBase::PARAM_DFLT => 'read|!read',
+ ApiBase::PARAM_TYPE => [
+ 'read',
+ '!read',
+ ],
+ ],
+ 'prop' => [
ApiBase::PARAM_ISMULTI => true,
- ApiBase::PARAM_TYPE => array(
+ ApiBase::PARAM_TYPE => [
'list',
'count',
- 'index',
- ),
+ 'seenTime',
+ ],
ApiBase::PARAM_DFLT => 'list',
- ),
- 'sections' => array(
+ ],
+ 'sections' => [
ApiBase::PARAM_DFLT => implode( '|', $sections ),
ApiBase::PARAM_TYPE => $sections,
ApiBase::PARAM_ISMULTI => true,
- ),
- 'groupbysection' => array(
+ ],
+ 'groupbysection' => [
ApiBase::PARAM_TYPE => 'boolean',
ApiBase::PARAM_DFLT => false,
- ),
- 'format' => array(
- ApiBase::PARAM_TYPE => array(
- 'text',
- 'flyout',
- 'html',
- ),
- ),
- 'limit' => array(
+ ],
+ 'format' => [
+ ApiBase::PARAM_TYPE => [
+ 'model',
+ 'special',
+ 'flyout', /* @deprecated */
+ 'html', /* @deprecated */
+ ],
+ ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
+ ],
+ 'limit' => [
ApiBase::PARAM_TYPE => 'limit',
ApiBase::PARAM_DFLT => 20,
ApiBase::PARAM_MIN => 1,
ApiBase::PARAM_MAX => ApiBase::LIMIT_SML1,
ApiBase::PARAM_MAX2 => ApiBase::LIMIT_SML2,
- ),
- 'index' => false,
- 'continue' => array(
- /** @todo Once support for MediaWiki < 1.25 is dropped, just use ApiBase::PARAM_HELP_MSG directly */
- constant( 'ApiBase::PARAM_HELP_MSG' ) ?: '' => 'api-help-param-continue',
- ),
- );
+ ],
+ 'continue' => [
+ ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
+ ],
+ 'unreadfirst' => [
+ ApiBase::PARAM_TYPE => 'boolean',
+ ApiBase::PARAM_DFLT => false,
+ ],
+ 'titles' => [
+ ApiBase::PARAM_ISMULTI => true,
+ ],
+ 'bundle' => [
+ ApiBase::PARAM_TYPE => 'boolean',
+ ApiBase::PARAM_DFLT => false,
+ ],
+ ];
foreach ( $sections as $section ) {
$params[$section . 'continue'] = null;
- $params[$section . 'unreadfirst'] = array(
+ $params[$section . 'unreadfirst'] = [
ApiBase::PARAM_TYPE => 'boolean',
ApiBase::PARAM_DFLT => false,
- );
+ ];
}
- return $params;
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'prop' => 'Details to request.',
- 'sections' => 'The notification sections to query (i.e. some combination of \'alert\' and \'message\').',
- 'groupbysection' => 'Whether to group the result by section, each section is fetched separately if set',
- 'format' => 'If specified, notifications will be returned formatted this way.',
- 'index' => 'If specified, a list of notification IDs, in order, will be returned.',
- 'limit' => 'The maximum number of notifications to return.',
- 'continue' => 'When more results are available, use this to continue, this is used only when groupbysection is not set.',
- 'alertcontinue' => 'When more alert results are available, use this to continue.',
- 'messagecontinue' => 'When more message results are available, use this to continue.',
- 'alertunreadfirst' => 'Whether to show unread message notifications first',
- 'messageunreadfirst' => 'Whether to show unread alert notifications first'
- );
- }
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Get notifications waiting for the current user';
- }
+ if ( $this->allowCrossWikiNotifications() ) {
+ $params += [
+ // create "x notifications from y wikis" notification bundle &
+ // include unread counts from other wikis in prop=count results
+ 'crosswikisummary' => [
+ ApiBase::PARAM_TYPE => 'boolean',
+ ApiBase::PARAM_DFLT => false,
+ ],
+ ];
+ }
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=query&meta=notifications',
- 'api.php?action=query&meta=notifications&notprop=count&notsections=alert|message&notgroupbysection=1',
- );
+ return $params;
}
/**
* @see ApiBase::getExamplesMessages()
+ * @return array
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=query&meta=notifications'
=> 'apihelp-query+notifications-example-1',
'action=query&meta=notifications&notprop=count&notsections=alert|message&notgroupbysection=1'
=> 'apihelp-query+notifications-example-2',
- );
+ ];
}
public function getHelpUrls() {
diff --git a/Echo/includes/api/ApiEchoUnreadNotificationPages.php b/Echo/includes/api/ApiEchoUnreadNotificationPages.php
new file mode 100644
index 00000000..53c1f761
--- /dev/null
+++ b/Echo/includes/api/ApiEchoUnreadNotificationPages.php
@@ -0,0 +1,212 @@
+<?php
+
+class ApiEchoUnreadNotificationPages extends ApiCrossWikiBase {
+ /**
+ * @var bool
+ */
+ protected $crossWikiSummary = false;
+
+ /**
+ * @param ApiQuery $query
+ * @param string $moduleName
+ */
+ public function __construct( $query, $moduleName ) {
+ parent::__construct( $query, $moduleName, 'unp' );
+ }
+
+ /**
+ * @throws ApiUsageException
+ */
+ public function execute() {
+ // To avoid API warning, register the parameter used to bust browser cache
+ $this->getMain()->getVal( '_' );
+
+ if ( $this->getUser()->isAnon() ) {
+ $this->dieWithError( 'apierror-mustbeloggedin-generic', 'login-required' );
+ }
+
+ $params = $this->extractRequestParams();
+
+ $result = [];
+ if ( in_array( wfWikiId(), $this->getRequestedWikis() ) ) {
+ $result[wfWikiID()] = $this->getFromLocal( $params['limit'], $params['grouppages'] );
+ }
+
+ if ( $this->getRequestedForeignWikis() ) {
+ $result += $this->getUnreadNotificationPagesFromForeign();
+ }
+
+ $apis = $this->foreignNotifications->getApiEndpoints( $this->getRequestedWikis() );
+ foreach ( $result as $wiki => $data ) {
+ $result[$wiki]['source'] = $apis[$wiki];
+ $result[$wiki]['pages'] = $data['pages'] ?: [];
+ }
+
+ $this->getResult()->addValue( 'query', $this->getModuleName(), $result );
+ }
+
+ /**
+ * @param int $limit
+ * @param bool $groupPages
+ * @return array
+ */
+ protected function getFromLocal( $limit, $groupPages ) {
+ $attributeManager = EchoAttributeManager::newFromGlobalVars();
+ $enabledTypes = $attributeManager->getUserEnabledEvents( $this->getUser(), 'web' );
+
+ $dbr = MWEchoDbFactory::newFromDefault()->getEchoDb( DB_SLAVE );
+ // If $groupPages is true, we need to fetch all pages and apply the ORDER BY and LIMIT ourselves
+ // after grouping.
+ $extraOptions = $groupPages ? [] : [ 'ORDER BY' => 'count DESC', 'LIMIT' => $limit ];
+ $rows = $dbr->select(
+ [ 'echo_event', 'echo_notification' ],
+ [ 'event_page_id', 'count' => 'COUNT(*)' ],
+ [
+ 'notification_user' => $this->getUser()->getId(),
+ 'notification_read_timestamp' => null,
+ 'event_deleted' => 0,
+ 'event_type' => $enabledTypes,
+ ],
+ __METHOD__,
+ [
+ 'GROUP BY' => 'event_page_id',
+ ] + $extraOptions,
+ [ 'echo_notification' => [ 'INNER JOIN', 'notification_event = event_id' ] ]
+ );
+
+ if ( $rows === false ) {
+ return [];
+ }
+
+ $nullCount = 0;
+ $pageCounts = [];
+ foreach ( $rows as $row ) {
+ if ( $row->event_page_id !== null ) {
+ $pageCounts[$row->event_page_id] = intval( $row->count );
+ } else {
+ $nullCount = intval( $row->count );
+ }
+ }
+
+ $titles = Title::newFromIDs( array_keys( $pageCounts ) );
+
+ $groupCounts = [];
+ foreach ( $titles as $title ) {
+ if ( $groupPages ) {
+ // If $title is a talk page, add its count to its subject page's count
+ $pageName = $title->getSubjectPage()->getPrefixedText();
+ } else {
+ $pageName = $title->getPrefixedText();
+ }
+
+ $count = $pageCounts[$title->getArticleId()];
+ if ( isset( $groupCounts[$pageName] ) ) {
+ $groupCounts[$pageName] += $count;
+ } else {
+ $groupCounts[$pageName] = $count;
+ }
+ }
+
+ $userPageName = $this->getUser()->getUserPage()->getPrefixedText();
+ if ( $nullCount > 0 && $groupPages ) {
+ // Add the count for NULL (not associated with any page) to the count for the user page
+ if ( isset( $groupCounts[$userPageName] ) ) {
+ $groupCounts[$userPageName] += $nullCount;
+ } else {
+ $groupCounts[$userPageName] = $nullCount;
+ }
+ }
+
+ arsort( $groupCounts );
+ if ( $groupPages ) {
+ $groupCounts = array_slice( $groupCounts, 0, $limit );
+ }
+
+ $result = [];
+ foreach ( $groupCounts as $pageName => $count ) {
+ if ( $groupPages ) {
+ $title = Title::newFromText( $pageName );
+ $pages = [ $title->getSubjectPage()->getPrefixedText() ];
+ if ( $title->canHaveTalkPage() ) {
+ $pages[] = $title->getTalkPage()->getPrefixedText();
+ }
+ if ( $pageName === $userPageName ) {
+ $pages[] = null;
+ }
+ $pageDescription = [
+ 'ns' => $title->getNamespace(),
+ 'title' => $title->getPrefixedText(),
+ 'unprefixed' => $title->getText(),
+ 'pages' => $pages,
+ ];
+ } else {
+ $pageDescription = [ 'title' => $pageName ];
+ }
+ $result[] = $pageDescription + [
+ 'count' => $count,
+ ];
+ }
+ if ( !$groupPages && $nullCount > 0 ) {
+ $result[] = [
+ 'title' => null,
+ 'count' => $nullCount,
+ ];
+ }
+
+ return [
+ 'pages' => $result,
+ 'totalCount' => MWEchoNotifUser::newFromUser( $this->getUser() )->getLocalNotificationCount(),
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ protected function getUnreadNotificationPagesFromForeign() {
+ $result = [];
+ foreach ( $this->getFromForeign() as $wiki => $data ) {
+ $result[$wiki] = $data['query'][$this->getModuleName()][$wiki];
+ }
+
+ return $result;
+ }
+
+ /**
+ * @return array
+ */
+ public function getAllowedParams() {
+ global $wgEchoMaxUpdateCount;
+
+ return parent::getAllowedParams() + [
+ 'grouppages' => [
+ ApiBase::PARAM_TYPE => 'boolean',
+ ApiBase::PARAM_DFLT => false,
+ ],
+ 'limit' => [
+ ApiBase::PARAM_TYPE => 'limit',
+ ApiBase::PARAM_DFLT => 10,
+ ApiBase::PARAM_MIN => 1,
+ ApiBase::PARAM_MAX => $wgEchoMaxUpdateCount,
+ ApiBase::PARAM_MAX2 => $wgEchoMaxUpdateCount,
+ ],
+ // there is no `offset` or `continue` value: the set of possible
+ // notifications is small enough to allow fetching all of them at
+ // once, and any sort of fetching would be unreliable because
+ // they're sorted based on count of notifications, which could
+ // change in between requests
+ ];
+ }
+
+ /**
+ * @see ApiBase::getExamplesMessages()
+ */
+ protected function getExamplesMessages() {
+ return [
+ 'action=query&meta=unreadnotificationpages' => 'apihelp-query+unreadnotificationpages-example-1',
+ ];
+ }
+
+ public function getHelpUrls() {
+ return 'https://www.mediawiki.org/wiki/Echo_(Notifications)/API';
+ }
+}
diff --git a/Echo/includes/cache/LocalCache.php b/Echo/includes/cache/LocalCache.php
index 6d357340..d951e307 100644
--- a/Echo/includes/cache/LocalCache.php
+++ b/Echo/includes/cache/LocalCache.php
@@ -15,7 +15,7 @@ abstract class EchoLocalCache {
/**
* Target object cache
- * @var MapCacheLRU
+ * @var HashBagOStuff
*/
protected $targets;
@@ -23,7 +23,7 @@ abstract class EchoLocalCache {
* Lookup ids that have not been resolved for a target
* @param int[]
*/
- protected $lookups = array();
+ protected $lookups = [];
/**
* Resolve ids in lookups to targets
@@ -34,13 +34,14 @@ abstract class EchoLocalCache {
* Use Factory method like EchoTitleLocalCache::create()
*/
protected function __construct() {
- $this->targets = new MapCacheLRU( self::TARGET_MAX_NUM );
+ $this->targets = new HashBagOStuff( [ 'maxKeys' => self::TARGET_MAX_NUM ] );
}
/**
* Add a key to the lookup and the key is used to resolve cache target
*
* @param int $key
+ * @param null $target
*/
public function add( $key, $target = null ) {
if (
@@ -70,6 +71,7 @@ abstract class EchoLocalCache {
return $target;
}
}
+
return null;
}
@@ -78,7 +80,7 @@ abstract class EchoLocalCache {
*/
public function clearAll() {
$this->targets->clear();
- $this->lookups = array();
+ $this->lookups = [];
}
/**
@@ -89,7 +91,7 @@ abstract class EchoLocalCache {
}
/**
- * @return array
+ * @return BagOStuff
*/
public function getTargets() {
return $this->targets;
diff --git a/Echo/includes/cache/RevisionLocalCache.php b/Echo/includes/cache/RevisionLocalCache.php
index 3e1f81c3..9831de49 100644
--- a/Echo/includes/cache/RevisionLocalCache.php
+++ b/Echo/includes/cache/RevisionLocalCache.php
@@ -18,11 +18,12 @@ class EchoRevisionLocalCache extends EchoLocalCache {
if ( !self::$instance ) {
self::$instance = new EchoRevisionLocalCache();
}
+
return self::$instance;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
protected function resolve() {
if ( $this->lookups ) {
@@ -34,21 +35,21 @@ class EchoRevisionLocalCache extends EchoLocalCache {
Revision::selectUserFields()
);
$res = $dbr->select(
- array( 'revision', 'page', 'user' ),
+ [ 'revision', 'page', 'user' ],
$fields,
- array( 'rev_id' => $this->lookups ),
+ [ 'rev_id' => $this->lookups ],
__METHOD__,
- array(),
- array(
+ [],
+ [
'page' => Revision::pageJoinCond(),
'user' => Revision::userJoinCond()
- )
+ ]
);
if ( $res ) {
foreach ( $res as $row ) {
$this->targets->set( $row->rev_id, new Revision( $row ) );
}
- $this->lookups = array();
+ $this->lookups = [];
}
}
}
diff --git a/Echo/includes/cache/TitleLocalCache.php b/Echo/includes/cache/TitleLocalCache.php
index 42e2be94..6c43790b 100644
--- a/Echo/includes/cache/TitleLocalCache.php
+++ b/Echo/includes/cache/TitleLocalCache.php
@@ -18,11 +18,12 @@ class EchoTitleLocalCache extends EchoLocalCache {
if ( !self::$instance ) {
self::$instance = new EchoTitleLocalCache();
}
+
return self::$instance;
}
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
protected function resolve() {
if ( $this->lookups ) {
@@ -30,7 +31,7 @@ class EchoTitleLocalCache extends EchoLocalCache {
foreach ( $titles as $title ) {
$this->targets->set( $title->getArticleId(), $title );
}
- $this->lookups = array();
+ $this->lookups = [];
}
}
diff --git a/Echo/includes/controller/ModerationController.php b/Echo/includes/controller/ModerationController.php
new file mode 100644
index 00000000..27241b49
--- /dev/null
+++ b/Echo/includes/controller/ModerationController.php
@@ -0,0 +1,41 @@
+<?php
+use MediaWiki\MediaWikiServices;
+
+/**
+ * This class represents the controller for moderating notifications
+ */
+class EchoModerationController {
+
+ /**
+ * Moderate or unmoderate events
+ *
+ * @param int[] $eventIds
+ * @param bool $moderate Whether to moderate or unmoderate the events
+ * @throws MWException
+ */
+ public static function moderate( $eventIds, $moderate ) {
+ if ( !$eventIds ) {
+ return;
+ }
+
+ $eventMapper = new EchoEventMapper();
+ $notificationMapper = new EchoNotificationMapper();
+
+ $affectedUserIds = $notificationMapper->fetchUsersWithNotificationsForEvents( $eventIds );
+ $eventMapper->toggleDeleted( $eventIds, $moderate );
+
+ DeferredUpdates::addCallableUpdate( function () use ( $affectedUserIds ) {
+ // This update runs after the main transaction round commits.
+ // Wait for the event deletions to be propagated to replica DBs
+ $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+ $lbFactory->waitForReplication( [ 'timeout' => 5 ] );
+ $lbFactory->flushReplicaSnapshots( 'EchoModerationController::moderate' );
+ // Recompute the notification count for the
+ // users whose notifications have been moderated.
+ foreach ( $affectedUserIds as $userId ) {
+ $user = User::newFromId( $userId );
+ MWEchoNotifUser::newFromUser( $user )->resetNotificationCount( DB_REPLICA );
+ }
+ } );
+ }
+}
diff --git a/Echo/includes/controller/NotificationController.php b/Echo/includes/controller/NotificationController.php
index cc4df9e1..788a60fb 100644
--- a/Echo/includes/controller/NotificationController.php
+++ b/Echo/includes/controller/NotificationController.php
@@ -1,59 +1,74 @@
<?php
-use MediaWiki\Logger\LoggerFactory;
/**
* This class represents the controller for notifications
*/
class EchoNotificationController {
/**
- * Echo event agent per wiki blacklist
+ * Echo maximum number of users to cache
*
- * @var string[]
+ * @var int $maxRecipientCacheSize
*/
- static protected $blacklist;
+ static protected $maxRecipientCacheSize = 200;
/**
- * Echo event agent per user whitelist, this overwrites $blacklist
+ * Echo event agent per user blacklist
*
- * @param string[]
+ * @var MapCacheLRU
*/
- static protected $userWhitelist;
+ static protected $blacklistByUser;
/**
- * Queue's that failed formatting and marks them as read at end of request.
+ * Echo event agent per wiki blacklist
*
- * @var EchoDeferredMarkAsReadUpdate|null
+ * @var EchoContainmentList|null
*/
- static protected $markAsRead;
+ static protected $wikiBlacklist;
/**
- * Format the notification count with Language::formatNum(). In addition, for large count,
- * return abbreviated version, e.g. 99+
+ * Echo event agent per user whitelist, this overwrites $blacklistByUser
*
- * @param int $count
- * @return string
+ * @var MapCacheLRU
*/
- public static function formatNotificationCount( $count ) {
- global $wgLang, $wgEchoMaxNotificationCount;
+ static protected $whitelistByUser;
- if ( $count > $wgEchoMaxNotificationCount ) {
- $count = wfMessage(
- 'echo-notification-count',
- $wgLang->formatNum( $wgEchoMaxNotificationCount )
- )->escaped();
+ /**
+ * Returns the count passed in, or MWEchoNotifUser::MAX_BADGE_COUNT + 1,
+ * whichever is less.
+ *
+ * @param int $count
+ * @return int Notification count, with ceiling applied
+ */
+ public static function getCappedNotificationCount( $count ) {
+ if ( $count <= MWEchoNotifUser::MAX_BADGE_COUNT ) {
+ return $count;
} else {
- $count = $wgLang->formatNum( $count );
+ return MWEchoNotifUser::MAX_BADGE_COUNT + 1;
}
+ }
- return $count;
+ /**
+ * Format the notification count as a string. This should only be used for an
+ * isolated string count, e.g. as displayed in personal tools or returned by the API.
+ *
+ * If using it in sentence context, pass the value from getCappedNotificationCount
+ * into a message and use PLURAL. Example: notification-bundle-header-page-linked
+ *
+ * @param int $count Notification count
+ * @return string Formatted count, after applying cap then formatting to string
+ */
+ public static function formatNotificationCount( $count ) {
+ $cappedCount = self::getCappedNotificationCount( $count );
+
+ return wfMessage( 'echo-badge-count' )->numParams( $cappedCount )->text();
}
/**
* Processes notifications for a newly-created EchoEvent
*
* @param EchoEvent $event
- * @param boolean $defer Defer to job queue or not
+ * @param bool $defer Defer to job queue or not
*/
public static function notify( $event, $defer = true ) {
// Defer to job queue if defer to job queue is requested and
@@ -61,10 +76,11 @@ class EchoNotificationController {
if ( $defer && $event->getUseJobQueue() ) {
// defer job insertion till end of request when all primary db transactions
// have been committed
- DeferredUpdates::addCallableUpdate( function() use ( $event ) {
+ DeferredUpdates::addCallableUpdate( function () use ( $event ) {
// can't use self::, php 5.3 doesn't inherit class scope
EchoNotificationController::enqueueEvent( $event );
} );
+
return;
}
@@ -76,7 +92,7 @@ class EchoNotificationController {
$type = $event->getType();
$notifyTypes = self::getEventNotifyTypes( $type );
- $userIds = array();
+ $userIds = [];
$userIdsCount = 0;
foreach ( self::getUsersToNotifyForEvent( $event ) as $user ) {
$userIds[$user->getId()] = $user->getId();
@@ -89,11 +105,11 @@ class EchoNotificationController {
$rev = Revision::newFromID( $extra['revid'], Revision::READ_LATEST );
if ( $rev->isMinor() ) {
- $notifyTypes = array_diff( $notifyTypes, array( 'email' ) );
+ $notifyTypes = array_diff( $notifyTypes, [ 'email' ] );
}
}
}
- Hooks::run( 'EchoGetNotificationTypes', array( $user, $event, &$userNotifyTypes ) );
+ Hooks::run( 'EchoGetNotificationTypes', [ $user, $event, &$userNotifyTypes ] );
// types such as web, email, etc
foreach ( $userNotifyTypes as $type ) {
@@ -104,7 +120,7 @@ class EchoNotificationController {
// Process 1000 users per NotificationDeleteJob
if ( $userIdsCount > 1000 ) {
self::enqueueDeleteJob( $userIds, $event );
- $userIds = array();
+ $userIds = [];
$userIdsCount = 0;
}
}
@@ -129,30 +145,44 @@ class EchoNotificationController {
$job = new EchoNotificationDeleteJob(
$event->getTitle() ?: Title::newMainPage(),
- array(
+ [
'userIds' => $userIds
- )
+ ]
);
JobQueueGroup::singleton()->push( $job );
}
/**
- * @param string $type Event type
- * @return string[] List of notification types to send for
+ * Get the notify types for this event, eg, web/email
+ *
+ * @param string $eventType Event type
+ * @return string[] List of notify types that apply for
* this event type
*/
- public static function getEventNotifyTypes( $type ) {
- // Get the notification types for this event, eg, web/email
- global $wgEchoDefaultNotificationTypes;
+ public static function getEventNotifyTypes( $eventType ) {
+ global $wgDefaultNotifyTypeAvailability,
+ $wgEchoNotifications;
+
+ $attributeManager = EchoAttributeManager::newFromGlobalVars();
+
+ $category = $attributeManager->getNotificationCategory( $eventType );
+
+ // If the category is displayed in preferences, we should go by that, rather
+ // than overrides that are inconsistent with what the user saw in preferences.
+ $isTypeSpecificConsidered = !$attributeManager->isCategoryDisplayedInPreferences(
+ $category
+ );
- $notifyTypes = $wgEchoDefaultNotificationTypes['all'];
- if ( isset( $wgEchoDefaultNotificationTypes[$type] ) ) {
+ $notifyTypes = $wgDefaultNotifyTypeAvailability;
+
+ if ( $isTypeSpecificConsidered && isset( $wgEchoNotifications[$eventType]['notify-type-availability'] ) ) {
$notifyTypes = array_merge(
$notifyTypes,
- $wgEchoDefaultNotificationTypes[$type]
+ $wgEchoNotifications[$eventType]['notify-type-availability']
);
}
+ // Category settings for availability are considered in EchoNotifier
return array_keys( array_filter( $notifyTypes ) );
}
@@ -164,45 +194,82 @@ class EchoNotificationController {
public static function enqueueEvent( EchoEvent $event ) {
$job = new EchoNotificationJob(
$event->getTitle() ?: Title::newMainPage(),
- array(
+ [
'event' => $event,
'masterPos' => MWEchoDbFactory::newFromDefault()
->getMasterPosition(),
- )
+ ]
);
JobQueueGroup::singleton()->push( $job );
}
-
/**
* Implements blacklist per active wiki expected to be initialized
* from InitializeSettings.php
*
- * @param EchoEvent $event The event to test for exclusion via global blacklist
- * @return boolean True when the event agent is in the global blacklist
+ * @param EchoEvent $event The event to test for exclusion
+ * @param User $user recipient of the notification for per-user blacklists
+ * @return bool True when the event agent is blacklisted
*/
- protected static function isBlacklisted( EchoEvent $event ) {
+ public static function isBlacklistedByUser( EchoEvent $event, User $user ) {
+ global $wgEchoAgentBlacklist, $wgEchoPerUserBlacklist;
+
+ $clusterCache = ObjectCache::getLocalClusterInstance();
+
if ( !$event->getAgent() ) {
return false;
}
- if ( self::$blacklist === null ) {
- global $wgEchoAgentBlacklist, $wgEchoOnWikiBlacklist,
- $wgMemc;
-
- self::$blacklist = new EchoContainmentSet;
- self::$blacklist->addArray( $wgEchoAgentBlacklist );
- if ( $wgEchoOnWikiBlacklist !== null ) {
- self::$blacklist->addOnWiki(
- NS_MEDIAWIKI,
- $wgEchoOnWikiBlacklist,
- $wgMemc,
- wfMemcKey( "echo_on_wiki_blacklist")
- );
+ // Ensure we have a list of blacklists
+ if ( self::$blacklistByUser === null ) {
+ self::$blacklistByUser = new MapCacheLRU( self::$maxRecipientCacheSize );
+ }
+
+ // Ensure we have a blacklist for the user
+ if ( !self::$blacklistByUser->has( $user->getId() ) ) {
+ $blacklist = new EchoContainmentSet( $user );
+
+ // Add the config setting
+ $blacklist->addArray( $wgEchoAgentBlacklist );
+
+ // Add wiki-wide blacklist
+ $wikiBlacklist = self::getWikiBlacklist();
+ if ( $wikiBlacklist !== null ) {
+ $blacklist->add( $wikiBlacklist );
}
+
+ // Add to blacklist from user preference
+ if ( $wgEchoPerUserBlacklist ) {
+ $blacklist->addFromUserOption( 'echo-notifications-blacklist' );
+ }
+
+ // Add user's blacklist to dictionary if user wasn't already there
+ self::$blacklistByUser->set( $user->getId(), $blacklist );
+ } else {
+ // Just get the user's blacklist if it's already there
+ $blacklist = self::$blacklistByUser->get( $user->getId() );
}
+ return $blacklist->contains( $event->getAgent()->getName() );
+ }
- return self::$blacklist->contains( $event->getAgent()->getName() );
+ /**
+ * @return EchoContainmentList|null
+ */
+ protected static function getWikiBlacklist() {
+ $clusterCache = ObjectCache::getLocalClusterInstance();
+ global $wgEchoOnWikiBlacklist;
+ if ( !$wgEchoOnWikiBlacklist ) {
+ return null;
+ }
+ if ( self::$wikiBlacklist === null ) {
+ self::$wikiBlacklist = new EchoCachedList(
+ $clusterCache,
+ $clusterCache->makeKey( "echo_on_wiki_blacklist" ),
+ new EchoOnWikiList( NS_MEDIAWIKI, $wgEchoOnWikiBlacklist )
+ );
+ }
+
+ return self::$wikiBlacklist;
}
/**
@@ -210,11 +277,11 @@ class EchoNotificationController {
*
* @param EchoEvent $event The event to test for inclusion in whitelist
* @param User $user The user that owns the whitelist
- * @return boolean True when the event agent is in the user whitelist
+ * @return bool True when the event agent is in the user whitelist
*/
public static function isWhitelistedByUser( EchoEvent $event, User $user ) {
- global $wgEchoPerUserWhitelistFormat, $wgMemc;
-
+ $clusterCache = ObjectCache::getLocalClusterInstance();
+ global $wgEchoPerUserWhitelistFormat;
if ( $wgEchoPerUserWhitelistFormat === null || !$event->getAgent() ) {
return false;
@@ -225,18 +292,26 @@ class EchoNotificationController {
return false; // anonymous user
}
- if ( !isset( self::$userWhitelist[$userId] ) ) {
- self::$userWhitelist[$userId] = new EchoContainmentSet;
- self::$userWhitelist[$userId]->addOnWiki(
+ // Ensure we have a list of whitelists
+ if ( self::$whitelistByUser === null ) {
+ self::$whitelistByUser = new MapCacheLRU( self::$maxRecipientCacheSize );
+ }
+
+ // Ensure we have a whitelist for the user
+ if ( !self::$whitelistByUser->has( $userId ) ) {
+ $whitelist = new EchoContainmentSet( $user );
+ self::$whitelistByUser->set( $userId, $whitelist );
+ $whitelist->addOnWiki(
NS_USER,
sprintf( $wgEchoPerUserWhitelistFormat, $user->getName() ),
- $wgMemc,
- wfMemcKey( "echo_on_wiki_whitelist_" . $userId )
+ $clusterCache,
+ $clusterCache->makeKey( "echo_on_wiki_whitelist_" . $userId )
);
+ } else {
+ // Just get the user's whitelist
+ $whitelist = self::$whitelistByUser->get( $userId );
}
-
- return self::$userWhitelist[$userId]
- ->contains( $event->getAgent()->getName() );
+ return $whitelist->contains( $event->getAgent()->getName() );
}
/**
@@ -259,34 +334,35 @@ class EchoNotificationController {
throw new MWException( "Cannot notify anonymous user: {$user->getName()}" );
}
- call_user_func_array( $wgEchoNotifiers[$type], array( $user, $event ) );
+ call_user_func_array( $wgEchoNotifiers[$type], [ $user, $event ] );
}
/**
* Returns an array each element of which is the result of a
- * user-locator attached to the event type.
+ * user-locator|user-filters attached to the event type.
*
* @param EchoEvent $event
+ * @param string $locator Either EchoAttributeManager::ATTR_LOCATORS or EchoAttributeManager::ATTR_FILTERS
* @return array
*/
- public static function evaluateUserLocators( EchoEvent $event ) {
+ public static function evaluateUserCallable( EchoEvent $event, $locator = EchoAttributeManager::ATTR_LOCATORS ) {
$attributeManager = EchoAttributeManager::newFromGlobalVars();
$type = $event->getType();
- $result = array();
- foreach ( $attributeManager->getUserLocators( $type ) as $callable ) {
+ $result = [];
+ foreach ( $attributeManager->getUserCallable( $type, $locator ) as $callable ) {
// locator options can be set per-event by using an array with
// name as first parameter.
if ( is_array( $callable ) ) {
$options = $callable;
- $spliced = array_splice( $options, 0, 1, array( $event ) );
+ $spliced = array_splice( $options, 0, 1, [ $event ] );
$callable = reset( $spliced );
} else {
- $options = array( $event );
+ $options = [ $event ];
}
if ( is_callable( $callable ) ) {
$result[] = call_user_func_array( $callable, $options );
} else {
- wfDebugLog( __CLASS__, __FUNCTION__ . ": Invalid user-locator returned for $type" );
+ wfDebugLog( __CLASS__, __FUNCTION__ . ": Invalid $locator returned for $type" );
}
}
@@ -301,31 +377,48 @@ class EchoNotificationController {
*/
public static function getUsersToNotifyForEvent( EchoEvent $event ) {
$notify = new EchoFilteredSequentialIterator;
- foreach ( self::evaluateUserLocators( $event ) as $users ) {
+ foreach ( self::evaluateUserCallable( $event, EchoAttributeManager::ATTR_LOCATORS ) as $users ) {
$notify->add( $users );
}
// Hook for injecting more users.
// @deprecated
- $users = array();
- Hooks::run( 'EchoGetDefaultNotifiedUsers', array( $event, &$users ) );
+ $users = [];
+ Hooks::run( 'EchoGetDefaultNotifiedUsers', [ $event, &$users ] );
if ( $users ) {
$notify->add( $users );
}
+ // Exclude certain users
+ foreach ( self::evaluateUserCallable( $event, EchoAttributeManager::ATTR_FILTERS ) as $users ) {
+ // the result of the callback can be both an iterator or array
+ $users = is_array( $users ) ? $users : iterator_to_array( $users );
+ $notify->addFilter( function ( User $user ) use ( $users ) {
+ // we need to check if $user is in $users, but they're not
+ // guaranteed to be the same object, so I'll compare ids.
+ $userId = $user->getId();
+ $userIds = array_map( function ( User $user ) {
+ return $user->getId();
+ }, $users );
+ return !in_array( $userId, $userIds );
+ } );
+ }
+
// Filter non-User, anon and duplicate users
- $seen = array();
- $notify->addFilter( function( $user ) use( &$seen ) {
+ $seen = [];
+ $notify->addFilter( function ( $user ) use ( &$seen ) {
if ( !$user instanceof User ) {
wfDebugLog( __METHOD__, 'Expected all User instances, received:' .
( is_object( $user ) ? get_class( $user ) : gettype( $user ) )
);
+
return false;
}
if ( $user->isAnon() || isset( $seen[$user->getId()] ) ) {
return false;
}
$seen[$user->getId()] = true;
+
return true;
} );
@@ -333,86 +426,33 @@ class EchoNotificationController {
$extra = $event->getExtra();
if ( ( !isset( $extra['notifyAgent'] ) || !$extra['notifyAgent'] ) && $event->getAgent() ) {
$agentId = $event->getAgent()->getId();
- $notify->addFilter( function( $user ) use( $agentId ) {
+ $notify->addFilter( function ( $user ) use ( $agentId ) {
return $user->getId() != $agentId;
} );
}
- // Apply per-wiki event blacklist and per-user whitelists
- // of that blacklist.
- if ( self::isBlacklisted( $event ) ) {
- $notify->addFilter( function( $user ) use( $event ) {
- // don't use self:: - PHP5.3 closures don't inherit class scope
- return EchoNotificationController::isWhitelistedByUser( $event, $user );
- } );
- }
-
- return $notify->getIterator();
- }
-
- /**
- * Formats a notification
- *
- * @param EchoEvent $event The event for a notification.
- * @param User $user The user to format the notification for.
- * @param string $format The format to show the notification in: text, html, or email
- * @param string $type The type of notification being distributed (e.g. email, web)
- * @return string|array The formatted notification, or an array of subject
- * and body (for emails), or an error message
- */
- public static function formatNotification( EchoEvent $event, User $user, $format = 'text', $type = 'web' ) {
- $eventType = $event->getType();
-
- $res = '';
- try {
- $formatter = EchoNotificationFormatter::factory( $eventType );
- $formatter->setOutputFormat( $format );
- } catch ( InvalidArgumentException $e ) {
- self::failFormatting( $event, $user );
- return '';
- }
- set_error_handler( array( __CLASS__, 'formatterErrorHandler' ), -1 );
- try {
- $res = $formatter->format( $event, $user, $type );
- } catch ( Exception $e ) {
- $context = array(
- 'id' => $event->getId(),
- 'eventType' => $eventType,
- 'format' => $format,
- 'type' => $type,
- 'user' => $user ? $user->getName() : 'no user',
- 'exceptionName' => get_class( $e ),
- 'exceptionMessage' => $e->getMessage(),
- );
- LoggerFactory::getInstance( 'Echo' )->error( 'Error formatting notification', $context );
- MWExceptionHandler::logException( $e );
- }
- restore_error_handler();
-
- if ( $res === '' ) {
- self::failFormatting( $event, $user );
- }
+ // Apply blacklists and whitelists.
+ $notify->addFilter( function ( $user ) use ( $event ) {
+ $title = $event->getTitle();
+
+ if ( self::isBlacklistedByUser( $event, $user ) &&
+ (
+ $title === null ||
+ !(
+ // Still notify for posts anywhere in
+ // user's talk space
+ $title->getRootText() === $user->getName() &&
+ $title->getNamespace() === NS_USER_TALK
+ )
+ )
+ ) {
+ return self::isWhitelistedByUser( $event, $user );
+ }
- return $res;
- }
+ return true;
+ } );
- /**
- * Event has failed to format for the given user. Mark it as read so
- * we do not continue to notify them about this broken event.
- *
- * @param EchoEvent $event
- * @param User $user
- */
- protected static function failFormatting( EchoEvent $event, $user ) {
- // FIXME: The only issue is that the badge count won't be up to date
- // till you refresh the page. Probably we could do this in the browser
- // so that if the formatting is empty and the notif is unread, put it
- // in the auto-mark-read API
- if ( self::$markAsRead === null ) {
- self::$markAsRead = new EchoDeferredMarkAsReadUpdate();
- DeferredUpdates::addUpdate( self::$markAsRead );
- }
- self::$markAsRead->add( $event, $user );
+ return $notify->getIterator();
}
/**
@@ -420,6 +460,12 @@ class EchoNotificationController {
*
* Converts E_RECOVERABLE_ERROR, such as passing null to a method expecting
* a non-null object, into exceptions.
+ * @param int $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param int $errline
+ * @return bool
+ * @throw EchoCatchableFatalErrorException
*/
public static function formatterErrorHandler( $errno, $errstr, $errfile, $errline ) {
if ( $errno !== E_RECOVERABLE_ERROR ) {
diff --git a/Echo/includes/formatters/ArticleReminderPresentationModel.php b/Echo/includes/formatters/ArticleReminderPresentationModel.php
new file mode 100644
index 00000000..06fa7646
--- /dev/null
+++ b/Echo/includes/formatters/ArticleReminderPresentationModel.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Presenter for 'article-reminder' notification
+ *
+ * @author Ela Opper
+ *
+ * @license MIT
+ */
+class EchoArticleReminderPresentationModel extends EchoEventPresentationModel {
+ public function canRender() {
+ return (bool)$this->event->getTitle();
+ }
+
+ public function getIconType() {
+ return 'article-reminder';
+ }
+
+ public function getHeaderMessage() {
+ $msg = $this->getMessageWithAgent( 'notification-header-article-reminder' );
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ return $msg;
+ }
+
+ public function getPrimaryLink() {
+ return [
+ 'url' => $this->event->getTitle()->getLocalURL(),
+ 'label' => $this->msg( 'notification-link-article-reminder' )->text(),
+ ];
+ }
+}
diff --git a/Echo/includes/formatters/BasicFormatter.php b/Echo/includes/formatters/BasicFormatter.php
deleted file mode 100644
index 651a92ac..00000000
--- a/Echo/includes/formatters/BasicFormatter.php
+++ /dev/null
@@ -1,925 +0,0 @@
-<?php
-
-/**
- * @Todo - Consider having $event/$user as class properties since the formatter is
- * always tied to these two entities, in this case, we won't have to pass it around
- * in all the internal method
- * @Todo - Instance variable $distributionType has been added, the local distribution
- * type variable $type passed along all the protected/private method should be removed
- * from all formatters
- */
-class EchoBasicFormatter extends EchoNotificationFormatter {
-
- /**
- * Notification title data for archive page
- * @param array
- */
- protected $title;
-
- /**
- * Notification title data for flyout
- * @param array
- */
- protected $flyoutTitle;
-
- /**
- * Notification title data for bundling ( flyout and archive page )
- */
- protected $bundleTitle;
-
- /**
- * Notification email data
- * @param array
- */
- protected $email;
-
- /**
- * Notification icon for each type
- * @param string
- */
- protected $icon;
-
- /**
- * @todo make this private
- * The language to format a message, default language
- * is the current language
- * @param mixed Language code or Language object
- */
- protected $language;
-
- /**
- * Data for constructing bundle message, data in this array
- * should be used in function processParams()
- * @var array
- */
- protected $bundleData = array (
- 'use-bundle' => false,
- 'raw-data-count' => 1
- );
-
- /**
- * Max number of raw bundle data to query for each bundle event
- */
- protected static $maxRawBundleData = 250;
-
- /**
- * @param array
- */
- public function __construct( $params ) {
- parent::__construct( $params );
-
- if ( !isset( $params['title-message'] ) ) {
- // Required, no default value set
- throw new InvalidArgumentException( "'title-message' parameter not set" );
- }
-
- // Set up default params if any are missing
- $params = $this->setDefaultParams( $params );
-
- // Title for archive page
- $this->title = array(
- 'message' => $params['title-message'],
- 'params' => $params['title-params']
- );
-
- // Title for the flyout
- $this->flyoutTitle = array(
- 'message' => $params['flyout-message'],
- 'params' => $params['flyout-params']
- );
-
- // Bundle title for both archive page and flyout
- $this->bundleTitle = array(
- 'message' => $params['bundle-message'],
- 'params' => $params['bundle-params']
- );
-
- // Notification payload data, eg, summary
- $this->payload = $params['payload'];
-
- // Notification email subject and body
- $this->email = array(
- 'subject' => array(
- 'message' => $params['email-subject-message'],
- 'params' => $params['email-subject-params']
- ),
- 'batch-body' => array(
- 'message' => $params['email-body-batch-message'],
- 'params' => $params['email-body-batch-params']
- ),
- 'batch-bundle-body' => array(
- 'message' => $params['email-body-batch-bundle-message'],
- 'params' => $params['email-body-batch-bundle-params']
- )
- );
-
- // Notification icon for the event type
- $this->icon = $params['icon'];
- }
-
- /**
- * Internal function for setting notification default params
- * @param $params array
- * @return array
- */
- protected function setDefaultParams( $params ) {
- $params += array(
- 'title-params' => array(),
- 'bundle-message' => '',
- 'bundle-params' => array(),
- 'payload' => array(),
- 'email-subject-message' => 'echo-email-subject-default',
- 'email-subject-params' => array(),
- 'email-body-batch-message' => 'echo-email-batch-body-default',
- 'email-body-batch-params' => array(),
- 'email-body-batch-bundle-message' => '',
- 'email-body-batch-bundle-params' => array(),
- 'icon' => 'placeholder'
- );
-
- // default flyout-message to title-message if not defined
- $params += array ( 'flyout-message' => $params['title-message'], 'flyout-params' => $params['title-params'] );
-
- return $params;
- }
-
- /**
- * Apply some custom change before formatting, child class overwriting this method
- * should always invoke a call to the parent method unless child class wants to overwrite
- * the default completely
- *
- * @param $event EchoEvent that the notification is for.
- * @param $user User to format the notification for.
- * @param $type string deprecated
- */
- protected function applyChangeBeforeFormatting( EchoEvent $event, User $user, $type ) {
- // Use the bundle message if use-bundle is true and there is a bundle message
- $this->generateBundleData( $event, $user, $type );
- if ( $this->bundleData['use-bundle'] && $this->bundleTitle['message'] ) {
- $this->title = $this->flyoutTitle = $this->bundleTitle;
- }
- }
-
- /**
- * Formats a notification
- *
- * @param $event EchoEvent that the notification is for.
- * @param $user User to format the notification for.
- * @param $type string The type of notification being distributed (e.g. email, web)
- * @return array|string
- */
- public function format( $event, $user, $type ) {
- $this->setDistributionType( $type );
- $this->applyChangeBeforeFormatting( $event, $user, $type );
-
- if ( $this->outputFormat === 'email' ) {
- return $this->formatEmail( $event, $user, $type );
- }
-
- if ( $this->outputFormat === 'text' ) {
- return $this->formatNotificationTitle( $event, $user )->text();
- }
-
- $iconUrl = $this->getIconUrl( $this->icon, $this->getLanguage()->getDir() );
-
- // Assume html as the format for the notification
- $output = Html::element(
- 'img',
- array(
- 'class' => "mw-echo-icon",
- 'src' => $iconUrl,
- )
- );
-
- // Build the notification title
- $content = Xml::tags(
- 'div',
- array( 'class' => 'mw-echo-title' ),
- $this->formatNotificationTitle( $event, $user )->parse()
- ) . "\n";
-
- // Build the notification payload
- $payload = '';
- foreach ( $this->payload as $payloadComponent ) {
- $payload .= $this->formatPayload( $payloadComponent, $event, $user );
- }
-
- if ( $payload !== '' ) {
- $content .= Xml::tags( 'div', array( 'class' => 'mw-echo-payload' ), $payload ) . "\n";
- }
-
- // Add footer (timestamp and secondary link)
- $content .= $this->formatFooter( $event, $user );
-
- // Add the primary link (hidden)
- if ( $this->outputFormat === 'flyout' ) {
- $content .= $this->getLink( $event, $user, 'primary' );
- }
-
- $output .= Xml::tags( 'div', array( 'class' => 'mw-echo-content' ), $content ) . "\n";
-
- // The state div is used to visually indicate read or unread status. This is
- // handled in a separate element than the notification element so that things
- // like the close box won't inherit the greyed out opacity (which can't be reset).
- $output = Xml::tags( 'div', array( 'class' => 'mw-echo-state' ), $output ) . "\n";
-
- return $output;
- }
-
- /**
- * @param $event EchoEvent
- * @param $user User
- * @return string
- */
- protected function formatNotificationTitle( $event, $user ) {
- if ( $this->outputFormat === 'flyout' ) {
- return $this->formatFragment( $this->flyoutTitle, $event, $user );
- } else {
- return $this->formatFragment( $this->title, $event, $user );
- }
- }
-
- /**
- * Create text version and/or html version for email notification
- *
- * @param $event EchoEvent
- * @param $user User
- * @param $type string deprecated
- * @return array
- */
- protected function formatEmail( $event, $user, $type ) {
- // Email should be always sent in user language
- $this->language = $user->getOption( 'language' );
-
- // Email digest
- if ( $this->distributionType === 'emaildigest' ) {
- return $this->formatEmailDigest( $event, $user );
- }
-
- // Echo single email
- $emailSingle = new EchoEmailSingle( $this, $event, $user );
- $textEmailFormatter = new EchoTextEmailFormatter( $emailSingle );
- // Update the distribution type to emailsubject when formatting
- // email subject
- // @FIXME - Find a better way to do this
- $distributionType = $this->distributionType;
- $this->setDistributionType( 'emailsubject' );
- $subject = $this->formatFragment( $this->email['subject'], $event, $user )->text();
- $this->setDistributionType( $distributionType );
-
- $content = array(
- // Single email subject, there is no need to to escape it for either html
- // or text email since it's always treated as plain text by mail client
- 'subject' => $subject,
- // Single email text body
- 'body' => $textEmailFormatter->formatEmail(),
- );
- $format = MWEchoNotifUser::newFromUser( $user )->getEmailFormat();
- if ( $format == EchoHooks::EMAIL_FORMAT_HTML ) {
- $htmlEmailFormatter = new EchoHTMLEmailFormatter( $emailSingle );
- $outputFormat = $this->outputFormat;
- $this->setOutputFormat( 'htmlemail' );
- // Add single email html body if user prefers html format
- $content['body'] = array (
- 'text' => $content['body'],
- 'html' => $htmlEmailFormatter->formatEmail()
- );
- $this->setOutputFormat( $outputFormat );
- }
-
- return $content;
- }
-
- /**
- * Format text and/or html verion of email digest fragment for this event
- * @param $event EchoEvent
- * @param $user User
- * @return array
- */
- protected function formatEmailDigest( $event, $user ) {
- if ( $this->bundleData['use-bundle'] && $this->email['batch-bundle-body'] ) {
- $key = $this->email['batch-bundle-body'];
- } else {
- $key = $this->email['batch-body'];
- }
-
- // Email digest text body
- $content = array( 'batch-body' => $this->formatFragment( $key, $event, $user )->text() );
- $format = MWEchoNotifUser::newFromUser( $user )->getEmailFormat();
- if ( $format == EchoHooks::EMAIL_FORMAT_HTML ) {
- $outputFormat = $this->outputFormat;
- $this->setOutputFormat( 'htmlemail' );
- $content['batch-body-html'] = $this->formatFragment( $key, $event, $user )->parse();
- $content['icon'] = $this->icon;
- $this->setOutputFormat( $outputFormat );
- }
- return $content;
- }
-
- /**
- * Get Message object in the desired language, use this method instead
- * of wfMessage() if a message would be used in either web or email
- * @param $msgStr string message string
- * @return Message
- */
- public function getMessage( $msgStr ) {
- return wfMessage( $msgStr )->inLanguage( $this->getLanguage() );
- }
-
- /**
- * @return Language
- */
- public function getLanguage() {
- global $wgLang;
- // @todo we should always set this
- if ( $this->language ) {
- return wfGetLangObj( $this->language );
- }
-
- return $wgLang;
- }
-
- /**
- * Creates a notification fragment based on a message and parameters
- *
- * @param $details array An i18n message and parameters to pass to the message
- * @param $event EchoEvent that the notification is for.
- * @param $user User to format the notification for.
- * @return Message
- */
- public function formatFragment( $details, $event, $user ) {
- $message = $this->getMessage( $details['message'] );
- $this->processParams( $details['params'], $event, $message, $user );
-
- return $message;
- }
-
- /**
- * Formats the payload of a notification, child method overwriting this method should
- * always call this method in default case so they can use the payload defined in this
- * function as well
- * @param $payload string
- * @param $event EchoEvent
- * @param $user User
- * @return string
- */
- protected function formatPayload( $payload, $event, $user ) {
- switch ( $payload ) {
- case 'summary':
- $revisionSnippet = $this->getRevisionSnippet( $event, $user );
- if ( $revisionSnippet ) {
- return Xml::tags(
- 'div',
- array( 'class' => 'mw-echo-edit-summary' ),
- Xml::tags(
- 'span', array( 'class' => 'comment' ),
- htmlspecialchars( $revisionSnippet )
- )
- );
- } else {
- return '';
- }
- break;
- case 'comment-text':
- return $this->formatCommentText( $event, $user );
- break;
- default:
- return '';
- }
- }
-
- /**
- * Extract the comment left by a user on a talk page from the event.
- * @param $event EchoEvent The event to format the comment of
- * @param $user User The user to format content for
- * @return string Up to the first 200 characters of the comment
- */
- protected function formatCommentText( EchoEvent $event, $user ) {
- if ( !$event->userCan( Revision::DELETED_TEXT, $user ) ) {
- return $this->getMessage( 'echo-rev-deleted-text-view' )->text();
- }
- $extra = $event->getExtra();
- if ( !isset( $extra['content'] ) ) {
- return '';
- }
- $content = EchoDiscussionParser::stripHeader( $extra['content'] );
- $content = EchoDiscussionParser::stripSignature( $content );
- $content = EchoDiscussionParser::stripIndents( $content );
- return EchoDiscussionParser::getTextSnippet( $content, $this->getLanguage(), 200 );
- }
-
- /**
- * Extract the subject anchor (linkable portion of the edited page) from
- * the event.
- *
- * @param $event EchoEvent The event to format the subject anchor of
- * @return string The anchor on page, or an empty string
- */
- protected function formatSubjectAnchor( EchoEvent $event ) {
- global $wgParser, $wgUser;
-
- if ( !$event->userCan( Revision::DELETED_TEXT, $wgUser ) ) {
- return $this->getMessage( 'echo-rev-deleted-text-view' )->text();
- }
- $extra = $event->getExtra();
- if ( empty( $extra['section-title'] ) ) {
- return '';
- }
-
- // Strip out #, keeping # in the i18n message makes it look more clear
- return substr( $wgParser->guessLegacySectionNameFromWikiText( $extra['section-title'] ), 1 );
- }
-
- /**
- * Build the footer for the notification (timestamp and secondary link)
- * @param EchoEvent $event
- * @param User $user The user to format the notification for.
- * @return String HTML
- */
- protected function formatFooter( $event, $user ) {
- // Default footer is timestamp
- $footer = $this->formatTimestamp( $event->getTimestamp() );
- $secondaryLink = $this->getLink( $event, $user, 'secondary' );
- if ( $secondaryLink ) {
- $footer = $this->getLanguage()->pipeList( array( $footer, $secondaryLink ) );
- }
- return Xml::tags( 'div', array( 'class' => 'mw-echo-notification-footer' ), $footer ) . "\n";
- }
-
- /**
- * Generate links based on output format and passed properties
- * $event EchoEvent
- * $message Message
- * $props array
- */
- protected function setTitleLink( $event, $message, $props = array() ) {
- $title = $event->getTitle();
- if ( !$title ) {
- $message->params( $this->getMessage( 'echo-no-title' )->text() );
- return;
- }
-
- if ( !isset( $props['fragment'] ) ) {
- $props['fragment'] = $this->formatSubjectAnchor( $event );
- }
-
- $link = $this->buildLinkParam( $title, $props );
- $message->params( $link );
- }
-
- /**
- * Build a link, to be used as message parameter, based on output format and
- * passed properties. Return value of this function can be used as parameter
- * for Message::params()
- * $title Title
- * $props array
- */
- protected function buildLinkParam( $title, $props = array() ) {
- $param = array();
- if ( isset( $props['param'] ) ) {
- $param = (array)$props['param'];
- }
-
- if ( isset( $props['fragment'] ) ) {
- $fragment = $props['fragment'];
- $title->setFragment( "#$fragment" );
- }
-
- if ( in_array( $this->outputFormat, array( 'html', 'flyout', 'htmlemail' ) ) ) {
- $attribs = array();
- if ( isset( $props['attribs'] ) ) {
- $attribs = (array)$props['attribs'];
- }
-
- if ( isset( $props['linkText'] ) ) {
- $linkText = $props['linkText'];
- } else {
- $linkText = htmlspecialchars( $title->getPrefixedText() );
- }
-
- $options = array();
- if ( $this->outputFormat === 'htmlemail' ) {
- $options = array( 'https' );
- }
-
- return array( Message::rawParam( Linker::link( $title, $linkText, $attribs, $param, $options ) ) );
- } elseif ( $this->outputFormat === 'email' ) {
- $url = $title->getFullURL( $param, false, PROTO_HTTPS );
- return $this->sanitizeEmailLink( $url );
- } else {
- return $title->getFullURL( $param );
- }
- }
-
- /**
- * Plain text email in some mail client is misinterpreting the ending
- * punctuation, this function would encode the last character
- *
- * @param $url string
- *
- * @return string
- */
- public function sanitizeEmailLink( $url ) {
- // $url should contain all ascii characters now, it's safe to use substr()
- $lastChar = substr( $url, -1 );
- if ( $lastChar && !ctype_alnum( $lastChar ) ) {
- $lastChar = str_replace(
- array( '.', '-', '(', ';', '!', ':', ',' ),
- array( '%2E', '%2D', '%28', '%3B', '%21', '%3A', '%2C' ),
- $lastChar
- );
- $url = substr( $url, 0, -1 ) . $lastChar;
- }
- return $url;
- }
-
- /**
- * Get raw bundle data for an event so it can be manipulated
- * @param EchoEvent
- * @param User
- * @param string deprecated
- * @return EchoEvent[]|bool
- */
- protected function getRawBundleData( $event, $user, $type ) {
- // We should keep bundling for events as long as it has bundle hash
- // even for events with bundling switched to off, this is mainly for
- // historical data
- if ( !$event->getBundleHash() ) {
- return false;
- }
-
- $eventMapper = new EchoEventMapper();
- $events = $eventMapper->fetchByUserBundleHash(
- $user, $event->getBundleHash(), $this->distributionType, 'DESC', self::$maxRawBundleData
- );
-
- if ( $events ) {
- $this->bundleData['raw-data-count'] += count( $events );
- // Distribution types other than web include the base event
- // in the result already, decrement it by one
- if ( $this->distributionType !== 'web' ) {
- $this->bundleData['raw-data-count']--;
- }
- }
-
- return $events;
- }
-
- /**
- * Construct the bundle data for an event, by default, the group iterator
- * is agent, eg, by user A and x others. custom formatter can overwrite
- * this function to use a differnt group iterator such as title, namespace
- *
- * @param EchoEvent
- * @param User
- * @param string deprecated
- * @throws MWException
- */
- protected function generateBundleData( $event, $user, $type ) {
- $data = $this->getRawBundleData( $event, $user, $type );
-
- // Default the last raw data to false, which means there is no
- // bundle data other than the base
- $this->bundleData['last-raw-data'] = false;
-
- if ( !$data ) {
- return;
- }
-
- $agents = array();
- $agent = $event->getAgent();
- if ( $agent ) {
- if ( $agent->isAnon() ) {
- $agents[$agent->getName()] = $agent->getName();
- } else {
- $agents[$agent->getId()] = $agent->getId();
- }
- } else {
- throw new MWException( "Agent is required for bundling notification!" );
- }
-
- // Initialize with 1 for the agent of current event
- $count = 1;
- foreach ( $data as $evt ) {
- if ( $evt->getAgent() ) {
- if ( $evt->getAgent()->isAnon() ) {
- $key = $evt->getAgent()->getName();
- } else {
- $key = $evt->getAgent()->getId();
- }
- if ( !isset( $agents[$key] ) ) {
- $agents[$key] = $key;
- $count++;
- }
- }
- $this->bundleData['last-raw-data'] = $evt;
- }
-
- $this->bundleData['agent-other-count'] = $count - 1;
- if ( $count > 1 ) {
- $this->bundleData['use-bundle'] = true;
- }
-
- // If there is more raw data than we requested, that means we have not
- // retrieved the very last raw record, set the key back to null
- if ( count( $data ) >= self::$maxRawBundleData ) {
- $this->bundleData['last-raw-data'] = null;
- }
- }
-
- /**
- * @return array
- */
- public function getBundleData() {
- return $this->bundleData;
- }
-
- /**
- * Convert the parameters into real values and pass them into the message
- *
- * @param $params array
- * @param $event EchoEvent
- * @param $message Message
- * @param $user User
- */
- protected function processParams( $params, $event, $message, $user ) {
- foreach ( $params as $param ) {
- $this->processParam( $event, $param, $message, $user );
- }
- }
-
- /**
- * Process a parameter that should be escaped for display except for use
- * cases like plain text email and email subject
- *
- * @param $message Message
- * @param $paramContent string
- */
- protected function processParamEscaped( $message, $paramContent ) {
- // Plain text email and email subject do not need to be escaped
- if ( $this->outputFormat !== 'email' && $this->distributionType !== 'emailsubject' ) {
- $paramContent = htmlspecialchars( $paramContent );
- }
-
- $message->rawParams( $paramContent );
- }
-
- /**
- * Get the URL for the primary or secondary link for an event
- *
- * @param EchoEvent $event
- * @param User $user The user receiving the notification
- * @param String $rank 'primary' or 'secondary' (default is 'primary')
- * @param boolean $local True to return a local (relative) URL, false to
- * return a full URL (for email for example) (default is true)
- * @param boolean $urlOnly True to return only the URL without the <a> tag,
- * false to return a full anchor link (default is false)
- * @param String $style A style attribute to apply to the anchor, e.g.
- * 'border: 1px solid green; text-decoration: none;' (optional)
- * @return String URL for link, or HTML for anchor tag, or empty string
- */
- public function getLink( $event, $user, $rank = 'primary', $local = true, $urlOnly = false, $style = '' ) {
- $destination = $event->getLinkDestination( $rank );
- if ( !$destination ) {
- return '';
- }
-
- // Get link parameters based on the destination
- list( $target, $query ) = $this->getLinkParams( $event, $user, $destination );
- // Note that $target can be a Title object or a raw url
- if ( !$target ) {
- return '';
- }
- if ( $urlOnly ) {
- if ( is_string( $target ) ) {
- // A raw url was passed back
- return $target;
- }
- if ( $local ) {
- return $target->getLinkURL( $query );
- } else {
- return $target->getFullURL( $query, false, PROTO_HTTPS );
- }
- } else {
- $message = $this->getMessage( $event->getLinkMessage( $rank ) )->text();
- $attribs = array( 'class' => "mw-echo-notification-{$rank}-link" );
- if ( $style ) {
- $attribs['style'] = $style;
- }
- $options = array();
- // If local is false, return an absolute url using HTTP protocol
- if ( !$local ) {
- $options[] = 'https';
- }
- if ( is_string( $target ) ) {
- $attribs['href'] = wfAppendQuery( $target, $query );
- return Html::element( 'a', $attribs, $message );
- } else {
- return Linker::link( $target, $message, $attribs, $query, $options );
- }
-
- }
- }
-
- /**
- * Helper function for getLink()
- *
- * @param EchoEvent $event
- * @param User $user The user receiving the notification
- * @param String $destination The destination type for the link, e.g. 'agent'
- * @return Array including target and query parameters. Note that target can
- * be either a Title or a full url
- */
- protected function getLinkParams( $event, $user, $destination ) {
- $target = null;
- $query = array();
- $title = $event->getTitle();
- // Set up link parameters based on the destination
- switch ( $destination ) {
- case 'agent':
- if ( $event->getAgent() ) {
- $target = $event->getAgent()->getUserPage();
- }
- break;
- case 'title':
- $target = $title;
- break;
- case 'section':
- $target = $title;
- if ( $target ) {
- $fragment = $this->formatSubjectAnchor( $event );
- if ( $fragment ) {
- $target->setFragment( "#$fragment" );
- }
- }
- break;
- case 'diff':
- $eventData = $event->getExtra();
- if ( isset( $eventData['revid'] ) && $title ) {
- $target = $title;
- // Explicitly set fragment to empty string for diff links, $title is
- // passed around by reference, it may end up using fragment set from
- // other parameters
- $target->setFragment( '#' );
- $query = array(
- 'oldid' => 'prev',
- 'diff' => $eventData['revid'],
- );
-
- $data = $this->getBundleLastRawData( $event, $user );
- if ( $data ) {
- $extra = $data->getExtra();
- if ( isset( $extra['revid'] ) ) {
- $oldId = $target->getPreviousRevisionID( $extra['revid'] );
- // The diff engine doesn't provide a way to diff against a null revision.
- // In this case, just fall back old id to the first revision
- if ( !$oldId ) {
- $oldId = $extra['revid'];
- }
- if ( $oldId < $eventData['revid'] ) {
- $query['oldid'] = $oldId;
- }
- }
- }
- }
- break;
- }
- return array( $target, $query );
- }
-
- /**
- * Get the last echo event in a set of bundling data. When bundling notifications,
- * we mostly only need the very first notification, which is the bundle base.
- * In some cases, like talk notification diff, Flow notificaiton first unread post,
- * we need data from the very last notification.
- *
- * @param EchoEvent
- * @param User
- * @return EchoEvent|boolean false for none
- */
- protected function getBundleLastRawData( EchoEvent $event, User $user ) {
- if ( $event->getBundleHash() ) {
- // First try cache data from preivous query
- if ( isset( $this->bundleData['last-raw-data'] ) ) {
- $data = $this->bundleData['last-raw-data'];
- // Then try to query the storage
- } else {
- $eventMapper = new EchoEventMapper();
- $data = $eventMapper->fetchByUserBundleHash(
- $user, $event->getBundleHash(), $this->distributionType, 'ASC', 1
- );
- if ( $data ) {
- $data = reset( $data );
- }
- }
-
- if ( $data ) {
- return $data;
- }
- }
-
- return false;
- }
-
- /**
- * Get the style for standard links in html email
- * @return string
- */
- public function getHTMLLinkStyle() {
- return 'text-decoration: none; color: #3A68B0;';
- }
-
- /**
- * Helper function for processParams()
- *
- * @param $event EchoEvent
- * @param $param string
- * @param $message Message
- * @param $user User
- * @throws MWException
- */
- protected function processParam( $event, $param, $message, $user ) {
- if ( $param === 'agent' ) {
- $agent = $event->getAgent();
- if ( !$agent ) {
- $message->params( $this->getMessage( 'echo-no-agent' )->text() );
- } elseif ( !$event->userCan( Revision::DELETED_USER, $user ) ) {
- $message->params( $this->getMessage( 'rev-deleted-user' )->text() );
- } else {
- if ( $this->outputFormat === 'htmlemail' ) {
- $message->rawParams(
- Linker::link(
- $agent->getUserPage(),
- $agent->getName(),
- array( 'style' => $this->getHTMLLinkStyle() ),
- array(),
- array( 'https' )
- )
- );
- } else {
- $message->params( $agent->getName() );
- }
- }
- // example: {7} others, {99+} others
- } elseif ( $param === 'agent-other-display' ) {
- global $wgEchoMaxNotificationCount;
-
- if ( $this->bundleData['agent-other-count'] > $wgEchoMaxNotificationCount ) {
- $message->params(
- $this->getMessage( 'echo-notification-count' )
- ->numParams( $wgEchoMaxNotificationCount )
- ->text()
- );
- } else {
- $message->numParams( $this->bundleData['agent-other-count'] );
- }
- // the number used for plural support
- } elseif ( $param === 'agent-other-count' ) {
- $message->params( $this->bundleData['agent-other-count'] );
- } elseif ( $param === 'user' ) {
- $message->params( $user->getName() );
- } elseif ( $param === 'title' ) {
- $title = $event->getTitle();
- if ( !$title ) {
- $message->params( $this->getMessage( 'echo-no-title' )->text() );
- } else {
- if ( $this->outputFormat === 'htmlemail' ) {
- $props = array (
- 'attribs' => array( 'style' => $this->getHTMLLinkStyle() )
- );
- $this->setTitleLink( $event, $message, $props );
- } else {
- $message->params( $this->formatTitle( $title ) );
- }
- }
- } elseif ( $param === 'titlelink' ) {
- $this->setTitleLink( $event, $message );
- } elseif ( $param === 'text-notification' ) {
- $oldOutputFormat = $this->outputFormat;
- $this->setOutputFormat( 'text' );
- // $type is ignored in this class
- $textNotification = $this->format( $event, $user, '' );
- $this->setOutputFormat( $oldOutputFormat );
-
- $message->params( $textNotification );
- } else {
- throw new MWException( "Unrecognised parameter $param" );
- }
- }
-
- /**
- * Getter method
- *
- * @param $key string
- *
- * @throws MWException
- * @return mixed
- */
- public function getValue( $key ) {
- if ( !property_exists( $this, $key ) ) {
- throw new MWException( "Call to non-existing property $key in " . get_class( $this ) );
- }
- return $this->$key;
- }
-
-}
diff --git a/Echo/includes/formatters/CommentFormatter.php b/Echo/includes/formatters/CommentFormatter.php
deleted file mode 100644
index c789d524..00000000
--- a/Echo/includes/formatters/CommentFormatter.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-class EchoCommentFormatter extends EchoEditFormatter {
- public function __construct( $params ) {
- parent::__construct( $params );
- }
-
- /**
- * @param EchoEvent $event
- * @param $param
- * @param Message $message
- * @param User $user
- */
- protected function processParam( $event, $param, $message, $user ) {
- if ( $param === 'content-page' ) {
- if ( $event->getTitle() ) {
- $message->params( $event->getTitle()->getSubjectPage()->getPrefixedText() );
- } else {
- $message->params( '' );
- }
- } elseif ( $param === 'subject-link' ) {
- $this->setTitleLink( $event, $message );
- // The title text without namespace
- } elseif ( $param === 'main-title-text' ) {
- if ( !$event->getTitle() ) {
- $message->params( $this->getMessage( 'echo-no-title' )->text() );
- } else {
- $message->params( $event->getTitle()->getText() );
- }
- } else {
- parent::processParam( $event, $param, $message, $user );
- }
- }
-}
diff --git a/Echo/includes/formatters/EchoEventDigestFormatter.php b/Echo/includes/formatters/EchoEventDigestFormatter.php
new file mode 100644
index 00000000..1fb1f765
--- /dev/null
+++ b/Echo/includes/formatters/EchoEventDigestFormatter.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * Abstract class for formatters that process multiple events.
+ *
+ * The formatter does not maintain any state except for the
+ * arguments passed in the constructor (user and language)
+ */
+abstract class EchoEventDigestFormatter {
+ public function __construct( User $user, Language $language ) {
+ $this->user = $user;
+ $this->language = $language;
+ }
+
+ /**
+ * Equivalent to IContextSource::msg for the current
+ * language
+ *
+ * @return Message
+ */
+ protected function msg( /* ,,, */ ) {
+ /**
+ * @var Message $msg
+ */
+ $msg = call_user_func_array( 'wfMessage', func_get_args() );
+ $msg->inLanguage( $this->language );
+
+ return $msg;
+ }
+
+ /**
+ * @param EchoEvent[] $events
+ * @param string $distributionType 'web' or 'email'
+ * @return array|bool|string Output format depends on implementation, false if it cannot be formatted
+ */
+ final public function format( array $events, $distributionType ) {
+ $models = [];
+ foreach ( $events as $event ) {
+ $model = EchoEventPresentationModel::factory( $event, $this->language, $this->user, $distributionType );
+ if ( $model->canRender() ) {
+ $models[] = $model;
+ }
+ }
+
+ return $models ? $this->formatModels( $models ) : false;
+ }
+
+ /**
+ * @param EchoEventPresentationModel[] $models
+ * @return string|array
+ */
+ abstract protected function formatModels( array $models );
+}
diff --git a/Echo/includes/formatters/EchoEventFormatter.php b/Echo/includes/formatters/EchoEventFormatter.php
new file mode 100644
index 00000000..c3d30413
--- /dev/null
+++ b/Echo/includes/formatters/EchoEventFormatter.php
@@ -0,0 +1,71 @@
+<?php
+use MediaWiki\Logger\LoggerFactory;
+
+/**
+ * Abstract class that each "formatter" should implement.
+ *
+ * A formatter is an output type, example formatters would be:
+ * * Special:Notifications
+ * * HTML email
+ * * plaintext email
+ *
+ * The formatter does not maintain any state except for the
+ * arguments passed in the constructor (user and language)
+ */
+abstract class EchoEventFormatter {
+ public function __construct( User $user, Language $language ) {
+ $this->user = $user;
+ $this->language = $language;
+ }
+
+ /**
+ * Equivalent to IContextSource::msg for the current
+ * language
+ *
+ * @return Message
+ */
+ protected function msg( /* ,,, */ ) {
+ /**
+ * @var Message $msg
+ */
+ $msg = call_user_func_array( 'wfMessage', func_get_args() );
+ $msg->inLanguage( $this->language );
+
+ return $msg;
+ }
+
+ /**
+ * @param EchoEvent $event
+ * @return string|array|bool Output format depends on implementation, false if it cannot be formatted
+ */
+ final public function format( EchoEvent $event ) {
+ // Deleted events should have been filtered out before getting there.
+ // This is just to be sure.
+ if ( $event->isDeleted() ) {
+ return false;
+ }
+
+ if ( !EchoEventPresentationModel::supportsPresentationModel( $event->getType() ) ) {
+ LoggerFactory::getInstance( 'Echo' )->warning(
+ "Ignoring event type \"{type}\" since it does not support Echo presentation model.",
+ [
+ 'type' => $event->getType(),
+ ]
+ );
+ return false;
+ }
+
+ $model = EchoEventPresentationModel::factory( $event, $this->language, $this->user );
+ if ( !$model->canRender() ) {
+ return false;
+ }
+
+ return $this->formatModel( $model );
+ }
+
+ /**
+ * @param EchoEventPresentationModel $model
+ * @return string|array
+ */
+ abstract protected function formatModel( EchoEventPresentationModel $model );
+}
diff --git a/Echo/includes/formatters/EchoFlyoutFormatter.php b/Echo/includes/formatters/EchoFlyoutFormatter.php
new file mode 100644
index 00000000..f0235089
--- /dev/null
+++ b/Echo/includes/formatters/EchoFlyoutFormatter.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * A formatter for the notification flyout popup
+ *
+ * Ideally we wouldn't need this and we'd just pass the
+ * presentation model to the client, but we need to continue
+ * sending HTML for backwards compatibility.
+ */
+class EchoFlyoutFormatter extends EchoEventFormatter {
+ protected function formatModel( EchoEventPresentationModel $model ) {
+ $icon = Html::element(
+ 'img',
+ [
+ 'class' => 'mw-echo-icon',
+ 'src' => $this->getIconURL( $model ),
+ ]
+ );
+
+ $html = Xml::tags(
+ 'div',
+ [ 'class' => 'mw-echo-title' ],
+ $model->getHeaderMessage()->parse()
+ ) . "\n";
+
+ $body = $model->getBodyMessage();
+ if ( $body ) {
+ $html .= Xml::tags(
+ 'div',
+ [ 'class' => 'mw-echo-payload' ],
+ $body->parse()
+ ) . "\n";
+ }
+
+ $ts = $this->language->getHumanTimestamp(
+ new MWTimestamp( $model->getTimestamp() ),
+ null,
+ $this->user
+ );
+
+ $footerItems = [ $ts ];
+ $secondaryLinks = array_filter( $model->getSecondaryLinks() );
+ foreach ( $secondaryLinks as $link ) {
+ $footerItems[] = Html::element( 'a', [ 'href' => $link['url'] ], $link['label'] );
+ }
+ $html .= Xml::tags(
+ 'div',
+ [ 'class' => 'mw-echo-notification-footer' ],
+ $this->language->pipeList( $footerItems )
+ ) . "\n";
+
+ // Add the primary link afterwards, if it has one
+ $primaryLink = $model->getPrimaryLinkWithMarkAsRead();
+ if ( $primaryLink !== false ) {
+ $html .= Html::element(
+ 'a',
+ [ 'class' => 'mw-echo-notification-primary-link', 'href' => $primaryLink['url'] ],
+ $primaryLink['label']
+ ) . "\n";
+ }
+
+ // Wrap everything in mw-echo-content class
+ $html = Xml::tags( 'div', [ 'class' => 'mw-echo-content' ], $html );
+
+ // And then add the icon in front and wrap with mw-echo-state class.
+ $html = Xml::tags( 'div', [ 'class' => 'mw-echo-state' ], $icon . $html );
+
+ return $html;
+ }
+
+ private function getIconURL( EchoEventPresentationModel $model ) {
+ return EchoIcon::getUrl(
+ $model->getIconType(),
+ $this->language->getDir()
+ );
+ }
+
+}
diff --git a/Echo/includes/formatters/EchoForeignPresentationModel.php b/Echo/includes/formatters/EchoForeignPresentationModel.php
new file mode 100644
index 00000000..0d040dfc
--- /dev/null
+++ b/Echo/includes/formatters/EchoForeignPresentationModel.php
@@ -0,0 +1,49 @@
+<?php
+
+class EchoForeignPresentationModel extends EchoEventPresentationModel {
+ public function getIconType() {
+ return 'global';
+ }
+
+ public function getPrimaryLink() {
+ return false;
+ }
+
+ protected function getHeaderMessageKey() {
+ $data = $this->event->getExtra();
+ $section = $data['section'] == 'message' ? 'notice' : $data['section'];
+
+ // notification-header-foreign-alert
+ // notification-header-foreign-notice
+ return "notification-header-{$this->type}-{$section}";
+ }
+
+ public function getHeaderMessage() {
+ $msg = parent::getHeaderMessage();
+
+ $data = $this->event->getExtra();
+ $firstWiki = reset( $data['wikis'] );
+ $names = $this->getWikiNames( [ $firstWiki ] );
+ $msg->params( $names[0] );
+ $msg->numParams( count( $data['wikis'] ) - 1 );
+ $msg->numParams( count( $data['wikis'] ) );
+
+ return $msg;
+ }
+
+ public function getBodyMessage() {
+ $data = $this->event->getExtra();
+ $msg = wfMessage( "notification-body-{$this->type}" );
+ $msg->params( $this->language->listToText( $this->getWikiNames( $data['wikis'] ) ) );
+ return $msg;
+ }
+
+ protected function getWikiNames( array $wikis ) {
+ $data = EchoForeignNotifications::getApiEndpoints( $wikis );
+ $names = [];
+ foreach ( $wikis as $wiki ) {
+ $names[] = $data[$wiki]['title'];
+ }
+ return $names;
+ }
+}
diff --git a/Echo/includes/formatters/EchoHtmlDigestEmailFormatter.php b/Echo/includes/formatters/EchoHtmlDigestEmailFormatter.php
new file mode 100644
index 00000000..f2f96cc3
--- /dev/null
+++ b/Echo/includes/formatters/EchoHtmlDigestEmailFormatter.php
@@ -0,0 +1,226 @@
+<?php
+
+class EchoHtmlDigestEmailFormatter extends EchoEventDigestFormatter {
+
+ /**
+ * @var string 'daily' or 'weekly'
+ */
+ protected $digestMode;
+
+ public function __construct( User $user, Language $language, $digestMode ) {
+ parent::__construct( $user, $language );
+ $this->digestMode = $digestMode;
+ }
+
+ /**
+ * @param EchoEventPresentationModel[] $models
+ * @return array of the following format:
+ * [ 'body' => formatted email body,
+ * 'subject' => formatted email subject ]
+ */
+ protected function formatModels( array $models ) {
+ // echo-email-batch-body-intro-daily
+ // echo-email-batch-body-intro-weekly
+ $intro = $this->msg( 'echo-email-batch-body-intro-' . $this->digestMode )
+ ->params( $this->user->getName() )
+ ->parse();
+ $intro = nl2br( $intro );
+
+ $eventsByCategory = $this->groupByCategory( $models );
+ ksort( $eventsByCategory );
+ $digestList = $this->renderDigestList( $eventsByCategory );
+
+ $htmlFormatter = new EchoHtmlEmailFormatter( $this->user, $this->language );
+
+ $body = $this->renderBody(
+ $this->language,
+ $intro,
+ $digestList,
+ $this->renderAction(),
+ $htmlFormatter->getFooter()
+ );
+
+ // echo-email-batch-subject-daily
+ // echo-email-batch-subject-weekly
+ $subject = $this->msg( 'echo-email-batch-subject-' . $this->digestMode )
+ ->numParams( count( $models ), count( $models ) )
+ ->text();
+
+ return [
+ 'subject' => $subject,
+ 'body' => $body,
+ ];
+ }
+
+ private function renderBody( Language $language, $intro, $digestList, $action, $footer ) {
+ $alignStart = $language->alignStart();
+ $langCode = $language->getCode();
+ $langDir = $language->getDir();
+
+ return <<< EOF
+<html><head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <style>
+ @media only screen and (max-width: 480px){
+ table[id="email-container"]{max-width:600px !important; width:100% !important;}
+ }
+ </style>
+</head><body>
+<table cellspacing="0" cellpadding="0" border="0" width="100%" align="center" lang="$langCode" dir="$langDir">
+<tr>
+ <td bgcolor="#EAECF0"><center>
+ <br /><br />
+ <table cellspacing="0" cellpadding="0" border="0" width="600" id="email-container">
+ <tr>
+ <td bgcolor="#FFFFFF" width="5%">&nbsp;</td>
+ <td bgcolor="#FFFFFF" width="6%">&nbsp;</td>
+ <td bgcolor="#FFFFFF" width="79%" style="line-height:40px;">&nbsp;</td>
+ <td bgcolor="#FFFFFF" width="10%">&nbsp;</td>
+ </tr>
+ <tr>
+ <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
+ <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
+ <td bgcolor="#FFFFFF" align="center" style="font-family: Arial, Helvetica, sans-serif; font-size:13px; line-height:20px; color:#72777D; text-align: center;">$intro</td>
+ <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
+ </tr>
+ <tr>
+ <td bgcolor="#FFFFFF" align="$alignStart" style="font-family: Arial, Helvetica, sans-serif; line-height: 20px; font-weight: 600;">
+ <table cellspacing="0" cellpadding="0" border="0" width="100%">
+ <tr>
+ <td bgcolor="#FFFFFF" align="$alignStart" style="font-family: Arial, Helvetica, sans-serif; font-size:13px; color: #54595D; padding-top: 25px;">
+ $digestList
+ </td>
+ </tr>
+ </table>
+ <br /><br />
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ <td bgcolor="#FFFFFF" style="line-height:60px;" align="center">$action</td>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ </tr>
+ <tr>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ <td bgcolor="#FFFFFF" style="line-height:40px;">&nbsp;</td>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ <td align="$alignStart" style="font-family: Arial, Helvetica, sans-serif; font-size:10px; line-height:13px; color:#72777D; padding: 10px 20px;"><br />
+ $footer
+ <br /><br />
+ </td>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="4">&nbsp;</td>
+ </tr>
+ </table>
+ <br><br></center>
+ </td>
+</tr>
+</table>
+</body></html>
+EOF;
+ }
+
+ /**
+ * @param string $type Notification type
+ * @param int $count Number of notifications in this type's section
+ * @return string Formatted category section title
+ */
+ private function getCategoryTitle( $type, $count ) {
+ return $this->msg( "echo-category-title-$type" )
+ ->numParams( $count )
+ ->parse();
+ }
+
+ /**
+ * @param EchoEventPresentationModel[] $models
+ * @return array [ 'category name' => EchoEventPresentationModel[] ]
+ */
+ private function groupByCategory( $models ) {
+ $eventsByCategory = [];
+ foreach ( $models as $model ) {
+ $eventsByCategory[$model->getCategory()][] = $model;
+ }
+ return $eventsByCategory;
+ }
+
+ /**
+ * Apply style to notification category header
+ * @param string $category Can contain HTML. Is included as-is in HTML template, is not escaped.
+ * @return string
+ */
+ protected function applyStyleToCategory( $category ) {
+ return <<< EOF
+<tr>
+ <td colspan="2" style="color: #72777D; font-weight: normal; font-size: 13px; padding-top: 15px;">
+ $category <br />
+ <hr style="background-color:#FFFFFF; color:#FFFFFF; border: 1px solid #EAECF0;" />
+ </td>
+</tr>
+EOF;
+ }
+
+ /**
+ * Apply style to individual notification event
+ * @param EchoEventPresentationModel $model
+ * @return string
+ */
+ protected function applyStyleToEvent( EchoEventPresentationModel $model ) {
+ $iconUrl = wfExpandUrl(
+ EchoIcon::getRasterizedUrl( $model->getIconType(), $this->language->getCode() ),
+ PROTO_CANONICAL
+ );
+
+ $imgSrc = Sanitizer::encodeAttribute( $iconUrl );
+
+ // notification text
+ $text = $model->getHeaderMessage()->parse();
+
+ return <<< EOF
+<tr>
+ <td width="30">
+ <img src="$imgSrc" width="30" height="30" style="vertical-align:middle;">
+ </td>
+ <td style="font-family: Arial, Helvetica, sans-serif; font-size:13px; color: #54595D;">
+ $text
+ </td>
+</tr>
+EOF;
+ }
+
+ private function renderDigestList( $eventsByCategory ) {
+ $result = [];
+ // build the html section for each category
+ foreach ( $eventsByCategory as $category => $models ) {
+ $output = $this->applyStyleToCategory(
+ $this->getCategoryTitle( $category, count( $models ) )
+ );
+ foreach ( $models as $model ) {
+ $output .= "\n" . $this->applyStyleToEvent( $model );
+ }
+ $result[] = '<table border="0" width="100%">' . $output . '</table>';
+ }
+
+ return trim( implode( "\n", $result ) );
+ }
+
+ private function renderAction() {
+ return Html::element(
+ 'a',
+ [
+ 'href' => SpecialPage::getTitleFor( 'Notifications' )->getFullURL( '', false, PROTO_CANONICAL ),
+ 'style' => EchoHtmlEmailFormatter::PRIMARY_LINK_STYLE,
+ ],
+ $this->msg( 'echo-email-batch-link-text-view-all-notifications' )->text()
+ );
+ }
+
+}
diff --git a/Echo/includes/formatters/EchoHtmlEmailFormatter.php b/Echo/includes/formatters/EchoHtmlEmailFormatter.php
new file mode 100644
index 00000000..4c28fe65
--- /dev/null
+++ b/Echo/includes/formatters/EchoHtmlEmailFormatter.php
@@ -0,0 +1,159 @@
+<?php
+
+class EchoHtmlEmailFormatter extends EchoEventFormatter {
+
+ const PRIMARY_LINK_STYLE = 'cursor:pointer; text-align:center; text-decoration:none; padding:.45em 0.6em .45em; color:#FFF; background:#36C; font-family: Arial, Helvetica, sans-serif;font-size: 13px;';
+ const SECONDARY_LINK_STYLE = 'text-decoration: none;font-size: 10px;font-family: Arial, Helvetica, sans-serif; color: #72777D;';
+
+ protected function formatModel( EchoEventPresentationModel $model ) {
+ $subject = $model->getSubjectMessage()->parse();
+
+ $intro = $model->getHeaderMessage()->parse();
+
+ $bodyMsg = $model->getBodyMessage();
+ $summary = $bodyMsg ? $bodyMsg->parse() : '';
+
+ $actions = [];
+
+ $primaryLink = $model->getPrimaryLinkWithMarkAsRead();
+ if ( $primaryLink ) {
+ $actions[] = $this->renderLink( $primaryLink, self::PRIMARY_LINK_STYLE );
+ }
+
+ foreach ( array_filter( $model->getSecondaryLinks() ) as $secondaryLink ) {
+ $actions[] = $this->renderLink( $secondaryLink, self::SECONDARY_LINK_STYLE );
+ }
+
+ $iconUrl = wfExpandUrl(
+ EchoIcon::getRasterizedUrl( $model->getIconType(), $this->language->getCode() ),
+ PROTO_CANONICAL
+ );
+
+ $body = $this->renderBody(
+ $this->language,
+ $iconUrl,
+ $summary,
+ implode( "&nbsp;&nbsp;", $actions ),
+ $intro,
+ $this->getFooter()
+ );
+
+ return [
+ 'body' => $body,
+ 'subject' => $subject,
+ ];
+ }
+
+ private function renderBody( Language $lang, $emailIcon, $summary, $action, $intro, $footer ) {
+ $alignStart = $lang->alignStart();
+ $langCode = $lang->getCode();
+ $langDir = $lang->getDir();
+
+ $iconImgSrc = Sanitizer::encodeAttribute( $emailIcon );
+
+ global $wgCanonicalServer;
+ return <<< EOF
+<html><head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <style>
+ @media only screen and (max-width: 480px){
+ table[id="email-container"]{max-width:600px !important; width:100% !important;}
+ }
+ </style>
+ <base href="{$wgCanonicalServer}">
+</head><body>
+<table cellspacing="0" cellpadding="0" border="0" width="100%" align="center" lang="{$langCode}" dir="{$langDir}">
+<tr>
+ <td bgcolor="#EAECF0"><center>
+ <br /><br />
+ <table cellspacing="0" cellpadding="0" border="0" width="600" id="email-container">
+ <tr>
+ <td bgcolor="#FFFFFF" width="5%">&nbsp;</td>
+ <td bgcolor="#FFFFFF" width="10%">&nbsp;</td>
+ <td bgcolor="#FFFFFF" width="80%" style="line-height:40px;">&nbsp;</td>
+ <td bgcolor="#FFFFFF" width="5%">&nbsp;</td>
+ </tr><tr>
+ <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
+ <td bgcolor="#FFFFFF" align="center" valign="top" rowspan="2"><img src="{$iconImgSrc}" alt="" height="30" width="30"></td>
+ <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:13px; line-height:20px; color:#72777D;">{$intro}</td>
+ <td bgcolor="#FFFFFF" rowspan="2">&nbsp;</td>
+ </tr><tr>
+ <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; line-height: 20px; font-weight: 600;">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; padding-top: 8px; font-size:13px; font-weight: bold; color: #54595D;">
+ {$summary}
+ </td>
+ </tr>
+ </table>
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td bgcolor="#FFFFFF" align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:14px; padding-top: 25px;">
+ {$action}
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr><tr>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ <td bgcolor="#FFFFFF" style="line-height:40px;">&nbsp;</td>
+ <td bgcolor="#FFFFFF">&nbsp;</td>
+ </tr><tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ <td align="{$alignStart}" style="font-family: Arial, Helvetica, sans-serif; font-size:10px; line-height:13px; color:#72777D; padding:10px 20px;"><br />
+ {$footer}
+ <br /><br />
+ </td>
+ <td>&nbsp;</td>
+ </tr><tr>
+ <td colspan="4">&nbsp;</td>
+ </tr>
+ </table>
+ <br><br></center>
+ </td>
+</tr>
+</table>
+</body></html>
+EOF;
+ }
+
+ /**
+ * @return string
+ */
+ public function getFooter() {
+ global $wgEchoEmailFooterAddress;
+
+ $preferenceLink = $this->renderLink(
+ [
+ 'label' => $this->msg( 'echo-email-html-footer-preference-link-text', $this->user )->text(),
+ 'url' => SpecialPage::getTitleFor( 'Preferences', false, 'mw-prefsection-echo' )->getFullURL( '', false, PROTO_CANONICAL ),
+ ],
+ 'text-decoration: none; color: #36C;'
+ );
+
+ $footer = $this->msg( 'echo-email-html-footer-with-link' )
+ ->rawParams( $preferenceLink )
+ ->params( $this->user )
+ ->parse();
+
+ if ( $wgEchoEmailFooterAddress ) {
+ $footer .= '<br />' . $wgEchoEmailFooterAddress;
+ }
+
+ return $footer;
+ }
+
+ private function renderLink( $link, $style ) {
+ return Html::element(
+ 'a',
+ [
+ 'href' => wfExpandUrl( $link['url'], PROTO_CANONICAL ),
+ 'style' => $style,
+ ],
+ $link['label']
+ );
+ }
+}
diff --git a/Echo/includes/formatters/EchoIcon.php b/Echo/includes/formatters/EchoIcon.php
new file mode 100644
index 00000000..74b90f6a
--- /dev/null
+++ b/Echo/includes/formatters/EchoIcon.php
@@ -0,0 +1,88 @@
+<?php
+
+class EchoIcon {
+
+ /**
+ * @param string $icon Name of icon as registered in BeforeCreateEchoEvent hook
+ * @param string $dir either 'ltr' or 'rtl'
+ * @return string
+ */
+ public static function getUrl( $icon, $dir ) {
+ global $wgEchoNotificationIcons, $wgExtensionAssetsPath;
+ if ( !isset( $wgEchoNotificationIcons[$icon] ) ) {
+ throw new InvalidArgumentException( "The $icon icon is not registered" );
+ }
+
+ $iconInfo = $wgEchoNotificationIcons[$icon];
+ $needsPrefixing = true;
+
+ // Now we need to check it has a valid url/path
+ if ( isset( $iconInfo['url'] ) && $iconInfo['url'] ) {
+ $iconUrl = $iconInfo['url'];
+ $needsPrefixing = false;
+ } elseif ( isset( $iconInfo['path'] ) && $iconInfo['path'] ) {
+ $iconUrl = $iconInfo['path'];
+ } else {
+ // Fallback to hardcoded 'placeholder'. This is used if someone
+ // doesn't configure the 'site' icon for example.
+ $icon = 'placeholder';
+ $iconUrl = $wgEchoNotificationIcons['placeholder']['path'];
+ }
+
+ // Might be an array with different icons for ltr/rtl
+ if ( is_array( $iconUrl ) ) {
+ if ( !isset( $iconUrl[$dir] ) ) {
+ throw new UnexpectedValueException( "Icon type $icon doesn't have an icon for $dir directionality" );
+ }
+
+ $iconUrl = $iconUrl[$dir];
+ }
+
+ // And if it was a 'path', stick the assets path in front
+ if ( $needsPrefixing ) {
+ $iconUrl = "$wgExtensionAssetsPath/$iconUrl";
+ }
+
+ return $iconUrl;
+ }
+
+ /**
+ * Get a link to a rasterized version of the icon
+ *
+ * @param string $icon Icon name
+ * @param string $lang Language
+ * @return string URL to the rasterized version of the icon
+ */
+ public static function getRasterizedUrl( $icon, $lang ) {
+ global $wgEchoNotificationIcons;
+ if ( !isset( $wgEchoNotificationIcons[$icon] ) ) {
+ throw new InvalidArgumentException( "The $icon icon is not registered" );
+ }
+
+ $url = isset( $wgEchoNotificationIcons[ $icon ][ 'url' ] ) ?
+ $wgEchoNotificationIcons[ $icon ][ 'url' ] :
+ null;
+
+ // If the defined URL is explicitly false, use placeholder
+ if ( $url === false ) {
+ $icon = 'placeholder';
+ }
+
+ // If the URL is null or false call the resource loader
+ // rasterizing module
+ if ( $url === false || $url === null ) {
+ $iconUrl = wfScript( 'load' ) . '?' . wfArrayToCgi( [
+ 'modules' => 'ext.echo.emailicons',
+ 'image' => $icon,
+ 'lang' => $lang,
+ 'format' => 'rasterized'
+ ] );
+ } else {
+ // For icons that are defined by URL
+ $iconUrl = $wgEchoNotificationIcons[ $icon ][ 'url' ];
+ }
+
+ return $iconUrl;
+ }
+
+}
diff --git a/Echo/includes/formatters/EchoModelFormatter.php b/Echo/includes/formatters/EchoModelFormatter.php
new file mode 100644
index 00000000..4d4050b4
--- /dev/null
+++ b/Echo/includes/formatters/EchoModelFormatter.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * A formatter for the notification flyout popup. Just the bare data needed to
+ * render everything client-side.
+ */
+class EchoModelFormatter extends EchoEventFormatter {
+ /**
+ * @param EchoEventPresentationModel $model
+ * @return array
+ */
+ protected function formatModel( EchoEventPresentationModel $model ) {
+ $data = $model->jsonSerialize();
+ $data['iconUrl'] = EchoIcon::getUrl( $model->getIconType(), $this->language->getDir() );
+
+ if ( isset( $data['links']['primary']['url'] ) ) {
+ $data['links']['primary']['url'] = wfExpandUrl( $data['links']['primary']['url'] );
+ }
+
+ foreach ( $data['links']['secondary'] as &$link ) {
+ $link['url'] = wfExpandUrl( $link['url'] );
+ }
+
+ $bundledIds = $model->getBundledIds();
+ if ( $bundledIds ) {
+ $data[ 'bundledIds' ] = $bundledIds;
+ }
+
+ return $data;
+ }
+}
diff --git a/Echo/includes/formatters/EchoPlainTextDigestEmailFormatter.php b/Echo/includes/formatters/EchoPlainTextDigestEmailFormatter.php
new file mode 100644
index 00000000..88d9c5f5
--- /dev/null
+++ b/Echo/includes/formatters/EchoPlainTextDigestEmailFormatter.php
@@ -0,0 +1,78 @@
+<?php
+
+class EchoPlainTextDigestEmailFormatter extends EchoEventDigestFormatter {
+
+ /**
+ * @var string 'daily' or 'weekly'
+ */
+ protected $digestMode;
+
+ public function __construct( User $user, Language $language, $digestMode ) {
+ parent::__construct( $user, $language );
+ $this->digestMode = $digestMode;
+ }
+
+ /**
+ * @param EchoEventPresentationModel[] $models
+ * @return array of the following format:
+ * [ 'body' => formatted email body,
+ * 'subject' => formatted email subject ]
+ */
+ protected function formatModels( array $models ) {
+ $content = [];
+ foreach ( $models as $model ) {
+ $content[$model->getCategory()][] = Sanitizer::stripAllTags( $model->getHeaderMessage()->parse() );
+ }
+
+ ksort( $content );
+
+ // echo-email-batch-body-intro-daily
+ // echo-email-batch-body-intro-weekly
+ $text = $this->msg( 'echo-email-batch-body-intro-' . $this->digestMode )
+ ->params( $this->user->getName() )->text();
+
+ // Does this need to be a message?
+ $bullet = $this->msg( 'echo-email-batch-bullet' )->text();
+
+ foreach ( $content as $type => $items ) {
+ $text .= "\n\n--\n\n";
+ $text .= $this->getCategoryTitle( $type, count( $items ) );
+ $text .= "\n";
+ foreach ( $items as $item ) {
+ $text .= "\n$bullet $item";
+ }
+ }
+
+ $colon = $this->msg( 'colon-separator' )->text();
+ $text .= "\n\n--\n\n";
+ $viewAll = $this->msg( 'echo-email-batch-link-text-view-all-notifications' )->text();
+ $link = SpecialPage::getTitleFor( 'Notifications' )->getFullURL( '', false, PROTO_CANONICAL );
+ $text .= "$viewAll$colon <$link>";
+
+ $plainTextFormatter = new EchoPlainTextEmailFormatter( $this->user, $this->language );
+
+ $text .= "\n\n{$plainTextFormatter->getFooter()}";
+
+ // echo-email-batch-subject-daily
+ // echo-email-batch-subject-weekly
+ $subject = $this->msg( 'echo-email-batch-subject-' . $this->digestMode )
+ ->numParams( count( $models ), count( $models ) )
+ ->text();
+
+ return [
+ 'subject' => $subject,
+ 'body' => $text,
+ ];
+ }
+
+ /**
+ * @param string $type Notification type
+ * @param int $count Number of notifications in this type's section
+ * @return string Formatted category section title
+ */
+ private function getCategoryTitle( $type, $count ) {
+ return $this->msg( "echo-category-title-$type" )
+ ->numParams( $count )
+ ->text();
+ }
+}
diff --git a/Echo/includes/formatters/EchoPlainTextEmailFormatter.php b/Echo/includes/formatters/EchoPlainTextEmailFormatter.php
new file mode 100644
index 00000000..34fdc7d1
--- /dev/null
+++ b/Echo/includes/formatters/EchoPlainTextEmailFormatter.php
@@ -0,0 +1,53 @@
+<?php
+
+class EchoPlainTextEmailFormatter extends EchoEventFormatter {
+ protected function formatModel( EchoEventPresentationModel $model ) {
+ $subject = Sanitizer::stripAllTags( $model->getSubjectMessage()->parse() );
+
+ $text = Sanitizer::stripAllTags( $model->getHeaderMessage()->parse() );
+
+ $text .= "\n\n";
+
+ $bodyMsg = $model->getBodyMessage();
+ if ( $bodyMsg ) {
+ $text .= Sanitizer::stripAllTags( $bodyMsg->parse() );
+ }
+
+ $primaryLink = $model->getPrimaryLinkWithMarkAsRead();
+
+ $primaryUrl = wfExpandUrl( $primaryLink['url'], PROTO_CANONICAL );
+ $colon = $this->msg( 'colon-separator' )->text();
+ $text .= "\n\n{$primaryLink['label']}$colon <$primaryUrl>";
+
+ foreach ( array_filter( $model->getSecondaryLinks() ) as $secondaryLink ) {
+ $url = wfExpandUrl( $secondaryLink['url'], PROTO_CANONICAL );
+ $text .= "\n\n{$secondaryLink['label']}$colon <$url>";
+ }
+
+ // Footer
+ $text .= "\n\n{$this->getFooter()}";
+
+ return [
+ 'body' => $text,
+ 'subject' => $subject,
+ ];
+ }
+
+ /**
+ * @return string
+ */
+ public function getFooter() {
+ global $wgEchoEmailFooterAddress;
+
+ $footerMsg = $this->msg( 'echo-email-plain-footer', $this->user )->text();
+ $prefsUrl = SpecialPage::getTitleFor( 'Preferences', false, 'mw-prefsection-echo' )
+ ->getFullURL( '', false, PROTO_CANONICAL );
+ $text = "--\n\n$footerMsg\n$prefsUrl";
+
+ if ( strlen( $wgEchoEmailFooterAddress ) ) {
+ $text .= "\n\n$wgEchoEmailFooterAddress";
+ }
+
+ return $text;
+ }
+}
diff --git a/Echo/includes/formatters/EditFormatter.php b/Echo/includes/formatters/EditFormatter.php
deleted file mode 100644
index e2d24aaa..00000000
--- a/Echo/includes/formatters/EditFormatter.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-
-class EchoEditFormatter extends EchoBasicFormatter {
-
- /**
- * @param EchoEvent $event
- * @param $param
- * @param $message Message
- * @param $user User
- */
- protected function processParam( $event, $param, $message, $user ) {
- if ( $param === 'subject-anchor' ) {
- $message->params( $this->formatSubjectAnchor( $event ) );
- } elseif ( $param === 'section-title' ) {
- $message->params( $this->getSectionTitle( $event, $user ) );
- } elseif ( $param === 'difflink' ) {
- $revid = $event->getExtraParam( 'revid' );
- if ( !$revid ) {
- $message->params( '' );
- return;
- }
- $diff = $event->getExtraParam( 'diffid', 'prev' );
- $props = array(
- 'attribs' => array( 'class' => 'mw-echo-diff' ),
- 'linkText' => $this->getMessage( 'parentheses' )
- ->params(
- $this->getMessage( 'showdiff' )->text()
- )->escaped(),
- 'param' => array(
- 'oldid' => $revid,
- 'diff' => $diff,
- ),
- // Set fragment to empty string for diff links
- 'fragment' => ''
- );
- $this->setTitleLink( $event, $message, $props );
- } elseif ( $param === 'summary' ) {
- $message->params( $this->getRevisionSnippet( $event, $user ) );
- } elseif ( $param === 'number' ) {
- $eventData = $event->getExtra();
- // The folliwing is a bit of a hack...
- // If the edit is a rollback, we want to say 'your edits' in the
- // notification. If the edit is an undo, we want to say 'your edit'
- // in the notification. To accomplish this, we pass a 'number' param
- // to the message which is set to 1 or 2 and formatted with {{PLURAL}}.
- if ( isset( $eventData['method'] ) && $eventData['method'] === 'rollback' ) {
- $message->params( 2 );
- } else {
- $message->params( 1 );
- }
- } elseif ( $param === 'userpage-contributions' ) {
- $user = $event->getAgent();
- $name = $user->getName();
- if ( $user->isAnon() ) {
- $message->params( "Special:Contributions/$name" );
- } else {
- $message->params( "User:$name" );
- }
- } else {
- parent::processParam( $event, $param, $message, $user );
- }
- }
-
- /**
- * Get the section title for a talk page post
- * @param $event EchoEvent
- * @param $user User
- * @return string
- */
- protected function getSectionTitle( $event, $user ) {
- $extra = $event->getExtra();
-
- if ( !empty( $extra['section-title'] ) ) {
- if ( $event->userCan( Revision::DELETED_TEXT, $user ) ) {
- return EchoDiscussionParser::getTextSnippet(
- $extra['section-title'],
- $this->getLanguage(),
- 30
- );
- } else {
- return $this->getMessage( 'echo-rev-deleted-text-view' )->text();
- }
- }
-
- return '';
- }
-}
diff --git a/Echo/includes/formatters/EditThresholdPresentationModel.php b/Echo/includes/formatters/EditThresholdPresentationModel.php
new file mode 100644
index 00000000..6a01cb5f
--- /dev/null
+++ b/Echo/includes/formatters/EditThresholdPresentationModel.php
@@ -0,0 +1,22 @@
+<?php
+
+class EchoEditThresholdPresentationModel extends EchoEventPresentationModel {
+
+ public function getIconType() {
+ return 'edit';
+ }
+
+ public function getHeaderMessageKey() {
+ return 'notification-header-thank-you-' . $this->event->getExtraParam( 'editCount' ) . '-edit';
+ }
+
+ public function getPrimaryLink() {
+ if ( !$this->event->getTitle() ) {
+ return false;
+ }
+ return [
+ 'url' => $this->event->getTitle()->getLocalURL(),
+ 'label' => $this->msg( 'notification-link-thank-you-edit', $this->getViewingUserForGender() )->text()
+ ];
+ }
+}
diff --git a/Echo/includes/formatters/EditUserTalkFormatter.php b/Echo/includes/formatters/EditUserTalkFormatter.php
deleted file mode 100644
index 2b5aaa24..00000000
--- a/Echo/includes/formatters/EditUserTalkFormatter.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-/**
- * Custom formatter for 'edit-user-talk' notifications
- */
-class EchoEditUserTalkFormatter extends EchoEditFormatter {
-
- /**
- * {@inheritDoc}
- */
- protected function applyChangeBeforeFormatting( EchoEvent $event, User $user, $type ) {
- parent::applyChangeBeforeFormatting( $event, $user, $type );
-
- // Replace default generic notification message with 'Someone left a message
- // on your talk page in "xxxx"' if
- // * the message is not bundled and
- // * there is a section title
- //
- // We could go with the approach of creating a new notification type, but
- // * this is variant is too small to introduce a new type
- // * may not fall back to default for talk page post with oversighted content
- // * message bundling is supposed to bundle the same notfication type, creating
- // a new type will not be able to bundle them together
- if ( !$this->bundleData['use-bundle'] && $this->getSectionTitle( $event, $user ) ) {
- $this->title = array(
- 'message' => 'notification-edit-talk-page-with-section',
- 'params' => array( 'agent', 'user', 'subject-anchor', 'section-title' )
- );
- $this->flyoutTitle = array(
- 'message' => 'notification-edit-talk-page-flyout-with-section',
- 'params' => array( 'agent', 'user', 'subject-anchor', 'section-title' )
- );
- $this->email['batch-body'] = array(
- 'message' => 'notification-edit-talk-page-email-batch-body-with-section',
- 'params' => array( 'agent', 'section-title' )
- );
- // Display the summary if there is a section title
- $this->payload = array( 'summary' );
- }
- }
-
-}
diff --git a/Echo/includes/formatters/EditUserTalkPresentationModel.php b/Echo/includes/formatters/EditUserTalkPresentationModel.php
new file mode 100644
index 00000000..1fd67369
--- /dev/null
+++ b/Echo/includes/formatters/EditUserTalkPresentationModel.php
@@ -0,0 +1,90 @@
+<?php
+
+class EchoEditUserTalkPresentationModel extends EchoEventPresentationModel {
+ use EchoPresentationModelSectionTrait;
+
+ public function canRender() {
+ return (bool)$this->event->getTitle();
+ }
+
+ public function getIconType() {
+ return 'edit-user-talk';
+ }
+
+ public function getPrimaryLink() {
+ return [
+ // Need FullURL so the section is included
+ 'url' => $this->getTitleWithSection()->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-message' )->text()
+ ];
+ }
+
+ public function getSecondaryLinks() {
+ $diffLink = [
+ 'url' => $this->getDiffLinkUrl(),
+ 'label' => $this->msg( 'notification-link-text-view-changes', $this->getViewingUserForGender() )->text(),
+ 'description' => '',
+ 'icon' => 'changes',
+ 'prioritized' => true
+ ];
+
+ if ( $this->isBundled() ) {
+ return [ $diffLink ];
+ } else {
+ return [ $this->getAgentLink(), $diffLink ];
+ }
+ }
+
+ public function getHeaderMessage() {
+ if ( $this->isBundled() ) {
+ $msg = $this->msg( "notification-bundle-header-{$this->type}-v2" );
+ $count = $this->getNotificationCountForOutput();
+
+ // Repeat is B/C until unused parameter is removed from translations
+ $msg->numParams( $count, $count );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ } elseif ( $this->hasSection() ) {
+ $msg = $this->getMessageWithAgent( "notification-header-{$this->type}-with-section" );
+ $msg->params( $this->getViewingUserForGender() );
+ $msg->plaintextParams( $this->getTruncatedSectionTitle() );
+ return $msg;
+ } else {
+ $msg = parent::getHeaderMessage();
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+ }
+
+ public function getBodyMessage() {
+ $sectionText = $this->event->getExtraParam( 'section-text' );
+ if ( !$this->isBundled() && $this->hasSection() && $sectionText !== null ) {
+ $msg = $this->msg( 'notification-body-edit-user-talk-with-section' );
+ // section-text is safe to use here, because hasSection() returns false if the revision is deleted
+ $msg->plaintextParams( $sectionText );
+ return $msg;
+ } else {
+ return false;
+ }
+ }
+
+ private function getDiffLinkUrl() {
+ $revId = $this->event->getExtraParam( 'revid' );
+ $oldId = $this->isBundled() ? $this->getRevBeforeFirstNotification() : 'prev';
+ $query = [
+ 'oldid' => $oldId,
+ 'diff' => $revId,
+ ];
+ return $this->event->getTitle()->getFullURL( $query );
+ }
+
+ private function getRevBeforeFirstNotification() {
+ $events = $this->getBundledEvents();
+ $firstNotificationRevId = end( $events )->getExtraParam( 'revid' );
+ return $this->event->getTitle()->getPreviousRevisionID( $firstNotificationRevId );
+ }
+
+ protected function getSubjectMessageKey() {
+ return 'notification-edit-talk-page-email-subject2';
+ }
+}
diff --git a/Echo/includes/formatters/EmailUserPresentationModel.php b/Echo/includes/formatters/EmailUserPresentationModel.php
new file mode 100644
index 00000000..da30d7ed
--- /dev/null
+++ b/Echo/includes/formatters/EmailUserPresentationModel.php
@@ -0,0 +1,21 @@
+<?php
+
+class EchoEmailUserPresentationModel extends EchoEventPresentationModel {
+
+ public function getIconType() {
+ return 'emailuser';
+ }
+
+ public function getPrimaryLink() {
+ return false;
+ }
+
+ public function getSecondaryLinks() {
+ return [ $this->getAgentLink() ];
+ }
+
+ public function getBodyMessage() {
+ $preview = $this->event->getExtraParam( 'preview' );
+ return $preview ? $this->msg( 'notification-body-emailuser' )->plaintextParams( $preview ) : false;
+ }
+}
diff --git a/Echo/includes/formatters/EventPresentationModel.php b/Echo/includes/formatters/EventPresentationModel.php
new file mode 100644
index 00000000..766cb902
--- /dev/null
+++ b/Echo/includes/formatters/EventPresentationModel.php
@@ -0,0 +1,678 @@
+<?php
+
+use Wikimedia\Timestamp\TimestampException;
+
+/**
+ * Class that returns structured data based
+ * on the provided event.
+ */
+abstract class EchoEventPresentationModel implements JsonSerializable {
+
+ /**
+ * Recommended length of usernames included in messages
+ */
+ const USERNAME_RECOMMENDED_LENGTH = 20;
+
+ /**
+ * Recommended length of usernames used as link label
+ */
+ const USERNAME_AS_LABEL_RECOMMENDED_LENGTH = 15;
+
+ /**
+ * Recommended length of page names included in messages
+ */
+ const PAGE_NAME_RECOMMENDED_LENGTH = 50;
+
+ /**
+ * Recommended length of page names used as link label
+ */
+ const PAGE_NAME_AS_LABEL_RECOMMENDED_LENGTH = 15;
+
+ /**
+ * Recommended length of section titles included in messages
+ */
+ const SECTION_TITLE_RECOMMENDED_LENGTH = 50;
+
+ /**
+ * @var EchoEvent
+ */
+ protected $event;
+
+ /**
+ * @var Language
+ */
+ protected $language;
+
+ /**
+ * @var string
+ */
+ protected $type;
+
+ /**
+ * @var User for permissions checking
+ */
+ private $user;
+
+ /**
+ * @var string 'web' or 'email'
+ */
+ private $distributionType;
+
+ /**
+ * @param EchoEvent $event
+ * @param Language|string $language
+ * @param User $user Only used for permissions checking and GENDER
+ * @param string $distributionType
+ */
+ protected function __construct( EchoEvent $event, $language, User $user, $distributionType ) {
+ $this->event = $event;
+ $this->type = $event->getType();
+ $this->language = wfGetLangObj( $language );
+ $this->user = $user;
+ $this->distributionType = $distributionType;
+ }
+
+ /**
+ * Convenience function to detect whether the event type
+ * has been updated to use the presentation model system
+ *
+ * @param string $type event type
+ * @return bool
+ */
+ public static function supportsPresentationModel( $type ) {
+ global $wgEchoNotifications;
+ return isset( $wgEchoNotifications[$type]['presentation-model'] );
+ }
+
+ /**
+ * @param EchoEvent $event
+ * @param Language|string $language
+ * @param User $user
+ * @param string $distributionType 'web' or 'email'
+ * @return EchoEventPresentationModel
+ */
+ public static function factory( EchoEvent $event, $language, User $user, $distributionType = 'web' ) {
+ global $wgEchoNotifications;
+ // @todo don't depend upon globals
+
+ $class = $wgEchoNotifications[$event->getType()]['presentation-model'];
+ return new $class( $event, $language, $user, $distributionType );
+ }
+
+ /**
+ * Get the type of event
+ *
+ * @return string
+ */
+ final public function getType() {
+ return $this->type;
+ }
+
+ /**
+ * Get the user receiving the notification
+ *
+ * @return User
+ */
+ final public function getUser() {
+ return $this->user;
+ }
+
+ /**
+ * Get the category of event
+ *
+ * @return string
+ */
+ final public function getCategory() {
+ return $this->event->getCategory();
+ }
+
+ /**
+ * Equivalent to IContextSource::msg for the current
+ * language
+ *
+ * @return Message
+ */
+ protected function msg( /* ,,, */ ) {
+ /**
+ * @var Message $msg
+ */
+ $msg = call_user_func_array( 'wfMessage', func_get_args() );
+ $msg->inLanguage( $this->language );
+
+ // Notifications are considered UI (and should be in UI language, not
+ // content), and this flag is set false by inLanguage.
+ $msg->setInterfaceMessageFlag( true );
+
+ return $msg;
+ }
+
+ /**
+ * @return EchoEvent[]
+ */
+ final protected function getBundledEvents() {
+ return $this->event->getBundledEvents() ?: [];
+ }
+
+ /**
+ * Get the ids of the bundled notifications or false if it's not bundled
+ *
+ * @return int[]|bool
+ */
+ public function getBundledIds() {
+ if ( $this->isBundled() ) {
+ return array_map( function ( EchoEvent $event ) {
+ return $event->getId();
+ }, $this->getBundledEvents() );
+ }
+ return false;
+ }
+
+ /**
+ * This method returns true when there are bundled notifications, even if they are all
+ * in the same group according to getBundleGrouping(). For presentation purposes, you may
+ * want to check if getBundleCount( true, $yourCallback ) > 1 instead.
+ *
+ * @return bool Whether there are other notifications bundled with this one.
+ */
+ final protected function isBundled() {
+ return $this->getBundleCount() > 1;
+ }
+
+ /**
+ * Count the number of event groups in this bundle.
+ *
+ * By default, each event is in its own group, and this method returns the number of events.
+ * To group events differently, pass $groupCallback. For example, to group events with the
+ * same title together, use $callback = function ( $event ) { return $event->getTitle()->getPrefixedText(); }
+ *
+ * If $includeCurrent is false, all events in the same group as the current one will be ignored.
+ *
+ * @param bool $includeCurrent Include the current event (and its group)
+ * @param callable $groupCallback Callback that takes an EchoEvent and returns a grouping value
+ * @return int Number of bundled events or groups
+ * @throws InvalidArgumentException
+ */
+ final protected function getBundleCount( $includeCurrent = true, $groupCallback = null ) {
+ $events = array_merge( $this->getBundledEvents(), [ $this->event ] );
+ if ( $groupCallback ) {
+ if ( !is_callable( $groupCallback ) ) {
+ // If we pass an invalid callback to array_map(), it'll just throw a warning
+ // and return NULL, so $count ends up being 0 or -1. Instead of doing that,
+ // throw an exception.
+ throw new InvalidArgumentException( 'Invalid callback passed to getBundleCount' );
+ }
+ $events = array_unique( array_map( $groupCallback, $events ) );
+ }
+ $count = count( $events );
+
+ if ( !$includeCurrent ) {
+ $count--;
+ }
+ return $count;
+ }
+
+ /**
+ * Return the count of notifications bundled together.
+ *
+ * For parameters, see getBundleCount().
+ *
+ * @param bool $includeCurrent
+ * @param callable $groupCallback
+ * @return int count
+ */
+ final protected function getNotificationCountForOutput( $includeCurrent = true, $groupCallback = null ) {
+ $count = $this->getBundleCount( $includeCurrent, $groupCallback );
+ $cappedCount = EchoNotificationController::getCappedNotificationCount( $count );
+ return $cappedCount;
+ }
+
+ /**
+ * @return string The symbolic icon name as defined in $wgEchoNotificationIcons
+ */
+ abstract public function getIconType();
+
+ /**
+ * @return string Timestamp the event occurred at
+ */
+ final public function getTimestamp() {
+ return $this->event->getTimestamp();
+ }
+
+ /**
+ * Helper for EchoEvent::userCan
+ *
+ * @param int $type Revision::DELETED_* constant
+ * @return bool
+ */
+ final protected function userCan( $type ) {
+ return $this->event->userCan( $type, $this->user );
+ }
+
+ /**
+ * @return array|bool ['wikitext to display', 'username for GENDER'], false if no agent
+ *
+ * We have to display wikitext so we can add CSS classes for revision deleted user.
+ * The goal of this function is for callers not to worry about whether
+ * the user is visible or not.
+ * @par Example:
+ * @code
+ * list( $formattedName, $genderName ) = $this->getAgentForOutput();
+ * $msg->params( $formattedName, $genderName );
+ * @endcode
+ */
+ final protected function getAgentForOutput() {
+ $agent = $this->event->getAgent();
+ if ( !$agent ) {
+ return false;
+ }
+
+ if ( $this->userCan( Revision::DELETED_USER ) ) {
+ // Not deleted
+ return [
+ $this->getTruncatedUsername( $agent ),
+ $agent->getName()
+ ];
+ } else {
+ // Deleted/hidden
+ $msg = $this->msg( 'rev-deleted-user' )->plain();
+ // HACK: Pass an invalid username to GENDER to force the default
+ return [ '<span class="history-deleted">' . $msg . '</span>', '[]' ];
+ }
+ }
+
+ /**
+ * Return a message with the given key and the agent's
+ * formatted name and name for GENDER as 1st and
+ * 2nd parameters.
+ * @param string $key
+ * @return Message
+ */
+ final protected function getMessageWithAgent( $key ) {
+ $msg = $this->msg( $key );
+ list( $formattedName, $genderName ) = $this->getAgentForOutput();
+ $msg->params( $formattedName, $genderName );
+ return $msg;
+ }
+
+ /**
+ * Get the viewing user's name for usage in GENDER
+ *
+ * @return string
+ */
+ final protected function getViewingUserForGender() {
+ return $this->user->getName();
+ }
+
+ /**
+ * @return array|null Link object to the user's page or Special:Contributions for anon users.
+ * Can be used for primary or secondary links.
+ * Same format as secondary link.
+ * Returns null if the current user cannot see the agent.
+ */
+ final protected function getAgentLink() {
+ return $this->getUserLink( $this->event->getAgent() );
+ }
+
+ /**
+ * To be overridden by subclasses if they are unable to render the
+ * notification, for example when a page is deleted.
+ * If this function returns false, no other methods will be called
+ * on the object.
+ *
+ * @return bool
+ */
+ public function canRender() {
+ return true;
+ }
+
+ /**
+ * @return string Message key that will be used in getHeaderMessage
+ */
+ protected function getHeaderMessageKey() {
+ return "notification-header-{$this->type}";
+ }
+
+ /**
+ * Get a message object and add the performer's name as
+ * a parameter. It is expected that subclasses will override
+ * this.
+ *
+ * @return Message
+ */
+ public function getHeaderMessage() {
+ return $this->getMessageWithAgent( $this->getHeaderMessageKey() );
+ }
+
+ /**
+ * @return string Message key that will be used in getCompactHeaderMessage
+ */
+ public function getCompactHeaderMessageKey() {
+ return "notification-compact-header-{$this->type}";
+ }
+
+ /**
+ * Get a message object and add the performer's name as
+ * a parameter. It is expected that subclasses will override
+ * this.
+ *
+ * This message should be more compact than the header message
+ * ( getHeaderMessage() ). It is displayed when a
+ * notification is part of an expanded bundle.
+ *
+ * @return Message
+ */
+ public function getCompactHeaderMessage() {
+ $msg = $this->getMessageWithAgent( $this->getCompactHeaderMessageKey() );
+ if ( $msg->isDisabled() ) {
+ // Back-compat for models that haven't been updated yet
+ $msg = $this->getHeaderMessage();
+ }
+
+ return $msg;
+ }
+
+ /**
+ * @return string Message key that will be used in getSubjectMessage
+ */
+ protected function getSubjectMessageKey() {
+ return "notification-subject-{$this->type}";
+ }
+
+ /**
+ * Get a message object and add the performer's name as
+ * a parameter. It is expected that subclasses will override
+ * this. The output of the message should be plaintext.
+ *
+ * This message is used as the subject line in
+ * single-notification emails.
+ *
+ * For backward compatibility, if this is not defined,
+ * the header message ( getHeaderMessage() ) is used instead.
+ *
+ * @return Message
+ */
+ public function getSubjectMessage() {
+ $msg = $this->getMessageWithAgent( $this->getSubjectMessageKey() );
+ if ( $msg->isDisabled() ) {
+ // Back-compat for models that haven't been updated yet
+ $msg = $this->getHeaderMessage();
+ }
+
+ return $msg;
+ }
+
+ /**
+ * Get a message for the notification's body, false if it has no body
+ *
+ * @return bool|Message
+ */
+ public function getBodyMessage() {
+ return false;
+ }
+
+ /**
+ * Array of primary link details, with possibly-relative URL & label.
+ *
+ * @return array|bool Array of link data, or false for no link:
+ * ['url' => (string) url, 'label' => (string) link text (non-escaped)]
+ */
+ abstract public function getPrimaryLink();
+
+ /**
+ * Like getPrimaryLink(), but with the URL altered to add ?markasread=XYZ. When this link is followed,
+ * the notification is marked as read.
+ *
+ * When the notification is a bundle, the notification IDs are added to the parameter value
+ * separated by a "|".
+ *
+ * @return array|bool
+ */
+ final public function getPrimaryLinkWithMarkAsRead() {
+ $primaryLink = $this->getPrimaryLink();
+ if ( $primaryLink ) {
+ $eventIds = [ $this->event->getId() ];
+ if ( $this->getBundledIds() ) {
+ $eventIds = array_merge( $eventIds, $this->getBundledIds() );
+ }
+ $primaryLink['url'] = wfAppendQuery( $primaryLink['url'], [ 'markasread' => implode( '|', $eventIds ) ] );
+ }
+ return $primaryLink;
+ }
+
+ /**
+ * Array of secondary link details, including possibly-relative URLs, label,
+ * description & icon name.
+ *
+ * @return array Array of links in the format of:
+ * [['url' => (string) url,
+ * 'label' => (string) link text (non-escaped),
+ * 'description' => (string) descriptive text (optional, non-escaped),
+ * 'icon' => (bool|string) symbolic ooui icon name (or false if there is none),
+ * 'type' => (string) optional action type. Used to note a dynamic action, by setting it to 'dynamic-action'
+ * 'data' => (array) optional array containing information about the dynamic action. It must include 'tokenType' (string), 'messages' (array) with messages supplied for the item and the confirmation dialog and 'params' (array) for the API operation needed to complete the action. For example:
+ * 'data' => [
+ * 'tokenType' => 'watch',
+ * 'params' => [
+ * 'action' => 'watch',
+ * 'titles' => 'Namespace:SomeTitle'
+ * ],
+ * 'messages' => [
+ * 'confirmation' => [
+ * 'title' => 'message (parsed as HTML)',
+ * 'description' => 'optional message (parsed as HTML)'
+ * ]
+ * ]
+ * ]
+ * 'prioritized' => (bool) true if the link should be outside the
+ * action menu, false for inside)],
+ * ...]
+ *
+ * Note that you should call array_values(array_filter()) on the
+ * result of this function (FIXME).
+ */
+ public function getSecondaryLinks() {
+ return [];
+ }
+
+ /**
+ * Get the ID of the associated event
+ * @return int Event id
+ */
+ public function getEventId() {
+ return $this->event->getId();
+ }
+
+ /**
+ * @return array
+ * @throws TimestampException
+ */
+ public function jsonSerialize() {
+ $body = $this->getBodyMessage();
+
+ return [
+ 'header' => $this->getHeaderMessage()->parse(),
+ 'compactHeader' => $this->getCompactHeaderMessage()->parse(),
+ 'body' => $body ? $body->escaped() : '',
+ 'icon' => $this->getIconType(),
+ 'links' => [
+ 'primary' => $this->getPrimaryLinkWithMarkAsRead() ?: [],
+ 'secondary' => array_values( array_filter( $this->getSecondaryLinks() ) ),
+ ],
+ ];
+ }
+
+ /**
+ * @param User $user
+ * @return string
+ */
+ protected function getTruncatedUsername( User $user ) {
+ return $this->language->embedBidi( $this->language->truncate( $user->getName(), self::USERNAME_RECOMMENDED_LENGTH, '...', false ) );
+ }
+
+ /**
+ * @param Title $title
+ * @param bool $includeNamespace
+ * @return string
+ */
+ protected function getTruncatedTitleText( Title $title, $includeNamespace = false ) {
+ $text = $includeNamespace ? $title->getPrefixedText() : $title->getText();
+ return $this->language->embedBidi( $this->language->truncate( $text, self::PAGE_NAME_RECOMMENDED_LENGTH, '...', false ) );
+ }
+
+ /**
+ * @param User|null $user
+ * @return array|null
+ */
+ final protected function getUserLink( $user ) {
+ if ( !$user ) {
+ return null;
+ }
+
+ if ( !$this->userCan( Revision::DELETED_USER ) ) {
+ return null;
+ }
+
+ $url = $user->isAnon()
+ ? SpecialPage::getTitleFor( 'Contributions', $user->getName() )->getFullURL()
+ : $user->getUserPage()->getFullURL();
+
+ $label = $user->getName();
+ $truncatedLabel = $this->language->truncate( $label, self::USERNAME_AS_LABEL_RECOMMENDED_LENGTH, '...', false );
+ $isTruncated = $label !== $truncatedLabel;
+
+ return [
+ 'url' => $url,
+ 'label' => $this->language->embedBidi( $truncatedLabel ),
+ 'tooltip' => $isTruncated ? $label : '',
+ 'description' => '',
+ 'icon' => 'userAvatar',
+ 'prioritized' => true,
+ ];
+ }
+
+ /**
+ * @param Title $title
+ * @param string $description
+ * @param bool $prioritized
+ * @param array $query
+ * @return array
+ */
+ final protected function getPageLink( Title $title, $description, $prioritized, $query = [] ) {
+ if ( $title->getNamespace() === NS_USER_TALK ) {
+ $icon = 'userSpeechBubble';
+ } elseif ( $title->isTalkPage() ) {
+ $icon = 'speechBubbles';
+ } else {
+ $icon = 'article';
+ }
+
+ return [
+ 'url' => $title->getFullURL( $query ),
+ 'label' => $this->language->embedBidi(
+ $this->language->truncate( $title->getText(), self::PAGE_NAME_AS_LABEL_RECOMMENDED_LENGTH, '...', false )
+ ),
+ 'tooltip' => $title->getPrefixedText(),
+ 'description' => $description,
+ 'icon' => $icon,
+ 'prioritized' => $prioritized,
+ ];
+ }
+
+ /**
+ * Get a dynamic action link
+ *
+ * @param Title $title Title relating to this action
+ * @param bool $icon Optional. Symbolic name of the OOUI icon to use
+ * @param string $label link text (non-escaped)
+ * @param string $description descriptive text (optional, non-escaped)
+ * @param array $data Action data
+ * @param array $query
+ * @return array Array compatible with the structure of
+ * secondary links
+ */
+ final protected function getDynamicActionLink( Title $title, $icon, $label, $description = null, $data = [], $query = [] ) {
+ if ( !$icon && $title->getNamespace() === NS_USER_TALK ) {
+ $icon = 'userSpeechBubble';
+ } elseif ( !$icon && $title->isTalkPage() ) {
+ $icon = 'speechBubbles';
+ } elseif ( !$icon ) {
+ $icon = 'article';
+ }
+
+ return [
+ 'type' => 'dynamic-action',
+ 'label' => $label,
+ 'description' => $description,
+ 'data' => $data,
+ 'url' => $title->getFullURL( $query ),
+ 'icon' => $icon,
+ ];
+ }
+
+ /**
+ * Get an 'watch' or 'unwatch' dynamic action link
+ *
+ * @param Title $title Title to watch or unwatch
+ * @return array Array compatible with dynamic action link
+ */
+ final protected function getWatchActionLink( Title $title ) {
+ $isTitleWatched = $this->getUser()->isWatched( $title );
+ $availableAction = $isTitleWatched ? 'unwatch' : 'watch';
+
+ $data = [
+ 'tokenType' => 'watch',
+ 'params' => [
+ 'action' => 'watch',
+ 'titles' => $title->getPrefixedText(),
+ ],
+ 'messages' => [
+ 'confirmation' => [
+ // notification-dynamic-actions-watch-confirmation
+ // notification-dynamic-actions-unwatch-confirmation
+ 'title' => $this
+ ->msg( 'notification-dynamic-actions-' . $availableAction . '-confirmation' )
+ ->params(
+ $this->getTruncatedTitleText( $title ),
+ $title->getFullURL(),
+ $this->getUser()->getName()
+ ),
+ // notification-dynamic-actions-watch-confirmation-description
+ // notification-dynamic-actions-unwatch-confirmation-description
+ 'description' => $this
+ ->msg( 'notification-dynamic-actions-' . $availableAction . '-confirmation-description' )
+ ->params(
+ $this->getTruncatedTitleText( $title ),
+ $title->getFullURL(),
+ $this->getUser()->getName()
+ ),
+ ],
+ ],
+ ];
+
+ // "Unwatching" action requires another parameter
+ if ( $isTitleWatched ) {
+ $data[ 'params' ][ 'unwatch' ] = 1;
+ }
+
+ return $this->getDynamicActionLink(
+ $title,
+ // Design requirements are to flip the star icons
+ // in their meaning; that is, for the 'unwatch' action
+ // we should display an empty star, and for the 'watch'
+ // action a full star. In OOUI icons, their names
+ // are reversed.
+ $isTitleWatched ? 'star' : 'unStar',
+ // notification-dynamic-actions-watch
+ // notification-dynamic-actions-unwatch
+ $this->msg( 'notification-dynamic-actions-' . $availableAction )
+ ->params(
+ $this->getTruncatedTitleText( $title ),
+ $title->getFullURL( [ 'action' => $availableAction ] ),
+ $this->getUser()->getName()
+ ),
+ null,
+ $data,
+ [ 'action' => $availableAction ]
+ );
+ }
+}
diff --git a/Echo/includes/formatters/MentionFormatter.php b/Echo/includes/formatters/MentionFormatter.php
deleted file mode 100644
index 2bd98ae2..00000000
--- a/Echo/includes/formatters/MentionFormatter.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-class EchoMentionFormatter extends EchoCommentFormatter {
- /**
- * {@inheritDoc}
- */
- protected function applyChangeBeforeFormatting( EchoEvent $event, User $user, $type ) {
- parent::applyChangeBeforeFormatting( $event, $user, $type );
-
- // If we can't find a section title for the mention,
- // fall back to `notification-mention-nosection`.
- if ( !$this->getSectionTitle( $event, $user ) ) {
- $this->title = array(
- 'message' => 'notification-mention-nosection',
- 'params' => array( 'agent', 'main-title-text', 'title' )
- );
- $this->flyoutTitle = array(
- 'message' => 'notification-mention-nosection-flyout',
- 'params' => array( 'agent', 'main-title-text', 'title' )
- );
- $this->email['batch-body'] = array(
- 'message' => 'notification-mention-nosection-email-batch-body',
- 'params' => array( 'agent', 'main-title-text' )
- );
- }
- }
-}
diff --git a/Echo/includes/formatters/MentionPresentationModel.php b/Echo/includes/formatters/MentionPresentationModel.php
new file mode 100644
index 00000000..69e3cc23
--- /dev/null
+++ b/Echo/includes/formatters/MentionPresentationModel.php
@@ -0,0 +1,129 @@
+<?php
+
+class EchoMentionPresentationModel extends EchoEventPresentationModel {
+ use EchoPresentationModelSectionTrait;
+
+ public function getIconType() {
+ return 'mention';
+ }
+
+ public function canRender() {
+ return (bool)$this->event->getTitle();
+ }
+
+ protected function getHeaderMessageKey() {
+ if ( $this->onArticleTalkpage() ) {
+ return $this->hasSection() ?
+ 'notification-header-mention-article-talkpage' :
+ 'notification-header-mention-article-talkpage-nosection';
+ } elseif ( $this->onAgentTalkpage() ) {
+ return $this->hasSection() ?
+ 'notification-header-mention-agent-talkpage' :
+ 'notification-header-mention-agent-talkpage-nosection';
+ } elseif ( $this->onUserTalkpage() ) {
+ return $this->hasSection() ?
+ 'notification-header-mention-user-talkpage-v2' :
+ 'notification-header-mention-user-talkpage-nosection';
+ } else {
+ return $this->hasSection() ?
+ 'notification-header-mention-other' :
+ 'notification-header-mention-other-nosection';
+ }
+ }
+
+ public function getHeaderMessage() {
+ $msg = $this->getMessageWithAgent( $this->getHeaderMessageKey() );
+ $msg->params( $this->getViewingUserForGender() );
+
+ if ( $this->onArticleTalkpage() ) {
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle() ) );
+ } elseif ( $this->onAgentTalkpage() ) {
+ // No params to add here.
+ // If we remove this check, onUserTalkpage() has to
+ // make sure it is a user talk page but NOT the agent's talk page.
+ } elseif ( $this->onUserTalkpage() ) {
+ $username = $this->event->getTitle()->getText();
+ $msg->params( $this->getTruncatedUsername( User::newFromName( $username, false ) ) );
+ $msg->params( $username );
+ } else {
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ }
+
+ if ( $this->hasSection() ) {
+ $msg->plaintextParams( $this->getTruncatedSectionTitle() );
+ }
+
+ return $msg;
+ }
+
+ public function getBodyMessage() {
+ $content = $this->event->getExtraParam( 'content' );
+ if ( $content && $this->userCan( Revision::DELETED_TEXT ) ) {
+ $msg = $this->msg( 'notification-body-mention' );
+ $msg->plaintextParams(
+ EchoDiscussionParser::getTextSnippet(
+ $content,
+ $this->language,
+ 150,
+ $this->event->getTitle()
+ )
+ );
+ return $msg;
+ } else {
+ return false;
+ }
+ }
+
+ public function getPrimaryLink() {
+ return [
+ // Need FullURL so the section is included
+ 'url' => $this->getTitleWithSection()->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-mention' )->text()
+ ];
+ }
+
+ public function getSecondaryLinks() {
+ $title = $this->event->getTitle();
+
+ $url = $title->getLocalURL( [
+ 'oldid' => 'prev',
+ 'diff' => $this->event->getExtraParam( 'revid' )
+ ] );
+ $viewChangesLink = [
+ 'url' => $url,
+ 'label' => $this->msg( 'notification-link-text-view-changes', $this->getViewingUserForGender() )->text(),
+ 'description' => '',
+ 'icon' => 'changes',
+ 'prioritized' => true,
+ ];
+
+ return [ $this->getAgentLink(), $viewChangesLink ];
+ }
+
+ private function onArticleTalkpage() {
+ return $this->event->getTitle()->getNamespace() === NS_TALK;
+ }
+
+ private function onAgentTalkpage() {
+ return $this->event->getTitle()->equals( $this->event->getAgent()->getTalkPage() );
+ }
+
+ private function onUserTalkpage() {
+ return $this->event->getTitle()->getNamespace() === NS_USER_TALK &&
+ $this->event->getTitle()->isTalkPage() &&
+ !$this->event->getTitle()->isSubpage();
+ }
+
+ private function isTalk() {
+ return $this->event->getTitle()->isTalkPage();
+ }
+
+ private function isArticle() {
+ $ns = $this->event->getTitle()->getNamespace();
+ return $ns === NS_MAIN || $ns === NS_TALK;
+ }
+
+ protected function getSubjectMessageKey() {
+ return 'notification-mention-email-subject';
+ }
+}
diff --git a/Echo/includes/formatters/MentionStatusPresentationModel.php b/Echo/includes/formatters/MentionStatusPresentationModel.php
new file mode 100644
index 00000000..974c23d2
--- /dev/null
+++ b/Echo/includes/formatters/MentionStatusPresentationModel.php
@@ -0,0 +1,142 @@
+<?php
+
+/**
+ * Presenter for 'mention-failure' and 'mention-success' notifications
+ *
+ * @author Christoph Fischer <christoph.fischer@wikimedia.de>
+ *
+ * @license MIT
+ */
+class EchoMentionStatusPresentationModel extends EchoEventPresentationModel {
+ use EchoPresentationModelSectionTrait;
+
+ public function getIconType() {
+ if ( $this->isMixedBundle() ) {
+ return 'mention-status-bundle';
+ }
+ if ( $this->isMentionSuccess() ) {
+ return 'mention-success';
+ }
+ return 'mention-failure';
+ }
+
+ public function canRender() {
+ return (bool)$this->event->getTitle();
+ }
+
+ public function getHeaderMessage() {
+ if ( $this->isTooManyMentionsFailure() ) {
+ $msg = $this->getMessageWithAgent( 'notification-header-mention-failure-too-many' );
+ $msg->numParams( $this->getMaxMentions() );
+ return $msg;
+ }
+
+ if ( $this->isBundled() ) {
+ if ( $this->isMixedBundle() ) {
+ $successCount = $this->getBundleSuccessCount();
+
+ $msg = $this->getMessageWithAgent( 'notification-header-mention-status-bundle' );
+ $msg->numParams( $this->getBundleCount() );
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle() ) );
+ $msg->numParams( $this->getBundleCount() - $successCount );
+ $msg->numParams( $successCount );
+ return $msg;
+ }
+ if ( $this->isMentionSuccess() ) {
+ $msgKey = 'notification-header-mention-success-bundle';
+ } else {
+ $msgKey = 'notification-header-mention-failure-bundle';
+ }
+ $msg = $this->getMessageWithAgent( $msgKey );
+ $msg->numParams( $this->getBundleCount() );
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle() ) );
+ return $msg;
+ }
+
+ if ( $this->isMentionSuccess() ) {
+ $msgKey = 'notification-header-mention-success';
+ } else {
+ // Messages that can be used here:
+ // * notification-header-mention-failure-user-unknown
+ // * notification-header-mention-failure-user-anonymous
+ $msgKey = 'notification-header-mention-failure-' . $this->getFailureType();
+ }
+ $msg = $this->getMessageWithAgent( $msgKey );
+ $msg->params( $this->getSubjectName() );
+ return $msg;
+ }
+
+ public function getCompactHeaderMessage() {
+ if ( $this->isMentionSuccess() ) {
+ $msg = $this->getMessageWithAgent( 'notification-compact-header-mention-success' );
+ } else {
+ // Messages that can be used here:
+ // * notification-compact-header-mention-failure-user-unknown
+ // * notification-compact-header-mention-failure-user-anonymous
+ $msg = $this->msg( 'notification-compact-header-mention-failure-' . $this->getFailureType() );
+ }
+ $msg->params( $this->getSubjectName() );
+ return $msg;
+ }
+
+ public function getPrimaryLink() {
+ return [
+ // Need FullURL so the section is included
+ 'url' => $this->getTitleWithSection()->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-mention-failure' )
+ ->numParams( $this->getBundleCount() )
+ ->text()
+ ];
+ }
+
+ public function getSecondaryLinks() {
+ if ( $this->isBundled() ) {
+ return [];
+ }
+
+ $talkPageLink = $this->getPageLink(
+ $this->getTitleWithSection(),
+ '',
+ true
+ );
+
+ return [ $talkPageLink ];
+ }
+
+ public function isMentionSuccessEvent( EchoEvent $event ) {
+ return $event->getType() === 'mention-success';
+ }
+
+ private function isMentionSuccess() {
+ return $this->isMentionSuccessEvent( $this->event );
+ }
+
+ private function getSubjectName() {
+ return $this->event->getExtraParam( 'subject-name', '' );
+ }
+
+ private function getFailureType() {
+ return $this->event->getExtraParam( 'failure-type', 'user-unknown' );
+ }
+
+ private function isTooManyMentionsFailure() {
+ return $this->getFailureType() === 'too-many' ||
+ $this->getType() === 'mention-failure-too-many';
+ }
+
+ private function getMaxMentions() {
+ global $wgEchoMaxMentionsCount;
+ return $this->event->getExtraParam( 'max-mentions', $wgEchoMaxMentionsCount );
+ }
+
+ private function getBundleSuccessCount() {
+ $events = array_merge( $this->getBundledEvents(), [ $this->event ] );
+ return count( array_filter( $events, [ $this, 'isMentionSuccessEvent' ] ) );
+ }
+
+ private function isMixedBundle() {
+ $successCount = $this->getBundleSuccessCount();
+ $failCount = $this->getBundleCount() - $successCount;
+ return $successCount > 0 && $failCount > 0;
+ }
+}
diff --git a/Echo/includes/formatters/NotificationFormatter.php b/Echo/includes/formatters/NotificationFormatter.php
deleted file mode 100644
index b7406d47..00000000
--- a/Echo/includes/formatters/NotificationFormatter.php
+++ /dev/null
@@ -1,190 +0,0 @@
-<?php
-
-/**
- * Abstract class for constructing a notification message, this class includes
- * only the most generic formatting functionality as it may be extended by
- * notification formatters for other extensions with unique content or
- * requirements.
- */
-abstract class EchoNotificationFormatter {
-
- /**
- * List of valid output format
- * @var array
- */
- protected $validOutputFormats = array( 'text', 'flyout', 'html', 'email', 'htmlemail' );
-
- /**
- * List of valid distribution type
- */
- protected $validDistributionType = array( 'web', 'email', 'emaildigest', 'emailsubject' );
-
- /**
- * Current output format, default is 'text'
- * @var string
- */
- protected $outputFormat = 'text';
-
- /**
- * Distribution type, default is 'web'
- * @var string
- */
- protected $distributionType = 'web';
-
- /**
- * List of parameters for constructing messages
- * @var array
- */
- protected $parameters;
-
- /**
- * Creates an instance of the given class with the given parameters.
- * @param $parameters array Associative array of parameters
- * @throws MWException
- */
- public function __construct( array $parameters ) {
- $this->parameters = $parameters;
- }
-
- /**
- * Shows a notification in human-readable format.
- * @param $event EchoEvent being notified about.
- * @param $user User being notified.
- * @param $type string The notification type (e.g. notify, email)
- * @return Mixed; depends on output format
- * @see EchoNotificationFormatter::setOutputFormat
- */
- public abstract function format( $event, $user, $type );
-
- /**
- * Set the output format that the notification will be displayed in.
- * @param $format string A valid output format (by default, 'text', 'html', 'flyout', and 'email' are allowed)
- * @throws InvalidArgumentException
- */
- public function setOutputFormat( $format ) {
- if ( !in_array( $format, $this->validOutputFormats, true ) ) {
- throw new InvalidArgumentException( "Invalid output format $format" );
- }
-
- $this->outputFormat = $format;
- }
-
- public function setDistributionType( $type ) {
- if ( !in_array( $type, $this->validDistributionType, true ) ) {
- throw new InvalidArgumentException( "Invalid distribution type $type" );
- }
-
- $this->distributionType = $type;
- }
-
- /**
- * Create an EchoNotificationFormatter for the given type.
- * @param string $type
- * Select the class of formatter to use with the 'formatter-class' field.
- * For other parameters, see the appropriate class' constructor.
- * @throws RuntimeException
- * @return EchoNotificationFormatter object.
- */
- public static function factory( $type ) {
- global $wgEchoNotifications;
- if ( !isset( $wgEchoNotifications[$type] ) ) {
- throw new InvalidArgumentException( "The notification type '$type' is not registered" );
- }
-
- $parameters = $wgEchoNotifications[$type];
- if ( isset( $parameters['formatter-class'] ) ) {
- $class = $parameters['formatter-class'];
- } else {
- $class = 'EchoBasicFormatter';
- }
-
- if ( !class_exists( $class ) ) {
- throw new RuntimeException( "Class $class does not exist" );
- }
-
- return new $class( $parameters );
- }
-
- /**
- * Returns a link to a title, or the title itself.
- * @param $title Title object
- * @return string Text suitable for output format
- */
- protected function formatTitle( Title $title ) {
- return $title->getPrefixedText();
- }
-
- /**
- * Formats a timestamp in a human-readable format
- * @param $ts string Timestamp in some format compatible with wfTimestamp()
- * @return string Human-readable timestamp
- */
- protected function formatTimestamp( $ts ) {
- $timestamp = new MWTimestamp( $ts );
- $ts = $timestamp->getHumanTimestamp();
- return $ts;
- }
-
- /**
- * @todo this shouldn't be static
- * @param string $icon Name of icon as registered in BeforeCreateEchoEvent hook
- * @param string $dir either 'ltr' or 'rtl'
- * @return string
- */
- public static function getIconUrl( $icon, $dir ) {
- global $wgEchoNotificationIcons, $wgExtensionAssetsPath;
- if ( !isset( $wgEchoNotificationIcons[$icon] ) ) {
- throw new InvalidArgumentException( "The $icon icon is not registered" );
- }
-
- $iconInfo = $wgEchoNotificationIcons[$icon];
- $needsPrefixing = true;
-
- // Now we need to check it has a valid url/path
- if ( isset( $iconInfo['url'] ) && $iconInfo['url'] ) {
- $iconUrl = $iconInfo['url'];
- $needsPrefixing = false;
- } elseif ( isset( $iconInfo['path'] ) && $iconInfo['path'] ) {
- $iconUrl = $iconInfo['path'];
- } else {
- // Fallback to hardcoded 'placeholder'. This is used if someone
- // doesn't configure the 'site' icon for example.
- $icon = 'placeholder';
- $iconUrl = $wgEchoNotificationIcons['placeholder']['path'];
- }
-
- // Might be an array with different icons for ltr/rtl
- if ( is_array( $iconUrl ) ) {
- if ( !isset( $iconUrl[$dir] ) ) {
- throw new UnexpectedValueException( "Icon type $icon doesn't have an icon for $dir directionality" );
- }
-
- $iconUrl = $iconUrl[$dir];
- }
-
- // And if it was a 'path', stick the assets path in front
- if ( $needsPrefixing ) {
- $iconUrl = "$wgExtensionAssetsPath/$iconUrl";
- }
-
- return $iconUrl;
- }
-
- /**
- * Returns a revision snippet
- * @param EchoEvent $event The event that the notification is for.
- * @param User $user The user to format the notification for.
- * @return String The revision snippet (or empty string)
- */
- public function getRevisionSnippet( $event, $user ) {
- $extra = $event->getExtra();
- if ( !isset( $extra['section-text'] ) || !$event->userCan( Revision::DELETED_TEXT, $user ) ) {
- return '';
- }
-
- $snippet = trim( $extra['section-text'] );
-
- return $snippet;
- }
-
-}
diff --git a/Echo/includes/formatters/PageLinkFormatter.php b/Echo/includes/formatters/PageLinkFormatter.php
deleted file mode 100644
index 80fbc456..00000000
--- a/Echo/includes/formatters/PageLinkFormatter.php
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-
-/**
- * Custom formatter for 'page-link' notifications
- */
-class EchoPageLinkFormatter extends EchoBasicFormatter {
-
- /**
- * This is a workaround for backwards compatibility.
- * In https://gerrit.wikimedia.org/r/#/c/63076 we changed
- * the schema to save link-from-page-id instead of
- * link-from-namespace & link-from-title
- */
- protected function extractExtra( $extra ) {
- if ( isset( $extra['link-from-namespace'], $extra['link-from-title'] )
- && !isset( $extra['link-from-page-id'] )
- ) {
- $title = Title::makeTitleSafe(
- $extra['link-from-namespace'],
- $extra['link-from-title']
- );
- if ( $title ) {
- $extra['link-from-page-id'] = $title->getArticleId();
- unset(
- $extra['link-from-namespace'],
- $extra['link-from-title']
- );
- }
- }
-
- return $extra;
- }
-
- /**
- * This method overwrite parent method and construct the bundle iterator
- * based on link from, it will be used in a message like this: Page A was
- * link from Page B and X other pages
- *
- * @param $event EchoEvent
- * @param $user User
- * @param $type string deprecated
- */
- protected function generateBundleData( $event, $user, $type ) {
- global $wgEchoMaxNotificationCount;
-
- $data = $this->getRawBundleData( $event, $user, $type );
-
- if ( !$data ) {
- return;
- }
- $extra = self::extractExtra( $event->getExtra() );
-
- if ( !$this->isTitleSet( $extra ) ) {
- // Link from title is required for bundling notification
- return;
- }
-
- $count = 1;
- $linkFrom = array(
- $extra['link-from-page-id'] => true
- );
- foreach ( $data as $bundledEvent ) {
- $extra = $bundledEvent->getExtra();
- if ( !$extra ) {
- continue;
- }
-
- if ( $this->isTitleSet( $extra ) ) {
- $pageId = $extra['link-from-page-id'];
-
- if ( !isset( $linkFrom[$pageId] ) ) {
- $linkFrom[$pageId] = true;
- $count++;
- }
- }
- if ( $count > $wgEchoMaxNotificationCount + 1 ) {
- break;
- }
- }
-
- $this->bundleData['link-from-page-other-count'] = $count - 1;
- if ( $count > 1 ) {
- $this->bundleData['use-bundle'] = true;
- }
- }
-
- /**
- * Internal function to check if link from page id key is set
- * @param $extra array
- * @return bool
- */
- private function isTitleSet( $extra ) {
- return isset( $extra['link-from-page-id'] ) && $extra['link-from-page-id'];
- }
-
- /**
- * @param $event EchoEvent
- * @param $param string
- * @param $message Message
- * @param $user User
- */
- protected function processParam( $event, $param, $message, $user ) {
- $extra = self::extractExtra( $event->getExtra() );
- switch ( $param ) {
- // 'A' part in this message: link from page A and X others
- case 'link-from-page':
- $title = null;
- if ( $this->isTitleSet( $extra ) ) {
- $title = Title::newFromId( $extra['link-from-page-id'] );
- // Link-from page could be a brand new page and page_id would not be replicated
- // to slave db yet. If job queue is enabled to process web and email notification,
- // the check against master database is not necessary since there is already a
- // delay in the job queue
- if ( !$title ) {
- global $wgEchoUseJobQueue;
- $diff = wfTimestamp() - wfTimestamp( TS_UNIX, $event->getTimestamp() );
- if ( !$wgEchoUseJobQueue && $diff < 5 ) {
- $title = Title::newFromID( $extra['link-from-page-id'], Title::GAID_FOR_UPDATE );
- }
- }
- if ( $title ) {
- if ( $this->outputFormat === 'htmlemail' ) {
- $message->rawParams(
- Linker::link(
- $title,
- $this->formatTitle( $title ),
- array( 'style' => $this->getHTMLLinkStyle() ),
- array(),
- array( 'https' )
- )
- );
- } else {
- $message->params( $this->formatTitle( $title ) );
- }
- }
- }
-
- if ( !$title ) {
- $message->params( $this->getMessage( 'echo-no-title' ) );
- }
- break;
-
- // example: {7} other page, {99+} other pages
- case 'link-from-page-other-display':
- global $wgEchoMaxNotificationCount;
-
- if ( $this->bundleData['link-from-page-other-count'] > $wgEchoMaxNotificationCount ) {
- $message->params(
- $this->getMessage( 'echo-notification-count' )
- ->numParams( $wgEchoMaxNotificationCount )
- ->text()
- );
- } else {
- $message->numParams( $this->bundleData['link-from-page-other-count'] );
- }
- break;
-
- // the number used for plural support
- case 'link-from-page-other-count':
- $message->params( $this->bundleData['link-from-page-other-count'] );
- break;
-
- default:
- parent::processParam( $event, $param, $message, $user );
- break;
- }
- }
-
- /**
- * Helper function for getLink()
- *
- * @param EchoEvent $event
- * @param User $user The user receiving the notification
- * @param String $destination The destination type for the link
- * @return Array including target and query parameters
- */
- protected function getLinkParams( $event, $user, $destination ) {
- $target = null;
- $query = array();
- // Set up link parameters based on the destination (or pass to parent)
- switch ( $destination ) {
- case 'link-from-page':
- if ( $this->bundleData['use-bundle'] ) {
- if ( $event->getTitle() ) {
- $target = SpecialPage::getTitleFor( 'WhatLinksHere', $event->getTitle()->getPrefixedText() );
- }
- } else {
- $extra = self::extractExtra( $event->getExtra() );
- if ( $this->isTitleSet( $extra ) ) {
- $target = Title::newFromId( $extra['link-from-page-id'] );
- }
- }
- break;
- default:
- return parent::getLinkParams( $event, $user, $destination );
- }
- return array( $target, $query );
- }
-}
diff --git a/Echo/includes/formatters/PageLinkedPresentationModel.php b/Echo/includes/formatters/PageLinkedPresentationModel.php
new file mode 100644
index 00000000..d6e41323
--- /dev/null
+++ b/Echo/includes/formatters/PageLinkedPresentationModel.php
@@ -0,0 +1,114 @@
+<?php
+
+class EchoPageLinkedPresentationModel extends EchoEventPresentationModel {
+
+ private $pageFrom;
+
+ public function getIconType() {
+ return 'linked';
+ }
+
+ /**
+ * The page containing the link may be a new page
+ * that is not yet replicated.
+ * This event won't be rendered unless/until
+ * both pages are available.
+ * @return bool
+ */
+ public function canRender() {
+ $pageTo = $this->event->getTitle();
+ $pageFrom = $this->getPageFrom();
+ return (bool)$pageTo && (bool)$pageFrom;
+ }
+
+ public function getPrimaryLink() {
+ if ( $this->isBundled() ) {
+ return false;
+ } else {
+ return [
+ 'url' => $this->getPageFrom()->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-page' )->text(),
+ ];
+ }
+ }
+
+ public function getSecondaryLinks() {
+ $whatLinksHereLink = [
+ 'url' => SpecialPage::getTitleFor( 'Whatlinkshere', $this->event->getTitle()->getPrefixedText() )->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-what-links-here' )->text(),
+ 'description' => '',
+ 'icon' => 'linked',
+ 'prioritized' => true
+ ];
+
+ $revid = $this->event->getExtraParam( 'revid' );
+ $diffLink = null;
+ if ( $revid !== null ) {
+ $diffLink = [
+ 'url' => $this->getPageFrom()->getFullURL( [ 'diff' => $revid, 'oldid' => 'prev' ] ),
+ 'label' => $this->msg( 'notification-link-text-view-changes', $this->getViewingUserForGender() )->text(),
+ 'description' => '',
+ 'icon' => 'changes',
+ 'prioritized' => true
+ ];
+ }
+
+ return [ $whatLinksHereLink, $diffLink ];
+ }
+
+ protected function getHeaderMessageKey() {
+ if ( $this->getBundleCount( true, [ $this, 'getLinkedPageId' ] ) > 1 ) {
+ return "notification-bundle-header-{$this->type}";
+ }
+ return "notification-header-{$this->type}";
+ }
+
+ public function getHeaderMessage() {
+ $msg = parent::getHeaderMessage();
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ $msg->params( $this->getTruncatedTitleText( $this->getPageFrom(), true ) );
+ $count =
+ $this->getNotificationCountForOutput( true, [ $this, 'getLinkedPageId' ] );
+
+ // Repeat is B/C until unused parameter is removed from translations
+ $msg->numParams( $count, $count );
+ return $msg;
+ }
+
+ public function getCompactHeaderMessage() {
+ $msg = $this->msg( parent::getCompactHeaderMessageKey() );
+ $msg->params( $this->getTruncatedTitleText( $this->getPageFrom(), true ) );
+ return $msg;
+ }
+
+ /**
+ * Get the page ID of the linked-from page for a given event.
+ * @param EchoEvent $event page-linked event
+ * @return int Page ID, or 0 if the page doesn't exist
+ */
+ public function getLinkedPageId( EchoEvent $event ) {
+ $extra = $event->getExtra();
+ if ( isset( $extra['link-from-page-id'] ) ) {
+ return $extra['link-from-page-id'];
+ }
+ // Backwards compatiblity for events from before https://gerrit.wikimedia.org/r/#/c/63076
+ if ( isset( $extra['link-from-namespace'] ) && isset( $extra['link-from-title'] ) ) {
+ $title = Title::makeTitleSafe( $extra['link-from-namespace'], $extra['link-from-title'] );
+ if ( $title ) {
+ return $title->getArticleId();
+ }
+ }
+ return 0;
+ }
+
+ private function getPageFrom() {
+ if ( !$this->pageFrom ) {
+ $this->pageFrom = Title::newFromId( $this->getLinkedPageId( $this->event ) );
+ }
+ return $this->pageFrom;
+ }
+
+ protected function getSubjectMessageKey() {
+ return 'notification-page-linked-email-subject';
+ }
+}
diff --git a/Echo/includes/formatters/PresentationModelSectionTrait.php b/Echo/includes/formatters/PresentationModelSectionTrait.php
new file mode 100644
index 00000000..7d0e6b9f
--- /dev/null
+++ b/Echo/includes/formatters/PresentationModelSectionTrait.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Trait that adds section title handling to an EchoEventPresentationModel subclass.
+ */
+trait EchoPresentationModelSectionTrait {
+ private $rawSectionTitle = null;
+ private $parsedSectionTitle = null;
+
+ /**
+ * Get the raw (unparsed) section title
+ * @return string Section title
+ */
+ protected function getRawSectionTitle() {
+ if ( $this->rawSectionTitle !== null ) {
+ return $this->rawSectionTitle;
+ }
+ $sectionTitle = $this->event->getExtraParam( 'section-title' );
+ if ( !$sectionTitle ) {
+ $this->rawSectionTitle = false;
+ return false;
+ }
+ // Check permissions
+ if ( !$this->userCan( Revision::DELETED_TEXT ) ) {
+ $this->rawSectionTitle = false;
+ return false;
+ }
+
+ $this->rawSectionTitle = $sectionTitle;
+ return $this->rawSectionTitle;
+ }
+
+ /**
+ * Get the section title parsed to plain text
+ * @return string Section title (plain text)
+ */
+ protected function getParsedSectionTitle() {
+ if ( $this->parsedSectionTitle !== null ) {
+ return $this->parsedSectionTitle;
+ }
+ $rawSectionTitle = $this->getRawSectionTitle();
+ if ( !$rawSectionTitle ) {
+ $this->parsedSectionTitle = false;
+ return false;
+ }
+ $this->parsedSectionTitle = EchoDiscussionParser::getTextSnippet(
+ $rawSectionTitle,
+ $this->language,
+ 150,
+ $this->event->getTitle()
+ );
+ return $this->parsedSectionTitle;
+ }
+
+ /**
+ * Check if there is a section.
+ *
+ * This also returns false if the revision is deleted,
+ * even if there is a section, because the section can't
+ * be viewed in that case.
+ * @return bool Whether there is a section
+ */
+ protected function hasSection() {
+ return (bool)$this->getRawSectionTitle();
+ }
+
+ /**
+ * Get a Title pointing to the section, if available.
+ * @return Title
+ */
+ protected function getTitleWithSection() {
+ $title = $this->event->getTitle();
+ $section = $this->getParsedSectionTitle();
+ // Like Parser::guessSectionNameFromWikiText() but without the link stripping
+ $fragment = Sanitizer::escapeId(
+ Sanitizer::normalizeSectionNameWhitespace( $section ),
+ 'noninitial'
+ );
+ if ( $section ) {
+ $title = Title::makeTitle(
+ $title->getNamespace(),
+ $title->getDBkey(),
+ $fragment
+ );
+ }
+ return $title;
+ }
+
+ protected function getTruncatedSectionTitle() {
+ return $this->language->embedBidi( $this->language->truncate(
+ $this->getParsedSectionTitle(),
+ self::SECTION_TITLE_RECOMMENDED_LENGTH,
+ '...',
+ false
+ ) );
+ }
+}
diff --git a/Echo/includes/formatters/RevertedPresentationModel.php b/Echo/includes/formatters/RevertedPresentationModel.php
new file mode 100644
index 00000000..04d63b93
--- /dev/null
+++ b/Echo/includes/formatters/RevertedPresentationModel.php
@@ -0,0 +1,85 @@
+<?php
+
+class EchoRevertedPresentationModel extends EchoEventPresentationModel {
+
+ public function getIconType() {
+ return 'revert';
+ }
+
+ public function canRender() {
+ return (bool)$this->event->getTitle();
+ }
+
+ public function getHeaderMessage() {
+ $msg = parent::getHeaderMessage();
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ $msg->params( $this->getNumberOfEdits() );
+ return $msg;
+ }
+
+ public function getBodyMessage() {
+ $summary = $this->event->getExtraParam( 'summary' );
+ if ( !$this->isAutomaticSummary( $summary ) && $this->userCan( Revision::DELETED_COMMENT ) ) {
+ $msg = $this->msg( "notification-body-{$this->type}" );
+ $msg->plaintextParams( $this->formatSummary( $summary ) );
+ return $msg;
+ } else {
+ return false;
+ }
+ }
+
+ private function formatSummary( $wikitext ) {
+ return EchoDiscussionParser::getTextSnippetFromSummary( $wikitext, $this->language );
+ }
+
+ public function getPrimaryLink() {
+ $url = $this->event->getTitle()->getLocalURL( [
+ 'oldid' => 'prev',
+ 'diff' => $this->event->getExtraParam( 'revid' )
+ ] );
+ return [
+ 'url' => $url,
+ 'label' => $this->msg( 'notification-link-text-view-changes', $this->getViewingUserForGender() )->text()
+ ];
+ }
+
+ public function getSecondaryLinks() {
+ $links = [ $this->getAgentLink() ];
+
+ $title = $this->event->getTitle();
+ if ( $title->canHaveTalkPage() ) {
+ $links[] = $this->getPageLink(
+ $title->getTalkPage(), null, true
+ );
+ }
+
+ return $links;
+ }
+
+ /**
+ * Return a number that represents if one or multiple edits
+ * have been reverted for formatting purposes.
+ * @return int
+ */
+ private function getNumberOfEdits() {
+ $method = $this->event->getExtraParam( 'method' );
+ if ( $method && $method === 'rollback' ) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+
+ private function isAutomaticSummary( $summary ) {
+ $autoSummaryMsg = wfMessage( 'undo-summary' )->inContentLanguage();
+ $autoSummaryMsg->params( $this->event->getExtraParam( 'reverted-revision-id' ) );
+ $autoSummaryMsg->params( $this->getViewingUserForGender() );
+ $autoSummary = $autoSummaryMsg->text();
+
+ return $summary === $autoSummary;
+ }
+
+ protected function getSubjectMessageKey() {
+ return 'notification-reverted-email-subject2';
+ }
+}
diff --git a/Echo/includes/formatters/SpecialNotificationsFormatter.php b/Echo/includes/formatters/SpecialNotificationsFormatter.php
new file mode 100644
index 00000000..d5e7d981
--- /dev/null
+++ b/Echo/includes/formatters/SpecialNotificationsFormatter.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * A formatter for Special:Notifications
+ *
+ * This formatter uses OOUI libraries. Any calls to this formatter must
+ * also call OutputPage::enableOOUI() before calling this formatter.
+ */
+class SpecialNotificationsFormatter extends EchoEventFormatter {
+ protected function formatModel( EchoEventPresentationModel $model ) {
+ $markReadSpecialPage = new SpecialNotificationsMarkRead();
+ $id = $model->getEventId();
+
+ $icon = Html::element(
+ 'img',
+ [
+ 'class' => 'mw-echo-icon',
+ 'src' => $this->getIconURL( $model ),
+ ]
+ );
+
+ OutputPage::setupOOUI();
+
+ $markAsReadIcon = new OOUI\IconWidget( [
+ 'icon' => 'close',
+ 'title' => wfMessage( 'echo-notification-markasread' ),
+ ] );
+
+ $markAsReadForm = $markReadSpecialPage->getMinimalForm(
+ $id,
+ $this->msg( 'echo-notification-markasread' )->text(),
+ false,
+ $markAsReadIcon->toString()
+ );
+
+ $markAsReadButton = Html::rawElement(
+ 'div',
+ [ 'class' => 'mw-echo-markAsReadButton' ],
+ $markAsReadForm->prepareForm()->getHTML( /* First submission attempt */ false )
+ );
+
+ $html = Xml::tags(
+ 'div',
+ [ 'class' => 'mw-echo-title' ],
+ $model->getHeaderMessage()->parse()
+ ) . "\n";
+
+ $body = $model->getBodyMessage();
+ if ( $body ) {
+ $html .= Xml::tags(
+ 'div',
+ [ 'class' => 'mw-echo-payload' ],
+ $body->escaped()
+ ) . "\n";
+ }
+
+ $ts = $this->language->getHumanTimestamp(
+ new MWTimestamp( $model->getTimestamp() ),
+ null,
+ $this->user
+ );
+
+ $footerItems = [ Html::element( 'span', [ 'class' => 'mw-echo-notification-footer-element' ], $ts ) ];
+
+ // Add links to the footer, primary goes first, then secondary ones
+ $links = [];
+ $primaryLink = $model->getPrimaryLinkWithMarkAsRead();
+ if ( $primaryLink !== false ) {
+ $links[] = $primaryLink;
+ }
+ $links = array_merge( $links, array_filter( $model->getSecondaryLinks() ) );
+ foreach ( $links as $link ) {
+ $footerAttributes = [
+ 'href' => $link['url'],
+ 'class' => 'mw-echo-notification-footer-element',
+ ];
+
+ if ( isset( $link['tooltip'] ) ) {
+ $footerAttributes['title'] = $link['tooltip'];
+ }
+
+ $footerItems[] = Html::element(
+ 'a',
+ $footerAttributes,
+ $link['label']
+ );
+ }
+
+ $pipe = wfMessage( 'pipe-separator' )->inLanguage( $this->language )->escaped();
+ $html .= Xml::tags(
+ 'div',
+ [ 'class' => 'mw-echo-notification-footer' ],
+ implode( Html::element( 'span', [ 'class' => 'mw-echo-notification-footer-element' ], $pipe ), $footerItems )
+ ) . "\n";
+
+ // Wrap everything in mw-echo-content class
+ $html = Xml::tags( 'div', [ 'class' => 'mw-echo-content' ], $html );
+
+ // And then add the mark as read button
+ // and the icon in front and wrap with
+ // mw-echo-state class.
+ $html = Xml::tags( 'div', [ 'class' => 'mw-echo-state' ], $markAsReadButton . $icon . $html );
+
+ return $html;
+ }
+
+ private function getIconURL( EchoEventPresentationModel $model ) {
+ return EchoIcon::getUrl(
+ $model->getIconType(),
+ $this->language->getDir()
+ );
+ }
+}
diff --git a/Echo/includes/formatters/UserRightsFormatter.php b/Echo/includes/formatters/UserRightsFormatter.php
deleted file mode 100644
index 3f1ca492..00000000
--- a/Echo/includes/formatters/UserRightsFormatter.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-/**
- * Formatter for 'user-rights' notifications
- */
-class EchoUserRightsFormatter extends EchoBasicFormatter {
-
- /**
- * @param $event EchoEvent
- * @param $param string
- * @param $message Message
- * @param $user User
- */
- protected function processParam( $event, $param, $message, $user ) {
- $extra = $event->getExtra();
- switch ( $param ) {
- // List of user rights that are granted or revoked
- case 'user-rights-list':
- $lang = $this->getLanguage();
-
- $list = array();
-
- foreach ( array( 'add', 'remove' ) as $action ) {
- if ( isset( $extra[$action] ) && $extra[$action] ) {
-
- // Get the localized group names, bug 55338
- $groups = array();
- foreach( $extra[$action] as $group ) {
- $msg = $this->getMessage( 'group-' . $group );
- $groups[] = $msg->isBlank() ? $group : $msg->escaped();
- }
-
- // Messages that can be used here:
- // * notification-user-rights-add
- // * notification-user-rights-remove
- $list[] = $this->getMessage( 'notification-user-rights-' . $action )
- ->params( $lang->commaList( $groups ), count( $groups ) )
- ->escaped();
- }
- }
- $message->params( $lang->semicolonList( $list ) );
- break;
-
- default:
- parent::processParam( $event, $param, $message, $user );
- break;
- }
- }
-
- /**
- * Helper function for getLink()
- *
- * @param EchoEvent $event
- * @param User $user The user receiving the notification
- * @param String $destination The destination type for the link
- * @return Array including target and query parameters
- */
- protected function getLinkParams( $event, $user, $destination ) {
- $target = null;
- $query = array();
- // Set up link parameters based on the destination (or pass to parent)
- switch ( $destination ) {
- case 'user-rights-list':
- $target = SpecialPage::getTitleFor( 'Listgrouprights' );
- break;
- default:
- return parent::getLinkParams( $event, $user, $destination );
- }
- return array( $target, $query );
- }
-}
diff --git a/Echo/includes/formatters/UserRightsPresentationModel.php b/Echo/includes/formatters/UserRightsPresentationModel.php
new file mode 100644
index 00000000..53f20d03
--- /dev/null
+++ b/Echo/includes/formatters/UserRightsPresentationModel.php
@@ -0,0 +1,110 @@
+<?php
+
+/**
+ * Formatter for 'user-rights' notifications
+ */
+class EchoUserRightsPresentationModel extends EchoEventPresentationModel {
+
+ public function getIconType() {
+ return 'user-rights';
+ }
+
+ public function getHeaderMessage() {
+ list( $formattedName, $genderName ) = $this->getAgentForOutput();
+ $add = array_map(
+ [ $this->language, 'embedBidi' ],
+ $this->getLocalizedGroupNames( array_values( $this->event->getExtraParam( 'add', [] ) ) )
+ );
+ $remove = array_map(
+ [ $this->language, 'embedBidi' ],
+ $this->getLocalizedGroupNames( array_values( $this->event->getExtraParam( 'remove', [] ) ) )
+ );
+ $expiryChanged = array_map(
+ [ $this->language, 'embedBidi' ],
+ $this->getLocalizedGroupNames( array_values( $this->event->getExtraParam( 'expiry-changed', [] ) ) )
+ );
+ if ( $expiryChanged ) {
+ $msg = $this->msg( 'notification-header-user-rights-expiry-change' );
+ $msg->params( $genderName );
+ $msg->params( $this->language->commaList( $expiryChanged ) );
+ $msg->params( count( $expiryChanged ) );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ } elseif ( $add && !$remove ) {
+ $msg = $this->msg( 'notification-header-user-rights-add-only' );
+ $msg->params( $genderName );
+ $msg->params( $this->language->commaList( $add ) );
+ $msg->params( count( $add ) );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ } elseif ( !$add && $remove ) {
+ $msg = $this->msg( 'notification-header-user-rights-remove-only' );
+ $msg->params( $genderName );
+ $msg->params( $this->language->commaList( $remove ) );
+ $msg->params( count( $remove ) );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ } else {
+ $msg = $this->msg( 'notification-header-user-rights-add-and-remove' );
+ $msg->params( $genderName );
+ $msg->params( $this->language->commaList( $add ) );
+ $msg->params( count( $add ) );
+ $msg->params( $this->language->commaList( $remove ) );
+ $msg->params( count( $remove ) );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+ }
+
+ public function getBodyMessage() {
+ $reason = $this->event->getExtraParam( 'reason' );
+ return $reason ? $this->msg( 'notification-body-user-rights' )->params( $reason ) : false;
+ }
+
+ private function getLocalizedGroupNames( $names ) {
+ return array_map( function ( $name ) {
+ $msg = $this->msg( 'group-' . $name );
+ return $msg->isBlank() ? $name : $msg->text();
+ }, $names );
+ }
+
+ public function getPrimaryLink() {
+ $addedGroups = array_values( $this->event->getExtraParam( 'add', [] ) );
+ $removedGroups = array_values( $this->event->getExtraParam( 'remove', [] ) );
+ if ( count( $addedGroups ) >= 1 && count( $removedGroups ) === 0 ) {
+ $fragment = $addedGroups[0];
+ } elseif ( count( $addedGroups ) === 0 && count( $removedGroups ) >= 1 ) {
+ $fragment = $removedGroups[0];
+ } else {
+ $fragment = '';
+ }
+ return [
+ 'url' => SpecialPage::getTitleFor( 'Listgrouprights', false, $fragment )->getFullURL(),
+ 'label' => $this->msg( 'echo-learn-more' )->text()
+ ];
+ }
+
+ public function getSecondaryLinks() {
+ return [ $this->getAgentLink(), $this->getLogLink() ];
+ }
+
+ private function getLogLink() {
+ $affectedUserPage = User::newFromId( $this->event->getExtraParam( 'user' ) )->getUserPage();
+ $query = [
+ 'type' => 'rights',
+ 'page' => $affectedUserPage->getPrefixedText(),
+ 'user' => $this->event->getAgent()->getName(),
+ ];
+ return [
+ 'label' => $this->msg( 'echo-log' )->text(),
+ 'url' => SpecialPage::getTitleFor( 'Log' )->getFullURL( $query ),
+ 'description' => '',
+ 'icon' => false,
+ 'prioritized' => true,
+ ];
+ }
+
+ protected function getSubjectMessageKey() {
+ return 'notification-user-rights-email-subject';
+ }
+}
diff --git a/Echo/includes/formatters/WelcomePresentationModel.php b/Echo/includes/formatters/WelcomePresentationModel.php
new file mode 100644
index 00000000..ca14f17b
--- /dev/null
+++ b/Echo/includes/formatters/WelcomePresentationModel.php
@@ -0,0 +1,25 @@
+<?php
+
+class EchoWelcomePresentationModel extends EchoEventPresentationModel {
+
+ public function getIconType() {
+ return 'site';
+ }
+
+ public function getPrimaryLink() {
+ $msg = $this->msg( 'notification-welcome-link' );
+ if ( $msg->isDisabled() ) {
+ return false;
+ }
+
+ $title = Title::newFromText( $msg->plain() );
+ if ( !$title ) {
+ return false;
+ }
+
+ return [
+ 'url' => $title->getFullURL(),
+ 'label' => $this->msg( 'notification-welcome-linktext' )->text(),
+ ];
+ }
+}
diff --git a/Echo/includes/gateway/UserNotificationGateway.php b/Echo/includes/gateway/UserNotificationGateway.php
index 5251b776..28261a7c 100644
--- a/Echo/includes/gateway/UserNotificationGateway.php
+++ b/Echo/includes/gateway/UserNotificationGateway.php
@@ -35,7 +35,7 @@ class EchoUserNotificationGateway {
/**
* Mark notifications as read
* @param $eventIDs array
- * @return boolean
+ * @return bool
*/
public function markRead( array $eventIDs ) {
if ( !$eventIDs ) {
@@ -46,12 +46,36 @@ class EchoUserNotificationGateway {
return $dbw->update(
self::$notificationTable,
- array( 'notification_read_timestamp' => $dbw->timestamp( wfTimestampNow() ) ),
- array(
+ [ 'notification_read_timestamp' => $dbw->timestamp( wfTimestampNow() ) ],
+ [
'notification_user' => $this->user->getId(),
'notification_event' => $eventIDs,
'notification_read_timestamp' => null,
- ),
+ ],
+ __METHOD__
+ );
+ }
+
+ /**
+ * Mark notifications as unread
+ * @param $eventIDs array
+ * @return bool
+ */
+ public function markUnRead( array $eventIDs ) {
+ if ( !$eventIDs ) {
+ return;
+ }
+
+ $dbw = $this->dbFactory->getEchoDb( DB_MASTER );
+
+ return $dbw->update(
+ self::$notificationTable,
+ [ 'notification_read_timestamp' => null ],
+ [
+ 'notification_user' => $this->user->getId(),
+ 'notification_event' => $eventIDs,
+ 'notification_read_timestamp IS NOT NULL'
+ ],
__METHOD__
);
}
@@ -66,25 +90,25 @@ class EchoUserNotificationGateway {
return $dbw->update(
self::$notificationTable,
- array( 'notification_read_timestamp' => $dbw->timestamp( wfTimestampNow() ) ),
- array(
+ [ 'notification_read_timestamp' => $dbw->timestamp( wfTimestampNow() ) ],
+ [
'notification_user' => $this->user->getId(),
- 'notification_read_timestamp' => NULL,
- 'notification_bundle_base' => 1,
- ),
+ 'notification_read_timestamp' => null,
+ ],
__METHOD__
);
}
/**
* Get notification count for the types specified
- * @param int use master or slave storage to pull count
- * @param array event types to retrieve
+ * @param int $dbSource use master or slave storage to pull count
+ * @param array $eventTypesToLoad event types to retrieve
+ * @param int $cap Max count
* @return int
*/
- public function getNotificationCount( $dbSource, array $eventTypesToLoad = array() ) {
+ public function getCappedNotificationCount( $dbSource, array $eventTypesToLoad = [], $cap = MWEchoNotifUser::MAX_BADGE_COUNT ) {
// double check
- if ( !in_array( $dbSource, array( DB_SLAVE, DB_MASTER ) ) ) {
+ if ( !in_array( $dbSource, [ DB_SLAVE, DB_MASTER ] ) ) {
$dbSource = DB_SLAVE;
}
@@ -92,60 +116,53 @@ class EchoUserNotificationGateway {
return 0;
}
- global $wgEchoMaxNotificationCount;
-
$db = $this->dbFactory->getEchoDb( $dbSource );
- $res = $db->select(
- array(
+ return $db->selectRowCount(
+ [
self::$notificationTable,
self::$eventTable
- ),
- array( 'notification_event' ),
- array(
+ ],
+ [ '1' ],
+ [
'notification_user' => $this->user->getId(),
- 'notification_bundle_base' => 1,
'notification_read_timestamp' => null,
+ 'event_deleted' => 0,
'event_type' => $eventTypesToLoad,
- ),
+ ],
__METHOD__,
- array( 'LIMIT' => $wgEchoMaxNotificationCount + 1 ),
- array(
- 'echo_event' => array( 'LEFT JOIN', 'notification_event=event_id' ),
- )
+ [ 'LIMIT' => $cap ],
+ [
+ 'echo_event' => [ 'LEFT JOIN', 'notification_event=event_id' ],
+ ]
);
- if ( $res ) {
- return $db->numRows( $res );
- } else {
- return 0;
- }
}
/**
* IMPORTANT: should only call this function if the number of unread notification
* is reasonable, for example, unread notification count is less than the max
- * display defined in $wgEchoMaxNotificationCount
+ * display defined in MWEchoNotifUser::MAX_BADGE_COUNT
* @param string
* @return int[]
*/
public function getUnreadNotifications( $type ) {
$dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
$res = $dbr->select(
- array(
+ [
self::$notificationTable,
self::$eventTable
- ),
- array( 'notification_event' ),
- array(
+ ],
+ [ 'notification_event' ],
+ [
'notification_user' => $this->user->getId(),
- 'notification_bundle_base' => 1,
'notification_read_timestamp' => null,
+ 'event_deleted' => 0,
'event_type' => $type,
'notification_event = event_id'
- ),
+ ],
__METHOD__
);
- $eventIds = array();
+ $eventIds = [];
if ( $res ) {
foreach ( $res as $row ) {
$eventIds[$row->notification_event] = $row->notification_event;
diff --git a/Echo/includes/iterator/CallbackFilterIterator.php b/Echo/includes/iterator/CallbackFilterIterator.php
deleted file mode 100644
index 4095d1d4..00000000
--- a/Echo/includes/iterator/CallbackFilterIterator.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-/**
- * This class is implemented as part of SPL starting at PHP5.4. This
- * re-implementation provides backwards compatibility to mediawiki
- * running on PHP5.3.
- */
-class CallbackFilterIterator extends FilterIterator {
- protected $callback;
-
- public function __construct( Iterator $iterator, $callback ) {
- parent::__construct( $iterator );
- $this->callback = $callback;
- }
-
- public function accept() {
- return call_user_func(
- $this->callback,
- $this->current(),
- $this->key(),
- $this->getInnerIterator()
- );
- }
-}
diff --git a/Echo/includes/iterator/FilteredSequentialIterator.php b/Echo/includes/iterator/FilteredSequentialIterator.php
index cc0271f9..246a0910 100644
--- a/Echo/includes/iterator/FilteredSequentialIterator.php
+++ b/Echo/includes/iterator/FilteredSequentialIterator.php
@@ -13,19 +13,19 @@
* $users = new EchoFilteredSequentialIterator;
* $users->add( array( $userA, $userB, $userC ) );
*
- * $it = new EchoBatchRowIterator( ... );
+ * $it = new BatchRowIterator( ... );
* ...
* $it = new RecursiveIteratorIterator( $it );
* $users->add( new EchoCallbackIterator( $it, function( $row ) {
- * ...
- * return $user;
+ * ...
+ * return $user;
* } ) );
*
* foreach ( $users as $user ) {
- * ...
+ * ...
* }
*
- * By default the EchoBatchRowIterator returns an array of rows, this class
+ * By default the BatchRowIterator returns an array of rows, this class
* expects a stream of user objects. To bridge that gap the
* RecursiveIteratorIterator is used to flatten and the EchoCallbackIterator
* is used to transform each database $row into a User object.
@@ -36,12 +36,12 @@ class EchoFilteredSequentialIterator implements IteratorAggregate {
/**
* @var Iterator[]
*/
- protected $iterators = array();
+ protected $iterators = [];
/**
* @var callable[]
*/
- protected $filters = array();
+ protected $filters = [];
/**
* @param Iterator|IteratorAggregate|array $users
@@ -87,15 +87,15 @@ class EchoFilteredSequentialIterator implements IteratorAggregate {
* @return Iterator
*/
protected function createIterator() {
- switch( count( $this->iterators ) ) {
- case 0:
- return new EmptyIterator;
+ switch ( count( $this->iterators ) ) {
+ case 0:
+ return new EmptyIterator;
- case 1:
- return reset( $this->iterators );
+ case 1:
+ return reset( $this->iterators );
- default:
- return new RecursiveIteratorIterator( new EchoMultipleIterator( $this->iterators ) );
+ default:
+ return new RecursiveIteratorIterator( new EchoMultipleIterator( $this->iterators ) );
}
}
@@ -103,23 +103,27 @@ class EchoFilteredSequentialIterator implements IteratorAggregate {
* @return callable
*/
protected function createFilter() {
- switch( count( $this->filters ) ) {
- case 0:
- return function() { return true; };
+ switch ( count( $this->filters ) ) {
+ case 0:
+ return function () {
+ return true;
+ };
- case 1:
- return reset( $this->filters );
+ case 1:
+ return reset( $this->filters );
- default:
- $filters = $this->filters;
- return function( $user ) use( $filters ) {
- foreach ( $filters as $filter ) {
- if ( !call_user_func( $filter, $user ) ) {
- return false;
+ default:
+ $filters = $this->filters;
+
+ return function ( $user ) use ( $filters ) {
+ foreach ( $filters as $filter ) {
+ if ( !call_user_func( $filter, $user ) ) {
+ return false;
+ }
}
- }
- return true;
- };
+
+ return true;
+ };
}
}
}
diff --git a/Echo/includes/iterator/MultipleIterator.php b/Echo/includes/iterator/MultipleIterator.php
index 4134326e..02d55d41 100644
--- a/Echo/includes/iterator/MultipleIterator.php
+++ b/Echo/includes/iterator/MultipleIterator.php
@@ -10,7 +10,7 @@
* * Lots less features(e.g. simple!)
*/
class EchoMultipleIterator implements RecursiveIterator {
- protected $active = array();
+ protected $active = [];
protected $children;
protected $key = 0;
@@ -44,10 +44,11 @@ class EchoMultipleIterator implements RecursiveIterator {
}
public function current() {
- $result = array();
+ $result = [];
foreach ( $this->active as $it ) {
$result[] = $it->current();
}
+
return $result;
}
diff --git a/Echo/includes/jobs/NotificationDeleteJob.php b/Echo/includes/jobs/NotificationDeleteJob.php
index ba7f36e3..2b6064ed 100644
--- a/Echo/includes/jobs/NotificationDeleteJob.php
+++ b/Echo/includes/jobs/NotificationDeleteJob.php
@@ -17,7 +17,7 @@ class EchoNotificationDeleteJob extends Job {
* UserIds to be processed
* @var int[]
*/
- protected $userIds = array();
+ protected $userIds = [];
/**
* @param Title $title
@@ -35,15 +35,16 @@ class EchoNotificationDeleteJob extends Job {
global $wgEchoMaxUpdateCount;
if ( count( $this->userIds ) > 1 ) {
// If there are multiple users, queue a single job for each one
- $jobs = array();
+ $jobs = [];
foreach ( $this->userIds as $userId ) {
- $jobs[] = new EchoNotificationDeleteJob( $this->title, array( 'userIds' => array( $userId ) ) );
+ $jobs[] = new EchoNotificationDeleteJob( $this->title, [ 'userIds' => [ $userId ] ] );
}
JobQueueGroup::singleton()->push( $jobs );
+
return true;
}
- $notifMapper = new EchoNotificationMapper();
+ $notifMapper = new EchoNotificationMapper();
$targetMapper = new EchoTargetPageMapper();
// Back-compat for older jobs which used array( $userId => $userId );
@@ -56,15 +57,11 @@ class EchoNotificationDeleteJob extends Job {
$user, $notif->getEvent()->getId()
);
if ( $res ) {
- $res = $targetMapper->deleteByUserEventOffset(
- $user, $notif->getEvent()->getId()
- );
- }
- if ( $res ) {
$notifUser = MWEchoNotifUser::newFromUser( $user );
$notifUser->resetNotificationCount( DB_MASTER );
}
}
+
return true;
}
diff --git a/Echo/includes/jobs/NotificationEmailBundleJob.php b/Echo/includes/jobs/NotificationEmailBundleJob.php
deleted file mode 100644
index fbb4ff89..00000000
--- a/Echo/includes/jobs/NotificationEmailBundleJob.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-class MWEchoNotificationEmailBundleJob extends Job {
- function __construct( $title, $params ) {
- parent::__construct( __CLASS__, $title, $params );
- // If there is already a job with the same params, this job will be ignored
- // for example, if there is a page link bundle notification job for article A
- // created by user B, any subsequent jobs with the same data will be ignored
- $this->removeDuplicates = true;
- }
-
- function run() {
- $bundle = MWEchoEmailBundler::newFromUserHash(
- User::newFromId( $this->params['user_id'] ),
- $this->params['bundle_hash']
- );
-
- if ( $bundle ) {
- $bundle->processBundleEmail();
- } else {
- throw new MWException( 'Fail to create bundle object for: user_id: ' . $this->params['user_id'] . ', bundle_hash: ' . $this->params['bundle_hash'] );
- }
-
- return true;
- }
-}
diff --git a/Echo/includes/jobs/NotificationJob.php b/Echo/includes/jobs/NotificationJob.php
index af7e1df6..a736d3d3 100644
--- a/Echo/includes/jobs/NotificationJob.php
+++ b/Echo/includes/jobs/NotificationJob.php
@@ -17,21 +17,27 @@ class EchoNotificationJob extends Job {
MWEchoDbFactory::newFromDefault()->waitFor( $masterPos );
EchoNotificationController::notify( $this->event, false );
+
return true;
}
- // back compat detects masterPos from prior job params
+ /**
+ * back compat detects masterPos from prior job params
+ *
+ * @return array
+ */
function getMasterPosition() {
- $masterPos = array(
+ $masterPos = [
'wikiDb' => false,
'echoDb' => false,
- );
+ ];
if ( !empty( $this->params['mainDbMasterPos'] ) ) {
$masterPos['wikiDb'] = $this->params['mainDbMasterPos'];
}
if ( !empty( $this->params['echoDbMasterPos'] ) ) {
$masterPos['echoDb'] = $this->params['echoDbMasterPos'];
}
+
return $masterPos;
}
}
diff --git a/Echo/includes/mapper/AbstractMapper.php b/Echo/includes/mapper/AbstractMapper.php
index a69aa105..d9603e0d 100644
--- a/Echo/includes/mapper/AbstractMapper.php
+++ b/Echo/includes/mapper/AbstractMapper.php
@@ -18,7 +18,7 @@ abstract class EchoAbstractMapper {
protected $listeners;
/**
- * @param MWEchoDbFactory|null
+ * @param MWEchoDbFactory|null $dbFactory
*/
public function __construct( MWEchoDbFactory $dbFactory = null ) {
if ( $dbFactory === null ) {
@@ -33,13 +33,14 @@ abstract class EchoAbstractMapper {
* @param string $method Method name
* @param string $key Identification of the callable
* @param callable $callable
+ * @throws MWException
*/
public function attachListener( $method, $key, $callable ) {
if ( !method_exists( $this, $method ) ) {
throw new MWException( $method . ' does not exist in ' . get_class( $this ) );
}
if ( !isset( $this->listeners[$method] ) ) {
- $this->listeners[$method] = array();
+ $this->listeners[$method] = [];
}
$this->listeners[$method][$key] = $callable;
@@ -61,6 +62,7 @@ abstract class EchoAbstractMapper {
* Get the listener for a method
*
* @return array
+ * @throws MWException
*/
public function getMethodListeners( $method ) {
if ( !method_exists( $this, $method ) ) {
@@ -69,7 +71,7 @@ abstract class EchoAbstractMapper {
if ( isset( $this->listeners[$method] ) ) {
return $this->listeners[$method];
} else {
- return array();
+ return [];
}
}
diff --git a/Echo/includes/mapper/EventMapper.php b/Echo/includes/mapper/EventMapper.php
index e60999a1..e5c3bac7 100644
--- a/Echo/includes/mapper/EventMapper.php
+++ b/Echo/includes/mapper/EventMapper.php
@@ -9,25 +9,24 @@ class EchoEventMapper extends EchoAbstractMapper {
/**
* Insert an event record
*
- * @param EchoEvent
+ * @param EchoEvent $event
* @return int|bool
*/
public function insert( EchoEvent $event ) {
$dbw = $this->dbFactory->getEchoDb( DB_MASTER );
- $id = $dbw->nextSequenceValue( 'echo_event_id' );
-
$row = $event->toDbArray();
- if ( $id ) {
- $row['event_id'] = $id;
- }
$res = $dbw->insert( 'echo_event', $row, __METHOD__ );
if ( $res ) {
- if ( !$id ) {
- $id = $dbw->insertId();
+ $id = $dbw->insertId();
+
+ $listeners = $this->getMethodListeners( __FUNCTION__ );
+ foreach ( $listeners as $listener ) {
+ $dbw->onTransactionIdle( $listener );
}
+
return $id;
} else {
return false;
@@ -37,17 +36,18 @@ class EchoEventMapper extends EchoAbstractMapper {
/**
* Create an EchoEvent by id
*
- * @param int
- * @param boolean
- * @return EchoEvent
+ * @param int $id
+ * @param bool $fromMaster
+ * @return EchoEvent|bool false if it wouldn't load/unserialize
* @throws MWException
*/
public function fetchById( $id, $fromMaster = false ) {
$db = $fromMaster ? $this->dbFactory->getEchoDb( DB_MASTER ) : $this->dbFactory->getEchoDb( DB_SLAVE );
- $row = $db->selectRow( 'echo_event', '*', array( 'event_id' => $id ), __METHOD__ );
+ $row = $db->selectRow( 'echo_event', '*', [ 'event_id' => $id ], __METHOD__ );
- if ( !$row && !$fromMaster ) {
+ // If the row was not found, fall back on the master if it makes sense to do so
+ if ( !$row && !$fromMaster && $this->dbFactory->canRetryMaster() ) {
return $this->fetchById( $id, true );
} elseif ( !$row ) {
throw new MWException( "No EchoEvent found with ID: $id" );
@@ -57,64 +57,109 @@ class EchoEventMapper extends EchoAbstractMapper {
}
/**
- * Get a list of echo events identified by user and bundle hash
- *
- * @param $user User
- * @param $bundleHash string the bundle hash
- * @param $type string distribution type
- * @param $order string 'ASC'/'DESC'
- * @param $limit int
- * @return EchoEvent[]|bool
+ * @param int[] $eventIds
+ * @param bool $deleted
+ * @return bool|ResultWrapper
*/
- public function fetchByUserBundleHash( User $user, $bundleHash, $type = 'web', $order = 'DESC', $limit = 250 ) {
- $dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
+ public function toggleDeleted( $eventIds, $deleted ) {
+ $dbw = $this->dbFactory->getEchoDb( DB_MASTER );
- // We only display 99+ if the number is over 100, we can do limit 250, this should
- // be sufficient to return 99 distinct group iterators, avoid select count( distinct )
- // for the following reason:
- // 1. it will not scale for large volume data
- // 2. notification may have random grouping iterator
- // 3. agent may be anonymous, can't do distinct over two columns: event_agent_id and event_agent_ip
- if ( $type == 'web' ) {
- $res = $dbr->select(
- array( 'echo_notification', 'echo_event' ),
- array( 'event_agent_id', 'event_agent_ip', 'event_extra',
- 'event_id', 'event_page_id', 'event_type', 'event_variant',
- 'notification_timestamp' ),
- array(
- 'notification_event=event_id',
- 'notification_user' => $user->getId(),
- 'notification_bundle_base' => 0,
- 'notification_bundle_display_hash' => $bundleHash
- ),
- __METHOD__,
- array( 'ORDER BY' => 'notification_timestamp ' . $order, 'LIMIT' => $limit )
- );
- // this would be email for now
- } else {
- $res = $dbr->select(
- array( 'echo_email_batch', 'echo_event' ),
- array( 'event_agent_id', 'event_agent_ip', 'event_extra',
- 'event_id', 'event_page_id', 'event_type', 'event_variant' ),
- array(
- 'eeb_event_id=event_id',
- 'eeb_user_id' => $user->getId(),
- 'eeb_event_hash' => $bundleHash
- ),
- __METHOD__,
- array( 'ORDER BY' => 'eeb_event_id ' . $order, 'LIMIT' => $limit )
- );
- }
+ $selectDeleted = $deleted ? 0 : 1;
+ $setDeleted = $deleted ? 1 : 0;
+ $res = $dbw->update(
+ 'echo_event',
+ [
+ 'event_deleted' => $setDeleted,
+ ],
+ [
+ 'event_deleted' => $selectDeleted,
+ 'event_id' => $eventIds,
+ ],
+ __METHOD__
+ );
+ return $res;
+ }
+
+ /**
+ * Fetch events associated with a page
+ *
+ * @param int $pageId
+ * @return EchoEvent[] Events
+ */
+ public function fetchByPage( $pageId ) {
+ $events = [];
+
+ $dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
+ $res = $dbr->select(
+ [ 'echo_event', 'echo_target_page' ],
+ [ '*' ],
+ [
+ 'etp_page' => $pageId
+ ],
+ __METHOD__,
+ [ 'GROUP BY' => 'etp_event' ],
+ [ 'echo_target_page' => [ 'INNER JOIN', 'event_id=etp_event' ] ]
+ );
if ( $res ) {
- $data = array();
foreach ( $res as $row ) {
- $data[] = EchoEvent::newFromRow( $row );
+ $events[] = EchoEvent::newFromRow( $row );
}
- return $data;
- } else {
- return false;
}
+
+ return $events;
+ }
+
+ /**
+ * Fetch event IDs associated with a page
+ *
+ * @param int $pageId
+ * @return int[] Event IDs
+ */
+ public function fetchIdsByPage( $pageId ) {
+ $events = $this->fetchByPage( $pageId );
+ $eventIds = array_map(
+ function ( EchoEvent $event ) {
+ return $event->getId();
+ },
+ $events
+ );
+ return $eventIds;
+ }
+
+ /**
+ * Fetch events unread by a user and associated with a page
+ *
+ * @param User $user
+ * @param int $pageId
+ * @return EchoEvent[]
+ */
+ public function fetchUnreadByUserAndPage( User $user, $pageId ) {
+ $dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
+
+ $res = $dbr->select(
+ [ 'echo_event', 'echo_notification', 'echo_target_page' ],
+ '*',
+ [
+ 'event_deleted' => 0,
+ 'notification_user' => $user->getId(),
+ 'notification_read_timestamp' => null,
+ 'etp_page' => $pageId,
+ ],
+ __METHOD__,
+ null,
+ [
+ 'echo_target_page' => [ 'INNER JOIN', 'etp_event=event_id' ],
+ 'echo_notification' => [ 'INNER JOIN', [ 'notification_event=event_id' ] ],
+ ]
+ );
+
+ $data = [];
+ foreach ( $res as $row ) {
+ $data[] = EchoEvent::newFromRow( $row );
+ }
+
+ return $data;
}
}
diff --git a/Echo/includes/mapper/NotificationMapper.php b/Echo/includes/mapper/NotificationMapper.php
index c43c2963..6ec00a9a 100644
--- a/Echo/includes/mapper/NotificationMapper.php
+++ b/Echo/includes/mapper/NotificationMapper.php
@@ -6,22 +6,6 @@
class EchoNotificationMapper extends EchoAbstractMapper {
/**
- * @var EchoTargetPageMapper
- */
- protected $targetPageMapper;
-
- public function __construct(
- MWEchoDbFactory $dbFactory = null,
- EchoTargetPageMapper $targetPageMapper = null
- ) {
- parent::__construct( $dbFactory );
- if ( $targetPageMapper === null ) {
- $targetPageMapper = new EchoTargetPageMapper( $this->dbFactory );
- }
- $this->targetPageMapper = $targetPageMapper;
- }
-
- /**
* Insert a notification record
* @param EchoNotification
* @return null
@@ -29,39 +13,41 @@ class EchoNotificationMapper extends EchoAbstractMapper {
public function insert( EchoNotification $notification ) {
$dbw = $this->dbFactory->getEchoDb( DB_MASTER );
- $fname = __METHOD__;
- $row = $notification->toDbArray();
$listeners = $this->getMethodListeners( __FUNCTION__ );
- $dbw->onTransactionIdle( function() use ( $dbw, $row, $fname, $listeners ) {
- $dbw->startAtomic( $fname );
- // reset the bundle base if this notification has a display hash
- // the result of this operation is that all previous notifications
- // with the same display hash are set to non-base because new record
- // is becoming the bundle base
- if ( $row['notification_bundle_display_hash'] ) {
- $dbw->update(
- 'echo_notification',
- array( 'notification_bundle_base' => 0 ),
- array(
- 'notification_user' => $row['notification_user'],
- 'notification_bundle_display_hash' => $row['notification_bundle_display_hash'],
- 'notification_bundle_base' => 1
- ),
- $fname
- );
- }
-
- $row['notification_timestamp'] = $dbw->timestamp( $row['notification_timestamp'] );
- $res = $dbw->insert( 'echo_notification', $row, $fname );
- $dbw->endAtomic( $fname );
+ $row = $notification->toDbArray();
+ DeferredUpdates::addUpdate( new AtomicSectionUpdate(
+ $dbw,
+ __METHOD__,
+ function ( IDatabase $dbw, $fname ) use ( $row, $listeners ) {
+ // Reset the bundle base if this notification has a display hash
+ // the result of this operation is that all previous notifications
+ // with the same display hash are set to non-base because new record
+ // is becoming the bundle base
+ if ( $row['notification_bundle_display_hash'] ) {
+ $dbw->update(
+ 'echo_notification',
+ [ 'notification_bundle_base' => 0 ],
+ [
+ 'notification_user' => $row['notification_user'],
+ 'notification_bundle_display_hash' =>
+ $row['notification_bundle_display_hash'],
+ 'notification_bundle_base' => 1
+ ],
+ $fname
+ );
+ }
- if ( $res ) {
- foreach ( $listeners as $listener ) {
- call_user_func( $listener );
+ $row['notification_timestamp'] =
+ $dbw->timestamp( $row['notification_timestamp'] );
+ $res = $dbw->insert( 'echo_notification', $row, $fname );
+ if ( $res ) {
+ foreach ( $listeners as $listener ) {
+ $dbw->onTransactionIdle( $listener );
+ }
}
}
- } );
+ ) );
}
/**
@@ -71,10 +57,10 @@ class EchoNotificationMapper extends EchoAbstractMapper {
* @return int[]
*/
protected function extractQueryOffset( $continue ) {
- $offset = array (
+ $offset = [
'timestamp' => 0,
'offset' => 0,
- );
+ ];
if ( $continue ) {
$values = explode( '|', $continue, 3 );
if ( count( $values ) !== 2 ) {
@@ -95,42 +81,48 @@ class EchoNotificationMapper extends EchoAbstractMapper {
* which is done via a deleteJob
* @param User $user
* @param int $limit
+ * @param string $continue Used for offset
* @param string[] $eventTypes
- * @param int $dbSource Use master or slave database to pull count
+ * @param Title[] $titles If set, only return notifications for these pages.
+ * To find notifications not associated with any page, add null as an element to this array.
+ * @param int $dbSource Use master or slave database
* @return EchoNotification[]
*/
- public function fetchUnreadByUser( User $user, $limit, array $eventTypes = array(), $dbSource = DB_SLAVE ) {
- $data = array();
-
- if ( !$eventTypes ) {
- return $data;
+ public function fetchUnreadByUser( User $user, $limit, $continue, array $eventTypes = [], array $titles = null, $dbSource = DB_SLAVE ) {
+ $conds['notification_read_timestamp'] = null;
+ if ( $titles ) {
+ $conds['event_page_id'] = $this->getIdsForTitles( $titles );
+ if ( !$conds['event_page_id'] ) {
+ return [];
+ }
}
+ return $this->fetchByUserInternal( $user, $limit, $continue, $eventTypes, $conds, $dbSource );
+ }
- $dbr = $this->dbFactory->getEchoDb( $dbSource );
- $res = $dbr->select(
- array( 'echo_notification', 'echo_event' ),
- '*',
- array(
- 'notification_user' => $user->getID(),
- 'event_type' => $eventTypes,
- 'notification_bundle_base' => 1,
- 'notification_read_timestamp' => NULL
- ),
- __METHOD__,
- array(
- 'LIMIT' => $limit,
- 'ORDER BY' => 'notification_timestamp DESC'
- ),
- array(
- 'echo_event' => array( 'LEFT JOIN', 'notification_event=event_id' ),
- )
- );
- if ( $res ) {
- foreach ( $res as $row ) {
- $data[$row->event_id] = EchoNotification::newFromRow( $row );
+ /**
+ * Get read notifications by user in the amount specified by limit order by
+ * notification timestamp in descending order. We have an index to retrieve
+ * unread notifications but it's not optimized for ordering by timestamp. The
+ * descending order is only allowed if we keep the notification in low volume,
+ * which is done via a deleteJob
+ * @param User $user
+ * @param int $limit
+ * @param string $continue Used for offset
+ * @param string[] $eventTypes
+ * @param Title[] $titles If set, only return notifications for these pages.
+ * To find notifications not associated with any page, add null as an element to this array.
+ * @param int $dbSource Use master or slave database
+ * @return EchoNotification[]
+ */
+ public function fetchReadByUser( User $user, $limit, $continue, array $eventTypes = [], array $titles = null, $dbSource = DB_SLAVE ) {
+ $conds = [ 'notification_read_timestamp IS NOT NULL' ];
+ if ( $titles ) {
+ $conds['event_page_id'] = $this->getIdsForTitles( $titles );
+ if ( !$conds['event_page_id'] ) {
+ return [];
}
}
- return $data;
+ return $this->fetchByUserInternal( $user, $limit, $continue, $eventTypes, $conds, $dbSource );
}
/**
@@ -141,32 +133,66 @@ class EchoNotificationMapper extends EchoAbstractMapper {
* @param string $continue Used for offset
* @param array $eventTypes Event types to load
* @param array $excludeEventIds Event id's to exclude.
+ * @param Title[] $titles If set, only return notifications for these pages.
+ * To find notifications not associated with any page, add null as an element to this array.
* @return EchoNotification[]
*/
- public function fetchByUser( User $user, $limit, $continue, array $eventTypes = array(), array $excludeEventIds = array() ) {
+ public function fetchByUser( User $user, $limit, $continue, array $eventTypes = [], array $excludeEventIds = [], array $titles = null ) {
$dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
+ $conds = [];
+ if ( $excludeEventIds ) {
+ $conds[] = 'event_id NOT IN ( ' . $dbr->makeList( $excludeEventIds ) . ' ) ';
+ }
+ if ( $titles ) {
+ $conds['event_page_id'] = $this->getIdsForTitles( $titles );
+ if ( !$conds['event_page_id'] ) {
+ return [];
+ }
+ }
+
+ return $this->fetchByUserInternal( $user, $limit, $continue, $eventTypes, $conds );
+ }
+
+ protected function getIdsForTitles( array $titles ) {
+ $ids = [];
+ foreach ( $titles as $title ) {
+ if ( $title === null ) {
+ $ids[] = null;
+ } elseif ( $title->exists() ) {
+ $ids[] = $title->getArticleId();
+ }
+ }
+ return $ids;
+ }
+
+ /**
+ * @param User $user the user to get notifications for
+ * @param int $limit The maximum number of notifications to return
+ * @param string $continue Used for offset
+ * @param array $eventTypes Event types to load
+ * @param array $conds Additional query conditions.
+ * @param int $dbSource Use master or slave database
+ * @return EchoNotification[]
+ */
+ protected function fetchByUserInternal( User $user, $limit, $continue, array $eventTypes = [], array $conds = [], $dbSource = DB_SLAVE ) {
+ $dbr = $this->dbFactory->getEchoDb( $dbSource );
+
if ( !$eventTypes ) {
- return array();
+ return [];
}
// There is a problem with querying by event type, if a user has only one or none
- // flow notification and huge amount other notications, the lookup of only flow
+ // flow notification and huge amount other notifications, the lookup of only flow
// notification will result in a slow query. Luckily users won't have that many
// notifications. We should have some cron job to remove old notifications so
// the notification volume is in a reasonable amount for such case. The other option
// is to denormalize notification table with event_type and lookup index.
- //
- // Look for notifications with base = 1
- $conds = array(
+ $conds = [
'notification_user' => $user->getID(),
'event_type' => $eventTypes,
- 'notification_bundle_base' => 1
- );
-
- if ( $excludeEventIds ) {
- $conds[] = 'event_id NOT IN ( ' . $dbr->makeList( $excludeEventIds ) . ' ) ';
- }
+ 'event_deleted' => 0,
+ ] + $conds;
$offset = $this->extractQueryOffset( $continue );
@@ -178,77 +204,68 @@ class EchoNotificationMapper extends EchoAbstractMapper {
}
$res = $dbr->select(
- array( 'echo_notification', 'echo_event', 'echo_target_page' ),
+ [ 'echo_notification', 'echo_event' ],
'*',
$conds,
__METHOD__,
- array(
+ [
'ORDER BY' => 'notification_timestamp DESC, notification_event DESC',
'LIMIT' => $limit,
- ),
- array(
- 'echo_event' => array( 'LEFT JOIN', 'notification_event=event_id' ),
- 'echo_target_page' => array( 'LEFT JOIN', array( 'notification_event=etp_event', 'notification_user=etp_user' ) ),
- )
+ ],
+ [
+ 'echo_event' => [ 'LEFT JOIN', 'notification_event=event_id' ],
+ ]
);
-
// query failure of some sort
if ( !$res ) {
- return array();
+ return [];
}
- $events = array();
+ $allNotifications = [];
foreach ( $res as $row ) {
- $events[$row->event_id] = $row;
- }
-
- // query returned no events
- if ( !$events ) {
- return array();
- }
-
- $targetPages = $this->targetPageMapper->fetchByUserPageId( $user, array_keys( $events ) );
-
- $data = array();
- foreach ( $events as $eventId => $row ) {
try {
- if ( isset( $targetPages[$row->event_id] ) ) {
- $targets = $targetPages[$row->event_id];
- } else {
- $targets = null;
+ $notification = EchoNotification::newFromRow( $row );
+ if ( $notification ) {
+ $allNotifications[] = $notification;
}
- $data[$row->event_id] = EchoNotification::newFromRow( $row, $targets );
} catch ( Exception $e ) {
$id = isset( $row->event_id ) ? $row->event_id : 'unknown event';
wfDebugLog( 'Echo', __METHOD__ . ": Failed initializing event: $id" );
MWExceptionHandler::logException( $e );
}
}
+
+ $data = [];
+ /** @var EchoNotification $notification */
+ foreach ( $allNotifications as $notification ) {
+ $data[ $notification->getEvent()->getId() ] = $notification;
+ }
+
return $data;
}
/**
* Get the last notification in a set of bundle-able notifications by a bundle hash
- * @param User
- * @param string The hash used to identify a set of bundle-able notifications
+ * @param User $user
+ * @param string $bundleHash The hash used to identify a set of bundle-able notifications
* @return EchoNotification|bool
*/
public function fetchNewestByUserBundleHash( User $user, $bundleHash ) {
$dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
$row = $dbr->selectRow(
- array( 'echo_notification', 'echo_event' ),
- array( '*' ),
- array(
+ [ 'echo_notification', 'echo_event' ],
+ [ '*' ],
+ [
'notification_user' => $user->getId(),
'notification_bundle_hash' => $bundleHash
- ),
+ ],
__METHOD__,
- array( 'ORDER BY' => 'notification_timestamp DESC', 'LIMIT' => 1 ),
- array(
- 'echo_event' => array( 'LEFT JOIN', 'notification_event=event_id' ),
- )
+ [ 'ORDER BY' => 'notification_timestamp DESC', 'LIMIT' => 1 ],
+ [
+ 'echo_event' => [ 'LEFT JOIN', 'notification_event=event_id' ],
+ ]
);
if ( $row ) {
return EchoNotification::newFromRow( $row );
@@ -258,6 +275,41 @@ class EchoNotificationMapper extends EchoAbstractMapper {
}
/**
+ * Fetch EchoNotifications by user and event IDs.
+ *
+ * @param User $user
+ * @param int[] $eventIds
+ * @return EchoNotification[]|bool
+ */
+ public function fetchByUserEvents( User $user, $eventIds ) {
+ $dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
+
+ $result = $dbr->select(
+ [ 'echo_notification', 'echo_event' ],
+ '*',
+ [
+ 'notification_user' => $user->getId(),
+ 'notification_event' => $eventIds
+ ],
+ __METHOD__,
+ [],
+ [
+ 'echo_event' => [ 'INNER JOIN', 'notification_event=event_id' ],
+ ]
+ );
+
+ if ( $result ) {
+ $notifications = [];
+ foreach ( $result as $row ) {
+ $notifications[] = EchoNotification::newFromRow( $row );
+ }
+ return $notifications;
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Fetch a notification by user in the specified offset. The caller should
* know that passing a big number for offset is NOT going to work
* @param User $user
@@ -267,21 +319,21 @@ class EchoNotificationMapper extends EchoAbstractMapper {
public function fetchByUserOffset( User $user, $offset ) {
$dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
$row = $dbr->selectRow(
- array( 'echo_notification', 'echo_event' ),
- array( '*' ),
- array(
+ [ 'echo_notification', 'echo_event' ],
+ [ '*' ],
+ [
'notification_user' => $user->getId(),
- 'notification_bundle_base' => 1
- ),
+ 'event_deleted' => 0,
+ ],
__METHOD__,
- array(
+ [
'ORDER BY' => 'notification_timestamp DESC, notification_event DESC',
'OFFSET' => $offset,
'LIMIT' => 1
- ),
- array(
- 'echo_event' => array( 'LEFT JOIN', 'notification_event=event_id' ),
- )
+ ],
+ [
+ 'echo_event' => [ 'LEFT JOIN', 'notification_event=event_id' ],
+ ]
);
if ( $row ) {
@@ -295,19 +347,49 @@ class EchoNotificationMapper extends EchoAbstractMapper {
* Batch delete notifications by user and eventId offset
* @param User $user
* @param int $eventId
- * @return boolean
+ * @return bool
*/
public function deleteByUserEventOffset( User $user, $eventId ) {
$dbw = $this->dbFactory->getEchoDb( DB_MASTER );
$res = $dbw->delete(
'echo_notification',
- array(
+ [
'notification_user' => $user->getId(),
'notification_event < ' . (int)$eventId
- ),
+ ],
__METHOD__
);
+
return $res;
}
+ /**
+ * Fetch ids of users that have notifications for certain events
+ *
+ * @param int[] $eventIds
+ * @return int[]|false
+ */
+ public function fetchUsersWithNotificationsForEvents( $eventIds ) {
+ $dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
+
+ $res = $dbr->select(
+ [ 'echo_notification' ],
+ [ 'userId' => 'DISTINCT notification_user' ],
+ [
+ 'notification_event' => $eventIds
+ ],
+ __METHOD__
+ );
+
+ if ( $res ) {
+ $userIds = [];
+ foreach ( $res as $row ) {
+ $userIds[] = $row->userId;
+ }
+ return $userIds;
+ } else {
+ return false;
+ }
+ }
+
}
diff --git a/Echo/includes/mapper/TargetPageMapper.php b/Echo/includes/mapper/TargetPageMapper.php
index b4a2108d..33dd7bc5 100644
--- a/Echo/includes/mapper/TargetPageMapper.php
+++ b/Echo/includes/mapper/TargetPageMapper.php
@@ -9,49 +9,16 @@ class EchoTargetPageMapper extends EchoAbstractMapper {
* List of db fields used to construct an EchoTargetPage model
* @var string[]
*/
- protected static $fields = array(
- 'etp_user',
+ protected static $fields = [
'etp_page',
'etp_event'
- );
-
- /**
- * Fetch EchoTargetPage instances by user & page_id. The resulting
- * array is indexed by the event id. Each entry contains an array
- * of EchoTargetPage instances.
- *
- * @param User $user
- * @param int|int[] $pageId One or more page ids to fetch target pages of
- * @return EchoTargetPage[][]|boolean
- */
- public function fetchByUserPageId( User $user, $pageId ) {
- $dbr = $this->dbFactory->getEchoDb( DB_SLAVE );
-
- $res = $dbr->select(
- array( 'echo_target_page' ),
- self::$fields,
- array(
- 'etp_user' => $user->getId(),
- 'etp_page' => $pageId
- ),
- __METHOD__
- );
- if ( $res ) {
- $targetPages = array();
- foreach ( $res as $row ) {
- $targetPages[$row->etp_event][] = EchoTargetPage::newFromRow( $row );
- }
- return $targetPages;
- } else {
- return false;
- }
- }
+ ];
/**
* Insert an EchoTargetPage instance into the database
*
* @param EchoTargetPage $targetPage
- * @return boolean
+ * @return bool
*/
public function insert( EchoTargetPage $targetPage ) {
$dbw = $this->dbFactory->getEchoDb( DB_MASTER );
@@ -62,91 +29,4 @@ class EchoTargetPageMapper extends EchoAbstractMapper {
return $res;
}
-
- /**
- * Delete an EchoTargetPage instance from the database
- *
- * @param EchoTargetPage
- * @return boolean
- */
- public function delete( EchoTargetPage $targetPage ) {
- $dbw = $this->dbFactory->getEchoDb( DB_MASTER );
-
- $res = $dbw->delete(
- 'echo_target_page',
- array(
- 'etp_user' => $targetPage->getUser()->getId(),
- 'etp_page' => $targetPage->getPageId(),
- 'etp_event' => $targetPage->getEventId()
- ),
- __METHOD__
- );
- return $res;
- }
-
- /**
- * Delete multiple EchoTargetPage records by user & set of event_id
- *
- * @param User $user
- * @param int[] $eventIds
- * @return boolean
- */
- public function deleteByUserEvents( User $user, array $eventIds ) {
- if ( !$eventIds ) {
- return true;
- }
-
- $dbw = $this->dbFactory->getEchoDb( DB_MASTER );
-
- $res = $dbw->delete(
- 'echo_target_page',
- array(
- 'etp_user' => $user->getId(),
- 'etp_event' => $eventIds
- ),
- __METHOD__
- );
- return $res;
- }
-
- /**
- * Delete multiple EchoTargetPage records by user & event_id offset
- *
- * @param User $user
- * @param int $eventId
- * @return boolean
- */
- public function deleteByUserEventOffset( User $user, $eventId ) {
- $dbw = $this->dbFactory->getEchoDb( DB_MASTER );
-
- $res = $dbw->delete(
- 'echo_target_page',
- array(
- 'etp_user' => $user->getId(),
- 'etp_event < ' . (int)$eventId
- ),
- __METHOD__
- );
- return $res;
- }
-
- /**
- * Delete multiple EchoTargetPage records by user
- *
- * @param User $user
- * @return boolean
- */
- public function deleteByUser( User $user ) {
- $dbw = $this->dbFactory->getEchoDb( DB_MASTER );
-
- $res = $dbw->delete(
- 'echo_target_page',
- array(
- 'etp_user' => $user->getId()
- ),
- __METHOD__
- );
- return $res;
- }
-
}
diff --git a/Echo/includes/model/Event.php b/Echo/includes/model/Event.php
index 7d4d0cd6..ecc0941a 100644
--- a/Echo/includes/model/Event.php
+++ b/Echo/includes/model/Event.php
@@ -1,10 +1,12 @@
<?php
+use MediaWiki\Logger\LoggerFactory;
+
/**
* Immutable class to represent an event.
* In Echo nomenclature, an event is a single occurrence.
*/
-class EchoEvent extends EchoAbstractEntity{
+class EchoEvent extends EchoAbstractEntity implements Bundleable {
protected $type = null;
protected $id = null;
@@ -29,7 +31,7 @@ class EchoEvent extends EchoAbstractEntity{
*/
protected $revision = null;
- protected $extra = array();
+ protected $extra = [];
/**
* Notification timestamp
@@ -45,20 +47,36 @@ class EchoEvent extends EchoAbstractEntity{
protected $bundleHash;
/**
+ * Other events bundled with this one
+ *
+ * @var EchoEvent[]
+ */
+ protected $bundledEvents;
+
+ /**
+ * Deletion flag
+ *
+ * @var int
+ */
+ protected $deleted = 0;
+
+ /**
* You should not call the constructor.
* Instead use one of the factory functions:
* EchoEvent::create To create a new event
* EchoEvent::newFromRow To create an event object from a row object
* EchoEvent::newFromID To create an event object from the database given its ID
*/
- protected function __construct() {}
+ protected function __construct() {
+ }
## Save the id and timestamp
function __sleep() {
if ( !$this->id ) {
throw new MWException( "Unable to serialize an uninitialized EchoEvent" );
}
- return array( 'id', 'timestamp' );
+
+ return [ 'id', 'timestamp' ];
}
function __wakeup() {
@@ -71,7 +89,7 @@ class EchoEvent extends EchoAbstractEntity{
/**
* Creates an EchoEvent object
- * @param $info array Named arguments:
+ * @param array $info Named arguments:
* type (required): The event type;
* variant: A variant of the type;
* agent: The user who caused the event;
@@ -79,18 +97,20 @@ class EchoEvent extends EchoAbstractEntity{
* extra: Event-specific extra information (e.g. post content)
*
* @throws MWException
- * @return EchoEvent|bool false if aborted via hook
+ * @return EchoEvent|bool false if aborted via hook or Echo DB is read-only
*/
- public static function create( $info = array() ) {
+ public static function create( $info = [] ) {
global $wgEchoNotifications;
// Do not create event and notifications if write access is locked
- if ( wfReadOnly() ) {
- throw new ReadOnlyError();
+ if ( wfReadOnly()
+ || MWEchoDbFactory::newFromDefault()->getEchoDb( DB_MASTER )->isReadOnly()
+ ) {
+ return false;
}
$obj = new EchoEvent;
- static $validFields = array( 'type', 'variant', 'agent', 'title', 'extra' );
+ static $validFields = [ 'type', 'variant', 'agent', 'title', 'extra' ];
if ( empty( $info['type'] ) ) {
throw new MWException( "'type' parameter is mandatory" );
@@ -119,6 +139,7 @@ class EchoEvent extends EchoAbstractEntity{
// event_extra.
if ( strlen( $obj->serializeExtra() ) > 50000 ) {
wfDebugLog( __CLASS__, __FUNCTION__ . ': event extra data is too huge for ' . $info['type'] );
+
return false;
}
@@ -130,24 +151,24 @@ class EchoEvent extends EchoAbstractEntity{
}
if ( $obj->agent && !
- ( $obj->agent instanceof User ||
- $obj->agent instanceof StubObject )
+ ( $obj->agent instanceof User ||
+ $obj->agent instanceof StubObject )
) {
throw new MWException( "Invalid user parameter" );
}
- if ( !Hooks::run( 'BeforeEchoEventInsert', array( $obj ) ) ) {
+ if ( !Hooks::run( 'BeforeEchoEventInsert', [ $obj ] ) ) {
return false;
}
- //@Todo - Database insert logic should not be inside the model
+ // @Todo - Database insert logic should not be inside the model
$obj->insert();
- Hooks::run( 'EchoEventInsertComplete', array( $obj ) );
+ Hooks::run( 'EchoEventInsertComplete', [ $obj ] );
global $wgEchoUseJobQueue;
- EchoNotificationController::notify( $obj, $wgEchoUseJobQueue );
+ EchoNotificationController::notify( $obj, $wgEchoUseJobQueue );
return $obj;
}
@@ -157,11 +178,12 @@ class EchoEvent extends EchoAbstractEntity{
* @return array
*/
public function toDbArray() {
- $data = array (
+ $data = [
'event_type' => $this->type,
'event_variant' => $this->variant,
+ 'event_deleted' => $this->deleted,
'event_extra' => $this->serializeExtra()
- );
+ ];
if ( $this->id ) {
$data['event_id'] = $this->id;
}
@@ -183,6 +205,7 @@ class EchoEvent extends EchoAbstractEntity{
$data['event_page_id'] = $pageId;
}
}
+
return $data;
}
@@ -205,12 +228,51 @@ class EchoEvent extends EchoAbstractEntity{
protected function insert() {
$eventMapper = new EchoEventMapper();
$this->id = $eventMapper->insert( $this );
+
+ $targetPages = self::resolveTargetPages( $this->getExtraParam( 'target-page' ) );
+ if ( $targetPages ) {
+ $targetMapper = new EchoTargetPageMapper();
+ foreach ( $targetPages as $title ) {
+ $targetPage = EchoTargetPage::create( $title, $this );
+ if ( $targetPage ) {
+ $targetMapper->insert( $targetPage );
+ }
+ }
+ }
+ }
+
+ /**
+ * @param int[]|int|false $targetPageIds
+ * @return Title[]
+ */
+ protected static function resolveTargetPages( $targetPageIds ) {
+ if ( !$targetPageIds ) {
+ return [];
+ }
+ if ( !is_array( $targetPageIds ) ) {
+ $targetPageIds = [ $targetPageIds ];
+ }
+ $result = [];
+ foreach ( $targetPageIds as $targetPageId ) {
+ // Make sure the target-page id is a valid id
+ $title = Title::newFromID( $targetPageId );
+ // Try master if there is no match
+ if ( !$title ) {
+ $title = Title::newFromID( $targetPageId, Title::GAID_FOR_UPDATE );
+ }
+ if ( $title ) {
+ $result[] = $title;
+ }
+ }
+
+ return $result;
}
/**
* Loads data from the provided $row into this object.
*
- * @param $row stdClass row object from echo_event
+ * @param stdClass $row row object from echo_event
+ * @return bool Whether loading was successful
*/
public function loadFromRow( $row ) {
$this->id = $row->event_id;
@@ -226,8 +288,20 @@ class EchoEvent extends EchoAbstractEntity{
}
$this->variant = $row->event_variant;
- $this->extra = $row->event_extra ? unserialize( $row->event_extra ) : array();
+ try {
+ $this->extra = $row->event_extra ? unserialize( $row->event_extra ) : [];
+ } catch ( Exception $e ) {
+ // T73489: unserializing can fail for old notifications
+ LoggerFactory::getInstance( 'Echo' )->warning(
+ 'Failed to unserialize event {id}',
+ [
+ 'id' => $row->event_id
+ ]
+ );
+ return false;
+ }
$this->pageId = $row->event_page_id;
+ $this->deleted = $row->event_deleted;
if ( $row->event_agent_id ) {
$this->agent = User::newFromID( $row->event_agent_id );
@@ -253,16 +327,22 @@ class EchoEvent extends EchoAbstractEntity{
$revisionCache = EchoRevisionLocalCache::create();
$revisionCache->add( $this->extra['revid'] );
}
+
+ return true;
}
/**
* Loads data from the database into this object, given the event ID.
- * @param $id int Event ID
- * @param $fromMaster bool
+ * @param int $id Event ID
+ * @param bool $fromMaster
+ * @return bool Whether it loaded successfully
*/
public function loadFromID( $id, $fromMaster = false ) {
$eventMapper = new EchoEventMapper();
$event = $eventMapper->fetchById( $id, $fromMaster );
+ if ( !$event ) {
+ return false;
+ }
// Copy over the attribute
$this->id = $event->id;
@@ -272,34 +352,39 @@ class EchoEvent extends EchoAbstractEntity{
$this->pageId = $event->pageId;
$this->agent = $event->agent;
$this->title = $event->title;
+ $this->deleted = $event->deleted;
// Don't overwrite timestamp if it exists already
if ( !$this->timestamp ) {
$this->timestamp = $event->timestamp;
}
+
+ return true;
}
/**
* Creates an EchoEvent from a row object
*
- * @param $row stdClass row object from echo_event
- * @return EchoEvent object.
+ * @param stdClass $row row object from echo_event
+ * @return EchoEvent|bool
*/
public static function newFromRow( $row ) {
$obj = new EchoEvent();
- $obj->loadFromRow( $row );
- return $obj;
+ return $obj->loadFromRow( $row )
+ ? $obj
+ : false;
}
/**
* Creates an EchoEvent from the database by ID
*
- * @param $id int Event ID
- * @return EchoEvent
+ * @param int $id Event ID
+ * @return EchoEvent|bool
*/
public static function newFromID( $id ) {
$obj = new EchoEvent();
- $obj->loadFromID( $id );
- return $obj;
+ return $obj->loadFromID( $id )
+ ? $obj
+ : false;
}
/**
@@ -312,7 +397,7 @@ class EchoEvent extends EchoAbstractEntity{
} elseif ( is_null( $this->extra ) ) {
$extra = null;
} else {
- $extra = serialize( array( $this->extra ) );
+ $extra = serialize( [ $this->extra ] );
}
return $extra;
@@ -331,9 +416,9 @@ class EchoEvent extends EchoAbstractEntity{
if ( isset( $wgEchoNotificationCategories[$category]['no-dismiss'] ) ) {
$noDismiss = $wgEchoNotificationCategories[$category]['no-dismiss'];
} else {
- $noDismiss = array();
+ $noDismiss = [];
}
- if ( !in_array( $distribution, $noDismiss ) && !in_array( 'all' , $noDismiss ) ) {
+ if ( !in_array( $distribution, $noDismiss ) && !in_array( 'all', $noDismiss ) ) {
return true;
} else {
return false;
@@ -345,13 +430,13 @@ class EchoEvent extends EchoAbstractEntity{
* field of this revision, if it's marked as deleted. When no
* revision is attached always returns true.
*
- * @param $field Integer:one of Revision::DELETED_TEXT,
+ * @param int $field One of Revision::DELETED_TEXT,
* Revision::DELETED_COMMENT,
* Revision::DELETED_USER
- * @param $user User object to check, or null to use $wgUser
- * @return Boolean
+ * @param User $user User object to check
+ * @return bool
*/
- public function userCan( $field, User $user = null ) {
+ public function userCan( $field, User $user ) {
$revision = $this->getRevision();
// User is handled specially
if ( $field === Revision::DELETED_USER ) {
@@ -366,11 +451,6 @@ class EchoEvent extends EchoAbstractEntity{
return $revision->userCan( $field, $user );
} else {
// Use User::isHidden()
- if ( !$user ) {
- // @FIXME Require a user object for this function
- global $wgUser;
- $user = $wgUser;
- }
return $user->isAllowedAny( 'viewsuppressed', 'hideuser' ) || !$agent->isHidden();
}
} elseif ( $revision ) {
@@ -430,9 +510,10 @@ class EchoEvent extends EchoAbstractEntity{
}
/**
- * @return Title|null
+ * @param bool $fromMaster
+ * @return null|Title
*/
- public function getTitle() {
+ public function getTitle( $fromMaster = false ) {
if ( $this->title ) {
return $this->title;
} elseif ( $this->pageId ) {
@@ -441,13 +522,15 @@ class EchoEvent extends EchoAbstractEntity{
if ( $title ) {
return $this->title = $title;
}
- return $this->title = Title::newFromId( $this->pageId );
+
+ return $this->title = Title::newFromID( $this->pageId, $fromMaster ? Title::GAID_FOR_UPDATE : 0 );
} elseif ( isset( $this->extra['page_title'], $this->extra['page_namespace'] ) ) {
return $this->title = Title::makeTitleSafe(
$this->extra['page_namespace'],
$this->extra['page_title']
);
}
+
return null;
}
@@ -463,8 +546,10 @@ class EchoEvent extends EchoAbstractEntity{
if ( $revision ) {
return $this->revision = $revision;
}
+
return $this->revision = Revision::newFromId( $this->extra['revid'] );
}
+
return null;
}
@@ -474,6 +559,7 @@ class EchoEvent extends EchoAbstractEntity{
*/
public function getCategory() {
$attributeManager = EchoAttributeManager::newFromGlobalVars();
+
return $attributeManager->getNotificationCategory( $this->type );
}
@@ -483,18 +569,20 @@ class EchoEvent extends EchoAbstractEntity{
*/
public function getSection() {
$attributeManager = EchoAttributeManager::newFromGlobalVars();
+
return $attributeManager->getNotificationSection( $this->type );
}
/**
* Determine whether an event can use the job queue, or should be immediate
- * @return boolean
+ * @return bool
*/
public function getUseJobQueue() {
global $wgEchoNotifications;
if ( isset( $wgEchoNotifications[$this->type]['immediate'] ) ) {
return !(bool)$wgEchoNotifications[$this->type]['immediate'];
}
+
return true;
}
@@ -512,14 +600,13 @@ class EchoEvent extends EchoAbstractEntity{
public function setTitle( Title $title ) {
$this->title = $title;
- $pageId = $title->getArticleId();
+ $pageId = $title->getArticleID();
if ( $pageId ) {
$this->pageId = $pageId;
} else {
- $this->extra['page_title'] = $title->getDBKey();
+ $this->extra['page_title'] = $title->getDBkey();
$this->extra['page_namespace'] = $title->getNamespace();
}
-
}
public function setExtra( $name, $value ) {
@@ -529,30 +616,32 @@ class EchoEvent extends EchoAbstractEntity{
/**
* Get the message key of the primary or secondary link for a notification type.
*
- * @param $rank String 'primary' or 'secondary'
+ * @param String $rank 'primary' or 'secondary'
* @return String i18n message key
*/
public function getLinkMessage( $rank ) {
global $wgEchoNotifications;
$type = $this->getType();
- if ( isset( $wgEchoNotifications[$type][$rank.'-link']['message'] ) ) {
- return $wgEchoNotifications[$type][$rank.'-link']['message'];
+ if ( isset( $wgEchoNotifications[$type][$rank . '-link']['message'] ) ) {
+ return $wgEchoNotifications[$type][$rank . '-link']['message'];
}
+
return '';
}
/**
* Get the link destination of the primary or secondary link for a notification type.
*
- * @param $rank String 'primary' or 'secondary'
+ * @param String $rank 'primary' or 'secondary'
* @return String The link destination, e.g. 'agent'
*/
public function getLinkDestination( $rank ) {
global $wgEchoNotifications;
$type = $this->getType();
- if ( isset( $wgEchoNotifications[$type][$rank.'-link']['destination'] ) ) {
- return $wgEchoNotifications[$type][$rank.'-link']['destination'];
+ if ( isset( $wgEchoNotifications[$type][$rank . '-link']['destination'] ) ) {
+ return $wgEchoNotifications[$type][$rank . '-link']['destination'];
}
+
return '';
}
@@ -564,9 +653,52 @@ class EchoEvent extends EchoAbstractEntity{
}
/**
- * @param $hash string
+ * @param string $hash
*/
public function setBundleHash( $hash ) {
$this->bundleHash = $hash;
}
+
+ /**
+ * @return bool
+ */
+ public function isDeleted() {
+ return $this->deleted === 1;
+ }
+
+ public function setBundledEvents( $events ) {
+ $this->bundledEvents = $events;
+ }
+
+ public function getBundledEvents() {
+ return $this->bundledEvents;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function canBeBundled() {
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getBundlingKey() {
+ return $this->getBundleHash();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function setBundledElements( $bundleables ) {
+ $this->setBundledEvents( $bundleables );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSortingKey() {
+ return $this->getTimestamp();
+ }
}
diff --git a/Echo/includes/model/Notification.php b/Echo/includes/model/Notification.php
index c538495b..4c5f338d 100644
--- a/Echo/includes/model/Notification.php
+++ b/Echo/includes/model/Notification.php
@@ -1,6 +1,6 @@
<?php
-class EchoNotification extends EchoAbstractEntity {
+class EchoNotification extends EchoAbstractEntity implements Bundleable {
/**
* @var User
@@ -50,13 +50,19 @@ class EchoNotification extends EchoAbstractEntity {
protected $bundleDisplayHash = '';
/**
+ * @var EchoNotification[]
+ */
+ protected $bundledNotifications;
+
+ /**
* Do not use this constructor.
*/
- protected function __construct() {}
+ protected function __construct() {
+ }
/**
* Creates an EchoNotification object based on event and user
- * @param $info array The following keys are required:
+ * @param array $info The following keys are required:
* - 'event' The EchoEvent being notified about.
* - 'user' The User being notified.
* @throws MWException
@@ -64,7 +70,7 @@ class EchoNotification extends EchoAbstractEntity {
*/
public static function create( array $info ) {
$obj = new EchoNotification();
- static $validFields = array( 'event', 'user' );
+ static $validFields = [ 'event', 'user' ];
foreach ( $validFields as $field ) {
if ( isset( $info[$field] ) ) {
@@ -89,7 +95,7 @@ class EchoNotification extends EchoAbstractEntity {
$obj->timestamp = wfTimestampNow();
}
- //@Todo - Database insert logic should not be inside the model
+ // @Todo - Database insert logic should not be inside the model
$obj->insert();
return $obj;
@@ -106,13 +112,9 @@ class EchoNotification extends EchoAbstractEntity {
// Get the bundle key for this event if web bundling is enabled
$bundleKey = '';
if ( !empty( $wgEchoNotifications[$this->event->getType()]['bundle']['web'] ) ) {
- Hooks::run( 'EchoGetBundleRules', array( $this->event, &$bundleKey ) );
+ Hooks::run( 'EchoGetBundleRules', [ $this->event, &$bundleKey ] );
}
- // The list of event ids to be removed from echo_target_page,
- // this is mainly for bundled notifications when an event is
- // no longer the bundle base
- $eventIds = array();
if ( $bundleKey ) {
$hash = md5( $bundleKey );
$this->bundleHash = $hash;
@@ -123,86 +125,35 @@ class EchoNotification extends EchoAbstractEntity {
// 2. last bundle notification with the same hash was read
if ( $lastNotif && !$lastNotif->getReadTimestamp() ) {
$this->bundleDisplayHash = $lastNotif->getBundleDisplayHash();
- $lastEvent = $lastNotif->getEvent();
- if ( $lastEvent ) {
- $eventIds[] = $lastEvent->getId();
- }
} else {
$this->bundleDisplayHash = md5( $bundleKey . '-display-hash-' . wfTimestampNow() );
}
}
- // Create a target page object if specified by event
- $event = $this->event;
- $user = $this->user;
- $targetPages = self::resolveTargetPages( $event->getExtraParam( 'target-page' ) );
- if ( $targetPages ) {
- $notifMapper->attachListener( 'insert', 'add-target-page', function() use ( $event, $user, $eventIds, $targetPages ) {
- $targetMapper = new EchoTargetPageMapper();
- if ( $eventIds ) {
- $targetMapper->deleteByUserEvents( $user, $eventIds );
- }
- foreach ( $targetPages as $title ) {
- $targetPage = EchoTargetPage::create( $user, $title, $event );
- if ( $targetPage ) {
- $targetMapper->insert( $targetPage );
- }
- }
- } );
- }
-
- $notifUser = MWEchoNotifUser::newFromUser( $user );
+ $notifUser = MWEchoNotifUser::newFromUser( $this->user );
$section = $this->event->getSection();
// Add listener to refresh notification count upon insert
$notifMapper->attachListener( 'insert', 'refresh-notif-count',
- function() use ( $notifUser, $section ) {
+ function () use ( $notifUser, $section ) {
$notifUser->resetNotificationCount( DB_MASTER );
- if ( $section === EchoAttributeManager::MESSAGE && !$notifUser->hasMessages() ) {
- $notifUser->cacheHasMessages();
- }
}
);
$notifMapper->insert( $this );
- if ( $event->getType() === 'edit-user-talk' ) {
+ if ( $this->event->getCategory() === 'edit-user-talk' ) {
$notifUser->flagCacheWithNewTalkNotification();
+ $this->user->setNewtalk( true );
}
- Hooks::run( 'EchoCreateNotificationComplete', array( $this ) );
- }
-
- /**
- * @param int[]|int|false $targetPageIds
- * @return Title[]
- */
- protected static function resolveTargetPages( $targetPageIds ) {
- if ( !$targetPageIds ) {
- return array();
- }
- if ( !is_array( $targetPageIds ) ) {
- $targetPageIds = array( $targetPageIds );
- }
- $result = array();
- foreach ( $targetPageIds as $targetPageId ) {
- // Make sure the target-page id is a valid id
- $title = Title::newFromID( $targetPageId );
- // Try master if there is no match
- if ( !$title ) {
- $title = Title::newFromID( $targetPageId, Title::GAID_FOR_UPDATE );
- }
- if ( $title ) {
- $result[] = $title;
- }
- }
- return $result;
+ Hooks::run( 'EchoCreateNotificationComplete', [ $this ] );
}
/**
* Load a notification record from std class
- * @param stdClass
- * @param EchoTargetPage[]|null An array of EchoTargetPage instances, or null if not loaded.
- * @return EchoNotification
+ * @param stdClass $row
+ * @param EchoTargetPage[]|null $targetPages An array of EchoTargetPage instances, or null if not loaded.
+ * @return EchoNotification|bool false if failed to load/unserialize
*/
public static function newFromRow( $row, $targetPages = null ) {
$notification = new EchoNotification();
@@ -213,6 +164,10 @@ class EchoNotification extends EchoAbstractEntity {
$notification->event = EchoEvent::newFromID( $row->notification_event );
}
+ if ( $notification->event === false ) {
+ return false;
+ }
+
$notification->targetPages = $targetPages;
$notification->user = User::newFromId( $row->notification_user );
// Notification timestamp should never be empty
@@ -225,6 +180,7 @@ class EchoNotification extends EchoAbstractEntity {
$notification->bundleBase = $row->notification_bundle_base;
$notification->bundleHash = $row->notification_bundle_hash;
$notification->bundleDisplayHash = $row->notification_bundle_display_hash;
+
return $notification;
}
@@ -233,7 +189,7 @@ class EchoNotification extends EchoAbstractEntity {
* @return array
*/
public function toDbArray() {
- return array(
+ return [
'notification_event' => $this->event->getId(),
'notification_user' => $this->user->getId(),
'notification_timestamp' => $this->timestamp,
@@ -241,7 +197,7 @@ class EchoNotification extends EchoAbstractEntity {
'notification_bundle_base' => $this->bundleBase,
'notification_bundle_hash' => $this->bundleHash,
'notification_bundle_display_hash' => $this->bundleDisplayHash
- );
+ ];
}
/**
@@ -276,6 +232,10 @@ class EchoNotification extends EchoAbstractEntity {
return $this->readTimestamp;
}
+ public function isRead() {
+ return $this->getReadTimestamp() !== null;
+ }
+
/**
* Getter method
* @return int Notification bundle base
@@ -309,4 +269,40 @@ class EchoNotification extends EchoAbstractEntity {
public function getTargetPages() {
return $this->targetPages;
}
+
+ public function setBundledNotifications( $notifications ) {
+ $this->bundledNotifications = $notifications;
+ }
+
+ public function getBundledNotifications() {
+ return $this->bundledNotifications;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function canBeBundled() {
+ return !$this->isRead();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getBundlingKey() {
+ return $this->getBundleHash();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function setBundledElements( $bundleables ) {
+ $this->setBundledNotifications( $bundleables );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSortingKey() {
+ return ( $this->isRead() ? '0' : '1' ) . '_' . $this->getTimestamp();
+ }
}
diff --git a/Echo/includes/model/TargetPage.php b/Echo/includes/model/TargetPage.php
index cc846605..2b371977 100644
--- a/Echo/includes/model/TargetPage.php
+++ b/Echo/includes/model/TargetPage.php
@@ -1,21 +1,16 @@
<?php
/**
- * Map a title to an echo notification so that we can mark a notification as read
+ * Map a title to an echo event so that we can mark a notification as read
* when visiting the page. This only supports titles with ids because majority
* of notifications have page_id and searching by namespace and title is slow
*/
class EchoTargetPage extends EchoAbstractEntity {
/**
- * @var User
+ * @var Title|null|bool false if not initialized yet
*/
- protected $user;
-
- /**
- * @var Title|null
- */
- protected $title;
+ protected $title = false;
/**
* @var int
@@ -33,29 +28,35 @@ class EchoTargetPage extends EchoAbstractEntity {
protected $eventId;
/**
+ * @var string
+ */
+ protected $eventType;
+
+ /**
* Only allow creating instance internally
*/
- protected function __construct() {}
+ protected function __construct() {
+ }
/**
- * Create a EchoTargetPage instance from User, Title and EchoEvent
+ * Create a EchoTargetPage instance from Title and EchoEvent
*
- * @param User $user
* @param Title $title
* @param EchoEvent $event
- * @return TargetPage|null
+ * @return EchoTargetPage|null
*/
- public static function create( User $user, Title $title, EchoEvent $event ) {
+ public static function create( Title $title, EchoEvent $event ) {
// This only support title with a page_id
- if ( $user->isAnon() || !$title->getArticleID() ) {
+ if ( !$title->getArticleID() ) {
return null;
}
$obj = new self();
- $obj->user = $user;
$obj->event = $event;
$obj->eventId = $event->getId();
+ $obj->eventType = $event->getType();
$obj->title = $title;
$obj->pageId = $title->getArticleID();
+
return $obj;
}
@@ -67,37 +68,33 @@ class EchoTargetPage extends EchoAbstractEntity {
* @throws MWException
*/
public static function newFromRow( $row ) {
- $requiredFields = array (
- 'etp_user',
+ $requiredFields = [
'etp_page',
'etp_event'
- );
+ ];
foreach ( $requiredFields as $field ) {
if ( !isset( $row->$field ) || !$row->$field ) {
throw new MWException( $field . ' is not set in the row!' );
}
}
$obj = new self();
- $obj->user = User::newFromId( $row->etp_user );
$obj->pageId = $row->etp_page;
$obj->eventId = $row->etp_event;
- return $obj;
- }
+ if ( isset( $row->event_type ) ) {
+ $obj->eventType = $row->event_type;
+ }
- /**
- * @return User
- */
- public function getUser() {
- return $this->user;
+ return $obj;
}
/**
* @return Title|null
*/
public function getTitle() {
- if ( !$this->title ) {
+ if ( $this->title === false ) {
$this->title = Title::newFromId( $this->pageId );
}
+
return $this->title;
}
@@ -115,6 +112,7 @@ class EchoTargetPage extends EchoAbstractEntity {
if ( !$this->event ) {
$this->event = EchoEvent::newFromID( $this->eventId );
}
+
return $this->event;
}
@@ -126,14 +124,24 @@ class EchoTargetPage extends EchoAbstractEntity {
}
/**
+ * @return string
+ */
+ public function getEventType() {
+ if ( !$this->eventType ) {
+ $this->eventType = $this->getEvent()->getType();
+ }
+
+ return $this->eventType;
+ }
+
+ /**
* Convert the properties to a database row
* @return array
*/
public function toDbArray() {
- return array (
- 'etp_user' => $this->user->getId(),
+ return [
'etp_page' => $this->pageId,
'etp_event' => $this->eventId
- );
+ ];
}
}
diff --git a/Echo/includes/ooui/LabelIconWidget.php b/Echo/includes/ooui/LabelIconWidget.php
new file mode 100644
index 00000000..e44e8ff9
--- /dev/null
+++ b/Echo/includes/ooui/LabelIconWidget.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace EchoOOUI;
+
+use OOUI\IconElement;
+use OOUI\LabelElement;
+use OOUI\TitledElement;
+use OOUI\Tag;
+use OOUI\Widget;
+
+/**
+ * Widget combining a label and icon
+ */
+class LabelIconWidget extends Widget {
+ use IconElement;
+ use LabelElement;
+ use TitledElement;
+
+ /**
+ * @param array $config Configuration options
+ * @param string|HtmlSnippet $config['label'] Label text
+ * @param string $config['title'] Title text
+ * @param string $config['icon'] Icon key
+ */
+ public function __construct( $config ) {
+ parent::__construct( $config );
+
+ $this->tableRow = new Tag( 'div' );
+ $this->tableRow->setAttributes( [
+ 'class' => 'oo-ui-labelIconWidget-row',
+ ] );
+
+ $this->icon = new Tag( 'div' );
+ $this->label = new Tag( 'div' );
+
+ $this->initializeIconElement( array_merge( $config, [ 'iconElement' => $this->icon ] ) );
+ $this->initializeLabelElement( array_merge( $config, [ 'labelElement' => $this->label ] ) );
+ $this->initializeTitledElement( $config );
+
+ $this->addClasses( [ 'oo-ui-labelIconWidget' ] );
+ $this->tableRow->appendContent( $this->icon, $this->label );
+ $this->appendContent( $this->tableRow );
+ }
+}
diff --git a/Echo/includes/schemaUpdate.php b/Echo/includes/schemaUpdate.php
index d8b62dec..4bc58daa 100644
--- a/Echo/includes/schemaUpdate.php
+++ b/Echo/includes/schemaUpdate.php
@@ -5,15 +5,14 @@
* Updates event_page_id based on event_page_title and event_page_namespace
* Updates extra data for page-linked events to contain page id's
*/
-class EchoSuppressionRowUpdateGenerator implements EchoRowUpdateGenerator
-{
+class EchoSuppressionRowUpdateGenerator implements RowUpdateGenerator {
/**
- * @var callable Hack to allow replacing Title::newFromText in tests
+ * @var callable Hack to allow replacing Title::makeTitleSafe in tests
*/
- protected $newTitleFromText = array( 'Title', 'newFromText' );
+ protected $newTitleFromNsAndText = [ 'Title', 'makeTitleSafe' ];
/**
- * {@inheritDoc}
+ * @inheritDoc
*/
public function update( $row ) {
$update = $this->updatePageIdFromTitle( $row );
@@ -27,21 +26,21 @@ class EchoSuppressionRowUpdateGenerator implements EchoRowUpdateGenerator
/**
* Hackish method of mocking Title::newFromText for tests
*
- * @param $callable callable
+ * @param callable $callable
*/
- public function setNewTitleFromText( $callable ) {
- $this->newTitleFromText = $callable;
+ public function setNewTitleFromNsAndText( $callable ) {
+ $this->newTitleFromNsAndText = $callable;
}
/**
- * Hackish method of mocking Title::newFromText for tests
+ * Hackish method of mocking Title::makeTitleSafe for tests
*
- * @param $text string The page name to look up
- * @param $defaultNamespace integer The default namespace of the page to look up
- * @return Title|null The title located for the text + namespace, or null if invalid
+ * @param int $namespace The namespace of the page to look up
+ * @param string $text The page name to look up
+ * @return Title|null The title located for the namespace + text, or null if invalid
*/
- protected function newTitleFromText( $text, $defaultNamespace = NS_MAIN ) {
- return call_user_func( $this->newTitleFromText, $text, $defaultNamespace );
+ protected function newTitleFromNsAndText( $namespace, $text ) {
+ return call_user_func( $this->newTitleFromNsAndText, $namespace, $text );
}
/**
@@ -49,12 +48,12 @@ class EchoSuppressionRowUpdateGenerator implements EchoRowUpdateGenerator
* to having only a page id in the table. Any event from a page that doesn't have an
* article id gets the title+namespace moved to the event extra data
*
- * @param $row stdClass A row from the database
+ * @param stdClass $row A row from the database
* @return array All updates required for this row
*/
protected function updatePageIdFromTitle( $row ) {
- $update = array();
- $title = $this->newTitleFromText( $row->event_page_title, $row->event_page_namespace );
+ $update = [];
+ $title = $this->newTitleFromNsAndText( $row->event_page_namespace, $row->event_page_title );
if ( $title !== null ) {
$pageId = $title->getArticleId();
if ( $pageId ) {
@@ -78,8 +77,8 @@ class EchoSuppressionRowUpdateGenerator implements EchoRowUpdateGenerator
* Updates the extra data for page-linked events to point to the id of the article
* rather than the namespace+title combo.
*
- * @param $row stdClass A row from the database
- * @param $update array
+ * @param stdClass $row A row from the database
+ * @param array $update
*
* @return array All updates required for this row
*/
@@ -87,7 +86,7 @@ class EchoSuppressionRowUpdateGenerator implements EchoRowUpdateGenerator
$extra = $this->extra( $row, $update );
if ( isset( $extra['link-from-title'], $extra['link-from-namespace'] ) ) {
- $title = $this->newTitleFromText( $extra['link-from-title'], $extra['link-from-namespace'] );
+ $title = $this->newTitleFromNsAndText( $extra['link-from-namespace'], $extra['link-from-title'] );
unset( $extra['link-from-title'], $extra['link-from-namespace'] );
// Link from page is always from a content page, if null or no article id it was
// somehow invalid
@@ -106,17 +105,18 @@ class EchoSuppressionRowUpdateGenerator implements EchoRowUpdateGenerator
* extra data returns that updated data rather than the origional. If
* no extra data exists returns array()
*
- * @param $row stdClass The database row being updated
- * @param $update array Updates that need to be applied to the database row
+ * @param stdClass $row The database row being updated
+ * @param array $update Updates that need to be applied to the database row
* @return array The event extra data
*/
- protected function extra( $row, array $update = array() ) {
+ protected function extra( $row, array $update = [] ) {
if ( isset( $update['event_extra'] ) ) {
return unserialize( $update['event_extra'] );
} elseif ( $row->event_extra ) {
return unserialize( $row->event_extra );
}
- return array();
+
+ return [];
}
}
diff --git a/Echo/includes/special/NotificationPager.php b/Echo/includes/special/NotificationPager.php
new file mode 100644
index 00000000..07a4e06c
--- /dev/null
+++ b/Echo/includes/special/NotificationPager.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * This pager is used by Special:Notifications (NO-JS).
+ * The heavy-lifting is done by IndexPager (grand-parent to this class).
+ * It paginates on notification_event for a specific user, only for the enabled event types.
+ *
+ * Class NotificationPager
+ */
+class NotificationPager extends ReverseChronologicalPager {
+ public function __construct() {
+ $dbFactory = MWEchoDbFactory::newFromDefault();
+ $this->mDb = $dbFactory->getEchoDb( DB_SLAVE );
+
+ parent::__construct();
+ }
+
+ function formatRow( $row ) {
+ $msg = "This pager does not support row formatting. Use 'getNotifications()' to get a list of EchoNotification objects.";
+ throw new Exception( $msg );
+ }
+
+ function getQueryInfo() {
+ $attributeManager = EchoAttributeManager::newFromGlobalVars();
+ $eventTypes = $attributeManager->getUserEnabledEvents( $this->getUser(), 'web' );
+
+ return [
+ 'tables' => [ 'echo_notification', 'echo_event' ],
+ 'fields' => '*',
+ 'conds' => [
+ 'notification_user' => $this->getUser()->getId(),
+ 'event_type' => $eventTypes,
+ 'event_deleted' => 0,
+ ],
+ 'options' => [],
+ 'join_conds' =>
+ [ 'echo_event' =>
+ [
+ 'JOIN',
+ 'notification_event=event_id',
+ ],
+ ],
+ ];
+ }
+
+ public function getNotifications() {
+ if ( !$this->mQueryDone ) {
+ $this->doQuery();
+ }
+
+ $notifications = [];
+ foreach ( $this->mResult as $row ) {
+ $notifications[] = EchoNotification::newFromRow( $row );
+ }
+
+ // get rid of the overfetched
+ if ( count( $notifications ) > $this->getLimit() ) {
+ array_pop( $notifications );
+ }
+
+ if ( $this->mIsBackwards ) {
+ $notifications = array_reverse( $notifications );
+ }
+
+ return $notifications;
+ }
+
+ function getIndexField() {
+ return 'notification_event';
+ }
+}
diff --git a/Echo/includes/special/SpecialDisplayNotificationsConfiguration.php b/Echo/includes/special/SpecialDisplayNotificationsConfiguration.php
new file mode 100644
index 00000000..09be63ca
--- /dev/null
+++ b/Echo/includes/special/SpecialDisplayNotificationsConfiguration.php
@@ -0,0 +1,302 @@
+<?Php
+
+class SpecialDisplayNotificationsConfiguration extends UnlistedSpecialPage {
+ /**
+ * EchoAttributeManager to access notification configuration
+ *
+ * @var EchoAttributeManager $attributeManager;
+ */
+ protected $attributeManager;
+
+ /**
+ * Notification controller
+ *
+ * @var EchoNotificationController $notificationController;
+ */
+ protected $notificationController;
+
+ /**
+ * Category names, mapping internal name to HTML-formatted name
+ *
+ * @var array $categoryNames
+ */
+ protected $categoryNames;
+
+ // Should be one mapping text (friendly) name to internal name, but there
+ // is no friendly name
+ /**
+ * Notification type names. Mapping internal name to internal name
+ *
+ * @var array $notificationTypeNames
+ */
+ protected $notificationTypeNames;
+
+ /**
+ * Notify types, mapping internal name to text name
+ *
+ * @var array $notifyTypes
+ */
+ protected $notifyTypes;
+
+ // Due to how HTMLForm works, it's convenient to have both directions
+ /**
+ * Category names, mapping HTML-formatted name to internal name
+ *
+ * @var array $flippedCategoryNames
+ */
+ protected $flippedCategoryNames;
+
+ /**
+ * Notify types, mapping text name to internal name
+ *
+ * @var array $flippedNotifyTypes
+ */
+ protected $flippedNotifyTypes;
+
+ public function __construct() {
+ parent::__construct( 'DisplayNotificationsConfiguration' );
+
+ $this->attributeManager = EchoAttributeManager::newFromGlobalVars();
+ $this->notificationController = new EchoNotificationController();
+ }
+
+ public function execute( $subPage ) {
+ global $wgEchoNotifiers, $wgEchoNotifications;
+
+ $this->setHeaders();
+ $this->checkPermissions();
+
+ $internalCategoryNames = $this->attributeManager->getInternalCategoryNames();
+ $this->categoryNames = [];
+
+ foreach ( $internalCategoryNames as $internalCategoryName ) {
+ $formattedFriendlyCategoryName = Html::element(
+ 'strong',
+ [],
+ $this->msg( 'echo-category-title-' . $internalCategoryName )->numParams( 1 )->text()
+ );
+
+ $formattedInternalCategoryName = $this->msg( 'parentheses' )->rawParams(
+ Html::element(
+ 'em',
+ [],
+ $internalCategoryName
+ )
+ )->parse();
+
+ $this->categoryNames[$internalCategoryName] = $formattedFriendlyCategoryName . ' ' . $formattedInternalCategoryName;
+ }
+
+ $this->flippedCategoryNames = array_flip( $this->categoryNames );
+
+ $this->notifyTypes = [];
+ foreach ( $wgEchoNotifiers as $notifyType => $notifier ) {
+ $this->notifyTypes[$notifyType] = $this->msg( 'echo-pref-' . $notifyType )->text();
+ }
+
+ $this->flippedNotifyTypes = array_flip( $this->notifyTypes );
+
+ $notificationTypes = array_keys( $wgEchoNotifications );
+ $this->notificationTypeNames = array_combine( $notificationTypes, $notificationTypes );
+
+ $this->getOutput()->setPageTitle( $this->msg( 'echo-displaynotificationsconfiguration' )->text() );
+ $this->outputHeader( 'echo-displaynotificationsconfiguration-summary' );
+ $this->outputConfiguration();
+ }
+
+ /**
+ * Outputs the Echo configuration
+ */
+ protected function outputConfiguration() {
+ $this->outputNotificationsInCategories();
+ $this->outputNotificationsInSections();
+ $this->outputAvailability();
+ $this->outputMandatory();
+ $this->outputEnabledDefault();
+ }
+
+ /**
+ * Displays a checkbox matrix, using an HTMLForm
+ *
+ * @param string $id Arbitrary ID
+ * @param string $legendMsgKey Message key for an explanatory legend. For example,
+ * "We wrote this feature because in the days of yore, there was but one notification badge"
+ * @param array $rowLabelMapping Associative array mapping label to tag
+ * @param array $columnLabelMapping Associative array mapping label to tag
+ * @param array $value Array consisting of strings in the format '$columnTag-$rowTag'
+ */
+ protected function outputCheckMatrix( $id, $legendMsgKey, array $rowLabelMapping, array $columnLabelMapping, array $value ) {
+ $form = new HTMLForm(
+ [
+ $id => [
+ 'type' => 'checkmatrix',
+ 'rows' => $rowLabelMapping,
+ 'columns' => $columnLabelMapping,
+ 'default' => $value,
+ 'disabled' => true,
+ ]
+ ],
+ $this
+ );
+
+ $form->setTitle( $this->getTitle() )
+ ->prepareForm()
+ ->suppressDefaultSubmit()
+ ->setWrapperLegendMsg( $legendMsgKey )
+ ->displayForm( false );
+ }
+
+ /**
+ * Outputs the notification types in each category
+ */
+ protected function outputNotificationsInCategories() {
+ $notificationsByCategory = $this->attributeManager->getEventsByCategory();
+
+ $out = $this->getOutput();
+ $out->addHTML(
+ Html::element(
+ 'h2',
+ [ 'id' => 'mw-echo-displaynotificationsconfiguration-notifications-by-category' ],
+ $this->msg( 'echo-displaynotificationsconfiguration-notifications-by-category-header' )->text()
+ )
+ );
+
+ $out->addHTML( Html::openElement( 'ul' ) );
+ foreach ( $notificationsByCategory as $categoryName => $notificationTypes ) {
+ $implodedTypes = Html::element(
+ 'span',
+ [],
+ implode( $this->msg( 'comma-separator' )->text(), $notificationTypes )
+ );
+
+ $out->addHTML(
+ Html::rawElement(
+ 'li',
+ [],
+ $this->categoryNames[$categoryName] . $this->msg( 'colon-separator' )->text() . ' ' . $implodedTypes
+ )
+ );
+ }
+ $out->addHTML( Html::closeElement( 'ul' ) );
+ }
+
+ /**
+ * Output the notification types in each section (alert/message)
+ */
+ protected function outputNotificationsInSections() {
+ $this->getOutput()->addHTML( Html::element( 'h2', [ 'id' => 'mw-echo-displaynotificationsconfiguration-sorting-by-section' ], $this->msg( 'echo-displaynotificationsconfiguration-sorting-by-section-header' )->text() ) );
+
+ $bySectionValue = [];
+
+ $flippedSectionNames = [];
+
+ foreach ( EchoAttributeManager::$sections as $section ) {
+ $types = $this->attributeManager->getEventsForSection( $section );
+ // echo-notification-alert-text-only, echo-notification-notice-text-only
+ $msgSection = $section == 'message' ? 'notice' : $section;
+ $flippedSectionNames[$this->msg( 'echo-notification-' . $msgSection . '-text-only' )->text()] = $section;
+ foreach ( $types as $type ) {
+ $bySectionValue[] = "$section-$type";
+ }
+ }
+
+ $this->outputCheckMatrix( 'type-by-section', 'echo-displaynotificationsconfiguration-sorting-by-section-legend', $this->notificationTypeNames, $flippedSectionNames, $bySectionValue );
+ }
+
+ /**
+ * Output which notify types are available for each category
+ */
+ protected function outputAvailability() {
+ global $wgEchoNotifications;
+
+ $this->getOutput()->addHTML( Html::element( 'h2', [ 'id' => 'mw-echo-displaynotificationsconfiguration-available-notification-methods' ], $this->msg( 'echo-displaynotificationsconfiguration-available-notification-methods-header' )->text() ) );
+
+ $byCategoryValue = [];
+
+ foreach ( $this->notifyTypes as $notifyType => $displayNotifyType ) {
+ foreach ( $this->categoryNames as $category => $displayCategory ) {
+ if ( $this->attributeManager->isNotifyTypeAvailableForCategory( $category, $notifyType ) ) {
+ $byCategoryValue[] = "$notifyType-$category";
+ }
+ }
+ }
+
+ $this->outputCheckMatrix( 'availability-by-category', 'echo-displaynotificationsconfiguration-available-notification-methods-by-category-legend', $this->flippedCategoryNames, $this->flippedNotifyTypes, $byCategoryValue );
+
+ $byTypeValue = [];
+
+ $specialNotificationTypes = array_keys( array_filter( $wgEchoNotifications, function ( $val ) {
+ return isset( $val['notify-type-availability'] );
+ } ) );
+ foreach ( $specialNotificationTypes as $notificationType ) {
+ $allowedNotifyTypes = $this->notificationController->getEventNotifyTypes( $notificationType );
+ foreach ( $allowedNotifyTypes as $notifyType ) {
+ $byTypeValue[] = "$notifyType-$notificationType";
+ }
+ }
+
+ // No user-friendly label for rows yet
+ $this->outputCheckMatrix( 'availability-by-type', 'echo-displaynotificationsconfiguration-available-notification-methods-by-type-legend', array_combine( $specialNotificationTypes, $specialNotificationTypes ), $this->flippedNotifyTypes, $byTypeValue );
+ }
+
+ /**
+ * Output which notification categories are turned on by default, for each notify type
+ */
+ protected function outputEnabledDefault() {
+ $this->getOutput()->addHTML( Html::element( 'h2', [ 'id' => 'mw-echo-displaynotificationsconfiguration-enabled-default' ], $this->msg( 'echo-displaynotificationsconfiguration-enabled-default-header' )->text() ) );
+
+ // In reality, anon users are not relevant to Echo, but this lets us easily query default options.
+ $anonUser = new User;
+
+ $byCategoryValueExisting = [];
+ foreach ( $this->notifyTypes as $notifyType => $displayNotifyType ) {
+ foreach ( $this->categoryNames as $category => $displayCategory ) {
+ $tag = "$notifyType-$category";
+ if ( $anonUser->getOption( "echo-subscriptions-$tag" ) ) {
+ $byCategoryValueExisting[] = "$notifyType-$category";
+ }
+ }
+ }
+
+ $this->outputCheckMatrix( 'enabled-by-default-generic', 'echo-displaynotificationsconfiguration-enabled-default-existing-users-legend', $this->flippedCategoryNames, $this->flippedNotifyTypes, $byCategoryValueExisting );
+
+ $loggedInUser = new User;
+ // This might not catch if there are other hooks that do similar.
+ // We can't run the actual hook, to avoid side effects.
+ $overrides = EchoHooks::getNewUserPreferenceOverrides();
+ foreach ( $overrides as $prefKey => $value ) {
+ $loggedInUser->setOption( $prefKey, $value );
+ }
+
+ $byCategoryValueNew = [];
+ foreach ( $this->notifyTypes as $notifyType => $displayNotifyType ) {
+ foreach ( $this->categoryNames as $category => $displayCategory ) {
+ $tag = "$notifyType-$category";
+ if ( $loggedInUser->getOption( "echo-subscriptions-$tag" ) ) {
+ $byCategoryValueNew[] = "$notifyType-$category";
+ }
+ }
+ }
+
+ $this->outputCheckMatrix( 'enabled-by-default-new', 'echo-displaynotificationsconfiguration-enabled-default-new-users-legend', $this->flippedCategoryNames, $this->flippedNotifyTypes, $byCategoryValueNew );
+ }
+
+ /**
+ * Output which notify types are mandatory for each category
+ */
+ protected function outputMandatory() {
+ $byCategoryValue = [];
+
+ $this->getOutput()->addHTML( Html::element( 'h2', [ 'id' => 'mw-echo-displaynotificationsconfiguration-mandatory-notification-methods' ], $this->msg( 'echo-displaynotificationsconfiguration-mandatory-notification-methods-header' )->text() ) );
+
+ foreach ( $this->notifyTypes as $notifyType => $displayNotifyType ) {
+ foreach ( $this->categoryNames as $category => $displayCategory ) {
+ if ( !$this->attributeManager->isNotifyTypeDismissableForCategory( $category, $notifyType ) ) {
+ $byCategoryValue[] = "$notifyType-$category";
+ }
+ }
+ }
+
+ $this->outputCheckMatrix( 'mandatory', 'echo-displaynotificationsconfiguration-mandatory-notification-methods-by-category-legend', $this->flippedCategoryNames, $this->flippedNotifyTypes, $byCategoryValue );
+ }
+}
diff --git a/Echo/includes/special/SpecialNotifications.php b/Echo/includes/special/SpecialNotifications.php
index 49af8fe6..e6552ee8 100644
--- a/Echo/includes/special/SpecialNotifications.php
+++ b/Echo/includes/special/SpecialNotifications.php
@@ -12,138 +12,228 @@ class SpecialNotifications extends SpecialPage {
}
public function execute( $par ) {
-
$this->setHeaders();
$out = $this->getOutput();
$out->setPageTitle( $this->msg( 'echo-specialpage' )->text() );
+ $this->addHelpLink( 'Help:Notifications/Special:Notifications' );
+
+ $out->addJsConfigVars( 'wgNotificationsSpecialPageLinks', [
+ 'help' => '//www.mediawiki.org/wiki/Special:MyLanguage/Help:Notifications/Special:Notifications',
+ 'preferences' => SpecialPage::getTitleFor( 'Preferences' )->getLinkURL() . '#mw-prefsection-echo',
+ ] );
+
$user = $this->getUser();
if ( $user->isAnon() ) {
- // return to this title upon login
- $returnTo = array( 'returnto' => $this->getPageTitle()->getPrefixedDBkey() );
- // the html message for anon users
- $anonMsgHtml = $this->msg(
- 'echo-anon',
- SpecialPage::getTitleFor( 'Userlogin', 'signup' )->getFullURL( $returnTo ),
- SpecialPage::getTitleFor( 'Userlogin' )->getFullURL( $returnTo )
- )->parse();
- $out->addHTML( Html::rawElement( 'span', array( 'class' => 'plainlinks' ), $anonMsgHtml ) );
+ // Redirect to login page and inform user of the need to login
+ $this->requireLogin( 'echo-notification-loginrequired' );
return;
}
$out->addSubtitle( $this->buildSubtitle() );
- // The continue parameter to pull current set of data from, this
- // would be used for browsers with javascript disabled
- $continue = $this->getRequest()->getVal( 'continue', null );
+ $out->enableOOUI();
- // Pull the notifications
- $notif = array();
- $notificationMapper = new EchoNotificationMapper();
+ $pager = new NotificationPager( $this->getContext() );
+ $pager->setOffset( $this->getRequest()->getVal( 'offset' ) );
+ $pager->setLimit( $this->getRequest()->getVal( 'limit', self::DISPLAY_NUM ) );
+ $notifications = $pager->getNotifications();
- $attributeManager = EchoAttributeManager::newFromGlobalVars();
- $notifications = $notificationMapper->fetchByUser(
- $user,
- /* $limit = */self::DISPLAY_NUM + 1,
- $continue,
- $attributeManager->getUserEnabledEvents( $user, 'web' )
- );
- foreach ( $notifications as $notification ) {
- $notif[] = EchoDataOutputFormatter::formatOutput( $notification, 'html', $user );
- }
+ $noJSDiv = new OOUI\Tag();
+ $noJSDiv->addClasses( [ 'mw-echo-special-nojs' ] );
// If there are no notifications, display a message saying so
- if ( !$notif ) {
- $out->addWikiMsg( 'echo-none' );
+ if ( !$notifications ) {
+ // Wrap this with nojs so it is still hidden if JS is loading
+ $noJSDiv->appendContent(
+ new OOUI\LabelWidget( [ 'label' => $this->msg( 'echo-none' )->text() ] )
+ );
+ $out->addHTML( $noJSDiv );
+ $out->addModules( [ 'ext.echo.special' ] );
return;
}
- // Check if there is more data to load for next request
- if ( count( $notif ) > self::DISPLAY_NUM ) {
- $lastItem = array_pop( $notif );
- $nextContinue = $lastItem['timestamp']['utcunix'] . '|' . $lastItem['id'];
- } else {
- $nextContinue = null;
+ $notif = [];
+ foreach ( $notifications as $notification ) {
+ $output = EchoDataOutputFormatter::formatOutput( $notification, 'special', $user, $this->getLanguage() );
+ if ( $output ) {
+ $notif[] = $output;
+ }
}
// Add the notifications to the page (interspersed with date headers)
$dateHeader = '';
- $notices = '';
- $unread = array();
+ $unread = [];
+ $anyUnread = false;
$echoSeenTime = EchoSeenTime::newFromUser( $user );
$seenTime = $echoSeenTime->getTime();
+ $notifArray = [];
foreach ( $notif as $row ) {
- $class = 'mw-echo-notification';
+ if ( !$row['*'] ) {
+ continue;
+ }
+
+ $classes = [ 'mw-echo-notification' ];
if ( !isset( $row['read'] ) ) {
- $class .= ' mw-echo-unread';
+ $classes[] = 'mw-echo-notification-unread';
if ( !$row['targetpages'] ) {
$unread[] = $row['id'];
}
}
if ( $seenTime !== null && $row['timestamp']['mw'] > $seenTime ) {
- $class .= ' mw-echo-unseen';
+ $classes[] = 'mw-echo-notification-unseen';
}
- if ( !$row['*'] ) {
- continue;
- }
// Output the date header if it has not been displayed
if ( $dateHeader !== $row['timestamp']['date'] ) {
$dateHeader = $row['timestamp']['date'];
- $notices .= Html::rawElement( 'li', array( 'class' => 'mw-echo-date-section' ), $dateHeader );
+ $notifArray[ $dateHeader ] = [
+ 'unread' => [],
+ 'notices' => []
+ ];
}
- $notices .= Html::rawElement(
- 'li',
- array(
- 'class' => $class,
+ // Collect unread IDs
+ if ( !isset( $row['read'] ) ) {
+ $anyUnread = true;
+ $notifArray[ $dateHeader ][ 'unread' ][] = $row['id'];
+ }
+
+ $li = new OOUI\Tag( 'li' );
+ $li
+ ->addClasses( $classes )
+ ->setAttributes( [
'data-notification-category' => $row['category'],
'data-notification-event' => $row['id'],
'data-notification-type' => $row['type']
- ),
- $row['*']
- );
+ ] )
+ ->appendContent( new OOUI\HtmlSnippet( $row['*'] ) );
+
+ // Store
+ $notifArray[ $dateHeader ][ 'notices' ][] = $li;
}
- $html = Html::rawElement( 'ul', array( 'id' => 'mw-echo-special-container' ), $notices );
-
- // Build the more link
- if ( $nextContinue ) {
- $html .= Html::element(
- 'a',
- array(
- 'href' => SpecialPage::getTitleFor( 'Notifications' )->getLinkURL(
- array( 'continue' => $nextContinue )
- ),
- 'class' => 'mw-ui-button mw-ui-primary',
- 'id' => 'mw-echo-more'
- ),
- $this->msg( 'moredotdotdot' )->text()
+
+ $markAllAsReadFormWrapper = '';
+ // Ensure there are some unread notifications
+ if ( $anyUnread ) {
+ $markReadSpecialPage = new SpecialNotificationsMarkRead();
+
+ $markAllAsReadText = $this->msg( 'echo-mark-all-as-read' )->text();
+ $markAllAsReadLabelIcon = new EchoOOUI\LabelIconWidget( [
+ 'label' => $markAllAsReadText,
+ 'icon' => 'doubleCheck',
+ ] );
+
+ $markAllAsReadForm = $markReadSpecialPage->getMinimalForm(
+ [ 'ALL' ],
+ $markAllAsReadText,
+ true,
+ $markAllAsReadLabelIcon->toString()
);
+
+ $formHtml = $markAllAsReadForm->prepareForm()->getHTML( /* First submission attempt */ false );
+
+ $markAllAsReadFormWrapper = new OOUI\Tag();
+ $markAllAsReadFormWrapper
+ ->addClasses( [ 'mw-echo-special-markAllReadButton' ] )
+ ->appendContent( new OOUI\HtmlSnippet( $formHtml ) );
}
- $out->addHTML( $html );
- $out->addModules( 'ext.echo.special' );
- $out->addJsConfigVars(
- array(
- 'wgEchoDisplayNum' => self::DISPLAY_NUM,
- 'wgEchoNextContinue' => $nextContinue,
- 'wgEchoDateHeader' => $dateHeader
- )
- );
- // For no-js support
- $out->addModuleStyles( array( 'ext.echo.styles.notifications', 'ext.echo.styles.special' ) );
+ // Build the list
+ $notices = new OOUI\Tag( 'ul' );
+ $notices->addClasses( [ 'mw-echo-special-notifications' ] );
+
+ $markReadSpecialPage = new SpecialNotificationsMarkRead();
+ foreach ( $notifArray as $section => $data ) {
+ // Heading
+ $heading = ( new OOUI\Tag( 'li' ) )->addClasses( [ 'mw-echo-date-section' ] );
+
+ $dateTitle = new OOUI\LabelWidget( [
+ 'classes' => [ 'mw-echo-date-section-text' ],
+ 'label' => $section
+ ] );
+
+ $heading->appendContent( $dateTitle );
+
+ // Mark all read button
+ if ( count( $data[ 'unread' ] ) > 0 ) {
+ // tell the UI to show 'unread' notifications only (instead of 'all')
+ $out->addJsConfigVars( 'wgEchoReadState', 'unread' );
+
+ $markReadSectionText = $this->msg( 'echo-specialpage-section-markread' )->text();
+ $markAsReadLabelIcon = new EchoOOUI\LabelIconWidget( [
+ 'label' => $markReadSectionText,
+ 'icon' => 'doubleCheck',
+ ] );
- DeferredUpdates::addCallableUpdate( function() use ( $user, $echoSeenTime, $unread ) {
- // Mark items as read
- if ( $unread ) {
- MWEchoNotifUser::newFromUser( $user )->markRead( $unread );
+ // There are unread notices. Add the 'mark section as read' button
+ $markSectionAsReadForm = $markReadSpecialPage->getMinimalForm(
+ $data[ 'unread' ],
+ $markReadSectionText,
+ true,
+ $markAsReadLabelIcon->toString()
+ );
+
+ $formHtml = $markSectionAsReadForm->prepareForm()->getHTML( /* First submission attempt */ false );
+
+ $formWrapper = new OOUI\Tag();
+ $formWrapper
+ ->addClasses( [ 'mw-echo-markAsReadSectionButton' ] )
+ ->appendContent( new OOUI\HtmlSnippet( $formHtml ) );
+
+ $heading->appendContent( $formWrapper );
}
- // Record time notifications have been seen
- $echoSeenTime->setTime( wfTimestamp( TS_MW ) );
- } );
+
+ // These two must be separate, because $data[ 'notices' ]
+ // is an array
+ $notices
+ ->appendContent( $heading )
+ ->appendContent( $data[ 'notices' ] );
+ }
+
+ $navBar = $pager->getNavigationBar();
+
+ $navTop = new OOUI\Tag();
+ $navBottom = new OOUI\Tag();
+ $container = new OOUI\Tag();
+
+ $navTop
+ ->addClasses( [ 'mw-echo-special-navbar-top' ] )
+ ->appendContent( new OOUI\HtmlSnippet( $navBar ) );
+ $navBottom
+ ->addClasses( [ 'mw-echo-special-navbar-bottom' ] )
+ ->appendContent( new OOUI\HtmlSnippet( $navBar ) );
+
+ // Put it all together
+ $container
+ ->addClasses( [ 'mw-echo-special-container' ] )
+ ->appendContent(
+ $navTop,
+ $markAllAsReadFormWrapper,
+ $notices,
+ $navBottom
+ );
+
+ // Wrap with nojs div
+ $noJSDiv->appendContent( $container );
+
+ $out->addHTML( $noJSDiv );
+
+ $out->addModules( [ 'ext.echo.special' ] );
+
+ // For no-js support
+ $out->addModuleStyles( [
+ 'ext.echo.styles.notifications',
+ 'ext.echo.styles.special',
+ // We already load badgeicons in the BeforePageDisplay hook, but not for minerva
+ 'ext.echo.badgeicons'
+ ] );
+
+ // Log visit
+ MWEchoEventLogging::logSpecialPageVisit( $user, $out->getSkin()->getSkinName() );
}
/**
@@ -151,32 +241,20 @@ class SpecialNotifications extends SpecialPage {
* @return string HTML for the subtitle
*/
public function buildSubtitle() {
- global $wgEchoHelpPage;
$lang = $this->getLanguage();
- $subtitleLinks = array();
- // More info link
- $subtitleLinks[] = Html::rawElement(
- 'a',
- array(
- 'href' => $wgEchoHelpPage,
- 'id' => 'mw-echo-moreinfo-link',
- 'class' => 'mw-echo-special-header-link',
- 'title' => $this->msg( 'echo-more-info' )->text(),
- 'target' => '_blank'
- ),
- $this->msg( 'echo-more-info' )->text()
- );
+ $subtitleLinks = [];
// Preferences link
- $subtitleLinks[] = Html::rawElement(
+ $subtitleLinks[] = Html::element(
'a',
- array(
+ [
'href' => SpecialPage::getTitleFor( 'Preferences' )->getLinkURL() . '#mw-prefsection-echo',
'id' => 'mw-echo-pref-link',
'class' => 'mw-echo-special-header-link',
'title' => $this->msg( 'preferences' )->text()
- ),
+ ],
$this->msg( 'preferences' )->text()
);
+ // using pipeList to make it easier to add some links in the future
return $lang->pipeList( $subtitleLinks );
}
diff --git a/Echo/includes/special/SpecialNotificationsMarkRead.php b/Echo/includes/special/SpecialNotificationsMarkRead.php
new file mode 100644
index 00000000..b69f6b02
--- /dev/null
+++ b/Echo/includes/special/SpecialNotificationsMarkRead.php
@@ -0,0 +1,152 @@
+<?php
+
+/**
+ * Form for marking notifications as read by ID.
+ *
+ * This uses the normal HTMLForm handling when receiving POSTs.
+ * However, for a better user no-JS user experience, we integrate
+ * a version of the form into Special:Notifications. Thus, this
+ * page should normally not need to be visited directly.
+ */
+class SpecialNotificationsMarkRead extends FormSpecialPage {
+ protected $eventId;
+
+ public function __construct() {
+ parent::__construct( 'NotificationsMarkRead' );
+ }
+
+ public function doesWrites() {
+ return true;
+ }
+
+ public function execute( $par ) {
+ parent::execute( $par );
+
+ $out = $this->getOutput();
+ $out->setPageTitle( $this->msg( 'echo-specialpage-markasread' )->text() );
+
+ // Redirect to login page and inform user of the need to login
+ $this->requireLogin( 'echo-notification-loginrequired' );
+ }
+
+ public function isListed() {
+ return false;
+ }
+
+ public function getDisplayFormat() {
+ return 'ooui';
+ }
+
+ /**
+ * Get an HTMLForm descriptor array
+ * @return array
+ */
+ protected function getFormFields() {
+ return [
+ 'id' => [
+ 'type' => 'hidden',
+ 'required' => true,
+ 'default' => $this->par,
+ 'filter-callback' => function ( $value, $alldata ) {
+ // Allow for a single value or a set of values
+ $result = explode( ',', $value );
+ return $result;
+ },
+ 'validation-callback' => function ( $value, $alldata ) {
+ if ( $value === [ 'ALL' ] ) {
+ return true;
+ }
+ if ( (int)$value <= 0 ) {
+ return $this->msg( 'echo-specialpage-markasread-invalid-id' );
+ }
+ foreach ( $value as $val ) {
+ if ( (int)( $val ) <= 0 ) {
+ return $this->msg( 'echo-specialpage-markasread-invalid-id' );
+ }
+ }
+ return true;
+ }
+ ]
+ ];
+ }
+
+ /**
+ * Gets a pre-filled version of the form; this should not have a legend or anything
+ * visible, except the button.
+ *
+ * @param int|array $idValue ID or array of IDs
+ * @param string $submitButtonValue Value attribute for button
+ * @param bool $framed Whether the button should be framed
+ * @param string $submitLabelHtml Raw HTML to use for button label
+ *
+ * @return HTMLForm
+ */
+ public function getMinimalForm( $idValue, $submitButtonValue, $framed, $submitLabelHtml ) {
+ if ( !is_array( $idValue ) ) {
+ $idValue = [ $idValue ];
+ }
+
+ $idString = join( ',', $idValue );
+
+ $this->setParameter( $idString );
+
+ $form = HTMLForm::factory(
+ $this->getDisplayFormat(),
+ $this->getFormFields(),
+ $this->getContext(),
+ $this->getMessagePrefix()
+ );
+
+ // HTMLForm assumes that the main submit button is always 'primary',
+ // which means it is colored. Since this form is being embedded multiple
+ // places on the page, it has to be neutral, so we make the button
+ // manually.
+ $form->suppressDefaultSubmit();
+
+ $form->setAction( $this->getPageTitle()->getLocalURL() );
+
+ $form->addButton( [
+ 'name' => 'submit',
+ 'value' => $submitButtonValue,
+ 'label-raw' => $submitLabelHtml,
+ 'framed' => $framed,
+ ] );
+
+ return $form;
+ }
+
+ /**
+ * Sets a custom label
+ *
+ * This is only called when the form is actually visited directly, which is not the
+ * main intended use.
+ * @param HTMLForm $form
+ */
+ protected function alterForm( HTMLForm $form ) {
+ $form->setSubmitText( $this->msg( 'echo-notification-markasread' )->text() );
+ }
+
+ /**
+ * Process the form on POST submission.
+ * @param array $data
+ * @param HTMLForm $form
+ * @return bool|string|array|Status As documented for HTMLForm::trySubmit.
+ */
+ public function onSubmit( array $data /* $form = null */ ) {
+ $notifUser = MWEchoNotifUser::newFromUser( $this->getUser() );
+
+ // Allow for all IDs
+ if ( $data['id'] === [ 'ALL' ] ) {
+ return $notifUser->markAllRead();
+ }
+
+ // Allow for multiple IDs or a single ID
+ $ids = $data['id'];
+ return $notifUser->markRead( $ids );
+ }
+
+ public function onSuccess() {
+ $page = SpecialPage::getTitleFor( 'Notifications' );
+ $this->getOutput()->redirect( $page->getFullUrl() );
+ }
+}
diff --git a/Echo/jsduck.external.js b/Echo/jsduck.external.js
new file mode 100644
index 00000000..14eb9e8f
--- /dev/null
+++ b/Echo/jsduck.external.js
@@ -0,0 +1,48 @@
+/**
+ * Source: <https://api.jquery.com/>
+ * @class jQuery
+ */
+
+/**
+ * Source: <https://api.jquery.com/jQuery.ajax/>
+ * @method ajax
+ * @static
+ * @return {jqXHR}
+ */
+
+/**
+ * Source: <https://api.jquery.com/Types/#Event>
+ * @class jQuery.Event
+ */
+
+/**
+ * Source: <https://api.jquery.com/Types/#Promise>
+ * @class jQuery.Promise
+ */
+
+/**
+ * Source: <https://api.jquery.com/jQuery.Deferred/>
+ * @class jQuery.Deferred
+ * @mixins jQuery.Promise
+ */
+
+/**
+ * Source: <https://api.jquery.com/Types/#jqXHR>
+ * @class jQuery.jqXHR
+ * @alternateClassName jqXHR
+ */
+
+/**
+ * Source: <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api>
+ * @class mw.Api
+ */
+
+/**
+ * Source: <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Message
+ * @class mw.Message
+ */
+
+/**
+ * Source: <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Title>
+ * @class mw.Title
+ */
diff --git a/Echo/jsduck.json b/Echo/jsduck.json
new file mode 100644
index 00000000..e3e7955b
--- /dev/null
+++ b/Echo/jsduck.json
@@ -0,0 +1,13 @@
+{
+ "--title": "Echo - Documentation",
+ "--processes": "0",
+ "--warnings-exit-nonzero": true,
+ "--external": "OO.*",
+ "--output": "docs",
+ "--tags": "jsduck_custom_tags.rb",
+ "--": [
+ "jsduck.external.js",
+ "modules",
+ "tests"
+ ]
+}
diff --git a/Echo/jsduck_custom_tags.rb b/Echo/jsduck_custom_tags.rb
new file mode 100644
index 00000000..6a4da00a
--- /dev/null
+++ b/Echo/jsduck_custom_tags.rb
@@ -0,0 +1,83 @@
+# Custom tags for JSDuck 5.x
+# See also:
+# - https://github.com/senchalabs/jsduck/wiki/Tags
+# - https://github.com/senchalabs/jsduck/wiki/Custom-tags
+# - https://github.com/senchalabs/jsduck/wiki/Custom-tags/7f5c32e568eab9edc8e3365e935bcb836cb11f1d
+require 'jsduck/tag/tag'
+
+class CommonTag < JsDuck::Tag::Tag
+ def initialize
+ @html_position = POS_DOC + 0.1
+ @repeatable = true
+ end
+
+ def parse_doc(scanner, _position)
+ if @multiline
+ return { tagname: @tagname, doc: :multiline }
+ else
+ text = scanner.match(/.*$/)
+ return { tagname: @tagname, doc: text }
+ end
+ end
+
+ def process_doc(context, tags, _position)
+ context[@tagname] = tags
+ end
+
+ def format(context, formatter)
+ context[@tagname].each do |tag|
+ tag[:doc] = formatter.format(tag[:doc])
+ end
+ end
+end
+
+class SeeTag < CommonTag
+ def initialize
+ @tagname = :see
+ @pattern = 'see'
+ super
+ end
+
+ def format(context, formatter)
+ position = context[:files][0]
+ context[@tagname].each do |tag|
+ tag[:doc] = '<li>' + render_long_see(tag[:doc], formatter, position) + '</li>'
+ end
+ end
+
+ def to_html(context)
+ <<-EOHTML
+ <h3 class="pa">Related</h3>
+ <ul>
+ #{context[@tagname].map {|tag| tag[:doc]}.join("\n")}
+ </ul>
+ EOHTML
+ end
+
+ def render_long_see(tag, formatter, position)
+ match = tag.match(/\A([^\s]+)( .*)?\Z/m)
+ if match
+ name = match[1]
+ doc = match[2] ? ': ' + match[2] : ''
+ return formatter.format("{@link #{name}} #{doc}")
+ else
+ JsDuck::Logger.warn(nil, 'Unexpected @see argument: "' + tag + '"', position)
+ return tag
+ end
+ end
+end
+
+class TodoTag < CommonTag
+ def initialize
+ @tagname = :todo
+ @pattern = 'todo'
+ super
+ end
+
+ def to_html(context)
+ <<-EOHTML
+ <h3>TODO</h3>
+ #{context[@tagname].last[:doc]}
+ EOHTML
+ end
+end
diff --git a/Echo/maintenance/backfillReadBundles.php b/Echo/maintenance/backfillReadBundles.php
new file mode 100644
index 00000000..db38ceeb
--- /dev/null
+++ b/Echo/maintenance/backfillReadBundles.php
@@ -0,0 +1,80 @@
+<?php
+
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+require_once "$IP/maintenance/Maintenance.php";
+
+class BackfillReadBundles extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = "Backfill echo_notification.notification_read_timestamp for bundles";
+
+ $this->setBatchSize( 300 );
+
+ $this->requireExtension( 'Echo' );
+ }
+
+ public function execute() {
+ $dbFactory = MWEchoDbFactory::newFromDefault();
+ $dbw = $dbFactory->getEchoDb( DB_MASTER );
+ $dbr = $dbFactory->getEchoDb( DB_SLAVE );
+ $iterator = new BatchRowIterator(
+ $dbr,
+ 'echo_notification',
+ [ 'notification_user', 'notification_event' ],
+ $this->mBatchSize
+ );
+ $iterator->setFetchColumns( [ 'notification_bundle_display_hash', 'notification_read_timestamp' ] );
+
+ $unreadNonBase = $dbr->selectSQLText(
+ 'echo_notification',
+ 'notification_bundle_display_hash',
+ [
+ 'notification_bundle_base' => 0,
+ 'notification_read_timestamp IS NULL',
+ "notification_bundle_display_hash <> ''",
+ ]
+ );
+
+ $iterator->addConditions( [
+ 'notification_bundle_base' => 1,
+ 'notification_read_timestamp IS NOT NULL',
+ "notification_bundle_display_hash IN ( $unreadNonBase )",
+ ] );
+
+ $processed = 0;
+ foreach ( $iterator as $batch ) {
+ foreach ( $batch as $row ) {
+ $userId = $row->notification_user;
+ $displayHash = $row->notification_bundle_display_hash;
+ $readTimestamp = $row->notification_read_timestamp;
+
+ $result = $dbw->update(
+ 'echo_notification',
+ [ 'notification_read_timestamp' => $readTimestamp ],
+ [
+ 'notification_user' => $userId,
+ 'notification_bundle_display_hash' => $displayHash,
+ 'notification_bundle_base' => 0,
+ 'notification_read_timestamp IS NULL',
+ ]
+ );
+
+ if ( !$result ) {
+ $this->output( "Failed to set read_timestamp on notifications with bundle_display_hash: $displayHash\n" );
+ }
+
+ $processed += $dbw->affectedRows();
+ }
+
+ $this->output( "Updated $processed notifications.\n" );
+ $dbFactory->waitForSlaves();
+ }
+ }
+}
+
+$maintClass = "BackfillReadBundles";
+require_once DO_MAINTENANCE;
diff --git a/Echo/maintenance/backfillUnreadWikis.php b/Echo/maintenance/backfillUnreadWikis.php
new file mode 100644
index 00000000..c89f24ea
--- /dev/null
+++ b/Echo/maintenance/backfillUnreadWikis.php
@@ -0,0 +1,73 @@
+<?php
+
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+require_once "$IP/maintenance/Maintenance.php";
+
+class BackfillUnreadWikis extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = "Backfill echo_unread_wikis table";
+ $this->addOption( 'rebuild', 'Only recompute already-existing rows' );
+ $this->setBatchSize( 300 );
+ $this->requireExtension( 'Echo' );
+ }
+
+ public function execute() {
+ $dbFactory = MWEchoDbFactory::newFromDefault();
+ $lookup = CentralIdLookup::factory();
+
+ $rebuild = $this->hasOption( 'rebuild' );
+ if ( $rebuild ) {
+ $iterator = new BatchRowIterator( $dbFactory->getSharedDb( DB_SLAVE ), 'echo_unread_wikis', 'euw_user', $this->mBatchSize );
+ $iterator->addConditions( [ 'euw_wiki' => wfWikiID() ] );
+ } else {
+ $iterator = new BatchRowIterator( wfGetDB( DB_SLAVE ), 'user', 'user_id', $this->mBatchSize );
+ $iterator->setFetchColumns( User::selectFields() );
+ }
+
+ $processed = 0;
+ foreach ( $iterator as $batch ) {
+ foreach ( $batch as $row ) {
+ if ( $rebuild ) {
+ $user = $lookup->localUserFromCentralId( $row->euw_user, CentralIdLookup::AUDIENCE_RAW );
+ } else {
+ $user = User::newFromRow( $row );
+ }
+ if ( !$user ) {
+ continue;
+ }
+
+ $notifUser = MWEchoNotifUser::newFromUser( $user );
+ $uw = EchoUnreadWikis::newFromUser( $user );
+ if ( $uw ) {
+ $alertCount = $notifUser->getNotificationCount( true, DB_SLAVE, EchoAttributeManager::ALERT, false );
+ $alertUnread = $notifUser->getLastUnreadNotificationTime( true, DB_SLAVE, EchoAttributeManager::ALERT, false );
+
+ $msgCount = $notifUser->getNotificationCount( true, DB_SLAVE, EchoAttributeManager::MESSAGE, false );
+ $msgUnread = $notifUser->getLastUnreadNotificationTime( true, DB_SLAVE, EchoAttributeManager::MESSAGE, false );
+
+ if ( ( $alertCount !== 0 && $alertUnread === false ) || ( $msgCount !== 0 && $msgUnread === false ) ) {
+ // If there are alerts, there should be an alert timestamp (same for messages).
+
+ // Otherwise, there is a race condition between the two values, indicating there's already
+ // just been an updateCount call, so we can skip this user.
+ continue;
+ }
+
+ $uw->updateCount( wfWikiID(), $alertCount, $alertUnread, $msgCount, $msgUnread );
+ }
+ }
+
+ $processed += count( $batch );
+ $this->output( "Updated $processed users.\n" );
+ $dbFactory->waitForSlaves();
+ }
+ }
+}
+
+$maintClass = "BackfillUnreadWikis";
+require_once DO_MAINTENANCE;
diff --git a/Echo/maintenance/generateSampleNotifications.php b/Echo/maintenance/generateSampleNotifications.php
new file mode 100644
index 00000000..ed6070c4
--- /dev/null
+++ b/Echo/maintenance/generateSampleNotifications.php
@@ -0,0 +1,499 @@
+<?php
+
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+require_once "$IP/maintenance/Maintenance.php";
+
+/**
+ * A maintenance script that generates sample notifications for testing purposes.
+ */
+class GenerateSampleNotifications extends Maintenance {
+
+ private $supportedNotificationTypes = [
+ 'welcome',
+ 'edit-user-talk',
+ 'mention',
+ 'page-linked',
+ 'reverted',
+ 'email',
+ 'user-rights',
+ 'cx',
+ 'osm',
+ 'edit-thanks',
+ 'edu',
+ 'page-connection',
+ ];
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Generate sample notifications";
+
+ $this->addOption(
+ 'force',
+ 'Bypass confirmation',
+ false, false, 'f' );
+
+ $allTypes = implode( ',', $this->supportedNotificationTypes );
+ $this->addOption(
+ 'types',
+ "Comma-separated list of notification types to generate ($allTypes)",
+ false, true, 't' );
+
+ $this->addOption(
+ 'user',
+ 'Name of the user receiving the notifications',
+ true, true, 'u' );
+
+ $this->addOption(
+ 'agent',
+ 'Name of the user creating the notifications',
+ true, true, 'a' );
+
+ $this->addOption(
+ 'other',
+ 'Name of another user involved with the notifications',
+ true, true, 'o' );
+
+ $this->requireExtension( 'Echo' );
+ }
+
+ public function execute() {
+ if ( !class_exists( 'EchoHooks' ) ) {
+ $this->error( "Echo isn't enabled on this wiki\n", 1 );
+ }
+
+ $user = $this->getOptionUser( 'user' );
+ $agent = $this->getOptionUser( 'agent' );
+ $otherUser = $this->getOptionUser( 'other' );
+ $title = Title::newFromText( 'This is a pretty long page title lets see if it is going to be truncated' );
+
+ $types = $this->getOption( 'types' );
+ if ( $types ) {
+ $types = explode( ',', $types );
+ } else {
+ $types = $this->supportedNotificationTypes;
+ }
+
+ $this->confirm();
+
+ $this->output( "Started processing...\n" );
+
+ if ( $this->shouldGenerate( 'welcome', $types ) ) {
+ $this->generateWelcome( $user );
+ }
+
+ if ( $this->shouldGenerate( 'edit-user-talk', $types ) ) {
+ $this->generateEditUserTalk( $user, $agent );
+ }
+
+ if ( $this->shouldGenerate( 'mention', $types ) ) {
+ $this->generateMention( $user, $agent, $otherUser, $title );
+ }
+
+ if ( $this->shouldGenerate( 'page-linked', $types ) ) {
+ $this->generatePageLink( $user, $agent );
+ }
+
+ if ( $this->shouldGenerate( 'reverted', $types ) ) {
+ $this->generateReverted( $user, $agent );
+ }
+
+ if ( $this->shouldGenerate( 'email', $types ) ) {
+ $this->generateEmail( $user, $agent );
+ }
+
+ if ( $this->shouldGenerate( 'user-rights', $types ) ) {
+ $this->generateUserRights( $user, $agent );
+ }
+
+ if ( $this->shouldGenerate( 'cx', $types ) ) {
+ $this->generateContentTranslation( $user );
+ }
+
+ if ( $this->shouldGenerate( 'osm', $types ) ) {
+ $this->generateOpenStackManager( $user, $agent );
+ }
+
+ if ( $this->shouldGenerate( 'edit-thanks', $types ) ) {
+ $this->generateEditThanks( $user, $agent, $otherUser );
+ }
+
+ if ( $this->shouldGenerate( 'edu', $types ) ) {
+ $this->generateEducationProgram( $user, $agent );
+ }
+
+ if ( $this->shouldGenerate( 'page-connection', $types ) ) {
+ $this->generateWikibase( $user, $agent );
+ }
+
+ $this->output( "Completed \n" );
+ }
+
+ private function generateEditUserTalk( User $user, User $agent ) {
+ $this->output( "{$agent->getName()} is writing on {$user->getName()}'s user talk page\n" );
+ $editId = $this->generateRandomString();
+ $section = "== section $editId ==\n\nthis is the text $editId\n\n~~~~\n\n";
+ $this->addToUserTalk( $user, $agent, $section );
+ }
+
+ private function getOptionUser( $optionName ) {
+ $username = $this->getOption( $optionName );
+ $user = User::newFromName( $username );
+ if ( $user->isAnon() ) {
+ $this->error( "User $username does not seem to exist in this wiki", 1 );
+ }
+ return $user;
+ }
+
+ private function generateRandomString( $length = 10 ) {
+ return substr( str_shuffle( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, $length );
+ }
+
+ protected function confirm() {
+ if ( $this->getOption( 'force', false ) ) {
+ return;
+ }
+ $this->output( "=== WARNING ===\n" );
+ $this->output( "This script modifies the content of several pages,\n" );
+ $this->output( "including user's talk pages.\n" );
+ $this->output( "ONLY RUN ON TEST WIKIS\n" );
+ $this->output( "Enter 'yes' if you wish to continue or any other key to exit\n" );
+ $confirm = $this->readconsole();
+ if ( $confirm !== 'yes' ) {
+ $this->error( 'Safe decision', 1 );
+ }
+ }
+
+ private function addToUserTalk( User $user, User $agent, $contentText ) {
+ $this->addToPageContent( $user->getTalkPage(), $agent, $contentText );
+ }
+
+ private function addToPageContent( Title $title, User $agent, $contentText ) {
+ $page = WikiPage::factory( $title );
+ $previousContent = "";
+ $page->loadPageData( 'fromdbmaster' );
+ $revision = $page->getRevision();
+ if ( $revision ) {
+ $content = $revision->getContent( Revision::FOR_PUBLIC );
+ if ( $content instanceof WikitextContent ) {
+ $previousContent = $content->getNativeData();
+ }
+ }
+ $status = $page->doEditContent(
+ new WikitextContent( $contentText . $previousContent ),
+ 'generating sample notifications',
+ 0,
+ false,
+ $agent
+ );
+
+ if ( !$status->isGood() ) {
+ $this->error( "Failed to edit {$title->getPrefixedText()}: {$status->getMessage()}" );
+ }
+
+ return $status->getValue()['revision'];
+ }
+
+ private function generateMention( User $user, User $agent, User $otherUser, Title $title ) {
+ $mention = "== section {$this->generateRandomString()} ==\nHello [[User:{$user->getName()}]] \n~~~~\n";
+
+ // article talk
+ $this->output( "{$agent->getName()} is mentioning {$user->getName()} on {$title->getTalkPage()->getPrefixedText()}\n" );
+ $this->addToPageContent( $title->getTalkPage(), $agent, $mention );
+
+ // agent tak
+ $this->output( "{$agent->getName()} is mentioning {$user->getName()} on {$agent->getTalkPage()->getPrefixedText()}\n" );
+ $this->addToPageContent( $agent->getTalkPage(), $agent, $mention );
+
+ // user talk
+ $this->output( "{$agent->getName()} is mentioning {$user->getName()} on {$otherUser->getTalkPage()->getPrefixedText()}\n" );
+ $this->addToPageContent( $otherUser->getTalkPage(), $agent, $mention );
+
+ // any other page
+ $this->output( "{$agent->getName()} is mentioning {$user->getName()} on {$title->getPrefixedText()}\n" );
+ $this->addToPageContent( $title, $agent, $mention );
+ }
+
+ private function generatePageLink( User $user, User $agent ) {
+ $this->generateOnePageLink( $user, $agent );
+ $this->generateMultiplePageLinks( $user, $agent );
+ }
+
+ private function generateNewPageTitle() {
+ return Title::newFromText( $this->generateRandomString() );
+ }
+
+ private function generateReverted( User $user, User $agent ) {
+ $agent->addGroup( 'sysop' );
+
+ // revert (undo)
+ $moai = Title::newFromText( 'Moai' );
+ $page = WikiPage::factory( $moai );
+ $this->output( "{$agent->getName()} is reverting {$user->getName()}'s edit on {$moai->getPrefixedText()}\n" );
+ $this->addToPageContent( $moai, $agent, "\ncreating a good revision here\n" );
+ $this->addToPageContent( $moai, $user, "\nadding a line here\n" );
+ $content = $page->getUndoContent( $page->getRevision(), $page->getRevision()->getPrevious() );
+ $status = $page->doEditContent( $content, 'undo', 0, false, $agent, null, [], $page->getRevision()->getId() );
+ if ( !$status->isGood() ) {
+ $this->error( "Failed to undo {$moai->getPrefixedText()}: {$status->getMessage()}" );
+ }
+
+ // rollback
+ $moai2 = Title::newFromText( 'Moai2' );
+ $page = WikiPage::factory( $moai2 );
+ $this->output( "{$agent->getName()} is rolling back {$user->getName()}'s edits on {$moai2->getPrefixedText()}\n" );
+ $this->addToPageContent( $moai2, $agent, "\ncreating a good revision here\n" );
+ $this->addToPageContent( $moai2, $user, "\nadding a line here\n" );
+ $this->addToPageContent( $moai2, $user, "\nadding a line here\n" );
+ $details = [];
+ $token = $agent->getEditToken( 'rollback', null );
+ $errors = $page->doRollback( $user->getName(), 'generating reverted notification', $token, false, $details, $agent );
+ if ( $errors ) {
+ $this->error( serialize( $errors ) );
+ }
+ }
+
+ private function generateWelcome( User $user ) {
+ $this->output( "Welcoming {$user->getName()}\n" );
+ EchoEvent::create( [
+ 'type' => 'welcome',
+ 'agent' => $user,
+ 'extra' => [
+ 'notifyAgent' => true
+ ]
+ ] );
+ }
+
+ private function generateEmail( User $user, User $agent ) {
+ $this->output( "{$agent->getName()} is emailing {$user->getName()}\n" );
+ EchoEvent::create( [
+ 'type' => 'emailuser',
+ 'extra' => [
+ 'to-user-id' => $user->getId(),
+ 'subject' => 'Long time no see',
+ ],
+ 'agent' => $agent,
+ ] );
+ }
+
+ private function generateUserRights( User $user, User $agent ) {
+ $this->output( "{$agent->getName()} is changing {$user->getName()}'s rights\n" );
+ $this->createUserRightsNotification( $user, $agent, [ 'OnlyAdd-1' ], null );
+ $this->createUserRightsNotification( $user, $agent, null, [ 'JustRemove-1', 'JustRemove-2' ] );
+ $this->createUserRightsNotification( $user, $agent, [ 'Add-1', 'Add-2' ], [ 'Remove-1', 'Remove-2' ] );
+ }
+
+ private function createUserRightsNotification( User $user, User $agent, $add, $remove ) {
+ EchoEvent::create(
+ [
+ 'type' => 'user-rights',
+ 'extra' => [
+ 'user' => $user->getID(),
+ 'add' => $add,
+ 'remove' => $remove,
+ 'reason' => 'This is the reason for changing your user rights.',
+ ],
+ 'agent' => $agent,
+ ]
+ );
+ }
+
+ private function generateContentTranslation( User $user ) {
+ if ( !class_exists( 'ContentTranslationHooks' ) ) {
+ return;
+ }
+
+ $this->output( "Generating CX notifications\n" );
+ foreach ( [ 'cx-first-translation', 'cx-tenth-translation', 'cx-hundredth-translation' ] as $eventType ) {
+ EchoEvent::create(
+ [
+ 'type' => $eventType,
+ 'extra' => [
+ 'recipient' => $user->getId(),
+ ],
+ ]
+ );
+ }
+
+ EchoEvent::create(
+ [
+ 'type' => 'cx-suggestions-available',
+ 'extra' => [
+ 'recipient' => $user->getId(),
+ 'lastTranslationTitle' => 'History of the People\'s Republic of China'
+ ],
+ ]
+ );
+ }
+
+ private function generateOnePageLink( User $user, User $agent ) {
+ $pageBeingLinked = $this->generateNewPageTitle();
+ $this->addToPageContent( $pageBeingLinked, $user, "this is a new page" );
+
+ $pageLinking = $this->generateNewPageTitle();
+ $content = "checkout [[{$pageBeingLinked->getPrefixedText()}]]!";
+ $this->output( "{$agent->getName()} is linking to {$pageBeingLinked->getPrefixedText()} from {$pageLinking->getPrefixedText()}\n" );
+ $this->addToPageContent( $pageLinking, $agent, $content );
+ }
+
+ private function generateMultiplePageLinks( User $user, User $agent ) {
+ $pageBeingLinked = $this->generateNewPageTitle();
+ $this->addToPageContent( $pageBeingLinked, $user, "this is a new page" );
+
+ $content = "checkout [[{$pageBeingLinked->getPrefixedText()}]]!";
+ $this->output( "{$agent->getName()} is linking to {$pageBeingLinked->getPrefixedText()} from multiple pages\n" );
+ $this->addToPageContent( $this->generateNewPageTitle(), $agent, $content );
+ $this->addToPageContent( $this->generateNewPageTitle(), $agent, $content );
+ $this->addToPageContent( $this->generateNewPageTitle(), $agent, $content );
+ }
+
+ private function generateOpenStackManager( User $user, User $agent ) {
+ if ( !class_exists( 'OpenStackManagerHooks' ) ) {
+ return;
+ }
+
+ $this->output( "Generating OpenStackManager notifications\n" );
+
+ foreach ( [ 'build-completed', 'reboot-completed', 'deleted' ] as $action ) {
+ EchoEvent::create( [
+ 'type' => "osm-instance-$action",
+ 'title' => Title::newFromText( "Moai" ),
+ 'agent' => $user,
+ 'extra' => [
+ 'instanceName' => 'instance1',
+ 'projectName' => 'TheProject',
+ 'notifyAgent' => true,
+ ]
+ ] );
+ }
+
+ EchoEvent::create( [
+ 'type' => 'osm-projectmembers-add',
+ 'title' => Title::newFromText( "Moai" ),
+ 'agent' => $agent,
+ 'extra' => [ 'userAdded' => $user->getId() ],
+ ] );
+ }
+
+ private function shouldGenerate( $type, $types ) {
+ return array_search( $type, $types ) !== false;
+ }
+
+ private function generateEditThanks( User $user, User $agent, User $otherUser ) {
+ $this->generateOneEditThanks( $user, $agent );
+ $this->generateMultipleEditThanks( $user, $agent, $otherUser );
+ }
+
+ private function generateOneEditThanks( User $user, User $agent ) {
+ if ( !class_exists( 'ThanksHooks' ) ) {
+ return;
+ }
+ // make an edit, thank it once
+ $title = $this->generateNewPageTitle();
+ $revision = $this->addToPageContent( $title, $user, "an awesome edit! ~~~~" );
+ EchoEvent::create( [
+ 'type' => 'edit-thank',
+ 'title' => $title,
+ 'extra' => [
+ 'revid' => $revision->getId(),
+ 'thanked-user-id' => $user->getId(),
+ 'source' => 'generateSampleNotifications.php',
+ ],
+ 'agent' => $agent,
+ ] );
+ $this->output( "{$agent->getName()} is thanking {$user->getName()} for edit {$revision->getId()} on {$title->getPrefixedText()}\n" );
+ }
+ private function generateMultipleEditThanks( User $user, User $agent, User $otherUser ) {
+ if ( !class_exists( 'ThanksHooks' ) ) {
+ return;
+ }
+ // make an edit, thank it twice
+ $title = $this->generateNewPageTitle();
+ $revision = $this->addToPageContent( $title, $user, "an even better edit! ~~~~" );
+ EchoEvent::create( [
+ 'type' => 'edit-thank',
+ 'title' => $title,
+ 'extra' => [
+ 'revid' => $revision->getId(),
+ 'thanked-user-id' => $user->getId(),
+ 'source' => 'generateSampleNotifications.php',
+ ],
+ 'agent' => $agent,
+ ] );
+ EchoEvent::create( [
+ 'type' => 'edit-thank',
+ 'title' => $title,
+ 'extra' => [
+ 'revid' => $revision->getId(),
+ 'thanked-user-id' => $user->getId(),
+ 'source' => 'generateSampleNotifications.php',
+ ],
+ 'agent' => $otherUser,
+ ] );
+ $this->output( "{$agent->getName()} and {$otherUser->getName()} are thanking {$user->getName()} for edit {$revision->getId()} on {$title->getPrefixedText()}\n" );
+ }
+
+ private function generateEducationProgram( User $user, User $agent ) {
+ if ( !class_exists( 'EducationProgram\Extension' ) ) {
+ $this->output( 'class EducationProgram\Extension not found' );
+ return;
+ }
+
+ $chem101 = Title::newFromText( 'School/Chemistry101' );
+ if ( !$chem101->exists() ) {
+ $this->addToPageContent( $chem101, $agent, "\nThis is the main page for the Chemistry 101 course\n" );
+ }
+
+ $notificationManager = EducationProgram\Extension::globalInstance()->getNotificationsManager();
+
+ $this->output( "{$agent->getName()} is adding {$user->getName()} to {$chem101->getPrefixedText()} as instructor, student, campus volunteer and online volunteer.\n" );
+
+ $types = [
+ 'ep-instructor-add-notification',
+ 'ep-online-add-notification',
+ 'ep-campus-add-notification',
+ 'ep-student-add-notification',
+ ];
+ foreach ( $types as $type ) {
+ $notificationManager->trigger(
+ $type,
+ [
+ 'role-add-title' => $chem101,
+ 'agent' => $agent,
+ 'users' => [ $user->getId() ],
+ ]
+ );
+ }
+
+ // NOTE: Not generating 'ep-course-talk-notification' for now
+ // as it requires a full setup to actually work (institution, course, instructors, students).
+ }
+
+ private function generateWikibase( User $user, User $agent ) {
+ if ( !class_exists( 'Wikibase\Client\Hooks\EchoNotificationsHandlers' ) ) {
+ $this->output( 'class Wikibase\Client\Hooks\EchoNotificationsHandlers not found' );
+ return;
+ }
+
+ $title = $this->generateNewPageTitle();
+ $this->addToPageContent( $title, $user, "this is a new page" );
+ $helpPage = Title::newFromText( 'Project:Wikidata' );
+ $this->addToPageContent( $helpPage, $user, "this is the help page" );
+
+ $this->output( "{$agent->getName()} is connecting {$user->getName()}'s page {$title->getPrefixedText()} to an item\n" );
+ EchoEvent::create( [
+ 'type' => Wikibase\Client\Hooks\EchoNotificationsHandlers::NOTIFICATION_TYPE,
+ 'title' => $title,
+ 'extra' => [
+ 'url' => Title::newFromText( 'Item:Q1' )->getFullURL(),
+ 'repoSiteName' => 'Wikidata'
+ ],
+ 'agent' => $agent,
+ ] );
+ }
+}
+
+$maintClass = "GenerateSampleNotifications";
+require_once DO_MAINTENANCE;
diff --git a/Echo/maintenance/processEchoEmailBatch.php b/Echo/maintenance/processEchoEmailBatch.php
index f826a5d2..9ad95086 100644
--- a/Echo/maintenance/processEchoEmailBatch.php
+++ b/Echo/maintenance/processEchoEmailBatch.php
@@ -2,9 +2,9 @@
$IP = getenv( 'MW_INSTALL_PATH' );
if ( $IP === false ) {
- $IP = dirname( __FILE__ ) . '/../../..';
+ $IP = __DIR__ . '/../../..';
}
-require_once( "$IP/maintenance/Maintenance.php" );
+require_once "$IP/maintenance/Maintenance.php";
/**
* A maintenance script that processes email digest
@@ -25,6 +25,8 @@ class ProcessEchoEmailBatch extends Maintenance {
"ignoreConfiguredSchedule",
"Send all pending notifications immediately even if configured to be weekly or daily.",
false, false, "i" );
+
+ $this->requireExtension( 'Echo' );
}
public function execute() {
@@ -75,4 +77,4 @@ class ProcessEchoEmailBatch extends Maintenance {
}
$maintClass = "ProcessEchoEmailBatch";
-require_once( DO_MAINTENANCE );
+require_once DO_MAINTENANCE;
diff --git a/Echo/maintenance/removeInvalidNotification.php b/Echo/maintenance/removeInvalidNotification.php
index c20f5021..58362b8b 100644
--- a/Echo/maintenance/removeInvalidNotification.php
+++ b/Echo/maintenance/removeInvalidNotification.php
@@ -4,23 +4,29 @@
*
* @ingroup Maintenance
*/
-require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
- : dirname( __FILE__ ) . '/../../../maintenance/Maintenance.php' );
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
/**
* Maintenance script that removes invalid notifications
*
* @ingroup Maintenance
*/
-class removeInvalidNotification extends Maintenance {
+class RemoveInvalidNotification extends Maintenance {
protected $batchSize = 500;
- protected $invalidEventType = array( 'article-linked' );
+ protected $invalidEventType = [ 'article-linked' ];
+
+ public function __construct() {
+ $this->mDescription = "Removes invalid notifications from the database.";
+ $this->requireExtension( 'Echo' );
+ }
public function execute() {
if ( !$this->invalidEventType ) {
$this->output( "There is nothing to process\n" );
+
return;
}
@@ -33,18 +39,18 @@ class removeInvalidNotification extends Maintenance {
while ( $count == $this->batchSize ) {
$res = $dbr->select(
- array( 'echo_event' ),
- array( 'event_id' ),
- array(
+ [ 'echo_event' ],
+ [ 'event_id' ],
+ [
'event_type' => $this->invalidEventType,
- ),
+ ],
__METHOD__,
- array( 'LIMIT' => $this->batchSize )
+ [ 'LIMIT' => $this->batchSize ]
);
- $event = array();
+ $event = [];
$count = 0;
- foreach( $res as $row ) {
+ foreach ( $res as $row ) {
if ( !in_array( $row->event_id, $event ) ) {
$event[] = $row->event_id;
}
@@ -52,20 +58,20 @@ class removeInvalidNotification extends Maintenance {
};
if ( $event ) {
- $dbw->begin();
+ $this->beginTransaction( $dbw, __METHOD__ );
$dbw->delete(
'echo_event',
- array( 'event_id' => $event ),
+ [ 'event_id' => $event ],
__METHOD__
);
$dbw->delete(
'echo_notification',
- array( 'notification_event' => $event ),
+ [ 'notification_event' => $event ],
__METHOD__
);
- $dbw->commit();
+ $this->commitTransaction( $dbw, __METHOD__ );
$this->output( "processing " . count( $event ) . " invalid events\n" );
wfWaitForSlaves( false, false, $wgEchoCluster );
@@ -77,5 +83,5 @@ class removeInvalidNotification extends Maintenance {
}
}
-$maintClass = 'removeInvalidNotification'; // Tells it to run the class
-require_once( RUN_MAINTENANCE_IF_MAIN );
+$maintClass = 'RemoveInvalidNotification'; // Tells it to run the class
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Echo/maintenance/removeInvalidTargetPage.php b/Echo/maintenance/removeInvalidTargetPage.php
deleted file mode 100644
index 10cd0c4c..00000000
--- a/Echo/maintenance/removeInvalidTargetPage.php
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-/**
- * Remove invalid records from echo_target_page. For instance, page has been
- * deleted or removed, notification has somehow been marked as read
- *
- * @ingroup Maintenance
- */
-require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
- ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
- : __DIR__ . '/../../../maintenance/Maintenance.php' );
-
-/**
- * Maintenance script that removes invalid target page
- *
- * @ingroup Maintenance
- */
-class removeInvalidTargetPage extends Maintenance {
-
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Delete invalid records from echo_target_page";
- $this->setBatchSize( 500 );
- }
-
- public function execute() {
- global $wgEchoCluster;
-
- $dbFactory = MWEchoDbFactory::newFromDefault();
- $dbw = $dbFactory->getEchoDb( DB_MASTER );
- $dbr = $dbFactory->getEchoDb( DB_SLAVE );
-
- $count = $this->mBatchSize;
- $userId = $eventId = 0;
-
- while ( $count == $this->mBatchSize ) {
- $res = $dbr->select(
- array(
- 'echo_target_page',
- 'echo_notification'
- ),
- array(
- 'etp_page',
- 'etp_user',
- 'etp_event',
- 'notification_read_timestamp',
- 'notification_bundle_base'
- ),
- array(
- "etp_user > $userId OR ( etp_user = $userId AND etp_event > $eventId )"
- ),
- __METHOD__,
- array(
- 'ORDER BY' => 'etp_user, etp_event',
- 'LIMIT' => $this->mBatchSize
- ),
- array(
- 'echo_notification' => array(
- 'LEFT JOIN',
- 'notification_event=etp_event AND notification_user = etp_user'
- ),
- )
- );
- if ( !$res ) {
- $this->error( 'Could not select record from echo_target_page.', 1 );
- }
-
- $pageIds = $titles = array();
- foreach ( $res as $row ) {
- $pageIds[$row->etp_page] = $row->etp_page;
- }
- if ( $pageIds ) {
- foreach ( Title::newFromIds( $pageIds ) as $title ) {
- $titles[$title->getArticleID()] = true;
- }
- }
-
- // Reset the head of the iterator
- $res->rewind();
- $count = $invalidCount = 0;
- foreach( $res as $row ) {
- if (
- // Delete if notification is read
- $row->notification_read_timestamp
- // Delete if this is no longer a base event and
- // it's not deleted from echo_target_page
- || $row->notification_bundle_base == '0'
- // Delete if title is no longer valid
- || !isset( $titles[$row->etp_page] )
- ) {
- $dbw->delete(
- 'echo_target_page',
- array(
- 'etp_user' => $row->etp_user,
- 'etp_event' => $row->etp_event
- ),
- __METHOD__
- );
- $invalidCount++;
- }
-
- $userId = $row->etp_user;
- $eventId = $row->etp_event;
- $count++;
- };
-
- $this->output( "Deleted $invalidCount records from $count records\n" );
- $dbFactory->waitForSlaves();
- }
- }
-}
-
-$maintClass = 'removeInvalidTargetPage'; // Tells it to run the class
-require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/Echo/maintenance/removeOrphanedEvents.php b/Echo/maintenance/removeOrphanedEvents.php
new file mode 100644
index 00000000..eb0cba23
--- /dev/null
+++ b/Echo/maintenance/removeOrphanedEvents.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Remove rows from echo_event that don't have corresponding rows in echo_notification.
+ *
+ * @ingroup Maintenance
+ */
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
+ ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
+
+/**
+ * Maintenance script that removes orphaned event rows
+ *
+ * @ingroup Maintenance
+ */
+class RemoveOrphanedEvents extends LoggedUpdateMaintenance {
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = "Remove rows from echo_event that don't have corresponding rows in echo_notification";
+
+ $this->setBatchSize( 500 );
+
+ $this->requireExtension( 'Echo' );
+ }
+
+ public function getUpdateKey() {
+ return __CLASS__;
+ }
+
+ public function doDBUpdates() {
+ $dbFactory = MWEchoDbFactory::newFromDefault();
+ $dbw = $dbFactory->getEchoDb( DB_MASTER );
+ $dbr = $dbFactory->getEchoDb( DB_SLAVE );
+ $iterator = new BatchRowIterator(
+ $dbr,
+ [ 'echo_event', 'echo_notification' ],
+ 'event_id',
+ $this->mBatchSize
+ );
+ $iterator->addJoinConditions( [
+ 'echo_notification' => [ 'LEFT JOIN', 'notification_event=event_id' ]
+ ] );
+ $iterator->addConditions( [
+ 'notification_user' => null
+ ] );
+
+ $this->output( "Removing orphaned echo_event rows...\n" );
+
+ $processed = 0;
+ foreach ( $iterator as $batch ) {
+ $ids = [];
+ foreach ( $batch as $row ) {
+ $ids[] = $row->event_id;
+ }
+ $dbw->delete(
+ 'echo_event',
+ [ 'event_id' => $ids ]
+
+ );
+ $processed += $dbw->affectedRows();
+ $this->output( "Deleted $processed orphaned rows.\n" );
+ $dbFactory->waitForSlaves();
+ }
+
+ return true;
+ }
+}
+
+$maintClass = 'RemoveOrphanedEvents';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Echo/maintenance/testDiscussionParser.php b/Echo/maintenance/testDiscussionParser.php
index d3564469..4aef748e 100644
--- a/Echo/maintenance/testDiscussionParser.php
+++ b/Echo/maintenance/testDiscussionParser.php
@@ -2,9 +2,9 @@
$IP = getenv( 'MW_INSTALL_PATH' );
if ( $IP === false ) {
- $IP = dirname( __FILE__ ) . '/../../..';
+ $IP = __DIR__ . '/../../..';
}
-require_once( "$IP/maintenance/Maintenance.php" );
+require_once "$IP/maintenance/Maintenance.php";
class TestDiscussionParser extends Maintenance {
public function __construct() {
@@ -12,6 +12,8 @@ class TestDiscussionParser extends Maintenance {
$this->mDescription = "Takes enwiki revision IDs and attempts to identify interested users";
$this->addArg( 'revisions', 'Revision IDs, separated by commas', true /*required*/ );
+
+ $this->requireExtension( 'Echo' );
}
public function execute() {
@@ -20,18 +22,18 @@ class TestDiscussionParser extends Maintenance {
$revisions = explode( ',', $this->getArg( 0 ) );
// Retrieve original revisions and their predecessors
- $requestData = array(
+ $requestData = [
'format' => 'php',
'action' => 'query',
'prop' => 'revisions',
'revids' => implode( '|', $revisions ),
- );
+ ];
$originalData = Http::post(
$apiURL,
- array(
+ [
'postData' => $requestData,
- )
+ ]
);
$data = unserialize( $originalData );
@@ -45,7 +47,7 @@ class TestDiscussionParser extends Maintenance {
$revid = $page['revisions'][0]['revid'];
- $newRequest = array(
+ $newRequest = [
'format' => 'php',
'action' => 'query',
'prop' => 'revisions',
@@ -53,13 +55,13 @@ class TestDiscussionParser extends Maintenance {
'rvstartid' => $revid,
'rvlimit' => 2,
'rvprop' => 'ids|content|user',
- );
+ ];
$newData = Http::post(
$apiURL,
- array(
+ [
'postData' => $newRequest,
- )
+ ]
);
$newData = unserialize( $newData );
@@ -88,4 +90,4 @@ class TestDiscussionParser extends Maintenance {
}
$maintClass = "TestDiscussionParser";
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Echo/maintenance/updateEchoSchemaForSuppression.php b/Echo/maintenance/updateEchoSchemaForSuppression.php
index 1f186f12..c6a6118c 100644
--- a/Echo/maintenance/updateEchoSchemaForSuppression.php
+++ b/Echo/maintenance/updateEchoSchemaForSuppression.php
@@ -5,58 +5,59 @@
*
* @ingroup Maintenance
*/
-require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
- : __DIR__ . '/../../../maintenance/Maintenance.php' );
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
/**
* Maintenance script that populates the event_page_id column of echo_event
*
* @ingroup Maintenance
*/
-class UpdateEchoSchemaForSuppression extends Maintenance {
+class UpdateEchoSchemaForSuppression extends LoggedUpdateMaintenance {
/**
- * @var $table string The table to update
+ * @var string The table to update
*/
protected $table = 'echo_event';
/**
- * @var $idField string The primary key column of the table to update
+ * @var string The primary key column of the table to update
*/
protected $idField = 'event_id';
public function __construct() {
parent::__construct();
$this->setBatchSize( 500 );
+ $this->requireExtension( 'Echo' );
}
- public function execute() {
+ public function getUpdateKey() {
+ return __CLASS__;
+ }
+
+ public function doDBUpdates() {
global $wgEchoCluster;
- $reader = new EchoBatchRowIterator( MWEchoDbFactory::getDB( DB_SLAVE ), $this->table, $this->idField, $this->mBatchSize );
- $reader->addConditions( array(
+ $reader = new BatchRowIterator( MWEchoDbFactory::getDB( DB_SLAVE ), $this->table, $this->idField, $this->mBatchSize );
+ $reader->addConditions( [
"event_page_title IS NOT NULL",
"event_page_id" => null,
- ) );
+ ] );
+ $reader->setFetchColumns( [ 'event_page_namespace', 'event_page_title', 'event_extra', 'event_type' ] );
- $updater = new EchoBatchRowUpdate(
+ $updater = new BatchRowUpdate(
$reader,
- new EchoBatchRowWriter( MWEchoDbFactory::getDB( DB_MASTER ), $this->table, $wgEchoCluster ),
+ new BatchRowWriter( MWEchoDbFactory::getDB( DB_MASTER ), $this->table, $wgEchoCluster ),
new EchoSuppressionRowUpdateGenerator
);
- $updater->setOutput( array( $this, '__internalOutput' ) );
+ $updater->setOutput( function ( $text ) {
+ $this->output( $text );
+ } );
$updater->execute();
- }
-
- /**
- * Internal use only. parent::output() is a protected method, only way to access it from
- * a callback in php5.3 is to make a public function. In 5.4 can replace with a Closure.
- */
- public function __internalOutput( $text ) {
- $this->output( $text );
+ return true;
}
}
$maintClass = 'UpdateEchoSchemaForSuppression'; // Tells it to run the class
-require_once ( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Echo/modules/api/mw.echo.api.APIHandler.js b/Echo/modules/api/mw.echo.api.APIHandler.js
new file mode 100644
index 00000000..ad45ceaf
--- /dev/null
+++ b/Echo/modules/api/mw.echo.api.APIHandler.js
@@ -0,0 +1,273 @@
+( function ( mw, $ ) {
+ /**
+ * Abstract notification API handler
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {mw.Api} api
+ * @param {Object} [config] Configuration object
+ * @cfg {number} [limit=25] The limit on how many notifications to fetch
+ * @cfg {string} [userLang=mw.config.get( 'wgUserLanguage' )] User language. Defaults
+ * to the default user language configuration settings.
+ */
+ mw.echo.api.APIHandler = function MwEchoApiAPIHandler( api, config ) {
+ config = config || {};
+
+ this.fetchNotificationsPromise = {};
+ this.apiErrorState = {};
+
+ this.limit = config.limit || 25;
+ this.userLang = config.userLang || mw.config.get( 'wgUserLanguage' );
+
+ this.api = api;
+
+ // Map the logical type to the type
+ // that the API recognizes
+ this.normalizedType = {
+ message: 'message',
+ alert: 'alert',
+ all: 'message|alert'
+ };
+
+ // Parameters that are sent through
+ // to the 'fetch notification' promise
+ // per type
+ this.typeParams = {
+ message: {},
+ alert: {},
+ all: {}
+ };
+ };
+
+ /* Setup */
+
+ OO.initClass( mw.echo.api.APIHandler );
+
+ /**
+ * Fetch notifications from the API.
+ *
+ * @param {string} type Notification type
+ * @param {Object} [overrideParams] An object defining parameters to override in the API
+ * fetching call.
+ * @return {jQuery.Promise} A promise that resolves with an object containing the
+ * notification items
+ */
+ mw.echo.api.APIHandler.prototype.fetchNotifications = null;
+
+ /**
+ * Send a general query to the API. This is mostly for dynamic actions
+ * where other extensions may set up API actions that are unique and
+ * unanticipated.
+ *
+ * @param {Object} data Data object about the operation.
+ * @param {string} [data.tokenType=csrf] Token type, 'csrf', 'watch', etc
+ * @param {Object} [data.params] Parameters to pass to the API call
+ * @return {jQuery.Promise} Promise that is resolved when the action
+ * is complete
+ */
+ mw.echo.api.APIHandler.prototype.queryAPI = function ( data ) {
+ return this.api.postWithToken( data.tokenType || 'csrf', data.params );
+ };
+
+ /**
+ * Fetch all pages with unread notifications in them per wiki
+ *
+ * @param {string|string[]} [sources=*] Requested sources. If not given
+ * or if a '*' is given, all available sources will be queried
+ * @return {jQuery.Promise} Promise that is resolved with an object
+ * of pages with the number of unread notifications per wiki
+ */
+ mw.echo.api.APIHandler.prototype.fetchUnreadNotificationPages = function ( sources ) {
+ var params = {
+ action: 'query',
+ meta: 'unreadnotificationpages',
+ uselang: this.userLang,
+ unpgrouppages: true
+ };
+
+ if ( !sources || sources === '*' ) {
+ params.unpwikis = '*';
+ } else {
+ sources = Array.isArray( sources ) ? sources : [ sources ];
+ params.unpwikis = sources.join( '|' );
+ }
+
+ return this.api.get( params );
+ };
+
+ /**
+ * Check if the given source is local
+ *
+ * @param {string|string[]} sources Source names
+ * @return {boolean} Source is local
+ */
+ mw.echo.api.APIHandler.prototype.isSourceLocal = function ( sources ) {
+ return Array.isArray( sources ) ?
+ (
+ sources.indexOf( 'local' ) !== -1 ||
+ sources.indexOf( mw.config.get( 'wgDBname' ) ) !== -1
+ ) :
+ (
+ sources === 'local' ||
+ sources === mw.config.get( 'wgDBname' )
+ );
+ };
+
+ /**
+ * Create a new fetchNotifications promise that queries the API and overrides
+ * the cached promise.
+ *
+ * @param {string} type Notification type
+ * @param {string[]} [sources] An array of sources to query
+ * @param {Object} [overrideParams] An object defining parameters to override in the API
+ * fetching call.
+ * @return {jQuery.Promise} Promise that is resolved when notifications are
+ * fetched from the API.
+ */
+ mw.echo.api.APIHandler.prototype.createNewFetchNotificationPromise = function ( type, sources, overrideParams ) {
+ var fetchNotifPromise,
+ fetchingSource = 'local',
+ me = this,
+ params = $.extend( {
+ action: 'query',
+ formatversion: 2,
+ meta: 'notifications',
+ notsections: this.normalizedType[ type ],
+ notformat: 'model',
+ notlimit: this.limit,
+ notprop: 'list|count|seenTime',
+ uselang: this.userLang
+ }, this.getTypeParams( type ) );
+
+ if ( !this.isSourceLocal( sources ) ) {
+ params.notwikis = sources.join( '|' );
+ params.notfilter = '!read';
+ fetchingSource = 'foreign';
+ }
+
+ // Initialize the nested value if it doesn't yet exist
+ this.fetchNotificationsPromise[ type ] = this.fetchNotificationsPromise[ type ] || {};
+ me.apiErrorState[ type ] = me.apiErrorState[ type ] || {};
+
+ // Reset cached values
+ this.fetchNotificationsPromise[ type ][ fetchingSource ] = null;
+ this.apiErrorState[ type ][ fetchingSource ] = false;
+
+ // Create the fetch promise
+ fetchNotifPromise = this.api.get( $.extend( true, params, overrideParams ) );
+
+ // Only cache promises that don't have override params in them
+ if ( !overrideParams ) {
+ this.fetchNotificationsPromise[ type ][ fetchingSource ] = fetchNotifPromise;
+ }
+
+ return fetchNotifPromise
+ .fail( function () {
+ // Mark API error state
+ me.apiErrorState[ type ][ fetchingSource ] = true;
+ } );
+ };
+
+ /**
+ * Update the seen timestamp
+ *
+ * @param {string|string[]} [types] Notification type 'message', 'alert' or [ 'message', 'alert' ].
+ * @return {jQuery.Promise} A promise that resolves with the seen timestamp, as a full UTC
+ * ISO 8601 timestamp.
+ */
+ mw.echo.api.APIHandler.prototype.updateSeenTime = null;
+
+ /**
+ * Mark all notifications as read
+ *
+ * @param {string|string[]} type Notification type 'message', 'alert' or 'all'.
+ * @return {jQuery.Promise} A promise that resolves when all notifications
+ * are marked as read.
+ */
+ mw.echo.api.APIHandler.prototype.markAllRead = null;
+
+ /**
+ * Mark multiple notification items as read using specific IDs
+ *
+ * @abstract
+ * @param {string[]} itemIdArray An array of notification item IDs
+ * @param {boolean} [isRead] Item's new read state; true for marking the item
+ * as read, false for marking the item as unread
+ * @return {jQuery.Promise} A promise that resolves when all given notifications
+ * are marked as read.
+ */
+ mw.echo.api.APIHandler.prototype.markItemsRead = null;
+
+ /**
+ * Update the read status of a notification item in the API
+ *
+ * @param {string} itemId Item id
+ * @param {boolean} [isRead] Item's new read state; true for marking the item
+ * as read, false for marking the item as unread
+ * @return {jQuery.Promise} A promise that resolves when the notifications
+ * are marked as read.
+ */
+ mw.echo.api.APIHandler.prototype.markItemRead = function ( itemId, isRead ) {
+ return this.markItemsRead( [ itemId ], isRead );
+ };
+
+ /**
+ * Query the API for unread count of the notifications in this model
+ *
+ * @param {string} type Notification type 'message', 'alert' or 'all'.
+ * @return {jQuery.Promise} jQuery promise that's resolved when the unread count is fetched
+ * and the badge label is updated.
+ */
+ mw.echo.api.APIHandler.prototype.fetchUnreadCount = null;
+
+ /**
+ * Check whether the model has an API error state flagged
+ *
+ * @param {string} type Notification type, 'alert', 'message' or 'all'
+ * @param {string|string[]} sources Source names
+ * @return {boolean} The model is in API error state
+ */
+ mw.echo.api.APIHandler.prototype.isFetchingErrorState = function ( type, sources ) {
+ var fetchingSource = 'local';
+
+ if ( !this.isSourceLocal( sources ) ) {
+ fetchingSource = 'foreign';
+ }
+ return !!( this.apiErrorState[ type ] && this.apiErrorState[ type ][ fetchingSource ] );
+ };
+
+ /**
+ * Return the fetch notifications promise
+ *
+ * @param {string} type Notification type, 'alert', 'message' or 'all'
+ * @param {string|string[]} [sources] A name of a source or an array of sources to query
+ * @param {Object} [overrideParams] An object defining parameters to override in the API
+ * fetching call.
+ * @return {jQuery.Promise} Promise that is resolved when notifications are
+ * fetched from the API.
+ */
+ mw.echo.api.APIHandler.prototype.getFetchNotificationPromise = function ( type, sources, overrideParams ) {
+ var fetchingSource = 'local';
+
+ if ( !this.isSourceLocal( sources ) ) {
+ fetchingSource = 'foreign';
+ }
+ if ( overrideParams || !this.fetchNotificationsPromise[ type ] || !this.fetchNotificationsPromise[ type ][ fetchingSource ] ) {
+ this.createNewFetchNotificationPromise( type, sources, overrideParams );
+ }
+ return this.fetchNotificationsPromise[ type ][ fetchingSource ];
+ };
+
+ /**
+ * Get the extra parameters for fetching notifications for a given
+ * notification type.
+ *
+ * @param {string} type Notification type
+ * @return {Object} Extra API parameters for fetch notifications
+ */
+ mw.echo.api.APIHandler.prototype.getTypeParams = function ( type ) {
+ return this.typeParams[ type ];
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/api/mw.echo.api.EchoApi.js b/Echo/modules/api/mw.echo.api.EchoApi.js
new file mode 100644
index 00000000..44992183
--- /dev/null
+++ b/Echo/modules/api/mw.echo.api.EchoApi.js
@@ -0,0 +1,339 @@
+( function ( mw, $ ) {
+ /**
+ * A class defining Echo API instructions and network operations
+ *
+ * @class
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ * @cfg {number} [limit=25] Number of notifications to fetch
+ */
+ mw.echo.api.EchoApi = function MwEchoApiEchoApi( config ) {
+ config = config || {};
+
+ this.network = new mw.echo.api.NetworkHandler( config );
+
+ this.fetchingPromise = null;
+ this.limit = config.limit || 25;
+ this.fetchingPrioritizer = new mw.echo.api.PromisePrioritizer();
+ };
+
+ OO.initClass( mw.echo.api.EchoApi );
+
+ /**
+ * Register a set of foreign sources.
+ *
+ * @param {Object} sources Object mapping source names to config objects
+ * @param {boolean} [unreadOnly=false] Fetch only unread notifications
+ * @param {number} [limit] Specific limit of notifications. Defaults to
+ * the default limit stated in the class.
+ */
+ mw.echo.api.EchoApi.prototype.registerForeignSources = function ( sources, unreadOnly, limit ) {
+ var s;
+
+ limit = limit || this.limit;
+
+ for ( s in sources ) {
+ this.network.setApiHandler( s, new mw.echo.api.ForeignAPIHandler( sources[ s ].url, {
+ unreadOnly: !!unreadOnly,
+ limit: limit
+ } ) );
+ }
+ };
+
+ /**
+ * Register a set of local sources.
+ *
+ * @param {string[]} sources An array of source names
+ */
+ mw.echo.api.EchoApi.prototype.registerLocalSources = function ( sources ) {
+ var i,
+ localHandler = this.network.getApiHandler( 'local' );
+
+ for ( i = 0; i < sources.length; i++ ) {
+ this.network.setApiHandler( sources[ i ], localHandler );
+ }
+ };
+
+ /**
+ * Fetch all pages with unread notifications in them per wiki
+ *
+ * @param {string[]} [sources=all] Requested sources
+ * @return {jQuery.Promise} Promise that is resolved with an object
+ * of pages with the number of unread notifications per wiki
+ */
+ mw.echo.api.EchoApi.prototype.fetchUnreadNotificationPages = function ( sources ) {
+ return this.network.getApiHandler( 'local' ).fetchUnreadNotificationPages( sources )
+ .then( function ( data ) {
+ return OO.getProp( data, 'query', 'unreadnotificationpages' );
+ } );
+ };
+
+ /**
+ * Fetch notifications from a given source with given filters
+ *
+ * @param {string} type Notification type to fetch: 'alert', 'message', or 'all'
+ * @param {string} [source] The source from which to fetch the notifications.
+ * If not given, the local notifications will be fetched.
+ * @param {Object} [filters] Filter values
+ * @return {jQuery.Promise} Promise that is resolved with all notifications for the
+ * requested types.
+ */
+ mw.echo.api.EchoApi.prototype.fetchFilteredNotifications = function ( type, source, filters ) {
+ source = source || 'local';
+
+ if ( source === 'local' ) {
+ return this.fetchNotifications( type, source, true, filters );
+ } else {
+ return this.fetchNotificationsFromRemoteSource( type, source, true, filters );
+ }
+ };
+
+ /**
+ * Convert the filter object to the relevant API parameters.
+ *
+ * @param {Object} [filterObject] The filter object
+ * @param {string} [filterObject.continue] A continue variable
+ * defining the offset to fetch notifications
+ * @param {string} [filterObject.readState] Notification read
+ * state, 'all', 'read' or 'unread'
+ * @param {boolean} [filterObject.unreadFirst] Fetch unread notifications
+ * first in the sorting order.
+ * @param {boolean} [filterObject.bundle] Bundle local notifications
+ * @param {string|string[]} [filterObject.titles] Requested titles. To request notifications with no title,
+ * use null (standalone or as an array element).
+ * @return {Object} API parameter definitions to override
+ */
+ mw.echo.api.EchoApi.prototype.convertFiltersToAPIParams = function ( filterObject ) {
+ var titles,
+ overrideParams = {};
+
+ filterObject = filterObject || {};
+
+ if ( filterObject.continue ) {
+ overrideParams.notcontinue = filterObject.continue;
+ }
+
+ if ( filterObject.unreadFirst ) {
+ overrideParams.notunreadfirst = 1;
+ }
+
+ if ( filterObject.bundle ) {
+ overrideParams.notbundle = 1;
+ }
+
+ if ( filterObject.readState && filterObject.readState !== 'all' ) {
+ overrideParams.notfilter = filterObject.readState === 'read' ?
+ 'read' :
+ '!read';
+ }
+
+ if ( filterObject.titles ) {
+ titles = Array.isArray( filterObject.titles ) ? filterObject.titles : [ filterObject.titles ];
+ if ( titles.indexOf( null ) !== -1 ) {
+ // Map null to '[]'
+ titles.splice( titles.indexOf( null ), 1, '[]' );
+ }
+ overrideParams.nottitles = titles.join( '|' );
+ }
+
+ return overrideParams;
+ };
+
+ /**
+ * Fetch remote notifications from a given source. This skips the local fetching that is
+ * usually done and calls the remote wiki directly.
+ *
+ * @param {string} type Notification type to fetch: 'alert', 'message', or 'all'
+ * @param {string|string[]} [source] The source from which to fetch the notifications.
+ * If not given, the local notifications will be fetched.
+ * @param {boolean} [isForced] Force a refresh on the fetch notifications promise
+ * @param {Object} [filters] Filter values
+ * @return {jQuery.Promise} Promise that is resolved with all notifications for the
+ * requested types.
+ */
+ mw.echo.api.EchoApi.prototype.fetchNotificationsFromRemoteSource = function ( type, source, isForced, filters ) {
+ var handler = this.network.getApiHandler( source );
+
+ if ( !handler ) {
+ return $.Deferred().reject().promise();
+ }
+
+ return this.fetchingPrioritizer.prioritize( handler.fetchNotifications(
+ type,
+ // For the remote source, we are fetching 'local' notifications
+ 'local',
+ !!isForced,
+ this.convertFiltersToAPIParams( filters )
+ ) )
+ .then( function ( result ) {
+ return OO.getProp( result.query, 'notifications' );
+ } );
+ };
+
+ /**
+ * Fetch notifications from the server based on type
+ *
+ * @param {string} type Notification type to fetch: 'alert', 'message', or 'all'
+ * @param {string|string[]} [sources] The source from which to fetch the notifications.
+ * If not given, the local notifications will be fetched.
+ * @param {boolean} [isForced] Force a refresh on the fetch notifications promise
+ * @param {Object} [filters] Filter values
+ * @return {jQuery.Promise} Promise that is resolved with all notifications for the
+ * requested types.
+ */
+ mw.echo.api.EchoApi.prototype.fetchNotifications = function ( type, sources, isForced, filters ) {
+ sources = Array.isArray( sources ) ?
+ sources :
+ sources ?
+ [ sources ] :
+ 'local';
+
+ return this.fetchingPrioritizer.prioritize( this.network.getApiHandler( 'local' ).fetchNotifications(
+ type,
+ sources,
+ isForced,
+ this.convertFiltersToAPIParams( filters )
+ ) )
+ .then( function ( result ) {
+ return OO.getProp( result.query, 'notifications' );
+ } );
+ };
+
+ /**
+ * Fetch notifications from several sources
+ *
+ * @param {string[]} sourceArray An array of sources to fetch from the group
+ * @param {string} type Notification type
+ * @param {boolean} bundle Bundle local notifications
+ * @return {jQuery.Promise} A promise that resolves with an object that maps wiki
+ * names to an array of their items' API data objects.
+ */
+ mw.echo.api.EchoApi.prototype.fetchNotificationGroups = function ( sourceArray, type, bundle ) {
+ var overrideParams = { notcrosswikisummary: false, notbundle: bundle };
+ return this.network.getApiHandler( 'local' ).fetchNotifications( type, sourceArray, true, overrideParams )
+ .then( function ( result ) {
+ var i,
+ items = OO.getProp( result, 'query', 'notifications', 'list' ),
+ groups = {};
+
+ // Split the items to groups
+ for ( i = 0; i < items.length; i++ ) {
+ groups[ items[ i ].wiki ] = groups[ items[ i ].wiki ] || [];
+ groups[ items[ i ].wiki ].push( items[ i ] );
+ }
+
+ return groups;
+ } );
+ };
+
+ /**
+ * Mark items as read in the API.
+ *
+ * @param {string[]} itemIds An array of item IDs to mark as read
+ * @param {string} source The source that these items belong to
+ * @param {boolean} [isRead] The read state of the item; true for marking the
+ * item as read, false for marking the item as unread
+ * @return {jQuery.Promise} A promise that is resolved when the operation
+ * is complete, with the number of unread notifications still remaining
+ * for that type in the given source
+ */
+ mw.echo.api.EchoApi.prototype.markItemsRead = function ( itemIds, source, isRead ) {
+ return this.network.getApiHandler( source ).markItemsRead( itemIds, isRead );
+ };
+
+ /**
+ * Mark all notifications for a given type as read in the given source.
+ *
+ * @param {string} source Symbolic name of notifications source
+ * @param {string} type Notifications type
+ * @return {jQuery.Promise} A promise that is resolved when the operation
+ * is complete, with the number of unread notifications still remaining
+ * for that type in the given source
+ */
+ mw.echo.api.EchoApi.prototype.markAllRead = function ( source, type ) {
+ return this.network.getApiHandler( source ).markAllRead( type );
+ };
+
+ /**
+ * Fetch the number of unread notifications for the given type in the given
+ * source.
+ *
+ * @param {string} source Notifications source
+ * @param {string} type Notification type
+ * @param {boolean} [localOnly] Fetches only the count of local notifications,
+ * and ignores cross-wiki notifications.
+ * @return {jQuery.Promise} A promise that is resolved with the number of
+ * unread notifications for the given type and source.
+ */
+ mw.echo.api.EchoApi.prototype.fetchUnreadCount = function ( source, type, localOnly ) {
+ return this.network.getApiHandler( source ).fetchUnreadCount( type, localOnly );
+ };
+
+ /**
+ * Update the seenTime property for the given type.
+ * We only need to update this in a single source for the seenTime
+ * to be updated globally - but we will let the consumer of
+ * this method override the choice of which source to update.
+ *
+ * @param {string} [type='alert,message'] Notification type
+ * @param {string} [source='local'] Notification source
+ * @return {jQuery.Promise} A promise that is resolved when the operation is complete.
+ */
+ mw.echo.api.EchoApi.prototype.updateSeenTime = function ( type, source ) {
+ source = source || 'local';
+ type = type || [ 'alert', 'message' ];
+
+ return this.network.getApiHandler( source ).updateSeenTime( type );
+ };
+
+ /**
+ * Send a general query to the API. This is mostly for dynamic actions
+ * where other extensions may set up API actions that are unique and
+ * unanticipated.
+ *
+ * @param {Object} params API parameters
+ * @param {string} [source='local'] Requested source to query
+ * @return {jQuery.Promise} Promise that is resolved when the action
+ * is complete
+ */
+ mw.echo.api.EchoApi.prototype.queryAPI = function ( params, source ) {
+ source = source || 'local';
+ return this.network.getApiHandler( source )
+ .queryAPI( params );
+ };
+
+ /**
+ * Check whether the API promise for fetch notification is in an error
+ * state for the given source and notification type.
+ *
+ * @param {string} source Notification source.
+ * @param {string} type Notification type
+ * @return {boolean} The API response for fetching notification has
+ * resolved in an error state, or is rejected.
+ */
+ mw.echo.api.EchoApi.prototype.isFetchingErrorState = function ( source, type ) {
+ return this.network.getApiHandler( source ).isFetchingErrorState( type, [ source ] );
+ };
+
+ /**
+ * Get the fetch notifications promise active for the current source and type.
+ *
+ * @param {string} source Notification source.
+ * @param {string} type Notification type
+ * @return {jQuery.Promise} Promise that is resolved when notifications are
+ * fetched from the API.
+ */
+ mw.echo.api.EchoApi.prototype.getFetchNotificationPromise = function ( source, type ) {
+ return this.network.getApiHandler( source ).getFetchNotificationPromise( type );
+ };
+
+ /**
+ * Get the set limit for fetching notifications per request
+ *
+ * @return {number} Limit of notifications per request
+ */
+ mw.echo.api.EchoApi.prototype.getLimit = function () {
+ return this.limit;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/api/mw.echo.api.ForeignAPIHandler.js b/Echo/modules/api/mw.echo.api.ForeignAPIHandler.js
new file mode 100644
index 00000000..f80ea803
--- /dev/null
+++ b/Echo/modules/api/mw.echo.api.ForeignAPIHandler.js
@@ -0,0 +1,44 @@
+( function ( mw, $ ) {
+ /**
+ * Foreign notification API handler
+ *
+ * @class
+ * @extends mw.echo.api.LocalAPIHandler
+ *
+ * @constructor
+ * @param {string} apiUrl A url for the access point of the
+ * foreign API.
+ * @param {Object} [config] Configuration object
+ * @cfg {boolean} [unreadOnly] Whether this handler should request unread
+ * notifications by default.
+ */
+ mw.echo.api.ForeignAPIHandler = function MwEchoApiForeignAPIHandler( apiUrl, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.api.ForeignAPIHandler.parent.call( this, config );
+
+ this.api = new mw.ForeignApi( apiUrl );
+ this.unreadOnly = config.unreadOnly !== undefined ? !!config.unreadOnly : false;
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.echo.api.ForeignAPIHandler, mw.echo.api.LocalAPIHandler );
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.api.ForeignAPIHandler.prototype.getTypeParams = function ( type ) {
+ var params = {
+ // Backwards compatibility
+ notforn: 1
+ };
+
+ if ( this.unreadOnly ) {
+ params = $.extend( {}, params, { notfilter: '!read' } );
+ }
+
+ return $.extend( {}, this.typeParams[ type ], params );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/api/mw.echo.api.LocalAPIHandler.js b/Echo/modules/api/mw.echo.api.LocalAPIHandler.js
new file mode 100644
index 00000000..a33091ac
--- /dev/null
+++ b/Echo/modules/api/mw.echo.api.LocalAPIHandler.js
@@ -0,0 +1,130 @@
+( function ( mw, $ ) {
+ /**
+ * Notification API handler
+ *
+ * @class
+ * @extends mw.echo.api.APIHandler
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ */
+ mw.echo.api.LocalAPIHandler = function MwEchoApiLocalAPIHandler( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.api.LocalAPIHandler.parent.call( this,
+ new mw.Api( { ajax: { cache: false } } ),
+ config
+ );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.echo.api.LocalAPIHandler, mw.echo.api.APIHandler );
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.api.LocalAPIHandler.prototype.fetchNotifications = function ( type, source, isForced, overrideParams ) {
+ if ( overrideParams ) {
+ return this.createNewFetchNotificationPromise( type, source, overrideParams );
+ } else if ( isForced || this.isFetchingErrorState( type, source ) ) {
+ // Force new promise
+ return this.createNewFetchNotificationPromise( type, source, overrideParams );
+ }
+
+ return this.getFetchNotificationPromise( type, source, overrideParams );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.api.LocalAPIHandler.prototype.updateSeenTime = function ( type ) {
+ type = Array.isArray( type ) ? type : [ type ];
+
+ return this.api.postWithToken( 'csrf', {
+ action: 'echomarkseen',
+ type: type.length === 1 ? type[ 0 ] : 'all',
+ timestampFormat: 'ISO_8601'
+ } )
+ .then( function ( data ) {
+ return data.query.echomarkseen.timestamp;
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.api.LocalAPIHandler.prototype.markAllRead = function ( type ) {
+ type = Array.isArray( type ) ? type : [ type ];
+
+ return this.api.postWithToken( 'csrf', {
+ action: 'echomarkread',
+ sections: type.join( '|' )
+ } )
+ .then( function ( result ) {
+ return OO.getProp( result.query, 'echomarkread', type, 'rawcount' ) || 0;
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.api.LocalAPIHandler.prototype.markItemsRead = function ( itemIdArray, isRead ) {
+ var data = {
+ action: 'echomarkread'
+ };
+
+ if ( isRead ) {
+ data.list = itemIdArray.join( '|' );
+ } else {
+ data.unreadlist = itemIdArray.join( '|' );
+ }
+
+ return this.api.postWithToken( 'csrf', data );
+ };
+
+ /**
+ * Fetch the number of unread notifications.
+ *
+ * @param {string} type Notification type, 'alert', 'message' or 'all'
+ * @param {boolean} [ignoreCrossWiki] Ignore cross-wiki notifications when fetching the count.
+ * If set to false (by default) it counts notifications across all wikis.
+ * @return {jQuery.Promise} Promise which resolves with the unread count
+ */
+ mw.echo.api.LocalAPIHandler.prototype.fetchUnreadCount = function ( type, ignoreCrossWiki ) {
+ var normalizedType = this.normalizedType[ type ],
+ apiData = {
+ action: 'query',
+ meta: 'notifications',
+ notsections: normalizedType,
+ notgroupbysection: 1,
+ notmessageunreadfirst: 1,
+ notlimit: this.limit,
+ notprop: 'count',
+ uselang: this.userLang
+ };
+
+ if ( !ignoreCrossWiki ) {
+ apiData.notcrosswikisummary = 1;
+ }
+
+ return this.api.get( apiData )
+ .then( function ( result ) {
+ if ( type === 'message' || type === 'alert' ) {
+ return OO.getProp( result.query, 'notifications', normalizedType, 'rawcount' ) || 0;
+ } else {
+ return OO.getProp( result.query, 'notifications', 'rawcount' ) || 0;
+ }
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.api.LocalAPIHandler.prototype.getTypeParams = function ( type ) {
+ return $.extend( {}, this.typeParams[ type ], {
+ notcrosswikisummary: 1
+ } );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/api/mw.echo.api.NetworkHandler.js b/Echo/modules/api/mw.echo.api.NetworkHandler.js
new file mode 100644
index 00000000..4875a001
--- /dev/null
+++ b/Echo/modules/api/mw.echo.api.NetworkHandler.js
@@ -0,0 +1,79 @@
+( function ( mw, $ ) {
+ /**
+ * Network handler for echo notifications. Manages multiple APIHandlers
+ * according to their sources.
+ *
+ * @class
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ * @cfg {number} limit Number of notifications to fetch
+ */
+ mw.echo.api.NetworkHandler = function MwEchoApiNetworkHandler( config ) {
+ config = config || {};
+
+ this.handlers = {};
+
+ // Add initial local handler
+ this.setApiHandler( 'local', new mw.echo.api.LocalAPIHandler( { limit: config.limit } ) );
+ };
+
+ /* Setup */
+
+ OO.initClass( mw.echo.api.NetworkHandler );
+
+ /* Static methods */
+ /**
+ * Wait for all promises to finish either with a resolve or reject and
+ * return them to the caller once they do.
+ *
+ * @param {jQuery.Promise[]} promiseArray An array of promises
+ * @return {jQuery.Promise} A promise that resolves when all the promises
+ * finished with some resolution or rejection.
+ */
+ mw.echo.api.NetworkHandler.static.waitForAllPromises = function ( promiseArray ) {
+ var i,
+ promises = promiseArray.slice( 0 ),
+ counter = 0,
+ deferred = $.Deferred(),
+ countPromises = function () {
+ counter++;
+ if ( counter === promises.length ) {
+ deferred.resolve( promises );
+ }
+ };
+
+ if ( !promiseArray.length ) {
+ deferred.resolve();
+ }
+
+ for ( i = 0; i < promises.length; i++ ) {
+ promises[ i ].always( countPromises );
+ }
+
+ return deferred.promise();
+ };
+
+ /* Methods */
+
+ /**
+ * Get the API handler that matches the symbolic name
+ *
+ * @param {string} name Symbolic name of the API handler
+ * @return {mw.echo.api.APIHandler|undefined} API handler, if exists
+ */
+ mw.echo.api.NetworkHandler.prototype.getApiHandler = function ( name ) {
+ return this.handlers[ name ];
+ };
+
+ /**
+ * Set an API handler by passing in an instance of an mw.echo.api.APIHandler subclass directly.
+ *
+ * @param {string} name Symbolic name
+ * @param {mw.echo.api.APIHandler} handler Handler object
+ * @throws {Error} If handler already exists
+ */
+ mw.echo.api.NetworkHandler.prototype.setApiHandler = function ( name, handler ) {
+ this.handlers[ name ] = handler;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/api/mw.echo.api.PromisePrioritizer.js b/Echo/modules/api/mw.echo.api.PromisePrioritizer.js
new file mode 100644
index 00000000..2c7cda7a
--- /dev/null
+++ b/Echo/modules/api/mw.echo.api.PromisePrioritizer.js
@@ -0,0 +1,88 @@
+( function ( mw, $ ) {
+ /**
+ * Promise prioritizer for API actions. The prioritizer takes
+ * a promise at a time, always prioritizing the latest promise and
+ * aborting and ignoring the others.
+ *
+ * This allows us to send multiple promises in quick successions but
+ * trust that we get back only the latest successful request.
+ *
+ * @class
+ *
+ * @constructor
+ */
+ mw.echo.api.PromisePrioritizer = function MwEchoApiPromisePrioritizer() {
+ this.deferred = $.Deferred();
+ this.promise = null;
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.echo.api.PromisePrioritizer );
+
+ /**
+ * Prioritize a promise
+ *
+ * @param {jQuery.Promise|Promise} promise Promise
+ * @return {jQuery.Promise} The main deferred object that resolves
+ * or rejects when the latest promise is resolved or rejected.
+ */
+ mw.echo.api.PromisePrioritizer.prototype.prioritize = function ( promise ) {
+ var previousPromise = this.promise;
+
+ promise
+ .then(
+ this.setSuccess.bind( this, promise ),
+ this.setFailure.bind( this, promise )
+ );
+ this.promise = promise;
+
+ if ( previousPromise && previousPromise.abort ) {
+ previousPromise.abort();
+ }
+
+ return this.deferred.promise();
+ };
+
+ /**
+ * Set success for the promise. Resolve the main deferred object only
+ * if we are dealing with the currently prioritized promise.
+ *
+ * @param {jQuery.Promise} promise The promise that resolved successfully.
+ * The main deferred object is resolved with the result of the
+ * latest prioritized promise.
+ */
+ mw.echo.api.PromisePrioritizer.prototype.setSuccess = function ( promise ) {
+ var prioritizer = this;
+
+ if ( this.promise === promise ) {
+ this.promise.done( function () {
+ prioritizer.deferred.resolve.apply( prioritizer.deferred, arguments );
+
+ prioritizer.promise = null;
+ prioritizer.deferred = $.Deferred();
+ } );
+ }
+ };
+
+ /**
+ * Set failure for the promise. Reject the main deferred object only
+ * if we are dealing with the currently prioritized promise.
+ *
+ * @param {jQuery.Promise} promise The promise that failed.
+ * The main deferred object is rejected with the result of the
+ * latest prioritized promise
+ */
+ mw.echo.api.PromisePrioritizer.prototype.setFailure = function ( promise ) {
+ var prioritizer = this;
+
+ if ( this.promise === promise ) {
+ this.promise.fail( function () {
+ prioritizer.deferred.reject.apply( prioritizer.deferred, arguments );
+
+ prioritizer.promise = null;
+ prioritizer.deferred = $.Deferred();
+ } );
+ }
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/api/mw.echo.api.js b/Echo/modules/api/mw.echo.api.js
new file mode 100644
index 00000000..25abf260
--- /dev/null
+++ b/Echo/modules/api/mw.echo.api.js
@@ -0,0 +1,4 @@
+( function ( mw ) {
+ mw.echo = mw.echo || {};
+ mw.echo.api = mw.echo.api || {};
+}( mediaWiki ) );
diff --git a/Echo/modules/controller/mw.echo.Controller.js b/Echo/modules/controller/mw.echo.Controller.js
new file mode 100644
index 00000000..52c095c1
--- /dev/null
+++ b/Echo/modules/controller/mw.echo.Controller.js
@@ -0,0 +1,791 @@
+( function ( mw, $ ) {
+ /* global moment:false */
+ /**
+ * Controller for Echo notifications
+ *
+ * @param {mw.echo.api.EchoApi} echoApi Echo API
+ * @param {mw.echo.dm.ModelManager} manager Model manager
+ */
+ mw.echo.Controller = function MwEchoController( echoApi, manager ) {
+ this.api = echoApi;
+ this.manager = manager;
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.echo.Controller );
+
+ /**
+ * Update a filter value.
+ * The method accepts a filter name and as many arguments
+ * as needed.
+ *
+ * @param {string} filter Filter name
+ */
+ mw.echo.Controller.prototype.setFilter = function ( filter ) {
+ var filtersModel = this.manager.getFiltersModel(),
+ values = Array.prototype.slice.call( arguments );
+
+ values.shift();
+
+ if ( filter === 'readState' ) {
+ filtersModel.setReadState( values[ 0 ] );
+ } else if ( filter === 'sourcePage' ) {
+ filtersModel.setCurrentSourcePage( values[ 0 ], values[ 1 ] );
+ this.manager.getLocalCounter().setSource( filtersModel.getSourcePagesModel().getCurrentSource() );
+ }
+
+ // Reset pagination
+ this.manager.getPaginationModel().reset();
+ };
+
+ /**
+ * Fetch the next page by date
+ *
+ * @return {jQuery.Promise} A promise that resolves with an object where the keys are
+ * days and the items are item IDs.
+ */
+ mw.echo.Controller.prototype.fetchNextPageByDate = function () {
+ this.manager.getPaginationModel().forwards();
+ return this.fetchLocalNotificationsByDate();
+ };
+
+ /**
+ * Fetch the previous page by date
+ *
+ * @return {jQuery.Promise} A promise that resolves with an object where the keys are
+ * days and the items are item IDs.
+ */
+ mw.echo.Controller.prototype.fetchPrevPageByDate = function () {
+ this.manager.getPaginationModel().backwards();
+ return this.fetchLocalNotificationsByDate();
+ };
+
+ /**
+ * Fetch the first page by date
+ *
+ * @return {jQuery.Promise} A promise that resolves with an object where the keys are
+ * days and the items are item IDs.
+ */
+ mw.echo.Controller.prototype.fetchFirstPageByDate = function () {
+ this.manager.getPaginationModel().setCurrPageIndex( 0 );
+ return this.fetchLocalNotificationsByDate();
+ };
+
+ /**
+ * Fetch unread pages in all wikis and create foreign API sources
+ * as needed.
+ *
+ * @return {jQuery.Promise} A promise that resolves when the page filter
+ * model is updated with the unread notification count per page per wiki
+ */
+ mw.echo.Controller.prototype.fetchUnreadPagesByWiki = function () {
+ var controller = this,
+ filterModel = this.manager.getFiltersModel(),
+ sourcePageModel = filterModel.getSourcePagesModel();
+
+ return this.api.fetchUnreadNotificationPages()
+ .then( function ( data ) {
+ var source,
+ result = {},
+ foreignSources = {};
+
+ for ( source in data ) {
+ if ( source !== mw.config.get( 'wgDBname' ) ) {
+ // Collect sources for API
+ foreignSources[ source ] = data[ source ].source;
+ }
+ result[ source === mw.config.get( 'wgDBname' ) ? 'local' : source ] = data[ source ];
+ }
+
+ // Register the foreign sources in the API
+ controller.api.registerForeignSources( foreignSources, false );
+
+ // Register pages
+ sourcePageModel.setAllSources( result );
+ } );
+ };
+
+ /**
+ * Fetch notifications from the local API and sort them by date.
+ * This method ignores cross-wiki notifications and bundles.
+ *
+ * @param {number} [page] Page number. If not given, it defaults to the current
+ * page.
+ * @return {jQuery.Promise} A promise that resolves with an object where the keys are
+ * days and the items are item IDs.
+ */
+ mw.echo.Controller.prototype.fetchLocalNotificationsByDate = function ( page ) {
+ var controller = this,
+ pagination = this.manager.getPaginationModel(),
+ filters = this.manager.getFiltersModel(),
+ currentSource = filters.getSourcePagesModel().getCurrentSource(),
+ continueValue = pagination.getPageContinue( page || pagination.getCurrPageIndex() );
+
+ pagination.setItemsPerPage( this.api.getLimit() );
+
+ return this.api.fetchFilteredNotifications(
+ this.manager.getTypeString(),
+ currentSource,
+ {
+ 'continue': continueValue,
+ readState: filters.getReadState(),
+ titles: filters.getSourcePagesModel().getGroupedPagesForCurrentTitle()
+ }
+ )
+ .then( function ( data ) {
+ var i, notifData, newNotifData, localizedDate, date, itemModel, symbolicName,
+ maxSeenTime,
+ dateItemIds = {},
+ dateItems = {},
+ models = {};
+
+ data = data || { list: [] };
+
+ // Go over the data
+ for ( i = 0; i < data.list.length; i++ ) {
+ notifData = data.list[ i ];
+
+ // Set source's seenTime
+ // TODO: This query brings up mixed alert and message notifications.
+ // Regularly, each of those will have a different seenTime that is
+ // calculated for each badge, but for this page, both are fetched.
+ // For the moment, we are picking the max seenTime from
+ // either alert or notice and updating both, since the page gives
+ // us a mixed view which will update both seenTime to be the same
+ // anyways.
+ maxSeenTime = data.seenTime.alert < data.seenTime.notice ?
+ data.seenTime.notice : data.seenTime.alert;
+ controller.manager.getSeenTimeModel().setSeenTime(
+ maxSeenTime
+ );
+
+ // Collect common data
+ newNotifData = controller.createNotificationData( notifData );
+ if ( notifData.type !== 'foreign' ) {
+ localizedDate = moment.utc( newNotifData.timestamp ).local().format( 'YYYYMMDD' );
+
+ newNotifData.modelName = 'local_' + localizedDate;
+ newNotifData.source = currentSource;
+
+ // Single notifications
+ itemModel = new mw.echo.dm.NotificationItem(
+ notifData.id,
+ newNotifData
+ );
+
+ dateItems[ localizedDate ] = dateItems[ localizedDate ] || [];
+ dateItems[ localizedDate ].push( itemModel );
+
+ dateItemIds[ localizedDate ] = dateItemIds[ localizedDate ] || [];
+ dateItemIds[ localizedDate ].push( notifData.id );
+ }
+ }
+
+ // Fill in the models
+ for ( date in dateItems ) {
+ symbolicName = 'local_' + date;
+
+ // Set up model
+ models[ symbolicName ] = new mw.echo.dm.NotificationsList( {
+ type: controller.manager.getTypes(),
+ name: symbolicName,
+ source: currentSource,
+ title: date,
+ timestamp: date,
+ sortingCallback: function ( a, b ) {
+ // Reverse sorting. In the special page we want the
+ // items sorted only by timestamp, regardless of
+ // read/unread state
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+
+ // Fallback on IDs
+ return b.getId() - a.getId();
+ }
+ } );
+ models[ symbolicName ].setItems( dateItems[ date ] );
+ }
+
+ // Register local sources
+ controller.api.registerLocalSources( Object.keys( models ) );
+
+ // Update the manager
+ controller.manager.setNotificationModels( models );
+
+ // Update the pagination
+ pagination.setNextPageContinue( data.continue );
+
+ // Update the local counter
+ controller.manager.getLocalCounter().update();
+
+ return dateItemIds;
+ } )
+ .then(
+ null,
+ function ( errCode, errObj ) {
+ return {
+ errCode: errCode,
+ errInfo: OO.getProp( errObj, 'error', 'info' )
+ };
+ }
+ );
+ };
+ /**
+ * Fetch notifications from the local API and update the notifications list.
+ *
+ * @param {boolean} [isForced] Force a renewed fetching promise. If set to false, the
+ * model will request the stored/cached fetching promise from the API. A 'true' value
+ * will force the API to re-request that information from the server and update the
+ * notifications.
+ * @return {jQuery.Promise} A promise that resolves with an array of notification IDs
+ */
+ mw.echo.Controller.prototype.fetchLocalNotifications = function ( isForced ) {
+ var controller = this,
+ // Create a new local list model
+ localListModel = new mw.echo.dm.NotificationsList( {
+ type: this.manager.getTypes()
+ } ),
+ localItems = [],
+ idArray = [];
+
+ this.manager.counter.update();
+
+ // Fetch the notifications from the database
+ // Initially, we're going to have to split the operation
+ // between local notifications and x-wiki notifications
+ // until the backend gives us the x-wiki notifications as
+ // part of the original response.
+ return this.api.fetchNotifications( this.manager.getTypeString(), 'local', !!isForced, { unreadFirst: true, bundle: true } /* filters */ )
+ .then(
+ // Success
+ function ( data ) {
+ var i, notifData, newNotifData,
+ foreignListModel, source, itemModel,
+ allModels = { local: localListModel },
+ createBundledNotification = function ( modelName, rawBundledNotifData ) {
+ var bundleNotifData = controller.createNotificationData( rawBundledNotifData );
+ bundleNotifData.bundled = true;
+ bundleNotifData.modelName = modelName;
+ return new mw.echo.dm.NotificationItem(
+ rawBundledNotifData.id,
+ bundleNotifData
+ );
+ };
+
+ data = data || { list: [] };
+
+ // Go over the data
+ for ( i = 0; i < data.list.length; i++ ) {
+ notifData = data.list[ i ];
+
+ // Set source's seenTime
+ controller.manager.getSeenTimeModel().setSeenTime(
+ controller.getTypes().length > 1 ?
+ (
+ data.seenTime.alert < data.seenTime.notice ?
+ data.seenTime.notice : data.seenTime.alert
+ ) :
+ data.seenTime[ controller.getTypeString() ]
+ );
+
+ // Collect common data
+ newNotifData = controller.createNotificationData( notifData );
+ if ( notifData.type === 'foreign' ) {
+ // x-wiki notification multi-group
+ // We need to request a new list model
+ newNotifData.name = 'xwiki';
+ allModels.xwiki = foreignListModel = new mw.echo.dm.CrossWikiNotificationItem( notifData.id, newNotifData );
+ foreignListModel.setForeign( true );
+
+ // Register foreign sources
+ controller.api.registerForeignSources( notifData.sources, true );
+ // Add the lists according to the sources
+ for ( source in notifData.sources ) {
+ foreignListModel.getList().addGroup(
+ source,
+ notifData.sources[ source ]
+ );
+ }
+
+ } else if ( Array.isArray( newNotifData.bundledNotifications ) ) {
+ // local bundle
+ newNotifData.modelName = 'bundle_' + notifData.id;
+ itemModel = new mw.echo.dm.BundleNotificationItem(
+ notifData.id,
+ newNotifData.bundledNotifications.map( createBundledNotification.bind( null, newNotifData.modelName ) ),
+ newNotifData
+ );
+ allModels[ newNotifData.modelName ] = itemModel;
+ } else {
+ // Local single notifications
+ itemModel = new mw.echo.dm.NotificationItem(
+ notifData.id,
+ newNotifData
+ );
+
+ idArray.push( notifData.id );
+ localItems.push( itemModel );
+
+ if ( newNotifData.bundledNotifications ) {
+ // This means that bundledNotifications is truthy
+ // but is not an array. We should log this in the console
+ mw.log.warn(
+ 'newNotifData.bundledNotifications is expected to be an array,' +
+ 'but instead received "' + $.type( newNotifData.bundledNotifications ) + '"'
+ );
+ }
+ }
+
+ }
+
+ // Refresh local items
+ localListModel.addItems( localItems );
+
+ // Update the controller
+ controller.manager.setNotificationModels( allModels );
+
+ return idArray;
+ },
+ // Failure
+ function ( errCode, errObj ) {
+ if ( !controller.manager.getNotificationModel( 'local' ) ) {
+ // Update the controller
+ controller.manager.setNotificationModels( { local: localListModel } );
+ }
+ return {
+ errCode: errCode,
+ errInfo: OO.getProp( errObj, 'error', 'info' )
+ };
+ }
+ );
+ };
+
+ /**
+ * Create notification data config object for notification items from the
+ * given API data.
+ *
+ * @param {Object} apiData API data
+ * @return {Object} Notification config data object
+ */
+ mw.echo.Controller.prototype.createNotificationData = function ( apiData ) {
+ var utcTimestamp, utcIsoMoment,
+ content = apiData[ '*' ] || {};
+
+ if ( apiData.timestamp.utciso8601 ) {
+ utcTimestamp = apiData.timestamp.utciso8601;
+ } else {
+ // Temporary until c05133283af0486e08c9a97a468bc075e238f2d2 rolls out to the
+ // whole WMF cluster
+ utcIsoMoment = moment.utc( apiData.timestamp.utcunix * 1000 );
+ utcTimestamp = utcIsoMoment.format( 'YYYY-MM-DD[T]HH:mm:ss[Z]' );
+ }
+
+ return {
+ type: apiData.section,
+ foreign: false,
+ source: 'local',
+ count: apiData.count,
+ read: !!apiData.read,
+ seen: (
+ !!apiData.read ||
+ utcTimestamp <= this.manager.getSeenTime()
+ ),
+ timestamp: utcTimestamp,
+ category: apiData.category,
+ content: {
+ header: content.header,
+ compactHeader: content.compactHeader,
+ body: content.body
+ },
+ iconURL: content.iconUrl,
+ iconType: content.icon,
+ primaryUrl: OO.getProp( content.links, 'primary', 'url' ),
+ secondaryUrls: OO.getProp( content.links, 'secondary' ) || [],
+ bundledIds: apiData.bundledIds,
+ bundledNotifications: apiData.bundledNotifications
+ };
+ };
+
+ /**
+ * Mark all items within a given list model as read.
+ *
+ * NOTE: This method is strictly for list models, and will not work for
+ * group list models. To mark items as read in the xwiki model, whether
+ * it is pre-populated or not, please see #markEntireCrossWikiItemAsRead
+ *
+ * @param {string} [modelName] Symbolic name for the model
+ * @param {boolean} [isRead=true]
+ * @return {jQuery.Promise} Promise that is resolved when all items
+ * were marked as read.
+ */
+ mw.echo.Controller.prototype.markEntireListModelRead = function ( modelName, isRead ) {
+ var i, items, item,
+ itemIds = [],
+ model = this.manager.getNotificationModel( modelName || 'local' );
+
+ if ( !model ) {
+ // Model doesn't exist
+ return $.Deferred().reject();
+ }
+
+ // Default to true
+ isRead = isRead === undefined ? true : isRead;
+
+ items = model.getItems();
+ for ( i = 0; i < items.length; i++ ) {
+ item = items[ i ];
+ if ( item.isRead() !== isRead ) {
+ itemIds.push( item.getId() );
+ }
+ }
+
+ return this.markItemsRead( itemIds, model.getName(), isRead );
+ };
+
+ /**
+ * Mark all notifications of a certain source as read, even those that
+ * are not currently displayed.
+ *
+ * @param {string} [source] Notification source. If not given, the currently
+ * selected source is used.
+ * @return {jQuery.Promise} A promise that is resolved after
+ * all notifications for the given source were marked as read
+ */
+ mw.echo.Controller.prototype.markAllRead = function ( source ) {
+ var model,
+ controller = this,
+ itemIds = [],
+ readState = this.manager.getFiltersModel().getReadState(),
+ localCounter = this.manager.getLocalCounter();
+
+ source = source || this.manager.getFiltersModel().getSourcePagesModel().getCurrentSource();
+
+ this.manager.getNotificationsBySource( source ).forEach( function ( notification ) {
+ if ( !notification.isRead() ) {
+ itemIds = itemIds.concat( notification.getAllIds() );
+ notification.toggleRead( true );
+
+ if ( readState === 'unread' ) {
+ // Remove the items if we are in 'unread' filter state
+ model = controller.manager.getNotificationModel( notification.getModelName() );
+ model.discardItems( notification );
+ }
+ }
+ } );
+
+ // Update pagination count
+ this.manager.updateCurrentPageItemCount();
+
+ localCounter.estimateChange( -itemIds.length );
+ return this.api.markAllRead(
+ source,
+ this.getTypes()
+ )
+ .then( this.refreshUnreadCount.bind( this ) )
+ .then( localCounter.update.bind( localCounter, true ) );
+ };
+
+ /**
+ * Mark all local notifications as read
+ *
+ * @return {jQuery.Promise} Promise that is resolved when all
+ * local notifications have been marked as read.
+ */
+ mw.echo.Controller.prototype.markLocalNotificationsRead = function () {
+ var modelName, model,
+ itemIds = [],
+ readState = this.manager.getFiltersModel().getReadState(),
+ modelItems = {};
+
+ this.manager.getLocalNotifications().forEach( function ( notification ) {
+ if ( !notification.isRead() ) {
+ itemIds = itemIds.concat( notification.getAllIds() );
+ notification.toggleRead( true );
+
+ modelName = notification.getModelName();
+ modelItems[ modelName ] = modelItems[ modelName ] || [];
+ modelItems[ modelName ].push( notification );
+ }
+ } );
+
+ // Remove the items if we are in 'unread' filter state
+ if ( readState === 'unread' ) {
+ for ( modelName in modelItems ) {
+ model = this.manager.getNotificationModel( modelName );
+ model.discardItems( modelItems[ modelName ] );
+ }
+ }
+
+ // Update pagination count
+ this.manager.updateCurrentPageItemCount();
+
+ this.manager.getUnreadCounter().estimateChange( -itemIds.length );
+ this.manager.getLocalCounter().estimateChange( -itemIds.length );
+ return this.api.markItemsRead( itemIds, 'local', true ).then( this.refreshUnreadCount.bind( this ) );
+ };
+
+ /**
+ * Fetch notifications from the cross-wiki sources.
+ *
+ * @return {jQuery.Promise} Promise that is resolved when all items
+ * from the cross-wiki sources are populated into the cross-wiki
+ * model.
+ */
+ mw.echo.Controller.prototype.fetchCrossWikiNotifications = function () {
+ var controller = this,
+ xwikiModel = this.manager.getNotificationModel( 'xwiki' );
+
+ if ( !xwikiModel ) {
+ // There is no xwiki notifications model, so we can't
+ // fetch into it
+ return $.Deferred().reject().promise();
+ }
+
+ return this.api.fetchNotificationGroups( xwikiModel.getSourceNames(), this.manager.getTypeString(), true )
+ .then(
+ function ( groupList ) {
+ var i, notifData, listModel, group, groupItems,
+ items = [];
+
+ for ( group in groupList ) {
+ listModel = xwikiModel.getItemBySource( group );
+ groupItems = groupList[ group ];
+
+ items = [];
+ for ( i = 0; i < groupItems.length; i++ ) {
+ notifData = controller.createNotificationData( groupItems[ i ] );
+ items.push(
+ new mw.echo.dm.NotificationItem( groupItems[ i ].id, $.extend( notifData, {
+ modelName: 'xwiki',
+ source: group,
+ bundled: true,
+ foreign: true
+ } ) )
+ );
+ }
+ // Add items
+ listModel.setItems( items );
+ }
+ },
+ function ( errCode, errObj ) {
+ return {
+ errCode: errCode,
+ errInfo: errCode === 'http' ?
+ mw.msg( 'echo-api-failure-cross-wiki' ) :
+ OO.getProp( errObj, 'error', 'info' )
+ };
+ }
+ );
+ };
+
+ /**
+ * Mark local items as read in the API.
+ *
+ * @param {string[]|string} itemIds An array of item IDs, or a single item ID, to mark as read
+ * @param {string} modelName The name of the model that these items belong to
+ * @param {boolean} [isRead=true] The read state of the item; true for marking the
+ * item as read, false for marking the item as unread
+ * @return {jQuery.Promise} A promise that is resolved when the operation
+ * is complete, with the number of unread notifications still remaining
+ * for the set type of this controller, in the given source.
+ */
+ mw.echo.Controller.prototype.markItemsRead = function ( itemIds, modelName, isRead ) {
+ var items,
+ model = this.manager.getNotificationModel( modelName ),
+ readState = this.manager.getFiltersModel().getReadState(),
+ allIds = [];
+
+ itemIds = Array.isArray( itemIds ) ? itemIds : [ itemIds ];
+
+ // Default to true
+ isRead = isRead === undefined ? true : isRead;
+
+ items = model.findByIds( itemIds );
+
+ // If we are only looking at specific read state,
+ // then we need to make sure the items are removed
+ // from the visible list, because they no longer
+ // correspond with the chosen state filter
+ if ( readState === 'read' && !isRead ) {
+ model.discardItems( items );
+ } else if ( readState === 'unread' && isRead ) {
+ model.discardItems( items );
+ // TODO: We should also find a way to update the pagination
+ // here properly. Do we pull more items from the next page
+ // when items are cleared? Do we set some threshhold for
+ // removed items where if it is reached, we update the list
+ // to reflect the new pagination? etc.
+ }
+
+ items.forEach( function ( notification ) {
+ allIds = allIds.concat( notification.getAllIds() );
+ if ( readState === 'all' ) {
+ notification.toggleRead( isRead );
+ }
+ } );
+
+ // Update pagination count
+ this.manager.updateCurrentPageItemCount();
+
+ this.manager.getUnreadCounter().estimateChange( isRead ? -allIds.length : allIds.length );
+ if ( modelName !== 'xwiki' ) {
+ // For the local counter, we should only estimate the change if the items
+ // are not cross-wiki
+ this.manager.getLocalCounter().estimateChange( isRead ? -allIds.length : allIds.length );
+ }
+
+ return this.api.markItemsRead( allIds, model.getSource(), isRead ).then( this.refreshUnreadCount.bind( this ) );
+ };
+
+ /**
+ * Mark cross-wiki items as read in the API.
+ *
+ * @param {string[]|string} itemIds An array of item IDs, or a single item ID, to mark as read
+ * @param {string} source The name for the source list that these items belong to
+ * @return {jQuery.Promise} A promise that is resolved when the operation
+ * is complete, with the number of unread notifications still remaining
+ * for the set type of this controller, in the given source.
+ */
+ mw.echo.Controller.prototype.markCrossWikiItemsRead = function ( itemIds, source ) {
+ var sourceModel,
+ notifs,
+ allIds = [],
+ xwikiModel = this.manager.getNotificationModel( 'xwiki' );
+
+ if ( !xwikiModel ) {
+ return $.Deferred().reject().promise();
+ }
+ itemIds = Array.isArray( itemIds ) ? itemIds : [ itemIds ];
+
+ sourceModel = xwikiModel.getList().getGroupByName( source );
+ notifs = sourceModel.findByIds( itemIds );
+ sourceModel.discardItems( notifs );
+ // Update pagination count
+ this.manager.updateCurrentPageItemCount();
+
+ notifs.forEach( function ( notif ) {
+ allIds = allIds.concat( notif.getAllIds() );
+ } );
+ this.manager.getUnreadCounter().estimateChange( -allIds.length );
+ return this.api.markItemsRead( allIds, source, true )
+ .then( this.refreshUnreadCount.bind( this ) );
+ };
+
+ /**
+ * Mark all cross-wiki notifications from all sources as read
+ *
+ * @return {jQuery.Promise} Promise that is resolved when all notifications
+ * are marked as read
+ */
+ mw.echo.Controller.prototype.markEntireCrossWikiItemAsRead = function () {
+ var controller = this,
+ xwikiModel = this.manager.getNotificationModel( 'xwiki' );
+
+ if ( !xwikiModel ) {
+ return $.Deferred().reject().promise();
+ }
+
+ this.manager.getUnreadCounter().estimateChange( -xwikiModel.getCount() );
+
+ return this.api.fetchNotificationGroups( xwikiModel.getSourceNames(), this.manager.getTypeString() )
+ .then( function ( groupList ) {
+ var i, listModel, group, groupItems,
+ promises = [],
+ idArray = [];
+
+ for ( group in groupList ) {
+ listModel = xwikiModel.getItemBySource( group );
+ groupItems = groupList[ group ];
+
+ idArray = [];
+ for ( i = 0; i < groupItems.length; i++ ) {
+ idArray = idArray.concat( groupItems[ i ].id ).concat( groupItems[ i ].bundledIds || [] );
+ }
+
+ // Mark items as read in the API
+ promises.push(
+ controller.api.markItemsRead( idArray, listModel.getName(), true )
+ );
+ }
+
+ // Synchronously remove this model from the widget
+ controller.removeCrossWikiItem();
+
+ return mw.echo.api.NetworkHandler.static.waitForAllPromises( promises )
+ .then( controller.refreshUnreadCount.bind( controller ) );
+ } );
+ };
+
+ /**
+ * Remove the entire cross-wiki model.
+ */
+ mw.echo.Controller.prototype.removeCrossWikiItem = function () {
+ this.manager.removeNotificationModel( 'xwiki' );
+ };
+
+ /**
+ * Refresh the unread notifications counter
+ *
+ * @return {jQuery.Promise} A promise that is resolved when the counter
+ * is updated with the actual unread count from the server.
+ */
+ mw.echo.Controller.prototype.refreshUnreadCount = function () {
+ return this.manager.getUnreadCounter().update();
+ };
+
+ /**
+ * Update global seenTime for all sources
+ *
+ * @return {jQuery.Promise} A promise that is resolved when the
+ * seenTime was updated for all the controller's types and sources.
+ */
+ mw.echo.Controller.prototype.updateSeenTime = function () {
+ var controller = this;
+
+ return this.api.updateSeenTime(
+ this.getTypes(),
+ // For consistency, use current source, though seenTime
+ // will be updated globally
+ this.manager.getFiltersModel().getSourcePagesModel().getCurrentSource()
+ )
+ .then( function ( time ) {
+ controller.manager.getSeenTimeModel().setSeenTime( time );
+ } );
+ };
+
+ /**
+ * Perform a dynamic action
+ *
+ * @param {Object} data Action data for the network
+ * @param {string} [source] Requested source to query. Defaults to currently
+ * selected source.
+ * @return {jQuery.Promise} jQuery promise that resolves when the action is done
+ */
+ mw.echo.Controller.prototype.performDynamicAction = function ( data, source ) {
+ source = source || this.manager.getFiltersModel().getSourcePagesModel().getCurrentSource();
+ return this.api.queryAPI( data, source );
+ };
+
+ /**
+ * Get the types associated with the controller and model
+ *
+ * @return {string[]} Notification types
+ */
+ mw.echo.Controller.prototype.getTypes = function () {
+ return this.manager.getTypes();
+ };
+
+ /**
+ * Return a string representation of the notification type.
+ * It could be 'alert', 'message' or, if both are set, 'all'
+ *
+ * @return {string} String representation of notifications type
+ */
+ mw.echo.Controller.prototype.getTypeString = function () {
+ return this.manager.getTypeString();
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/echo.mixins.less b/Echo/modules/echo.mixins.less
new file mode 100644
index 00000000..11a7f26a
--- /dev/null
+++ b/Echo/modules/echo.mixins.less
@@ -0,0 +1,12 @@
+.mw-echo-ui-mixin-hover-opacity() {
+ opacity: @opacity-low;
+ &:hover {
+ opacity: 1;
+ }
+}
+
+.mw-echo-ui-mixin-one-line-truncated() {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
diff --git a/Echo/modules/echo.variables.less b/Echo/modules/echo.variables.less
index 93930064..1f22a160 100644
--- a/Echo/modules/echo.variables.less
+++ b/Echo/modules/echo.variables.less
@@ -1,12 +1,51 @@
+// Taken from WikimediaUI base v0.6.1
+// Background Colors
+@background-color-base: #fff;
+
+// Foreground Colors
+@color-base: #222;
+@color-base-active: #000;
+@color-base-emphasized: @color-base-active;
+// Primary 'Progressive' Color, Background Color
+@background-color-primary: #eaf3ff;
+@color-primary: #36c;
+// 'Destructive' Color
+@color-destructive: #d33;
+
+// Border Colors
+@border-color-heading: #c8ccd1;
+
+// Echo's original variables
+@grey-light: #72777d;
+@grey-medium: #54595d;
+
@badge-padding: 0.12em;
@badge-icon-size: 1.1em;
-@badge-text-color-idle: white;
-@badge-distance-adjustment: -0.4em;
-@badge-background-unseen-alert: #D11813;
-@badge-background-unseen-message: #5D95FF;
+@badge-distance-adjustment: 1em;
+@badge-offscreen-offset: 1000px;
@notification-background-unseen: #dce8ff;
-@notification-background-unread: white;
-@notification-background-read: #f1f1f1;
+@notification-background-unread: @background-color-base;
+@notification-background-read: #eaecf0;
+
+@badge-counter-background-seen: @grey-light;
+@badge-counter-background-unseen-alert: @color-destructive;
+@badge-counter-background-unseen-message: @color-primary;
+
+@notification-text-color: @color-base-emphasized;
+@notification-body-color: @grey-light;
+
+@bundle-group-padding: 0.7em;
+@notification-popup-width: 500px;
+
+@opacity-low: 0.5;
+@opacity-mid: 0.8;
+
+@specialpage-separation-unit: 0.7em;
+@specialpage-sidebar-width: 20em;
+
+@specialpage-hd-width: 982px;
+
+@specialpage-width: 1000px;
-@notification-popup-width: 450px;
+@border-color: @border-color-heading;
diff --git a/Echo/modules/ext.echo.init.js b/Echo/modules/ext.echo.init.js
index dc5fc0c4..b5e09628 100644
--- a/Echo/modules/ext.echo.init.js
+++ b/Echo/modules/ext.echo.init.js
@@ -1,29 +1,27 @@
( function ( mw, $ ) {
'use strict';
- mw.echo = mw.echo || {};
+ // Remove ?markasread=XYZ from the URL
+ var uri = new mw.Uri();
+ if ( uri.query.markasread !== undefined ) {
+ delete uri.query.markasread;
+ window.history.replaceState( null, document.title, uri );
+ }
- mw.echo.apiCallParams = {
- action: 'query',
- meta: 'notifications',
- // We have to send the API 'groupbysection' otherwise
- // the 'messageunreadfirst' doesn't do anything.
- // TODO: Fix the API.
- notgroupbysection: 1,
- notmessageunreadfirst: 1,
- notformat: 'flyout',
- notlimit: 25,
- notprop: 'index|list|count',
- uselang: mw.config.get( 'wgUserLanguage' )
- };
+ mw.echo = mw.echo || {};
+ mw.echo.config = mw.echo.config || {};
+ // Set default max prioritized action links per item
+ mw.echo.config.maxPrioritizedActions = 2;
// Activate ooui
- $( document ).ready( function () {
- var apiRequest, myWidget,
+ $( function () {
+ var myWidget, echoApi,
$existingAlertLink = $( '#pt-notifications-alert a' ),
- $existingMessageLink = $( '#pt-notifications-message a' ),
- numAlerts = $existingAlertLink.text(),
- numMessages = $existingMessageLink.text(),
+ $existingMessageLink = $( '#pt-notifications-notice a' ),
+ numAlerts = $existingAlertLink.attr( 'data-counter-num' ),
+ numMessages = $existingMessageLink.attr( 'data-counter-num' ),
+ badgeLabelAlerts = $existingAlertLink.attr( 'data-counter-text' ),
+ badgeLabelMessages = $existingMessageLink.attr( 'data-counter-text' ),
hasUnseenAlerts = $existingAlertLink.hasClass( 'mw-echo-unseen-notifications' ),
hasUnseenMessages = $existingMessageLink.hasClass( 'mw-echo-unseen-notifications' ),
// Store links
@@ -33,53 +31,95 @@
};
// Respond to click on the notification button and load the UI on demand
- $( '.mw-echo-notification-badge-nojs' ).click( function () {
- var myType = $( this ).parent().prop( 'id' ) === 'pt-notifications-alert' ? 'alert' : 'message';
+ $( '.mw-echo-notification-badge-nojs' ).click( function ( e ) {
+ var time = mw.now(),
+ myType = $( this ).parent().prop( 'id' ) === 'pt-notifications-alert' ? 'alert' : 'message';
+
+ if ( e.which !== 1 ) {
+ return;
+ }
+
// Dim the button while we load
$( this ).addClass( 'mw-echo-notifications-badge-dimmed' );
// Fire the notification API requests
- apiRequest = new mw.Api( { ajax: { cache: false } } ).get( $.extend( { notsections: myType }, mw.echo.apiCallParams ) );
+ echoApi = new mw.echo.api.EchoApi();
+ echoApi.fetchNotifications( myType )
+ .then( function ( data ) {
+ mw.track( 'timing.MediaWiki.echo.overlay.api', mw.now() - time );
+ return data;
+ } );
// Load the ui
- mw.loader.using( 'ext.echo.ui', function () {
+ mw.loader.using( 'ext.echo.ui.desktop', function () {
+ var messageController,
+ alertController,
+ messageModelManager,
+ alertModelManager,
+ unreadMessageCounter,
+ unreadAlertCounter,
+ maxNotificationCount = mw.config.get( 'wgEchoMaxNotificationCount' );
+
+ // Overlay
+ $( 'body' ).append( mw.echo.ui.$overlay );
// Load message button and popup if messages exist
if ( $existingMessageLink.length ) {
- mw.echo.ui.messageWidget = new mw.echo.ui.NotificationBadgeWidget( {
- type: 'message',
- markReadWhenSeen: false,
- numItems: numMessages,
- hasUnseen: hasUnseenMessages,
- badgeIcon: 'speechBubble',
- links: links
- } );
- // HACK: avoid late debouncedUpdateThemeClasses
- mw.echo.ui.messageWidget.badgeButton.debouncedUpdateThemeClasses();
+ unreadMessageCounter = new mw.echo.dm.UnreadNotificationCounter( echoApi, 'message', maxNotificationCount );
+ messageModelManager = new mw.echo.dm.ModelManager( unreadMessageCounter, { type: 'message' } );
+ messageController = new mw.echo.Controller( echoApi, messageModelManager );
+
+ mw.echo.ui.messageWidget = new mw.echo.ui.NotificationBadgeWidget(
+ messageController,
+ messageModelManager,
+ {
+ $overlay: mw.echo.ui.$overlay,
+ numItems: Number( numMessages ),
+ hasUnseen: hasUnseenMessages,
+ badgeIcon: 'tray',
+ convertedNumber: badgeLabelMessages,
+ links: links,
+ href: $existingMessageLink.attr( 'href' )
+ }
+ );
// Replace the link button with the ooui button
$existingMessageLink.parent().replaceWith( mw.echo.ui.messageWidget.$element );
}
+ unreadAlertCounter = new mw.echo.dm.UnreadNotificationCounter( echoApi, 'alert', maxNotificationCount );
+ alertModelManager = new mw.echo.dm.ModelManager( unreadAlertCounter, { type: 'alert' } );
+ alertController = new mw.echo.Controller( echoApi, alertModelManager );
+
+ mw.echo.ui.alertWidget = new mw.echo.ui.NotificationBadgeWidget(
+ alertController,
+ alertModelManager,
+ {
+ numItems: Number( numAlerts ),
+ convertedNumber: badgeLabelAlerts,
+ hasUnseen: hasUnseenAlerts,
+ badgeIcon: 'bell',
+ links: links,
+ $overlay: mw.echo.ui.$overlay,
+ href: $existingAlertLink.attr( 'href' )
+ }
+ );
- // Load alerts popup and button
- mw.echo.ui.alertWidget = new mw.echo.ui.NotificationBadgeWidget( {
- type: 'alert',
- markReadWhenSeen: true,
- numItems: numAlerts,
- hasUnseen: hasUnseenAlerts,
- badgeIcon: {
- seen: 'bell',
- unseen: 'bellOn'
- },
- links: links
+ alertModelManager.on( 'allTalkRead', function () {
+ // If there was a talk page notification, get rid of it
+ $( '#pt-mytalk a' )
+ .removeClass( 'mw-echo-alert' )
+ .text( mw.msg( 'mytalk' ) );
} );
- // HACK: avoid late debouncedUpdateThemeClasses
- mw.echo.ui.alertWidget.badgeButton.debouncedUpdateThemeClasses();
+
// Replace the link button with the ooui button
$existingAlertLink.parent().replaceWith( mw.echo.ui.alertWidget.$element );
// HACK: Now that the module loaded, show the popup
myWidget = myType === 'alert' ? mw.echo.ui.alertWidget : mw.echo.ui.messageWidget;
- myWidget.populateNotifications( apiRequest );
+ myWidget.once( 'finishLoading', function () {
+ // Log timing after notifications are shown
+ mw.track( 'timing.MediaWiki.echo.overlay', mw.now() - time );
+ } );
myWidget.popup.toggle( true );
+ mw.track( 'timing.MediaWiki.echo.overlay.ooui', mw.now() - time );
} );
if ( hasUnseenAlerts || hasUnseenMessages ) {
@@ -92,4 +132,4 @@
} );
} );
-} )( mediaWiki, jQuery );
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ext.echo.moment-hack.js b/Echo/modules/ext.echo.moment-hack.js
new file mode 100644
index 00000000..bd6baba9
--- /dev/null
+++ b/Echo/modules/ext.echo.moment-hack.js
@@ -0,0 +1,48 @@
+( function ( mw ) {
+ /* global moment:false */
+ 'use strict';
+
+ var momentOrigLocale = moment.locale();
+
+ // Set up new 'short relative time' locale strings for momentjs
+ moment.defineLocale( 'echo-shortRelativeTime', {
+ relativeTime: function ( number, withoutSuffix, key ) {
+ var keymap = {
+ s: 'seconds',
+ m: 'minutes',
+ mm: 'minutes',
+ h: 'hours',
+ hh: 'hours',
+ d: 'days',
+ dd: 'days',
+ M: 'months',
+ MM: 'months',
+ y: 'years',
+ yy: 'years'
+ };
+ return mw.msg( 'notification-timestamp-ago-' + keymap[ key ], mw.language.convertNumber( number ) );
+ },
+ calendar: {
+ // Brackets must surround this output, otherwise moment thinks
+ // this is a format string, and replaces all 'm' with minutes,
+ // 's' with seconds, 'd' with days, etc, which is very amusing,
+ // but entirely unhelpful
+ sameDay: '[' + mw.msg( 'notification-timestamp-today' ) + ']',
+ lastDay: '[' + mw.msg( 'notification-timestamp-yesterday' ) + ']',
+ lastWeek: function () {
+ return '[' + mw.msg(
+ [
+ 'sunday',
+ 'monday',
+ 'tuesday',
+ 'wednesday',
+ 'thursday',
+ 'friday',
+ 'saturday'
+ ][ this.day() ] ) + ']';
+ }
+ }
+ } );
+ // Reset back to original locale
+ moment.locale( momentOrigLocale );
+}( mediaWiki ) );
diff --git a/Echo/modules/hooks.txt b/Echo/modules/hooks.txt
index bad428af..db115fca 100644
--- a/Echo/modules/hooks.txt
+++ b/Echo/modules/hooks.txt
@@ -2,6 +2,25 @@ hooks.txt
This documents Echo's client-side hooks:
-'ext.echo.overlay.beforeShowingOverlay': Before showing the Echo overlay, it is
-passed to this hook, which can modify the DOM or take other actions.
-$overlay: the jQuery-wrapped element for the overlay
+'ext.echo.notifications.beforeRender': Before notification widgets are rendered
+the wrapper of the notifications and the individual notification jQuery elements
+are passed to this hook, which can modify the DOM or take other actions.
+* $wrapper: The jQuery object that is the wrapper for the notification items
+* $elements: A jQuery group of all notification elements that are about to be rendered.
+
+'ext.echo.badge.countChange': When the count changes in the Notifications popup
+badge, this hook is fired with the new count.
+* type: Notifications type that the badge represents. Can be 'message', 'alert' or 'all'
+* count: The new numerical count in the notifications popup.
+* label: The label for this number, for presentation purposes.
+
+'ext.echo.popup.onInitialize': Fired when the popup is opened and after notifications
+were fetched from the API.
+* types: Notifications type that the badge represents. Can be 'message', 'alert' or 'all'
+* controller: The instance of the controller responsible for the specific popup operations
+
+'ext.echo.special.onInitialize': Fired when the special page is initialized. Note that this
+is also fired whenever the special page notification display is changed, like when clicking
+a filter, changing pagination, or viewing notifications for a remote wiki or page.
+* types: Notifications type that the badge represents. Can be 'message', 'alert' or 'all'
+* controller: The instance of the controller responsible for the specific popup operations
diff --git a/Echo/modules/icons/CrossReferenced.png b/Echo/modules/icons/CrossReferenced.png
deleted file mode 100644
index 74a191f5..00000000
--- a/Echo/modules/icons/CrossReferenced.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Deletion.png b/Echo/modules/icons/Deletion.png
deleted file mode 100644
index 8abc2e3d..00000000
--- a/Echo/modules/icons/Deletion.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Featured.png b/Echo/modules/icons/Featured.png
deleted file mode 100644
index 349892a7..00000000
--- a/Echo/modules/icons/Featured.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Generic.png b/Echo/modules/icons/Generic.png
deleted file mode 100644
index 36a9fb1b..00000000
--- a/Echo/modules/icons/Generic.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Gratitude.png b/Echo/modules/icons/Gratitude.png
deleted file mode 100644
index d22e8b63..00000000
--- a/Echo/modules/icons/Gratitude.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Help.png b/Echo/modules/icons/Help.png
deleted file mode 100644
index 5a7133d2..00000000
--- a/Echo/modules/icons/Help.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/NotificationsPage-ltr.png b/Echo/modules/icons/NotificationsPage-ltr.png
deleted file mode 100644
index 065be02c..00000000
--- a/Echo/modules/icons/NotificationsPage-ltr.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/NotificationsPage-rtl.png b/Echo/modules/icons/NotificationsPage-rtl.png
deleted file mode 100644
index 09370026..00000000
--- a/Echo/modules/icons/NotificationsPage-rtl.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Preferences.png b/Echo/modules/icons/Preferences.png
deleted file mode 100644
index ff892422..00000000
--- a/Echo/modules/icons/Preferences.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Revert.png b/Echo/modules/icons/Revert.png
deleted file mode 100644
index 426ee050..00000000
--- a/Echo/modules/icons/Revert.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Reviewed.png b/Echo/modules/icons/Reviewed.png
deleted file mode 100644
index 43cdd55f..00000000
--- a/Echo/modules/icons/Reviewed.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/ReviewedWithTags.png b/Echo/modules/icons/ReviewedWithTags.png
deleted file mode 100644
index c18a2b8d..00000000
--- a/Echo/modules/icons/ReviewedWithTags.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Settings.png b/Echo/modules/icons/Settings.png
deleted file mode 100644
index f6cfc7a1..00000000
--- a/Echo/modules/icons/Settings.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/Talk.png b/Echo/modules/icons/Talk.png
deleted file mode 100644
index 41387cc0..00000000
--- a/Echo/modules/icons/Talk.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/icons/apex/badgeicons.json b/Echo/modules/icons/apex/badgeicons.json
deleted file mode 100644
index 4182a1a4..00000000
--- a/Echo/modules/icons/apex/badgeicons.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "prefix": "oo-ui-icon",
- "images": {
- "bell": { "file": "../bell.svg" },
- "bellOn": { "file": {
- "ltr": "../bellOn-ltr.svg",
- "rtl": "../bellOn-rtl.svg"
- } },
- "speechBubble": { "file": {
- "ltr": "../speechBubble-ltr.svg",
- "rtl": "../speechBubble-rtl.svg"
- } }
- }
-}
diff --git a/Echo/modules/icons/badgeicons.json b/Echo/modules/icons/badgeicons.json
new file mode 100644
index 00000000..1593a5ce
--- /dev/null
+++ b/Echo/modules/icons/badgeicons.json
@@ -0,0 +1,19 @@
+{
+ "variants": {
+ "invert": {
+ "color": "#FFFFFF"
+ }
+ },
+ "images": {
+ "bell": {
+ "file": "icons/bell.svg"
+ },
+ "tray": {
+ "file": "icons/tray.svg"
+ },
+ "doubleCheck": {
+ "file": "icons/double-check.svg",
+ "variants": [ "invert" ]
+ }
+ }
+}
diff --git a/Echo/modules/icons/bellOn-rtl.svg b/Echo/modules/icons/bellOn-rtl.svg
index ae035290..92bcef54 100644
--- a/Echo/modules/icons/bellOn-rtl.svg
+++ b/Echo/modules/icons/bellOn-rtl.svg
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
- <path d="M6.21 14.7L4.51 10c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z" id="path56"/>
+ <path d="M6.21 14.7L4.51 10c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
</svg>
diff --git a/Echo/modules/icons/speechBubble-rtl.svg b/Echo/modules/icons/changes.svg
index 139c34ea..efe65282 100644
--- a/Echo/modules/icons/speechBubble-rtl.svg
+++ b/Echo/modules/icons/changes.svg
@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
- <g id="g586">
- <path d="M5 20h17l-3-3V6H2v11c0 1.7 1.3 3 3 3z" id="path588"/>
- </g>
+ <path d="M1.6 4h18.72v2H3.68v12H1.6V4zm20.8 2.998V20H4.72V6.998H22.4z"/>
</svg>
diff --git a/Echo/modules/icons/chat.svg b/Echo/modules/icons/chat.svg
new file mode 100644
index 00000000..61b69b2f
--- /dev/null
+++ b/Echo/modules/icons/chat.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#36c" d="M27.143 11.143V24L30 26.857H10V11.143h17.143zM2.857 4H20v5.714H8.57v10H0l2.857-2.857V4z" fill-rule="evenodd"/>
+</svg>
diff --git a/Echo/modules/icons/double-check.svg b/Echo/modules/icons/double-check.svg
new file mode 100644
index 00000000..4dd298d2
--- /dev/null
+++ b/Echo/modules/icons/double-check.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 9.5L9.5 17 6 13.5 4.5 15l5 5L20 9.5c-.706-.706-2.294-.706-3 0z"/>
+ <path d="M17 4.5L9.5 12 6 8.5 4.5 10l5 5L20 4.5c-.706-.706-2.294-.706-3 0z"/>
+</svg>
diff --git a/Echo/modules/icons/edit-user-talk.svg b/Echo/modules/icons/edit-user-talk.svg
new file mode 100644
index 00000000..c78c9c10
--- /dev/null
+++ b/Echo/modules/icons/edit-user-talk.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#36c" d="M27.143 10.143V23L30 25.857H10V10.143h17.143zM2.857 3H20v5.714H8.57v10H0l2.857-2.857V3zm18.007 17.636c-.49-.163-.49-.6-.546-1.09v-.055c.764-.65 1.364-1.74 1.364-2.94 0-2.564-1.09-3.546-2.727-3.546-1.146 0-2.728.656-2.728 3.546 0 1.145.6 2.236 1.364 2.945v.055c0 .49-.05.927-.54 1.09 0 0-1.58.6-2.18.82-.71.217-1.366.544-1.366 1.362v.546h10.91v-.546c0-.654-.436-1.09-1.364-1.363-.655-.22-2.18-.82-2.18-.82z" fill-rule="evenodd"/>
+</svg>
diff --git a/Echo/modules/icons/emailuser.svg b/Echo/modules/icons/emailuser.svg
new file mode 100644
index 00000000..03e6ad84
--- /dev/null
+++ b/Echo/modules/icons/emailuser.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#00af89" d="M15.05 14.6L27 8.95V6H3v2.925L15.05 14.6zm.025 3.3L3 12.25V24h24V12.25L15.075 17.9z" fill-rule="evenodd"/>
+</svg>
diff --git a/Echo/modules/icons/feedback.svg b/Echo/modules/icons/feedback.svg
new file mode 100644
index 00000000..c0aad33e
--- /dev/null
+++ b/Echo/modules/icons/feedback.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30">
+ <path fill="#36c" d="M8.354 21.387l.993 3.567c.347 1.297 1.854 2.071 3.15 1.724 1.221-.327 1.969-1.669 1.621-2.965l-.666-2.327H29L24.15 3 1.27 15.987c-.746 1.293.155 4.664 1.442 5.4h5.642z"/>
+</svg>
diff --git a/Echo/modules/icons/generic.svg b/Echo/modules/icons/generic.svg
new file mode 100644
index 00000000..e9c1b736
--- /dev/null
+++ b/Echo/modules/icons/generic.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30">
+ <g fill="#54595d">
+ <path d="M15.5 1C9.713 1 5 5.71 5 11.5 5 17.285 9.713 22 15.5 22S26 17.285 26 11.5C26 5.71 21.287 1 15.5 1zm0 2c4.706 0 8.5 3.793 8.5 8.5 0 4.705-3.794 8.5-8.5 8.5A8.485 8.485 0 0 1 7 11.5C7 6.792 10.794 3 15.5 3z"/>
+ <path d="M14.463 15.07h1.947v1.723h-1.947V15.07zm0-8.403h1.947v4.442l-.192 2.42h-1.554l-.2-2.42V6.666z"/>
+ </g>
+</svg>
diff --git a/Echo/modules/icons/global.svg b/Echo/modules/icons/global.svg
new file mode 100644
index 00000000..5038a09c
--- /dev/null
+++ b/Echo/modules/icons/global.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#36c" d="M15 30C6.716 30 0 23.284 0 15 0 6.716 6.716 0 15 0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15zm.047-25.838c-1.188.034-3.375.315-3.375.315s.36.686.36.99c0 .304-.09 1.12-.09 1.485 0 .364 1.332.076 1.575-.045.243-.122 1.845-1.53 1.845-1.53s.587-.882.405-1.125c-.046-.06-.324-.1-.72-.09zM8.612 5.197c.086.945 1.215 1.575 1.215 1.575l.18-.63s-.966-.945-1.395-.945zm-1.125.63s-.585.5-1.53.585c-.355.032-1.073-.104-1.845-.225-1.71 1.972-2.873 4.41-3.285 7.11l.315-.45s1.108 1.988 1.71 2.16c.6.172 1.284.78 1.8 1.125.515.344.85 2.12.765 3.15-.086 1.03.695 1.158 1.125 1.845.43.687 1.366 4.79 1.71 5.22.343.43.683-1.804.855-2.835.172-1.03 2.43-2.93 2.43-3.96 0-1.03-2.59-2.5-3.105-3.015-.516-.516-2.128-.765-3.33-.765-1.203 0-1.22-1.624-2.25-1.71-1.03-.086.18-1.44.18-1.44s2.818-.45 3.42-.45c.6 0 .777-1.702 1.035-2.475.257-.773 2.168-.7 2.34-1.215.172-.516-.782-1.035-1.125-1.035-.344 0-1.813.524-2.07.18-.258-.344 1.485-1.395 1.485-1.395l-.63-.405zm13.05 0c-.284.022-.54.074-.63.135-.182.12-.673.31-.855.585-.182.273-.393.898-.18 1.08.212.182.373.226.495.135.12-.09 1.048-.887 1.17-.765.12.12.407.855.225.855-.182 0-1.485.405-1.485.405s-.005-.247-.09-.225c-.086.02-.005.338-.09.36-.086.02-1.215.54-1.215.54s-.143.127-.315.27l-.36.36c-.01.01-.04.036-.045.045-.086.15-.562.863-.54 1.035.02.172-.1.54.135.54.236 0 1.827-.982 1.935-.81.107.17.27.18.27.18s-.108-.225 0-.225c.107 0 .81.27.81.27s-.106-.448.045-.405c.15.043.84.855.99.855.15 0 .516-.01.495-.225-.022-.215-.1-.482.18-.675.28-.194 1.133-.333 1.305-.225.17.107.437.23.18.36-.258.13-.57-.02-.72.045-.15.064-.564.48-.585.63-.022.15.808.814.765.9-.043.086-.47.495-.9.495-.43 0-3.578-.787-4.05-.765-.473.02-.887.143-1.08.315-.194.17-1.018.933-1.125 1.17-.108.236-.573 1.378-.315 1.98.257.6.84 1.692 1.485 1.8.644.107 1.426.154 1.62.09.193-.065 1.238 1.095 1.26 1.89.02.794-.057 2.79.18 3.285.236.494.418 1.414 1.17 1.35.75-.065 1.362-.242 1.62-.585.257-.344.976-2.096 1.17-3.105.193-1.01 1.086-2.526 1.215-3.105.13-.58.146-.91-.09-1.08-.237-.172-.7-.167-.72-.36-.022-.194.3-.022.495 0 .193.02.908-.032 1.08-.225.17-.194.467-.823.36-1.08-.108-.258-.585-.81-.585-.81s1.926.232 2.7.855c.45.362.812.83 1.08 1.215-.067-3.546-1.433-6.775-3.645-9.225-.02.002-.078.045-.09.045-.334 0-2.925.495-2.925.495s-.565-.645-.99-.675c-.213-.016-.526-.023-.81 0zm-3.285 1.89s-.306 1.245.135 1.215c.44-.03-.135-1.215-.135-1.215zm-.585.54s-.527.268-.405.405c.12.137.374.21.45.09.076-.122-.045-.495-.045-.495zm8.235 11.655c-.175.038-.38.178-.495.315-.114.137-.286.62-.225.9.06.28.314.66.405.63.09-.03.33-.12.36-.63.03-.51.113-.966.045-1.08-.07-.114-.09-.135-.09-.135z" fill-rule="evenodd"/>
+</svg>
diff --git a/Echo/modules/icons/help.svg b/Echo/modules/icons/help.svg
new file mode 100644
index 00000000..fcbefd12
--- /dev/null
+++ b/Echo/modules/icons/help.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g>
+ <path d="M12.001 2.085c-5.478 0-9.916 4.438-9.916 9.916 0 5.476 4.438 9.914 9.916 9.914 5.476 0 9.914-4.438 9.914-9.914 0-5.478-4.438-9.916-9.914-9.916zm.001 18c-4.465 0-8.084-3.619-8.084-8.083 0-4.465 3.619-8.084 8.084-8.084 4.464 0 8.083 3.619 8.083 8.084 0 4.464-3.619 8.083-8.083 8.083z"/>
+ <g>
+ <path d="M11.766 6.688c-2.5 0-3.219 2.188-3.219 2.188l1.411.854s.298-.791.901-1.229c.516-.375 1.625-.625 2.219.125.701.885-.17 1.587-1.078 2.719-.953 1.186-1 3.655-1 3.655h1.969s.135-2.318 1.041-3.381c.603-.707 1.443-1.338 1.443-2.494s-1.187-2.437-3.687-2.437z"/>
+ <path d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/Echo/modules/icons/link-blue.svg b/Echo/modules/icons/link-blue.svg
new file mode 100644
index 00000000..6a37deb9
--- /dev/null
+++ b/Echo/modules/icons/link-blue.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" width="30" height="30">
+ <g fill="#36c">
+ <path d="M20.437 2.69c-3.37 0-5.778 3.05-8.186 5.297.322 0 .804-.16 1.285-.16.803 0 1.605.16 2.408.48 1.284-1.283 2.568-2.727 4.494-2.727.963 0 2.087.48 2.89 1.123 1.605 1.605 1.605 4.174 0 5.78l-4.174 4.172c-.642.642-1.926 1.124-2.89 1.124-2.246 0-3.37-1.446-4.172-3.212l-2.086 2.087c1.284 2.408 3.21 4.173 6.1 4.173 1.926 0 3.69-.802 4.815-2.086l4.172-4.174c1.445-1.444 2.408-3.21 2.408-5.297-.32-3.53-3.53-6.58-7.063-6.58z"/>
+ <path d="M13.535 22.113l-1.444 1.444c-.64.642-1.925 1.124-2.89 1.124-.962 0-2.085-.48-2.888-1.123-1.605-1.605-1.605-4.334 0-5.778l4.174-4.175c.642-.642 1.926-1.123 2.89-1.123 2.246 0 3.37 1.605 4.172 3.21l2.087-2.087c-1.284-2.407-3.21-4.173-6.1-4.173-1.926 0-3.692.803-4.815 2.087L4.547 15.69c-2.73 2.73-2.73 7.063 0 9.63 2.568 2.57 7.062 2.73 9.47 0l3.05-3.05c-.482.162-.963.162-1.445.162-.803 0-1.445 0-2.087-.32z"/>
+ </g>
+</svg>
diff --git a/Echo/modules/icons/mediawiki/badgeicons.json b/Echo/modules/icons/mediawiki/badgeicons.json
deleted file mode 100644
index 21c82201..00000000
--- a/Echo/modules/icons/mediawiki/badgeicons.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "prefix": "oo-ui-icon",
- "variants": {
- "invert": {
- "color": "#FFFFFF",
- "global": true
- }
- },
- "images": {
- "bell": { "file": "../bell.svg" },
- "bellOn": { "file": {
- "ltr": "../bellOn-ltr.svg",
- "rtl": "../bellOn-rtl.svg"
- } },
- "speechBubble": { "file": {
- "ltr": "../speechBubble-ltr.svg",
- "rtl": "../speechBubble-rtl.svg"
- } }
- }
-}
diff --git a/Echo/modules/icons/mention-failure.svg b/Echo/modules/icons/mention-failure.svg
new file mode 100644
index 00000000..00c980b4
--- /dev/null
+++ b/Echo/modules/icons/mention-failure.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 188.36253 188.36253">
+ <path d="M45.695 153.668h135.38l-23.01-22.484V41.298l30.298-30.297L177.362 0 0 177.362l11 11 34.695-34.694zM20.002 137.68V30.003H127.68L20.002 137.68z" fill="#54595d" fill-rule="evenodd"/>
+</svg>
diff --git a/Echo/modules/icons/mention-status-bundle.svg b/Echo/modules/icons/mention-status-bundle.svg
new file mode 100644
index 00000000..56295b29
--- /dev/null
+++ b/Echo/modules/icons/mention-status-bundle.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 241.12238 168.78567">
+ <path d="M36.168 168.786h204.954l-36.168-36.169V0H0v132.617c0 20.496 15.673 36.169 36.168 36.169z" fill="#36c"/>
+ <path d="M109.656 102.624H96.183l-2.185-68.481h17.842l-2.184 68.48zm-15.84 26.864v-13.601h17.66v13.601h-17.66z" fill="#fff"/>
+</svg>
diff --git a/Echo/modules/icons/mention-success.svg b/Echo/modules/icons/mention-success.svg
new file mode 100644
index 00000000..843b81f5
--- /dev/null
+++ b/Echo/modules/icons/mention-success.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 213.37759 149.36432">
+ <path d="M32.007 149.364h181.37l-32.006-32.006V0H0v117.358c0 18.137 13.87 32.006 32.007 32.006z" fill="#00af89"/>
+ <path d="M134.904 42.575L78.27 99.207 49.955 70.89l-8.495 8.495 36.811 36.81 73.622-73.621c-4.53-4.531-12.459-4.531-16.99 0z" fill="#fff"/>
+</svg>
diff --git a/Echo/modules/icons/mention.svg b/Echo/modules/icons/mention.svg
new file mode 100644
index 00000000..f090bf1c
--- /dev/null
+++ b/Echo/modules/icons/mention.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#36c" d="M27.143 23L30 25.857H10V10.143h17.143V23zM20 3v5.714H8.57v10H0l2.857-2.857V3H20zm5.016 14.242c0 .613-.083 1.16-.25 1.645-.167.484-.4.893-.7 1.226-.303.333-.655.586-1.058.758-.403.177-.836.26-1.298.26-.43 0-.783-.09-1.057-.28-.274-.19-.433-.44-.476-.75h-.064c-.15.248-.387.48-.71.7-.322.22-.726.33-1.21.33-.365 0-.69-.065-.975-.2-.285-.134-.527-.322-.726-.564-.2-.242-.352-.53-.46-.863-.107-.332-.16-.7-.16-1.096 0-.45.072-.895.217-1.33.14-.436.35-.823.624-1.162.274-.336.6-.61.976-.82.377-.21.8-.315 1.275-.315.408 0 .747.085 1.016.257.27.172.44.377.518.613h.015l.113-.548h1.74l-.5 2.532c-.053.257-.1.504-.144.74-.042.238-.064.436-.064.598 0 .15.033.285.097.403.065.12.188.18.37.18.324 0 .61-.186.864-.557.253-.37.38-.933.38-1.686 0-.623-.103-1.174-.307-1.653-.204-.48-.49-.88-.862-1.2-.37-.326-.81-.57-1.322-.737-.512-.168-1.074-.25-1.686-.25-.656 0-1.256.114-1.8.346-.54.23-1.007.547-1.394.95-.387.403-.688.885-.903 1.444-.215.56-.323 1.16-.323 1.807 0 .69.114 1.308.34 1.856.226.55.546 1.017.96 1.404.414.387.903.686 1.467.895.564.21 1.185.315 1.862.315.775 0 1.466-.12 2.074-.364.607-.24 1.153-.582 1.637-1.023l1.02 1.13c-.626.61-1.354 1.06-2.187 1.345-.833.285-1.74.427-2.717.427-.915 0-1.754-.148-2.517-.444-.765-.292-1.42-.704-1.97-1.23-.55-.527-.976-1.16-1.282-1.896-.306-.737-.46-1.54-.46-2.41 0-.86.165-1.658.493-2.39.327-.73.77-1.366 1.33-1.903.56-.54 1.215-.96 1.967-1.266.753-.306 1.56-.46 2.42-.46.752 0 1.48.11 2.185.33.704.22 1.323.553 1.855.994.532.44.96.986 1.282 1.637.32.65.48 1.41.48 2.283zm-4.984.355c0-.162-.013-.317-.04-.468-.027-.156-.073-.29-.137-.408-.065-.118-.156-.213-.274-.282-.114-.07-.264-.104-.45-.104-.2 0-.384.06-.55.184-.16.125-.3.286-.42.485-.113.2-.204.422-.27.67-.063.247-.096.49-.096.725 0 .27.063.525.187.767.123.24.357.362.7.362.238 0 .44-.066.614-.19.173-.123.313-.28.42-.475.108-.193.19-.402.243-.628.053-.227.08-.44.08-.646z" fill-rule="evenodd"/>
+</svg>
diff --git a/Echo/modules/icons/ooui-edit-ltr-progressive.svg b/Echo/modules/icons/ooui-edit-ltr-progressive.svg
new file mode 100644
index 00000000..bacc712f
--- /dev/null
+++ b/Echo/modules/icons/ooui-edit-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 2L5 14l-1 5 5-1L21 6c0-2-2-4-4-4zM7.2 15.5c-.3-.3-.7-.6-1-.8C8.5 12.4 17.5 3.3 17.5 3.3c.4.1.7.3 1 .7L7.2 15.5z" fill="#36c"/>
+</svg>
diff --git a/Echo/modules/icons/ooui-edit-rtl-progressive.svg b/Echo/modules/icons/ooui-edit-rtl-progressive.svg
new file mode 100644
index 00000000..6f16aef9
--- /dev/null
+++ b/Echo/modules/icons/ooui-edit-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 2l12 12 1 5-5-1L4 6c0-2 2-4 4-4zm9.8 13.5c.3-.3.7-.6 1-.8C16.5 12.4 7.5 3.3 7.5 3.3c-.4.1-.7.3-1 .7l11.3 11.5z" fill="#36c"/>
+</svg>
diff --git a/Echo/modules/icons/revert.svg b/Echo/modules/icons/revert.svg
new file mode 100644
index 00000000..af0f2b49
--- /dev/null
+++ b/Echo/modules/icons/revert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30">
+ <g fill="#54595d" transform="translate(1.16 2.44) scale(.98216)">
+ <rect width="11" height="1" rx=".5" ry=".5" x=".5" y="25"/>
+ <g transform="rotate(38 8.548 27.52)">
+ <rect width="10" height="7" rx="1" y="18"/>
+ <path d="M0 14h10v1H0zm0 2h10v1H0zM0 0h10v13H0V0zm2 0h2v11H2V0z"/>
+ </g>
+ </g>
+</svg>
diff --git a/Echo/modules/icons/reviewed.svg b/Echo/modules/icons/reviewed.svg
new file mode 100644
index 00000000..cf406727
--- /dev/null
+++ b/Echo/modules/icons/reviewed.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#36c" d="M28.444 14.444l-9.333 10.89-6.22-6.223-1.553 1.56 7.778 7.778L30 16l-1.556-1.556zm-6.222 4.667V2H2v20.222c0 2.645 2.022 4.667 4.667 4.667h7.777l-4.666-4.67H5.11V20.66h4.046l1.555-1.556h-5.6V17.55h14v1.556H16l1.556 1.557h3.11l1.556-1.556zm-17.11-14h6.22v1.56h-6.22V5.11zm0 3.116h6.22V9.78h-6.22V8.22zm0 3.11h6.22v1.557h-6.22v-1.556zm14 4.668h-14V14.45h14V16zm-6.223-3.11V5.11h6.22v7.78h-6.22z" fill-rule="evenodd"/>
+</svg>
diff --git a/Echo/modules/icons/speechBubble-ltr.svg b/Echo/modules/icons/speechBubbles-ltr.svg
index 6e5eacd9..d6832183 100644
--- a/Echo/modules/icons/speechBubble-ltr.svg
+++ b/Echo/modules/icons/speechBubbles-ltr.svg
@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
- <g>
- <path d="M19 20H2l3-3V6h17v11c0 1.7-1.3 3-3 3z"/>
- </g>
+ <path d="M20 9v9l2 2H8V9h12zM3 4h12v4H7v7H1l2-2V4z"/>
</svg>
diff --git a/Echo/modules/icons/speechBubbles-rtl.svg b/Echo/modules/icons/speechBubbles-rtl.svg
new file mode 100644
index 00000000..db548a45
--- /dev/null
+++ b/Echo/modules/icons/speechBubbles-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 9v9l-2 2h14V9H3zm17-5H8v4h8v7h6l-2-2V4z"/>
+</svg>
diff --git a/Echo/modules/icons/thanks-ltr.svg b/Echo/modules/icons/thanks-ltr.svg
new file mode 100644
index 00000000..f277ce4d
--- /dev/null
+++ b/Echo/modules/icons/thanks-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm11.2 2.5c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2.6-1.3 1.2-1.3zm-5.4 0c.7 0 1.2.6 1.2 1.2s-.6 1.3-1.2 1.3-1.2-.6-1.2-1.2.5-1.3 1.2-1.3zm2.7 8.5c-5.1 0-6-5-6-5s2 1 6 1l6-1s-1 5-6 5z"/>
+</svg>
diff --git a/Echo/modules/icons/thanks-rtl.svg b/Echo/modules/icons/thanks-rtl.svg
new file mode 100644
index 00000000..0f9a6fb3
--- /dev/null
+++ b/Echo/modules/icons/thanks-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 6v11l3 3H5c-1.7 0-3-1.3-3-3V6h17zM7.8 8.5c-.7 0-1.2.6-1.2 1.2S7.1 11 7.8 11 9 10.4 9 9.8s-.6-1.3-1.2-1.3zm5.4 0c-.7 0-1.2.6-1.2 1.2s.6 1.3 1.2 1.3 1.2-.6 1.2-1.2-.5-1.3-1.2-1.3zM10.5 17c5.1 0 6-5 6-5s-2 1-6 1l-6-1s1 5 6 5z"/>
+</svg>
diff --git a/Echo/modules/icons/trash.svg b/Echo/modules/icons/trash.svg
new file mode 100644
index 00000000..02bdcd69
--- /dev/null
+++ b/Echo/modules/icons/trash.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#54595d" fill-rule="evenodd" d="M7 8.25c0-1.558 1.275-2.833 2.833-2.833h2.834L14.083 4h2.834l1.416 1.417h2.834C22.725 5.417 24 6.692 24 8.25H7M8.417 9.667h14.166L21.167 25.25H9.833"/>
+</svg>
diff --git a/Echo/modules/icons/tray.svg b/Echo/modules/icons/tray.svg
new file mode 100644
index 00000000..7c617eec
--- /dev/null
+++ b/Echo/modules/icons/tray.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 13.35l1.8-7.2c.2-.996.81-1.8 1.8-1.8h10.8c.99 0 1.6.867 1.8 1.8l1.8 7.2v4.5c0 .99-.81 1.8-1.8 1.8H4.8c-.99 0-1.8-.81-1.8-1.8v-4.5zm6.96 1.8h4.08c-.49.557-1.212.9-2.04.9a2.68 2.68 0 0 1-2.04-.9h4.08c.414-.472.66-1.098.66-1.8h4.14l-1.44-7.2H6.6l-1.44 7.2H9.3c0 .702.246 1.328.66 1.8z"/>
+</svg>
diff --git a/Echo/modules/icons/user-rights.svg b/Echo/modules/icons/user-rights.svg
new file mode 100644
index 00000000..6903ea8a
--- /dev/null
+++ b/Echo/modules/icons/user-rights.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
+ <path fill="#36c" d="M14.086 16.562v-.105c1.465-1.256 2.617-3.35 2.617-5.653C16.703 5.884 14.61 4 11.468 4 9.27 4 6.234 5.256 6.234 10.804c0 2.2 1.152 4.293 2.617 5.653v.105c0 .942-.1 1.78-1.042 2.094 0 0-3.035 1.15-4.187 1.57-1.36.42-2.62 1.047-2.62 2.617v1.047h14.957l-.053-.053.455-.682L17 22l-1.164-.024-.836-.14v-3.23c-.81-.347-.815-1.148-.914-2.044zM29.6 21.075V18.61l-1.53-.255c-.085-.34-.255-.68-.51-1.19l.935-1.275-1.785-1.785-1.275.935c-.425-.255-.85-.425-1.19-.51l-.17-1.53H21.61l-.255 1.53c-.425.085-.765.255-1.19.51l-1.275-.935-1.785 1.785.85 1.275c-.255.425-.34.765-.51 1.19l-1.445.17v2.465l1.53.255c.085.425.255.765.51 1.19l-.85 1.275 1.785 1.785 1.275-.85c.34.17.765.34 1.19.51l.255 1.53h2.55l.255-1.53c.425-.085.765-.255 1.19-.51l1.275.935 1.785-1.785-.935-1.275c.255-.425.425-.85.51-1.19l1.275-.255zm-6.8 1.275c-1.445 0-2.55-1.105-2.55-2.55 0-1.445 1.105-2.55 2.55-2.55 1.445 0 2.55 1.105 2.55 2.55 0 1.445-1.105 2.55-2.55 2.55z" fill-rule="evenodd"/>
+</svg>
diff --git a/Echo/modules/icons/user-speech-bubble.svg b/Echo/modules/icons/user-speech-bubble.svg
new file mode 100644
index 00000000..12e60d42
--- /dev/null
+++ b/Echo/modules/icons/user-speech-bubble.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 16.8c-.96-.32-3.2-1.2-3.2-1.2-.72-.24-.72-.88-.8-1.6v-.08c1.12-.96 2-2.56 2-4.32 0-3.76-1.6-5.2-4-5.2-1.68 0-4 .96-4 5.2 0 1.68.88 3.28 2 4.32V14c0 .72-.08 1.36-.8 1.6 0 0-2.32.88-3.2 1.2-1.04.32-2 .8-2 2v.8h16v-.8c0-.96-.64-1.6-2-2zm.367-5.46l-1.796 2.938H24V4.4h-9.633v6.94z"/>
+</svg>
diff --git a/Echo/modules/logger/mw.echo.Logger.js b/Echo/modules/logger/mw.echo.Logger.js
index ccf1add6..725c2d03 100644
--- a/Echo/modules/logger/mw.echo.Logger.js
+++ b/Echo/modules/logger/mw.echo.Logger.js
@@ -19,7 +19,7 @@
// This should usually already be loaded, but not always
this.deferred = mw.loader.using( 'ext.eventLogging', function () {
mw.eventLog.setDefaults( 'EchoInteraction', {
- version: mw.config.get( 'wgEchoConfig' ).version,
+ version: mw.config.get( 'wgEchoEventLoggingVersion' ),
userId: +mw.config.get( 'wgUserId' ),
editCount: +mw.config.get( 'wgUserEditCount' )
} );
@@ -38,11 +38,10 @@
* is enabled
*
* @static
- * @property {[type]}
+ * @property {boolean}
*/
mw.echo.Logger.static.clickThroughEnabled = OO.getProp(
- mw.config.get( 'wgEchoConfig' ),
- 'eventlogging',
+ mw.config.get( 'wgEchoEventLoggingSchemas' ),
'EchoInteraction',
'enabled'
);
@@ -74,7 +73,10 @@
*/
mw.echo.Logger.static.actions = {
notificationClick: 'notification-link-click',
- notificationImpression: 'notification-impression'
+ notificationBundleExpand: 'notification-bundle-expand',
+ notificationImpression: 'notification-impression',
+ markAllReadClick: 'mark-all-read-click',
+ markXWikiReadClick: 'mark-entire-xwiki-bundle-read-click'
};
/* Methods */
@@ -84,16 +86,19 @@
*
* @param {string} action The interaction
* @param {string} [context] 'flyout'/'archive' or undefined for the badge
- * @param {int} [eventId] Notification event id
+ * @param {number} [eventId] Notification event id
* @param {string} [eventType] notification type
* @param {boolean} [mobile] True if interaction was on a mobile device
+ * @param {string} [notifWiki] Foreign wiki the notification came from
*/
- mw.echo.Logger.prototype.logInteraction = function ( action, context, eventId, eventType, mobile ) {
- if ( !this.constructor.clickThroughEnabled ) {
+ mw.echo.Logger.prototype.logInteraction = function ( action, context, eventId, eventType, mobile, notifWiki ) {
+ var myEvt;
+
+ if ( !this.constructor.static.clickThroughEnabled ) {
return;
}
- var myEvt = {
+ myEvt = {
action: action
};
@@ -107,8 +112,12 @@
if ( eventType ) {
myEvt.notificationType = eventType;
}
- if ( mobile ) {
- myEvt.mobile = mobile;
+ if ( mobile !== undefined || mw.config.get( 'skin' ) === 'minerva' ) {
+ myEvt.mobile = mobile || mw.config.get( 'skin' ) === 'minerva';
+ }
+
+ if ( notifWiki && notifWiki !== mw.config.get( 'wgDBname' ) && notifWiki !== 'local' ) {
+ myEvt.notifWiki = notifWiki;
}
this.deferred.done( function () {
@@ -122,20 +131,25 @@
* @param {string} type Notification type; 'alert' or 'message'
* @param {number[]} notificationIds Array of notification ids
* @param {string} context 'flyout'/'archive' or undefined for the badge
- * @param {boolean} [mobile] True if interaction was on a mobile device
+ * @param {string} [notifWiki='local'] Foreign wiki the notifications came from
+ * @param {boolean} [mobile=false] True if interaction was on a mobile device
*/
- mw.echo.Logger.prototype.logNotificationImpressions = function ( type, notificationIds, context, mobile ) {
- var i, len;
+ mw.echo.Logger.prototype.logNotificationImpressions = function ( type, notificationIds, context, notifWiki, mobile ) {
+ var i, len, key;
for ( i = 0, len = notificationIds.length; i < len; i++ ) {
- if ( !this.notificationsIdCache[ notificationIds[i] ] ) {
+ key = notifWiki && notifWiki !== mw.config.get( 'wgDBname' ) && notifWiki !== 'local' ?
+ notificationIds[ i ] + '-' + notifWiki :
+ notificationIds[ i ];
+
+ if ( !this.notificationsIdCache[ key ] ) {
// Log notification impression
- this.logInteraction( 'notification-impression', context, notificationIds[i], type, mobile );
+ this.logInteraction( 'notification-impression', context, notificationIds[ i ], type, mobile, notifWiki );
// Cache
- this.notificationsIdCache[ notificationIds[i] ] = true;
+ this.notificationsIdCache[ key ] = true;
}
}
};
mw.echo.logger = new mw.echo.Logger();
-} )( jQuery, mediaWiki );
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.BundleNotificationItem.js b/Echo/modules/model/mw.echo.dm.BundleNotificationItem.js
new file mode 100644
index 00000000..ec769ba1
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.BundleNotificationItem.js
@@ -0,0 +1,162 @@
+( function ( mw ) {
+ /**
+ * Bundle notification item model. Contains a list of bundled notifications.
+ * Is expandable.
+ *
+ * @class
+ * @extends mw.echo.dm.NotificationItem
+ *
+ * @constructor
+ * @param {number} id Notification id
+ * @param {mw.echo.dm.NotificationItem[]} bundledNotificationModels
+ * @param {Object} [config] Configuration object
+ */
+ mw.echo.dm.BundleNotificationItem = function MwEchoDmBundleNotificationItem( id, bundledNotificationModels, config ) {
+ config = config || {};
+
+ mw.echo.dm.BundleNotificationItem.parent.call( this, id, config );
+
+ this.getSecondaryUrls().forEach( function ( link ) {
+ // hack: put all secondary actions in the menu for now
+ // this is a temporary fix for
+ // - alignment of the labels
+ // - make sure there isn't to many secondary links (causes a horizontal scrollbar)
+ delete link.prioritized;
+ } );
+
+ this.setForeign( false );
+ this.count = bundledNotificationModels.length;
+
+ // bundled notifications use the compact header and do not have icons
+ bundledNotificationModels.forEach( function ( bundled ) {
+ bundled.content.header = bundled.content.compactHeader;
+ delete bundled.iconURL;
+ } );
+
+ this.list = new mw.echo.dm.NotificationsList();
+ this.list.setItems( bundledNotificationModels );
+
+ this.list.connect( this, { itemUpdate: 'onItemUpdate' } );
+
+ // For bundles, 'read' is a computed state based on
+ // inner notifications.
+ // Calling toggleRead here to initialize based
+ // on current computed state.
+ this.toggleRead( this.isRead() );
+ };
+
+ OO.inheritClass( mw.echo.dm.BundleNotificationItem, mw.echo.dm.NotificationItem );
+
+ /* Methods */
+
+ /**
+ * Whenever a bundled notification changes, update the read status of the parent.
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.onItemUpdate = function () {
+ this.toggleRead( this.isRead() );
+ };
+
+ /**
+ * @return {boolean} Whether this bundle is completely read
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.isRead = function () {
+ var itemIsRead = function ( item ) { return item.isRead(); };
+ return this.list.getItems().every( itemIsRead );
+ };
+
+ /**
+ * Get the list of bundled notifications
+ *
+ * @return {mw.echo.dm.NotificationsList} List of bundled notifications
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.getList = function () {
+ return this.list;
+ };
+
+ /**
+ * Get expected item count from all sources
+ *
+ * @return {number} Item count
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.getCount = function () {
+ return this.list.getItemCount();
+ };
+
+ /**
+ * Check if there are unseen items in any of the cross wiki source lists.
+ * This method is required for all models that are managed by the
+ * mw.echo.dm.ModelManager.
+ *
+ * @return {boolean} There are unseen items
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.hasUnseen = function () {
+ var isUnseen = function ( item ) {
+ return !item.isSeen();
+ };
+ return this.list.getItems().some( isUnseen );
+ };
+
+ /**
+ * Set all notifications to seen
+ *
+ * @param {number} timestamp New seen timestamp
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.updateSeenState = function ( timestamp ) {
+ this.list.getItems().forEach( function ( notification ) {
+ notification.toggleSeen(
+ notification.isRead() || notification.getTimestamp() < timestamp
+ );
+ } );
+ };
+
+ /**
+ * This item is a group.
+ * This method is required for all models that are managed by the
+ * mw.echo.dm.ModelManager.
+ *
+ * @return {boolean} This item is a group
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.isGroup = function () {
+ return true;
+ };
+
+ /**
+ * Get the all ids contained in this notification
+ *
+ * @return {number[]}
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.getAllIds = function () {
+ return this.list.getItems().map( function ( item ) {
+ return item.getId();
+ } );
+ };
+
+ /**
+ * Find all items that match the given IDs.
+ *
+ * @param {number[]} ids An array of item IDs
+ * @return {mw.echo.dm.NotificationItem[]} An array of matching items
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.findByIds = function ( ids ) {
+ return this.list.findByIds( ids );
+ };
+
+ /**
+ * Get bundled notifications
+ *
+ * @return {mw.echo.dm.NotificationItem[]} bundled notifications
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.getItems = function () {
+ return this.list.getItems();
+ };
+
+ /**
+ * Get model name
+ *
+ * @return {string} model name
+ */
+ mw.echo.dm.BundleNotificationItem.prototype.getName = function () {
+ return this.getModelName();
+ };
+
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.CrossWikiNotificationItem.js b/Echo/modules/model/mw.echo.dm.CrossWikiNotificationItem.js
new file mode 100644
index 00000000..1183aee2
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.CrossWikiNotificationItem.js
@@ -0,0 +1,165 @@
+( function ( mw ) {
+ /**
+ * Cross-wiki notification item model. Contains a list of sources,
+ * that each contain a list of notification items from that source.
+ *
+ * @class
+ * @extends mw.echo.dm.NotificationItem
+ *
+ * @constructor
+ * @param {number} id Notification id
+ * @param {Object} [config] Configuration object
+ * @cfg {number} count The initial anticipated count of notifications through all
+ * of the sources.
+ */
+ mw.echo.dm.CrossWikiNotificationItem = function MwEchoDmCrossWikiNotificationItem( id, config ) {
+ config = config || {};
+
+ mw.echo.dm.CrossWikiNotificationItem.parent.call( this, id, config );
+
+ this.foreign = true;
+ this.source = null;
+ this.count = config.count || 0;
+ this.modelName = config.modelName || 'xwiki';
+
+ this.list = new mw.echo.dm.NotificationGroupsList();
+
+ this.list.connect( this, { discard: 'onListDiscard' } );
+ };
+
+ OO.inheritClass( mw.echo.dm.CrossWikiNotificationItem, mw.echo.dm.NotificationItem );
+
+ /* Events */
+
+ /**
+ * @event discard
+ * @param {string} name The symbolic name for the list model that was discarded
+ *
+ * A sub list has been discarded
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to list being removed from the cross-wiki bundle.
+ *
+ * @param {mw.echo.dm.NotificationGroupsList} sourceModel The source model that was removed
+ * @fires discard
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.onListDiscard = function ( sourceModel ) {
+ this.emit( 'discard', sourceModel.getName() );
+ };
+
+ /**
+ * Get the list of sources
+ *
+ * @return {mw.echo.dm.NotificationGroupsList} List of sources
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.getList = function () {
+ return this.list;
+ };
+
+ /**
+ * Get an array of source names that are in the cross-wiki list
+ *
+ * @return {string[]} Source names
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.getSourceNames = function () {
+ var i,
+ sourceNames = [],
+ sourceLists = this.list.getItems();
+
+ for ( i = 0; i < sourceLists.length; i++ ) {
+ sourceNames.push( sourceLists[ i ].getName() );
+ }
+
+ return sourceNames;
+ };
+
+ /**
+ * Get a specific item from the list by its source name
+ *
+ * @param {string} sourceName Source name
+ * @return {mw.echo.dm.NotificationGroupsList} Source item
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.getItemBySource = function ( sourceName ) {
+ return this.list.getGroupByName( sourceName );
+ };
+
+ /**
+ * Get expected item count from all sources
+ *
+ * @return {number} Item count
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.getCount = function () {
+ return this.count;
+ };
+
+ /**
+ * Check if there are unseen items in any of the cross wiki source lists.
+ * This method is required for all models that are managed by the
+ * mw.echo.dm.ModelManager.
+ *
+ * @return {boolean} There are unseen items
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.hasUnseen = function () {
+ var i, j, items,
+ sourceLists = this.getList().getItems();
+
+ for ( i = 0; i < sourceLists.length; i++ ) {
+ items = sourceLists[ i ].getItems();
+ for ( j = 0; j < items.length; j++ ) {
+ if ( !items[ j ].isSeen() ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * Set all notifications in all groups to seen
+ *
+ * @param {number} timestamp New seen timestamp
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.updateSeenState = function ( timestamp ) {
+ this.getList().getItems().forEach( function ( source ) {
+ source.getItems().forEach( function ( notification ) {
+ notification.toggleSeen(
+ notification.isRead() || notification.getTimestamp() < timestamp
+ );
+ } );
+ } );
+ };
+
+ /**
+ * Get all items in the cross wiki notification bundle
+ *
+ * @return {mw.echo.dm.NotificationItem[]} All items across all sources
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.getItems = function () {
+ var notifications = [];
+ this.list.getItems().forEach( function ( sourceList ) {
+ notifications = notifications.concat( sourceList.getItems() );
+ } );
+
+ return notifications;
+ };
+
+ /**
+ * This item is a group.
+ * This method is required for all models that are managed by the
+ * mw.echo.dm.ModelManager.
+ *
+ * @return {boolean} This item is a group
+ */
+ mw.echo.dm.CrossWikiNotificationItem.prototype.isGroup = function () {
+ return true;
+ };
+
+ mw.echo.dm.CrossWikiNotificationItem.prototype.isEmpty = function () {
+ return this.getList().isEmpty();
+ };
+
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.FiltersModel.js b/Echo/modules/model/mw.echo.dm.FiltersModel.js
new file mode 100644
index 00000000..62c3e0e8
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.FiltersModel.js
@@ -0,0 +1,99 @@
+( function ( mw ) {
+ /**
+ * Filters model for displaying filtered notification list.
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} config Configuration object
+ * @cfg {string} [readState='all'] Notifications read state. Allowed
+ * values are 'all', 'read' or 'unread'.
+ * @cfg {string} [selectedSource] Currently selected source
+ */
+ mw.echo.dm.FiltersModel = function MwEchoDmFiltersModel( config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.readState = config.readState || 'all';
+
+ this.sourcePagesModel = new mw.echo.dm.SourcePagesModel();
+ this.selectedSource = config.selectedSource || '';
+ this.selectedSourcePage = null;
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.echo.dm.FiltersModel );
+ OO.mixinClass( mw.echo.dm.FiltersModel, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event update
+ *
+ * The filters have been updated
+ */
+
+ /* Methods */
+
+ /**
+ * Set the read state filter
+ *
+ * @param {string} readState Notifications read state
+ */
+ mw.echo.dm.FiltersModel.prototype.setReadState = function ( readState ) {
+ var allowed = [ 'all', 'read', 'unread' ];
+ if (
+ this.readState !== readState &&
+ allowed.indexOf( readState ) > -1
+ ) {
+ this.readState = readState;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get the read state filter
+ *
+ * @return {string} Notifications read state
+ */
+ mw.echo.dm.FiltersModel.prototype.getReadState = function () {
+ return this.readState;
+ };
+
+ /**
+ * Set the currently selected source and page.
+ * If no page is given, or if page is null, the source title
+ * is assumed to be selected.
+ *
+ * @param {string} source Source name
+ * @param {string} [page] Page name
+ */
+ mw.echo.dm.FiltersModel.prototype.setCurrentSourcePage = function ( source, page ) {
+ this.sourcePagesModel.setCurrentSourcePage( source, page );
+ };
+
+ /**
+ * Get the total count of a source. This sums the count of all
+ * sub pages in that source.
+ *
+ * @param {string} source Symbolic name for source
+ * @return {number} Total count
+ */
+ mw.echo.dm.FiltersModel.prototype.getSourceTotalCount = function ( source ) {
+ return this.sourcePagesModel.getSourceTotalCount( source );
+ };
+
+ /**
+ * Get the source page model
+ *
+ * @return {mw.echo.dm.SourcePagesModel} Source pages model
+ */
+ mw.echo.dm.FiltersModel.prototype.getSourcePagesModel = function () {
+ return this.sourcePagesModel;
+ };
+
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.ModelManager.js b/Echo/modules/model/mw.echo.dm.ModelManager.js
new file mode 100644
index 00000000..213d4b59
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.ModelManager.js
@@ -0,0 +1,484 @@
+( function ( mw ) {
+ /**
+ * A container that manages all models that are involved in creating
+ * the notification list. There are currently two types of models:
+ * * mw.echo.dm.SortedList - This currently includes the local model
+ * or any model that has individual messages.
+ * * mw.echo.dm.CrossWikiNotificationItem - This is a model for the
+ * cross wiki notification, which acts as an item but itself contains
+ * a list.
+ *
+ * All notification models that are managed by the manager must implement the
+ * following methods:
+ * * getName - This should retrieve the model's name for the manager to fetch
+ * * isGroup - This should be true for xwiki model and local bundles
+ * * hasUnseen - This should iterate in the model's items and check whether
+ * there are any unseen notifications within them.
+ * * getCount - Get a total count of available notifications currently in the model
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {mw.echo.dm.UnreadNotificationCounter} counter Unread counter
+ * @param {Object} [config] Configuration object
+ * @cfg {string|string[]} [type="message"] The type of the notifications in
+ * the models that this manager handles.
+ * @cfg {number} [itemsPerPage=25] Number of items per page
+ * @cfg {string} [readState] Notifications read state. Pass through to mw.echo.dm.FiltersModel
+ */
+ mw.echo.dm.ModelManager = function MwEchoDmModelManager( counter, config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.counter = counter;
+ // Keep types in an array
+ this.types = config.type || 'message';
+ this.types = Array.isArray( this.types ) ?
+ config.type : [ this.types ];
+
+ this.seenTimeModel = new mw.echo.dm.SeenTimeModel( { types: this.types } );
+
+ this.notificationModels = {};
+ this.paginationModel = new mw.echo.dm.PaginationModel( {
+ itemsPerPage: config.itemsPerPage || 25
+ } );
+ this.filtersModel = new mw.echo.dm.FiltersModel( {
+ selectedSource: 'local',
+ readState: config.readState
+ } );
+
+ // Events
+ this.seenTimeModel.connect( this, { update: 'onSeenTimeUpdate' } );
+
+ this.localCounter = config.localCounter || new mw.echo.dm.UnreadNotificationCounter();
+ this.localCounter.connect( this, { countChange: [ 'emit', 'localCountChange' ] } );
+ };
+
+ OO.initClass( mw.echo.dm.ModelManager );
+ OO.mixinClass( mw.echo.dm.ModelManager, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event update
+ * @param {Object[]} Current available notifications
+ *
+ * The model has been rebuilt or has been updated
+ */
+
+ /**
+ * @event discard
+ * @param {string} modelId Discard model id
+ *
+ * A model has been permanently removed
+ */
+
+ /**
+ * @event seen
+ * @param {string} source Source where seenTime was updated
+ * @param {number} timestamp The new seen timestamp, as a full UTC ISO 8601 timestamp
+ *
+ * All notifications in that source are seen
+ */
+
+ /**
+ * @event allTalkRead
+ *
+ * There are no more local talk page notifications
+ */
+
+ /**
+ * @event modelItemUpdate
+ * @param {string} modelId Model ID
+ * @param {mw.echo.dm.NotificationItem} item Updated item
+ *
+ * A specific item inside a notifications model has been updated
+ */
+
+ /**
+ * @event localCountChange
+ *
+ * There was a change in the count of local unread notifications
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to seen time change for a given source
+ *
+ * @param {string} timestamp Seen time, as a full UTC ISO 8601 timestamp
+ * @fires seen
+ */
+ mw.echo.dm.ModelManager.prototype.onSeenTimeUpdate = function ( timestamp ) {
+ var modelId,
+ models = this.getAllNotificationModels();
+
+ for ( modelId in models ) {
+ models[ modelId ].updateSeenState( timestamp );
+ }
+
+ this.emit( 'seen', timestamp );
+ };
+
+ /**
+ * Respond to a notification model discarding items.
+ *
+ * @param {string} modelId Model name
+ */
+ mw.echo.dm.ModelManager.prototype.onModelDiscardItems = function ( modelId ) {
+ var model = this.getNotificationModel( modelId );
+
+ // If the model is empty, remove it
+ if ( model.isEmpty() ) {
+ this.removeNotificationModel( modelId );
+ }
+ };
+
+ /**
+ * Get the notifications
+ *
+ * @return {Object} Object of notification models and their symbolic names
+ */
+ mw.echo.dm.ModelManager.prototype.getAllNotificationModels = function () {
+ return this.notificationModels;
+ };
+
+ /**
+ * Set the models in the manager.
+ *
+ * @param {Object} modelDefinitions An object defining the models
+ * The format for the definition object is:
+ * {
+ * 'modelId': {mw.echo.dm.SortedList},
+ * ...
+ * }
+ */
+ mw.echo.dm.ModelManager.prototype.setNotificationModels = function ( modelDefinitions ) {
+ var modelId;
+
+ this.resetNotificationModels();
+
+ for ( modelId in modelDefinitions ) {
+ this.notificationModels[ modelId ] = modelDefinitions[ modelId ];
+ this.notificationModels[ modelId ].connect( this, {
+ discard: [ 'onModelDiscardItems', modelId ],
+ itemUpdate: [ 'onModelItemUpdate', modelId ]
+ } );
+ }
+
+ // Update pagination count
+ this.updateCurrentPageItemCount();
+
+ this.emit( 'update', this.getAllNotificationModels() );
+ };
+
+ /**
+ * Respond to model update event
+ *
+ * @param {string} modelName Model name
+ * @param {mw.echo.dm.notificationItem} item Notification item
+ * @fires modelUpdate
+ */
+ mw.echo.dm.ModelManager.prototype.onModelItemUpdate = function ( modelName, item ) {
+ this.checkLocalUnreadTalk();
+
+ this.emit( 'modelItemUpdate', modelName, item );
+ };
+
+ /**
+ * Update the current page item count based on available items
+ */
+ mw.echo.dm.ModelManager.prototype.updateCurrentPageItemCount = function () {
+ this.getPaginationModel().setCurrentPageItemCount( this.getAllNotificationCount() );
+ };
+
+ /**
+ * Go over all the notification models and return the total number of
+ * available notifications.
+ *
+ * @return {number} A count of all notifications
+ */
+ mw.echo.dm.ModelManager.prototype.getAllNotificationCount = function () {
+ var model,
+ count = 0,
+ models = this.getAllNotificationModels();
+
+ for ( model in models ) {
+ count += models[ model ].getCount();
+ }
+
+ return count;
+ };
+
+ /**
+ * Get a notification model.
+ *
+ * @param {string} modelName Unique model name
+ * @return {mw.echo.dm.SortedList} Notifications model
+ */
+ mw.echo.dm.ModelManager.prototype.getNotificationModel = function ( modelName ) {
+ return this.notificationModels[ modelName ];
+ };
+
+ /**
+ * Get the pagination model
+ *
+ * @return {mw.echo.dm.PaginationModel} Pagination model
+ */
+ mw.echo.dm.ModelManager.prototype.getPaginationModel = function () {
+ return this.paginationModel;
+ };
+
+ /**
+ * Get the filters model
+ *
+ * @return {mw.echo.dm.FiltersModel} Filters model
+ */
+ mw.echo.dm.ModelManager.prototype.getFiltersModel = function () {
+ return this.filtersModel;
+ };
+
+ /**
+ * Remove a model from the manager
+ *
+ * @param {string} modelName Symbolic name of the model
+ * @fires remove
+ */
+ mw.echo.dm.ModelManager.prototype.removeNotificationModel = function ( modelName ) {
+ delete this.notificationModels[ modelName ];
+
+ this.emit( 'discard', modelName );
+ };
+
+ /**
+ * Reset all models
+ *
+ * @private
+ */
+ mw.echo.dm.ModelManager.prototype.resetNotificationModels = function () {
+ var model;
+
+ for ( model in this.notificationModels ) {
+ if ( this.notificationModels.hasOwnProperty( model ) ) {
+ this.notificationModels[ model ].disconnect( this );
+ delete this.notificationModels[ model ];
+ }
+ }
+ };
+
+ /**
+ * Get the unread notification counter
+ *
+ * @return {mw.echo.dm.UnreadNotificationCounter} Unread notification counter
+ */
+ mw.echo.dm.ModelManager.prototype.getUnreadCounter = function () {
+ return this.counter;
+ };
+
+ /**
+ * Check if the local model has any unread notifications.
+ *
+ * @return {boolean} Local model has unread notifications.
+ */
+ mw.echo.dm.ModelManager.prototype.hasLocalUnread = function () {
+ var isUnread = function ( item ) {
+ return !item.isRead();
+ };
+
+ return this.getLocalNotifications().some( isUnread );
+ };
+
+ /**
+ * Get local unread notifications
+ *
+ * @return {mw.echo.dm.NotificationItem[]} Local unread notifications
+ */
+ mw.echo.dm.ModelManager.prototype.getLocalUnread = function () {
+ var isUnread = function ( item ) {
+ return !item.isRead();
+ };
+
+ return this.getLocalNotifications().filter( isUnread );
+ };
+ /**
+ * Check whether there are talk notifications, and emit an event
+ * in case there aren't any left.
+ *
+ * @fires allTalkRead
+ */
+ mw.echo.dm.ModelManager.prototype.checkLocalUnreadTalk = function () {
+ if ( !this.hasLocalUnreadTalk() ) {
+ this.emit( 'allTalkRead' );
+ }
+ };
+
+ /**
+ * Check if the local model has any unread talk page notifications.
+ *
+ * @return {boolean} Local model has unread talk page notifications.
+ */
+ mw.echo.dm.ModelManager.prototype.hasLocalUnreadTalk = function () {
+ var isUnreadUserTalk = function ( item ) {
+ return !item.isRead() && item.getCategory() === 'edit-user-talk';
+ };
+
+ return this.getLocalNotifications().some( isUnreadUserTalk );
+ };
+
+ /**
+ * Check if a model has any unseen notifications.
+ *
+ * @param {string} modelId Model ID
+ * @return {boolean} The given model has unseen notifications.
+ */
+ mw.echo.dm.ModelManager.prototype.hasUnseenInModel = function ( modelId ) {
+ var model = this.getNotificationModel( modelId || 'local' );
+
+ return model && model.hasUnseen();
+ };
+
+ /**
+ * Check if a model has any unseen notifications.
+ *
+ * @param {string} [source='local'] Model source
+ * @return {boolean} The given models has unseen notifications.
+ */
+ mw.echo.dm.ModelManager.prototype.hasUnseenInSource = function ( source ) {
+ var i, modelNames;
+
+ source = source || 'local';
+ modelNames = this.getModelsBySource( source );
+
+ for ( i = 0; i < modelNames.length; i++ ) {
+ if ( this.getNotificationModel( modelNames[ i ] ).hasUnseen() ) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * Check if there are unseen notifications in any of the models
+ *
+ * @return {boolean} Local model has unseen notifications.
+ */
+ mw.echo.dm.ModelManager.prototype.hasUnseenInAnyModel = function () {
+ var model,
+ models = this.getAllNotificationModels();
+
+ for ( model in models ) {
+ if ( models[ model ].hasUnseen() ) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * Get the system seen time
+ *
+ * @param {string} [source='local'] Seen time source
+ * @return {string} Seen time, as a full UTC ISO 8601 timestamp
+ */
+ mw.echo.dm.ModelManager.prototype.getSeenTime = function ( source ) {
+ return this.getSeenTimeModel().getSeenTime( source );
+ };
+
+ /**
+ * Get the array of model types
+ *
+ * @return {string[]} Model types
+ */
+ mw.echo.dm.ModelManager.prototype.getTypes = function () {
+ return this.types;
+ };
+
+ /**
+ * Get the model types string; 'message', 'alert', or 'all'
+ *
+ * @return {string} Model types
+ */
+ mw.echo.dm.ModelManager.prototype.getTypeString = function () {
+ return (
+ this.types.length === 1 ?
+ this.types[ 0 ] :
+ 'all'
+ );
+ };
+
+ /**
+ * Get the local counter
+ *
+ * @return {mw.echo.dm.UnreadNotificationCounter} Local counter
+ */
+ mw.echo.dm.ModelManager.prototype.getLocalCounter = function () {
+ return this.localCounter;
+ };
+
+ /**
+ * Get all local notifications
+ *
+ * @return {mw.echo.dm.NotificationItem[]} all local notifications
+ */
+ mw.echo.dm.ModelManager.prototype.getLocalNotifications = function () {
+ return this.getNotificationsBySource( 'local' );
+ };
+
+ /**
+ * Get all notifications that come from a given source
+ *
+ * @param {string} [source='local'] Source name
+ * @return {mw.echo.dm.NotificationItem[]} All notifications from that source
+ */
+ mw.echo.dm.ModelManager.prototype.getNotificationsBySource = function ( source ) {
+ var notifications = [],
+ manager = this;
+
+ source = source || 'local';
+
+ Object.keys( this.getAllNotificationModels() ).forEach( function ( modelName ) {
+ var model = manager.getNotificationModel( modelName );
+ if ( model.getSource() === source ) {
+ notifications = notifications.concat( model.getItems() );
+ }
+ } );
+ return notifications;
+ };
+
+ /**
+ * Get all models that have a specific source
+ *
+ * @param {string} [source='local'] Given source
+ * @return {string[]} All model IDs that use this source
+ */
+ mw.echo.dm.ModelManager.prototype.getModelsBySource = function ( source ) {
+ var modelIds = [],
+ manager = this;
+
+ source = source || 'local';
+
+ Object.keys( this.getAllNotificationModels() ).forEach( function ( modelName ) {
+ var model = manager.getNotificationModel( modelName );
+ if ( model.getSource() === source ) {
+ modelIds.push( modelName );
+ }
+ } );
+ return modelIds;
+ };
+
+ /**
+ * Get the SeenTime model
+ *
+ * @return {mw.echo.dm.SeenTimeModel} SeenTime model
+ */
+ mw.echo.dm.ModelManager.prototype.getSeenTimeModel = function () {
+ return this.seenTimeModel;
+
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/model/mw.echo.dm.NotificationGroupsList.js b/Echo/modules/model/mw.echo.dm.NotificationGroupsList.js
new file mode 100644
index 00000000..639145f5
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.NotificationGroupsList.js
@@ -0,0 +1,164 @@
+( function ( mw ) {
+ /**
+ * Notification groups list data structure.
+ * It contains mw.echo.dm.NotificationsList items
+ *
+ * This contains a list of grouped notifications by source, and
+ * serves as a list of lists for cross-wiki notifications based
+ * on their remote sources and/or wikis.
+ *
+ * @class
+ * @extends mw.echo.dm.SortedList
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [foreign] The list contains foreign notifications
+ */
+ mw.echo.dm.NotificationGroupsList = function MwEchoDmNotificationGroupsList( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.dm.NotificationGroupsList.parent.call( this );
+
+ // Sorting callback
+ this.setSortingCallback( function ( a, b ) {
+ // Reverse sorting
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+
+ // Fallback on Source
+ return b.getName() - a.getName();
+ } );
+
+ this.foreign = !!config.foreign;
+ this.groups = {};
+
+ this.aggregate( { discard: 'groupDiscardItem' } );
+ this.connect( this, { groupDiscardItem: 'onGroupDiscardItem' } );
+ };
+
+ /* Initialization */
+ OO.inheritClass( mw.echo.dm.NotificationGroupsList, mw.echo.dm.SortedList );
+
+ /* Events */
+
+ /**
+ * @event discard
+ *
+ * A group was permanently removed
+ */
+
+ /* Methods */
+
+ /**
+ * Handle a discard event from any list.
+ * This means that one of the sources has discarded an item.
+ *
+ * @param {mw.echo.dm.NotificationsList} groupList List source model for the item
+ */
+ mw.echo.dm.NotificationGroupsList.prototype.onGroupDiscardItem = function ( groupList ) {
+ // Check if the list has anything at all
+ if ( groupList.isEmpty() ) {
+ // Remove it
+ this.removeGroup( groupList.getName() );
+ }
+ };
+
+ /**
+ * Add a group to the list. This is a more convenient alias to using
+ * addItems()
+ *
+ * @param {string} groupSource Symbolic name for the source of
+ * this group, to be recognized for API operations
+ * @param {Object} sourceData Source data
+ * @param {mw.echo.dm.NotificationItem[]} [groupItems] Optional items to add to this group
+ */
+ mw.echo.dm.NotificationGroupsList.prototype.addGroup = function ( groupSource, sourceData, groupItems ) {
+ var groupListModel = new mw.echo.dm.NotificationsList( {
+ title: sourceData.title,
+ name: groupSource,
+ source: groupSource,
+ sourceURL: sourceData.base,
+ timestamp: sourceData.ts
+ } );
+
+ if ( Array.isArray( groupItems ) && groupItems.length > 0 ) {
+ groupListModel.addItems( groupItems );
+ }
+
+ // Add the group
+ this.addItems( [ groupListModel ] );
+ };
+
+ /**
+ * Get the timestamp of the list by taking the latest list's
+ * timestamp.
+ *
+ * @return {string} Latest timestamp
+ */
+ mw.echo.dm.NotificationGroupsList.prototype.getTimestamp = function () {
+ var items = this.getItems();
+
+ return (
+ items.length > 0 ?
+ items[ 0 ].getTimestamp() :
+ 0
+ );
+ };
+
+ /**
+ * Add items to a specific group by its source identifier.
+ *
+ * @param {string} groupSource Source identifier of the group
+ * @param {mw.echo.dm.NotificationItem[]} groupItems Items to add to this group
+ */
+ mw.echo.dm.NotificationGroupsList.prototype.addItemsToGroup = function ( groupSource, groupItems ) {
+ var group = this.getGroupByName( groupSource );
+
+ if ( group ) {
+ group.addItems( groupItems );
+ }
+ };
+ /**
+ * Remove a group from the list. This is an easier to use alias
+ * to 'removeItems()' method.
+ *
+ * Since this is an intentional action, we fire 'discard' event.
+ * The main reason for this is that the event 'remove' is a general
+ * event that is fired both when a user intends on removing an
+ * item and also when an item is temporarily removed to be re-added
+ * for the sake of sorting. To avoid ambiguity, we use 'discard' event.
+ *
+ * @param {string} groupName Group name
+ * @fires discard
+ */
+ mw.echo.dm.NotificationGroupsList.prototype.removeGroup = function ( groupName ) {
+ var group = this.getGroupByName( groupName );
+
+ if ( group ) {
+ this.removeItems( group );
+ this.emit( 'discard', group );
+ }
+ };
+
+ /**
+ * Get a group by its source identifier.
+ *
+ * @param {string} groupName Group name
+ * @return {mw.echo.dm.NotificationsList|null} Requested group, null if none was found.
+ */
+ mw.echo.dm.NotificationGroupsList.prototype.getGroupByName = function ( groupName ) {
+ var i,
+ items = this.getItems();
+
+ for ( i = 0; i < items.length; i++ ) {
+ if ( items[ i ].getName() === groupName ) {
+ return items[ i ];
+ }
+ }
+ return null;
+ };
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.NotificationItem.js b/Echo/modules/model/mw.echo.dm.NotificationItem.js
new file mode 100644
index 00000000..568166f9
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.NotificationItem.js
@@ -0,0 +1,303 @@
+( function ( mw, $ ) {
+ /* global moment:false */
+ /**
+ * Notification item data structure.
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ * @mixins OO.SortedEmitterList
+ *
+ * @constructor
+ * @param {number} id Notification id,
+ * @param {Object} [config] Configuration object
+ * @cfg {string} [iconUrl] A URL for the given icon.
+ * @cfg {string} [iconType] A string noting the icon type.
+ * @cfg {Object} [content] The message object defining the text for the header and,
+ * optionally, the body of the notification.
+ * @cfg {string} [content.header=''] The header text of the notification
+ * @cfg {string} [content.body=''] The body text of the notification
+ * @cfg {string} [category] The category of this notification. The category identifies
+ * where the notification originates from.
+ * @cfg {string} [type='message'] The notification type 'message' or 'alert'
+ * @cfg {boolean} [read=false] State the read state of the option
+ * @cfg {boolean} [seen=false] State the seen state of the option
+ * @cfg {string} [timestamp] Notification timestamp in ISO 8601 format
+ * @cfg {string} [primaryUrl] Notification primary link in raw url format
+ * @cfg {boolean} [foreign=false] This notification is from a foreign source
+ * @cfg {boolean} [bundled=false] This notification is part of a bundle
+ * @cfg {number[]} [bundledIds] IDs of notifications bundled with this one
+ * @cfg {string} [modelName='local'] The name of the model this item belongs to
+ * @cfg {string} [source] The source this notification is coming from, if it is foreign
+ * @cfg {Object[]} [secondaryUrls] An array of objects defining the secondary URLs
+ * for this notification. The secondary URLs are expected to have this structure:
+ * {
+ * "iconType": "userAvatar", // A symbolic name for the icon.
+ * // Will render as oo-ui-icon-* class.
+ * "label": "", // The label for the link
+ * "prioritized": true/false, // Prioritized links are outside of the popup
+ * // menu, whenever possible.
+ * "url": "..." // The url for the secondary link
+ * }
+ */
+ mw.echo.dm.NotificationItem = function MwEchoDmNotificationItem( id, config ) {
+ var fallbackDate = moment.utc().format( 'YYYY-MM-DD[T]HH:mm:ss[Z]' );
+
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ // Properties
+ this.id = id;
+ this.modelName = config.modelName || 'local';
+ this.content = $.extend( { header: '', body: '' }, config.content );
+ this.category = config.category || '';
+ this.type = config.type || 'message';
+ this.foreign = !!config.foreign;
+ this.bundled = !!config.bundled;
+ this.source = config.source || '';
+ this.iconType = config.iconType;
+ this.iconURL = config.iconURL;
+
+ this.read = !!config.read;
+ this.seen = !!config.seen;
+
+ this.timestamp = config.timestamp || fallbackDate;
+ this.setPrimaryUrl( config.primaryUrl );
+ this.setSecondaryUrls( config.secondaryUrls );
+ this.bundledIds = config.bundledIds;
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.echo.dm.NotificationItem );
+ OO.mixinClass( mw.echo.dm.NotificationItem, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event update
+ *
+ * Item details have changed or were updated
+ */
+
+ /* Methods */
+
+ /**
+ * Get NotificationItem id
+ *
+ * @return {string} NotificationItem Id
+ */
+ mw.echo.dm.NotificationItem.prototype.getId = function () {
+ return this.id;
+ };
+
+ /**
+ * Get NotificationItem content header
+ *
+ * @return {string} NotificationItem content
+ */
+ mw.echo.dm.NotificationItem.prototype.getContentHeader = function () {
+ return this.content.header;
+ };
+
+ /**
+ * Get NotificationItem content body
+ *
+ * @return {string} NotificationItem content body
+ */
+ mw.echo.dm.NotificationItem.prototype.getContentBody = function () {
+ return this.content.body;
+ };
+
+ /**
+ * Get NotificationItem category
+ *
+ * @return {string} NotificationItem category
+ */
+ mw.echo.dm.NotificationItem.prototype.getCategory = function () {
+ return this.category;
+ };
+
+ /**
+ * Get NotificationItem type
+ *
+ * @return {string} NotificationItem type
+ */
+ mw.echo.dm.NotificationItem.prototype.getType = function () {
+ return this.type;
+ };
+
+ /**
+ * Check whether this notification item is read
+ *
+ * @return {boolean} Notification item is read
+ */
+ mw.echo.dm.NotificationItem.prototype.isRead = function () {
+ return this.read;
+ };
+
+ /**
+ * Check whether this notification item is seen
+ *
+ * @return {boolean} Notification item is seen
+ */
+ mw.echo.dm.NotificationItem.prototype.isSeen = function () {
+ return this.seen;
+ };
+
+ /**
+ * Check whether this notification item is foreign
+ *
+ * @return {boolean} Notification item is foreign
+ */
+ mw.echo.dm.NotificationItem.prototype.isForeign = function () {
+ return this.foreign;
+ };
+
+ /**
+ * Check whether this notification item is part of a bundle
+ *
+ * @return {boolean} Notification item is part of a bundle
+ */
+ mw.echo.dm.NotificationItem.prototype.isBundled = function () {
+ return this.bundled;
+ };
+
+ /**
+ * Set this notification item as foreign
+ *
+ * @param {boolean} isForeign Notification item is foreign
+ */
+ mw.echo.dm.NotificationItem.prototype.setForeign = function ( isForeign ) {
+ this.foreign = isForeign;
+ };
+
+ /**
+ * Toggle the read state of the widget
+ *
+ * @param {boolean} [read] The current read state. If not given, the state will
+ * become the opposite of its current state.
+ * @fires update
+ */
+ mw.echo.dm.NotificationItem.prototype.toggleRead = function ( read ) {
+ read = read !== undefined ? read : !this.read;
+ if ( this.read !== read ) {
+ this.read = read;
+ this.emit( 'update' );
+ this.emit( 'sortChange' );
+ }
+ };
+
+ /**
+ * Toggle the seen state of the widget
+ *
+ * @param {boolean} [seen] The current seen state. If not given, the state will
+ * become the opposite of its current state.
+ * @fires update
+ */
+ mw.echo.dm.NotificationItem.prototype.toggleSeen = function ( seen ) {
+ seen = seen !== undefined ? seen : !this.seen;
+ if (
+ this.seen !== seen &&
+ // Do not change the state of a read item, since its
+ // seen state (never 'unseen') never changes
+ !this.isRead()
+ ) {
+ this.seen = seen;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get the notification timestamp
+ *
+ * @return {number} Notification timestamp in Mediawiki timestamp format
+ */
+ mw.echo.dm.NotificationItem.prototype.getTimestamp = function () {
+ return this.timestamp;
+ };
+
+ /**
+ * Set the notification link
+ *
+ * @param {string} link Notification url
+ */
+ mw.echo.dm.NotificationItem.prototype.setPrimaryUrl = function ( link ) {
+ this.primaryUrl = link;
+ };
+
+ /**
+ * Get the notification link
+ *
+ * @return {string} Notification url
+ */
+ mw.echo.dm.NotificationItem.prototype.getPrimaryUrl = function () {
+ return this.primaryUrl;
+ };
+
+ /**
+ * Get the notification icon URL
+ *
+ * @return {string} Notification icon URL
+ */
+ mw.echo.dm.NotificationItem.prototype.getIconURL = function () {
+ return this.iconURL;
+ };
+
+ /**
+ * Get the notification icon type
+ *
+ * @return {string} Notification icon type
+ */
+ mw.echo.dm.NotificationItem.prototype.getIconType = function () {
+ return this.iconType;
+ };
+
+ /**
+ * Set the notification's secondary links
+ * See constructor documentation for the structure of these links objects.
+ *
+ * @param {Object[]} links Secondary url definitions
+ */
+ mw.echo.dm.NotificationItem.prototype.setSecondaryUrls = function ( links ) {
+ this.secondaryUrls = links || [];
+ };
+
+ /**
+ * Get the notification's secondary links
+ *
+ * @return {Object[]} Secondary url definitions
+ */
+ mw.echo.dm.NotificationItem.prototype.getSecondaryUrls = function () {
+ return this.secondaryUrls;
+ };
+
+ /**
+ * Get the notification's source
+ *
+ * @return {string} Notification source
+ */
+ mw.echo.dm.NotificationItem.prototype.getSource = function () {
+ return this.source;
+ };
+
+ /**
+ * Get the notification's model name
+ *
+ * @return {string} Notification model name
+ */
+ mw.echo.dm.NotificationItem.prototype.getModelName = function () {
+ return this.modelName;
+ };
+
+ /**
+ * Get the all ids contained in this notification
+ *
+ * @return {number[]}
+ */
+ mw.echo.dm.NotificationItem.prototype.getAllIds = function () {
+ return [ this.getId() ].concat( this.bundledIds || [] );
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/model/mw.echo.dm.NotificationsList.js b/Echo/modules/model/mw.echo.dm.NotificationsList.js
new file mode 100644
index 00000000..fa0fe020
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.NotificationsList.js
@@ -0,0 +1,271 @@
+( function ( mw ) {
+ /**
+ * Notifications list data structure.
+ *
+ * This contains the list of mw.echo.dm.NotificationItem items
+ * in the specified order and reflects when the list has changed.
+ *
+ * @class
+ * @extends mw.echo.dm.SortedList
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ * @cfg {Function} [sortingCallback] A function defining the sorting order
+ * of items in this list.
+ * @cfg {string} [title] An optional title for this notifications list
+ * @cfg {string} [name='local'] Symbolic name for this list
+ * @cfg {string} [source='local'] Symbolic name for the source of this list.
+ * This is used mainly for recognizing where API actions should be by the
+ * controller.
+ * @cfg {string} [sourceURL] The URL for the article base of the remote
+ * group or wiki
+ * @cfg {string} [timestamp=0] A timestamp representing the latest item in
+ * then list.
+ */
+ mw.echo.dm.NotificationsList = function MwEchoDmNotificationsList( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.dm.NotificationsList.parent.call( this );
+
+ this.name = config.name || 'local';
+ this.source = config.source || 'local';
+ this.sourceURL = config.sourceURL || '';
+ this.title = config.title || '';
+ this.fallbackTimestamp = config.timestamp || 0;
+
+ // Sorting callback
+ this.setSortingCallback( config.sortingCallback || function ( a, b ) {
+ if ( !a.isRead() && b.isRead() ) {
+ return -1; // Unread items are always above read items
+ } else if ( a.isRead() && !b.isRead() ) {
+ return 1;
+ } else if ( !a.isForeign() && b.isForeign() ) {
+ return -1;
+ } else if ( a.isForeign() && !b.isForeign() ) {
+ return 1;
+ }
+
+ // Reverse sorting
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+
+ // Fallback on IDs
+ return b.getId() - a.getId();
+ } );
+
+ // Events
+ this.aggregate( { update: 'itemUpdate' } );
+ };
+
+ /* Initialization */
+ OO.inheritClass( mw.echo.dm.NotificationsList, mw.echo.dm.SortedList );
+
+ /* Events */
+
+ /**
+ * @event update
+ * @param {mw.echo.dm.NotificationItem[]} items Current items in the list
+ *
+ * The list has been updated
+ */
+
+ /**
+ * @event itemUpdate
+ * @param {mw.echo.dm.NotificationItem} item Item that has changed
+ *
+ * An item in the list has been updated
+ */
+
+ /**
+ * @event discard
+ * @param {mw.echo.dm.NotificationItem} item Item that was discarded
+ *
+ * An item was discarded
+ */
+
+ /* Methods */
+
+ /**
+ * Set the items in this list
+ *
+ * @param {mw.echo.dm.NotificationItem[]} items Items to insert into the list
+ * @fires update
+ */
+ mw.echo.dm.NotificationsList.prototype.setItems = function ( items ) {
+ this.clearItems();
+ this.addItems( items );
+ this.emit( 'update', this.getItems() );
+ };
+
+ /**
+ * Discard items from the list.
+ *
+ * This is a more precise operation than 'removeItems' because when
+ * the list is resorting the position of a single item, it removes
+ * the item and reinserts it, which makes the 'remove' event unhelpful
+ * to differentiate between actually discarding items, and only
+ * temporarily moving them.
+ *
+ * @param {mw.echo.dm.NotificationItem[]} items Items to insert into the list
+ */
+ mw.echo.dm.NotificationsList.prototype.discardItems = function ( items ) {
+ this.removeItems( items );
+ this.emit( 'discard', items );
+ };
+
+ /**
+ * Get an array of all items' IDs.
+ *
+ * @return {number[]} Item IDs
+ */
+ mw.echo.dm.NotificationsList.prototype.getAllItemIds = function () {
+ var i,
+ idArray = [],
+ items = this.getItems();
+
+ for ( i = 0; i < items.length; i++ ) {
+ idArray.push( items[ i ].getId() );
+ }
+
+ return idArray;
+ };
+
+ /**
+ * Get an array of all items' IDs for a given type
+ *
+ * @param {string} type Notification type
+ * @return {number[]} Item IDs
+ */
+ mw.echo.dm.NotificationsList.prototype.getAllItemIdsByType = function ( type ) {
+ var i,
+ idArray = [],
+ items = this.getItems();
+
+ for ( i = 0; i < items.length; i++ ) {
+ if ( items[ i ].getType() === type ) {
+ idArray.push( items[ i ].getId() );
+ }
+ }
+
+ return idArray;
+ };
+
+ /**
+ * Get the title associated with this list.
+ *
+ * @return {string} List title
+ */
+ mw.echo.dm.NotificationsList.prototype.getTitle = function () {
+ return this.title;
+ };
+
+ /**
+ * Get the name associated with this list.
+ *
+ * @return {string} List name
+ */
+ mw.echo.dm.NotificationsList.prototype.getName = function () {
+ return this.name;
+ };
+
+ /**
+ * Get the source associated with this list.
+ *
+ * @return {string} List source
+ */
+ mw.echo.dm.NotificationsList.prototype.getSource = function () {
+ return this.source;
+ };
+
+ /**
+ * Get the source article url associated with this list.
+ *
+ * @return {string} List source article url
+ */
+ mw.echo.dm.NotificationsList.prototype.getSourceURL = function () {
+ return this.sourceURL;
+ };
+
+ /**
+ * Get the timestamp of the list by taking the latest notification
+ * timestamp.
+ *
+ * @return {string} Latest timestamp
+ */
+ mw.echo.dm.NotificationsList.prototype.getTimestamp = function () {
+ var items = this.getItems();
+
+ return (
+ items.length > 0 ?
+ // In the cases where we want a single timestamp for a
+ // group, the group is usually all unread, which makes
+ // the first item its newest
+ items[ 0 ].getTimestamp() :
+ this.fallbackTimestamp
+ );
+ };
+
+ /**
+ * Find all items that match the given IDs.
+ *
+ * @param {number[]} ids An array of item IDs
+ * @return {mw.echo.dm.NotificationItem[]} An array of matching items
+ */
+ mw.echo.dm.NotificationsList.prototype.findByIds = function ( ids ) {
+ return this.getItems().filter( function ( item ) {
+ return ids.indexOf( item.getId() ) !== -1;
+ } );
+ };
+
+ /**
+ * A general method to get the number of notifications in this list
+ *
+ * @return {number} Item count
+ */
+ mw.echo.dm.NotificationsList.prototype.getCount = function () {
+ return this.getItemCount();
+ };
+
+ /**
+ * Check if there are unseen items in this list
+ *
+ * @return {boolean} There are unseen items in the list
+ */
+ mw.echo.dm.NotificationsList.prototype.hasUnseen = function () {
+ var isItemUnseen = function ( item ) {
+ return !item.isSeen();
+ },
+ items = this.getItems();
+
+ return !!items.some( isItemUnseen );
+ };
+
+ /**
+ * Set all notifications to seen
+ *
+ * @param {string} timestamp New seen timestamp
+ */
+ mw.echo.dm.NotificationsList.prototype.updateSeenState = function ( timestamp ) {
+ this.getItems().forEach( function ( notification ) {
+ notification.toggleSeen(
+ notification.isRead() || notification.getTimestamp() < timestamp
+ );
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.dm.NotificationsList.prototype.isGroup = function () {
+ return false;
+ };
+
+ mw.echo.dm.NotificationsList.prototype.isForeign = function () {
+ return this.getSource() !== 'local';
+ };
+
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.PaginationModel.js b/Echo/modules/model/mw.echo.dm.PaginationModel.js
new file mode 100644
index 00000000..eae7c35d
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.PaginationModel.js
@@ -0,0 +1,222 @@
+( function ( mw ) {
+ /**
+ * Pagination model for echo notifications pages.
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} config Configuration object
+ * @cfg {string} [pageNext] The continue value of the next page
+ * @cfg {number} [itemsPerPage] The number of items per page
+ * @cfg {number} [currentPageItemCount] The number of items that are in the
+ * current page. If not given, the initial count defaults to the total number
+ * of items per page.
+ */
+ mw.echo.dm.PaginationModel = function MwEchoDmPaginationModel( config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.pagesContinue = [];
+ this.itemsPerPage = config.itemsPerPage || 25;
+ this.currentPageItemCount = config.currentPageItemCount || this.itemsPerPage;
+
+ // Set initial page
+ this.currPageIndex = 0;
+ this.pagesContinue[ 0 ] = '';
+
+ // If a next page is given, fill it
+ if ( config.pageNext ) {
+ this.setPageContinue( 1, config.pageNext );
+ }
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.echo.dm.PaginationModel );
+ OO.mixinClass( mw.echo.dm.PaginationModel, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event update
+ *
+ * Pagination information was updated
+ */
+
+ /* Methods */
+
+ /**
+ * Reset pagination data
+ *
+ * @fires update
+ */
+ mw.echo.dm.PaginationModel.prototype.reset = function () {
+ this.pagesContinue = [];
+ this.currPageIndex = 0;
+ this.currentPageItemCount = this.itemsPerPage;
+
+ this.emit( 'update' );
+ };
+ /**
+ * Set a page index with its 'continue' value, used for API fetching
+ *
+ * @param {number} page Page index
+ * @param {string} continueVal Continue string value
+ */
+ mw.echo.dm.PaginationModel.prototype.setPageContinue = function ( page, continueVal ) {
+ if ( this.pagesContinue[ page ] !== continueVal ) {
+ this.pagesContinue[ page ] = continueVal;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get the 'continue' value of a certain page
+ *
+ * @param {number} page Page index
+ * @return {string} Continue string value
+ */
+ mw.echo.dm.PaginationModel.prototype.getPageContinue = function ( page ) {
+ return this.pagesContinue[ page ];
+ };
+
+ /**
+ * Get the current page index
+ *
+ * @return {number} Current page index
+ */
+ mw.echo.dm.PaginationModel.prototype.getCurrPageIndex = function () {
+ return this.currPageIndex;
+ };
+
+ /**
+ * Set the current page index
+ *
+ * @private
+ * @param {number} index Current page index
+ */
+ mw.echo.dm.PaginationModel.prototype.setCurrPageIndex = function ( index ) {
+ this.currPageIndex = index;
+ };
+
+ /**
+ * Move forward to the next page
+ *
+ * @fires update
+ */
+ mw.echo.dm.PaginationModel.prototype.forwards = function () {
+ if ( this.hasNextPage() ) {
+ this.setCurrPageIndex( this.currPageIndex + 1 );
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Move backwards to the previous page
+ *
+ * @fires update
+ */
+ mw.echo.dm.PaginationModel.prototype.backwards = function () {
+ if ( this.hasPrevPage() ) {
+ this.setCurrPageIndex( this.currPageIndex - 1 );
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get the previous page continue value
+ *
+ * @return {string} Previous page continue value
+ */
+ mw.echo.dm.PaginationModel.prototype.getPrevPageContinue = function () {
+ return this.pagesContinue[ this.currPageIndex - 1 ] || '';
+ };
+
+ /**
+ * Get the current page continue value
+ *
+ * @return {string} Current page continue value
+ */
+ mw.echo.dm.PaginationModel.prototype.getCurrPageContinue = function () {
+ return this.pagesContinue[ this.currPageIndex ] || '';
+ };
+
+ /**
+ * Get the next page continue value
+ *
+ * @return {string} Next page continue value
+ */
+ mw.echo.dm.PaginationModel.prototype.getNextPageContinue = function () {
+ return this.pagesContinue[ this.currPageIndex + 1 ] || '';
+ };
+
+ /**
+ * Set the next page continue value
+ *
+ * @param {string} cont Next page continue value
+ */
+ mw.echo.dm.PaginationModel.prototype.setNextPageContinue = function ( cont ) {
+ this.setPageContinue( this.currPageIndex + 1, cont );
+ };
+
+ /**
+ * Check whether a previous page exists
+ *
+ * @return {boolean} Previous page exists
+ */
+ mw.echo.dm.PaginationModel.prototype.hasPrevPage = function () {
+ return this.currPageIndex > 0;
+ };
+
+ /**
+ * Check whether a next page exists
+ *
+ * @return {boolean} Next page exists
+ */
+ mw.echo.dm.PaginationModel.prototype.hasNextPage = function () {
+ return !!this.pagesContinue[ this.currPageIndex + 1 ];
+ };
+
+ /**
+ * Set the number of items in the current page
+ *
+ * @param {number} count Number of items
+ * @fires update
+ */
+ mw.echo.dm.PaginationModel.prototype.setCurrentPageItemCount = function ( count ) {
+ if ( this.currentPageItemCount !== count ) {
+ this.currentPageItemCount = count;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get the number of items in the current page
+ *
+ * @return {number} Number of items
+ */
+ mw.echo.dm.PaginationModel.prototype.getCurrentPageItemCount = function () {
+ return this.currentPageItemCount;
+ };
+
+ /**
+ * Set the number of items per page
+ *
+ * @param {number} count Number of items per page
+ */
+ mw.echo.dm.PaginationModel.prototype.setItemsPerPage = function ( count ) {
+ this.itemsPerPage = count;
+ };
+
+ /**
+ * Get the number of items per page
+ *
+ * @return {number} Number of items per page
+ */
+ mw.echo.dm.PaginationModel.prototype.getItemsPerPage = function () {
+ return this.itemsPerPage;
+ };
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.SeenTimeModel.js b/Echo/modules/model/mw.echo.dm.SeenTimeModel.js
new file mode 100644
index 00000000..e00702e9
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.SeenTimeModel.js
@@ -0,0 +1,81 @@
+( function ( mw ) {
+ /**
+ * SeenTime model for Echo notifications
+ *
+ * @param {Object} [config] Configuration
+ * @cfg {string|string[]} [types='alert','message'] The types of notifications
+ * that this model handles
+ */
+ mw.echo.dm.SeenTimeModel = function MwEchoSeenTimeModel( config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.types = [ 'alert', 'message' ];
+ if ( config.types ) {
+ this.types = Array.isArray( config.types ) ? config.types : [ config.types ];
+ }
+
+ this.seenTime = mw.config.get( 'wgEchoSeenTime' ) || {};
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.echo.dm.SeenTimeModel );
+ OO.mixinClass( mw.echo.dm.SeenTimeModel, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event update
+ * @param {string} time Seen time, as a full UTC ISO 8601 timestamp.
+ *
+ * Seen time has been updated for the given source
+ */
+
+ /* Methods */
+
+ /**
+ * Get the global seenTime value
+ *
+ * @return {string} Seen time, as a full UTC ISO 8601 timestamp.
+ */
+ mw.echo.dm.SeenTimeModel.prototype.getSeenTime = function () {
+ return this.seenTime[ this.getTypes()[ 0 ] ] || 0;
+ };
+
+ /**
+ * Set the seen time value for the source
+ *
+ * @private
+ * @param {string} time Seen time, as a full UTC ISO 8601 timestamp.
+ * @fires update
+ */
+ mw.echo.dm.SeenTimeModel.prototype.setSeenTime = function ( time ) {
+ var model = this,
+ hasChanged = false;
+
+ this.getTypes().forEach( function ( type ) {
+ if ( model.seenTime[ type ] !== time ) {
+ model.seenTime[ type ] = time;
+ hasChanged = true;
+ }
+ } );
+
+ if ( hasChanged ) {
+ this.emit( 'update', time );
+ }
+ };
+
+ /**
+ * Get the types associated with this model
+ *
+ * @private
+ * @return {string[]} Types for this model; an array of 'alert', 'message' or both.
+ */
+ mw.echo.dm.SeenTimeModel.prototype.getTypes = function () {
+ return this.types;
+ };
+
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.SortedList.js b/Echo/modules/model/mw.echo.dm.SortedList.js
new file mode 100644
index 00000000..b6b1b073
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.SortedList.js
@@ -0,0 +1,30 @@
+( function ( mw ) {
+ /**
+ * Sorted list abstract data structure.
+ *
+ * @class
+ * @abstract
+ * @mixins OO.EventEmitter
+ * @mixins OO.SortedEmitterList
+ *
+ * @constructor
+ */
+ mw.echo.dm.SortedList = function MwEchoDmSortedList() {
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+ OO.SortedEmitterList.call( this );
+ };
+
+ /* Initialization */
+
+ OO.mixinClass( mw.echo.dm.SortedList, OO.EventEmitter );
+ OO.mixinClass( mw.echo.dm.SortedList, OO.SortedEmitterList );
+
+ /**
+ * Defines whether or not this list contains items
+ * or lists of items.
+ *
+ * @return {boolean} This list is a group
+ */
+ mw.echo.dm.SortedList.prototype.isGroup = null;
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.SourcePagesModel.js b/Echo/modules/model/mw.echo.dm.SourcePagesModel.js
new file mode 100644
index 00000000..c305f7d9
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.SourcePagesModel.js
@@ -0,0 +1,180 @@
+( function ( mw ) {
+ /**
+ * Source pages model for notification filtering
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} config Configuration object
+ * @cfg {string} [currentSource] The selected source for the model.
+ * Defaults to the current wiki.
+ */
+ mw.echo.dm.SourcePagesModel = function MwEchoDmSourcePagesModel( config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.sources = {};
+
+ this.currentSource = config.currentSource || 'local';
+ this.currentPage = null;
+ };
+
+ /* Initialization */
+ OO.initClass( mw.echo.dm.SourcePagesModel );
+ OO.mixinClass( mw.echo.dm.SourcePagesModel, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event update
+ *
+ * The state of the source page model has changed
+ */
+
+ /* Methds */
+
+ /**
+ * Set the current source and page.
+ *
+ * @param {string} source New source
+ * @param {string} page New page
+ * @fires update
+ */
+ mw.echo.dm.SourcePagesModel.prototype.setCurrentSourcePage = function ( source, page ) {
+ if (
+ this.currentSource !== source ||
+ this.currentPage !== page
+ ) {
+ this.currentSource = source;
+ this.currentPage = page;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get the current source
+ *
+ * @return {string} Current source
+ */
+ mw.echo.dm.SourcePagesModel.prototype.getCurrentSource = function () {
+ return this.currentSource;
+ };
+
+ /**
+ * Get the title of the currently selected page
+ *
+ * @return {string} Page title
+ */
+ mw.echo.dm.SourcePagesModel.prototype.getCurrentPage = function () {
+ return this.currentPage;
+ };
+
+ /**
+ * Set all sources and pages. This will also reset and override any
+ * previously set information.
+ *
+ * @param {Object} sourceData A detailed object about sources and pages
+ */
+ mw.echo.dm.SourcePagesModel.prototype.setAllSources = function ( sourceData ) {
+ var source;
+
+ this.reset();
+ for ( source in sourceData ) {
+ if ( sourceData.hasOwnProperty( source ) ) {
+ this.setSourcePagesDetails( source, sourceData[ source ] );
+ }
+ }
+ this.emit( 'update' );
+ };
+
+ /**
+ * Get an array of all source names
+ *
+ * @return {string[]} Array of source names
+ */
+ mw.echo.dm.SourcePagesModel.prototype.getSourcesArray = function () {
+ return Object.keys( this.sources );
+ };
+
+ /**
+ * Get the title of a source
+ *
+ * @param {string} source Symbolic name of the source
+ * @return {string} Source title
+ */
+ mw.echo.dm.SourcePagesModel.prototype.getSourceTitle = function ( source ) {
+ return this.sources[ source ] && this.sources[ source ].title;
+ };
+
+ /**
+ * Get the total count of a source
+ *
+ * @param {string} source Symbolic name of the source
+ * @return {number} Total count
+ */
+ mw.echo.dm.SourcePagesModel.prototype.getSourceTotalCount = function ( source ) {
+ return ( this.sources[ source ] && this.sources[ source ].totalCount ) || 0;
+ };
+
+ /**
+ * Get all pages in a source
+ *
+ * @param {string} source Symbolic name of the source
+ * @return {Object} Page definitions in this source
+ */
+ mw.echo.dm.SourcePagesModel.prototype.getSourcePages = function ( source ) {
+ return this.sources[ source ] && this.sources[ source ].pages;
+ };
+
+ /**
+ * Get the list of page titles associated with one group title.
+ *
+ * @param {string} source Symbolic name of the source
+ * @param {string} title Group title
+ * @return {string[]} Page titles
+ */
+ mw.echo.dm.SourcePagesModel.prototype.getGroupedPagesForTitle = function ( source, title ) {
+ return OO.getProp( this.sources, source, 'pages', title, 'pages' ) || [];
+ };
+
+ /**
+ * Get the list of page titles associated with the current group title.
+ *
+ * @return {string[]} Page titles
+ */
+ mw.echo.dm.SourcePagesModel.prototype.getGroupedPagesForCurrentTitle = function () {
+ return this.getGroupedPagesForTitle( this.getCurrentSource(), this.getCurrentPage() );
+ };
+
+ /**
+ * Reset the data
+ */
+ mw.echo.dm.SourcePagesModel.prototype.reset = function () {
+ this.sources = {};
+ };
+
+ /**
+ * Set the details of a source and its page definitions
+ *
+ * @private
+ * @param {string} source Source symbolic name
+ * @param {Object} details Details object
+ */
+ mw.echo.dm.SourcePagesModel.prototype.setSourcePagesDetails = function ( source, details ) {
+ var i, page;
+ this.sources[ source ] = {
+ title: details.source.title || source,
+ base: details.source.base,
+ totalCount: details.totalCount || 0,
+ pages: {}
+ };
+
+ for ( i = 0; i < details.pages.length; i++ ) {
+ page = details.pages[ i ];
+ this.sources[ source ].pages[ page.title ] = page;
+ }
+ };
+}( mediaWiki ) );
diff --git a/Echo/modules/model/mw.echo.dm.UnreadNotificationCounter.js b/Echo/modules/model/mw.echo.dm.UnreadNotificationCounter.js
new file mode 100644
index 00000000..3257df51
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.UnreadNotificationCounter.js
@@ -0,0 +1,147 @@
+( function ( mw, $ ) {
+ /**
+ * Echo notification UnreadNotificationCounter model
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} api An instance of EchoAPI.
+ * @param {string} type The notification type 'message', 'alert', or 'all'.
+ * @param {number} max Maximum number supported. Above this number there is no precision, we only know it is 'more than max'.
+ * @param {Object} config Configuration object
+ * @cfg {boolean} [localOnly=false] The update only takes into account
+ * local notifications and ignores the number of cross-wiki notifications.
+ * @cfg {string} [source='local'] The source for this counter. Specifically important if the counter
+ * is set to be counting only local notifications
+ */
+ mw.echo.dm.UnreadNotificationCounter = function mwEchoDmUnreadNotificationCounter( api, type, max, config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.api = api;
+ this.type = type;
+ this.max = max;
+ this.prioritizer = new mw.echo.api.PromisePrioritizer();
+
+ this.count = 0;
+ this.localOnly = config.localOnly === undefined ? false : !!config.localOnly;
+ this.source = config.source || 'local';
+ };
+
+ /* Inheritance */
+
+ OO.mixinClass( mw.echo.dm.UnreadNotificationCounter, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event countChange
+ * @param {number} count Notification count
+ *
+ * The number of unread notification represented by this counter has changed.
+ */
+
+ /* Methods */
+
+ /**
+ * Normalizes for a capped count in case the requested count
+ * is higher than the cap.
+ *
+ * This is the client-side version of
+ * NotificationController::getCappedNotificationCount.
+ *
+ * @param {number} count Count before cap is applied
+ * @return {number} Count with cap applied
+ */
+ mw.echo.dm.UnreadNotificationCounter.prototype.getCappedNotificationCount = function ( count ) {
+ if ( count < 0 ) {
+ return 0;
+ } else if ( count <= this.max ) {
+ return count;
+ } else {
+ return this.max + 1;
+ }
+ };
+
+ /**
+ * Get the current count
+ *
+ * @return {number} current count
+ */
+ mw.echo.dm.UnreadNotificationCounter.prototype.getCount = function () {
+ return this.count;
+ };
+
+ /**
+ * Set the current count
+ *
+ * @param {number} count
+ * @param {boolean} isEstimation Whether this number is estimated or accurate
+ */
+ mw.echo.dm.UnreadNotificationCounter.prototype.setCount = function ( count, isEstimation ) {
+ if ( isEstimation ) {
+ if ( this.count > this.max ) {
+ // this prevents toggling between 90-ish and 99+
+ return;
+ }
+ if ( count < 0 ) {
+ // wrong estimation?
+ return;
+ }
+ }
+
+ // Normalize
+ count = this.getCappedNotificationCount( count );
+
+ if ( count !== this.count ) {
+ this.count = count;
+ this.emit( 'countChange', this.count );
+ }
+ };
+
+ /**
+ * Report an estimated change to this counter
+ *
+ * @param {number} delta
+ */
+ mw.echo.dm.UnreadNotificationCounter.prototype.estimateChange = function ( delta ) {
+ this.setCount( this.count + delta, true );
+ };
+
+ /**
+ * Request that this counter update itself from the API
+ *
+ * @return {jQuery.Promise} Promise that is resolved when the actual unread
+ * count is fetched, with the actual unread notification count.
+ */
+ mw.echo.dm.UnreadNotificationCounter.prototype.update = function () {
+ var model = this;
+
+ if ( !this.api ) {
+ return $.Deferred().reject();
+ }
+
+ return this.prioritizer.prioritize( this.api.fetchUnreadCount(
+ this.source,
+ this.type,
+ this.localOnly
+ ) ).then( function ( actualCount ) {
+ model.setCount( actualCount, false );
+
+ return actualCount;
+ } );
+ };
+
+ /**
+ * Set the source for this counter
+ *
+ * @param {string} source Source name
+ */
+ mw.echo.dm.UnreadNotificationCounter.prototype.setSource = function ( source ) {
+ this.source = source;
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/model/mw.echo.dm.js b/Echo/modules/model/mw.echo.dm.js
new file mode 100644
index 00000000..4d9e3d3f
--- /dev/null
+++ b/Echo/modules/model/mw.echo.dm.js
@@ -0,0 +1,3 @@
+( function ( mw ) {
+ mw.echo.dm = {};
+}( mediaWiki ) );
diff --git a/Echo/modules/mw.echo.js b/Echo/modules/mw.echo.js
new file mode 100644
index 00000000..cd4101bb
--- /dev/null
+++ b/Echo/modules/mw.echo.js
@@ -0,0 +1,4 @@
+( function ( mw ) {
+ mw.echo = mw.echo || {};
+ mw.echo.config = mw.echo.config || { maxPrioritizedActions: 2 };
+}( mediaWiki ) );
diff --git a/Echo/modules/nojs/mw.echo.alert.less b/Echo/modules/nojs/mw.echo.alert.less
index 2e27a25e..c26c47dd 100644
--- a/Echo/modules/nojs/mw.echo.alert.less
+++ b/Echo/modules/nojs/mw.echo.alert.less
@@ -1,7 +1,7 @@
.mw-echo-alert {
- border-radius: 2px;
- background-color: #F9C557;
- padding: 0.25em 0.8em 0.2em 0.8em;
- color: #555555;
- font-weight: normal;
+ border-radius: 2px;
+ background-color: #fc3;
+ padding: 0.25em 0.8em 0.2em 0.8em;
+ color: #222;
+ font-weight: normal;
}
diff --git a/Echo/modules/nojs/mw.echo.alert.monobook.less b/Echo/modules/nojs/mw.echo.alert.monobook.less
index f1cfd054..95db1c0f 100644
--- a/Echo/modules/nojs/mw.echo.alert.monobook.less
+++ b/Echo/modules/nojs/mw.echo.alert.monobook.less
@@ -1,3 +1,3 @@
#pt-mytalk a.mw-echo-alert:hover {
- background-color: #FAB951;
+ background-color: #fab951;
}
diff --git a/Echo/modules/nojs/mw.echo.badge.less b/Echo/modules/nojs/mw.echo.badge.less
index 0ede1fb3..3d267aff 100644
--- a/Echo/modules/nojs/mw.echo.badge.less
+++ b/Echo/modules/nojs/mw.echo.badge.less
@@ -1,62 +1,92 @@
@import '../echo.variables';
+@import 'mediawiki.mixins';
+/* stylelint-disable no-descending-specificity */
/* We have to include the #pt-notifications selector due to monobook */
.mw-echo-notifications-badge {
#pt-notifications-alert &,
- #pt-notifications-message & {
- border-radius: 0.2em;
- background-color: #d2d2d2;
- font-size: 1.125em;
- font-weight: bold;
- color: white;
+ #pt-notifications-notice & {
+ position: relative;
+ display: block;
+ width: 24px;
+ height: 24px;
+ // Hide the text, but keep accessible for screen-readers
+ // Later we put the icons back onscreen with an opposite offset
+ top: -@badge-offscreen-offset - 5px;
cursor: pointer;
text-decoration: none;
- margin-top: -0.2em;
- display: inline-block;
-
- padding: @badge-padding (@badge-padding + 0.25em) @badge-padding (@badge-padding + 0.25em + 1.1em);
- height: 1.05em;
-
- body.ltr & {
- background-position: @badge-padding 0.1em;
- }
- body.rtl & {
- // CSS sucks, we can't specify background-position-x from the right
- // You can in Firefox with background-position-x: right 0.12em;
- // but that's not supported in any other browsers
- background-position: ~"calc(100% - @{badge-padding}) 0.1em";
- }
- background-size: @badge-icon-size;
- background-repeat: no-repeat;
&:hover,
&:active,
&:focus {
- background-color: #c2c2c2;
- outline: none;
- -moz-outline-style: none;
+ outline: 0;
+ -moz-outline-style: 0;
}
&-dimmed {
opacity: 0.4;
}
- }
- #pt-notifications-message & {
- margin-left: @badge-distance-adjustment;
+ // Background icon
+ &:before {
+ position: absolute;
+ display: inline-block;
+ cursor: pointer;
+ opacity: 0.8;
+ content: '';
+ background-repeat: no-repeat;
+ // Bring it back onscreen
+ top: @badge-offscreen-offset;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
- + .oo-ui-popupWidget {
- left: (1em + @badge-distance-adjustment);
+ // Counter
+ &:after {
+ position: absolute;
+ display: inline-block;
+ cursor: pointer;
+ // Bring it back onscreen
+ top: @badge-offscreen-offset + 9px;
+ left: 55%;
+ font-size: 0.9em;
+ font-weight: bold;
+ padding: 0 0.3em;
+ border: 1px solid #fff;
+ border-radius: 2px;
+ background-color: @badge-counter-background-seen;
+ content: attr( data-counter-text );
+ color: #fff;
}
- }
+ &.mw-echo-notifications-badge-long-label {
+ &:after {
+ left: 35%;
+ }
+ }
+
+ &.mw-echo-notifications-badge-all-read {
+ opacity: 0.625;
- &.mw-echo-unseen-notifications {
- #pt-notifications-alert & {
- background-color: @badge-background-unseen-alert;
+ &:after {
+ visibility: hidden;
+ }
}
- #pt-notifications-message & {
- background-color: @badge-background-unseen-message;
+ }
+
+ #pt-notifications-alert & {
+ &:before {
+ /* @embed */
+ background-image: url( ../icons/bell.svg );
+ }
+ }
+
+ #pt-notifications-notice & {
+ &:before {
+ /* @embed */
+ background-image: url( ../icons/tray.svg );
}
}
}
+/* stylelint-enable no-descending-specificity */
diff --git a/Echo/modules/nojs/mw.echo.badge.modern.less b/Echo/modules/nojs/mw.echo.badge.modern.less
new file mode 100644
index 00000000..48484017
--- /dev/null
+++ b/Echo/modules/nojs/mw.echo.badge.modern.less
@@ -0,0 +1,8 @@
+.mw-echo-notifications-badge {
+ #pt-notifications-alert &,
+ #pt-notifications-notice & {
+ &:before {
+ z-index: 0;
+ }
+ }
+}
diff --git a/Echo/modules/nojs/mw.echo.badge.monobook.less b/Echo/modules/nojs/mw.echo.badge.monobook.less
new file mode 100644
index 00000000..576d4901
--- /dev/null
+++ b/Echo/modules/nojs/mw.echo.badge.monobook.less
@@ -0,0 +1,36 @@
+@import '../echo.variables';
+
+/* We have to include the #pt-notifications selector due to monobook */
+.mw-echo-notifications-badge {
+ #pt-notifications-notice &,
+ #pt-notifications-alert & {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ top: -@badge-offscreen-offset - 1px;
+
+ &:before {
+ background-size: 16px 16px;
+ }
+
+ &:after {
+ top: @badge-offscreen-offset + 3px;
+ }
+ }
+
+ &.oo-ui-flaggedElement-unseen,
+ &.mw-echo-unseen-notifications {
+ #pt-notifications-alert &:after {
+ background-color: @badge-counter-background-unseen-alert;
+ }
+
+ #pt-notifications-notice &:after {
+ background-color: @badge-counter-background-unseen-message;
+ }
+ }
+}
+
+#p-personal #pt-notifications-alert,
+#p-personal #pt-notifications-notice {
+ margin-right: 0.2em;
+}
diff --git a/Echo/modules/nojs/mw.echo.badge.vector.less b/Echo/modules/nojs/mw.echo.badge.vector.less
new file mode 100644
index 00000000..eba9aa56
--- /dev/null
+++ b/Echo/modules/nojs/mw.echo.badge.vector.less
@@ -0,0 +1,21 @@
+@import '../echo.variables';
+
+/* We have to include the #pt-notifications selector due to monobook */
+.mw-echo-notifications-badge {
+ &.oo-ui-flaggedElement-unseen,
+ &.mw-echo-unseen-notifications {
+ #pt-notifications-alert &:after {
+ background-color: @badge-counter-background-unseen-alert;
+ }
+
+ #pt-notifications-notice &:after {
+ background-color: @badge-counter-background-unseen-message;
+ }
+ }
+}
+
+#p-personal #pt-notifications-alert,
+#p-personal #pt-notifications-notice {
+ margin-top: 0.3em;
+ margin-right: 0.4em;
+}
diff --git a/Echo/modules/nojs/mw.echo.notifications.less b/Echo/modules/nojs/mw.echo.notifications.less
index 07fa1a63..4627fdc6 100644
--- a/Echo/modules/nojs/mw.echo.notifications.less
+++ b/Echo/modules/nojs/mw.echo.notifications.less
@@ -1,10 +1,13 @@
-// This needs to be outside the upper selector 'NotificationOptionWidget'
-// because the same styles also apply (for the moment, at least) to the notification
-// objects in the Special:Notifications page, which are, individually
-// not wrapped with a notificationOptionWidget.
+@import '../echo.variables';
+@import '../echo.mixins';
+@import 'mediawiki.mixins';
+
+// This is only valid for the Special:Notifications page in no-JS mode,
+// where the formatting of the notifications include the following structure
.mw-echo-state {
display: block;
- padding: 15px 40px 10px 10px;
+ width: 100%;
+ .box-sizing( border-box );
.mw-echo-notification-primary-link {
display: none;
@@ -18,13 +21,13 @@
margin-left: 10px;
}
.mw-echo-notification {
+ background-color: @background-color-base;
+ color: @grey-light;
clear: both;
display: block;
- color: #6D6D6D;
line-height: 90%;
margin: 0;
min-height: 30px;
- background-color: white;
position: relative;
padding-top: 15px;
padding-bottom: 10px;
@@ -32,10 +35,6 @@
overflow: hidden;
zoom: 1;
- &.mw-echo-unread {
- color: #252525;
- }
-
span.autocomment {
color: inherit;
font-style: normal;
@@ -43,7 +42,7 @@
}
.mw-echo-notifications {
- background-color: #EEEEEE;
+ background-color: @notification-background-read;
}
.mw-echo-content {
@@ -51,20 +50,20 @@
display: block;
.mw-echo-title {
- color: #666666;
+ color: @notification-text-color;
+ }
+
+ .mw-echo-payload {
+ .mw-echo-ui-mixin-one-line-truncated;
+ color: @notification-body-color;
+ margin-top: 4px;
+ }
+
+ .mw-echo-title,
+ .mw-echo-payload {
font-size: 1em;
line-height: 1.4em;
- .mw-echo-title-heading {
- color: #666;
- font-size: 1.15em;
- }
- .mw-echo-title-heading,
- .mw-echo-title-heading a {
- font-weight: bold;
- }
-
- .mw-echo-title-heading,
.plainlinks {
white-space: nowrap;
overflow: hidden;
@@ -75,10 +74,19 @@
}
}
- .mw-echo-timestamp, .mw-echo-notification-footer {
- color: #6D6D6D;
+ .mw-echo-notification-footer {
+ color: @grey-light;
font-size: 11px;
margin-top: 0.2em;
+
+ .mw-echo-notification-footer-element {
+ display: inline-block;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ max-width: 15em;
+ margin-right: 0.5em;
+ }
}
}
}
diff --git a/Echo/modules/nojs/mw.echo.special.less b/Echo/modules/nojs/mw.echo.special.less
index a0a0360b..87a76552 100644
--- a/Echo/modules/nojs/mw.echo.special.less
+++ b/Echo/modules/nojs/mw.echo.special.less
@@ -1,16 +1,40 @@
/* Echo specific CSS */
+@import '../echo.variables';
-#mw-echo-more {
- display: block;
- text-align: center;
- font-size: 13px;
+.mw-echo-special-container {
max-width: 600px;
}
-/* Custom header styling for Vector and Monobook skins */
-.mw-special-Notifications.skin-vector #firstHeading,
-.mw-special-Notifications.skin-monobook #firstHeading {
- max-width: 600px;
+.client-js .mw-echo-special-nojs {
+ min-height: 5em;
+ /* @embed */
+ background-image: url( ../../images/pending.gif );
+
+ .mw-echo-special-container {
+ display: none;
+ }
+}
+
+// Hide the help link and the preferences link
+// in the JS version, since both appear inside
+// the cog menu
+.client-js #mw-indicator-mw-helplink {
+ display: none;
+}
+
+.client-js #mw-echo-pref-link,
+.client-js #contentSub {
+ display: none;
+}
+
+@media all and ( min-width: @specialpage-hd-width ) {
+ .client-js #mw-content-text {
+ margin-top: 2em;
+ }
+}
+
+.mw-echo-special-markAllReadButton {
+ float: right;
}
/* Special styles to use if we're converting subtitle links into header icons */
@@ -20,75 +44,119 @@
height: 19px;
width: 19px;
}
-
- #mw-echo-pref-link {
- float: right;
- margin: 5px 3px;
- /* @embed */
- background-image: url(../icons/Preferences.png);
- background-repeat: no-repeat;
- background-position: 0 0;
- filter: alpha(opacity=50);
- opacity: 0.5;
-
- &:hover {
- filter: alpha(opacity=100);
- opacity: 1.0;
- }
- }
-
- #mw-echo-moreinfo-link {
- display: inline-block;
- margin: 0 3px;
- /* @embed */
- background-image: url(../icons/Help.png);
- background-repeat: no-repeat;
- background-position: 0 0;
- filter: alpha(opacity=50);
- opacity: 0.5;
-
- &:hover {
- filter: alpha(opacity=100);
- opacity: 1.0;
- }
- }
}
.mw-echo-date-section {
- font-weight: 800;
- font-size: 1.1em;
+ border-bottom: 1px solid @border-color;
+ margin: 20px 0 5px 0;
+ color: @grey-light;
+ display: inline-block;
+ width: 100%;
+ padding-bottom: 0.5em;
+}
+
+.mw-echo-date-section-text {
text-transform: uppercase;
- border-bottom: 1px solid #C9C9C9;
- margin: 30px 0 5px 50px;
- color: #686868;
- max-width: 550px;
+ font-size: 1.1em;
+ font-weight: 800;
+ display: inline-block;
}
-ul#mw-echo-special-container {
+ul.mw-echo-special-notifications {
+ div.mw-htmlform-submit-buttons {
+ margin: 0;
+ }
list-style: none none;
padding: 0;
- margin: 30px 0 0 0;
- max-width: 600px;
+ margin: 0;
+ width: 100%;
+}
+
+.mw-echo-special-navbar-top {
+ margin-bottom: 10px;
+}
+
+.mw-echo-special-navbar-bottom {
+ margin-top: 20px;
+ padding-top: 10px;
+ border-top: 1px solid @border-color;
}
.mw-echo-notification {
- padding: 15px 35px 10px 0;
+ padding: 30px 40px 15px 10px;
+
+ .mw-echo-markAsReadButton {
+ display: none;
+
+ button {
+ padding: 0;
+ }
+ }
}
-#mw-echo-special-container {
+.mw-echo-markAsReadSectionButton {
+ float: right;
+ display: inline-block;
+
+ button.oo-ui-buttonElement-button {
+ padding: 2px 12px 2px 12px;
+ }
+
+ // HACK: temporary workaround for T136024
+ line-height: normal;
+
+ .oo-ui-buttonElement-button {
+ .oo-ui-labelElement-label {
+ font-weight: normal;
+ }
+ }
+}
+
+.mw-echo-special-notifications {
+ overflow-y: auto;
+
.mw-echo-notification {
- background-color: transparent;
+ background-color: #f8f9fa;
&:hover {
/* Fallback for IE<=8 */
- background-color: #F6F6F6;
- background-color: rgba(0, 0, 0, 0.035);
+ background-color: #f6f6f6;
+ background-color: rgba( 0, 0, 0, 0.035 );
}
- &.mw-echo-unread {
+ &-unread {
+ color: @color-base;
+ background-color: transparent;
+ padding-right: 0;
+
.mw-echo-title {
font-weight: bold;
}
+
+ .mw-echo-markAsReadButton {
+ float: right;
+ display: inline-block;
+ margin: 0;
+
+ opacity: 0.5;
+ &:hover {
+ opacity: 1;
+ }
+ }
}
}
}
+
+div.mw-htmlform-ooui-wrapper {
+ margin: 0;
+}
+
+@media all and ( max-width: ( @specialpage-hd-width - 1 ) ) {
+ .pre-content.heading-holder {
+ // Center 'preferences' in mobile special page
+ text-align: center;
+ }
+ .mw-echo-special-header-link {
+ display: none;
+ }
+}
diff --git a/Echo/modules/ooui/mw.echo.ui.BadgeLinkWidget.js b/Echo/modules/ooui/mw.echo.ui.BadgeLinkWidget.js
deleted file mode 100644
index 2a7ae68f..00000000
--- a/Echo/modules/ooui/mw.echo.ui.BadgeLinkWidget.js
+++ /dev/null
@@ -1,44 +0,0 @@
-( function ( mw, $ ) {
- /**
- * Notification badge button widget for echo popup.
- *
- * @class
- * @extends OO.ui.ButtonWidget
- *
- * @constructor
- * @param {Object} [config] Configuration object
- * @cfg {string|Object} [badgeIcon] The icons to use for this button.
- * If this is a string, it will be used as the icon regardless of the state.
- * If it is an object, it must include
- * the properties 'unseen' and 'seen' with icons attached to both. For example:
- * { badgeIcon: {
- * unseen: 'bellOn',
- * seen: 'bell'
- * } }
- */
- mw.echo.ui.BadgeLinkWidget = function MwEchoUiBadgeLinkWidget( config ) {
- config = config || {};
-
- // Parent constructor
- mw.echo.ui.BadgeLinkWidget.parent.call( this, config );
-
- // Mixin constructors
- OO.ui.mixin.LabelElement.call( this, $.extend( { $label: this.$element }, config ) );
- OO.ui.mixin.ButtonElement.call( this, $.extend( { $button: this.$element }, config ) );
- OO.ui.mixin.IconElement.call( this, $.extend( { $icon: this.$element }, config ) );
- OO.ui.mixin.TitledElement.call( this, $.extend( { $titled: this.$element }, config ) );
- OO.ui.mixin.FlaggedElement.call( this, $.extend( {}, config, { $flagged: this.$element } ) );
-
- this.$element.addClass( 'mw-echo-notifications-badge' );
- };
-
- OO.inheritClass( mw.echo.ui.BadgeLinkWidget, OO.ui.Widget );
- OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.LabelElement );
- OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.ButtonElement );
- OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.IconElement );
- OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.TitledElement );
- OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.FlaggedElement );
-
- mw.echo.ui.BadgeLinkWidget.static.tagName = 'a';
-
-} )( mediaWiki, jQuery );
diff --git a/Echo/modules/ooui/mw.echo.ui.NotificationBadgeWidget.js b/Echo/modules/ooui/mw.echo.ui.NotificationBadgeWidget.js
deleted file mode 100644
index c7ba0776..00000000
--- a/Echo/modules/ooui/mw.echo.ui.NotificationBadgeWidget.js
+++ /dev/null
@@ -1,320 +0,0 @@
-( function ( mw, $ ) {
- /**
- * Notification badge button widget for echo popup.
- *
- * @class
- * @extends OO.ui.ButtonWidget
- *
- * @constructor
- * @param {Object} [config] Configuration object
- * @cfg {string} [type='alert'] Notification type 'alert' or 'message'
- * @cfg {number} [numItems=0] How many items are in the button display
- * @cfg {boolean} [hasUnseen=false] Whether there are unseen items
- * @cfg {boolean} [markReadWhenSeen=false] Mark all notifications as read on open
- * @cfg {number} [popupWidth=450] The width of the popup
- * @cfg {string|Object} [badgeIcon] The icons to use for this button.
- * If this is a string, it will be used as the icon regardless of the state.
- * If it is an object, it must include
- * the properties 'unseen' and 'seen' with icons attached to both. For example:
- * { badgeIcon: {
- * unseen: 'bellOn',
- * seen: 'bell'
- * } }
- */
- mw.echo.ui.NotificationBadgeWidget = function MwEchoUiNotificationBadgeButtonPopupWidget( config ) {
- var buttonFlags, allNotificationsButton, preferencesButton, footerButtonGroupWidget, $footer;
-
- config = config || {};
- config.links = config.links || {};
-
- // Parent constructor
- mw.echo.ui.NotificationBadgeWidget.parent.call( this, config );
-
- // Mixin constructors
- OO.ui.mixin.PendingElement.call( this, config );
-
- this.type = config.type || 'alert';
- this.numItems = config.numItems || 0;
- this.markReadWhenSeen = !!config.markReadWhenSeen;
- this.badgeIcon = config.badgeIcon || {};
- this.hasRunFirstTime = false;
-
- buttonFlags = [ 'primary' ];
- if ( !!config.hasUnseen ) {
- buttonFlags.push( 'unseen' );
- }
-
- this.badgeButton = new mw.echo.ui.BadgeLinkWidget( {
- label: this.numItems,
- flags: buttonFlags,
- badgeIcon: config.badgeIcon,
- // The following messages can be used here:
- // tooltip-pt-notifications-alert
- // tooltip-pt-notifications-message
- title: mw.msg( 'tooltip-pt-notifications-' + this.type )
- } );
-
- // View model
- this.notificationsModel = new mw.echo.dm.NotificationsModel( {
- type: this.type,
- limit: 25,
- userLang: mw.config.get( 'wgUserLanguage' ),
- apiData: mw.echo.apiCallParams
- } );
-
- // Notifications widget
- this.notificationsWidget = new mw.echo.ui.NotificationsWidget(
- this.notificationsModel,
- {
- type: this.type,
- markReadWhenSeen: this.markReadWhenSeen
- }
- );
-
- // Footer
- allNotificationsButton = new OO.ui.ButtonWidget( {
- icon: 'next',
- label: mw.msg( 'echo-overlay-link' ),
- href: config.links.notifications,
- classes: [ 'mw-echo-ui-notificationBadgeButtonPopupWidget-footer-allnotifs' ]
- } );
-
- preferencesButton = new OO.ui.ButtonWidget( {
- icon: 'advanced',
- label: mw.msg( 'mypreferences' ),
- href: config.links.preferences,
- classes: [ 'mw-echo-ui-notificationBadgeButtonPopupWidget-footer-preferences' ]
- } );
-
- footerButtonGroupWidget = new OO.ui.ButtonGroupWidget( {
- items: [ allNotificationsButton, preferencesButton ]
- } );
- $footer = $( '<div>' )
- .addClass( 'mw-echo-ui-notificationBadgeButtonPopupWidget-footer' )
- .append( footerButtonGroupWidget.$element );
-
- this.popup = new OO.ui.PopupWidget( {
- $content: this.notificationsWidget.$element,
- $footer: $footer,
- width: config.popupWidth || 450,
- autoClose: true,
- $autoCloseIgnore: this.$element,
- head: true,
- // The following messages can be used here:
- // echo-notification-alert-text-only
- // echo-notification-message-text-only
- label: mw.msg( 'echo-notification-' + this.type + '-text-only' )
- } );
- // HACK: Add an icon to the popup head label
- this.popupHeadIcon = new OO.ui.IconWidget();
- this.popup.$head.prepend( this.popupHeadIcon.$element );
-
- this.setPendingElement( this.popup.$head );
- this.updateIcon( !!config.hasUnseen );
-
- // Mark all as read button
- this.markAllReadButton = new OO.ui.ButtonWidget( {
- framed: false,
- label: mw.msg( 'echo-mark-all-as-read' ),
- classes: [ 'mw-echo-ui-notificationsWidget-markAllReadButton' ]
- } );
-
- // Hide the close button
- this.popup.closeButton.toggle( false );
- // Add the 'mark all as read' button to the header
- this.popup.$head.append( this.markAllReadButton.$element );
- this.markAllReadButton.toggle( !this.markReadWhenSeen && !!config.hasUnseen );
-
- // Events
- this.markAllReadButton.connect( this, { click: 'onMarkAllReadButtonClick' } );
- this.notificationsModel.connect( this, {
- updateSeenTime: 'updateBadge',
- add: 'updateBadge',
- unseenChange: 'updateBadge',
- unreadChange: 'updateBadge'
- } );
- this.popup.connect( this, { toggle: 'onPopupToggle' } );
- this.badgeButton.connect( this, {
- click: 'onBadgeButtonClick'
- } );
-
- this.$element
- .prop( 'id', 'pt-notifications-' + this.type )
- // The following classes can be used here:
- // mw-echo-ui-notificationBadgeButtonPopupWidget-alert
- // mw-echo-ui-notificationBadgeButtonPopupWidget-message
- .addClass(
- 'mw-echo-ui-notificationBadgeButtonPopupWidget ' +
- 'mw-echo-ui-notificationBadgeButtonPopupWidget-' + this.type
- )
- .append(
- this.badgeButton.$element,
- this.popup.$element
- );
- };
-
- /* Initialization */
-
- OO.inheritClass( mw.echo.ui.NotificationBadgeWidget, OO.ui.Widget );
- OO.mixinClass( mw.echo.ui.NotificationBadgeWidget, OO.ui.mixin.PendingElement );
-
- /* Static properties */
-
- mw.echo.ui.NotificationBadgeWidget.static.tagName = 'li';
-
- /* Methods */
-
- /**
- * Respond to badge button click
- */
- mw.echo.ui.NotificationBadgeWidget.prototype.onBadgeButtonClick = function () {
- this.popup.toggle( true );
- };
-
- /**
- * Update the badge icon with the read/unread versions if they exist.
- *
- * @param {boolean} hasUnseen Widget has unseen notifications
- */
- mw.echo.ui.NotificationBadgeWidget.prototype.updateIcon = function ( hasUnseen ) {
- var icon = typeof this.badgeIcon === 'string' ?
- this.badgeIcon :
- this.badgeIcon[ hasUnseen ? 'unseen' : 'seen' ];
-
- this.badgeButton.setIcon( icon );
- this.popupHeadIcon.setIcon( icon );
- };
-
- /**
- * Update the badge state and label based on changes to the model
- */
- mw.echo.ui.NotificationBadgeWidget.prototype.updateBadge = function () {
- var unseenCount = this.notificationsModel.getUnseenCount(),
- unreadCount = this.notificationsModel.getUnreadCount();
-
- // Update numbers and seen/unseen state
- this.badgeButton.setFlags( { unseen: !!unseenCount } );
- this.badgeButton.setLabel( mw.language.convertNumber( unreadCount ) );
- this.updateIcon( !!unseenCount );
-
- // Check if we need to display the 'mark all unread' button
- this.markAllReadButton.toggle( !!unreadCount );
- };
-
- /**
- * Respond to 'mark all as read' button click
- */
- mw.echo.ui.NotificationBadgeWidget.prototype.onMarkAllReadButtonClick = function () {
- this.notificationsModel.markAllRead();
- };
-
- /**
- * Populate notifications from the API.
- *
- * @param {jQuery.Promise} [fetchingApiRequest] An existing promise for fetching
- * notifications from the API. This allows us to start fetching notifications
- * externally.
- * @return {jQuery.Promise} Promise that is resolved when the notifications populate
- */
- mw.echo.ui.NotificationBadgeWidget.prototype.populateNotifications = function ( fetchingApiRequest ) {
- var widget = this,
- time = mw.now();
-
- // The model retrieves the ongoing promise or returns the existing one that it
- // has. When the promise is completed successfuly, it nullifies itself so we can
- // request for it to be rebuilt and the request to the API resent.
- // However, in the case of an API failure, the promise does not nullify itself.
- // In that case we also want the model to rebuild the request, so in this condition
- // we must check both cases.
- if ( !this.notificationsModel.isFetchingNotifications() || this.notificationsModel.isFetchingErrorState() ) {
- this.pushPending();
- this.markAllReadButton.toggle( false );
- return this.notificationsModel.fetchNotifications( fetchingApiRequest )
- .then( function ( idArray ) {
- // Clip again
- widget.popup.clip();
-
- // Log impressions
- mw.echo.logger.logNotificationImpressions( this.type, idArray, mw.echo.Logger.static.context.popup );
-
- // Log timing
- mw.track( 'timing.MediaWiki.echo.overlay', mw.now() - time );
-
- // // Mark notifications as 'read' if markReadWhenSeen is set to true
- if ( widget.markReadWhenSeen ) {
- return widget.notificationsModel.markAllRead();
- }
- } )
- .then( function () {
- // Update seen time
- widget.notificationsModel.updateSeenTime();
- } )
- .then(
- // Success
- function () {
- // Display the message only if there are no notifications
- if ( widget.notificationsModel.isEmpty() ) {
- widget.notificationsWidget.resetLoadingOption( mw.msg( 'echo-notification-placeholder' ) );
- }
- },
- // Fail
- function ( errCode ) {
- // Display the message only if there are no notifications
- if ( widget.notificationsModel.isEmpty() ) {
- widget.notificationsWidget.resetLoadingOption( mw.msg( 'echo-api-failure', errCode ) );
- }
- }
- )
- .always( function () {
- // Pop pending
- widget.popPending();
- // Nullify the promise; let the user fetch again
- widget.fetchNotificationsPromise = null;
- } );
- } else {
- return this.notificationsModel.getFetchNotificationPromise();
- }
- };
-
- /**
- * Extend the response to button click so we can also update the notification list.
- */
- mw.echo.ui.NotificationBadgeWidget.prototype.onPopupToggle = function ( isVisible ) {
- if ( !isVisible ) {
- // If the popup is closing, leave
- return;
- }
-
- // Log the click event
- mw.echo.logger.logInteraction(
- 'ui-badge-link-click',
- mw.echo.Logger.static.context,
- null,
- this.type
- );
-
- if ( this.hasRunFirstTime ) {
- // HACK: Clippable doesn't resize the clippable area when
- // it calculates the new size. Since the popup contents changed
- // and the popup is "empty" now, we need to manually set its
- // size to 1px so the clip calculations will resize it properly.
- // See bug report: https://phabricator.wikimedia.org/T110759
- this.popup.$clippable.css( 'height', '1px' );
- this.popup.clip();
- }
- // Always populate on popup open. The model and widget should handle
- // the case where the promise is already underway.
- this.populateNotifications();
- this.hasRunFirstTime = true;
- };
-
- /**
- * Get the notifications model attached to this widget
- *
- * @return {mw.echo.dm.NotificationsModel} Notifications model
- */
- mw.echo.ui.NotificationBadgeWidget.prototype.getModel = function () {
- return this.notificationsModel;
- };
-
-} )( mediaWiki, jQuery );
diff --git a/Echo/modules/ooui/mw.echo.ui.NotificationOptionWidget.js b/Echo/modules/ooui/mw.echo.ui.NotificationOptionWidget.js
deleted file mode 100644
index a4fdc545..00000000
--- a/Echo/modules/ooui/mw.echo.ui.NotificationOptionWidget.js
+++ /dev/null
@@ -1,131 +0,0 @@
-( function ( mw, $ ) {
- /**
- * Notification option widget for echo popup.
- *
- * @class
- * @extends OO.ui.OptionWidget
- *
- * @constructor
- * @param {Object} [config] Configuration object
- * @cfg {boolean} [markReadWhenSeen=false] This option is marked as read when it is viewed
- */
- mw.echo.ui.NotificationOptionWidget = function MwEchoUiNotificationOptionWidget( model, config ) {
- config = config || {};
-
- this.model = model;
-
- // Parent constructor
- mw.echo.ui.NotificationOptionWidget.parent.call( this, $.extend( { data: this.model.getId() }, config ) );
-
- this.markAsReadButton = new OO.ui.ButtonWidget( {
- icon: 'close',
- framed: false,
- classes: [ 'mw-echo-ui-notificationOptionWidget-markAsReadButton' ]
- } );
-
- this.setLabel( this.model.getContent() );
-
- this.toggleRead( this.model.isRead() );
- this.toggleSeen( this.model.isSeen() );
-
- this.markReadWhenSeen = !!config.markReadWhenSeen;
-
- // Events
- this.markAsReadButton.connect( this, { click: 'onMarkAsReadButtonClick' } );
- this.model.connect( this, {
- seen: 'toggleSeen',
- read: 'toggleRead'
- } );
-
- this.$element
- .addClass( 'mw-echo-ui-notificationOptionWidget' )
- .append(
- // HACK: Wrap the entire option with a link that takes
- // the user to the primary url. This is not perfect,
- // but it makes the behavior native to the browser rather
- // than us listening to click events and opening new
- // windows.
- $( '<a>' )
- .addClass( 'mw-echo-ui-notificationOptionWidget-linkWrapper' )
- .attr( 'href', this.model.getPrimaryUrl() )
- .append(
- this.markAsReadButton.$element,
- this.$label
- )
- );
-
- this.$element.toggleClass( 'mw-echo-ui-notificationOptionWidget-initiallyUnseen', !this.model.isSeen() );
- };
-
- /* Initialization */
-
- OO.inheritClass( mw.echo.ui.NotificationOptionWidget, OO.ui.OptionWidget );
-
- /* Events */
-
- /**
- * @event markAsRead
- *
- * Mark this notification as read
- */
-
- /* Methods */
-
- /**
- * Respond to mark as read button click
- */
- mw.echo.ui.NotificationOptionWidget.prototype.onMarkAsReadButtonClick = function () {
- this.model.toggleRead( true );
- };
- /**
- * Toggle the read state of the widget
- *
- * @param {boolean} [read] The current read state. If not given, the state will
- * become the opposite of its current state.
- */
- mw.echo.ui.NotificationOptionWidget.prototype.toggleRead = function ( read ) {
- this.read = read !== undefined ? read : !this.read;
-
- this.$element.toggleClass( 'mw-echo-ui-notificationOptionWidget-unread', !this.read );
- this.markAsReadButton.toggle( !this.read );
- };
-
- /**
- * Toggle the seen state of the widget
- *
- * @param {boolean} [seen] The current seen state. If not given, the state will
- * become the opposite of its current state.
- */
- mw.echo.ui.NotificationOptionWidget.prototype.toggleSeen = function ( seen ) {
- this.seen = seen !== undefined ? seen : !this.seen;
-
- this.$element
- .toggleClass( 'mw-echo-ui-notificationOptionWidget-unseen', !this.seen );
- };
-
- /**
- * Get the notification link
- *
- * @return {string} Notification link
- */
- mw.echo.ui.NotificationOptionWidget.prototype.getModel = function () {
- return this.model;
- };
-
- /**
- * Get the notification link
- *
- * @return {string} Notification link
- */
- mw.echo.ui.NotificationOptionWidget.prototype.getPrimaryUrl = function () {
- return this.model.getPrimaryUrl();
- };
-
- /**
- * Disconnect events when widget is destroyed.
- */
- mw.echo.ui.NotificationOptionWidget.prototype.destroy = function () {
- this.model.disconnect( this );
- };
-
-} )( mediaWiki, jQuery );
diff --git a/Echo/modules/ooui/mw.echo.ui.NotificationsWidget.js b/Echo/modules/ooui/mw.echo.ui.NotificationsWidget.js
deleted file mode 100644
index b37bc158..00000000
--- a/Echo/modules/ooui/mw.echo.ui.NotificationsWidget.js
+++ /dev/null
@@ -1,134 +0,0 @@
-( function ( mw, $ ) {
- /**
- * Notification widget for echo popup.
- *
- * @class
- * @extends OO.ui.Widget
- *
- * @constructor
- * @param {mw.echo.dm.NotificationsModel} model Notifications view model
- * @param {Object} [config] Configuration object
- * @cfg {boolean} [markReadWhenSeen=false] State whether the notifications are all
- * marked as read when they are seen.
- */
- mw.echo.ui.NotificationsWidget = function MwEchoUiNotificationsWidget( model, config ) {
- config = config || {};
-
- this.model = model;
-
- this.markReadWhenSeen = !!config.markReadWhenSeen;
-
- // Parent constructor
- mw.echo.ui.NotificationsWidget.parent.call( this, config );
-
- // Dummy 'loading' option widget
- this.loadingOptionWidget = new mw.echo.ui.PlaceholderOptionWidget();
- this.addItems( [ this.loadingOptionWidget ] );
-
- // Events
- this.model.connect( this, {
- add: 'onModelNotificationAdd',
- remove: 'onModelNotificationRemove',
- clear: 'onModelNotificationClear'
- } );
-
- this.$element
- .addClass( 'mw-echo-ui-notificationsWidget' );
- };
-
- /* Initialization */
-
- OO.inheritClass( mw.echo.ui.NotificationsWidget, OO.ui.SelectWidget );
-
- /* Methods */
-
- /**
- * Respond to model add event
- *
- * @param {mw.echo.dm.NotificationItem[]} Added notification items
- */
- mw.echo.ui.NotificationsWidget.prototype.onModelNotificationAdd = function ( notificationItems, index ) {
- var i, len, widget,
- $elements = $(),
- optionWidgets = [];
-
- for ( i = 0, len = notificationItems.length; i < len; i++ ) {
- widget = new mw.echo.ui.NotificationOptionWidget(
- notificationItems[i],
- {
- markReadWhenSeen: this.markReadWhenSeen
- }
- );
- optionWidgets.push( widget );
- // Collect the elements for the hook firing
- $elements = $elements.add( widget.$element );
- }
-
- // Fire hook for gadgets to update the option list
- mw.hook( 'ext.echo.overlay.beforeShowingOverlay' ).fire( $elements );
-
- // Remove dummy option
- this.removeItems( [ this.loadingOptionWidget ] );
-
- this.addItems( optionWidgets, index );
- };
-
- /**
- * Respond to model add event
- *
- * @param {mw.echo.dm.NotificationItem[]} Removed notification items
- */
- mw.echo.ui.NotificationsWidget.prototype.onModelNotificationClear = function () {
- var i, len,
- items = this.getItems();
-
- // Destroy all the widgets and their events
- for ( i = 0, len = items.length; i < len; i++ ) {
- if ( typeof items[i].destroy === 'function' ) {
- // Destroy if destroyable
- items[i].destroy();
- }
- }
-
- this.clearItems();
-
- // Add dummy option
- this.resetLoadingOption();
- };
-
- /**
- * Respond to model add event
- *
- * @param {mw.echo.dm.NotificationItem[]} Removed notification items
- */
- mw.echo.ui.NotificationsWidget.prototype.onModelNotificationRemove = function ( notificationItems ) {
- var i, len, widget, items,
- removalWidgets = [];
-
- for ( i = 0, len = notificationItems.length; i < len; i++ ) {
- widget = this.getItemById( notificationItems[i].getId() );
- if ( widget && typeof widget.destroy === 'function' ) {
- // Destroy all widgets that can be destroyed
- widget.destroy();
- }
- removalWidgets.push( widget );
- }
-
- this.removeItems( removalWidgets );
-
- items = this.getItems();
- if ( !items.length ) {
- this.resetLoadingOption();
- }
- };
-
- /**
- * Reset the loading 'dummy' option widget
- *
- * @param {string} [label] Label for the option widget
- */
- mw.echo.ui.NotificationsWidget.prototype.resetLoadingOption = function ( label ) {
- this.loadingOptionWidget.setLabel( label || '' );
- this.addItems( [ this.loadingOptionWidget ] );
- };
-} )( mediaWiki, jQuery );
diff --git a/Echo/modules/ooui/mw.echo.ui.PlaceholderOptionWidget.js b/Echo/modules/ooui/mw.echo.ui.PlaceholderOptionWidget.js
deleted file mode 100644
index a5571b1c..00000000
--- a/Echo/modules/ooui/mw.echo.ui.PlaceholderOptionWidget.js
+++ /dev/null
@@ -1,24 +0,0 @@
-( function ( mw, $ ) {
- /**
- * Placeholder notification option widget for echo popup.
- *
- * @class
- * @extends OO.ui.OptionWidget
- *
- * @constructor
- * @param {Object} [config] Configuration object
- */
- mw.echo.ui.PlaceholderOptionWidget = function MwEchoUiPlaceholderOptionWidget( config ) {
- // Parent constructor
- mw.echo.ui.PlaceholderOptionWidget.parent.call( this, $.extend( { data: null }, config ) );
-
- this.$element.addClass( 'mw-echo-ui-notificationsWidget-loadingOption' );
- };
-
- OO.inheritClass( mw.echo.ui.PlaceholderOptionWidget, OO.ui.OptionWidget );
-
- mw.echo.ui.PlaceholderOptionWidget.static.selectable = false;
- mw.echo.ui.PlaceholderOptionWidget.static.highlightable = false;
- mw.echo.ui.PlaceholderOptionWidget.static.pressable = false;
-
-} )( mediaWiki, jQuery );
diff --git a/Echo/modules/ooui/mw.echo.ui.js b/Echo/modules/ooui/mw.echo.ui.js
deleted file mode 100644
index c84979a8..00000000
--- a/Echo/modules/ooui/mw.echo.ui.js
+++ /dev/null
@@ -1,4 +0,0 @@
-( function ( mw ) {
- mw.echo = mw.echo || {};
- mw.echo.ui = {};
-} )( mediaWiki );
diff --git a/Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.less b/Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.less
deleted file mode 100644
index a88c3e34..00000000
--- a/Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.less
+++ /dev/null
@@ -1,67 +0,0 @@
-@import '../../echo.variables';
-
-// These rules are outside of the LESS nesting because they don't work inside
-// the nested rule. These should be very strong so as to override the base styles
-#pt-notifications-alert .mw-echo-notifications-badge.oo-ui-flaggedElement-unseen {
- background-color: @badge-background-unseen-alert;
-}
-#pt-notifications-message .mw-echo-notifications-badge.oo-ui-flaggedElement-unseen {
- background-color: @badge-background-unseen-message;
-}
-
-.mw-echo-ui-notificationBadgeButtonPopupWidget {
- position: relative;
-
- .oo-ui-popupWidget-footer {
- border-top: 1px solid #DDDDDD;
- width: 100%;
-
- .oo-ui-buttonElement {
- display: table-cell;
- white-space: normal;
- font-weight: bold;
- width: @notification-popup-width / 2;
- box-sizing: border-box;
-
- &:last-child {
- border-left: 1px solid #DDDDDD;
- }
-
- > .oo-ui-buttonElement-button {
- display: block;
- line-height: 4em;
- margin: 0;
- border: 0;
- }
- }
- }
-
- .oo-ui-popupWidget {
- // #p-personal li has a font-size of 0.75em, but we want the
- // font size here to be exactly 0.875em, so we must override
- // the parent em sizing by dividing.
- font-size: 0.875em / 0.75em;
-
- // Align the popup with the center of the button
- left: 1em;
- }
-
- .oo-ui-popupWidget-head {
- height: 3.5em;
- > .oo-ui-iconWidget {
- float: left;
- margin: 0.7em 0 1em 1em;
- }
-
- > .oo-ui-labelElement-label {
- font-size: 1.2em;
- padding: 0.3em;
- margin-left: 0;
- font-weight: bold;
- }
-
- .mw-echo-ui-notificationsWidget-markAllReadButton {
- margin: 1.25em 1em;
- }
- }
-}
diff --git a/Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.modern.less b/Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.modern.less
deleted file mode 100644
index 782a63d8..00000000
--- a/Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.modern.less
+++ /dev/null
@@ -1,13 +0,0 @@
-body #p-personal {
- overflow: visible;
-}
-
-.mw-echo-ui-notificationBadgeButtonPopupWidget {
- font-variant: normal;
- text-transform: none;
- font-weight: normal;
- // Badge
- > .oo-ui-buttonElement-button {
- border-radius: none;
- }
-}
diff --git a/Echo/modules/ooui/styles/mw.echo.ui.NotificationOptionWidget.less b/Echo/modules/ooui/styles/mw.echo.ui.NotificationOptionWidget.less
deleted file mode 100644
index ebdbae0d..00000000
--- a/Echo/modules/ooui/styles/mw.echo.ui.NotificationOptionWidget.less
+++ /dev/null
@@ -1,94 +0,0 @@
-@import '../../echo.variables';
-
-.mw-echo-ui-notificationOptionWidget {
- padding: 0.5em;
- background-color: #F1F1F1;
- border-bottom: 1px solid #DDDDDD;
- white-space: normal;
- font-size: 13px;
- line-height: 16px;
-
- &:hover > a {
- text-decoration: none;
- }
-
- &:not(:hover) a,
- #p-personal &:not(:hover) a.new {
- color: #666666;
- }
-
- &:last-child {
- border-bottom: none;
- }
-
- .oo-ui-labelElement-label {
- // We have to override this with !important because OOUI's rules for
- // the label element are extremely strong and cannot be overridden
- white-space: normal !important;
- }
-
- &-markAsReadButton {
- float: right;
- font-size: 0.5em;
- opacity: 0.5;
- padding: 0.5em;
-
- &:hover {
- opacity: 1;
- }
- }
-
- &-initiallyUnseen {
- -webkit-animation-name: unseen-fadeout-to-read;
- animation-name: unseen-fadeout-to-read;
- -webkit-animation-duration: .5s;
- animation-duration: .5s;
- -webkit-animation-delay: 2s;
- animation-delay: 2s;
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- -webkit-animation-fill-mode: both;
- animation-fill-mode: both;
-
- &.mw-echo-ui-notificationOptionWidget-unread {
- -webkit-animation-name: unseen-fadeout-to-unread;
- animation-name: unseen-fadeout-to-unread;
- }
- }
- &-unread {
- background-color: white;
- }
-
- &.oo-ui-optionWidget-selected,
- &.oo-ui-optionWidget-highlighted {
- background-color: #F9F9F9;
- }
-
- &-unread.oo-ui-optionWidget-highlighted {
- background-color: white;
- }
-
- // NOTE: The internal styling of the notifications is outside this file, because
- // it also affects the notifications in Special:Notifications
- // These styles are in modules/nojs/ext.echo.notifications.less
-}
-
-@-webkit-keyframes unseen-fadeout-to-unread {
- from { background-color: @notification-background-unseen; }
- to { background-color: @notification-background-unread; }
-}
-
-@keyframes unseen-fadeout-to-unread {
- from { background-color: @notification-background-unseen; }
- to { background-color: @notification-background-unread; }
-}
-
-@-webkit-keyframes unseen-fadeout-to-read {
- from { background-color: @notification-background-unseen; }
- to { background-color: @notification-background-read; }
-}
-
-@keyframes unseen-fadeout-to-read {
- from { background-color: @notification-background-unseen; }
- to { background-color: @notification-background-read; }
-}
diff --git a/Echo/modules/ooui/styles/mw.echo.ui.NotificationOptionWidget.modern.less b/Echo/modules/ooui/styles/mw.echo.ui.NotificationOptionWidget.modern.less
deleted file mode 100644
index ccc9355a..00000000
--- a/Echo/modules/ooui/styles/mw.echo.ui.NotificationOptionWidget.modern.less
+++ /dev/null
@@ -1,18 +0,0 @@
-.mw-echo-ui-notificationOptionWidget {
- #p-personal & a,
- #p-personal & a.new {
- // In modern, the hover color is white, which is unhelpful.
- color: #666666;
- text-decoration: none;
- }
-
-}
-
-#p-personal .mw-echo-ui-notificationBadgeButtonPopupWidget-footer a {
- color: #666666;
-}
-
-// Override personal tools padding for links
-#p-personal li .mw-echo-state a {
- padding: 0 0 0 0;
-}
diff --git a/Echo/modules/ooui/styles/mw.echo.ui.NotificationsWidget.less b/Echo/modules/ooui/styles/mw.echo.ui.NotificationsWidget.less
deleted file mode 100644
index ba4ad8c1..00000000
--- a/Echo/modules/ooui/styles/mw.echo.ui.NotificationsWidget.less
+++ /dev/null
@@ -1,9 +0,0 @@
-.mw-echo-ui-notificationsWidget {
- border-top: 1px solid #DDDDDD;
- &-loadingOption {
- padding: 2em;
- &.oo-ui-optionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
- white-space: normal;
- }
- }
-}
diff --git a/Echo/modules/special/Feedback.png b/Echo/modules/special/Feedback.png
deleted file mode 100644
index a911d99d..00000000
--- a/Echo/modules/special/Feedback.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/special/FeedbackHover.png b/Echo/modules/special/FeedbackHover.png
deleted file mode 100644
index c46f04a0..00000000
--- a/Echo/modules/special/FeedbackHover.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/special/Help.png b/Echo/modules/special/Help.png
deleted file mode 100644
index e3de9a51..00000000
--- a/Echo/modules/special/Help.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/special/MoreInfo.png b/Echo/modules/special/MoreInfo.png
deleted file mode 100644
index 6efb4473..00000000
--- a/Echo/modules/special/MoreInfo.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/special/MoreInfoHover.png b/Echo/modules/special/MoreInfoHover.png
deleted file mode 100644
index 7607a7f0..00000000
--- a/Echo/modules/special/MoreInfoHover.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/special/Preferences.png b/Echo/modules/special/Preferences.png
deleted file mode 100644
index ff892422..00000000
--- a/Echo/modules/special/Preferences.png
+++ /dev/null
Binary files differ
diff --git a/Echo/modules/special/ext.echo.special.js b/Echo/modules/special/ext.echo.special.js
index d349cb78..a0c9ba24 100644
--- a/Echo/modules/special/ext.echo.special.js
+++ b/Echo/modules/special/ext.echo.special.js
@@ -1,171 +1,51 @@
( function ( $, mw ) {
'use strict';
- var useLang = mw.config.get( 'wgUserLanguage' );
- mw.echo.special = {
-
- notcontinue: null,
- header: '',
- processing: false,
-
- /**
- * Initialize the property in special notification page.
- */
- initialize: function () {
- var skin = mw.config.get( 'skin' );
-
- // Convert more link into a button
- $( '#mw-echo-more' )
- .click( function ( e ) {
- e.preventDefault();
- if ( !mw.echo.special.processing ) {
- mw.echo.special.processing = true;
- mw.echo.special.loadMore();
- }
- }
- );
- mw.echo.special.notcontinue = mw.config.get( 'wgEchoNextContinue' );
- mw.echo.special.header = mw.config.get( 'wgEchoDateHeader' );
-
- // Set up each individual notification with eventlogging, a close
- // box and dismiss interface if it is dismissable.
- $( '.mw-echo-notification' ).each( function () {
- mw.echo.logger.logInteraction(
- 'notification-impression',
- mw.echo.Logger.static.context.archive,
- Number( $( this ).attr( 'data-notification-event' ) ),
- $( this ).attr( 'data-notification-type' )
- );
- } );
-
- $( '#mw-echo-moreinfo-link' ).click( function () {
- mw.echo.logger.logInteraction( 'ui-help-click', mw.echo.Logger.static.context.archive );
- } );
- $( '#mw-echo-pref-link' ).click( function () {
- mw.echo.logger.logInteraction( 'ui-prefs-click', mw.echo.Logger.static.context.archive );
- } );
-
- // Convert subtitle links into header icons for Vector and Monobook skins
- if ( skin === 'vector' || skin === 'monobook' ) {
- $( '#mw-echo-moreinfo-link, #mw-echo-pref-link' )
- .empty()
- .appendTo( '#firstHeading' );
- $( '#contentSub' ).empty();
- }
-
- },
-
- /**
- * Load more notification records.
- */
- loadMore: function () {
- var notifications, data, container, $li,
- api = new mw.Api( { ajax: { cache: false } } ),
- seenTime = mw.config.get( 'wgEchoSeenTime' ),
- that = this,
- unread = [],
- apiData = {
- action: 'query',
- meta: 'notifications',
- notformat: 'html',
- notprop: 'index|list',
- notcontinue: this.notcontinue,
- notlimit: mw.config.get( 'wgEchoDisplayNum' ),
- uselang: useLang
- };
-
- api.get( apiData ).done( function ( result ) {
- container = $( '#mw-echo-special-container' );
- notifications = result.query.notifications;
- unread = [];
-
- $.each( notifications.index, function ( index, id ) {
- data = notifications.list[id];
-
- if ( that.header !== data.timestamp.date ) {
- that.header = data.timestamp.date;
- $( '<li></li>' ).addClass( 'mw-echo-date-section' ).append( that.header ).appendTo( container );
- }
-
- $li = $( '<li></li>' )
- .data( 'details', data )
- .data( 'id', id )
- .addClass( 'mw-echo-notification' )
- .attr( {
- 'data-notification-category': data.category,
- 'data-notification-event': data.id,
- 'data-notification-type': data.type
- } )
- .append( data['*'] )
- .appendTo( container );
-
- if ( !data.read ) {
- $li.addClass( 'mw-echo-unread' );
- unread.push( id );
- }
-
- if ( seenTime !== null && data.timestamp.mw > seenTime ) {
- $li.addClass( 'mw-echo-unseen' );
+ /*!
+ * Echo Special:Notifications page initialization
+ */
+ $( function () {
+ var specialPageContainer,
+ limitNotifications = 50,
+ links = mw.config.get( 'wgNotificationsSpecialPageLinks' ),
+ $content = $( '#mw-content-text' ),
+ echoApi = new mw.echo.api.EchoApi( { limit: limitNotifications } ),
+ unreadCounter = new mw.echo.dm.UnreadNotificationCounter( echoApi, [ 'message', 'alert' ], limitNotifications ),
+ modelManager = new mw.echo.dm.ModelManager( unreadCounter, {
+ type: [ 'message', 'alert' ],
+ itemsPerPage: limitNotifications,
+ readState: mw.config.get( 'wgEchoReadState' ),
+ localCounter: new mw.echo.dm.UnreadNotificationCounter(
+ echoApi,
+ [ 'message', 'alert' ],
+ limitNotifications,
+ {
+ localOnly: true,
+ source: 'local'
}
-
- mw.echo.logger.logInteraction(
- 'notification-impression',
- mw.echo.Logger.static.context.archive,
- Number( $li.attr( 'data-notification-event' ) ),
- $li.attr( 'data-notification-type' )
- );
- } );
-
- that.notcontinue = notifications['continue'];
- if ( unread.length > 0 ) {
- that.markAsRead( unread );
- } else {
- that.onSuccess();
- }
- } ).fail( function () {
- that.onError();
- } );
- },
-
- /**
- * Mark notifications as read.
- */
- markAsRead: function ( unread ) {
- var api = new mw.Api(),
- that = this;
- api.postWithToken( 'edit', {
- action: 'echomarkread',
- list: unread.join( '|' ),
- uselang: useLang
- } ).done( function () {
- // HACK: We should really redo the way the entire special
- // page handles the notifications now that they are separated
- // into 'alert' and 'messages'. However, until that happens,
- // the badges should be updated individually.
- // Don't try this at home.
- mw.echo.ui.messageWidget.fetchUnreadCountFromApi();
- mw.echo.ui.alertWidget.fetchUnreadCountFromApi();
-
- that.onSuccess();
- } ).fail( function () {
- that.onError();
- } );
- },
-
- onSuccess: function () {
- if ( !this.notcontinue ) {
- $( '#mw-echo-more' ).hide();
+ )
+ } ),
+ controller = new mw.echo.Controller( echoApi, modelManager );
+
+ // Set default max prioritized action links per item.
+ // For general purpose we have 2, for mobile only 1
+ mw.echo.config.maxPrioritizedActions = mw.config.get( 'skin' ) === 'minerva' ? 1 : 2;
+
+ specialPageContainer = new mw.echo.ui.NotificationsInboxWidget(
+ controller,
+ modelManager,
+ {
+ limit: limitNotifications,
+ $overlay: mw.echo.ui.$overlay,
+ prefLink: links.preferences,
+ helpLink: links.help
}
- this.processing = false;
- },
-
- onError: function () {
- // Todo: Show detail error message based on error code
- $( '#mw-echo-more' ).text( mw.msg( 'echo-load-more-error' ) );
- this.processing = false;
- }
- };
+ );
- $( document ).ready( mw.echo.special.initialize );
+ // Overlay
+ $( 'body' ).append( mw.echo.ui.$overlay );
-} )( jQuery, mediaWiki );
+ // Notifications
+ $content.empty().append( specialPageContainer.$element );
+ } );
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/styles/LabelIconWidget.less b/Echo/modules/styles/LabelIconWidget.less
new file mode 100644
index 00000000..9aec81f5
--- /dev/null
+++ b/Echo/modules/styles/LabelIconWidget.less
@@ -0,0 +1,13 @@
+.oo-ui-labelIconWidget {
+ display: table;
+}
+
+.oo-ui-labelIconWidget-row {
+ display: table-row;
+
+ .oo-ui-iconElement-icon,
+ .oo-ui-labelElement-label {
+ display: table-cell;
+ vertical-align: middle;
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.ActionMenuPopupWidget.less b/Echo/modules/styles/mw.echo.ui.ActionMenuPopupWidget.less
new file mode 100644
index 00000000..f1734ae5
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.ActionMenuPopupWidget.less
@@ -0,0 +1,6 @@
+.mw-echo-ui-actionMenuPopupWidget-menu {
+ &.oo-ui-menuSelectWidget {
+ // Override width: 100%; rule from OOUI
+ width: auto;
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.ConfirmationPopupWidget.less b/Echo/modules/styles/mw.echo.ui.ConfirmationPopupWidget.less
new file mode 100644
index 00000000..bede9d83
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.ConfirmationPopupWidget.less
@@ -0,0 +1,24 @@
+.mw-echo-ui-confirmationPopupWidget {
+ position: relative;
+ bottom: 1em;
+ width: 100%;
+ text-align: center;
+
+ &-popup {
+ display: inline-block;
+ background-color: #333;
+ border-radius: 2px;
+ padding: 0.5em 1em;
+ text-align: left;
+ color: #fff;
+
+ span {
+ vertical-align: middle;
+ }
+
+ .oo-ui-iconElement-icon {
+ display: inline-block;
+ margin-right: 0.5em;
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.CrossWikiNotificationItemWidget.less b/Echo/modules/styles/mw.echo.ui.CrossWikiNotificationItemWidget.less
new file mode 100644
index 00000000..deb8b70a
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.CrossWikiNotificationItemWidget.less
@@ -0,0 +1,74 @@
+@import '../echo.variables';
+
+.mw-echo-ui-crossWikiNotificationItemWidget,
+.mw-echo-ui-bundleNotificationItemWidget {
+ // Remove the padding that ItemWidget puts in
+ padding-left: 0;
+ padding-right: 0;
+ padding-bottom: 0;
+
+ // This is an abbreviation for the pieces that make up
+ // the face of the cross-wiki notification item
+ // without the inner group items
+ .mw-echo-ui-notificationItemWidget {
+ // Compensate for the 1em of left/right padding and 0.5em of bottom padding that we removed
+ &-icon {
+ margin-left: 1em;
+ }
+
+ &-content {
+ // The icon is 30px
+ margin-left: 30px;
+
+ padding-bottom: 1em;
+ // 0.8em from ItemWidget, plus 0.8em
+ padding-left: 1.6em;
+ padding-right: 0.8em;
+
+ .mw-echo-ui-notificationItemWidget-markAsReadButton {
+ margin-right: -0.8em;
+ }
+ }
+
+ &-icon,
+ &-content {
+ // There's no link but there is a click action, so change the cursor to indicate that (T138913)
+ cursor: pointer;
+ }
+ }
+
+ &-separator {
+ display: block;
+ position: absolute;
+ bottom: 0.4em;
+ width: 100%;
+ border-bottom: 1px solid #eaecf0;
+
+ .mw-echo-ui-crossWikiNotificationItemWidget-expanded &,
+ .mw-echo-ui-bundleNotificationItemWidget-expanded & {
+ display: none;
+ }
+ }
+
+ &-group {
+ cursor: default;
+ padding: @bundle-group-padding;
+ background-color: #f8f9fa;
+ -webkit-box-shadow: inset 0 -2px 0 0 rgba( 0, 0, 0, 0.05 ), inset 0 2px 0 0 rgba( 0, 0, 0, 0.05 );
+ -moz-box-shadow: inset 0 -2px 0 0 rgba( 0, 0, 0, 0.05 ), inset 0 2px 0 0 rgba( 0, 0, 0, 0.05 );
+ box-shadow: inset 0 -2px 0 0 rgba( 0, 0, 0, 0.05 ), inset 0 2px 0 0 rgba( 0, 0, 0, 0.05 );
+ border-bottom: 1px solid #ddd;
+ margin-bottom: 0.4em;
+ }
+
+ .mw-echo-ui-subGroupListWidget-header {
+ margin-bottom: @bundle-group-padding;
+
+ &-row-title {
+ // Override OOUI's line height for labels
+ line-height: 1em !important;
+ font-weight: bold;
+ color: @grey-medium;
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.CrossWikiUnreadFilterWidget.less b/Echo/modules/styles/mw.echo.ui.CrossWikiUnreadFilterWidget.less
new file mode 100644
index 00000000..859e604a
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.CrossWikiUnreadFilterWidget.less
@@ -0,0 +1,18 @@
+@import '../echo.variables';
+
+.mw-echo-ui-crossWikiUnreadFilterWidget {
+ border: 1px solid @border-color;
+ padding: @specialpage-separation-unit;
+ width: @specialpage-sidebar-width;
+
+ &-title {
+ display: block;
+ font-size: 1.3em;
+ font-weight: bold;
+ }
+
+ &-subtitle {
+ display: block;
+ color: @grey-light;
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.CrossWikiUnreadFilterWidget.monobook.less b/Echo/modules/styles/mw.echo.ui.CrossWikiUnreadFilterWidget.monobook.less
new file mode 100644
index 00000000..d9454f9c
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.CrossWikiUnreadFilterWidget.monobook.less
@@ -0,0 +1,7 @@
+@import '../echo.variables';
+
+.mw-echo-ui-crossWikiUnreadFilterWidget {
+ .mw-echo-ui-pageNotificationsOptionWidget-count .oo-ui-labelWidget {
+ padding: 0;
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.DatedNotificationsWidget.less b/Echo/modules/styles/mw.echo.ui.DatedNotificationsWidget.less
new file mode 100644
index 00000000..b740f9ab
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.DatedNotificationsWidget.less
@@ -0,0 +1,22 @@
+@import '../echo.variables';
+.mw-echo-ui-datedNotificationsWidget {
+ min-height: 5em;
+
+ // We want everything inside the widget to be
+ // pending/transparent, but not the widget itself
+ // because otherwise, the background pending animation
+ // is also transparent.
+ &.oo-ui-pendingElement-pending > * {
+ opacity: 0.5;
+ }
+
+ .mw-echo-ui-subGroupListWidget {
+ // This is a hack to make sure that this widget
+ // is the nearest scrollable widget for the submenus
+ overflow-y: auto;
+
+ &-header {
+ margin-bottom: @specialpage-separation-unit;
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.DatedSubGroupListWidget.less b/Echo/modules/styles/mw.echo.ui.DatedSubGroupListWidget.less
new file mode 100644
index 00000000..ff40fb30
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.DatedSubGroupListWidget.less
@@ -0,0 +1,42 @@
+@import '../echo.variables';
+.mw-echo-ui-datedSubGroupListWidget {
+ .mw-body-content &-title {
+ // Since the title is <h2> we want to specifically
+ // change the styling to bring it back to mimic a
+ // content span. We also must override the h2 rules
+ // so specificity is important
+ font-weight: inherit;
+ font-size: inherit;
+ font-family: inherit;
+ border: 0;
+
+ &-primary {
+ font-size: 1.5em;
+ margin-right: 0.5em;
+ display: inline-block;
+
+ &:first-letter {
+ text-transform: uppercase;
+ }
+ }
+
+ &-secondary {
+ font-size: 1.5em;
+ color: @grey-light;
+ }
+ }
+
+ @media all and ( max-width: ( @specialpage-hd-width - 1 ) ) {
+ .mw-echo-ui-subGroupListWidget-header-row-markAllReadButton {
+ font-size: 0.8em;
+ }
+
+ &-title-primary {
+ font-size: 1.2em;
+ }
+
+ &-title-secondary {
+ display: none;
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.FooterNoticeWidget.less b/Echo/modules/styles/mw.echo.ui.FooterNoticeWidget.less
new file mode 100644
index 00000000..8bc9c7da
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.FooterNoticeWidget.less
@@ -0,0 +1,39 @@
+@import '../echo.variables';
+@import '../echo.mixins';
+
+.mw-echo-ui-footerNoticeWidget {
+ padding: 0.5em;
+ border-bottom: 1px solid #ddd;
+ white-space: normal;
+ line-height: 16px;
+
+ &-row {
+ display: table-row;
+ }
+
+ &-dismiss,
+ &-info,
+ &-label {
+ display: table-cell;
+ }
+
+ &-label {
+ width: 100%;
+ }
+
+ &-icon {
+ padding-right: 0.5em;
+ }
+
+ &-dismiss,
+ &-info {
+ .mw-echo-ui-mixin-hover-opacity();
+
+ vertical-align: top;
+
+ .oo-ui-iconElement-icon {
+ width: 1.3em !important;
+ height: 1.3em !important;
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.MenuItemWidget.less b/Echo/modules/styles/mw.echo.ui.MenuItemWidget.less
new file mode 100644
index 00000000..6c955fd6
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.MenuItemWidget.less
@@ -0,0 +1,90 @@
+@import '../echo.variables';
+@import '../echo.mixins';
+
+.mw-echo-ui-menuItemWidget {
+ &-icon {
+ display: inline-block;
+ // We have to override oojs-ui's width/height, which uses
+ // a very specific selector
+ width: 1.5em !important;
+ height: 1.5em !important;
+ min-width: 1.5em !important;
+ min-height: 1.5em !important;
+
+ position: absolute;
+ top: 0;
+ }
+
+ &-content {
+ display: inline-block;
+ margin-left: 1.5em + 0.5em; // Icon width + 0.5em spacing
+
+ // We have to override oojs-ui's color, which uses
+ // a very specific selector
+ font-weight: normal !important;
+ color: @color-base !important;
+ // Set max-width so buttons are truncated
+ max-width: 15em;
+
+ &-description {
+ color: #666 !important;
+ }
+ }
+
+ &-prioritized {
+ .mw-echo-ui-mixin-hover-opacity();
+ display: inline-block;
+ padding: 0;
+ }
+
+ &-dynamic-action {
+ padding: 1.5em;
+
+ &:hover {
+ background-color: @background-color-base;
+ }
+
+ .mw-echo-ui-menuItemWidget-content {
+ &-description {
+ padding-top: 1em;
+ }
+
+ span.oo-ui-labelElement-label {
+ white-space: normal;
+ overflow: visible;
+ }
+ }
+ }
+
+ // Correct for when inside the popup menu
+ .mw-echo-ui-actionMenuPopupWidget-menu & {
+ display: block;
+ padding: 0.7em;
+
+ &:hover {
+ background-color: #eaecf0;
+ }
+
+ &-icon {
+ // The icon should be 15px, which is 1.1em. However,
+ // ooui icons are surrounded by whitespace. In this case,
+ // the whitespace is about 6px out of the original 24px
+ // so the non-whitespace dimensions are 3/4 of the total.
+ // So to compensate, the new size should be 1.1em*4/3 = 1.4em
+ width: 1.4em !important;
+ height: 1.4em !important;
+ // Take into account the padding and subtract half of
+ // the whitespace adjustment of the icon
+ top: 0.7em - 0.3em / 2;
+ }
+
+ &-content {
+ margin-left: 1.4em + 0.7em; // Icon width + 0.7em spacing
+ font-weight: bold !important;
+
+ span.oo-ui-labelElement-label {
+ line-height: 1em;
+ }
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.less b/Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.less
new file mode 100644
index 00000000..183edf91
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.less
@@ -0,0 +1,92 @@
+@import 'mediawiki.mixins';
+@import '../echo.variables';
+
+.mw-echo-ui-notificationBadgeButtonPopupWidget {
+ position: relative;
+
+ > .oo-ui-popupWidget {
+ // #p-personal li has a font-size of 0.75em, but we want the
+ // font size here to be exactly 0.875em, so we must override
+ // the parent em sizing by dividing.
+ font-size: 0.875em / 0.75em;
+
+ > .oo-ui-popupWidget-popup {
+ > .oo-ui-popupWidget-head {
+ height: 3.5em;
+ border-bottom: 1px solid #ddd;
+
+ > .oo-ui-iconWidget {
+ /* ( 3.5 - 1.875 ) / 2 = 0.8125 */
+ margin: 0.8125em 0 0.8125em 1em;
+ float: left;
+ opacity: @opacity-mid;
+ }
+
+ > .oo-ui-labelElement-label {
+ font-size: 1.2em;
+ padding: 0.3em;
+ margin-left: 0;
+ font-weight: bold;
+ }
+
+ .mw-echo-ui-notificationsWidget-markAllReadButton {
+ margin-right: 1em;
+ }
+ }
+
+ > .oo-ui-popupWidget-body {
+ // Work around scrollbar rendering bug in Chrome
+ overflow-y: visible;
+ // ...but make sure we don't actually overflow in the Y direction,
+ // to avoid breaking ClippableElement
+ overflow-x: auto;
+
+ > .mw-echo-ui-notificationsListWidget > .mw-echo-ui-notificationItemWidget {
+ // The popup body itself has a border. We need to override the notification
+ // item widget styles so that the edge borders of the items are not duplicated
+ border-left: 0;
+ border-right: 0;
+ &:last-child {
+ border-bottom: 0;
+ }
+ }
+ }
+
+ > .oo-ui-popupWidget-footer {
+ border-top: 1px solid #ddd;
+ width: 100%;
+
+ // Override the margins that OOUI suddenly added to popup footers (T171302)
+ margin: 0;
+
+ > .oo-ui-buttonGroupWidget {
+ display: block;
+ }
+
+ .mw-echo-ui-notificationBadgeButtonPopupWidget-footer-buttons {
+ display: table-row;
+
+ .oo-ui-buttonElement {
+ display: table-cell;
+ white-space: normal;
+ font-weight: bold;
+ width: @notification-popup-width / 2;
+ .box-sizing( border-box );
+
+ &:last-child {
+ border-left: 1px solid #ddd;
+ }
+
+ > .oo-ui-buttonElement-button {
+ display: block;
+ line-height: 2.6em;
+ margin: 0;
+ border: 0;
+ padding: 0.5em;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.modern.less b/Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.modern.less
new file mode 100644
index 00000000..6dc59143
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.modern.less
@@ -0,0 +1,18 @@
+body #p-personal {
+ overflow: visible;
+}
+
+#p-personal li.mw-echo-ui-notificationBadgeButtonPopupWidget {
+ font-variant: normal;
+ text-transform: none;
+ font-weight: normal;
+ // Badge
+ > .oo-ui-buttonElement-button {
+ border-radius: 0;
+ }
+ // Popup buttons
+ .oo-ui-buttonElement-button:hover {
+ // In modern, the hover color is white, which is unhelpful.
+ color: #666;
+ }
+}
diff --git a/Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.monobook.less b/Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.monobook.less
index f122c85e..9f408922 100644
--- a/Echo/modules/ooui/styles/mw.echo.ui.NotificationBadgeWidget.monobook.less
+++ b/Echo/modules/styles/mw.echo.ui.NotificationBadgeWidget.monobook.less
@@ -1,14 +1,23 @@
-@import '../../echo.variables';
+@import '../echo.variables';
-.mw-echo-ui-notificationBadgeButtonPopupWidget {
+#p-personal li.mw-echo-ui-notificationBadgeButtonPopupWidget {
text-transform: none;
font-weight: normal;
+
+ &,
+ .oo-ui-popupWidget a.oo-ui-buttonElement-button {
+ color: #333;
+ }
+
+ a {
+ background-color: initial;
+ }
+
// Badge
> .oo-ui-buttonElement-button {
- padding-right: (@badge-padding + 0.25em);
&:hover {
.oo-ui-labelElement-label {
- color: black !important;
+ color: #000 !important;
}
}
}
@@ -18,5 +27,4 @@
// Override text-align that monobook uses for #p-personal li
text-align: left;
}
-
}
diff --git a/Echo/modules/styles/mw.echo.ui.NotificationItemWidget.less b/Echo/modules/styles/mw.echo.ui.NotificationItemWidget.less
new file mode 100644
index 00000000..ccb21bcd
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.NotificationItemWidget.less
@@ -0,0 +1,290 @@
+@import 'mediawiki.mixins';
+@import '../echo.variables';
+@import '../echo.mixins';
+
+.mw-echo-ui-notificationItemWidget {
+ background-color: #f1f1f1;
+ position: relative;
+ white-space: normal;
+ padding: 0.8em 1em 0.5em 1em;
+ .box-sizing( border-box );
+
+ border: 1px solid #ddd;
+ border-bottom: 0;
+
+ &:hover {
+ background-color: #ececec;
+ }
+
+ &:last-child {
+ border-bottom: 1px solid #ddd;
+ }
+
+ &-unread {
+ background-color: @background-color-base;
+
+ &:hover {
+ background-color: #f8f9fa;
+ }
+ }
+
+ > a,
+ &:hover > a {
+ text-decoration: none;
+ }
+
+ // Dynamic-action messages in mw.notify
+ &-notify {
+ &-title {
+ font-weight: bold;
+ font-size: 1.2em;
+ }
+
+ &-description {
+ font-size: 1em;
+ color: @grey-medium;
+ }
+ }
+
+ &-icon {
+ position: absolute;
+
+ img {
+ height: 30px;
+ width: 30px;
+ }
+ }
+
+ &-content {
+ display: block;
+ // The icon is 30px
+ margin-left: 30px;
+ padding-left: 0.8em;
+ .box-sizing( border-box );
+
+ &-message {
+ line-height: 1.3em;
+ // Compensate for the placement of the 'mark as read'
+ // button, so the message is not stretched past it.
+ // The 'mark as read' circle is placed with a right
+ // margin of -1em
+ padding-right: 1em;
+ // break-word rules are inconsistent accross browsers
+ // these three rules should cover the main use cases
+ // with major browser support
+ word-break: break-word;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+
+ &-header {
+ color: @notification-text-color;
+ }
+ &-body {
+ // In the popup only, truncate the text to one-line
+ // with ellipses
+ .mw-echo-ui-notificationBadgeButtonPopupWidget-popup & {
+ .mw-echo-ui-mixin-one-line-truncated;
+ }
+ color: @notification-body-color;
+ margin-top: 4px;
+ }
+ }
+
+ &-table {
+ display: table;
+ width: 100%;
+ margin-top: 0.8em;
+ }
+
+ &-actions {
+ display: table-row;
+ font-size: 0.9em;
+
+ & > &-buttons.oo-ui-buttonSelectWidget {
+ display: table-cell;
+ vertical-align: bottom;
+ }
+
+ &-button,
+ .mw-echo-ui-menuItemWidget-prioritized {
+ margin-right: 1.2em;
+ }
+
+ &-menu {
+ .mw-echo-ui-mixin-hover-opacity();
+ display: table-cell;
+ vertical-align: bottom;
+ padding: 0;
+ }
+
+ &-timestamp {
+ display: table-cell;
+ vertical-align: bottom;
+ text-align: right;
+ color: @color-base-emphasized;
+ opacity: @opacity-low;
+ white-space: nowrap;
+ width: 100%;
+ }
+
+ }
+ }
+
+ &-markAsReadButton {
+ float: right;
+ font-size: 1em;
+ // Compensate for the padding in the item widget
+ margin-top: -0.8em;
+ margin-right: -1em;
+ padding: 0;
+
+ .mw-echo-ui-notificationItemWidget-bundled & {
+ margin-top: 0;
+ }
+ }
+
+ // Table layout only for the content inside bundles
+ &-bundled {
+ display: table;
+ width: 100%;
+ padding: 0.5em;
+
+ .mw-echo-ui-notificationItemWidget-content {
+ display: table-row;
+ padding-left: 0.5em + 1.5em;
+
+ .mw-echo-ui-notificationItemWidget {
+ // CSS table layout
+ &-icon,
+ &-content-message,
+ &-content-actions,
+ &-markAsReadButton {
+ display: table-cell;
+ vertical-align: top;
+ }
+
+ // Positioning fixes for bundled items
+ &-icon {
+ position: relative;
+ padding-right: 0.5em;
+
+ img {
+ height: 1.5em;
+ width: 1.5em;
+ }
+
+ }
+
+ &-content-message {
+ display: table-cell;
+ padding-right: 0.5em;
+ width: 100%;
+
+ &-header {
+ width: 100%;
+
+ &-wrapper {
+ position: relative;
+ }
+
+ // Bundled notifications don't have bodies, only headers,
+ // so they use <em> to designate excerpts. Use the body color
+ // for these.
+ em {
+ color: @notification-body-color;
+ font-style: normal;
+ }
+ }
+ }
+
+ &-content-actions {
+ &-row {
+ display: table-row;
+ }
+
+ &-buttons {
+ display: table-cell;
+ vertical-align: middle;
+ }
+
+ &-menu {
+ display: table-cell;
+ vertical-align: middle;
+ }
+
+ &-timestamp {
+ float: none;
+ display: table-cell;
+ vertical-align: middle;
+ padding-right: 0.5em;
+ white-space: nowrap;
+ }
+ }
+
+ &-markAsReadButton {
+ display: table-cell;
+ vertical-align: top;
+ float: none;
+ }
+ }
+ }
+ }
+
+ &-initiallyUnseen {
+ -webkit-animation-name: unseen-fadeout-to-read;
+ animation-name: unseen-fadeout-to-read;
+ -webkit-animation-duration: 0.5s;
+ animation-duration: 0.5s;
+ -webkit-animation-delay: 2s;
+ animation-delay: 2s;
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out;
+ -webkit-animation-fill-mode: both;
+ animation-fill-mode: both;
+
+ &.mw-echo-ui-notificationItemWidget-unread {
+ -webkit-animation-name: unseen-fadeout-to-unread;
+ animation-name: unseen-fadeout-to-unread;
+ }
+ }
+
+ // NOTE: The internal styling of the notifications is outside this file, because
+ // it also affects the notifications in Special:Notifications
+ // These styles are in modules/nojs/ext.echo.notifications.less
+}
+
+@-webkit-keyframes unseen-fadeout-to-unread {
+ from {
+ background-color: @notification-background-unseen;
+ }
+ to {
+ background-color: @notification-background-unread;
+ }
+}
+
+@keyframes unseen-fadeout-to-unread {
+ from {
+ background-color: @notification-background-unseen;
+ }
+ to {
+ background-color: @notification-background-unread;
+ }
+}
+
+@-webkit-keyframes unseen-fadeout-to-read {
+ from {
+ background-color: @notification-background-unseen;
+ }
+ to {
+ background-color: @notification-background-read;
+ }
+}
+
+@keyframes unseen-fadeout-to-read {
+ from {
+ background-color: @notification-background-unseen;
+ }
+ to {
+ background-color: @notification-background-read;
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.NotificationItemWidget.modern.less b/Echo/modules/styles/mw.echo.ui.NotificationItemWidget.modern.less
new file mode 100644
index 00000000..b6edb0df
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.NotificationItemWidget.modern.less
@@ -0,0 +1,25 @@
+/* stylelint-disable no-descending-specificity */
+#p-personal {
+ .mw-echo-ui-notificationItemWidget {
+ & a,
+ & a.new {
+ // Oh and double everything for :hover since Modern does that too.
+ &,
+ &:hover {
+ // In modern, the hover color is white, which is unhelpful.
+ color: #666;
+ text-decoration: none;
+ }
+ }
+ }
+
+ // Override personal tools padding for links
+ li .mw-echo-state a {
+ padding: 0;
+ }
+
+ .mw-echo-ui-notificationBadgeButtonPopupWidget-footer a {
+ color: #666;
+ }
+}
+/* stylelint-enable no-descending-specificity */
diff --git a/Echo/modules/styles/mw.echo.ui.NotificationsInboxWidget.less b/Echo/modules/styles/mw.echo.ui.NotificationsInboxWidget.less
new file mode 100644
index 00000000..2b29b68c
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.NotificationsInboxWidget.less
@@ -0,0 +1,94 @@
+@import '../echo.variables';
+.mw-echo-ui-notificationsInboxWidget {
+ display: table;
+ width: 100%;
+ max-width: @specialpage-width;
+ position: relative;
+
+ &-row {
+ display: table-row;
+ width: 100%;
+ }
+
+ &-toolbarWrapper {
+ height: 4em;
+ }
+
+ &-cell {
+ display: table-cell;
+ vertical-align: middle;
+ &-placeholder {
+ display: table-cell;
+ width: 100%;
+ }
+ }
+
+ &-sidebar {
+ width: @specialpage-sidebar-width;
+ padding-right: 1em;
+ vertical-align: top;
+
+ @media all and ( max-width: ( @specialpage-hd-width - 1 ) ) {
+ // Hide the sidebar for small screens
+ display: none;
+ }
+ }
+ &-main {
+ vertical-align: top;
+
+ &-toolbar {
+ &-top {
+ display: table;
+ width: 100%;
+ }
+
+ &-affixed {
+ position: fixed;
+ z-index: 2;
+ top: 0;
+ background: #fff;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ box-shadow: 0 2px 0 0 rgba( 0, 0, 0, 0.1 );
+ }
+
+ &-settings {
+ padding-left: 1em;
+ }
+ }
+ }
+
+ @media all and ( max-width: ( @specialpage-hd-width - 1 ) ) {
+ // Override table-layout for the top toolbar so we get
+ // filters and pagination under one another
+ &-main {
+ &-toolbar {
+ &-top {
+ display: block;
+ margin-bottom: 1em;
+
+ .mw-echo-ui-notificationsInboxWidget-row {
+ display: block;
+ text-align: center;
+ }
+ }
+ &-readState {
+ display: inline-block;
+ }
+ &-settings,
+ &-pagination {
+ display: inline-block;
+ margin-top: 1em;
+ }
+ &-settings {
+ .oo-ui-popupWidget-popup {
+ text-align: left;
+ }
+ }
+ }
+ }
+ &-toolbarWrapper {
+ height: 8em;
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.NotificationsListWidget.less b/Echo/modules/styles/mw.echo.ui.NotificationsListWidget.less
new file mode 100644
index 00000000..ced6f2db
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.NotificationsListWidget.less
@@ -0,0 +1,22 @@
+@import '../echo.variables';
+
+.mw-echo-ui-notificationsListWidget {
+ .mw-echo-ui-notificationsListWidget-bundle & {
+ padding: 0;
+ }
+
+ > .mw-echo-ui-notificationItemWidget:first-child {
+ border-top: 0;
+ }
+
+ > a,
+ &:hover > a {
+ text-decoration: none;
+ color: @grey-medium;
+ }
+
+ &:not( :hover ) a,
+ #p-personal &:not( :hover ) a.new {
+ color: @grey-medium;
+ }
+}
diff --git a/Echo/modules/ooui/styles/mw.echo.ui.NotificationsWidget.monobook.less b/Echo/modules/styles/mw.echo.ui.NotificationsListWidget.monobook.less
index 2f863d25..df796f2b 100644
--- a/Echo/modules/ooui/styles/mw.echo.ui.NotificationsWidget.monobook.less
+++ b/Echo/modules/styles/mw.echo.ui.NotificationsListWidget.monobook.less
@@ -1,4 +1,4 @@
-.mw-echo-ui-notificationsWidget {
+.mw-echo-ui-notificationsListWidget {
text-align: left;
text-transform: none;
}
diff --git a/Echo/modules/styles/mw.echo.ui.NotificationsWrapper.less b/Echo/modules/styles/mw.echo.ui.NotificationsWrapper.less
new file mode 100644
index 00000000..0cea05c7
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.NotificationsWrapper.less
@@ -0,0 +1,3 @@
+.mw-echo-notificationsWrapper {
+ overflow-y: auto;
+}
diff --git a/Echo/modules/styles/mw.echo.ui.PageFilterWidget.less b/Echo/modules/styles/mw.echo.ui.PageFilterWidget.less
new file mode 100644
index 00000000..8f22f272
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.PageFilterWidget.less
@@ -0,0 +1,8 @@
+@import '../echo.variables';
+.mw-echo-ui-pageFilterWidget {
+ margin-top: 2 * @specialpage-separation-unit;
+
+ &-title {
+ font-weight: bold;
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.PageNotificationsOptionWidget.less b/Echo/modules/styles/mw.echo.ui.PageNotificationsOptionWidget.less
new file mode 100644
index 00000000..f2556b5e
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.PageNotificationsOptionWidget.less
@@ -0,0 +1,53 @@
+@import 'mediawiki.mixins';
+@import '../echo.variables';
+
+.mw-echo-ui-pageNotificationsOptionWidget {
+ clear: both;
+ width: 100%;
+ .box-sizing( border-box );
+
+ &.oo-ui-optionWidget {
+ .transition( ~'background-color 100ms, color 100ms' );
+
+ &-highlighted {
+ background-color: #eaecf0;
+ color: @color-base-active;
+ }
+
+ &-selected {
+ background-color: @background-color-primary;
+ color: @color-primary;
+ }
+
+ &-selected&-highlighted,
+ &-pressed&-highlighted {
+ background-color: rgba( 41, 98, 204, 0.1 );
+ color: @color-primary;
+ }
+ }
+
+ &-icon {
+ float: left;
+ .oo-ui-iconElement-icon {
+ display: inline-block;
+ }
+ }
+
+ &-title {
+ padding: 0.2em 0;
+ }
+
+ &-count {
+ background-color: #eaecf0;
+ color: @grey-medium;
+ float: right;
+ padding: 0.2em 0.5em;
+ margin-left: 0.5em;
+ border-radius: 2px;
+
+ .oo-ui-optionWidget-selected & {
+ background: none; // `background-color: transparent` would be the goto value, but IE 8-9 introduces a bug
+ color: @color-primary;
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.PaginationWidget.less b/Echo/modules/styles/mw.echo.ui.PaginationWidget.less
new file mode 100644
index 00000000..a88f9bb4
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.PaginationWidget.less
@@ -0,0 +1,19 @@
+.mw-echo-ui-paginationWidget {
+ display: table;
+
+ &-row {
+ display: table-row;
+ }
+
+ &-label,
+ &-start,
+ &-direction {
+ display: table-cell;
+ vertical-align: middle;
+ }
+
+ &-label {
+ padding: 0 0.5em;
+ white-space: nowrap;
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.PlaceholderItemWidget.less b/Echo/modules/styles/mw.echo.ui.PlaceholderItemWidget.less
new file mode 100644
index 00000000..7ea644e4
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.PlaceholderItemWidget.less
@@ -0,0 +1,5 @@
+@import '../echo.variables';
+.mw-echo-ui-placeholderItemWidget {
+ padding: 2em;
+ background-color: @notification-background-read;
+}
diff --git a/Echo/modules/styles/mw.echo.ui.SpecialHelpMenuWidget.less b/Echo/modules/styles/mw.echo.ui.SpecialHelpMenuWidget.less
new file mode 100644
index 00000000..83b71770
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.SpecialHelpMenuWidget.less
@@ -0,0 +1,41 @@
+@import '../echo.variables';
+
+.mw-echo-ui-specialHelpMenuWidget {
+ .oo-ui-popupWidget-body {
+ // Override clippable inline rules
+ overflow-y: hidden !important;
+ overflow-x: hidden !important;
+ }
+
+ &-markAllRead-label {
+ &-title {
+ display: block;
+ }
+
+ &-subtitle {
+ display: block;
+ color: @grey-light;
+ margin-top: 0.2em;
+ }
+ }
+
+ &-menu {
+ .oo-ui-buttonWidget {
+ display: block;
+ padding: 0.5em;
+ margin-right: 0;
+
+ .oo-ui-labelElement-label {
+ white-space: normal;
+ // Width of the popup (300px) minus the
+ // width of the icon (1.875em) minus the
+ // padding of the button (0.5em * 2)
+ width: ~'calc(300px - 1.875em - 1em)';
+ }
+
+ &:hover {
+ background-color: #ddd;
+ }
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.SubGroupListWidget.less b/Echo/modules/styles/mw.echo.ui.SubGroupListWidget.less
new file mode 100644
index 00000000..f537c581
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.SubGroupListWidget.less
@@ -0,0 +1,36 @@
+@import '../echo.variables';
+
+.mw-echo-ui-subGroupListWidget {
+
+ &:not( :first-child ) {
+ padding-top: @bundle-group-padding;
+ }
+
+ &-header {
+ display: table;
+ width: 100%;
+
+ &-row {
+ display: table-row;
+
+ &-title {
+ display: table-cell;
+ width: 100%;
+ vertical-align: bottom;
+
+ .oo-ui-labelElement-label {
+ white-space: normal;
+ }
+ }
+
+ &-markAllReadButton {
+ display: table-cell;
+ text-align: right;
+ }
+ }
+ }
+
+ .mw-echo-ui-sortedListWidget {
+ margin-bottom: @bundle-group-padding / 2;
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.ToggleReadCircleButtonWidget.less b/Echo/modules/styles/mw.echo.ui.ToggleReadCircleButtonWidget.less
new file mode 100644
index 00000000..ecee6410
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.ToggleReadCircleButtonWidget.less
@@ -0,0 +1,39 @@
+@import 'mediawiki.mixins';
+@import '../echo.variables';
+
+.mw-echo-ui-toggleReadCircleButtonWidget {
+ &-circle {
+ border-radius: 50%;
+ min-width: 10px;
+ width: @bundle-group-padding;
+ min-height: 10px;
+ height: @bundle-group-padding;
+ margin: @bundle-group-padding;
+ .box-sizing( border-box );
+
+ // Mark as read
+ background-color: #36c;
+ border: 0;
+
+ // Mark as unread
+ &-unread {
+ background-color: #eaecf0;
+ border: 1px solid @grey-light;
+ }
+ }
+
+ // Override OOUI specific rule for frameless buttons that adds a ~2.5em padding-top
+ &.oo-ui-widget.oo-ui-widget-enabled.oo-ui-buttonElement.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button {
+ padding-top: 0;
+ }
+
+ &:hover .mw-echo-ui-toggleReadCircleButtonWidget-circle {
+ // Mark as read
+ background-color: #447ff5;
+
+ // Mark as unread
+ &-unread {
+ background-color: #c8ccd1;
+ }
+ }
+}
diff --git a/Echo/modules/styles/mw.echo.ui.overlay.less b/Echo/modules/styles/mw.echo.ui.overlay.less
new file mode 100644
index 00000000..66d6765c
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.overlay.less
@@ -0,0 +1,8 @@
+.mw-echo-ui-overlay {
+ font-size: 0.875em;
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 1;
+}
diff --git a/Echo/modules/styles/mw.echo.ui.overlay.minerva.less b/Echo/modules/styles/mw.echo.ui.overlay.minerva.less
new file mode 100644
index 00000000..9007ab67
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.overlay.minerva.less
@@ -0,0 +1,26 @@
+/* In mobile, overlay is positioned at the bottom */
+.mw-echo-ui-overlay {
+ position: fixed;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ top: auto;
+
+ .mw-echo-ui-actionMenuPopupWidget-menu {
+ padding: 0.5em;
+ font-size: 1.5em;
+ box-shadow: none;
+ border: 1px solid #666;
+ // Override the positioning of the menu
+ // so it is "stuck" on the bottom of the
+ // notification overlay panel
+ position: static !important;
+ bottom: 0 !important;
+ left: 0 !important;
+ width: 100% !important;
+ max-width: none !important;
+ height: auto !important;
+ top: auto !important;
+ }
+}
+
diff --git a/Echo/modules/styles/mw.echo.ui.overlay.monobook.less b/Echo/modules/styles/mw.echo.ui.overlay.monobook.less
new file mode 100644
index 00000000..da3e7d30
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.overlay.monobook.less
@@ -0,0 +1,8 @@
+.mw-echo-ui-overlay {
+ // We need the overlay to be adjusted for:
+ // #globalWrapper 127%
+ // .pBody 95%
+ // .portlet ul 95%
+ // .mw-echo-ui-notificationBadgeButtonPopupWidget > .oo-ui-popupWidget 0.875/0.75em
+ font-size: 1.27 * 0.95 * 0.95 * 0.875 / 0.75 em;
+}
diff --git a/Echo/modules/styles/mw.echo.ui.overlay.vector.less b/Echo/modules/styles/mw.echo.ui.overlay.vector.less
new file mode 100644
index 00000000..a67b1bbe
--- /dev/null
+++ b/Echo/modules/styles/mw.echo.ui.overlay.vector.less
@@ -0,0 +1,3 @@
+.mw-echo-ui-overlay {
+ z-index: 101;
+}
diff --git a/Echo/modules/ui/mw.echo.ui.ActionMenuPopupWidget.js b/Echo/modules/ui/mw.echo.ui.ActionMenuPopupWidget.js
new file mode 100644
index 00000000..70c07950
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.ActionMenuPopupWidget.js
@@ -0,0 +1,89 @@
+( function ( mw ) {
+ /**
+ * Action menu popup widget for echo items.
+ *
+ * We don't currently have anything that properly answers the complete
+ * design for our popup menus in OOUI, so this widget serves two purposes:
+ * 1. The MenuSelectWidget is intended to deliver a menu that relates
+ * directly to its anchor, so its sizing is dictated by whatever anchors
+ * it. This is not what we require, so we have to override the 'click' event
+ * to reset the width of the menu.
+ * 2. It abstracts the behavior of the item menus for easier management
+ * in the item widget itself (which is fairly large)
+ *
+ * @class
+ * @extends OO.ui.ButtonWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ * @cfg {number} [menuWidth=300] The width of the popup menu
+ */
+ mw.echo.ui.ActionMenuPopupWidget = function MwEchoUiActionMenuPopupWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.ActionMenuPopupWidget.parent.call( this, config );
+
+ this.$overlay = config.$overlay || this.$element;
+
+ this.menuWidth = config.menuWidth || 300;
+
+ // Menu
+ this.menu = new OO.ui.MenuSelectWidget( {
+ $floatableContainer: this.$element,
+ classes: [ 'mw-echo-ui-actionMenuPopupWidget-menu' ],
+ widget: this
+ } );
+ this.$overlay.append( this.menu.$element );
+
+ // Events
+ this.connect( this, { click: 'onAction' } );
+ this.getMenu().connect( this, {
+ remove: 'decideToggle',
+ add: 'decideToggle',
+ clear: 'decideToggle'
+ } );
+ // Initialization
+ this.$element
+ .addClass( 'mw-echo-ui-actionMenuPopupWidget' );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.echo.ui.ActionMenuPopupWidget, OO.ui.ButtonWidget );
+
+ /**
+ * Handle the button action being triggered.
+ *
+ * @private
+ */
+ mw.echo.ui.ActionMenuPopupWidget.prototype.onAction = function () {
+ this.menu.toggle();
+ // HACK: The menu is attempting to be the same size as the container,
+ // which in our case is not the point at all. We need the menu
+ // to be larger, so force this setting:
+ this.menu.$element.css( 'width', this.menuWidth );
+ // HACK: Prevent ClippableElement from overwriting this width value on scroll
+ // or window resize
+ this.menu.toggleClipping( false );
+ };
+
+ /**
+ * Decide whether the menu should be visible, based on whether it is
+ * empty or not.
+ */
+ mw.echo.ui.ActionMenuPopupWidget.prototype.decideToggle = function () {
+ this.toggle( !this.getMenu().isEmpty() );
+ };
+
+ /**
+ * Get the widget's action menu
+ *
+ * @return {OO.ui.MenuSelectWidget} Menu
+ */
+ mw.echo.ui.ActionMenuPopupWidget.prototype.getMenu = function () {
+ return this.menu;
+ };
+}( mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.BadgeLinkWidget.js b/Echo/modules/ui/mw.echo.ui.BadgeLinkWidget.js
new file mode 100644
index 00000000..8339e6b4
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.BadgeLinkWidget.js
@@ -0,0 +1,77 @@
+( function ( mw, $ ) {
+ /**
+ * Notification badge button widget for echo popup.
+ *
+ * @class
+ * @extends OO.ui.ButtonWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {string} [type] The notification types this button represents;
+ * 'message', 'alert' or 'all'
+ * @cfg {string} [href] URL the badge links to
+ * @cfg {string} [convertedNumber] A converted version of the initial count
+ */
+ mw.echo.ui.BadgeLinkWidget = function MwEchoUiBadgeLinkWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.BadgeLinkWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.LabelElement.call( this, $.extend( { $label: this.$element }, config ) );
+ OO.ui.mixin.ButtonElement.call( this, $.extend( { $button: this.$element }, config ) );
+ OO.ui.mixin.TitledElement.call( this, $.extend( { $titled: this.$element }, config ) );
+ OO.ui.mixin.FlaggedElement.call( this, $.extend( {}, config, { $flagged: this.$element } ) );
+
+ this.$element
+ .addClass( 'mw-echo-notifications-badge' );
+
+ this.count = 0;
+ this.type = config.type || 'alert';
+ this.setCount( config.numItems, config.convertedNumber );
+
+ if ( config.href !== undefined && OO.ui.isSafeUrl( config.href ) ) {
+ this.$element.attr( 'href', config.href );
+ }
+ };
+
+ OO.inheritClass( mw.echo.ui.BadgeLinkWidget, OO.ui.Widget );
+ OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.LabelElement );
+ OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.ButtonElement );
+ OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.TitledElement );
+ OO.mixinClass( mw.echo.ui.BadgeLinkWidget, OO.ui.mixin.FlaggedElement );
+
+ mw.echo.ui.BadgeLinkWidget.static.tagName = 'a';
+
+ /**
+ * Set the count labels for this button.
+ *
+ * @param {number} numItems Number of items
+ * @param {string} [convertedNumber] Label of the button. Defaults to the default message
+ * showing the item number.
+ */
+ mw.echo.ui.BadgeLinkWidget.prototype.setCount = function ( numItems, convertedNumber ) {
+ convertedNumber = convertedNumber !== undefined ? convertedNumber : numItems;
+
+ this.$element
+ .toggleClass( 'mw-echo-notifications-badge-all-read', !numItems )
+ .toggleClass( 'mw-echo-notifications-badge-long-label', convertedNumber.length > 2 )
+ .attr( 'data-counter-num', numItems )
+ .attr( 'data-counter-text', convertedNumber );
+
+ this.setLabel( mw.msg(
+ this.type === 'alert' ?
+ 'echo-notification-alert' :
+ 'echo-notification-notice',
+ convertedNumber
+ ) );
+
+ if ( this.count !== numItems ) {
+ this.count = numItems;
+
+ // Fire badge count change hook
+ mw.hook( 'ext.echo.badge.countChange' ).fire( this.type, this.count, convertedNumber );
+ }
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.BundleNotificationItemWidget.js b/Echo/modules/ui/mw.echo.ui.BundleNotificationItemWidget.js
new file mode 100644
index 00000000..aa98aa43
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.BundleNotificationItemWidget.js
@@ -0,0 +1,227 @@
+( function ( mw, $ ) {
+ /**
+ * Bundle notification item widget.
+ * This widget is expandable and displays
+ * inner notifications that constitute the bundle.
+ *
+ * @class
+ * @extends mw.echo.ui.NotificationItemWidget
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo notifications controller
+ * @param {mw.echo.dm.BundleNotificationItem} model Notification group model
+ * @param {Object} [config] Configuration object
+ * @cfg {boolean} [animateSorting=false] Animate the sorting of items
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ */
+ mw.echo.ui.BundleNotificationItemWidget = function MwEchoUiBundleNotificationItemWidget( controller, model, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.BundleNotificationItemWidget.parent.call( this, controller, model, config );
+
+ this.controller = controller;
+ this.model = model;
+
+ this.toggleMarkAsReadButtons( true );
+
+ this.listWidget = new mw.echo.ui.SortedListWidget(
+ // Sorting callback
+ function ( a, b ) {
+ // Reverse sorting
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+
+ // Fallback on IDs
+ return b.getId() - a.getId();
+ },
+ // Config
+ {
+ classes: [ 'mw-echo-ui-bundleNotificationItemWidget-group' ],
+ timestamp: this.getTimestamp(),
+ $overlay: this.$overlay,
+ animated: !!config.animateSorting
+ }
+ );
+
+ this.listWidget.$element
+ // We have to manually set the display to 'none' here because
+ // otherwise the 'slideUp' and 'slideDown' jQuery effects don't
+ // work
+ .css( 'display', 'none' );
+
+ // Initialize closed
+ this.expanded = false;
+
+ // Add "expand" button
+ this.toggleExpandButton = new OO.ui.ButtonOptionWidget( {
+ icon: 'expand',
+ framed: false,
+ classes: [ 'mw-echo-ui-notificationItemWidget-content-actions-button' ]
+ } );
+ this.updateExpandButton();
+ this.actionsButtonSelectWidget.addItems( [ this.toggleExpandButton ], 0 );
+
+ // Events
+ this.toggleExpandButton.connect( this, { click: 'expand' } );
+
+ if ( !this.model.getPrimaryUrl() ) {
+ // If there's no primary link, make sure a click
+ // triggers the 'expand' action
+ this.$content.on( 'click', this.expand.bind( this ) );
+ }
+
+ // Initialization
+ this.populateFromModel();
+ this.toggleExpanded( false );
+ this.toggleRead( false );
+ this.$element
+ .addClass( 'mw-echo-ui-bundleNotificationItemWidget' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-bundleNotificationItemWidget-separator' ),
+ this.listWidget.$element
+ );
+
+ // Events
+ this.model.connect( this, { update: 'updateDataFromModel' } );
+
+ // Update read and seen states from the model
+ this.updateDataFromModel();
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.BundleNotificationItemWidget, mw.echo.ui.NotificationItemWidget );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.onPrimaryLinkClick = function () {
+ // Log notification click
+
+ mw.echo.logger.logInteraction(
+ mw.echo.Logger.static.actions.notificationClick,
+ mw.echo.Logger.static.context.popup,
+ this.getModel().getId(),
+ this.getModel().getCategory(),
+ false,
+ // Source of this notification if it is cross-wiki
+ this.bundle ? this.getModel().getSource() : ''
+ );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.markRead = function ( isRead ) {
+ this.controller.markEntireListModelRead( this.model.getModelName(), isRead );
+ };
+
+ /**
+ * Populate the items in this widget according to the data
+ * in the model
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.populateFromModel = function () {
+ var widget = this;
+ this.getList().addItems( this.model.getList().getItems().map( function ( singleNotifModel ) {
+ return new mw.echo.ui.SingleNotificationItemWidget(
+ widget.controller,
+ singleNotifModel,
+ {
+ $overlay: widget.$overlay,
+ bundle: true
+ }
+ );
+ } ) );
+ };
+
+ /**
+ * Update item state when the item model changes.
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.updateDataFromModel = function () {
+ this.toggleRead( this.model.isRead() );
+ this.toggleSeen( this.model.isSeen() );
+ this.emit( 'sortChange' );
+ };
+
+ /**
+ * Toggle the visibility of the notification item list and the placeholder/error widget.
+ *
+ * @param {boolean} showList Show the list
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.toggleListDisplay = function ( showList ) {
+ this.listWidget.toggle( showList );
+ };
+
+ /**
+ * Expand the group and fetch the list of notifications.
+ * Only fetch the first time we expand.
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.expand = function () {
+ var widget = this;
+
+ this.toggleExpanded( !this.expanded );
+ this.updateExpandButton();
+
+ this.$element.toggleClass( 'mw-echo-ui-bundleNotificationItemWidget-expanded', this.expanded );
+
+ if ( !this.expanded ) {
+ return;
+ }
+
+ // Log the expand action
+ mw.echo.logger.logInteraction(
+ mw.echo.Logger.static.actions.notificationBundleExpand,
+ mw.echo.Logger.static.context.popup,
+ widget.getModel().getId(),
+ widget.getModel().getCategory()
+ );
+ };
+
+ /**
+ * Toggle the expand/collapsed state of this group widget
+ *
+ * @param {boolean} show Show the widget expanded
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.toggleExpanded = function ( show ) {
+ this.expanded = show !== undefined ? !!show : !this.expanded;
+
+ if ( show ) {
+ this.getList().$element.slideDown();
+ } else {
+ this.getList().$element.slideUp();
+ }
+ };
+
+ /**
+ * Update the expand button label
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.updateExpandButton = function () {
+ this.toggleExpandButton.setLabel(
+ this.expanded ?
+ mw.msg( 'notification-link-text-collapse-all' ) :
+ mw.msg( 'notification-link-text-expand-all' )
+ );
+ this.toggleExpandButton.setIcon(
+ this.expanded ?
+ 'collapse' :
+ 'expand'
+ );
+ };
+
+ /**
+ * Get the list widget contained in this item
+ *
+ * @return {mw.echo.ui.SortedListWidget} List widget
+ */
+ mw.echo.ui.BundleNotificationItemWidget.prototype.getList = function () {
+ return this.listWidget;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.ClonedNotificationItemWidget.js b/Echo/modules/ui/mw.echo.ui.ClonedNotificationItemWidget.js
new file mode 100644
index 00000000..c2115c7e
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.ClonedNotificationItemWidget.js
@@ -0,0 +1,87 @@
+( function ( mw ) {
+ /* global moment:false */
+ /**
+ * A wrapper widget for a fake, cloned notification. This is used
+ * for the fade in/out effects while reordering.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {jQuery} $element A clone of an mw.echo.ui.NotificationItemWidget's $element
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [timestamp] The timestamp for this cloned widget, in UTC and ISO 8601 format
+ * @cfg {boolean} [read=false] The read state for this cloned widget
+ * @cfg {boolean} [foreign=false] The foreignness state of this cloned widget
+ * @cfg {number} [id] The id for this cloned widget
+ */
+ mw.echo.ui.ClonedNotificationItemWidget = function MwEchoUiClonedNotificationItemWidget( $element, config ) {
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.ClonedNotificationItemWidget.parent.call( this, config );
+
+ this.$element = $element;
+ this.timestamp = config.timestamp || moment.utc().format( 'YYYY-MM-DD[T]HH:mm:ss[Z]' );
+ this.read = !!config.read;
+ this.foreign = config.foreign === undefined ? true : config.foreign;
+ this.id = config.id;
+
+ this.$element.addClass( 'mw-echo-ui-clonedNotificationItemWidget' );
+ };
+
+ /* Initialization */
+ OO.inheritClass( mw.echo.ui.ClonedNotificationItemWidget, OO.ui.Widget );
+
+ /**
+ * Get the widget's timestamp
+ *
+ * @return {string} Timestamp in UTC, ISO 8601 format
+ */
+ mw.echo.ui.ClonedNotificationItemWidget.prototype.getTimestamp = function () {
+ return this.timestamp;
+ };
+
+ /**
+ * Get the widget's read state
+ *
+ * @return {boolean} Widget is read
+ */
+ mw.echo.ui.ClonedNotificationItemWidget.prototype.isRead = function () {
+ return this.read;
+ };
+
+ /**
+ * Get the widget's id
+ *
+ * @return {number} Widget id
+ */
+ mw.echo.ui.ClonedNotificationItemWidget.prototype.getId = function () {
+ return this.id;
+ };
+
+ /**
+ * The foreign state of this widget
+ *
+ * @return {boolean} This item widget is foreign
+ */
+ mw.echo.ui.ClonedNotificationItemWidget.prototype.isForeign = function () {
+ return this.foreign;
+ };
+
+ /**
+ * This widget is fake by definition.
+ *
+ * @return {boolean} true
+ */
+ mw.echo.ui.ClonedNotificationItemWidget.prototype.isFake = function () {
+ return true;
+ };
+
+ /**
+ * No-op
+ */
+ mw.echo.ui.ClonedNotificationItemWidget.prototype.resetInitiallyUnseen = function () {
+ };
+
+}( mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.ConfirmationPopupWidget.js b/Echo/modules/ui/mw.echo.ui.ConfirmationPopupWidget.js
new file mode 100644
index 00000000..840366ca
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.ConfirmationPopupWidget.js
@@ -0,0 +1,67 @@
+( function ( mw, $ ) {
+ /**
+ * Confirmation overlay widget, especially for mobile display.
+ * The behavior of this widget is to appear with a given confirmation
+ * message and then disapear after a given interval.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.IconElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {number} [interval=2000] The number of milliseconds that it takes
+ * for the popup to disappear after appearing.
+ */
+ mw.echo.ui.ConfirmationPopupWidget = function MwEchoUiConfirmationPopupWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.ConfirmationPopupWidget.parent.call( this, config );
+
+ // Mixin constructor
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.IconElement.call( this, $.extend( { icon: 'doubleCheck' }, config ) );
+
+ this.interval = config.interval || 2000;
+
+ this.$element
+ .addClass( 'mw-echo-ui-confirmationPopupWidget' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-confirmationPopupWidget-popup' )
+ .append( this.$icon, this.$label )
+ )
+ // We're using explicit hide here because the widget uses
+ // animated fadeOut
+ .hide();
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.ConfirmationPopupWidget, OO.ui.Widget );
+ OO.mixinClass( mw.echo.ui.ConfirmationPopupWidget, OO.ui.mixin.LabelElement );
+ OO.mixinClass( mw.echo.ui.ConfirmationPopupWidget, OO.ui.mixin.IconElement );
+
+ /**
+ * Show the widget and then animate its fade out.
+ */
+ mw.echo.ui.ConfirmationPopupWidget.prototype.showAnimated = function () {
+ // OOUI removes the oo-ui-image-invert class when it is initialized
+ // without explicit flag classes, so we have to re-add this when we
+ // display the icon for the icon to be inverted
+ this.$icon.addClass( 'oo-ui-image-invert' );
+ this.$element.show();
+ setTimeout( this.hide.bind( this ), this.interval );
+ };
+
+ /**
+ * Hide the widget by fading it out
+ *
+ * @private
+ */
+ mw.echo.ui.ConfirmationPopupWidget.prototype.hide = function () {
+ this.$element.fadeOut();
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.CrossWikiNotificationItemWidget.js b/Echo/modules/ui/mw.echo.ui.CrossWikiNotificationItemWidget.js
new file mode 100644
index 00000000..64dff510
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.CrossWikiNotificationItemWidget.js
@@ -0,0 +1,360 @@
+( function ( mw, $ ) {
+ /**
+ * Cross-wiki notification item widget.
+ * This widget is expandable and displays groups of
+ * notification item lists by their sources.
+ *
+ * TODO: When we have local bundles (without groups of lists)
+ * we can separate the "expand" functionality and UI to another mixin
+ * so we can use it with both widgets.
+ *
+ * @class
+ * @extends mw.echo.ui.NotificationItemWidget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo notifications controller
+ * @param {mw.echo.dm.CrossWikiNotificationItem} model Notification group model
+ * @param {Object} [config] Configuration object
+ * @cfg {boolean} [animateSorting=false] Animate the sorting of items
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget = function MwEchoUiCrossWikiNotificationItemWidget( controller, model, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.CrossWikiNotificationItemWidget.parent.call( this, controller, model, config );
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.controller = controller;
+ this.model = model;
+
+ // In cross-wiki groups we only have 'mark as read'
+ this.toggleMarkAsReadButtons( true );
+
+ this.listWidget = new mw.echo.ui.SortedListWidget(
+ // Sorting callback
+ function ( a, b ) {
+ // Define the sorting order.
+ // This will go by the lists' timestamp, which in turn
+ // take the latest timestamp in their items
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+
+ // Fallback on IDs
+ return b.getSource() - a.getSource();
+ },
+ // Config
+ {
+ classes: [ 'mw-echo-ui-crossWikiNotificationItemWidget-group' ],
+ timestamp: this.getTimestamp(),
+ $overlay: this.$overlay,
+ animated: config.animateSorting
+ }
+ );
+
+ this.listWidget.$element
+ // We have to manually set the display to 'none' here because
+ // otherwise the 'slideUp' and 'slideDown' jQuery effects don't
+ // work
+ .css( 'display', 'none' );
+ this.setPendingElement( this.listWidget.$element );
+
+ this.errorWidget = new mw.echo.ui.PlaceholderItemWidget();
+ this.errorWidget.toggle( false );
+
+ // Initialize closed
+ this.showTitles = true;
+ this.expanded = false;
+ this.fetchedOnce = false;
+
+ // Add "expand" button
+ this.toggleExpandButton = new OO.ui.ButtonOptionWidget( {
+ icon: 'expand',
+ framed: false,
+ classes: [ 'mw-echo-ui-notificationItemWidget-content-actions-button' ]
+ } );
+ this.updateExpandButton();
+ this.actionsButtonSelectWidget.addItems( [ this.toggleExpandButton ] );
+
+ // Events
+ this.model.connect( this, { discard: 'onModelDiscard' } );
+ this.toggleExpandButton.connect( this, { click: 'expand' } );
+ this.$content.on( 'click', this.expand.bind( this ) );
+
+ // TODO: Handle cases where the group became empty or a case where the group only has 1 item left.
+ // Note: Right now this code works primarily for cross-wiki notifications. These act differently
+ // than local bundles. Cross-wiki notifications, when they "lose" their items for being read, they
+ // vanish from the list. Unlike them, the plan for local bundles is that read sub-items go outside
+ // the bundle and become their own items in the general notificationsWidget, and when the local bundle
+ // has 1 notification left, the group will actually transform into that last notification item.
+ // We don't listen to the empty event right now, because the entire item is deleted in cross-wiki
+ // notifications. When we work on local bundles, we will have to add that event listener per item.
+
+ // Initialization
+ this.populateFromModel();
+ this.toggleExpanded( false );
+ this.toggleRead( false );
+ this.toggleTitles( true );
+ this.$element
+ .addClass( 'mw-echo-ui-crossWikiNotificationItemWidget' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-crossWikiNotificationItemWidget-separator' ),
+ this.listWidget.$element,
+ this.errorWidget.$element
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.CrossWikiNotificationItemWidget, mw.echo.ui.NotificationItemWidget );
+ OO.mixinClass( mw.echo.ui.CrossWikiNotificationItemWidget, OO.ui.mixin.PendingElement );
+
+ /* Methods */
+
+ /**
+ * Respond to model removing source group
+ *
+ * @param {string} groupName Symbolic name of the group
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.onModelDiscard = function ( groupName ) {
+ var list = this.getList(),
+ group = list.getItemFromId( groupName );
+
+ list.removeItems( [ group ] );
+
+ if ( list.isEmpty() ) {
+ this.controller.removeCrossWikiItem();
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.onMarkAsReadButtonClick = function () {
+ // Log this action
+ mw.echo.logger.logInteraction(
+ mw.echo.Logger.static.actions.markXWikiReadClick,
+ mw.echo.Logger.static.context.popup,
+ null, // Event ID is omitted
+ this.controller.getTypeString() // The type of the list in general
+ );
+
+ // Parent
+ return mw.echo.ui.CrossWikiNotificationItemWidget.parent.prototype.onMarkAsReadButtonClick.call( this );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.markRead = function () {
+ // Cross wiki notification is always only marked as read, never as
+ // unread. The original parameter is unneeded
+ this.controller.markEntireCrossWikiItemAsRead();
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.onPrimaryLinkClick = function () {
+ // Log notification click
+
+ mw.echo.logger.logInteraction(
+ mw.echo.Logger.static.actions.notificationClick,
+ mw.echo.Logger.static.context.popup,
+ this.getModel().getId(),
+ this.getModel().getCategory(),
+ false,
+ // Source of this notification if it is cross-wiki
+ this.bundle ? this.getModel().getSource() : ''
+ );
+ };
+
+ /**
+ * Populate the items in this widget according to the data
+ * in the model
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.populateFromModel = function () {
+ var i,
+ groupWidgets = [],
+ groups = this.model.getList().getItems();
+
+ for ( i = 0; i < groups.length; i++ ) {
+ // Create SubGroup widgets
+ groupWidgets.push(
+ new mw.echo.ui.SubGroupListWidget(
+ this.controller,
+ groups[ i ],
+ {
+ $overlay: this.$overlay,
+ showTitle: this.showTitles
+ }
+ )
+ );
+ }
+ this.getList().addItems( groupWidgets );
+ };
+
+ /**
+ * Toggle the visibility of the titles
+ *
+ * @param {boolean} [show] Show titles
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.toggleTitles = function ( show ) {
+ var i,
+ items = this.getList().getItems();
+
+ show = show === undefined ? !this.showTitles : show;
+
+ if ( this.showTitles !== show ) {
+ this.showTitles = show;
+ for ( i = 0; i < items.length; i++ ) {
+ items[ i ].toggleTitle( show );
+ }
+ }
+ };
+
+ /**
+ * Check whether the titles should be shown and toggle them
+ * in each of the group lists.
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.checkShowTitles = function () {
+ this.toggleTitles( this.getList().getItemCount() > 1 );
+ };
+
+ /**
+ * Toggle the visibility of the notification item list and the placeholder/error widget.
+ *
+ * @param {boolean} showList Show the list
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.toggleListDisplay = function ( showList ) {
+ this.errorWidget.toggle( !showList );
+ this.listWidget.toggle( showList );
+ };
+
+ /**
+ * Show an error message
+ *
+ * @param {string} label Error label
+ * @param {string} link Error link
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.showErrorMessage = function ( label, link ) {
+ this.errorWidget.setLabel( label || '' );
+ this.errorWidget.setLink( link || '' );
+
+ this.toggleListDisplay( false );
+ };
+
+ /**
+ * Expand the group and fetch the list of notifications.
+ * Only fetch the first time we expand.
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.expand = function () {
+ var widget = this;
+
+ this.toggleExpanded( !this.expanded );
+ this.updateExpandButton();
+
+ if ( !this.expanded ) {
+ return;
+ }
+
+ // Log the expand action
+ mw.echo.logger.logInteraction(
+ mw.echo.Logger.static.actions.notificationBundleExpand,
+ mw.echo.Logger.static.context.popup,
+ widget.getModel().getId(),
+ widget.getModel().getCategory()
+ );
+
+ if ( !this.fetchedOnce ) {
+ // Expand
+ this.pushPending();
+ this.toggleListDisplay( true );
+ // Query all sources
+ this.controller.fetchCrossWikiNotifications()
+ .then(
+ null,
+ function ( result ) {
+ var loginPageTitle = mw.Title.newFromText( 'Special:UserLogin' );
+ // If failure, check if the failure is due to login
+ // so we can display a more comprehensive error
+ // message in that case
+ if ( result.errCode === 'notlogin-required' ) {
+ // Login error
+ widget.showErrorMessage(
+ mw.message( 'echo-notification-popup-loginrequired' ),
+ // Set the option link to the login page
+ loginPageTitle.getUrl()
+ );
+ } else {
+ // General error
+ widget.showErrorMessage( mw.msg( 'echo-api-failure' ) );
+ }
+ }
+ )
+ .always( this.popPending.bind( this ) );
+
+ // Only run the fetch notifications action once
+ this.fetchedOnce = true;
+ }
+ };
+
+ /**
+ * Toggle the expand/collapsed state of this group widget
+ *
+ * @param {boolean} show Show the widget expanded
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.toggleExpanded = function ( show ) {
+ this.expanded = show !== undefined ? !!show : !this.expanded;
+
+ this.$element.toggleClass( 'mw-echo-ui-crossWikiNotificationItemWidget-expanded', this.expanded );
+
+ if ( this.expanded ) {
+ this.getList().$element.slideDown();
+ } else {
+ this.getList().$element.slideUp();
+ }
+ };
+
+ /**
+ * Update the expand button label
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.updateExpandButton = function () {
+ var type = this.model.getType();
+
+ this.toggleExpandButton.setLabel(
+ this.expanded ?
+ mw.msg( 'notification-link-text-collapse-all' ) :
+ // Messages that appear here are:
+ // notification-link-text-expand-alert-count
+ // notification-link-text-expand-notice-count
+ mw.msg(
+ 'notification-link-text-expand-' +
+ ( type === 'message' ? 'notice' : type ) +
+ '-count',
+ mw.language.convertNumber( this.model.getCount() )
+ )
+ );
+ this.toggleExpandButton.setIcon(
+ this.expanded ?
+ 'collapse' :
+ 'expand'
+ );
+ };
+
+ /**
+ * Get the list widget contained in this item
+ *
+ * @return {mw.echo.ui.SortedListWidget} List widget
+ */
+ mw.echo.ui.CrossWikiNotificationItemWidget.prototype.getList = function () {
+ return this.listWidget;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.CrossWikiUnreadFilterWidget.js b/Echo/modules/ui/mw.echo.ui.CrossWikiUnreadFilterWidget.js
new file mode 100644
index 00000000..fe6d13f2
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.CrossWikiUnreadFilterWidget.js
@@ -0,0 +1,173 @@
+( function ( $, mw ) {
+ /**
+ * A filter for cross-wiki unread notifications
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo controller
+ * @param {mw.echo.dm.FiltersModel} filtersModel Filter model
+ * @param {Object} [config] Configuration object
+ */
+ mw.echo.ui.CrossWikiUnreadFilterWidget = function MwEchoUiCrossWikiUnreadFilterWidget( controller, filtersModel, config ) {
+ var titleWidget, subtitleWidget;
+
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.CrossWikiUnreadFilterWidget.parent.call( this,
+ // Sorting callback
+ function ( a, b ) {
+ var diff;
+
+ // Local source is always first
+ if ( a.getSource() === 'local' ) {
+ return -1;
+ } else if ( b.getSource() === 'local' ) {
+ return 1;
+ }
+
+ diff = Number( b.getTotalCount() ) - Number( a.getTotalCount() );
+ if ( diff !== 0 ) {
+ return diff;
+ }
+
+ // Fallback on Source
+ return b.getSource() - a.getSource();
+ },
+ // Config
+ config
+ );
+ // Mixin
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.controller = controller;
+ this.model = filtersModel;
+ this.previousPageSelected = null;
+
+ titleWidget = new OO.ui.LabelWidget( {
+ classes: [ 'mw-echo-ui-crossWikiUnreadFilterWidget-title' ],
+ label: mw.msg( 'echo-specialpage-pagefilters-title' )
+ } );
+ subtitleWidget = new OO.ui.LabelWidget( {
+ classes: [ 'mw-echo-ui-crossWikiUnreadFilterWidget-subtitle' ],
+ label: mw.msg( 'echo-specialpage-pagefilters-subtitle' )
+ } );
+
+ // Events
+ this.aggregate( { choose: 'pageFilterChoose' } );
+ this.connect( this, { pageFilterChoose: 'onPageFilterChoose' } );
+
+ this.$element
+ .addClass( 'mw-echo-ui-crossWikiUnreadFilterWidget' )
+ .append(
+ titleWidget.$element,
+ subtitleWidget.$element,
+ this.$group
+ .addClass( 'mw-echo-ui-crossWikiUnreadFilterWidget-group' )
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.CrossWikiUnreadFilterWidget, mw.echo.ui.SortedListWidget );
+ OO.mixinClass( mw.echo.ui.CrossWikiUnreadFilterWidget, OO.ui.mixin.PendingElement );
+
+ /* Events */
+
+ /**
+ * @event filter
+ * @param {string} source Source symbolic name
+ * @param {number} [pageId] Chosen page ID
+ *
+ * A source page filter was chosen
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to choose event in one of the page filter widgets
+ *
+ * @param {mw.echo.ui.PageFilterWidget} widget The widget the event originated from
+ * @param {mw.echo.ui.PageNotificationsOptionWidget} item The chosen item
+ * @fires filter
+ */
+ mw.echo.ui.CrossWikiUnreadFilterWidget.prototype.onPageFilterChoose = function ( widget, item ) {
+ var source = widget.getSource(),
+ page = item && item.getData();
+
+ if ( item ) {
+ this.setItemSelected( item );
+ // Emit a choice
+ this.emit( 'filter', source, page );
+ }
+ };
+
+ /**
+ * Set the selected item
+ *
+ * @param {mw.echo.ui.PageNotificationsOptionWidget} item Item to select
+ */
+ mw.echo.ui.CrossWikiUnreadFilterWidget.prototype.setItemSelected = function ( item ) {
+ // Unselect the previous item
+ if ( this.previousPageSelected ) {
+ this.previousPageSelected.setSelected( false );
+ }
+ item.setSelected( true );
+ this.previousPageSelected = item;
+ };
+
+ /**
+ * Populate the sources
+ */
+ mw.echo.ui.CrossWikiUnreadFilterWidget.prototype.populateSources = function () {
+ this.pushPending();
+ this.controller.fetchUnreadPagesByWiki()
+ .then( this.populateDataFromModel.bind( this ) )
+ .always( this.popPending.bind( this ) );
+ };
+
+ /**
+ * Populate the widget from the model data
+ */
+ mw.echo.ui.CrossWikiUnreadFilterWidget.prototype.populateDataFromModel = function () {
+ var i, source, widget, selectedWidget, item,
+ widgets = [],
+ sourcePageModel = this.model.getSourcePagesModel(),
+ selectedSource = sourcePageModel.getCurrentSource(),
+ selectedPage = sourcePageModel.getCurrentPage(),
+ sources = sourcePageModel.getSourcesArray();
+
+ for ( i = 0; i < sources.length; i++ ) {
+ source = sources[ i ];
+ widget = new mw.echo.ui.PageFilterWidget(
+ sourcePageModel,
+ source,
+ {
+ title: sourcePageModel.getSourceTitle( source ),
+ unreadCount: sourcePageModel.getSourceTotalCount( source ),
+ initialSelection: this.previousPageSelected && this.previousPageSelected.getData()
+ }
+ );
+
+ widgets.push( widget );
+ }
+
+ this.clearItems();
+ this.addItems( widgets );
+
+ // Select the current source
+ selectedWidget = this.getItemFromData( selectedSource );
+ if ( selectedPage ) {
+ // Select a specific page
+ item = selectedWidget.getItemFromData( selectedPage );
+ } else {
+ // The wiki title is selected
+ item = selectedWidget.getTitleItem();
+ }
+ this.setItemSelected( item );
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.DatedNotificationsWidget.js b/Echo/modules/ui/mw.echo.ui.DatedNotificationsWidget.js
new file mode 100644
index 00000000..fb015c33
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.DatedNotificationsWidget.js
@@ -0,0 +1,174 @@
+( function ( $, mw ) {
+ /**
+ * A notifications list organized and separated by dates
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo controller
+ * @param {mw.echo.dm.ModelManager} modelManager Model manager
+ * @param {Object} [config] Configuration object
+ * @cfg {boolean} [animateSorting=false] Animate the sorting of items
+ * @cfg {jQuery} [$overlay] An overlay for the popup menus
+ */
+ mw.echo.ui.DatedNotificationsWidget = function MwEchoUiDatedNotificationsListWidget( controller, modelManager, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.DatedNotificationsWidget.parent.call( this, config );
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.manager = modelManager;
+ this.controller = controller;
+ this.models = {};
+
+ this.$overlay = config.$overlay || this.$element;
+ this.animateSorting = !!config.animateSorting;
+
+ this.listWidget = new mw.echo.ui.SortedListWidget(
+ // Sorting callback
+ function ( a, b ) {
+ // Reverse sorting
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+ },
+ // Config
+ {
+ classes: [ 'mw-echo-ui-datedNotificationsWidget-group' ],
+ $overlay: this.$overlay,
+ animated: false
+ }
+ );
+
+ // Events
+ this.manager.connect( this, {
+ update: 'populateFromModel',
+ discard: 'onManagerDiscardModel'
+ } );
+
+ this.$element
+ .addClass( 'mw-echo-ui-datedNotificationsWidget' )
+ .append( this.listWidget.$element );
+
+ // Initialization
+ this.populateFromModel();
+ };
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.DatedNotificationsWidget, OO.ui.Widget );
+ OO.mixinClass( mw.echo.ui.DatedNotificationsWidget, OO.ui.mixin.PendingElement );
+
+ mw.echo.ui.DatedNotificationsWidget.prototype.onManagerDiscardModel = function ( modelId ) {
+ var group,
+ model = this.models[ modelId ],
+ list = this.getList();
+
+ if ( model ) {
+ group = list.getItemFromId( model.getName() );
+ list.removeItems( [ group ] );
+ }
+ };
+ /**
+ * Respond to model removing source group
+ *
+ * @param {string} source Symbolic name of the source group
+ */
+ mw.echo.ui.DatedNotificationsWidget.prototype.onModelRemoveSource = function ( source ) {
+ var list = this.getList(),
+ group = list.getItemFromId( source );
+
+ list.removeItems( [ group ] );
+ };
+
+ /**
+ * Respond to model manager update event.
+ * This event means we are repopulating the entire list and the
+ * associated models within it.
+ *
+ * @param {Object} models List models, indexed by ID
+ */
+ mw.echo.ui.DatedNotificationsWidget.prototype.populateFromModel = function ( models ) {
+ var modelId, model, subgroupWidget,
+ groupWidgets = [];
+
+ // Detach all attached models
+ for ( modelId in this.models ) {
+ this.detachModel( modelId );
+ }
+
+ for ( model in models ) {
+ // Create SubGroup widgets
+ subgroupWidget = new mw.echo.ui.DatedSubGroupListWidget(
+ this.controller,
+ models[ model ],
+ {
+ showTitle: true,
+ showMarkAllRead: true,
+ $overlay: this.$overlay,
+ animated: this.animateSorting
+ }
+ );
+ this.attachModel( model, models[ model ] );
+
+ subgroupWidget.resetItemsFromModel();
+ groupWidgets.push( subgroupWidget );
+ }
+
+ // Reset the list and re-add the items
+ this.getList().clearItems();
+ this.getList().addItems( groupWidgets );
+ };
+
+ /**
+ * Attach a model to the widget
+ *
+ * @param {string} modelId Symbolic name for the model
+ * @param {mw.echo.dm.SortedList} model Notifications list model
+ */
+ mw.echo.ui.DatedNotificationsWidget.prototype.attachModel = function ( modelId, model ) {
+ this.models[ modelId ] = model;
+ };
+
+ /**
+ * Detach a model from the widget
+ *
+ * @param {string} modelId Notifications list model
+ */
+ mw.echo.ui.DatedNotificationsWidget.prototype.detachModel = function ( modelId ) {
+ this.models[ modelId ].disconnect( this );
+ delete this.models[ modelId ];
+ };
+
+ /**
+ * Get the list widget contained in this item
+ *
+ * @return {mw.echo.ui.SortedListWidget} List widget
+ */
+ mw.echo.ui.DatedNotificationsWidget.prototype.getList = function () {
+ return this.listWidget;
+ };
+
+ /**
+ * Get the number of all notifications in all sections of the widget
+ *
+ * @return {number} The number of all notifications
+ */
+ mw.echo.ui.DatedNotificationsWidget.prototype.getAllNotificationCount = function () {
+ var i,
+ count = 0,
+ groups = this.getList().getItems();
+
+ for ( i = 0; i < groups.length; i++ ) {
+ count += groups[ i ].getListWidget().getItemCount();
+ }
+
+ return count;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.DatedSubGroupListWidget.js b/Echo/modules/ui/mw.echo.ui.DatedSubGroupListWidget.js
new file mode 100644
index 00000000..8196e0b8
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.DatedSubGroupListWidget.js
@@ -0,0 +1,67 @@
+( function ( mw, $ ) {
+ /* global moment:false */
+ /**
+ * A sub group widget that displays notifications divided by dates.
+ *
+ * @class
+ * @extends mw.echo.ui.SubGroupListWidget
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Notifications controller
+ * @param {mw.echo.dm.SortedList} listModel Notifications list model for this source
+ * @param {Object} [config] Configuration object
+ */
+ mw.echo.ui.DatedSubGroupListWidget = function MwEchoUiDatedSubGroupListWidget( controller, listModel, config ) {
+ var momentTimestamp, diff, fullDate, stringTimestamp,
+ now = moment(),
+ $primaryDate = $( '<span>' )
+ .addClass( 'mw-echo-ui-datedSubGroupListWidget-title-primary' ),
+ $secondaryDate = $( '<span>' )
+ .addClass( 'mw-echo-ui-datedSubGroupListWidget-title-secondary' ),
+ $title = $( '<h2>' )
+ .addClass( 'mw-echo-ui-datedSubGroupListWidget-title' )
+ .append( $primaryDate, $secondaryDate );
+
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.DatedSubGroupListWidget.parent.call( this, controller, listModel, $.extend( {
+ // Since this widget is defined as a dated list, we sort
+ // its items according to timestamp without consideration
+ // of read state or foreignness.
+ sortingCallback: function ( a, b ) {
+ // Reverse sorting
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+
+ // Fallback on IDs
+ return b.getId() - a.getId();
+ }
+ }, config ) );
+
+ // Round all dates to the day they're in, as if they all happened at 00:00h
+ stringTimestamp = moment.utc( this.model.getTimestamp() ).local().format( 'YYYY-MM-DD' );
+ momentTimestamp = moment( stringTimestamp );
+ diff = now.diff( momentTimestamp, 'weeks' );
+ fullDate = momentTimestamp.format( 'LL' );
+
+ $primaryDate.text( fullDate );
+ if ( diff === 0 ) {
+ $secondaryDate.text( fullDate );
+ momentTimestamp.locale( 'echo-shortRelativeTime' );
+ $primaryDate.text( momentTimestamp.calendar() );
+ }
+
+ this.title.setLabel( $title );
+
+ this.$element
+ .addClass( 'mw-echo-ui-datedSubGroupListWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.DatedSubGroupListWidget, mw.echo.ui.SubGroupListWidget );
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.FooterNoticeWidget.js b/Echo/modules/ui/mw.echo.ui.FooterNoticeWidget.js
new file mode 100644
index 00000000..f61c87cf
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.FooterNoticeWidget.js
@@ -0,0 +1,81 @@
+( function ( mw, $ ) {
+ /**
+ * Footer notice widget.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {string} [iconUrl] The source URL of the feedback icon
+ * @cfg {string} [url] The URL for the survey
+ * @cfg {string} [message] The message to display, in HTML or jQuery object.
+ * The message should already be formatted properly.
+ */
+ mw.echo.ui.FooterNoticeWidget = function MwEchoUiFooterNoticeWidget( config ) {
+ var $icon, label, dismissButton,
+ $row = $( '<div>' )
+ .addClass( 'mw-echo-ui-footerNoticeWidget-row' );
+
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.FooterNoticeWidget.parent.call( this, config );
+
+ if ( config.iconUrl ) {
+ $icon = $( '<div>' )
+ .addClass( 'mw-echo-ui-footerNoticeWidget-icon' )
+ .append( $( '<img>' ).attr( { src: config.iconUrl, width: 30, height: 30 } ) );
+
+ $row.append( $icon );
+ }
+
+ label = new OO.ui.LabelWidget( {
+ label: $( '<span>' ).append( $.parseHTML( config.message ) ).contents(),
+ classes: [ 'mw-echo-ui-footerNoticeWidget-label' ]
+ } );
+
+ dismissButton = new OO.ui.ButtonWidget( {
+ icon: 'close',
+ framed: false,
+ classes: [ 'mw-echo-ui-footerNoticeWidget-dismiss' ]
+ } );
+
+ // Events
+ dismissButton.connect( this, { click: 'onDismissButtonClick' } );
+
+ this.$element
+ .addClass( 'mw-echo-ui-footerNoticeWidget' )
+ .append(
+ $row
+ .append(
+ label.$element,
+ dismissButton.$element
+ )
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.FooterNoticeWidget, OO.ui.Widget );
+
+ /* Events */
+
+ /**
+ * The notice was dismissed.
+ *
+ * @event dismiss
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to dismiss button click.
+ *
+ * @fires dismiss
+ */
+ mw.echo.ui.FooterNoticeWidget.prototype.onDismissButtonClick = function () {
+ this.toggle( false );
+ this.emit( 'dismiss' );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.MenuItemWidget.js b/Echo/modules/ui/mw.echo.ui.MenuItemWidget.js
new file mode 100644
index 00000000..aa1219df
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.MenuItemWidget.js
@@ -0,0 +1,137 @@
+( function ( mw, $ ) {
+ /**
+ * Secondary menu item
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {string} [description] An optional description for the item
+ * @cfg {string} [icon] An optional icon for the item
+ * @cfg {boolean} [prioritized] The item is prioritized outside the
+ * popup menu.
+ */
+ mw.echo.ui.MenuItemWidget = function MwEchoUiMenuItemWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.MenuItemWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.dynamic = config.type === 'dynamic-action';
+ this.prioritized = !!config.prioritized;
+ this.messages = this.isDynamicAction() ?
+ config.actionData.messages :
+ {};
+
+ this.actionData = config.actionData || {};
+
+ // Optional description
+ this.descriptionLabel = new OO.ui.LabelWidget( {
+ classes: [ 'mw-echo-ui-menuItemWidget-content-description' ],
+ label: config.description || ''
+ } );
+ this.descriptionLabel.toggle( !this.prioritized && config.description );
+
+ // Build the option
+ this.$element
+ .addClass( 'mw-echo-ui-menuItemWidget' )
+ .toggleClass( 'mw-echo-ui-menuItemWidget-prioritized', this.prioritized )
+ .toggleClass( 'mw-echo-ui-menuItemWidget-dynamic-action', this.isDynamicAction() )
+ .append(
+ this.$icon
+ .addClass( 'mw-echo-ui-menuItemWidget-icon' ),
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-menuItemWidget-content' )
+ .append(
+ this.$label
+ .addClass( 'mw-echo-ui-menuItemWidget-content-label' ),
+ this.descriptionLabel.$element
+ )
+ );
+
+ if ( config.url && !this.isDynamicAction() ) {
+ this.hasLink = true;
+ this.$element.contents()
+ .wrapAll(
+ // HACK: Wrap the entire item with a link that takes
+ // the user to the primary url. This is not perfect,
+ // but it makes the behavior native to the browser rather
+ // than us listening to click events and opening new
+ // windows.
+ $( '<a>' )
+ .addClass( 'mw-echo-ui-menuItemWidget-linkWrapper' )
+ .attr( 'href', config.url )
+ .attr( 'title', config.tooltip )
+ );
+ }
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.MenuItemWidget, OO.ui.OptionWidget );
+ OO.mixinClass( mw.echo.ui.MenuItemWidget, OO.ui.mixin.IconElement );
+ OO.mixinClass( mw.echo.ui.MenuItemWidget, OO.ui.mixin.PendingElement );
+
+ /* Static Properties */
+
+ mw.echo.ui.MenuItemWidget.static.highlightable = false;
+ mw.echo.ui.MenuItemWidget.static.pressable = false;
+
+ /* Methods */
+
+ mw.echo.ui.MenuItemWidget.prototype.isSelectable = function () {
+ // If we have a link force selectability to false, otherwise defer to parent method
+ // Without a link (for dynamic actions or specific internal actions) we need this widget
+ // to be selectable so it emits the 'choose' event
+ return !this.hasLink && mw.echo.ui.MenuItemWidget.parent.prototype.isSelectable.apply( this, arguments );
+ };
+
+ /**
+ * Check whether this item is prioritized
+ *
+ * @return {boolean} Item is prioritized
+ */
+ mw.echo.ui.MenuItemWidget.prototype.isPrioritized = function () {
+ return this.prioritized;
+ };
+
+ /**
+ * Get the messages for the confirmation dialog
+ * We expect optionally two messages - title and description.
+ *
+ * NOTE: The messages are parsed as HTML. If user-input is expected
+ * please make sure to properly escape it.
+ *
+ * @return {Object} Messages for the confirmation dialog
+ * @return {string} return.title Title for the confirmation dialog
+ * @return {string} return.description Description for the confirmation dialog
+ */
+ mw.echo.ui.MenuItemWidget.prototype.getConfirmationMessages = function () {
+ return this.messages.confirmation;
+ };
+
+ /**
+ * Get the action data associated with this item
+ *
+ * @return {Object} Action data
+ */
+ mw.echo.ui.MenuItemWidget.prototype.getActionData = function () {
+ return this.actionData;
+ };
+
+ /**
+ * This item is a dynamic action
+ *
+ * @return {boolean} Item is a dynamic action
+ */
+ mw.echo.ui.MenuItemWidget.prototype.isDynamicAction = function () {
+ return this.dynamic;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.NotificationBadgeWidget.js b/Echo/modules/ui/mw.echo.ui.NotificationBadgeWidget.js
new file mode 100644
index 00000000..1bf9981e
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.NotificationBadgeWidget.js
@@ -0,0 +1,376 @@
+( function ( mw, $ ) {
+ /**
+ * Notification badge button widget for echo popup.
+ *
+ * @class
+ * @extends OO.ui.ButtonWidget
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo notifications controller
+ * @param {mw.echo.dm.ModelManager} manager Model manager
+ * @param {Object} [config] Configuration object
+ * @cfg {string|string[]} [type='message'] The type or array of types of
+ * notifications that are in this model. They can be 'alert', 'message' or
+ * an array of both. Defaults to 'message'
+ * @cfg {number} [numItems=0] The number of items that are in the button display
+ * @cfg {string} [badgeLabel=0] The initial label for the badge. This is the
+ * formatted version of the number of items in the badge.
+ * @cfg {boolean} [hasUnseen=false] Whether there are unseen items
+ * @cfg {number} [popupWidth=450] The width of the popup
+ * @cfg {string} [badgeIcon] Icon to use for the popup header
+ * @cfg {string} [href] URL the badge links to
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ */
+ mw.echo.ui.NotificationBadgeWidget = function MwEchoUiNotificationBadgeButtonPopupWidget( controller, manager, config ) {
+ var buttonFlags, allNotificationsButton, preferencesButton, footerButtonGroupWidget, $footer,
+ notice, adjustedTypeString;
+
+ config = config || {};
+ config.links = config.links || {};
+
+ // Parent constructor
+ mw.echo.ui.NotificationBadgeWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.$overlay = config.$overlay || this.$element;
+ // Create a menu overlay
+ this.$menuOverlay = $( '<div>' )
+ .addClass( 'mw-echo-ui-NotificationBadgeWidget-overlay-menu' );
+ this.$overlay.append( this.$menuOverlay );
+
+ // Controller
+ this.controller = controller;
+ this.manager = manager;
+
+ adjustedTypeString = this.controller.getTypeString() === 'message' ? 'notice' : this.controller.getTypeString();
+
+ // Properties
+ this.types = this.manager.getTypes();
+
+ this.numItems = config.numItems || 0;
+ this.hasRunFirstTime = false;
+
+ buttonFlags = [];
+ if ( config.hasUnseen ) {
+ buttonFlags.push( 'unseen' );
+ }
+
+ this.badgeButton = new mw.echo.ui.BadgeLinkWidget( {
+ convertedNumber: config.convertedNumber,
+ type: this.manager.getTypeString(),
+ numItems: this.numItems,
+ flags: buttonFlags,
+ // The following messages can be used here:
+ // tooltip-pt-notifications-alert
+ // tooltip-pt-notifications-notice
+ title: mw.msg( 'tooltip-pt-notifications-' + adjustedTypeString ),
+ href: config.href
+ } );
+
+ // Notifications list widget
+ this.notificationsWidget = new mw.echo.ui.NotificationsListWidget(
+ this.controller,
+ this.manager,
+ {
+ type: this.types,
+ $overlay: this.$menuOverlay,
+ animated: true
+ }
+ );
+
+ // Footer
+ allNotificationsButton = new OO.ui.ButtonWidget( {
+ icon: 'next',
+ label: mw.msg( 'echo-overlay-link' ),
+ href: config.links.notifications,
+ classes: [ 'mw-echo-ui-notificationBadgeButtonPopupWidget-footer-allnotifs' ]
+ } );
+
+ preferencesButton = new OO.ui.ButtonWidget( {
+ icon: 'advanced',
+ label: mw.msg( 'mypreferences' ),
+ href: config.links.preferences,
+ classes: [ 'mw-echo-ui-notificationBadgeButtonPopupWidget-footer-preferences' ]
+ } );
+
+ footerButtonGroupWidget = new OO.ui.ButtonGroupWidget( {
+ items: [ allNotificationsButton, preferencesButton ],
+ classes: [ 'mw-echo-ui-notificationBadgeButtonPopupWidget-footer-buttons' ]
+ } );
+ $footer = $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationBadgeButtonPopupWidget-footer' )
+ .append( footerButtonGroupWidget.$element );
+
+ // Footer notice
+ if (
+ mw.config.get( 'wgEchoShowSpecialPageInvitation' ) &&
+ !mw.user.options.get( 'echo-dismiss-special-page-invitation' )
+ ) {
+ notice = new mw.echo.ui.FooterNoticeWidget( {
+ // This is probably not the right way of doing this
+ iconUrl: mw.config.get( 'wgExtensionAssetsPath' ) + '/Echo/modules/icons/feedback.svg',
+ message: mw.message(
+ 'echo-popup-footer-special-page-invitation',
+ // Text
+ mw.msg( 'echo-popup-footer-special-page-invitation-link' ),
+ // Link
+ mw.util.getUrl( 'Special:Notifications' )
+ ).parse()
+ } );
+ // Event
+ notice.connect( this, { dismiss: 'onFooterNoticeDismiss' } );
+ // Prepend to the footer
+ $footer.prepend( notice.$element );
+ }
+
+ this.popup = new OO.ui.PopupWidget( {
+ $content: this.notificationsWidget.$element,
+ $footer: $footer,
+ width: config.popupWidth || 500,
+ autoClose: true,
+ containerPadding: 20,
+ // Also ignore clicks from the nested action menu items, that
+ // actually exist in the overlay
+ $autoCloseIgnore: this.$element.add( this.$menuOverlay ),
+ head: true,
+ // The following messages can be used here:
+ // echo-notification-alert-text-only
+ // echo-notification-notice-text-only
+ label: mw.msg(
+ 'echo-notification-' + adjustedTypeString +
+ '-text-only'
+ ),
+ classes: [ 'mw-echo-ui-notificationBadgeButtonPopupWidget-popup' ]
+ } );
+ // HACK: Add an icon to the popup head label
+ this.popupHeadIcon = new OO.ui.IconWidget( { icon: config.badgeIcon } );
+ this.popup.$head.prepend( this.popupHeadIcon.$element );
+
+ this.setPendingElement( this.popup.$head );
+
+ // Mark all as read button
+ this.markAllReadButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ label: mw.msg( 'echo-mark-all-as-read' ),
+ classes: [ 'mw-echo-ui-notificationsWidget-markAllReadButton' ]
+ } );
+
+ // Hide the close button
+ this.popup.closeButton.toggle( false );
+ // Add the 'mark all as read' button to the header
+ this.popup.$head.append( this.markAllReadButton.$element );
+ this.markAllReadButton.toggle( false );
+
+ // Events
+ this.markAllReadButton.connect( this, { click: 'onMarkAllReadButtonClick' } );
+ this.manager.connect( this, {
+ update: 'updateBadge'
+ } );
+ this.manager.getSeenTimeModel().connect( this, { update: 'onSeenTimeModelUpdate' } );
+ this.manager.getUnreadCounter().connect( this, { countChange: 'updateBadge' } );
+ this.popup.connect( this, { toggle: 'onPopupToggle' } );
+ this.badgeButton.connect( this, {
+ click: 'onBadgeButtonClick'
+ } );
+ this.notificationsWidget.connect( this, { modified: 'onNotificationsListModified' } );
+
+ this.$element
+ .prop( 'id', 'pt-notifications-' + adjustedTypeString )
+ // The following classes can be used here:
+ // mw-echo-ui-notificationBadgeButtonPopupWidget-alert
+ // mw-echo-ui-notificationBadgeButtonPopupWidget-message
+ .addClass(
+ 'mw-echo-ui-notificationBadgeButtonPopupWidget ' +
+ 'mw-echo-ui-notificationBadgeButtonPopupWidget-' + adjustedTypeString
+ )
+ .append(
+ this.badgeButton.$element,
+ this.popup.$element
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.NotificationBadgeWidget, OO.ui.Widget );
+ OO.mixinClass( mw.echo.ui.NotificationBadgeWidget, OO.ui.mixin.PendingElement );
+
+ /* Static properties */
+
+ mw.echo.ui.NotificationBadgeWidget.static.tagName = 'li';
+
+ /* Events */
+
+ /**
+ * @event allRead
+ * All notifications were marked as read
+ */
+
+ /**
+ * @event finishLoading
+ * Notifications have successfully finished being processed and are fully loaded
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to list widget modified event.
+ *
+ * This means the list's actual DOM was modified and we should make sure
+ * that the popup resizes itself.
+ */
+ mw.echo.ui.NotificationBadgeWidget.prototype.onNotificationsListModified = function () {
+ this.popup.clip();
+ };
+
+ mw.echo.ui.NotificationBadgeWidget.prototype.onFooterNoticeDismiss = function () {
+ // Clip again to recalculate height
+ this.popup.clip();
+
+ // Save the preference in general
+ new mw.Api().saveOption( 'echo-dismiss-special-page-invitation', 1 );
+ // Save the preference for this session
+ mw.user.options.set( 'echo-dismiss-special-page-invitation', 1 );
+ };
+
+ /**
+ * Respond to badge button click
+ */
+ mw.echo.ui.NotificationBadgeWidget.prototype.onBadgeButtonClick = function () {
+ this.popup.toggle();
+ };
+
+ /**
+ * Respond to SeenTime model update event
+ */
+ mw.echo.ui.NotificationBadgeWidget.prototype.onSeenTimeModelUpdate = function () {
+ this.updateBadgeSeenState( false );
+ };
+
+ /**
+ * Update the badge style to match whether it contains unseen notifications.
+ *
+ * @param {boolean} [hasUnseen=false] There are unseen notifications
+ */
+ mw.echo.ui.NotificationBadgeWidget.prototype.updateBadgeSeenState = function ( hasUnseen ) {
+ hasUnseen = hasUnseen === undefined ? false : !!hasUnseen;
+
+ this.badgeButton.setFlags( { unseen: !!hasUnseen } );
+ };
+
+ /**
+ * Update the badge state and label based on changes to the model
+ */
+ mw.echo.ui.NotificationBadgeWidget.prototype.updateBadge = function () {
+ var unreadCount, cappedUnreadCount, badgeLabel;
+
+ unreadCount = this.manager.getUnreadCounter().getCount();
+ cappedUnreadCount = this.manager.getUnreadCounter().getCappedNotificationCount( unreadCount );
+ cappedUnreadCount = mw.language.convertNumber( cappedUnreadCount );
+ badgeLabel = mw.message( 'echo-badge-count', mw.language.convertNumber( cappedUnreadCount ) ).text();
+
+ this.badgeButton.setLabel( badgeLabel );
+ this.badgeButton.setCount( unreadCount, badgeLabel );
+ // Update seen state only if the counter is 0
+ // so we don't run into inconsistencies and have an unseen state
+ // for the badge with 0 unread notifications
+ if ( unreadCount === 0 ) {
+ this.updateBadgeSeenState( false );
+ }
+
+ // Check if we need to display the 'mark all unread' button
+ this.markAllReadButton.toggle( this.manager.hasLocalUnread() );
+ };
+
+ /**
+ * Respond to 'mark all as read' button click
+ */
+ mw.echo.ui.NotificationBadgeWidget.prototype.onMarkAllReadButtonClick = function () {
+ // Log the click action
+ mw.echo.logger.logInteraction(
+ mw.echo.Logger.static.actions.markAllReadClick,
+ mw.echo.Logger.static.context.popup,
+ null, // Event id isn't relevant
+ this.manager.getTypeString() // The type of the list
+ );
+
+ this.controller.markLocalNotificationsRead();
+ };
+
+ /**
+ * Extend the response to button click so we can also update the notification list.
+ *
+ * @param {boolean} isVisible The popup is visible
+ * @fires finishLoading
+ */
+ mw.echo.ui.NotificationBadgeWidget.prototype.onPopupToggle = function ( isVisible ) {
+ var widget = this;
+
+ if ( this.promiseRunning ) {
+ return;
+ }
+
+ if ( !isVisible ) {
+ widget.notificationsWidget.resetInitiallyUnseenItems();
+ return;
+ }
+
+ // Log the click event
+ mw.echo.logger.logInteraction(
+ 'ui-badge-link-click',
+ mw.echo.Logger.static.context.badge,
+ null,
+ this.controller.getTypeString()
+ );
+
+ if ( this.hasRunFirstTime ) {
+ // HACK: Clippable doesn't resize the clippable area when
+ // it calculates the new size. Since the popup contents changed
+ // and the popup is "empty" now, we need to manually set its
+ // size to 1px so the clip calculations will resize it properly.
+ // See bug report: https://phabricator.wikimedia.org/T110759
+ this.popup.$clippable.css( 'height', '1px' );
+ this.popup.clip();
+ }
+
+ this.pushPending();
+ this.markAllReadButton.toggle( false );
+ this.promiseRunning = true;
+
+ // Always populate on popup open. The model and widget should handle
+ // the case where the promise is already underway.
+ this.controller.fetchLocalNotifications( this.hasRunFirstTime )
+ .then(
+ // Success
+ function () {
+ if ( widget.popup.isVisible() ) {
+ // Fire initialization hook
+ mw.hook( 'ext.echo.popup.onInitialize' ).fire( widget.manager.getTypeString(), widget.controller );
+
+ // Update seen time
+ return widget.controller.updateSeenTime();
+ }
+ },
+ // Failure
+ function ( errorObj ) {
+ if ( errorObj.errCode === 'notlogin-required' ) {
+ // Login required message
+ widget.notificationsWidget.resetLoadingOption( mw.msg( 'echo-notification-loginrequired' ) );
+ } else {
+ // Generic API failure message
+ widget.notificationsWidget.resetLoadingOption( mw.msg( 'echo-api-failure' ) );
+ }
+ }
+ )
+ .then( this.emit.bind( this, 'finishLoading' ) )
+ .always( function () {
+ widget.popup.clip();
+ // Pop pending
+ widget.popPending();
+ widget.promiseRunning = false;
+ } );
+ this.hasRunFirstTime = true;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.NotificationItemWidget.js b/Echo/modules/ui/mw.echo.ui.NotificationItemWidget.js
new file mode 100644
index 00000000..9dbebae4
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.NotificationItemWidget.js
@@ -0,0 +1,422 @@
+( function ( mw, $ ) {
+ /* global moment:false */
+ /**
+ * A base widget for displaying notification items.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo controller
+ * @param {mw.echo.dm.NotificationItem} model Notification item model
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ * @cfg {boolean} [bundle=false] This notification item is part of a bundle.
+ */
+ mw.echo.ui.NotificationItemWidget = function MwEchoUiNotificationItemWidget( controller, model, config ) {
+ var i, secondaryUrls, urlObj, linkButton, $icon, isOutsideMenu, echoMoment,
+ outsideMenuItemCounter = 0,
+ $message = $( '<div>' ).addClass( 'mw-echo-ui-notificationItemWidget-content-message' );
+
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.NotificationItemWidget.parent.call( this, $.extend( { data: model.getId() }, config ) );
+
+ this.controller = controller;
+ this.model = model;
+
+ this.$overlay = config.$overlay || this.$element;
+ this.bundle = !!config.bundle;
+
+ this.$content = $( '<div>' ).addClass( 'mw-echo-ui-notificationItemWidget-content' );
+ this.$actions = $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-content-actions' );
+
+ // Mark as read
+ this.markAsReadButton = new mw.echo.ui.ToggleReadCircleButtonWidget( {
+ framed: false,
+ title: mw.msg( 'echo-notification-markasread-tooltip' ),
+ classes: [ 'mw-echo-ui-notificationItemWidget-markAsReadButton' ],
+ markAsRead: !this.model.isRead()
+ } );
+
+ // Icon
+ if ( this.model.getIconURL() ) {
+ $icon = $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-icon' )
+ .append( $( '<img>' ).attr( 'src', this.model.getIconURL() ) );
+ }
+
+ // Content
+ $message.append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-content-message-header-wrapper' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-content-message-header' )
+ .append( this.model.getContentHeader() )
+ )
+ );
+ if ( !this.bundle && this.model.getContentBody() ) {
+ $message.append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-content-message-body' )
+ .append( this.model.getContentBody() )
+ // dir=auto has a similar effect to wrapping the content in <bdi>, but
+ // makes text-overflow: ellipsis; behave less strangely
+ .attr( 'dir', 'auto' )
+ );
+ }
+
+ // Actions menu
+ this.actionsButtonSelectWidget = new OO.ui.ButtonSelectWidget( {
+ classes: [ 'mw-echo-ui-notificationItemWidget-content-actions-buttons' ]
+ } );
+
+ // Popup menu
+ this.menuPopupButtonWidget = new mw.echo.ui.ActionMenuPopupWidget( {
+ framed: false,
+ icon: 'ellipsis',
+ $overlay: this.$overlay,
+ menuWidth: 200,
+ title: mw.msg( 'echo-notification-more-options-tooltip' ),
+ classes: [ 'mw-echo-ui-notificationItemWidget-content-actions-menu' ]
+ } );
+
+ // Timestamp
+ // We want to use extra-short timestamp strings; we change the locale
+ // to our echo-defined one and use that instead of the normal moment locale
+ echoMoment = moment.utc( this.model.getTimestamp() );
+ echoMoment.locale( 'echo-shortRelativeTime' );
+ echoMoment.local();
+
+ this.timestampWidget = new OO.ui.LabelWidget( {
+ classes: [ 'mw-echo-ui-notificationItemWidget-content-actions-timestamp' ],
+ // Get the time 'fromNow' without the suffix 'ago'
+ label: echoMoment.fromNow( true )
+ } );
+
+ // Build the actions line
+ if ( this.bundle ) {
+ // In a bundled item, the timestamp should go before the menu
+ this.$actions.append(
+ $( '<div>' )
+ // We are wrapping the actions in a 'row' div so that the
+ // internal pieces are also a table layout
+ .addClass( 'mw-echo-ui-notificationItemWidget-content-actions-row' )
+ .append(
+ this.actionsButtonSelectWidget.$element,
+ this.timestampWidget.$element,
+ this.menuPopupButtonWidget.$element
+ )
+ );
+ } else {
+ this.$actions.append(
+ this.actionsButtonSelectWidget.$element,
+ this.menuPopupButtonWidget.$element,
+ this.timestampWidget.$element
+ );
+ }
+
+ // Actions
+ secondaryUrls = this.model.getSecondaryUrls();
+ for ( i = 0; i < secondaryUrls.length; i++ ) {
+ urlObj = secondaryUrls[ i ];
+
+ // Items are placed outside the dotdotdot menu if they are
+ // prioritized explicitly, *except* for items inside a bundle
+ // (where all actions are inside the menu) or there are more than
+ // two prioritized actions (all others go into the menu)
+ isOutsideMenu = !this.bundle && urlObj.prioritized && outsideMenuItemCounter < mw.echo.config.maxPrioritizedActions;
+
+ linkButton = new mw.echo.ui.MenuItemWidget( {
+ type: urlObj.type,
+ actionData: urlObj.data,
+ icon: urlObj.icon || 'next',
+ label: urlObj.label,
+ tooltip: urlObj.tooltip,
+ description: urlObj.description,
+ url: urlObj.url,
+ prioritized: isOutsideMenu
+ } );
+
+ // Limit to 2 items outside the menu
+ if ( isOutsideMenu ) {
+ this.actionsButtonSelectWidget.addItems( [ linkButton ] );
+ outsideMenuItemCounter++;
+ } else {
+ this.menuPopupButtonWidget.getMenu().addItems( [ linkButton ] );
+ }
+ }
+
+ if ( this.bundle ) {
+ // In a bundle, we have table layout, so the icon is
+ // inserted into the content, and the 'mark as read'
+ // button is not floating, and should be at the end
+ this.$content.append(
+ $icon,
+ $message,
+ this.$actions,
+ this.markAsReadButton.$element
+ );
+ this.$element.append( this.$content );
+ } else {
+ this.$content.append(
+ this.markAsReadButton.$element,
+ $message,
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-content-table' )
+ .append( this.$actions )
+ );
+ this.$element.append( $icon, this.$content );
+ }
+
+ // Events
+ this.menuPopupButtonWidget.getMenu().connect( this, { choose: 'onPopupButtonWidgetChoose' } );
+ this.markAsReadButton.connect( this, { click: 'onMarkAsReadButtonClick' } );
+
+ this.$element
+ .addClass( 'mw-echo-ui-notificationItemWidget' )
+ .toggleClass( 'mw-echo-ui-notificationItemWidget-initiallyUnseen', !this.model.isSeen() && !this.bundle )
+ .toggleClass( 'mw-echo-ui-notificationItemWidget-bundled', this.bundle );
+
+ // Wrap the entire item with primary url
+ if ( this.model.getPrimaryUrl() ) {
+ this.$element.contents()
+ .wrapAll(
+ // HACK: Wrap the entire item with a link that takes
+ // the user to the primary url. This is not perfect,
+ // but it makes the behavior native to the browser rather
+ // than us listening to click events and opening new
+ // windows.
+ $( '<a>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-linkWrapper' )
+ .attr( 'href', this.model.getPrimaryUrl() )
+ .on( 'click', this.onPrimaryLinkClick.bind( this ) )
+ );
+ }
+ };
+
+ OO.inheritClass( mw.echo.ui.NotificationItemWidget, OO.ui.Widget );
+
+ /**
+ * Respond to primary link click.
+ * Override this in the descendents.
+ *
+ * @return {boolean} true
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.onPrimaryLinkClick = function () {
+ return true;
+ };
+
+ /**
+ * Manage a click on a dynamic secondary link.
+ * We can't know what the link intends us to do in the API, so we trust the 'apiParams'
+ * to tell the controller. When the link is clicked, we will pass the information on
+ * to the controller, which will manage whatever promise and action is needed.
+ *
+ * NOTE: The messages are parsed as HTML. If user-input is expected
+ * please make sure to properly escape it.
+ *
+ * @param {mw.echo.ui.MenuItemWidget} item The selected item
+ * @return {boolean} False to prevent the native event
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.onPopupButtonWidgetChoose = function ( item ) {
+ var actionData = item && item.getActionData(),
+ messages = item && item.getConfirmationMessages(),
+ widget = this;
+
+ // Send to controller
+ item.pushPending();
+ this.controller.performDynamicAction( actionData, this.getModel().getSource() )
+ .then( function () {
+ var $title = $( '<p>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-notify-title' )
+ .append( $.parseHTML( messages.title ) ),
+ $description = $( '<p>' )
+ .addClass( 'mw-echo-ui-notificationItemWidget-notify-description' )
+ .append( $.parseHTML( messages.description ) ),
+ $confirmation;
+
+ // Get rid of the button
+ item.disconnect( this );
+ if ( item.isPrioritized() ) {
+ widget.actionsButtonSelectWidget.removeItems( [ item ] );
+ } else {
+ // It's inside the popup menu
+ widget.menuPopupButtonWidget.getMenu().removeItems( [ item ] );
+ }
+
+ // Make sure to hide either piece if it is empty
+ $title.toggle( !!$title.text() );
+ $description.toggle( !!$description.text() );
+
+ // Display confirmation
+ $confirmation = $( '<div>' )
+ .append( $title, $description );
+
+ // Send to mw.notify
+ mw.notify( $confirmation );
+ } );
+
+ // Prevent the click propagation
+ return false;
+ };
+
+ /**
+ * Respond to mark as read button click
+ *
+ * @return {boolean} False to prevent the native event
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.onMarkAsReadButtonClick = function () {
+ // If we're marking read or unread, the notification was already seen.
+ // Remove the animation class
+ this.$element.removeClass( 'mw-echo-ui-notificationItemWidget-initiallyUnseen' );
+ this.markRead( !this.model.isRead() );
+ // Prevent propogation in case there's a link wrapping the content
+ // and the mark as read/unread button
+ return false;
+ };
+
+ /**
+ * Mark this notification as read
+ *
+ * @method
+ * @abstract
+ * @param {boolean} [isRead=true] Notification is marked as read
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.markRead = null;
+
+ /**
+ * Get the notification link
+ *
+ * @return {string} Notification link
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.getPrimaryUrl = function () {
+ return this.model.getPrimaryUrl();
+ };
+
+ /**
+ * Get the item id
+ *
+ * @return {number} Notification id
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.getTimestamp = function () {
+ return this.model.getTimestamp();
+ };
+
+ /**
+ * Get the notification Id
+ *
+ * @return {number} Notification id
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.getId = function () {
+ return this.model.getId();
+ };
+
+ /**
+ * Check whether this item is seen.
+ *
+ * @return {boolean} Item is seen
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.isSeen = function () {
+ return this.model.isSeen();
+ };
+
+ /**
+ * Check whether this item is read.
+ *
+ * @return {boolean} Item is read
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.isRead = function () {
+ return this.model.isRead();
+ };
+
+ /**
+ * Check whether this item is foreign.
+ *
+ * @return {boolean} Item is foreign
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.isForeign = function () {
+ return this.model.isForeign();
+ };
+
+ /**
+ * Toggle the function of the 'mark as read' buttons from 'mark as read' to 'mark as unread'
+ * and vice versa.
+ *
+ * @param {boolean} [showMarkAsRead] Show the 'mark as read' buttons
+ * - "false" means that the item is marked as read, whereby we show the user 'mark unread'
+ * buttons.
+ * - "true" means that the item is marked as unread and we show the user 'mark as read'
+ * buttons
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.toggleMarkAsReadButtons = function ( showMarkAsRead ) {
+ showMarkAsRead = showMarkAsRead !== undefined ? showMarkAsRead : !this.model.isRead();
+
+ this.markAsReadButton.toggleState( showMarkAsRead );
+ this.menuPopupButtonWidget.toggle( !this.menuPopupButtonWidget.getMenu().isEmpty() );
+ };
+
+ /**
+ * Toggle the read state of the widget
+ *
+ * @param {boolean} [read] The current read state. If not given, the state will
+ * become the opposite of its current state.
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.toggleRead = function ( read ) {
+ this.read = read !== undefined ? read : !this.read;
+
+ this.$element.toggleClass( 'mw-echo-ui-notificationItemWidget-unread', !this.read );
+ this.toggleMarkAsReadButtons( !this.read );
+ };
+
+ /**
+ * Toggle the seen state of the widget
+ *
+ * @param {boolean} [seen] The current seen state. If not given, the state will
+ * become the opposite of its current state.
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.toggleSeen = function ( seen ) {
+ this.seen = seen !== undefined ? seen : !this.seen;
+
+ this.$element
+ .toggleClass( 'mw-echo-ui-notificationItemWidget-unseen', !this.seen );
+ };
+
+ /**
+ * Get the model associated with this widget.
+ *
+ * @return {mw.echo.dm.NotificationItem} Item model
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.getModel = function () {
+ return this.model;
+ };
+
+ /**
+ * Disconnect events when widget is destroyed.
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.destroy = function () {
+ this.model.disconnect( this );
+ };
+
+ /**
+ * Remove the 'initiallyUnseen' class, which was only used for the
+ * unseen animation when the user has first seen it.
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.resetInitiallyUnseen = function () {
+ this.$element.removeClass( 'mw-echo-ui-notificationItemWidget-initiallyUnseen' );
+ };
+
+ /**
+ * Declares whether this widget is a cloned fake.
+ *
+ * @return {boolean} false
+ */
+ mw.echo.ui.NotificationItemWidget.prototype.isFake = function () {
+ return false;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.NotificationsInboxWidget.js b/Echo/modules/ui/mw.echo.ui.NotificationsInboxWidget.js
new file mode 100644
index 00000000..8c29cb76
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.NotificationsInboxWidget.js
@@ -0,0 +1,347 @@
+( function ( $, mw ) {
+ /**
+ * An inbox-type widget that encompases a dated notifications list with pagination
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo controller
+ * @param {mw.echo.dm.ModelManager} manager Model manager
+ * @param {Object} [config] Configuration object
+ * @cfg {number} [limit=25] Limit the number of notifications per page
+ * @cfg {jQuery} [$overlay] An overlay for the popup menus
+ */
+ mw.echo.ui.NotificationsInboxWidget = function MwEchoUiNotificationsInboxWidget( controller, manager, config ) {
+ var $main, $sidebar;
+
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.NotificationsInboxWidget.parent.call( this, config );
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.controller = controller;
+ this.manager = manager;
+
+ this.$overlay = config.$overlay || this.$element;
+ this.limit = config.limit || 25;
+
+ this.error = false;
+
+ // A notice or error message widget
+ this.noticeMessageWidget = new OO.ui.LabelWidget( {
+ classes: [ 'mw-echo-ui-notificationsInboxWidget-notice' ]
+ } );
+
+ // Notifications list
+ this.datedListWidget = new mw.echo.ui.DatedNotificationsWidget(
+ this.controller,
+ this.manager,
+ {
+ $overlay: this.$overlay,
+ animateSorting: false
+ }
+ );
+ this.setPendingElement( this.datedListWidget.$element );
+
+ // Pagination
+ this.topPaginationWidget = new mw.echo.ui.PaginationWidget(
+ this.manager.getPaginationModel(),
+ {
+ itemsPerPage: this.limit
+ }
+ );
+ this.bottomPaginationWidget = new mw.echo.ui.PaginationWidget(
+ this.manager.getPaginationModel(),
+ {
+ itemsPerPage: this.limit
+ }
+ );
+
+ // Settings menu
+ this.settingsMenu = new mw.echo.ui.SpecialHelpMenuWidget(
+ this.manager,
+ {
+ framed: true,
+ helpLink: config.helpLink,
+ prefLink: config.prefLink
+ }
+ );
+
+ // Filter by read state
+ this.readStateSelectWidget = new mw.echo.ui.ReadStateButtonSelectWidget();
+
+ // Sidebar filters
+ this.xwikiUnreadWidget = new mw.echo.ui.CrossWikiUnreadFilterWidget(
+ this.controller,
+ this.manager.getFiltersModel()
+ );
+
+ // Events
+ this.readStateSelectWidget.connect( this, { filter: 'onReadStateFilter' } );
+ this.xwikiUnreadWidget.connect( this, { filter: 'onSourcePageFilter' } );
+ this.manager.connect( this, {
+ modelItemUpdate: 'updatePaginationLabels',
+ localCountChange: 'updatePaginationLabels'
+ } );
+ this.manager.getFiltersModel().connect( this, { update: 'updateReadStateSelectWidget' } );
+ this.manager.getPaginationModel().connect( this, { update: 'updatePaginationLabels' } );
+ this.topPaginationWidget.connect( this, { change: 'populateNotifications' } );
+ this.bottomPaginationWidget.connect( this, { change: 'populateNotifications' } );
+ this.settingsMenu.connect( this, { markAllRead: 'onSettingsMarkAllRead' } );
+ $( window ).on( 'scroll resize', this.onWindowScroll.bind( this ) );
+
+ this.topPaginationWidget.setDisabled( true );
+ this.bottomPaginationWidget.setDisabled( true );
+
+ this.$topToolbar =
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-top' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-row' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-readState' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
+ .append( this.readStateSelectWidget.$element ),
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-cell-placeholder' ),
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-pagination' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
+ .append( this.topPaginationWidget.$element ),
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-settings' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
+ .append( this.settingsMenu.$element )
+ )
+ );
+
+ this.$toolbarWrapper =
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-toolbarWrapper' )
+ .append( this.$topToolbar );
+
+ $sidebar = $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-sidebar' )
+ .append( this.xwikiUnreadWidget.$element );
+
+ $main = $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-main' )
+ .append(
+ this.$toolbarWrapper,
+ this.noticeMessageWidget.$element,
+ this.datedListWidget.$element
+ );
+
+ this.$element
+ .addClass( 'mw-echo-ui-notificationsInboxWidget' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-row' )
+ .append(
+ $sidebar
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-cell' ),
+ $main
+ .addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
+ )
+ );
+
+ this.updateReadStateSelectWidget();
+ this.xwikiUnreadWidget.populateSources();
+ this.populateNotifications();
+
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.NotificationsInboxWidget, OO.ui.Widget );
+ OO.mixinClass( mw.echo.ui.NotificationsInboxWidget, OO.ui.mixin.PendingElement );
+
+ /* Methods */
+
+ /**
+ * Respond to filters update
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.updateReadStateSelectWidget = function () {
+ this.readStateSelectWidget
+ .getItemFromData( this.manager.getFiltersModel().getReadState() )
+ .setSelected( true );
+ };
+
+ /**
+ * Update pagination messages
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.updatePaginationLabels = function () {
+ this.resetMessageLabel();
+ // Update the pagination label
+ this.topPaginationWidget.updateLabel();
+ this.bottomPaginationWidget.updateLabel();
+ };
+
+ /**
+ * Respond to mark all read for selected wiki
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.onSettingsMarkAllRead = function () {
+ this.pushPending();
+ this.controller.markAllRead()
+ .always( this.popPending.bind( this ) );
+ };
+
+ /**
+ * Respond to unread page filter
+ *
+ * @param {string} source Source symbolic name
+ * @param {string} page Page name
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.onSourcePageFilter = function ( source, page ) {
+ this.controller.setFilter( 'sourcePage', source, page );
+ this.populateNotifications();
+ };
+
+ /**
+ * Respond to read state filter event
+ *
+ * @param {string} readState Read state 'all', 'read' or 'unread'
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.onReadStateFilter = function ( readState ) {
+ this.controller.setFilter( 'readState', readState );
+ this.populateNotifications();
+ };
+
+ /**
+ * Populate the notifications list
+ *
+ * @param {string} [direction] Direction to fetch from. 'prev' for previous page
+ * or 'next' for the next page. If not given, the first page of results will be fetched.
+ * @return {jQuery.Promise} A promise that is resolved when the results
+ * have been fetched.
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.populateNotifications = function ( direction ) {
+ var fetchPromise,
+ widget = this;
+
+ if ( direction === 'prev' ) {
+ fetchPromise = this.controller.fetchPrevPageByDate();
+ } else if ( direction === 'next' ) {
+ fetchPromise = this.controller.fetchNextPageByDate();
+ } else {
+ fetchPromise = this.controller.fetchFirstPageByDate();
+ }
+
+ this.pushPending();
+ this.error = false;
+ return fetchPromise
+ .then(
+ // Success
+ function () {
+ // Fire initialization hook
+ mw.hook( 'ext.echo.special.onInitialize' ).fire( widget.controller.manager.getTypeString(), widget.controller );
+
+ widget.popPending();
+ // Update seen time
+ widget.controller.updateSeenTime();
+ },
+ // Failure
+ function ( errObj ) {
+ var msg;
+ if ( errObj.errCode === 'notlogin-required' ) {
+ // Login required message
+ msg = mw.msg( 'echo-notification-loginrequired' );
+ } else {
+ // Generic API failure message
+ msg = mw.msg( 'echo-api-failure' );
+ }
+ widget.error = true;
+ widget.noticeMessageWidget.setLabel( msg );
+ widget.displayMessage( true );
+ }
+ )
+ .always( this.popPending.bind( this ) );
+ };
+
+ /**
+ * Extend the pushPending method to disable UI elements
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.pushPending = function () {
+ this.noticeMessageWidget.toggle( false );
+ this.topPaginationWidget.setDisabled( true );
+ this.bottomPaginationWidget.setDisabled( true );
+
+ // Mixin method
+ OO.ui.mixin.PendingElement.prototype.pushPending.call( this );
+ };
+
+ /**
+ * Extend the popPending method to enable UI elements
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.popPending = function () {
+ if ( !this.error ) {
+ this.resetMessageLabel();
+ }
+
+ this.topPaginationWidget.setDisabled( false );
+ this.bottomPaginationWidget.setDisabled( false );
+
+ // Mixin method
+ OO.ui.mixin.PendingElement.prototype.popPending.call( this );
+ };
+
+ /**
+ * Reset the the text of the error message that displays in place of the list
+ * in case the list is empty.
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.resetMessageLabel = function () {
+ var label,
+ count = this.manager.getPaginationModel().getCurrentPageItemCount();
+
+ if ( count === 0 ) {
+ label = this.manager.getFiltersModel().getReadState() === 'all' ?
+ mw.msg( 'echo-notification-placeholder' ) :
+ mw.msg( 'echo-notification-placeholder-filters' );
+
+ this.noticeMessageWidget.setLabel( label );
+ }
+
+ this.displayMessage( count === 0 );
+ };
+
+ /**
+ * Display the error/notice message instead of the notifications list or vise versa.
+ *
+ * @private
+ * @param {boolean} displayMessage Display error message
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.displayMessage = function ( displayMessage ) {
+ this.noticeMessageWidget.toggle( displayMessage );
+ this.datedListWidget.toggle( !displayMessage );
+ };
+
+ /**
+ * Respond to window scroll
+ */
+ mw.echo.ui.NotificationsInboxWidget.prototype.onWindowScroll = function () {
+ var scrollTop = $( window ).scrollTop(),
+ isScrolledDown = scrollTop >= this.$topToolbar.parent().offset().top;
+
+ // Fix the widget to the top when we scroll down below its original
+ // location
+ this.$topToolbar.toggleClass(
+ 'mw-echo-ui-notificationsInboxWidget-main-toolbar-affixed',
+ isScrolledDown
+ );
+ if ( isScrolledDown ) {
+ // Copy width from parent, width: 100% doesn't do what we want when
+ // position: fixed; is set
+ this.$topToolbar.css( 'width', this.$topToolbar.parent().width() );
+ } else {
+ // Unset width when we no longer have position: fixed;
+ this.$topToolbar.css( 'width', '' );
+ }
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.NotificationsListWidget.js b/Echo/modules/ui/mw.echo.ui.NotificationsListWidget.js
new file mode 100644
index 00000000..14348d5f
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.NotificationsListWidget.js
@@ -0,0 +1,244 @@
+( function ( mw, $ ) {
+ /**
+ * Notifications list widget.
+ * All of its items must be of the mw.echo.ui.NotificationItem type.
+ *
+ * @class
+ * @extends mw.echo.ui.SortedListWidget
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo notifications controller
+ * @param {mw.echo.dm.ModelManager} manager Model manager
+ * @param {Object} [config] Configuration object
+ * marked as read when they are seen.
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ */
+ mw.echo.ui.NotificationsListWidget = function MwEchoUiNotificationsListWidget( controller, manager, config ) {
+ config = config || {};
+ // Parent constructor
+ mw.echo.ui.NotificationsListWidget.parent.call(
+ this,
+ // Sorting callback
+ function ( a, b ) {
+ if ( !a.isRead() && b.isRead() ) {
+ return -1; // Unread items are always above read items
+ } else if ( a.isRead() && !b.isRead() ) {
+ return 1;
+ } else if ( !a.isForeign() && b.isForeign() ) {
+ return -1;
+ } else if ( a.isForeign() && !b.isForeign() ) {
+ return 1;
+ }
+
+ // Reverse sorting
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+
+ // Fallback on IDs
+ return b.getId() - a.getId();
+ },
+ config
+ );
+
+ // Initialize models
+ this.controller = controller;
+ this.manager = manager;
+ this.models = {};
+
+ // Properties
+ this.$overlay = config.$overlay || this.$element;
+ this.timestamp = config.timestamp || 0;
+
+ // Dummy 'loading' option widget
+ this.loadingOptionWidget = new mw.echo.ui.PlaceholderItemWidget();
+
+ this.resetLoadingOption();
+
+ this.manager.connect( this, {
+ update: 'resetDataFromModel',
+ discard: 'onModelManagerDiscard'
+ } );
+
+ this.$element
+ .addClass( 'mw-echo-ui-notificationsListWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.NotificationsListWidget, mw.echo.ui.SortedListWidget );
+
+ /* Events */
+
+ /**
+ * @event modified
+ *
+ * The content of this list has changed.
+ * This event is to state that not only has the content changed
+ * but the actual DOM has been manipulated.
+ */
+
+ /* Methods */
+
+ mw.echo.ui.NotificationsListWidget.prototype.onModelManagerDiscard = function ( modelName ) {
+ var i,
+ items = this.getItems();
+
+ // For the moment, this is only relevant for xwiki bundles.
+ // Local single items will not get their entire model removed, but
+ // local bundles may - when that happens, the condition below should
+ // also deal with local bundles and removing them specifically
+ if ( modelName === 'xwiki' ) {
+ for ( i = 0; i < items.length; i++ ) {
+ if ( items[ i ] instanceof mw.echo.ui.CrossWikiNotificationItemWidget ) {
+ this.removeItems( [ items[ i ] ] );
+ this.checkForEmptyNotificationsList();
+ return;
+ }
+ }
+ }
+
+ this.emit( 'modified' );
+ };
+
+ /**
+ * Respond to model manager update event.
+ * This event means we are repopulating the entire list and the
+ * associated models within it.
+ *
+ * @param {Object} models Object of new models to populate the
+ * list.
+ * @fires modified
+ */
+ mw.echo.ui.NotificationsListWidget.prototype.resetDataFromModel = function ( models ) {
+ var i, modelId, model, subItems, subItem, widget,
+ itemWidgets = [],
+ $elements = $();
+
+ // Detach all attached models
+ for ( modelId in this.models ) {
+ this.detachModel( modelId );
+ }
+
+ // Attach and process new models
+ for ( modelId in models ) {
+ model = models[ modelId ];
+ this.attachModel( modelId, model );
+
+ // Build widgets based on the data in the model
+ if ( model.isGroup() ) {
+ if ( model.isForeign() ) {
+ // One Widget to Rule Them All
+ widget = new mw.echo.ui.CrossWikiNotificationItemWidget(
+ this.controller,
+ model,
+ {
+ $overlay: this.$overlay,
+ animateSorting: this.animated
+ }
+ );
+ } else {
+ // local bundle
+ widget = new mw.echo.ui.BundleNotificationItemWidget(
+ this.controller,
+ model,
+ {
+ $overlay: this.$overlay,
+ bundle: false,
+ animateSorting: this.animated
+ }
+ );
+ }
+ itemWidgets.push( widget );
+ $elements = $elements.add( widget.$element );
+ } else {
+ subItems = model.getItems();
+ // Separate widgets per item
+ for ( i = 0; i < subItems.length; i++ ) {
+ subItem = subItems[ i ];
+ widget = new mw.echo.ui.SingleNotificationItemWidget(
+ this.controller,
+ subItem,
+ {
+ $overlay: this.$overlay,
+ bundle: false
+ }
+ );
+ itemWidgets.push( widget );
+ $elements = $elements.add( widget.$element );
+ }
+ }
+ }
+
+ // Reset the current items and re-add the new item widgets
+ this.clearItems();
+
+ // fire render hook
+ mw.hook( 'ext.echo.notifications.beforeRender' ).fire( this.$element, $elements );
+
+ this.addItems( itemWidgets );
+
+ this.checkForEmptyNotificationsList();
+
+ this.emit( 'modified' );
+ };
+
+ /**
+ * Attach a model to the widget
+ *
+ * @param {string} modelId Symbolic name for the model
+ * @param {mw.echo.dm.SortedList} model Notifications list model
+ */
+ mw.echo.ui.NotificationsListWidget.prototype.attachModel = function ( modelId, model ) {
+ this.models[ modelId ] = model;
+ };
+
+ /**
+ * Detach a model from the widget
+ *
+ * @param {string} modelId Notifications list model
+ */
+ mw.echo.ui.NotificationsListWidget.prototype.detachModel = function ( modelId ) {
+ this.models[ modelId ].disconnect( this );
+ delete this.models[ modelId ];
+ };
+
+ /**
+ * Reset the loading 'dummy' option widget
+ *
+ * @param {string} [label] Label for the option widget
+ * @param {string} [link] Link for the option widget
+ * @fires modified
+ */
+ mw.echo.ui.NotificationsListWidget.prototype.resetLoadingOption = function ( label, link ) {
+ this.loadingOptionWidget.setLabel( label || '' );
+ this.loadingOptionWidget.setLink( link || '' );
+ if ( this.isEmpty() ) {
+ this.addItems( [ this.loadingOptionWidget ] );
+ }
+ this.emit( 'modified' );
+ };
+
+ /**
+ * Check if the list of notifications is empty and udpate the placeholder
+ * widget as needed.
+ */
+ mw.echo.ui.NotificationsListWidget.prototype.checkForEmptyNotificationsList = function () {
+ this.resetLoadingOption( this.isEmpty() ? mw.msg( 'echo-notification-placeholder' ) : '' );
+ };
+
+ /**
+ * Reset the 'initiallyUnseen' state of all items
+ */
+ mw.echo.ui.NotificationsListWidget.prototype.resetInitiallyUnseenItems = function () {
+ var i,
+ itemWidgets = this.getItems();
+
+ for ( i = 0; i < itemWidgets.length; i++ ) {
+ itemWidgets[ i ].resetInitiallyUnseen();
+ }
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.NotificationsWrapper.js b/Echo/modules/ui/mw.echo.ui.NotificationsWrapper.js
new file mode 100644
index 00000000..8ea1405a
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.NotificationsWrapper.js
@@ -0,0 +1,83 @@
+( function ( mw ) {
+ /**
+ * Wrapper for the notifications widget, for view outside the popup.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo controller
+ * @param {mw.echo.dm.ModelManager} model Notifications model manager
+ * @param {Object} [config] Configuration object
+ */
+ mw.echo.ui.NotificationsWrapper = function MwEchoUiNotificationsWrapper( controller, model, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.NotificationsWrapper.parent.call( this, config );
+
+ // Mixin constructor
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.controller = controller;
+ this.model = model;
+
+ this.notificationsWidget = new mw.echo.ui.NotificationsListWidget(
+ this.controller,
+ this.model,
+ {
+ $overlay: config.$overlay,
+ types: this.controller.getTypes(),
+ label: mw.msg( 'notifications' ),
+ icon: 'bell'
+ }
+ );
+
+ // Initialize
+ this.$element
+ .addClass( 'mw-echo-notificationsWrapper' )
+ .append( this.notificationsWidget.$element );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.NotificationsWrapper, OO.ui.Widget );
+ OO.mixinClass( mw.echo.ui.NotificationsWrapper, OO.ui.mixin.PendingElement );
+
+ /* Events */
+
+ /**
+ * @event finishLoading
+ * Notifications have successfully finished being processed and are fully loaded
+ */
+
+ /* Methods */
+
+ /**
+ * Populate the notifications panel
+ *
+ * @return {jQuery.Promise} A promise that is resolved when all notifications
+ * were fetched from the API and added to the model and UI.
+ */
+ mw.echo.ui.NotificationsWrapper.prototype.populate = function () {
+ var widget = this;
+
+ this.pushPending();
+ return this.controller.fetchLocalNotifications( true )
+ .then( null, function ( errorObj ) {
+ if ( errorObj.errCode === 'notlogin-required' ) {
+ // Login required message
+ widget.notificationsWidget.resetLoadingOption( mw.msg( 'echo-notification-loginrequired' ) );
+ } else {
+ // Generic API failure message
+ widget.notificationsWidget.resetLoadingOption( mw.msg( 'echo-api-failure' ) );
+ }
+ } )
+ .always( function () {
+ widget.popPending();
+ widget.emit( 'finishLoading' );
+ widget.promiseRunning = false;
+ } );
+ };
+}( mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.PageFilterWidget.js b/Echo/modules/ui/mw.echo.ui.PageFilterWidget.js
new file mode 100644
index 00000000..710e919c
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.PageFilterWidget.js
@@ -0,0 +1,156 @@
+( function ( $, mw ) {
+ /**
+ * A widget that displays wikis and their pages to choose a filter
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ *
+ * @constructor
+ * @param {mw.echo.dm.FiltersModel} filterModel Filters model
+ * @param {string} source Symbolic name for the source
+ * @param {Object} [config] Configuration object
+ * @cfg {string} [title] The title of this page group, usually
+ * the name of the wiki that the pages belong to
+ * @cfg {number} [unreadCount] Number of unread notifications
+ * @cfg {number} [initialSelection] The page title of the option to select initially
+ */
+ mw.echo.ui.PageFilterWidget = function MwEchoUiPageFilterWidget( filterModel, source, config ) {
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.PageFilterWidget.parent.call( this, config );
+
+ this.model = filterModel;
+ this.source = source;
+ // This is to be able to fetch and recognize this widget
+ // according to its source. The source is, in this case,
+ // unique per filter widget.
+ this.data = this.source;
+ this.totalCount = config.unreadCount || this.model.getSourceTotalCount( this.source );
+
+ this.initialSelection = config.initialSelection;
+
+ // Title option
+ this.title = new mw.echo.ui.PageNotificationsOptionWidget( {
+ label: config.title,
+ title: config.title,
+ count: this.totalCount,
+ isCapped: true,
+ data: null,
+ classes: [ 'mw-echo-ui-pageFilterWidget-title' ]
+ } );
+
+ // Initialization
+ this.populateDataFromModel();
+ this.$element
+ .addClass( 'mw-echo-ui-pageFilterWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.PageFilterWidget, OO.ui.SelectWidget );
+
+ /**
+ * Set the total count of this group
+ *
+ * @return {number} Total count
+ */
+ mw.echo.ui.PageFilterWidget.prototype.getTotalCount = function () {
+ return this.totalCount;
+ };
+
+ /**
+ * Populate the widget from the model
+ */
+ mw.echo.ui.PageFilterWidget.prototype.populateDataFromModel = function () {
+ var title, widget, isUserPage,
+ optionWidgets = [],
+ sourcePages = this.model.getSourcePages( this.source );
+
+ for ( title in sourcePages ) {
+ isUserPage = sourcePages[ title ].ns === mw.config.get( 'wgNamespaceIds' ).user;
+ widget = new mw.echo.ui.PageNotificationsOptionWidget( {
+ label: isUserPage ? sourcePages[ title ].unprefixed : title,
+ title: isUserPage ? sourcePages[ title ].unprefixed : title,
+ icon: isUserPage ? 'userAvatar' : 'article',
+ count: sourcePages[ title ].count,
+ data: title,
+ classes: [ 'mw-echo-ui-pageFilterWidget-page' ]
+ } );
+ optionWidgets.push( widget );
+
+ if ( this.initialSelection === title ) {
+ widget.setSelected( true );
+ }
+ }
+
+ this.setItems( optionWidgets );
+ };
+
+ /**
+ * Get the source associated with this filter
+ *
+ * @return {string} Source symbolic name
+ */
+ mw.echo.ui.PageFilterWidget.prototype.getSource = function () {
+ return this.source;
+ };
+
+ /**
+ * Get the title item
+ *
+ * @return {mw.echo.ui.PageNotificationsOptionWidget} Page title item
+ */
+ mw.echo.ui.PageFilterWidget.prototype.getTitleItem = function () {
+ return this.title;
+ };
+
+ /**
+ * Set the page items in this widget, in order
+ *
+ * @param {mw.echo.ui.PageNotificationsOptionWidget[]} items Item widgets to order and insert
+ */
+ mw.echo.ui.PageFilterWidget.prototype.setItems = function ( items ) {
+ var i, index;
+
+ this.clearItems();
+ for ( i = 0; i < items.length; i++ ) {
+ index = this.findInsertionIndex( items[ i ] );
+ this.addItems( [ items[ i ] ], index );
+ }
+
+ // Add the title on top
+ this.addItems( [ this.title ], 0 );
+ };
+
+ /**
+ * Find the proper insertion index for ordering when inserting items
+ *
+ * @private
+ * @param {mw.echo.ui.PageNotificationsOptionWidget} item Item widget
+ * @return {number} Insertion index
+ */
+ mw.echo.ui.PageFilterWidget.prototype.findInsertionIndex = function ( item ) {
+ var widget = this;
+
+ return OO.binarySearch(
+ this.items,
+ function ( otherItem ) {
+ return widget.sortingFunction( item, otherItem );
+ },
+ true
+ );
+ };
+
+ /**
+ * Sorting function for item insertion
+ *
+ * @private
+ * @param {mw.echo.ui.PageNotificationsOptionWidget} item Item widget
+ * @param {mw.echo.ui.PageNotificationsOptionWidget} otherItem Another item widget
+ * @return {number} Ordering value
+ */
+ mw.echo.ui.PageFilterWidget.prototype.sortingFunction = function ( item, otherItem ) {
+ return Number( otherItem.getCount() ) - Number( item.getCount() );
+ };
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.PageNotificationsOptionWidget.js b/Echo/modules/ui/mw.echo.ui.PageNotificationsOptionWidget.js
new file mode 100644
index 00000000..a4ac6bd7
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.PageNotificationsOptionWidget.js
@@ -0,0 +1,96 @@
+( function ( $, mw ) {
+ /**
+ * An option widget for the page filter in PageFilterWidget
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {number} [count] Number of unread notifications
+ * @cfg {boolean} [isCapped] The count for this widget is capped
+ */
+ mw.echo.ui.PageNotificationsOptionWidget = function MwEchoUiPageNotificationsOptionWidget( config ) {
+ var countLabel;
+
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.PageNotificationsOptionWidget.parent.call( this, config );
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.TitledElement.call( this, config );
+
+ this.$label
+ .addClass( 'mw-echo-ui-pageNotificationsOptionWidget-title-label' );
+
+ this.count = config.count !== undefined ? config.count : 0;
+
+ countLabel = mw.language.convertNumber( this.count );
+ countLabel = config.isCapped ?
+ mw.msg( 'echo-badge-count', countLabel ) : countLabel;
+
+ this.unreadCountLabel = new OO.ui.LabelWidget( {
+ classes: [ 'mw-echo-ui-pageNotificationsOptionWidget-label-count' ],
+ label: countLabel
+ } );
+
+ // Initialization
+ this.$element
+ .addClass( 'mw-echo-ui-pageNotificationsOptionWidget' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-pageNotificationsOptionWidget-count' )
+ .append( this.unreadCountLabel.$element ),
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-pageNotificationsOptionWidget-title' )
+ .append( this.$label )
+ );
+
+ if ( this.getIcon() ) {
+ this.$element.prepend(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-pageNotificationsOptionWidget-icon' )
+ .append( this.$icon )
+ );
+ }
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.PageNotificationsOptionWidget, OO.ui.OptionWidget );
+ OO.mixinClass( mw.echo.ui.PageNotificationsOptionWidget, OO.ui.mixin.IconElement );
+ OO.mixinClass( mw.echo.ui.PageNotificationsOptionWidget, OO.ui.mixin.TitledElement );
+
+ /**
+ * Get the page count
+ *
+ * @return {number} Page count
+ */
+ mw.echo.ui.PageNotificationsOptionWidget.prototype.getCount = function () {
+ return this.count;
+ };
+
+ mw.echo.ui.PageNotificationsOptionWidget.prototype.setPressed = function ( state ) {
+ mw.echo.ui.PageNotificationsOptionWidget.parent.prototype.setPressed.call( this, state );
+ if ( this.pressed ) {
+ this.setFlags( 'progressive' );
+ } else if ( !this.selected ) {
+ this.clearFlags();
+ }
+ return this;
+ };
+
+ mw.echo.ui.PageNotificationsOptionWidget.prototype.setSelected = function ( state ) {
+ mw.echo.ui.PageNotificationsOptionWidget.parent.prototype.setSelected.call( this, state );
+ if ( this.selected ) {
+ this.setFlags( 'progressive' );
+ } else {
+ this.clearFlags();
+ }
+ return this;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.PaginationWidget.js b/Echo/modules/ui/mw.echo.ui.PaginationWidget.js
new file mode 100644
index 00000000..0a3208e3
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.PaginationWidget.js
@@ -0,0 +1,179 @@
+( function ( $, mw ) {
+ /**
+ * A pagination widget allowing the user to go forward, backwards,
+ * and after a couple of pages, go back to home.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.echo.dm.PaginationModel} paginationModel Pagination model
+ * @param {Object} [config] Configuration object
+ * @cfg {number} [itemsPerPage=25] Number of items per page
+ * @cfg {number} [showFirstButton=true] Show a button that allows the user
+ * to go back to the first page.
+ * @cfg {number} [showFirstButtonAfter=2] Pick the number of pages that it
+ * takes to show the button that takes the user back to the first set
+ * of results.
+ * @cfg {string} [startButtonLabel] The label used for the start button
+ */
+ mw.echo.ui.PaginationWidget = function MwEchoUiPaginationWidget( paginationModel, config ) {
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.PaginationWidget.parent.call( this, config );
+
+ this.model = paginationModel;
+
+ this.showFirstButton = config.showFirstButton === undefined ? true : !!config.showFirstButton;
+ this.showFirstButtonAfter = config.showFirstButtonAfter || 2;
+ this.itemsPerPage = config.itemsPerPage || 25;
+
+ // Pagination elements
+ this.labelWidget = new OO.ui.LabelWidget( {
+ classes: [ 'mw-echo-ui-paginationWidget-label' ]
+ } );
+
+ this.startButton = new OO.ui.ButtonWidget( {
+ classes: [ 'mw-echo-ui-paginationWidget-start' ],
+ label: config.startButtonLabel || mw.msg( 'notification-timestamp-today' ),
+ data: 'start'
+ } );
+
+ this.dirSelectWidget = new OO.ui.ButtonSelectWidget( {
+ classes: [ 'mw-echo-ui-paginationWidget-direction' ],
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ icon: 'previous',
+ data: 'prev'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ icon: 'next',
+ data: 'next'
+ } )
+ ]
+ } );
+
+ // Events
+ this.startButton.connect( this, { click: [ 'emit', 'change', 'start' ] } );
+ this.dirSelectWidget.connect( this, { choose: 'onDirSelectWidgetChoose' } );
+ this.model.connect( this, { update: 'updateWidgetState' } );
+
+ // Initialization
+ this.updateWidgetState();
+ this.$element
+ .addClass( 'mw-echo-ui-paginationWidget' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-paginationWidget-row' )
+ .append(
+ this.labelWidget.$element,
+ this.startButton.$element,
+ this.dirSelectWidget.$element
+ )
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.PaginationWidget, OO.ui.Widget );
+
+ /* Events */
+
+ /**
+ * @event change
+ * @param {string} direction Direction of movement 'prev',
+ * 'next' or 'start'
+ *
+ * Pagination changed
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to dir select widget choose event
+ *
+ * @param {OO.ui.ButtonOptionWidget} item Chosen button
+ * @fires change
+ */
+ mw.echo.ui.PaginationWidget.prototype.onDirSelectWidgetChoose = function ( item ) {
+ var dir = item && item.getData();
+
+ if ( dir ) {
+ this.emit( 'change', dir );
+ item.setSelected( false );
+ }
+ };
+
+ /**
+ * Update the state - disabled and visibility - of the sub widgets.
+ */
+ mw.echo.ui.PaginationWidget.prototype.updateWidgetState = function () {
+ this.dirSelectWidget.getItemFromData( 'prev' )
+ .setDisabled( this.isDisabled() || !this.model.hasPrevPage() );
+ this.dirSelectWidget.getItemFromData( 'next' )
+ .setDisabled( this.isDisabled() || !this.model.hasNextPage() );
+
+ this.startButton.toggle(
+ !this.isDisabled() &&
+ this.model.getCurrPageIndex() >= this.showFirstButtonAfter
+ );
+
+ // Only show pagination buttons if there's anywhere to go
+ this.dirSelectWidget.toggle( this.model.hasPrevPage() || this.model.hasNextPage() );
+
+ // Update label text and visibility
+ this.updateLabel();
+ this.labelWidget.toggle( !this.isDisabled() );
+ };
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Set the 'disabled' state of the widget.
+ *
+ * @param {boolean} disabled Disable widget
+ * @chainable
+ */
+ mw.echo.ui.PaginationWidget.prototype.setDisabled = function ( disabled ) {
+ // Parent
+ mw.echo.ui.PaginationWidget.parent.prototype.setDisabled.call( this, disabled );
+
+ if (
+ this.dirSelectWidget &&
+ this.startButton &&
+ this.labelWidget
+ ) {
+ this.updateWidgetState();
+ }
+
+ return this;
+ };
+
+ /**
+ * Update the pagination label according to the page number, the amount of notifications
+ * per page, and the number of notifications on the current page.
+ */
+ mw.echo.ui.PaginationWidget.prototype.updateLabel = function () {
+ var label,
+ itemsInPage = this.model.getCurrentPageItemCount(),
+ firstNotifNum = this.model.getCurrPageIndex() * this.itemsPerPage,
+ lastNotifNum = firstNotifNum + itemsInPage;
+
+ if ( itemsInPage === 0 ) {
+ label = '';
+ } else if ( !this.model.hasPrevPage() && !this.model.hasNextPage() ) {
+ label = mw.msg(
+ 'echo-specialpage-pagination-numnotifications',
+ mw.language.convertNumber( itemsInPage )
+ );
+ } else {
+ label = mw.msg(
+ 'echo-specialpage-pagination-range',
+ mw.language.convertNumber( firstNotifNum + 1 ),
+ mw.language.convertNumber( lastNotifNum )
+ );
+ }
+
+ this.labelWidget.setLabel( label );
+ };
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.PlaceholderItemWidget.js b/Echo/modules/ui/mw.echo.ui.PlaceholderItemWidget.js
new file mode 100644
index 00000000..b501dfd1
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.PlaceholderItemWidget.js
@@ -0,0 +1,92 @@
+( function ( mw, $ ) {
+ /**
+ * Placeholder notification option widget for echo popup.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.LabelElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {string} [link] A link that this widget leads to.
+ */
+ mw.echo.ui.PlaceholderItemWidget = function MwEchoUiPlaceholderItemWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.PlaceholderItemWidget.parent.call( this, $.extend( { data: null }, config ) );
+
+ // Mixin constructor
+ OO.ui.mixin.LabelElement.call( this, config );
+
+ this.$element.addClass( 'mw-echo-ui-placeholderItemWidget' );
+
+ this.setLink( config.link );
+ };
+
+ OO.inheritClass( mw.echo.ui.PlaceholderItemWidget, OO.ui.Widget );
+ OO.mixinClass( mw.echo.ui.PlaceholderItemWidget, OO.ui.mixin.LabelElement );
+
+ /**
+ * Set (or unset) the main link url for this widget
+ *
+ * @param {string} url The widget url
+ */
+ mw.echo.ui.PlaceholderItemWidget.prototype.setLink = function ( url ) {
+ var $link;
+ if ( url ) {
+ $link = $( '<a>' )
+ .addClass( 'mw-echo-ui-placeholderItemWidget-link' )
+ .attr( 'href', url );
+ this.$element.html( $link.append( this.$label ) );
+ } else {
+ this.$element.html( this.$label );
+ }
+ };
+
+ /**
+ * Return false on 'isRead' call for the notification list
+ * sorting.
+ *
+ * @return {boolean} false
+ */
+ mw.echo.ui.PlaceholderItemWidget.prototype.isRead = function () {
+ return false;
+ };
+
+ /**
+ * Return false on 'isForeign' call for the notification list
+ * sorting.
+ *
+ * @return {boolean} false
+ */
+ mw.echo.ui.PlaceholderItemWidget.prototype.isForeign = function () {
+ return false;
+ };
+
+ /**
+ * Return 0 on getTimestamp call for the notification list
+ * sorting.
+ *
+ * @return {number} 0
+ */
+ mw.echo.ui.PlaceholderItemWidget.prototype.getTimestamp = function () {
+ return 0;
+ };
+
+ /**
+ * Return 0 on getId call for the notification list
+ * sorting.
+ *
+ * @return {number} 0
+ */
+ mw.echo.ui.PlaceholderItemWidget.prototype.getId = function () {
+ return 0;
+ };
+
+ /**
+ * Do nothing for resetInitiallyUnseen since it is requested by the list widget
+ */
+ mw.echo.ui.PlaceholderItemWidget.prototype.resetInitiallyUnseen = function () {};
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.ReadStateButtonSelectWidget.js b/Echo/modules/ui/mw.echo.ui.ReadStateButtonSelectWidget.js
new file mode 100644
index 00000000..05ed8e70
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.ReadStateButtonSelectWidget.js
@@ -0,0 +1,64 @@
+( function ( $, mw ) {
+ /**
+ * A select widget for notification read state: 'all', 'read' or 'unread'
+ *
+ * @class
+ * @extends OO.ui.ButtonSelectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ */
+ mw.echo.ui.ReadStateButtonSelectWidget = function MwEchoUiReadStateButtonSelectWidget( config ) {
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.ReadStateButtonSelectWidget.parent.call( this, $.extend( config, {
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ data: 'all',
+ label: mw.msg( 'notification-inbox-filter-all' )
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'read',
+ label: mw.msg( 'notification-inbox-filter-read' )
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'unread',
+ label: mw.msg( 'notification-inbox-filter-unread' )
+ } )
+ ]
+ } ) );
+
+ this.connect( this, { choose: 'onChoose' } );
+
+ this.$element
+ .addClass( 'mw-echo-ui-readStateButtonSelectWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.ReadStateButtonSelectWidget, OO.ui.ButtonSelectWidget );
+
+ /* Events */
+
+ /**
+ * @event filter
+ * @param {string} readState The chosen read state
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to choose event
+ *
+ * @param {OO.ui.ButtonOptionWidget} item Chosen item
+ * @fires filter
+ */
+ mw.echo.ui.ReadStateButtonSelectWidget.prototype.onChoose = function ( item ) {
+ var data = item && item.getData();
+
+ if ( data ) {
+ this.emit( 'filter', data );
+ }
+ };
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.SingleNotificationItemWidget.js b/Echo/modules/ui/mw.echo.ui.SingleNotificationItemWidget.js
new file mode 100644
index 00000000..38a8bece
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.SingleNotificationItemWidget.js
@@ -0,0 +1,101 @@
+( function ( mw ) {
+ /**
+ * Single notification item widget for echo popup.
+ *
+ * @class
+ * @extends mw.echo.ui.NotificationItemWidget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {mw.echo.Controller} controller Echo notifications controller
+ * @param {mw.echo.dm.NotificationItem} model Notification item model
+ * @param {Object} [config] Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ * @cfg {boolean} [bundle=false] This notification is part of a bundle
+ */
+ mw.echo.ui.SingleNotificationItemWidget = function MwEchoUiSingleNotificationItemWidget( controller, model, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.SingleNotificationItemWidget.parent.call( this, controller, model, config );
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.controller = controller;
+ this.model = model;
+
+ this.bundle = !!config.bundle;
+ this.$overlay = config.$overlay || this.$element;
+
+ // Toggle 'mark as read' functionality
+ this.toggleMarkAsReadButtons( !this.model.isRead() );
+
+ // Events
+ this.model.connect( this, { update: 'updateDataFromModel' } );
+
+ // Update read and seen states from the model
+ this.updateDataFromModel();
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.SingleNotificationItemWidget, mw.echo.ui.NotificationItemWidget );
+ OO.mixinClass( mw.echo.ui.SingleNotificationItemWidget, OO.ui.mixin.PendingElement );
+
+ /* Methods */
+ mw.echo.ui.SingleNotificationItemWidget.prototype.onPrimaryLinkClick = function () {
+ // Log notification click
+
+ mw.echo.logger.logInteraction(
+ mw.echo.Logger.static.actions.notificationClick,
+ mw.echo.Logger.static.context.popup,
+ this.getModel().getId(),
+ this.getModel().getCategory(),
+ false,
+ // Source of this notification if it is cross-wiki
+ // TODO: For notifications in local bundles, we need
+ // to consider changing this
+ this.bundle ? this.getModel().getSource() : ''
+ );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.ui.SingleNotificationItemWidget.prototype.markRead = function ( isRead ) {
+ isRead = isRead !== undefined ? !!isRead : true;
+
+ if ( this.model.isForeign() ) {
+ this.controller.markCrossWikiItemsRead( this.model.getId(), this.model.getSource() );
+ } else {
+ this.controller.markItemsRead( this.model.getId(), this.model.getModelName(), isRead );
+ }
+ };
+
+ /**
+ * Extend 'toggleRead' to emit sortChange so the item can be sorted
+ * when its read state was updated
+ *
+ * @inheritdoc
+ * @fires sortChange
+ */
+ mw.echo.ui.SingleNotificationItemWidget.prototype.toggleRead = function ( read ) {
+ var oldState = this.read;
+
+ // Parent
+ mw.echo.ui.SingleNotificationItemWidget.parent.prototype.toggleRead.call( this, read );
+
+ if ( oldState !== read ) {
+ this.emit( 'sortChange' );
+ }
+ };
+
+ /**
+ * Update item state when the item model changes.
+ */
+ mw.echo.ui.SingleNotificationItemWidget.prototype.updateDataFromModel = function () {
+ this.toggleRead( this.model.isRead() );
+ this.toggleSeen( this.model.isSeen() );
+ };
+}( mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.SortedListWidget.js b/Echo/modules/ui/mw.echo.ui.SortedListWidget.js
new file mode 100644
index 00000000..591c0ada
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.SortedListWidget.js
@@ -0,0 +1,280 @@
+( function ( mw ) {
+ /**
+ * Sorted list widget. This is a group widget that sorts its items
+ * according to a given sorting callback.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.SortedEmitterList
+ *
+ * @constructor
+ * @param {Function} sortingCallback Callback that compares two items.
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$group] The container element created by the class. If this configuration
+ * is omitted, the group element will use a generated `<div>`.
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ * @cfg {number} [timestamp=0] A fallback timestamp for the list, usually representing
+ * the timestamp of the latest item.
+ * @cfg {boolean} [animated=false] Animate the sorting of items
+ */
+ mw.echo.ui.SortedListWidget = function MwEchoUiSortedListWidget( sortingCallback, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.SortedListWidget.parent.call( this, config );
+ // Mixin constructor
+ OO.SortedEmitterList.call( this, sortingCallback );
+
+ // Properties
+ this.$group = null;
+ this.$overlay = config.$overlay;
+ this.timestamp = config.timestamp || 0;
+
+ this.animated = !!config.animated;
+
+ // Initialization
+ this.setGroupElement( config.$group || this.$element );
+
+ this.$element
+ .addClass( 'mw-echo-ui-sortedListWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.SortedListWidget, OO.ui.Widget );
+ OO.mixinClass( mw.echo.ui.SortedListWidget, OO.SortedEmitterList );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.echo.ui.SortedListWidget.prototype.onItemSortChange = function ( item ) {
+ var fakeWidget,
+ widget = this;
+
+ if ( this.animated ) {
+ // Create a fake widget with cloned contents
+ fakeWidget = new mw.echo.ui.ClonedNotificationItemWidget(
+ item.$element.clone( true ),
+ {
+ id: item.getId() + '.42',
+ // HACK: We are assuming that the item sort change
+ // is triggered when the item is marked read/unread
+ // This is a generally correct assumption, but it may
+ // cause issues when the case is unclear. We should try
+ // and come up with a good way to measure the previous
+ // state of the item instead
+ read: !item.isRead(),
+ foreign: item.isForeign(),
+ timestamp: item.getTimestamp()
+ }
+ );
+
+ // remove real item from item list, without touching the DOM
+ this.removeItems( item );
+
+ // insert real item, hidden
+ item.$element.hide();
+ this.addItems( item );
+
+ // insert fake
+ this.addItems( fakeWidget );
+
+ // fade out fake
+ fakeWidget.$element.fadeOut( 400, function () {
+ // remove fake
+ widget.removeItems( fakeWidget );
+ // fade-in real item
+ item.$element.fadeIn( 400 );
+ } );
+ } else {
+ // Mixin method
+ OO.SortedEmitterList.prototype.onItemSortChange.call( this, item );
+ }
+ };
+ /**
+ * Set the group element.
+ *
+ * If an element is already set, items will be moved to the new element.
+ *
+ * @param {jQuery} $group Element to use as group
+ */
+ mw.echo.ui.SortedListWidget.prototype.setGroupElement = function ( $group ) {
+ var i, len;
+
+ this.$group = $group;
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.$group.append( this.items[ i ].$element );
+ }
+ };
+
+ /**
+ * Get an item by its id.
+ *
+ * @param {number} id Item id to search for
+ * @return {OO.ui.Element|null} Item with equivalent data, `null` if none exists
+ */
+ mw.echo.ui.SortedListWidget.prototype.getItemFromId = function ( id ) {
+ var i, len, item,
+ hash = OO.getHash( id );
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ item = this.items[ i ];
+ if ( hash === OO.getHash( item.getId() ) ) {
+ return item;
+ }
+ }
+
+ return null;
+ };
+
+ /**
+ * Get an item by its data.
+ *
+ * @param {string} data Item data to search for
+ * @return {OO.ui.Element|null} Item with equivalent data, `null` if none exists
+ */
+ mw.echo.ui.SortedListWidget.prototype.getItemFromData = function ( data ) {
+ var i, len, item,
+ hash = OO.getHash( data );
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ item = this.items[ i ];
+ if ( hash === OO.getHash( item.getData() ) ) {
+ return item;
+ }
+ }
+
+ return null;
+ };
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Remove items.
+ *
+ * @param {OO.EventEmitter[]} items Items to remove
+ * @chainable
+ * @fires remove
+ */
+ mw.echo.ui.SortedListWidget.prototype.removeItems = function ( items ) {
+ var i, item, index;
+
+ if ( !Array.isArray( items ) ) {
+ items = [ items ];
+ }
+
+ if ( items.length > 0 ) {
+ // Remove specific items
+ for ( i = 0; i < items.length; i++ ) {
+ item = items[ i ];
+ index = this.items.indexOf( item );
+ if ( index !== -1 ) {
+ item.setElementGroup( null );
+ item.$element.detach();
+ }
+ }
+ }
+
+ return OO.SortedEmitterList.prototype.removeItems.call( this, items );
+ };
+
+ /**
+ * Utility method to insert an item into the list, and
+ * connect it to aggregate events.
+ *
+ * Don't call this directly unless you know what you're doing.
+ * Use #addItems instead.
+ *
+ * @private
+ * @param {OO.EventEmitter} item Items to add
+ * @param {number} index Index to add items at
+ * @return {number} The index the item was added at
+ */
+ mw.echo.ui.SortedListWidget.prototype.insertItem = function ( item, index ) {
+ // Call parent and get the normalized index
+ index = OO.SortedEmitterList.prototype.insertItem.call( this, item, index );
+
+ item.setElementGroup( this );
+
+ this.attachItemToDom( item, index );
+
+ return index;
+ };
+
+ /**
+ * Move an item from its current position to a new index.
+ *
+ * The item is expected to exist in the list. If it doesn't,
+ * the method will throw an exception.
+ *
+ * @private
+ * @param {OO.EventEmitter} item Items to add
+ * @param {number} index Index to move the item to
+ * @return {number} The index the item was moved to
+ * @throws {Error} If item is not in the list
+ */
+ mw.echo.ui.SortedListWidget.prototype.moveItem = function ( item, index ) {
+ // Call parent and get the normalized index
+ index = OO.SortedEmitterList.prototype.moveItem.call( this, item, index );
+
+ this.attachItemToDom( item, index );
+
+ return index;
+ };
+
+ /**
+ * Attach the item to the Dom in its intended position, based
+ * on the given index.
+ *
+ * @param {OO.EventEmitter} item Item
+ * @param {number} index Index to insert the item into
+ */
+ mw.echo.ui.SortedListWidget.prototype.attachItemToDom = function ( item, index ) {
+ if ( index === undefined || index < 0 || index >= this.items.length - 1 ) {
+ this.$group.append( item.$element.get( 0 ) );
+ } else if ( index === 0 ) {
+ this.$group.prepend( item.$element.get( 0 ) );
+ } else {
+ this.items[ index + 1 ].$element.before( item.$element.get( 0 ) );
+ }
+ };
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Clear all items
+ *
+ * @chainable
+ * @fires clear
+ */
+ mw.echo.ui.SortedListWidget.prototype.clearItems = function () {
+ var i, len, item;
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ item = this.items[ i ];
+ item.setElementGroup( null );
+ item.$element.detach();
+ }
+
+ // Mixin method
+ return OO.SortedEmitterList.prototype.clearItems.call( this );
+ };
+
+ /**
+ * Get the timestamp of the list by taking the latest notification
+ * timestamp.
+ *
+ * @return {string} Latest timestamp
+ */
+ mw.echo.ui.SortedListWidget.prototype.getTimestamp = function () {
+ var items = this.getItems();
+
+ return (
+ items.length > 0 ?
+ items[ 0 ].getTimestamp() :
+ this.timestamp
+ );
+ };
+
+}( mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.SpecialHelpMenuWidget.js b/Echo/modules/ui/mw.echo.ui.SpecialHelpMenuWidget.js
new file mode 100644
index 00000000..54a37252
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.SpecialHelpMenuWidget.js
@@ -0,0 +1,159 @@
+( function ( $, mw ) {
+ /**
+ * Widget for the settings menu in the Special:Notifications page
+ *
+ * @param {mw.echo.dm.ModelManager} manager Model manager
+ * @param {Object} config Configuration object
+ */
+ mw.echo.ui.SpecialHelpMenuWidget = function MwEchoUiSpecialHelpMenuWidget( manager, config ) {
+ var $menu = $( '<div>' )
+ .addClass( 'mw-echo-ui-specialHelpMenuWidget-menu' );
+
+ config = config || {};
+
+ // Parent constructor
+ mw.echo.ui.SpecialHelpMenuWidget.parent.call( this, $.extend( {
+ icon: 'advanced',
+ indicator: 'down',
+ popup: {
+ $content: $menu,
+ width: 300
+ }
+ }, config ) );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupWidget.call( this, $.extend( {}, config, { $group: $menu } ) );
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.manager = manager;
+
+ this.markAllReadButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'doubleCheck',
+ label: this.getMarkAllReadButtonLabel()
+ } );
+ this.setPendingElement( this.$element );
+ this.markAllReadButton.toggle( false );
+
+ this.addItems( [ this.markAllReadButton ] );
+ if ( config.prefLink ) {
+ this.addItems( [
+ // Preferences link
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'advanced',
+ label: mw.msg( 'mypreferences' ),
+ href: config.prefLink
+ } )
+ ] );
+ }
+
+ if ( config.helpLink ) {
+ this.addItems( [
+ // Help link
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'help',
+ label: mw.msg( 'echo-learn-more' ),
+ href: config.helpLink
+ } )
+ ] );
+ }
+
+ // Events
+ this.markAllReadButton.connect( this, { click: 'onMarkAllreadButtonClick' } );
+ this.manager.connect( this, {
+ localCountChange: 'onLocalCountChange'
+ } );
+ this.manager.getFiltersModel().getSourcePagesModel().connect( this, { update: 'onSourcePageUpdate' } );
+
+ this.$element
+ .addClass( 'mw-echo-ui-specialHelpMenuWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.SpecialHelpMenuWidget, OO.ui.PopupButtonWidget );
+ OO.mixinClass( mw.echo.ui.SpecialHelpMenuWidget, OO.ui.mixin.GroupElement );
+ OO.mixinClass( mw.echo.ui.SpecialHelpMenuWidget, OO.ui.mixin.PendingElement );
+
+ /* Events */
+
+ /**
+ * @event markAllRead
+ *
+ * Mark all notifications as read in the selected wiki
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to source page change
+ */
+ mw.echo.ui.SpecialHelpMenuWidget.prototype.onSourcePageUpdate = function () {
+ this.markAllReadButton.setLabel( this.getMarkAllReadButtonLabel() );
+
+ };
+
+ /**
+ * Respond to local counter update event
+ *
+ * @param {number} count New count
+ */
+ mw.echo.ui.SpecialHelpMenuWidget.prototype.onLocalCountChange = function ( count ) {
+ this.markAllReadButton.toggle( count > 0 );
+ };
+
+ /**
+ * Respond to mark all read button click
+ */
+ mw.echo.ui.SpecialHelpMenuWidget.prototype.onMarkAllreadButtonClick = function () {
+ // Log this action
+ mw.echo.logger.logInteraction(
+ mw.echo.Logger.static.actions.markAllReadClick,
+ mw.echo.Logger.static.context.archive,
+ null, // Notification ID is irrelevant
+ this.manager.getTypeString(), // The type of the list in general
+ null, // The Logger has logic to decide whether this is mobile or not
+ this.manager.getFiltersModel().getSourcePagesModel().getCurrentSource() // Source name
+ );
+
+ this.popup.toggle( false );
+ this.emit( 'markAllRead' );
+ };
+
+ /**
+ * Build the button label
+ *
+ * @return {string} Mark all read button label
+ */
+ mw.echo.ui.SpecialHelpMenuWidget.prototype.getMarkAllReadButtonLabel = function () {
+ var pageModel = this.manager.getFiltersModel().getSourcePagesModel(),
+ source = pageModel.getCurrentSource(),
+ sourceTitle = pageModel.getSourceTitle( source );
+
+ return sourceTitle ?
+ mw.msg( 'echo-mark-wiki-as-read', sourceTitle ) :
+ mw.msg( 'echo-mark-all-as-read' );
+ };
+
+ /**
+ * Extend the pushPending method to disable the mark all read button
+ */
+ mw.echo.ui.SpecialHelpMenuWidget.prototype.pushPending = function () {
+ this.markAllReadButton.setDisabled( true );
+
+ // Mixin method
+ OO.ui.mixin.PendingElement.prototype.pushPending.call( this );
+ };
+
+ /**
+ * Extend the popPending method to enable the mark all read button
+ */
+ mw.echo.ui.SpecialHelpMenuWidget.prototype.popPending = function () {
+ this.markAllReadButton.setDisabled( false );
+
+ // Mixin method
+ OO.ui.mixin.PendingElement.prototype.popPending.call( this );
+ };
+}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/ui/mw.echo.ui.SubGroupListWidget.js b/Echo/modules/ui/mw.echo.ui.SubGroupListWidget.js
new file mode 100644
index 00000000..cf2f3442
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.SubGroupListWidget.js
@@ -0,0 +1,281 @@
+( function ( mw, $ ) {
+ /**
+ * Sub group list widget.
+ * This widget contains a list of notifications from a single source
+ * in a cross-wiki notifications group.
+ *
+ * @param {mw.echo.Controller} controller Notifications controller
+ * @param {mw.echo.dm.SortedList} listModel Notifications list model for this source
+ * @param {Object} config Configuration object
+ * @cfg {boolean} [showTitle=false] Show the title of this group
+ * @cfg {boolean} [showMarkAllRead=false] Show a mark all read button for this group
+ * @cfg {boolean} [animateSorting=false] Animate the sorting of items
+ * @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
+ * for popups.
+ */
+ mw.echo.ui.SubGroupListWidget = function MwEchoUiSubGroupListWidget( controller, listModel, config ) {
+ var sourceURL,
+ $header = $( '<div>' )
+ .addClass( 'mw-echo-ui-subGroupListWidget-header' );
+
+ config = config || {};
+
+ this.controller = controller;
+ this.model = listModel;
+
+ // Parent constructor
+ mw.echo.ui.SubGroupListWidget.parent.call( this, $.extend( { data: this.getSource() }, config ) );
+
+ this.showTitle = !!config.showTitle;
+ this.showMarkAllRead = !!config.showMarkAllRead;
+ this.$overlay = config.$overlay || this.$element;
+
+ this.listWidget = new mw.echo.ui.SortedListWidget(
+ // Sorting callback
+ config.sortingCallback || function ( a, b ) {
+ // Reverse sorting
+ if ( b.getTimestamp() < a.getTimestamp() ) {
+ return -1;
+ } else if ( b.getTimestamp() > a.getTimestamp() ) {
+ return 1;
+ }
+
+ // Fallback on IDs
+ return b.getId() - a.getId();
+ },
+ // Config
+ {
+ $overlay: this.$overlay,
+ animated: config.animateSorting
+ }
+ );
+
+ sourceURL = this.model.getSourceURL() ?
+ this.model.getSourceURL().replace( '$1', 'Special:Notifications' ) :
+ null;
+ if ( sourceURL ) {
+ this.title = new OO.ui.ButtonWidget( {
+ framed: false,
+ classes: [ 'mw-echo-ui-subGroupListWidget-header-row-title' ],
+ href: sourceURL
+ } );
+ } else {
+ this.title = new OO.ui.LabelWidget( {
+ classes: [ 'mw-echo-ui-subGroupListWidget-header-row-title' ]
+ } );
+ }
+
+ if ( this.model.getTitle() ) {
+ this.title.setLabel( this.model.getTitle() );
+ }
+ this.title.toggle( this.showTitle );
+
+ // Mark all as read button
+ this.markAllReadButton = new OO.ui.ButtonWidget( {
+ framed: true,
+ icon: 'doubleCheck',
+ label: mw.msg( 'echo-specialpage-section-markread' ),
+ classes: [ 'mw-echo-ui-subGroupListWidget-header-row-markAllReadButton' ]
+ } );
+
+ // Events
+ this.model.connect( this, {
+ // Cross-wiki items can be discarded when marked as read.
+ // We need to differentiate this explicit action from the
+ // action of 'remove' because 'remove' is also used when
+ // an item is resorted by OO.SortedEmitterWidget before
+ // it is re-added again
+ discard: 'onModelDiscardItems',
+ // Update all items
+ update: 'resetItemsFromModel'
+ } );
+ this.model.connect( this, { itemUpdate: 'toggleMarkAllReadButton' } );
+ this.markAllReadButton.connect( this, { click: 'onMarkAllReadButtonClick' } );
+
+ // Initialize
+ this.toggleMarkAllReadButton();
+
+ this.$element
+ .addClass( 'mw-echo-ui-subGroupListWidget' )
+ .append(
+ $header.append(
+ $( '<div>' )
+ .addClass( 'mw-echo-ui-subGroupListWidget-header-row' )
+ .append(
+ this.title.$element,
+ this.markAllReadButton.$element
+ )
+ ),
+ this.listWidget.$element
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.SubGroupListWidget, OO.ui.Widget );
+
+ /* Methods */
+
+ /**
+ * Toggle the visibility of the mark all read button for this group
+ * based on whether there are unread notifications
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.toggleMarkAllReadButton = function () {
+ this.markAllReadButton.toggle( this.showMarkAllRead && this.hasUnread() );
+ };
+
+ /**
+ * Respond to 'mark all as read' button click
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.onMarkAllReadButtonClick = function () {
+ this.controller.markEntireListModelRead( this.model.getName() );
+ };
+
+ /**
+ * Check whether this sub group list has any unread notifications
+ *
+ * @return {boolean} Sub group has unread notifications
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.hasUnread = function () {
+ var isUnread = function ( item ) {
+ return !item.isRead();
+ },
+ items = this.model.getItems();
+
+ return items.some( isUnread );
+ };
+
+ /**
+ * Reset the items and rebuild them according to the model.
+ *
+ * @param {mw.echo.dm.NotificationItem[]} [items] Item models that are added.
+ * If this is empty, the widget will request all the items from the model.
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.resetItemsFromModel = function ( items ) {
+ var i, widget,
+ itemWidgets = [],
+ $elements = $();
+
+ items = items || this.model.getItems();
+
+ for ( i = 0; i < items.length; i++ ) {
+ widget = new mw.echo.ui.SingleNotificationItemWidget(
+ this.controller,
+ items[ i ],
+ {
+ $overlay: this.$overlay,
+ bundle: items[ i ].isBundled()
+ }
+ );
+ itemWidgets.push( widget );
+ $elements = $elements.add( widget.$element );
+ }
+
+ // Clear the current items if any exist
+ this.getListWidget().clearItems();
+
+ // fire render hook
+ mw.hook( 'ext.echo.notifications.beforeRender' ).fire( this.$element, $elements );
+
+ // Add the new items
+ this.getListWidget().addItems( itemWidgets );
+ };
+
+ /**
+ * Respond to model remove event. This may happen when an item
+ * is marked as read.
+ *
+ * @param {mw.echo.dm.NotificationItem[]} items Notification item models
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.onModelDiscardItems = function ( items ) {
+ var i,
+ itemWidgets = [];
+
+ for ( i = 0; i < items.length; i++ ) {
+ itemWidgets.push( this.listWidget.getItemFromId( items[ i ].getId() ) );
+ }
+ this.listWidget.removeItems( itemWidgets );
+ };
+
+ /**
+ * Get the associated list widget. This is useful to specifically
+ * add and/or remove items from the list.
+ *
+ * @return {mw.echo.ui.SortedListWidget} List widget
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.getListWidget = function () {
+ return this.listWidget;
+ };
+
+ /**
+ * Get the timestamp for the list
+ *
+ * @return {number} Timestamp
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.getTimestamp = function () {
+ return this.model.getTimestamp();
+ };
+
+ /**
+ * Toggle the visibility of the title
+ *
+ * @param {boolean} show Show the title
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.toggleTitle = function ( show ) {
+ show = show !== undefined ? show : !this.showTitle;
+
+ if ( this.showTitle !== show ) {
+ this.showTitle = show;
+ this.title.toggle( this.showTitle );
+ }
+ };
+
+ /**
+ * Get a the source of this list.
+ *
+ * @return {string} Group source
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.getSource = function () {
+ return this.model.getSource();
+ };
+
+ /**
+ * Get an array of IDs of all of the items in this group
+ *
+ * @return {number[]} Array of item IDs
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.getAllItemIDs = function () {
+ return this.model.getAllItemIds();
+ };
+
+ /**
+ * Get an array of IDs of all of the items in this group that
+ * correspond to a specific type
+ *
+ * @param {string} type Item type
+ * @return {number[]} Array of item IDs
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.getAllItemIDsByType = function ( type ) {
+ return this.model.getAllItemIdsByType( type );
+ };
+
+ /**
+ * Check whether this group is foreign
+ *
+ * @return {boolean} This group is foreign
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.isForeign = function () {
+ return this.model.isForeign();
+ };
+
+ /**
+ * Get the group id, which is represented by its model symbolic name.
+ * This is meant for sorting callbacks that fallback on
+ * sorting by IDs.
+ *
+ * @return {string} Group source
+ */
+ mw.echo.ui.SubGroupListWidget.prototype.getId = function () {
+ return this.model.getName();
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.ToggleReadCircleButtonWidget.js b/Echo/modules/ui/mw.echo.ui.ToggleReadCircleButtonWidget.js
new file mode 100644
index 00000000..01ac164c
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.ToggleReadCircleButtonWidget.js
@@ -0,0 +1,53 @@
+( function ( mw, $ ) {
+ /**
+ * A button showing a circle that represents either 'mark as read' or 'mark as unread' states.
+ *
+ * @class
+ * @extends OO.ui.ButtonWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [markAsRead=true] Display mark as read state. If false, the button displays
+ * mark as unread state.
+ */
+ mw.echo.ui.ToggleReadCircleButtonWidget = function MwEchoUiToggleReadCircleButtonWidget( config ) {
+ config = config || {};
+
+ // Parent
+ mw.echo.ui.ToggleReadCircleButtonWidget.parent.call( this, config );
+
+ this.$circle = $( '<div>' )
+ .addClass( 'mw-echo-ui-toggleReadCircleButtonWidget-circle' );
+ this.$button.append( this.$circle );
+
+ this.toggleState( config.markAsRead === undefined ? true : !!config.markAsRead );
+
+ this.$element
+ .addClass( 'mw-echo-ui-toggleReadCircleButtonWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.echo.ui.ToggleReadCircleButtonWidget, OO.ui.ButtonWidget );
+
+ /* Methods */
+
+ /**
+ * Toggle the state of the button from 'mark as read' to 'mark as unread'
+ * and vice versa.
+ *
+ * @param {boolean} [isMarkAsRead] The state is mark as read
+ */
+ mw.echo.ui.ToggleReadCircleButtonWidget.prototype.toggleState = function ( isMarkAsRead ) {
+ isMarkAsRead = isMarkAsRead === undefined ? !this.markAsRead : !!isMarkAsRead;
+
+ this.markAsRead = isMarkAsRead;
+
+ this.$circle.toggleClass( 'mw-echo-ui-toggleReadCircleButtonWidget-circle-unread', !this.markAsRead );
+ this.setTitle(
+ this.markAsRead ?
+ mw.msg( 'echo-notification-markasread' ) :
+ mw.msg( 'echo-notification-markasunread' )
+ );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/ui/mw.echo.ui.js b/Echo/modules/ui/mw.echo.ui.js
new file mode 100644
index 00000000..12f39607
--- /dev/null
+++ b/Echo/modules/ui/mw.echo.ui.js
@@ -0,0 +1,7 @@
+( function ( mw, $ ) {
+ mw.echo = mw.echo || {};
+ mw.echo.ui = {
+ $overlay: $( '<div>' )
+ .addClass( 'mw-echo-ui-overlay' )
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/viewmodel/mw.echo.dm.List.js b/Echo/modules/viewmodel/mw.echo.dm.List.js
deleted file mode 100644
index 381ec5a6..00000000
--- a/Echo/modules/viewmodel/mw.echo.dm.List.js
+++ /dev/null
@@ -1,272 +0,0 @@
-( function ( $, mw ) {
- /**
- * Echo List mixin
- *
- * @mixin
- * @abstract
- * @constructor
- * @param {Object} config Configuration options
- */
- mw.echo.dm.List = function mwFlowDmList( config ) {
- // Configuration initialization
- config = config || {};
-
- this.items = [];
-
- // Store references to items by their ids
- this.itemsById = {};
-
- this.aggregateItemEvents = {};
- };
-
- /* Events */
-
- /**
- * @event add Items have been added
- * @param {mw.echo.dm.NotificationItem[]} items Added items
- * @param {number} index Index items were added at
- */
-
- /**
- * @event remove Items have been removed
- * @param {mw.echo.dm.NotificationItem[]} items Removed items
- */
-
- /**
- * @event clear All items have been removed
- */
-
- /* Methods */
-
- /**
- * Get all items
- *
- * @return {mw.echo.dm.NotificationItem[]} Items in the list
- */
- mw.echo.dm.List.prototype.getItems = function () {
- return this.items.slice( 0 );
- };
-
- /**
- * Get an item by its id
- * @param {string} id Item id
- * @return {mw.echo.dm.NotificationItem} Item
- */
- mw.echo.dm.List.prototype.getItemById = function ( id ) {
- return this.itemsById[ id ];
- };
-
- /**
- * Get the index of a specific item
- *
- * @param {mw.echo.dm.NotificationItem} item Requested item
- * @return {number} Index of the item
- */
- mw.echo.dm.List.prototype.getItemIndex = function ( item ) {
- return this.items.indexOf( item );
- };
-
- /**
- * Get number of items
- *
- * @return {number} Number of items in the list
- */
- mw.echo.dm.List.prototype.getItemCount = function () {
- return this.items.length;
- };
-
- /**
- * Check if a list contains no items.
- *
- * @return {boolean} Group is empty
- */
- mw.echo.dm.List.prototype.isEmpty = function () {
- return !this.items.length;
- };
-
- /**
- * Aggregate the events emitted by the group.
- * Taken from oojs-ui's OO.ui.GroupElement#aggregate
- *
- * When events are aggregated, the group will listen to all contained items for the event,
- * and then emit the event under a new name. The new event will contain an additional leading
- * parameter containing the item that emitted the original event. Other arguments emitted from
- * the original event are passed through.
- *
- * @param {Object.<string,string|null>} events An object keyed by the name of the event that should be
- * aggregated (e.g., ‘click’) and the value of the new name to use (e.g., ‘groupClick’).
- * A `null` value will remove aggregated events.
-
- * @throws {Error} An error is thrown if aggregation already exists.
- */
- mw.echo.dm.List.prototype.aggregate = function ( events ) {
- var i, len, item, add, remove, itemEvent, groupEvent;
-
- for ( itemEvent in events ) {
- groupEvent = events[ itemEvent ];
-
- // Remove existing aggregated event
- if ( Object.prototype.hasOwnProperty.call( this.aggregateItemEvents, itemEvent ) ) {
- // Don't allow duplicate aggregations
- if ( groupEvent ) {
- throw new Error( 'Duplicate item event aggregation for ' + itemEvent );
- }
- // Remove event aggregation from existing items
- for ( i = 0, len = this.items.length; i < len; i++ ) {
- item = this.items[ i ];
- if ( item.connect && item.disconnect ) {
- remove = {};
- remove[ itemEvent ] = [ 'emit', this.aggregateItemEvents[ itemEvent ], item ];
- item.disconnect( this, remove );
- }
- }
- // Prevent future items from aggregating event
- delete this.aggregateItemEvents[ itemEvent ];
- }
-
- // Add new aggregate event
- if ( groupEvent ) {
- // Make future items aggregate event
- this.aggregateItemEvents[ itemEvent ] = groupEvent;
- // Add event aggregation to existing items
- for ( i = 0, len = this.items.length; i < len; i++ ) {
- item = this.items[ i ];
- if ( item.connect && item.disconnect ) {
- add = {};
- add[ itemEvent ] = [ 'emit', groupEvent, item ];
- item.connect( this, add );
- }
- }
- }
- }
- };
-
- /**
- * Add items
- *
- * @param {mw.echo.dm.NotificationItem[]} items Items to add
- * @param {number} index Index to add items at
- * @chainable
- * @fires add
- */
- mw.echo.dm.List.prototype.addItems = function ( items, index ) {
- var i, len, item, event, events, currentIndex, existingItem, at;
-
- if ( items.length === 0 ) {
- return this;
- }
-
- // Support adding existing items at new locations
- for ( i = 0, len = items.length; i < len; i++ ) {
- item = items[i];
- existingItem = this.getItemById( item.getId() );
-
- // Check if item exists then remove it first, effectively "moving" it
- currentIndex = this.items.indexOf( existingItem );
- if ( currentIndex >= 0 ) {
- this.removeItems( [ existingItem ] );
- // Adjust index to compensate for removal
- if ( currentIndex < index ) {
- index--;
- }
- }
-
- // Add the item
- if ( item.connect && item.disconnect && !$.isEmptyObject( this.aggregateItemEvents ) ) {
- events = {};
- for ( event in this.aggregateItemEvents ) {
- events[ event ] = [ 'emit', this.aggregateItemEvents[ event ], item ];
- }
- item.connect( this, events );
- }
-
- // Add by reference
- this.itemsById[ item.getId() ] = items[i];
- }
-
- if ( index === undefined || index < 0 || index >= this.items.length ) {
- at = this.items.length;
- this.items.push.apply( this.items, items );
- } else if ( index === 0 ) {
- at = 0;
- this.items.unshift.apply( this.items, items );
- } else {
- at = index;
- this.items.splice.apply( this.items, [ index, 0 ].concat( items ) );
- }
- this.emit( 'add', items, at );
-
- return this;
- };
-
- /**
- * Remove items
- *
- * @param {mw.echo.dm.NotificationItem[]} items Items to remove
- * @chainable
- * @fires remove
- */
- mw.echo.dm.List.prototype.removeItems = function ( items ) {
- var i, len, item, index, remove, itemEvent,
- removed = [];
-
- if ( items.length === 0 ) {
- return this;
- }
-
- // Remove specific items
- for ( i = 0, len = items.length; i < len; i++ ) {
- item = items[ i ];
- index = this.items.indexOf( item );
- if ( index !== -1 ) {
- if (
- item.connect && item.disconnect &&
- !$.isEmptyObject( this.aggregateItemEvents )
- ) {
- remove = {};
- if ( Object.prototype.hasOwnProperty.call( this.aggregateItemEvents, itemEvent ) ) {
- remove[ itemEvent ] = [ 'emit', this.aggregateItemEvents[ itemEvent ], item ];
- }
- item.disconnect( this, remove );
- }
- this.items.splice( index, 1 );
- // Remove reference by Id
- delete this.itemsById[ item.getId() ];
- }
- }
- this.emit( 'remove', removed );
-
- return this;
- };
-
- /**
- * Clear all items
- *
- * @fires clear
- */
- mw.echo.dm.List.prototype.clearItems = function () {
- var i, len, item, remove, itemEvent;
-
- // Remove all items
- for ( i = 0, len = this.items.length; i < len; i++ ) {
- item = this.items[ i ];
- if (
- item.connect && item.disconnect &&
- !$.isEmptyObject( this.aggregateItemEvents )
- ) {
- remove = {};
- if ( Object.prototype.hasOwnProperty.call( this.aggregateItemEvents, itemEvent ) ) {
- remove[ itemEvent ] = [ 'emit', this.aggregateItemEvents[ itemEvent ], item ];
- }
- item.disconnect( this, remove );
- }
- }
-
- this.items = [];
- this.itemsById = {};
-
- this.emit( 'clear' );
-
- return this;
- };
-}( jQuery, mediaWiki ) );
diff --git a/Echo/modules/viewmodel/mw.echo.dm.NotificationItem.js b/Echo/modules/viewmodel/mw.echo.dm.NotificationItem.js
deleted file mode 100644
index ed254f4f..00000000
--- a/Echo/modules/viewmodel/mw.echo.dm.NotificationItem.js
+++ /dev/null
@@ -1,176 +0,0 @@
-( function ( mw, $ ) {
- /**
- * Echo notification NotificationItem model
- *
- * @class
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {number} id Notification id,
- * @param {Object} [config] Configuration object
- * @cfg {jQuery|string} [content] The html content of this notification
- * @cfg {string} [category] The category of this notification. The category identifies
- * where the notification originates from.
- * @cfg {boolean} [read=false] State the read state of the option
- * @cfg {boolean} [seen=false] State the seen state of the option
- * @cfg {string} [timestamp] Notification timestamp in Mediawiki timestamp format
- * @cfg {string} [primaryUrl] Notification primary link in raw url format
- */
- mw.echo.dm.NotificationItem = function mwFlowDmNotificationItem( id, config ) {
- var date = new Date(),
- normalizeNumber = function ( number ) {
- return ( number < 10 ? '0' : '' ) + String( number );
- },
- fallbackMWDate = date.getUTCFullYear() +
- normalizeNumber( date.getMonth() ) +
- normalizeNumber( date.getUTCDate() ) +
- normalizeNumber( date.getUTCHours() ) +
- normalizeNumber( date.getUTCMinutes() ) +
- normalizeNumber( date.getUTCSeconds() );
-
- // Mixin constructor
- OO.EventEmitter.call( this );
-
- this.id = id || null;
-
- // TODO: We should work on the API to release and work with actual
- // data here, rather than getting a pre-made html content of the
- // notification.
- this.content = config.content || $();
-
- this.category = config.category || '';
-
- this.toggleRead( !!config.read );
- this.toggleSeen( !!config.seen );
-
- this.setTimestamp( config.timestamp || fallbackMWDate );
- this.setPrimaryUrl( config.primaryUrl );
- };
-
- /* Inheritance */
-
- OO.mixinClass( mw.echo.dm.NotificationItem, OO.EventEmitter );
-
- /* Events */
-
- /**
- * @event seen
- * @param {boolean} [seen] Notification is seen
- *
- * Seen status of the notification has changed
- */
-
- /**
- * @event read
- * @param {boolean} [read] Notification is read
- *
- * Read status of the notification has changed
- */
-
- /* Methods */
-
- /**
- * Get NotificationItem id
- * @return {string} NotificationItem Id
- */
- mw.echo.dm.NotificationItem.prototype.getId = function () {
- return this.id;
- };
-
- /**
- * Get NotificationItem content
- * @return {jQuery|string} NotificationItem content
- */
- mw.echo.dm.NotificationItem.prototype.getContent = function () {
- return this.content;
- };
-
- /**
- * Get NotificationItem category
- * @return {string} NotificationItem category
- */
- mw.echo.dm.NotificationItem.prototype.getCategory = function () {
- return this.category;
- };
-
- /**
- * Check whether this notification item is read
- * @return {boolean} Notification item is read
- */
- mw.echo.dm.NotificationItem.prototype.isRead = function () {
- return this.read;
- };
-
- /**
- * Check whether this notification item is seen
- * @return {boolean} Notification item is seen
- */
- mw.echo.dm.NotificationItem.prototype.isSeen = function () {
- return this.seen;
- };
-
- /**
- * Toggle the read state of the widget
- *
- * @param {boolean} [read] The current read state. If not given, the state will
- * become the opposite of its current state.
- */
- mw.echo.dm.NotificationItem.prototype.toggleRead = function ( read ) {
- read = read !== undefined ? read : !this.read;
- if ( this.read !== read ) {
- this.read = read;
- this.emit( 'read', this.read );
- }
- };
-
- /**
- * Toggle the seen state of the widget
- *
- * @param {boolean} [seen] The current seen state. If not given, the state will
- * become the opposite of its current state.
- */
- mw.echo.dm.NotificationItem.prototype.toggleSeen = function ( seen ) {
- seen = seen !== undefined ? seen : !this.seen;
- if ( this.seen !== seen ) {
- this.seen = seen;
- this.emit( 'seen', this.seen );
- }
- };
-
- /**
- * Set the notification timestamp
- *
- * @param {number} timestamp Notification timestamp in Mediawiki timestamp format
- */
- mw.echo.dm.NotificationItem.prototype.setTimestamp = function ( timestamp ) {
- this.timestamp = Number( timestamp );
- };
-
- /**
- * Get the notification timestamp
- *
- * @return {number} Notification timestamp in Mediawiki timestamp format
- */
- mw.echo.dm.NotificationItem.prototype.getTimestamp = function () {
- return this.timestamp;
- };
-
- /**
- * Set the notification link
- *
- * @param {string} link Notification url
- */
- mw.echo.dm.NotificationItem.prototype.setPrimaryUrl = function ( link ) {
- this.primaryUrl = link;
- };
-
- /**
- * Get the notification link
- *
- * @return {string} Notification url
- */
- mw.echo.dm.NotificationItem.prototype.getPrimaryUrl = function () {
- return this.primaryUrl;
- };
-
-}( mediaWiki, jQuery ) );
diff --git a/Echo/modules/viewmodel/mw.echo.dm.NotificationList.js b/Echo/modules/viewmodel/mw.echo.dm.NotificationList.js
deleted file mode 100644
index 7d4fbea3..00000000
--- a/Echo/modules/viewmodel/mw.echo.dm.NotificationList.js
+++ /dev/null
@@ -1,26 +0,0 @@
-( function ( mw ) {
- /**
- * Notification list
- *
- * @class
- * @mixins OO.EventEmitter
- * @mixins mw.echo.dm.List
- *
- * @constructor
- * @param {Object} [config] Configuration object
- */
- mw.echo.dm.NotificationList = function MwEchoDmNotificationList() {
-
- // Mixin constructor
- OO.EventEmitter.call( this );
-
- // Mixin constructor
- mw.echo.dm.List.call( this );
- };
-
- /* Initialization */
-
- OO.initClass( mw.echo.dm.NotificationList );
- OO.mixinClass( mw.echo.dm.NotificationList, OO.EventEmitter );
- OO.mixinClass( mw.echo.dm.NotificationList, mw.echo.dm.List );
-} )( mediaWiki );
diff --git a/Echo/modules/viewmodel/mw.echo.dm.NotificationsModel.js b/Echo/modules/viewmodel/mw.echo.dm.NotificationsModel.js
deleted file mode 100644
index 3fd1ee4e..00000000
--- a/Echo/modules/viewmodel/mw.echo.dm.NotificationsModel.js
+++ /dev/null
@@ -1,428 +0,0 @@
-( function ( mw, $ ) {
- /**
- * Notification view model
- *
- * @class
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {Object} [config] Configuration object
- * @cfg {string} [type='alert'] Notification type 'alert', 'message' or 'all'
- * @cfg {number} [limit=25] Notification limit
- * @cfg {string} [userLang] User language
- */
- mw.echo.dm.NotificationsModel = function MwEchoDmNotificationsModel( config ) {
- config = config || {};
-
- // Mixin constructor
- OO.EventEmitter.call( this );
-
- // Mixin constructor
- mw.echo.dm.List.call( this );
-
- this.type = config.type || 'alert';
- this.limit = config.limit || 25;
- this.userLang = config.userLang || 'en';
-
- this.api = new mw.Api( { ajax: { cache: false } } );
- this.fetchNotificationsPromise = null;
- this.apiErrorState = false;
-
- this.seenTime = mw.config.get( 'wgEchoSeenTime' );
-
- // Store references to unseen and unread notifications
- this.unseenNotifications = new mw.echo.dm.NotificationList();
- this.unreadNotifications = new mw.echo.dm.NotificationList();
-
- // Events
- this.aggregate( {
- seen: 'itemSeen',
- read: 'itemRead'
- } );
-
- this.connect( this, {
- itemSeen: 'onItemSeen',
- itemRead: 'onItemRead'
- } );
- };
-
- /* Initialization */
-
- OO.initClass( mw.echo.dm.NotificationsModel );
- OO.mixinClass( mw.echo.dm.NotificationsModel, OO.EventEmitter );
- OO.mixinClass( mw.echo.dm.NotificationsModel, mw.echo.dm.List );
-
- /* Events */
-
- /**
- * @event updateSeenTime
- *
- * Seen time has been updated
- */
-
- /**
- * @event unseenChange
- * @param {number} count Number of unseen items
- *
- * Items' seen status has changed
- */
-
- /**
- * @event unreadChange
- * @param {number} count Number of unread items
- *
- * Items' read status has changed
- */
-
- /* Methods */
-
- /**
- * Respond to item seen state change
- *
- * @param {mw.echo.dm.NotificationItem} item Notification item
- * @param {boolean} isSeen Notification is seen
- * @fires unseenChange
- */
- mw.echo.dm.NotificationsModel.prototype.onItemSeen = function ( item, isSeen ) {
- var id = item && item.getId(),
- unseenItem = id && this.unseenNotifications.getItemById( id );
-
- if ( unseenItem ) {
- if ( isSeen ) {
- this.unseenNotifications.removeItems( [ unseenItem ] );
- } else {
- this.unseenNotifications.addItems( [ unseenItem ] );
- }
- this.emit( 'unseenChange', this.unseenNotifications.getItems() );
- }
- };
-
- /**
- * Respond to item read state change
- *
- * @param {mw.echo.dm.NotificationItem} item Notification item
- * @param {boolean} isRead Notification is read
- * @fires unreadChange
- */
- mw.echo.dm.NotificationsModel.prototype.onItemRead = function ( item, isRead ) {
- var id = item && item.getId(),
- unreadItem = id && this.unreadNotifications.getItemById( id );
-
- if ( unreadItem ) {
- if ( isRead ) {
- this.markItemReadInApi( id );
- this.unreadNotifications.removeItems( [ unreadItem ] );
- } else {
- this.unreadNotifications.addItems( [ unreadItem ] );
- }
- this.emit( 'unreadChange', this.unreadNotifications.getItems() );
- }
- };
-
- /**
- * Get the type of the notifications that this model deals with.
- * Notifications type are given from the API: 'alert', 'message', 'all'
- *
- * @return {string} Notifications type
- */
- mw.echo.dm.NotificationsModel.prototype.getType = function () {
- return this.type;
- };
-
- /**
- * Get the counter of how many notifications are unseen
- *
- * @return {number} Number of unseen notifications
- */
- mw.echo.dm.NotificationsModel.prototype.getUnseenCount = function () {
- return this.unseenNotifications.getItemCount();
- };
-
- /**
- * Get the counter of how many notifications are unread
- *
- * @return {number} Number of unread notifications
- */
- mw.echo.dm.NotificationsModel.prototype.getUnreadCount = function () {
- return this.unreadNotifications.getItemCount();
- };
-
- /**
- * Set the system seen time - the last time we've marked notification as seen
- *
- * @private
- * @param {string} Mediawiki seen timestamp in Mediawiki timestamp format
- */
- mw.echo.dm.NotificationsModel.prototype.setSeenTime = function ( time ) {
- this.seenTime[this.type] = time;
- };
-
- /**
- * Get the system seen time
- *
- * @return {string} Mediawiki seen timestamp in Mediawiki timestamp format
- */
- mw.echo.dm.NotificationsModel.prototype.getSeenTime = function () {
- return this.seenTime[this.type];
- };
-
- /**
- * Check whether the model is fetching notifications from the API
- *
- * @return {boolean} The model is in the process of fetching from the API
- */
- mw.echo.dm.NotificationsModel.prototype.isFetchingNotifications = function () {
- return !!this.fetchNotificationsPromise;
- };
-
- /**
- * Check whether the model has an api error state flagged
- *
- * @return {boolean} The model is in api error state
- */
- mw.echo.dm.NotificationsModel.prototype.isFetchingErrorState = function () {
- return !!this.apiErrorState;
- };
-
- /**
- * Return the fetch notifications promise
- * @return {jQuery.Promise} Promise that is resolved when notifications were
- * fetched from the API.
- */
- mw.echo.dm.NotificationsModel.prototype.getFetchNotificationPromise = function () {
- return this.fetchNotificationsPromise;
- };
-
- /**
- * Update the seen timestamp
- *
- * @return {jQuery.Promise} A promise that resolves with the seen timestamp
- * @fires updateSeenTime
- */
- mw.echo.dm.NotificationsModel.prototype.updateSeenTime = function () {
- var i, len,
- model = this,
- items = this.unseenNotifications.getItems();
-
- // Update the notifications seen status
- for ( i = 0, len = items.length; i < len; i++ ) {
- items[i].toggleSeen( true );
- }
- this.emit( 'updateSeenTime' );
-
- return this.api.postWithToken( 'edit', {
- action: 'echomarkseen',
- type: this.type
- } )
- .then( function ( data ) {
- var time = data.query.echomarkseen.timestamp;
-
- // Update seen time from the server
- model.setSeenTime( time );
- } );
- };
-
- /**
- * Mark all notifications as read
- *
- * @return {jQuery.Promise} A promise that resolves when all notifications
- * were marked as read.
- */
- mw.echo.dm.NotificationsModel.prototype.markAllRead = function () {
- var model = this,
- data = {
- action: 'echomarkread',
- uselang: this.userLang,
- sections: this.type
- };
-
- if ( !this.unreadNotifications.getItemCount() ) {
- return $.Deferred().resolve( 0 ).promise();
- }
-
- return this.api.postWithToken( 'edit', data )
- .then( function ( result ) {
- return result.query.echomarkread[model.type].rawcount || 0;
- } )
- .then( function () {
- var i, len,
- items = model.unreadNotifications.getItems();
-
- for ( i = 0, len = items.length; i < len; i++ ) {
- items[i].toggleRead( true );
- items[i].toggleSeen( true );
- }
- model.unreadNotifications.clearItems();
- } );
- };
-
- /**
- * Update the read status of a notification item in the API
- *
- * @param {string} itemId Item id
- * @return {jQuery.Promise} A promise that resolves when the notifications
- * were marked as read.
- */
- mw.echo.dm.NotificationsModel.prototype.markItemReadInApi = function ( itemId ) {
- var model = this,
- data = {
- action: 'echomarkread',
- uselang: this.userLang,
- list: itemId
- };
-
- if ( !this.unreadNotifications.getItemCount() ) {
- return $.Deferred().resolve( 0 ).promise();
- }
-
- return this.api.postWithToken( 'edit', data )
- .then( function ( result ) {
- return result.query.echomarkread[model.type].rawcount || 0;
- } );
- };
-
- /**
- * Fetch notifications from the API and update the notifications list.
- *
- * @param {jQuery.Promise} An existing promise querying the API for notifications.
- * This allows us to send an API request external to the DM and have the model
- * handle the operation as if it asked for the request itself, updating all that
- * needs to be updated and emitting all proper events.
- * @return {jQuery.Promise} A promise that resolves with an array of notification
- * id's.
- */
- mw.echo.dm.NotificationsModel.prototype.fetchNotifications = function ( apiPromise ) {
- var model = this,
- params = $.extend( { notsections: this.type }, mw.echo.apiCallParams );
-
- // Rebuild the notifications promise either when it is null or when
- // it exists in a failed state
- if ( !this.fetchNotificationsPromise || this.isFetchingErrorState() ) {
- this.apiErrorState = false;
- this.fetchNotificationsPromise = ( apiPromise || this.api.get( params ) )
- .then( function ( result ) {
- var notifData, i, len, $content, wasSeen, wasRead, notificationModel,
- optionItems = [],
- idArray = [],
- data = result.query.notifications[model.type];
-
- for ( i = 0, len = data.index.length; i < len; i++ ) {
- notifData = data.list[ data.index[i] ];
- if ( model.getItemById( notifData.id ) ) {
- // Skip if we already have the item
- continue;
- }
- // TODO: This should really be formatted better, and the OptionWidget
- // should be the one that displays whatever icon relates to this notification
- // according to its type.
- $content = $( $.parseHTML( notifData['*'] ) );
-
- wasRead = !!notifData.read;
- wasSeen = notifData.timestamp.mw <= model.getSeenTime();
- notificationModel = new mw.echo.dm.NotificationItem(
- notifData.id,
- {
- read: wasRead,
- seen: wasSeen,
- timestamp: notifData.timestamp.mw,
- category: notifData.category,
- content: $content,
- // Hack: Get the primary link from the $content
- primaryUrl: $content.find( '.mw-echo-notification-primary-link' ).attr( 'href' )
- }
- );
-
- idArray.push( notifData.id );
- optionItems.push( notificationModel );
- }
- model.addItems( optionItems, 0 );
-
- return idArray;
- } )
- .fail( function () {
- // Mark API error state
- model.apiErrorState = true;
- } )
- .always( function ( idArray ) {
- model.fetchNotificationsPromise = null;
-
- return idArray;
- } );
- }
- return this.fetchNotificationsPromise;
- };
-
- /**
- * Update the unread and unseen tracking lists when we add items
- *
- * @param {mw.echo.dm.NotificationItem[]} items Items to add
- * @param {number} index Index to add items at
- */
- mw.echo.dm.NotificationsModel.prototype.addItems = function ( items, index ) {
- var i, len;
-
- for ( i = 0, len = items.length; i < len; i++ ) {
- if ( !items[i].isRead() ) {
- this.unreadNotifications.addItems( [ items[i] ] );
- }
- if ( !items[i].isSeen() ) {
- this.unseenNotifications.addItems( [ items[i] ] );
- }
- }
-
- // Parent
- mw.echo.dm.List.prototype.addItems.call( this, items, index );
- };
-
- /**
- * Update the unread and unseen tracking lists when we remove items
- *
- * @param {mw.echo.dm.NotificationItem[]} items Items to remove
- * @param {number} index Index to add items at
- */
- mw.echo.dm.NotificationsModel.prototype.removeItems = function ( items ) {
- var i, len;
-
- for ( i = 0, len = items.length; i < len; i++ ) {
- this.unreadNotifications.removeItems( [ items[i] ] );
- this.unseenNotifications.removeItems( [ items[i] ] );
- }
-
- // Parent
- mw.echo.dm.List.prototype.removeItems.call( this, items );
- };
-
- /**
- * Update the unread and unseen tracking lists when we clear items
- */
- mw.echo.dm.NotificationsModel.prototype.clearItems = function () {
- this.unreadNotifications.clearItems();
- this.unseenNotifications.clearItems();
-
- // Parent
- mw.echo.dm.List.prototype.clearItems.call( this );
- };
-
- /**
- * Query the API for unread count of the notifications in this model
- *
- * @return {jQuery.Promise} jQuery promise that's resolved when the unread count is fetched
- * and the badge label is updated.
- */
- mw.echo.dm.NotificationsModel.prototype.fetchUnreadCountFromApi = function () {
- var apiData = {
- action: 'query',
- meta: 'notifications',
- notsections: this.getType(),
- notmessageunreadfirst: 1,
- notlimit: this.limit,
- notprop: 'index|count',
- uselang: this.userLang
- };
-
- return this.api.get( apiData )
- .then( function ( result ) {
- return OO.getProp( result.query, 'notifications', 'rawcount' ) || 0;
- } );
- };
-} )( mediaWiki, jQuery );
diff --git a/Echo/modules/viewmodel/mw.echo.dm.js b/Echo/modules/viewmodel/mw.echo.dm.js
deleted file mode 100644
index e7d7c702..00000000
--- a/Echo/modules/viewmodel/mw.echo.dm.js
+++ /dev/null
@@ -1,4 +0,0 @@
-( function ( mw ) {
- mw.echo = mw.echo || {};
- mw.echo.dm = {};
-} )( mediaWiki );
diff --git a/Echo/package.json b/Echo/package.json
index f7128dbe..bd5d5e98 100644
--- a/Echo/package.json
+++ b/Echo/package.json
@@ -1,20 +1,21 @@
{
- "name": "echo",
- "version": "0.0.1",
- "private": true,
- "description": "Build tools for Echo.",
- "scripts": {
- "test": "grunt test"
- },
- "devDependencies": {
- "grunt": "0.4.5",
- "grunt-cli": "0.1.13",
- "grunt-contrib-csslint": "0.4.0",
- "grunt-contrib-jshint": "0.11.3",
- "grunt-contrib-watch": "0.6.1",
- "grunt-banana-checker": "0.2.2",
- "grunt-jscs": "1.8.0",
- "jshint": "2.8.0",
- "grunt-jsonlint": "1.0.4"
- }
+ "name": "echo",
+ "version": "0.0.1",
+ "private": true,
+ "description": "Build tools for Echo.",
+ "scripts": {
+ "test": "grunt test",
+ "doc": "jsduck"
+ },
+ "devDependencies": {
+ "eslint-config-wikimedia": "0.4.0",
+ "grunt": "1.0.1",
+ "grunt-banana-checker": "0.5.0",
+ "grunt-contrib-watch": "1.0.0",
+ "grunt-eslint": "19.0.0",
+ "grunt-jsonlint": "1.0.8",
+ "grunt-stylelint": "0.7.0",
+ "stylelint": "7.8.0",
+ "stylelint-config-wikimedia": "0.4.1"
+ }
}
diff --git a/Echo/phpcs.xml b/Echo/phpcs.xml
new file mode 100644
index 00000000..2adc8f65
--- /dev/null
+++ b/Echo/phpcs.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<ruleset name="MediaWiki">
+ <file>.</file>
+ <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
+ <exclude name="Generic.Files.LineLength.TooLong" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.ExtraParamComment" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingParamComment" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingParamName" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingParamTag" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingReturn" />
+ <exclude name="MediaWiki.Files.ClassMatchesFilename.NotMatch" />
+ <exclude name="MediaWiki.Files.ClassMatchesFilename.WrongCase" />
+ <exclude name="MediaWiki.Files.OneClassPerFile.MultipleFound" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationProtected" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPublic" />
+ <exclude name="MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName" />
+ <exclude name="MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment" />
+ </rule>
+ <arg name="encoding" value="UTF-8" />
+ <arg name="extensions" value="php,php5,inc" />
+ <arg name="colors" />
+</ruleset>
diff --git a/Echo/scripts/gen-autoload.php b/Echo/scripts/gen-autoload.php
index 38290ff2..d6be1612 100644
--- a/Echo/scripts/gen-autoload.php
+++ b/Echo/scripts/gen-autoload.php
@@ -1,24 +1,46 @@
<?php
-require_once __DIR__ . '/../../../includes/utils/AutoloadGenerator.php';
-
-function main() {
- $base = dirname( __DIR__ );
- $generator = new AutoloadGenerator( $base );
- $dirs = array(
- 'includes',
- 'tests',
- );
- foreach ( $dirs as $dir ) {
- $generator->readDir( $base . '/' . $dir );
- }
- foreach ( glob( $base . '/*.php' ) as $file ) {
- $generator->readFile( $file );
+// Keep in sync with same script in Flow.
+
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
+ ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
+
+/**
+ * Generates Echo autoload info
+ */
+
+class GenerateEchoAutoload extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Generates Echo autoload data';
}
- $generator->generateAutoload( basename( __DIR__ ) . '/' . basename( __FILE__ ) );
+ public function execute() {
+ $base = dirname( __DIR__ );
+ $generator = new AutoloadGenerator( $base );
+ $dirs = [
+ 'includes',
+ 'tests',
+ 'maintenance',
+ ];
+ foreach ( $dirs as $dir ) {
+ $generator->readDir( $base . '/' . $dir );
+ }
+ foreach ( glob( $base . '/*.php' ) as $file ) {
+ $generator->readFile( $file );
+ }
- echo "Done.\n\n";
+ $target = $generator->getTargetFileInfo();
+
+ file_put_contents(
+ $target['filename'],
+ $generator->getAutoload( basename( __DIR__ ) . '/' . basename( __FILE__ ) )
+ );
+
+ echo "Done.\n\n";
+ }
}
-main();
+$maintClass = "GenerateEchoAutoload";
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Echo/scripts/generatecss.php b/Echo/scripts/generatecss.php
index ed67a4fa..ed6496d8 100644
--- a/Echo/scripts/generatecss.php
+++ b/Echo/scripts/generatecss.php
@@ -1,5 +1,5 @@
<?php
-if ( sizeof( $argv ) < 3 ) {
+if ( count( $argv ) < 3 ) {
print "Call with 2 arguments: the path to the load url and the file to output to";
exit();
}
@@ -9,15 +9,14 @@ $outputFile = $argv[2];
define( 'MEDIAWIKI', true );
const NS_MAIN = 0;
$wgVersion = 1.23;
-$wgSpecialPages = array();
-$wgResourceModules = array();
+$wgSpecialPages = [];
+$wgResourceModules = [];
include "Resources.php";
-$query = array();
-$blacklist = array(
-);
-foreach( $wgResourceModules as $moduleName => $def ) {
+$query = [];
+$blacklist = [];
+foreach ( $wgResourceModules as $moduleName => $def ) {
if ( !in_array( $moduleName, $blacklist ) ) {
$query[] = $moduleName;
}
@@ -25,5 +24,5 @@ foreach( $wgResourceModules as $moduleName => $def ) {
$url = $loadUrl . '?only=styles&skin=vector&modules=' . implode( $query, '|' );
echo $url;
-$css = file_get_contents($url);
+$css = file_get_contents( $url );
file_put_contents( $outputFile, $css );
diff --git a/Echo/scripts/qunit.sh b/Echo/scripts/qunit.sh
deleted file mode 100755
index 4af3391c..00000000
--- a/Echo/scripts/qunit.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-echo "Running QUnit tests..."
-if command -v phantomjs > /dev/null ; then
- URL=${MEDIAWIKI_URL:-"http://127.0.0.1:80/w/index.php/"}
- echo "Using $URL as a development environment host."
- echo "Please ensure \$wgEnableJavaScriptTest = true; in your LocalSettings.php"
- echo "To specify a different host set MEDIAWIKI_URL environment variable"
- echo '(e.g. by running "export MEDIAWIKI_URL=http://127.0.0.1:80/w/index.php/")'
- phantomjs tests/externals/phantomjs-qunit-runner.js "${URL}Special:JavaScriptTest/qunit?filter=ext.echo"
-else
- echo "You need to install PhantomJS to run QUnit tests in terminal!"
- echo "See http://phantomjs.org/"
- exit 1
-fi
diff --git a/Echo/tests/NotificationsTest.php b/Echo/tests/NotificationsTest.php
index b9609238..cc7ddfe6 100644
--- a/Echo/tests/NotificationsTest.php
+++ b/Echo/tests/NotificationsTest.php
@@ -8,14 +8,16 @@
class NotificationsTest extends MediaWikiTestCase {
/** @var User $sysop */
+ // @codingStandardsIgnoreStart
var $sysop;
+ // @codingStandardsIgnoreEnd
- public function setUp() {
+ protected function setUp() {
parent::setUp();
$this->sysop = User::newFromName( 'UTSysop' );
$this->setMwGlobals( 'wgUser', $this->sysop );
-
}
+
/**
* Helper function to get a user's latest notification
* @param User $user
@@ -23,9 +25,11 @@ class NotificationsTest extends MediaWikiTestCase {
*/
public static function getLatestNotification( $user ) {
$notifs = ApiEchoNotifications::getNotifications( $user );
- $index = array_keys($notifs);
+ $index = array_keys( $notifs );
+
return EchoEvent::newFromID( $notifs[$index[0]]['id'] );
}
+
/**
* @covers EchoHooks::onUserRights
*/
@@ -38,14 +42,14 @@ class NotificationsTest extends MediaWikiTestCase {
$context->setUser( $this->sysop );
$ur = new UserrightsPage();
$ur->setContext( $context );
- $ur->doSaveUserGroups( $user, array('sysop'), array(), 'reason' );
+ $ur->doSaveUserGroups( $user, [ 'sysop' ], [], 'reason' );
$event = self::getLatestNotification( $user );
$this->assertEquals( $event->getType(), 'user-rights' );
$this->assertEquals( $this->sysop->getName(), $event->getAgent()->getName() );
$extra = $event->getExtra();
$this->assertArrayHasKey( 'add', $extra );
- $this->assertArrayEquals( array( 'sysop' ), $extra['add'] );
- $this->assertArrayEquals( array(), $extra['remove'] );
+ $this->assertArrayEquals( [ 'sysop' ], $extra['add'] );
+ $this->assertArrayEquals( [], $extra['remove'] );
}
}
diff --git a/Echo/tests/bootstrap.php b/Echo/tests/bootstrap.php
index cddd5d5a..d4852266 100644
--- a/Echo/tests/bootstrap.php
+++ b/Echo/tests/bootstrap.php
@@ -15,5 +15,4 @@ if ( $IP === false ) {
}
}
-require_once( $IP . "/tests/phpunit/bootstrap.php" );
-
+require_once $IP . "/tests/phpunit/bootstrap.php";
diff --git a/Echo/tests/browser/README.md b/Echo/tests/browser/README.md
new file mode 100644
index 00000000..36319498
--- /dev/null
+++ b/Echo/tests/browser/README.md
@@ -0,0 +1 @@
+Please see https://github.com/wikimedia/mediawiki-selenium for instructions on how to run tests.
diff --git a/Echo/tests/browser/ci.yml b/Echo/tests/browser/ci.yml
new file mode 100644
index 00000000..c2eca934
--- /dev/null
+++ b/Echo/tests/browser/ci.yml
@@ -0,0 +1,9 @@
+BROWSER:
+ - chrome
+ - firefox
+
+MEDIAWIKI_ENVIRONMENT:
+ - beta
+
+PLATFORM:
+ - Linux
diff --git a/Echo/tests/browser/environments.yml b/Echo/tests/browser/environments.yml
new file mode 100644
index 00000000..c32e21bb
--- /dev/null
+++ b/Echo/tests/browser/environments.yml
@@ -0,0 +1,48 @@
+# Customize this configuration as necessary to provide defaults for various
+# test environments.
+#
+# The set of defaults to use is determined by the MEDIAWIKI_ENVIRONMENT
+# environment variable.
+#
+# export MEDIAWIKI_ENVIRONMENT=mw-vagrant-host
+# bundle exec cucumber
+#
+# Additional variables set by the environment will override the corresponding
+# defaults defined here.
+#
+# export MEDIAWIKI_ENVIRONMENT=mw-vagrant-host
+# export MEDIAWIKI_USER=Selenium_user2
+# bundle exec cucumber
+#
+mw-vagrant-host: &default
+ user_factory: true
+ mediawiki_url: http://127.0.0.1:8080/wiki/
+
+mw-vagrant-guest:
+ user_factory: true
+ mediawiki_url: http://127.0.0.1/wiki/
+
+local:
+ mediawiki_user: Admin
+ mediawiki_password: vagrant
+ mediawiki_user_b: Selenium Echo user 2
+ mediawiki_url: http://dev.wiki.local.wmftest.net:8080/wiki/
+
+beta:
+ mediawiki_url: https://en.wikipedia.beta.wmflabs.org/wiki/
+ mediawiki_user: Selenium_user
+ mediawiki_user_b: Selenium Echo user 2
+ # mediawiki_password: SET THIS IN THE ENVIRONMENT!
+
+test2:
+ mediawiki_url: https://test2.wikipedia.org/wiki/
+ mediawiki_user: Selenium_user
+ mediawiki_user_b: Selenium Echo user 2
+ # mediawiki_password: SET THIS IN THE ENVIRONMENT!
+
+integration:
+ browser: chrome
+ user_factory: true
+ # mediawiki_url: THIS WILL BE SET BY JENKINS
+
+default: *default
diff --git a/Echo/tests/browser/features/flyout.feature b/Echo/tests/browser/features/flyout.feature
deleted file mode 100644
index 43072350..00000000
--- a/Echo/tests/browser/features/flyout.feature
+++ /dev/null
@@ -1,17 +0,0 @@
-@chrome @en.wikipedia.beta.wmflabs.org @firefox @login @test2.wikipedia.org
-Feature: Flyout
-
- Background:
- Given I am on the "Selenium Echo flyout test page" page
-
- Scenario: Flyout button not present when anon
- Then I do not see the notification flyout button
-
- Scenario: Flyout button present
- Given I am logged in
- Then I see the notification flyout button
-
- Scenario: Flyout button present
- Given I am logged in
- When I click the notification flyout button
- Then I see the notification flyout
diff --git a/Echo/tests/browser/features/flyout_nojs.feature b/Echo/tests/browser/features/flyout_nojs.feature
deleted file mode 100644
index 5fc2894d..00000000
--- a/Echo/tests/browser/features/flyout_nojs.feature
+++ /dev/null
@@ -1,12 +0,0 @@
-@custom-browser @en.wikipedia.beta.wmflabs.org @firefox @login @test2.wikipedia.org
-Feature: Flyout (nojs)
-
- Background:
- Given I am using user agent "Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)"
- And I am on the "Selenium Echo flyout test page" page
-
- Scenario: Flyout button present
- Given I am logged in
- When I click the notification flyout button
- Then I am on the Special Notifications page
- And I see the first heading on the page says Notifications
diff --git a/Echo/tests/browser/features/messages.feature b/Echo/tests/browser/features/messages.feature
deleted file mode 100644
index e17df3e1..00000000
--- a/Echo/tests/browser/features/messages.feature
+++ /dev/null
@@ -1,15 +0,0 @@
-@chrome @en.wikipedia.beta.wmflabs.org @firefox @login @test2.wikipedia.org
-Feature: Scenarios that trigger notifications
-
- Scenario: Mark all as read
- Given I am logged in with no notifications
- And I have a Flow message that triggers an alert notification
- And another user mentions me on the wiki
- And I am on the "Selenium Echo flyout test page" page
- And I have new notifications
- And I click the notification flyout button
- And I see the notification flyout
- And I click for the Messages view
- When I click the mark all as read button
- And I am on the "Selenium Echo flyout test page" page
- Then I have no new notifications
diff --git a/Echo/tests/browser/features/no_javascript.feature b/Echo/tests/browser/features/no_javascript.feature
new file mode 100644
index 00000000..a8b318ed
--- /dev/null
+++ b/Echo/tests/browser/features/no_javascript.feature
@@ -0,0 +1,11 @@
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @localhost @vagrant
+Feature: Basic features for no-js functionality
+
+ Background:
+ Given I am using a nojs browser
+
+ Scenario: Clicking alerts badge goes to Special:Notifications
+ Given I am logged in
+ When I click the alert badge
+ And I wait for the page to load
+ Then I am on Special Notifications page
diff --git a/Echo/tests/browser/features/notifications.feature b/Echo/tests/browser/features/notifications.feature
index 58feec9e..3d443a7d 100644
--- a/Echo/tests/browser/features/notifications.feature
+++ b/Echo/tests/browser/features/notifications.feature
@@ -1,40 +1,22 @@
-@chrome @en.wikipedia.beta.wmflabs.org @firefox @login @test2.wikipedia.org
-Feature: Notification types
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @localhost @vagrant
+Feature: Testing notification types
- # Scenarios which trigger notifications
- Scenario: Someone links to a page I created
- Given I am logged in with no notifications
- And another user has linked to a page I created from another page
- And I reload the page 5 times or until a notification shows up
- When I am on the "Selenium Echo flyout test page" page
- Then I have new notifications
+ Background:
+ Given I am logged in
+ And all my notifications are read
- Scenario: Mention message triggers notification
- Given I am logged in with no notifications
- And another user mentions me on the wiki
- And I reload the page 5 times or until a notification shows up
- When I am on the "Selenium Echo flyout test page" page
- Then I have new notifications
+ Scenario: Someone mentions me
+ Given another user mentions me
+ When I refresh the page
+ Then the alert badge is showing unseen notifications
+ And the alert badge value is "Alert (1)"
- Scenario: Talk page message triggers talk notification
- Given I am logged in with no notifications
- # And I do not have Flow boards enabled on the user talk namespace
- And another user writes on my talk page
- And I reload the page 5 times or until a notification shows up
- When I am on the "Selenium Echo flyout test page" page
- Then I have new notifications
-
- Scenario: New user gets a sign up notification
- Given I am logged in as a new user
- And I am on the "Selenium Echo flyout test page" page
- Then I have new notifications
-
- Scenario: Page revert
- # Too hard. Will do later.
-
- # Scenarios which do not trigger notifications (but might be expected to)
- Scenario: The @ message is not a keyword
- Given I am logged in with no notifications
- And another user @s me on "Talk:Echo at test"
- When I am on the "Selenium Echo flyout test page" page
- Then I have no new notifications
+ @skip
+ Scenario: Someone writes on my talk page
+ Given another user writes on my talk page
+ When I refresh the page
+ Then the alert badge is showing unseen notifications
+ And the alert badge value is "Alert (1)"
+ When I click the alert badge
+ And I see the alert popup
+ Then there are "1" unread notifications in the alert popup
diff --git a/Echo/tests/browser/features/notifications_userrights.feature b/Echo/tests/browser/features/notifications_userrights.feature
deleted file mode 100644
index 0e947e70..00000000
--- a/Echo/tests/browser/features/notifications_userrights.feature
+++ /dev/null
@@ -1,10 +0,0 @@
-@chrome @firefox @login
-Feature: User rights
-
- Scenario: Change in user rights
- Given I am logged in as a new user with no notifications
- # This step requires user rights. Selenium user doesn't have sufficient user rights on beta labs.
- When my user rights get changed
- And I come back from grabbing a cup of coffee
- And I am on the "Selenium Echo flyout test page" page
- Then I have new notifications
diff --git a/Echo/tests/browser/features/step_definition/badge_steps.rb b/Echo/tests/browser/features/step_definition/badge_steps.rb
new file mode 100644
index 00000000..82590cb1
--- /dev/null
+++ b/Echo/tests/browser/features/step_definition/badge_steps.rb
@@ -0,0 +1,10 @@
+# Steps related to clicking and interacting with the badge
+# Work in both nojs and js version
+
+Given(/^I click the alert badge$/) do
+ on(ArticlePage).alerts_element.when_present.click
+end
+
+Given(/^I click the notice badge$/) do
+ on(ArticlePage).notices_element.when_present.click
+end
diff --git a/Echo/tests/browser/features/step_definition/no_javascript.rb b/Echo/tests/browser/features/step_definition/no_javascript.rb
new file mode 100644
index 00000000..5cf97b1b
--- /dev/null
+++ b/Echo/tests/browser/features/step_definition/no_javascript.rb
@@ -0,0 +1,21 @@
+# This test has no javascript
+# Therefore this test has no AJAX
+# Therefore it should run without any "when_present" clauses
+# If you need a "when_present" to make the test run, that is a bug
+
+Given(/^I am using a nojs browser$/) do
+ # The following user-agent string contains:
+ # SymbianOS: for RL to NOT load the modern experience
+ # SMART-TV-SamsungBrowser: to bypass mobile-frontend and stay on the desktop site
+ browser_factory.override(browser_user_agent: 'SymbianOS,SMART-TV-SamsungBrowser')
+end
+
+Given(/^I wait for the page to load$/) do
+ # Wait for the page to load. We're technically clicking the <li> rather than <a>,
+ # so the special-case implicit wait after clicking links doesn't kick in.
+ browser.wait
+end
+
+Given(/^I am on Special Notifications page$/) do
+ expect(on(SpecialNotificationsPage).firstHeading).to match('Notifications')
+end
diff --git a/Echo/tests/browser/features/step_definition/notifications_steps.rb b/Echo/tests/browser/features/step_definition/notifications_steps.rb
new file mode 100644
index 00000000..5557c5db
--- /dev/null
+++ b/Echo/tests/browser/features/step_definition/notifications_steps.rb
@@ -0,0 +1,76 @@
+Given(/^all my notifications are read$/) do
+ clear_unread_notifications(@username)
+end
+
+Given(/^I refresh the page$/) do
+ on(ArticlePage) do |page|
+ page.refresh
+ end
+end
+
+Given(/^another user mentions me$/) do
+ message = '===Mention test===\nI am mentioning [[User:' + user(nil) +
+ ']] in this page to test Echo notifications. ~~~~'
+ as_user(:b) do
+ api.create_page(
+ @data_manager.get('Echo_test_page'),
+ message
+ )
+ end
+end
+
+Given(/^another user writes on my talk page$/) do
+ talk_page = "User_talk:#{user}"
+ message = '===Talk page test===\n' +
+ 'I am writing a message in your user page to test Echo notifications. ~~~~'
+ as_user(:b) do
+ api.create_page(talk_page, message)
+ end
+end
+
+Given(/^the alert badge is showing unseen notifications$/) do
+ on(ArticlePage) do |page|
+ page.refresh_until do
+ page.alerts.badge_unseen_element.exists?
+ end
+ end
+end
+
+Given(/^the notice badge is showing unseen notifications$/) do
+ on(ArticlePage) do |page|
+ page.refresh_until do
+ page.notices.badge_unseen_element.exists?
+ end
+ end
+end
+
+Given(/^the alert badge value is "(.+)"$/) do |num|
+ on(ArticlePage) do |page|
+ page.refresh_until do
+ # `.text` doesn't work for invisible elements, and Selenium thinks the badge is invisible
+ page.alerts.badge_element.attribute('innerText') == num
+ end
+ end
+end
+
+Given(/^the notice badge value is "(.+)"$/) do |num|
+ on(ArticlePage) do |page|
+ page.refresh_until do
+ page.notices.badge_element.attribute('innerText') == num
+ end
+ end
+end
+
+Given(/^there are "(.+)" unread notifications in the notice popup$/) do |num|
+ on(ArticlePage) do |page|
+ page.notices.when_loaded
+ expect(page.notices.num_unread_notifications).to eq(num.to_i)
+ end
+end
+
+Given(/^there are "(.+)" unread notifications in the alert popup$/) do |num|
+ on(ArticlePage) do |page|
+ page.alerts.when_loaded
+ expect(page.alerts.num_unread_notifications).to eq(num.to_i)
+ end
+end
diff --git a/Echo/tests/browser/features/step_definition/popup_steps.rb b/Echo/tests/browser/features/step_definition/popup_steps.rb
new file mode 100644
index 00000000..e6c8f0f0
--- /dev/null
+++ b/Echo/tests/browser/features/step_definition/popup_steps.rb
@@ -0,0 +1,11 @@
+Given(/^I see the alert popup$/) do
+ on(ArticlePage) do |page|
+ expect(page.alerts.title_element.when_present.text).to match('Alerts')
+ end
+end
+
+Given(/^I see the message popup$/) do
+ on(ArticlePage) do |page|
+ expect(page.messages.title_element.when_present.text).to match('Messages')
+ end
+end
diff --git a/Echo/tests/browser/features/step_definitions/common_steps.rb b/Echo/tests/browser/features/step_definitions/common_steps.rb
deleted file mode 100644
index ca57e136..00000000
--- a/Echo/tests/browser/features/step_definitions/common_steps.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-def new_username
- "EchoUserNew#{@random_string}"
-end
-
-def session_username
- "#{ENV['MEDIAWIKI_USER']}_#{@browser.name}"
-end
-
-def session_username_b
- 'EchoUser'
-end
-
-Given(/^I am logged in as the user "(.*?)"$/) do |username|
- step 'the user "' + username + '" exists'
- visit(LoginPage).login_with(username, ENV['MEDIAWIKI_PASSWORD'])
-end
-
-# Note Echo redefines this so that the user is unique to the current browser
-Given(/^I am logged in my non-shared account$/) do
- username = session_username
- step 'I am logged in as the user "' + username + '"'
-end
-
-Given(/^I am on the "(.+)" page$/) do |title|
- on(APIPage).create title, 'Test is used by Selenium web driver'
- visit(ArticlePage, using_params: { article_name: title })
-end
-
-Given(/^I am using user agent "(.+)"$/) do |user_agent|
- @user_agent = user_agent
- @browser = browser(test_name(@scenario), user_agent: user_agent)
- $session_id = @browser.driver.instance_variable_get(:@bridge).session_id
-end
-
-Given(/^my user rights get changed$/) do
- @username = new_username
- client = on(APIPage).client
- client.log_in(ENV['MEDIAWIKI_USER'], ENV['MEDIAWIKI_PASSWORD'])
- resp = client.query(action: 'query', list: 'users', ususers: @username, ustoken: 'userrights')
- data = resp.data
- @token = data['users'][0]['userrightstoken']
- client.action('userrights', token_type: false, token: @token, add: 'bot', user: @username)
-end
-
-Given(/^the user "(.*?)" exists$/) do |username|
- on(APIPage).client.log_in(ENV['MEDIAWIKI_USER'], ENV['MEDIAWIKI_PASSWORD'])
- begin
- on(APIPage).client.create_account(username, ENV['MEDIAWIKI_PASSWORD'])
- puts 'Successfully created user ' + username
- rescue MediawikiApi::ApiError
- puts 'Assuming in step that user ' + username + ' already exists since was unable to create.'
- end
-end
-
-Then(/^I am on the Special Notifications page$/) do
- expect(@browser.url).to match 'Special:Notifications'
-end
-
-Then(/^I see the first heading on the page says Notifications$/) do
- expect(on(ArticlePage).first_heading).to eq 'Notifications'
-end
diff --git a/Echo/tests/browser/features/step_definitions/flyout_steps.rb b/Echo/tests/browser/features/step_definitions/flyout_steps.rb
deleted file mode 100644
index 7474f6b2..00000000
--- a/Echo/tests/browser/features/step_definitions/flyout_steps.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-When(/^I click the notification flyout button$/) do
- # Sleep works around Chrome 40 issue that began
- # ~2015-03-04
- sleep 1
- on(ArticlePage).flyout_link_element.when_present.click
-end
-
-Then(/^I do not see the notification flyout button$/) do
- expect(on(ArticlePage).flyout_link_container_element).not_to be_visible
-end
-
-Then(/^I see the notification flyout$/) do
- expect(on(ArticlePage).flyout_element.when_present).to be_visible
-end
-
-Then(/^I see the notification flyout button$/) do
- expect(on(ArticlePage).flyout_link_container_element.when_present).to be_visible
-end
diff --git a/Echo/tests/browser/features/step_definitions/messages_steps.rb b/Echo/tests/browser/features/step_definitions/messages_steps.rb
deleted file mode 100644
index d8d61034..00000000
--- a/Echo/tests/browser/features/step_definitions/messages_steps.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-Given(/^I click for the Messages view$/) do
- on(ArticlePage).messages_view_link_element.when_present.click
-end
-
-Given(/^I have a Flow message that triggers an alert notification$/) do
- client = on(APIPage).client
- username = session_username_b
- step 'the user "' + username + '" exists'
- client.log_in(username, ENV['MEDIAWIKI_PASSWORD'])
- client.action(
- 'flow', token_type: 'edit', submodule: 'new-topic', page: 'Talk:Flow QA', nttopic: 'Mention #1',
- ntcontent: '[[User:' + session_username + ']] I wanted to say hello.')
-end
-
-When(/^I click the mark all as read button$/) do
- on(ArticlePage).mark_as_read_element.when_present.click
-end
diff --git a/Echo/tests/browser/features/step_definitions/notifications_steps.rb b/Echo/tests/browser/features/step_definitions/notifications_steps.rb
deleted file mode 100644
index 01ba8512..00000000
--- a/Echo/tests/browser/features/step_definitions/notifications_steps.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-def make_page_with_user(title, text, username)
- client = on(APIPage).client
- client.log_in(username, ENV['MEDIAWIKI_PASSWORD'])
- client.create_page(title, text)
-end
-
-def clear_notifications(username)
- client = on(APIPage).client
- step 'the user "' + username + '" exists'
- client.log_in(username, ENV['MEDIAWIKI_PASSWORD'])
- client.action('echomarkread', token_type: 'edit', all: '1')
-end
-
-def make_page_with_user_b(title, text)
- username = session_username_b
- step 'the user "' + username + '" exists'
- make_page_with_user(title, text, username)
-end
-
-def make_page_with_user_a(title, text)
- make_page_with_user(title, text, session_username)
-end
-
-def poll_for_new_notifications(number_of_polls)
- number_of_polls.to_i.times do
- step 'I am on the "Selenium Echo flyout test page" page'
- break if on(ArticlePage).flyout_link_element.class_name =~ /mw-echo-unseen-notifications/
- end
-end
-
-Given(/^another user has linked to a page I created from another page$/) do
- title = 'Selenium Echo link test ' + @random_string
- make_page_with_user_a(title, 'Selenium test page. Feel free to delete me.')
- title2 = title + ' ' + @random_string
- make_page_with_user_b(title2, 'I am linking to [[' + title + ']].')
-end
-
-Given(/^another user writes on my talk page$/) do
- make_page_with_user_b(
- 'User talk:' + session_username,
- "== Barnstar ==\nHello Selenium, here is a barnstar for all your testing! " +
- @random_string + "~~~~\n")
-end
-
-Given(/^another user @s me on "(.*?)"$/) do |title|
- username = session_username.sub('_', ' ')
- text = '@' + username + ' Cho cho cho. ~~~~'
- make_page_with_user_b(title, text)
-end
-
-Given(/^I reload the page (.*?) times or until a notification shows up$/) do |number_of_polls|
- poll_for_new_notifications(number_of_polls)
-end
-
-Given(/^another user mentions me on the wiki$/) do
- title = 'Selenium Echo mention test ' + @random_string
- username = session_username.sub('_', ' ')
- text = "== The walrus ==\n[[User:" + username + "]]: Cho cho cho. ~~~~\n"
- make_page_with_user_b(title, text)
-end
-
-Given(/^I am logged in as a new user$/) do
- @username = new_username
- step 'I am logged in as the user "' + @username + '"'
-end
-
-Given(/^I am logged in as a new user with no notifications$/) do
- @username = new_username
- clear_notifications(@username)
- step 'I am logged in as the user "' + @username + '"'
-end
-
-Given(/^I am logged in with no notifications$/) do
- # Mark all messages as read
- client = on(APIPage).client
- username = session_username
- step 'the user "' + username + '" exists'
- client.log_in(username, ENV['MEDIAWIKI_PASSWORD'])
- client.action('echomarkread', token_type: 'edit', all: '1')
-
- step 'I am logged in my non-shared account'
- step 'I have no new notifications'
-end
-
-Then(/^I have no new notifications$/) do
- expect(on(ArticlePage).flyout_link_element.when_present.class_name).not_to match 'mw-echo-unseen-notifications'
-end
-
-Then(/^I have new notifications$/) do
- expect(on(ArticlePage).flyout_link_element.when_present.class_name).to match 'mw-echo-unseen-notifications'
-end
diff --git a/Echo/tests/browser/features/support/components/notifications.rb b/Echo/tests/browser/features/support/components/notifications.rb
new file mode 100644
index 00000000..6f8d5ab8
--- /dev/null
+++ b/Echo/tests/browser/features/support/components/notifications.rb
@@ -0,0 +1,21 @@
+class Notifications
+ include PageObject
+
+ link(:badge, css: '.mw-echo-notifications-badge')
+ link(:badge_unseen, css: '.mw-echo-unseen-notifications')
+ link(:mark_all_as_read, css: '.mw-echo-ui-notificationsListWidget-markAllReadButton > a')
+ div(:popup, css: '.mw-echo-ui-notificationBadgeButtonPopupWidget-popup')
+ span(:title, css: '.oo-ui-popupWidget-head > .oo-ui-labelElement-label')
+ div(
+ :notifications_container,
+ css: '.mw-echo-ui-notificationsListWidget > .mw-echo-ui-notificationItemWidget')
+
+ def when_loaded
+ title_element.when_present
+ notifications_container_element.when_present
+ end
+
+ def num_unread_notifications
+ div_elements(css: '.mw-echo-ui-notificationItemWidget-unread').size
+ end
+end
diff --git a/Echo/tests/browser/features/support/data_manager.rb b/Echo/tests/browser/features/support/data_manager.rb
new file mode 100644
index 00000000..0ff6d66c
--- /dev/null
+++ b/Echo/tests/browser/features/support/data_manager.rb
@@ -0,0 +1,11 @@
+# Data manager for Echo tests
+class DataManager
+ def initialize
+ @data = {}
+ end
+
+ def get(part)
+ @data[part] = "#{part}_#{Random.srand}" unless @data.key? part
+ @data[part]
+ end
+end
diff --git a/Echo/tests/browser/features/support/echo_api_helper.rb b/Echo/tests/browser/features/support/echo_api_helper.rb
new file mode 100644
index 00000000..77b7e5ab
--- /dev/null
+++ b/Echo/tests/browser/features/support/echo_api_helper.rb
@@ -0,0 +1,25 @@
+module EchoAPIHelper
+ def create_page_with_user(title, text, username)
+ as_user(username) do
+ api.create_page title, text
+ end
+ end
+
+ def clear_unread_notifications(username)
+ as_user(username) do
+ api.action('echomarkread', token_type: 'csrf', all: '1')
+ end
+ end
+
+ def update_seentime(username, notificationType)
+ as_user(username) do
+ api.action('echomarkseen', token_type: 'csrf', type: notificationType)
+ end
+ end
+
+ def watch_page(username, pageTitle)
+ as_user(username) do
+ api.action('watch', token_type: 'watch', title: pageTitle)
+ end
+ end
+end
diff --git a/Echo/tests/browser/features/support/echo_pageobject_extension.rb b/Echo/tests/browser/features/support/echo_pageobject_extension.rb
new file mode 100644
index 00000000..8e18a6e6
--- /dev/null
+++ b/Echo/tests/browser/features/support/echo_pageobject_extension.rb
@@ -0,0 +1,9 @@
+module PageObject
+ def refresh_until(timeout = PageObject.default_page_wait, message = nil)
+ platform.wait_until(timeout, message) do
+ yield.tap do |result|
+ refresh unless result
+ end
+ end
+ end
+end
diff --git a/Echo/tests/browser/features/support/env.rb b/Echo/tests/browser/features/support/env.rb
index cdbe1a44..d7dbf3e0 100644
--- a/Echo/tests/browser/features/support/env.rb
+++ b/Echo/tests/browser/features/support/env.rb
@@ -1,12 +1,10 @@
-require 'rubygems'
-require 'bundler/setup'
+require 'mediawiki_selenium/cucumber'
+require 'mediawiki_selenium/pages'
+require 'mediawiki_selenium/step_definitions'
-Bundler.require
-
-if ENV['PAGE_WAIT_TIMEOUT']
- PageObject.default_page_wait = ENV['PAGE_WAIT_TIMEOUT'].to_i
+def env_or_default(key, default)
+ ENV[key].nil? ? default : ENV[key].to_i
end
-if ENV['ELEMENT_WAIT_TIMEOUT']
- PageObject.default_element_wait = ENV['ELEMENT_WAIT_TIMEOUT'].to_i
-end
+PageObject.default_page_wait = env_or_default 'PAGE_WAIT_TIMEOUT', 60
+PageObject.default_element_wait = env_or_default 'ELEMENT_WAIT_TIMEOUT', 60
diff --git a/Echo/tests/browser/features/support/hooks.rb b/Echo/tests/browser/features/support/hooks.rb
index 7da02d58..0d84341d 100644
--- a/Echo/tests/browser/features/support/hooks.rb
+++ b/Echo/tests/browser/features/support/hooks.rb
@@ -1,3 +1,10 @@
# Allow running of bundle exec cucumber --dry-run -f stepdefs
require 'mediawiki_selenium'
require 'page-object'
+require_relative 'echo_api_helper'
+require_relative 'echo_pageobject_extension'
+require_relative 'data_manager'
+
+World(EchoAPIHelper)
+
+Before { @data_manager = DataManager.new }
diff --git a/Echo/tests/browser/features/support/pages/article_page.rb b/Echo/tests/browser/features/support/pages/article_page.rb
index d35f7330..25ffa043 100644
--- a/Echo/tests/browser/features/support/pages/article_page.rb
+++ b/Echo/tests/browser/features/support/pages/article_page.rb
@@ -1,16 +1,8 @@
-# Page Object describing Headings, Flyouts, and Overlay in Echo
class ArticlePage
include PageObject
- include URL
- page_url URL.url('<%=params[:article_name]%><%=params[:hash]%>')
- h1(:first_heading, id: 'firstHeading')
- li(:flyout_link_container, css: '#pt-notifications')
- a(:flyout_link, css: '#pt-notifications a')
- div(:flyout, css: '.mw-echo-overlay')
-
- # Overlay header
- a(:alert_tab_link, css: '.mw-echo-overlay-title ul li a', index: 1)
- button(:mark_as_read, css: '.mw-echo-notifications > button')
- a(:messages_view_link, css: '.mw-ui-active')
+ li(:alerts, css: '#pt-notifications-alert')
+ li(:notices, css: '#pt-notifications-notice')
+ page_section(:alerts, Notifications, css: '#pt-notifications-alert')
+ page_section(:notices, Notifications, css: '#pt-notifications-notice')
end
diff --git a/Echo/tests/browser/features/support/pages/special_notifications_page.rb b/Echo/tests/browser/features/support/pages/special_notifications_page.rb
new file mode 100644
index 00000000..3f6f0c25
--- /dev/null
+++ b/Echo/tests/browser/features/support/pages/special_notifications_page.rb
@@ -0,0 +1,8 @@
+# Special:Notifications page
+class SpecialNotificationsPage
+ include PageObject
+
+ page_url 'Special:Notifications'
+
+ h1(:firstHeading, css: '.firstHeading')
+end
diff --git a/Echo/tests/externals/phantomjs-qunit-runner.js b/Echo/tests/externals/phantomjs-qunit-runner.js
deleted file mode 100644
index 4b1d38b1..00000000
--- a/Echo/tests/externals/phantomjs-qunit-runner.js
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * QtWebKit-powered headless test runner using PhantomJS
- *
- * PhantomJS binaries: http://phantomjs.org/download.html
- * Requires PhantomJS 1.6+ (1.7+ recommended)
- *
- * Run with:
- * phantomjs runner.js [url-of-your-qunit-testsuite]
- *
- * e.g.
- * phantomjs runner.js http://localhost/qunit/test/index.html
- */
-
-/*jshint latedef:false */
-/*global phantom:false, require:false, console:false, window:false, QUnit:false */
-
-(function() {
- 'use strict';
-
- var args = require('system').args;
-
- // arg[0]: scriptName, args[1...]: arguments
- if (args.length !== 2) {
- console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite]');
- phantom.exit(1);
- }
-
- var url = args[1],
- page = require('webpage').create();
-
- // Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
- page.onConsoleMessage = function(msg) {
- console.log(msg);
- };
-
- page.onInitialized = function() {
- page.evaluate(addLogging);
- };
-
- page.onCallback = function(message) {
- var result,
- failed;
-
- if (message) {
- if (message.name === 'QUnit.done') {
- result = message.data;
- failed = !result || result.failed;
-
- phantom.exit(failed ? 1 : 0);
- }
- }
- };
-
- page.open(url, function(status) {
- if (status !== 'success') {
- console.error('Unable to access network: ' + status);
- phantom.exit(1);
- } else {
- // Cannot do this verification with the 'DOMContentLoaded' handler because it
- // will be too late to attach it if a page does not have any script tags.
- var qunitMissing = page.evaluate(function() { return (typeof QUnit === 'undefined' || !QUnit); });
- if (qunitMissing) {
- console.error('The `QUnit` object is not present on this page.');
- phantom.exit(1);
- }
-
- // Do nothing... the callback mechanism will handle everything!
- }
- });
-
- function addLogging() {
- window.document.addEventListener('DOMContentLoaded', function() {
- var current_test_assertions = [];
-
- QUnit.log(function(details) {
- var response;
-
- // Ignore passing assertions
- if (details.result) {
- return;
- }
-
- response = details.message || '';
-
- if (typeof details.expected !== 'undefined') {
- if (response) {
- response += ', ';
- }
-
- response += 'expected: ' + details.expected + ', but was: ' + details.actual;
- if (details.source) {
- response += "\n" + details.source;
- }
- }
-
- current_test_assertions.push('Failed assertion: ' + response);
- });
-
- QUnit.testDone(function(result) {
- var i,
- len,
- name = result.module + ': ' + result.name;
-
- if (result.failed) {
- console.log('Test failed: ' + name);
-
- for (i = 0, len = current_test_assertions.length; i < len; i++) {
- console.log(' ' + current_test_assertions[i]);
- }
- }
-
- current_test_assertions.length = 0;
- });
-
- QUnit.done(function(result) {
- console.log('Took ' + result.runtime + 'ms to run ' + result.total + ' tests. ' + result.passed + ' passed, ' + result.failed + ' failed.');
-
- if (typeof window.callPhantom === 'function') {
- window.callPhantom({
- 'name': 'QUnit.done',
- 'data': result
- });
- }
- });
- }, false);
- }
-})();
diff --git a/Echo/tests/phpunit/AttributeManagerTest.php b/Echo/tests/phpunit/AttributeManagerTest.php
index cc23cb0e..f9b0c939 100644
--- a/Echo/tests/phpunit/AttributeManagerTest.php
+++ b/Echo/tests/phpunit/AttributeManagerTest.php
@@ -7,135 +7,135 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
}
public static function getUserLocatorsProvider() {
- return array(
- array(
+ return [
+ [
'No errors when requesting unknown type',
// expected result
- array(),
+ [],
// event type
'foo',
// notification configuration
- array(),
- ),
+ [],
+ ],
- array(
+ [
'Returns selected notification configuration',
// expected result
- array( 'woot!' ),
+ [ 'woot!' ],
// event type
'magic',
// notification configuration
- array(
- 'foo' => array(
- 'user-locators' => array( 'frown' ),
- ),
- 'magic' => array(
- 'user-locators' => array( 'woot!' ),
- ),
- ),
- ),
+ [
+ 'foo' => [
+ EchoAttributeManager::ATTR_LOCATORS => [ 'frown' ],
+ ],
+ 'magic' => [
+ EchoAttributeManager::ATTR_LOCATORS => [ 'woot!' ],
+ ],
+ ],
+ ],
- array(
+ [
'Accepts user-locators as string and returns array',
// expected result
- array( 'sagen' ),
+ [ 'sagen' ],
// event type
'challah',
// notification configuration
- array(
- 'challah' => array(
- 'user-locators' => 'sagen',
- ),
- ),
- ),
- );
+ [
+ 'challah' => [
+ EchoAttributeManager::ATTR_LOCATORS => 'sagen',
+ ],
+ ],
+ ],
+ ];
}
/**
* @dataProvider getUserLocatorsProvider
*/
- public function testGetUserLocators( $message, $expect, $type, $notifications) {
- $manager = new EchoAttributeManager( $notifications, array() );
+ public function testGetUserLocators( $message, $expect, $type, $notifications ) {
+ $manager = new EchoAttributeManager( $notifications, [], [], [], [] );
- $result = $manager->getUserLocators( $type );
+ $result = $manager->getUserCallable( $type, EchoAttributeManager::ATTR_LOCATORS );
$this->assertEquals( $expect, $result, $message );
}
public function testGetCategoryEligibility() {
- $notif = array(
- 'event_one' => array (
+ $notif = [
+ 'event_one' => [
'category' => 'category_one'
- ),
- );
- $category = array(
- 'category_one' => array (
+ ],
+ ];
+ $category = [
+ 'category_one' => [
'priority' => 10
- )
- );
- $manager = new EchoAttributeManager( $notif, $category );
+ ]
+ ];
+ $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
$this->assertTrue( $manager->getCategoryEligibility( $this->mockUser(), 'category_one' ) );
- $category = array(
- 'category_one' => array (
+ $category = [
+ 'category_one' => [
'priority' => 10,
- 'usergroups' => array(
+ 'usergroups' => [
'sysop'
- )
- )
- );
- $manager = new EchoAttributeManager( $notif, $category );
+ ]
+ ]
+ ];
+ $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
$this->assertFalse( $manager->getCategoryEligibility( $this->mockUser(), 'category_one' ) );
}
public function testGetNotificationCategory() {
- $notif = array(
- 'event_one' => array (
+ $notif = [
+ 'event_one' => [
'category' => 'category_one'
- ),
- );
- $category = array(
- 'category_one' => array (
+ ],
+ ];
+ $category = [
+ 'category_one' => [
'priority' => 10
- )
- );
- $manager = new EchoAttributeManager( $notif, $category );
+ ]
+ ];
+ $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
$this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'category_one' );
- $manager = new EchoAttributeManager( $notif, array() );
+ $manager = new EchoAttributeManager( $notif, [], [], [], [] );
$this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'other' );
- $notif = array(
- 'event_one' => array (
+ $notif = [
+ 'event_one' => [
'category' => 'category_two'
- ),
- );
- $category = array(
- 'category_one' => array (
+ ],
+ ];
+ $category = [
+ 'category_one' => [
'priority' => 10
- )
- );
- $manager = new EchoAttributeManager( $notif, $category );
+ ]
+ ];
+ $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
$this->assertEquals( $manager->getNotificationCategory( 'event_one' ), 'other' );
}
public function testGetCategoryPriority() {
- $notif = array(
- 'event_one' => array (
+ $notif = [
+ 'event_one' => [
'category' => 'category_two'
- ),
- );
- $category = array(
- 'category_one' => array (
+ ],
+ ];
+ $category = [
+ 'category_one' => [
'priority' => 6
- ),
- 'category_two' => array (
+ ],
+ 'category_two' => [
'priority' => 100
- ),
- 'category_three' => array (
+ ],
+ 'category_three' => [
'priority' => -10
- ),
- 'category_four' => array ()
- );
- $manager = new EchoAttributeManager( $notif, $category );
+ ],
+ 'category_four' => []
+ ];
+ $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
$this->assertEquals( 6, $manager->getCategoryPriority( 'category_one' ) );
$this->assertEquals( 10, $manager->getCategoryPriority( 'category_two' ) );
$this->assertEquals( 10, $manager->getCategoryPriority( 'category_three' ) );
@@ -143,172 +143,314 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
}
public function testGetNotificationPriority() {
- $notif = array(
- 'event_one' => array (
+ $notif = [
+ 'event_one' => [
'category' => 'category_one'
- ),
- 'event_two' => array (
+ ],
+ 'event_two' => [
'category' => 'category_two'
- ),
- 'event_three' => array (
+ ],
+ 'event_three' => [
'category' => 'category_three'
- ),
- 'event_four' => array (
+ ],
+ 'event_four' => [
'category' => 'category_four'
- )
- );
- $category = array(
- 'category_one' => array (
+ ]
+ ];
+ $category = [
+ 'category_one' => [
'priority' => 6
- ),
- 'category_two' => array (
+ ],
+ 'category_two' => [
'priority' => 100
- ),
- 'category_three' => array (
+ ],
+ 'category_three' => [
'priority' => -10
- ),
- 'category_four' => array ()
- );
- $manager = new EchoAttributeManager( $notif, $category );
+ ],
+ 'category_four' => []
+ ];
+ $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
$this->assertEquals( 6, $manager->getNotificationPriority( 'event_one' ) );
$this->assertEquals( 10, $manager->getNotificationPriority( 'event_two' ) );
$this->assertEquals( 10, $manager->getNotificationPriority( 'event_three' ) );
$this->assertEquals( 10, $manager->getNotificationPriority( 'event_four' ) );
}
- public function testGetMessageEvents() {
- $notif = array(
- 'event_one' => array (
+ public static function getEventsForSectionProvider() {
+ $notifications = [
+ 'event_one' => [
'category' => 'category_one',
- 'section' => 'message'
- ),
- 'event_two' => array (
- 'category' => 'category_two'
- ),
- 'event_three' => array (
+ 'section' => 'message',
+ ],
+ 'event_two' => [
+ 'category' => 'category_two',
+ 'section' => 'invalid',
+ ],
+ 'event_three' => [
'category' => 'category_three',
- 'section' => 'message'
- ),
- 'event_four' => array (
- 'category' => 'category_four'
- )
- );
- $category = array(
- 'category_one' => array (
- 'priority' => 6
- )
- );
- $manager = new EchoAttributeManager( $notif, $category );
- $this->assertEquals( $manager->getMessageEvents(), array( 'event_one', 'event_three' ) );
+ 'section' => 'message',
+ ],
+ 'event_four' => [
+ 'category' => 'category_four',
+ // Omitted
+ ],
+ 'event_five' => [
+ 'category' => 'category_two',
+ 'section' => 'alert',
+ ],
+ ];
+
+ return [
+ [
+ [ 'event_one', 'event_three' ],
+ $notifications,
+ 'message',
+ 'Messages',
+ ],
+
+ [
+ [ 'event_two', 'event_four', 'event_five' ],
+ $notifications,
+ 'alert',
+ 'Alerts',
+ ],
+ ];
}
- public function testGetAlertEvents() {
- $notif = array(
- 'event_one' => array (
- 'category' => 'category_one',
- 'section' => 'message'
- ),
- 'event_two' => array (
- 'category' => 'category_two'
- ),
- 'event_three' => array (
- 'category' => 'category_three',
- 'section' => 'alert'
- ),
- 'event_four' => array (
- 'category' => 'category_four'
- )
- );
- $category = array(
- 'category_one' => array (
- 'priority' => 6
- )
- );
- $manager = new EchoAttributeManager( $notif, $category );
- $this->assertEquals( $manager->getAlertEvents(), array( 'event_two', 'event_three', 'event_four' ) );
+ /**
+ * @dataProvider getEventsForSectionProvider
+ */
+ public function testGetEventsForSection( $expected, $notificationTypes, $section, $message ) {
+ $am = new EchoAttributeManager( $notificationTypes, [], [], [], [] );
+ $actual = $am->getEventsForSection( $section );
+ $this->assertEquals( $expected, $actual, $message );
}
public function testGetUserEnabledEvents() {
- $notif = array(
- 'event_one' => array (
+ $notif = [
+ 'event_one' => [
'category' => 'category_one'
- ),
- 'event_two' => array (
+ ],
+ 'event_two' => [
'category' => 'category_two'
- ),
- 'event_three' => array (
+ ],
+ 'event_three' => [
'category' => 'category_three'
- ),
- );
- $category = array(
- 'category_one' => array (
+ ],
+ ];
+ $category = [
+ 'category_one' => [
'priority' => 10,
- 'usergroups' => array(
+ 'usergroups' => [
'sysop'
- )
- ),
- 'category_two' => array (
+ ]
+ ],
+ 'category_two' => [
'priority' => 10,
- 'usergroups' => array(
+ 'usergroups' => [
'echo_group'
- )
- ),
- 'category_three' => array (
+ ]
+ ],
+ 'category_three' => [
'priority' => 10,
- ),
- );
- $manager = new EchoAttributeManager( $notif, $category );
- $this->assertEquals( $manager->getUserEnabledEvents( $this->mockUser(), 'web' ), array( 'event_two', 'event_three' ) );
+ ],
+ ];
+ $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $this->assertEquals( $manager->getUserEnabledEvents( $this->mockUser(), 'web' ), [ 'event_two', 'event_three' ] );
}
public function testGetUserEnabledEventsbySections() {
- $notif = array(
- 'event_one' => array (
+ $notif = [
+ 'event_one' => [
'category' => 'category_one'
- ),
- 'event_two' => array (
+ ],
+ 'event_two' => [
'category' => 'category_two',
'section' => 'message'
- ),
- 'event_three' => array (
+ ],
+ 'event_three' => [
'category' => 'category_three',
'section' => 'alert'
- ),
- 'event_four' => array (
+ ],
+ 'event_four' => [
'category' => 'category_three',
- ),
- );
- $category = array(
- 'category_one' => array (
+ ],
+ ];
+ $category = [
+ 'category_one' => [
'priority' => 10,
- ),
- 'category_two' => array (
+ ],
+ 'category_two' => [
'priority' => 10,
- ),
- 'category_three' => array (
+ ],
+ 'category_three' => [
'priority' => 10
- ),
- );
- $manager = new EchoAttributeManager( $notif, $category );
- $expected = array( 'event_one', 'event_three', 'event_four' );
- $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', array( 'alert' ) );
+ ],
+ ];
+ $manager = new EchoAttributeManager( $notif, $category, [], [], [] );
+ $expected = [ 'event_one', 'event_three', 'event_four' ];
+ $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'alert' ] );
sort( $expected );
sort( $actual );
$this->assertEquals( $actual, $expected );
- $expected = array( 'event_two' );
- $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', array( 'message' ) );
+ $expected = [ 'event_two' ];
+ $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'message' ] );
sort( $expected );
sort( $actual );
$this->assertEquals( $actual, $expected );
- $expected = array( 'event_one', 'event_two', 'event_three', 'event_four' );
- $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', array( 'message', 'alert' ) );
+ $expected = [ 'event_one', 'event_two', 'event_three', 'event_four' ];
+ $actual = $manager->getUserEnabledEventsBySections( $this->mockUser(), 'web', [ 'message', 'alert' ] );
sort( $expected );
sort( $actual );
$this->assertEquals( $actual, $expected );
}
+ public static function getEventsByCategoryProvider() {
+ return [
+ [
+ 'Mix of populated and empty categories handled appropriately',
+ [
+ 'category_one' => [
+ 'event_two',
+ 'event_five',
+ ],
+ 'category_two' => [
+ 'event_one',
+ 'event_three',
+ 'event_four',
+ ],
+ 'category_three' => [],
+ ],
+ [
+ 'category_one' => [],
+ 'category_two' => [],
+ 'category_three' => [],
+ ],
+ [
+ 'event_one' => [
+ 'category' => 'category_two',
+ ],
+ 'event_two' => [
+ 'category' => 'category_one',
+ ],
+ 'event_three' => [
+ 'category' => 'category_two',
+ ],
+ 'event_four' => [
+ 'category' => 'category_two',
+ ],
+ 'event_five' => [
+ 'category' => 'category_one',
+ ],
+ ]
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider getEventsByCategoryProvider
+ */
+ public function testGetEventsByCategory( $message, $expectedMapping, $categories, $notifications ) {
+ $am = new EchoAttributeManager( $notifications, $categories, [], [], [] );
+ $actualMapping = $am->getEventsByCategory();
+ $this->assertEquals( $expectedMapping, $actualMapping, $message );
+ }
+
+ public static function isNotifyTypeAvailableForCategoryProvider() {
+ return [
+ [
+ 'Fallback to default entirely',
+ true,
+ 'category_one',
+ 'web',
+ [ 'web' => true, 'email' => true ],
+ []
+ ],
+ [
+ 'Fallback to default for single type',
+ false,
+ 'category_two',
+ 'email',
+ [ 'web' => true, 'email' => false ],
+ [
+ 'category_two' => [
+ 'web' => true,
+ ],
+ ]
+ ],
+ [
+ 'Use override',
+ false,
+ 'category_three',
+ 'web',
+ [ 'web' => true, 'email' => true ],
+ [
+ 'category_three' => [
+ 'web' => false,
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ @dataProvider isNotifyTypeAvailableForCategoryProvider
+ */
+ public function testIsNotifyTypeAvailableForCategory( $message, $expected, $categoryName, $notifyType, $defaultNotifyTypeAvailability, $notifyTypeAvailabilityByCategory ) {
+ $am = new EchoAttributeManager( [], [], $defaultNotifyTypeAvailability, $notifyTypeAvailabilityByCategory, [] );
+ $actual = $am->isNotifyTypeAvailableForCategory( $categoryName, $notifyType );
+ $this->assertEquals( $expected, $actual, $message );
+ }
+
+ public static function isNotifyTypeDismissableForCategoryProvider() {
+ return [
+ [
+ 'Not dismissable because of all',
+ false,
+ [
+ 'category_one' => [
+ 'no-dismiss' => [ 'all' ],
+ ]
+ ],
+ 'category_one',
+ 'web',
+ ],
+ [
+ 'Not dismissable because of specific notify type',
+ false,
+ [
+ 'category_two' => [
+ 'no-dismiss' => [ 'email' ],
+ ]
+ ],
+ 'category_two',
+ 'email',
+ ],
+ [
+ 'Dismissable because of different affected notify type',
+ true,
+ [
+ 'category_three' => [
+ 'no-dismiss' => [ 'web' ],
+ ]
+ ],
+ 'category_three',
+ 'email',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider isNotifyTypeDismissableForCategoryProvider
+ */
+ public function testIsNotifyTypeDismissableForCategory( $message, $expected, $categories, $categoryName, $notifyType ) {
+ $am = new EchoAttributeManager( [], $categories, [], [], [] );
+ $actual = $am->isNotifyTypeDismissableForCategory( $categoryName, $notifyType );
+ $this->assertEquals( $expected, $actual, $message );
+ }
+
/**
* Mock object of User
*/
@@ -324,7 +466,8 @@ class EchoAttributeManagerTest extends MediaWikiTestCase {
->will( $this->returnValue( true ) );
$user->expects( $this->any() )
->method( 'getGroups' )
- ->will( $this->returnValue( array( 'echo_group' ) ) );
+ ->will( $this->returnValue( [ 'echo_group' ] ) );
+
return $user;
}
}
diff --git a/Echo/tests/phpunit/BatchRowUpdateTest.php b/Echo/tests/phpunit/BatchRowUpdateTest.php
deleted file mode 100644
index 5a7f1894..00000000
--- a/Echo/tests/phpunit/BatchRowUpdateTest.php
+++ /dev/null
@@ -1,244 +0,0 @@
-<?php
-
-require_once __DIR__ . "/../../includes/BatchRowUpdate.php";
-
-/**
- * Tests for BatchRowUpdate and its components
- * @group Echo
- */
-class BatchRowUpdateTest extends MediaWikiTestCase {
-
- public function testWriterBasicFunctionality() {
- $db = $this->mockDb();
- $writer = new EchoBatchRowWriter( $db, 'echo_event' );
-
- $updates = array(
- self::mockUpdate( array( 'something' => 'changed' ) ),
- self::mockUpdate( array( 'otherthing' => 'changed' ) ),
- self::mockUpdate( array( 'and' => 'something', 'else' => 'changed' ) ),
- );
-
- $db->expects( $this->exactly( count( $updates ) ) )
- ->method( 'update' );
-
- $writer->write( $updates );
- }
-
- static protected function mockUpdate( array $changes ) {
- static $i = 0;
- return array(
- 'primaryKey' => array( 'event_id' => $i++ ),
- 'changes' => $changes,
- );
- }
-
- public function testReaderBasicIterate() {
- $db = $this->mockDb();
- $batchSize = 2;
- $reader = new EchoBatchRowIterator( $db, 'some_table', 'id_field', $batchSize );
-
- $response = $this->genSelectResult( $batchSize, /*numRows*/ 5, function() {
- static $i = 0;
- return array( 'id_field' => ++$i );
- } );
- $db->expects( $this->exactly( count( $response ) ) )
- ->method( 'select' )
- ->will( $this->consecutivelyReturnFromSelect( $response ) );
-
- $pos = 0;
- foreach ( $reader as $rows ) {
- $this->assertEquals( $response[$pos], $rows, "Testing row in position $pos" );
- $pos++;
- }
- // -1 is because the final array() marks the end and isnt included
- $this->assertEquals( count( $response ) - 1, $pos );
- }
-
- static public function provider_readerGetPrimaryKey() {
- $row = array(
- 'id_field' => 42,
- 'some_col' => 'dvorak',
- 'other_col' => 'samurai',
- );
- return array(
-
- array(
- 'Must return single column pk when requested',
- array( 'id_field' => 42 ),
- $row
- ),
-
- array(
- 'Must return multiple column pks when requested',
- array( 'id_field' => 42, 'other_col' => 'samurai' ),
- $row
- ),
-
- );
- }
-
- /**
- * @dataProvider provider_readerGetPrimaryKey
- */
- public function testReaderGetPrimaryKey( $message, array $expected, array $row ) {
- $reader = new EchoBatchRowIterator( $this->mockDb(), 'some_table', array_keys( $expected ), 8675309 );
- $this->assertEquals( $expected, $reader->extractPrimaryKeys( (object) $row ), $message );
- }
-
- static public function provider_readerSetFetchColumns() {
- return array(
-
- array(
- 'Must merge primary keys into select conditions',
- // Expected column select
- array( 'foo', 'bar' ),
- // primary keys
- array( 'foo' ),
- // setFetchColumn
- array( 'bar' )
- ),
-
- array(
- 'Must not merge primary keys into the all columns selector',
- // Expected column select
- array( '*' ),
- // primary keys
- array( 'foo' ),
- // setFetchColumn
- array( '*' ),
- ),
-
- array(
- 'Must not duplicate primary keys into column selector',
- // Expected column select.
- // TODO: figure out how to only assert the array_values portion and not the keys
- array( 0 => 'foo', 1 => 'bar', 3 => 'baz' ),
- // primary keys
- array( 'foo', 'bar', ),
- // setFetchColumn
- array( 'bar', 'baz' ),
- ),
- );
- }
-
- /**
- * @dataProvider provider_readerSetFetchColumns
- */
- public function testReaderSetFetchColumns( $message, array $columns, array $primaryKeys, array $fetchColumns ) {
- $db = $this->mockDb();
- $db->expects( $this->once() )
- ->method( 'select' )
- ->with( 'some_table', $columns ) // only testing second parameter of DatabaseBase::select
- ->will( $this->returnValue( new ArrayIterator( array() ) ) );
-
- $reader = new EchoBatchRowIterator( $db, 'some_table', $primaryKeys, 22 );
- $reader->setFetchColumns( $fetchColumns );
- // triggers first database select
- $reader->rewind();
- }
-
- static public function provider_readerSelectConditions() {
- return array(
-
- array(
- "With single primary key must generate id > 'value'",
- // Expected second iteration
- array( "( id_field > '3' )" ),
- // Primary key(s)
- 'id_field',
- ),
-
- array(
- 'With multiple primary keys the first conditions must use >= and the final condition must use >',
- // Expected second iteration
- array( "( id_field = '3' AND foo > '103' ) OR ( id_field > '3' )" ),
- // Primary key(s)
- array( 'id_field', 'foo' ),
- ),
-
- );
- }
-
- /**
- * Slightly hackish to use reflection, but asserting different parameters
- * to consecutive calls of DatabaseBase::select in phpunit is error prone
- *
- * @dataProvider provider_readerSelectConditions
- */
- public function testReaderSelectConditionsMultiplePrimaryKeys( $message, $expectedSecondIteration, $primaryKeys, $batchSize = 3 ) {
- $results = $this->genSelectResult( $batchSize, $batchSize * 3, function() {
- static $i = 0, $j = 100, $k = 1000;
- return array( 'id_field' => ++$i, 'foo' => ++$j, 'bar' => ++$k );
- } );
- $db = $this->mockDbConsecutiveSelect( $results );
-
- $conditions = array( 'bar' => 42, 'baz' => 'hai' );
- $reader = new EchoBatchRowIterator( $db, 'some_table', $primaryKeys, $batchSize );
- $reader->addConditions( $conditions );
-
- $buildConditions = new ReflectionMethod( $reader, 'buildConditions' );
- $buildConditions->setAccessible( true );
-
- // On first iteration only the passed conditions must be used
- $this->assertEquals( $conditions, $buildConditions->invoke( $reader ),
- 'First iteration must return only the conditions passed in addConditions' );
- $reader->rewind();
-
- // Second iteration must use the maximum primary key of last set
- $this->assertEquals(
- $conditions + $expectedSecondIteration,
- $buildConditions->invoke( $reader ),
- $message
- );
- }
-
- protected function mockDbConsecutiveSelect( array $retvals ) {
- $db = $this->mockDb();
- $db->expects( $this->any() )
- ->method( 'select' )
- ->will( $this->consecutivelyReturnFromSelect( $retvals ) );
- $db->expects( $this->any() )
- ->method( 'addQuotes' )
- ->will( $this->returnCallback( function( $value ) {
- return "'$value'"; // not real quoting: doesn't matter in test
- } ) );
-
- return $db;
- }
-
- protected function consecutivelyReturnFromSelect( array $results ) {
- $retvals = array();
- foreach ( $results as $rows ) {
- // The DatabaseBase::select method returns iterators, so we do too.
- $retvals[] = $this->returnValue( new ArrayIterator( $rows ) );
- }
-
- return call_user_func_array( array( $this, 'onConsecutiveCalls' ), $retvals );
- }
-
-
- protected function genSelectResult( $batchSize, $numRows, $rowGenerator ) {
- $res = array();
- for ( $i = 0; $i < $numRows; $i += $batchSize ) {
- $rows = array();
- for ( $j = 0; $j < $batchSize && $i + $j < $numRows; $j++ ) {
- $rows [] = (object) call_user_func( $rowGenerator );
- }
- $res[] = $rows;
- }
- $res[] = array(); // termination condition requires empty result for last row
- return $res;
- }
-
- protected function mockDb() {
- // Cant mock from DatabaseType or DatabaseBase, they dont
- // have the full gamut of methods
- $databaseMysql = $this->getMockBuilder( 'DatabaseMysql' )
- ->disableOriginalConstructor()
- ->getMock();
- $databaseMysql->expects( $this->any() )
- ->method( 'isOpen' )
- ->will( $this->returnValue( true ) );
- return $databaseMysql;
- }
-}
diff --git a/Echo/tests/phpunit/BundlerTest.php b/Echo/tests/phpunit/BundlerTest.php
new file mode 100644
index 00000000..bd2f4499
--- /dev/null
+++ b/Echo/tests/phpunit/BundlerTest.php
@@ -0,0 +1,44 @@
+<?php
+
+class BundlerTest extends MediaWikiTestCase {
+
+ public function testBundle() {
+ $read = true;
+ $unread = false;
+ $n1 = $this->createNotificationForBundling( 'bundle_hash_1', 'timestamp_4', $read );
+ $n2 = $this->createNotificationForBundling( 'bundle_hash_1', 'timestamp_1', $read );
+ $n3 = $this->createNotificationForBundling( 'bundle_hash_2', 'timestamp_3', $unread );
+ $n4 = $this->createNotificationForBundling( 'bundle_hash_2', 'timestamp_2', $unread );
+ $n5 = $this->createNotificationForBundling( 'bundle_hash_2', 'timestamp_5', $read );
+ $notifications = [ $n1, $n2, $n3, $n4, $n5 ];
+
+ $bundler = new Bundler();
+ $bundledNotifications = $bundler->bundle( $notifications );
+
+ $this->assertCount( 4, $bundledNotifications );
+ $this->assertSame( $n5, $bundledNotifications[0] );
+ $this->assertSame( $n1, $bundledNotifications[1] );
+ $this->assertSame( $n3, $bundledNotifications[2] );
+ $this->assertCount( 1, $bundledNotifications[2]->getBundledNotifications() );
+ $this->assertSame( $n4, $bundledNotifications[2]->getBundledNotifications()[0] );
+ $this->assertSame( $n2, $bundledNotifications[3] );
+ }
+
+ private function createNotificationForBundling( $bundleHash, $timestamp, $readStatus ) {
+ $mock = $this->getMockBuilder( 'EchoNotification' )
+ ->disableOriginalConstructor()
+ ->setMethods( [
+ 'getBundlingKey',
+ 'getSortingKey',
+ 'canBeBundled',
+ ] )
+ ->getMock();
+
+ $mock->method( 'getBundlingKey' )->willReturn( $bundleHash );
+ $mock->method( 'getSortingKey' )->willReturn( $timestamp );
+ $mock->method( 'canBeBundled' )->willReturn( !$readStatus );
+
+ return $mock;
+ }
+
+}
diff --git a/Echo/tests/phpunit/ContainmentSetTest.php b/Echo/tests/phpunit/ContainmentSetTest.php
index 5c17f58f..077e235b 100644
--- a/Echo/tests/phpunit/ContainmentSetTest.php
+++ b/Echo/tests/phpunit/ContainmentSetTest.php
@@ -6,28 +6,27 @@
class ContainmentSetTest extends MediaWikiTestCase {
public function testGenericContains() {
- $list = new EchoContainmentSet();
+ $list = new EchoContainmentSet( self::getTestUser()->getUser() );
- $list->addArray( array( 'foo', 'bar' ) );
+ $list->addArray( [ 'foo', 'bar' ] );
$this->assertTrue( $list->contains( 'foo' ) );
$this->assertTrue( $list->contains( 'bar' ) );
$this->assertFalse( $list->contains( 'whammo' ) );
- $list->addArray( array( 'whammo' ) );
+ $list->addArray( [ 'whammo' ] );
$this->assertTrue( $list->contains( 'whammo' ) );
}
public function testCachedListInnerListIsOnlyCalledOnce() {
-
// the global $wgMemc during tests is an EmptyBagOStuff, so it
// wont do anything. We use a HashBagOStuff to get more like a real
// client
$innerCache = new HashBagOStuff;
- $inner = array( 'bing', 'bang' );
+ $inner = [ 'bing', 'bang' ];
// We use a mock instead of the real thing for the $this->once() assertion
// verifying that the cache doesn't just keep asking the inner object
- $list = $this->getMockBuilder('EchoArrayList')
+ $list = $this->getMockBuilder( 'EchoArrayList' )
->disableOriginalConstructor()
->getMock();
$list->expects( $this->once() )
@@ -54,14 +53,14 @@ class ContainmentSetTest extends MediaWikiTestCase {
$list = new EchoOnWikiList( NS_USER, "Foo/Bar-baz" );
$this->assertEquals(
- array( 'abc', 'def', 'ghi' ),
+ [ 'abc', 'def', 'ghi' ],
$list->getValues()
);
}
public function testOnWikiListNonExistant() {
$list = new EchoOnWikiList( NS_USER, "Some_Non_Existant_Page" );
- $this->assertEquals( array(), $list->getValues() );
+ $this->assertEquals( [], $list->getValues() );
}
protected function editPage( $pageName, $text, $summary = '', $defaultNs = NS_MAIN ) {
diff --git a/Echo/tests/phpunit/DiffParserTest.php b/Echo/tests/phpunit/DiffParserTest.php
index 7db7de88..14dc8a7d 100644
--- a/Echo/tests/phpunit/DiffParserTest.php
+++ b/Echo/tests/phpunit/DiffParserTest.php
@@ -14,177 +14,189 @@ class EchoDiffParserTest extends MediaWikiTestCase {
$this->assertEquals( $expect, $changeSet, $message );
}
- static public function provider_getChangeSet() {
- return array(
+ public static function provider_getChangeSet() {
+ return [
- array(
+ [
'Duplicate content must generate no changes',
// Expected change set
- array(),
+ [],
// Left text
"a\nb\nc",
// Right text
"a\nb\nc",
- ),
+ ],
- array(
+ [
'Removing blank lines must generate no changes',
// Expected change set
- array(),
+ [],
// Left text
"a\n\nb\n\nc",
// Right text
"a\nb\nc\n",
- ),
+ ],
- array(
+ [
'Must generate a single add change with only lines added',
// Expected change set
- array( self::mockAction( 'add', "foo\nbar", 1 ) ),
+ [ self::mockAction( 'add', "foo\nbar", 1 ) ],
// Left
"something",
// Right
"foo\nbar\nsomething",
- ),
+ ],
- array(
+ [
'Must generate a single subtract change with only lines subtracted',
// Expected change set
- array( self::mockAction( 'subtract', "Zomg\nHiHiHi", 2 ) ),
+ [ self::mockAction( 'subtract', "Zomg\nHiHiHi", 2 ) ],
// Left
"dummy\nZomg\nHiHiHi",
// Right
"dummy",
- ),
+ ],
- array(
+ [
'Adding content seperated by no change must generate multiple changes',
// Expected change set
- array(
+ [
self::mockAction( 'add', 'b1', 3 ),
self::mockAction( 'add', "d1\nd2", 5, 6 ),
- ),
+ ],
// Left text
"a\nb\nc\nd\ne\nf",
// Right text
"a\nb\nb1\nc\nd\nd1\nd2\ne\nf",
- ),
+ ],
- array(
+ [
+ 'Additon with empty line should be one action',
+ // Expected change set
+ [ self::mockAction( 'add', "User\n\nSignature", 1 ) ],
+ // Left text
+ "",
+ // Right text
+ "User\n\nSignature",
+ ],
+
+ [
'Extra blank lines on the edges must be trimmed',
// Expected change set
- array( self::mockAction( 'add', "Zomg\nHiHiHi", 1 ) ),
+ [ self::mockAction( 'add', "Zomg\nHiHiHi", 1 ) ],
// Left text
"",
// Right text
"\nZomg\nHiHiHi\n",
- ),
+ ],
- array(
+ [
'Extra blank lines inside the content must not be trimmed',
// Expected change set
- array( self::mockAction( 'add', "\nZomg\nHiHiHi\n", 2 ) ),
+ [ self::mockAction( 'add', "\nZomg\nHiHiHi\n", 2 ) ],
// Left text
"foo\nbar",
// Right text
"foo\n\nZomg\nHiHiHi\n\nbar",
- ),
+ ],
- array(
+ [
'A blank line replaced with content must be an add',
// Expected change set
- array( self::mockAction( 'add', 'cowbell', 1 ) ),
+ [ self::mockAction( 'add', 'cowbell', 1 ) ],
// Left Text
"",
// Right Text
"cowbell",
- ),
+ ],
- array(
+ [
'A blanked out line must be a subtraction',
// Expected change set
- array( self::mockAction( 'subtract', 'cowbell', 1 ) ),
+ [ self::mockAction( 'subtract', 'cowbell', 1 ) ],
// Left text
"cowbell",
// Right text
"",
- ),
+ ],
- array(
+ [
'A line with its content replaced must be a change',
// Expected change set
- array( self::mockChange( 'Its all about the journey', 'dummy', 1 ) ),
+ [ self::mockChange( 'Its all about the journey', 'dummy', 1 ) ],
// Left text
"Its all about the journey",
// Right text
"dummy",
- ),
+ ],
- array(
+ [
'Changing lines and adding more must result in two changes',
// Expected change set
- array(
+ [
self::mockChange( 'Must be in a hurry to finish this thing', 'Must be in a hurry', 1 ),
self::mockAction( 'add', 'Finish this thing', 2 ),
- ),
+ ],
// Left text
"Must be in a hurry to finish this thing",
// Right text
"Must be in a hurry\nFinish this thing",
- ),
+ ],
- array(
+ [
'Changing multiple lines and adding more must result in two changes',
// Expected change set
- array(
+ [
self::mockChange( "Must not be\nin much of a hurry", "Must be\nin a hurry", 2 ),
self::mockAction( 'subtract', "to finish\nthis thing", 4 ),
- ),
+ ],
// Left text
"abc\nMust not be\nin much of a hurry\nto finish\nthis thing",
// Right text
"abc\nMust be\nin a hurry",
- ),
+ ],
- array(
+ [
'Must generate multiple add, change, and subtract actions',
// Expected change set
- array(
+ [
self::mockChange( "abc\nSome", "Other\nThings", 1 ),
self::mockAction( 'subtract', "Stuff", 3 ),
self::mockChange( "And\nThen", "There\nWas", 6, 5 ),
self::mockAction( 'add', 'Fencing', 8, 7 ),
- ),
+ ],
// Left text
"abc\nSome\nStuff\ndef\nghi\nAnd\nThen\njkl\nmno",
// Right text
"\nOther\nThings\ndef\nghi\nThere\nWas\nFencing\njkl\nmno",
- ),
- );
+ ],
+ ];
}
- static protected function mockAction( $action, $content, $left, $right = null ) {
+ protected static function mockAction( $action, $content, $left, $right = null ) {
if ( $right === null ) {
$right = $left;
}
- return array(
+
+ return [
'action' => $action,
'content' => $content,
'left-pos' => $left,
'right-pos' => $right,
- );
+ ];
}
- static public function mockChange( $oldContent, $newContent, $left, $right = null ) {
+ public static function mockChange( $oldContent, $newContent, $left, $right = null ) {
if ( $right === null ) {
$right = $left;
}
- return array(
+
+ return [
'action' => 'change',
'old_content' => $oldContent,
'new_content' => $newContent,
'left-pos' => $left,
'right-pos' => $right,
- );
+ ];
}
}
diff --git a/Echo/tests/phpunit/DiscussionParserTest.php b/Echo/tests/phpunit/DiscussionParserTest.php
index f388b6df..35da3fae 100644
--- a/Echo/tests/phpunit/DiscussionParserTest.php
+++ b/Echo/tests/phpunit/DiscussionParserTest.php
@@ -1,5 +1,9 @@
<?php
+use MediaWiki\MediaWikiServices;
+use Wikimedia\ScopedCallback;
+use Wikimedia\TestingAccessWrapper;
+
/**
* @group Echo
* @group Database
@@ -8,175 +12,193 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
/**
* @var array
*/
- protected $tablesUsed = array( 'user', 'revision', 'text', 'page' );
+ protected $tablesUsed = [ 'user', 'revision', 'ip_changes', 'text', 'page' ];
/**
- * Users used in these tests: signature extraction, mentioned users, ... all
- * assume a user exists.
+ * Convenience users for use in these tests.
+ * Can be setup one by one using the setupTestUser() method
+ * Or all at once using the setupAllTestUsers() method
*
* @var array [username => [user preference => preference value]]
*/
- protected $testUsers = array(
- // username
- 'Werdna' => array(
- // user preferences
+ protected $testUsers = [
+ 'Werdna' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'Werdna2' => array(
+ ],
+ 'Werdna2' => [
'nickname' => '[[User:Werdna2|Andrew]]',
'fancysig' => '1',
- ),
- 'Werdna3' => array(
+ ],
+ 'Werdna3' => [
'nickname' => '[[User talk:Werdna3|Andrew]]',
'fancysig' => '1',
- ),
- 'Werdna4' => array(
+ ],
+ 'Werdna4' => [
'nickname' => '[[User:Werdna4|wer]dna]]',
'fancysig' => '1',
- ),
- 'We buried our secrets in the garden' => array(
+ ],
+ 'We buried our secrets in the garden' => [
'nickname' => '[[User talk:We buried our secrets in the garden#top|wbositg]]',
'fancysig' => '1',
- ),
- 'I Heart Spaces' => array(
+ ],
+ 'I Heart Spaces' => [
'nickname' => '[[User:I_Heart_Spaces]] ([[User_talk:I_Heart_Spaces]])',
'fancysig' => '1',
- ),
- 'Jam' => array(
+ ],
+ 'Jam' => [
'nickname' => '[[User:Jam]]',
'fancysig' => '1',
- ),
- 'Reverta-me' => array(
+ ],
+ 'Reverta-me' => [
'nickname' => "[[User:Reverta-me|<span style=\"font-size:13px; color:blue;font-family:Lucida Handwriting;text-shadow:aqua 5px 3px 12px;\">Aaaaa Bbbbbbb</span>]]'' <sup>[[User Talk:Reverta-me|<font color=\"gold\" face=\"Lucida Calligraphy\">Discussão</font>]]</sup>''",
'fancysig' => '1',
- ),
- 'Jorm' => array(
+ ],
+ 'Jorm' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'Jdforrester' => array(
+ ],
+ 'Jdforrester' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'DarTar' => array(
+ ],
+ 'DarTar' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'Bsitu' => array(
+ ],
+ 'Bsitu' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'JarJar' => array(
+ ],
+ 'JarJar' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'Schnark' => array(
+ ],
+ 'Schnark' => [
'nickname' => '[[Benutzer:Schnark]] ([[Benutzer:Schnark/js|js]])',
'fancysig' => '1',
- ),
- 'Cwobeel' => array(
+ ],
+ 'Cwobeel' => [
'nickname' => '[[User:Cwobeel|<span style="color:#339966">Cwobeel</span>]] [[User_talk:Cwobeel|<span style="font-size:80%">(talk)</span>]]',
'fancysig' => '1',
- ),
- 'Bob K31416' => array(
+ ],
+ 'Bob K31416' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'X" onclick="alert(\'XSS\');" title="y' => array(
+ ],
+ 'X" onclick="alert(\'XSS\');" title="y' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'He7d3r' => array(
+ ],
+ 'He7d3r' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'PauloEduardo' => array(
+ ],
+ 'PauloEduardo' => [
'nickname' => "[[User:PauloEduardo|<span style=\"font-size:13px; color:blue;font-family:Lucida Handwriting;text-shadow:aqua 5px 3px 12px;\">Paulo Eduardo</span>]]'' <sup>[[User Talk:PauloEduardo|<font color=\"gold\" face=\"Lucida Calligraphy\">Discussão</font>]]</sup>''",
'fancysig' => '1',
- ),
- 'PatHadley' => array(
+ ],
+ 'PatHadley' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'Samwalton9' => array(
+ ],
+ 'Samwalton9' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'Kudpung' => array(
+ ],
+ 'Kudpung' => [
'nickname' => '[[User:Kudpung|Kudpung กุดผึ้ง]] ([[User talk:Kudpung#top|talk]])',
'fancysig' => '1',
- ),
- 'Jim Carter' => array(
+ ],
+ 'Jim Carter' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'Buster7' => array(
+ ],
+ 'Buster7' => [
'nickname' => '',
'fancysig' => '0',
- ),
- 'Admin' => array(
+ ],
+ 'Admin' => [
'nickname' => '[[:User:Admin|Admin]]',
'fancysig' => '1',
- ),
- 'Test11' => array(
+ ],
+ 'Test11' => [
'nickname' => '',
'fancysig' => '0',
- ),
- );
+ ],
+ ];
protected function setUp() {
parent::setUp();
+ $this->setMwGlobals( [ 'wgDiff' => false ] );
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+
+ global $wgHooks;
+ unset( $wgHooks['BeforeEchoEventInsert'][999] );
+ }
- if ( extension_loaded( 'wikidiff2' ) ) {
- $this->setMwGlobals( array( 'wgDiff' => false ) );
+ private function setupAllTestUsers() {
+ foreach ( array_keys( $this->testUsers ) as $username ) {
+ $this->setupTestUser( $username );
}
+ }
- // we only need to add these users once, we won't (can't) tear them down anyway
- static $executed = false;
- if ( $executed === true ) {
+ private function setupTestUser( $username ) {
+ // Skip user creation requests that are not in the list (such as IPs)
+ if ( !array_key_exists( $username, $this->testUsers ) ) {
return;
}
- foreach ( $this->testUsers as $username => $preferences ) {
- $user = User::createNew( $username );
+ $preferences = $this->testUsers[$username];
+ $user = User::createNew( $username );
- // set signature preferences
- if ( $user ) {
- foreach ( $preferences as $option => $value ) {
- $user->setOption( $option, $value );
- }
- $user->saveSettings();
+ // Set preferences
+ if ( $user ) {
+ foreach ( $preferences as $option => $value ) {
+ $user->setOption( $option, $value );
}
+ $user->saveSettings();
}
-
- $executed = true;
}
- protected function tearDown() {
- parent::tearDown();
+ public function provideHeaderExtractions() {
+ return [
+ [ '', false ],
+ [ '== Grand jury no bill reception ==', 'Grand jury no bill reception' ],
+ [ '=== Echo-Test ===', 'Echo-Test' ],
+ [ '==== Notificações ====', 'Notificações' ],
+ [ '=====Me?=====', 'Me?' ],
+ ];
+ }
- global $wgHooks;
- unset( $wgHooks['BeforeEchoEventInsert'][999] );
+ /**
+ * @dataProvider provideHeaderExtractions
+ */
+ public function testExtractHeader( $text, $expected ) {
+ $this->assertEquals( $expected, EchoDiscussionParser::extractHeader( $text ) );
}
public function generateEventsForRevisionData() {
- return array(
- array(
+ return [
+ [
'new' => 637638133,
'old' => 637637213,
'username' => 'Cwobeel',
'lang' => 'en',
- 'pages' => array(
+ 'pages' => [
// pages expected to exist (e.g. templates to be expanded)
'Template:u' => '[[User:{{{1}}}|{{<includeonly>safesubst:</includeonly>#if:{{{2|}}}|{{{2}}}|{{{1}}}}}]]<noinclude>{{documentation}}</noinclude>',
- ),
+ ],
'title' => 'UTPage', // can't remember, not important here
- 'expected' => array(
+ 'expected' => [
// events expected to be fired going from old revision to new
- array(
+ [
'type' => 'mention',
'agent' => 'Cwobeel',
+ 'section-title' => 'Grand jury no bill reception',
/*
* I wish I could also compare EchoEvent::$extra data to
* compare user ids of mentioned users. However, due to
@@ -185,45 +207,47 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
* user ids of the folks we're about to insert...
* I'll skip that part for now.
*/
- ),
- ),
- ),
- array(
+ ],
+ ],
+ ],
+ [
'new' => 138275105,
'old' => 138274875,
'username' => 'Schnark',
'lang' => 'de',
- 'pages' => array(),
+ 'pages' => [],
'title' => 'UTPage', // can't remember, not important here
- 'expected' => array(
- array(
+ 'expected' => [
+ [
'type' => 'mention',
'agent' => 'Schnark',
- ),
- ),
- ),
- array(
+ 'section-title' => 'Echo-Test',
+ ],
+ ],
+ ],
+ [
'new' => 40610292,
'old' => 40608353,
'username' => 'PauloEduardo',
'lang' => 'pt',
- 'pages' => array(
+ 'pages' => [
'Predefinição:U' => '[[User:{{{1|<noinclude>Exemplo</noinclude>}}}|{{{{{|safesubst:}}}#if:{{{2|}}}|{{{2}}}|{{{1|<noinclude>Exemplo</noinclude>}}}}}]]<noinclude>{{Atalho|Predefinição:U}}{{Documentação|Predefinição:Usuário/doc}}</noinclude>',
- ),
+ ],
'title' => 'UTPage', // can't remember, not important here
- 'expected' => array(
- array(
+ 'expected' => [
+ [
'type' => 'mention',
'agent' => 'PauloEduardo',
- ),
- ),
- ),
- array(
+ 'section-title' => 'Notificações',
+ ],
+ ],
+ ],
+ [
'new' => 646792804,
'old' => 646790570,
'username' => 'PatHadley',
'lang' => 'en',
- 'pages' => array(
+ 'pages' => [
'Template:ping' => '{{SAFESUBST:<noinclude />#if:{{{1|<noinclude>$</noinclude>}}}
|<span class="template-ping">@[[:User:{{SAFESUBST:<noinclude />BASEPAGENAME:{{{1|Example}}}}}|{{SAFESUBST:<noinclude />BASEPAGENAME:{{{label1|{{{1|Example}}}}}}}}]]{{SAFESUBST:<noinclude />#if:{{{2|}}}
|, [[:User:{{SAFESUBST:<noinclude />BASEPAGENAME:{{{2|Example}}}}}|{{SAFESUBST:<noinclude />BASEPAGENAME:{{{label2|{{{2|Example}}}}}}}}]]{{SAFESUBST:<noinclude />#if:{{{3|}}}
@@ -244,86 +268,695 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
{{documentation}}
</noinclude>',
'MediaWiki:Signature' => '[[User:$1|$2]] {{#ifeq:{{FULLPAGENAME}}|User talk:$1|([[User talk:$1#top|talk]])|([[User talk:$1|talk]])}}',
- ),
+ ],
'title' => 'User_talk:PatHadley',
- 'expected' => array(
- array(
+ 'expected' => [
+ [
'type' => 'mention',
'agent' => 'PatHadley',
- ),
- array(
+ 'section-title' => 'Wizardry required',
+ ],
+ [
'type' => 'edit-user-talk',
'agent' => 'PatHadley',
- ),
- ),
+ 'section-title' => 'Wizardry required',
+ ],
+ ],
'precondition' => 'isParserFunctionsInstalled',
- ),
- array(
+ ],
+ [
'new' => 647260329,
'old' => 647258025,
'username' => 'Kudpung',
'lang' => 'en',
- 'pages' => array(
+ 'pages' => [
'Template:U' => '[[User:{{{1}}}|{{<includeonly>safesubst:</includeonly>#if:{{{2|}}}|{{{2}}}|{{{1}}}}}]]<noinclude>{{documentation}}</noinclude>',
- ),
+ ],
'title' => 'User_talk:Kudpung',
- 'expected' => array(
- array(
+ 'expected' => [
+ [
'type' => 'mention',
'agent' => 'Kudpung',
- ),
- array(
+ 'section-title' => 'Me?',
+ ],
+ [
'type' => 'edit-user-talk',
'agent' => 'Kudpung',
- ),
- ),
- ),
+ 'section-title' => 'Me?',
+ ],
+ ],
+ ],
// T68512, leading colon in user page link in signature
- array(
+ [
'new' => 612485855,
'old' => 612485595,
'username' => 'Admin',
'lang' => 'en',
- 'pages' => array(),
+ 'pages' => [],
'title' => 'User_talk:Admin',
- 'expected' => array(
- array(
+ 'expected' => [
+ [
'type' => 'mention',
'agent' => 'Admin',
- ),
- array(
+ 'section-title' => 'Hi',
+ ],
+ [
'type' => 'edit-user-talk',
'agent' => 'Admin',
- ),
- ),
+ 'section-title' => 'Hi',
+ ],
+ ],
'precondition' => 'isParserFunctionsInstalled',
- ),
- );
+ ],
+ // T154406 unintended mentions when changing content
+ [
+ 'new' => 987667999,
+ 'old' => 987667998,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'MultipleSignatureMentions',
+ 'expected' => [],
+ ],
+ ];
}
/**
* @dataProvider generateEventsForRevisionData
*/
- public function testGenerateEventsForRevision( $newId, $oldId, $username, $lang, $pages, $title, $expected, $precondition = '' ) {
+ public function testGenerateEventsForRevision(
+ $newId, $oldId, $username, $lang, $pages, $title, $expected, $precondition = ''
+ ) {
if ( $precondition !== '' ) {
$result = $this->$precondition();
if ( $result !== true ) {
$this->markTestSkipped( $result );
+
return;
}
}
- $this->setMwGlobals( array(
+ $this->setupAllTestUsers();
+
+ $revision = $this->setupTestRevisionsForEventGeneration(
+ $newId, $oldId, $username, $lang, $pages, $title
+ );
+ $events = [];
+ $this->setupEventCallbackForEventGeneration(
+ function ( EchoEvent $event ) use ( &$events ) {
+ $events[] = [
+ 'type' => $event->getType(),
+ 'agent' => $event->getAgent()->getName(),
+ 'section-title' => $event->getExtraParam( 'section-title' ),
+ ];
+ return false;
+ }
+ );
+
+ // disable mention failure and success notifications
+ $this->setMwGlobals( 'wgEchoMentionStatusNotifications', false );
+
+ EchoDiscussionParser::generateEventsForRevision( $revision );
+
+ $this->assertEquals( $expected, $events );
+ }
+
+ public function provider_generateEventsForRevision_mentionStatus() {
+ return [
+ [
+ 'new' => 747747748,
+ 'old' => 747747747,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage',
+ 'expected' => [
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Hello Users',
+ 'notifyAgent' => true,
+ 'subject-name' => 'Ping',
+ ],
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Hello Users',
+ 'notifyAgent' => true,
+ 'subject-name' => 'Po?ng',
+ ],
+ ],
+ ],
+ [
+ 'new' => 747747750,
+ 'old' => 747747747,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage',
+ 'expected' => [
+ [
+ 'type' => 'mention',
+ 'agent' => 'Admin',
+ 'section-title' => 'Hello Users',
+ 'notifyAgent' => null,
+ 'subject-name' => null,
+ ],
+ [
+ 'type' => 'mention-success',
+ 'agent' => 'Admin',
+ 'section-title' => 'Hello Users',
+ 'notifyAgent' => true,
+ 'subject-name' => 'Test11',
+ ],
+ ],
+ ],
+ [
+ 'new' => 747798766,
+ 'old' => 747798765,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage',
+ 'expected' => [
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 2',
+ 'notifyAgent' => true,
+ 'subject-name' => 'NoUser',
+ ],
+ ],
+ ],
+ [
+ 'new' => 747798767,
+ 'old' => 747798765,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage',
+ 'expected' => [
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 2',
+ 'notifyAgent' => true,
+ 'subject-name' => 'NoUser',
+ ],
+ ],
+ ],
+ [
+ 'new' => 747798768,
+ 'old' => 747798765,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage',
+ 'expected' => [],
+ ],
+ [
+ 'new' => 747798770,
+ 'old' => 747798765,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage',
+ 'expected' => [
+ [
+ 'type' => 'mention',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1.5',
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ],
+ [
+ 'type' => 'mention-success',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1.5',
+ 'subject-name' => 'Test11',
+ 'notifyAgent' => true,
+ ],
+ ],
+ ],
+ [
+ 'new' => 747798771,
+ 'old' => 747798765,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage',
+ 'expected' => [
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1.5',
+ 'subject-name' => 'NoUser1.5',
+ 'notifyAgent' => true,
+ ],
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 2',
+ 'subject-name' => 'NoUser2',
+ 'notifyAgent' => true,
+ ],
+ ],
+ ],
+ [
+ 'new' => 747798772,
+ 'old' => 747798765,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage',
+ 'expected' => [
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1',
+ 'subject-name' => 'NoUser1',
+ 'notifyAgent' => true,
+ ],
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1.75',
+ 'subject-name' => 'NoUser1.75',
+ 'notifyAgent' => true,
+ ],
+ [
+ 'type' => 'mention-failure',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 2',
+ 'subject-name' => 'NoUser2',
+ 'notifyAgent' => true,
+ ],
+ ],
+ [
+ 'new' => 987654322,
+ 'old' => 987654321,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'User_talk:Admin',
+ 'expected' => [ [
+ 'type' => 'edit-user-talk',
+ 'agent' => 'Admin',
+ 'section-title' => false,
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ] ],
+ ],
+ [
+ 'new' => 987654323,
+ 'old' => 987654321,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'User_talk:Admin',
+ 'expected' => [
+ [
+ 'type' => 'mention',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1',
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ],
+ [
+ 'type' => 'mention-success',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1',
+ 'subject-name' => 'Test11',
+ 'notifyAgent' => true,
+ ],
+ [
+ 'type' => 'edit-user-talk',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1',
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ],
+ ],
+ ],
+ ],
+ [
+ 'new' => 987654324,
+ 'old' => 987654321,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'User_talk:Admin',
+ 'expected' => [
+ [
+ 'type' => 'mention',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1',
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ],
+ [
+ 'type' => 'mention-success',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 1',
+ 'subject-name' => 'Test11',
+ 'notifyAgent' => true,
+ ],
+ [
+ 'type' => 'edit-user-talk',
+ 'agent' => 'Admin',
+ 'section-title' => false,
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ],
+ ],
+ ],
+ [
+ 'new' => 987654325,
+ 'old' => 987654321,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'User_talk:Admin',
+ 'expected' => [
+ [
+ 'type' => 'mention',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 2',
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ],
+ [
+ 'type' => 'mention-success',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 2',
+ 'subject-name' => 'Test11',
+ 'notifyAgent' => true,
+ ],
+ [
+ 'type' => 'edit-user-talk',
+ 'agent' => 'Admin',
+ 'section-title' => 'Section 2',
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ],
+ ],
+ ],
+ [
+ 'new' => 987654401,
+ 'old' => 987654400,
+ 'username' => 'Admin',
+ 'lang' => 'en',
+ 'pages' => [],
+ 'title' => 'UTPage2',
+ 'expected' => [
+ [
+ 'type' => 'mention',
+ 'agent' => 'Admin',
+ 'section-title' => false,
+ 'subject-name' => null,
+ 'notifyAgent' => null,
+ ],
+ [
+ 'type' => 'mention-success',
+ 'agent' => 'Admin',
+ 'section-title' => false,
+ 'subject-name' => 'Test11',
+ 'notifyAgent' => true,
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provider_generateEventsForRevision_mentionStatus
+ */
+ public function testGenerateEventsForRevision_mentionStatus(
+ $newId, $oldId, $username, $lang, $pages, $title, $expected
+ ) {
+ $this->setupAllTestUsers();
+
+ $revision = $this->setupTestRevisionsForEventGeneration(
+ $newId, $oldId, $username, $lang, $pages, $title
+ );
+ $events = [];
+ $this->setupEventCallbackForEventGeneration(
+ function ( EchoEvent $event ) use ( &$events ) {
+ $events[] = [
+ 'type' => $event->getType(),
+ 'agent' => $event->getAgent()->getName(),
+ 'section-title' => $event->getExtraParam( 'section-title' ),
+ 'notifyAgent' => $event->getExtraParam( 'notifyAgent' ),
+ 'subject-name' => $event->getExtraParam( 'subject-name' ),
+ ];
+ return false;
+ }
+ );
+
+ // enable mention failure and success notifications
+ $this->setMwGlobals( 'wgEchoMentionStatusNotifications', true );
+ // enable multiple sections mentions
+ $this->setMwGlobals( 'wgEchoMentionsOnMultipleSectionEdits', true );
+
+ EchoDiscussionParser::generateEventsForRevision( $revision );
+
+ $this->assertEquals( $expected, $events );
+ }
+
+ public function provider_extractSections() {
+ return [
+ [
+ 'content' => 'Just Text.',
+ 'result' => [
+ [
+ 'header' => false,
+ 'content' => 'Just Text.',
+ ],
+ ],
+ ],
+ [
+ 'content' =>
+<<<TEXT
+Text and a
+== Headline ==
+with text
+TEXT
+ ,
+ 'result' => [
+ [
+ 'header' => false,
+ 'content' =>
+<<<TEXT
+Text and a
+TEXT
+ ,
+ ],
+ [
+ 'header' => 'Headline',
+ 'content' =>
+<<<TEXT
+== Headline ==
+with text
+TEXT
+ ,
+ ],
+ ],
+ ],
+ [
+ 'content' =>
+<<<TEXT
+== Headline ==
+Text and a [[User:Test]]
+TEXT
+ ,
+ 'result' => [
+ [
+ 'header' => 'Headline',
+ 'content' =>
+<<<TEXT
+== Headline ==
+Text and a [[User:Test]]
+TEXT
+ ,
+ ],
+ ],
+ ],
+ [
+ 'content' =>
+<<<TEXT
+Content 0
+== Headline 1 ==
+Content 1
+=== Headline 2 ===
+Content 2
+TEXT
+ ,
+ 'result' => [
+ [
+ 'header' => false,
+ 'content' => 'Content 0',
+ ],
+ [
+ 'header' => 'Headline 1',
+ 'content' =>
+<<<TEXT
+== Headline 1 ==
+Content 1
+TEXT
+ ,
+ ],
+ [
+ 'header' => 'Headline 2',
+ 'content' =>
+<<<TEXT
+=== Headline 2 ===
+Content 2
+TEXT
+ ,
+ ],
+ ],
+ ],
+ [
+ 'content' =>
+<<<TEXT
+== Headline 1 ==
+مرحبا كيف حالك
+=== Headline 2 ===
+انا بخير شكرا
+TEXT
+ ,
+ 'result' => [
+ [
+ 'header' => 'Headline 1',
+ 'content' =>
+<<<TEXT
+== Headline 1 ==
+مرحبا كيف حالك
+TEXT
+ ,
+ ],
+ [
+ 'header' => 'Headline 2',
+ 'content' =>
+<<<TEXT
+=== Headline 2 ===
+انا بخير شكرا
+TEXT
+ ,
+ ],
+ ],
+ ],
+ [
+ 'content' =>
+<<<TEXT
+مرحبا كيف حالك
+=== Headline 1 ===
+انا بخير شكرا
+TEXT
+ ,
+ 'result' => [
+ [
+ 'header' => false,
+ 'content' =>
+<<<TEXT
+مرحبا كيف حالك
+TEXT
+ ,
+ ],
+ [
+ 'header' => 'Headline 1',
+ 'content' =>
+<<<TEXT
+=== Headline 1 ===
+انا بخير شكرا
+TEXT
+ ,
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provider_extractSections
+ */
+ public function testExtractSections( $content, $result ) {
+ $discussionParser = TestingAccessWrapper::newFromClass( 'EchoDiscussionParser' );
+ $sections = $discussionParser->extractSections( $content );
+
+ $this->assertEquals( $result, $sections );
+ }
+
+ public function testGenerateEventsForRevision_tooManyMentionsFailure() {
+ $expected = [
+ [
+ 'type' => 'mention-failure-too-many',
+ 'agent' => 'Admin',
+ 'section-title' => 'Hello Users',
+ 'max-mentions' => 5,
+ ],
+ ];
+
+ $this->setupTestUser( 'Admin' );
+ $revision = $this->setupTestRevisionsForEventGeneration( 747747749, 747747747, 'Admin', 'en', [], 'UTPage' );
+
+ $events = [];
+ $this->setupEventCallbackForEventGeneration(
+ function ( EchoEvent $event ) use ( &$events ) {
+ $events[] = [
+ 'type' => $event->getType(),
+ 'agent' => $event->getAgent()->getName(),
+ 'section-title' => $event->getExtraParam( 'section-title' ),
+ 'max-mentions' => $event->getExtraParam( 'max-mentions' ),
+ ];
+ return false;
+ }
+ );
+
+ $this->setMwGlobals( [
+ // enable mention failure and success notifications
+ 'wgEchoMentionStatusNotifications' => true,
+ // lower limit for the mention-failure-too-many notification
+ 'wgEchoMaxMentionsCount' => 5
+ ] );
+
+ EchoDiscussionParser::generateEventsForRevision( $revision );
+
+ $this->assertEquals( $expected, $events );
+ }
+
+ private function setupTestRevisionsForEventGeneration( $newId, $oldId, $username, $lang, $pages, $title ) {
+ $langObj = Language::factory( $lang );
+ $this->setMwGlobals( [
// this global is used by the code that interprets the namespace part of
// titles (Title::getTitleParser), so should be the fake language ;)
- 'wgContLang' => Language::factory( $lang ),
+ 'wgContLang' => $langObj,
// this one allows Mediawiki:xyz pages to be set as messages
'wgUseDatabaseMessages' => true
- ) );
+ ] );
+
+ // Since we reset the $wgContLang global, reset the TitleParser service
+ $services = MediaWikiServices::getInstance();
+ if ( is_callable( [ $services, 'getTitleParser' ] ) ) {
+ // TODO: All of this should use $this->setService()
+ $services->resetServiceForTesting( 'TitleParser' );
+ $services->redefineService( 'TitleParser', function () use ( $langObj ) {
+ global $wgLocalInterwikis;
+ return new MediaWikiTitleCodec(
+ $langObj,
+ new GenderCache(),
+ $wgLocalInterwikis
+ );
+ } );
+ // Cleanup
+ $lock = new ScopedCallback( function () use ( $services ) {
+ $services->resetServiceForTesting( 'TitleParser' );
+ } );
+ }
// pages to be created: templates may be used to ping users (e.g.
// {{u|...}}) but if we don't have that template, it just won't work!
- $pages += array( $title => '' );
+ $pages += [ $title => '' ];
foreach ( $pages as $pageTitle => $pageText ) {
$template = WikiPage::factory( Title::newFromText( $pageTitle ) );
$template->doEditContent( new WikitextContent( $pageText ), '' );
@@ -348,14 +981,14 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
$property->setValue( $title, $lang );
// create stub Revision object
- $row = array(
+ $row = [
'id' => $newId,
'user_text' => $username,
'user' => User::newFromName( $username )->getId(),
'parent_id' => $oldId,
'text' => $newText,
'title' => $title,
- );
+ ];
$revision = Revision::newFromRow( $row );
// generate diff between 2 revisions
@@ -368,69 +1001,25 @@ class EchoDiscussionParserTest extends MediaWikiTestCase {
$class = new ReflectionClass( 'EchoDiscussionParser' );
$property = $class->getProperty( 'revisionInterpretationCache' );
$property->setAccessible( true );
- $property->setValue( array( $revision->getId() => $output ) );
+ $property->setValue( [ $revision->getId() => $output ] );
+ return $revision;
+ }
+ private function setupEventCallbackForEventGeneration( callable $callback ) {
// to catch the generated event, I'm going to attach a callback to the
// hook that's being run just prior to sending the notifications out
- $events = array();
- $callback = function( EchoEvent $event ) use ( &$events ) {
- $events[] = array(
- 'type' => $event->getType(),
- 'agent' => $event->getAgent()->getName(),
- );
-
- // don't let the event go out, abort from within this hook
- return false;
- };
-
// can't use setMwGlobals here, so I'll just re-attach to the same key
// for every dataProvider value (and don't worry, I'm removing it on
// tearDown too - I just felt the attaching should be happening here
// instead of on setUp, or code would get too messy)
global $wgHooks;
$wgHooks['BeforeEchoEventInsert'][999] = $callback;
-
- // finally, dear god, start generating the events already!
- EchoDiscussionParser::generateEventsForRevision( $revision );
-
- $this->assertEquals( $expected, $events );
}
// TODO test cases for:
// - stripHeader
- // - stripIndents
// - stripSignature
- public function testDiscussionParserAcceptsInternalDiff() {
- global $wgDiff;
-
- $origWgDiff = $wgDiff;
- $wgDiff = '/does/not/exist/or/at/least/we/hope/not';
- try {
- $res = EchoDiscussionParser::getMachineReadableDiff(
- <<<TEXT
-line 1
-line 2
-line 3
-line 4
-TEXT
- ,
- <<<TEXT
-line 1
-line c
-line 4
-TEXT
- );
- } catch ( MWException $e ) {
- $wgDiff = $origWgDiff;
- throw $e;
- }
- $wgDiff = $origWgDiff;
-
- // Test failure occurs when MWException is thrown due to parsing failure
- $this->assertTrue( true );
- }
-
public function testTimestampRegex() {
$exemplarTimestamp = self::getExemplarTimestamp();
$timestampRegex = EchoDiscussionParser::getTimestampRegex();
@@ -440,7 +1029,7 @@ TEXT
}
public function testGetTimestampPosition() {
- $line = 'Hello World. '. self::getExemplarTimestamp();
+ $line = 'Hello World. ' . self::getExemplarTimestamp();
$pos = EchoDiscussionParser::getTimestampPosition( $line );
$this->assertEquals( 13, $pos );
}
@@ -450,8 +1039,13 @@ TEXT
* FIXME some of the app logic is in the test...
*/
public function testSigningDetection( $line, $expectedUser ) {
+ if ( is_array( $expectedUser ) ) {
+ $this->setupTestUser( $expectedUser[1] );
+ }
+
if ( !EchoDiscussionParser::isSignedComment( $line ) ) {
$this->assertEquals( $expectedUser, false );
+
return;
}
@@ -461,7 +1055,7 @@ TEXT
$this->assertEquals( false, $expectedUser );
} elseif ( is_array( $expectedUser ) ) {
// Sometimes testing for correct user detection,
- // sometimes testing for offset detection
+ // sometimes testing for offset detection
$this->assertEquals( $expectedUser, $output );
} else {
$this->assertEquals( $expectedUser, $output[1] );
@@ -470,97 +1064,98 @@ TEXT
public function signingDetectionData() {
$ts = self::getExemplarTimestamp();
- return array(
+
+ return [
// Basic
- array(
+ [
"I like this. [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
- array(
+ [
13,
'Werdna'
- ),
- ),
+ ],
+ ],
// Confounding
- array(
+ [
"[[User:Jorm]] is a meanie. --[[User:Werdna2|Andrew]] $ts",
- array(
+ [
29,
"Werdna2"
- ),
- ),
+ ],
+ ],
// Talk page link only
- array(
+ [
"[[User:Swalling|Steve]] is the best person I have ever met. --[[User talk:Werdna3|Andrew]] $ts",
- array(
+ [
62,
'Werdna3'
- ),
- ),
+ ],
+ ],
// Anonymous user
- array(
+ [
"I am anonymous because I like my IP address. --[[Special:Contributions/127.0.0.1|127.0.0.1]] $ts",
- array(
+ [
47,
'127.0.0.1'
- ),
- ),
+ ],
+ ],
// No signature
- array(
- "Well, \nI do think that [[User:Newyorkbrad]] is pretty cool, but what do I know?",
+ [
+ "Well, \nI do think that [[User:Newyorkbrad]] is pretty cool, but what do I know?",
false
- ),
+ ],
// Hash symbols in usernames
- array(
+ [
"What do you think? [[User talk:We buried our secrets in the garden#top|wbositg]] $ts",
- array(
+ [
19,
'We buried our secrets in the garden'
- ),
- ),
+ ],
+ ],
// Title that gets normalized different than it is provided in the wikitext
- array(
+ [
"Beep boop [[User:I_Heart_Spaces]] ([[User_talk:I_Heart_Spaces]]) $ts",
- array(
+ [
strlen( "Beep boop " ),
'I Heart Spaces'
- ),
- ),
+ ],
+ ],
// Accepts ] in the pipe
- array(
+ [
"Shake n Bake --[[User:Werdna4|wer]dna]] $ts",
- array(
+ [
strlen( "Shake n Bake --" ),
'Werdna4',
- ),
- ),
+ ],
+ ],
- array(
+ [
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxã? [[User:Jam]] $ts",
- array(
+ [
strlen( "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxã? " ),
"Jam"
- ),
- ),
+ ],
+ ],
// extra long signature
- array(
+ [
"{{U|He7d3r}}, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxã? [[User:Reverta-me|<span style=\"font-size:13px; color:blue;font-family:Lucida Handwriting;text-shadow:aqua 5px 3px 12px;\">Aaaaa Bbbbbbb</span>]]'' <sup>[[User Talk:Reverta-me|<font color=\"gold\" face=\"Lucida Calligraphy\">Discussão</font>]]</sup>''",
- array(
+ [
strlen( "{{U|He7d3r}}, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxã? " ),
'Reverta-me',
- ),
- ),
+ ],
+ ],
// Bug: T87852
- array(
+ [
"Test --[[Benutzer:Schnark]] ([[Benutzer:Schnark/js|js]])",
- array(
+ [
strlen( "Test --" ),
'Schnark',
- ),
- ),
+ ],
+ ],
// when adding additional tests, make sure to add the non-anon users
// to EchoDiscussionParserTest::$testusers - the DiscussionParser
// needs the users to exist, because it'll generate a comparison
// signature, which is different when the user is considered anon
- );
+ ];
}
/** @dataProvider diffData */
@@ -573,79 +1168,79 @@ TEXT
}
public function diffData() {
- return array(
- array(
+ return [
+ [
<<<TEXT
line 1
line 2
line 3
line 4
TEXT
- ,<<<TEXT
+ , <<<TEXT
line 1
line 3
line 4
TEXT
- ,
- array( array(
+ ,
+ [ [
'action' => 'subtract',
'content' => 'line 2',
'left-pos' => 2,
'right-pos' => 2,
- ) )
- ),
- array(
+ ] ]
+ ],
+ [
<<<TEXT
line 1
line 2
line 3
line 4
TEXT
- ,<<<TEXT
+ , <<<TEXT
line 1
line 2
line 2.5
line 3
line 4
TEXT
- ,
- array( array(
+ ,
+ [ [
'action' => 'add',
'content' => 'line 2.5',
'left-pos' => 3,
'right-pos' => 3,
- ) )
- ),
- array(
+ ] ]
+ ],
+ [
<<<TEXT
line 1
line 2
line 3
line 4
TEXT
- ,<<<TEXT
+ , <<<TEXT
line 1
line b
line 3
line 4
TEXT
- ,
- array( array(
+ ,
+ [ [
'action' => 'change',
'old_content' => 'line 2',
'new_content' => 'line b',
'left-pos' => 2,
'right-pos' => 2,
- ) )
- ),
- array(
+ ] ]
+ ],
+ [
<<<TEXT
line 1
line 2
line 3
line 4
TEXT
- ,<<<TEXT
+ , <<<TEXT
line 1
line b
line c
@@ -653,29 +1248,30 @@ line d
line 3
line 4
TEXT
- ,
- array(
- array(
+ ,
+ [
+ [
'action' => 'change',
'old_content' => 'line 2',
'new_content' => 'line b',
'left-pos' => 2,
'right-pos' => 2,
- ),
- array(
+ ],
+ [
'action' => 'add',
'content' => 'line c
line d',
'left-pos' => 3,
'right-pos' => 3,
- ),
- ),
- ),
- );
+ ],
+ ],
+ ],
+ ];
}
/** @dataProvider annotationData */
public function testAnnotation( $message, $diff, $user, $expectedAnnotation ) {
+ $this->setupTestUser( $user );
$actual = EchoDiscussionParser::interpretDiff( $diff, $user );
$this->assertEquals( $expectedAnnotation, $actual, $message );
}
@@ -683,36 +1279,36 @@ line d',
public function annotationData() {
$ts = self::getExemplarTimestamp();
- return array(
+ return [
- array(
+ [
'Must detect added comments',
// Diff
- array(
+ [
// Action
- array(
+ [
'action' => 'add',
'content' => ":What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
'left-pos' => 3,
'right-pos' => 3,
- ),
- '_info' => array(
- 'lhs' => array(
+ ],
+ '_info' => [
+ 'lhs' => [
'== Section 1 ==',
"I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts",
- ),
- 'rhs' => array(
+ ],
+ 'rhs' => [
'== Section 1 ==',
"I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts",
":What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
- ),
- ),
- ),
+ ],
+ ],
+ ],
// User
'Werdna',
// Expected annotation
- array(
- array(
+ [
+ [
'type' => 'add-comment',
'content' => ":What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
'full-section' => <<<TEXT
@@ -720,42 +1316,42 @@ line d',
I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts
:What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts
TEXT
- ),
- ),
- ),
+ ],
+ ],
+ ],
- array(
+ [
'Full Section must not include the following pre-existing section',
// Diff
- array(
+ [
// Action
- array(
+ [
'action' => 'add',
'content' => ":What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
'left-pos' => 3,
'right-pos' => 3,
- ),
- '_info' => array(
- 'lhs' => array(
+ ],
+ '_info' => [
+ 'lhs' => [
'== Section 1 ==',
"I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts",
'== Section 2 ==',
"Well well well. [[User:DarTar|DarTar]] ([[User talk:DarTar|talk]]) $ts",
- ),
- 'rhs' => array(
+ ],
+ 'rhs' => [
'== Section 1 ==',
"I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts",
":What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
'== Section 2 ==',
"Well well well. [[User:DarTar|DarTar]] ([[User talk:DarTar|talk]]) $ts",
- ),
- ),
- ),
+ ],
+ ],
+ ],
// User
'Werdna',
// Expected annotation
- array(
- array(
+ [
+ [
'type' => 'add-comment',
'content' => ":What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
'full-section' => <<<TEXT
@@ -763,34 +1359,34 @@ TEXT
I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts
:What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts
TEXT
- ),
- ),
- ),
+ ],
+ ],
+ ],
- array(
+ [
'Must detect new-section-with-comment when a new section is added',
// Diff
- array(
+ [
// Action
- array(
+ [
'action' => 'add',
'content' => <<<TEXT
== Section 1a ==
Hmmm? [[User:Jdforrester|Jdforrester]] ([[User talk:Jdforrester|talk]]) $ts
TEXT
- ,
+ ,
'left-pos' => 4,
'right-pos' => 4,
- ),
- '_info' => array(
- 'lhs' => array(
+ ],
+ '_info' => [
+ 'lhs' => [
'== Section 1 ==',
"I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts",
":What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
'== Section 2 ==',
"Well well well. [[User:DarTar|DarTar]] ([[User talk:DarTar|talk]]) $ts",
- ),
- 'rhs' => array(
+ ],
+ 'rhs' => [
'== Section 1 ==',
"I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts",
":What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts",
@@ -798,25 +1394,25 @@ TEXT
'Hmmm? [[User:Jdforrester|Jdforrester]] ([[User talk:Jdforrested|talk]]) $ts',
'== Section 2 ==',
"Well well well. [[User:DarTar|DarTar]] ([[User talk:DarTar|talk]]) $ts",
- ),
- ),
- ),
+ ],
+ ],
+ ],
// User
'Jdforrester',
// Expected annotation
- array(
- array(
+ [
+ [
'type' => 'new-section-with-comment',
'content' => <<<TEXT
== Section 1a ==
Hmmm? [[User:Jdforrester|Jdforrester]] ([[User talk:Jdforrester|talk]]) $ts
TEXT
- ,
- ),
- ),
- ),
+ ,
+ ],
+ ],
+ ],
- array(
+ [
'Must detect multiple added comments when multiple sections are edited',
EchoDiscussionParser::getMachineReadableDiff(
<<<TEXT
@@ -828,7 +1424,7 @@ Well well well. [[User:DarTar|DarTar]] ([[User talk:DarTar|talk]]) $ts
== Section 3 ==
Hai [[User:Bsitu|Bsitu]] ([[User talk:Bsitu|talk]]) $ts
TEXT
- ,
+,
<<<TEXT
== Section 1 ==
I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts
@@ -844,8 +1440,8 @@ TEXT
// User
'JarJar',
// Expected annotation
- array(
- array(
+ [
+ [
'type' => 'add-comment',
'content' => ":New Comment [[User:JarJar|JarJar]] ([[User talk:JarJar|talk]]) $ts",
'full-section' => <<<TEXT
@@ -854,8 +1450,8 @@ I do not like you. [[User:Jorm|Jorm]] ([[User talk:Jorm|talk]]) $ts
:What do you think? [[User:Werdna|Werdna]] ([[User talk:Werdna|talk]]) $ts
:New Comment [[User:JarJar|JarJar]] ([[User talk:JarJar|talk]]) $ts
TEXT
- ),
- array(
+ ],
+ [
'type' => 'add-comment',
'content' => ":Other New Comment [[User:JarJar|JarJar]] ([[User talk:JarJar|talk]]) $ts",
'full-section' => <<<TEXT
@@ -863,11 +1459,11 @@ TEXT
Hai [[User:Bsitu|Bsitu]] ([[User talk:Bsitu|talk]]) $ts
:Other New Comment [[User:JarJar|JarJar]] ([[User talk:JarJar|talk]]) $ts
TEXT
- ),
- ),
- ),
+ ],
+ ],
+ ],
- array(
+ [
'Bug T78424',
EchoDiscussionParser::getMachineReadableDiff(
<<<TEXT
@@ -875,7 +1471,7 @@ TEXT
''The Boston Post'' source that was used in the reception section has a couple of problems. First, it's actually a repost of ''The Washington Post'', but ''The Washington Post'' doesn't allow the Internet Archive to preserve it. Should it still be sourced to Boston or to Washington? Second, it seems to be a lot of analysis that can't be summed up easily without trimming it out, and doesn't really fit with the reception section and should probably moved next to Wilson's testimony. Any suggestions? --[[User:RAN1|RAN1]] ([[User talk:RAN1|talk]]) 01:44, 11 December 2014 (UTC)
TEXT
- ,
+,
<<<TEXT
== Washington Post Reception Source ==
@@ -889,20 +1485,20 @@ TEXT
// User
'Cwobeel',
// Expected annotation
- array(
- array(
+ [
+ [
'type' => 'new-section-with-comment',
'content' => '== Grand jury no bill reception ==
{{u|Bob K31416}} has started a process of summarizing that section, in a manner that I believe it to be counter productive. We have expert opinions from legal, law enforcement, politicians, and media outlets all of which are notable and informative. [[WP:NOTPAPER|Wikipedia is not paper]] – If the section is too long, the correct process to avoid losing good content that is well sources, is to create a sub-article with all the detail, and summarize here per [[WP:SUMMARY]]. But deleting useful and well sourced material, is not acceptable. We are here to build an encyclopedia. - [[User:Cwobeel|<span style="color:#339966">Cwobeel</span>]] [[User_talk:Cwobeel|<span style="font-size:80%">(talk)</span>]] 16:02, 11 December 2014 (UTC)',
- ),
- ),
- ),
+ ],
+ ],
+ ],
// when adding additional tests, make sure to add the non-anon users
// to EchoDiscussionParserTest::$testusers - the DiscussionParser
// needs the users to exist, because it'll generate a comparison
// signature, which is different when the user is considered anon
- );
+ ];
}
public static function getExemplarTimestamp() {
@@ -917,12 +1513,12 @@ TEXT
return $exemplarTimestamp;
}
- static public function provider_detectSectionTitleAndText() {
+ public static function provider_detectSectionTitleAndText() {
$name = 'Werdna'; // See EchoDiscussionParserTest::$testusers
$comment = self::signedMessage( $name );
- return array(
- array(
+ return [
+ [
'Must detect first sub heading when inserting in the middle of two sub headings',
// expected header content
'Sub Heading 1',
@@ -940,9 +1536,9 @@ $comment
",
// user signing new comment
$name
- ),
+ ],
- array(
+ [
'Must detect second sub heading when inserting in the end of two sub headings',
// expected header content
'Sub Heading 2',
@@ -960,9 +1556,9 @@ $comment
",
// user signing new comment
$name
- ),
+ ],
- array(
+ [
'Commenting in multiple sub-headings must result in no section link',
// expected header content
'',
@@ -982,9 +1578,9 @@ $comment
",
// user signing new comment
$name
- ),
+ ],
- array(
+ [
'Must accept headings without a space between the = and the section name',
// expected header content
'Heading',
@@ -996,9 +1592,9 @@ $comment
",
// user signing new comment
$name
- ),
+ ],
- array(
+ [
'Must not accept invalid headings split with a return',
// expected header content
'',
@@ -1011,14 +1607,16 @@ $comment
",
// user signing new comment
$name
- ),
- );
+ ],
+ ];
}
/**
* @dataProvider provider_detectSectionTitleAndText
*/
public function testDetectSectionTitleAndText( $message, $expect, $format, $name ) {
+ $this->setupTestUser( $name );
+
// str_replace because we want to replace multiple instances of '%s' with the same value
$before = str_replace( '%s', '', $format );
$after = str_replace( '%s', self::signedMessage( $name ), $format );
@@ -1029,7 +1627,7 @@ $comment
// There should be a section-text only if there is section-title
$expectText = $expect ? self::message( $name ) : '';
$this->assertEquals(
- array( 'section-title' => $expect, 'section-text' => $expectText ),
+ [ 'section-title' => $expect, 'section-text' => $expectText ],
EchoDiscussionParser::detectSectionTitleAndText( $interp ),
$message
);
@@ -1043,9 +1641,9 @@ $comment
return 'foo';
}
- static public function provider_getFullSection() {
- $tests = array(
- array(
+ public static function provider_getFullSection() {
+ $tests = [
+ [
'Extracts full section',
// Full document content
<<<TEXT
@@ -1056,30 +1654,30 @@ bar
==Header 3==
baz
TEXT
- ,
+ ,
// Map of Line numbers to expanded section content
- array(
+ [
1 => "==Header 1==\nfoo",
2 => "==Header 1==\nfoo",
3 => "===Header 2===\nbar",
4 => "===Header 2===\nbar",
5 => "==Header 3==\nbaz",
6 => "==Header 3==\nbaz",
- ),
- ),
- );
+ ],
+ ],
+ ];
// Allow for setting an array of line numbers to expand from rather than
// just a single line number
- $retval = array();
+ $retval = [];
foreach ( $tests as $test ) {
foreach ( $test[2] as $lineNum => $expected ) {
- $retval[] = array(
+ $retval[] = [
$test[0],
$expected,
$test[1],
$lineNum,
- );
+ ];
}
}
@@ -1103,6 +1701,97 @@ TEXT
$this->assertEquals( 2, EchoDiscussionParser::getSectionCount( $one . $two ) );
$this->assertEquals( 2, EchoDiscussionParser::getSectionCount( $one . $three ) );
$this->assertEquals( 3, EchoDiscussionParser::getSectionCount( $one . $two . $three ) );
+ $this->assertEquals( 30, EchoDiscussionParser::getSectionCount(
+ file_get_contents( __DIR__ . '/revision_txt/637638133.txt' )
+ ) );
+ }
+
+ public function testGetOverallUserMentionsCount() {
+ $userMentions = [
+ 'validMentions' => [ 1 => 1 ],
+ 'unknownUsers' => [ 'NotKnown1', 'NotKnown2' ],
+ 'anonymousUsers' => [ '127.0.0.1' ],
+ ];
+
+ $discussionParser = TestingAccessWrapper::newFromClass( 'EchoDiscussionParser' );
+ $this->assertEquals( 4, $discussionParser->getOverallUserMentionsCount( $userMentions ) );
+ }
+
+ public function provider_getUserMentions() {
+ return [
+ [
+ [ 'NotKnown1' => 0 ],
+ [
+ 'validMentions' => [],
+ 'unknownUsers' => [ 'NotKnown1' ],
+ 'anonymousUsers' => [],
+ ],
+ 1
+ ],
+ [
+ [ '127.0.0.1' => 0 ],
+ [
+ 'validMentions' => [],
+ 'unknownUsers' => [],
+ 'anonymousUsers' => [ '127.0.0.1' ],
+ ],
+ 1
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provider_getUserMentions
+ */
+ public function testGetUserMentions( $userLinks, $expectedUserMentions, $agent ) {
+ $title = Title::newFromText( 'Test' );
+ $discussionParser = TestingAccessWrapper::newFromClass( 'EchoDiscussionParser' );
+ $this->assertEquals( $expectedUserMentions, $discussionParser->getUserMentions( $title, $agent, $userLinks ) );
+ }
+
+ public function testGetUserMentions_validMention() {
+ $userName = 'Admin';
+ $this->setupTestUser( $userName );
+ $userId = User::newFromName( $userName )->getId();
+ $expectedUserMentions = [
+ 'validMentions' => [ $userId => $userId ],
+ 'unknownUsers' => [],
+ 'anonymousUsers' => [],
+ ];
+ $userLinks = [ $userName => $userId ];
+ $this->testGetUserMentions( $userLinks, $expectedUserMentions, 1 );
+ }
+
+ public function testGetUserMentions_ownMention() {
+ $userName = 'Admin';
+ $this->setupTestUser( $userName );
+ $userId = User::newFromName( 'Admin' )->getId();
+ $expectedUserMentions = [
+ 'validMentions' => [],
+ 'unknownUsers' => [],
+ 'anonymousUsers' => [],
+ ];
+ $userLinks = [ $userName => $userId ];
+ $this->testGetUserMentions( $userLinks, $expectedUserMentions, $userId );
+ }
+
+ public function testGetUserMentions_tooManyMentions() {
+ $userLinks = [
+ 'NotKnown1' => 0,
+ 'NotKnown2' => 0,
+ 'NotKnown3' => 0,
+ '127.0.0.1' => 0,
+ '127.0.0.2' => 0,
+ ];
+
+ $this->setMwGlobals( [
+ // lower limit for the mention-too-many notification
+ 'wgEchoMaxMentionsCount' => 3
+ ] );
+
+ $title = Title::newFromText( 'Test' );
+ $discussionParser = TestingAccessWrapper::newFromClass( 'EchoDiscussionParser' );
+ $this->assertEquals( 4, $discussionParser->getOverallUserMentionsCount( $discussionParser->getUserMentions( $title, 1, $userLinks ) ) );
}
protected function isParserFunctionsInstalled() {
@@ -1112,4 +1801,16 @@ TEXT
return "ParserFunctions not enabled";
}
}
+
+ public function testGetTextSnippet() {
+ $this->assertEquals(
+ 'Page001',
+ EchoDiscussionParser::getTextSnippet(
+ '[[:{{BASEPAGENAME}}]]',
+ Language::factory( 'en' ),
+ 150,
+ Title::newFromText( 'Page001' )
+ )
+ );
+ }
}
diff --git a/Echo/tests/phpunit/EchoDbFactoryTest.php b/Echo/tests/phpunit/EchoDbFactoryTest.php
index 61cffabf..18ac1170 100644
--- a/Echo/tests/phpunit/EchoDbFactoryTest.php
+++ b/Echo/tests/phpunit/EchoDbFactoryTest.php
@@ -5,6 +5,7 @@ class MWEchoDbFactoryTest extends MediaWikiTestCase {
public function testNewFromDefault() {
$db = MWEchoDbFactory::newFromDefault();
$this->assertInstanceOf( 'MWEchoDbFactory', $db );
+
return $db;
}
diff --git a/Echo/tests/phpunit/EmailFormatterTest.php b/Echo/tests/phpunit/EmailFormatterTest.php
deleted file mode 100644
index 4384f3e8..00000000
--- a/Echo/tests/phpunit/EmailFormatterTest.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-
-/**
- * @group Echo
- */
-class EchoEmailFormatterTest extends MediaWikiTestCase {
-
- private $emailSingle;
- private $emailDigest;
-
- public function setUp() {
- parent::setUp();
-
- $this->setMwGlobals( 'wgAllowHTMLEmail', true );
-
- $event = $this->mockEvent( 'edit-user-talk' );
- $event->expects( $this->any() )
- ->method( 'getTitle' )
- ->will( $this->returnValue( Title::newMainPage() ) );
-
- $formatter = EchoNotificationFormatter::factory( $event->getType() );
- $formatter->setOutputFormat( 'email' );
-
- $user = User::newFromId( 1 );
- $user->setName( 'Test' );
- $user->setOption( 'echo-email-format', EchoHooks::EMAIL_FORMAT_HTML );
-
- $this->emailSingle = new EchoEmailSingle( $formatter, $event, $user );
-
- $content[$event->getCategory()][] = EchoNotificationController::formatNotification( $event, $user, 'email', 'emaildigest' );
- $this->emailDigest = new EchoEmailDigest( User::newFromId( 2 ), $content );
- }
-
- public function testEmailFormatter() {
- $pattern = '/%%(.*?)%%/is';
-
- // Single email mode
- $textFormatter = new EchoTextEmailFormatter( $this->emailSingle );
- $this->assertRegExp( $pattern, $this->emailSingle->getTextTemplate() );
- $this->assertEquals( 0, preg_match ( $pattern, $textFormatter->formatEmail() ) );
-
- $htmlFormatter = new EchoHTMLEmailFormatter( $this->emailSingle );
- $this->assertRegExp( $pattern, $this->emailSingle->getHTMLTemplate() );
- $this->assertEquals( 0, preg_match ( $pattern, $htmlFormatter->formatEmail() ) );
-
- // Digest email mode
- $textFormatter = new EchoTextEmailFormatter( $this->emailDigest );
- $this->assertRegExp( $pattern, $this->emailSingle->getTextTemplate() );
- $this->assertEquals( 0, preg_match ( $pattern, $textFormatter->formatEmail() ) );
-
- $htmlFormatter = new EchoHTMLEmailFormatter( $this->emailDigest );
- $this->assertRegExp( $pattern, $this->emailSingle->getHTMLTemplate() );
- $this->assertEquals( 0, preg_match ( $pattern, $htmlFormatter->formatEmail() ) );
- }
-
- public function testBuildAction() {
- $this->emailSingle->attachDecorator( new EchoTextEmailDecorator() );
- $this->assertEquals( 0, preg_match ( '/<a /i', $this->emailSingle->buildAction() ) );
-
- $this->emailSingle->attachDecorator( new EchoHTMLEmailDecorator() );
- $this->assertRegExp( '/<a /i', $this->emailSingle->buildAction() );
-
- $this->emailDigest->attachDecorator( new EchoTextEmailDecorator() );
- $this->assertEquals( 0, preg_match ( '/<a /i', $this->emailDigest->buildAction() ) );
-
- $this->emailDigest->attachDecorator( new EchoHTMLEmailDecorator() );
- $this->assertRegExp( '/<a /i', $this->emailDigest->buildAction() );
- }
-
- /**
- * @param string $type
- * @return PHPUnit_Framework_MockObject_MockObject|EchoEvent
- */
- protected function mockEvent( $type ) {
- $methods = get_class_methods( 'EchoEvent' );
- $methods = array_diff( $methods, array( 'userCan', 'getLinkMessage', 'getLinkDestination' ) );
-
- $attribManager = EchoAttributeManager::newFromGlobalVars();
- $event = $this->getMockBuilder( 'EchoEvent' )
- ->disableOriginalConstructor()
- ->setMethods( $methods )
- ->getMock();
- $event->expects( $this->any() )
- ->method( 'getType' )
- ->will( $this->returnValue( $type ) );
- $event->expects( $this->any() )
- ->method( 'getCategory' )
- ->will( $this->returnValue( $attribManager->getNotificationCategory( $type ) ) );
- return $event;
- }
-
-}
diff --git a/Echo/tests/phpunit/NotifUserTest.php b/Echo/tests/phpunit/NotifUserTest.php
index e1e69ce0..d766a546 100644
--- a/Echo/tests/phpunit/NotifUserTest.php
+++ b/Echo/tests/phpunit/NotifUserTest.php
@@ -1,13 +1,21 @@
<?php
+use MediaWiki\MediaWikiServices;
/**
* @group Echo
*/
class MWEchoNotifUserTest extends MediaWikiTestCase {
+ /**
+ * @var WANObjectCache
+ */
+ private $cache;
+
protected function setUp() {
parent::setUp();
- $this->setMwGlobals( 'wgMemc', new HashBagOStuff() );
+ $this->cache = new WANObjectCache( [
+ 'cache' => MediaWikiServices::getInstance()->getMainObjectStash(),
+ ] );
}
public function testNewFromUser() {
@@ -26,29 +34,23 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
}
public function testFlagCacheWithNewTalkNotification() {
- global $wgMemc;
-
- $notifUser = MWEchoNotifUser::newFromUser( User::newFromId( 2 ) );
+ $notifUser = $this->newNotifUser();
$notifUser->flagCacheWithNewTalkNotification();
- $this->assertEquals( '1', $wgMemc->get( $notifUser->getTalkNotificationCacheKey() ) );
+ $this->assertEquals( '1', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) );
}
public function testFlagCacheWithNoTalkNotification() {
- global $wgMemc;
-
- $notifUser = MWEchoNotifUser::newFromUser( User::newFromId( 2 ) );
+ $notifUser = $this->newNotifUser();
$notifUser->flagCacheWithNoTalkNotification();
- $this->assertEquals( '0', $wgMemc->get( $notifUser->getTalkNotificationCacheKey() ) );
+ $this->assertEquals( '0', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) );
}
public function testNotifCountHasReachedMax() {
- global $wgEchoMaxNotificationCount;
-
- $notifUser = MWEchoNotifUser::newFromUser( User::newFromId( 2 ) );
+ $notifUser = $this->newNotifUser();
- if ( $notifUser->getNotificationCount() > $wgEchoMaxNotificationCount ) {
+ if ( $notifUser->getLocalNotificationCount() > MWEchoNotifUser::MAX_BADGE_COUNT ) {
$this->assertTrue( $notifUser->notifCountHasReachedMax() );
} else {
$this->assertFalse( $notifUser->notifCountHasReachedMax() );
@@ -56,9 +58,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
}
public function testClearTalkNotification() {
- global $wgMemc;
-
- $notifUser = MWEchoNotifUser::newFromUser( User::newFromId( 2 ) );
+ $notifUser = $this->newNotifUser();
$notifUser->flagCacheWithNewTalkNotification();
@@ -66,60 +66,51 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
$notifUser->clearTalkNotification();
if ( $hasMax ) {
- $this->assertEquals( '1', $wgMemc->get( $notifUser->getTalkNotificationCacheKey() ) );
+ $this->assertEquals( '1', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) );
} else {
- $this->assertEquals( '0', $wgMemc->get( $notifUser->getTalkNotificationCacheKey() ) );
+ $this->assertEquals( '0', $this->cache->get( $notifUser->getTalkNotificationCacheKey() ) );
}
}
public function testGetEmailFormat() {
- global $wgAllowHTMLEmail;
-
- $format = $wgAllowHTMLEmail;
-
$user = User::newFromId( 2 );
$notifUser = MWEchoNotifUser::newFromUser( $user );
$this->setMwGlobals( 'wgAllowHTMLEmail', true );
$this->assertEquals( $notifUser->getEmailFormat(), $user->getOption( 'echo-email-format' ) );
$this->setMwGlobals( 'wgAllowHTMLEmail', false );
- $this->assertEquals( $notifUser->getEmailFormat(), EchoHooks::EMAIL_FORMAT_PLAIN_TEXT );
-
- $this->setMwGlobals( 'wgAllowHTMLEmail', $format );
+ $this->assertEquals( $notifUser->getEmailFormat(), EchoEmailFormat::PLAIN_TEXT );
}
public function testMarkRead() {
- global $wgMemc;
$notifUser = new MWEchoNotifUser(
User::newFromId( 2 ),
- $wgMemc,
- $this->mockEchoUserNotificationGateway( array( 'markRead' => true ) ),
+ $this->cache,
+ $this->mockEchoUserNotificationGateway( [ 'markRead' => true ] ),
$this->mockEchoNotificationMapper(),
$this->mockEchoTargetPageMapper()
);
- $this->assertFalse( $notifUser->markRead( array() ) );
- $this->assertTrue( $notifUser->markRead( array( 1 ) ) );
+ $this->assertFalse( $notifUser->markRead( [] ) );
+ $this->assertTrue( $notifUser->markRead( [ 1 ] ) );
$notifUser = new MWEchoNotifUser(
User::newFromId( 2 ),
- $wgMemc,
- $this->mockEchoUserNotificationGateway( array( 'markRead' => false ) ),
+ $this->cache,
+ $this->mockEchoUserNotificationGateway( [ 'markRead' => false ] ),
$this->mockEchoNotificationMapper(),
$this->mockEchoTargetPageMapper()
);
- $this->assertFalse( $notifUser->markRead( array() ) );
- $this->assertFalse( $notifUser->markRead( array( 1 ) ) );
+ $this->assertFalse( $notifUser->markRead( [] ) );
+ $this->assertFalse( $notifUser->markRead( [ 1 ] ) );
}
public function testMarkAllRead() {
- global $wgMemc;
-
// Successful mark as read & non empty fetch
$notifUser = new MWEchoNotifUser(
User::newFromId( 2 ),
- $wgMemc,
- $this->mockEchoUserNotificationGateway( array( 'markRead' => true ) ),
- $this->mockEchoNotificationMapper( array( $this->mockEchoNotification() ) ),
+ $this->cache,
+ $this->mockEchoUserNotificationGateway( [ 'markRead' => true ] ),
+ $this->mockEchoNotificationMapper( [ $this->mockEchoNotification() ] ),
$this->mockEchoTargetPageMapper()
);
$this->assertTrue( $notifUser->markAllRead() );
@@ -127,9 +118,9 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
// Unsuccessful mark as read & non empty fetch
$notifUser = new MWEchoNotifUser(
User::newFromId( 2 ),
- $wgMemc,
- $this->mockEchoUserNotificationGateway( array( 'markRead' => false ) ),
- $this->mockEchoNotificationMapper( array( $this->mockEchoNotification() ) ),
+ $this->cache,
+ $this->mockEchoUserNotificationGateway( [ 'markRead' => false ] ),
+ $this->mockEchoNotificationMapper( [ $this->mockEchoNotification() ] ),
$this->mockEchoTargetPageMapper()
);
$this->assertFalse( $notifUser->markAllRead() );
@@ -137,8 +128,8 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
// Successful mark as read & empty fetch
$notifUser = new MWEchoNotifUser(
User::newFromId( 2 ),
- $wgMemc,
- $this->mockEchoUserNotificationGateway( array( 'markRead' => true ) ),
+ $this->cache,
+ $this->mockEchoUserNotificationGateway( [ 'markRead' => true ] ),
$this->mockEchoNotificationMapper(),
$this->mockEchoTargetPageMapper()
);
@@ -147,44 +138,47 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
// Unsuccessful mark as read & empty fetch
$notifUser = new MWEchoNotifUser(
User::newFromId( 2 ),
- $wgMemc,
- $this->mockEchoUserNotificationGateway( array( 'markRead' => false ) ),
+ $this->cache,
+ $this->mockEchoUserNotificationGateway( [ 'markRead' => false ] ),
$this->mockEchoNotificationMapper(),
$this->mockEchoTargetPageMapper()
);
$this->assertFalse( $notifUser->markAllRead() );
}
- public function mockEchoUserNotificationGateway( array $dbResult = array() ) {
- $dbResult += array(
+ public function mockEchoUserNotificationGateway( array $dbResult = [] ) {
+ $dbResult += [
'markRead' => true
- );
+ ];
$gateway = $this->getMockBuilder( 'EchoUserNotificationGateway' )
->disableOriginalConstructor()
->getMock();
$gateway->expects( $this->any() )
->method( 'markRead' )
->will( $this->returnValue( $dbResult['markRead'] ) );
+
return $gateway;
}
- public function mockEchoNotificationMapper( array $result = array() ) {
+ public function mockEchoNotificationMapper( array $result = [] ) {
$mapper = $this->getMockBuilder( 'EchoNotificationMapper' )
->disableOriginalConstructor()
->getMock();
$mapper->expects( $this->any() )
->method( 'fetchUnreadByUser' )
->will( $this->returnValue( $result ) );
+
return $mapper;
}
- public function mockEchoTargetPageMapper( array $result = array() ) {
+ public function mockEchoTargetPageMapper( array $result = [] ) {
$mapper = $this->getMockBuilder( 'EchoTargetPageMapper' )
->disableOriginalConstructor()
->getMock();
$mapper->expects( $this->any() )
->method( 'deleteByUserEvents' )
->will( $this->returnValue( $result ) );
+
return $mapper;
}
@@ -195,6 +189,7 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
$notification->expects( $this->any() )
->method( 'getEvent' )
->will( $this->returnValue( $this->mockEchoEvent() ) );
+
return $notification;
}
@@ -205,6 +200,17 @@ class MWEchoNotifUserTest extends MediaWikiTestCase {
$event->expects( $this->any() )
->method( 'getId' )
->will( $this->returnValue( 1 ) );
+
return $event;
}
+
+ protected function newNotifUser() {
+ return new MWEchoNotifUser(
+ User::newFromId( 2 ),
+ $this->cache,
+ $this->mockEchoUserNotificationGateway(),
+ $this->mockEchoNotificationMapper(),
+ $this->mockEchoTargetPageMapper()
+ );
+ }
}
diff --git a/Echo/tests/phpunit/TalkPageFunctionalTest.php b/Echo/tests/phpunit/TalkPageFunctionalTest.php
index 0476c312..4c80f2e0 100644
--- a/Echo/tests/phpunit/TalkPageFunctionalTest.php
+++ b/Echo/tests/phpunit/TalkPageFunctionalTest.php
@@ -1,4 +1,5 @@
<?php
+
/**
* @group Echo
* @group DataBase
@@ -8,7 +9,7 @@ class EchoTalkPageFunctionalTest extends ApiTestCase {
protected $dbr;
- public function setUp() {
+ protected function setUp() {
parent::setUp();
$this->dbr = MWEchoDbFactory::getDB( DB_SLAVE );
}
@@ -22,14 +23,14 @@ class EchoTalkPageFunctionalTest extends ApiTestCase {
$editor = self::$users['sysop']->getUser()->getName();
$talkPage = self::$users['uploader']->getUser()->getName();
// A set of messages which will be inserted
- $messages = array(
+ $messages = [
'Moar Cowbell',
"I can haz test\n\nplz?", // checks that the parser allows multi-line comments
'blah blah',
- );
+ ];
$messageCount = 0;
- $this->assertCount($messageCount, $this->fetchAllEvents() );
+ $this->assertCount( $messageCount, $this->fetchAllEvents() );
// Start a talkpage
$content = "== Section 8 ==\n\n" . $this->signedMessage( $editor, $messages[$messageCount] );
@@ -37,7 +38,7 @@ class EchoTalkPageFunctionalTest extends ApiTestCase {
// Ensure the proper event was created
$events = $this->fetchAllEvents();
- $this->assertCount(1 + $messageCount, $events, 'After initial edit a single event must exist.'); // +1 is due to 0 index
+ $this->assertCount( 1 + $messageCount, $events, 'After initial edit a single event must exist.' ); // +1 is due to 0 index
$row = array_shift( $events );
$this->assertEquals( 'edit-user-talk', $row->event_type );
$this->assertEventSectionTitle( 'Section 8', $row );
@@ -49,7 +50,7 @@ class EchoTalkPageFunctionalTest extends ApiTestCase {
// Ensure another event was created
$events = $this->fetchAllEvents();
- $this->assertCount(1 + $messageCount, $events);
+ $this->assertCount( 1 + $messageCount, $events );
$row = array_shift( $events );
$this->assertEquals( 'edit-user-talk', $row->event_type );
$this->assertEventSectionTitle( 'Section 8', $row );
@@ -61,7 +62,7 @@ class EchoTalkPageFunctionalTest extends ApiTestCase {
// Ensure this event has the new section title
$events = $this->fetchAllEvents();
- $this->assertCount(1 + $messageCount, $events);
+ $this->assertCount( 1 + $messageCount, $events );
$row = array_pop( $events );
$this->assertEquals( 'edit-user-talk', $row->event_type );
$this->assertEventSectionTitle( 'EE', $row );
@@ -78,13 +79,13 @@ class EchoTalkPageFunctionalTest extends ApiTestCase {
* @return array All events in db sorted from oldest to newest
*/
protected function fetchAllEvents() {
- $res = $this->dbr->select( 'echo_event', array( '*' ), array(), __METHOD__, array( 'ORDER BY' => 'event_id ASC' ) );
+ $res = $this->dbr->select( 'echo_event', [ '*' ], [], __METHOD__, [ 'ORDER BY' => 'event_id ASC' ] );
return iterator_to_array( $res );
}
protected function signedMessage( $name, $content = 'Moar cowbell', $depth = 1 ) {
- return str_repeat(':', $depth)." $content [[User:$name|$name]] ([[User talk:$name|$name]]) 00:17, 7 May 2013 (UTC)\n";
+ return str_repeat( ':', $depth ) . " $content [[User:$name|$name]] ([[User talk:$name|$name]]) 00:17, 7 May 2013 (UTC)\n";
}
}
diff --git a/Echo/tests/phpunit/ThankYouEditTest.php b/Echo/tests/phpunit/ThankYouEditTest.php
new file mode 100644
index 00000000..a573bdb1
--- /dev/null
+++ b/Echo/tests/phpunit/ThankYouEditTest.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @group Echo
+ */
+class MWEchoThankYouEditTest extends MediaWikiTestCase {
+
+ protected function setUp() {
+ parent::setUp();
+ $this->tablesUsed[] = 'echo_event';
+ $this->tablesUsed[] = 'echo_notification';
+ }
+
+ private function deleteEchoData() {
+ $db = MWEchoDbFactory::newFromDefault()->getEchoDb( DB_MASTER );
+ $db->delete( 'echo_event', '*', __METHOD__ );
+ $db->delete( 'echo_notification', '*', __METHOD__ );
+ }
+
+ public function testFirstEdit() {
+ // setup
+ $this->deleteEchoData();
+ $user = $this->getMutableTestUser()->getUser();
+ $title = Title::newFromText( 'Help:MWEchoThankYouEditTest_testFirstEdit' );
+
+ // action
+ $this->edit( $title, $user, 'this is my first edit' );
+
+ // assertions
+ $notificationMapper = new EchoNotificationMapper();
+ $notifications = $notificationMapper->fetchByUser( $user, 10, null, [ 'thank-you-edit' ] );
+ $this->assertCount( 1, $notifications );
+
+ /** @var EchoNotification $notification */
+ $notification = reset( $notifications );
+ $this->assertEquals( 1, $notification->getEvent()->getExtraParam( 'editCount', 'not found' ) );
+ }
+
+ public function testTenthEdit() {
+ // setup
+ $this->deleteEchoData();
+ $user = $this->getMutableTestUser()->getUser();
+ $title = Title::newFromText( 'Help:MWEchoThankYouEditTest_testTenthEdit' );
+
+ // action
+ // we could fast-forward the edit-count to speed things up
+ // but this is the only way to make sure duplicate notifications
+ // are not generated
+ for ( $i = 0; $i < 12; $i++ ) {
+ $this->edit( $title, $user, "this is edit #$i" );
+ }
+
+ // assertions
+ $notificationMapper = new EchoNotificationMapper();
+ $notifications = $notificationMapper->fetchByUser( $user, 10, null, [ 'thank-you-edit' ] );
+ $this->assertCount( 2, $notifications );
+
+ /** @var EchoNotification $notification */
+ $notification = reset( $notifications );
+ $this->assertEquals( 10, $notification->getEvent()->getExtraParam( 'editCount', 'not found' ) );
+ }
+
+ private function edit( Title $title, User $user, $text ) {
+ $page = WikiPage::factory( $title );
+ $content = ContentHandler::makeContent( $text, $title );
+ $page->doEditContent( $content, 'test', 0, false, $user );
+ }
+}
diff --git a/Echo/tests/phpunit/UserLocatorTest.php b/Echo/tests/phpunit/UserLocatorTest.php
index 47d86edd..f09f80a9 100644
--- a/Echo/tests/phpunit/UserLocatorTest.php
+++ b/Echo/tests/phpunit/UserLocatorTest.php
@@ -5,18 +5,18 @@
*/
class EchoUserLocatorTest extends MediaWikiTestCase {
- protected $tablesUsed = array( 'user', 'watchlist' );
+ protected $tablesUsed = [ 'user', 'watchlist' ];
public function testLocateUsersWatchingTitle() {
$title = Title::makeTitleSafe( NS_USER_TALK, 'Something_something_something' );
$key = $title->getDBkey();
for ( $i = 1000; $i < 1050; ++$i ) {
- $rows[] = array(
+ $rows[] = [
'wl_user' => $i,
'wl_namespace' => NS_USER_TALK,
'wl_title' => $key
- );
+ ];
}
wfGetDB( DB_MASTER )->insert( 'watchlist', $rows, __METHOD__ );
@@ -37,38 +37,38 @@ class EchoUserLocatorTest extends MediaWikiTestCase {
}
public function locateTalkPageOwnerProvider() {
- return array(
- array(
+ return [
+ [
'Allows null event title',
// expected user id's
- array(),
+ [],
// event title
null
- ),
+ ],
- array(
+ [
'No users selected for non-user talk namespace',
// expected user id's
- array(),
+ [],
// event title
Title::newMainPage(),
- ),
+ ],
- array(
+ [
'Selects user from NS_USER_TALK',
// callback returning expected user ids and event title.
// required because database insert must be inside test.
- function() {
+ function () {
$user = User::newFromName( 'UTUser' );
$user->addToDatabase();
- return array(
- array( $user->getId() ),
+ return [
+ [ $user->getId() ],
$user->getTalkPage(),
- );
+ ];
}
- ),
- );
+ ],
+ ];
}
/**
@@ -88,28 +88,27 @@ class EchoUserLocatorTest extends MediaWikiTestCase {
}
public function locateArticleCreatorProvider() {
- return array(
- array(
+ return [
+ [
'Something',
- function() {
+ function () {
$user = User::newFromName( 'UTUser' );
$user->addToDatabase();
- return array(
- array( $user->getId() ),
+ return [
+ [ $user->getId() ],
$user->getTalkPage(),
$user
- );
+ ];
}
- ),
- );
+ ],
+ ];
}
/**
* @dataProvider locateArticleCreatorProvider
*/
public function testLocateArticleCreator( $message, $initialize ) {
-
list( $expect, $title, $user ) = $initialize();
WikiPage::factory( $title )->doEditContent(
/* $content = */ ContentHandler::makeContent( 'content', $title ),
@@ -132,31 +131,31 @@ class EchoUserLocatorTest extends MediaWikiTestCase {
}
public static function locateEventAgentProvider() {
- return array(
- array(
+ return [
+ [
'Null event agent returns no users',
// expected result user id's
- array(),
+ [],
// event agent
null,
- ),
+ ],
- array(
+ [
'Anonymous event agent returns no users',
// expected result user id's
- array(),
+ [],
// event agent
User::newFromName( '4.5.6.7', /* $validate = */ false ),
- ),
+ ],
- array(
+ [
'Registed event agent returned as user',
// expected result user id's
- array( 42 ),
+ [ 42 ],
// event agent
User::newFromId( 42 ),
- ),
- );
+ ],
+ ];
}
/**
@@ -173,68 +172,68 @@ class EchoUserLocatorTest extends MediaWikiTestCase {
}
public function locateFromEventExtraProvider() {
- return array(
- array(
+ return [
+ [
'Event without extra data returns empty result',
// expected user list
- array(),
+ [],
// event extra data
- array(),
+ [],
// extra keys to get ids from
- array( 'foo' ),
- ),
+ [ 'foo' ],
+ ],
- array(
+ [
'Event with specified extra data returns expected result',
// expected user list
- array( 123 ),
+ [ 123 ],
// event extra data
- array( 'foo' => 123 ),
+ [ 'foo' => 123 ],
// extra keys to get ids from
- array( 'foo' ),
- ),
+ [ 'foo' ],
+ ],
- array(
+ [
'Accepts User objects instead of user ids',
// expected user list
- array( 123 ),
+ [ 123 ],
// event extra data
- array( 'foo' => User::newFromId( 123 ) ),
+ [ 'foo' => User::newFromId( 123 ) ],
// extra keys to get ids from
- array( 'foo' ),
- ),
+ [ 'foo' ],
+ ],
- array(
+ [
'Allows inner key to be array of ids',
// expected user list
- array( 123, 321 ),
+ [ 123, 321 ],
// event extra data
- array( 'foo' => array( 123, 321 ) ),
+ [ 'foo' => [ 123, 321 ] ],
// extra keys to get ids from
- array( 'foo' ),
- ),
+ [ 'foo' ],
+ ],
- array(
+ [
'Empty inner array causes no error',
// expected user list
- array(),
+ [],
// event extra data
- array( 'foo' => array() ),
+ [ 'foo' => [] ],
// extra keys to get ids from
- array( 'foo' ),
- ),
+ [ 'foo' ],
+ ],
- array(
+ [
'Accepts User object at inner level',
// expected user list
- array( 123 ),
+ [ 123 ],
// event extra data
- array( 'foo' => array( User::newFromId( 123 ) ) ),
+ [ 'foo' => [ User::newFromId( 123 ) ] ],
// extra keys to get ids from
- array( 'foo' ),
- ),
+ [ 'foo' ],
+ ],
- );
+ ];
}
/**
@@ -254,11 +253,12 @@ class EchoUserLocatorTest extends MediaWikiTestCase {
}
protected static function arrayToValueMap( array $array ) {
- $result = array();
+ $result = [];
foreach ( $array as $key => $value ) {
// EchoEvent::getExtraParam second argument defaults to null
- $result[] = array( $key, null, $value );
+ $result[] = [ $key, null, $value ];
}
+
return $result;
}
diff --git a/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php b/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php
index 104e0b00..135d1867 100644
--- a/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php
+++ b/Echo/tests/phpunit/api/ApiEchoMarkReadTest.php
@@ -3,6 +3,7 @@
/**
* @group medium
* @group API
+ * @group Database
* @covers ApiQuery
*/
class ApiEchoMarkReadTest extends ApiTestCase {
@@ -17,13 +18,12 @@ class ApiEchoMarkReadTest extends ApiTestCase {
}
public function testMarkReadWithList() {
-
$tokens = $this->getTokens();
// Grouping by section
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'action' => 'echomarkread',
'notlist' => '121|122|123',
- 'token' => $tokens['edittoken'] ) );
+ 'token' => $tokens['edittoken'] ] );
$this->assertArrayHasKey( 'query', $data[0] );
$this->assertArrayHasKey( 'echomarkread', $data[0]['query'] );
@@ -48,13 +48,12 @@ class ApiEchoMarkReadTest extends ApiTestCase {
}
public function testMarkReadWithAll() {
-
$tokens = $this->getTokens();
// Grouping by section
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'action' => 'echomarkread',
'notall' => '1',
- 'token' => $tokens['edittoken'] ) );
+ 'token' => $tokens['edittoken'] ] );
$this->assertArrayHasKey( 'query', $data[0] );
$this->assertArrayHasKey( 'echomarkread', $data[0]['query'] );
@@ -79,13 +78,12 @@ class ApiEchoMarkReadTest extends ApiTestCase {
}
public function testMarkReadWithSections() {
-
$tokens = $this->getTokens();
// Grouping by section
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'action' => 'echomarkread',
'sections' => 'alert|message',
- 'token' => $tokens['edittoken'] ) );
+ 'token' => $tokens['edittoken'] ] );
$this->assertArrayHasKey( 'query', $data[0] );
$this->assertArrayHasKey( 'echomarkread', $data[0]['query'] );
diff --git a/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php b/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php
index cd1a9732..9f86a6ef 100644
--- a/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php
+++ b/Echo/tests/phpunit/api/ApiEchoNotificationsTest.php
@@ -9,13 +9,13 @@ class ApiEchoNotificationsTest extends ApiTestCase {
public function testWithSectionGrouping() {
// Grouping by section
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'action' => 'query',
'meta' => 'notifications',
'notsections' => 'alert|message',
'notgroupbysection' => 1,
'notlimit' => 10,
- 'notprop' => 'index|list|count' ) );
+ 'notprop' => 'list|count' ] );
$this->assertArrayHasKey( 'query', $data[0] );
$this->assertArrayHasKey( 'notifications', $data[0]['query'] );
@@ -31,7 +31,6 @@ class ApiEchoNotificationsTest extends ApiTestCase {
$alert = $result['alert'];
$this->assertArrayHasKey( 'list', $alert );
$this->assertArrayHasKey( 'continue', $alert );
- $this->assertArrayHasKey( 'index', $alert );
$this->assertArrayHasKey( 'rawcount', $alert );
$this->assertArrayHasKey( 'count', $alert );
@@ -40,18 +39,17 @@ class ApiEchoNotificationsTest extends ApiTestCase {
$message = $result['message'];
$this->assertArrayHasKey( 'list', $message );
$this->assertArrayHasKey( 'continue', $message );
- $this->assertArrayHasKey( 'index', $message );
$this->assertArrayHasKey( 'rawcount', $message );
$this->assertArrayHasKey( 'count', $message );
}
public function testWithoutSectionGrouping() {
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'action' => 'query',
'meta' => 'notifications',
'notsections' => 'alert|message',
'notlimit' => 10,
- 'notprop' => 'index|list|count' ) );
+ 'notprop' => 'list|count' ] );
$this->assertArrayHasKey( 'query', $data[0] );
$this->assertArrayHasKey( 'notifications', $data[0]['query'] );
@@ -62,7 +60,6 @@ class ApiEchoNotificationsTest extends ApiTestCase {
$this->assertArrayHasKey( 'rawcount', $result );
$this->assertArrayHasKey( 'list', $result );
$this->assertArrayHasKey( 'continue', $result );
- $this->assertArrayHasKey( 'index', $result );
$this->assertTrue( !isset( $result['alert'] ) );
$this->assertTrue( !isset( $result['message'] ) );
diff --git a/Echo/tests/phpunit/cache/TitleLocalCacheTest.php b/Echo/tests/phpunit/cache/TitleLocalCacheTest.php
index 142a8b57..af255edb 100644
--- a/Echo/tests/phpunit/cache/TitleLocalCacheTest.php
+++ b/Echo/tests/phpunit/cache/TitleLocalCacheTest.php
@@ -5,6 +5,7 @@ class EchoTitleLocalCacheTest extends MediaWikiTestCase {
public function testCreate() {
$cache = EchoTitleLocalCache::create();
$this->assertInstanceOf( 'EchoTitleLocalCache', $cache );
+
return $cache;
}
@@ -22,24 +23,25 @@ class EchoTitleLocalCacheTest extends MediaWikiTestCase {
* @depends testCreate
*/
public function testGet( $cache ) {
- $lruMap = new MapCacheLRU( EchoLocalCache::TARGET_MAX_NUM );
- $titleIds = array();
- $res = $this->insertPage( "EchoTitleLocalCacheTest_testGet" );
- $titleIds[$res['id']] = $res['id'];
+ $map = new HashBagOStuff( [ 'maxKeys' => EchoLocalCache::TARGET_MAX_NUM ] );
+ $titleIds = [];
+
// First title included in cache
- $lruMap->set( $res['id'], $res['title'] );
+ $res = $this->insertPage( 'EchoTitleLocalCacheTest_testGet' );
+ $titleIds[$res['id']] = $res['id'];
+ $map->set( $res['id'], $res['title'] );
- // second title not in internal cache, resolves from db.
- $res = $this->insertPage( "EchoTitleLocalCacheTest_testGet2" );
+ // Second title not in internal cache, resolves from db.
+ $res = $this->insertPage( 'EchoTitleLocalCacheTest_testGet2' );
$titleIds[$res['id']] = $res['id'];
$object = new \ReflectionObject( $cache );
- // Load our generated MapCacheLRU in as the targets(known mapping from
+ // Load our generated map in as the targets (known mapping from
// title id to title object) into $cache
$targets = $object->getProperty( 'targets' );
$targets->setAccessible( true );
- $targets->setValue( $cache, $lruMap );
+ $targets->setValue( $cache, $map );
// Load both of the titles we are curious about into the list of titles
// to be looked up
@@ -62,20 +64,20 @@ class EchoTitleLocalCacheTest extends MediaWikiTestCase {
* @depends testCreate
*/
public function testClearAll( $cache ) {
+ $map = new HashBagOStuff( [ 'maxKeys' => EchoLocalCache::TARGET_MAX_NUM ] );
+ $map->set( 1, $this->mockTitle() );
$object = new \ReflectionObject( $cache );
$targets = $object->getProperty( 'targets' );
$targets->setAccessible( true );
- $lruMap = new MapCacheLRU( EchoLocalCache::TARGET_MAX_NUM );
- $lruMap->set( 1, $this->mockTitle() );
- $targets->setValue( $cache, $lruMap );
+ $targets->setValue( $cache, $map );
$lookups = $object->getProperty( 'lookups' );
$lookups->setAccessible( true );
- $lookups->setValue( $cache, array( '1' => '1', '2' => '2' ) );
+ $lookups->setValue( $cache, [ '1' => '1', '2' => '2' ] );
$cache->clearAll();
$this->assertTrue( count( $cache->getLookups() ) == 0 );
- $this->assertNull( $cache->getTargets()->get( 1 ) );
- $this->assertNull( $cache->getTargets()->get( '1' ) );
+ $this->assertEquals( false, $cache->getTargets()->get( 1 ) );
+ $this->assertEquals( false, $cache->getTargets()->get( '1' ) );
}
/**
@@ -85,6 +87,7 @@ class EchoTitleLocalCacheTest extends MediaWikiTestCase {
$title = $this->getMockBuilder( 'Title' )
->disableOriginalConstructor()
->getMock();
+
return $title;
}
}
diff --git a/Echo/tests/phpunit/controller/NotificationControllerTest.php b/Echo/tests/phpunit/controller/NotificationControllerTest.php
index fdfb9c25..8a38a7e5 100644
--- a/Echo/tests/phpunit/controller/NotificationControllerTest.php
+++ b/Echo/tests/phpunit/controller/NotificationControllerTest.php
@@ -3,72 +3,78 @@
class NotificationControllerTest extends MediaWikiTestCase {
public function evaluateUserLocatorsProvider() {
- return array(
- array(
+ return [
+ [
'With no options no users are notified',
// expected result
- array(),
+ [],
// event user locator config
- array(),
- ),
+ [],
+ ],
- array(
+ [
'Does not error when given non-existant user-locator',
// expected result
- array(),
+ [],
// event user locator config
- array( 'not-callable' ),
- ),
+ [ 'not-callable' ],
+ ],
- array(
+ [
'Calls selected locator and returns result',
// expected result
- array( array( 123 ) ),
+ [ [ 123 ] ],
// event user locator config
- function() { return array( 123 => 123 ); }
- ),
+ function () {
+ return [ 123 => 123 ];
+ }
+ ],
- array(
+ [
'evaluates multiple locators',
// expected result
- array( array( 123 ), array( 456 ) ),
+ [ [ 123 ], [ 456 ] ],
// event user locator config
- array(
- function() { return array( 123 => 123 ); },
- function() { return array( 456 => 456 ); },
- ),
- ),
-
- array(
+ [
+ function () {
+ return [ 123 => 123 ];
+ },
+ function () {
+ return [ 456 => 456 ];
+ },
+ ],
+ ],
+
+ [
'Passes parameters to locateFromEventExtra in expected manner',
// expected result
- array( array( 123 ) ),
+ [ [ 123 ] ],
// event user locator config
- array(
- array( 'EchoUserLocator::locateFromEventExtra', array( 'other-user' ) ),
- ),
+ [
+ [ 'EchoUserLocator::locateFromEventExtra', [ 'other-user' ] ],
+ ],
// additional setup
- function( $test, $event ) {
+ function ( $test, $event ) {
$event->expects( $test->any() )
->method( 'getExtraParam' )
->with( 'other-user' )
->will( $test->returnValue( 123 ) );
}
- ),
- );
+ ],
+ ];
}
/**
* @dataProvider evaluateUserLocatorsProvider
*/
public function testEvaluateUserLocators( $message, $expect, $locatorConfigForEventType, $setup = null ) {
- $this->setMwGlobals( array(
- 'wgEchoNotifications' => array(
- 'unit-test' => array(
- 'user-locators' => $locatorConfigForEventType
- ),
- ),
- ) );
+ $this->setMwGlobals( [
+ 'wgEchoNotifications' => [
+ 'unit-test' => [
+ EchoAttributeManager::ATTR_LOCATORS => $locatorConfigForEventType
+ ],
+ ],
+ ] );
$event = $this->getMockBuilder( 'EchoEvent' )
->disableOriginalConstructor()
@@ -81,53 +87,53 @@ class NotificationControllerTest extends MediaWikiTestCase {
$setup( $this, $event );
}
- $result = EchoNotificationController::evaluateUserLocators( $event );
+ $result = EchoNotificationController::evaluateUserCallable( $event, EchoAttributeManager::ATTR_LOCATORS );
$this->assertEquals( $expect, array_map( 'array_keys', $result ), $message );
}
public function testEvaluateUserLocatorPassesParameters() {
$test = $this;
- $callback = function( $event, $firstOption, $secondOption ) use( $test ) {
+ $callback = function ( $event, $firstOption, $secondOption ) use ( $test ) {
$test->assertInstanceOf( 'EchoEvent', $event );
$test->assertEquals( 'first', $firstOption );
$test->assertEquals( 'second', $secondOption );
- return array();
+ return [];
};
self::testEvaluateUserLocators(
__FUNCTION__,
- array( array() ),
- array( array( $callback, 'first', 'second' ) )
+ [ [] ],
+ [ [ $callback, 'first', 'second' ] ]
);
}
public function getUsersToNotifyForEventProvider() {
- return array(
- array(
+ return [
+ [
'Filters anonymous users',
// expected result
- array(),
+ [],
// users returned from locator
- array( User::newFromName( '4.5.6.7', false ) ),
- ),
+ [ User::newFromName( '4.5.6.7', false ) ],
+ ],
- array(
+ [
'Filters duplicate users',
// expected result
- array( 123 ),
+ [ 123 ],
// users returned from locator
- array( User::newFromId( 123 ), User::newFromId( 123 ) ),
- ),
+ [ User::newFromId( 123 ), User::newFromId( 123 ) ],
+ ],
- array(
+ [
'Filters non-user objects',
// expected result
- array( 123 ),
+ [ 123 ],
// users returned from locator
- array( null, 'foo', User::newFromId( 123 ), new stdClass, 456 ),
- ),
- );
+ [ null, 'foo', User::newFromId( 123 ), new stdClass, 456 ],
+ ],
+ ];
}
/**
@@ -138,13 +144,15 @@ class NotificationControllerTest extends MediaWikiTestCase {
$expect,
$users
) {
- $this->setMwGlobals( array(
- 'wgEchoNotifications' => array(
- 'unit-test' => array(
- 'user-locators' => function() use( $users ) { return $users; },
- ),
- ),
- ) );
+ $this->setMwGlobals( [
+ 'wgEchoNotifications' => [
+ 'unit-test' => [
+ EchoAttributeManager::ATTR_LOCATORS => function () use ( $users ) {
+ return $users;
+ },
+ ],
+ ],
+ ] );
$event = $this->getMockBuilder( 'EchoEvent' )
->disableOriginalConstructor()
@@ -154,7 +162,7 @@ class NotificationControllerTest extends MediaWikiTestCase {
->will( $this->returnValue( 'unit-test' ) );
$result = EchoNotificationController::getUsersToNotifyForEvent( $event );
- $ids = array();
+ $ids = [];
foreach ( $result as $user ) {
$ids[] = $user->getId();
}
@@ -177,43 +185,66 @@ class NotificationControllerTest extends MediaWikiTestCase {
}
public static function getEventNotifyTypesProvider() {
- return array(
- array(
+ return [
+ [
'Selects the `all` configuration by default',
// expected result
- array( 'web' ),
+ [ 'web' ],
// event type
'bar',
// default notification types configuration
- array(
- 'all' => array( 'web' => true ),
- 'foo' => array( 'email' => true ),
- ),
- ),
-
- array(
+ [ 'web' => true ],
+ // type-specific
+ [
+ 'foo' => [
+ 'notify-type-availability' => [ 'email' => true ],
+ ],
+ ],
+ ],
+
+ [
'Overrides `all` configuration with event type configuration',
// expected result
- array( 'web' ),
+ [ 'web' ],
// event type
'foo',
// default notification types configuration
- array(
- 'all' => array( 'web' => true, 'email' => true ),
- 'foo' => array( 'email' => false ),
- 'bar' => array( 'sms' => true ),
- ),
- ),
- );
+ [ 'web' => true, 'email' => true ],
+ // type-specific
+ [
+ 'foo' => [
+ 'notify-type-availability' => [ 'email' => false ],
+ ],
+ 'bar' => [
+ 'notify-type-availability' => [ 'sms' => true ],
+ ],
+ ],
+ ],
+
+ [
+ 'Uses all configuration when notify-type-availability not set at all',
+ // expected result
+ [ 'web', 'email' ],
+ // event type
+ 'baz',
+ // default notification types configuration
+ [ 'web' => true, 'email' => true ],
+ // type-specific
+ [
+ 'baz' => [],
+ ],
+ ]
+ ];
}
/**
* @dataProvider getEventNotifyTypesProvider
*/
- public function testGetEventNotifyTypes( $message, $expect, $type, array $notificationTypes ) {
- $this->setMwGlobals( array(
- 'wgEchoDefaultNotificationTypes' => $notificationTypes,
- ) );
+ public function testGetEventNotifyTypes( $message, $expect, $type, array $defaultNotifyTypeAvailability, array $notifications ) {
+ $this->setMwGlobals( [
+ 'wgDefaultNotifyTypeAvailability' => $defaultNotifyTypeAvailability,
+ 'wgEchoNotifications' => $notifications,
+ ] );
$result = EchoNotificationController::getEventNotifyTypes( $type );
$this->assertEquals( $expect, $result, $message );
}
diff --git a/Echo/tests/phpunit/formatters/NotificationFormatterTest.php b/Echo/tests/phpunit/formatters/NotificationFormatterTest.php
deleted file mode 100644
index e2b4ab16..00000000
--- a/Echo/tests/phpunit/formatters/NotificationFormatterTest.php
+++ /dev/null
@@ -1,321 +0,0 @@
-<?php
-
-/**
- * @group Echo
- */
-class EchoNotificationFormatterTest extends MediaWikiTestCase {
-
- public function setUp() {
- parent::setUp();
- $user = new User();
- $user->setName( 'Notification-formatter-test' );
- $user->addToDatabase();
- $this->setMwGlobals( 'wgUser', $user );
- }
-
- public static function provider_editUserTalkEmail() {
- return array(
- array( '/Main_Page[^#]/', null ),
- array( '/Main_Page#Section_8/', 'Section 8' ),
- );
- }
-
- /**
- * @dataProvider provider_editUserTalkEmail
- */
- public function testEditUserTalkEmailNotificationLink( $pattern, $sectionTitle ) {
- $event = $this->mockEvent( 'edit-user-talk', array(
- 'section-title' => $sectionTitle,
- ) );
- $event->expects( $this->any() )
- ->method( 'getTitle' )
- ->will( $this->returnValue( Title::newMainPage() ) );
- $formatted = $this->format( $event, 'email' );
- if ( is_array( $formatted['body'] ) ) {
- $this->assertRegExp( $pattern, $formatted['body']['text'] );
- $this->assertRegExp( $pattern, $formatted['body']['html'] );
- } else {
- $this->assertRegExp( $pattern, $formatted['body'] );
- }
-
- # Reset the Title cache
- $mainPage = Title::newMainPage();
- $mainPage->setFragment('');
- # And assert it has been cleaned up
- $mainPageCached = Title::newMainPage();
- $this->assertEquals( '', $mainPageCached->getFragment() );
-
- }
-
- public static function provider_editUserTalk() {
- return array(
- // if there is a section-title, the message should be '[[User:user_name|user_name]] left a message on
- // your talk page in '[[User talk:user_name#section_title|section_title]]'
- array( '/[[User talk:[^#]+#moar_cowbell|moar_cowbell]]/', 'moar_cowbell', 'text' ),
- array( '/#moar_cowbell/', 'moar_cowbell', 'html' ),
- array( '/#moar_cowbell/', 'moar_cowbell', 'flyout' ),
- );
- }
-
- /**
- * @dataProvider provider_editUserTalk
- */
- public function testEditUserTalkFlyoutSectionLinkFragment( $pattern, $sectionTitle, $format ) {
- // Required hack so parser doesnt turn the links into redlinks which contain no fragment
- global $wgUser;
- LinkCache::singleton()->addGoodLinkObj( 42, $wgUser->getTalkPage() );
-
- $event = $this->mockEvent( 'edit-user-talk', array(
- 'section-title' => $sectionTitle,
- ) );
- $this->assertRegExp( $pattern, $this->format( $event, $format ) );
- }
-
- public function provider_formatterDoesntFail() {
- // Remove events from this array once they have specific tests for their formatting
- $untested = array(
- 'welcome' => array(),
- 'reverted' => array(
- 'revid' => 42,
- 'reverted-user-id' => 77,
- 'reverted-revision-id' => 13,
- 'method' => 'undo',
- ),
- 'page-linked' => array(
- 'link-from-page-id' => 42,
- ),
- 'mention' => array(
- 'content' => 'lorem ipsum dolar sit amet',
- 'section-title' => 'Zombies',
- 'revid' => 42,
- 'mentionedusers' => array( 101 => 101 ),
- ),
- 'user-rights' => array(
- 'user' => 187,
- 'add' => array( 'aaa', 'bbb' ),
- 'remove' => array( 'other' ),
- ),
- );
- $formats = array( 'html', 'flyout', 'email', 'text' );
- $tests = array();
- $loggedUser = User::newFromName( 'Notification-formatter-test' );
- $anonUser = new User();
-
- foreach ( $untested as $type => $extra ) {
- foreach ( $formats as $format ) {
- // Run tests with blank extra data and with the provided extra data
- $tests[] = array( $format, $type, $extra, $loggedUser );
- $tests[] = array( $format, $type, array(), $anonUser );
- }
- }
-
- return $tests;
- }
-
- public static function provider_revisionSummary() {
- $sectionText = '(dummy comment)';
-
- // Test the 4 different events that reference the summary, although they should follow mostly
- // the same code they may use different classes extended from the EchoNotificationFormatter
- $tests = array();
- $events = array( 'edit-user-talk' );
- foreach ( $events as $eventType ) {
- $tests[] = array( $eventType, $sectionText, 0);
- $tests[] = array( $eventType, $sectionText, Revision::DELETED_TEXT );
- }
-
- return $tests;
- }
-
- /**
- * @dataProvider provider_revisionSummary
- */
- public function testRevisionSummarySuppression( $eventType, $text, $deleted ) {
- // Revision needs a comment to attempt to format
- $event = $this->mockEvent(
- $eventType,
- array( 'section-title' => 'Test Title', 'section-text' => $text ),
- new Revision( compact( 'deleted' ) )
- );
- if ( $deleted === Revision::DELETED_TEXT ) {
- $this->assertNotContains( $text, $this->format( $event, 'html' ) );
- } else {
- $this->assertContains( $text, $this->format( $event, 'html' ) );
- }
- }
-
- public static function provider_revisionAgent() {
- $userText = '10.2.3.4';
- $suppressed = wfMessage( 'rev-deleted-user' )->text();
-
- $tests = array();
- $events = array( 'edit-user-talk', 'reverted', 'mention' );
- foreach ( $events as $eventType ) {
- $tests[] = array( $eventType, $userText, $userText, 0 );
- $tests[] = array( $eventType, $suppressed, $userText, Revision::DELETED_USER );
- }
-
- return $tests;
- }
-
- /**
- * @dataProvider provider_revisionAgent
- */
- public function testAgentSuppression( $eventType, $expect, $user_text, $deleted ) {
- $event = $this->mockEvent(
- $eventType,
- array(),
- new Revision( compact( 'user_text', 'deleted' ) )
- );
-
- $user = new User;
- $user->setName( $user_text );
- $event->expects( $this->any() )
- ->method( 'getAgent' )
- ->will( $this->returnValue( $user ) );
-
- $this->assertContains( $expect, $this->format( $event, 'html' ) );
- }
-
- public static function provider_sectionTitle() {
- $message = "some_section_title"; // underscores simplifies the test, since it will transform ' ' to '_'
- $suppressed = wfMessage( 'echo-rev-deleted-text-view')->text();
-
- $tests = array();
- $events = array( 'mention' ); // currently only mention uses sectionTitle, but likely edit-user-talk will soon as well
- foreach ( $events as $eventType ) {
- $tests[] = array( $eventType, $message, $message, 0);
- $tests[] = array( $eventType, $suppressed, $message, Revision::DELETED_TEXT );
- }
-
- return $tests;
- }
-
- /**
- * @dataProvider provider_formatterDoesntFail
- */
- public function testFormatterDoesntFail( $format, $type, array $extra, User $agent ) {
- $result = $this->format( $this->mockEvent( $type, $extra, null, $agent ), $format );
-
- // generic assertion, could do better
- if ( $format === 'email' ) {
- $this->assertInternalType( 'array', $result );
- $this->assertCount( 2, $result );
- } else {
- $this->assertInternalType( 'string', $result );
- $this->assertGreaterThan( 0, strlen( $result ) );
- }
- }
-
- /**
- * @dataProvider provider_sectionTitle
- */
- public function testMentionSubjectSectionTitleSuppression( $eventType, $expect, $sectionTitle, $deleted ) {
- $event = $this->mockEvent(
- $eventType,
- array( 'section-title' => $sectionTitle ),
- new Revision( compact( 'deleted' ) )
- );
-
- $this->assertContains( $expect, $this->format( $event, 'html' ) );
- }
-
- protected function format( EchoEvent $event, $format, $user = false, $type = 'web' ) {
- if ( $user === false ) {
- $user = User::newFromName( 'Notification-formatter-test' );
- }
-
- // Notification users can not be anonymous, use a fake user id
- return EchoNotificationController::formatNotification( $event, $user, $format, $type );
- }
-
- protected function mockEvent( $type, array $extra = array(), Revision $rev = null, User $agent = null ) {
- $methods = get_class_methods( 'EchoEvent' );
- $methods = array_diff( $methods, array( 'userCan', 'getLinkMessage', 'getLinkDestination' ) );
-
- $event = $this->getMockBuilder( 'EchoEvent' )
- ->disableOriginalConstructor()
- ->setMethods( $methods )
- ->getMock();
- $event->expects( $this->any() )
- ->method( 'getType' )
- ->will( $this->returnValue( $type ) );
- $event->expects( $this->any() )
- ->method( 'getExtra' )
- ->will( $this->returnValue( $extra ) );
- if ( $agent !== null ) {
- $event->expects( $this->any() )
- ->method( 'getAgent' )
- ->will( $this->returnValue( $agent ) );
- }
- if ( $rev !== null ) {
- $event->expects( $this->any() )
- ->method( 'getRevision' )
- ->will( $this->returnValue( $rev ) );
- }
- return $event;
- }
-
- /**
- * @dataProvider provideGetIconUrl
- */
- public function testGetIconUrl( $global, $icon, $dir, $expected, $exception = null ) {
- $this->setMwGlobals( array(
- 'wgEchoNotificationIcons' => $global,
- 'wgExtensionAssetsPath' => 'http://example.org'
- ) );
-
- if ( $exception ) {
- $this->setExpectedException( $exception );
- }
-
- $url = EchoNotificationFormatter::getIconUrl( $icon, $dir );
- $this->assertEquals( $expected, $url );
- }
-
- public static function provideGetIconUrl() {
- $standard = array(
- 'foo' => array(
- 'path' => 'foo.png',
- ),
- 'bar' => array(
- 'path' => array(
- 'ltr' => 'bar.png'
- ),
- ),
- 'baz' => array(
- 'path' => array(
- 'ltr' => 'baz-ltr.png',
- 'rtl' => 'baz-rtl.png',
- ),
- ),
- 'site' => array(
- 'url' => false,
- ),
- 'placeholder' => array(
- 'path' => 'placeholder.png',
- ),
- );
- $tests = array(
- // Standard, no ltr/rtl
- array( $standard, 'foo', 'ltr', 'http://example.org/foo.png' ),
- array( $standard, 'foo', 'rtl', 'http://example.org/foo.png' ),
- // Only ltr configured (bad!)
- array( $standard, 'bar', 'ltr', 'http://example.org/bar.png' ),
- array( $standard, 'bar', 'rtl', '', 'UnexpectedValueException' ),
- // Different for ltr/rtl
- array( $standard, 'baz', 'ltr', 'http://example.org/baz-ltr.png' ),
- array( $standard, 'baz', 'rtl', 'http://example.org/baz-rtl.png' ),
- // Not registered
- array( $standard, 'invalid', 'ltr', '', 'InvalidArgumentException' ),
- // No url set, fallback to placeholder
- array( $standard, 'site', 'ltr', 'http://example.org/placeholder.png' ),
- );
-
- // Set the 'url', and it doesn't fallback anymore
- $standard['site']['url'] = 'http://example.com/site.png';
- $tests[] = array( $standard, 'site', 'ltr', 'http://example.com/site.png' );
-
- return $tests;
- }
-}
diff --git a/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php b/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php
index 5fa9b0fc..7e656e19 100644
--- a/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php
+++ b/Echo/tests/phpunit/gateway/UserNotificationGatewayTest.php
@@ -5,57 +5,57 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase {
public function testMarkRead() {
// no event ids to mark
$gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory() );
- $this->assertNull( $gateway->markRead( array() ) );
+ $this->assertNull( $gateway->markRead( [] ) );
// successful update
- $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( array( 'update' => true ) ) );
- $this->assertTrue( $gateway->markRead( array( 2 ) ) );
+ $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => true ] ) );
+ $this->assertTrue( $gateway->markRead( [ 2 ] ) );
// unsuccessful update
- $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( array( 'update' => false ) ) );
- $this->assertFalse( $gateway->markRead( array( 2 ) ) );
+ $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => false ] ) );
+ $this->assertFalse( $gateway->markRead( [ 2 ] ) );
}
public function testMarkAllRead() {
// successful update
- $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( array( 'update' => true ) ) );
- $this->assertTrue( $gateway->markAllRead( array( 2 ) ) );
+ $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => true ] ) );
+ $this->assertTrue( $gateway->markAllRead( [ 2 ] ) );
// unsuccessful update
- $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( array( 'update' => false ) ) );
- $this->assertFalse( $gateway->markAllRead( array( 2 ) ) );
+ $gateway = new EchoUserNotificationGateway( User::newFromId( 1 ), $this->mockMWEchoDbFactory( [ 'update' => false ] ) );
+ $this->assertFalse( $gateway->markAllRead( [ 2 ] ) );
}
public function testGetNotificationCount() {
// unsuccessful select
- $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( array( 'select' => false ) ) );
- $this->assertEquals( 0, $gateway->getNotificationCount( DB_SLAVE, array( 'event_one' ) ) );
+ $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 0 ] ) );
+ $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one' ] ) );
// successful select of alert
- $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( array( 'select' => array( 1, 2 ) ) ) );
- $this->assertEquals( 2, $gateway->getNotificationCount( DB_SLAVE, array( 'event_one', 'event_two' ) ) );
+ $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 2 ] ) );
+ $this->assertEquals( 2, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one', 'event_two' ] ) );
// there is event, should return 0
- $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( array( 'select' => array( 1, 2 ) ) ) );
- $this->assertEquals( 0, $gateway->getNotificationCount( DB_SLAVE, array() ) );
+ $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 2 ] ) );
+ $this->assertEquals( 0, $gateway->getCappedNotificationCount( DB_SLAVE, [] ) );
// successful select
- $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( array( 'select' => array( 1, 2, 3 ) ) ) );
- $this->assertEquals( 3, $gateway->getNotificationCount( DB_SLAVE, array( 'event_one' ) ) );
+ $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'selectRowCount' => 3 ] ) );
+ $this->assertEquals( 3, $gateway->getCappedNotificationCount( DB_SLAVE, [ 'event_one' ] ) );
}
public function testGetUnreadNotifications() {
- $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( array( 'select' => false ) ) );
+ $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'select' => false ] ) );
$this->assertEmpty( $gateway->getUnreadNotifications( 'user_talk' ) );
- $dbResult = array(
- (object)array( 'notification_event' => 1 ),
- (object)array( 'notification_event' => 2 ),
- (object)array( 'notification_event' => 3 ),
- );
- $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( array( 'select' => $dbResult ) ) );
+ $dbResult = [
+ (object)[ 'notification_event' => 1 ],
+ (object)[ 'notification_event' => 2 ],
+ (object)[ 'notification_event' => 3 ],
+ ];
+ $gateway = new EchoUserNotificationGateway( $this->mockUser(), $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ) );
$res = $gateway->getUnreadNotifications( 'user_talk' );
- $this->assertEquals( $res, array( 1 => 1, 2 => 2, 3 => 3 ) );
+ $this->assertEquals( $res, [ 1 => 1, 2 => 2, 3 => 3 ] );
}
/**
@@ -73,32 +73,35 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase {
->will( $this->returnValue( true ) );
$user->expects( $this->any() )
->method( 'getGroups' )
- ->will( $this->returnValue( array( $group ) ) );
+ ->will( $this->returnValue( [ $group ] ) );
+
return $user;
}
/**
* Mock object of MWEchoDbFactory
*/
- protected function mockMWEchoDbFactory( array $dbResult = array() ) {
+ protected function mockMWEchoDbFactory( array $dbResult = [] ) {
$dbFactory = $this->getMockBuilder( 'MWEchoDbFactory' )
->disableOriginalConstructor()
->getMock();
$dbFactory->expects( $this->any() )
->method( 'getEchoDb' )
->will( $this->returnValue( $this->mockDb( $dbResult ) ) );
+
return $dbFactory;
}
/**
* Mock object of DatabaseMysql ( DatabaseBase )
*/
- protected function mockDb( array $dbResult = array() ) {
- $dbResult += array(
+ protected function mockDb( array $dbResult = [] ) {
+ $dbResult += [
'update' => '',
'select' => '',
'selectRow' => '',
- );
+ 'selectRowCount' => '',
+ ];
$db = $this->getMockBuilder( 'DatabaseMysql' )
->disableOriginalConstructor()
->getMock();
@@ -112,8 +115,12 @@ class EchoUserNotificationGatewayTest extends MediaWikiTestCase {
->method( 'selectRow' )
->will( $this->returnValue( $dbResult['selectRow'] ) );
$db->expects( $this->any() )
+ ->method( 'selectRowCount' )
+ ->will( $this->returnValue( $dbResult['selectRowCount'] ) );
+ $db->expects( $this->any() )
->method( 'numRows' )
->will( $this->returnValue( count( $dbResult['select'] ) ) );
+
return $db;
}
diff --git a/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php b/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php
index 900db22b..b05e3229 100644
--- a/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php
+++ b/Echo/tests/phpunit/iterator/FilteredSequentialIteratorTest.php
@@ -4,8 +4,8 @@ class FilteredSequentialIteratorTest extends MediaWikiTestCase {
public function testEchoCallbackIteratorDoesntBlowUp() {
$it = new EchoCallbackIterator(
- new ArrayIterator( array( 1, 2, 3 ) ),
- function( $num ) {
+ new ArrayIterator( [ 1, 2, 3 ] ),
+ function ( $num ) {
return "There were $num items";
}
);
@@ -14,70 +14,74 @@ class FilteredSequentialIteratorTest extends MediaWikiTestCase {
$res[] = $val;
}
- $expected = array( "There were 1 items", "There were 2 items", "There were 3 items" );
+ $expected = [ "There were 1 items", "There were 2 items", "There were 3 items" ];
$this->assertEquals( $expected, $res, 'Basic iteration with callback applied' );
}
public static function echoFilteredSequentialIteratorProvider() {
- $odd = function( $v ) { return $v & 1; };
- $greaterThanFour = function( $v ) { return $v > 4; };
+ $odd = function ( $v ) {
+ return $v & 1;
+ };
+ $greaterThanFour = function ( $v ) {
+ return $v > 4;
+ };
- return array(
- array(
+ return [
+ [
'Empty object still works',
// expected result
- array(),
+ [],
// list of iterators/arrays/etc each containing users
- array(),
+ [],
// list of filters to apply on output
- array(),
- ),
- array(
+ [],
+ ],
+ [
'Basic iteration with one array and no filters',
// expected result
- array( 1, 2, 3 ),
+ [ 1, 2, 3 ],
// list of iterators/arrays/etc each containing users
- array( array( 1, 2, 3 ) ),
+ [ [ 1, 2, 3 ] ],
// list of filters to apply on output
- array()
- ),
- array(
+ []
+ ],
+ [
'Basic iteration with one array and one filters',
// expected result
- array( 1, 3 ),
+ [ 1, 3 ],
// list of tierators/arrays/etc each containing users
- array( array( 1, 2, 3 ) ),
+ [ [ 1, 2, 3 ] ],
// list of filters to apply on output
- array( $odd ),
- ),
- array(
+ [ $odd ],
+ ],
+ [
'Iteration with multiple input arrays and no filters',
// expected result (iterators are run in parallel)
- array( 1, 4, 2, 5, 3 ),
+ [ 1, 4, 2, 5, 3 ],
// list of tierators/arrays/etc each containing users
- array( array( 1, 2, 3 ), array( 4, 5 ) ),
+ [ [ 1, 2, 3 ], [ 4, 5 ] ],
// list of filters to apply on output
- array(),
- ),
- array(
+ [],
+ ],
+ [
'Iteration with multiple input arrays and multiple filters',
// expected result
- array( 5 ),
+ [ 5 ],
// list of tierators/arrays/etc each containing users
- array( array( 1, 2 ), array( 3, 4 ), array( 5, 6 ) ),
+ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ],
// list of filters to apply on output
- array( $odd, $greaterThanFour ),
- ),
- array(
+ [ $odd, $greaterThanFour ],
+ ],
+ [
'Iteration with interspersed empty arrays',
// expected result
- array( 1, 3, 2 ),
+ [ 1, 3, 2 ],
// list of tierators/arrays/etc each containing users
- array( array(), array( 1, 2 ), array( 3 ), array() ),
+ [ [], [ 1, 2 ], [ 3 ], [] ],
// list of filters to apply on output
- array(),
- ),
- );
+ [],
+ ],
+ ];
}
/**
@@ -94,7 +98,7 @@ class FilteredSequentialIteratorTest extends MediaWikiTestCase {
$notify->addFilter( $filter );
}
- $result = array();
+ $result = [];
foreach ( $notify as $value ) {
$result[] = $value;
}
diff --git a/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php b/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php
index 5547e384..0a32d8af 100644
--- a/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php
+++ b/Echo/tests/phpunit/maintenance/SupressionMaintenanceTest.php
@@ -6,7 +6,7 @@
class SuppressionMaintenanceTest extends MediaWikiTestCase {
public static function provider_updateRow() {
- $input = array(
+ $input = [
'event_id' => 2,
'event_type' => 'mention',
'event_variant' => null,
@@ -17,101 +17,103 @@ class SuppressionMaintenanceTest extends MediaWikiTestCase {
'event_page_extra' => null,
'event_extra' => null,
'event_page_id' => null,
- );
- return array(
- array( 'Unrelated row must result in no update', array(), $input ),
+ ];
- array(
+ return [
+ [ 'Unrelated row must result in no update', [], $input ],
+
+ [
'Page title and namespace for non-existant page must move into event_extra',
- array( // expected update
- 'event_extra' => serialize( array(
+ [ // expected update
+ 'event_extra' => serialize( [
'page_title' => 'Yabba Dabba Do',
'page_namespace' => NS_MAIN
- ) ),
- ),
- array( // input row
+ ] ),
+ ],
+ [ // input row
'event_page_title' => 'Yabba Dabba Do',
'event_page_namespace' => NS_MAIN,
- ) + $input,
- ),
+ ] + $input,
+ ],
- array(
+ [
'Page title and namespace for existing page must be result in update to event_page_id',
- array( // expected update
+ [ // expected update
'event_page_id' => 42,
- ),
- array( // input row
+ ],
+ [ // input row
'event_page_title' => 'Mount Rushmore',
'event_page_namespace' => NS_MAIN,
- ) + $input,
+ ] + $input,
self::attachTitleFor( 42, 'Mount Rushmore', NS_MAIN )
- ),
+ ],
- array(
+ [
'When updating non-existant page must keep old extra data',
- array( // expected update
- 'event_extra' => serialize( array(
+ [ // expected update
+ 'event_extra' => serialize( [
'foo' => 'bar',
'page_title' => 'Yabba Dabba Do',
'page_namespace' => NS_MAIN
- ) ),
- ),
- array( // input row
+ ] ),
+ ],
+ [ // input row
'event_page_title' => 'Yabba Dabba Do',
'event_page_namespace' => NS_MAIN,
- 'event_extra' => serialize( array( 'foo' => 'bar' ) ),
- ) + $input,
- ),
+ 'event_extra' => serialize( [ 'foo' => 'bar' ] ),
+ ] + $input,
+ ],
- array(
+ [
'Must update link-from-title/namespace to link-from-page-id for page-linked events',
- array( // expected update
- 'event_extra' => serialize( array( 'link-from-page-id' => 99 ) ),
- ),
- array( //input row
+ [ // expected update
+ 'event_extra' => serialize( [ 'link-from-page-id' => 99 ] ),
+ ],
+ [ // input row
'event_type' => 'page-linked',
- 'event_extra' => serialize( array(
+ 'event_extra' => serialize( [
'link-from-title' => 'Horse',
'link-from-namespace' => NS_USER_TALK
- ) ),
- ) + $input,
+ ] ),
+ ] + $input,
self::attachTitleFor( 99, 'Horse', NS_USER_TALK )
- ),
+ ],
- array(
+ [
'Must perform both generic update and page-linked update at same time',
- array( // expected update
- 'event_extra' => serialize( array( 'link-from-page-id' => 8675309 ) ),
+ [ // expected update
+ 'event_extra' => serialize( [ 'link-from-page-id' => 8675309 ] ),
'event_page_id' => 8675309,
- ),
- array( //input row
+ ],
+ [ // input row
'event_type' => 'page-linked',
- 'event_extra' => serialize( array(
+ 'event_extra' => serialize( [
'link-from-title' => 'Jenny',
'link-from-namespace' => NS_MAIN,
- ) ),
+ ] ),
'event_page_title' => 'Jenny',
'event_page_namespace' => NS_MAIN,
- ) + $input,
+ ] + $input,
self::attachTitleFor( 8675309, 'Jenny', NS_MAIN ),
- ),
- );
+ ],
+ ];
}
protected static function attachTitleFor( $id, $providedText, $providedNamespace ) {
- return function( $test, $gen ) use ( $id, $providedText, $providedNamespace ) {
+ return function ( $test, $gen ) use ( $id, $providedText, $providedNamespace ) {
$title = $test->getMock( 'Title' );
$title->expects( $test->any() )
->method( 'getArticleId' )
->will( $test->returnValue( $id ) );
- $titles = array( $providedNamespace => array( $providedText => $title ) );
+ $titles = [ $providedNamespace => [ $providedText => $title ] ];
- $gen->setNewTitleFromText( function( $text, $defaultNamespace ) use( $titles ) {
- if ( isset( $titles[$defaultNamespace][$text] ) ) {
- return $titles[$defaultNamespace][$text];
+ $gen->setNewTitleFromNsAndText( function ( $namespace, $text ) use ( $titles ) {
+ if ( isset( $titles[$namespace][$text] ) ) {
+ return $titles[$namespace][$text];
}
- return Title::newFromText( $text, $defaultNamespace );
+
+ return Title::makeTitleSafe( $namespace, $text );
} );
};
}
@@ -124,7 +126,7 @@ class SuppressionMaintenanceTest extends MediaWikiTestCase {
if ( $callable ) {
call_user_func( $callable, $this, $gen );
}
- $update = $gen->update( (object) $input );
+ $update = $gen->update( (object)$input );
$this->assertEquals( $expected, $update, $message );
}
}
diff --git a/Echo/tests/phpunit/mapper/AbstractMapperTest.php b/Echo/tests/phpunit/mapper/AbstractMapperTest.php
index cf91a459..5c3a5826 100644
--- a/Echo/tests/phpunit/mapper/AbstractMapperTest.php
+++ b/Echo/tests/phpunit/mapper/AbstractMapperTest.php
@@ -4,7 +4,8 @@ class EchoAbstractMapperTest extends MediaWikiTestCase {
public function testAttachListener() {
$mapper = new EchoAbstractMapperStub();
- $mapper->attachListener( 'testMethod', 'key_a', function() {} );
+ $mapper->attachListener( 'testMethod', 'key_a', function () {
+ } );
$class = new ReflectionClass( 'EchoAbstractMapperStub' );
$property = $class->getProperty( 'listeners' );
@@ -14,7 +15,8 @@ class EchoAbstractMapperTest extends MediaWikiTestCase {
$this->assertArrayHasKey( 'testMethod', $listeners );
$this->assertArrayHasKey( 'key_a', $listeners['testMethod'] );
$this->assertTrue( is_callable( $listeners['testMethod']['key_a'] ) );
- return array( 'mapper' => $mapper, 'property' => $property );
+
+ return [ 'mapper' => $mapper, 'property' => $property ];
}
/**
@@ -22,7 +24,8 @@ class EchoAbstractMapperTest extends MediaWikiTestCase {
*/
public function testAttachListenerWithException() {
$mapper = new EchoAbstractMapperStub();
- $mapper->attachListener( 'nonExistingMethod', 'key_a', function() {} );
+ $mapper->attachListener( 'nonExistingMethod', 'key_a', function () {
+ } );
}
/**
@@ -69,7 +72,6 @@ class EchoAbstractMapperTest extends MediaWikiTestCase {
class EchoAbstractMapperStub extends EchoAbstractMapper {
public function testMethod() {
-
}
}
diff --git a/Echo/tests/phpunit/mapper/EventMapperTest.php b/Echo/tests/phpunit/mapper/EventMapperTest.php
index 834df687..e9528ca9 100644
--- a/Echo/tests/phpunit/mapper/EventMapperTest.php
+++ b/Echo/tests/phpunit/mapper/EventMapperTest.php
@@ -3,23 +3,23 @@
class EchoEventMapperTest extends MediaWikiTestCase {
public function provideDataTestInsert() {
- return array (
- array (
+ return [
+ [
'successful insert with next sequence = 1',
- array ( 'nextSequenceValue' => 1, 'insert' => true, 'insertId' => 2 ),
+ [ 'insert' => true, 'insertId' => 1 ],
1
- ),
- array (
+ ],
+ [
'successful insert with insert id = 2',
- array ( 'nextSequenceValue' => null, 'insert' => true, 'insertId' => 2 ),
+ [ 'insert' => true, 'insertId' => 2 ],
2
- ),
- array (
+ ],
+ [
'unsuccessful insert',
- array ( 'nextSequenceValue' => null, 'insert' => false, 'insertId' => 2 ),
+ [ 'insert' => false, 'insertId' => 2 ],
false
- ),
- );
+ ],
+ ];
}
/**
@@ -37,17 +37,18 @@ class EchoEventMapperTest extends MediaWikiTestCase {
public function testSuccessfulFetchById() {
$eventMapper = new EchoEventMapper(
$this->mockMWEchoDbFactory(
- array(
- 'selectRow' => (object)array (
+ [
+ 'selectRow' => (object)[
'event_id' => 1,
'event_type' => 'test',
'event_variant' => '',
'event_extra' => '',
'event_page_id' => '',
'event_agent_id' => '',
- 'event_agent_ip' => ''
- )
- )
+ 'event_agent_ip' => '',
+ 'event_deleted' => 0,
+ ]
+ ]
)
);
$res = $eventMapper->fetchById( 1 );
@@ -60,52 +61,15 @@ class EchoEventMapperTest extends MediaWikiTestCase {
public function testUnsuccessfulFetchById() {
$eventMapper = new EchoEventMapper(
$this->mockMWEchoDbFactory(
- array(
+ [
'selectRow' => false
- )
+ ]
)
);
$res = $eventMapper->fetchById( 1 );
$this->assertInstanceOf( 'EchoEvent', $res );
}
- public function testFetchByUserBundleHash() {
- // Unsuccessful select
- $event = $this->mockEchoEvent();
- $eventMapper = new EchoEventMapper( $this->mockMWEchoDbFactory( array ( 'select' => false ) ) );
- $res = $eventMapper->fetchByUserBundleHash( User::newFromId( 1 ), 'testhash', 'web', 'DESC', 250 );
- $this->assertFalse( $res );
-
- // Successful select
- $event = $this->mockEchoEvent();
- $dbResult = array (
- (object)array (
- 'event_id' => 1,
- 'event_type' => 'test',
- 'event_variant' => '',
- 'event_extra' => '',
- 'event_page_id' => '',
- 'event_agent_id' => '',
- 'event_agent_ip' => ''
- ),
- (object)array (
- 'event_id' => 2,
- 'event_type' => 'test2',
- 'event_variant' => '',
- 'event_extra' => '',
- 'event_page_id' => '',
- 'event_agent_id' => '',
- 'event_agent_ip' => ''
- )
- );
- $eventMapper = new EchoEventMapper( $this->mockMWEchoDbFactory( array ( 'select' => $dbResult ) ) );
- $res = $eventMapper->fetchByUserBundleHash( User::newFromId( 1 ), 'testhash', 'web', 'DESC', 250 );
- $this->assertTrue( is_array( $res ) );
- foreach ( $res as $row ) {
- $this->assertInstanceOf( 'EchoEvent', $row );
- }
- }
-
/**
* Mock object of EchoEvent
*/
@@ -115,7 +79,8 @@ class EchoEventMapperTest extends MediaWikiTestCase {
->getMock();
$event->expects( $this->any() )
->method( 'toDbArray' )
- ->will( $this->returnValue( array() ) );
+ ->will( $this->returnValue( [] ) );
+
return $event;
}
@@ -129,6 +94,7 @@ class EchoEventMapperTest extends MediaWikiTestCase {
$dbFactory->expects( $this->any() )
->method( 'getEchoDb' )
->will( $this->returnValue( $this->mockDb( $dbResult ) ) );
+
return $dbFactory;
}
@@ -136,20 +102,16 @@ class EchoEventMapperTest extends MediaWikiTestCase {
* Mock object of DatabaseMysql ( DatabaseBase )
*/
protected function mockDb( array $dbResult ) {
- $dbResult += array(
- 'nextSequenceValue' => '',
+ $dbResult += [
'insert' => '',
'insertId' => '',
'select' => '',
'selectRow' => ''
- );
+ ];
$db = $this->getMockBuilder( 'DatabaseMysql' )
->disableOriginalConstructor()
->getMock();
$db->expects( $this->any() )
- ->method( 'nextSequenceValue' )
- ->will( $this->returnValue( $dbResult['nextSequenceValue'] ) );
- $db->expects( $this->any() )
->method( 'insert' )
->will( $this->returnValue( $dbResult['insert'] ) );
$db->expects( $this->any() )
@@ -161,6 +123,7 @@ class EchoEventMapperTest extends MediaWikiTestCase {
$db->expects( $this->any() )
->method( 'selectRow' )
->will( $this->returnValue( $dbResult['selectRow'] ) );
+
return $db;
}
diff --git a/Echo/tests/phpunit/mapper/NotificationMapperTest.php b/Echo/tests/phpunit/mapper/NotificationMapperTest.php
index 3a67219a..420c0934 100644
--- a/Echo/tests/phpunit/mapper/NotificationMapperTest.php
+++ b/Echo/tests/phpunit/mapper/NotificationMapperTest.php
@@ -9,15 +9,15 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
$this->assertTrue( true );
}
- public function fetchUnreadByUser( User $user, $limit, array $eventTypes = array() ) {
+ public function fetchUnreadByUser( User $user, $limit, array $eventTypes = [] ) {
// Unsuccessful select
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'select' => false ) ) );
- $res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, '' );
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => false ] ) );
+ $res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, null, '' );
$this->assertEmpty( $res );
// Successful select
- $dbResult = array(
- (object)array (
+ $dbResult = [
+ (object)[
'event_id' => 1,
'event_type' => 'test_event',
'event_variant' => '',
@@ -31,30 +31,30 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
'notification_bundle_base' => 1,
'notification_bundle_hash' => 'testhash',
'notification_bundle_display_hash' => 'testdisplayhash'
- )
- );
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'select' => $dbResult ) ) );
- $res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, '', array() );
- $this->assertEmpty( $res );
+ ]
+ ];
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ) );
+ $res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, null, '', [] );
+ $this->assertEmpty( $res );
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'select' => $dbResult ) ) );
- $res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, '', array( 'test_event' ) );
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => $dbResult ] ) );
+ $res = $notifMapper->fetchUnreadByUser( $this->mockUser(), 10, null, '', [ 'test_event' ] );
$this->assertTrue( is_array( $res ) );
$this->assertGreaterThan( 0, count( $res ) );
foreach ( $res as $row ) {
- $this->assertInstanceOf( 'EchoNotification', $row );
+ $this->assertInstanceOf( 'EchoNotification', $row );
}
}
public function testFetchByUser() {
// Unsuccessful select
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'select' => false ) ) );
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => false ] ) );
$res = $notifMapper->fetchByUser( $this->mockUser(), 10, '' );
$this->assertEmpty( $res );
// Successful select
- $notifDbResult = array(
- (object)array (
+ $notifDbResult = [
+ (object)[
'event_id' => 1,
'event_type' => 'test_event',
'event_variant' => '',
@@ -62,53 +62,53 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
'event_page_id' => '',
'event_agent_id' => '',
'event_agent_ip' => '',
+ 'event_deleted' => 0,
'notification_user' => 1,
'notification_timestamp' => '20140615101010',
'notification_read_timestamp' => '20140616101010',
'notification_bundle_base' => 1,
'notification_bundle_hash' => 'testhash',
'notification_bundle_display_hash' => 'testdisplayhash'
- )
- );
+ ]
+ ];
- $tpDbResult = array(
- (object)array(
- 'etp_user' => 1, // userid
+ $tpDbResult = [
+ (object)[
'etp_page' => 7, // pageid
'etp_event' => 1, // eventid
- ),
- );
+ ],
+ ];
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'select' => $notifDbResult ) ) );
- $res = $notifMapper->fetchByUser( $this->mockUser(), 10, '', array() );
- $this->assertEmpty( $res );
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'select' => $notifDbResult ] ) );
+ $res = $notifMapper->fetchByUser( $this->mockUser(), 10, '', [] );
+ $this->assertEmpty( $res );
$notifMapper = new EchoNotificationMapper(
- $this->mockMWEchoDbFactory( array ( 'select' => $notifDbResult ) ),
+ $this->mockMWEchoDbFactory( [ 'select' => $notifDbResult ] ),
new EchoTargetPageMapper(
- $this->mockMWEchoDbFactory( array( 'select' => $tpDbResult ) )
+ $this->mockMWEchoDbFactory( [ 'select' => $tpDbResult ] )
)
);
- $res = $notifMapper->fetchByUser( $this->mockUser(), 10, '', array( 'test_event' ) );
+ $res = $notifMapper->fetchByUser( $this->mockUser(), 10, '', [ 'test_event' ] );
$this->assertTrue( is_array( $res ) );
$this->assertGreaterThan( 0, count( $res ) );
foreach ( $res as $row ) {
- $this->assertInstanceOf( 'EchoNotification', $row );
+ $this->assertInstanceOf( 'EchoNotification', $row );
}
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array() ) );
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [] ) );
$res = $notifMapper->fetchByUser( $this->mockUser(), 10, '' );
$this->assertEmpty( $res );
}
public function testFetchNewestByUserBundleHash() {
// Unsuccessful select
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'selectRow' => false ) ) );
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'selectRow' => false ] ) );
$res = $notifMapper->fetchNewestByUserBundleHash( User::newFromId( 1 ), 'testhash' );
$this->assertFalse( $res );
// Successful select
- $dbResult = (object)array (
+ $dbResult = (object)[
'event_id' => 1,
'event_type' => 'test',
'event_variant' => '',
@@ -116,26 +116,27 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
'event_page_id' => '',
'event_agent_id' => '',
'event_agent_ip' => '',
+ 'event_deleted' => 0,
'notification_user' => 1,
'notification_timestamp' => '20140615101010',
'notification_read_timestamp' => '20140616101010',
'notification_bundle_base' => 1,
'notification_bundle_hash' => 'testhash',
'notification_bundle_display_hash' => 'testdisplayhash'
- );
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'selectRow' => $dbResult ) ) );
+ ];
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'selectRow' => $dbResult ] ) );
$row = $notifMapper->fetchNewestByUserBundleHash( User::newFromId( 1 ), 'testdisplayhash' );
$this->assertInstanceOf( 'EchoNotification', $row );
}
public function testFetchByUserOffset() {
// Unsuccessful select
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'selectRow' => false ) ) );
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'selectRow' => false ] ) );
$res = $notifMapper->fetchByUserOffset( User::newFromId( 1 ), 500 );
$this->assertFalse( $res );
// Successful select
- $dbResult = (object)array (
+ $dbResult = (object)[
'event_id' => 1,
'event_type' => 'test',
'event_variant' => '',
@@ -143,24 +144,25 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
'event_page_id' => '',
'event_agent_id' => '',
'event_agent_ip' => '',
+ 'event_deleted' => 0,
'notification_user' => 1,
'notification_timestamp' => '20140615101010',
'notification_read_timestamp' => '20140616101010',
'notification_bundle_base' => 1,
'notification_bundle_hash' => 'testhash',
'notification_bundle_display_hash' => 'testdisplayhash'
- );
- $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( array ( 'selectRow' => $dbResult ) ) );
- $row = $notifMapper->fetchNewestByUserBundleHash( User::newFromId( 1 ), 500 );
+ ];
+ $notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( [ 'selectRow' => $dbResult ] ) );
+ $row = $notifMapper->fetchByUserOffset( User::newFromId( 1 ), 500 );
$this->assertInstanceOf( 'EchoNotification', $row );
}
public function testDeleteByUserEventOffset() {
- $dbResult = array( 'delete' => true );
+ $dbResult = [ 'delete' => true ];
$notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $dbResult ) );
$this->assertTrue( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) );
- $dbResult = array( 'delete' => false );
+ $dbResult = [ 'delete' => false ];
$notifMapper = new EchoNotificationMapper( $this->mockMWEchoDbFactory( $dbResult ) );
$this->assertFalse( $notifMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ) );
}
@@ -180,7 +182,8 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
->will( $this->returnValue( true ) );
$user->expects( $this->any() )
->method( 'getGroups' )
- ->will( $this->returnValue( array( 'echo_group' ) ) );
+ ->will( $this->returnValue( [ 'echo_group' ] ) );
+
return $user;
}
@@ -193,7 +196,8 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
->getMock();
$event->expects( $this->any() )
->method( 'toDbArray' )
- ->will( $this->returnValue( array() ) );
+ ->will( $this->returnValue( [] ) );
+
return $event;
}
@@ -207,6 +211,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
$dbFactory->expects( $this->any() )
->method( 'getEchoDb' )
->will( $this->returnValue( $this->mockDb( $dbResult ) ) );
+
return $dbFactory;
}
@@ -214,12 +219,12 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
* Mock object of DatabaseMysql ( DatabaseBase )
*/
protected function mockDb( array $dbResult ) {
- $dbResult += array(
+ $dbResult += [
'insert' => '',
'select' => '',
'selectRow' => '',
'delete' => ''
- );
+ ];
$db = $this->getMockBuilder( 'DatabaseMysql' )
->disableOriginalConstructor()
@@ -236,7 +241,7 @@ class EchoNotificationMapperTest extends MediaWikiTestCase {
$db->expects( $this->any() )
->method( 'selectRow' )
->will( $this->returnValue( $dbResult['selectRow'] ) );
- $db->expects ( $this->any() )
+ $db->expects( $this->any() )
->method( 'onTransactionIdle' )
->will( new EchoExecuteFirstArgumentStub );
@@ -253,9 +258,10 @@ class EchoExecuteFirstArgumentStub implements PHPUnit_Framework_MockObject_Stub
if ( !$invocation->arguments ) {
throw new PHPUnit_Framework_Exception( 'Method call must have an argument' );
}
+
return call_user_func( reset( $invocation->arguments ) );
}
-
+
public function toString() {
return 'return result of call_user_func on first invocation argument';
}
diff --git a/Echo/tests/phpunit/mapper/TargetPageMapperTest.php b/Echo/tests/phpunit/mapper/TargetPageMapperTest.php
index 6358df31..522ee34d 100644
--- a/Echo/tests/phpunit/mapper/TargetPageMapperTest.php
+++ b/Echo/tests/phpunit/mapper/TargetPageMapperTest.php
@@ -2,52 +2,24 @@
class EchoTargetPageMapperTest extends MediaWikiTestCase {
- public function testFetchByUserPageId() {
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( array ( 'select' => false ) ) );
- $res = $targetMapper->fetchByUserPageId( User::newFromId( 1 ), 1 );
- $this->assertFalse( $res );
-
- $dbResult = array (
- (object)array (
- 'etp_user' => 1,
- 'etp_page' => 2,
- 'etp_event' => 3
- ),
- (object)array (
- 'etp_user' => 1,
- 'etp_page' => 2,
- 'etp_event' => 7,
- )
- );
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( array ( 'select' => $dbResult ) ) );
- $res = $targetMapper->fetchByUserPageId( User::newFromId( 1 ), 2 );
- $this->assertTrue( is_array( $res ) );
- $this->assertCount( 2, $res );
- foreach ( $res as $targetPages ) {
- $this->assertTrue( is_array( $targetPages ) );
- $this->assertCount( 1, $targetPages );
- $this->assertInstanceOf( 'EchoTargetPage', reset( $targetPages ) );
- }
- }
-
public function provideDataTestInsert() {
- return array (
- array (
+ return [
+ [
'successful insert with next sequence = 1',
- array ( 'nextSequenceValue' => 1, 'insert' => true, 'insertId' => 2 ),
+ [ 'insert' => true, 'insertId' => 2 ],
1
- ),
- array (
+ ],
+ [
'successful insert with insert id = 2',
- array ( 'nextSequenceValue' => null, 'insert' => true, 'insertId' => 2 ),
+ [ 'insert' => true, 'insertId' => 2 ],
2
- ),
- array (
+ ],
+ [
'unsuccessful insert',
- array ( 'nextSequenceValue' => null, 'insert' => false, 'insertId' => 2 ),
+ [ 'insert' => false, 'insertId' => 2 ],
false
- ),
- );
+ ],
+ ];
}
/**
@@ -59,54 +31,6 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
$this->assertEquals( $result, $targetMapper->insert( $target ), $message );
}
- public function testDelete() {
- $dbResult = array( 'delete' => true );
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertTrue( $targetMapper->delete( $this->mockEchoTargetPage() ) );
-
- $dbResult = array( 'delete' => false );
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertFalse( $targetMapper->delete( $this->mockEchoTargetPage() ) );
- }
-
- public function provideDataTestDeleteByUserEvents() {
- return array(
- array( true, array( 1 ), true ),
- array( false, array( 1 ), false ),
- array( true, array(), true ),
- array( false, array(), true ),
- );
- }
-
- /**
- * @dataProvider provideDataTestDeleteByUserEvents
- */
- public function testDeleteByUserEvents( $deleteResult, $eventIds, $result ) {
- $dbResult = array( 'delete' => $deleteResult );
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertSame( $targetMapper->deleteByUserEvents( User::newFromId( 1 ), $eventIds ), $result );
- }
-
- public function testDeleteByUser() {
- $dbResult = array( 'delete' => true );
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertSame( $targetMapper->deleteByUser( User::newFromId( 1 ) ), true );
-
- $dbResult = array( 'delete' => false );
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertSame( $targetMapper->deleteByUser( User::newFromId( 1 ) ), false );
- }
-
- public function testDeleteByUserEventOffset() {
- $dbResult = array( 'delete' => true );
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertSame( $targetMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ), true );
-
- $dbResult = array( 'delete' => false );
- $targetMapper = new EchoTargetPageMapper( $this->mockMWEchoDbFactory( $dbResult ) );
- $this->assertSame( $targetMapper->deleteByUserEventOffset( User::newFromId( 1 ), 500 ), false );
- }
-
/**
* Mock object of EchoTargetPage
*/
@@ -116,7 +40,7 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
->getMock();
$target->expects( $this->any() )
->method( 'toDbArray' )
- ->will( $this->returnValue( array() ) );
+ ->will( $this->returnValue( [] ) );
$target->expects( $this->any() )
->method( 'getUser' )
->will( $this->returnValue( User::newFromId( 1 ) ) );
@@ -126,6 +50,7 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
$target->expects( $this->any() )
->method( 'getEventId' )
->will( $this->returnValue( 3 ) );
+
return $target;
}
@@ -139,6 +64,7 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
$dbFactory->expects( $this->any() )
->method( 'getEchoDb' )
->will( $this->returnValue( $this->mockDb( $dbResult ) ) );
+
return $dbFactory;
}
@@ -146,20 +72,16 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
* Mock object of DatabaseMysql ( DatabaseBase )
*/
protected function mockDb( array $dbResult ) {
- $dbResult += array(
- 'nextSequenceValue' => '',
+ $dbResult += [
'insert' => '',
'insertId' => '',
'select' => '',
'delete' => ''
- );
+ ];
$db = $this->getMockBuilder( 'DatabaseMysql' )
->disableOriginalConstructor()
->getMock();
$db->expects( $this->any() )
- ->method( 'nextSequenceValue' )
- ->will( $this->returnValue( $dbResult['nextSequenceValue'] ) );
- $db->expects( $this->any() )
->method( 'insert' )
->will( $this->returnValue( $dbResult['insert'] ) );
$db->expects( $this->any() )
@@ -171,6 +93,7 @@ class EchoTargetPageMapperTest extends MediaWikiTestCase {
$db->expects( $this->any() )
->method( 'delete' )
->will( $this->returnValue( $dbResult['delete'] ) );
+
return $db;
}
diff --git a/Echo/tests/phpunit/model/NotificationTest.php b/Echo/tests/phpunit/model/NotificationTest.php
index 267bd25a..d6d45c3e 100644
--- a/Echo/tests/phpunit/model/NotificationTest.php
+++ b/Echo/tests/phpunit/model/NotificationTest.php
@@ -25,9 +25,9 @@ class EchoNotificationTest extends MediaWikiTestCase {
wfTimestamp( TS_MW, $row['notification_read_timestamp'] )
);
- $notif = EchoNotification::newFromRow( (object)$row, array(
+ $notif = EchoNotification::newFromRow( (object)$row, [
EchoTargetPage::newFromRow( (object)$this->mockTargetPageRow() )
- ) );
+ ] );
$this->assertGreaterThan( 0, count( $notif->getTargetPages() ) );
foreach ( $notif->getTargetPages() as $targetPage ) {
$this->assertInstanceOf( 'EchoTargetPage', $targetPage );
@@ -48,7 +48,7 @@ class EchoNotificationTest extends MediaWikiTestCase {
* Mock a notification row from database
*/
protected function mockNotificationRow() {
- return array (
+ return [
'notification_user' => 1,
'notification_event' => 1,
'notification_timestamp' => time(),
@@ -56,33 +56,33 @@ class EchoNotificationTest extends MediaWikiTestCase {
'notification_bundle_base' => 1,
'notification_bundle_hash' => 'testhash',
'notification_bundle_display_hash' => 'testdisplayhash'
- );
+ ];
}
/**
* Mock an event row from database
*/
protected function mockEventRow() {
- return array (
+ return [
'event_id' => 1,
'event_type' => 'test_event',
'event_variant' => '',
'event_extra' => '',
'event_page_id' => '',
'event_agent_id' => '',
- 'event_agent_ip' => ''
- );
+ 'event_agent_ip' => '',
+ 'event_deleted' => 0,
+ ];
}
/**
* Mock a target page row
*/
protected function mockTargetPageRow() {
- return array (
- 'etp_user' => 1,
+ return [
'etp_page' => 2,
'etp_event' => 1
- );
+ ];
}
}
diff --git a/Echo/tests/phpunit/model/TargetPageTest.php b/Echo/tests/phpunit/model/TargetPageTest.php
index 29670ff7..a7f7c035 100644
--- a/Echo/tests/phpunit/model/TargetPageTest.php
+++ b/Echo/tests/phpunit/model/TargetPageTest.php
@@ -5,23 +5,6 @@ class EchoTargetPageTest extends MediaWikiTestCase {
public function testCreate() {
$this->assertNull(
EchoTargetPage::create(
- User::newFromId( 0 ),
- $this->mockTitle( 1 ),
- $this->mockEchoEvent()
- )
- );
-
- $this->assertNull(
- EchoTargetPage::create(
- User::newFromId( 1 ),
- $this->mockTitle( 0 ),
- $this->mockEchoEvent()
- )
- );
-
- $this->assertNull(
- EchoTargetPage::create(
- User::newFromId( 0 ),
$this->mockTitle( 0 ),
$this->mockEchoEvent()
)
@@ -30,7 +13,6 @@ class EchoTargetPageTest extends MediaWikiTestCase {
$this->assertInstanceOf(
'EchoTargetPage',
EchoTargetPage::create(
- User::newFromId( 1 ),
$this->mockTitle( 1 ),
$this->mockEchoEvent()
)
@@ -38,13 +20,13 @@ class EchoTargetPageTest extends MediaWikiTestCase {
}
public function testNewFromRow() {
- $row = (object) array (
- 'etp_user' => 1,
+ $row = (object)[
'etp_page' => 2,
'etp_event' => 3
- );
+ ];
$obj = EchoTargetPage::newFromRow( $row );
$this->assertInstanceOf( 'EchoTargetPage', $obj );
+
return $obj;
}
@@ -52,10 +34,9 @@ class EchoTargetPageTest extends MediaWikiTestCase {
* @expectedException MWException
*/
public function testNewFromRowWithException() {
- $row = (object) array (
- 'etp_page' => 2,
+ $row = (object)[
'etp_event' => 3
- );
+ ];
$this->assertInstanceOf( 'EchoTargetPage', EchoTargetPage::newFromRow( $row ) );
}
@@ -65,7 +46,11 @@ class EchoTargetPageTest extends MediaWikiTestCase {
public function testToDbArray( $obj ) {
$row = $obj->toDbArray();
$this->assertTrue( is_array( $row ) );
- $this->assertArrayHasKey( 'etp_user', $row );
+
+ // Not very common to assert that a field does _not_ exist
+ // but since we are explicitly removing it, it seems to make sense.
+ $this->assertArrayNotHasKey( 'etp_user', $row );
+
$this->assertArrayHasKey( 'etp_page', $row );
$this->assertArrayHasKey( 'etp_event', $row );
}
@@ -80,6 +65,7 @@ class EchoTargetPageTest extends MediaWikiTestCase {
$event->expects( $this->any() )
->method( 'getArticleID' )
->will( $this->returnValue( $pageId ) );
+
return $event;
}
@@ -93,6 +79,7 @@ class EchoTargetPageTest extends MediaWikiTestCase {
$event->expects( $this->any() )
->method( 'getId' )
->will( $this->returnValue( $eventId ) );
+
return $event;
}
diff --git a/Echo/tests/phpunit/revision_txt/747747747.txt b/Echo/tests/phpunit/revision_txt/747747747.txt
new file mode 100644
index 00000000..6da5594d
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747747747.txt
@@ -0,0 +1,3 @@
+== Hello World ==
+
+Hello!
diff --git a/Echo/tests/phpunit/revision_txt/747747748.txt b/Echo/tests/phpunit/revision_txt/747747748.txt
new file mode 100644
index 00000000..169ebc9b
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747747748.txt
@@ -0,0 +1,11 @@
+== Hello World ==
+
+Hello!
+
+== Hello Users ==
+
+Try to mention non existing users:
+
+[[User:Ping]] [[User:Po?ng]] [[User:Peng/subpage]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC) \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747747749.txt b/Echo/tests/phpunit/revision_txt/747747749.txt
new file mode 100644
index 00000000..87825107
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747747749.txt
@@ -0,0 +1,11 @@
+== Hello World ==
+
+Hello!
+
+== Hello Users ==
+
+Try to mention non existing users:
+
+[[User:Test11]] [[User:Buster7]] [[User:Kudpung]] [[User:Samwalton9]] [[User:PatHadley]] [[User:PauloEduardo]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC) \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747747750.txt b/Echo/tests/phpunit/revision_txt/747747750.txt
new file mode 100644
index 00000000..3dbacfbd
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747747750.txt
@@ -0,0 +1,11 @@
+== Hello World ==
+
+Hello!
+
+== Hello Users ==
+
+Try to mention existing user:
+
+[[User:Test11]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC) \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747798765.txt b/Echo/tests/phpunit/revision_txt/747798765.txt
new file mode 100644
index 00000000..94c8f99b
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747798765.txt
@@ -0,0 +1,9 @@
+Simultaneously edit multiple sections
+
+== Section 1 ==
+
+Content 1
+
+== Section 2 ==
+
+Content 2 \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747798766.txt b/Echo/tests/phpunit/revision_txt/747798766.txt
new file mode 100644
index 00000000..99bce40c
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747798766.txt
@@ -0,0 +1,19 @@
+Simultaneously edit multiple sections
+
+== Section 1 ==
+
+Content 1
+
+New content with userlink ( dont try to mention this one )
+
+[[User:Test11]]
+
+== Section 2 ==
+
+Content 2
+
+New content with userlink & signature in another section ( try to mention this one )
+
+[[User:NoUser]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC) \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747798767.txt b/Echo/tests/phpunit/revision_txt/747798767.txt
new file mode 100644
index 00000000..26954a15
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747798767.txt
@@ -0,0 +1,25 @@
+Simultaneously edit multiple sections
+
+== Section 1 ==
+
+Content 1
+
+New content with userlink ( dont try to mention this one )
+
+[[User:Test11]]
+
+== Section 1.5 ==
+
+New section in between with userlink ( dont try to mention this one )
+
+[[User:Test11]]
+
+== Section 2 ==
+
+Content 2
+
+New content with userlink & signature in another section ( try to mention this one )
+
+[[User:NoUser]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC) \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747798768.txt b/Echo/tests/phpunit/revision_txt/747798768.txt
new file mode 100644
index 00000000..8569f9ef
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747798768.txt
@@ -0,0 +1,17 @@
+Simultaneously edit multiple sections
+
+== Section 1 ==
+
+Content 1
+
+New content with signature
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC)
+
+== Section 2 ==
+
+Content 2
+
+New content with userlink ( dont try to mention this one )
+
+[[User:Test11]] \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747798770.txt b/Echo/tests/phpunit/revision_txt/747798770.txt
new file mode 100644
index 00000000..55067bc7
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747798770.txt
@@ -0,0 +1,25 @@
+Simultaneously edit multiple sections
+
+== Section 1 ==
+
+Content 1
+
+New Content with userlink ( dont try to mention this one )
+
+[[User:NoUser1]]
+
+== Section 1.5 ==
+
+New section in between with userlink & signature ( try to mention this one )
+
+[[User:Test11]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC)
+
+== Section 2 ==
+
+Content 2
+
+New Content with userlink ( dont try to mention this one )
+
+[[User:NoUser2]] \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747798771.txt b/Echo/tests/phpunit/revision_txt/747798771.txt
new file mode 100644
index 00000000..96c8ba5a
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747798771.txt
@@ -0,0 +1,27 @@
+Simultaneously edit multiple sections
+
+== Section 1 ==
+
+Content 1
+
+New Content with userlink ( dont try to mention this one )
+
+[[User:NoUser1]]
+
+== Section 1.5 ==
+
+New section in between with userlink & signature ( try to mention this one )
+
+[[User:NoUser1.5]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC)
+
+== Section 2 ==
+
+Content 2
+
+New Content with userlink & signature ( try to mention this one )
+
+[[User:NoUser2]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC) \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/747798772.txt b/Echo/tests/phpunit/revision_txt/747798772.txt
new file mode 100644
index 00000000..e44c4549
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/747798772.txt
@@ -0,0 +1,35 @@
+Simultaneously edit multiple sections
+
+== Section 1 ==
+
+Content 1
+
+New Content with userlink & signature ( try to mention this one )
+
+[[User:NoUser1]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC)
+
+== Section 1.5 ==
+
+New section in between with userlink ( don't try to mention this one )
+
+[[User:NoUser1.5]]
+
+== Section 1.75 ==
+
+New section in between with userlink & signature ( try to mention this one )
+
+[[User:NoUser1.75]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC
+
+== Section 2 ==
+
+Content 2
+
+New Content with userlink & signature ( try to mention this one )
+
+[[User:NoUser2]]
+
+[[:User:Admin|Admin]] 13:22, 23 June 2016 (UTC) \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/987654321.txt b/Echo/tests/phpunit/revision_txt/987654321.txt
new file mode 100644
index 00000000..2d01e38a
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/987654321.txt
@@ -0,0 +1,2 @@
+== Section 1 ==
+Hi.
diff --git a/Echo/tests/phpunit/revision_txt/987654322.txt b/Echo/tests/phpunit/revision_txt/987654322.txt
new file mode 100644
index 00000000..b8a1722b
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/987654322.txt
@@ -0,0 +1,2 @@
+== Section 1 ==
+Hi [[User:Test11]].
diff --git a/Echo/tests/phpunit/revision_txt/987654323.txt b/Echo/tests/phpunit/revision_txt/987654323.txt
new file mode 100644
index 00000000..cd1e6ca3
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/987654323.txt
@@ -0,0 +1,4 @@
+== Section 1 ==
+Hi [[User:Test11]].
+
+[[:User:Admin|Admin]] 23:47, 6 July 2015 (UTC)
diff --git a/Echo/tests/phpunit/revision_txt/987654324.txt b/Echo/tests/phpunit/revision_txt/987654324.txt
new file mode 100644
index 00000000..d30166d7
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/987654324.txt
@@ -0,0 +1,2 @@
+== Section 1 ==
+Hi [[User:Test11]] - [[:User:Admin|Admin]] 23:47, 6 July 2015 (UTC)
diff --git a/Echo/tests/phpunit/revision_txt/987654325.txt b/Echo/tests/phpunit/revision_txt/987654325.txt
new file mode 100644
index 00000000..3ba1be74
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/987654325.txt
@@ -0,0 +1,4 @@
+== Section 1 ==
+[[User:JarJar|JarJar]]
+== Section 2 ==
+Hi [[User:Test11|Test11]] - [[:User:Admin|Admin]] 23:47, 6 July 2015 (UTC)
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-01/empty-file b/Echo/tests/phpunit/revision_txt/987654400.txt
index e69de29b..e69de29b 100644
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-01/empty-file
+++ b/Echo/tests/phpunit/revision_txt/987654400.txt
diff --git a/Echo/tests/phpunit/revision_txt/987654401.txt b/Echo/tests/phpunit/revision_txt/987654401.txt
new file mode 100644
index 00000000..44f46f23
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/987654401.txt
@@ -0,0 +1,3 @@
+Hi [[User:Test11]]!
+
+[[:User:Admin|Admin]] 23:47, 6 July 2015 (UTC)
diff --git a/Echo/tests/phpunit/revision_txt/987667998.txt b/Echo/tests/phpunit/revision_txt/987667998.txt
new file mode 100644
index 00000000..371276ce
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/987667998.txt
@@ -0,0 +1,15 @@
+== Old Content ==
+
+== Section 1 ==
+Lorem ipsum amet, ut officia eius nihil ad qui ducimus, minus impedit, voluptas neque in quia autem hic animi, quisquam blanditiis adipisci accusantium laudantium, eligendi dolor eligendi enim dolor laborum commodi laboris debitis debitis numquam odit dolore quidem qui doloribus incidunt, aliquid sit quam nostrum cum ad suscipit enim consequatur, est ut rerum fuga. Voluptatum fuga. Doloribus et itaque sequi esse, ea eiusmod hic in suscipit nihil est corrupti, molestias ut sunt, velit cumque ut enim inventore veniam, sequi est ea cillum error veniam, quisquam veniam, ad quisquam delectus, eos omnis eaqu.
+Ipsum harum maiores consectetur, nulla debitis molestiae sit cum quidem enim alias tenetur dolores architecto quia repellendus. Doloribus duis enim sunt, iste nulla enim dolores sit, voluptatem qui.
+
+== Section 2 ==
+Lorem ipsum qui quis nihil eius ea irure voluptas dolorem consequuntur et officia sit, iure amet, id optio, dolor distinctio. Quia qui aliqua. Sint mollit dolor consectetur sapiente est numquam obcaecati error ea qui est magnam placeat, reprehenderit, quia cum atque incididunt sit eu est, temporibus qui eaque iste id, et ut eu explicabo. Recusandae. Hic voluptatem. Dolor dolores occaecat odio natus dolorum cupidatat blanditiis ratione quidem aliquid anim accusamus ut expedita blanditiis reprehenderit neque ea quas quaerat omnis eu placeat, excepteur inventore consequat. Dolore animi, minima ut dignissimos facere et aut consequat. Incidunt, lorem se.
+Other Line
+Ipsum harum maiores consectetur, nulla debitis molestiae sit cum quidem enim alias tenetur dolores architecto quia repellendus. Doloribus duis enim sunt, iste nulla enim dolores sit, voluptatem qui.
+
+== Section 3 ==
+Lorem ipsum qui quis nihil eius ea irure voluptas dolorem consequuntur et officia sit, iure amet, id optio, dolor distinctio. Quia qui aliqua. Sint mollit dolor consectetur sapiente est numquam obcaecati error ea qui est magnam placeat, reprehenderit, quia cum atque incididunt sit eu est, temporibus qui eaque iste id, et ut eu explicabo. Recusandae. Hic voluptatem. Dolor dolores occaecat odio natus dolorum cupidatat blanditiis ratione quidem aliquid anim accusamus ut expedita blanditiis reprehenderit neque ea quas quaerat omnis eu placeat, excepteur inventore consequat. Dolore animi, minima ut dignissimos facere et aut consequat. Incidunt, lorem se.
+
+Lorem ipsum ea architecto magna ut quia iure dolor nobis iste aut quam quos voluptatem consequatur? Et deleniti excepteur beatae voluptatem, odit qui necessitatibus pariatur? Repellendus. Est minus odio est architecto molestiae quis perferendis porro tempore, quidem Nam officia autem voluptatem. Qui officia quo occaecat pariatur. Aliquip dolorum et quam ut eos, excepturi soluta delectus, voluptate architecto sint voluptatem molestiae libero proident, esse, culpa, velit repellendus. Quaerat ut sed soluta magni voluptatem. Laborum. Amet, et consectetur nisi ut quia est in mollitia sed quibusdam nulla qui explicabo. Hic vel quis nihi. \ No newline at end of file
diff --git a/Echo/tests/phpunit/revision_txt/987667999.txt b/Echo/tests/phpunit/revision_txt/987667999.txt
new file mode 100644
index 00000000..4f9e18b7
--- /dev/null
+++ b/Echo/tests/phpunit/revision_txt/987667999.txt
@@ -0,0 +1,15 @@
+== Replace Content ==
+
+== Section 4 ==
+Lorem ipsum eligendi rerum nesciunt, iusto do dolore officia sint inventore qui fugiat eos dolor debitis debitis laborum cum alias anim laborum. Mollitia ullam esse quidem reprehenderit, ipsum, magni quae praesentium harum veniam, ipsa, exercitationem Nam elit, cupiditate enim aut omnis ipsum, voluptates exercitationem voluptatem qui odio ullam voluptates aut sint cupidatat commodi voluptatum in pariatur? Dolor dolores aperiam vel voluptatum non debitis aliquid sunt magni est iure obcaecati cum harum qui id deserunt possimus, enim corporis au.
+
+== Section 5 ==
+Lorem ipsum porro beatae sapiente amet, ea sit, velit, non odit quisquam mollit est, voluptatum consectetur, tenetur aut dolores cum sed ad labore ea veniam, eos velit minima consequatur veniam, voluptas obcaecati aliquid dolore ab occaecat do voluptatem. Minus ut elit, quasi voluptatibus pariatur. Sit aliquip nisi quisquam temporibus rerum esse quas necessitatibus recusandae. Culpa dolor voluptatem. Nesciunt, incididunt temporibus in dicta dolor saepe eiusmod aute.
+Hi - [[User:He7d3r|He7d3r]] ([[User talk:He7d3r|talk]]) 14:19, 9 February 2017 (UTC)
+:Hi, you! - [[User:Test11|Test11]] ([[User talk:Test11|talk]]) 14:19, 10 February 2017 (UTC)
+::Hi, as well! - [[:User:Admin|Admin]] 23:47, 11 February 2017 (UTC)
+
+== Section 6 ==
+Lorem ipsum molestiae quia voluptatibus aliquid quis ut ullamco vitae adipisicing enim voluptas dolores consectetur ducimus, quia qui eos, aut sint ut corporis mollitia recusandae. Et impedit, omnis earum magni iur.
+Lorem ipsum numquam sint mollitia vel voluptatem nihil reprehenderit, enim qui voluptatum eligendi animi, id, in qui Nam saepe adipisci qui voluptas libero ut ut adipisicing provident, ut animi, deleniti sed voluptas id, sit minus modi molestias rerum illum, excepteu.
+Lorem ipsum qui est, deleniti veniam, eos, qui labore nihil numquam inventore mollit alias sapiente ad perferendis cillum incididunt qui consectetur amet, aliquip in maiores tempore, a dolore corporis eu optio, quod excepteur illo minima laboris duis aut reiciendis ducimus, sunt error enim anim ducimus, nisi doloribus veniam, eius ea voluptate. \ No newline at end of file
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js b/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js
new file mode 100644
index 00000000..66e259c6
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js
@@ -0,0 +1,117 @@
+( function ( mw ) {
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.BundleNotificationItem' );
+
+ QUnit.test( 'Constructing the model', function ( assert ) {
+ var bundledItems = [
+ new mw.echo.dm.NotificationItem( 0, { read: false, seen: false, timestamp: '201601010000' } ),
+ new mw.echo.dm.NotificationItem( 1, { read: false, seen: false, timestamp: '201601010100' } ),
+ new mw.echo.dm.NotificationItem( 2, { read: false, seen: true, timestamp: '201601010200' } ),
+ new mw.echo.dm.NotificationItem( 3, { read: false, seen: true, timestamp: '201601010300' } ),
+ new mw.echo.dm.NotificationItem( 4, { read: false, seen: true, timestamp: '201601010400' } )
+ ],
+ bundle = new mw.echo.dm.BundleNotificationItem(
+ 100,
+ bundledItems,
+ { modelName: 'foo' }
+ );
+
+ assert.equal(
+ bundle.getCount(),
+ 5,
+ 'Bundled items added to internal list'
+ );
+
+ assert.equal(
+ bundle.getName(),
+ 'foo',
+ 'Bundle name stored'
+ );
+
+ assert.deepEqual(
+ bundle.getAllIds(),
+ [ 4, 3, 2, 1, 0 ],
+ 'All ids present'
+ );
+
+ assert.equal(
+ bundle.isRead(),
+ false,
+ 'Bundle with all unread items is unread'
+ );
+
+ assert.equal(
+ bundle.hasUnseen(),
+ true,
+ 'Bundle has unseen items'
+ );
+
+ assert.deepEqual(
+ ( function () {
+ var findItems = bundle.findByIds( [ 1, 4 ] );
+ return findItems.map( function ( item ) {
+ return item.getId();
+ } );
+ }() ),
+ [ 4, 1 ],
+ 'findByIds fetches correct items in the default sorting order'
+ );
+ } );
+
+ QUnit.test( 'Managing a list of items', function ( assert ) {
+ var i,
+ bundledItems = [
+ new mw.echo.dm.NotificationItem( 0, { read: false, seen: false, timestamp: '201601010000' } ),
+ new mw.echo.dm.NotificationItem( 1, { read: false, seen: false, timestamp: '201601010100' } ),
+ new mw.echo.dm.NotificationItem( 2, { read: false, seen: true, timestamp: '201601010200' } ),
+ new mw.echo.dm.NotificationItem( 3, { read: false, seen: true, timestamp: '201601010300' } ),
+ new mw.echo.dm.NotificationItem( 4, { read: false, seen: true, timestamp: '201601010400' } )
+ ],
+ bundle = new mw.echo.dm.BundleNotificationItem(
+ 100,
+ bundledItems,
+ {
+ name: 'foo'
+ }
+ );
+
+ assert.equal(
+ bundle.hasUnseen(),
+ true,
+ 'Bundle has unseen'
+ );
+
+ // Mark all items as seen
+ for ( i = 0; i < bundledItems.length; i++ ) {
+ bundledItems[ i ].toggleSeen( true );
+ }
+
+ assert.equal(
+ bundle.hasUnseen(),
+ false,
+ 'Bundle does not have unseen after all items marked as seen'
+ );
+
+ assert.equal(
+ bundle.isRead(),
+ false,
+ 'Bundle is unread'
+ );
+ // Mark one item as read
+ bundledItems[ 0 ].toggleRead( true );
+ assert.equal(
+ bundle.isRead(),
+ false,
+ 'Bundle is still unread if it has some unread items'
+ );
+
+ // Mark all items as read
+ for ( i = 0; i < bundledItems.length; i++ ) {
+ bundledItems[ i ].toggleRead( true );
+ }
+ assert.equal(
+ bundle.isRead(),
+ true,
+ 'Bundle is marked as read if all items are read'
+ );
+ } );
+}( mediaWiki ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js b/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js
new file mode 100644
index 00000000..6073a1a5
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js
@@ -0,0 +1,311 @@
+( function ( mw, $ ) {
+ var defaults = {
+ getModelName: 'xwiki',
+ getSourceNames: [],
+ getCount: 0,
+ hasUnseen: false,
+ getItems: [],
+ isEmpty: true
+ };
+
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.CrossWikiNotificationItem' );
+
+ QUnit.test( 'Constructing the model', function ( assert ) {
+ var i, method, model,
+ cases = [
+ {
+ params: {
+ id: -1,
+ config: {}
+ },
+ expected: defaults,
+ msg: 'Default values'
+ },
+ {
+ params: {
+ id: -1,
+ config: { modelName: 'foo' }
+ },
+ expected: $.extend( true, {}, defaults, {
+ getModelName: 'foo'
+ } ),
+ msg: 'Overriding model name'
+ },
+ {
+ params: {
+ id: -1,
+ config: { count: 10 }
+ },
+ expected: $.extend( true, {}, defaults, {
+ getCount: 10
+ } ),
+ msg: 'Overriding model count'
+ }
+ ];
+
+ for ( i = 0; i < cases.length; i++ ) {
+ model = new mw.echo.dm.CrossWikiNotificationItem(
+ cases[ i ].params.id,
+ cases[ i ].params.config
+ );
+
+ for ( method in defaults ) {
+ assert.deepEqual(
+ // Method
+ model[ method ](),
+ // Expected value
+ cases[ i ].expected[ method ],
+ cases[ i ].msg + ' (' + method + ')'
+ );
+ }
+ }
+ } );
+
+ QUnit.test( 'Managing notification lists', function ( assert ) {
+ var i, j,
+ model = new mw.echo.dm.CrossWikiNotificationItem( 1 ),
+ groupDefinitions = [
+ {
+ name: 'foo',
+ sourceData: {
+ title: 'Foo Wiki',
+ base: 'http://foo.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 0, { source: 'foo', read: false, seen: false, timestamp: '201601010100' } ),
+ new mw.echo.dm.NotificationItem( 1, { source: 'foo', read: false, seen: false, timestamp: '201601010200' } ),
+ new mw.echo.dm.NotificationItem( 2, { source: 'foo', read: false, seen: false, timestamp: '201601010300' } )
+ ]
+ },
+ {
+ name: 'bar',
+ sourceData: {
+ title: 'Bar Wiki',
+ base: 'http://bar.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 3, { source: 'bar', read: false, seen: false, timestamp: '201601020000' } ),
+ new mw.echo.dm.NotificationItem( 4, { source: 'bar', read: false, seen: false, timestamp: '201601020100' } ),
+ new mw.echo.dm.NotificationItem( 5, { source: 'bar', read: false, seen: false, timestamp: '201601020200' } ),
+ new mw.echo.dm.NotificationItem( 6, { source: 'bar', read: false, seen: false, timestamp: '201601020300' } )
+ ]
+ },
+ {
+ name: 'baz',
+ sourceData: {
+ title: 'Baz Wiki',
+ base: 'http://baz.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 7, { source: 'baz', timestamp: '201601050100' } )
+ ]
+ }
+ ];
+
+ // Add groups to model
+ for ( i = 0; i < groupDefinitions.length; i++ ) {
+ model.getList().addGroup(
+ groupDefinitions[ i ].name,
+ groupDefinitions[ i ].sourceData,
+ groupDefinitions[ i ].items
+ );
+ }
+
+ assert.deepEqual(
+ model.getSourceNames(),
+ [ 'baz', 'bar', 'foo' ],
+ 'Model source names exist in order'
+ );
+ assert.equal(
+ model.hasUnseen(),
+ true,
+ 'hasUnseen is true if there are unseen items in any group'
+ );
+
+ // Mark all items as seen except one
+ for ( i = 0; i < groupDefinitions.length; i++ ) {
+ for ( j = 0; j < groupDefinitions[ i ].items.length; j++ ) {
+ groupDefinitions[ i ].items[ j ].toggleSeen( true );
+ }
+ }
+ groupDefinitions[ 0 ].items[ 0 ].toggleSeen( false );
+ assert.equal(
+ model.hasUnseen(),
+ true,
+ 'hasUnseen is true even if only one item in one group is unseen'
+ );
+
+ groupDefinitions[ 0 ].items[ 0 ].toggleSeen( true );
+ assert.equal(
+ model.hasUnseen(),
+ false,
+ 'hasUnseen is false if there are no unseen items in any of the groups'
+ );
+
+ // Discard group
+ model.getList().removeGroup( 'foo' );
+ assert.deepEqual(
+ model.getSourceNames(),
+ [ 'baz', 'bar' ],
+ 'Group discarded successfully'
+ );
+ } );
+
+ QUnit.test( 'Update seen state', function ( assert ) {
+ var i, numUnseenItems, numAllItems,
+ model = new mw.echo.dm.CrossWikiNotificationItem( 1 ),
+ groupDefinitions = [
+ {
+ name: 'foo',
+ sourceData: {
+ title: 'Foo Wiki',
+ base: 'http://foo.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 0, { source: 'foo', read: false, seen: false, timestamp: '201601010100' } ),
+ new mw.echo.dm.NotificationItem( 1, { source: 'foo', read: false, seen: false, timestamp: '201601010200' } ),
+ new mw.echo.dm.NotificationItem( 2, { source: 'foo', read: false, seen: false, timestamp: '201601010300' } )
+ ]
+ },
+ {
+ name: 'bar',
+ sourceData: {
+ title: 'Bar Wiki',
+ base: 'http://bar.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 3, { source: 'bar', read: false, seen: false, timestamp: '201601020000' } ),
+ new mw.echo.dm.NotificationItem( 4, { source: 'bar', read: false, seen: false, timestamp: '201601020100' } ),
+ new mw.echo.dm.NotificationItem( 5, { source: 'bar', read: false, seen: false, timestamp: '201601020200' } ),
+ new mw.echo.dm.NotificationItem( 6, { source: 'bar', read: false, seen: false, timestamp: '201601020300' } )
+ ]
+ },
+ {
+ name: 'baz',
+ sourceData: {
+ title: 'Baz Wiki',
+ base: 'http://baz.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 7, { source: 'baz', timestamp: '201601050100' } )
+ ]
+ }
+ ];
+
+ // Count all actual items
+ numAllItems = groupDefinitions.reduce( function ( prev, curr ) {
+ return prev + curr.items.length;
+ }, 0 );
+
+ // Add groups to model
+ for ( i = 0; i < groupDefinitions.length; i++ ) {
+ model.getList().addGroup(
+ groupDefinitions[ i ].name,
+ groupDefinitions[ i ].sourceData,
+ groupDefinitions[ i ].items
+ );
+ }
+
+ numUnseenItems = model.getItems().filter( function ( item ) {
+ return !item.isSeen();
+ } ).length;
+ assert.equal(
+ numUnseenItems,
+ numAllItems,
+ 'Starting state: all items are unseen'
+ );
+
+ // Update seen time to be bigger than 'foo' but smaller than the other groups
+ model.updateSeenState( '201601010400' );
+
+ numUnseenItems = model.getItems().filter( function ( item ) {
+ return !item.isSeen();
+ } ).length;
+ assert.equal(
+ numUnseenItems,
+ numAllItems - groupDefinitions[ 0 ].items.length,
+ 'Only some items are seen'
+ );
+
+ // Update seen time to be bigger than all
+ model.updateSeenState( '201701010000' );
+
+ numUnseenItems = model.getItems().filter( function ( item ) {
+ return !item.isSeen();
+ } ).length;
+ assert.equal(
+ numUnseenItems,
+ 0,
+ 'All items are seen'
+ );
+ } );
+
+ QUnit.test( 'Emit discard event', function ( assert ) {
+ var i,
+ results = [],
+ model = new mw.echo.dm.CrossWikiNotificationItem( -1 ),
+ groupDefinitions = [
+ {
+ name: 'foo',
+ sourceData: {
+ title: 'Foo Wiki',
+ base: 'http://foo.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 0, { source: 'foo', read: false, seen: false, timestamp: '201601010100' } ),
+ new mw.echo.dm.NotificationItem( 1, { source: 'foo', read: false, seen: false, timestamp: '201601010200' } ),
+ new mw.echo.dm.NotificationItem( 2, { source: 'foo', read: false, seen: false, timestamp: '201601010300' } )
+ ]
+ },
+ {
+ name: 'bar',
+ sourceData: {
+ title: 'Bar Wiki',
+ base: 'http://bar.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 3, { source: 'bar', read: false, seen: false, timestamp: '201601020000' } ),
+ new mw.echo.dm.NotificationItem( 4, { source: 'bar', read: false, seen: false, timestamp: '201601020100' } ),
+ new mw.echo.dm.NotificationItem( 5, { source: 'bar', read: false, seen: false, timestamp: '201601020200' } ),
+ new mw.echo.dm.NotificationItem( 6, { source: 'bar', read: false, seen: false, timestamp: '201601020300' } )
+ ]
+ },
+ {
+ name: 'baz',
+ sourceData: {
+ title: 'Baz Wiki',
+ base: 'http://baz.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 7, { source: 'baz', timestamp: '201601050100' } )
+ ]
+ }
+ ];
+
+ // Add groups to model
+ for ( i = 0; i < groupDefinitions.length; i++ ) {
+ model.getList().addGroup(
+ groupDefinitions[ i ].name,
+ groupDefinitions[ i ].sourceData,
+ groupDefinitions[ i ].items
+ );
+ }
+
+ // Listen to event
+ model.on( 'discard', function ( name ) {
+ results.push( name );
+ } );
+
+ // Trigger
+ model.getList().removeGroup( 'foo' ); // [ 'foo' ]
+ // Empty a list
+ model.getList().getGroupByName( 'baz' ).discardItems( groupDefinitions[ 2 ].items ); // [ 'foo', 'baz' ]
+
+ assert.deepEqual(
+ results,
+ [ 'foo', 'baz' ],
+ 'Discard event emitted'
+ );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js b/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js
new file mode 100644
index 00000000..c080e242
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.FiltersModel.js
@@ -0,0 +1,110 @@
+( function ( mw, $ ) {
+ var defaultValues = {
+ getReadState: 'all'
+ };
+
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.FiltersModel' );
+
+ QUnit.test( 'Constructing the model', function ( assert ) {
+ var i, model, method,
+ cases = [
+ {
+ msg: 'Empty config',
+ config: {},
+ expected: defaultValues
+ },
+ {
+ msg: 'Readstate: unread',
+ config: {
+ readState: 'unread'
+ },
+ expected: $.extend( true, {}, defaultValues, {
+ getReadState: 'unread'
+ } )
+ },
+ {
+ msg: 'Readstate: read',
+ config: {
+ readState: 'read'
+ },
+ expected: $.extend( true, {}, defaultValues, {
+ getReadState: 'read'
+ } )
+ }
+ ];
+
+ for ( i = 0; i < cases.length; i++ ) {
+ model = new mw.echo.dm.FiltersModel( cases[ i ].config );
+
+ for ( method in cases[ i ].expected ) {
+ assert.deepEqual(
+ // Run the method
+ model[ method ](),
+ // Expected value
+ cases[ i ].expected[ method ],
+ // Message
+ cases[ i ].msg + ' (' + method + ')'
+ );
+ }
+ }
+ } );
+
+ QUnit.test( 'Changing filters', function ( assert ) {
+ var model = new mw.echo.dm.FiltersModel();
+
+ assert.equal(
+ model.getReadState(),
+ 'all',
+ 'Initial value: all'
+ );
+
+ model.setReadState( 'unread' );
+ assert.equal(
+ model.getReadState(),
+ 'unread',
+ 'Changing state (unread)'
+ );
+
+ model.setReadState( 'read' );
+ assert.equal(
+ model.getReadState(),
+ 'read',
+ 'Changing state (read)'
+ );
+
+ model.setReadState( 'foo' );
+ assert.equal(
+ model.getReadState(),
+ 'read',
+ 'Ignoring invalid state (foo)'
+ );
+ } );
+
+ QUnit.test( 'Emitting update event', function ( assert ) {
+ var results = [],
+ model = new mw.echo.dm.FiltersModel();
+
+ // Listen to update event
+ model.on( 'update', function () {
+ results.push( model.getReadState() );
+ } );
+
+ // Trigger events
+ model.setReadState( 'read' ); // [ 'read' ]
+ model.setReadState( 'unread' ); // [ 'read', 'unread' ]
+ model.setReadState( 'unread' ); // (no change, no event) [ 'read', 'unread' ]
+ model.setReadState( 'all' ); // [ 'read', 'unread', 'all' ]
+ model.setReadState( 'foo' ); // (invalid value, no event) [ 'read', 'unread', 'all' ]
+ model.setReadState( 'unread' ); // [ 'read', 'unread', 'all', 'unread' ]
+
+ assert.deepEqual(
+ // Actual
+ results,
+ // Expected:
+ [ 'read', 'unread', 'all', 'unread' ],
+ // Message
+ 'Update events emitted'
+ );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js
new file mode 100644
index 00000000..63c381e8
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js
@@ -0,0 +1,156 @@
+( function ( mw ) {
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.NotificationGroupsList' );
+
+ QUnit.test( 'Constructing the model', function ( assert ) {
+ var model = new mw.echo.dm.NotificationGroupsList();
+
+ assert.equal(
+ model.getTimestamp(),
+ 0,
+ 'Empty group has timestamp 0'
+ );
+ } );
+
+ QUnit.test( 'Managing lists', function ( assert ) {
+ var i, group,
+ model = new mw.echo.dm.NotificationGroupsList(),
+ groupDefinitions = [
+ {
+ name: 'foo',
+ sourceData: {
+ title: 'Foo Wiki',
+ base: 'http://foo.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 0 ),
+ new mw.echo.dm.NotificationItem( 1 ),
+ new mw.echo.dm.NotificationItem( 2 )
+ ]
+ },
+ {
+ name: 'bar',
+ sourceData: {
+ title: 'Bar Wiki',
+ base: 'http://bar.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 3 ),
+ new mw.echo.dm.NotificationItem( 4 ),
+ new mw.echo.dm.NotificationItem( 5 ),
+ new mw.echo.dm.NotificationItem( 6 )
+ ]
+ },
+ {
+ name: 'baz',
+ sourceData: {
+ title: 'Baz Wiki',
+ base: 'http://baz.wiki.sample/$1'
+ },
+ items: [
+ new mw.echo.dm.NotificationItem( 7 )
+ ]
+ }
+ ];
+
+ for ( i = 0; i < groupDefinitions.length; i++ ) {
+ model.addGroup(
+ groupDefinitions[ i ].name,
+ groupDefinitions[ i ].sourceData,
+ groupDefinitions[ i ].items
+ );
+
+ assert.equal(
+ model.getItemCount(),
+ i + 1,
+ 'Group number increases after addGroup ("' + groupDefinitions[ i ].name + '")'
+ );
+
+ group = model.getGroupByName( groupDefinitions[ i ].name );
+ assert.equal(
+ group.getName(),
+ groupDefinitions[ i ].name,
+ 'Group exists after addGroup ("' + groupDefinitions[ i ].name + '")'
+ );
+ }
+
+ // Remove group
+ model.removeGroup( groupDefinitions[ 0 ].name );
+
+ assert.equal(
+ model.getItemCount(),
+ groupDefinitions.length - 1,
+ 'Group number decreased after removeGroup'
+ );
+ assert.equal(
+ model.getGroupByName( groupDefinitions[ 0 ] ),
+ null,
+ 'Removed group is no longer in the list'
+ );
+
+ // Removing the last item from a group should remove the group
+ group = model.getGroupByName( 'baz' );
+ group.discardItems( groupDefinitions[ 2 ].items );
+ assert.equal(
+ model.getGroupByName( 'baz' ),
+ null,
+ 'Empty group is no longer in the list'
+ );
+ } );
+
+ QUnit.test( 'Emitting discard event', function ( assert ) {
+ var group,
+ results = [],
+ model = new mw.echo.dm.NotificationGroupsList(),
+ groups = {
+ first: [
+ new mw.echo.dm.NotificationItem( 0 ),
+ new mw.echo.dm.NotificationItem( 1 ),
+ new mw.echo.dm.NotificationItem( 2 )
+ ],
+ second: [
+ new mw.echo.dm.NotificationItem( 3 ),
+ new mw.echo.dm.NotificationItem( 4 ),
+ new mw.echo.dm.NotificationItem( 5 )
+ ],
+ third: [
+ new mw.echo.dm.NotificationItem( 6 ),
+ new mw.echo.dm.NotificationItem( 7 )
+ ],
+ fourth: [
+ new mw.echo.dm.NotificationItem( 8 ),
+ new mw.echo.dm.NotificationItem( 9 )
+ ]
+ };
+
+ // Listen to the event
+ model
+ .on( 'discard', function ( group ) {
+ results.push( group.getName() );
+ } );
+
+ // Fill the list
+ for ( group in groups ) {
+ model.addGroup( group, {}, groups[ group ] );
+ }
+
+ // Trigger events
+ model.removeGroup( 'first' ); // [ 'first' ]
+ model.removeGroup( 'fourth' ); // [ 'first', 'fourth' ]
+ // Group doesn't exist, no change
+ model.removeGroup( 'first' ); // [ 'first', 'fourth' ]
+ // Discard of an item in a group (no event on the list model)
+ model.getGroupByName( 'third' ).discardItems( groups.third[ 0 ] ); // [ 'first', 'fourth' ]
+ // Discard of the last item in a group (trigger discard event on the list model)
+ model.getGroupByName( 'third' ).discardItems( groups.third[ 1 ] ); // [ 'first', 'fourth', 'third' ]
+
+ assert.deepEqual(
+ // Actual
+ results,
+ // Expected:
+ [ 'first', 'fourth', 'third' ],
+ // Message
+ 'Discard events emitted'
+ );
+ } );
+
+}( mediaWiki ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js
new file mode 100644
index 00000000..f49201e4
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationItem.js
@@ -0,0 +1,146 @@
+( function ( mw, $ ) {
+ var fakeData = {
+ type: 'alert',
+ read: true,
+ seen: true,
+ timestamp: '2016-09-14T23:21:56Z',
+ content: {
+ header: 'Your edit on <strong>Moai</strong> was reverted.',
+ compactHeader: 'Your edit on <strong>Moai</strong> was reverted.',
+ body: 'undo'
+ },
+ iconType: 'revert',
+ primaryUrl: 'http://dev.wiki.local.wmftest.net:8080/w/index.php?title=Moai&oldid=prev&diff=1978&markasread=2126',
+ secondaryUrls: [
+ {
+ url: 'http://dev.wiki.local.wmftest.net:8080/wiki/User:RandomUser',
+ label: 'RandomUser',
+ icon: 'userAvatar'
+ },
+ {
+ url: 'http://dev.wiki.local.wmftest.net:8080/wiki/Talk:Moai',
+ label: 'Moai',
+ tooltip: 'Talk:Moai',
+ icon: 'speechBubbles'
+ }
+ ]
+ },
+ now = 1234567890000,
+ nowFormatted = '2009-02-13T23:31:30Z';
+
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.NotificationItem', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.sandbox.useFakeTimers( now );
+ }
+ } ) );
+
+ QUnit.test( 'Constructing items', function ( assert ) {
+ var i, j, itemModel, checkMethods,
+ defaultValues = {
+ getId: undefined,
+ getContentHeader: '',
+ getContentBody: '',
+ getCategory: '',
+ getType: 'message',
+ isRead: false,
+ isSeen: false,
+ isForeign: false,
+ isBundled: false,
+ getTimestamp: nowFormatted,
+ getPrimaryUrl: undefined,
+ getIconURL: undefined,
+ getIconType: undefined,
+ getSecondaryUrls: [],
+ getModelName: 'local',
+ getAllIds: []
+ },
+ tests = [
+ {
+ msg: 'Empty data',
+ params: { id: 0, config: {} },
+ tests: 'all',
+ expected: $.extend( true, {}, defaultValues, { getId: 0, getAllIds: [ 0 ] } )
+ },
+ {
+ msg: 'Fake data',
+ params: { id: 999, config: fakeData },
+ tests: 'all',
+ expected: $.extend( true, {}, defaultValues, {
+ getId: 999,
+ getAllIds: [ 999 ],
+ getType: 'alert',
+ isRead: true,
+ isSeen: true,
+ getTimestamp: '2016-09-14T23:21:56Z',
+ getContentHeader: 'Your edit on <strong>Moai</strong> was reverted.',
+ getContentBody: 'undo',
+ getIconType: 'revert',
+ getPrimaryUrl: 'http://dev.wiki.local.wmftest.net:8080/w/index.php?title=Moai&oldid=prev&diff=1978&markasread=2126',
+ getSecondaryUrls: [
+ {
+ url: 'http://dev.wiki.local.wmftest.net:8080/wiki/User:RandomUser',
+ label: 'RandomUser',
+ icon: 'userAvatar'
+ },
+ {
+ url: 'http://dev.wiki.local.wmftest.net:8080/wiki/Talk:Moai',
+ label: 'Moai',
+ tooltip: 'Talk:Moai',
+ icon: 'speechBubbles'
+ }
+ ]
+ } )
+ }
+ ];
+
+ for ( i = 0; i < tests.length; i++ ) {
+ itemModel = new mw.echo.dm.NotificationItem( tests[ i ].params.id, tests[ i ].params.config );
+
+ checkMethods = tests[ i ].tests;
+ if ( tests[ i ].tests === 'all' ) {
+ checkMethods = Object.keys( defaultValues );
+ }
+
+ for ( j = 0; j < checkMethods.length; j++ ) {
+ assert.deepEqual(
+ // Run the method
+ itemModel[ checkMethods[ j ] ](),
+ // Expected result
+ tests[ i ].expected[ checkMethods[ j ] ],
+ // Message
+ tests[ i ].msg + ' (' + checkMethods[ j ] + ')'
+ );
+ }
+ }
+ } );
+
+ QUnit.test( 'Emitting update event', function ( assert ) {
+ var results = [],
+ itemModel = new mw.echo.dm.NotificationItem( 0, $.extend( true, {}, fakeData, { seen: false, read: false } ) );
+
+ // Listen to update event
+ itemModel.on( 'update', function () {
+ results.push( [
+ itemModel.isRead(),
+ itemModel.isSeen()
+ ] );
+ } );
+
+ // Trigger events
+ itemModel.toggleSeen( true ); // [ [ false, true ] ]
+ itemModel.toggleSeen( true ); // [ [ false, true ] ] ( No change, event was not emitted )
+ itemModel.toggleRead( true ); // [ [ false, true ], [ true, true ] ]
+ itemModel.toggleRead( true ); // [ [ false, true ], [ true, true ] ] ( No change, event was not emitted )
+ itemModel.toggleRead( false ); // [ [ false, true ], [ true, true ], [ false, true ] ]
+ itemModel.toggleSeen( false ); // [ [ false, true ], [ true, true ], [ false, true ], [ false, false ] ]
+ itemModel.toggleRead( true ); // [ [ false, true ], [ true, true ], [ false, true ], [ false, false ], [ true, false ] ]
+
+ assert.deepEqual(
+ results,
+ // Expected:
+ [ [ false, true ], [ true, true ], [ false, true ], [ false, false ], [ true, false ] ],
+ 'Read and seen changes produced "update" events'
+ );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js
new file mode 100644
index 00000000..107d4fc0
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.NotificationsList.js
@@ -0,0 +1,189 @@
+( function ( mw, $ ) {
+ var defaultValues = {
+ getAllItemIds: [],
+ getAllItemIdsByType: [],
+ getTitle: '',
+ getName: 'local',
+ getSource: 'local',
+ getSourceURL: '',
+ getTimestamp: 0,
+ getCount: 0,
+ hasUnseen: false,
+ isForeign: false
+ };
+
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.NotificationsList' );
+
+ QUnit.test( 'Constructing the model', function ( assert ) {
+ var i, model, method,
+ cases = [
+ {
+ msg: 'Empty config',
+ config: {},
+ expected: defaultValues
+ },
+ {
+ msg: 'Prefilled data',
+ config: {
+ title: 'Some title',
+ name: 'local_demo',
+ source: 'hewiki',
+ sourceURL: 'http://he.wiki.local.wmftest.net:8080/wiki/$1',
+ timestamp: '20160916171300'
+ },
+ expected: $.extend( true, {}, defaultValues, {
+ getTitle: 'Some title',
+ getName: 'local_demo',
+ getSource: 'hewiki',
+ getSourceURL: 'http://he.wiki.local.wmftest.net:8080/wiki/$1',
+ getTimestamp: '20160916171300',
+ isForeign: true
+ } )
+ }
+ ];
+
+ for ( i = 0; i < cases.length; i++ ) {
+ model = new mw.echo.dm.NotificationsList( cases[ i ].config );
+
+ for ( method in cases[ i ].expected ) {
+ assert.deepEqual(
+ // Run the method
+ model[ method ](),
+ // Expected value
+ cases[ i ].expected[ method ],
+ // Message
+ cases[ i ].msg + ' (' + method + ')'
+ );
+ }
+ }
+ } );
+
+ QUnit.test( 'Handling notification items', function ( assert ) {
+ var model = new mw.echo.dm.NotificationsList( { timestamp: '200101010000' } ),
+ items = [
+ new mw.echo.dm.NotificationItem( 0, { type: 'alert', timestamp: '201609190000', read: false, seen: false } ),
+ new mw.echo.dm.NotificationItem( 1, { type: 'message', timestamp: '201609190100', read: false, seen: true } ),
+ new mw.echo.dm.NotificationItem( 2, { type: 'alert', timestamp: '201609190200', read: true, seen: true } ),
+ new mw.echo.dm.NotificationItem( 3, { type: 'message', timestamp: '201609190300', read: true, seen: true } ),
+ new mw.echo.dm.NotificationItem( 4, { type: 'alert', timestamp: '201609190400', read: true, seen: true } ),
+ new mw.echo.dm.NotificationItem( 5, { type: 'message', timestamp: '201609190500', read: true, seen: false } )
+ ];
+
+ assert.equal(
+ model.getCount(),
+ 0,
+ 'Model list starts empty'
+ );
+ assert.equal(
+ model.getTimestamp(),
+ '200101010000',
+ 'Model timestamp is its default'
+ );
+
+ model.setItems( items );
+ assert.equal(
+ model.getCount(),
+ 6,
+ 'Item list setup'
+ );
+ assert.equal(
+ model.getTimestamp(),
+ '201609190100',
+ 'Model timestamp is the latest unread item\'s timestamp'
+ );
+ assert.deepEqual(
+ model.getAllItemIds(),
+ [ 1, 0, 5, 4, 3, 2 ],
+ 'getAllItemIds (sorted)'
+ );
+ assert.deepEqual(
+ [
+ model.getAllItemIdsByType( 'alert' ),
+ model.getAllItemIdsByType( 'message' )
+ ],
+ [
+ [ 0, 4, 2 ],
+ [ 1, 5, 3 ]
+ ],
+ 'getAllItemIdsByType (sorted)'
+ );
+ assert.deepEqual(
+ model.findByIds( [ 1, 2 ] ),
+ [ items[ 1 ], items[ 2 ] ],
+ 'findByIds'
+ );
+
+ // Change item state (trigger resort)
+ items[ 1 ].toggleRead( true );
+ items[ 3 ].toggleRead( false );
+ items[ 5 ].toggleSeen( true ); // Will not affect sorting order of the item
+ assert.deepEqual(
+ model.getAllItemIds(),
+ [ 3, 0, 5, 4, 2, 1 ],
+ 'getAllItemIds (re-sorted)'
+ );
+
+ // Discard items
+ model.discardItems( [ items[ 5 ], items[ 2 ] ] );
+
+ assert.deepEqual(
+ model.getAllItemIds(),
+ [ 3, 0, 4, 1 ],
+ 'getAllItemIds (discarded items)'
+ );
+ assert.deepEqual(
+ [
+ model.getAllItemIdsByType( 'alert' ),
+ model.getAllItemIdsByType( 'message' )
+ ],
+ [
+ [ 0, 4 ],
+ [ 3, 1 ]
+ ],
+ 'getAllItemIdsByType (discarded items)'
+ );
+
+ } );
+
+ QUnit.test( 'Intercepting events', function ( assert ) {
+ var model = new mw.echo.dm.NotificationsList(),
+ result = [],
+ items = [
+ new mw.echo.dm.NotificationItem( 0, { timestamp: '201609190000', read: false, seen: false } ),
+ new mw.echo.dm.NotificationItem( 1, { timestamp: '201609190100', read: false, seen: true } ),
+ new mw.echo.dm.NotificationItem( 2, { timestamp: '201609190200', read: true, seen: true } ),
+ new mw.echo.dm.NotificationItem( 3, { timestamp: '201609190300', read: true, seen: true } ),
+ new mw.echo.dm.NotificationItem( 4, { timestamp: '201609190400', read: true, seen: true } ),
+ new mw.echo.dm.NotificationItem( 5, { timestamp: '201609190500', read: true, seen: true } )
+ ];
+
+ // Listen to events
+ model
+ .on( 'update', function ( items ) {
+ result.push( 'update:' + items.length );
+ } )
+ .on( 'discard', function ( item ) {
+ result.push( 'discard:' + item.getId() );
+ } )
+ .on( 'itemUpdate', function ( item ) {
+ result.push( 'itemUpdate:' + item.getId() );
+ } );
+
+ // Set up and trigger events
+ model
+ .setItems( items ); // [ 'update:6' ]
+ model.discardItems( items[ items.length - 1 ] ); // [ 'update:6', 'discard:5' ]
+ items[ 0 ].toggleSeen( true ); // [ 'update:6', 'discard:5', 'itemUpdate:0' ]
+ items[ 1 ].toggleRead( true ); // [ 'update:6', 'discard:5', 'itemUpdate:0', 'itemUpdate:1' ]
+
+ assert.deepEqual(
+ // Actual
+ result,
+ // Expected:
+ [ 'update:6', 'discard:5', 'itemUpdate:0', 'itemUpdate:1' ],
+ // Message
+ 'Events emitted correctly'
+ );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js b/Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js
new file mode 100644
index 00000000..84b6ca7f
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.PaginationModel.js
@@ -0,0 +1,91 @@
+( function ( mw, $ ) {
+ var defaultValues = {
+ getPageContinue: undefined,
+ getCurrPageIndex: 0,
+ getPrevPageContinue: '',
+ getCurrPageContinue: '',
+ getNextPageContinue: '',
+ hasPrevPage: false,
+ hasNextPage: false,
+ getCurrentPageItemCount: 25,
+ getItemsPerPage: 25
+ };
+
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.PaginationModel' );
+
+ QUnit.test( 'Constructing the model', function ( assert ) {
+ var i, model, method,
+ cases = [
+ {
+ msg: 'Empty config',
+ config: {},
+ expected: defaultValues
+ },
+ {
+ msg: 'Overridng defaults',
+ config: {
+ pageNext: 'continueValNext|123',
+ itemsPerPage: 10
+ },
+ expected: $.extend( true, {}, defaultValues, {
+ getNextPageContinue: 'continueValNext|123',
+ hasNextPage: true,
+ getItemsPerPage: 10,
+ getCurrentPageItemCount: 10
+ } )
+ }
+ ];
+
+ for ( i = 0; i < cases.length; i++ ) {
+ model = new mw.echo.dm.PaginationModel( cases[ i ].config );
+
+ for ( method in cases[ i ].expected ) {
+ assert.deepEqual(
+ // Run the method
+ model[ method ](),
+ // Expected value
+ cases[ i ].expected[ method ],
+ // Message
+ cases[ i ].msg + ' (' + method + ')'
+ );
+ }
+ }
+ } );
+
+ QUnit.test( 'Emitting update event', function ( assert ) {
+ var results = [],
+ model = new mw.echo.dm.PaginationModel();
+
+ // Listen to update event
+ model.on( 'update', function () {
+ results.push( [
+ model.getCurrPageIndex(),
+ model.hasNextPage()
+ ] );
+ } );
+
+ // Trigger events
+
+ // Set up initial pages (first page is 0)
+ model.setPageContinue( 1, 'page2|2' ); // [ [ 0, true ] ]
+ model.setPageContinue( 2, 'page3|3' ); // [ [ 0, true ], [ 0, true ] ]
+ model.setPageContinue( 3, 'page4|4' ); // [ [ 0, true ], [ 0, true ], [ 0, true ] ]
+
+ model.forwards(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ] ]
+ model.forwards(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ] ]
+ model.forwards(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ] ]
+ model.backwards(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ], [ 2, true ] ]
+ model.setCurrentPageItemCount(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ], [ 2, true ], [ 2, true ] ]
+ model.reset(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ], [ 2, true ], [ 2, true ], [ 0, false ] ]
+
+ assert.deepEqual(
+ // Actual
+ results,
+ // Expected:
+ [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ], [ 2, true ], [ 2, true ], [ 0, false ] ],
+ // Message
+ 'Update events emitted'
+ );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js b/Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js
new file mode 100644
index 00000000..6adf1d8d
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js
@@ -0,0 +1,56 @@
+( function ( mw ) {
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.SeenTimeModel' );
+
+ QUnit.test( 'Constructing the model', function ( assert ) {
+ var model = new mw.echo.dm.SeenTimeModel();
+
+ assert.deepEqual(
+ model.getTypes(),
+ [ 'alert', 'message' ],
+ 'Default model has both types'
+ );
+ } );
+
+ QUnit.test( 'Handling seenTime', function ( assert ) {
+ var model;
+
+ model = new mw.echo.dm.SeenTimeModel();
+ model.setSeenTime( '20160101010000' );
+
+ assert.deepEqual(
+ model.getSeenTime(),
+ '20160101010000',
+ 'Model sets seen time for both types'
+ );
+
+ model = new mw.echo.dm.SeenTimeModel( { types: 'alert' } );
+ model.setSeenTime( '20160101010001' );
+
+ assert.deepEqual(
+ model.getSeenTime(),
+ '20160101010001',
+ 'Alerts seen time model returns correct time'
+ );
+ } );
+
+ QUnit.test( 'Emitting update event', function ( assert ) {
+ var results = [],
+ model = new mw.echo.dm.SeenTimeModel();
+
+ // Attach a listener
+ model.on( 'update', function ( time ) {
+ results.push( time );
+ } );
+
+ // Trigger events
+ model.setSeenTime( '1' ); // [ '1' ]
+ model.setSeenTime( '2' ); // [ '1', '2' ]
+ model.setSeenTime( '2' ); // (no change, no event) [ '1', '2' ]
+
+ assert.deepEqual(
+ results,
+ [ '1', '2' ],
+ 'Update event emitted'
+ );
+ } );
+}( mediaWiki ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js b/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js
new file mode 100644
index 00000000..53f9b9de
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js
@@ -0,0 +1,172 @@
+( function ( mw ) {
+ // Mock partial API response we feed into the model
+ var sources = {
+ local: {
+ pages: [
+ {
+ ns: 2,
+ title: 'User:Admin',
+ unprefixed: 'Admin',
+ pages: [
+ 'User:Admin',
+ 'User talk:Admin',
+ null
+ ],
+ count: 24
+ },
+ {
+ ns: 2,
+ title: 'User:RandomUser',
+ unprefixed: 'RandomUser',
+ pages: [
+ 'User:RandomUser',
+ 'User talk:RandomUser'
+ ],
+ count: 6
+ },
+ {
+ ns: 0,
+ title: 'Moai',
+ unprefixed: 'Moai',
+ pages: [
+ 'Moai',
+ 'Talk:Moai'
+ ],
+ count: 3
+ }
+ ],
+ totalCount: 33,
+ source: {
+ title: 'LocalWiki',
+ url: 'http://dev.wiki.local.wmftest.net:8080/w/api.php',
+ base: 'http://dev.wiki.local.wmftest.net:8080/wiki/$1'
+ }
+ },
+ hewiki: {
+ pages: [
+ {
+ ns: 2,
+ title: 'Foo',
+ unprefixed: 'Foo',
+ pages: [
+ 'Foo',
+ 'Talk:Foo',
+ null
+ ],
+ count: 10
+ },
+ {
+ ns: 0,
+ title: 'User:Bar',
+ unprefixed: 'Bar',
+ pages: [
+ 'User:Bar',
+ 'User talk:Bar'
+ ],
+ count: 5
+ }
+ ],
+ totalCount: 15,
+ source: {
+ title: 'Hebrew Wikipedia',
+ url: 'http://he.wiki.local.wmftest.net:8080/w/api.php',
+ base: 'http://he.wiki.local.wmftest.net:8080/wiki/$1'
+ }
+ }
+ };
+
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.SourcePagesModel' );
+
+ QUnit.test( 'Creating source-page map', function ( assert ) {
+ var model = new mw.echo.dm.SourcePagesModel();
+
+ model.setAllSources( sources );
+
+ assert.equal(
+ model.getCurrentSource(),
+ 'local',
+ 'Default source is local'
+ );
+ assert.equal(
+ model.getCurrentPage(),
+ null,
+ 'Default page is null'
+ );
+ assert.deepEqual(
+ model.getSourcesArray(),
+ [ 'local', 'hewiki' ],
+ 'Source array includes all sources'
+ );
+ assert.equal(
+ model.getSourceTitle( 'hewiki' ),
+ 'Hebrew Wikipedia',
+ 'Source title'
+ );
+ assert.equal(
+ model.getSourceTotalCount( 'hewiki' ),
+ 15,
+ 'Source total count'
+ );
+ assert.deepEqual(
+ model.getSourcePages( 'local' ),
+ {
+ Moai: {
+ count: 3,
+ ns: 0,
+ pages: [
+ 'Moai',
+ 'Talk:Moai'
+ ],
+ title: 'Moai',
+ unprefixed: 'Moai'
+ },
+ 'User:Admin': {
+ count: 24,
+ ns: 2,
+ pages: [
+ 'User:Admin',
+ 'User talk:Admin',
+ null
+ ],
+ title: 'User:Admin',
+ unprefixed: 'Admin'
+ },
+ 'User:RandomUser': {
+ count: 6,
+ ns: 2,
+ pages: [
+ 'User:RandomUser',
+ 'User talk:RandomUser'
+ ],
+ title: 'User:RandomUser',
+ unprefixed: 'RandomUser'
+ }
+ },
+ 'Outputting source pages'
+ );
+ assert.deepEqual(
+ model.getGroupedPagesForTitle( 'local', 'User:Admin' ),
+ [
+ 'User:Admin',
+ 'User talk:Admin',
+ null
+ ],
+ 'Grouped pages per title'
+ );
+
+ // Change source
+ model.setCurrentSourcePage( 'hewiki', 'User:Bar' );
+
+ assert.equal(
+ model.getCurrentSource(),
+ 'hewiki',
+ 'Source changed successfully'
+ );
+ assert.equal(
+ model.getCurrentPage(),
+ 'User:Bar',
+ 'Page changed successfully'
+ );
+
+ } );
+}( mediaWiki ) );
diff --git a/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js b/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js
new file mode 100644
index 00000000..8b2662e1
--- /dev/null
+++ b/Echo/tests/qunit/model/test_mw.echo.dm.UnreadNotificationCounter.js
@@ -0,0 +1,85 @@
+( function ( mw ) {
+ QUnit.module( 'ext.echo.dm - mw.echo.dm.UnreadNotificationCounter' );
+
+ QUnit.test( 'Returning capped notifications count', function ( assert ) {
+ var i,
+ model = new mw.echo.dm.UnreadNotificationCounter(
+ null,
+ 'all', // type
+ 10 // max
+ ),
+ cases = [
+ { input: 5, output: 5 },
+ { input: 20, output: 11 },
+ { input: 10, output: 10 }
+ ];
+
+ for ( i = 0; i < cases.length; i++ ) {
+ assert.equal(
+ model.getCappedNotificationCount( cases[ i ].input ),
+ cases[ i ].output,
+ 'Capped notifications count: ' +
+ cases[ i ].input + ' -> ' +
+ cases[ i ].output
+ );
+ }
+ } );
+
+ QUnit.test( 'Estimate change', function ( assert ) {
+ var model = new mw.echo.dm.UnreadNotificationCounter(
+ null,
+ 'all', // type
+ 99 // max
+ );
+ // Set initial
+ model.setCount( 50 );
+
+ model.estimateChange( -10 );
+ assert.equal(
+ model.getCount(),
+ 40, // 50-10
+ 'Estimation within range'
+ );
+
+ model.estimateChange( 70 );
+ assert.equal(
+ model.getCount(),
+ 100, // Estimation reached above cap - cap is set
+ 'Estimation brings count to cap'
+ );
+
+ model.estimateChange( -10 );
+ assert.equal(
+ model.getCount(),
+ 100, // We are already above cap, count will not change
+ 'Estimation while counter is outside of cap - no change'
+ );
+ } );
+
+ QUnit.test( 'Emitting countChange event', function ( assert ) {
+ var results = [],
+ model = new mw.echo.dm.UnreadNotificationCounter(
+ null,
+ 'all', // type
+ 99 // max
+ );
+
+ // Listen to event
+ model.on( 'countChange', function ( count ) {
+ results.push( count );
+ } );
+
+ // Trigger events
+ model.setCount( 50 ); // [ 50 ]
+ model.setCount( 300, true ); // (estimate, above max, bring to cap) [ 50, 100 ]
+ model.setCount( -1, true ); // (estimate while counter is above cap, no event) [ 50, 100 ]
+ model.setCount( 200 ); // (setting above cap, value is capped, same as current, no event) [ 50,100 ]
+ model.setCount( 10 ); // [ 50, 100, 10 ]
+
+ assert.deepEqual(
+ results,
+ [ 50, 100, 10 ],
+ 'countChange events emitted.'
+ );
+ } );
+}( mediaWiki ) );
diff --git a/Echo/tests/qunit/overlay/test_ext.echo.overlay.js b/Echo/tests/qunit/overlay/test_ext.echo.overlay.js
index e4cdd9f5..213ffddd 100644
--- a/Echo/tests/qunit/overlay/test_ext.echo.overlay.js
+++ b/Echo/tests/qunit/overlay/test_ext.echo.overlay.js
@@ -1,12 +1,14 @@
( function ( $, mw ) {
QUnit.module( 'ext.echo.overlay', {
setup: function () {
+ var ApiStub;
+
this.$badge = $( '<a class="mw-echo-notifications-badge mw-echo-unseen-notifications">1</a>' );
this.sandbox.stub( mw.echo, 'getBadge' ).returns( this.$badge );
// Kill any existing overlays to avoid clashing with other tests
$( '.mw-echo-overlay' ).remove();
- var ApiStub = function ( mode, numberUnreadMessages ) {
+ ApiStub = function ( mode, numberUnreadMessages ) {
this.mode = mode;
this.numberUnreadMessages = numberUnreadMessages || 7;
};
@@ -22,7 +24,7 @@
break;
default:
- throw 'Unrecognized post action: ' + data.action;
+ throw new Error( 'Unrecognized post action: ' + data.action );
}
return $.Deferred().resolve( data );
@@ -62,7 +64,7 @@
for ( i = 0; i < 7; i++ ) {
id = 500 + i;
index.push( id );
- listObj[id] = {
+ listObj[ id ] = {
'*': '!',
category: 'message',
id: id,
diff --git a/Echo/tests/qunit/viewmodel/test_mw.echo.dm.NotificationsModel.js b/Echo/tests/qunit/viewmodel/test_mw.echo.dm.NotificationsModel.js
deleted file mode 100644
index 8a30deff..00000000
--- a/Echo/tests/qunit/viewmodel/test_mw.echo.dm.NotificationsModel.js
+++ /dev/null
@@ -1,164 +0,0 @@
-( function ( mw ) {
- QUnit.module( 'ext.echo.dm mw.echo.dm.NotificationsModel' );
-
- function runPreparation( model, testPrepare ) {
- var j, jlen;
-
- for ( j = 0, jlen = testPrepare.length; j < jlen; j++ ) {
- model[ testPrepare[j].method ].apply( model, testPrepare[j].params );
- }
- }
-
- QUnit.test( 'Adding notifications', function ( assert ) {
- var i, ilen, model, actual, test,
- cases = [
- {
- prepare: [
- {
- method: 'addItems',
- params: [
- [
- new mw.echo.dm.NotificationItem( 1, { content: '1', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 2, { content: '2', timestamp: '20150828172900' } )
- ]
- ]
- }
- ],
- run: {
- method: 'getItemCount'
- },
- expect: 2,
- message: 'Adding items'
- },
- {
- prepare: [
- {
- method: 'addItems',
- params: [
- [
- new mw.echo.dm.NotificationItem( 1, { content: '1', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 2, { content: '2', timestamp: '20150828172900' } )
- // TODO: This should actually work, but due to a bug in List, the 'don't add items twice'
- // only works when we explicitly request to add the item a separate second time.
- // This should be fixed in List and upstreamed to OOUI GroupElement which is where
- // it came from.
- // new mw.echo.dm.NotificationItem( 1, { content: '1', timestamp: '20150828172900' } )
- ]
- ]
- },
- {
- method: 'addItems',
- params: [
- [
- new mw.echo.dm.NotificationItem( 1, { content: '1', timestamp: '20150828172900' } )
- ]
- ]
- }
- ],
- run: {
- method: 'getItemCount'
- },
- expect: 2,
- message: 'Do not re-add items with existing ids'
- }
- ];
-
- assert.expect( cases.length );
-
- for ( i = 0, ilen = cases.length; i < ilen; i++ ) {
- model = new mw.echo.dm.NotificationsModel( {
- type: 'alert',
- limit: 25,
- userLang: 'en'
- } );
-
- test = cases[i];
-
- // Run preparation
- runPreparation( model, test.prepare );
-
- // Test
- actual = model[ test.run.method ].apply( model, cases[i].run.params );
- assert.equal( actual, cases[i].expect, cases[i].message );
- }
- } );
-
- QUnit.test( 'Deleting notifications', 2, function ( assert ) {
- var model = new mw.echo.dm.NotificationsModel( {
- type: 'alert',
- limit: 25,
- userLang: 'en'
- } ),
- items = [
- new mw.echo.dm.NotificationItem( 1, { content: '1', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 2, { content: '2', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 3, { content: '3', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 4, { content: '4', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 5, { content: '5', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 6, { content: '6', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 7, { content: '7', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 8, { content: '8', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 9, { content: '9', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 10, { content: '10', timestamp: '20150828172900' } )
- ];
-
- // Add initial notifications
- model.addItems( items );
-
- // Verify we have the correct number initially
- assert.equal( model.getItemCount(), 10, 'Added initial number of notifications' );
-
- // Remove notifications
- model.removeItems( [ items[0], items[1], items[5] ] );
-
- // Test
- assert.equal( model.getItemCount(), 7, 'Successfully deleted notifications' );
- } );
-
- QUnit.test( 'Clearing notifications', function ( assert ) {
- var i, ilen, model, actual, test,
- cases = [
- {
- prepare: [
- {
- method: 'addItems',
- params: [
- [
- new mw.echo.dm.NotificationItem( 1, { content: '1', timestamp: '20150828172900' } ),
- new mw.echo.dm.NotificationItem( 2, { content: '2', timestamp: '20150828172900' } )
- ]
- ]
- },
- {
- method: 'clearItems'
- }
- ],
- run: {
- method: 'getItemCount'
- },
- expect: 0,
- message: 'Clearing notifications'
- }
- ];
-
- assert.expect( cases.length );
-
- for ( i = 0, ilen = cases.length; i < ilen; i++ ) {
- model = new mw.echo.dm.NotificationsModel( {
- type: 'alert',
- limit: 25,
- userLang: 'en'
- } );
-
- test = cases[i];
-
- // Run preparation
- runPreparation( model, test.prepare );
-
- // Test
- actual = model[ test.run.method ].apply( model, cases[i].run.params );
- assert.equal( actual, cases[i].expect, cases[i].message );
- }
- } );
-
-} )( mediaWiki );
diff --git a/Echo/tests/rspec/README.md b/Echo/tests/rspec/README.md
new file mode 100644
index 00000000..5cf77fbf
--- /dev/null
+++ b/Echo/tests/rspec/README.md
@@ -0,0 +1,7 @@
+# Usage
+
+ vagrant up
+ vagrant roles enable echo flow wikimediaflow
+ vagrant provision
+ bundle install
+ bundle exec rake spec
diff --git a/Echo/tests/rspec/notification_spec.rb b/Echo/tests/rspec/notification_spec.rb
new file mode 100644
index 00000000..ff4b9a63
--- /dev/null
+++ b/Echo/tests/rspec/notification_spec.rb
@@ -0,0 +1,55 @@
+require 'mediawiki_api'
+
+describe 'Echo' do
+ before(:all) do
+ if ENV['JENKINS_HOME']
+ # jenkins
+ @mediawiki_api = "#{ENV['MW_SERVER']}#{ENV['MW_SCRIPT_PATH']}/api.php"
+ @admin_username = 'WikiAdmin'
+ @admin_password = 'testpass'
+ else
+ # mediawiki-vagrant
+ @mediawiki_api = 'http://127.0.0.1:8080/w/api.php'
+ @admin_username = 'Admin'
+ @admin_password = 'vagrant'
+ end
+
+ @client = MediawikiApi::Client.new @mediawiki_api
+ end
+
+ before(:each) do
+ @client.log_in @admin_username, @admin_password
+
+ require 'securerandom'
+ @random_username = "U#{SecureRandom.hex(5)}"
+ @random_password = SecureRandom.hex(5)
+ end
+
+ it 'should notify a new user with welcome message' do
+ @client.create_account(@random_username, @random_password)
+
+ @client.log_in @random_username, @random_password
+ notifications = @client.query(meta: 'notifications').data['notifications']['list']
+
+ welcome_notification = notifications.first
+ expect(welcome_notification['type']).to eq 'welcome'
+ expect(welcome_notification['agent']['name']).to eq @random_username
+ expect(welcome_notification['timestamp']['date']).to eq 'Today'
+ end
+
+ it 'should notify user about mention on wikitext page' do
+ @client.create_account(@random_username, @random_password)
+
+ page = SecureRandom.hex(5).capitalize
+ @client.edit(title: page, text: "[[User:#{@random_username}]] ~~~~")
+
+ @client.log_in @random_username, @random_password
+ notifications = @client.query(meta: 'notifications').data['notifications']['list']
+
+ mention_notification = notifications.last
+ expect(mention_notification['type']).to eq 'mention'
+ expect(mention_notification['agent']['name']).to eq @admin_username
+ expect(mention_notification['title']['full']).to eq page
+ end
+
+end
diff --git a/Echo/vendor/autoload.php b/Echo/vendor/autoload.php
deleted file mode 100644
index ef448cb6..00000000
--- a/Echo/vendor/autoload.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-
-// autoload.php @generated by Composer
-
-require_once __DIR__ . '/composer' . '/autoload_real.php';
-
-return ComposerAutoloaderInit3acc14d05c751a237c597c5fc1976051::getLoader();
diff --git a/Echo/vendor/bin/parallel-lint b/Echo/vendor/bin/parallel-lint
deleted file mode 120000
index 902305e2..00000000
--- a/Echo/vendor/bin/parallel-lint
+++ /dev/null
@@ -1 +0,0 @@
-../jakub-onderka/php-parallel-lint/parallel-lint \ No newline at end of file
diff --git a/Echo/vendor/composer/ClassLoader.php b/Echo/vendor/composer/ClassLoader.php
deleted file mode 100644
index 5e1469e8..00000000
--- a/Echo/vendor/composer/ClassLoader.php
+++ /dev/null
@@ -1,413 +0,0 @@
-<?php
-
-/*
- * This file is part of Composer.
- *
- * (c) Nils Adermann <naderman@naderman.de>
- * Jordi Boggiano <j.boggiano@seld.be>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Composer\Autoload;
-
-/**
- * ClassLoader implements a PSR-0 class loader
- *
- * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
- *
- * $loader = new \Composer\Autoload\ClassLoader();
- *
- * // register classes with namespaces
- * $loader->add('Symfony\Component', __DIR__.'/component');
- * $loader->add('Symfony', __DIR__.'/framework');
- *
- * // activate the autoloader
- * $loader->register();
- *
- * // to enable searching the include path (eg. for PEAR packages)
- * $loader->setUseIncludePath(true);
- *
- * In this example, if you try to use a class in the Symfony\Component
- * namespace or one of its children (Symfony\Component\Console for instance),
- * the autoloader will first look for the class under the component/
- * directory, and it will then fallback to the framework/ directory if not
- * found before giving up.
- *
- * This class is loosely based on the Symfony UniversalClassLoader.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- * @author Jordi Boggiano <j.boggiano@seld.be>
- */
-class ClassLoader
-{
- // PSR-4
- private $prefixLengthsPsr4 = array();
- private $prefixDirsPsr4 = array();
- private $fallbackDirsPsr4 = array();
-
- // PSR-0
- private $prefixesPsr0 = array();
- private $fallbackDirsPsr0 = array();
-
- private $useIncludePath = false;
- private $classMap = array();
-
- private $classMapAuthoritative = false;
-
- public function getPrefixes()
- {
- if (!empty($this->prefixesPsr0)) {
- return call_user_func_array('array_merge', $this->prefixesPsr0);
- }
-
- return array();
- }
-
- public function getPrefixesPsr4()
- {
- return $this->prefixDirsPsr4;
- }
-
- public function getFallbackDirs()
- {
- return $this->fallbackDirsPsr0;
- }
-
- public function getFallbackDirsPsr4()
- {
- return $this->fallbackDirsPsr4;
- }
-
- public function getClassMap()
- {
- return $this->classMap;
- }
-
- /**
- * @param array $classMap Class to filename map
- */
- public function addClassMap(array $classMap)
- {
- if ($this->classMap) {
- $this->classMap = array_merge($this->classMap, $classMap);
- } else {
- $this->classMap = $classMap;
- }
- }
-
- /**
- * Registers a set of PSR-0 directories for a given prefix, either
- * appending or prepending to the ones previously set for this prefix.
- *
- * @param string $prefix The prefix
- * @param array|string $paths The PSR-0 root directories
- * @param bool $prepend Whether to prepend the directories
- */
- public function add($prefix, $paths, $prepend = false)
- {
- if (!$prefix) {
- if ($prepend) {
- $this->fallbackDirsPsr0 = array_merge(
- (array) $paths,
- $this->fallbackDirsPsr0
- );
- } else {
- $this->fallbackDirsPsr0 = array_merge(
- $this->fallbackDirsPsr0,
- (array) $paths
- );
- }
-
- return;
- }
-
- $first = $prefix[0];
- if (!isset($this->prefixesPsr0[$first][$prefix])) {
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
-
- return;
- }
- if ($prepend) {
- $this->prefixesPsr0[$first][$prefix] = array_merge(
- (array) $paths,
- $this->prefixesPsr0[$first][$prefix]
- );
- } else {
- $this->prefixesPsr0[$first][$prefix] = array_merge(
- $this->prefixesPsr0[$first][$prefix],
- (array) $paths
- );
- }
- }
-
- /**
- * Registers a set of PSR-4 directories for a given namespace, either
- * appending or prepending to the ones previously set for this namespace.
- *
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param array|string $paths The PSR-0 base directories
- * @param bool $prepend Whether to prepend the directories
- *
- * @throws \InvalidArgumentException
- */
- public function addPsr4($prefix, $paths, $prepend = false)
- {
- if (!$prefix) {
- // Register directories for the root namespace.
- if ($prepend) {
- $this->fallbackDirsPsr4 = array_merge(
- (array) $paths,
- $this->fallbackDirsPsr4
- );
- } else {
- $this->fallbackDirsPsr4 = array_merge(
- $this->fallbackDirsPsr4,
- (array) $paths
- );
- }
- } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
- // Register directories for a new namespace.
- $length = strlen($prefix);
- if ('\\' !== $prefix[$length - 1]) {
- throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
- }
- $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
- } elseif ($prepend) {
- // Prepend directories for an already registered namespace.
- $this->prefixDirsPsr4[$prefix] = array_merge(
- (array) $paths,
- $this->prefixDirsPsr4[$prefix]
- );
- } else {
- // Append directories for an already registered namespace.
- $this->prefixDirsPsr4[$prefix] = array_merge(
- $this->prefixDirsPsr4[$prefix],
- (array) $paths
- );
- }
- }
-
- /**
- * Registers a set of PSR-0 directories for a given prefix,
- * replacing any others previously set for this prefix.
- *
- * @param string $prefix The prefix
- * @param array|string $paths The PSR-0 base directories
- */
- public function set($prefix, $paths)
- {
- if (!$prefix) {
- $this->fallbackDirsPsr0 = (array) $paths;
- } else {
- $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
- }
- }
-
- /**
- * Registers a set of PSR-4 directories for a given namespace,
- * replacing any others previously set for this namespace.
- *
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param array|string $paths The PSR-4 base directories
- *
- * @throws \InvalidArgumentException
- */
- public function setPsr4($prefix, $paths)
- {
- if (!$prefix) {
- $this->fallbackDirsPsr4 = (array) $paths;
- } else {
- $length = strlen($prefix);
- if ('\\' !== $prefix[$length - 1]) {
- throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
- }
- $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
- }
- }
-
- /**
- * Turns on searching the include path for class files.
- *
- * @param bool $useIncludePath
- */
- public function setUseIncludePath($useIncludePath)
- {
- $this->useIncludePath = $useIncludePath;
- }
-
- /**
- * Can be used to check if the autoloader uses the include path to check
- * for classes.
- *
- * @return bool
- */
- public function getUseIncludePath()
- {
- return $this->useIncludePath;
- }
-
- /**
- * Turns off searching the prefix and fallback directories for classes
- * that have not been registered with the class map.
- *
- * @param bool $classMapAuthoritative
- */
- public function setClassMapAuthoritative($classMapAuthoritative)
- {
- $this->classMapAuthoritative = $classMapAuthoritative;
- }
-
- /**
- * Should class lookup fail if not found in the current class map?
- *
- * @return bool
- */
- public function isClassMapAuthoritative()
- {
- return $this->classMapAuthoritative;
- }
-
- /**
- * Registers this instance as an autoloader.
- *
- * @param bool $prepend Whether to prepend the autoloader or not
- */
- public function register($prepend = false)
- {
- spl_autoload_register(array($this, 'loadClass'), true, $prepend);
- }
-
- /**
- * Unregisters this instance as an autoloader.
- */
- public function unregister()
- {
- spl_autoload_unregister(array($this, 'loadClass'));
- }
-
- /**
- * Loads the given class or interface.
- *
- * @param string $class The name of the class
- * @return bool|null True if loaded, null otherwise
- */
- public function loadClass($class)
- {
- if ($file = $this->findFile($class)) {
- includeFile($file);
-
- return true;
- }
- }
-
- /**
- * Finds the path to the file where the class is defined.
- *
- * @param string $class The name of the class
- *
- * @return string|false The path if found, false otherwise
- */
- public function findFile($class)
- {
- // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
- if ('\\' == $class[0]) {
- $class = substr($class, 1);
- }
-
- // class map lookup
- if (isset($this->classMap[$class])) {
- return $this->classMap[$class];
- }
- if ($this->classMapAuthoritative) {
- return false;
- }
-
- $file = $this->findFileWithExtension($class, '.php');
-
- // Search for Hack files if we are running on HHVM
- if ($file === null && defined('HHVM_VERSION')) {
- $file = $this->findFileWithExtension($class, '.hh');
- }
-
- if ($file === null) {
- // Remember that this class does not exist.
- return $this->classMap[$class] = false;
- }
-
- return $file;
- }
-
- private function findFileWithExtension($class, $ext)
- {
- // PSR-4 lookup
- $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
-
- $first = $class[0];
- if (isset($this->prefixLengthsPsr4[$first])) {
- foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
- if (0 === strpos($class, $prefix)) {
- foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
- return $file;
- }
- }
- }
- }
- }
-
- // PSR-4 fallback dirs
- foreach ($this->fallbackDirsPsr4 as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
- return $file;
- }
- }
-
- // PSR-0 lookup
- if (false !== $pos = strrpos($class, '\\')) {
- // namespaced class name
- $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
- . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
- } else {
- // PEAR-like class name
- $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
- }
-
- if (isset($this->prefixesPsr0[$first])) {
- foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
- if (0 === strpos($class, $prefix)) {
- foreach ($dirs as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
- return $file;
- }
- }
- }
- }
- }
-
- // PSR-0 fallback dirs
- foreach ($this->fallbackDirsPsr0 as $dir) {
- if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
- return $file;
- }
- }
-
- // PSR-0 include paths.
- if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
- return $file;
- }
- }
-}
-
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- */
-function includeFile($file)
-{
- include $file;
-}
diff --git a/Echo/vendor/composer/autoload_classmap.php b/Echo/vendor/composer/autoload_classmap.php
deleted file mode 100644
index 7ec65e63..00000000
--- a/Echo/vendor/composer/autoload_classmap.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-// autoload_classmap.php @generated by Composer
-
-$vendorDir = dirname(dirname(__FILE__));
-$baseDir = dirname($vendorDir);
-
-return array(
- 'ExampleClass' => $vendorDir . '/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/class.php',
- 'ExampleTrait' => $vendorDir . '/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/trait.php',
- 'JakubOnderka\\PhpParallelLint\\ArrayIterator' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Settings.php',
- 'JakubOnderka\\PhpParallelLint\\Blame' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Error.php',
- 'JakubOnderka\\PhpParallelLint\\ConsoleWriter' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JakubOnderka\\PhpParallelLint\\Error' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Error.php',
- 'JakubOnderka\\PhpParallelLint\\ErrorFormatter' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/ErrorFormatter.php',
- 'JakubOnderka\\PhpParallelLint\\Exception' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/exceptions.php',
- 'JakubOnderka\\PhpParallelLint\\FileWriter' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JakubOnderka\\PhpParallelLint\\IWriter' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JakubOnderka\\PhpParallelLint\\InvalidArgumentException' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/exceptions.php',
- 'JakubOnderka\\PhpParallelLint\\JsonOutput' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JakubOnderka\\PhpParallelLint\\Manager' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Manager.php',
- 'JakubOnderka\\PhpParallelLint\\MultipleWriter' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JakubOnderka\\PhpParallelLint\\NotExistsPathException' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/exceptions.php',
- 'JakubOnderka\\PhpParallelLint\\NullWriter' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JakubOnderka\\PhpParallelLint\\Output' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JakubOnderka\\PhpParallelLint\\ParallelLint' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/ParallelLint.php',
- 'JakubOnderka\\PhpParallelLint\\Process\\GitBlameProcess' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Process/GitBlameProcess.php',
- 'JakubOnderka\\PhpParallelLint\\Process\\LintProcess' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Process/LintProcess.php',
- 'JakubOnderka\\PhpParallelLint\\Process\\PhpExecutable' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Process/PhpExecutable.php',
- 'JakubOnderka\\PhpParallelLint\\Process\\PhpProcess' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Process/PhpProcess.php',
- 'JakubOnderka\\PhpParallelLint\\Process\\Process' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Process/Process.php',
- 'JakubOnderka\\PhpParallelLint\\Process\\SkipLintProcess' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Process/SkipLintProcess.php',
- 'JakubOnderka\\PhpParallelLint\\RecursiveDirectoryFilterIterator' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Manager.php',
- 'JakubOnderka\\PhpParallelLint\\Result' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Result.php',
- 'JakubOnderka\\PhpParallelLint\\RunTimeException' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/exceptions.php',
- 'JakubOnderka\\PhpParallelLint\\Settings' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Settings.php',
- 'JakubOnderka\\PhpParallelLint\\SyntaxError' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Error.php',
- 'JakubOnderka\\PhpParallelLint\\TextOutput' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JakubOnderka\\PhpParallelLint\\TextOutputColored' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/Output.php',
- 'JsonSerializable' => $vendorDir . '/jakub-onderka/php-parallel-lint/src/JsonSerializable.php',
-);
diff --git a/Echo/vendor/composer/autoload_namespaces.php b/Echo/vendor/composer/autoload_namespaces.php
deleted file mode 100644
index b7fc0125..00000000
--- a/Echo/vendor/composer/autoload_namespaces.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-
-// autoload_namespaces.php @generated by Composer
-
-$vendorDir = dirname(dirname(__FILE__));
-$baseDir = dirname($vendorDir);
-
-return array(
-);
diff --git a/Echo/vendor/composer/autoload_psr4.php b/Echo/vendor/composer/autoload_psr4.php
deleted file mode 100644
index b265c64a..00000000
--- a/Echo/vendor/composer/autoload_psr4.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-
-// autoload_psr4.php @generated by Composer
-
-$vendorDir = dirname(dirname(__FILE__));
-$baseDir = dirname($vendorDir);
-
-return array(
-);
diff --git a/Echo/vendor/composer/autoload_real.php b/Echo/vendor/composer/autoload_real.php
deleted file mode 100644
index 2c3a25f7..00000000
--- a/Echo/vendor/composer/autoload_real.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-// autoload_real.php @generated by Composer
-
-class ComposerAutoloaderInit3acc14d05c751a237c597c5fc1976051
-{
- private static $loader;
-
- public static function loadClassLoader($class)
- {
- if ('Composer\Autoload\ClassLoader' === $class) {
- require __DIR__ . '/ClassLoader.php';
- }
- }
-
- public static function getLoader()
- {
- if (null !== self::$loader) {
- return self::$loader;
- }
-
- spl_autoload_register(array('ComposerAutoloaderInit3acc14d05c751a237c597c5fc1976051', 'loadClassLoader'), true, true);
- self::$loader = $loader = new \Composer\Autoload\ClassLoader();
- spl_autoload_unregister(array('ComposerAutoloaderInit3acc14d05c751a237c597c5fc1976051', 'loadClassLoader'));
-
- $map = require __DIR__ . '/autoload_namespaces.php';
- foreach ($map as $namespace => $path) {
- $loader->set($namespace, $path);
- }
-
- $map = require __DIR__ . '/autoload_psr4.php';
- foreach ($map as $namespace => $path) {
- $loader->setPsr4($namespace, $path);
- }
-
- $classMap = require __DIR__ . '/autoload_classmap.php';
- if ($classMap) {
- $loader->addClassMap($classMap);
- }
-
- $loader->register(true);
-
- return $loader;
- }
-}
-
-function composerRequire3acc14d05c751a237c597c5fc1976051($file)
-{
- require $file;
-}
diff --git a/Echo/vendor/composer/installed.json b/Echo/vendor/composer/installed.json
deleted file mode 100644
index 92f131a9..00000000
--- a/Echo/vendor/composer/installed.json
+++ /dev/null
@@ -1,51 +0,0 @@
-[
- {
- "name": "jakub-onderka/php-parallel-lint",
- "version": "v0.9",
- "version_normalized": "0.9.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git",
- "reference": "1b693fb455201cacf595163c92bfb1adfa2158d8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/1b693fb455201cacf595163c92bfb1adfa2158d8",
- "reference": "1b693fb455201cacf595163c92bfb1adfa2158d8",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "jakub-onderka/php-console-highlighter": "~0.3",
- "nette/tester": "~1.3"
- },
- "suggest": {
- "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet"
- },
- "time": "2015-06-16 10:17:07",
- "bin": [
- "parallel-lint"
- ],
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "classmap": [
- "./"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD"
- ],
- "authors": [
- {
- "name": "Jakub Onderka",
- "email": "jakub.onderka@gmail.com"
- }
- ],
- "description": "This tool check syntax of PHP files about 20x faster than serial check.",
- "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint"
- }
-]
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/.gitignore b/Echo/vendor/jakub-onderka/php-parallel-lint/.gitignore
deleted file mode 100644
index 8b7ef350..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/vendor
-composer.lock
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/.travis.yml b/Echo/vendor/jakub-onderka/php-parallel-lint/.travis.yml
deleted file mode 100644
index d5855272..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/.travis.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-language: php
-
-php:
- - 5.3.3
- - 5.4
- - 5.5
- - 5.6
- - 7.0
- - hhvm
-
-matrix:
- allow_failures:
- - php: 7.0
-
-before_script:
- - composer self-update
- - composer install --no-interaction --prefer-source --dev
- - composer require jakub-onderka/php-console-highlighter 0.3
-
-script:
- - ./vendor/bin/tester -p php tests
- - ./parallel-lint --exclude vendor --exclude tests/examples --no-colors .
- - ./parallel-lint --exclude vendor --exclude tests/examples .
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/LICENSE b/Echo/vendor/jakub-onderka/php-parallel-lint/LICENSE
deleted file mode 100644
index 09429bbf..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2012, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/README.md b/Echo/vendor/jakub-onderka/php-parallel-lint/README.md
deleted file mode 100644
index ce57ab16..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/README.md
+++ /dev/null
@@ -1,70 +0,0 @@
-PHP Parallel Lint
-=================
-
-This tool check syntax of PHP files faster then serial check with fancier output.
-
-Running parallel jobs in PHP inspired by Nette framework tests.
-
-![Alt text](/tests/examples/example-images/use-success.png?raw=true "Example use of tool")
-
-Install
--------
-
-Just create a `composer.json` file and run the `php composer.phar install` command to install it:
-
-```json
-{
- "require-dev": {
- "jakub-onderka/php-parallel-lint": "0.*"
- }
-}
-```
-
-For colored output install suggested package `jakub-onderka/php-console-highlighter`. After a `composer.json` file include:
-
-```json
-{
- "require-dev": {
- "jakub-onderka/php-parallel-lint": "0.*",
- "jakub-onderka/php-console-highlighter": "0.*"
- }
-}
-```
-
-Example output
---------------
-
-![Alt text](/tests/examples/example-images/use-error.png?raw=true "Example use of tool with error")
-
-Recommended setting for usage with Symfony framework
---------------
-
-For run from command line:
-
-```
-$ ./bin/parallel-lint --exclude app --exclude vendor .
-```
-
-or setting for ANT:
-
-```xml
-<condition property="parallel-lint" value="${basedir}/bin/parallel-lint.bat" else="${basedir}/bin/parallel-lint">
- <os family="windows"/>
-</condition>
-
-<target name="parallel-lint" description="Run PHP parallel lint">
- <exec executable="${parallel-lint}" failonerror="true">
- <arg line="--exclude" />
- <arg path="${basedir}/app/" />
- <arg line="--exclude" />
- <arg path="${basedir}/vendor/" />
- <arg path="${basedir}" />
- </exec>
-</target>
-```
-
-------
-
-[![Downloads this Month](https://img.shields.io/packagist/dm/jakub-onderka/php-parallel-lint.svg)](https://packagist.org/packages/jakub-onderka/php-parallel-lint)
-[![Build Status](https://travis-ci.org/JakubOnderka/PHP-Parallel-Lint.svg?branch=master)](https://travis-ci.org/JakubOnderka/PHP-Parallel-Lint)
-[![License](https://poser.pugx.org/jakub-onderka/php-parallel-lint/license.svg)](https://packagist.org/packages/jakub-onderka/php-parallel-lint)
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/bin/skip-linting.php b/Echo/vendor/jakub-onderka/php-parallel-lint/bin/skip-linting.php
deleted file mode 100644
index f8f997b4..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/bin/skip-linting.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-$stdin = fopen('php://stdin', 'r');
-$input = stream_get_contents($stdin);
-fclose($stdin);
-
-foreach (explode("\n", $input) as $file) {
- $skip = false;
- $f = @fopen($file, 'r');
- if ($f) {
- $firstLine = fgets($f);
- @fclose($f);
-
- if (!preg_match('~<?php\\s*\\/\\/\s*lint\s*([^\d\s]+)\s*([^\s]+)\s*~i', $firstLine, $m)) {
- $skip = false;
- }
-
- $skip = isset($m[2]) && !version_compare(PHP_VERSION, $m[2], $m[1]);
- }
-
- echo "$file;" . ($skip ? '1' : '0') . "\n";
-}
-
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/composer.json b/Echo/vendor/jakub-onderka/php-parallel-lint/composer.json
deleted file mode 100644
index a05e2b24..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/composer.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "jakub-onderka/php-parallel-lint",
- "description": "This tool check syntax of PHP files about 20x faster than serial check.",
- "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint",
- "license": "BSD",
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "nette/tester": "~1.3",
- "jakub-onderka/php-console-highlighter": "~0.3"
- },
- "suggest": {
- "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet"
- },
- "authors": [
- {
- "name": "Jakub Onderka",
- "email": "jakub.onderka@gmail.com"
- }
- ],
- "autoload": {
- "classmap": [
- "./"
- ]
- },
- "bin": ["parallel-lint"]
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/parallel-lint b/Echo/vendor/jakub-onderka/php-parallel-lint/parallel-lint
deleted file mode 100755
index cb320718..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/parallel-lint
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env php
-<?php
-
-require __DIR__ . '/parallel-lint.php';
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/parallel-lint.php b/Echo/vendor/jakub-onderka/php-parallel-lint/parallel-lint.php
deleted file mode 100644
index 999b25c8..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/parallel-lint.php
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-use JakubOnderka\PhpParallelLint;
-
-if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50303) {
- echo "PHP Parallel Lint require PHP 5.3.3 or newer.\n";
- die(255);
-}
-const SUCCESS = 0,
- WITH_ERRORS = 1,
- FAILED = 255;
-
-function showOptions()
-{
-?>
-Options:
- -p <php> Specify PHP-CGI executable to run (default: 'php').
- -s, --short Set short_open_tag to On (default: Off).
- -a, -asp Set asp_tags to On (default: Off).
- -e <ext> Check only files with selected extensions separated by comma.
- (default: php,php3,php4,php5,phtml)
- --exclude Exclude directory. If you want exclude multiple directories, use
- multiple exclude parameters.
- -j <num> Run <num> jobs in parallel (default: 10).
- --no-colors Disable colors in console output.
- --json Output results as JSON string (require PHP 5.4).
- --blame Try to show git blame for row with error.
- --git <git> Path to Git executable to show blame message (default: 'git').
- --stdin Load files and folder to test from standard input.
- --ignore-fails Ignore failed tests.
- -h, --help Print this help.
-<?php
-}
-
-function showUsage()
-{
- ?>
-PHP Parallel Lint version 0.9
------------------------------
-Usage:
- parallel-lint [sa] [-p php] [-e ext] [-j num] [--exclude dir] [files or directories]
-
-<?php
-showOptions();
-die();
-}
-
-if (in_array('-h', $_SERVER['argv']) || in_array('--help', $_SERVER['argv'])) {
- showUsage();
-}
-
-$files = array(
- __DIR__ . '/../../autoload.php',
- __DIR__ . '/vendor/autoload.php'
-);
-
-$autoloadFileFound = false;
-foreach ($files as $file) {
- if (file_exists($file)) {
- require $file;
- $autoloadFileFound = true;
- break;
- }
-}
-
-if (!$autoloadFileFound) {
- echo 'You need to set up the project dependencies using the following commands:' . PHP_EOL .
- 'curl -s http://getcomposer.org/installer | php' . PHP_EOL .
- 'php composer.phar install' . PHP_EOL;
- die(FAILED);
-}
-
-try {
- $settings = PhpParallelLint\Settings::parseArguments($_SERVER['argv']);
-
- if ($settings->json && PHP_VERSION_ID < 50400) {
- throw new \Exception('JSON output require PHP version 5.4 and newer.');
- }
-
- if ($settings->stdin) {
- $settings->addPaths(PhpParallelLint\Settings::getPathsFromStdIn());
- }
-
- if (empty($settings->paths)) {
- showUsage();
- }
-
- $manager = new PhpParallelLint\Manager;
- $result = $manager->run($settings);
-
- if ($settings->ignoreFails) {
- die($result->hasSyntaxError() ? WITH_ERRORS : SUCCESS);
- } else {
- die($result->hasError() ? WITH_ERRORS : SUCCESS);
- }
-
-} catch (PhpParallelLint\InvalidArgumentException $e) {
- echo "Invalid option {$e->getArgument()}" . PHP_EOL . PHP_EOL;
- showOptions();
- die(FAILED);
-
-} catch (PhpParallelLint\Exception $e) {
- if ($settings->json) {
- echo json_encode($e);
- } else {
- echo $e->getMessage(), PHP_EOL;
- }
- die(FAILED);
-
-} catch (Exception $e) {
- echo $e->getMessage(), PHP_EOL;
- die(FAILED);
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/phpcs-ruleset.xml b/Echo/vendor/jakub-onderka/php-parallel-lint/phpcs-ruleset.xml
deleted file mode 100644
index 3aa686e8..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/phpcs-ruleset.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0"?>
-<ruleset name="PHP-Parallel-Lint">
- <description>PHP Parallel Lint coding standard.</description>
-
- <rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
- <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
- <rule ref="PEAR.Functions.FunctionDeclaration"/>
- <rule ref="PEAR.Functions.FunctionCallSignature"/>
- <rule ref="PEAR.Functions.FunctionCallSignature.Indent">
- <severity>0</severity>
- </rule>
- <rule ref="PEAR.Functions.FunctionCallSignature.CloseBracketLine">
- <severity>0</severity>
- </rule>
- <rule ref="PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket">
- <severity>0</severity>
- </rule>
- <rule ref="PEAR.Functions.ValidDefaultValue"/>
- <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
-
- <rule ref="Generic.PHP.DisallowShortOpenTag"/>
- <rule ref="Generic.PHP.LowerCaseConstant"/>
- <rule ref="Generic.PHP.NoSilencedErrors"/>
- <rule ref="Squiz.PHP.GlobalKeyword"/>
- <rule ref="Squiz.PHP.LowercasePHPFunctions"/>
- <rule ref="Squiz.PHP.NonExecutableCode"/>
- <rule ref="Generic.PHP.ForbiddenFunctions"/>
- <rule ref="Generic.PHP.DeprecatedFunctions"/>
-
- <rule ref="Generic.Strings.UnnecessaryStringConcat"/>
-
- <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
- <rule ref="PEAR.WhiteSpace.ScopeClosingBrace"/>
-
- <rule ref="PEAR.Classes.ClassDeclaration"/>
-
- <rule ref="Generic.ControlStructures.InlineControlStructure"/>
- <rule ref="PEAR.ControlStructures.ControlSignature"/>
-
- <rule ref="Generic.Files.LineLength">
- <properties>
- <property name="lineLimit" value="125"/>
- <property name="absoluteLineLimit" value="200"/>
- </properties>
- </rule>
- <rule ref="Zend.Files.ClosingTag"/>
- <rule ref="Generic.Files.LineEndings"/>
-
- <rule ref="Generic.NamingConventions.ConstructorName"/>
- <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
-
- <rule ref="Generic.Metrics.NestingLevel"/>
- <rule ref="Generic.Metrics.CyclomaticComplexity"/>
-
- <rule ref="Generic.CodeAnalysis.EmptyStatement"/>
- <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>
- <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
- <rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
- <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
- <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
-
- <rule ref="PEAR.Commenting.InlineComment"/>
-
- <rule ref="Generic.Formatting.SpaceAfterCast"/>
- <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
-
- <rule ref="Squiz.Arrays.ArrayBracketSpacing"/>
- <rule ref="Squiz.ControlStructures.ElseIfDeclaration"/>
- <rule ref="Squiz.WhiteSpace.SemicolonSpacing"/>
-
-</ruleset>
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Error.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Error.php
deleted file mode 100644
index 56d44647..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Error.php
+++ /dev/null
@@ -1,244 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint;
-
-/*
-Copyright (c) 2012, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
- */
-
-class Error implements \JsonSerializable
-{
- /** @var string */
- protected $filePath;
-
- /** @var string */
- protected $message;
-
- /**
- * @param string $filePath
- * @param string $message
- */
- public function __construct($filePath, $message)
- {
- $this->filePath = $filePath;
- $this->message = rtrim($message);
- }
-
- /**
- * @return string
- */
- public function getMessage()
- {
- return $this->message;
- }
-
- /**
- * @return string
- */
- public function getFilePath()
- {
- return $this->filePath;
- }
-
- /**
- * @return string
- */
- public function getShortFilePath()
- {
- return str_replace(getcwd(), '', $this->filePath);
- }
-
- /**
- * (PHP 5 &gt;= 5.4.0)<br/>
- * Specify data which should be serialized to JSON
- * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by <b>json_encode</b>,
- * which is a value of any type other than a resource.
- */
- public function jsonSerialize()
- {
- return array(
- 'type' => 'error',
- 'file' => $this->getFilePath(),
- 'message' => $this->getMessage(),
- );
- }
-}
-
-class Blame implements \JsonSerializable
-{
- public $name;
-
- public $email;
-
- /** @var \DateTime */
- public $datetime;
-
- public $commitHash;
-
- public $summary;
-
- /**
- * (PHP 5 &gt;= 5.4.0)<br/>
- * Specify data which should be serialized to JSON
- * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by <b>json_encode</b>,
- * which is a value of any type other than a resource.
- */
- function jsonSerialize()
- {
- return array(
- 'name' => $this->name,
- 'email' => $this->email,
- 'datetime' => $this->datetime,
- 'commitHash' => $this->commitHash,
- 'summary' => $this->summary,
- );
- }
-
-
-}
-
-class SyntaxError extends Error
-{
- /** @var Blame */
- private $blame;
-
- /**
- * @return int|null
- */
- public function getLine()
- {
- preg_match('~on line ([0-9]*)~', $this->message, $matches);
-
- if ($matches && isset($matches[1])) {
- $onLine = (int) $matches[1];
- return $onLine;
- }
-
- return null;
- }
-
- /**
- * @param bool $translateTokens
- * @return mixed|string
- */
- public function getNormalizedMessage($translateTokens = false)
- {
- $message = preg_replace('~(Parse|Fatal) error: syntax error, ~', '', $this->message);
- $message = ucfirst($message);
- $message = preg_replace('~ in (.*) on line [0-9]*~', '', $message);
-
- if ($translateTokens) {
- $message = $this->translateTokens($message);
- }
-
- return $message;
- }
-
- /**
- * @param Blame $blame
- */
- public function setBlame(Blame $blame)
- {
- $this->blame = $blame;
- }
-
- /**
- * @return Blame
- */
- public function getBlame()
- {
- return $this->blame;
- }
-
- /**
- * @param string $message
- * @return string
- */
- protected function translateTokens($message)
- {
- static $translateTokens = array(
- 'T_FILE' => '__FILE__',
- 'T_FUNC_C' => '__FUNCTION__',
- 'T_HALT_COMPILER' => '__halt_compiler()',
- 'T_INC' => '++',
- 'T_IS_EQUAL' => '==',
- 'T_IS_GREATER_OR_EQUAL' => '>=',
- 'T_IS_IDENTICAL' => '===',
- 'T_IS_NOT_IDENTICAL' => '!==',
- 'T_IS_SMALLER_OR_EQUAL' => '<=',
- 'T_LINE' => '__LINE__',
- 'T_METHOD_C' => '__METHOD__',
- 'T_MINUS_EQUAL' => '-=',
- 'T_MOD_EQUAL' => '%=',
- 'T_MUL_EQUAL' => '*=',
- 'T_NS_C' => '__NAMESPACE__',
- 'T_NS_SEPARATOR' => '\\',
- 'T_OBJECT_OPERATOR' => '->',
- 'T_OR_EQUAL' => '|=',
- 'T_PAAMAYIM_NEKUDOTAYIM' => '::',
- 'T_PLUS_EQUAL' => '+=',
- 'T_SL' => '<<',
- 'T_SL_EQUAL' => '<<=',
- 'T_SR' => '>>',
- 'T_SR_EQUAL' => '>>=',
- 'T_START_HEREDOC' => '<<<',
- 'T_XOR_EQUAL' => '^=',
- 'T_ECHO' => 'echo'
- );
-
- return preg_replace_callback('~T_([A-Z_]*)~', function ($matches) use ($translateTokens) {
- list($tokenName) = $matches;
- if (isset($translateTokens[$tokenName])) {
- $operator = $translateTokens[$tokenName];
- return "$operator ($tokenName)";
- }
-
- return $tokenName;
- }, $message);
- }
-
- /**
- * (PHP 5 &gt;= 5.4.0)<br/>
- * Specify data which should be serialized to JSON
- * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by <b>json_encode</b>,
- * which is a value of any type other than a resource.
- */
- public function jsonSerialize()
- {
- return array(
- 'type' => 'syntaxError',
- 'file' => $this->getFilePath(),
- 'line' => $this->getLine(),
- 'message' => $this->getMessage(),
- 'normalizeMessage' => $this->getNormalizedMessage(),
- 'blame' => $this->blame,
- );
- }
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/ErrorFormatter.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/ErrorFormatter.php
deleted file mode 100644
index 863e8df3..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/ErrorFormatter.php
+++ /dev/null
@@ -1,152 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint;
-
-/*
-Copyright (c) 2014, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
- */
-
-use JakubOnderka\PhpConsoleColor\ConsoleColor;
-use JakubOnderka\PhpConsoleHighlighter\Highlighter;
-
-class ErrorFormatter
-{
- /** @var bool */
- private $useColors;
-
- /** @var bool */
- private $translateTokens;
-
- public function __construct($useColors = false, $translateTokens = false)
- {
- $this->useColors = $useColors;
- $this->translateTokens = $translateTokens;
- }
-
- /**
- * @param Error $error
- * @return string
- */
- public function format(Error $error)
- {
- if ($error instanceof SyntaxError) {
- return $this->formatSyntaxErrorMessage($error);
- } else {
- if ($error->getMessage()) {
- return $error->getMessage();
- } else {
- return "Unknown error for file '{$error->getFilePath()}'.";
- }
- }
- }
-
- /**
- * @param SyntaxError $error
- * @param bool $withCodeSnipped
- * @return string
- */
- public function formatSyntaxErrorMessage(SyntaxError $error, $withCodeSnipped = true)
- {
- $string = "Parse error: {$error->getShortFilePath()}";
-
- if ($error->getLine()) {
- $onLine = $error->getLine();
- $string .= ":$onLine" . PHP_EOL;
-
- if ($withCodeSnipped) {
- if ($this->useColors) {
- $string .= $this->getColoredCodeSnippet($error->getFilePath(), $onLine);
- } else {
- $string .= $this->getCodeSnippet($error->getFilePath(), $onLine);
- }
- }
- }
-
- $string .= $error->getNormalizedMessage($this->translateTokens);
-
- if ($error->getBlame()) {
- $blame = $error->getBlame();
- $shortCommitHash = substr($blame->commitHash, 0, 8);
- $dateTime = $blame->datetime->format('c');
- $string .= PHP_EOL . "Blame {$blame->name} <{$blame->email}>, commit '$shortCommitHash' from $dateTime";
- }
-
- return $string;
- }
-
- /**
- * @param string $filePath
- * @param int $lineNumber
- * @param int $linesBefore
- * @param int $linesAfter
- * @return string
- */
- protected function getCodeSnippet($filePath, $lineNumber, $linesBefore = 2, $linesAfter = 2)
- {
- $lines = file($filePath);
-
- $offset = $lineNumber - $linesBefore - 1;
- $offset = max($offset, 0);
- $length = $linesAfter + $linesBefore + 1;
- $lines = array_slice($lines, $offset, $length, $preserveKeys = true);
-
- end($lines);
- $lineStrlen = strlen(key($lines) + 1);
-
- $snippet = '';
- foreach ($lines as $i => $line) {
- $snippet .= ($lineNumber === $i + 1 ? ' > ' : ' ');
- $snippet .= str_pad($i + 1, $lineStrlen, ' ', STR_PAD_LEFT) . '| ' . rtrim($line) . PHP_EOL;
- }
-
- return $snippet;
- }
-
- /**
- * @param string $filePath
- * @param int $lineNumber
- * @param int $linesBefore
- * @param int $linesAfter
- * @return string
- */
- protected function getColoredCodeSnippet($filePath, $lineNumber, $linesBefore = 2, $linesAfter = 2)
- {
- if (
- !class_exists('\JakubOnderka\PhpConsoleHighlighter\Highlighter') ||
- !class_exists('\JakubOnderka\PhpConsoleColor\ConsoleColor')
- ) {
- return $this->getCodeSnippet($filePath, $lineNumber, $linesBefore, $linesAfter);
- }
-
- $colors = new ConsoleColor();
- $colors->setForceStyle(true);
- $highlighter = new Highlighter($colors);
-
- $fileContent = file_get_contents($filePath);
- return $highlighter->getCodeSnippet($fileContent, $lineNumber, $linesBefore, $linesAfter);
- }
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/JsonSerializable.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/JsonSerializable.php
deleted file mode 100644
index dde24f55..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/JsonSerializable.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-
-if (!interface_exists('JsonSerializable')) {
- interface JsonSerializable {
- public function jsonSerialize();
- }
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Manager.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Manager.php
deleted file mode 100644
index 1f38e31b..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Manager.php
+++ /dev/null
@@ -1,272 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint;
-
-/*
-Copyright (c) 2012, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
- */
-
-use JakubOnderka\PhpParallelLint\Process\GitBlameProcess;
-use JakubOnderka\PhpParallelLint\Process\PhpExecutable;
-
-class Manager
-{
- /** @var Output */
- protected $output;
-
- /**
- * @param null|Settings $settings
- * @return Result
- * @throws \Exception
- */
- public function run(Settings $settings = null)
- {
- $settings = $settings ?: new Settings;
- $output = $this->output ?: $this->getDefaultOutput($settings);
-
- $phpExecutable = PhpExecutable::getPhpExecutable($settings->phpExecutable);
- $translateTokens = $phpExecutable->isIsHhvmType() || $phpExecutable->getVersionId() < 50400; // From PHP version 5.4 are tokens translated by default
-
- $output->writeHeader($phpExecutable->getVersionId(), $settings->parallelJobs, $phpExecutable->getHhvmVersion());
-
- $files = $this->getFilesFromPaths($settings->paths, $settings->extensions, $settings->excluded);
-
- if (empty($files)) {
- throw new Exception('No file found to check.');
- }
-
- $output->setTotalFileCount(count($files));
-
- $parallelLint = new ParallelLint($phpExecutable, $settings->parallelJobs);
- $parallelLint->setAspTagsEnabled($settings->aspTags);
- $parallelLint->setShortTagEnabled($settings->shortTag);
-
- $parallelLint->setProcessCallback(function ($status, $file) use ($output) {
- if ($status === ParallelLint::STATUS_OK) {
- $output->ok();
- } elseif ($status === ParallelLint::STATUS_SKIP) {
- $output->skip();
- } elseif ($status === ParallelLint::STATUS_ERROR) {
- $output->error();
- } else {
- $output->fail();
- }
- });
-
- $result = $parallelLint->lint($files);
-
- if ($settings->blame) {
- $this->gitBlame($result, $settings);
- }
-
- $output->writeResult($result, new ErrorFormatter($settings->colors, $translateTokens), $settings->ignoreFails);
-
- return $result;
- }
-
- /**
- * @param Output $output
- */
- public function setOutput(Output $output)
- {
- $this->output = $output;
- }
-
- /**
- * @param Settings $settings
- * @return Output
- */
- protected function getDefaultOutput(Settings $settings)
- {
- $writer = new ConsoleWriter;
- if ($settings->json) {
- return new JsonOutput($writer);
- } else {
- return ($settings->colors ? new TextOutputColored($writer) : new TextOutput($writer));
- }
- }
-
- /**
- * @param Result $result
- * @param Settings $settings
- * @throws Exception
- */
- protected function gitBlame(Result $result, Settings $settings)
- {
- if (!GitBlameProcess::gitExists($settings->gitExecutable)) {
- return;
- }
-
- foreach ($result->getErrors() as $error) {
- if ($error instanceof SyntaxError) {
- $process = new GitBlameProcess($settings->gitExecutable, $error->getFilePath(), $error->getLine());
- $process->waitForFinish();
-
- if ($process->isSuccess()) {
- $blame = new Blame;
- $blame->name = $process->getAuthor();
- $blame->email = $process->getAuthorEmail();
- $blame->datetime = $process->getAuthorTime();
- $blame->commitHash = $process->getCommitHash();
- $blame->summary = $process->getSummary();
-
- $error->setBlame($blame);
- }
- }
- }
- }
-
- /**
- * @param array $paths
- * @param array $extensions
- * @param array $excluded
- * @return array
- * @throws NotExistsPathException
- */
- protected function getFilesFromPaths(array $paths, array $extensions, array $excluded = array())
- {
- $extensions = array_flip($extensions);
- $files = array();
-
- foreach ($paths as $path) {
- if (is_file($path)) {
- $files[] = $path;
- } elseif (is_dir($path)) {
- $iterator = new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS);
- if (!empty($excluded)) {
- $iterator = new RecursiveDirectoryFilterIterator($iterator, $excluded);
- }
- $iterator = new \RecursiveIteratorIterator(
- $iterator,
- \RecursiveIteratorIterator::LEAVES_ONLY,
- \RecursiveIteratorIterator::CATCH_GET_CHILD
- );
-
- /** @var \SplFileInfo[] $iterator */
- foreach ($iterator as $directoryFile) {
- if (isset($extensions[pathinfo($directoryFile->getFilename(), PATHINFO_EXTENSION)])) {
- $files[] = (string) $directoryFile;
- }
- }
- } else {
- throw new NotExistsPathException($path);
- }
- }
-
- $files = array_unique($files);
-
- return $files;
- }
-}
-
-class RecursiveDirectoryFilterIterator extends \RecursiveFilterIterator
-{
- /** @var \RecursiveDirectoryIterator */
- private $iterator;
-
- /** @var array */
- private $excluded = array();
-
- /**
- * @param \RecursiveDirectoryIterator $iterator
- * @param array $excluded
- */
- public function __construct(\RecursiveDirectoryIterator $iterator, array $excluded)
- {
- parent::__construct($iterator);
- $this->iterator = $iterator;
- $this->excluded = array_map(array($this, 'getPathname'), $excluded);
- }
-
- /**
- * (PHP 5 &gt;= 5.1.0)<br/>
- * Check whether the current element of the iterator is acceptable
- *
- * @link http://php.net/manual/en/filteriterator.accept.php
- * @return bool true if the current element is acceptable, otherwise false.
- */
- public function accept()
- {
- $current = $this->current()->getPathname();
- $current = $this->normalizeDirectorySeparator($current);
-
- if ('.' . DIRECTORY_SEPARATOR !== $current[0] . $current[1]) {
- $current = '.' . DIRECTORY_SEPARATOR . $current;
- }
-
- return !in_array($current, $this->excluded);
- }
-
- /**
- * (PHP 5 &gt;= 5.1.0)<br/>
- * Check whether the inner iterator's current element has children
- *
- * @link http://php.net/manual/en/recursivefilteriterator.haschildren.php
- * @return bool true if the inner iterator has children, otherwise false
- */
- public function hasChildren()
- {
- return $this->iterator->hasChildren();
- }
-
- /**
- * (PHP 5 &gt;= 5.1.0)<br/>
- * Return the inner iterator's children contained in a RecursiveFilterIterator
- *
- * @link http://php.net/manual/en/recursivefilteriterator.getchildren.php
- * @return \RecursiveFilterIterator containing the inner iterator's children.
- */
- public function getChildren()
- {
- return new self($this->iterator->getChildren(), $this->excluded);
- }
-
- /**
- * @param string $file
- * @return string
- */
- private function getPathname($file)
- {
- $file = $this->normalizeDirectorySeparator($file);
-
- if ('.' . DIRECTORY_SEPARATOR !== $file[0] . $file[1]) {
- $file = '.' . DIRECTORY_SEPARATOR . $file;
- }
-
- $directoryFile = new \SplFileInfo($file);
- return $directoryFile->getPathname();
- }
-
- /**
- * @param string $file
- * @return string
- */
- private function normalizeDirectorySeparator($file)
- {
- return str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $file);
- }
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Output.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Output.php
deleted file mode 100644
index 2e4964b6..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Output.php
+++ /dev/null
@@ -1,449 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint;
-
-/*
-Copyright (c) 2012, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
- */
-
-interface Output
-{
- public function __construct(IWriter $writer);
-
- public function ok();
-
- public function skip();
-
- public function error();
-
- public function fail();
-
- public function setTotalFileCount($count);
-
- public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null);
-
- public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails);
-}
-
-class JsonOutput implements Output
-{
- /** @var IWriter */
- protected $writer;
-
- /** @var int */
- protected $phpVersion;
-
- /** @var int */
- protected $parallelJobs;
-
- /** @var string */
- protected $hhvmVersion;
-
- /**
- * @param IWriter $writer
- */
- public function __construct(IWriter $writer)
- {
- $this->writer = $writer;
- }
-
- public function ok()
- {
-
- }
-
- public function skip()
- {
-
- }
-
- public function error()
- {
-
- }
-
- public function fail()
- {
-
- }
-
- public function setTotalFileCount($count)
- {
-
- }
-
- public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null)
- {
- $this->phpVersion = $phpVersion;
- $this->parallelJobs = $parallelJobs;
- $this->hhvmVersion = $hhvmVersion;
- }
-
- public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
- {
- echo json_encode(array(
- 'phpVersion' => $this->phpVersion,
- 'hhvmVersion' => $this->hhvmVersion,
- 'parallelJobs' => $this->parallelJobs,
- 'results' => $result,
- ));
- }
-}
-
-class TextOutput implements Output
-{
- const TYPE_DEFAULT = 'default',
- TYPE_SKIP = 'skip',
- TYPE_ERROR = 'error',
- TYPE_OK = 'ok';
-
- /** @var int */
- public $filesPerLine = 60;
-
- /** @var int */
- protected $checkedFiles;
-
- /** @var int */
- protected $totalFileCount;
-
- /** @var IWriter */
- protected $writer;
-
- /**
- * @param IWriter $writer
- */
- public function __construct(IWriter $writer)
- {
- $this->writer = $writer;
- }
-
- public function ok()
- {
- $this->writer->write('.');
- $this->progress();
- }
-
- public function skip()
- {
- $this->write('S', self::TYPE_SKIP);
- $this->progress();
- }
-
- public function error()
- {
- $this->write('X', self::TYPE_ERROR);
- $this->progress();
- }
-
- public function fail()
- {
- $this->writer->write('-');
- $this->progress();
- }
-
- /**
- * @param string $string
- * @param string $type
- */
- public function write($string, $type = self::TYPE_DEFAULT)
- {
- $this->writer->write($string);
- }
-
- /**
- * @param string|null $line
- * @param string $type
- */
- public function writeLine($line = null, $type = self::TYPE_DEFAULT)
- {
- $this->write($line, $type);
- $this->writeNewLine();
- }
-
- /**
- * @param int $count
- */
- public function writeNewLine($count = 1)
- {
- $this->write(str_repeat(PHP_EOL, $count));
- }
-
- /**
- * @param int $count
- */
- public function setTotalFileCount($count)
- {
- $this->totalFileCount = $count;
- }
-
- /**
- * @param int $phpVersion
- * @param int $parallelJobs
- * @param string $hhvmVersion
- */
- public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null)
- {
- $this->write("PHP {$this->phpVersionIdToString($phpVersion)} | ");
-
- if ($hhvmVersion) {
- $this->write("HHVM $hhvmVersion | ");
- }
-
- if ($parallelJobs === 1) {
- $this->writeLine("1 job");
- } else {
- $this->writeLine("{$parallelJobs} parallel jobs");
- }
- }
-
- /**
- * @param Result $result
- * @param ErrorFormatter $errorFormatter
- * @param bool $ignoreFails
- */
- public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
- {
- if ($this->checkedFiles % $this->filesPerLine !== 0) {
- $rest = $this->filesPerLine - ($this->checkedFiles % $this->filesPerLine);
- $this->write(str_repeat(' ', $rest));
- $this->writeProgress();
- }
-
- $this->writeNewLine(2);
-
- $testTime = round($result->getTestTime(), 1);
- $message = "Checked {$result->getCheckedFilesCount()} files in $testTime ";
- $message .= $testTime == 1 ? 'second' : 'seconds';
-
- if ($result->getSkippedFilesCount() > 0) {
- $message .= "skipped {$result->getSkippedFilesCount()} ";
- $message .= ($result->getSkippedFilesCount() === 1 ? 'file' : 'files');
- }
-
- $this->writeLine($message);
-
- if (!$result->hasSyntaxError()) {
- $message = "No syntax error found";
- } else {
- $message = "Syntax error found in {$result->getFilesWithSyntaxErrorCount()} ";
- $message .= ($result->getFilesWithSyntaxErrorCount() === 1 ? 'file' : 'files');
- }
-
- if ($result->hasFilesWithFail()) {
- $message .= ", failed to check {$result->getFilesWithFailCount()} ";
- $message .= ($result->getFilesWithFailCount() === 1 ? 'file' : 'files');
-
- if ($ignoreFails) {
- $message .= ' (ignored)';
- }
- }
-
- $hasError = $ignoreFails ? $result->hasSyntaxError() : $result->hasError();
- $this->writeLine($message, $hasError ? self::TYPE_ERROR : self::TYPE_OK);
-
- if ($result->hasError()) {
- $this->writeNewLine();
- foreach ($result->getErrors() as $error) {
- $this->writeLine(str_repeat('-', 60));
- $this->writeLine($errorFormatter->format($error));
- }
- }
- }
-
- protected function progress()
- {
- ++$this->checkedFiles;
-
- if ($this->checkedFiles % $this->filesPerLine === 0) {
- $this->writeProgress();
- }
- }
-
- protected function writeProgress()
- {
- $percent = floor($this->checkedFiles / $this->totalFileCount * 100);
- $current = $this->stringWidth($this->checkedFiles, strlen($this->totalFileCount));
- $this->writeLine(" $current/$this->totalFileCount ($percent %)");
- }
-
- /**
- * @param string $input
- * @param int $width
- * @return string
- */
- protected function stringWidth($input, $width = 3)
- {
- $multiplier = $width - strlen($input);
- return str_repeat(' ', $multiplier > 0 ? $multiplier : 0) . $input;
- }
-
- /**
- * @param int $phpVersionId
- * @return string
- */
- protected function phpVersionIdToString($phpVersionId)
- {
- $releaseVersion = (int) substr($phpVersionId, -2, 2);
- $minorVersion = (int) substr($phpVersionId, -4, 2);
- $majorVersion = (int) substr($phpVersionId, 0, strlen($phpVersionId) - 4);
-
- return "$majorVersion.$minorVersion.$releaseVersion";
- }
-}
-
-class TextOutputColored extends TextOutput
-{
- /** @var \JakubOnderka\PhpConsoleColor\ConsoleColor */
- private $colors;
-
- public function __construct(IWriter $writer)
- {
- parent::__construct($writer);
-
- if (class_exists('\JakubOnderka\PhpConsoleColor\ConsoleColor')) {
- $this->colors = new \JakubOnderka\PhpConsoleColor\ConsoleColor();
- $this->colors->setForceStyle(true);
- }
- }
-
- /**
- * @param string $string
- * @param string $type
- * @throws \JakubOnderka\PhpConsoleColor\InvalidStyleException
- */
- public function write($string, $type = self::TYPE_DEFAULT)
- {
- if (!$this->colors instanceof \JakubOnderka\PhpConsoleColor\ConsoleColor) {
- parent::write($string, $type);
- } else {
- switch ($type) {
- case self::TYPE_OK:
- parent::write($this->colors->apply('bg_green', $string));
- break;
-
- case self::TYPE_SKIP:
- parent::write($this->colors->apply('bg_yellow', $string));
- break;
-
- case self::TYPE_ERROR:
- parent::write($this->colors->apply('bg_red', $string));
- break;
-
- default:
- parent::write($string);
- }
- }
- }
-}
-
-interface IWriter
-{
- /**
- * @param string $string
- */
- public function write($string);
-}
-
-class NullWriter implements IWriter
-{
- /**
- * @param string $string
- */
- public function write($string)
- {
-
- }
-}
-
-class ConsoleWriter implements IWriter
-{
- /**
- * @param string $string
- */
- public function write($string)
- {
- echo $string;
- }
-}
-
-class FileWriter implements IWriter
-{
- /** @var string */
- protected $logFile;
-
- /** @var string */
- protected $buffer;
-
- public function __construct($logFile)
- {
- $this->logFile = $logFile;
- }
-
- public function write($string)
- {
- $this->buffer .= $string;
- }
-
- public function __destruct()
- {
- file_put_contents($this->logFile, $this->buffer);
- }
-}
-
-class MultipleWriter implements IWriter
-{
- /** @var IWriter[] */
- protected $writers;
-
- /**
- * @param IWriter[] $writers
- */
- public function __construct(array $writers)
- {
- foreach ($writers as $writer) {
- $this->addWriter($writer);
- }
- }
-
- /**
- * @param IWriter $writer
- */
- public function addWriter(IWriter $writer)
- {
- $this->writers[] = $writer;
- }
-
- /**
- * @param $string
- */
- public function write($string)
- {
- foreach ($this->writers as $writer) {
- $writer->write($string);
- }
- }
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/ParallelLint.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/ParallelLint.php
deleted file mode 100644
index d491d349..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/ParallelLint.php
+++ /dev/null
@@ -1,261 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint;
-
-/*
-Copyright (c) 2012, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
- */
-
-use JakubOnderka\PhpParallelLint\Process\LintProcess;
-use JakubOnderka\PhpParallelLint\Process\PhpExecutable;
-use JakubOnderka\PhpParallelLint\Process\SkipLintProcess;
-
-class ParallelLint
-{
- const STATUS_OK = 'ok',
- STATUS_SKIP = 'skip',
- STATUS_FAIL = 'fail',
- STATUS_ERROR = 'error';
-
- /** @var int */
- private $parallelJobs;
-
- /** @var PhpExecutable */
- private $phpExecutable;
-
- /** @var bool */
- private $aspTagsEnabled = false;
-
- /** @var bool */
- private $shortTagEnabled = false;
-
- /** @var callable */
- private $processCallback;
-
- public function __construct(PhpExecutable $phpExecutable, $parallelJobs = 10)
- {
- $this->phpExecutable = $phpExecutable;
- $this->parallelJobs = $parallelJobs;
- }
-
- /**
- * @param array $files
- * @return Result
- * @throws \Exception
- */
- public function lint(array $files)
- {
- $startTime = microtime(true);
-
- $skipLintProcess = new SkipLintProcess($this->phpExecutable, $files);
-
- $processCallback = is_callable($this->processCallback) ? $this->processCallback : function() {};
-
- /**
- * @var LintProcess[] $running
- * @var LintProcess[] $waiting
- */
- $errors = $running = $waiting = array();
- $skippedFiles = $checkedFiles = array();
-
- while ($files || $running) {
- for ($i = count($running); $files && $i < $this->parallelJobs; $i++) {
- $file = array_shift($files);
-
- if ($skipLintProcess->isSkipped($file) === true) {
- $skippedFiles[] = $file;
- $processCallback(self::STATUS_SKIP, $file);
- } else {
- $running[$file] = new LintProcess(
- $this->phpExecutable,
- $file,
- $this->aspTagsEnabled,
- $this->shortTagEnabled
- );
- }
- }
-
- $skipLintProcess->getChunk();
- usleep(100);
-
- foreach ($running as $file => $process) {
- if ($process->isFinished()) {
- unset($running[$file]);
-
- $skipStatus = $skipLintProcess->isSkipped($file);
- if ($skipStatus === null) {
- $waiting[$file] = $process;
-
- } elseif ($skipStatus === true) {
- $skippedFiles[] = $file;
- $processCallback(self::STATUS_SKIP, $file);
-
- } elseif ($process->isSuccess()) {
- $checkedFiles[] = $file;
- $processCallback(self::STATUS_OK, $file);
-
- } elseif ($process->hasSyntaxError()) {
- $checkedFiles[] = $file;
- $errors[] = new SyntaxError($file, $process->getSyntaxError());
- $processCallback(self::STATUS_ERROR, $file);
-
- } else {
- $errors[] = new Error($file, $process->getOutput());
- $processCallback(self::STATUS_FAIL, $file);
- }
- }
- }
- }
-
- if (!empty($waiting)) {
- $skipLintProcess->waitForFinish();
-
- foreach ($waiting as $file => $process) {
- $skipStatus = $skipLintProcess->isSkipped($file);
- if ($skipStatus === null) {
- throw new \Exception("File $file has empty skip status. Please contact PHP Parallel Lint author.");
-
- } elseif ($skipStatus === true) {
- $skippedFiles[] = $file;
- $processCallback(self::STATUS_SKIP, $file);
-
- } elseif ($process->isSuccess()) {
- $checkedFiles[] = $file;
- $processCallback(self::STATUS_OK, $file);
-
- } elseif ($process->hasSyntaxError()) {
- $checkedFiles[] = $file;
- $errors[] = new SyntaxError($file, $process->getSyntaxError());
- $processCallback(self::STATUS_ERROR, $file);
-
- } else {
- $errors[] = new Error($file, $process->getOutput());
- $processCallback(self::STATUS_FAIL, $file);
- }
- }
- }
-
- $testTime = microtime(true) - $startTime;
-
- return new Result($errors, $checkedFiles, $skippedFiles, $testTime);
- }
-
- /**
- * @return int
- */
- public function getParallelJobs()
- {
- return $this->parallelJobs;
- }
-
- /**
- * @param int $parallelJobs
- * @return ParallelLint
- */
- public function setParallelJobs($parallelJobs)
- {
- $this->parallelJobs = $parallelJobs;
-
- return $this;
- }
-
- /**
- * @return string
- */
- public function getPhpExecutable()
- {
- return $this->phpExecutable;
- }
-
- /**
- * @param string $phpExecutable
- * @return ParallelLint
- */
- public function setPhpExecutable($phpExecutable)
- {
- $this->phpExecutable = $phpExecutable;
-
- return $this;
- }
-
- /**
- * @return callable
- */
- public function getProcessCallback()
- {
- return $this->processCallback;
- }
-
- /**
- * @param callable $processCallback
- * @return ParallelLint
- */
- public function setProcessCallback($processCallback)
- {
- $this->processCallback = $processCallback;
-
- return $this;
- }
-
- /**
- * @return boolean
- */
- public function isAspTagsEnabled()
- {
- return $this->aspTagsEnabled;
- }
-
- /**
- * @param boolean $aspTagsEnabled
- * @return ParallelLint
- */
- public function setAspTagsEnabled($aspTagsEnabled)
- {
- $this->aspTagsEnabled = $aspTagsEnabled;
-
- return $this;
- }
-
- /**
- * @return boolean
- */
- public function isShortTagEnabled()
- {
- return $this->shortTagEnabled;
- }
-
- /**
- * @param boolean $shortTagEnabled
- * @return ParallelLint
- */
- public function setShortTagEnabled($shortTagEnabled)
- {
- $this->shortTagEnabled = $shortTagEnabled;
-
- return $this;
- }
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/GitBlameProcess.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/GitBlameProcess.php
deleted file mode 100644
index 640a83cd..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/GitBlameProcess.php
+++ /dev/null
@@ -1,143 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint\Process;
-
-use JakubOnderka\PhpParallelLint\RunTimeException;
-
-class GitBlameProcess extends Process
-{
- /**
- * @param string $gitExecutable
- * @param string $file
- * @param int $line
- */
- public function __construct($gitExecutable, $file, $line)
- {
- $cmd = escapeshellcmd($gitExecutable) . " blame -p -L $line,+1 " . escapeshellarg($file);
- parent::__construct($cmd);
- }
-
- /**
- * @return bool
- */
- public function isSuccess()
- {
- return $this->getStatusCode() === 0;
- }
-
- /**
- * @return string
- * @throws RunTimeException
- */
- public function getAuthor()
- {
- if (!$this->isSuccess()) {
- throw new RunTimeException("Author can be taken only for success process output.");
- }
-
- $output = $this->getOutput();
- preg_match('~^author (.*)~m', $output, $matches);
- return $matches[1];
- }
-
- /**
- * @return string
- * @throws RunTimeException
- */
- public function getAuthorEmail()
- {
- if (!$this->isSuccess()) {
- throw new RunTimeException("Author e-mail can be taken only for success process output.");
- }
-
- $output = $this->getOutput();
- preg_match('~^author-mail <(.*)>~m', $output, $matches);
- return $matches[1];
- }
-
- /**
- * @return \DateTime
- * @throws RunTimeException
- */
- public function getAuthorTime()
- {
- if (!$this->isSuccess()) {
- throw new RunTimeException("Author time can be taken only for success process output.");
- }
-
- $output = $this->getOutput();
-
- preg_match('~^author-time (.*)~m', $output, $matches);
- $time = $matches[1];
-
- preg_match('~^author-tz (.*)~m', $output, $matches);
- $zone = $matches[1];
-
- return $this->getDateTime($time, $zone);
- }
-
- /**
- * @return string
- * @throws RunTimeException
- */
- public function getCommitHash()
- {
- if (!$this->isSuccess()) {
- throw new RunTimeException("Commit hash can be taken only for success process output.");
- }
-
- return substr($this->getOutput(), 0, strpos($this->getOutput(), ' '));
- }
-
- /**
- * @return string
- * @throws RunTimeException
- */
- public function getSummary()
- {
- if (!$this->isSuccess()) {
- throw new RunTimeException("Commit summary can be taken only for success process output.");
- }
-
- $output = $this->getOutput();
- preg_match('~^summary (.*)~m', $output, $matches);
- return $matches[1];
- }
-
- /**
- * @param string $gitExecutable
- * @return bool
- */
- public static function gitExists($gitExecutable)
- {
- $process = new Process(escapeshellcmd($gitExecutable) . ' --version');
- $process->waitForFinish();
- return $process->getStatusCode() === 0;
- }
-
- /**
- * This harakiri method is required to correct support time zone in PHP 5.4
- *
- * @param int $time
- * @param string $zone
- * @return \DateTime
- */
- protected function getDateTime($time, $zone)
- {
- $utcTimeZone = new \DateTimeZone('UTC');
- $datetime = \DateTime::createFromFormat('U', $time, $utcTimeZone);
-
- $way = substr($zone, 0, 1);
- $hours = (int) substr($zone, 1, 2);
- $minutes = (int) substr($zone, 3, 2);
-
- $interval = new \DateInterval("PT{$hours}H{$minutes}M");
-
- if ($way === '+') {
- $datetime->add($interval);
- } else {
- $datetime->sub($interval);
- }
-
- return new \DateTime($datetime->format('Y-m-d\TH:i:s') . $zone, $utcTimeZone);
- }
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/LintProcess.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/LintProcess.php
deleted file mode 100644
index a411d645..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/LintProcess.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint\Process;
-
-class LintProcess extends PhpProcess
-{
- /**
- * @param PhpExecutable $phpExecutable
- * @param string $fileToCheck Path to file to check
- * @param bool $aspTags
- * @param bool $shortTag
- */
- public function __construct(PhpExecutable $phpExecutable, $fileToCheck, $aspTags = false, $shortTag = false)
- {
- if (empty($fileToCheck)) {
- throw new \InvalidArgumentException("File to check must be set.");
- }
-
- $parameters = array(
- '-d asp_tags=' . ($aspTags ? 'On' : 'Off'),
- '-d short_open_tag=' . ($shortTag ? 'On' : 'Off'),
- '-d error_reporting=E_ALL',
- '-n',
- '-l',
- escapeshellarg($fileToCheck),
- );
-
- parent::__construct($phpExecutable, $parameters);
- }
-
- /**
- * @return bool
- */
- public function hasSyntaxError()
- {
- return strpos($this->getOutput(), 'Fatal error') !== false ||
- strpos($this->getOutput(), 'Parse error') !== false;
- }
-
- /**
- * @return bool|string
- */
- public function getSyntaxError()
- {
- if ($this->hasSyntaxError()) {
- list(, $out) = explode("\n", $this->getOutput());
- return $out;
- }
-
- return false;
- }
-
- /**
- * @return bool
- */
- public function isFail()
- {
- return defined('PHP_WINDOWS_VERSION_MAJOR') ? $this->getStatusCode() === 1 : parent::isFail();
- }
-
- /**
- * @return bool
- */
- public function isSuccess()
- {
- return $this->getStatusCode() === 0;
- }
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/PhpExecutable.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/PhpExecutable.php
deleted file mode 100644
index 5593a911..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/PhpExecutable.php
+++ /dev/null
@@ -1,128 +0,0 @@
-<?php
-
-namespace JakubOnderka\PhpParallelLint\Process;
-
-use JakubOnderka\PhpParallelLint\RunTimeException;
-
-class PhpExecutable
-{
- /** @var string */
- private $path;
-
- /**
- * Version as PHP_VERSION_ID constant
- * @var int
- */
- private $versionId;
-
- /** @var string */
- private $hhvmVersion;
-
- /** @var bool */
- private $isHhvmType;
-
- /**
- * @param string $path
- * @param int $versionId
- * @param string $hhvmVersion
- * @param bool $isHhvmType
- */
- public function __construct($path, $versionId, $hhvmVersion, $isHhvmType)
- {
- $this->path = $path;
- $this->versionId = $versionId;
- $this->hhvmVersion = $hhvmVersion;
- $this->isHhvmType = $isHhvmType;
- }
-
- /**
- * @return string
- */
- public function getHhvmVersion()
- {
- return $this->hhvmVersion;
- }
-
- /**
- * @return boolean
- */
- public function isIsHhvmType()
- {
- return $this->isHhvmType;
- }
-
- /**
- * @return string
- */
- public function getPath()
- {
- return $this->path;
- }
-
- /**
- * @return int
- */
- public function getVersionId()
- {
- return $this->versionId;
- }
-
- /**
- * @param string $phpExecutable
- * @return PhpExecutable
- * @throws \Exception
- */
- public static function getPhpExecutable($phpExecutable)
- {
- $codeToExecute = <<<PHP
-echo 'PHP;', PHP_VERSION_ID, ';', defined('HPHP_VERSION') ? HPHP_VERSION : null;
-PHP;
-
- $process = new Process(escapeshellarg($phpExecutable) . ' -n -r ' . escapeshellarg($codeToExecute));
- $process->waitForFinish();
-
- try {
- if ($process->getStatusCode() !== 0 && $process->getStatusCode() !== 255) {
- throw new RunTimeException("Unable to execute '{$phpExecutable}'.");
- }
-
- return self::getPhpExecutableFromOutput($phpExecutable, $process->getOutput());
-
- } catch (RunTimeException $e) {
- // Try HHVM type
- $process = new Process(escapeshellarg($phpExecutable) . ' --php -r ' . escapeshellarg($codeToExecute));
- $process->waitForFinish();
-
- if ($process->getStatusCode() !== 0 && $process->getStatusCode() !== 255) {
- throw new RunTimeException("Unable to execute '{$phpExecutable}'.");
- }
-
- return self::getPhpExecutableFromOutput($phpExecutable, $process->getOutput(), $isHhvmType = true);
- }
- }
-
- /**
- * @param string $phpExecutable
- * @param string $output
- * @param bool $isHhvmType
- * @return PhpExecutable
- * @throws RunTimeException
- */
- private static function getPhpExecutableFromOutput($phpExecutable, $output, $isHhvmType = false)
- {
- $parts = explode(';', $output);
-
- if ($parts[0] !== 'PHP' || !preg_match('~([0-9]+)~', $parts[1], $matches)) {
- throw new RunTimeException("'{$phpExecutable}' is not valid PHP binary.");
- }
-
- $hhvmVersion = isset($parts[2]) ? $parts[2] : false;
-
- return new PhpExecutable(
- $phpExecutable,
- intval($matches[1]),
- $hhvmVersion,
- $isHhvmType
- );
- }
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/PhpProcess.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/PhpProcess.php
deleted file mode 100644
index 0bab5b69..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/PhpProcess.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-namespace JakubOnderka\PhpParallelLint\Process;
-
-class PhpProcess extends Process
-{
- /**
- * @param PhpExecutable $phpExecutable
- * @param array $parameters
- * @param string|null $stdIn
- */
- public function __construct(PhpExecutable $phpExecutable, array $parameters = array(), $stdIn = null)
- {
- $cmdLine = escapeshellcmd($phpExecutable->getPath()) . ' ' . $this->constructParameters($parameters, $phpExecutable->isIsHhvmType());
- parent::__construct($cmdLine, $stdIn);
- }
-
- /**
- * @param array $parameters
- * @return string
- */
- private function constructParameters(array $parameters, $isHhvm)
- {
- return ($isHhvm ? '--php ' : '') . implode(' ', $parameters);
- }
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/Process.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/Process.php
deleted file mode 100644
index 3f93b228..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/Process.php
+++ /dev/null
@@ -1,149 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint\Process;
-
-use JakubOnderka\PhpParallelLint\RunTimeException;
-
-class Process
-{
- const STDIN = 0,
- STDOUT = 1,
- STDERR = 2;
-
- const READ = 'r',
- WRITE = 'w';
-
- /** @var resource */
- protected $process;
-
- /** @var resource */
- protected $stdout;
-
- /** @var resource */
- protected $stderr;
-
- /** @var string */
- private $output;
-
- /** @var string */
- private $errorOutput;
-
- /** @var int */
- private $statusCode;
-
- /**
- * @param string $cmdLine
- * @param string $stdInInput
- * @throws RuntimeException
- */
- public function __construct($cmdLine, $stdInInput = null)
- {
- $descriptors = array(
- self::STDIN => array('pipe', self::READ),
- self::STDOUT => array('pipe', self::WRITE),
- self::STDERR => array('pipe', self::WRITE),
- );
-
- $this->process = proc_open($cmdLine, $descriptors, $pipes, null, null, array('bypass_shell' => true));
-
- if ($this->process === false) {
- throw new RuntimeException("Cannot create new process $cmdLine");
- }
-
- list($stdin, $this->stdout, $this->stderr) = $pipes;
-
- if ($stdInInput) {
- fwrite($stdin, $stdInInput);
- }
-
- fclose($stdin);
- }
-
- /**
- * @return bool
- */
- public function isFinished()
- {
- if ($this->statusCode !== NULL) {
- return true;
- }
-
- $status = proc_get_status($this->process);
-
- if ($status['running']) {
- return false;
- } elseif ($this->statusCode === null) {
- $this->statusCode = (int) $status['exitcode'];
- }
-
- // Process outputs
- $this->output = stream_get_contents($this->stdout);
- fclose($this->stdout);
-
- $this->errorOutput = stream_get_contents($this->stderr);
- fclose($this->stderr);
-
- $statusCode = proc_close($this->process);
-
- if ($this->statusCode === null) {
- $this->statusCode = $statusCode;
- }
-
- $this->process = null;
-
- return true;
- }
-
- public function waitForFinish()
- {
- while (!$this->isFinished()) {
- usleep(100);
- }
- }
-
- /**
- * @return string
- * @throws RuntimeException
- */
- public function getOutput()
- {
- if (!$this->isFinished()) {
- throw new RuntimeException("Cannot get output for running process");
- }
-
- return $this->output;
- }
-
- /**
- * @return string
- * @throws RuntimeException
- */
- public function getErrorOutput()
- {
- if (!$this->isFinished()) {
- throw new RuntimeException("Cannot get error output for running process");
- }
-
- return $this->errorOutput;
- }
-
- /**
- * @return int
- * @throws RuntimeException
- */
- public function getStatusCode()
- {
- if (!$this->isFinished()) {
- throw new RuntimeException("Cannot get status code for running process");
- }
-
- return $this->statusCode;
- }
-
- /**
- * @return bool
- */
- public function isFail()
- {
- return $this->getStatusCode() === 1;
- }
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/SkipLintProcess.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/SkipLintProcess.php
deleted file mode 100644
index a55f83a9..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Process/SkipLintProcess.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint\Process;
-
-class SkipLintProcess extends PhpProcess
-{
- /** @var array */
- private $skipped = array();
-
- /** @var bool */
- private $done = false;
-
- /** @var string */
- private $endLastChunk = '';
-
- /**
- * @param PhpExecutable $phpExecutable
- * @param array $filesToCheck
- */
- public function __construct(PhpExecutable $phpExecutable, array $filesToCheck)
- {
- $parameters = array('-n ' . escapeshellarg(__DIR__ . '/../../bin/skip-linting.php'));
-
- parent::__construct($phpExecutable, $parameters, implode("\n", $filesToCheck));
- }
-
- public function getChunk()
- {
- if (!$this->isFinished()) {
- $this->processLines(fread($this->stdout, 8192));
- }
- }
-
- /**
- * @return bool
- * @throws \JakubOnderka\PhpParallelLint\RunTimeException
- */
- public function isFinished()
- {
- $isFinished = parent::isFinished();
- if ($isFinished && !$this->done) {
- $this->done = true;
- $output = $this->getOutput();
- $this->processLines($output);
- }
-
- return $isFinished;
- }
-
- /**
- * @param string $file
- * @return bool|null
- */
- public function isSkipped($file)
- {
- if (isset($this->skipped[$file])) {
- return $this->skipped[$file];
- }
-
- return null;
- }
-
- /**
- * @param string $content
- */
- private function processLines($content)
- {
- if (!empty($content)) {
- $lines = explode("\n", $this->endLastChunk . $content);
- $this->endLastChunk = array_pop($lines);
- foreach ($lines as $line) {
- $parts = explode(';', $line);
- list($file, $status) = $parts;
- $this->skipped[$file] = $status === '1' ? true : false;
- }
- }
- }
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Result.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Result.php
deleted file mode 100644
index 6826de13..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Result.php
+++ /dev/null
@@ -1,197 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint;
-
-/*
-Copyright (c) 2012, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
- */
-
-class Result implements \JsonSerializable
-{
- /** @var Error[] */
- private $errors;
-
- /** @var array */
- private $checkedFiles;
-
- /** @var array */
- private $skippedFiles;
-
- /** @var float */
- private $testTime;
-
- /**
- * @param Error[] $errors
- * @param array $checkedFiles
- * @param array $skippedFiles
- * @param float $testTime
- */
- public function __construct(array $errors, array $checkedFiles, array $skippedFiles, $testTime)
- {
- $this->errors = $errors;
- $this->checkedFiles = $checkedFiles;
- $this->skippedFiles = $skippedFiles;
- $this->testTime = $testTime;
- }
-
- /**
- * @return array
- */
- public function getErrors()
- {
- return $this->errors;
- }
-
- /**
- * @return bool
- */
- public function hasError()
- {
- return !empty($this->errors);
- }
-
- /**
- * @return array
- */
- public function getFilesWithFail()
- {
- $filesWithFail = array();
- foreach ($this->errors as $error) {
- if (!$error instanceof SyntaxError) {
- $filesWithFail[] = $error->getFilePath();
- }
- }
-
- return $filesWithFail;
- }
-
- /**
- * @return int
- */
- public function getFilesWithFailCount()
- {
- return count($this->getFilesWithFail());
- }
-
- /**
- * @return bool
- */
- public function hasFilesWithFail()
- {
- return $this->getFilesWithFailCount() !== 0;
- }
-
- /**
- * @return array
- */
- public function getCheckedFiles()
- {
- return $this->checkedFiles;
- }
-
- /**
- * @return int
- */
- public function getCheckedFilesCount()
- {
- return count($this->checkedFiles);
- }
-
- /**
- * @return array
- */
- public function getSkippedFiles()
- {
- return $this->skippedFiles;
- }
-
- /**
- * @return int
- */
- public function getSkippedFilesCount()
- {
- return count($this->skippedFiles);
- }
-
- /**
- * @return array
- */
- public function getFilesWithSyntaxError()
- {
- $filesWithSyntaxError = array();
- foreach ($this->errors as $error) {
- if ($error instanceof SyntaxError) {
- $filesWithSyntaxError[] = $error->getFilePath();
- }
- }
-
- return $filesWithSyntaxError;
- }
-
- /**
- * @return int
- */
- public function getFilesWithSyntaxErrorCount()
- {
- return count($this->getFilesWithSyntaxError());
- }
-
- /**
- * @return bool
- */
- public function hasSyntaxError()
- {
- return $this->getFilesWithSyntaxErrorCount() !== 0;
- }
-
- /**
- * @return float
- */
- public function getTestTime()
- {
- return $this->testTime;
- }
-
- /**
- * (PHP 5 &gt;= 5.4.0)<br/>
- * Specify data which should be serialized to JSON
- * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by <b>json_encode</b>,
- * which is a value of any type other than a resource.
- */
- function jsonSerialize()
- {
- return array(
- 'checkedFiles' => $this->getCheckedFiles(),
- 'filesWithSyntaxError' => $this->getFilesWithSyntaxError(),
- 'skippedFiles' => $this->getSkippedFiles(),
- 'errors' => $this->getErrors(),
- );
- }
-
-
-} \ No newline at end of file
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Settings.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/Settings.php
deleted file mode 100644
index 0104417a..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/Settings.php
+++ /dev/null
@@ -1,217 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint;
-
-/*
-Copyright (c) 2012, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
- */
-
-class Settings
-{
- /**
- * Path to PHP executable
- * @var string
- */
- public $phpExecutable = 'php';
-
- /**
- * Check code inside PHP opening short tag <? or <?= in PHP 5.3
- * @var bool
- */
- public $shortTag = false;
-
- /**
- * Check PHP code inside ASP-style <% %> tags.
- * @var bool
- */
- public $aspTags = false;
-
- /**
- * Number of jobs running in same time
- * @var int
- */
- public $parallelJobs = 10;
-
- /**
- * If path contains directory, only file with these extensions are checked
- * @var array
- */
- public $extensions = array('php', 'phtml', 'php3', 'php4', 'php5');
-
- /**
- * Array of file or directories to check
- * @var array
- */
- public $paths = array();
-
- /**
- * Dont't check files or directories
- * @var array
- */
- public $excluded = array();
-
- /**
- * Print to console with colors
- * @var bool
- */
- public $colors = true;
-
- /**
- * Output results as JSON string
- * @var bool
- */
- public $json = false;
-
- /**
- * Read files and folder to tests from standard input (blocking)
- * @var bool
- */
- public $stdin = false;
-
- /**
- * Try to show git blame for row with error
- * @var bool
- */
- public $blame = false;
-
- /**
- * Path to git executable for blame
- * @var string
- */
- public $gitExecutable = 'git';
-
- /**
- * @var bool
- */
- public $ignoreFails = false;
-
- /**
- * @param array $paths
- */
- public function addPaths(array $paths)
- {
- $this->paths = array_merge($this->paths, $paths);
- }
-
- /**
- * @param array $arguments
- * @return Settings
- * @throws InvalidArgumentException
- */
- public static function parseArguments(array $arguments)
- {
- $arguments = new ArrayIterator(array_slice($arguments, 1));
- $settings = new self;
-
- foreach ($arguments as $argument) {
- if ($argument{0} !== '-') {
- $settings->paths[] = $argument;
- } else {
- switch ($argument) {
- case '-p':
- $settings->phpExecutable = $arguments->getNext();
- break;
-
- case '-s':
- case '--short':
- $settings->shortTag = true;
- break;
-
- case '-a':
- case '--asp':
- $settings->aspTags = true;
- break;
-
- case '--exclude':
- $settings->excluded[] = $arguments->getNext();
- break;
-
- case '-e':
- $settings->extensions = array_map('trim', explode(',', $arguments->getNext()));
- break;
-
- case '-j':
- $settings->parallelJobs = max((int) $arguments->getNext(), 1);
- break;
-
- case '--no-colors':
- $settings->colors = false;
- break;
-
- case '--json':
- $settings->json = true;
- break;
-
- case '--git':
- $settings->gitExecutable = $arguments->getNext();
- break;
-
- case '--stdin':
- $settings->stdin = true;
- break;
-
- case '--blame':
- $settings->blame = true;
- break;
-
- case '--ignore-fails':
- $settings->ignoreFails = true;
- break;
-
- default:
- throw new InvalidArgumentException($argument);
- }
- }
- }
-
- return $settings;
- }
-
- /**
- * @return array
- */
- public static function getPathsFromStdIn()
- {
- $content = stream_get_contents(STDIN);
-
- if (empty($content)) {
- return array();
- }
-
- $lines = explode("\n", rtrim($content));
- return array_map('rtrim', $lines);
- }
-}
-
-class ArrayIterator extends \ArrayIterator
-{
- public function getNext()
- {
- $this->next();
- return $this->current();
- }
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/src/exceptions.php b/Echo/vendor/jakub-onderka/php-parallel-lint/src/exceptions.php
deleted file mode 100644
index 97f7d54a..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/src/exceptions.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-namespace JakubOnderka\PhpParallelLint;
-
-/*
-Copyright (c) 2012, Jakub Onderka
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of the FreeBSD Project.
- */
-
-class Exception extends \Exception implements \JsonSerializable
-{
- public function jsonSerialize()
- {
- return array(
- 'type' => get_class($this),
- 'message' => $this->getMessage(),
- 'code' => $this->getCode(),
- );
- }
-}
-
-class RunTimeException extends Exception
-{
-
-}
-
-class InvalidArgumentException extends Exception
-{
- protected $argument;
-
- public function __construct($argument)
- {
- $this->argument = $argument;
- $this->message = "Invalid argument $argument";
- }
-
- public function getArgument()
- {
- return $this->argument;
- }
-}
-
-class NotExistsPathException extends Exception
-{
- protected $path;
-
- public function __construct($path)
- {
- $this->path = $path;
- $this->message = "Path '$path' not found";
- }
-
- public function getPath()
- {
- return $this->path;
- }
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/Manager.run.phpt b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/Manager.run.phpt
deleted file mode 100644
index 169608c7..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/Manager.run.phpt
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-
-/**
- * @testCase
- */
-
-require __DIR__ . '/../vendor/autoload.php';
-
-use JakubOnderka\PhpParallelLint\Manager;
-use JakubOnderka\PhpParallelLint\NullWriter;
-use JakubOnderka\PhpParallelLint\Settings;
-use JakubOnderka\PhpParallelLint\TextOutput;
-use Tester\Assert;
-
-class ManagerRunTest extends Tester\TestCase
-{
- public function testBadPath()
- {
- $settings = $this->prepareSettings();
- $settings->paths = array('path/for-not-found/');
- $manager = $this->getManager($settings);
- Assert::exception(function() use ($manager, $settings) {
- $manager->run($settings);
- }, 'JakubOnderka\PhpParallelLint\NotExistsPathException');
- }
-
- public function testFilesNotFound()
- {
- $settings = $this->prepareSettings();
- $settings->paths = array('examples/example-01/');
- $manager = $this->getManager($settings);
- Assert::exception(function() use ($manager, $settings) {
- $manager->run($settings);
- }, 'JakubOnderka\PhpParallelLint\Exception', 'No file found to check.');
- }
-
- public function testSuccess()
- {
- $settings = $this->prepareSettings();
- $settings->paths = array('examples/example-02/');
-
- $manager = $this->getManager($settings);
- $result = $manager->run($settings);
- Assert::false($result->hasError());
- }
-
- public function testError()
- {
- $settings = $this->prepareSettings();
- $settings->paths = array('examples/example-03/');
-
- $manager = $this->getManager($settings);
- $result = $manager->run($settings);
- Assert::true($result->hasError());
- }
-
- public function testExcludeRelativeSubdirectory()
- {
- $settings = $this->prepareSettings();
- $settings->paths = array('examples/example-04/');
-
- $manager = $this->getManager($settings);
- $result = $manager->run($settings);
- Assert::true($result->hasError());
-
- $settings->excluded = array('examples/example-04/dir1/dir2');
-
- $manager = $this->getManager($settings);
- $result = $manager->run($settings);
- Assert::false($result->hasError());
- }
-
- public function testExcludeAbsoluteSubdirectory()
- {
- $settings = $this->prepareSettings();
- $cwd = getcwd();
- $settings->paths = array($cwd . '/examples/example-04/');
- $settings->excluded = array();
-
- $manager = $this->getManager($settings);
- $result = $manager->run($settings);
- Assert::true($result->hasError());
-
- $settings->excluded = array($cwd . '/examples/example-04/dir1/dir2');
-
- $manager = $this->getManager($settings);
- $result = $manager->run($settings);
- Assert::false($result->hasError());
- }
-
- /**
- * @param Settings $settings
- * @return Manager
- */
- private function getManager(Settings $settings)
- {
- $manager = new Manager($settings);
- $manager->setOutput(new TextOutput(new NullWriter()));
- return $manager;
- }
-
- /**
- * @return JakubOnderka\PhpParallelLint\Settings
- */
- private function prepareSettings()
- {
- $settings = new Settings();
- $settings->phpExecutable = 'php';
- $settings->shortTag = false;
- $settings->aspTags = false;
- $settings->parallelJobs = 10;
- $settings->extensions = array('php', 'phtml', 'php3', 'php4', 'php5');
- $settings->paths = array('FOR-SET');
- $settings->excluded = array();
- $settings->colors = false;
-
- return $settings;
- }
-}
-
-$testCase = new ManagerRunTest;
-$testCase->run();
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/ParallelLint.lint.phpt b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/ParallelLint.lint.phpt
deleted file mode 100644
index 2aecb127..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/ParallelLint.lint.phpt
+++ /dev/null
@@ -1,116 +0,0 @@
-<?php
-
-/**
- * @testCase
- */
-
-require __DIR__ . '/../vendor/autoload.php';
-
-use JakubOnderka\PhpParallelLint\ParallelLint;
-use Tester\Assert;
-
-class ParallelLintLintTest extends Tester\TestCase
-{
- public function testSettersAndGetters()
- {
- $phpExecutable = $this->getPhpExecutable();
- $parallelLint = new ParallelLint($phpExecutable, 10);
- Assert::equal($phpExecutable, $parallelLint->getPhpExecutable());
- Assert::equal(10, $parallelLint->getParallelJobs());
-
- $phpExecutable2 = $this->getPhpExecutable();
- $parallelLint->setPhpExecutable($phpExecutable2);
- Assert::equal($phpExecutable2, $parallelLint->getPhpExecutable());
-
- $parallelLint->setParallelJobs(33);
- Assert::equal(33, $parallelLint->getParallelJobs());
-
- $parallelLint->setShortTagEnabled(true);
- Assert::true($parallelLint->isShortTagEnabled());
-
- $parallelLint->setAspTagsEnabled(true);
- Assert::true($parallelLint->isAspTagsEnabled());
-
- $parallelLint->setShortTagEnabled(false);
- Assert::false($parallelLint->isShortTagEnabled());
-
- $parallelLint->setAspTagsEnabled(false);
- Assert::false($parallelLint->isAspTagsEnabled());
- }
-
- public function testEmptyArray()
- {
- $parallelLint = new ParallelLint($this->getPhpExecutable());
- $result = $parallelLint->lint(array());
-
- Assert::equal(0, $result->getCheckedFilesCount());
- Assert::equal(0, $result->getFilesWithSyntaxErrorCount());
- Assert::false($result->hasSyntaxError());
- Assert::equal(0, count($result->getErrors()));
- }
-
- public function testNotExistsFile()
- {
- $parallelLint = new ParallelLint($this->getPhpExecutable());
- $result = $parallelLint->lint(array('path/for-not-found/'));
-
- Assert::equal(0, $result->getCheckedFilesCount());
- Assert::equal(0, $result->getFilesWithSyntaxErrorCount());
- Assert::false($result->hasSyntaxError());
- Assert::equal(1, count($result->getErrors()));
- }
-
- public function testEmptyFile()
- {
- $parallelLint = new ParallelLint($this->getPhpExecutable());
- $result = $parallelLint->lint(array(__DIR__ . '/examples/example-01/empty-file'));
-
- Assert::equal(1, $result->getCheckedFilesCount());
- Assert::equal(0, $result->getFilesWithSyntaxErrorCount());
- Assert::false($result->hasSyntaxError());
- Assert::equal(0, count($result->getErrors()));
- }
-
- public function testValidFile()
- {
- $parallelLint = new ParallelLint($this->getPhpExecutable());
- $result = $parallelLint->lint(array(__DIR__ . '/examples/example-02/example.php'));
-
- Assert::equal(1, $result->getCheckedFilesCount());
- Assert::equal(0, $result->getFilesWithSyntaxErrorCount());
- Assert::equal(0, count($result->getErrors()));
- }
-
- public function testInvalidFile()
- {
- $parallelLint = new ParallelLint($this->getPhpExecutable());
- $result = $parallelLint->lint(array(__DIR__ . '/examples/example-03/example.php'));
-
- Assert::equal(1, $result->getCheckedFilesCount());
- Assert::equal(1, $result->getFilesWithSyntaxErrorCount());
- Assert::true($result->hasSyntaxError());
- Assert::equal(1, count($result->getErrors()));
- }
-
- public function testValidAndInvalidFiles()
- {
- $parallelLint = new ParallelLint($this->getPhpExecutable());
- $result = $parallelLint->lint(array(
- __DIR__ . '/examples/example-02/example.php',
- __DIR__ . '/examples/example-03/example.php',
- ));
-
- Assert::equal(2, $result->getCheckedFilesCount());
- Assert::equal(1, $result->getFilesWithSyntaxErrorCount());
- Assert::true($result->hasSyntaxError());
- Assert::equal(1, count($result->getErrors()));
- }
-
- private function getPhpExecutable()
- {
- return \JakubOnderka\PhpParallelLint\Process\PhpExecutable::getPhpExecutable('php');
- }
-}
-
-$testCase = new ParallelLintLintTest;
-$testCase->run();
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/Settings.parseArguments.phpt b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/Settings.parseArguments.phpt
deleted file mode 100644
index 1c12c95a..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/Settings.parseArguments.phpt
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-/**
- * @testCase
- */
-
-require __DIR__ . '/../vendor/autoload.php';
-
-use JakubOnderka\PhpParallelLint\Settings;
-use Tester\Assert;
-
-class SettingsParseArgumentsTest extends Tester\TestCase
-{
- public function testNoneArguments()
- {
- $commandLine = "./parallel-lint .";
- $argv = explode(" ", $commandLine);
- $settings = Settings::parseArguments($argv);
-
- $expectedSettings = new Settings();
- $expectedSettings->phpExecutable = 'php';
- $expectedSettings->shortTag = false;
- $expectedSettings->aspTags = false;
- $expectedSettings->parallelJobs = 10;
- $expectedSettings->extensions = array('php', 'phtml', 'php3', 'php4', 'php5');
- $expectedSettings->paths = array('.');
- $expectedSettings->excluded = array();
- $expectedSettings->colors = true;
- $expectedSettings->json = false;
-
- Assert::equal($expectedSettings->phpExecutable, $settings->phpExecutable);
- Assert::equal($expectedSettings->shortTag, $settings->shortTag);
- Assert::equal($expectedSettings->aspTags, $settings->aspTags);
- Assert::equal($expectedSettings->parallelJobs, $settings->parallelJobs);
- Assert::equal($expectedSettings->extensions, $settings->extensions);
- Assert::equal($expectedSettings->paths, $settings->paths);
- Assert::equal($expectedSettings->excluded, $settings->excluded);
- Assert::equal($expectedSettings->colors, $settings->colors);
- Assert::equal($expectedSettings->json, $settings->json);
- }
-
- public function testMoreArguments()
- {
- $commandLine = "./parallel-lint --exclude vendor --no-colors .";
- $argv = explode(" ", $commandLine);
- $settings = Settings::parseArguments($argv);
-
- $expectedSettings = new Settings();
- $expectedSettings->phpExecutable = 'php';
- $expectedSettings->shortTag = false;
- $expectedSettings->aspTags = false;
- $expectedSettings->parallelJobs = 10;
- $expectedSettings->extensions = array('php', 'phtml', 'php3', 'php4', 'php5');
- $expectedSettings->paths = array('.');
- $expectedSettings->excluded = array('vendor');
- $expectedSettings->colors = false;
- $expectedSettings->json = false;
-
- Assert::equal($expectedSettings->phpExecutable, $settings->phpExecutable);
- Assert::equal($expectedSettings->shortTag, $settings->shortTag);
- Assert::equal($expectedSettings->aspTags, $settings->aspTags);
- Assert::equal($expectedSettings->parallelJobs, $settings->parallelJobs);
- Assert::equal($expectedSettings->extensions, $settings->extensions);
- Assert::equal($expectedSettings->paths, $settings->paths);
- Assert::equal($expectedSettings->excluded, $settings->excluded);
- Assert::equal($expectedSettings->colors, $settings->colors);
- Assert::equal($expectedSettings->json, $settings->json);
- }
-}
-
-$testCase = new SettingsParseArgumentsTest;
-$testCase->run();
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/SkipLintProcess.phpt b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/SkipLintProcess.phpt
deleted file mode 100644
index fa4fe854..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/SkipLintProcess.phpt
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-/**
- * @testCase
- */
-
-require __DIR__ . '/../vendor/autoload.php';
-
-use Tester\Assert;
-
-class SkipLintProcessTest extends Tester\TestCase
-{
- public function testLargeInput()
- {
- $filesToCheck = array(
- __DIR__ . '/skip-on-5.3/class.php',
- __DIR__ . '/skip-on-5.3/trait.php',
- );
-
- for ($i = 0; $i < 15; $i++) {
- $filesToCheck = array_merge($filesToCheck, $filesToCheck);
- }
-
- $phpExecutable = \JakubOnderka\PhpParallelLint\Process\PhpExecutable::getPhpExecutable('php');
- $process = new \JakubOnderka\PhpParallelLint\Process\SkipLintProcess($phpExecutable, $filesToCheck);
-
- while (!$process->isFinished()) {
- usleep(100);
- $process->getChunk();
- }
-
- foreach ($filesToCheck as $fileToCheck) {
- $status = $process->isSkipped($fileToCheck);
- Assert::notEqual(null, $status);
- }
- }
-}
-
-$skipLintProcessTest = new SkipLintProcessTest;
-$skipLintProcessTest->run();
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-02/example.php b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-02/example.php
deleted file mode 100644
index 2186cb4a..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-02/example.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-
-$myInteger = 100;
-echo $myInteger;
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-03/example.php b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-03/example.php
deleted file mode 100644
index 2b037450..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-03/example.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-
-$myInteger = 1;
-echo $;
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/dir1/dir2/index.php b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/dir1/dir2/index.php
deleted file mode 100644
index c50d1245..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/dir1/dir2/index.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-$foo ='bar'
-echo $foo;
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/dir1/index.php b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/dir1/index.php
deleted file mode 100644
index 8644320d..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/dir1/index.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-$foo = 'bar';
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/index.php b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/index.php
deleted file mode 100644
index 8644320d..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-04/index.php
+++ /dev/null
@@ -1,2 +0,0 @@
-<?php
-$foo = 'bar';
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-images/use-error.png b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-images/use-error.png
deleted file mode 100644
index 666b3d6c..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-images/use-error.png
+++ /dev/null
Binary files differ
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-images/use-success.png b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-images/use-success.png
deleted file mode 100644
index c1d17e50..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/examples/example-images/use-success.png
+++ /dev/null
Binary files differ
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/class.php b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/class.php
deleted file mode 100644
index e9166f3d..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/class.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-
-class ExampleClass
-{
-
-}
diff --git a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/trait.php b/Echo/vendor/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/trait.php
deleted file mode 100644
index 64fc31e3..00000000
--- a/Echo/vendor/jakub-onderka/php-parallel-lint/tests/skip-on-5.3/trait.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php // lint >= 5.4
-
-trait ExampleTrait
-{
-
-}
diff --git a/Echo/version b/Echo/version
index 2332c0da..b3cbabfb 100644
--- a/Echo/version
+++ b/Echo/version
@@ -1,4 +1,4 @@
-Echo: REL1_26
-2015-11-17T01:05:21
+Echo: REL1_30
+2018-08-23T23:04:30
-1d2029d
+d64a26d